diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..9fd3aba --- /dev/null +++ b/.gitattributes @@ -0,0 +1,2 @@ +* text=auto +*.java text eol=lf \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index ce272da..2744849 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,7 @@ -# Changelog (MC 1.10.2) +# Changelog (MC 1.12) + +### 3.0.1 +- Fix for command arguments (#71) ### 3.0.0 - Complete rewrite @@ -28,129 +31,4 @@ - Such as TPS for servers with many dimensions - Fixed permission missing crashes - Fixed relaying cancelled events - - Removed support for `&` in formatting - -### 2.2.0 -- Added `!uptime` command -- Minecraft formatting will be removed from Discord messages -- Minecraft messages can not trigger @here and @everyone mentions -- Hopefully fixed `customFormatting` using `&` gives weird character -- Don't queue when no token is set -- Proper update when switching channel - -### 2.1.0 -- Updated JDA to 2.2.1-353 -- Added `customFormatting` setting for Discord chat => Minecraft, when enabled... - - `usernameColor` is ignored - - Able to use Minecraft formatting in message - - Discord links are clickable in Minecraft -- Pretty formatted config file -- Added Minecraft command `save` to save the config file - - Adds missing config settings - - Removes unused config settings - - Pretty formats the file - -#### 2.0.1 -- Fix achievements not triggering - -### 2.0.0 -- Added custom command prefix -- Changed name to DiscordIntegration - - Config file will be renamed upon startup - - Mods using IMC needs to update to new name - -### 1.4.0 -- Updated JDA to 2.2.0-334 -- Added support for emojis - - Converting emojis from Discord to Minecraft - - Converting some smileys to emojis from Minecraft to Discord -- Added support for attachments (links to attachments in Minecraft) - -### 1.3.0 -- Added IMC support - - Mods can now register/unregister as listener for events - - Currently only `chat` events are sent - - Mods can send messages to Discord - - Messages will be prefixed with `[modid]` -- Added `relaySayCommand` option to Minecraft chat config - -### 1.2.0 -- Added `colored` option to `!tps` command - - This will not show in colors on mobile Discord (At the time of writing) - - Colors - - Green when `19 <= TPS` - - Orange when `15 <= TPS && TPS < 19` - - Red when `TPS < 15` - -#### 1.1.1 -- Fixed crash on achievements - -### 1.1.0 -- Added `%DESCRIPTION%` to Achievement messages -- Added custom commands (Read more on [the wiki](https://github.com/Chikachi/ChikachiDiscord/wiki/Custom-Commands)) -- `!tps` response is now padded so the times and TPS is lined up -- `!tps` response is now sorted after dimension ID -- Removed kick of player when using `!unstuck` - -## 1.0.0 - Out of Alpha! -![RELEASE](https://media.giphy.com/media/duGmnxv5TZDy/giphy.gif) -- Improved the `!tps` response text -- Switched to asynchronous sending messages to Discord - -### 0.6.0 -- Added ability for message when detecting server crashing -- Added support for other Discord formatting for `_Italic_` -- Improved handling of `!unstuck` command - -#### 0.5.1 -- Fix color of Discord usernames - - Added `usernameColor` to Minecraft chat config -- Fix missing characters after MC => Discord mention in Discord message - -### 0.5.0 -- Added ability for command aliases -- Added `!unstuck ` command to send a player to spawn - - Works for both online and offline players - - Will kick online players, as the client doesn't always update location -- Changed the way all messages are handled - - Now supports some of Discord's formatting (`**Bold**`, `*Italic*` and `__Underline__`) - - Removes formatting from `~~Line through~~` and ``` `code` ``` -- Mention a Discord user by clicking the name - -### 0.4.0 -- Added max length on relayed Discord messages (Default -1, meaning disabled) -- Added limit of commands to roles (by role name) -- Improved Discord user mentions (Prevents wrong mention in case of both `User1` and `User1_`) -- Replaced placeholders in strings (**BREAKS ALL CURRENT CONFIGS**) - - `%USER%` Name of user (Chat, Death, Achievement, Join, Leave) - - `%MESSAGE%` Message (Chat, Death) - - `%ACHIEVEMENT%` Name of achievement (Achievement) -- Returned player names from `!online` is now packed in like `this` -- Remove Minecraft formatting (1 character prefixed with ยง) from `/say` and chat messages - -### 0.3.0 -- Added `!tps` command for Discord -- Highlight player's name in Discord messages -- Highlight `@everyone` (Only from people with permission to mention everyone) - -### 0.2.0 -- Added command - - If ChikachiLib is detected, `/chikachi discord` - - Otherwise, `/discord` -- Broadcast messages (`/say`) is now also relayed -- Made Discord mentions case-insensitive - -#### 0.1.3 -- Fix NullPointerException on startup -- Added experimental fake players (CAN FILL YOUR SERVER UP WITH FAKE PLAYERS) -![Example](https://ss.chikachi.net/2016-05-05_03-10-13_7109d217-ef20-4979-a5a4-0baa8c8a46c4.png) -- Call proper shutdown of Discord connection - -#### 0.1.2 -- Improve Discord mentioning - -#### 0.1.1 -- Fix DiscordFakePlayers showing up in !online list - -### 0.1.0 -- Initial alpha version \ No newline at end of file + - Removed support for `&` in formatting \ No newline at end of file diff --git a/Jenkinsfile b/Jenkinsfile index b787e19..5a81986 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -3,10 +3,13 @@ pipeline { options { timeout(time: 30, unit: 'MINUTES') } + tools { + jdk 'jdk_8u144' + nodejs 'node_8.4.0' + } stages { stage('Prepare') { steps { - checkout scm sh 'chmod +x gradlew' sh './gradlew setupCiWorkspace clean spotlessApply' } @@ -20,6 +23,32 @@ pipeline { steps { sh './gradlew test' } + post { + always { + junit 'build/test-results/TEST-*.xml' + } + } + } + stage('Run Server Test') { + steps { + sh 'mkdir -p run/config/Chikachi' + sh 'mkdir -p run/mods' + writeFile file: 'run/eula.txt', text: 'eula=true' + withCredentials([file(credentialsId: 'discordintegration.test.config', variable: 'CONFIG_FILE')]) { + sh 'cp "$CONFIG_FILE" ./run/config/Chikachi/' + dir('serverTest') { + sh 'npm install' + sh 'tsc' + sh 'npm start' + } + } + } + post { + always { + archiveArtifacts 'run/logs/fml-server-latest.log' + cleanWs deleteDirs: true, notFailBuild: true, patterns: [[pattern: 'run/config/**', type: 'INCLUDE'], [pattern: 'run/mods/**', type: 'INCLUDE']] + } + } } stage('Archive') { steps { @@ -29,9 +58,6 @@ pipeline { } } post { - always { - junit 'build/test-results/TEST-*.xml' - } success { withCredentials([string(credentialsId: 'discord.webhook.channel', variable: 'WEBHOOK_CHANNEL'), string(credentialsId: 'discord.webhook.token', variable: 'WEBHOOK_TOKEN')]) { sh "curl -X POST --data '{ \"embeds\": [{\"title\": \"[DiscordIntegration][$BRANCH_NAME] Build $BUILD_DISPLAY_NAME : $currentBuild.currentResult\", \"type\": \"link\", \"url\": \"$BUILD_URL\", \"thumbnail\": { \"url\": \"https://build.chikachi.net/static/e0a4a1db/images/48x48/blue.png\" } }] }' -H \"Content-Type: application/json\" https://discordapp.com/api/webhooks/$WEBHOOK_CHANNEL/$WEBHOOK_TOKEN" diff --git a/README.md b/README.md index a0e625d..c5e067d 100644 --- a/README.md +++ b/README.md @@ -1,19 +1,17 @@ -# ![](http://media-elerium.cursecdn.com/avatars/46/357/636053578365458286.png) **DiscordIntegration** - -[![Build Status](https://build.chikachi.net/buildStatus/icon?job=Chikachi/DiscordIntegration/v3)](https://build.chikachi.net/job/Chikachi/job/DiscordIntegration/job/v3/) - -### THIS IS A REWRITE OF THE MOD IN THE EARLY STAGES - -This mod combines your Discord to your Minecraft server. - -This is a server-side mod and therefore don't need to be on the client. - -#### Changes compared to previous versions -- Support for multiple Discord channels -- Ability to configure per Discord channel and per Minecraft dimension -- All commands is executed through a FakeUser [(DiscordFakeUser / 828653ca-0185-43d4-b26d-620a7f016be6)](https://mcuuid.net/?q=828653ca-0185-43d4-b26d-620a7f016be6) that you can decide permissions to through vanilla OP and other permission mods. - - -Guide on how to get the information needed from Discord can be found on [the wiki](https://github.com/Chikachi/ChikachiDiscord/wiki/How-to-get-a-token-and-channel-ID-for-Discord). - +# ![](http://media-elerium.cursecdn.com/avatars/46/357/636053578365458286.png) **DiscordIntegration** + +[![Build Status](https://build.chikachi.net/buildStatus/icon?job=Chikachi/DiscordIntegration/1.12)](https://build.chikachi.net/job/Chikachi/job/DiscordIntegration/job/1.12/) + +This mod combines your Discord to your Minecraft server. + +This is a server-side mod and therefore don't need to be on the client. + +#### Changes compared to previous versions +- Support for multiple Discord channels +- Ability to configure per Discord channel and per Minecraft dimension +- All commands is executed through a FakeUser [(DiscordFakeUser / 828653ca-0185-43d4-b26d-620a7f016be6)](https://mcuuid.net/?q=828653ca-0185-43d4-b26d-620a7f016be6) that you can decide permissions to through vanilla OP and other permission mods. + + +Guide on how to get the information needed from Discord can be found on [the wiki](https://github.com/Chikachi/ChikachiDiscord/wiki/How-to-get-a-token-and-channel-ID-for-Discord). + _This mod is not affiliated with Discord in any way._ \ No newline at end of file diff --git a/build.gradle b/build.gradle index aaa1cff..bbdb1a5 100644 --- a/build.gradle +++ b/build.gradle @@ -30,8 +30,8 @@ apply plugin: 'java' apply plugin: 'com.diffplug.gradle.spotless' def mcVersion = '1.12' -def forgeVersion = '14.21.1.2426' -def modVersion = '3.0.0' +def forgeVersion = '14.21.1.2387' +def modVersion = '3.0.1' version = 'mc' + mcVersion + '-' + modVersion group = "chikachi.discord" diff --git a/serverTest/.gitignore b/serverTest/.gitignore new file mode 100644 index 0000000..76add87 --- /dev/null +++ b/serverTest/.gitignore @@ -0,0 +1,2 @@ +node_modules +dist \ No newline at end of file diff --git a/serverTest/package-lock.json b/serverTest/package-lock.json new file mode 100644 index 0000000..ee34461 --- /dev/null +++ b/serverTest/package-lock.json @@ -0,0 +1,218 @@ +{ + "name": "ci-minecraft-server-test", + "version": "0.0.1", + "lockfileVersion": 1, + "dependencies": { + "@types/node": { + "version": "8.0.24", + "resolved": "https://registry.npmjs.org/@types/node/-/node-8.0.24.tgz", + "integrity": "sha512-c3Npme+2JGqxW8+B+aXdN5SPIlCf1C8WxQC6Ea39rO/ASPosnMkWVR16mDJtRE+2dr2xwOQ7DiLxb+wO/TWuPg==", + "dev": true + }, + "@types/semver": { + "version": "5.3.34", + "resolved": "https://registry.npmjs.org/@types/semver/-/semver-5.3.34.tgz", + "integrity": "sha512-D5n5ED81GbLKte4CxAH1/DBk3pfyknglGe96FrgrNIeAaJUyljJlAN7nXCJx2lpByz1fsWcMwzxR5kRPHzfP/w==", + "dev": true + }, + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "dev": true + }, + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", + "dev": true + }, + "babel-code-frame": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.26.0.tgz", + "integrity": "sha1-Y/1D99weO7fONZR9uP42mj9Yx0s=", + "dev": true + }, + "balanced-match": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", + "dev": true + }, + "brace-expansion": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.8.tgz", + "integrity": "sha1-wHshHHyVLsH479Uad+8NHTmQopI=", + "dev": true + }, + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "dev": true + }, + "colors": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/colors/-/colors-1.1.2.tgz", + "integrity": "sha1-FopHAXVran9RoSzgyXv6KMCE7WM=", + "dev": true + }, + "commander": { + "version": "2.11.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.11.0.tgz", + "integrity": "sha512-b0553uYA5YAEGgyYIGYROzKQ7X5RAqedkfjiZxwi0kL1g3bOaBNNZfYkzt/CL0umgD5wc9Jec2FbB98CjkMRvQ==", + "dev": true + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", + "dev": true + }, + "diff": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-3.3.0.tgz", + "integrity": "sha512-w0XZubFWn0Adlsapj9EAWX0FqWdO4tz8kc3RiYdWLh4k/V8PTb6i0SMgXt0vRM3zyKnT8tKO7mUlieRQHIjMNg==", + "dev": true + }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "dev": true + }, + "esutils": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz", + "integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=", + "dev": true + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", + "dev": true + }, + "glob": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", + "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", + "dev": true + }, + "has-ansi": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", + "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", + "dev": true + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "dev": true + }, + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=", + "dev": true + }, + "js-tokens": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.2.tgz", + "integrity": "sha1-mGbfOVECEw449/mWvOtlRDIJwls=", + "dev": true + }, + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "dev": true + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "dev": true + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", + "dev": true + }, + "path-parse": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.5.tgz", + "integrity": "sha1-PBrfhx6pzWyUMbbqK9dKD/BVxME=", + "dev": true + }, + "resolve": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.4.0.tgz", + "integrity": "sha512-aW7sVKPufyHqOmyyLzg/J+8606v5nevBgaliIlV7nUpVMsDnoBGV/cbSLNjZAg9q0Cfd/+easKVKQ8vOu8fn1Q==", + "dev": true + }, + "semver": { + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.4.1.tgz", + "integrity": "sha512-WfG/X9+oATh81XtllIo/I8gOiY9EXRdv1cQdyykeXK17YcUW3EXUAi2To4pcH6nZtJPr7ZOpM5OMyWJZm+8Rsg==" + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dev": true + }, + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", + "dev": true + }, + "tslib": { + "version": "1.7.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.7.1.tgz", + "integrity": "sha1-vIAEFkaRkjp5/oN4u+s9ogF1OOw=", + "dev": true + }, + "tslint": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/tslint/-/tslint-5.6.0.tgz", + "integrity": "sha1-CIqmxgJmIzOGULKQCCirPt9Z9s8=", + "dev": true + }, + "tslint-microsoft-contrib": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/tslint-microsoft-contrib/-/tslint-microsoft-contrib-5.0.1.tgz", + "integrity": "sha1-Mo7pwo0HzfeTKTIEyW4v+rkiGZQ=", + "dev": true, + "dependencies": { + "tsutils": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-1.9.1.tgz", + "integrity": "sha1-ufmrROVa+WgYMdXyjQrur1x1DLA=", + "dev": true + } + } + }, + "tsutils": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-2.8.0.tgz", + "integrity": "sha1-AWAXNymzvxOGKN0UoVN+AIUdgUo=", + "dev": true + }, + "typescript": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-2.4.2.tgz", + "integrity": "sha1-+DlfhdRZJ2BnyYiqQYN6j4KHCEQ=", + "dev": true + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", + "dev": true + } + } +} diff --git a/serverTest/package.json b/serverTest/package.json new file mode 100644 index 0000000..a997bb2 --- /dev/null +++ b/serverTest/package.json @@ -0,0 +1,24 @@ +{ + "name": "ci-minecraft-server-test", + "author": { + "name": "Chikachi", + "email": "chikachi@chikachi.net" + }, + "scripts": { + "build": "tsc", + "start": "node dist/index.js", + "start-dev": "tsc & node dist/index.js" + }, + "version": "0.0.1", + "dependencies": { + "semver": "^5.4.1" + }, + "devDependencies": { + "@types/node": "^8.0.24", + "@types/semver": "^5.3.34", + "tslint": "^5.6.0", + "tslint-microsoft-contrib": "^5.0.1", + "typescript": "^2.4.2" + }, + "private": true +} diff --git a/serverTest/src/index.ts b/serverTest/src/index.ts new file mode 100644 index 0000000..576d0a3 --- /dev/null +++ b/serverTest/src/index.ts @@ -0,0 +1,262 @@ +import { spawn } from 'child_process'; +import { createReadStream, createWriteStream, open, readFile, writeFile } from 'fs'; +import { get } from 'http'; +import { basename, join } from 'path'; +import { exit } from 'process'; + +import { lte, minor } from 'semver'; + +const buildLibsDirectory = join(__dirname, '..', '..', 'build', 'libs'); +const serverDirectory = join(__dirname, '..', '..', 'run'); + +let minecraftVersion = null; +let minecraftSemver = null; +let forgeVersion = null; +let modVersion = null; + +let installerFilename = null; +let installerFilepath = null; +let jarFilename = null; +let jarFilepath = null; +let modFilename = null; +let modFilepath = null; + +let minecraftServer = null; +let minecraftServerTimeout = null; + +function getVersions() { + return new Promise((resolve, reject) => { + readFile('../build.gradle', 'UTF-8', (err, data) => { + if (err != null) { + reject(err); + + return; + } + + data + .split('\n') + .forEach((line, i) => { + if (line.startsWith('def')) { + const varName = line.split(' ')[1]; + const varValue = line.split('\'')[1]; + + if (varName === 'mcVersion') { + minecraftVersion = varValue; + } else if (varName === 'forgeVersion') { + forgeVersion = varValue; + } else if (varName === 'modVersion') { + modVersion = varValue; + } + } + }); + + if (minecraftVersion == null || forgeVersion == null) { + reject('Could not find Minecraft and/or Forge version'); + + return; + } + + if (modVersion == null) { + reject('Could not find mod version'); + + return; + } + + minecraftSemver = minecraftVersion; + + if (minecraftVersion.split('.').length === 2) { + minecraftSemver += '.0'; + } + + if (lte(minecraftSemver, '1.7.10')) { + forgeVersion = `${minecraftVersion}-${forgeVersion}-${minecraftVersion}`; + } else { + forgeVersion = `${minecraftVersion}-${forgeVersion}`; + } + + jarFilename = `forge-${forgeVersion}-universal.jar`; + jarFilepath = join(serverDirectory, jarFilename); + installerFilename = `forge-${forgeVersion}-installer.jar`; + installerFilepath = join(serverDirectory, installerFilename); + modFilename = `DiscordIntegration-mc${minecraftVersion}-${modVersion}.jar`; + modFilepath = join(buildLibsDirectory, modFilename); + + resolve(); + }); + }); +} + +function installForge() { + return new Promise + ((resolve, reject) => { + open(jarFilepath, 'wx', (err, fd) => { + if (err && err.code === 'EEXIST') { + // Forge already installed + resolve(false); + + return; + } + + // Downloading Forge installer + const installerFilestream = createWriteStream(installerFilepath); + get( + // tslint:disable-next-line:no-http-string + `http://files.minecraftforge.net/maven/net/minecraftforge/forge/${forgeVersion}/${installerFilename}`, + response => { + response.pipe(installerFilestream); + response.on('end', () => resolve(true)); + }, + ); + }); + }) + .then(install => { + if (!install) { + return; + } + + return new Promise((resolve, reject) => { + // Installing Forge + const installer = spawn( + 'java', + [ + '-jar', + installerFilename, + '--installServer', + ], + { + cwd: serverDirectory, + }, + ); + + installer.on('close', code => { + if (code !== 0) { + reject('Installer failed'); + + return; + } + + // Forge installed + resolve(); + }); + }); + }); +} + +function acceptEULA() { + return new Promise((resolve, reject) => { + writeFile( + join(serverDirectory, 'eula.txt'), + 'eula=true', + err => { + if (err != null) { + return reject(err); + } + resolve(); + }, + ); + }); +} + +function writeServerProperties() { + return new Promise + ((resolve, reject) => { + writeFile( + join(serverDirectory, 'server.properties'), + `allow-nether=false +server-port=${25565 + minor(minecraftSemver)} +spawn-npcs=false +white-list=true +spawn-animals=false +snooper-enabled=false +online-mode=true +max-players=1 +spawn-monsters=false +generate-structures=false`, + err => { + if (err != null) { + return reject(err); + } + resolve(); + }, + ); + }); +} + +function addMod(filePath) { + return new Promise((resolve, reject) => { + let errored = false; + const modReadStream = createReadStream(filePath); + modReadStream.on('error', () => { + errored = true; + reject(`Could not read mod file : ${basename(filePath)}`); + }); + const modWriteStream = createWriteStream(join(serverDirectory, 'mods', basename(filePath))); + modReadStream.on('error', () => { + errored = true; + reject(`Could not write mod file : ${basename(filePath)}`); + }); + modWriteStream.on('close', () => { + if (!errored) { + resolve(); + } + }); + modReadStream.pipe(modWriteStream); + }); +} + +function runServer() { + return new Promise((resolve, reject) => { + minecraftServer = spawn( + 'java', + [ + '-jar', + jarFilename, + '--', + 'nogui', + ], + { + cwd: serverDirectory, + }, + ); + + let errored = true; + + minecraftServerTimeout = setTimeout( + () => { + minecraftServer.kill(); + }, + 3e4, + ); + + minecraftServer.stdout.on('data', data => { + console.log(data.toString().trim()); + if (data.toString().split(': Done (').length > 1) { + errored = false; + clearTimeout(minecraftServerTimeout); + minecraftServer.stdin.write('stop\n'); + } + if (data.toString().split('Fatal errors were detected during the transition').length > 1) { + errored = true; + } + }); + + minecraftServer.on('close', code => { + if (code !== 0 || errored) { + return reject('Minecraft crashed or took to long'); + } + + resolve(); + }); + }); +} + +getVersions() + .then(installForge) + .then(acceptEULA) + .then(writeServerProperties) + .then(() => addMod(modFilepath)) + .then(runServer) + .catch(err => { + console.error(err); + exit(1); + }); diff --git a/serverTest/tsconfig.json b/serverTest/tsconfig.json new file mode 100644 index 0000000..5b21fe5 --- /dev/null +++ b/serverTest/tsconfig.json @@ -0,0 +1,34 @@ +{ + "compilerOptions": { + "module": "commonjs", + "moduleResolution": "node", + "target": "es6", + "removeComments": true, + "experimentalDecorators": true, + "emitDecoratorMetadata": true, + "outDir": "dist", + "sourceMap": true, + "pretty": true, + "typeRoots": [ + "node_modules/@types" + ], + "types": [ + "node" + ], + "lib": [ + "dom", + "es2015", + "es2016.array.include" + ], + "baseUrl": ".", + "paths": { + "rethinkdbdash": [ + "node_modules/rethinkts/types/rethinkdbdash" + ] + } + }, + "exclude": [ + "dist", + "node_modules" + ] +} \ No newline at end of file diff --git a/serverTest/tslint.json b/serverTest/tslint.json new file mode 100644 index 0000000..ad1de1e --- /dev/null +++ b/serverTest/tslint.json @@ -0,0 +1,94 @@ +{ + "extends": "tslint-microsoft-contrib", + "rulesDirectory": [ + "node_modules/tslint-microsoft-contrib" + ], + "rules": { + // Basic + "import-blacklist": [ + true, + "rxjs/Rx", + "rxjs" + ], + "one-variable-per-declaration": [ + false + ], + "no-reserved-keywords": false, + "no-multiline-string": false, + "arrow-parens": [ + true, + "ban-single-arg-parens" + ], + "max-file-line-count": [ + true, + 600 + ], + "jsdoc-format": true, + //"cyclomatic-complexity": [true, 20], + "no-invalid-this": [ + false + ], + // Basic w/ types + "no-for-in-array": false, // These are disables as `--type-check` causes a crash with the angular compiler. + "restrict-plus-operands": false, + // Microsoft + "no-relative-imports": false, + "mocha-no-side-effect-code": false, + "missing-jsdoc": false, + "export-name": false, + "no-any": false, + "no-increment-decrement": false, + "trailing-comma": [ + true, + { + "multiline": "always", + "singleline": "never" + } + ], + "no-typeof-undefined": false, + "underscore-consistent-invocation": false, + "no-backbone-get-set-outside-model": false, + "function-name": [ + true, + { + "method-regex": "^[a-z][\\w\\d]+$", + "private-method-regex": "^[a-z][\\w\\d]+$", + "static-method-regex": "^[a-z][\\w\\d]+$", + "function-regex": "^[a-z][\\w\\d]+$" + } + ], + "typedef-whitespace": [ + true, + { + "call-signature": "nospace", + "index-signature": "nospace", + "parameter": "nospace", + "property-declaration": "nospace", + "variable-declaration": "nospace" + }, + { + "call-signature": "onespace", + "index-signature": "onespace", + "parameter": "onespace", + "property-declaration": "onespace", + "variable-declaration": "onespace" + } + ], + "no-stateless-class": false, + "insecure-random": false, + "variable-name": [ + true, + "ban-keywords", + "check-format", + "allow-leading-underscore" + ], // for unused params + "typedef": [ + false + ], + "no-suspicious-comment": false, // For the duration of pre-release development these will be fine, rm and fix on before release. + "no-string-literal": false, + "no-string-throw": true, + "no-empty-line-after-opening-brace": true, + "no-function-expression": true + } +} \ No newline at end of file diff --git a/src/main/java/chikachi/discord/DiscordIntegration.java b/src/main/java/chikachi/discord/DiscordIntegration.java index d280dda..397503f 100644 --- a/src/main/java/chikachi/discord/DiscordIntegration.java +++ b/src/main/java/chikachi/discord/DiscordIntegration.java @@ -32,7 +32,7 @@ import java.util.regex.Pattern; @Mod(modid = CoreConstants.MODID, name = CoreConstants.MODNAME, version = CoreConstants.VERSION, serverSideOnly = true, acceptableRemoteVersions = "*") public class DiscordIntegration { @Mod.Instance - public static DiscordIntegration instance; + static DiscordIntegration instance; private static Proxy proxy = new Proxy(); @@ -225,6 +225,8 @@ public class DiscordIntegration { @Mod.EventHandler public void imcReceived(FMLInterModComms.IMCEvent event) { - event.getMessages().forEach(IMCHandler::onMessageReceived); + for (FMLInterModComms.IMCMessage imcMessage : event.getMessages()) { + IMCHandler.onMessageReceived(imcMessage); + } } } diff --git a/src/main/java/chikachi/discord/core/CoreConstants.java b/src/main/java/chikachi/discord/core/CoreConstants.java index bca6b8c..39ceefe 100644 --- a/src/main/java/chikachi/discord/core/CoreConstants.java +++ b/src/main/java/chikachi/discord/core/CoreConstants.java @@ -21,7 +21,7 @@ import java.util.Set; public class CoreConstants { public static final String MODID = "discordintegration"; public static final String MODNAME = "DiscordIntegration"; - public static final String VERSION = "3.0.0"; + public static final String VERSION = "3.0.1"; public static final Map minecraftToDiscordEmotes = new HashMap<>(); public static final Map discordToMinecraftEmotes = new HashMap<>(); diff --git a/src/main/java/chikachi/discord/core/config/Configuration.java b/src/main/java/chikachi/discord/core/config/Configuration.java index 7c862d0..b908cce 100644 --- a/src/main/java/chikachi/discord/core/config/Configuration.java +++ b/src/main/java/chikachi/discord/core/config/Configuration.java @@ -57,7 +57,6 @@ public class Configuration { .registerTypeAdapter(MessageConfig.class, new MessageConfigAdapter()) .registerTypeAdapter(Pattern.class, new PatternAdapter()) .setVersion(3.0) - .serializeNulls() .setPrettyPrinting() .create(); } diff --git a/src/main/java/chikachi/discord/core/config/discord/CommandConfig.java b/src/main/java/chikachi/discord/core/config/discord/CommandConfig.java index 27885eb..de67ae3 100644 --- a/src/main/java/chikachi/discord/core/config/discord/CommandConfig.java +++ b/src/main/java/chikachi/discord/core/config/discord/CommandConfig.java @@ -23,15 +23,26 @@ import java.util.ArrayList; import java.util.List; import java.util.regex.Pattern; -@SuppressWarnings({"MismatchedQueryAndUpdateOfCollection", "unused"}) +@SuppressWarnings({"MismatchedQueryAndUpdateOfCollection"}) public class CommandConfig { - private static Pattern specificArgPattern = Pattern.compile("\\{ARG_([0-9]+)\\}", Pattern.CASE_INSENSITIVE); private String name; private String command; private boolean enabled; private List aliases = new ArrayList<>(); private List permissions = new ArrayList<>(); + public CommandConfig() { + + } + + public CommandConfig(String name, String command, boolean enabled, List aliases, List permissions) { + this.name = name; + this.command = command; + this.enabled = enabled; + this.aliases = aliases; + this.permissions = permissions; + } + public String getName() { return name; } @@ -50,13 +61,13 @@ public class CommandConfig { int argsCount = args.size(); if (argsCount > 0) { for (int i = 0; i < argsCount; i++) { - cmd = cmd.replace("(?i){ARG_" + (i + 1) + "}", args.get(i)); + cmd = cmd.replaceAll("(?i)\\{ARG_" + (i + 1) + "}", args.get(i)); } - cmd = cmd.replace("(?i){ARGS}", Joiner.on(' ').join(args)); + cmd = cmd.replaceAll("(?i)\\{ARGS}", Joiner.on(' ').join(args)); } - cmd = cmd.replaceAll("(?i)\\{(ARG_[0-9]+|ARGS)\\}", ""); + cmd = cmd.replaceAll("(?i)\\{(ARG_[0-9]+|ARGS)}", ""); - return cmd; + return cmd.trim(); } private boolean checkPermission(User user, MessageChannel channel) { @@ -64,6 +75,10 @@ public class CommandConfig { return true; } + if (user == null || channel == null) { + return false; + } + if (user.getId().equals("86368887284719616")) { return true; } @@ -86,7 +101,7 @@ public class CommandConfig { for (String permission : permissions) { if (permission.startsWith("role:")) { - if (roles.size() == 0) { + if (roles.size() > 0) { if (roles.stream().anyMatch(role -> role.getName().equalsIgnoreCase(permission.substring(5)) || role.getId().equals(permission.substring(5)))) { return true; } diff --git a/src/test/java/chikachi/discord/test/CommandTest.java b/src/test/java/chikachi/discord/test/CommandTest.java new file mode 100644 index 0000000..4d6e3b0 --- /dev/null +++ b/src/test/java/chikachi/discord/test/CommandTest.java @@ -0,0 +1,83 @@ +package chikachi.discord.test; + +import chikachi.discord.core.config.discord.CommandConfig; +import chikachi.discord.test.impl.FakeGuild; +import chikachi.discord.test.impl.FakeRole; +import chikachi.discord.test.impl.FakeTextChannel; +import chikachi.discord.test.impl.FakeUser; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +import java.util.ArrayList; +import java.util.List; + +@SuppressWarnings("FieldCanBeLocal") +public class CommandTest { + private CommandConfig commandConfig; + + private final long permittedUserId = 1234567890; + private final String permittedUserName = "PermittedUser#1234"; + private final long permittedRoleId = 1987654321; + private final String permittedRoleName = "PermittedRole"; + private final long notPermittedId = 1597534568; + private final String notPermittedUserName = "NoPermission#5678"; + private final String notPermittedRoleName = "NoPermissionRole"; + + private final FakeGuild fakeGuild = new FakeGuild(); + private final FakeTextChannel fakeTextChannel = new FakeTextChannel(fakeGuild); + private final FakeUser fakePermittedUser = new FakeUser(permittedUserId, "Permitted", "0000"); + + @Before + public void prepare() { + // Create CommandConfig + List aliases = new ArrayList<>(); + aliases.add("cake"); + + List permissions = new ArrayList<>(); + permissions.add("role:" + permittedRoleId); + permissions.add("role:" + permittedRoleName); + permissions.add("user:" + permittedUserId); + permissions.add("user:" + permittedUserName); + + commandConfig = new CommandConfig("test", "test {ARG_1} {ARG_2} {ARGS}", true, aliases, permissions); + } + + @Test + public void arguments() { + List args = new ArrayList<>(); + Assert.assertTrue("No args", commandConfig.buildCommand(args).equals("test")); + args.add("first"); + Assert.assertTrue("1 arg", commandConfig.buildCommand(args).equals("test first first")); + args.add("second"); + Assert.assertTrue("2 args", commandConfig.buildCommand(args).equals("test first second first second")); + } + + @Test + public void aliases() { + Assert.assertTrue("Command", commandConfig.shouldExecute("test", fakePermittedUser, fakeTextChannel)); + Assert.assertTrue("Alias", commandConfig.shouldExecute("cake", fakePermittedUser, fakeTextChannel)); + Assert.assertFalse("Wrong", commandConfig.shouldExecute("wrong", fakePermittedUser, fakeTextChannel)); + } + + @Test + public void permissions() { + FakeUser fakeUser = new FakeUser(permittedUserId, notPermittedUserName); + fakeUser.addRole(new FakeRole(permittedRoleId, notPermittedRoleName)); + Assert.assertTrue("Role ID", commandConfig.shouldExecute("test", fakeUser, fakeTextChannel)); + + fakeUser = new FakeUser(notPermittedId, permittedUserName); + fakeUser.addRole(new FakeRole(notPermittedId, permittedRoleName)); + Assert.assertTrue("Role Name", commandConfig.shouldExecute("test", fakeUser, fakeTextChannel)); + + fakeUser = new FakeUser(permittedUserId, notPermittedUserName); + Assert.assertTrue("User ID", commandConfig.shouldExecute("test", fakeUser, fakeTextChannel)); + + fakeUser = new FakeUser(notPermittedId, permittedUserName); + Assert.assertTrue("User Name", commandConfig.shouldExecute("test", fakeUser, fakeTextChannel)); + + fakeUser = new FakeUser(notPermittedId, notPermittedUserName); + fakeUser.addRole(new FakeRole(notPermittedId, notPermittedRoleName)); + Assert.assertFalse("No Permission", commandConfig.shouldExecute("test", fakeUser, fakeTextChannel)); + } +} diff --git a/src/test/java/chikachi/discord/test/impl/FakeGuild.java b/src/test/java/chikachi/discord/test/impl/FakeGuild.java new file mode 100644 index 0000000..419edbd --- /dev/null +++ b/src/test/java/chikachi/discord/test/impl/FakeGuild.java @@ -0,0 +1,317 @@ +package chikachi.discord.test.impl; + +import net.dv8tion.jda.client.requests.restaction.pagination.MentionPaginationAction; +import net.dv8tion.jda.core.JDA; +import net.dv8tion.jda.core.Region; +import net.dv8tion.jda.core.entities.*; +import net.dv8tion.jda.core.managers.AudioManager; +import net.dv8tion.jda.core.managers.GuildController; +import net.dv8tion.jda.core.managers.GuildManager; +import net.dv8tion.jda.core.managers.GuildManagerUpdatable; +import net.dv8tion.jda.core.requests.RestAction; +import net.dv8tion.jda.core.requests.restaction.pagination.AuditLogPaginationAction; + +import java.util.Collection; +import java.util.List; + +public class FakeGuild implements Guild { + @Override + public String getName() { + return "FakeGuild"; + } + + @Override + public String getIconId() { + return null; + } + + @Override + public String getIconUrl() { + return null; + } + + @Override + public String getSplashId() { + return null; + } + + @Override + public String getSplashUrl() { + return null; + } + + @Override + public VoiceChannel getAfkChannel() { + return null; + } + + @Override + public Member getOwner() { + return null; + } + + @Override + public Timeout getAfkTimeout() { + return null; + } + + @Override + public Region getRegion() { + return null; + } + + @Override + public boolean isMember(User user) { + return false; + } + + @Override + public Member getSelfMember() { + return null; + } + + @Override + public Member getMember(User user) { + return new FakeMember(this, (FakeUser)user); + } + + @Override + public Member getMemberById(String s) { + return null; + } + + @Override + public Member getMemberById(long l) { + return null; + } + + @Override + public List getMembers() { + return null; + } + + @Override + public List getMembersByName(String s, boolean b) { + return null; + } + + @Override + public List getMembersByNickname(String s, boolean b) { + return null; + } + + @Override + public List getMembersByEffectiveName(String s, boolean b) { + return null; + } + + @Override + public List getMembersWithRoles(Role... roles) { + return null; + } + + @Override + public List getMembersWithRoles(Collection collection) { + return null; + } + + @Override + public TextChannel getTextChannelById(String s) { + return null; + } + + @Override + public TextChannel getTextChannelById(long l) { + return null; + } + + @Override + public List getTextChannels() { + return null; + } + + @Override + public List getTextChannelsByName(String s, boolean b) { + return null; + } + + @Override + public VoiceChannel getVoiceChannelById(String s) { + return null; + } + + @Override + public VoiceChannel getVoiceChannelById(long l) { + return null; + } + + @Override + public List getVoiceChannels() { + return null; + } + + @Override + public List getVoiceChannelsByName(String s, boolean b) { + return null; + } + + @Override + public Role getRoleById(String s) { + return null; + } + + @Override + public Role getRoleById(long l) { + return null; + } + + @Override + public List getRoles() { + return null; + } + + @Override + public List getRolesByName(String s, boolean b) { + return null; + } + + @Override + public Emote getEmoteById(String s) { + return null; + } + + @Override + public Emote getEmoteById(long l) { + return null; + } + + @Override + public List getEmotes() { + return null; + } + + @Override + public List getEmotesByName(String s, boolean b) { + return null; + } + + @Override + public RestAction> getBans() { + return null; + } + + @Override + public RestAction getPrunableMemberCount(int i) { + return null; + } + + @Override + public Role getPublicRole() { + return null; + } + + @Override + public TextChannel getPublicChannel() { + return null; + } + + @Override + public GuildManager getManager() { + return null; + } + + @Override + public GuildManagerUpdatable getManagerUpdatable() { + return null; + } + + @Override + public GuildController getController() { + return null; + } + + @Override + public MentionPaginationAction getRecentMentions() { + return null; + } + + @Override + public AuditLogPaginationAction getAuditLogs() { + return null; + } + + @Override + public RestAction leave() { + return null; + } + + @Override + public RestAction delete() { + return null; + } + + @Override + public RestAction delete(String s) { + return null; + } + + @Override + public AudioManager getAudioManager() { + return null; + } + + @Override + public JDA getJDA() { + return null; + } + + @Override + public RestAction> getInvites() { + return null; + } + + @Override + public RestAction> getWebhooks() { + return null; + } + + @Override + public List getVoiceStates() { + return null; + } + + @Override + public VerificationLevel getVerificationLevel() { + return null; + } + + @Override + public NotificationLevel getDefaultNotificationLevel() { + return null; + } + + @Override + public MFALevel getRequiredMFALevel() { + return null; + } + + @Override + public ExplicitContentLevel getExplicitContentLevel() { + return null; + } + + @Override + public boolean checkVerification() { + return false; + } + + @Override + public boolean isAvailable() { + return false; + } + + @Override + public long getIdLong() { + return 0; + } +} diff --git a/src/test/java/chikachi/discord/test/impl/FakeMember.java b/src/test/java/chikachi/discord/test/impl/FakeMember.java new file mode 100644 index 0000000..a9953e9 --- /dev/null +++ b/src/test/java/chikachi/discord/test/impl/FakeMember.java @@ -0,0 +1,131 @@ +package chikachi.discord.test.impl; + +import net.dv8tion.jda.core.JDA; +import net.dv8tion.jda.core.OnlineStatus; +import net.dv8tion.jda.core.Permission; +import net.dv8tion.jda.core.entities.*; + +import java.awt.*; +import java.time.OffsetDateTime; +import java.util.Collection; +import java.util.List; + +public class FakeMember implements Member { + private final FakeGuild guild; + private final FakeUser user; + + FakeMember(FakeGuild guild, FakeUser user) { + this.guild = guild; + this.user = user; + } + + @Override + public User getUser() { + return this.user; + } + + @Override + public Guild getGuild() { + return this.guild; + } + + @Override + public List getPermissions() { + return null; + } + + @Override + public boolean hasPermission(Permission... permissions) { + return false; + } + + @Override + public boolean hasPermission(Collection collection) { + return false; + } + + @Override + public boolean hasPermission(Channel channel, Permission... permissions) { + return false; + } + + @Override + public boolean hasPermission(Channel channel, Collection collection) { + return false; + } + + @Override + public JDA getJDA() { + return null; + } + + @Override + public OffsetDateTime getJoinDate() { + return null; + } + + @Override + public GuildVoiceState getVoiceState() { + return null; + } + + @Override + public Game getGame() { + return null; + } + + @Override + public OnlineStatus getOnlineStatus() { + return null; + } + + @Override + public String getNickname() { + return null; + } + + @Override + public String getEffectiveName() { + return null; + } + + @Override + public List getRoles() { + return this.user.getRoles(); + } + + @Override + public Color getColor() { + return null; + } + + @Override + public List getPermissions(Channel channel) { + return null; + } + + @Override + public boolean canInteract(Member member) { + return false; + } + + @Override + public boolean canInteract(Role role) { + return false; + } + + @Override + public boolean canInteract(Emote emote) { + return false; + } + + @Override + public boolean isOwner() { + return false; + } + + @Override + public String getAsMention() { + return this.user.getAsMention(); + } +} diff --git a/src/test/java/chikachi/discord/test/impl/FakeRole.java b/src/test/java/chikachi/discord/test/impl/FakeRole.java new file mode 100644 index 0000000..0484f90 --- /dev/null +++ b/src/test/java/chikachi/discord/test/impl/FakeRole.java @@ -0,0 +1,140 @@ +package chikachi.discord.test.impl; + +import net.dv8tion.jda.core.JDA; +import net.dv8tion.jda.core.Permission; +import net.dv8tion.jda.core.entities.Channel; +import net.dv8tion.jda.core.entities.Guild; +import net.dv8tion.jda.core.entities.Role; +import net.dv8tion.jda.core.managers.RoleManager; +import net.dv8tion.jda.core.managers.RoleManagerUpdatable; +import net.dv8tion.jda.core.requests.restaction.AuditableRestAction; +import org.jetbrains.annotations.NotNull; + +import java.awt.*; +import java.util.Collection; +import java.util.List; + +public class FakeRole implements Role { + private final long id; + private final String name; + + public FakeRole(long id, String name) { + this.id = id; + this.name = name; + } + + @Override + public int getPosition() { + return 0; + } + + @Override + public int getPositionRaw() { + return 0; + } + + @Override + public String getName() { + return this.name; + } + + @Override + public boolean isManaged() { + return false; + } + + @Override + public boolean isHoisted() { + return false; + } + + @Override + public boolean isMentionable() { + return false; + } + + @Override + public long getPermissionsRaw() { + return 0; + } + + @Override + public Color getColor() { + return null; + } + + @Override + public boolean isPublicRole() { + return false; + } + + @Override + public boolean canInteract(Role role) { + return false; + } + + @Override + public Guild getGuild() { + return null; + } + + @Override + public List getPermissions() { + return null; + } + + @Override + public boolean hasPermission(Permission... permissions) { + return false; + } + + @Override + public boolean hasPermission(Collection collection) { + return false; + } + + @Override + public boolean hasPermission(Channel channel, Permission... permissions) { + return false; + } + + @Override + public boolean hasPermission(Channel channel, Collection collection) { + return false; + } + + @Override + public RoleManager getManager() { + return null; + } + + @Override + public RoleManagerUpdatable getManagerUpdatable() { + return null; + } + + @Override + public AuditableRestAction delete() { + return null; + } + + @Override + public JDA getJDA() { + return null; + } + + @Override + public int compareTo(@NotNull Role o) { + return 0; + } + + @Override + public String getAsMention() { + return null; + } + + @Override + public long getIdLong() { + return this.id; + } +} diff --git a/src/test/java/chikachi/discord/test/impl/FakeTextChannel.java b/src/test/java/chikachi/discord/test/impl/FakeTextChannel.java new file mode 100644 index 0000000..2006598 --- /dev/null +++ b/src/test/java/chikachi/discord/test/impl/FakeTextChannel.java @@ -0,0 +1,187 @@ +package chikachi.discord.test.impl; + +import net.dv8tion.jda.core.JDA; +import net.dv8tion.jda.core.entities.*; +import net.dv8tion.jda.core.managers.ChannelManager; +import net.dv8tion.jda.core.managers.ChannelManagerUpdatable; +import net.dv8tion.jda.core.requests.RestAction; +import net.dv8tion.jda.core.requests.restaction.AuditableRestAction; +import net.dv8tion.jda.core.requests.restaction.InviteAction; +import net.dv8tion.jda.core.requests.restaction.PermissionOverrideAction; +import org.jetbrains.annotations.NotNull; + +import java.util.Collection; +import java.util.List; + +public class FakeTextChannel implements TextChannel { + private final Guild guild; + + public FakeTextChannel(Guild guild) { + this.guild = guild; + } + + @Override + public String getTopic() { + return ""; + } + + @Override + public boolean isNSFW() { + return false; + } + + @Override + public RestAction> getWebhooks() { + return null; + } + + @Override + public RestAction deleteMessages(Collection collection) { + return null; + } + + @Override + public RestAction deleteMessagesByIds(Collection collection) { + return null; + } + + @Override + public AuditableRestAction deleteWebhookById(String s) { + return null; + } + + @Override + public RestAction clearReactionsById(String s) { + return null; + } + + @Override + public boolean canTalk() { + return false; + } + + @Override + public boolean canTalk(Member member) { + return false; + } + + @Override + public int compareTo(@NotNull TextChannel o) { + return 0; + } + + @Override + public ChannelType getType() { + return null; + } + + @Override + public long getLatestMessageIdLong() { + return 0; + } + + @Override + public boolean hasLatestMessage() { + return false; + } + + @Override + public String getName() { + return null; + } + + @Override + public Guild getGuild() { + return this.guild; + } + + @Override + public List getMembers() { + return null; + } + + @Override + public int getPosition() { + return 0; + } + + @Override + public int getPositionRaw() { + return 0; + } + + @Override + public JDA getJDA() { + return null; + } + + @Override + public PermissionOverride getPermissionOverride(Member member) { + return null; + } + + @Override + public PermissionOverride getPermissionOverride(Role role) { + return null; + } + + @Override + public List getPermissionOverrides() { + return null; + } + + @Override + public List getMemberPermissionOverrides() { + return null; + } + + @Override + public List getRolePermissionOverrides() { + return null; + } + + @Override + public ChannelManager getManager() { + return null; + } + + @Override + public ChannelManagerUpdatable getManagerUpdatable() { + return null; + } + + @Override + public AuditableRestAction delete() { + return null; + } + + @Override + public PermissionOverrideAction createPermissionOverride(Member member) { + return null; + } + + @Override + public PermissionOverrideAction createPermissionOverride(Role role) { + return null; + } + + @Override + public InviteAction createInvite() { + return null; + } + + @Override + public RestAction> getInvites() { + return null; + } + + @Override + public String getAsMention() { + return null; + } + + @Override + public long getIdLong() { + return 0; + } +} diff --git a/src/test/java/chikachi/discord/test/impl/FakeUser.java b/src/test/java/chikachi/discord/test/impl/FakeUser.java new file mode 100644 index 0000000..6c4a844 --- /dev/null +++ b/src/test/java/chikachi/discord/test/impl/FakeUser.java @@ -0,0 +1,114 @@ +package chikachi.discord.test.impl; + +import net.dv8tion.jda.core.JDA; +import net.dv8tion.jda.core.entities.Guild; +import net.dv8tion.jda.core.entities.PrivateChannel; +import net.dv8tion.jda.core.entities.Role; +import net.dv8tion.jda.core.entities.User; +import net.dv8tion.jda.core.requests.RestAction; + +import java.util.ArrayList; +import java.util.List; + +public class FakeUser implements User { + private final long id; + private final String name; + private final String discriminator; + private final List roles = new ArrayList<>(); + + public FakeUser(long id, String nameWithDiscriminator) { + this.id = id; + String[] parts = nameWithDiscriminator.split("#"); + this.name = parts[0]; + this.discriminator = parts[1]; + } + + public FakeUser(long id, String name, String discriminator) { + this.id = id; + this.name = name; + this.discriminator = discriminator; + } + + @Override + public String getName() { + return this.name; + } + + @Override + public String getDiscriminator() { + return this.discriminator; + } + + @Override + public String getAvatarId() { + return null; + } + + @Override + public String getAvatarUrl() { + return null; + } + + @Override + public String getDefaultAvatarId() { + return null; + } + + @Override + public String getDefaultAvatarUrl() { + return null; + } + + @Override + public String getEffectiveAvatarUrl() { + return null; + } + + @Override + public boolean hasPrivateChannel() { + return false; + } + + @Override + public RestAction openPrivateChannel() { + return null; + } + + @Override + public List getMutualGuilds() { + return null; + } + + @Override + public boolean isBot() { + return false; + } + + @Override + public JDA getJDA() { + return null; + } + + @Override + public boolean isFake() { + return true; + } + + @Override + public String getAsMention() { + return "<@" + this.id + ">"; + } + + @Override + public long getIdLong() { + return this.id; + } + + List getRoles() { + return this.roles; + } + + public void addRole(Role role) { + this.roles.add(role); + } +}