diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 12c2754..541c7e4 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -33,16 +33,6 @@ jobs: MAVEN_USERNAME: ${{ github.repository_owner }} MAVEN_TOKEN: ${{secrets.GITHUB_TOKEN}} - - name: "Release Asset Upload" - id: upload-release-asset - uses: shogo82148/actions-upload-release-asset@v1 - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - with: - upload_url: ${{ github.event.release.upload_url }} - asset_path: asset/*.jar - asset_content_type: application/java-archive - - name: "Javadoc Deploy Staging" run: | rm -rf docs diff --git a/pom.xml b/pom.xml index e92bdae..91b85a4 100644 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ 4.0.0 - 11 + 8 ${java.version} ${java.version} UTF-8 @@ -60,6 +60,13 @@ + + scm:git:https://github.com/CarmJos/GithubReleases4J.git + scm:git:ssh://github.com/CarmJos/GithubReleases4J.git + https://github.com/CarmJos/GithubReleases4J + HEAD + + @@ -92,10 +99,9 @@ - com.konghq - unirest-java - 3.13.6 - compile + org.json + json + 20211205 @@ -124,91 +130,87 @@ false + + org.apache.maven.plugins + maven-javadoc-plugin + 3.2.0 + + javadoc + + https://javadoc.io/doc/org.jetbrains/annotations/ + + false + UTF-8 + UTF-8 + UTF-8 + zh_CN + + + + attach-javadocs + + jar + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.8.1 + + ${java.version} + ${java.version} + UTF-8 + -parameters + + + + org.apache.maven.plugins + maven-jar-plugin + 3.2.0 + + + org.apache.maven.plugins + maven-source-plugin + 3.2.0 + + + package + + jar-no-fork + + + + + + org.apache.maven.plugins + maven-shade-plugin + 3.2.3 + + + package + + shade + + + false + + + + + + + *:* + + META-INF/MANIFEST.MF + META-INF/*.txt + + + + + - - - - org.apache.maven.plugins - maven-javadoc-plugin - 3.2.0 - - javadoc - - https://javadoc.io/doc/org.jetbrains/annotations/ - - false - UTF-8 - UTF-8 - UTF-8 - zh_CN - - - - attach-javadocs - - jar - - - - - - org.apache.maven.plugins - maven-compiler-plugin - 3.8.1 - - ${java.version} - ${java.version} - UTF-8 - -parameters - - - - org.apache.maven.plugins - maven-jar-plugin - 3.2.0 - - - org.apache.maven.plugins - maven-source-plugin - 3.2.0 - - - package - - jar-no-fork - - - - - - org.apache.maven.plugins - maven-shade-plugin - 3.2.3 - - - package - - shade - - - false - - - - - - - *:* - - META-INF/MANIFEST.MF - META-INF/*.txt - - - - - - - src/main/resources diff --git a/src/main/java/cc/carm/lib/githubreleases4j/GitHubHttpUtils.java b/src/main/java/cc/carm/lib/githubreleases4j/GitHubHttpUtils.java new file mode 100644 index 0000000..b3566ac --- /dev/null +++ b/src/main/java/cc/carm/lib/githubreleases4j/GitHubHttpUtils.java @@ -0,0 +1,82 @@ +package cc.carm.lib.githubreleases4j; + +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.json.JSONArray; +import org.json.JSONObject; + +import java.io.*; +import java.net.URL; +import java.net.URLConnection; +import java.nio.charset.StandardCharsets; +import java.nio.file.CopyOption; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.stream.Collectors; + +public class GitHubHttpUtils { + + private GitHubHttpUtils() { + } + + protected static JSONObject getObject(@NotNull String urlString, @Nullable String token) throws IOException { + URL url = new URL(urlString); + URLConnection conn = url.openConnection(); + conn.setRequestProperty("User-Agent", "GithubReleases4J"); + if (token != null) { + conn.setRequestProperty("Authorization", "token " + token); + } + conn.setRequestProperty("Accept", "application/vnd.github.v3+json"); + conn.connect(); + + InputStream in = conn.getInputStream(); + + BufferedReader reader = new BufferedReader(new InputStreamReader(in, StandardCharsets.UTF_8)); + String responseBody = reader.lines().collect(Collectors.joining(System.lineSeparator())); + reader.close(); + return new JSONObject(responseBody); + } + + protected static JSONArray getArray(@NotNull String urlString, String token) throws IOException { + URL url = new URL(urlString); + + URLConnection conn = url.openConnection(); + conn.setRequestProperty("User-Agent", "GithubReleases4J"); + if (token != null) { + conn.setRequestProperty("Authorization", "token " + token); + } + conn.setRequestProperty("Accept", "application/vnd.github.v3+json"); + conn.connect(); + + InputStream in = conn.getInputStream(); + + BufferedReader reader = new BufferedReader(new InputStreamReader(in, StandardCharsets.UTF_8)); + String responseBody = reader.lines().collect(Collectors.joining(System.lineSeparator())); + reader.close(); + + return new JSONArray(responseBody); + } + + protected static File download(@NotNull String urlString, @Nullable String token, + @NotNull String path, CopyOption... copyOptions) throws IOException { + URL url = new URL(urlString); + Path target = Paths.get(path); + + URLConnection conn = url.openConnection(); + conn.setRequestProperty("User-Agent", "GithubReleases4J"); + if (token != null) { + conn.setRequestProperty("Authorization", "token " + token); + } + conn.setRequestProperty("Accept", "application/vnd.github.v3+json"); + + InputStream in = conn.getInputStream(); + + Files.copy(in, target, copyOptions); + in.close(); + + return target.toFile(); + } + + +} diff --git a/src/main/java/cc/carm/lib/githubreleases4j/GithubAsset.java b/src/main/java/cc/carm/lib/githubreleases4j/GithubAsset.java new file mode 100644 index 0000000..8fe28ad --- /dev/null +++ b/src/main/java/cc/carm/lib/githubreleases4j/GithubAsset.java @@ -0,0 +1,107 @@ +package cc.carm.lib.githubreleases4j; + +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.json.JSONObject; + +import java.io.File; +import java.io.IOException; +import java.nio.file.CopyOption; +import java.util.Date; +import java.util.Optional; + +public class GithubAsset { + + + protected static GithubAsset of(@NotNull GithubRelease source, @NotNull JSONObject contents) { + return new GithubAsset(source, contents); + } + + protected static GithubAsset of(@NotNull GithubRelease source, @NotNull String jsonString) { + return of(source, new JSONObject(jsonString)); + } + + private final @NotNull GithubRelease source; + private final @NotNull JSONObject contents; + + private GithubAsset(@NotNull GithubRelease source, @NotNull JSONObject contents) { + this.source = source; + this.contents = contents; + } + + protected @NotNull GithubRelease getSource() { + return source; + } + + protected @NotNull JSONObject getContents() { + return contents; + } + + public int getID() { + return getContents().getInt("id"); + } + + public @NotNull String getURL() { + return getContents().getString("url"); + } + + public @NotNull String getBrowserDownloadURL() { + return getContents().getString("browser_download_url"); + } + + public @NotNull String getNodeID() { + return getContents().getString("node_id"); + } + + public @NotNull String getName() { + return getContents().getString("name"); + } + + public @NotNull String getLabel() { + return getContents().getString("label"); + } + + public @NotNull String getState() { + return getContents().getString("state"); + } + + public @NotNull String getContentType() { + return getContents().getString("content_type"); + } + + public int getSize() { + return getContents().getInt("size"); + } + + public int getDownloadCount() { + return getContents().getInt("download_count"); + } + + public @Nullable Date getCreateTime() { + return GithubReleases4J.parseDate(getContents().getString("created_at")); + } + + public @Nullable Date getUpdateTime() { + return GithubReleases4J.parseDate(getContents().getString("updated_at")); + } + + public File download() throws IOException { + return download(null); + } + + public File download(@Nullable String path, CopyOption... options) throws IOException { + path = path == null ? getName() : path; + return GitHubHttpUtils.download(getBrowserDownloadURL(), getSource().getAuthToken(), path, options); + } + + public GithubUser getUploader() { + return Optional.ofNullable(getContents().getJSONObject("uploader")) + .map(GithubUser::of) + .orElse(null); + } + + @Override + public String toString() { + return getContents().toString(0); + } +} diff --git a/src/main/java/cc/carm/lib/githubreleases4j/GithubRelease.java b/src/main/java/cc/carm/lib/githubreleases4j/GithubRelease.java index 2f26962..c132cad 100644 --- a/src/main/java/cc/carm/lib/githubreleases4j/GithubRelease.java +++ b/src/main/java/cc/carm/lib/githubreleases4j/GithubRelease.java @@ -1,4 +1,154 @@ package cc.carm.lib.githubreleases4j; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.json.JSONArray; +import org.json.JSONObject; + +import java.util.ArrayList; +import java.util.Date; +import java.util.List; +import java.util.Optional; +import java.util.stream.Collectors; +import java.util.stream.IntStream; + public class GithubRelease { + + protected static @NotNull GithubRelease of(@NotNull String owner, @NotNull String repository, + @Nullable String token, + @NotNull JSONObject contents) { + return new GithubRelease(owner, repository, token, contents); + } + + protected static @NotNull GithubRelease of(@NotNull String owner, @NotNull String repository, + @NotNull JSONObject contents) { + return of(owner, repository, null, contents); + } + + public final @NotNull String owner; + public final @NotNull String repository; + protected @Nullable String authToken; + + private final @NotNull JSONObject contents; + + protected GithubRelease(@NotNull String owner, @NotNull String repository, + @Nullable String authToken, @NotNull JSONObject contents) { + this.owner = owner; + this.repository = repository; + this.authToken = authToken; + + this.contents = contents; + } + + protected @NotNull JSONObject getContents() { + return contents; + } + + public @NotNull String getOwner() { + return owner; + } + + public @NotNull String getRepository() { + return repository; + } + + protected @Nullable String getAuthToken() { + return authToken; + } + + public void setAuthToken(@Nullable String authToken) { + this.authToken = authToken; + } + + public int getID() { + return getContents().getInt("id"); + } + + public @NotNull String getTagName() { + return getContents().getString("tag_name"); + } + + public @NotNull String getName() { + return getContents().getString("name"); + } + + public @NotNull String getBody() { + return getContents().getString("body"); + } + + public boolean isDraft() { + return getContents().getBoolean("draft"); + } + + public boolean isPrerelease() { + return getContents().getBoolean("prerelease"); + } + + public @Nullable Date getCreateTime() { + return GithubReleases4J.parseDate(getContents().getString("created_at")); + } + + public @Nullable Date getPublishTime() { + return GithubReleases4J.parseDate(getContents().getString("published_at")); + } + + public @NotNull String getNodeID() { + return getContents().getString("node_id"); + } + + + public @NotNull String getTagCommitIsh() { + return getContents().getString("target_commitish"); + } + + + public @NotNull String getURL() { + return getContents().getString("url"); + } + + public @NotNull String getHTMLUrl() { + return getContents().getString("html_url"); + } + + public @NotNull String getAssetsURL() { + return getContents().getString("assets_url"); + } + + public @NotNull String getUploadURL() { + return getContents().getString("upload_url"); + } + + public String getTarballURL() { + return getContents().getString("tarball_url"); + } + + public String getZipBallURL() { + return getContents().getString("zipball_url"); + } + + public @Nullable String getDiscussionURL() { + return getContents().getString("discussion_url"); + } + + public GithubUser getAuthor() { + return Optional.ofNullable(getContents().getJSONObject("author")) + .map(GithubUser::of) + .orElse(null); + } + + public List getAssets() { + JSONArray assetsArray = getContents().getJSONArray("assets"); + if (assetsArray == null) return new ArrayList<>(); + return IntStream.range(0, assetsArray.length()) + .mapToObj(assetsArray::getJSONObject) + .map(assetsJSON -> GithubAsset.of(this, assetsJSON)) + .collect(Collectors.toList()); + } + + @Override + public String toString() { + return getContents().toString(0); + } + + } diff --git a/src/main/java/cc/carm/lib/githubreleases4j/GithubReleases4J.java b/src/main/java/cc/carm/lib/githubreleases4j/GithubReleases4J.java new file mode 100644 index 0000000..5e654f2 --- /dev/null +++ b/src/main/java/cc/carm/lib/githubreleases4j/GithubReleases4J.java @@ -0,0 +1,99 @@ +package cc.carm.lib.githubreleases4j; + +import org.jetbrains.annotations.Contract; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.json.JSONArray; +import org.json.JSONObject; + +import java.io.IOException; +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.Date; +import java.util.List; +import java.util.stream.Collectors; +import java.util.stream.IntStream; + +public class GithubReleases4J { + + private GithubReleases4J() { + } + + public static String GITHUB_API_URL = "https://api.github.com"; + public static SimpleDateFormat GH_TIME_FORMAT = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'"); + + public static @NotNull List listReleases(@NotNull String owner, @NotNull String repository, + @Nullable String token) { + try { + JSONArray releasesArray = GitHubHttpUtils.getArray(buildURL( + "%s/repos/%s/%s/releases", GITHUB_API_URL, owner, repository + ), token); + + return IntStream.range(0, releasesArray.length()) + .mapToObj(releasesArray::getJSONObject) + .map(releaseJSON -> GithubRelease.of(owner, repository, token, releaseJSON)) + .collect(Collectors.toList()); + } catch (IOException e) { + return new ArrayList<>(); + } + } + + public static @NotNull List listReleases(@NotNull String owner, @NotNull String repository) { + return listReleases(owner, repository, null); + } + + public static @Nullable GithubRelease getRelease(@NotNull String owner, @NotNull String repository, + @NotNull String releaseID, @Nullable String token) { + + try { + JSONObject releaseJSON = GitHubHttpUtils.getObject(buildURL( + "%s/repos/%s/%s/releases/%s", GITHUB_API_URL, owner, repository, releaseID + ), token); + + return GithubRelease.of(owner, repository, token, releaseJSON); + } catch (IOException e) { + return null; + } + + } + + public static @Nullable GithubRelease getRelease(@NotNull String owner, @NotNull String repository, + @NotNull String releaseID) { + return getRelease(owner, repository, releaseID, null); + } + + public static @Nullable GithubRelease getReleaseByTag(@NotNull String owner, @NotNull String repository, + @NotNull String tagName, @Nullable String token) { + return getRelease(owner, repository, "tags/" + tagName, token); + } + + + public static @Nullable GithubRelease getReleaseByTag(@NotNull String owner, @NotNull String repository, + @NotNull String tagName) { + return getReleaseByTag(owner, repository, tagName, null); + } + + public static @Nullable GithubRelease getLatestRelease(@NotNull String owner, @NotNull String repository, + @Nullable String token) { + return getRelease(owner, repository, "latest", token); + } + + public static @Nullable GithubRelease getLatestRelease(@NotNull String owner, @NotNull String repository) { + return getLatestRelease(owner, repository, null); + } + + private static String buildURL(@NotNull String url, Object... params) { + return String.format(url, params); + } + + @Contract("null->null") + protected static @Nullable Date parseDate(@Nullable String dateString) { + if (dateString == null) return null; + try { + return GH_TIME_FORMAT.parse(dateString); + } catch (Exception exception) { + return null; + } + } + +} diff --git a/src/main/java/cc/carm/lib/githubreleases4j/GithubUser.java b/src/main/java/cc/carm/lib/githubreleases4j/GithubUser.java new file mode 100644 index 0000000..587c28e --- /dev/null +++ b/src/main/java/cc/carm/lib/githubreleases4j/GithubUser.java @@ -0,0 +1,30 @@ +package cc.carm.lib.githubreleases4j; + +import org.jetbrains.annotations.NotNull; +import org.json.JSONObject; + +public class GithubUser { + + protected static GithubUser of(@NotNull JSONObject contents) { + return new GithubUser(contents); + } + + protected static GithubUser of(@NotNull String jsonString) { + return of(new JSONObject(jsonString)); + } + + private final @NotNull JSONObject contents; + + private GithubUser(@NotNull JSONObject contents) { + this.contents = contents; + } + + protected @NotNull JSONObject getContents() { + return contents; + } + + @Override + public String toString() { + return getContents().toString(0); + } +} diff --git a/src/test/java/GithubReleasesTest.java b/src/test/java/GithubReleasesTest.java new file mode 100644 index 0000000..d5c2109 --- /dev/null +++ b/src/test/java/GithubReleasesTest.java @@ -0,0 +1,53 @@ +import cc.carm.lib.githubreleases4j.GithubAsset; +import cc.carm.lib.githubreleases4j.GithubRelease; +import cc.carm.lib.githubreleases4j.GithubReleases4J; +import org.jetbrains.annotations.Nullable; +import org.junit.Test; + +import java.io.File; +import java.io.IOException; +import java.text.SimpleDateFormat; + +public class GithubReleasesTest { + + public static final SimpleDateFormat FORMAT = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); + + @Test + public void onTest() { + + GithubReleases4J.listReleases("CarmJos", "EasyPlugin") + .stream().limit(2).forEach(GithubReleasesTest::printInfo); + + GithubRelease release = GithubReleases4J.getLatestRelease("CarmJos", "UltraDepository"); + if (release != null) { + printInfo(release); + release.getAssets().stream().findFirst().ifPresent(githubAsset -> { + try { + File file = githubAsset.download(null); + } catch (IOException e) { + e.printStackTrace(); + } + }); + } + + + } + + private static void printInfo(@Nullable GithubRelease release) { + if (release == null) System.out.println("# NULL"); + else { + System.out.println("# " + release.getName() + " [" + FORMAT.format(release.getCreateTime()) + "]"); +// List assets = release.getAssets(); +// assets.forEach(GithubReleasesTest::printAssets); + } + } + + private static void printAssets(@Nullable GithubAsset assets) { + if (assets == null) System.out.println("- NULL"); + else { + System.out.println("- " + assets.getName() + " [" + assets.getSize() + "]"); + } + } + + +}