├── .github └── workflows │ ├── build.yml │ └── publish.yml ├── .gitignore ├── LICENSE ├── README.md ├── build.gradle ├── flows-amazon ├── build.gradle └── src │ └── main │ └── java │ └── io │ └── hanbings │ └── flows │ └── amazon │ ├── AmazonAccess.java │ ├── AmazonIdentify.java │ ├── AmazonOAuth.java │ └── AmazonProfile.java ├── flows-baidu ├── build.gradle └── src │ └── main │ └── java │ └── io │ └── hanbings │ └── flows │ └── baidu │ ├── BaiduAccess.java │ ├── BaiduIdentify.java │ ├── BaiduOAuth.java │ └── BaiduProfile.java ├── flows-common ├── build.gradle └── src │ └── main │ └── java │ └── io │ └── hanbings │ └── flows │ └── common │ ├── OAuth.java │ ├── OAuthCallback.java │ ├── OAuthRequest.java │ ├── OAuthResponse.java │ ├── OAuthSerialization.java │ ├── OAuthState.java │ ├── exception │ └── NoResponseReceivedException.java │ ├── function │ └── Lazy.java │ └── interfaces │ ├── Access.java │ ├── Accessible.java │ ├── Callback.java │ ├── Identifiable.java │ ├── Identify.java │ ├── Profilable.java │ ├── Profile.java │ ├── Refresh.java │ ├── Refreshable.java │ ├── Request.java │ ├── Response.java │ ├── Revokable.java │ ├── Revoke.java │ ├── Serialization.java │ └── State.java ├── flows-discord ├── build.gradle └── src │ └── main │ └── java │ └── io │ └── hanbings │ └── flows │ └── discord │ ├── DiscordAccess.java │ ├── DiscordIdentify.java │ ├── DiscordOAuth.java │ ├── DiscordProfile.java │ └── DiscordRevoke.java ├── flows-dropbox ├── build.gradle └── src │ └── main │ └── java │ └── io │ └── hanbings │ └── flows │ └── dropbox │ ├── DropboxAccess.java │ ├── DropboxOAuth.java │ ├── DropboxRefresh.java │ └── DropboxRevoke.java ├── flows-ebay ├── build.gradle └── src │ └── main │ └── java │ └── io │ └── hanbings │ └── flows │ └── ebay │ ├── EbayAccess.java │ ├── EbayIdentify.java │ ├── EbayOAuth.java │ └── EbayProfile.java ├── flows-etsy └── build.gradle ├── flows-extra ├── build.gradle └── src │ └── main │ └── java │ └── io │ └── hanbings │ └── flows │ └── extra │ └── OkhttpRequest.java ├── flows-facebook ├── build.gradle └── src │ └── main │ └── java │ └── io │ └── hanbings │ └── flows │ └── facebook │ ├── FacebookAccess.java │ └── FacebookOAuth.java ├── flows-flickr └── build.gradle ├── flows-github ├── build.gradle └── src │ └── main │ └── java │ └── io │ └── hanbings │ └── flows │ └── github │ ├── GithubAccess.java │ ├── GithubIdentify.java │ ├── GithubOAuth.java │ └── GithubProfile.java ├── flows-gitlab ├── build.gradle └── src │ └── main │ └── java │ └── io │ └── hanbings │ └── flows │ └── gitlab │ ├── GitlabAccess.java │ ├── GitlabIdentify.java │ ├── GitlabOAuth.java │ └── GitlabProfile.java ├── flows-google ├── build.gradle └── src │ └── main │ └── java │ └── io │ └── hanbings │ └── flows │ └── google │ ├── GoogleAccess.java │ ├── GoogleIdentify.java │ ├── GoogleOAuth.java │ ├── GoogleProfile.java │ └── GoogleRevoke.java ├── flows-imgur └── build.gradle ├── flows-instagram └── build.gradle ├── flows-line └── build.gradle ├── flows-microsoft ├── build.gradle └── src │ └── main │ └── java │ └── io │ └── hanbings │ └── flows │ └── microsoft │ ├── MicrosoftAccess.java │ ├── MicrosoftCommonOAuth.java │ ├── MicrosoftConsumersOAuth.java │ ├── MicrosoftIdentify.java │ ├── MicrosoftOAuth.java │ ├── MicrosoftOrganizationsOAuth.java │ ├── MicrosoftProfile.java │ └── MicrosoftRevoke.java ├── flows-pinterest └── build.gradle ├── flows-qq ├── build.gradle └── src │ └── main │ └── java │ └── io │ └── hanbings │ └── flows │ └── qq │ ├── QQAccess.java │ ├── QQIdentify.java │ ├── QQOAuth.java │ └── QQProfile.java ├── flows-reddit └── build.gradle ├── flows-soundcloud └── build.gradle ├── flows-spotify └── build.gradle ├── flows-stackoverflow └── build.gradle ├── flows-tiktok ├── build.gradle └── src │ └── main │ └── java │ └── io │ └── hanbings │ └── flows │ └── tiktok │ ├── TiktokAccess.java │ ├── TiktokIdentify.java │ ├── TiktokOAuth.java │ └── TiktokProfile.java ├── flows-tumblr └── build.gradle ├── flows-twitch ├── build.gradle └── src │ └── main │ └── java │ └── io │ └── hanbings │ └── flows │ └── twitch │ ├── TwitchAccess.java │ ├── TwitchIdentify.java │ ├── TwitchOAuth.java │ └── TwitchProfile.java ├── flows-twitter ├── build.gradle └── src │ └── main │ └── java │ └── io │ └── hanbings │ └── flows │ └── twitter │ ├── TwitterAccess.java │ ├── TwitterIdentify.java │ ├── TwitterOAuth.java │ └── TwitterProfile.java ├── flows-weibo ├── build.gradle └── src │ └── main │ └── java │ └── io │ └── hanbings │ └── flows │ └── weibo │ ├── WeiboAccess.java │ ├── WeiboIdentify.java │ ├── WeiboOAuth.java │ ├── WeiboProfile.java │ └── WeiboRevoke.java ├── flows-wordpress ├── build.gradle └── src │ └── main │ └── java │ └── io │ └── hanbings │ └── flows │ └── wordpress │ ├── WordpressAccess.java │ ├── WordpressIdentify.java │ ├── WordpressOAuth.java │ └── WordpressProfile.java ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat └── settings.gradle /.github/workflows/build.yml: -------------------------------------------------------------------------------- 1 | name: Flows Build 2 | 3 | on: 4 | push: 5 | branches: [ main ] 6 | pull_request: 7 | branches: [ main ] 8 | 9 | jobs: 10 | build: 11 | runs-on: ubuntu-latest 12 | if: "! contains(github.event.head_commit.message, '#Skip')" 13 | steps: 14 | - uses: actions/checkout@v3 15 | 16 | - name: Set up JDK 17 17 | uses: actions/setup-java@v3 18 | with: 19 | java-version: 17 20 | distribution: adopt 21 | 22 | - name: Grant execute permission for gradlew 23 | run: chmod +x gradlew 24 | 25 | - name: Build with Gradle (build project) 26 | run: ./gradlew build -x test 27 | 28 | - name: Build with Gradle (shadow) 29 | run: ./gradlew shadowJar 30 | 31 | - name: Build with Gradle (collect) 32 | run: ./gradlew collect 33 | 34 | - uses: actions/upload-artifact@v3 35 | with: 36 | name: build 37 | path: build/libs -------------------------------------------------------------------------------- /.github/workflows/publish.yml: -------------------------------------------------------------------------------- 1 | name: Flows Publish 2 | 3 | on: 4 | push: 5 | branches: [ main ] 6 | 7 | jobs: 8 | publish: 9 | runs-on: ubuntu-latest 10 | if: "! contains(github.event.head_commit.message, '#Skip')" 11 | steps: 12 | - uses: actions/checkout@v3 13 | 14 | - name: Fetch commit hash 15 | id: sha 16 | if: "! contains(github.event.head_commit.message, '#Release')" 17 | run: | 18 | sha=$(git rev-parse --short ${{ github.sha }}) 19 | echo "::set-output name=short_sha::$sha" 20 | 21 | - name: Replace publish version 22 | if: "! contains(github.event.head_commit.message, '#Release')" 23 | uses: Nambers/ReplaceStringInFile@v1.1 24 | with: 25 | path: ${{ github.workspace }}/build.gradle 26 | oldString: '@{{COMMIT_SHORT_SHA}}' 27 | newString: ${{ steps.sha.outputs.short_sha }} 28 | 29 | - name: Set up JDK 17 30 | uses: actions/setup-java@v3 31 | with: 32 | java-version: 17 33 | distribution: adopt 34 | 35 | - name: Grant execute permission for gradlew 36 | run: chmod +x gradlew 37 | 38 | - name: Build with Gradle (build) 39 | run: ./gradlew build -x test 40 | 41 | - name: Build with Gradle (publish) 42 | run: ./gradlew publish 43 | env: 44 | REPOSITORY_ROOT_URL: ${{ secrets.REPOSITORY_ROOT_URL }} 45 | REPOSITORY_USER: ${{ secrets.REPOSITORY_USER }} 46 | REPOSITORY_TOKEN: ${{ secrets.REPOSITORY_TOKEN }} -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # User-specific stuff 2 | .idea/ 3 | 4 | *.iml 5 | *.ipr 6 | *.iws 7 | 8 | # IntelliJ 9 | out/ 10 | # mpeltonen/sbt-idea plugin 11 | .idea_modules/ 12 | 13 | # JIRA plugin 14 | atlassian-ide-plugin.xml 15 | 16 | # Compiled class file 17 | *.class 18 | 19 | # Log file 20 | *.log 21 | 22 | # BlueJ files 23 | *.ctxt 24 | 25 | # Package Files # 26 | *.war 27 | *.nar 28 | *.ear 29 | *.zip 30 | *.tar.gz 31 | *.rar 32 | 33 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml 34 | hs_err_pid* 35 | 36 | *~ 37 | 38 | # temporary files which can be created if a process still has a handle open of a deleted file 39 | .fuse_hidden* 40 | 41 | # KDE directory preferences 42 | .directory 43 | 44 | # Linux trash folder which might appear on any partition or disk 45 | .Trash-* 46 | 47 | # .nfs files are created when an open file is removed but is still being accessed 48 | .nfs* 49 | 50 | # General 51 | .DS_Store 52 | .AppleDouble 53 | .LSOverride 54 | 55 | # Icon must end with two \r 56 | Icon 57 | 58 | # Thumbnails 59 | ._* 60 | 61 | # Files that might appear in the root of a volume 62 | .DocumentRevisions-V100 63 | .fseventsd 64 | .Spotlight-V100 65 | .TemporaryItems 66 | .Trashes 67 | .VolumeIcon.icns 68 | .com.apple.timemachine.donotpresent 69 | 70 | # Directories potentially created on remote AFP share 71 | .AppleDB 72 | .AppleDesktop 73 | Network Trash Folder 74 | Temporary Items 75 | .apdisk 76 | 77 | # Windows thumbnail cache files 78 | Thumbs.db 79 | Thumbs.db:encryptable 80 | ehthumbs.db 81 | ehthumbs_vista.db 82 | 83 | # Dump file 84 | *.stackdump 85 | 86 | # Folder config file 87 | [Dd]esktop.ini 88 | 89 | # Recycle Bin used on file shares 90 | $RECYCLE.BIN/ 91 | 92 | # Windows Installer files 93 | *.cab 94 | *.msi 95 | *.msix 96 | *.msm 97 | *.msp 98 | 99 | # Windows shortcuts 100 | *.lnk 101 | 102 | .gradle 103 | build/ 104 | 105 | # Ignore Gradle GUI config 106 | gradle-app.setting 107 | 108 | # Cache of project 109 | .gradletasknamecache 110 | 111 | **/build/ 112 | 113 | # Common working directory 114 | run/ 115 | 116 | # Avoid ignoring Gradle wrapper jar file (.jar files are usually ignored) 117 | !gradle-wrapper.jar 118 | gradle.properties 119 | repo/ 120 | 121 | # logs directory 122 | logs/ -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ![Flows](https://picture.hanbings.io/2023/02/07/dbd60957f0391.png) 2 | 3 |

🌊 Flows

4 |
海纳百川 有容乃大!
5 | 6 | ## 🍀 这是什么? 7 | 8 | **洋流**是一条 OAuth 客户端的辅助工具,通过低耦合的设计给用户高自定义度的接口,并且洋流集成了常见 OAuth 平台的封装,提供了光速集成第三方登录的能力。 9 | 10 | **洋流**的主要特性如下: 11 | 12 | - 常见的 OAuth 平台适配 13 | - 支持自定义 State 生成器、自定义 Http 客户端、自定义 Json 解析器 14 | - 提供通用默认实现以便支持未适配 OAuth 平台 15 | - 默认 Http 客户端实现支持 Socks 代理 16 | - 可爱 17 | 18 | 19 | 20 | **Github OAuth 示例** 21 | 22 | 洋流提供了许多的重载方法,用于应对不同情况下的请求,有些带自有请求头的,也有要求必须要 Scope 的。 23 | 24 | ```java 25 | // 创建 OAuth 原始处理器 26 | OAuth oauth = new GithubOAuth( 27 | "id", 28 | "secret", 29 | "https://exmaple.com/api/v0/login/oauth/github/callback" 30 | ); 31 | 32 | // 生成授权 url 33 | String url = oauth.authorize(); 34 | // 生成带参数或指定 scope 35 | String spec = oauth.authorize(List.of("email"), Map.of("Accept", "application/json")); 36 | 37 | //解析回调的 url 并获取 token 38 | // 输入原始 url 自动解析 code 以及 state 39 | oauth.token("url"); 40 | // 更改回调地址 41 | oauth.token("url", "redirect"); 42 | // 手动指定参数 43 | oauth.token("code", "state", "redirect"); 44 | 45 | // 处理返回值 46 | oauth.token("code", "state", "redirect") 47 | .succeed(data -> System.out.println(data.accessToken())) 48 | .fail(wrong -> System.out.println(wrong.errorDescription())) 49 | .except(throwable -> System.out.println(throwable.getMessage())); 50 | 51 | // 假设请求成功 直接获取数据 52 | GithubAccess access = oauth.token("code", "state", "redirect").data(); 53 | ``` 54 | 55 | **使用 Socks 代理** 56 | 57 | ```java 58 | oauth.proxy(() -> 59 | new Request.Proxy( 60 | Proxy.Type.SOCKS, 61 | "127.0.0.1", 62 | 10086, 63 | "username", 64 | "password" 65 | ) 66 | ); 67 | ``` 68 | 69 | **更换 State 生成器** 70 | 71 | 默认随机生成 UUID 并设置 300 秒有效期 72 | 73 | ```java 74 | oauth.state( 75 | Lazy.of(() -> new OAuthState(300, () -> UUID.randomUUID().toString())) 76 | ); 77 | ``` 78 | 79 | **更换 Http 客户端** 80 | 81 | 默认使用 `java.net.http` 的 HttpClient 发起请求,无需任何第三方依赖,在 `flows-extra` 中还有一个 Okhttp 的实现 82 | 83 | ```java 84 | // 实现比较繁杂 就不展示啦 x 85 | oauth.request( 86 | Lazy.of(() -> proxy == null ? new OAuthRequest() : new OAuthRequest(proxy.get())) 87 | ); 88 | ``` 89 | 90 | **更换 Json 解析器** 91 | 92 | 默认使用 Gson 作为 Json 解析器 93 | 94 | ```java 95 | oauth.serialization( 96 | Lazy.of(() -> new Serialization() { 97 | final Gson gson = new Gson(); 98 | 99 | @Override 100 | public T object(Class type, String raw) { 101 | return gson.fromJson(raw, type); 102 | } 103 | 104 | @Override 105 | public Map map(Class key, Class value, String raw) { 106 | return gson.fromJson(raw, new TypeToken>() { 107 | }.getType()); 108 | } 109 | 110 | @Override 111 | public List list(Class type, String raw) { 112 | return gson.fromJson(raw, new TypeToken>() { 113 | }.getType()); 114 | } 115 | }) 116 | ); 117 | ``` 118 | 119 | ## ⚡️ 快速开始 120 | 121 | *稍后补充* 122 | 123 | ## 🍉 一些小事情 124 | 125 | **F:这是一个什么样的项目?** 126 | 127 | Q:这是一个计划用于生产环境,长期维护和对社区友善且开放的个人项目。 128 | 129 | **F:为什么使用 JDK 17 而不是 JDK 11 甚至是 JDK 8?** 130 | 131 | Q:JDK 17 是一个 LTS (long-term support)版本,它拥有长达十年的支持时间。JDK 17 中拥有的特性例如 Record 和 Switch 模式匹配,它们都可以有效提高开发者效率。许多框架已经开始迁移到新版本的 JDK17,例如 [Spring Framework 6](https://spring.io/blog/2021/09/02/a-java-17-and-jakarta-ee-9-baseline-for-spring-framework-6) 和 [Spring Boot 3](https://spring.io/blog/2022/05/24/preparing-for-spring-boot-3-0),开发者已经没有什么理由不使用新版本 JDK 了。另外,基于旧版本 JDK 的项目在完成初期开发后换用组件的几率很小,对于旧版本 JDK 的支持所带来的收益是小于成本的。 132 | 133 | **F:泛型、多个接口和复杂回调,是不是过度设计?** 134 | 135 | Q:为了保证线上业务安全,避免一个异常拖垮整个应用,尽可能获取足够详细的错误信息,进行一定程度的封装是必要的,如果用户不想编写繁杂的回调,也可以通过 `Callback` 对象直接获得数据或异常。 136 | 137 | **F:商业计划?** 138 | 139 | Q:本项目基于 Apache 2.0 许可证,项目本身完全是免费开源的,同样的,项目依赖库也将选择可商用开源许可的开源项目,使用本项目开发的独立项目可用于商业用途,请阅读 `开源许可` 部分。 140 | 141 | 142 | ## ⚖ 开源许可 143 | 144 | 本项目使用 [Apache License, Version 2.0](https://www.apache.org/licenses/LICENSE-2.0.html) 许可协议进行开源。 145 | 146 | 本项目是**非盈利性**项目。 147 | 148 | 依据协议,本项目**允许**遵守协议的前提下基于本项目开发的项目**进行商用**,但需要注意的是,本项目中的图片(包括 Readme.md 文件中所展示的吉祥物小鱼洋流和可能出现的其他图片)**不属于开源的范围** 它们属于开发者 [寒冰 hanbings](https://github.com/hanbings) 个人所有,~~是寒冰的崽子~~,请在复制、修改本项目时**移除它们**。 149 | 150 | **版权警告:吉祥物小鱼洋流图片中所使用 Flows 字样字体为商业需授权字体 Snap ITC** 151 | 152 | ## 🍀 关于开源 153 | 154 | 开源是一种精神。 155 | 156 | 开源运动所坚持的原则: 157 | 158 | 1. 坚持开放与共享,鼓励最大化的参与与协作。 159 | 2. 尊重作者权益,保证软件程序完整的同时,鼓励修改的自由以及衍生创新。 160 | 3. 保持独立性和中立性。 161 | 162 | 与来自五湖四海的开发者共同**讨论**技术问题,**解决**技术难题,**促进**应用的发展是开源的本质目的。 163 | 164 | **众人拾柴火焰高,开源需要依靠大家的努力,请自觉遵守开源协议,弘扬开源精神,共建开源社区!** -------------------------------------------------------------------------------- /build.gradle: -------------------------------------------------------------------------------- 1 | allprojects { 2 | apply plugin: 'java' 3 | apply plugin: 'maven-publish' 4 | 5 | group = 'io.hanbings.flows' 6 | // 正式版本号在 publish 设置块中 7 | version = '@{{COMMIT_SHORT_SHA}}-SNAPSHOT' 8 | 9 | repositories { 10 | mavenCentral() 11 | } 12 | 13 | dependencies { 14 | testImplementation 'org.junit.jupiter:junit-jupiter-api:5.9.0' 15 | testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.9.0' 16 | 17 | compileOnly 'org.projectlombok:lombok:1.18.24' 18 | annotationProcessor 'org.projectlombok:lombok:1.18.24' 19 | 20 | testCompileOnly 'org.projectlombok:lombok:1.18.24' 21 | testAnnotationProcessor 'org.projectlombok:lombok:1.18.24' 22 | 23 | // https://mvnrepository.com/artifact/org.jetbrains/annotations 24 | compileOnly 'org.jetbrains:annotations:23.1.0' 25 | } 26 | 27 | java { 28 | sourceCompatibility = JavaVersion.VERSION_17 29 | targetCompatibility = JavaVersion.VERSION_17 30 | } 31 | 32 | test { 33 | useJUnitPlatform() 34 | } 35 | 36 | compileJava { 37 | options.encoding = 'UTF-8' 38 | } 39 | 40 | compileTestJava { 41 | options.encoding = 'UTF-8' 42 | } 43 | 44 | javadoc { 45 | options.addBooleanOption('html5', true) 46 | options.addStringOption('Xdoclint:none', '-quiet') 47 | options.encoding('utf-8') 48 | } 49 | 50 | task sourcesJar(type: Jar) { 51 | from sourceSets.main.allSource 52 | archiveClassifier.convention('sources') 53 | archiveClassifier.set('sources') 54 | } 55 | 56 | task javadocJar(type: Jar) { 57 | from javadoc 58 | archiveClassifier.convention('javadocs') 59 | archiveClassifier.set('javadocs') 60 | } 61 | 62 | publishing { 63 | repositories { 64 | maven { 65 | // 处理 Release 情况下发布的包 66 | if (project.version.toString().contains('COMMIT_SHORT_SHA')) { 67 | // 如果 version 字符串没有被替换则表明正在 Release 发布或本地发布 68 | // 进行重新替换版本号 69 | version = '1.0.0' 70 | } 71 | 72 | url = uri((project.findProperty("repository_root_url") ?: System.getenv("REPOSITORY_ROOT_URL")) 73 | + (project.version.toString().endsWith('-SNAPSHOT') ? 'snapshots' : 'releases')) 74 | credentials { 75 | username = project.findProperty("repository_user") ?: System.getenv("REPOSITORY_USER") 76 | password = project.findProperty("repository_token") ?: System.getenv("REPOSITORY_TOKEN") 77 | } 78 | } 79 | } 80 | publications { 81 | mavenJava(MavenPublication) { 82 | artifact(jar) 83 | artifact(sourcesJar) 84 | artifact(javadocJar) 85 | } 86 | } 87 | } 88 | } 89 | 90 | buildscript { 91 | repositories { 92 | maven { 93 | url "https://plugins.gradle.org/m2/" 94 | } 95 | } 96 | dependencies { 97 | classpath "gradle.plugin.com.github.johnrengelman:shadow:7.1.2" 98 | } 99 | } 100 | 101 | apply plugin: "com.github.johnrengelman.shadow" 102 | 103 | task collect(type: Copy) { 104 | destinationDir = file('build/libs') 105 | subprojects.each { p -> from p.file('build/libs') } 106 | } 107 | 108 | dependencies { 109 | subprojects.each { p -> implementation create(p) } 110 | subprojects.stream() 111 | .filter(p -> p.name != "flows-common") 112 | .each { p -> 113 | { 114 | p.dependencies { 115 | // common 116 | implementation project(":flows-common") 117 | 118 | // https://mvnrepository.com/artifact/com.google.code.gson/gson 119 | implementation 'com.google.code.gson:gson:2.10' 120 | 121 | // https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-annotations 122 | implementation("com.fasterxml.jackson.core:jackson-annotations:2.14.1") 123 | } 124 | } 125 | } 126 | } 127 | -------------------------------------------------------------------------------- /flows-amazon/build.gradle: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanbings/flows/3170ba366276be6987d16aa05db5d22045519cfa/flows-amazon/build.gradle -------------------------------------------------------------------------------- /flows-amazon/src/main/java/io/hanbings/flows/amazon/AmazonAccess.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2023 Flows 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package io.hanbings.flows.amazon; 18 | 19 | import io.hanbings.flows.common.interfaces.Access; 20 | 21 | public record AmazonAccess( 22 | String accessToken 23 | ) implements Access { 24 | public record Wrong( 25 | String error, 26 | String errorDescription 27 | ) implements Access.Wrong { 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /flows-amazon/src/main/java/io/hanbings/flows/amazon/AmazonIdentify.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2023 Flows 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package io.hanbings.flows.amazon; 18 | 19 | public record AmazonIdentify() { 20 | } 21 | -------------------------------------------------------------------------------- /flows-amazon/src/main/java/io/hanbings/flows/amazon/AmazonOAuth.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2023 Flows 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package io.hanbings.flows.amazon; 18 | 19 | import io.hanbings.flows.common.OAuth; 20 | 21 | import java.util.List; 22 | import java.util.Map; 23 | 24 | public class AmazonOAuth extends OAuth { 25 | private AmazonOAuth() { 26 | super(null, null, null, null); 27 | } 28 | 29 | public AmazonOAuth(String client, String secret, String redirect) { 30 | super( 31 | "https://www.amazon.com/ap/oa", 32 | "https://api.amazon.com/auth/o2/token", 33 | List.of(), 34 | Map.of() 35 | ); 36 | 37 | this.client(client); 38 | this.secret(secret); 39 | this.redirect(redirect); 40 | } 41 | 42 | public AmazonOAuth(String client, String secret, String redirect, 43 | List scopes, Map params) { 44 | super( 45 | "https://www.amazon.com/ap/oa", 46 | "https://api.amazon.com/auth/o2/token", 47 | scopes, 48 | params 49 | ); 50 | 51 | this.client(client); 52 | this.secret(secret); 53 | this.redirect(redirect); 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /flows-amazon/src/main/java/io/hanbings/flows/amazon/AmazonProfile.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2023 Flows 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package io.hanbings.flows.amazon; 18 | 19 | public record AmazonProfile() { 20 | } 21 | -------------------------------------------------------------------------------- /flows-baidu/build.gradle: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanbings/flows/3170ba366276be6987d16aa05db5d22045519cfa/flows-baidu/build.gradle -------------------------------------------------------------------------------- /flows-baidu/src/main/java/io/hanbings/flows/baidu/BaiduAccess.java: -------------------------------------------------------------------------------- 1 | package io.hanbings.flows.baidu; 2 | 3 | import com.fasterxml.jackson.annotation.JsonProperty; 4 | import com.google.gson.annotations.SerializedName; 5 | import io.hanbings.flows.common.interfaces.Access; 6 | import io.hanbings.flows.common.interfaces.Refresh; 7 | 8 | public record BaiduAccess( 9 | @JsonProperty("access_token") 10 | @SerializedName("access_token") 11 | String accessToken, 12 | @JsonProperty("expires_in") 13 | @SerializedName("expires_in") 14 | long expiresIn, 15 | @JsonProperty("refresh_token") 16 | @SerializedName("refresh_token") 17 | String refreshToken, 18 | @JsonProperty("scope") 19 | @SerializedName("scope") 20 | String scope, 21 | @JsonProperty("session_key") 22 | @SerializedName("session_key") 23 | String sessionKey, 24 | @JsonProperty("session_secret") 25 | @SerializedName("session_secret") 26 | String sessionSecret 27 | ) implements Access, Refresh { 28 | public record Wrong( 29 | @JsonProperty("error") 30 | @SerializedName("error") 31 | String code, 32 | @JsonProperty("error_description") 33 | @SerializedName("error_description") 34 | String error 35 | ) implements Access.Wrong, Refresh.Wrong { 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /flows-baidu/src/main/java/io/hanbings/flows/baidu/BaiduIdentify.java: -------------------------------------------------------------------------------- 1 | package io.hanbings.flows.baidu; 2 | 3 | import com.fasterxml.jackson.annotation.JsonProperty; 4 | import com.google.gson.annotations.SerializedName; 5 | import io.hanbings.flows.common.interfaces.Identify; 6 | 7 | @SuppressWarnings("SpellCheckingInspection") 8 | public record BaiduIdentify( 9 | @JsonProperty("openid") 10 | @SerializedName("openid") 11 | String openid, 12 | @JsonProperty("portrait") 13 | @SerializedName("portrait") 14 | String avatar, 15 | @JsonProperty("username") 16 | @SerializedName("username") 17 | String username, 18 | @JsonProperty("username") 19 | @SerializedName("username") 20 | String nickname, 21 | String email, 22 | @JsonProperty("securemobile") 23 | @SerializedName("securemobile") 24 | String phone 25 | ) implements Identify { 26 | public record Wrong( 27 | @JsonProperty("error_msg") 28 | @SerializedName("error_msg") 29 | String error, 30 | @JsonProperty("error_code") 31 | @SerializedName("error_code") 32 | int code 33 | ) implements Identify.Wrong { 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /flows-baidu/src/main/java/io/hanbings/flows/baidu/BaiduOAuth.java: -------------------------------------------------------------------------------- 1 | package io.hanbings.flows.baidu; 2 | 3 | import io.hanbings.flows.common.OAuth; 4 | import io.hanbings.flows.common.OAuthCallback; 5 | import io.hanbings.flows.common.interfaces.*; 6 | 7 | import java.util.HashMap; 8 | import java.util.List; 9 | import java.util.Map; 10 | 11 | @SuppressWarnings("unused") 12 | public class BaiduOAuth 13 | extends 14 | OAuth 15 | implements 16 | Refreshable, 17 | Profilable, 18 | Identifiable { 19 | final String USER_INFO = "https://openapi.baidu.com/rest/2.0/passport/users/getInfo"; 20 | final String refreshment = "https://openapi.baidu.com/oauth/2.0/token"; 21 | 22 | private BaiduOAuth() { 23 | super(null, null, null, null); 24 | } 25 | 26 | public BaiduOAuth(String client, String secret, String redirect) { 27 | super( 28 | "https://openapi.baidu.com/oauth/2.0/authorize", 29 | "https://openapi.baidu.com/oauth/2.0/token", 30 | List.of(), 31 | Map.of() 32 | ); 33 | 34 | this.client(client); 35 | this.secret(secret); 36 | this.redirect(redirect); 37 | } 38 | 39 | public BaiduOAuth(String client, String secret, String redirect, 40 | List scopes, Map params) { 41 | super( 42 | "https://openapi.baidu.com/oauth/2.0/authorize", 43 | "https://openapi.baidu.com/oauth/2.0/token", 44 | scopes, 45 | params 46 | ); 47 | 48 | this.client(client); 49 | this.secret(secret); 50 | this.redirect(redirect); 51 | } 52 | 53 | @Override 54 | public String authorize(List scopes, Map params) { 55 | List sco = scopes == null ? this.scopes() : scopes; 56 | Map par = params == null ? this.params() : params; 57 | 58 | Map temp = new HashMap<>() {{ 59 | put("client_id", client()); 60 | put("redirect_uri", redirect()); 61 | put("response_type", "code"); 62 | put("scope", "basic"); 63 | put("state", state().get().add()); 64 | 65 | if (sco != null) put("scope", sco.get(0)); 66 | 67 | putAll(par); 68 | }}; 69 | 70 | // url builder 71 | StringBuilder url = new StringBuilder().append(authorization()); 72 | 73 | if (temp.size() != 0) { 74 | url.append("?"); 75 | 76 | // map to string 77 | temp.forEach((k, v) -> url.append(k).append("=").append(v).append("&")); 78 | 79 | // eat last '&' and return string 80 | return url.substring(0, url.length() - 1); 81 | } 82 | 83 | return url.toString(); 84 | } 85 | 86 | @Override 87 | public Callback token(String code, String state, String redirect) { 88 | Response response = this.request() 89 | .get() 90 | .post( 91 | this.serialization().get(), 92 | this.proxy() == null ? null : this.proxy().get(), 93 | this.access(), 94 | Map.of( 95 | "grant_type", "authorization_code", 96 | "code", code, 97 | "client_id", client(), 98 | "client_secret", secret(), 99 | "redirect_uri", redirect == null ? this.redirect() : redirect 100 | ) 101 | ); 102 | 103 | if (response.code() == 200) { 104 | BaiduAccess access = this.serialization() 105 | .get() 106 | .object(BaiduAccess.class, response.raw()); 107 | 108 | return OAuthCallback.response(access.accessToken(), access, null, response); 109 | } 110 | 111 | if (response.code() != 200 && response.code() != 0) { 112 | BaiduAccess.Wrong wrong = this.serialization() 113 | .get() 114 | .object(BaiduAccess.Wrong.class, response.raw()); 115 | 116 | return OAuthCallback.response(null, null, wrong, response); 117 | } 118 | 119 | return OAuthCallback.exception( 120 | null, 121 | response.exception() ? response.throwable() : new IllegalArgumentException() 122 | ); 123 | } 124 | 125 | @Override 126 | public Callback identify(String token) { 127 | Response response = this.request() 128 | .get() 129 | .get( 130 | this.serialization().get(), 131 | this.proxy() == null ? null : this.proxy().get(), 132 | USER_INFO, 133 | Map.of( 134 | "access_token", token 135 | ) 136 | ); 137 | 138 | if (response.code() == 200) { 139 | BaiduIdentify identify = this.serialization() 140 | .get() 141 | .object(BaiduIdentify.class, response.raw()); 142 | 143 | return OAuthCallback.response(token, identify, null, response); 144 | } 145 | 146 | if (response.code() != 200 && response.code() != 0) { 147 | BaiduIdentify.Wrong wrong = this.serialization() 148 | .get() 149 | .object(BaiduIdentify.Wrong.class, response.raw()); 150 | 151 | return OAuthCallback.response(null, null, wrong, response); 152 | } 153 | 154 | return OAuthCallback.exception( 155 | null, 156 | response.exception() ? response.throwable() : new IllegalArgumentException() 157 | ); 158 | } 159 | 160 | @Override 161 | public Callback profile(String token) { 162 | Response response = this.request() 163 | .get() 164 | .get( 165 | this.serialization().get(), 166 | this.proxy() == null ? null : this.proxy().get(), 167 | USER_INFO, 168 | Map.of( 169 | "access_token", token 170 | ) 171 | ); 172 | 173 | if (response.code() == 200) { 174 | BaiduProfile profile = this.serialization() 175 | .get() 176 | .object(BaiduProfile.class, response.raw()); 177 | 178 | return OAuthCallback.response(token, profile, null, response); 179 | } 180 | 181 | if (response.code() != 200 && response.code() != 0) { 182 | BaiduProfile.Wrong wrong = this.serialization() 183 | .get() 184 | .object(BaiduProfile.Wrong.class, response.raw()); 185 | 186 | return OAuthCallback.response(null, null, wrong, response); 187 | } 188 | 189 | return OAuthCallback.exception( 190 | null, 191 | response.exception() ? response.throwable() : new IllegalArgumentException() 192 | ); 193 | } 194 | 195 | @Override 196 | public Callback refresh(String token) { 197 | Response response = this.request() 198 | .get() 199 | .post( 200 | this.serialization().get(), 201 | this.proxy() == null ? null : this.proxy().get(), 202 | refreshment, 203 | Map.of( 204 | "grant_type", "refresh_token", 205 | "refresh_token", token, 206 | "client_id", client(), 207 | "client_secret", secret() 208 | ) 209 | ); 210 | 211 | if (response.code() == 200) { 212 | BaiduAccess access = this.serialization() 213 | .get() 214 | .object(BaiduAccess.class, response.raw()); 215 | 216 | return OAuthCallback.response(access.accessToken(), access, null, response); 217 | } 218 | 219 | if (response.code() != 200 && response.code() != 0) { 220 | BaiduAccess.Wrong wrong = this.serialization() 221 | .get() 222 | .object(BaiduAccess.Wrong.class, response.raw()); 223 | 224 | return OAuthCallback.response(null, null, wrong, response); 225 | } 226 | 227 | return OAuthCallback.exception( 228 | null, 229 | response.exception() ? response.throwable() : new IllegalArgumentException() 230 | ); 231 | } 232 | } 233 | -------------------------------------------------------------------------------- /flows-baidu/src/main/java/io/hanbings/flows/baidu/BaiduProfile.java: -------------------------------------------------------------------------------- 1 | package io.hanbings.flows.baidu; 2 | 3 | import com.fasterxml.jackson.annotation.JsonProperty; 4 | import com.google.gson.annotations.SerializedName; 5 | import io.hanbings.flows.common.interfaces.Profile; 6 | 7 | @SuppressWarnings("SpellCheckingInspection") 8 | public record BaiduProfile( 9 | @JsonProperty("openid") 10 | @SerializedName("openid") 11 | String openid, 12 | @JsonProperty("unionid") 13 | @SerializedName("unionid") 14 | String unionid, 15 | @JsonProperty("userid") 16 | @SerializedName("userid") 17 | String userid, 18 | @JsonProperty("securemobile") 19 | @SerializedName("securemobile") 20 | String securemobile, 21 | @JsonProperty("username") 22 | @SerializedName("username") 23 | String username, 24 | @JsonProperty("portrait") 25 | @SerializedName("portrait") 26 | String portrait, 27 | @JsonProperty("userdetail") 28 | @SerializedName("userdetail") 29 | String userdetail, 30 | @JsonProperty("birthday") 31 | @SerializedName("birthday") 32 | String birthday, 33 | @JsonProperty("marriage") 34 | @SerializedName("marriage") 35 | String marriage, 36 | @JsonProperty("sex") 37 | @SerializedName("sex") 38 | String sex, 39 | @JsonProperty("blood") 40 | @SerializedName("blood") 41 | String blood, 42 | @JsonProperty("is_bind_mobile") 43 | @SerializedName("is_bind_mobile") 44 | int isBindMobile, 45 | @JsonProperty("is_realname") 46 | @SerializedName("is_realname") 47 | int isRealname 48 | ) implements Profile { 49 | public record Wrong( 50 | @JsonProperty("error_code") 51 | @SerializedName("error_code") 52 | int errorCode, 53 | @JsonProperty("error_msg") 54 | @SerializedName("error_msg") 55 | String errorMsg 56 | ) implements Profile.Wrong { 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /flows-common/build.gradle: -------------------------------------------------------------------------------- 1 | dependencies { 2 | // https://mvnrepository.com/artifact/com.google.code.gson/gson 3 | implementation 'com.google.code.gson:gson:2.10' 4 | 5 | // https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-annotations 6 | implementation("com.fasterxml.jackson.core:jackson-annotations:2.14.1") 7 | } -------------------------------------------------------------------------------- /flows-common/src/main/java/io/hanbings/flows/common/OAuth.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2023 Flows 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package io.hanbings.flows.common; 18 | 19 | import io.hanbings.flows.common.function.Lazy; 20 | import io.hanbings.flows.common.interfaces.*; 21 | import lombok.Getter; 22 | import lombok.RequiredArgsConstructor; 23 | import lombok.Setter; 24 | import lombok.experimental.Accessors; 25 | import org.jetbrains.annotations.Nullable; 26 | 27 | import java.util.HashMap; 28 | import java.util.List; 29 | import java.util.Map; 30 | import java.util.UUID; 31 | import java.util.function.Supplier; 32 | import java.util.stream.IntStream; 33 | 34 | /** 35 | * OAuth 平台需要实现的基本接口
36 | * 一般来说参数最多的是具体实现,其余均为可选参数的重载
37 | * 各个平台的注意事项参见各个平台 *OAuth 类的注释 38 | * 39 | * @param data 数据类 是描述成功接收 Access Token 的数据容器 40 | * @param wrong 错误类 是描述成功请求但返回错误状态码的数据容器 41 | */ 42 | @Setter 43 | @Getter 44 | @RequiredArgsConstructor 45 | @SuppressWarnings("unused") 46 | @Accessors(fluent = true, chain = true) 47 | public class OAuth implements Accessible { 48 | final String authorization; 49 | final String access; 50 | final List scopes; 51 | final Map params; 52 | String client; 53 | String secret; 54 | String redirect; 55 | 56 | Supplier proxy = null; 57 | Lazy request = Lazy.of( 58 | () -> proxy == null ? new OAuthRequest() : new OAuthRequest(proxy.get()) 59 | ); 60 | Lazy serialization = Lazy.of(OAuthSerialization::new); 61 | Lazy state = Lazy.of(() -> new OAuthState(300, () -> UUID.randomUUID().toString())); 62 | 63 | /** 64 | * 该方法默认添加
65 | * 1. client_id OAuth 服务商提供的 Client ID
66 | * 2. redirect_uri 在 OAuth 服务商设置回调 url
67 | * 3. state 自动生成和判断的安全凭据
68 | * 在 scope 默认的分隔符是 %20 即空格的 http encode
69 | *

开发者注意事项:

70 | * 实现该方法时需要注意 null 的参数传入
71 | * 传入 null 时使用 this.scopes 和 this.params 获取默认的 scopes 和 params
72 | * 73 | * @param scopes 构造 OAuth 请求范围 传入 null 时将会使用构造方法传入的默认 scopes 74 | * @param params 构造 authorize url 的参数 传入 null 时将会使用构造方法传入的默认 params 75 | * @return 返回 authorize url 76 | */ 77 | @Override 78 | public String authorize(@Nullable List scopes, @Nullable Map params) { 79 | List sco = scopes == null ? this.scopes() : scopes; 80 | Map par = params == null ? this.params() : params; 81 | 82 | Map temp = new HashMap<>() {{ 83 | put("client_id", client()); 84 | put("redirect_uri", redirect()); 85 | put("state", state().get().add()); 86 | 87 | // put scopes 88 | StringBuilder scope = new StringBuilder(); 89 | 90 | IntStream.range(0, sco.size()).forEach(count -> { 91 | if (count != 0) { 92 | scope.append("%20"); 93 | } 94 | 95 | scope.append(sco.get(count)); 96 | }); 97 | 98 | if (scope.length() != 0) { 99 | put("scope", scope.toString()); 100 | } 101 | 102 | // merge map 103 | putAll(par); 104 | }}; 105 | 106 | // url builder 107 | StringBuilder url = new StringBuilder().append(authorization); 108 | 109 | if (temp.size() != 0) { 110 | url.append("?"); 111 | 112 | // map to string 113 | temp.forEach((k, v) -> url.append(k).append("=").append(v).append("&")); 114 | 115 | // eat last '&' and return string 116 | return url.substring(0, url.length() - 1); 117 | } 118 | 119 | return url.toString(); 120 | } 121 | 122 | /** 123 | * 该方法默认未实现 需要依据平台对 OAuth 标准的执行进行视频 124 | * 125 | * @param code 授权码 126 | * @param state 自动生成和判断的安全凭据 127 | * @param redirect 回调 url 128 | * @return 返回 authorize url 129 | */ 130 | @Override 131 | public Callback token(String code, String state, String redirect) { 132 | throw new UnsupportedOperationException(); 133 | } 134 | } 135 | -------------------------------------------------------------------------------- /flows-common/src/main/java/io/hanbings/flows/common/OAuthCallback.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2023 Flows 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package io.hanbings.flows.common; 18 | 19 | import io.hanbings.flows.common.interfaces.Callback; 20 | import io.hanbings.flows.common.interfaces.Response; 21 | import org.jetbrains.annotations.NotNull; 22 | import org.jetbrains.annotations.Nullable; 23 | 24 | import java.util.function.Consumer; 25 | 26 | public class OAuthCallback { 27 | private OAuthCallback() { 28 | } 29 | 30 | public static Callback response(@NotNull Response response) { 31 | return new OAuthCallback.Complete<>(response); 32 | } 33 | 34 | public static Callback response( 35 | String token, @Nullable D data, @Nullable W wrong, @NotNull Response response 36 | ) { 37 | return (data == null && wrong == null) ? 38 | new OAuthCallback.Exception<>(token, new IllegalArgumentException(), null) : 39 | ((wrong == null) ? 40 | new OAuthCallback.Success<>(token, data, response) : 41 | new OAuthCallback.Failure<>(token, wrong, response) 42 | ); 43 | } 44 | 45 | public static Callback exception(String token, Throwable throwable) { 46 | return new OAuthCallback.Exception<>(token, throwable, null); 47 | } 48 | 49 | record Complete(Response response) implements Callback { 50 | @Override 51 | public D data() { 52 | return null; 53 | } 54 | 55 | @Override 56 | public W wrong() { 57 | return null; 58 | } 59 | 60 | @Override 61 | public String token() { 62 | return null; 63 | } 64 | 65 | @Override 66 | public Throwable throwable() { 67 | return null; 68 | } 69 | 70 | @Override 71 | public Callback succeed(Consumer data) { 72 | return this; 73 | } 74 | 75 | @Override 76 | public Callback completed(Consumer response) { 77 | response.accept(this.response); 78 | 79 | return this; 80 | } 81 | 82 | @Override 83 | public Callback fail(Consumer wrong) { 84 | return this; 85 | } 86 | 87 | @Override 88 | public Callback except(Consumer throwable) { 89 | return this; 90 | } 91 | 92 | @Override 93 | public boolean success() { 94 | return false; 95 | } 96 | } 97 | 98 | record Success(String token, D data, Response response) implements Callback { 99 | 100 | @Override 101 | public W wrong() { 102 | return null; 103 | } 104 | 105 | @Override 106 | public Throwable throwable() { 107 | return null; 108 | } 109 | 110 | @Override 111 | public Callback succeed(Consumer data) { 112 | data.accept(this.data); 113 | 114 | return this; 115 | } 116 | 117 | @Override 118 | public Callback completed(Consumer response) { 119 | response.accept(this.response); 120 | 121 | return this; 122 | } 123 | 124 | @Override 125 | public Callback fail(Consumer wrong) { 126 | return this; 127 | } 128 | 129 | @Override 130 | public Callback except(Consumer exception) { 131 | return this; 132 | } 133 | 134 | @Override 135 | public boolean success() { 136 | return true; 137 | } 138 | } 139 | 140 | record Failure(String token, W wrong, Response response) implements Callback { 141 | @Override 142 | public D data() { 143 | return null; 144 | } 145 | 146 | @Override 147 | public Throwable throwable() { 148 | return null; 149 | } 150 | 151 | @Override 152 | public Callback succeed(Consumer data) { 153 | return this; 154 | } 155 | 156 | @Override 157 | public Callback completed(Consumer response) { 158 | response.accept(this.response); 159 | 160 | return this; 161 | } 162 | 163 | @Override 164 | public Callback fail(Consumer wrong) { 165 | wrong.accept(this.wrong); 166 | 167 | return this; 168 | } 169 | 170 | @Override 171 | public Callback except(Consumer exception) { 172 | return this; 173 | } 174 | 175 | @Override 176 | public boolean success() { 177 | return false; 178 | } 179 | } 180 | 181 | record Exception(String token, Throwable throwable, Response response) implements Callback { 182 | @Override 183 | public D data() { 184 | return null; 185 | } 186 | 187 | @Override 188 | public W wrong() { 189 | return null; 190 | } 191 | 192 | @Override 193 | public Callback succeed(Consumer data) { 194 | return this; 195 | } 196 | 197 | @Override 198 | public Callback completed(Consumer response) { 199 | return this; 200 | } 201 | 202 | @Override 203 | public Callback fail(Consumer wrong) { 204 | return this; 205 | } 206 | 207 | @Override 208 | public Callback except(Consumer throwable) { 209 | throwable.accept(this.throwable); 210 | 211 | return this; 212 | } 213 | 214 | @Override 215 | public boolean success() { 216 | return false; 217 | } 218 | } 219 | } 220 | -------------------------------------------------------------------------------- /flows-common/src/main/java/io/hanbings/flows/common/OAuthRequest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2023 Flows 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package io.hanbings.flows.common; 18 | 19 | import io.hanbings.flows.common.interfaces.Request; 20 | import io.hanbings.flows.common.interfaces.Response; 21 | import io.hanbings.flows.common.interfaces.Serialization; 22 | import lombok.AllArgsConstructor; 23 | 24 | import java.io.IOException; 25 | import java.net.*; 26 | import java.net.http.HttpClient; 27 | import java.net.http.HttpRequest; 28 | import java.net.http.HttpResponse; 29 | import java.util.Map; 30 | 31 | @AllArgsConstructor 32 | public class OAuthRequest implements Request { 33 | HttpClient client; 34 | 35 | public OAuthRequest() { 36 | client = HttpClient.newBuilder().build(); 37 | } 38 | 39 | public OAuthRequest(Proxy proxy) { 40 | // 设置 Socks 代理的认证 41 | Authenticator.setDefault(new Authenticator() { 42 | @Override 43 | protected PasswordAuthentication getPasswordAuthentication() { 44 | if (getRequestingHost().equalsIgnoreCase(proxy.host())) { 45 | if (proxy.port() == getRequestingPort()) { 46 | return new PasswordAuthentication(proxy.username(), proxy.password().toCharArray()); 47 | } 48 | } 49 | return null; 50 | } 51 | }); 52 | 53 | // 为客户端设置 Socks 代理 54 | client = HttpClient.newBuilder() 55 | .proxy(ProxySelector.of(new InetSocketAddress(proxy.host(), proxy.port()))) 56 | .build(); 57 | } 58 | 59 | @Override 60 | public Response get(Serialization serialization, Proxy proxy, String url) { 61 | return get(serialization, proxy, url, Map.of(), Map.of()); 62 | } 63 | 64 | @Override 65 | public Response get(Serialization serialization, Proxy proxy, String url, 66 | Map params) { 67 | return get(serialization, proxy, url, params, Map.of()); 68 | } 69 | 70 | @Override 71 | public Response get( 72 | Serialization serialization, 73 | Proxy proxy, 74 | String url, 75 | Map params, 76 | Map headers 77 | ) { 78 | // 处理 url 的 params 79 | URI check; 80 | URI target; 81 | 82 | try { 83 | // 从旧的 url 创建 URI 对象 84 | check = new URI(url); 85 | 86 | StringBuilder strings = new StringBuilder(); 87 | 88 | // 判断是否已经有 query 参数 如果没有还需要 & 带在 url 尾部 89 | if (check.getQuery() != null) { 90 | strings.append(check.getQuery()).append("&"); 91 | } 92 | // 转换参数拼接到 url 尾部 93 | params.forEach((k, v) -> strings.append(k).append("=").append(v).append("&")); 94 | 95 | // 构造新 url 96 | target = new URI( 97 | check.getScheme(), 98 | check.getAuthority(), 99 | check.getPath(), 100 | strings.toString(), 101 | check.getFragment() 102 | ); 103 | } catch (URISyntaxException e) { 104 | return new OAuthResponse(true, e, 0, null, null); 105 | } 106 | 107 | // 为了掺入 headers 参数拆分 builder 108 | HttpRequest.Builder builder = HttpRequest.newBuilder() 109 | .GET() 110 | .uri(target); 111 | // 添加 headers 112 | headers.forEach(builder::header); 113 | 114 | // 发出请求 115 | try { 116 | HttpResponse response = client.send( 117 | builder.build(), 118 | HttpResponse.BodyHandlers.ofString() 119 | ); 120 | 121 | return new OAuthResponse( 122 | false, 123 | null, 124 | response.statusCode(), 125 | response.body(), 126 | serialization.map( 127 | String.class, 128 | String.class, 129 | response.body() 130 | ) 131 | ); 132 | } catch (IOException | InterruptedException e) { 133 | return new OAuthResponse(true, e, 0, null, null); 134 | } 135 | } 136 | 137 | @Override 138 | public Response post(Serialization serialization, Proxy proxy, String url) { 139 | return this.post(serialization, proxy, url, Map.of(), Map.of()); 140 | } 141 | 142 | @Override 143 | public Response post(Serialization serialization, Proxy proxy, String url, 144 | Map form) { 145 | return this.post(serialization, proxy, url, form, Map.of()); 146 | } 147 | 148 | @Override 149 | public Response post( 150 | Serialization serialization, 151 | Proxy proxy, 152 | String url, 153 | Map form, 154 | Map headers 155 | ) { 156 | // 构造表单 157 | StringBuilder strings = new StringBuilder(); 158 | // 拼接数据 159 | form.forEach((k, v) -> strings.append(k).append("=").append(v).append("&")); 160 | 161 | // 为了掺入 headers 参数拆分 builder 162 | HttpRequest.Builder builder = HttpRequest.newBuilder() 163 | .POST(HttpRequest.BodyPublishers.ofString(strings.toString())) 164 | .uri(URI.create(url)); 165 | // 添加 headers 166 | headers.forEach(builder::header); 167 | 168 | // 发出请求 169 | try { 170 | HttpResponse response = client.send( 171 | builder.build(), 172 | HttpResponse.BodyHandlers.ofString() 173 | ); 174 | 175 | return new OAuthResponse( 176 | false, 177 | null, 178 | response.statusCode(), 179 | response.body(), 180 | serialization.map( 181 | String.class, 182 | String.class, 183 | response.body() 184 | ) 185 | ); 186 | } catch (IOException | InterruptedException e) { 187 | return new OAuthResponse(true, e, 0, null, null); 188 | } 189 | } 190 | } 191 | -------------------------------------------------------------------------------- /flows-common/src/main/java/io/hanbings/flows/common/OAuthResponse.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2023 Flows 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package io.hanbings.flows.common; 18 | 19 | import io.hanbings.flows.common.interfaces.Response; 20 | 21 | import java.util.Map; 22 | 23 | public record OAuthResponse( 24 | boolean exception, 25 | Throwable throwable, 26 | int code, 27 | String raw, 28 | Map data 29 | ) implements Response { 30 | } 31 | -------------------------------------------------------------------------------- /flows-common/src/main/java/io/hanbings/flows/common/OAuthSerialization.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2023 Flows 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package io.hanbings.flows.common; 18 | 19 | import com.google.gson.Gson; 20 | import com.google.gson.reflect.TypeToken; 21 | import io.hanbings.flows.common.interfaces.Serialization; 22 | 23 | import java.util.List; 24 | import java.util.Map; 25 | 26 | public class OAuthSerialization implements Serialization { 27 | Gson gson = new Gson(); 28 | 29 | @Override 30 | public T object(Class type, String raw) { 31 | return gson.fromJson(raw, type); 32 | } 33 | 34 | @Override 35 | public Map map(Class key, Class value, String raw) { 36 | return gson.fromJson(raw, new TypeToken>() { 37 | }.getType()); 38 | } 39 | 40 | @Override 41 | public List list(Class type, String raw) { 42 | return gson.fromJson(raw, new TypeToken>() { 43 | }.getType()); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /flows-common/src/main/java/io/hanbings/flows/common/OAuthState.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2023 Flows 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package io.hanbings.flows.common; 18 | 19 | import io.hanbings.flows.common.interfaces.State; 20 | import lombok.RequiredArgsConstructor; 21 | 22 | import java.util.HashSet; 23 | import java.util.Map; 24 | import java.util.Set; 25 | import java.util.concurrent.ConcurrentHashMap; 26 | import java.util.function.Supplier; 27 | 28 | @RequiredArgsConstructor 29 | public class OAuthState implements State { 30 | final long expire; 31 | final Supplier state; 32 | 33 | Map states = new ConcurrentHashMap<>(); 34 | 35 | @Override 36 | public String add() { 37 | String state = this.state.get(); 38 | states.put(state, System.currentTimeMillis() + expire); 39 | 40 | return state; 41 | } 42 | 43 | @Override 44 | public void add(String state) { 45 | states.put(state, System.currentTimeMillis() + expire); 46 | } 47 | 48 | @Override 49 | public boolean has(String state) { 50 | return states.containsKey(state) && (states.get(state) < System.currentTimeMillis()); 51 | } 52 | 53 | @Override 54 | public boolean fire(String state) { 55 | if (!states.containsKey(state)) { 56 | return false; 57 | } 58 | 59 | return states.remove(state) < System.currentTimeMillis(); 60 | } 61 | 62 | @Override 63 | public void clean() { 64 | // current time 65 | long time = System.currentTimeMillis(); 66 | // temp 67 | Set delete = new HashSet<>(); 68 | 69 | // collect expire keys 70 | states.forEach((k, v) -> { 71 | if (v < time) { 72 | delete.add(k); 73 | } 74 | }); 75 | 76 | // delete 77 | delete.forEach(k -> states.remove(k)); 78 | } 79 | 80 | @Override 81 | public void empty() { 82 | states.clear(); 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /flows-common/src/main/java/io/hanbings/flows/common/exception/NoResponseReceivedException.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2023 Flows 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package io.hanbings.flows.common.exception; 18 | 19 | @SuppressWarnings("unused") 20 | public class NoResponseReceivedException extends Exception { 21 | } 22 | -------------------------------------------------------------------------------- /flows-common/src/main/java/io/hanbings/flows/common/function/Lazy.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2023 Flows 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package io.hanbings.flows.common.function; 18 | 19 | import lombok.RequiredArgsConstructor; 20 | 21 | import java.util.function.Supplier; 22 | 23 | @SuppressWarnings("unused") 24 | @RequiredArgsConstructor(staticName = "of") 25 | public class Lazy { 26 | final Supplier supplier; 27 | volatile T value; 28 | volatile boolean initialized; 29 | 30 | public T get() { 31 | if (value == null) { 32 | synchronized (this) { 33 | if (value == null) { 34 | value = supplier.get(); 35 | initialized = true; 36 | } 37 | } 38 | } 39 | return value; 40 | } 41 | 42 | public boolean initialized() { 43 | return initialized; 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /flows-common/src/main/java/io/hanbings/flows/common/interfaces/Access.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2023 Flows 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package io.hanbings.flows.common.interfaces; 18 | 19 | /** 20 | * 用于 OAuth 授权后所返回的数据模型 21 | * 通常包含 access token 作为权限凭据 22 | */ 23 | @SuppressWarnings("unused") 24 | public interface Access { 25 | /** 26 | * 权限凭据 27 | * 28 | * @return 字符串类型凭据 29 | */ 30 | String accessToken(); 31 | 32 | /** 33 | * 用于描述 OAuth 授权错误返回的数据模型 34 | */ 35 | interface Wrong { 36 | /** 37 | * 错误的详细信息 38 | * 39 | * @return 错误信息 40 | */ 41 | String error(); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /flows-common/src/main/java/io/hanbings/flows/common/interfaces/Accessible.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2023 Flows 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package io.hanbings.flows.common.interfaces; 18 | 19 | import io.hanbings.flows.common.OAuthCallback; 20 | 21 | import java.net.URI; 22 | import java.net.URISyntaxException; 23 | import java.util.Arrays; 24 | import java.util.HashMap; 25 | import java.util.List; 26 | import java.util.Map; 27 | 28 | /** 29 | * 用于描述可 OAuth 授权的提供商 30 | * 31 | * @param Data 继承 Access 接口的数据模型 32 | * @param Wrong 继承 Access.Wrong 接口的错误信息模型 33 | */ 34 | @SuppressWarnings("unused") 35 | public interface Accessible { 36 | /** 37 | * 生成授权 url 38 | * 39 | * @return 字符串 url 40 | */ 41 | default String authorize() { 42 | return authorize(null, null); 43 | } 44 | 45 | /** 46 | * 指定 Scope 生成授权 url 47 | * 48 | * @param scopes 指定的 Scope 列表 49 | * @return 字符串 url 50 | */ 51 | default String authorize(List scopes) { 52 | return authorize(scopes, null); 53 | } 54 | 55 | /** 56 | * 指定 query 参数生成授权 url 57 | * 58 | * @param params 指定的 http query 参数 59 | * @return 字符串 url 60 | */ 61 | default String authorize(Map params) { 62 | return authorize(null, params); 63 | } 64 | 65 | /** 66 | * 指定 Scope 和 query 参数生成授权 url 67 | * 68 | * @param scopes 指定的 Scope 列表 69 | * @param params 指定的 http query 参数 70 | * @return 字符串 url 71 | */ 72 | String authorize(List scopes, Map params); 73 | 74 | /** 75 | * code 换 token 执行授权码模式流程 76 | * 77 | * @param url callback 返回的完整 url 将自动解析 78 | * @return Callback 数据 79 | */ 80 | default Callback token(String url) { 81 | return token(url, null); 82 | } 83 | 84 | /** 85 | * code 换 token 执行授权码模式流程 86 | * 87 | * @param url callback 返回的完整 url 将自动解析 88 | * @param redirect 回调数据被传送到的地址 需要在提供商处注册该域 89 | * @return Callback 数据 90 | */ 91 | default Callback token(String url, String redirect) { 92 | String code; 93 | String state; 94 | 95 | try { 96 | code = Accessible.Utils.params(url).get("code"); 97 | state = Accessible.Utils.params(url).get("state"); 98 | } catch (URISyntaxException e) { 99 | return OAuthCallback.exception(null, e); 100 | } 101 | 102 | return token(code, state, redirect); 103 | } 104 | 105 | /** 106 | * 使用授权码获取 token 107 | * 108 | * @param code 授权码 109 | * @param state state 码 110 | * @param redirect 回调地址 111 | * @return Callback 数据 112 | */ 113 | Callback token(String code, String state, String redirect); 114 | 115 | class Utils { 116 | public static String params(String url, Map params) throws URISyntaxException { 117 | URI check = new URI(url); 118 | 119 | StringBuilder builder = new StringBuilder(); 120 | 121 | if (check.getQuery() != null) { 122 | builder.append(check.getQuery()).append("&"); 123 | } 124 | 125 | params.forEach((k, v) -> { 126 | builder.append(k).append("=").append(v).append("&"); 127 | }); 128 | 129 | return new URI( 130 | check.getScheme(), 131 | check.getAuthority(), 132 | check.getPath(), 133 | builder.toString(), 134 | check.getFragment() 135 | ).toString(); 136 | } 137 | 138 | public static Map params(String url) throws URISyntaxException { 139 | return new HashMap<>() {{ 140 | Arrays.stream(new URI(url).getQuery().split("&")).forEach(s -> { 141 | put(s.substring(0, s.indexOf("=")), s.substring(s.indexOf("="))); 142 | }); 143 | }}; 144 | } 145 | } 146 | } 147 | -------------------------------------------------------------------------------- /flows-common/src/main/java/io/hanbings/flows/common/interfaces/Callback.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2023 Flows 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package io.hanbings.flows.common.interfaces; 18 | 19 | import java.util.function.Consumer; 20 | 21 | /** 22 | * 回调数据 23 | * 24 | * @param 回调数据模型 25 | * @param 回调错误信息 26 | */ 27 | @SuppressWarnings("unused") 28 | public interface Callback { 29 | /** 30 | * 当请求返回成功(200 状态码)时该数据不为空 31 | * 32 | * @return 指定的回调数据 33 | */ 34 | D data(); 35 | 36 | /** 37 | * 当请求返回失败(或非 200 状态码)时该数据不为空 38 | * 39 | * @return 指定的错误信息 40 | */ 41 | W wrong(); 42 | 43 | /** 44 | * 请求发出成功并收到返回时(任意状态码)不为空 45 | * 46 | * @return 请求所返回的数据原始内容 47 | */ 48 | Response response(); 49 | 50 | /** 51 | * 请求中携带的 token 52 | * 53 | * @return access token 54 | */ 55 | String token(); 56 | 57 | /** 58 | * 请求发生异常时不为空 59 | * 60 | * @return 异常 61 | */ 62 | Throwable throwable(); 63 | 64 | /** 65 | * 请求成功发起且收到服务器的消息(状态码 200) 66 | * 67 | * @param data 处理数据的逻辑 68 | * @return Callback 成功 69 | */ 70 | Callback succeed(Consumer data); 71 | 72 | /** 73 | * 请求成功发出且收到服务器的消息但是没有对应的状态码解析器 74 | * 75 | * @param response 处理数据的逻辑 76 | * @return Callback 请求成功 77 | */ 78 | Callback completed(Consumer response); 79 | 80 | /** 81 | * 请求成功发出且收到服务器消息但可能是失败状态(状态码 404 502 等)
82 | * 状态码是否触发该回调取决于实现 83 | * 84 | * @param wrong 错误信息 85 | * @return Callback 失败 86 | */ 87 | Callback fail(Consumer wrong); 88 | 89 | /** 90 | * 请求发生异常 91 | * 92 | * @param throwable 异常 93 | * @return Callback 异常 94 | */ 95 | Callback except(Consumer throwable); 96 | 97 | /** 98 | * 是否请求成功且成功解析状态码为 200 的数据 99 | * 100 | * @return 是否成功 101 | */ 102 | boolean success(); 103 | } 104 | -------------------------------------------------------------------------------- /flows-common/src/main/java/io/hanbings/flows/common/interfaces/Identifiable.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2023 Flows 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package io.hanbings.flows.common.interfaces; 18 | 19 | /** 20 | * 描述 OAuth 是否可提供身份识别信息 21 | * 具有该能力的 OAuth 适配器将继承该接口 22 | * 23 | * @param 身份识别信息的数据模型 24 | * @param 身份识别信息的错误信息 25 | */ 26 | @SuppressWarnings("unused") 27 | public interface Identifiable { 28 | /** 29 | * 传入具有权限的 token 30 | * 31 | * @param token access token 32 | * @return Callback 数据 33 | */ 34 | Callback identify(String token); 35 | } 36 | -------------------------------------------------------------------------------- /flows-common/src/main/java/io/hanbings/flows/common/interfaces/Identify.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2023 Flows 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package io.hanbings.flows.common.interfaces; 18 | 19 | import org.jetbrains.annotations.NotNull; 20 | import org.jetbrains.annotations.Nullable; 21 | 22 | /** 23 | * 用于描述 OAuth 提供商提供的身份识别信息 24 | */ 25 | @SuppressWarnings("unused") 26 | public interface Identify { 27 | /** 28 | * 该身份提供商用户的唯一 ID 29 | * 30 | * @return 唯一 ID 字符串 31 | */ 32 | @NotNull String openid(); 33 | 34 | /** 35 | * 该身份提供商用户的头像 36 | * 37 | * @return 头像 url 38 | */ 39 | @NotNull String avatar(); 40 | 41 | /** 42 | * 用户名 43 | * 44 | * @return 字符串用户名 45 | */ 46 | @NotNull String username(); 47 | 48 | /** 49 | * 用户昵称 50 | * 51 | * @return 字符串用户名 52 | */ 53 | @NotNull String nickname(); 54 | 55 | /** 56 | * 邮件地址 如果提供商有多个邮件地址将默认填入第一个 57 | * 58 | * @return 邮件地址字符串 59 | */ 60 | @Nullable String email(); 61 | 62 | /** 63 | * 手机号码 64 | * 65 | * @return 手机号码字符串 66 | */ 67 | @Nullable String phone(); 68 | 69 | /** 70 | * 错误信息 71 | */ 72 | interface Wrong { 73 | 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /flows-common/src/main/java/io/hanbings/flows/common/interfaces/Profilable.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2023 Flows 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package io.hanbings.flows.common.interfaces; 18 | 19 | /** 20 | * 用于描述 OAuth 提供商提供的个人资料 21 | * 22 | * @param 个人资料数据模型 23 | * @param 错误信息 24 | */ 25 | @SuppressWarnings("SpellCheckingInspection unused") 26 | public interface Profilable { 27 | /** 28 | * 使用有效 token 获取个人资料 29 | * 30 | * @param token access token 31 | * @return Callback 数据 32 | */ 33 | Callback profile(String token); 34 | } -------------------------------------------------------------------------------- /flows-common/src/main/java/io/hanbings/flows/common/interfaces/Profile.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2023 Flows 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package io.hanbings.flows.common.interfaces; 18 | 19 | /** 20 | * 个人资料数据模型 21 | */ 22 | @SuppressWarnings("unused") 23 | public interface Profile { 24 | /** 25 | * 错误信息 26 | */ 27 | interface Wrong { 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /flows-common/src/main/java/io/hanbings/flows/common/interfaces/Refresh.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2023 Flows 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package io.hanbings.flows.common.interfaces; 18 | 19 | /** 20 | * 用于 OAuth 重新授权(刷新)后所返回的数据模型 21 | * 通常包含 access token 作为权限凭据 22 | */ 23 | @SuppressWarnings("unused") 24 | public interface Refresh { 25 | /** 26 | * access token 27 | * 28 | * @return 字符串凭据 29 | */ 30 | String accessToken(); 31 | 32 | /** 33 | * 错误信息 34 | */ 35 | interface Wrong { 36 | /** 37 | * 错误信息 38 | * 39 | * @return 字符串错误信息 40 | */ 41 | String error(); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /flows-common/src/main/java/io/hanbings/flows/common/interfaces/Refreshable.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2023 Flows 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package io.hanbings.flows.common.interfaces; 18 | 19 | /** 20 | * 支持刷新的 OAuth 提供商适配将实现该接口 21 | * 22 | * @param 刷新后返回的数据模型 23 | * @param 错误信息 24 | */ 25 | @SuppressWarnings("unused") 26 | public interface Refreshable { 27 | /** 28 | * 刷新 token 29 | * 30 | * @param token 旧的凭据或刷新凭据 取决于提供商要求 31 | * @return Callback 数据 32 | */ 33 | Callback refresh(String token); 34 | } 35 | -------------------------------------------------------------------------------- /flows-common/src/main/java/io/hanbings/flows/common/interfaces/Request.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2023 Flows 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package io.hanbings.flows.common.interfaces; 18 | 19 | import lombok.AllArgsConstructor; 20 | import lombok.Getter; 21 | import lombok.Setter; 22 | import lombok.experimental.Accessors; 23 | 24 | import java.util.Map; 25 | 26 | /** 27 | * http 请求封装 28 | */ 29 | @SuppressWarnings("unused") 30 | public interface Request { 31 | /** 32 | * Get 请求 33 | * 34 | * @param serialization 解析器 35 | * @param proxy 代理 36 | * @param url 请求的 url 37 | * @return Response 数据 38 | */ 39 | Response get(Serialization serialization, Proxy proxy, String url); 40 | 41 | /** 42 | * Get 请求 43 | * 44 | * @param serialization 解析器 45 | * @param proxy 代理 46 | * @param url 请求的 url 47 | * @param params query 参数 48 | * @return Response 数据 49 | */ 50 | Response get(Serialization serialization, Proxy proxy, String url, Map params); 51 | 52 | /** 53 | * Get 请求 54 | * 55 | * @param serialization 解析器 56 | * @param proxy 代理 57 | * @param url 请求的 url 58 | * @param params query 参数 59 | * @param headers 添加 headers 60 | * @return Response 数据 61 | */ 62 | Response get(Serialization serialization, Proxy proxy, String url, 63 | Map params, Map headers); 64 | 65 | /** 66 | * Post 请求 67 | * 68 | * @param serialization 解析器 69 | * @param proxy 代理 70 | * @param url 请求的 url 71 | * @return Response 数据 72 | */ 73 | Response post(Serialization serialization, Proxy proxy, String url); 74 | 75 | /** 76 | * Post 请求 77 | * 78 | * @param serialization 解析器 79 | * @param proxy 代理 80 | * @param url 请求的 url 81 | * @param form 表单数据 82 | * @return Response 数据 83 | */ 84 | Response post(Serialization serialization, Proxy proxy, String url, Map form); 85 | 86 | /** 87 | * Post 请求 88 | * 89 | * @param serialization 解析器 90 | * @param proxy 代理 91 | * @param url 请求的 url 92 | * @param form 表单数据 93 | * @param headers 添加 headers 94 | * @return Response 数据 95 | */ 96 | Response post(Serialization serialization, Proxy proxy, String url, 97 | Map form, Map headers); 98 | 99 | @Setter 100 | @Getter 101 | @AllArgsConstructor 102 | @SuppressWarnings("unused") 103 | @Accessors(fluent = true, chain = true) 104 | class Proxy { 105 | java.net.Proxy.Type type; 106 | String host; 107 | int port; 108 | String username; 109 | String password; 110 | } 111 | } 112 | -------------------------------------------------------------------------------- /flows-common/src/main/java/io/hanbings/flows/common/interfaces/Response.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2023 Flows 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package io.hanbings.flows.common.interfaces; 18 | 19 | import java.util.Map; 20 | 21 | /** 22 | * 用于描述 http 请求所返回的数据的原始形式 23 | */ 24 | @SuppressWarnings("unused") 25 | public interface Response { 26 | /** 27 | * 是否发生了异常 28 | * 29 | * @return 是否异常 30 | */ 31 | boolean exception(); 32 | 33 | /** 34 | * 异常的数据 没有异常发生则为 null 35 | * 36 | * @return 异常 37 | */ 38 | Throwable throwable(); 39 | 40 | /** 41 | * 状态码 42 | * 43 | * @return 状态码 44 | */ 45 | int code(); 46 | 47 | /** 48 | * 请求的原始数据 49 | * 50 | * @return 字符串类型原始数据 51 | */ 52 | String raw(); 53 | 54 | /** 55 | * 如果数据是 json 则会被解析为 Map
56 | * 事实上大多数 OAuth 接口都返回 json
57 | * 因为这是 OAuth 协议所规定的
58 | * 所以这个方法大多数情况下不为 null 59 | * 60 | * @return json 转换而来的键值对 61 | */ 62 | Map data(); 63 | } 64 | -------------------------------------------------------------------------------- /flows-common/src/main/java/io/hanbings/flows/common/interfaces/Revokable.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2023 Flows 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package io.hanbings.flows.common.interfaces; 18 | 19 | /** 20 | * OAuth 提供商支持撤消 token 则会实现该接口 21 | * 22 | * @param 数据模型 23 | * @param 错误信息 24 | */ 25 | @SuppressWarnings("SpellCheckingInspection unused") 26 | public interface Revokable { 27 | /** 28 | * 使用具有权限的 token 撤消 token 29 | * 30 | * @param token 这个 token 由服务提供商决定 31 | * @return Callback 数据 32 | */ 33 | Callback revoke(String token); 34 | } 35 | -------------------------------------------------------------------------------- /flows-common/src/main/java/io/hanbings/flows/common/interfaces/Revoke.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2023 Flows 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package io.hanbings.flows.common.interfaces; 18 | 19 | /** 20 | * 撤消返回的数据模型
21 | * 因为该功能不在 OAuth 协议范围内
22 | * 此类型仅作泛型类型标记 23 | */ 24 | @SuppressWarnings("unused") 25 | public interface Revoke { 26 | /*s 27 | 错误信息 28 | */ 29 | interface Wrong { 30 | 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /flows-common/src/main/java/io/hanbings/flows/common/interfaces/Serialization.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2023 Flows 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package io.hanbings.flows.common.interfaces; 18 | 19 | import java.util.List; 20 | import java.util.Map; 21 | 22 | /** 23 | * json 解析器接口 24 | * 实现该接口以自定义解析器 25 | */ 26 | @SuppressWarnings("unused") 27 | public interface Serialization { 28 | /** 29 | * 从 json 解析到对象 30 | * 31 | * @param type 对象类型 32 | * @param raw json 原始数据 33 | * @param 对象类型 34 | * @return 对象 35 | */ 36 | T object(Class type, String raw); 37 | 38 | /** 39 | * 将 json 解析到键值对 40 | * 41 | * @param key 键类型 42 | * @param value 值类型 43 | * @param raw json 原始数据 44 | * @param 键类型 45 | * @param 值类型 46 | * @return 键值对 47 | */ 48 | Map map(Class key, Class value, String raw); 49 | 50 | /** 51 | * 将 json 解析到列表 52 | * 53 | * @param type 类型 54 | * @param raw json 原始数据 55 | * @param 列表类型 56 | * @return 列表 57 | */ 58 | List list(Class type, String raw); 59 | } 60 | -------------------------------------------------------------------------------- /flows-common/src/main/java/io/hanbings/flows/common/interfaces/State.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2023 Flows 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package io.hanbings.flows.common.interfaces; 18 | 19 | /** 20 | * state 接口 自定义 state 21 | */ 22 | @SuppressWarnings("unused") 23 | public interface State { 24 | /** 25 | * 添加一个有效 state 26 | * 27 | * @return state 28 | */ 29 | String add(); 30 | 31 | /** 32 | * 传入一个 state 33 | * 34 | * @param state 字符串类型 state 35 | */ 36 | void add(String state); 37 | 38 | /** 39 | * 查询是否存在 state 过期也判断为不存在 40 | * 41 | * @param state 字符串类型 state 42 | * @return 是否存在 43 | */ 44 | boolean has(String state); 45 | 46 | /** 47 | * 销毁 state 48 | * 49 | * @param state 字符串 state 50 | * @return 是否销毁成功 51 | */ 52 | boolean fire(String state); 53 | 54 | /** 55 | * 清空 56 | */ 57 | void empty(); 58 | 59 | /** 60 | * 清空 61 | */ 62 | void clean(); 63 | } 64 | -------------------------------------------------------------------------------- /flows-discord/build.gradle: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanbings/flows/3170ba366276be6987d16aa05db5d22045519cfa/flows-discord/build.gradle -------------------------------------------------------------------------------- /flows-discord/src/main/java/io/hanbings/flows/discord/DiscordAccess.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2023 Flows 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package io.hanbings.flows.discord; 18 | 19 | import com.fasterxml.jackson.annotation.JsonProperty; 20 | import com.google.gson.annotations.SerializedName; 21 | import io.hanbings.flows.common.interfaces.Access; 22 | import io.hanbings.flows.common.interfaces.Refresh; 23 | 24 | public record DiscordAccess( 25 | @JsonProperty("access_token") 26 | @SerializedName("access_token") 27 | String accessToken, 28 | @JsonProperty("token_type") 29 | @SerializedName("token_type") 30 | String tokenType, 31 | @JsonProperty("expires_in") 32 | @SerializedName("expires_in") 33 | long expiresIn, 34 | @JsonProperty("refresh_token") 35 | @SerializedName("refresh_token") 36 | String refreshToken, 37 | @JsonProperty("scope") 38 | @SerializedName("scope") 39 | String scope 40 | ) implements Access, Refresh { 41 | public record Wrong( 42 | @JsonProperty("error") 43 | @SerializedName("error") 44 | String error 45 | ) implements Access.Wrong, Refresh.Wrong { 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /flows-discord/src/main/java/io/hanbings/flows/discord/DiscordIdentify.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2023 Flows 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package io.hanbings.flows.discord; 18 | 19 | import com.fasterxml.jackson.annotation.JsonProperty; 20 | import com.google.gson.annotations.SerializedName; 21 | import io.hanbings.flows.common.interfaces.Identify; 22 | 23 | public record DiscordIdentify( 24 | @JsonProperty("id") 25 | @SerializedName("id") 26 | String openid, 27 | @JsonProperty("avatar_url") 28 | @SerializedName("avatar_url") 29 | String avatar, 30 | @JsonProperty("login") 31 | @SerializedName("login") 32 | String username, 33 | @JsonProperty("username") 34 | @SerializedName("username") 35 | String nickname, 36 | @JsonProperty("email") 37 | @SerializedName("email") 38 | String email, 39 | String phone 40 | ) implements Identify { 41 | public record Wrong( 42 | @JsonProperty("code") 43 | @SerializedName("code") 44 | int code, 45 | @JsonProperty("message") 46 | @SerializedName("message") 47 | String message 48 | ) implements Identify.Wrong { 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /flows-discord/src/main/java/io/hanbings/flows/discord/DiscordProfile.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2023 Flows 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package io.hanbings.flows.discord; 18 | 19 | import com.fasterxml.jackson.annotation.JsonProperty; 20 | import com.google.gson.annotations.SerializedName; 21 | import io.hanbings.flows.common.interfaces.Profile; 22 | 23 | public record DiscordProfile( 24 | @JsonProperty("premium_type") 25 | @SerializedName("premium_type") 26 | int premiumType, 27 | @JsonProperty("accent_color") 28 | @SerializedName("accent_color") 29 | int accentColor, 30 | @JsonProperty("flags") 31 | @SerializedName("flags") 32 | int flags, 33 | @JsonProperty("banner") 34 | @SerializedName("banner") 35 | String banner, 36 | @JsonProperty("id") 37 | @SerializedName("id") 38 | String id, 39 | @JsonProperty("avatar") 40 | @SerializedName("avatar") 41 | String avatar, 42 | @JsonProperty("public_flags") 43 | @SerializedName("public_flags") 44 | int publicFlags, 45 | @JsonProperty("username") 46 | @SerializedName("username") 47 | String username, 48 | @JsonProperty("discriminator") 49 | @SerializedName("discriminator") 50 | String discriminator, 51 | @JsonProperty("global_name") 52 | @SerializedName("global_name") 53 | String globalName, 54 | @JsonProperty("display_name") 55 | @SerializedName("display_name") 56 | String displayName, 57 | @JsonProperty("banner_color") 58 | @SerializedName("banner_color") 59 | String bannerColor, 60 | @JsonProperty("locale") 61 | @SerializedName("locale") 62 | String locale, 63 | @JsonProperty("mfa_enabled") 64 | @SerializedName("mfa_enabled") 65 | String mfaEnabled, 66 | @JsonProperty("avatar_description") 67 | @SerializedName("avatar_description") 68 | String avatarDescription 69 | ) implements Profile { 70 | public record Wrong( 71 | @JsonProperty("code") 72 | @SerializedName("code") 73 | int code, 74 | @JsonProperty("message") 75 | @SerializedName("message") 76 | String message 77 | ) implements Profile.Wrong { 78 | } 79 | } -------------------------------------------------------------------------------- /flows-discord/src/main/java/io/hanbings/flows/discord/DiscordRevoke.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2023 Flows 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package io.hanbings.flows.discord; 18 | 19 | import io.hanbings.flows.common.interfaces.Revoke; 20 | 21 | public record DiscordRevoke() implements Revoke { 22 | public record Wrong() implements Revoke.Wrong { 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /flows-dropbox/build.gradle: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanbings/flows/3170ba366276be6987d16aa05db5d22045519cfa/flows-dropbox/build.gradle -------------------------------------------------------------------------------- /flows-dropbox/src/main/java/io/hanbings/flows/dropbox/DropboxAccess.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2023 Flows 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package io.hanbings.flows.dropbox; 18 | 19 | import com.fasterxml.jackson.annotation.JsonProperty; 20 | import com.google.gson.annotations.SerializedName; 21 | import io.hanbings.flows.common.interfaces.Access; 22 | 23 | public record DropboxAccess( 24 | @JsonProperty("access_token") 25 | @SerializedName("access_token") 26 | String accessToken, 27 | @JsonProperty("expires_in") 28 | @SerializedName("expires_in") 29 | String expiresIn, 30 | @JsonProperty("token_type") 31 | @SerializedName("token_type") 32 | String tokenType, 33 | @JsonProperty("scope") 34 | @SerializedName("scope") 35 | String scope, 36 | @JsonProperty("account_id") 37 | @SerializedName("account_id") 38 | String accountId, 39 | @JsonProperty("team_id") 40 | @SerializedName("team_id") 41 | String teamId, 42 | @JsonProperty("refresh_token") 43 | @SerializedName("refresh_token") 44 | String refreshToken, 45 | @JsonProperty("id_token") 46 | @SerializedName("id_token") 47 | String idToken, 48 | @JsonProperty("uid") 49 | @SerializedName("uid") 50 | String uid 51 | ) implements Access { 52 | public record Wrong( 53 | @JsonProperty("error") 54 | @SerializedName("error") 55 | String error, 56 | @JsonProperty("error_description") 57 | @SerializedName("error_description") 58 | String errorDescription, 59 | @JsonProperty("state") 60 | @SerializedName("state") 61 | String state 62 | ) implements Access.Wrong { 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /flows-dropbox/src/main/java/io/hanbings/flows/dropbox/DropboxOAuth.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2023 Flows 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package io.hanbings.flows.dropbox; 18 | 19 | import io.hanbings.flows.common.OAuth; 20 | import io.hanbings.flows.common.OAuthCallback; 21 | import io.hanbings.flows.common.OAuthSerialization; 22 | import io.hanbings.flows.common.interfaces.Callback; 23 | import io.hanbings.flows.common.interfaces.Refreshable; 24 | import io.hanbings.flows.common.interfaces.Response; 25 | import io.hanbings.flows.common.interfaces.Revokable; 26 | 27 | import java.util.HashMap; 28 | import java.util.List; 29 | import java.util.Map; 30 | 31 | @SuppressWarnings("unused") 32 | public class DropboxOAuth 33 | extends 34 | OAuth 35 | implements 36 | Refreshable, 37 | Revokable { 38 | final String refreshment = "https://api.dropboxapi.com/oauth2/token"; 39 | final String revocation = "https://api.dropboxapi.com/2/auth/token/revoke"; 40 | 41 | private DropboxOAuth() { 42 | super(null, null, null, null); 43 | } 44 | 45 | public DropboxOAuth(String client, String secret, String redirect) { 46 | super( 47 | "https://www.dropbox.com/oauth2/authorize", 48 | "https://api.dropboxapi.com/oauth2/token", 49 | List.of(), 50 | Map.of() 51 | ); 52 | 53 | this.client(client); 54 | this.secret(secret); 55 | this.redirect(redirect); 56 | } 57 | 58 | public DropboxOAuth(String client, String secret, String redirect, 59 | List scopes, Map params) { 60 | super( 61 | "https://www.dropbox.com/oauth2/authorize", 62 | "https://api.dropboxapi.com/oauth2/token", 63 | scopes, 64 | params 65 | ); 66 | 67 | this.client(client); 68 | this.secret(secret); 69 | this.redirect(redirect); 70 | } 71 | 72 | @Override 73 | public String authorize(List scopes, Map params) { 74 | return super.authorize( 75 | scopes, 76 | new HashMap<>() {{ 77 | putAll(params); 78 | put("response_type", "code"); 79 | }} 80 | ); 81 | } 82 | 83 | @Override 84 | public Callback token(String code, String state, String redirect) { 85 | Response response = this.request() 86 | .get() 87 | .post( 88 | this.serialization().get(), 89 | this.proxy() == null ? null : this.proxy().get(), 90 | this.access(), 91 | Map.of( 92 | "client_id", this.client(), 93 | "client_secret", this.secret(), 94 | "grant_type", "authorization_code", 95 | "redirect_uri", redirect, 96 | "code", code 97 | ), 98 | Map.of( 99 | "Accept", "application/json", 100 | "Content-Type", "application/x-www-form-urlencoded" 101 | ) 102 | ); 103 | 104 | if (response.code() == 200) { 105 | DropboxAccess access = this.serialization() 106 | .get() 107 | .object(DropboxAccess.class, response.raw()); 108 | 109 | return OAuthCallback.response(access.accessToken(), access, null, response); 110 | 111 | } 112 | 113 | if (response.code() == 400) { 114 | DropboxAccess.Wrong wrong = this.serialization() 115 | .get() 116 | .object(DropboxAccess.Wrong.class, response.raw()); 117 | 118 | return OAuthCallback.response(null, null, wrong, response); 119 | } 120 | 121 | return OAuthCallback.exception( 122 | null, 123 | response.exception() ? response.throwable() : new IllegalArgumentException() 124 | ); 125 | } 126 | 127 | @Override 128 | public Callback revoke(String token) { 129 | Response response = this.request() 130 | .get() 131 | .post( 132 | new OAuthSerialization() { 133 | @Override 134 | public Map map(Class key, Class value, String raw) { 135 | return Map.of(); 136 | } 137 | }, 138 | this.proxy() == null ? null : this.proxy().get(), 139 | this.revocation, 140 | Map.of(), 141 | Map.of( 142 | "Authorization", String.format("Bearer %s", token) 143 | ) 144 | ); 145 | 146 | if (response.code() == 200) { 147 | DropboxRevoke access = this.serialization() 148 | .get() 149 | .object(DropboxRevoke.class, "{ }"); 150 | 151 | return OAuthCallback.response(null, access, null, response); 152 | } 153 | 154 | return OAuthCallback.exception( 155 | null, 156 | response.exception() ? response.throwable() : new IllegalArgumentException() 157 | ); 158 | } 159 | 160 | @Override 161 | public Callback refresh(String token) { 162 | Response response = this.request() 163 | .get() 164 | .post( 165 | this.serialization().get(), 166 | this.proxy() == null ? null : this.proxy().get(), 167 | this.access(), 168 | Map.of( 169 | "client_id", this.client(), 170 | "client_secret", this.secret(), 171 | "grant_type", "refresh_token", 172 | "refresh_token", token 173 | ), 174 | Map.of( 175 | "Accept", "application/json", 176 | "Content-Type", "application/x-www-form-urlencoded" 177 | ) 178 | ); 179 | 180 | if (response.code() == 200) { 181 | DropboxRefresh access = this.serialization() 182 | .get() 183 | .object(DropboxRefresh.class, response.raw()); 184 | 185 | return OAuthCallback.response(access.accessToken(), access, null, response); 186 | 187 | } 188 | 189 | if (response.code() == 400) { 190 | DropboxRefresh.Wrong wrong = this.serialization() 191 | .get() 192 | .object(DropboxRefresh.Wrong.class, response.raw()); 193 | 194 | return OAuthCallback.response(null, null, wrong, response); 195 | } 196 | 197 | return OAuthCallback.exception( 198 | null, 199 | response.exception() ? response.throwable() : new IllegalArgumentException() 200 | ); 201 | } 202 | } 203 | -------------------------------------------------------------------------------- /flows-dropbox/src/main/java/io/hanbings/flows/dropbox/DropboxRefresh.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2023 Flows 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package io.hanbings.flows.dropbox; 18 | 19 | import com.fasterxml.jackson.annotation.JsonProperty; 20 | import com.google.gson.annotations.SerializedName; 21 | import io.hanbings.flows.common.interfaces.Refresh; 22 | 23 | public record DropboxRefresh( 24 | @JsonProperty("access_token") 25 | @SerializedName("access_token") 26 | String accessToken, 27 | @JsonProperty("expires_in") 28 | @SerializedName("expires_in") 29 | String expiresIn, 30 | @JsonProperty("token_type") 31 | @SerializedName("token_type") 32 | String tokenType 33 | ) implements Refresh { 34 | public record Wrong( 35 | @JsonProperty("error") 36 | @SerializedName("error") 37 | String error, 38 | @JsonProperty("error_description") 39 | @SerializedName("error_description") 40 | String errorDescription, 41 | @JsonProperty("state") 42 | @SerializedName("state") 43 | String state 44 | ) implements Refresh.Wrong { 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /flows-dropbox/src/main/java/io/hanbings/flows/dropbox/DropboxRevoke.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2023 Flows 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package io.hanbings.flows.dropbox; 18 | 19 | import io.hanbings.flows.common.interfaces.Revoke; 20 | 21 | public record DropboxRevoke() implements Revoke { 22 | public record Wrong() implements Revoke.Wrong { 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /flows-ebay/build.gradle: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanbings/flows/3170ba366276be6987d16aa05db5d22045519cfa/flows-ebay/build.gradle -------------------------------------------------------------------------------- /flows-ebay/src/main/java/io/hanbings/flows/ebay/EbayAccess.java: -------------------------------------------------------------------------------- 1 | package io.hanbings.flows.ebay; 2 | 3 | import io.hanbings.flows.common.interfaces.Access; 4 | 5 | public record EbayAccess( 6 | String accessToken 7 | ) implements Access { 8 | public record Wrong( 9 | String error, 10 | String errorDescription 11 | ) implements Access.Wrong { 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /flows-ebay/src/main/java/io/hanbings/flows/ebay/EbayIdentify.java: -------------------------------------------------------------------------------- 1 | package io.hanbings.flows.ebay; 2 | 3 | public record EbayIdentify() { 4 | } 5 | -------------------------------------------------------------------------------- /flows-ebay/src/main/java/io/hanbings/flows/ebay/EbayOAuth.java: -------------------------------------------------------------------------------- 1 | package io.hanbings.flows.ebay; 2 | 3 | public class EbayOAuth { 4 | } 5 | -------------------------------------------------------------------------------- /flows-ebay/src/main/java/io/hanbings/flows/ebay/EbayProfile.java: -------------------------------------------------------------------------------- 1 | package io.hanbings.flows.ebay; 2 | 3 | public record EbayProfile() { 4 | } 5 | -------------------------------------------------------------------------------- /flows-etsy/build.gradle: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanbings/flows/3170ba366276be6987d16aa05db5d22045519cfa/flows-etsy/build.gradle -------------------------------------------------------------------------------- /flows-extra/build.gradle: -------------------------------------------------------------------------------- 1 | dependencies { 2 | // https://mvnrepository.com/artifact/com.squareup.okhttp3/okhttp 3 | implementation 'com.squareup.okhttp3:okhttp:4.10.0' 4 | } -------------------------------------------------------------------------------- /flows-extra/src/main/java/io/hanbings/flows/extra/OkhttpRequest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2023 Flows 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package io.hanbings.flows.extra; 18 | 19 | import io.hanbings.flows.common.OAuthResponse; 20 | import io.hanbings.flows.common.interfaces.Request; 21 | import io.hanbings.flows.common.interfaces.Response; 22 | import io.hanbings.flows.common.interfaces.Serialization; 23 | import okhttp3.Call; 24 | import okhttp3.FormBody; 25 | import okhttp3.OkHttpClient; 26 | import okhttp3.RequestBody; 27 | import org.jetbrains.annotations.Nullable; 28 | 29 | import java.io.IOException; 30 | import java.net.Authenticator; 31 | import java.net.InetSocketAddress; 32 | import java.net.PasswordAuthentication; 33 | import java.util.ArrayList; 34 | import java.util.List; 35 | import java.util.Map; 36 | import java.util.Objects; 37 | 38 | public class OkhttpRequest implements Request { 39 | OkHttpClient client; 40 | 41 | public OkhttpRequest() { 42 | client = new OkHttpClient(); 43 | } 44 | 45 | public OkhttpRequest(Proxy proxy) { 46 | client = client(proxy); 47 | } 48 | 49 | static OkHttpClient client(Proxy proxy) { 50 | Authenticator.setDefault(new Authenticator() { 51 | @Override 52 | protected PasswordAuthentication getPasswordAuthentication() { 53 | if (getRequestingHost().equalsIgnoreCase(proxy.host())) { 54 | if (proxy.port() == getRequestingPort()) { 55 | return new PasswordAuthentication(proxy.username(), proxy.password().toCharArray()); 56 | } 57 | } 58 | return null; 59 | } 60 | }); 61 | 62 | return new OkHttpClient.Builder() 63 | .proxy(new java.net.Proxy(proxy.type(), new InetSocketAddress(proxy.host(), proxy.port()))) 64 | .build(); 65 | } 66 | 67 | @Override 68 | public Response get(Serialization serialization, 69 | @Nullable Proxy proxy, String url) { 70 | return get(serialization, proxy, url, Map.of(), Map.of()); 71 | } 72 | 73 | @Override 74 | public Response get(Serialization serialization, 75 | @Nullable Proxy proxy, String url, Map params) { 76 | return get(serialization, proxy, url, params, Map.of()); 77 | } 78 | 79 | @Override 80 | public Response get( 81 | Serialization serialization, 82 | Proxy proxy, 83 | String url, 84 | Map params, 85 | Map headers 86 | ) { 87 | okhttp3.Request.Builder builder = new okhttp3.Request.Builder().url(url).get(); 88 | headers.forEach(builder::addHeader); 89 | okhttp3.Request request = builder.build(); 90 | Call call = proxy == null ? client.newCall(request) : client(proxy).newCall(request); 91 | 92 | try (okhttp3.Response response = call.execute()) { 93 | String content = Objects.requireNonNull(response.body()).string(); 94 | 95 | return new OAuthResponse( 96 | false, 97 | null, 98 | response.code(), 99 | content, 100 | serialization.map( 101 | String.class, 102 | String.class, 103 | content 104 | ) 105 | ); 106 | } catch (IOException e) { 107 | return new OAuthResponse(true, e, 0, null, null); 108 | } 109 | } 110 | 111 | @Override 112 | public Response post(Serialization serialization, 113 | @Nullable Proxy proxy, String url) { 114 | return this.post(serialization, proxy, url, Map.of(), Map.of()); 115 | } 116 | 117 | @Override 118 | public Response post(Serialization serialization, 119 | @Nullable Proxy proxy, String url, Map form) { 120 | return this.post(serialization, proxy, url, form, Map.of()); 121 | } 122 | 123 | @Override 124 | @SuppressWarnings("deprecation") 125 | public Response post( 126 | Serialization serialization, 127 | Proxy proxy, 128 | String url, 129 | Map form, 130 | Map headers 131 | ) { 132 | okhttp3.Request.Builder builder = new okhttp3.Request.Builder().url(url); 133 | 134 | if (form.size() > 0) { 135 | List keys = new ArrayList<>(); 136 | List values = new ArrayList<>(); 137 | 138 | form.forEach((k, v) -> { 139 | keys.add(k); 140 | values.add(v); 141 | }); 142 | 143 | builder.post(new FormBody(keys, values)); 144 | } else { 145 | builder.post(RequestBody.create(null, "")); 146 | } 147 | 148 | headers.forEach(builder::addHeader); 149 | okhttp3.Request request = builder.build(); 150 | Call call = proxy == null ? client.newCall(request) : client(proxy).newCall(request); 151 | 152 | try (okhttp3.Response response = call.execute()) { 153 | String content = Objects.requireNonNull(response.body()).string(); 154 | 155 | return new OAuthResponse( 156 | false, 157 | null, 158 | response.code(), 159 | content, 160 | serialization.map( 161 | String.class, 162 | String.class, 163 | content 164 | ) 165 | ); 166 | } catch (IOException e) { 167 | return new OAuthResponse(true, e, 0, null, null); 168 | } 169 | } 170 | } 171 | -------------------------------------------------------------------------------- /flows-facebook/build.gradle: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanbings/flows/3170ba366276be6987d16aa05db5d22045519cfa/flows-facebook/build.gradle -------------------------------------------------------------------------------- /flows-facebook/src/main/java/io/hanbings/flows/facebook/FacebookAccess.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2023 Flows 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package io.hanbings.flows.facebook; 18 | 19 | import com.google.gson.annotations.SerializedName; 20 | import io.hanbings.flows.common.interfaces.Access; 21 | 22 | public record FacebookAccess( 23 | @SerializedName("access_token") 24 | String accessToken 25 | ) implements Access { 26 | public record Wrong( 27 | @SerializedName("error") 28 | String error 29 | ) implements Access.Wrong { 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /flows-facebook/src/main/java/io/hanbings/flows/facebook/FacebookOAuth.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2023 Flows 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package io.hanbings.flows.facebook; 18 | 19 | import io.hanbings.flows.common.OAuth; 20 | 21 | public class FacebookOAuth extends OAuth { 22 | private FacebookOAuth() { 23 | super( 24 | "https://www.facebook.com/v15.0/dialog/oauth", 25 | "https://graph.facebook.com/v15.0/oauth/access_token", 26 | null, 27 | null 28 | ); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /flows-flickr/build.gradle: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanbings/flows/3170ba366276be6987d16aa05db5d22045519cfa/flows-flickr/build.gradle -------------------------------------------------------------------------------- /flows-github/build.gradle: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanbings/flows/3170ba366276be6987d16aa05db5d22045519cfa/flows-github/build.gradle -------------------------------------------------------------------------------- /flows-github/src/main/java/io/hanbings/flows/github/GithubAccess.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2023 Flows 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package io.hanbings.flows.github; 18 | 19 | import com.fasterxml.jackson.annotation.JsonProperty; 20 | import com.google.gson.annotations.SerializedName; 21 | import io.hanbings.flows.common.interfaces.Access; 22 | 23 | public record GithubAccess( 24 | @JsonProperty("access_token") 25 | @SerializedName("access_token") 26 | String accessToken, 27 | @JsonProperty("token_type") 28 | @SerializedName("token_type") 29 | String tokenType, 30 | @JsonProperty("scope") 31 | @SerializedName("scope") 32 | String scope 33 | ) implements Access { 34 | public record Wrong( 35 | @JsonProperty("error_uri") 36 | @SerializedName("error_uri") 37 | String errorUri, 38 | @JsonProperty("error") 39 | @SerializedName("error") 40 | String error, 41 | @JsonProperty("error_description") 42 | @SerializedName("error_description") 43 | String errorDescription 44 | ) implements Access.Wrong { 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /flows-github/src/main/java/io/hanbings/flows/github/GithubIdentify.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2023 Flows 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package io.hanbings.flows.github; 18 | 19 | import com.fasterxml.jackson.annotation.JsonProperty; 20 | import com.google.gson.annotations.SerializedName; 21 | import io.hanbings.flows.common.interfaces.Identify; 22 | 23 | import java.util.List; 24 | 25 | public record GithubIdentify( 26 | @JsonProperty("id") 27 | @SerializedName("id") 28 | String openid, 29 | @JsonProperty("avatar_url") 30 | @SerializedName("avatar_url") 31 | String avatar, 32 | @JsonProperty("login") 33 | @SerializedName("login") 34 | String username, 35 | @JsonProperty("name") 36 | @SerializedName("name") 37 | String nickname, 38 | @JsonProperty("email") 39 | @SerializedName("email") 40 | String email, 41 | String phone 42 | ) implements Identify { 43 | public record Wrong( 44 | @JsonProperty("message") 45 | @SerializedName("message") 46 | String message, 47 | @JsonProperty("documentation_url") 48 | @SerializedName("documentation_url") 49 | String documentationUrl 50 | ) implements Identify.Wrong { 51 | } 52 | 53 | public record Emails( 54 | @SerializedName("emails") 55 | List emails 56 | ) { 57 | 58 | } 59 | 60 | public record Email( 61 | @JsonProperty("visibility") 62 | @SerializedName("visibility") 63 | String visibility, 64 | @JsonProperty("verified") 65 | @SerializedName("verified") 66 | boolean verified, 67 | @JsonProperty("email") 68 | @SerializedName("email") 69 | String email, 70 | @JsonProperty("primary") 71 | @SerializedName("primary") 72 | boolean primary 73 | ) { 74 | 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /flows-github/src/main/java/io/hanbings/flows/github/GithubOAuth.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2023 Flows 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package io.hanbings.flows.github; 18 | 19 | import com.google.gson.Gson; 20 | import com.google.gson.reflect.TypeToken; 21 | import io.hanbings.flows.common.OAuth; 22 | import io.hanbings.flows.common.OAuthCallback; 23 | import io.hanbings.flows.common.OAuthSerialization; 24 | import io.hanbings.flows.common.interfaces.Callback; 25 | import io.hanbings.flows.common.interfaces.Identifiable; 26 | import io.hanbings.flows.common.interfaces.Profilable; 27 | import io.hanbings.flows.common.interfaces.Response; 28 | 29 | import java.util.HashMap; 30 | import java.util.List; 31 | import java.util.Map; 32 | 33 | @SuppressWarnings("unused") 34 | public class GithubOAuth 35 | extends 36 | OAuth 37 | implements 38 | Profilable, 39 | Identifiable { 40 | private GithubOAuth() { 41 | super(null, null, null, null); 42 | } 43 | 44 | public GithubOAuth(String client, String secret, String redirect) { 45 | super( 46 | "https://github.com/login/oauth/authorize", 47 | "https://github.com/login/oauth/access_token", 48 | List.of(), 49 | Map.of() 50 | ); 51 | 52 | this.client(client); 53 | this.secret(secret); 54 | this.redirect(redirect); 55 | } 56 | 57 | public GithubOAuth(String client, String secret, String redirect, 58 | List scopes, Map params) { 59 | super( 60 | "https://github.com/login/oauth/authorize", 61 | "https://github.com/login/oauth/access_token", 62 | scopes, 63 | params 64 | ); 65 | 66 | this.client(client); 67 | this.secret(secret); 68 | this.redirect(redirect); 69 | } 70 | 71 | @Override 72 | public Callback token(String code, String state, String redirect) { 73 | Response response = this.request() 74 | .get() 75 | .post( 76 | this.serialization().get(), 77 | this.proxy() == null ? null : this.proxy().get(), 78 | this.access(), 79 | Map.of( 80 | "client_id", this.client(), 81 | "client_secret", this.secret(), 82 | "redirect_uri", redirect, 83 | "code", code, 84 | "state", state 85 | ), 86 | Map.of( 87 | "Accept", "application/json", 88 | "Content-Type", "application/x-www-form-urlencoded" 89 | ) 90 | ); 91 | 92 | if (response.code() == 200) { 93 | if (serialization().get().map(String.class, String.class, response.raw()).containsKey("access_token")) { 94 | GithubAccess access = this.serialization() 95 | .get() 96 | .object(GithubAccess.class, response.raw()); 97 | 98 | return OAuthCallback.response(access.accessToken(), access, null, response); 99 | } else { 100 | GithubAccess.Wrong wrong = this.serialization() 101 | .get() 102 | .object(GithubAccess.Wrong.class, response.raw()); 103 | 104 | return OAuthCallback.response(null, null, wrong, response); 105 | } 106 | } 107 | 108 | return response.exception() ? 109 | OAuthCallback.exception(null, response.throwable()) : 110 | OAuthCallback.response(response); 111 | } 112 | 113 | @Override 114 | public Callback profile(String token) { 115 | Response response = request() 116 | .get() 117 | .get( 118 | this.serialization().get(), 119 | this.proxy() == null ? null : this.proxy().get(), 120 | "https://api.github.com/user", 121 | Map.of(), 122 | Map.of( 123 | "Accept", "application/vnd.github+json", 124 | "Authorization", String.format("Bearer %s", token), 125 | "X-GitHub-Api-Version", "2022-11-28" 126 | ) 127 | ); 128 | 129 | if (response.code() == 200) { 130 | GithubProfile profile = this.serialization() 131 | .get() 132 | .object(GithubProfile.class, response.raw()); 133 | 134 | return OAuthCallback.response(token, profile, null, response); 135 | } 136 | 137 | if (response.code() == 401) { 138 | GithubProfile.Wrong wrong = this.serialization() 139 | .get() 140 | .object(GithubProfile.Wrong.class, response.raw()); 141 | 142 | return OAuthCallback.response(null, null, wrong, response); 143 | } 144 | 145 | return response.exception() 146 | ? OAuthCallback.exception(null, response.throwable()) 147 | : OAuthCallback.response(response); 148 | } 149 | 150 | @Override 151 | public Callback identify(String token) { 152 | // headers 153 | Map headers = Map.of( 154 | "Accept", "application/vnd.github+json", 155 | "Authorization", String.format("Bearer %s", token), 156 | "X-GitHub-Api-Version", "2022-11-28" 157 | ); 158 | // profile 159 | Response profiles = request() 160 | .get() 161 | .get( 162 | serialization().get(), 163 | this.proxy() == null ? null : this.proxy().get(), 164 | "https://api.github.com/user", 165 | Map.of(), 166 | headers 167 | ); 168 | // email 169 | Response emails = request() 170 | .get() 171 | .get( 172 | new OAuthSerialization() { 173 | @Override 174 | public Map map(Class key, Class value, String raw) { 175 | List list = new Gson().fromJson(raw, new TypeToken>() { 176 | }.getType()); 177 | return new HashMap<>() {{ 178 | list.forEach(e -> put(e, null)); 179 | }}; 180 | } 181 | }, 182 | this.proxy() == null ? null : this.proxy().get(), 183 | "https://api.github.com/user/emails", 184 | Map.of(), 185 | headers 186 | ); 187 | 188 | // serialize 189 | if (profiles.code() == 200 && (emails.code() == 200 || emails.code() == 404)) { 190 | // serialize email 191 | // todo: 换用 getAsJsonArray 解析多个 json 组成的 Json 数组 192 | GithubIdentify.Emails email = this.serialization().get().object( 193 | GithubIdentify.Emails.class, 194 | "{\"emails\":" + emails.raw() + "}" 195 | ); 196 | GithubProfile profile = this.serialization().get().object(GithubProfile.class, profiles.raw()); 197 | 198 | GithubIdentify identify = new GithubIdentify( 199 | String.valueOf(profile.id()), 200 | profile.avatarUrl(), 201 | profile.login(), 202 | profile.name(), 203 | email.emails() == null ? null : (email.emails().size() == 0 ? null : email.emails().get(0).email()), 204 | null 205 | ); 206 | 207 | return OAuthCallback.response(token, identify, null, profiles); 208 | } 209 | 210 | if (profiles.exception()) return OAuthCallback.exception(token, profiles.throwable()); 211 | if (emails.exception()) return OAuthCallback.exception(token, emails.throwable()); 212 | 213 | return OAuthCallback.response(profiles.code() == 200 ? profiles : emails); 214 | } 215 | } 216 | -------------------------------------------------------------------------------- /flows-github/src/main/java/io/hanbings/flows/github/GithubProfile.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2023 Flows 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package io.hanbings.flows.github; 18 | 19 | import com.fasterxml.jackson.annotation.JsonProperty; 20 | import com.google.gson.annotations.SerializedName; 21 | import io.hanbings.flows.common.interfaces.Profile; 22 | 23 | @SuppressWarnings("SpellCheckingInspection") 24 | public record GithubProfile( 25 | @JsonProperty("gists_url") 26 | @SerializedName("gists_url") 27 | String gistsUrl, 28 | @JsonProperty("repos_url") 29 | @SerializedName("repos_url") 30 | String reposUrl, 31 | @JsonProperty("following_url") 32 | @SerializedName("following_url") 33 | String followingUrl, 34 | @JsonProperty("twitter_username") 35 | @SerializedName("twitter_username") 36 | String twitterUsername, 37 | @JsonProperty("bio") 38 | @SerializedName("bio") 39 | String bio, 40 | @JsonProperty("created_at") 41 | @SerializedName("created_at") 42 | String createdAt, 43 | @JsonProperty("login") 44 | @SerializedName("login") 45 | String login, 46 | @JsonProperty("type") 47 | @SerializedName("type") 48 | String type, 49 | @JsonProperty("blog") 50 | @SerializedName("blog") 51 | String blog, 52 | @JsonProperty("subscriptions_url") 53 | @SerializedName("subscriptions_url") 54 | String subscriptionsUrl, 55 | @JsonProperty("updated_at") 56 | @SerializedName("updated_at") 57 | String updatedAt, 58 | @JsonProperty("site_admin") 59 | @SerializedName("site_admin") 60 | boolean siteAdmin, 61 | @JsonProperty("company") 62 | @SerializedName("company") 63 | Object company, 64 | @JsonProperty("id") 65 | @SerializedName("id") 66 | int id, 67 | @JsonProperty("public_repos") 68 | @SerializedName("public_repos") 69 | int publicRepos, 70 | @JsonProperty("gravatar_id") 71 | @SerializedName("gravatar_id") 72 | String gravatarId, 73 | @JsonProperty("email") 74 | @SerializedName("email") 75 | Object email, 76 | @JsonProperty("organizations_url") 77 | @SerializedName("organizations_url") 78 | String organizationsUrl, 79 | @JsonProperty("hireable") 80 | @SerializedName("hireable") 81 | Object hireable, 82 | @JsonProperty("starred_url") 83 | @SerializedName("starred_url") 84 | String starredUrl, 85 | @JsonProperty("followers_url") 86 | @SerializedName("followers_url") 87 | String followersUrl, 88 | @JsonProperty("public_gists") 89 | @SerializedName("public_gists") 90 | int publicGists, 91 | @JsonProperty("url") 92 | @SerializedName("url") 93 | String url, 94 | @JsonProperty("received_events_url") 95 | @SerializedName("received_events_url") 96 | String receivedEventsUrl, 97 | @JsonProperty("followers") 98 | @SerializedName("followers") 99 | int followers, 100 | @JsonProperty("avatar_url") 101 | @SerializedName("avatar_url") 102 | String avatarUrl, 103 | @JsonProperty("events_url") 104 | @SerializedName("events_url") 105 | String eventsUrl, 106 | @JsonProperty("html_url") 107 | @SerializedName("html_url") 108 | String htmlUrl, 109 | @JsonProperty("following") 110 | @SerializedName("following") 111 | int following, 112 | @JsonProperty("name") 113 | @SerializedName("name") 114 | String name, 115 | @JsonProperty("location") 116 | @SerializedName("location") 117 | String location, 118 | @JsonProperty("node_id") 119 | @SerializedName("node_id") 120 | String nodeId 121 | ) implements Profile { 122 | public record Wrong( 123 | @JsonProperty("message") 124 | @SerializedName("message") 125 | String message, 126 | @JsonProperty("documentation_url") 127 | @SerializedName("documentation_url") 128 | String documentationUrl 129 | ) implements Profile.Wrong { 130 | 131 | } 132 | } -------------------------------------------------------------------------------- /flows-gitlab/build.gradle: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanbings/flows/3170ba366276be6987d16aa05db5d22045519cfa/flows-gitlab/build.gradle -------------------------------------------------------------------------------- /flows-gitlab/src/main/java/io/hanbings/flows/gitlab/GitlabAccess.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2023 Flows 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package io.hanbings.flows.gitlab; 18 | 19 | import io.hanbings.flows.common.interfaces.Access; 20 | 21 | public record GitlabAccess( 22 | String accessToken 23 | ) implements Access { 24 | public record Wrong( 25 | String error, 26 | String errorDescription 27 | ) implements Access.Wrong { 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /flows-gitlab/src/main/java/io/hanbings/flows/gitlab/GitlabIdentify.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2023 Flows 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package io.hanbings.flows.gitlab; 18 | 19 | public record GitlabIdentify() { 20 | } 21 | -------------------------------------------------------------------------------- /flows-gitlab/src/main/java/io/hanbings/flows/gitlab/GitlabOAuth.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2023 Flows 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package io.hanbings.flows.gitlab; 18 | 19 | import io.hanbings.flows.common.OAuth; 20 | 21 | import java.util.List; 22 | import java.util.Map; 23 | 24 | public class GitlabOAuth extends OAuth { 25 | private GitlabOAuth() { 26 | super(null, null, null, null); 27 | } 28 | 29 | public GitlabOAuth(String client, String secret, String redirect) { 30 | super( 31 | "https://gitlab.com/oauth/authorize", 32 | "https://gitlab.com/oauth/token", 33 | List.of(), 34 | Map.of() 35 | ); 36 | 37 | this.client(client); 38 | this.secret(secret); 39 | this.redirect(redirect); 40 | } 41 | 42 | public GitlabOAuth(String client, String secret, String redirect, 43 | List scopes, Map params) { 44 | super( 45 | "https://gitlab.com/oauth/authorize", 46 | "https://gitlab.com/oauth/token", 47 | scopes, 48 | params 49 | ); 50 | 51 | this.client(client); 52 | this.secret(secret); 53 | this.redirect(redirect); 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /flows-gitlab/src/main/java/io/hanbings/flows/gitlab/GitlabProfile.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2023 Flows 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package io.hanbings.flows.gitlab; 18 | 19 | public record GitlabProfile() { 20 | } 21 | -------------------------------------------------------------------------------- /flows-google/build.gradle: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanbings/flows/3170ba366276be6987d16aa05db5d22045519cfa/flows-google/build.gradle -------------------------------------------------------------------------------- /flows-google/src/main/java/io/hanbings/flows/google/GoogleAccess.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2023 Flows 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package io.hanbings.flows.google; 18 | 19 | import com.fasterxml.jackson.annotation.JsonProperty; 20 | import com.google.gson.annotations.SerializedName; 21 | import io.hanbings.flows.common.interfaces.Access; 22 | import io.hanbings.flows.common.interfaces.Refresh; 23 | 24 | public record GoogleAccess( 25 | @JsonProperty("access_token") 26 | @SerializedName("access_token") 27 | String accessToken, 28 | @JsonProperty("expires_in") 29 | @SerializedName("expires_in") 30 | String expiresIn, 31 | @JsonProperty("refresh_token") 32 | @SerializedName("refresh_token") 33 | String refreshToken, 34 | @JsonProperty("scope") 35 | @SerializedName("scope") 36 | String scope, 37 | @JsonProperty("token_type") 38 | @SerializedName("token_type") 39 | String tokenType 40 | ) implements Access, Refresh { 41 | public record Wrong( 42 | @JsonProperty("error") 43 | @SerializedName("error") 44 | String error, 45 | @JsonProperty("error_description") 46 | @SerializedName("error_description") 47 | String errorDescription 48 | ) implements Access.Wrong, Refresh.Wrong { 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /flows-google/src/main/java/io/hanbings/flows/google/GoogleIdentify.java: -------------------------------------------------------------------------------- 1 | package io.hanbings.flows.google; 2 | 3 | import com.fasterxml.jackson.annotation.JsonProperty; 4 | import com.google.gson.annotations.SerializedName; 5 | import io.hanbings.flows.common.interfaces.Identify; 6 | 7 | public record GoogleIdentify( 8 | @JsonProperty("sub") 9 | @SerializedName("sub") 10 | String openid, 11 | @JsonProperty("picture") 12 | @SerializedName("picture") 13 | String avatar, 14 | @JsonProperty("name") 15 | @SerializedName("name") 16 | String username, 17 | @JsonProperty("username") 18 | @SerializedName("username") 19 | String nickname, 20 | @JsonProperty("email") 21 | @SerializedName("email") 22 | String email, 23 | String phone 24 | ) implements Identify { 25 | public record Wrong( 26 | @JsonProperty("error") 27 | @SerializedName("error") 28 | String error, 29 | @JsonProperty("error_description") 30 | @SerializedName("error_description") 31 | String errorDescription 32 | ) implements Identify.Wrong { 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /flows-google/src/main/java/io/hanbings/flows/google/GoogleProfile.java: -------------------------------------------------------------------------------- 1 | package io.hanbings.flows.google; 2 | 3 | import com.fasterxml.jackson.annotation.JsonProperty; 4 | import com.google.gson.annotations.SerializedName; 5 | import io.hanbings.flows.common.interfaces.Profile; 6 | 7 | public record GoogleProfile( 8 | @JsonProperty("sub") 9 | @SerializedName("sub") 10 | String sub, 11 | @JsonProperty("name") 12 | @SerializedName("name") 13 | String name, 14 | @JsonProperty("given_name") 15 | @SerializedName("given_name") 16 | String givenName, 17 | @JsonProperty("family_name") 18 | @SerializedName("family_name") 19 | String familyName, 20 | @JsonProperty("picture") 21 | @SerializedName("picture") 22 | String picture, 23 | @JsonProperty("email") 24 | @SerializedName("email") 25 | String email, 26 | @JsonProperty("locale") 27 | @SerializedName("locale") 28 | String locale 29 | ) implements Profile { 30 | public record Wrong( 31 | @JsonProperty("error") 32 | @SerializedName("error") 33 | String error, 34 | @JsonProperty("error_description") 35 | @SerializedName("error_description") 36 | String errorDescription 37 | ) implements Profile.Wrong { 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /flows-google/src/main/java/io/hanbings/flows/google/GoogleRevoke.java: -------------------------------------------------------------------------------- 1 | package io.hanbings.flows.google; 2 | 3 | import com.fasterxml.jackson.annotation.JsonProperty; 4 | import com.google.gson.annotations.SerializedName; 5 | import io.hanbings.flows.common.interfaces.Revoke; 6 | 7 | public record GoogleRevoke() implements Revoke { 8 | public record Wrong( 9 | @JsonProperty("error") 10 | @SerializedName("error") 11 | String error, 12 | @JsonProperty("error_description") 13 | @SerializedName("error_description") 14 | String errorDescription 15 | ) implements Revoke.Wrong { 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /flows-imgur/build.gradle: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanbings/flows/3170ba366276be6987d16aa05db5d22045519cfa/flows-imgur/build.gradle -------------------------------------------------------------------------------- /flows-instagram/build.gradle: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanbings/flows/3170ba366276be6987d16aa05db5d22045519cfa/flows-instagram/build.gradle -------------------------------------------------------------------------------- /flows-line/build.gradle: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanbings/flows/3170ba366276be6987d16aa05db5d22045519cfa/flows-line/build.gradle -------------------------------------------------------------------------------- /flows-microsoft/build.gradle: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanbings/flows/3170ba366276be6987d16aa05db5d22045519cfa/flows-microsoft/build.gradle -------------------------------------------------------------------------------- /flows-microsoft/src/main/java/io/hanbings/flows/microsoft/MicrosoftAccess.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2023 Flows 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package io.hanbings.flows.microsoft; 18 | 19 | import com.fasterxml.jackson.annotation.JsonProperty; 20 | import com.google.gson.annotations.SerializedName; 21 | import io.hanbings.flows.common.interfaces.Access; 22 | import io.hanbings.flows.common.interfaces.Refresh; 23 | 24 | import java.util.List; 25 | 26 | public record MicrosoftAccess( 27 | @JsonProperty("access_token") 28 | @SerializedName("access_token") 29 | String accessToken, 30 | @JsonProperty("token_type") 31 | @SerializedName("token_type") 32 | String tokenType, 33 | @JsonProperty("expires_in") 34 | @SerializedName("expires_in") 35 | String expiresIn, 36 | @JsonProperty("scope") 37 | @SerializedName("scope") 38 | String scope, 39 | @JsonProperty("refresh_token") 40 | @SerializedName("refresh_token") 41 | String refreshToken, 42 | @JsonProperty("id_token") 43 | @SerializedName("id_token") 44 | String idToken 45 | ) implements Access, Refresh { 46 | public record Wrong( 47 | @JsonProperty("error") 48 | @SerializedName("error") 49 | String error, 50 | @JsonProperty("error_description") 51 | @SerializedName("error_description") 52 | String errorDescription, 53 | @JsonProperty("error_codes") 54 | @SerializedName("error_codes") 55 | List errorCodes, 56 | @JsonProperty("timestamp") 57 | @SerializedName("timestamp") 58 | String timestamp, 59 | @JsonProperty("trace_id") 60 | @SerializedName("trace_id") 61 | String traceId, 62 | @JsonProperty("correlation_id") 63 | @SerializedName("correlation_id") 64 | String correlationId 65 | ) implements Access.Wrong, Refresh.Wrong { 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /flows-microsoft/src/main/java/io/hanbings/flows/microsoft/MicrosoftCommonOAuth.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2023 Flows 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package io.hanbings.flows.microsoft; 18 | 19 | import java.util.List; 20 | import java.util.Map; 21 | 22 | @SuppressWarnings("unused") 23 | public class MicrosoftCommonOAuth extends MicrosoftOAuth { 24 | private MicrosoftCommonOAuth() { 25 | super(null, null, null, null, null, null, null); 26 | } 27 | 28 | public MicrosoftCommonOAuth(String client, String secret, String redirect) { 29 | super( 30 | "https://login.microsoftonline.com/common/oauth2/v2.0/authorize", 31 | "https://login.microsoftonline.com/common/oauth2/v2.0/token", 32 | client, 33 | secret, 34 | redirect, 35 | List.of(), 36 | Map.of() 37 | ); 38 | } 39 | 40 | public MicrosoftCommonOAuth(String client, String secret, String redirect, 41 | List scopes, Map params) { 42 | super( 43 | "https://login.microsoftonline.com/common/oauth2/v2.0/authorize", 44 | "https://login.microsoftonline.com/common/oauth2/v2.0/token", 45 | client, 46 | secret, 47 | redirect, 48 | scopes, 49 | params 50 | ); 51 | } 52 | 53 | @Override 54 | @SuppressWarnings("all") 55 | public String refreshment() { 56 | return "https://login.microsoftonline.com/common/oauth2/v2.0/token"; 57 | } 58 | 59 | @Override 60 | @SuppressWarnings("all") 61 | public String revocation() { 62 | return "https://login.microsoftonline.com/common/oauth2/v2.0/logout"; 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /flows-microsoft/src/main/java/io/hanbings/flows/microsoft/MicrosoftConsumersOAuth.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2023 Flows 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package io.hanbings.flows.microsoft; 18 | 19 | import java.util.List; 20 | import java.util.Map; 21 | 22 | @SuppressWarnings("unused") 23 | public class MicrosoftConsumersOAuth extends MicrosoftOAuth { 24 | private MicrosoftConsumersOAuth() { 25 | super(null, null, null, null, null, null, null); 26 | } 27 | 28 | public MicrosoftConsumersOAuth(String client, String secret, String redirect) { 29 | super( 30 | "https://login.microsoftonline.com/consumers/oauth2/v2.0/authorize", 31 | "https://login.microsoftonline.com/consumers/oauth2/v2.0/token", 32 | client, 33 | secret, 34 | redirect, 35 | List.of(), 36 | Map.of() 37 | ); 38 | } 39 | 40 | public MicrosoftConsumersOAuth(String client, String secret, String redirect, 41 | List scopes, Map params) { 42 | super( 43 | "https://login.microsoftonline.com/consumers/oauth2/v2.0/authorize", 44 | "https://login.microsoftonline.com/consumers/oauth2/v2.0/token", 45 | client, 46 | secret, 47 | redirect, 48 | scopes, 49 | params 50 | ); 51 | } 52 | 53 | @Override 54 | public String refreshment() { 55 | return "https://login.microsoftonline.com/consumers/oauth2/v2.0/token"; 56 | } 57 | 58 | @Override 59 | public String revocation() { 60 | return "https://login.microsoftonline.com/consumers/oauth2/v2.0/logout"; 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /flows-microsoft/src/main/java/io/hanbings/flows/microsoft/MicrosoftIdentify.java: -------------------------------------------------------------------------------- 1 | package io.hanbings.flows.microsoft; 2 | 3 | import com.fasterxml.jackson.annotation.JsonProperty; 4 | import com.google.gson.annotations.SerializedName; 5 | import io.hanbings.flows.common.interfaces.Identify; 6 | 7 | import java.util.List; 8 | 9 | public record MicrosoftIdentify( 10 | @JsonProperty("id") 11 | @SerializedName("id") 12 | String openid, 13 | String avatar, 14 | @JsonProperty("givenName") 15 | @SerializedName("givenName") 16 | String username, 17 | @JsonProperty("displayName") 18 | @SerializedName("displayName") 19 | String nickname, 20 | @JsonProperty("mail") 21 | @SerializedName("mail") 22 | String email, 23 | @JsonProperty("mobilePhone") 24 | @SerializedName("mobilePhone") 25 | String phone 26 | ) implements Identify { 27 | public record Wrong( 28 | @JsonProperty("error") 29 | @SerializedName("error") 30 | String error, 31 | @JsonProperty("error_description") 32 | @SerializedName("error_description") 33 | String errorDescription, 34 | @JsonProperty("error_codes") 35 | @SerializedName("error_codes") 36 | List errorCodes, 37 | @JsonProperty("timestamp") 38 | @SerializedName("timestamp") 39 | String timestamp, 40 | @JsonProperty("trace_id") 41 | @SerializedName("trace_id") 42 | String traceId, 43 | @JsonProperty("correlation_id") 44 | @SerializedName("correlation_id") 45 | String correlationId 46 | ) implements Identify.Wrong { 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /flows-microsoft/src/main/java/io/hanbings/flows/microsoft/MicrosoftOrganizationsOAuth.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2023 Flows 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package io.hanbings.flows.microsoft; 18 | 19 | import java.util.List; 20 | import java.util.Map; 21 | 22 | @SuppressWarnings("unused") 23 | public class MicrosoftOrganizationsOAuth extends MicrosoftOAuth { 24 | private MicrosoftOrganizationsOAuth() { 25 | super(null, null, null, null, null, null, null); 26 | } 27 | 28 | public MicrosoftOrganizationsOAuth(String client, String secret, String redirect) { 29 | super( 30 | "https://login.microsoftonline.com/organizations/oauth2/v2.0/authorize", 31 | "https://login.microsoftonline.com/organizations/oauth2/v2.0/token", 32 | client, 33 | secret, 34 | redirect, 35 | List.of(), 36 | Map.of() 37 | ); 38 | } 39 | 40 | public MicrosoftOrganizationsOAuth(String client, String secret, String redirect, 41 | List scopes, Map params) { 42 | super( 43 | "https://login.microsoftonline.com/organizations/oauth2/v2.0/authorize", 44 | "https://login.microsoftonline.com/organizations/oauth2/v2.0/token", 45 | client, 46 | secret, 47 | redirect, 48 | scopes, 49 | params 50 | ); 51 | } 52 | 53 | @Override 54 | public String refreshment() { 55 | return "https://login.microsoftonline.com/organizations/oauth2/v2.0/token"; 56 | } 57 | 58 | @Override 59 | public String revocation() { 60 | return "https://login.microsoftonline.com/organizations/oauth2/v2.0/logout"; 61 | } 62 | } -------------------------------------------------------------------------------- /flows-microsoft/src/main/java/io/hanbings/flows/microsoft/MicrosoftProfile.java: -------------------------------------------------------------------------------- 1 | package io.hanbings.flows.microsoft; 2 | 3 | import com.fasterxml.jackson.annotation.JsonProperty; 4 | import com.google.gson.annotations.SerializedName; 5 | import io.hanbings.flows.common.interfaces.Profile; 6 | 7 | import java.util.List; 8 | 9 | public record MicrosoftProfile( 10 | @JsonProperty("businessPhones") 11 | @SerializedName("businessPhones") 12 | List businessPhones, 13 | @JsonProperty("displayName") 14 | @SerializedName("displayName") 15 | String displayName, 16 | @JsonProperty("givenName") 17 | @SerializedName("givenName") 18 | String givenName, 19 | @JsonProperty("jobTitle") 20 | @SerializedName("jobTitle") 21 | String jobTitle, 22 | @JsonProperty("mail") 23 | @SerializedName("mail") 24 | String mail, 25 | @JsonProperty("mobilePhone") 26 | @SerializedName("mobilePhone") 27 | String mobilePhone, 28 | @JsonProperty("officeLocation") 29 | @SerializedName("officeLocation") 30 | String officeLocation, 31 | @JsonProperty("preferredLanguage") 32 | @SerializedName("preferredLanguage") 33 | String preferredLanguage, 34 | @JsonProperty("surname") 35 | @SerializedName("surname") 36 | String surname, 37 | @JsonProperty("userPrincipalName") 38 | @SerializedName("userPrincipalName") 39 | String userPrincipalName, 40 | @JsonProperty("id") 41 | @SerializedName("id") 42 | String id 43 | ) implements Profile { 44 | public record Wrong( 45 | @JsonProperty("error") 46 | @SerializedName("error") 47 | String error, 48 | @JsonProperty("error_description") 49 | @SerializedName("error_description") 50 | String errorDescription, 51 | @JsonProperty("error_codes") 52 | @SerializedName("error_codes") 53 | List errorCodes, 54 | @JsonProperty("timestamp") 55 | @SerializedName("timestamp") 56 | String timestamp, 57 | @JsonProperty("trace_id") 58 | @SerializedName("trace_id") 59 | String traceId, 60 | @JsonProperty("correlation_id") 61 | @SerializedName("correlation_id") 62 | String correlationId 63 | ) implements Profile.Wrong { 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /flows-microsoft/src/main/java/io/hanbings/flows/microsoft/MicrosoftRevoke.java: -------------------------------------------------------------------------------- 1 | package io.hanbings.flows.microsoft; 2 | 3 | import com.fasterxml.jackson.annotation.JsonProperty; 4 | import com.google.gson.annotations.SerializedName; 5 | import io.hanbings.flows.common.interfaces.Revoke; 6 | 7 | import java.util.List; 8 | 9 | public record MicrosoftRevoke() implements Revoke { 10 | public record Wrong( 11 | @JsonProperty("error") 12 | @SerializedName("error") 13 | String error, 14 | @JsonProperty("error_description") 15 | @SerializedName("error_description") 16 | String errorDescription, 17 | @JsonProperty("error_codes") 18 | @SerializedName("error_codes") 19 | List errorCodes, 20 | @JsonProperty("timestamp") 21 | @SerializedName("timestamp") 22 | String timestamp, 23 | @JsonProperty("trace_id") 24 | @SerializedName("trace_id") 25 | String traceId, 26 | @JsonProperty("correlation_id") 27 | @SerializedName("correlation_id") 28 | String correlationId 29 | ) implements Revoke.Wrong { 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /flows-pinterest/build.gradle: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanbings/flows/3170ba366276be6987d16aa05db5d22045519cfa/flows-pinterest/build.gradle -------------------------------------------------------------------------------- /flows-qq/build.gradle: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanbings/flows/3170ba366276be6987d16aa05db5d22045519cfa/flows-qq/build.gradle -------------------------------------------------------------------------------- /flows-qq/src/main/java/io/hanbings/flows/qq/QQAccess.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2023 Flows 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package io.hanbings.flows.qq; 18 | 19 | import com.fasterxml.jackson.annotation.JsonProperty; 20 | import com.google.gson.annotations.SerializedName; 21 | import io.hanbings.flows.common.interfaces.Access; 22 | import io.hanbings.flows.common.interfaces.Refresh; 23 | 24 | public record QQAccess( 25 | @JsonProperty("access_token") 26 | @SerializedName("access_token") 27 | String accessToken, 28 | @JsonProperty("expires_in") 29 | @SerializedName("expires_in") 30 | long expiresIn, 31 | @JsonProperty("refresh_token") 32 | @SerializedName("refresh_token") 33 | String refreshToken 34 | ) implements Access, Refresh { 35 | public record Wrong( 36 | @JsonProperty("msg") 37 | @SerializedName("msg") 38 | String error, 39 | @JsonProperty("code") 40 | @SerializedName("code") 41 | int code 42 | ) implements Access.Wrong, Refresh.Wrong { 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /flows-qq/src/main/java/io/hanbings/flows/qq/QQIdentify.java: -------------------------------------------------------------------------------- 1 | package io.hanbings.flows.qq; 2 | 3 | import com.fasterxml.jackson.annotation.JsonProperty; 4 | import com.google.gson.annotations.SerializedName; 5 | import io.hanbings.flows.common.interfaces.Identify; 6 | 7 | @SuppressWarnings("SpellCheckingInspection") 8 | public record QQIdentify( 9 | @JsonProperty("openid") 10 | @SerializedName("openid") 11 | String openid, 12 | @JsonProperty("figureurl_qq_1") 13 | @SerializedName("figureurl_qq_1") 14 | String avatar, 15 | @JsonProperty("nickname") 16 | @SerializedName("nickname") 17 | String username, 18 | @JsonProperty("name") 19 | @SerializedName("name") 20 | String nickname, 21 | String email, 22 | String phone 23 | ) implements Identify { 24 | public record Wrong( 25 | @JsonProperty("code") 26 | @SerializedName("code") 27 | int code, 28 | @JsonProperty("msg") 29 | @SerializedName("msg") 30 | String msg 31 | ) implements Identify.Wrong { 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /flows-qq/src/main/java/io/hanbings/flows/qq/QQProfile.java: -------------------------------------------------------------------------------- 1 | package io.hanbings.flows.qq; 2 | 3 | import com.fasterxml.jackson.annotation.JsonProperty; 4 | import com.google.gson.annotations.SerializedName; 5 | import io.hanbings.flows.common.interfaces.Profile; 6 | 7 | @SuppressWarnings("SpellCheckingInspection") 8 | public record QQProfile( 9 | @JsonProperty("ret") 10 | @SerializedName("ret") 11 | int ret, 12 | @JsonProperty("msg") 13 | @SerializedName("msg") 14 | String msg, 15 | @JsonProperty("is_lost") 16 | @SerializedName("is_lost") 17 | int isLost, 18 | @JsonProperty("nickname") 19 | @SerializedName("nickname") 20 | String nickname, 21 | @JsonProperty("figureurl") 22 | @SerializedName("figureurl") 23 | String figureurl, 24 | @JsonProperty("figureurl_1") 25 | @SerializedName("figureurl_1") 26 | String figureurl_1, 27 | @JsonProperty("figureurl_2") 28 | @SerializedName("figureurl_2") 29 | String figureurl_2, 30 | @JsonProperty("figureurl_qq_1") 31 | @SerializedName("figureurl_qq_1") 32 | String figureurl_qq_1, 33 | @JsonProperty("figureurl_qq_2") 34 | @SerializedName("figureurl_qq_2") 35 | String figureurl_qq_2, 36 | @JsonProperty("gender") 37 | @SerializedName("gender") 38 | String gender, 39 | @JsonProperty("gender_type") 40 | @SerializedName("gender_type") 41 | int genderType, 42 | @JsonProperty("province") 43 | @SerializedName("province") 44 | String province, 45 | @JsonProperty("city") 46 | @SerializedName("city") 47 | String city, 48 | @JsonProperty("year") 49 | @SerializedName("year") 50 | int year, 51 | @JsonProperty("constellation") 52 | @SerializedName("constellation") 53 | String constellation, 54 | @JsonProperty("is_yellow_vip") 55 | @SerializedName("is_yellow_vip") 56 | String isYellowVip, 57 | @JsonProperty("yellow_vip_level") 58 | @SerializedName("yellow_vip_level") 59 | int yellowVipLevel, 60 | @JsonProperty("is_yellow_year_vip") 61 | @SerializedName("is_yellow_year_vip") 62 | int isYellowYearVip 63 | 64 | ) implements Profile { 65 | public record Wrong( 66 | @JsonProperty("code") 67 | @SerializedName("code") 68 | int code, 69 | @JsonProperty("msg") 70 | @SerializedName("msg") 71 | String msg 72 | ) implements Profile.Wrong { 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /flows-reddit/build.gradle: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanbings/flows/3170ba366276be6987d16aa05db5d22045519cfa/flows-reddit/build.gradle -------------------------------------------------------------------------------- /flows-soundcloud/build.gradle: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanbings/flows/3170ba366276be6987d16aa05db5d22045519cfa/flows-soundcloud/build.gradle -------------------------------------------------------------------------------- /flows-spotify/build.gradle: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanbings/flows/3170ba366276be6987d16aa05db5d22045519cfa/flows-spotify/build.gradle -------------------------------------------------------------------------------- /flows-stackoverflow/build.gradle: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanbings/flows/3170ba366276be6987d16aa05db5d22045519cfa/flows-stackoverflow/build.gradle -------------------------------------------------------------------------------- /flows-tiktok/build.gradle: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanbings/flows/3170ba366276be6987d16aa05db5d22045519cfa/flows-tiktok/build.gradle -------------------------------------------------------------------------------- /flows-tiktok/src/main/java/io/hanbings/flows/tiktok/TiktokAccess.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2023 Flows 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package io.hanbings.flows.tiktok; 18 | 19 | import io.hanbings.flows.common.interfaces.Access; 20 | 21 | public record TiktokAccess( 22 | String accessToken 23 | ) implements Access { 24 | public record Wrong( 25 | String error, 26 | String errorDescription 27 | ) implements Access.Wrong { 28 | } 29 | } -------------------------------------------------------------------------------- /flows-tiktok/src/main/java/io/hanbings/flows/tiktok/TiktokIdentify.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2023 Flows 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package io.hanbings.flows.tiktok; 18 | 19 | public record TiktokIdentify() { 20 | } 21 | -------------------------------------------------------------------------------- /flows-tiktok/src/main/java/io/hanbings/flows/tiktok/TiktokOAuth.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2023 Flows 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package io.hanbings.flows.tiktok; 18 | 19 | import io.hanbings.flows.common.OAuth; 20 | 21 | import java.util.List; 22 | import java.util.Map; 23 | 24 | public class TiktokOAuth extends OAuth { 25 | private TiktokOAuth() { 26 | super(null, null, null, null); 27 | } 28 | 29 | public TiktokOAuth(String client, String secret, String redirect) { 30 | super( 31 | "https://www.tiktok.com/auth/authorize/", 32 | "https://open-api.tiktok.com/oauth/access_token/", 33 | List.of(), 34 | Map.of() 35 | ); 36 | 37 | this.client(client); 38 | this.secret(secret); 39 | this.redirect(redirect); 40 | } 41 | 42 | public TiktokOAuth(String client, String secret, String redirect, 43 | List scopes, Map params) { 44 | super( 45 | "https://www.tiktok.com/auth/authorize/", 46 | "https://open-api.tiktok.com/oauth/access_token/", 47 | scopes, 48 | params 49 | ); 50 | 51 | this.client(client); 52 | this.secret(secret); 53 | this.redirect(redirect); 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /flows-tiktok/src/main/java/io/hanbings/flows/tiktok/TiktokProfile.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2023 Flows 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package io.hanbings.flows.tiktok; 18 | 19 | public record TiktokProfile() { 20 | } 21 | -------------------------------------------------------------------------------- /flows-tumblr/build.gradle: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanbings/flows/3170ba366276be6987d16aa05db5d22045519cfa/flows-tumblr/build.gradle -------------------------------------------------------------------------------- /flows-twitch/build.gradle: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanbings/flows/3170ba366276be6987d16aa05db5d22045519cfa/flows-twitch/build.gradle -------------------------------------------------------------------------------- /flows-twitch/src/main/java/io/hanbings/flows/twitch/TwitchAccess.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2023 Flows 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package io.hanbings.flows.twitch; 18 | 19 | import io.hanbings.flows.common.interfaces.Access; 20 | 21 | public record TwitchAccess( 22 | String accessToken 23 | ) implements Access { 24 | public record Wrong( 25 | String error, 26 | String errorDescription 27 | ) implements Access.Wrong { 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /flows-twitch/src/main/java/io/hanbings/flows/twitch/TwitchIdentify.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2023 Flows 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package io.hanbings.flows.twitch; 18 | 19 | public record TwitchIdentify() { 20 | } 21 | -------------------------------------------------------------------------------- /flows-twitch/src/main/java/io/hanbings/flows/twitch/TwitchOAuth.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2023 Flows 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package io.hanbings.flows.twitch; 18 | 19 | import io.hanbings.flows.common.OAuth; 20 | 21 | import java.util.List; 22 | import java.util.Map; 23 | 24 | public class TwitchOAuth extends OAuth { 25 | private TwitchOAuth() { 26 | super(null, null, null, null); 27 | } 28 | 29 | public TwitchOAuth(String client, String secret, String redirect) { 30 | super( 31 | "https://id.twitch.tv/oauth2/authorize", 32 | "https://id.twitch.tv/oauth2/token", 33 | List.of(), 34 | Map.of() 35 | ); 36 | 37 | this.client(client); 38 | this.secret(secret); 39 | this.redirect(redirect); 40 | } 41 | 42 | public TwitchOAuth(String client, String secret, String redirect, 43 | List scopes, Map params) { 44 | super( 45 | "https://id.twitch.tv/oauth2/authorize", 46 | "https://id.twitch.tv/oauth2/token", 47 | scopes, 48 | params 49 | ); 50 | 51 | this.client(client); 52 | this.secret(secret); 53 | this.redirect(redirect); 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /flows-twitch/src/main/java/io/hanbings/flows/twitch/TwitchProfile.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2023 Flows 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package io.hanbings.flows.twitch; 18 | 19 | public record TwitchProfile() { 20 | } 21 | -------------------------------------------------------------------------------- /flows-twitter/build.gradle: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanbings/flows/3170ba366276be6987d16aa05db5d22045519cfa/flows-twitter/build.gradle -------------------------------------------------------------------------------- /flows-twitter/src/main/java/io/hanbings/flows/twitter/TwitterAccess.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2023 Flows 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package io.hanbings.flows.twitter; 18 | 19 | import io.hanbings.flows.common.interfaces.Access; 20 | 21 | public record TwitterAccess( 22 | String accessToken 23 | ) implements Access { 24 | public record Wrong( 25 | String error, 26 | String errorDescription 27 | ) implements Access.Wrong { 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /flows-twitter/src/main/java/io/hanbings/flows/twitter/TwitterIdentify.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2023 Flows 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package io.hanbings.flows.twitter; 18 | 19 | public record TwitterIdentify() { 20 | } 21 | -------------------------------------------------------------------------------- /flows-twitter/src/main/java/io/hanbings/flows/twitter/TwitterOAuth.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2023 Flows 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package io.hanbings.flows.twitter; 18 | 19 | import io.hanbings.flows.common.OAuth; 20 | 21 | import java.util.List; 22 | import java.util.Map; 23 | 24 | public class TwitterOAuth extends OAuth { 25 | private TwitterOAuth() { 26 | super(null, null, null, null); 27 | } 28 | 29 | public TwitterOAuth(String client, String secret, String redirect) { 30 | super( 31 | "https://twitter.com/i/oauth2/authorize", 32 | "https://api.twitter.com/2/oauth2/token", 33 | List.of(), 34 | Map.of() 35 | ); 36 | 37 | this.client(client); 38 | this.secret(secret); 39 | this.redirect(redirect); 40 | } 41 | 42 | public TwitterOAuth(String client, String secret, String redirect, 43 | List scopes, Map params) { 44 | super( 45 | "https://twitter.com/i/oauth2/authorize", 46 | "https://api.twitter.com/2/oauth2/token", 47 | scopes, 48 | params 49 | ); 50 | 51 | this.client(client); 52 | this.secret(secret); 53 | this.redirect(redirect); 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /flows-twitter/src/main/java/io/hanbings/flows/twitter/TwitterProfile.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2023 Flows 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package io.hanbings.flows.twitter; 18 | 19 | public record TwitterProfile() { 20 | } 21 | -------------------------------------------------------------------------------- /flows-weibo/build.gradle: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanbings/flows/3170ba366276be6987d16aa05db5d22045519cfa/flows-weibo/build.gradle -------------------------------------------------------------------------------- /flows-weibo/src/main/java/io/hanbings/flows/weibo/WeiboAccess.java: -------------------------------------------------------------------------------- 1 | package io.hanbings.flows.weibo; 2 | 3 | import com.fasterxml.jackson.annotation.JsonProperty; 4 | import com.google.gson.annotations.SerializedName; 5 | import io.hanbings.flows.common.interfaces.Access; 6 | 7 | public record WeiboAccess( 8 | @JsonProperty("access_token") 9 | @SerializedName("access_token") 10 | String accessToken, 11 | @JsonProperty("expires_in") 12 | @SerializedName("expires_in") 13 | long expiresIn, 14 | @JsonProperty("remind_in") 15 | @SerializedName("remind_in") 16 | String remindIn, 17 | @JsonProperty("uid") 18 | @SerializedName("uid") 19 | String uid 20 | ) implements Access { 21 | public record Wrong( 22 | @JsonProperty("error") 23 | @SerializedName("error") 24 | String error, 25 | @JsonProperty("error_code") 26 | @SerializedName("error_code") 27 | int code, 28 | @JsonProperty("request") 29 | @SerializedName("request") 30 | String request 31 | ) implements Access.Wrong { 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /flows-weibo/src/main/java/io/hanbings/flows/weibo/WeiboIdentify.java: -------------------------------------------------------------------------------- 1 | package io.hanbings.flows.weibo; 2 | 3 | import com.fasterxml.jackson.annotation.JsonProperty; 4 | import com.google.gson.annotations.SerializedName; 5 | import io.hanbings.flows.common.interfaces.Identify; 6 | 7 | public record WeiboIdentify( 8 | @JsonProperty("id") 9 | @SerializedName("id") 10 | String openid, 11 | @JsonProperty("avatar_large") 12 | @SerializedName("avatar_large") 13 | String avatar, 14 | @JsonProperty("name") 15 | @SerializedName("name") 16 | String username, 17 | @JsonProperty("screen_name") 18 | @SerializedName("screen_name") 19 | String nickname, 20 | String email, 21 | String phone 22 | ) implements Identify { 23 | public record Wrong( 24 | @JsonProperty("error") 25 | @SerializedName("error") 26 | String error, 27 | @JsonProperty("error_code") 28 | @SerializedName("error_code") 29 | int code, 30 | @JsonProperty("request") 31 | @SerializedName("request") 32 | String request 33 | ) implements Identify.Wrong { 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /flows-weibo/src/main/java/io/hanbings/flows/weibo/WeiboOAuth.java: -------------------------------------------------------------------------------- 1 | package io.hanbings.flows.weibo; 2 | 3 | import io.hanbings.flows.common.OAuth; 4 | import io.hanbings.flows.common.OAuthCallback; 5 | import io.hanbings.flows.common.interfaces.*; 6 | 7 | import java.util.HashMap; 8 | import java.util.List; 9 | import java.util.Map; 10 | 11 | @SuppressWarnings("unused") 12 | public class WeiboOAuth 13 | extends 14 | OAuth 15 | implements 16 | Revokable, 17 | Profilable, 18 | Identifiable { 19 | final String USER_INFO = "https://api.weibo.com/2/users/show.json"; 20 | final String revocation = "https://api.weibo.com/oauth2/revokeoauth2"; 21 | 22 | private WeiboOAuth() { 23 | super(null, null, null, null); 24 | } 25 | 26 | public WeiboOAuth(String client, String secret, String redirect) { 27 | super( 28 | "https://api.weibo.com/oauth2/authorize", 29 | "https://api.weibo.com/oauth2/access_token", 30 | List.of(), 31 | Map.of() 32 | ); 33 | 34 | this.client(client); 35 | this.secret(secret); 36 | this.redirect(redirect); 37 | } 38 | 39 | public WeiboOAuth(String client, String secret, String redirect, 40 | List scopes, Map params) { 41 | super( 42 | "https://api.weibo.com/oauth2/authorize", 43 | "https://api.weibo.com/oauth2/access_token", 44 | scopes, 45 | params 46 | ); 47 | 48 | this.client(client); 49 | this.secret(secret); 50 | this.redirect(redirect); 51 | } 52 | 53 | @Override 54 | public String authorize(List scopes, Map params) { 55 | List sco = scopes == null ? this.scopes() : scopes; 56 | Map par = params == null ? this.params() : params; 57 | 58 | Map temp = new HashMap<>() {{ 59 | put("client_id", client()); 60 | put("redirect_uri", redirect()); 61 | put("scope", String.join(",", sco)); 62 | put("state", state().get().add()); 63 | 64 | putAll(par); 65 | }}; 66 | 67 | // url builder 68 | StringBuilder url = new StringBuilder().append(authorization()); 69 | 70 | if (temp.size() != 0) { 71 | url.append("?"); 72 | 73 | // map to string 74 | temp.forEach((k, v) -> url.append(k).append("=").append(v).append("&")); 75 | 76 | // eat last '&' and return string 77 | return url.substring(0, url.length() - 1); 78 | } 79 | 80 | return url.toString(); 81 | } 82 | 83 | @Override 84 | public Callback token(String code, String state, String redirect) { 85 | Response response = this.request() 86 | .get() 87 | .post( 88 | this.serialization().get(), 89 | this.proxy() == null ? null : this.proxy().get(), 90 | this.access(), 91 | Map.of( 92 | "client_id", this.client(), 93 | "client_secret", this.secret(), 94 | "grant_type", "authorization_code", 95 | "code", code, 96 | "redirect_uri", redirect 97 | ) 98 | ); 99 | 100 | if (response.code() == 200) { 101 | WeiboAccess access = this.serialization() 102 | .get() 103 | .object(WeiboAccess.class, response.raw()); 104 | 105 | return OAuthCallback.response(access.accessToken(), access, null, response); 106 | } 107 | 108 | if (response.code() != 200 && response.code() != 0) { 109 | WeiboAccess.Wrong wrong = this.serialization() 110 | .get() 111 | .object(WeiboAccess.Wrong.class, response.raw()); 112 | 113 | return OAuthCallback.response(null, null, wrong, response); 114 | } 115 | 116 | return OAuthCallback.exception( 117 | null, 118 | response.exception() ? response.throwable() : new IllegalArgumentException() 119 | ); 120 | } 121 | 122 | @Override 123 | public Callback identify(String token) { 124 | Response response = this.request() 125 | .get() 126 | .get( 127 | this.serialization().get(), 128 | this.proxy() == null ? null : this.proxy().get(), 129 | USER_INFO, 130 | Map.of( 131 | "access_token", token 132 | ) 133 | ); 134 | 135 | if (response.code() == 200) { 136 | WeiboIdentify identify = this.serialization() 137 | .get() 138 | .object(WeiboIdentify.class, response.raw()); 139 | 140 | return OAuthCallback.response(token, identify, null, response); 141 | } 142 | 143 | if (response.code() != 200 && response.code() != 0) { 144 | WeiboIdentify.Wrong wrong = this.serialization() 145 | .get() 146 | .object(WeiboIdentify.Wrong.class, response.raw()); 147 | 148 | return OAuthCallback.response(null, null, wrong, response); 149 | } 150 | 151 | return OAuthCallback.exception( 152 | null, 153 | response.exception() ? response.throwable() : new IllegalArgumentException() 154 | ); 155 | } 156 | 157 | @Override 158 | public Callback profile(String token) { 159 | Response response = this.request() 160 | .get() 161 | .get( 162 | this.serialization().get(), 163 | this.proxy() == null ? null : this.proxy().get(), 164 | USER_INFO, 165 | Map.of( 166 | "access_token", token 167 | ) 168 | ); 169 | 170 | if (response.code() == 200) { 171 | WeiboProfile profile = this.serialization() 172 | .get() 173 | .object(WeiboProfile.class, response.raw()); 174 | 175 | return OAuthCallback.response(token, profile, null, response); 176 | } 177 | 178 | if (response.code() != 200 && response.code() != 0) { 179 | WeiboProfile.Wrong wrong = this.serialization() 180 | .get() 181 | .object(WeiboProfile.Wrong.class, response.raw()); 182 | 183 | return OAuthCallback.response(null, null, wrong, response); 184 | } 185 | 186 | return OAuthCallback.exception( 187 | null, 188 | response.exception() ? response.throwable() : new IllegalArgumentException() 189 | ); 190 | } 191 | 192 | @Override 193 | public Callback revoke(String token) { 194 | Response response = this.request() 195 | .get() 196 | .post( 197 | this.serialization().get(), 198 | this.proxy() == null ? null : this.proxy().get(), 199 | revocation, 200 | Map.of( 201 | "access_token", token 202 | ) 203 | ); 204 | 205 | if (response.code() == 200) { 206 | WeiboRevoke revoke = this.serialization() 207 | .get() 208 | .object(WeiboRevoke.class, response.raw()); 209 | 210 | return OAuthCallback.response(token, revoke, null, response); 211 | } 212 | 213 | if (response.code() != 200 && response.code() != 0) { 214 | WeiboRevoke.Wrong wrong = this.serialization() 215 | .get() 216 | .object(WeiboRevoke.Wrong.class, response.raw()); 217 | 218 | return OAuthCallback.response(null, null, wrong, response); 219 | } 220 | 221 | return OAuthCallback.exception( 222 | null, 223 | response.exception() ? response.throwable() : new IllegalArgumentException() 224 | ); 225 | } 226 | } 227 | -------------------------------------------------------------------------------- /flows-weibo/src/main/java/io/hanbings/flows/weibo/WeiboProfile.java: -------------------------------------------------------------------------------- 1 | package io.hanbings.flows.weibo; 2 | 3 | import com.fasterxml.jackson.annotation.JsonProperty; 4 | import com.google.gson.annotations.SerializedName; 5 | import io.hanbings.flows.common.interfaces.Profile; 6 | 7 | @SuppressWarnings("SpellCheckingInspection") 8 | public record WeiboProfile( 9 | @JsonProperty("id") 10 | @SerializedName("id") 11 | String id, 12 | @JsonProperty("idstr") 13 | @SerializedName("idstr") 14 | String idstr, 15 | @JsonProperty("screen_name") 16 | @SerializedName("screen_name") 17 | String screenName, 18 | @JsonProperty("name") 19 | @SerializedName("name") 20 | String name, 21 | @JsonProperty("province") 22 | @SerializedName("province") 23 | String province, 24 | @JsonProperty("city") 25 | @SerializedName("city") 26 | String city, 27 | @JsonProperty("location") 28 | @SerializedName("location") 29 | String location, 30 | @JsonProperty("description") 31 | @SerializedName("description") 32 | String description, 33 | @JsonProperty("url") 34 | @SerializedName("url") 35 | String url, 36 | @JsonProperty("profile_image_url") 37 | @SerializedName("profile_image_url") 38 | String profileImageUrl, 39 | @JsonProperty("profile_url") 40 | @SerializedName("profile_url") 41 | String profileUrl, 42 | @JsonProperty("domain") 43 | @SerializedName("domain") 44 | String domain, 45 | @JsonProperty("weihao") 46 | @SerializedName("weihao") 47 | String weihao, 48 | @JsonProperty("gender") 49 | @SerializedName("gender") 50 | String gender, 51 | @JsonProperty("followers_count") 52 | @SerializedName("followers_count") 53 | int followersCount, 54 | @JsonProperty("friends_count") 55 | @SerializedName("friends_count") 56 | int friendsCount, 57 | @JsonProperty("statuses_count") 58 | @SerializedName("statuses_count") 59 | int statusesCount, 60 | @JsonProperty("favourites_count") 61 | @SerializedName("favourites_count") 62 | int favouritesCount, 63 | @JsonProperty("created_at") 64 | @SerializedName("created_at") 65 | String createdAt, 66 | @JsonProperty("following") 67 | @SerializedName("following") 68 | boolean following, 69 | @JsonProperty("allow_all_act_msg") 70 | @SerializedName("allow_all_act_msg") 71 | boolean allowAllActMsg, 72 | @JsonProperty("geo_enabled") 73 | @SerializedName("geo_enabled") 74 | boolean geoEnabled, 75 | @JsonProperty("verified") 76 | @SerializedName("verified") 77 | boolean verified, 78 | @JsonProperty("verified_type") 79 | @SerializedName("verified_type") 80 | int verifiedType, 81 | @JsonProperty("remark") 82 | @SerializedName("remark") 83 | String remark, 84 | @JsonProperty("status") 85 | @SerializedName("status") 86 | Object status, 87 | @JsonProperty("allow_all_comment") 88 | @SerializedName("allow_all_comment") 89 | boolean allowAllComment, 90 | @JsonProperty("avatar_large") 91 | @SerializedName("avatar_large") 92 | String avatarLarge, 93 | @JsonProperty("avatar_hd") 94 | @SerializedName("avatar_hd") 95 | String avatarHd, 96 | @JsonProperty("verified_reason") 97 | @SerializedName("verified_reason") 98 | String verifiedReason, 99 | @JsonProperty("follow_me") 100 | @SerializedName("follow_me") 101 | boolean followMe, 102 | @JsonProperty("online_status") 103 | @SerializedName("online_status") 104 | int onlineStatus, 105 | @JsonProperty("bi_followers_count") 106 | @SerializedName("bi_followers_count") 107 | int biFollowersCount, 108 | @JsonProperty("lang") 109 | @SerializedName("lang") 110 | String lang 111 | ) implements Profile { 112 | public record Wrong( 113 | @JsonProperty("error") 114 | @SerializedName("error") 115 | String error, 116 | @JsonProperty("error_code") 117 | @SerializedName("error_code") 118 | int code, 119 | @JsonProperty("request") 120 | @SerializedName("request") 121 | String request 122 | ) implements Profile.Wrong { 123 | } 124 | } 125 | -------------------------------------------------------------------------------- /flows-weibo/src/main/java/io/hanbings/flows/weibo/WeiboRevoke.java: -------------------------------------------------------------------------------- 1 | package io.hanbings.flows.weibo; 2 | 3 | import com.fasterxml.jackson.annotation.JsonProperty; 4 | import com.google.gson.annotations.SerializedName; 5 | import io.hanbings.flows.common.interfaces.Revoke; 6 | 7 | public record WeiboRevoke( 8 | @JsonProperty("result") 9 | @SerializedName("result") 10 | String result 11 | ) implements Revoke { 12 | public record Wrong( 13 | @JsonProperty("error") 14 | @SerializedName("error") 15 | String error, 16 | @JsonProperty("error_code") 17 | @SerializedName("error_code") 18 | int code, 19 | @JsonProperty("request") 20 | @SerializedName("request") 21 | String request 22 | ) implements Revoke.Wrong { 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /flows-wordpress/build.gradle: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanbings/flows/3170ba366276be6987d16aa05db5d22045519cfa/flows-wordpress/build.gradle -------------------------------------------------------------------------------- /flows-wordpress/src/main/java/io/hanbings/flows/wordpress/WordpressAccess.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2023 Flows 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package io.hanbings.flows.wordpress; 18 | 19 | import io.hanbings.flows.common.interfaces.Access; 20 | 21 | public record WordpressAccess( 22 | String accessToken 23 | ) implements Access { 24 | public record Wrong( 25 | String error, 26 | String errorDescription 27 | ) implements Access.Wrong { 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /flows-wordpress/src/main/java/io/hanbings/flows/wordpress/WordpressIdentify.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2023 Flows 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package io.hanbings.flows.wordpress; 18 | 19 | public record WordpressIdentify() { 20 | } 21 | -------------------------------------------------------------------------------- /flows-wordpress/src/main/java/io/hanbings/flows/wordpress/WordpressOAuth.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2023 Flows 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package io.hanbings.flows.wordpress; 18 | 19 | import io.hanbings.flows.common.OAuth; 20 | 21 | import java.util.List; 22 | import java.util.Map; 23 | 24 | public class WordpressOAuth extends OAuth { 25 | private WordpressOAuth() { 26 | super(null, null, null, null); 27 | } 28 | 29 | public WordpressOAuth(String client, String secret, String redirect) { 30 | super( 31 | "https://public-api.wordpress.com/oauth2/authorize", 32 | "https://public-api.wordpress.com/oauth2/token", 33 | List.of(), 34 | Map.of() 35 | ); 36 | 37 | this.client(client); 38 | this.secret(secret); 39 | this.redirect(redirect); 40 | } 41 | 42 | public WordpressOAuth(String client, String secret, String redirect, 43 | List scopes, Map params) { 44 | super( 45 | "https://public-api.wordpress.com/oauth2/authorize", 46 | "https://public-api.wordpress.com/oauth2/token", 47 | scopes, 48 | params 49 | ); 50 | 51 | this.client(client); 52 | this.secret(secret); 53 | this.redirect(redirect); 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /flows-wordpress/src/main/java/io/hanbings/flows/wordpress/WordpressProfile.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2023 Flows 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package io.hanbings.flows.wordpress; 18 | 19 | public record WordpressProfile() { 20 | } 21 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hanbings/flows/3170ba366276be6987d16aa05db5d22045519cfa/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-7.4-bin.zip 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | -------------------------------------------------------------------------------- /gradlew: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # 4 | # Copyright © 2015-2021 the original authors. 5 | # 6 | # Licensed under the Apache License, Version 2.0 (the "License"); 7 | # you may not use this file except in compliance with the License. 8 | # You may obtain a copy of the License at 9 | # 10 | # https://www.apache.org/licenses/LICENSE-2.0 11 | # 12 | # Unless required by applicable law or agreed to in writing, software 13 | # distributed under the License is distributed on an "AS IS" BASIS, 14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | # See the License for the specific language governing permissions and 16 | # limitations under the License. 17 | # 18 | 19 | ############################################################################## 20 | # 21 | # Gradle start up script for POSIX generated by Gradle. 22 | # 23 | # Important for running: 24 | # 25 | # (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is 26 | # noncompliant, but you have some other compliant shell such as ksh or 27 | # bash, then to run this script, type that shell name before the whole 28 | # command line, like: 29 | # 30 | # ksh Gradle 31 | # 32 | # Busybox and similar reduced shells will NOT work, because this script 33 | # requires all of these POSIX shell features: 34 | # * functions; 35 | # * expansions «$var», «${var}», «${var:-default}», «${var+SET}», 36 | # «${var#prefix}», «${var%suffix}», and «$( cmd )»; 37 | # * compound commands having a testable exit status, especially «case»; 38 | # * various built-in commands including «command», «set», and «ulimit». 39 | # 40 | # Important for patching: 41 | # 42 | # (2) This script targets any POSIX shell, so it avoids extensions provided 43 | # by Bash, Ksh, etc; in particular arrays are avoided. 44 | # 45 | # The "traditional" practice of packing multiple parameters into a 46 | # space-separated string is a well documented source of bugs and security 47 | # problems, so this is (mostly) avoided, by progressively accumulating 48 | # options in "$@", and eventually passing that to Java. 49 | # 50 | # Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS, 51 | # and GRADLE_OPTS) rely on word-splitting, this is performed explicitly; 52 | # see the in-line comments for details. 53 | # 54 | # There are tweaks for specific operating systems such as AIX, CygWin, 55 | # Darwin, MinGW, and NonStop. 56 | # 57 | # (3) This script is generated from the Groovy template 58 | # https://github.com/gradle/gradle/blob/master/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt 59 | # within the Gradle project. 60 | # 61 | # You can find Gradle at https://github.com/gradle/gradle/. 62 | # 63 | ############################################################################## 64 | 65 | # Attempt to set APP_HOME 66 | 67 | # Resolve links: $0 may be a link 68 | app_path=$0 69 | 70 | # Need this for daisy-chained symlinks. 71 | while 72 | APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path 73 | [ -h "$app_path" ] 74 | do 75 | ls=$( ls -ld "$app_path" ) 76 | link=${ls#*' -> '} 77 | case $link in #( 78 | /*) app_path=$link ;; #( 79 | *) app_path=$APP_HOME$link ;; 80 | esac 81 | done 82 | 83 | APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit 84 | 85 | APP_NAME="Gradle" 86 | APP_BASE_NAME=${0##*/} 87 | 88 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 89 | DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' 90 | 91 | # Use the maximum available, or set MAX_FD != -1 to use that value. 92 | MAX_FD=maximum 93 | 94 | warn () { 95 | echo "$*" 96 | } >&2 97 | 98 | die () { 99 | echo 100 | echo "$*" 101 | echo 102 | exit 1 103 | } >&2 104 | 105 | # OS specific support (must be 'true' or 'false'). 106 | cygwin=false 107 | msys=false 108 | darwin=false 109 | nonstop=false 110 | case "$( uname )" in #( 111 | CYGWIN* ) cygwin=true ;; #( 112 | Darwin* ) darwin=true ;; #( 113 | MSYS* | MINGW* ) msys=true ;; #( 114 | NONSTOP* ) nonstop=true ;; 115 | esac 116 | 117 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 118 | 119 | 120 | # Determine the Java command to use to start the JVM. 121 | if [ -n "$JAVA_HOME" ] ; then 122 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 123 | # IBM's JDK on AIX uses strange locations for the executables 124 | JAVACMD=$JAVA_HOME/jre/sh/java 125 | else 126 | JAVACMD=$JAVA_HOME/bin/java 127 | fi 128 | if [ ! -x "$JAVACMD" ] ; then 129 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 130 | 131 | Please set the JAVA_HOME variable in your environment to match the 132 | location of your Java installation." 133 | fi 134 | else 135 | JAVACMD=java 136 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 137 | 138 | Please set the JAVA_HOME variable in your environment to match the 139 | location of your Java installation." 140 | fi 141 | 142 | # Increase the maximum file descriptors if we can. 143 | if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then 144 | case $MAX_FD in #( 145 | max*) 146 | MAX_FD=$( ulimit -H -n ) || 147 | warn "Could not query maximum file descriptor limit" 148 | esac 149 | case $MAX_FD in #( 150 | '' | soft) :;; #( 151 | *) 152 | ulimit -n "$MAX_FD" || 153 | warn "Could not set maximum file descriptor limit to $MAX_FD" 154 | esac 155 | fi 156 | 157 | # Collect all arguments for the java command, stacking in reverse order: 158 | # * args from the command line 159 | # * the main class name 160 | # * -classpath 161 | # * -D...appname settings 162 | # * --module-path (only if needed) 163 | # * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables. 164 | 165 | # For Cygwin or MSYS, switch paths to Windows format before running java 166 | if "$cygwin" || "$msys" ; then 167 | APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) 168 | CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) 169 | 170 | JAVACMD=$( cygpath --unix "$JAVACMD" ) 171 | 172 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 173 | for arg do 174 | if 175 | case $arg in #( 176 | -*) false ;; # don't mess with options #( 177 | /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath 178 | [ -e "$t" ] ;; #( 179 | *) false ;; 180 | esac 181 | then 182 | arg=$( cygpath --path --ignore --mixed "$arg" ) 183 | fi 184 | # Roll the args list around exactly as many times as the number of 185 | # args, so each arg winds up back in the position where it started, but 186 | # possibly modified. 187 | # 188 | # NB: a `for` loop captures its iteration list before it begins, so 189 | # changing the positional parameters here affects neither the number of 190 | # iterations, nor the values presented in `arg`. 191 | shift # remove old arg 192 | set -- "$@" "$arg" # push replacement arg 193 | done 194 | fi 195 | 196 | # Collect all arguments for the java command; 197 | # * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of 198 | # shell script including quotes and variable substitutions, so put them in 199 | # double quotes to make sure that they get re-expanded; and 200 | # * put everything else in single quotes, so that it's not re-expanded. 201 | 202 | set -- \ 203 | "-Dorg.gradle.appname=$APP_BASE_NAME" \ 204 | -classpath "$CLASSPATH" \ 205 | org.gradle.wrapper.GradleWrapperMain \ 206 | "$@" 207 | 208 | # Use "xargs" to parse quoted args. 209 | # 210 | # With -n1 it outputs one arg per line, with the quotes and backslashes removed. 211 | # 212 | # In Bash we could simply go: 213 | # 214 | # readarray ARGS < <( xargs -n1 <<<"$var" ) && 215 | # set -- "${ARGS[@]}" "$@" 216 | # 217 | # but POSIX shell has neither arrays nor command substitution, so instead we 218 | # post-process each arg (as a line of input to sed) to backslash-escape any 219 | # character that might be a shell metacharacter, then use eval to reverse 220 | # that process (while maintaining the separation between arguments), and wrap 221 | # the whole thing up as a single "set" statement. 222 | # 223 | # This will of course break if any of these variables contains a newline or 224 | # an unmatched quote. 225 | # 226 | 227 | eval "set -- $( 228 | printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | 229 | xargs -n1 | 230 | sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | 231 | tr '\n' ' ' 232 | )" '"$@"' 233 | 234 | exec "$JAVACMD" "$@" 235 | -------------------------------------------------------------------------------- /gradlew.bat: -------------------------------------------------------------------------------- 1 | @rem 2 | @rem Copyright 2015 the original author or authors. 3 | @rem 4 | @rem Licensed under the Apache License, Version 2.0 (the "License"); 5 | @rem you may not use this file except in compliance with the License. 6 | @rem You may obtain a copy of the License at 7 | @rem 8 | @rem https://www.apache.org/licenses/LICENSE-2.0 9 | @rem 10 | @rem Unless required by applicable law or agreed to in writing, software 11 | @rem distributed under the License is distributed on an "AS IS" BASIS, 12 | @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | @rem See the License for the specific language governing permissions and 14 | @rem limitations under the License. 15 | @rem 16 | 17 | @if "%DEBUG%" == "" @echo off 18 | @rem ########################################################################## 19 | @rem 20 | @rem Gradle startup script for Windows 21 | @rem 22 | @rem ########################################################################## 23 | 24 | @rem Set local scope for the variables with windows NT shell 25 | if "%OS%"=="Windows_NT" setlocal 26 | 27 | set DIRNAME=%~dp0 28 | if "%DIRNAME%" == "" set DIRNAME=. 29 | set APP_BASE_NAME=%~n0 30 | set APP_HOME=%DIRNAME% 31 | 32 | @rem Resolve any "." and ".." in APP_HOME to make it shorter. 33 | for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi 34 | 35 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 36 | set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" 37 | 38 | @rem Find java.exe 39 | if defined JAVA_HOME goto findJavaFromJavaHome 40 | 41 | set JAVA_EXE=java.exe 42 | %JAVA_EXE% -version >NUL 2>&1 43 | if "%ERRORLEVEL%" == "0" goto execute 44 | 45 | echo. 46 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 47 | echo. 48 | echo Please set the JAVA_HOME variable in your environment to match the 49 | echo location of your Java installation. 50 | 51 | goto fail 52 | 53 | :findJavaFromJavaHome 54 | set JAVA_HOME=%JAVA_HOME:"=% 55 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 56 | 57 | if exist "%JAVA_EXE%" goto execute 58 | 59 | echo. 60 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 61 | echo. 62 | echo Please set the JAVA_HOME variable in your environment to match the 63 | echo location of your Java installation. 64 | 65 | goto fail 66 | 67 | :execute 68 | @rem Setup the command line 69 | 70 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 71 | 72 | 73 | @rem Execute Gradle 74 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* 75 | 76 | :end 77 | @rem End local scope for the variables with windows NT shell 78 | if "%ERRORLEVEL%"=="0" goto mainEnd 79 | 80 | :fail 81 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 82 | rem the _cmd.exe /c_ return code! 83 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 84 | exit /b 1 85 | 86 | :mainEnd 87 | if "%OS%"=="Windows_NT" endlocal 88 | 89 | :omega 90 | -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- 1 | rootProject.name = 'flows' 2 | include 'flows-amazon' 3 | include 'flows-baidu' 4 | include 'flows-common' 5 | include 'flows-discord' 6 | include 'flows-dropbox' 7 | include 'flows-ebay' 8 | include 'flows-etsy' 9 | include 'flows-extra' 10 | include 'flows-facebook' 11 | include 'flows-flickr' 12 | include 'flows-github' 13 | include 'flows-gitlab' 14 | include 'flows-google' 15 | include 'flows-imgur' 16 | include 'flows-instagram' 17 | include 'flows-line' 18 | include 'flows-microsoft' 19 | include 'flows-pinterest' 20 | include 'flows-qq' 21 | include 'flows-reddit' 22 | include 'flows-soundcloud' 23 | include 'flows-spotify' 24 | include 'flows-stackoverflow' 25 | include 'flows-tiktok' 26 | include 'flows-tumblr' 27 | include 'flows-twitch' 28 | include 'flows-twitter' 29 | include 'flows-weibo' 30 | include 'flows-wordpress' 31 | 32 | --------------------------------------------------------------------------------