From a57e0f5497320331f8c3be1dcd5e201c37d21640 Mon Sep 17 00:00:00 2001 From: zeekling Date: Sat, 25 Jul 2020 23:04:33 +0800 Subject: [PATCH] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E8=AE=BF=E9=97=AEgithub?= =?UTF-8?q?=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 2 + pom.xml | 63 ++++++ .../java/com/zeekling/blog/BlogUpdate.java | 14 ++ .../zeekling/constants/GitHubConstants.java | 17 ++ src/main/java/com/zeekling/util/GitHubs.java | 194 ++++++++++++++++++ .../com/zeekling/blog/BlogUpdateTest.java | 10 + .../java/com/zeekling/util/GitHubsTest.java | 13 ++ 7 files changed, 313 insertions(+) create mode 100644 pom.xml create mode 100644 src/main/java/com/zeekling/blog/BlogUpdate.java create mode 100644 src/main/java/com/zeekling/constants/GitHubConstants.java create mode 100644 src/main/java/com/zeekling/util/GitHubs.java create mode 100644 src/test/java/com/zeekling/blog/BlogUpdateTest.java create mode 100644 src/test/java/com/zeekling/util/GitHubsTest.java diff --git a/.gitignore b/.gitignore index f2bdeaa..acbf00b 100644 --- a/.gitignore +++ b/.gitignore @@ -46,3 +46,5 @@ tags .idea target +*.iml +gradle diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..0c09d38 --- /dev/null +++ b/pom.xml @@ -0,0 +1,63 @@ + + + 4.0.0 + + com.zeekling + github_zeekling + 1.0-SNAPSHOT + + + + + org.json + json + 20200518 + + + + org.jodd + jodd-http + 5.0.13 + + + + + + log4j + log4j + 1.2.17 + + + + + commons-lang + commons-lang + 2.6 + + + + org.testng + testng + 7.1.0 + test + + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.1 + + 1.8 + 1.8 + + + + + + \ No newline at end of file diff --git a/src/main/java/com/zeekling/blog/BlogUpdate.java b/src/main/java/com/zeekling/blog/BlogUpdate.java new file mode 100644 index 0000000..ad72f3a --- /dev/null +++ b/src/main/java/com/zeekling/blog/BlogUpdate.java @@ -0,0 +1,14 @@ +package com.zeekling.blog; + +/** + * @author zeekling [lingzhaohui@zeekling.cn] + * @version 1.0 + * @apiNote + * @since 2020-07-25 + */ +public class BlogUpdate { + + + + +} diff --git a/src/main/java/com/zeekling/constants/GitHubConstants.java b/src/main/java/com/zeekling/constants/GitHubConstants.java new file mode 100644 index 0000000..4635334 --- /dev/null +++ b/src/main/java/com/zeekling/constants/GitHubConstants.java @@ -0,0 +1,17 @@ +package com.zeekling.constants; + +/** + * @author zeekling [lingzhaohui@zeekling.cn] + * @version 1.0 + * @apiNote 常亮列表 + * @since 2020-07-25 + */ +public class GitHubConstants { + + public static final String USER_AGENT = "zeekling/" + "; +https://github.com/zeekling/zeekling"; + + public static final String CODE = "code"; + + public static final String DATA = "data"; + +} diff --git a/src/main/java/com/zeekling/util/GitHubs.java b/src/main/java/com/zeekling/util/GitHubs.java new file mode 100644 index 0000000..e0fc887 --- /dev/null +++ b/src/main/java/com/zeekling/util/GitHubs.java @@ -0,0 +1,194 @@ +/* + * Solo - A small and beautiful blogging system written in Java. + * Copyright (c) 2010-present, b3log.org + * + * Solo is licensed under Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * http://license.coscl.org.cn/MulanPSL2 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PSL v2 for more details. + */ +package com.zeekling.util; + + +import com.zeekling.constants.GitHubConstants; +import org.apache.commons.lang.StringUtils; +import jodd.http.HttpRequest; +import jodd.http.HttpResponse; +import org.apache.log4j.Level; +import org.apache.log4j.LogManager; +import org.apache.log4j.Logger; +import org.json.JSONArray; +import org.json.JSONObject; + +import java.util.Base64; + + +/** + * GitHub utilities. + * + * @author Liang Ding + * @version 1.1.0.0, May 20, 2020 + * @since 3.0.0 + */ +public final class GitHubs { + + /** + * Logger. + */ + private static final Logger LOGGER = LogManager.getLogger(GitHubs.class); + + /** + * Gets GitHub repos. + * + * @param githubUserId the specified GitHub user id + * @return GitHub repos, returns {@code null} if not found + */ + public static JSONArray getGitHubRepos(final String githubUserId) { + try { + final HttpResponse res = HttpRequest.get("https://hacpai.com/github/repos?id=" + githubUserId).trustAllCerts(true). + connectionTimeout(3000).timeout(7000).header("User-Agent", GitHubConstants.USER_AGENT).send(); + if (200 != res.statusCode()) { + return null; + } + res.charset("UTF-8"); + final JSONObject result = new JSONObject(res.bodyText()); + if (0 != result.optInt(GitHubConstants.CODE)) { + return null; + } + final JSONObject data = result.optJSONObject(GitHubConstants.DATA); + return data.optJSONArray("githubrepos"); + } catch (final Exception e) { + LOGGER.log(Level.ERROR, "Gets GitHub repos failed", e); + return null; + } + } + + /** + * Updates a file by the specified personal access token, GitHub login name, repo name, file path and file content. + * + * @param pat the specified personal access token + * @param loginName the specified GitHub login name + * @param repoName the specified repo name + * @param filePath the specfiied file name + * @param content the specified file content + * @return {@code true} if ok, returns {@code false} if failed + */ + public static boolean updateFile(final String pat, final String loginName, final String repoName, final String filePath, final byte[] content) { + final String fullRepoName = loginName + "/" + repoName; + try { + HttpResponse response = HttpRequest.get("https://api.github.com/repos/" + fullRepoName + "/git/trees/master").header("Authorization", "token " + pat). + connectionTimeout(7000).timeout(60000).header("User-Agent", GitHubConstants.USER_AGENT).send(); + int statusCode = response.statusCode(); + response.charset("UTF-8"); + String responseBody = response.bodyText(); + if (200 != statusCode && 409 != statusCode) { + LOGGER.log(Level.ERROR, "Get git tree of file [" + filePath + "] failed: " + responseBody); + return false; + } + + final JSONObject body = new JSONObject(). + put("message", ":memo: 更新博客"). + put("content", Base64.getEncoder().encodeToString(content)); + if (200 == statusCode) { + final JSONObject responseData = new JSONObject(responseBody); + final JSONArray tree = responseData.optJSONArray("tree"); + for (int i = 0; i < tree.length(); i++) { + final JSONObject file = tree.optJSONObject(i); + if (StringUtils.equals(filePath, file.optString("path"))) { + body.put("sha", file.optString("sha")); + break; + } + } + } + + response = HttpRequest.put("https://api.github.com/repos/" + fullRepoName + "/contents/" + filePath).header("Authorization", "token " + pat). + connectionTimeout(7000).timeout(60000 * 2).header("User-Agent", GitHubConstants.USER_AGENT).bodyText(body.toString()).send(); + statusCode = response.statusCode(); + response.charset("UTF-8"); + responseBody = response.bodyText(); + if (200 != statusCode && 201 != statusCode) { + LOGGER.log(Level.ERROR, "Updates repo [" + repoName + "] file [" + filePath + "] failed: " + responseBody); + return false; + } + return true; + } catch (final Exception e) { + LOGGER.log(Level.ERROR, "Updates repo [" + repoName + "] file [" + filePath + "] failed: " + e.getMessage()); + return false; + } + } + + /** + * Creates or updates a GitHub repository by the specified personal access token, GitHub login name, repo name repo desc and repo homepage. + * + * @param pat the specified personal access token + * @param loginName the specified GitHub login name + * @param repoName the specified repo name + * @param repoDesc the specified repo desc + * @param repoHomepage the specified repo homepage + * @return {@code true} if ok, returns {@code false} if failed + */ + public static boolean createOrUpdateGitHubRepo(final String pat, final String loginName, final String repoName, final String repoDesc, final String repoHomepage) { + try { + final JSONObject body = new JSONObject(). + put("name", repoName). + put("description", repoDesc). + put("homepage", repoHomepage). + put("has_wiki", false). + put("has_projects", false); + HttpResponse response = HttpRequest.post("https://api.github.com/user/repos").header("Authorization", "token " + pat). + connectionTimeout(7000).timeout(30000).header("User-Agent", GitHubConstants.USER_AGENT).bodyText(body.toString()).send(); + int statusCode = response.statusCode(); + response.charset("UTF-8"); + String responseBody = response.bodyText(); + if (201 != statusCode && 422 != statusCode) { + LOGGER.log(Level.ERROR, "Creates GitHub repo [" + repoName + "] failed: " + responseBody); + return false; + } + if (201 == statusCode) { + return true; + } + + response = HttpRequest.patch("https://api.github.com/repos/" + loginName + "/" + repoName).header("Authorization", "token " + pat). + connectionTimeout(7000).timeout(30000).header("User-Agent", GitHubConstants.USER_AGENT).bodyText(body.toString()).send(); + statusCode = response.statusCode(); + responseBody = response.bodyText(); + if (200 != statusCode) { + LOGGER.log(Level.ERROR, "Updates GitHub repo [" + repoName + "] failed: " + responseBody); + return false; + } + return true; + } catch (final Exception e) { + LOGGER.log(Level.ERROR, "Creates or updates GitHub repo failed: " + e.getMessage()); + return false; + } + } + + /** + * Gets GitHub user by the specified personal access token. + * + * @param pat the specified personal access token + * @return GitHub user, returns {@code null} if failed + */ + public static JSONObject getGitHubUser(final String pat) { + try { + final HttpResponse response = HttpRequest.get("https://api.github.com/user").header("Authorization", "token " + pat). + connectionTimeout(7000).timeout(30000).header("User-Agent", GitHubConstants.USER_AGENT).send(); + if (200 != response.statusCode()) { + return null; + } + response.charset("UTF-8"); + return new JSONObject(response.bodyText()); + } catch (final Exception e) { + LOGGER.log(Level.ERROR, "Gets GitHub user info failed: " + e.getMessage()); + return null; + } + } + + /** + * Private constructor. + */ + private GitHubs() { + } +} diff --git a/src/test/java/com/zeekling/blog/BlogUpdateTest.java b/src/test/java/com/zeekling/blog/BlogUpdateTest.java new file mode 100644 index 0000000..349069e --- /dev/null +++ b/src/test/java/com/zeekling/blog/BlogUpdateTest.java @@ -0,0 +1,10 @@ +package com.zeekling.blog; + +/** + * @author zeekling [lingzhaohui@zeekling.cn] + * @version 1.0 + * @apiNote + * @since 2020-07-25 + */ +public class BlogUpdateTest { +} diff --git a/src/test/java/com/zeekling/util/GitHubsTest.java b/src/test/java/com/zeekling/util/GitHubsTest.java new file mode 100644 index 0000000..fd194fc --- /dev/null +++ b/src/test/java/com/zeekling/util/GitHubsTest.java @@ -0,0 +1,13 @@ +package com.zeekling.util; + +/** + * @author zeekling [lingzhaohui@zeekling.cn] + * @version 1.0 + * @apiNote + * @since 2020-07-25 + */ +public class GitHubsTest { + + + +}