master
Chikachi 2017-08-22 18:26:42 +02:00
parent 70a50df4bd
commit 182f99716d
No known key found for this signature in database
GPG Key ID: 0136086A0AC09F5E
21 changed files with 1688 additions and 162 deletions

2
.gitattributes vendored Normal file
View File

@ -0,0 +1,2 @@
* text=auto
*.java text eol=lf

View File

@ -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 <player>` 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
- Removed support for `&` in formatting

34
Jenkinsfile vendored
View File

@ -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"

View File

@ -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._

View File

@ -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"

2
serverTest/.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
node_modules
dist

218
serverTest/package-lock.json generated Normal file
View File

@ -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
}
}
}

24
serverTest/package.json Normal file
View File

@ -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
}

262
serverTest/src/index.ts Normal file
View File

@ -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);
});

34
serverTest/tsconfig.json Normal file
View File

@ -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"
]
}

94
serverTest/tslint.json Normal file
View File

@ -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
}
}

View File

@ -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);
}
}
}

View File

@ -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<String, String> minecraftToDiscordEmotes = new HashMap<>();
public static final Map<String, String> discordToMinecraftEmotes = new HashMap<>();

View File

@ -57,7 +57,6 @@ public class Configuration {
.registerTypeAdapter(MessageConfig.class, new MessageConfigAdapter())
.registerTypeAdapter(Pattern.class, new PatternAdapter())
.setVersion(3.0)
.serializeNulls()
.setPrettyPrinting()
.create();
}

View File

@ -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<String> aliases = new ArrayList<>();
private List<String> permissions = new ArrayList<>();
public CommandConfig() {
}
public CommandConfig(String name, String command, boolean enabled, List<String> aliases, List<String> 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;
}

View File

@ -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<String> aliases = new ArrayList<>();
aliases.add("cake");
List<String> 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<String> 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));
}
}

View File

@ -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<Member> getMembers() {
return null;
}
@Override
public List<Member> getMembersByName(String s, boolean b) {
return null;
}
@Override
public List<Member> getMembersByNickname(String s, boolean b) {
return null;
}
@Override
public List<Member> getMembersByEffectiveName(String s, boolean b) {
return null;
}
@Override
public List<Member> getMembersWithRoles(Role... roles) {
return null;
}
@Override
public List<Member> getMembersWithRoles(Collection<Role> collection) {
return null;
}
@Override
public TextChannel getTextChannelById(String s) {
return null;
}
@Override
public TextChannel getTextChannelById(long l) {
return null;
}
@Override
public List<TextChannel> getTextChannels() {
return null;
}
@Override
public List<TextChannel> 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<VoiceChannel> getVoiceChannels() {
return null;
}
@Override
public List<VoiceChannel> 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<Role> getRoles() {
return null;
}
@Override
public List<Role> 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<Emote> getEmotes() {
return null;
}
@Override
public List<Emote> getEmotesByName(String s, boolean b) {
return null;
}
@Override
public RestAction<List<User>> getBans() {
return null;
}
@Override
public RestAction<Integer> 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<Void> leave() {
return null;
}
@Override
public RestAction<Void> delete() {
return null;
}
@Override
public RestAction<Void> delete(String s) {
return null;
}
@Override
public AudioManager getAudioManager() {
return null;
}
@Override
public JDA getJDA() {
return null;
}
@Override
public RestAction<List<Invite>> getInvites() {
return null;
}
@Override
public RestAction<List<Webhook>> getWebhooks() {
return null;
}
@Override
public List<GuildVoiceState> 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;
}
}

View File

@ -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<Permission> getPermissions() {
return null;
}
@Override
public boolean hasPermission(Permission... permissions) {
return false;
}
@Override
public boolean hasPermission(Collection<Permission> collection) {
return false;
}
@Override
public boolean hasPermission(Channel channel, Permission... permissions) {
return false;
}
@Override
public boolean hasPermission(Channel channel, Collection<Permission> 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<Role> getRoles() {
return this.user.getRoles();
}
@Override
public Color getColor() {
return null;
}
@Override
public List<Permission> 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();
}
}

View File

@ -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<Permission> getPermissions() {
return null;
}
@Override
public boolean hasPermission(Permission... permissions) {
return false;
}
@Override
public boolean hasPermission(Collection<Permission> collection) {
return false;
}
@Override
public boolean hasPermission(Channel channel, Permission... permissions) {
return false;
}
@Override
public boolean hasPermission(Channel channel, Collection<Permission> collection) {
return false;
}
@Override
public RoleManager getManager() {
return null;
}
@Override
public RoleManagerUpdatable getManagerUpdatable() {
return null;
}
@Override
public AuditableRestAction<Void> 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;
}
}

View File

@ -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<List<Webhook>> getWebhooks() {
return null;
}
@Override
public RestAction<Void> deleteMessages(Collection<Message> collection) {
return null;
}
@Override
public RestAction<Void> deleteMessagesByIds(Collection<String> collection) {
return null;
}
@Override
public AuditableRestAction<Void> deleteWebhookById(String s) {
return null;
}
@Override
public RestAction<Void> 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<Member> 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<PermissionOverride> getPermissionOverrides() {
return null;
}
@Override
public List<PermissionOverride> getMemberPermissionOverrides() {
return null;
}
@Override
public List<PermissionOverride> getRolePermissionOverrides() {
return null;
}
@Override
public ChannelManager getManager() {
return null;
}
@Override
public ChannelManagerUpdatable getManagerUpdatable() {
return null;
}
@Override
public AuditableRestAction<Void> 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<List<Invite>> getInvites() {
return null;
}
@Override
public String getAsMention() {
return null;
}
@Override
public long getIdLong() {
return 0;
}
}

View File

@ -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<Role> 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<PrivateChannel> openPrivateChannel() {
return null;
}
@Override
public List<Guild> 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<Role> getRoles() {
return this.roles;
}
public void addRole(Role role) {
this.roles.add(role);
}
}