From c1ed93203cb43c2634cd677c98140e0879cc5f25 Mon Sep 17 00:00:00 2001 From: Sekwah Date: Sun, 24 Apr 2022 13:44:14 +0100 Subject: [PATCH] chore(ci): add pre-commit as well as split variables out --- .github/workflows/gradle.yml | 80 ++--- .github/workflows/pre-commit-check.yaml | 41 +++ .pre-commit-config.yaml | 17 + .versionrc.js | 130 ++++---- DragAndDropStarter.bat | 2 +- TODO.md | 18 -- build.gradle | 216 +------------ .../core/AdvancedPortalsCore.java | 54 ++-- .../core/AdvancedPortalsModule.java | 76 ++--- .../core/config/ConfigHandler.java | 20 +- .../core/data/DataStorage.java | 298 +++++++++--------- curse.gradle | 172 ++++++++++ discord.gradle | 54 ++++ env-variables.gradle | 16 + gradlew.bat | 168 +++++----- lang/build.gradle | 2 - lang/src/main/resources/lang/en_GB.lang | 1 - lang/src/main/resources/lang/fr_FR.lang | 2 +- settings.gradle | 22 +- version.txt | 1 + 20 files changed, 736 insertions(+), 654 deletions(-) create mode 100644 .github/workflows/pre-commit-check.yaml create mode 100644 .pre-commit-config.yaml delete mode 100644 TODO.md create mode 100644 curse.gradle create mode 100644 discord.gradle create mode 100644 env-variables.gradle create mode 100644 version.txt diff --git a/.github/workflows/gradle.yml b/.github/workflows/gradle.yml index 622b9f6..4ebfe8a 100644 --- a/.github/workflows/gradle.yml +++ b/.github/workflows/gradle.yml @@ -1,40 +1,40 @@ -name: Build Project - -on: - push: - branches: - - '**' - tags: - - '*' - pull_request: - -jobs: - build: - - runs-on: ubuntu-latest - - steps: - - uses: actions/checkout@v2 - - name: Set up JDK 8 - uses: actions/setup-java@v2 - with: - distribution: 'zulu' - java-version: '8.0' - - name: Cache Gradle packages - uses: actions/cache@v2 - with: - path: ~/.gradle/caches - key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle') }} - restore-keys: ${{ runner.os }}-gradle - - name: Build with Gradle - run: ./gradlew buildSubmodules build - - name: Upload to Discord (If pre-release tag) - if: "startsWith(github.ref, 'refs/tags/v') && contains(github.ref, '-')" - env: - DISCORD_WEBHOOK: ${{ secrets.DISCORD_WEBHOOK }} - run: ./gradlew discordupload - - name: Publish to Curseforge (If release tag) - if: "startsWith(github.ref, 'refs/tags/v') && !contains(github.ref, '-')" - env: - CURSE_API: ${{ secrets.CURSE_API }} - run: ./gradlew curseforge +name: Build Project + +on: + push: + branches: + - '**' + tags: + - '*' + pull_request: + +jobs: + build: + + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v2 + - name: Set up JDK 8 + uses: actions/setup-java@v2 + with: + distribution: 'zulu' + java-version: '8.0' + - name: Cache Gradle packages + uses: actions/cache@v2 + with: + path: ~/.gradle/caches + key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle') }} + restore-keys: ${{ runner.os }}-gradle + - name: Build with Gradle + run: ./gradlew buildSubmodules build + - name: Upload to Discord (If pre-release tag) + if: "startsWith(github.ref, 'refs/tags/v') && contains(github.ref, '-')" + env: + DISCORD_WEBHOOK: ${{ secrets.DISCORD_WEBHOOK }} + run: ./gradlew discordupload + - name: Publish to Curseforge (If release tag) + if: "startsWith(github.ref, 'refs/tags/v') && !contains(github.ref, '-')" + env: + CURSE_API: ${{ secrets.CURSE_API }} + run: ./gradlew curseforge diff --git a/.github/workflows/pre-commit-check.yaml b/.github/workflows/pre-commit-check.yaml new file mode 100644 index 0000000..f578df7 --- /dev/null +++ b/.github/workflows/pre-commit-check.yaml @@ -0,0 +1,41 @@ +name: "Pre-commit consistency check" + +on: + workflow_dispatch: + pull_request: + +concurrency: + group: ${{ github.head_ref }}-precommit + cancel-in-progress: true + +jobs: + pre-commit-check: + name: Run pre-commit checks + runs-on: ubuntu-20.04 + steps: + - name: Checkout + uses: actions/checkout@v2 + with: + fetch-depth: 0 + + - uses: dorny/paths-filter@v2 + id: filter + with: + list-files: shell + filters: | + addedOrModified: + - added|modified: '**' + + # run only if changed files were detected + - name: Run against changes + uses: pre-commit/action@v2.0.3 + if: steps.filter.outputs.addedOrModified == 'true' + with: + extra_args: --files ${{ steps.filter.outputs.addedOrModified_files }} + + # run if no changed files were detected (e.g. workflow_dispatch on master branch) + - name: Run against all files + uses: pre-commit/action@v2.0.3 + if: steps.filter.outputs.addedOrModified != 'true' + with: + extra_args: --all-files diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100644 index 0000000..53eda73 --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1,17 @@ +# See https://pre-commit.com for more information +repos: + - repo: https://github.com/pre-commit/pre-commit-hooks + rev: v4.0.1 + hooks: + - id: trailing-whitespace + - id: end-of-file-fixer + - id: fix-byte-order-marker + - id: mixed-line-ending + - id: check-merge-conflict + - id: check-case-conflict + + - repo: https://github.com/Lucas-C/pre-commit-hooks + rev: v1.1.10 + hooks: + - id: remove-crlf + - id: remove-tabs diff --git a/.versionrc.js b/.versionrc.js index dde3314..a5b60d2 100644 --- a/.versionrc.js +++ b/.versionrc.js @@ -1,65 +1,65 @@ -let versionRegex = /(\nversion:\s)([0-9.-]+)/; -let velocityVersionRegex = /(\sversion\s=\s")([0-9.-]+)("\))/; - - -const ymlUpdater = { - updater: { - 'readVersion': (contents) => { - return versionRegex.exec(contents)[2]; - }, - 'writeVersion': (contents, version) => { - return contents.replace(versionRegex, `$1${version}`); - } - } -} - -const bungee = { - filename: 'src/main/resources/bungee.yml', - ...ymlUpdater, -} - -const spigotPlugin = { - filename: 'spigot/src/main/resources/plugin.yml', - ...ymlUpdater, -} - - -const gradleTracker = { - filename: 'gradle.properties', - updater: { - 'readVersion': (contents) => { - return versionRegex.exec(contents)[2]; - }, - 'writeVersion': (contents, version) => { - return contents.replace(versionRegex, `$1${version}`); - } - } -} - - -const velocity_plugin = { - filename: 'src/main/java/com/sekwah/advancedportals/velocity/AdvancedPortalsPlugin.java', - updater: { - 'readVersion': (contents) => { - return velocityVersionRegex.exec(contents)[2]; - }, - 'writeVersion': (contents, version) => { - return contents.replace(velocityVersionRegex, `$1${version}$3`); - } - } -} - -const files = [gradleTracker] // spigotPlugin, velocity_plugin, bungee - -module.exports = { - bumpFiles: files, - packageFiles: files, - // In case you need to force a version change (mostly due to change of scope of the update e.g. major now instead of patch) - //releaseAs: '1.0.0', - header:"# Changelog\n" + - "\n" + - "All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.\n" + - "\n" + - "For the release changelogs see [CHANGELOG.md](CHANGELOG.md) \n" + - "For the snapshot changelogs see [SNAPSHOT_CHANGELOG.md](SNAPSHOT_CHANGELOG.md)\n", -} +let versionRegex = /(\nversion:\s)([0-9.-]+)/; +let velocityVersionRegex = /(\sversion\s=\s")([0-9.-]+)("\))/; + + +const ymlUpdater = { + updater: { + 'readVersion': (contents) => { + return versionRegex.exec(contents)[2]; + }, + 'writeVersion': (contents, version) => { + return contents.replace(versionRegex, `$1${version}`); + } + } +} + +const bungee = { + filename: 'src/main/resources/bungee.yml', + ...ymlUpdater, +} + +const spigotPlugin = { + filename: 'spigot/src/main/resources/plugin.yml', + ...ymlUpdater, +} + + +const gradleTracker = { + filename: 'gradle.properties', + updater: { + 'readVersion': (contents) => { + return versionRegex.exec(contents)[2]; + }, + 'writeVersion': (contents, version) => { + return contents.replace(versionRegex, `$1${version}`); + } + } +} + + +const velocity_plugin = { + filename: 'src/main/java/com/sekwah/advancedportals/velocity/AdvancedPortalsPlugin.java', + updater: { + 'readVersion': (contents) => { + return velocityVersionRegex.exec(contents)[2]; + }, + 'writeVersion': (contents, version) => { + return contents.replace(velocityVersionRegex, `$1${version}$3`); + } + } +} + +const files = [gradleTracker] // spigotPlugin, velocity_plugin, bungee + +module.exports = { + bumpFiles: files, + packageFiles: files, + // In case you need to force a version change (mostly due to change of scope of the update e.g. major now instead of patch) + //releaseAs: '1.0.0', + header:"# Changelog\n" + + "\n" + + "All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.\n" + + "\n" + + "For the release changelogs see [CHANGELOG.md](CHANGELOG.md) \n" + + "For the snapshot changelogs see [SNAPSHOT_CHANGELOG.md](SNAPSHOT_CHANGELOG.md)\n", +} diff --git a/DragAndDropStarter.bat b/DragAndDropStarter.bat index ab45dc3..7266fce 100644 --- a/DragAndDropStarter.bat +++ b/DragAndDropStarter.bat @@ -4,4 +4,4 @@ REM Use this file for testing cases for different versions, just drag the versio java -Xmx4096M -DIReallyKnowWhatIAmDoingISwear=true -jar %1 REM Could add a 32 bit test part but noone uses 32 bit anymore GOTO A -PAUSE. \ No newline at end of file +PAUSE. diff --git a/TODO.md b/TODO.md deleted file mode 100644 index 45e11fd..0000000 --- a/TODO.md +++ /dev/null @@ -1,18 +0,0 @@ -TODO -================ -Main Tasks (Generally should be done in order) - -Tag registration system (Mostly done, just needs to be tested and implemented) - -Portal trigger system - -Configs for language files to allow all messages to change - -Change item data from strings to an object with strings in maybe - -Bungee Support Set Locations - -Keept the data storage for destinations and portals generally the same -but modify it a little to be nicer for the tag registry. - -Recode for spongepowered or find a way to make it work easier for them. diff --git a/build.gradle b/build.gradle index cd5e748..ebdf166 100644 --- a/build.gradle +++ b/build.gradle @@ -1,19 +1,3 @@ -import org.apache.commons.codec.Charsets -import org.apache.http.HttpEntity -import org.apache.http.HttpResponse -import org.apache.http.client.HttpClient -import org.apache.http.client.config.CookieSpecs -import org.apache.http.client.config.RequestConfig -import org.apache.http.client.methods.CloseableHttpResponse -import org.apache.http.client.methods.HttpPost -import org.apache.http.entity.ContentType -import org.apache.http.entity.mime.MultipartEntityBuilder -import org.apache.http.impl.client.CloseableHttpClient -import org.apache.http.impl.client.HttpClientBuilder -import org.apache.http.impl.client.HttpClients -import org.apache.http.client.methods.HttpGet -import com.google.gson.Gson - allprojects { apply plugin: 'java' @@ -46,16 +30,16 @@ buildscript { } } +apply from: 'env-variables.gradle' + archivesBaseName = "Advanced-Portals" group = 'com.sekwah.advancedportals' -version = '1.0.0' +def versionString = (file('./version.txt').text + (isRelease ? "" : "-${snapshotName}${shaRef}")).replaceAll('\n', '') +setVersion(versionString) +println "Version: ${getVersion()}" description = "" -def branch = System.getenv("GITHUB_REF"); -def sha = System.getenv("GITHUB_SHA"); -def isDevBranch = branch == null || !(branch.startsWith("refs/tags/") && !branch.contains("-")) - tasks.withType(JavaCompile) { options.encoding = 'UTF-8' } @@ -81,6 +65,10 @@ dependencies { includeLibs project(':velocity') } +apply from: 'env-variables.gradle' + +println "Branch ${ext.branch}${ext.shaRef} isRelease: '${ext.isRelease}'" + jar { // Filters the files out that are in the build folders. Look to see if there is a better way to do this? @@ -91,189 +79,3 @@ jar { it.isDirectory() ? it : zipTree(it) } } - -/** For pre-releases and testers to be able to try the latest commits if they want. - * If the builds start exceeding 8MB then we may want to upload to s3 instead and periodically clear. - * TODO possibly add a task that announces when builds are made? - * Though add a note that it may take a while for Curse to approve the files. - */ -task discordupload { - dependsOn(jar) - doLast { - String discordWebhook = System.getenv("DISCORD_WEBHOOK") - - if(discordWebhook != null) { - println("Logging Into Discord") - - CloseableHttpClient httpClient = HttpClients.createDefault() - HttpPost uploadFile = new HttpPost(discordWebhook) - - MultipartEntityBuilder builder = MultipartEntityBuilder.create() - builder.addTextBody("content", "New automated dev build\n\n" + - "Current Features: <${project.github}/blob/${sha}/docs/changelogs/SNAPSHOT_CHANGELOG.md>") - - builder.addBinaryBody("file", file(jar.archiveFile).newInputStream(), ContentType.APPLICATION_OCTET_STREAM, jar.archiveName) - - HttpEntity multipart = builder.build() - - uploadFile.setEntity(multipart) - CloseableHttpResponse response = httpClient.execute(uploadFile) - response.getEntity() - - println("Posted build") - - } else { - println("Discord webhook unspecified") - } - } -} - - -static String getValueFromCurseAPI(apiKey, endpoint) { - String API_BASE_URL = 'https://minecraft.curseforge.com' - - Gson gson = new Gson() - - HttpClient client = HttpClientBuilder.create() - .setDefaultRequestConfig(RequestConfig.custom() - .setCookieSpec(CookieSpecs.IGNORE_COOKIES).build()).build() - - HttpGet get = new HttpGet(API_BASE_URL + endpoint) - get.setHeader('X-Api-Token', apiKey) - - HttpResponse response = client.execute(get) - - int statusCode = response.statusLine.statusCode - - if (statusCode == 200) { - byte[] data = response.entity.content.bytes - return new String(data, Charsets.UTF_8) - } else { - if (response.getFirstHeader('content-type').value.contains('json')) { - InputStreamReader reader = new InputStreamReader(response.entity.content) - reader.close() - throw new RuntimeException("[CurseForge] Error") - } else { - throw new RuntimeException("[CurseForge] HTTP Error Code $response.statusLine.statusCode: $response.statusLine.reasonPhrase") - } - } -} - -/** - * Upload a single file (in case you also want to upload the other files like source n stuff) - * @param json - * @param file - * @return - * @throws IOException - * @throws URISyntaxException - */ -UploadResponse uploadFile(Metadata metadata, File file, String apiKey, Gson gson) throws IOException, URISyntaxException { - String API_BASE_URL = 'https://minecraft.curseforge.com' - String UPLOAD_URL = "/api/projects/%s/upload-file" - // Upload - // Important info - String uploadUrl = String.format(API_BASE_URL + UPLOAD_URL, project.curse_project_id) - - HttpClient client = HttpClientBuilder.create() - .setDefaultRequestConfig(RequestConfig.custom() - .setCookieSpec(CookieSpecs.IGNORE_COOKIES).build()).build() - - HttpPost post = new HttpPost(uploadUrl) - post.setHeader('X-Api-Token', apiKey) - - - // https://support.curseforge.com/en/support/solutions/articles/9000197321-curseforge-api - post.setEntity(MultipartEntityBuilder.create() - .addTextBody('metadata', gson.toJson(metadata), ContentType.APPLICATION_JSON) - .addBinaryBody('file', file) - .build()) - - HttpResponse response = client.execute(post) - InputStreamReader reader = new InputStreamReader(response.entity.content) - UploadResponse uploadResponse = gson.fromJson(reader, UploadResponse) - reader.close() - return uploadResponse -} - -class GameVersion { - int id - int gameVersionTypeID - String name - String slug -} - -/** - * As described here https://support.curseforge.com/en/support/solutions/articles/9000197321-curseforge-api - */ -class Metadata { - String changelog - String changelogType - int[] gameVersions - String releaseType -} - -class UploadResponse { - int id; -} - - -// Based on https://github.com/matthewprenger/CurseGradle as it didnt support Bukkit uploads at the time. -task curseforge { - dependsOn(jar) - doLast { - String apiKey = null - - if (System.getenv("CURSE_API") != null) { - apiKey = System.getenv("CURSE_API") - } - - if(apiKey != null) { - - Gson gson = new Gson() - - //String VERSION_TYPES_URL = "/api/game/version-types" - int gameVersionTypeID = 1 - String VERSION_URL = "/api/game/versions" - println("Uploading to CurseForge") - - // Get game versions - String gameVersionsString = getValueFromCurseAPI(apiKey, VERSION_URL) - GameVersion[] gameVersions = gson.fromJson(gameVersionsString, GameVersion[].class) - def versions = gameVersions.findAll {it.gameVersionTypeID == gameVersionTypeID} - - String[] supportedVersions = [ - "1.16", - "1.15", - "1.14", - "1.13" - ] - - def supportedGameVersions = versions.findAll {supportedVersions.contains(it.name)} - int[] supportedGameVersionIds = supportedGameVersions.collect {it.id}.toArray() - - println("Supported Version Id's ${supportedGameVersionIds}") - - Metadata uploadMetadata = new Metadata(); - - uploadMetadata.changelog = "${project.github}/blob/${sha}/docs/changelogs/CHANGELOG.md" - uploadMetadata.changelogType = "markdown" - uploadMetadata.releaseType = isDevBranch ? "beta" : "release" - uploadMetadata.gameVersions = supportedGameVersionIds - - def uploadId = uploadFile(uploadMetadata, file(jar.archiveFile), apiKey, gson) - - println("Uploaded with ID: ${uploadId.id}") - - println("Published build") - - } else { - println("Discord webhook unspecified") - } - } -// id = project.curse_project_id -// // TODO add code to reference this but also cut the latest change logs in for the files -// changelog = "${project.github}/blob/${sha}/CHANGELOG.md" -// changelogType = 'markdown' -// releaseType = 'release' -} - diff --git a/core/src/main/java/com/sekwah/advancedportals/core/AdvancedPortalsCore.java b/core/src/main/java/com/sekwah/advancedportals/core/AdvancedPortalsCore.java index 7434223..b8f8322 100644 --- a/core/src/main/java/com/sekwah/advancedportals/core/AdvancedPortalsCore.java +++ b/core/src/main/java/com/sekwah/advancedportals/core/AdvancedPortalsCore.java @@ -1,27 +1,27 @@ -package com.sekwah.advancedportals.core; - -import com.google.inject.Guice; -import com.google.inject.Injector; -import com.sekwah.advancedportals.core.config.CoreModule; - -public class AdvancedPortalsCore { - - /** - * https://github.com/google/guice/wiki/GettingStarted - * - */ - private Injector injector = Guice.createInjector(new CoreModule(this)); - - /** - * For some platforms we could do this on construction but this just allows for a bit more control - */ - public void onEnable() { - AdvancedPortalsModule module = new AdvancedPortalsModule(this); - injector = module.getInjector(); - } - - public void onDisable() { - - } - -} +package com.sekwah.advancedportals.core; + +import com.google.inject.Guice; +import com.google.inject.Injector; +import com.sekwah.advancedportals.core.config.CoreModule; + +public class AdvancedPortalsCore { + + /** + * https://github.com/google/guice/wiki/GettingStarted + * + */ + private Injector injector = Guice.createInjector(new CoreModule(this)); + + /** + * For some platforms we could do this on construction but this just allows for a bit more control + */ + public void onEnable() { + AdvancedPortalsModule module = new AdvancedPortalsModule(this); + injector = module.getInjector(); + } + + public void onDisable() { + + } + +} diff --git a/core/src/main/java/com/sekwah/advancedportals/core/AdvancedPortalsModule.java b/core/src/main/java/com/sekwah/advancedportals/core/AdvancedPortalsModule.java index 0fd107f..3bbbd16 100644 --- a/core/src/main/java/com/sekwah/advancedportals/core/AdvancedPortalsModule.java +++ b/core/src/main/java/com/sekwah/advancedportals/core/AdvancedPortalsModule.java @@ -1,38 +1,38 @@ -package com.sekwah.advancedportals.core; - -import com.google.inject.AbstractModule; -import com.google.inject.Guice; -import com.google.inject.Injector; -import com.sekwah.advancedportals.core.config.Config; -import com.sekwah.advancedportals.core.config.ConfigHandler; - -import javax.annotation.Nonnull; - -public class AdvancedPortalsModule extends AbstractModule { - - - private Injector injector; - private AdvancedPortalsCore advancedPortalsCore; - - public AdvancedPortalsModule(AdvancedPortalsCore advancedPortalsCore) { - this.advancedPortalsCore = advancedPortalsCore; - } - - @Override - protected void configure() { - // Instances - bind(AdvancedPortalsCore.class).toInstance(advancedPortalsCore); - - // Providers - bind(Config.class).toProvider(ConfigHandler.class); - } - - public Injector createInjector() { - return Guice.createInjector(this); - } - - @Nonnull - public Injector getInjector() { - return injector; - } -} +package com.sekwah.advancedportals.core; + +import com.google.inject.AbstractModule; +import com.google.inject.Guice; +import com.google.inject.Injector; +import com.sekwah.advancedportals.core.config.Config; +import com.sekwah.advancedportals.core.config.ConfigHandler; + +import javax.annotation.Nonnull; + +public class AdvancedPortalsModule extends AbstractModule { + + + private Injector injector; + private AdvancedPortalsCore advancedPortalsCore; + + public AdvancedPortalsModule(AdvancedPortalsCore advancedPortalsCore) { + this.advancedPortalsCore = advancedPortalsCore; + } + + @Override + protected void configure() { + // Instances + bind(AdvancedPortalsCore.class).toInstance(advancedPortalsCore); + + // Providers + bind(Config.class).toProvider(ConfigHandler.class); + } + + public Injector createInjector() { + return Guice.createInjector(this); + } + + @Nonnull + public Injector getInjector() { + return injector; + } +} diff --git a/core/src/main/java/com/sekwah/advancedportals/core/config/ConfigHandler.java b/core/src/main/java/com/sekwah/advancedportals/core/config/ConfigHandler.java index 568245a..28f5ef6 100644 --- a/core/src/main/java/com/sekwah/advancedportals/core/config/ConfigHandler.java +++ b/core/src/main/java/com/sekwah/advancedportals/core/config/ConfigHandler.java @@ -1,10 +1,10 @@ -package com.sekwah.advancedportals.core.config; - -import com.google.inject.Provider; - -public class ConfigHandler implements Provider { - @Override - public Config get() { - return null; - } -} +package com.sekwah.advancedportals.core.config; + +import com.google.inject.Provider; + +public class ConfigHandler implements Provider { + @Override + public Config get() { + return null; + } +} diff --git a/core/src/main/java/com/sekwah/advancedportals/core/data/DataStorage.java b/core/src/main/java/com/sekwah/advancedportals/core/data/DataStorage.java index ea323b2..24c4301 100644 --- a/core/src/main/java/com/sekwah/advancedportals/core/data/DataStorage.java +++ b/core/src/main/java/com/sekwah/advancedportals/core/data/DataStorage.java @@ -1,149 +1,149 @@ -package com.sekwah.advancedportals.core.data; - -import com.google.gson.Gson; -import com.google.gson.GsonBuilder; -import com.google.inject.Inject; -import com.sekwah.advancedportals.core.AdvancedPortalsCore; -import com.sekwah.advancedportals.util.InfoLogger; - -import java.io.*; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Type; - -public class DataStorage { - - private Gson gson = new GsonBuilder().setPrettyPrinting().create(); - - private File dataFolder; - - @Inject - private AdvancedPortalsCore portalsCore; - - @Inject - private InfoLogger infoLogger; - - public DataStorage(File dataStorageLoc) { - this.dataFolder = dataStorageLoc; - } - - /** - * Copies the default file, defaults to true to keep true to the name - * - * @param fileLoc - * @return - */ - public boolean copyDefaultFile(String fileLoc) { - return this.copyDefaultFile(fileLoc, true); - } - - public void copyDefaultFiles(boolean override, String... fileLocs) { - for (String fileLoc : fileLocs) { - this.copyDefaultFile(fileLoc, override); - } - } - - public T loadJson(Type dataHolder, String location) { - InputStream jsonResource = this.loadResource(location); - if(jsonResource == null) { - return null; - } - BufferedReader bufReader = new BufferedReader(new InputStreamReader(jsonResource)); - T object = gson.fromJson(bufReader, dataHolder); - return object; - } - public T loadJson(Class dataHolder, String location) { - InputStream jsonResource = this.loadResource(location); - if(jsonResource == null) { - try { - return dataHolder.getDeclaredConstructor().newInstance(); - } catch (InstantiationException | IllegalAccessException | NoSuchMethodException | InvocationTargetException e) { - e.printStackTrace(); - } - return null; - } - BufferedReader bufReader = new BufferedReader(new InputStreamReader(jsonResource)); - return gson.fromJson(bufReader, dataHolder); - } - - public void storeJson(Object dataHolder, String location) { - String json = gson.toJson(dataHolder); - try { - FileWriter fileWriter = new FileWriter(new File(this.dataFolder, location)); - fileWriter.write(json); - fileWriter.close(); - } catch (IOException e) { - e.printStackTrace(); - } - } - - /** - * Copies the specified file out of the plugin and into the plugins folder. - * - * @param fileLoc - * @return if the file is copied, will be false if override is false and the file already existed. - */ - public boolean copyDefaultFile(String fileLoc, boolean overwrite) { - File outFile = new File(this.dataFolder, fileLoc); - if (!outFile.exists()) { - outFile.getParentFile().mkdirs(); - } - if (!outFile.exists() || overwrite) { - try { - InputStream inputStream = this.getClass().getClassLoader().getResourceAsStream(fileLoc); - if(inputStream == null) { - return false; - } - - FileOutputStream outStream = new FileOutputStream(outFile); - - byte[] buf = new byte[1024]; - int len; - while ((len = inputStream.read(buf)) > 0) { - outStream.write(buf, 0, len); - } - inputStream.close(); - outStream.close(); - } catch (NullPointerException e) { - e.printStackTrace(); - this.infoLogger.logWarning("Could not load " + fileLoc + ". The file does" + - "not exist or there has been an error reading the file."); - return false; - } catch (FileNotFoundException e) { - e.printStackTrace(); - this.infoLogger.logWarning("Could not create " + fileLoc); - } catch (IOException e) { - e.printStackTrace(); - this.infoLogger.logWarning("File error reading " + fileLoc); - } - } - return true; - } - - /** - * A method to try to grab the files from the plugin and if its in the plugin folder load from there instead. - *

- * @param location - * @return - */ - public InputStream loadResource(String location) { - File inFile = new File(dataFolder, location); - if (inFile.exists() && !inFile.isDirectory()) { - try { - return new FileInputStream(inFile); - } catch (FileNotFoundException e) { - e.printStackTrace(); - return null; - } - } else { - try { - copyDefaultFile(location, false); - return this.getClass().getClassLoader().getResourceAsStream(location); - } catch (NullPointerException e) { - e.printStackTrace(); - this.infoLogger.logWarning("Could not load " + location + ". The file does" + - "not exist or there has been an error reading the file."); - return null; - } - } - } -} +package com.sekwah.advancedportals.core.data; + +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import com.google.inject.Inject; +import com.sekwah.advancedportals.core.AdvancedPortalsCore; +import com.sekwah.advancedportals.util.InfoLogger; + +import java.io.*; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Type; + +public class DataStorage { + + private Gson gson = new GsonBuilder().setPrettyPrinting().create(); + + private File dataFolder; + + @Inject + private AdvancedPortalsCore portalsCore; + + @Inject + private InfoLogger infoLogger; + + public DataStorage(File dataStorageLoc) { + this.dataFolder = dataStorageLoc; + } + + /** + * Copies the default file, defaults to true to keep true to the name + * + * @param fileLoc + * @return + */ + public boolean copyDefaultFile(String fileLoc) { + return this.copyDefaultFile(fileLoc, true); + } + + public void copyDefaultFiles(boolean override, String... fileLocs) { + for (String fileLoc : fileLocs) { + this.copyDefaultFile(fileLoc, override); + } + } + + public T loadJson(Type dataHolder, String location) { + InputStream jsonResource = this.loadResource(location); + if(jsonResource == null) { + return null; + } + BufferedReader bufReader = new BufferedReader(new InputStreamReader(jsonResource)); + T object = gson.fromJson(bufReader, dataHolder); + return object; + } + public T loadJson(Class dataHolder, String location) { + InputStream jsonResource = this.loadResource(location); + if(jsonResource == null) { + try { + return dataHolder.getDeclaredConstructor().newInstance(); + } catch (InstantiationException | IllegalAccessException | NoSuchMethodException | InvocationTargetException e) { + e.printStackTrace(); + } + return null; + } + BufferedReader bufReader = new BufferedReader(new InputStreamReader(jsonResource)); + return gson.fromJson(bufReader, dataHolder); + } + + public void storeJson(Object dataHolder, String location) { + String json = gson.toJson(dataHolder); + try { + FileWriter fileWriter = new FileWriter(new File(this.dataFolder, location)); + fileWriter.write(json); + fileWriter.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + + /** + * Copies the specified file out of the plugin and into the plugins folder. + * + * @param fileLoc + * @return if the file is copied, will be false if override is false and the file already existed. + */ + public boolean copyDefaultFile(String fileLoc, boolean overwrite) { + File outFile = new File(this.dataFolder, fileLoc); + if (!outFile.exists()) { + outFile.getParentFile().mkdirs(); + } + if (!outFile.exists() || overwrite) { + try { + InputStream inputStream = this.getClass().getClassLoader().getResourceAsStream(fileLoc); + if(inputStream == null) { + return false; + } + + FileOutputStream outStream = new FileOutputStream(outFile); + + byte[] buf = new byte[1024]; + int len; + while ((len = inputStream.read(buf)) > 0) { + outStream.write(buf, 0, len); + } + inputStream.close(); + outStream.close(); + } catch (NullPointerException e) { + e.printStackTrace(); + this.infoLogger.logWarning("Could not load " + fileLoc + ". The file does" + + "not exist or there has been an error reading the file."); + return false; + } catch (FileNotFoundException e) { + e.printStackTrace(); + this.infoLogger.logWarning("Could not create " + fileLoc); + } catch (IOException e) { + e.printStackTrace(); + this.infoLogger.logWarning("File error reading " + fileLoc); + } + } + return true; + } + + /** + * A method to try to grab the files from the plugin and if its in the plugin folder load from there instead. + *

+ * @param location + * @return + */ + public InputStream loadResource(String location) { + File inFile = new File(dataFolder, location); + if (inFile.exists() && !inFile.isDirectory()) { + try { + return new FileInputStream(inFile); + } catch (FileNotFoundException e) { + e.printStackTrace(); + return null; + } + } else { + try { + copyDefaultFile(location, false); + return this.getClass().getClassLoader().getResourceAsStream(location); + } catch (NullPointerException e) { + e.printStackTrace(); + this.infoLogger.logWarning("Could not load " + location + ". The file does" + + "not exist or there has been an error reading the file."); + return null; + } + } + } +} diff --git a/curse.gradle b/curse.gradle new file mode 100644 index 0000000..426f12d --- /dev/null +++ b/curse.gradle @@ -0,0 +1,172 @@ +import org.apache.commons.codec.Charsets +import org.apache.http.HttpResponse +import org.apache.http.client.HttpClient +import org.apache.http.client.config.CookieSpecs +import org.apache.http.client.config.RequestConfig +import org.apache.http.client.methods.HttpPost +import org.apache.http.entity.ContentType +import org.apache.http.entity.mime.MultipartEntityBuilder +import org.apache.http.impl.client.HttpClientBuilder +import org.apache.http.client.methods.HttpGet +import com.google.gson.Gson + +buildscript { + repositories { + mavenCentral() + } + dependencies { + classpath "org.apache.httpcomponents:httpmime:4.5.13" + classpath "com.google.code.gson:gson:2.8.6" + classpath "org.apache.httpcomponents:httpclient:4.5.13" + } +} + +apply from: 'env-variables.gradle' + +static String getValueFromCurseAPI(apiKey, endpoint) { + String API_BASE_URL = 'https://minecraft.curseforge.com' + + HttpClient client = HttpClientBuilder.create() + .setDefaultRequestConfig(RequestConfig.custom() + .setCookieSpec(CookieSpecs.IGNORE_COOKIES).build()).build() + + HttpGet get = new HttpGet(API_BASE_URL + endpoint) + get.setHeader('X-Api-Token', apiKey) + + HttpResponse response = client.execute(get) + + int statusCode = response.statusLine.statusCode + + if (statusCode == 200) { + byte[] data = response.entity.content.bytes + return new String(data, Charsets.UTF_8) + } else { + if (response.getFirstHeader('content-type').value.contains('json')) { + InputStreamReader reader = new InputStreamReader(response.entity.content) + reader.close() + throw new RuntimeException("[CurseForge] Error") + } else { + throw new RuntimeException("[CurseForge] HTTP Error Code $response.statusLine.statusCode: $response.statusLine.reasonPhrase") + } + } +} + +/** + * Upload a single file (in case you also want to upload the other files like source n stuff) + * @param json + * @param file + * @return + * @throws IOException + * @throws URISyntaxException + */ +UploadResponse uploadFile(Metadata metadata, File file, String apiKey, Gson gson) throws IOException, URISyntaxException { + String API_BASE_URL = 'https://minecraft.curseforge.com' + String UPLOAD_URL = "/api/projects/%s/upload-file" + // Upload + // Important info + String uploadUrl = String.format(API_BASE_URL + UPLOAD_URL, project.curse_project_id) + + HttpClient client = HttpClientBuilder.create() + .setDefaultRequestConfig(RequestConfig.custom() + .setCookieSpec(CookieSpecs.IGNORE_COOKIES).build()).build() + + HttpPost post = new HttpPost(uploadUrl) + post.setHeader('X-Api-Token', apiKey) + + + // https://support.curseforge.com/en/support/solutions/articles/9000197321-curseforge-api + post.setEntity(MultipartEntityBuilder.create() + .addTextBody('metadata', gson.toJson(metadata), ContentType.APPLICATION_JSON) + .addBinaryBody('file', file) + .build()) + + HttpResponse response = client.execute(post) + InputStreamReader reader = new InputStreamReader(response.entity.content) + UploadResponse uploadResponse = gson.fromJson(reader, UploadResponse) + reader.close() + return uploadResponse +} + +class GameVersion { + int id + int gameVersionTypeID + String name + String slug +} + +/** + * As described here https://support.curseforge.com/en/support/solutions/articles/9000197321-curseforge-api + */ +class Metadata { + String changelog + String changelogType + int[] gameVersions + String releaseType +} + +class UploadResponse { + int id +} + + +// Based on https://github.com/matthewprenger/CurseGradle as it didnt support Bukkit uploads at the time. +task curseforge { + dependsOn(jar) + doLast { + String apiKey = null + + if (System.getenv("CURSE_API") != null) { + apiKey = System.getenv("CURSE_API") + } + + if(apiKey != null) { + + Gson gson = new Gson() + + //String VERSION_TYPES_URL = "/api/game/version-types" + int gameVersionTypeID = 1 + String VERSION_URL = "/api/game/versions" + println("Uploading to CurseForge") + + // Get game versions + String gameVersionsString = getValueFromCurseAPI(apiKey, VERSION_URL) + GameVersion[] gameVersions = gson.fromJson(gameVersionsString, GameVersion[].class) + def versions = gameVersions.findAll {it.gameVersionTypeID == gameVersionTypeID} + + String[] supportedVersions = [ + "1.18", + "1.17", + "1.16", + "1.15", + "1.14", + "1.13" + ] + + def supportedGameVersions = versions.findAll {supportedVersions.contains(it.name)} + int[] supportedGameVersionIds = supportedGameVersions.collect {it.id}.toArray() + + println("Supported Version Id's ${supportedGameVersionIds}") + + Metadata uploadMetadata = new Metadata() + + uploadMetadata.changelog = "${project.github}/blob/${ext.githubSha}/docs/changelogs/CHANGELOG.md" + uploadMetadata.changelogType = "markdown" + uploadMetadata.releaseType = ext.isDevBranch ? "beta" : "release" + uploadMetadata.gameVersions = supportedGameVersionIds + + def uploadId = uploadFile(uploadMetadata, file(jar.archiveFile), apiKey, gson) + + println("Uploaded with ID: ${uploadId.id}") + + println("Published build") + + } else { + println("Curse token unspecified") + } + } +// id = project.curse_project_id +// // TODO add code to reference this but also cut the latest change logs in for the files +// changelog = "${project.github}/blob/${sha}/CHANGELOG.md" +// changelogType = 'markdown' +// releaseType = 'release' +} diff --git a/discord.gradle b/discord.gradle new file mode 100644 index 0000000..093ff84 --- /dev/null +++ b/discord.gradle @@ -0,0 +1,54 @@ +import org.apache.http.HttpEntity +import org.apache.http.client.methods.CloseableHttpResponse +import org.apache.http.client.methods.HttpPost +import org.apache.http.entity.ContentType +import org.apache.http.entity.mime.MultipartEntityBuilder +import org.apache.http.impl.client.CloseableHttpClient +import org.apache.http.impl.client.HttpClients + +buildscript { + repositories { + mavenCentral() + } + dependencies { + classpath "org.apache.httpcomponents:httpmime:4.5.13" + } +} + +apply from: 'env-variables.gradle' + +/** For pre-releases and testers to be able to try the latest commits if they want. + * If the builds start exceeding 8MB then we may want to upload to s3 instead and periodically clear. + * TODO possibly add a task that announces when builds are made? + * Though add a note that it may take a while for Curse to approve the files. + */ +task discordupload { + dependsOn(jar) + doLast { + String discordWebhook = System.getenv("DISCORD_WEBHOOK") + + if(discordWebhook != null) { + println("Logging Into Discord") + + CloseableHttpClient httpClient = HttpClients.createDefault() + HttpPost uploadFile = new HttpPost(discordWebhook) + + MultipartEntityBuilder builder = MultipartEntityBuilder.create() + builder.addTextBody("content", "New automated dev build\n\n" + + "Current Features: <${project.github}/blob/${ext.githubSha}/docs/changelogs/SNAPSHOT_CHANGELOG.md>") + + builder.addBinaryBody("file", file(jar.archiveFile).newInputStream(), ContentType.APPLICATION_OCTET_STREAM, jar.archiveName) + + HttpEntity multipart = builder.build() + + uploadFile.setEntity(multipart) + CloseableHttpResponse response = httpClient.execute(uploadFile) + response.getEntity() + + println("Posted build") + + } else { + println("Discord webhook unspecified ${sha}") + } + } +} diff --git a/env-variables.gradle b/env-variables.gradle new file mode 100644 index 0000000..bed0097 --- /dev/null +++ b/env-variables.gradle @@ -0,0 +1,16 @@ + +def branch = System.getenv("GITHUB_REF") +if(branch != null) { + branch = branch.replace('refs/heads/', '') +} +def isRelease = System.getenv("IS_RELEASE") == "true" + +def snapshotName = (branch == null || branch.startsWith("release-please")) ? "SNAPSHOT" : branch +def githubSha = System.getenv("GITHUB_SHA") +def shaRef = githubSha != null ? "-${githubSha.substring(0, 8)}" : "" + +ext.branch = branch +ext.snapshotName = snapshotName +ext.githubSha = githubSha +ext.shaRef = shaRef +ext.isRelease = isRelease diff --git a/gradlew.bat b/gradlew.bat index e95643d..f955316 100644 --- a/gradlew.bat +++ b/gradlew.bat @@ -1,84 +1,84 @@ -@if "%DEBUG%" == "" @echo off -@rem ########################################################################## -@rem -@rem Gradle startup script for Windows -@rem -@rem ########################################################################## - -@rem Set local scope for the variables with windows NT shell -if "%OS%"=="Windows_NT" setlocal - -set DIRNAME=%~dp0 -if "%DIRNAME%" == "" set DIRNAME=. -set APP_BASE_NAME=%~n0 -set APP_HOME=%DIRNAME% - -@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -set DEFAULT_JVM_OPTS= - -@rem Find java.exe -if defined JAVA_HOME goto findJavaFromJavaHome - -set JAVA_EXE=java.exe -%JAVA_EXE% -version >NUL 2>&1 -if "%ERRORLEVEL%" == "0" goto init - -echo. -echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. - -goto fail - -:findJavaFromJavaHome -set JAVA_HOME=%JAVA_HOME:"=% -set JAVA_EXE=%JAVA_HOME%/bin/java.exe - -if exist "%JAVA_EXE%" goto init - -echo. -echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% -echo. -echo Please set the JAVA_HOME variable in your environment to match the -echo location of your Java installation. - -goto fail - -:init -@rem Get command-line arguments, handling Windows variants - -if not "%OS%" == "Windows_NT" goto win9xME_args - -:win9xME_args -@rem Slurp the command line arguments. -set CMD_LINE_ARGS= -set _SKIP=2 - -:win9xME_args_slurp -if "x%~1" == "x" goto execute - -set CMD_LINE_ARGS=%* - -:execute -@rem Setup the command line - -set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar - -@rem Execute Gradle -"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% - -:end -@rem End local scope for the variables with windows NT shell -if "%ERRORLEVEL%"=="0" goto mainEnd - -:fail -rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of -rem the _cmd.exe /c_ return code! -if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 -exit /b 1 - -:mainEnd -if "%OS%"=="Windows_NT" endlocal - -:omega +@if "%DEBUG%" == "" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%" == "" set DIRNAME=. +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS= + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if "%ERRORLEVEL%" == "0" goto init + +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto init + +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:init +@rem Get command-line arguments, handling Windows variants + +if not "%OS%" == "Windows_NT" goto win9xME_args + +:win9xME_args +@rem Slurp the command line arguments. +set CMD_LINE_ARGS= +set _SKIP=2 + +:win9xME_args_slurp +if "x%~1" == "x" goto execute + +set CMD_LINE_ARGS=%* + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% + +:end +@rem End local scope for the variables with windows NT shell +if "%ERRORLEVEL%"=="0" goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 +exit /b 1 + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/lang/build.gradle b/lang/build.gradle index 35a994d..e076b51 100644 --- a/lang/build.gradle +++ b/lang/build.gradle @@ -1,3 +1 @@ // Check the root build.gradle under allprojects for common settings - - diff --git a/lang/src/main/resources/lang/en_GB.lang b/lang/src/main/resources/lang/en_GB.lang index 033e520..879a743 100644 --- a/lang/src/main/resources/lang/en_GB.lang +++ b/lang/src/main/resources/lang/en_GB.lang @@ -86,4 +86,3 @@ command.trans.help=Copy translation new default translation file command.version.help=Returns the current version of the plugin command.subcommand.nopermission= Sorry but you don't have permission for that, please use \u00A7e/%1$s help \u00A7cif you would like a list of possible sub commands. - diff --git a/lang/src/main/resources/lang/fr_FR.lang b/lang/src/main/resources/lang/fr_FR.lang index 9506ebf..2776033 100644 --- a/lang/src/main/resources/lang/fr_FR.lang +++ b/lang/src/main/resources/lang/fr_FR.lang @@ -43,7 +43,7 @@ command.create.complete= Le portail a bien été créé. command.createdesti.help=Crée une destination command.createdesti.error= Une erreur est survenue en créant la destination: command.createdesti.console= Vous ne pouvez pas créer une destination en utilisant la console. -command.createdesti.detailedhelp=Le format est /desti create (name) [tag:tagvalue] +command.createdesti.detailedhelp=Le format est /desti create (name) [tag:tagvalue] command.createdesti.complete= La destination a bien été créée. command.create.tags=\u00A7aTags: diff --git a/settings.gradle b/settings.gradle index 4f9ddb5..09475d0 100644 --- a/settings.gradle +++ b/settings.gradle @@ -1,11 +1,11 @@ -rootProject.name = "advanced-portals" -// Core modules -include 'core' -include 'lang' - -// Implementations -include 'spigot' - -// Proxies -include 'velocity' -include 'bungee' +rootProject.name = "advanced-portals" +// Core modules +include 'core' +include 'lang' + +// Implementations +include 'spigot' + +// Proxies +include 'velocity' +include 'bungee' diff --git a/version.txt b/version.txt new file mode 100644 index 0000000..2003b63 --- /dev/null +++ b/version.txt @@ -0,0 +1 @@ +0.9.2