diff --git a/web/.eslintrc b/web/.eslintrc
index daa1eb7..ce442a1 100644
--- a/web/.eslintrc
+++ b/web/.eslintrc
@@ -1,6 +1,6 @@
{
"root": true,
- "extends": ["@nuxt/eslint-config"],
+ "extends": ["@nuxt/eslint-config", "plugin:tailwindcss/recommended"],
"rules": {
"vue/max-attributes-per-line": ["error", {
"singleline": {
diff --git a/web/components/team/None.vue b/web/components/team/None.vue
index d9a889e..a7461a3 100644
--- a/web/components/team/None.vue
+++ b/web/components/team/None.vue
@@ -3,8 +3,17 @@
Je zit momenteel niet in een team. Maak een team aan of wacht tot dat je geinvite wordt
You don't have any team invites
@@ -12,6 +21,7 @@
Naam / Prefix
+ Create Team
diff --git a/web/nuxt.config.ts b/web/nuxt.config.ts
index 25a6154..607187c 100644
--- a/web/nuxt.config.ts
+++ b/web/nuxt.config.ts
@@ -13,11 +13,14 @@ export default defineNuxtConfig({
runtimeConfig: {
discordId: '',
discordSecret: '',
+ discordHost: '',
jwtSecret: '',
dbUrl: '',
mineckerHost: '',
mineckerApiKey: '',
- mincecraftContainer: 'mc-school',
+ rconPassword: '',
+ rconPort: '25575',
+ rconHost: 'localhost',
public: {
redirectUrl: 'https://discord.com/api/oauth2/authorize?client_id=1052974736432443432&redirect_uri=http%3A%2F%2Flocalhost%3A3000%2Fapi%2Fauth&response_type=code&scope=identify',
}
diff --git a/web/package-lock.json b/web/package-lock.json
index c2ddc40..d4a201e 100644
--- a/web/package-lock.json
+++ b/web/package-lock.json
@@ -11,6 +11,7 @@
"@xeovalyte/nuxt-xvtoast": "^1.1.3",
"@xeovalyte/nuxt-xvui": "git+https://gitea.xeovalyte.dev/xeovalyte/nuxt-xvui.git",
"jsonwebtoken": "^9.0.0",
+ "minecraft-server-util": "^5.4.2",
"mongodb": "^5.3.0",
"socket.io-client": "^4.6.1",
"surrealdb.js": "^0.6.0"
@@ -24,6 +25,7 @@
"@vueuse/core": "^10.1.0",
"@vueuse/nuxt": "^10.1.0",
"eslint": "^8.39.0",
+ "eslint-plugin-tailwindcss": "^3.11.0",
"nuxt": "^3.4.2",
"nuxt-icon": "^0.3.3"
}
@@ -5357,6 +5359,22 @@
"url": "https://opencollective.com/eslint"
}
},
+ "node_modules/eslint-plugin-tailwindcss": {
+ "version": "3.11.0",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-tailwindcss/-/eslint-plugin-tailwindcss-3.11.0.tgz",
+ "integrity": "sha512-RaraOG4D6VXutKnoNvFQ4+frTWGJDKtezy1yCrGFS7Um1to/npDNdh2GL19IRoGB/eanbtwhxFXy+xyEw0grAg==",
+ "dev": true,
+ "dependencies": {
+ "fast-glob": "^3.2.5",
+ "postcss": "^8.4.4"
+ },
+ "engines": {
+ "node": ">=12.13.0"
+ },
+ "peerDependencies": {
+ "tailwindcss": "^3.2.2"
+ }
+ },
"node_modules/eslint-plugin-vue": {
"version": "9.11.0",
"resolved": "https://registry.npmjs.org/eslint-plugin-vue/-/eslint-plugin-vue-9.11.0.tgz",
@@ -8092,6 +8110,22 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
+ "node_modules/minecraft-motd-util": {
+ "version": "1.1.12",
+ "resolved": "https://registry.npmjs.org/minecraft-motd-util/-/minecraft-motd-util-1.1.12.tgz",
+ "integrity": "sha512-5TuTRjrRupSTruea0nRC37r0FdhkS1O4wIJKAYfwJRCQd/X4Zyl/dVIs96h9UVW6N8jhIuz9pNkrDsqyN7VBdA=="
+ },
+ "node_modules/minecraft-server-util": {
+ "version": "5.4.2",
+ "resolved": "https://registry.npmjs.org/minecraft-server-util/-/minecraft-server-util-5.4.2.tgz",
+ "integrity": "sha512-QjCM23pnXya+Fi2i3VxpQ5RS6luBA6Tkr0GAIG9dVhOrG5fBw10MVQyd13fJ4RquY3jQwNiHGX05G/0lnrQD5A==",
+ "dependencies": {
+ "minecraft-motd-util": "^1.1.9"
+ },
+ "engines": {
+ "node": ">=10.0.0"
+ }
+ },
"node_modules/minimatch": {
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
@@ -17427,6 +17461,16 @@
}
}
},
+ "eslint-plugin-tailwindcss": {
+ "version": "3.11.0",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-tailwindcss/-/eslint-plugin-tailwindcss-3.11.0.tgz",
+ "integrity": "sha512-RaraOG4D6VXutKnoNvFQ4+frTWGJDKtezy1yCrGFS7Um1to/npDNdh2GL19IRoGB/eanbtwhxFXy+xyEw0grAg==",
+ "dev": true,
+ "requires": {
+ "fast-glob": "^3.2.5",
+ "postcss": "^8.4.4"
+ }
+ },
"eslint-plugin-vue": {
"version": "9.11.0",
"resolved": "https://registry.npmjs.org/eslint-plugin-vue/-/eslint-plugin-vue-9.11.0.tgz",
@@ -19460,6 +19504,19 @@
"integrity": "sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==",
"dev": true
},
+ "minecraft-motd-util": {
+ "version": "1.1.12",
+ "resolved": "https://registry.npmjs.org/minecraft-motd-util/-/minecraft-motd-util-1.1.12.tgz",
+ "integrity": "sha512-5TuTRjrRupSTruea0nRC37r0FdhkS1O4wIJKAYfwJRCQd/X4Zyl/dVIs96h9UVW6N8jhIuz9pNkrDsqyN7VBdA=="
+ },
+ "minecraft-server-util": {
+ "version": "5.4.2",
+ "resolved": "https://registry.npmjs.org/minecraft-server-util/-/minecraft-server-util-5.4.2.tgz",
+ "integrity": "sha512-QjCM23pnXya+Fi2i3VxpQ5RS6luBA6Tkr0GAIG9dVhOrG5fBw10MVQyd13fJ4RquY3jQwNiHGX05G/0lnrQD5A==",
+ "requires": {
+ "minecraft-motd-util": "^1.1.9"
+ }
+ },
"minimatch": {
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
diff --git a/web/package.json b/web/package.json
index 01cce0d..d380ca7 100644
--- a/web/package.json
+++ b/web/package.json
@@ -18,6 +18,7 @@
"@vueuse/core": "^10.1.0",
"@vueuse/nuxt": "^10.1.0",
"eslint": "^8.39.0",
+ "eslint-plugin-tailwindcss": "^3.11.0",
"nuxt": "^3.4.2",
"nuxt-icon": "^0.3.3"
},
@@ -26,6 +27,7 @@
"@xeovalyte/nuxt-xvtoast": "^1.1.3",
"@xeovalyte/nuxt-xvui": "git+https://gitea.xeovalyte.dev/xeovalyte/nuxt-xvui.git",
"jsonwebtoken": "^9.0.0",
+ "minecraft-server-util": "^5.4.2",
"mongodb": "^5.3.0",
"socket.io-client": "^4.6.1",
"surrealdb.js": "^0.6.0"
diff --git a/web/server/api/minecraft/message/chattodiscord.js b/web/server/api/minecraft/message/chattodiscord.js
new file mode 100644
index 0000000..b817ae6
--- /dev/null
+++ b/web/server/api/minecraft/message/chattodiscord.js
@@ -0,0 +1,20 @@
+export default defineEventHandler(async (event) => {
+ const { content, uuid } = await readBody(event);
+
+ const config = useRuntimeConfig();
+
+ const coll = db.collection('users')
+ const doc = await coll.findOne({ 'minecraft.uuid': uuid })
+
+ await $fetch(config.discordHost + '/minecraft/sendchatmessage', {
+ method: 'POST',
+ body: {
+ username: doc.discord.username + ' | ' + doc.minecraft.username,
+ // avatarURL: 'https://cdn.discordapp.com/avatars/' + doc.discord.id + '/' + doc.discord.avatarHash + '.png',
+ avatarURL: 'https://api.mineatar.io/face/' + doc.minecraft.uuid + '?scale=16',
+ content: content,
+ }
+ })
+
+ return { code: 'success' }
+});
diff --git a/web/server/api/minecraft/message/chattominecraft.js b/web/server/api/minecraft/message/chattominecraft.js
new file mode 100644
index 0000000..6a24da2
--- /dev/null
+++ b/web/server/api/minecraft/message/chattominecraft.js
@@ -0,0 +1,10 @@
+export default defineEventHandler(async (event) => {
+ const { discordId, content } = await readBody(event);
+
+ const coll = db.collection('users');
+ const doc = await coll.findOne({ 'discord.id': discordId });
+
+ await sendRconCommand(`tellraw @a {"text":"(DC) ${doc.discord.username} > ${content}"}`)
+
+ return { whoo: 'hi' }
+});
diff --git a/web/server/api/minecraft/message/gametodiscord.js b/web/server/api/minecraft/message/gametodiscord.js
new file mode 100644
index 0000000..2e1ed15
--- /dev/null
+++ b/web/server/api/minecraft/message/gametodiscord.js
@@ -0,0 +1,18 @@
+export default defineEventHandler(async (event) => {
+ const { content, uuid } = await readBody(event);
+
+ const config = useRuntimeConfig();
+
+ const coll = db.collection('users')
+ const doc = await coll.findOne({ 'minecraft.uuid': uuid })
+
+ await $fetch(config.discordHost + '/minecraft/sendgamemessage', {
+ method: 'POST',
+ body: {
+ avatarURL: 'https://api.mineatar.io/face/' + doc.minecraft.uuid + '?scale=16',
+ content: content,
+ }
+ })
+
+ return { code: 'success' }
+});
diff --git a/web/server/utils/rcon.js b/web/server/utils/rcon.js
new file mode 100644
index 0000000..c5fffc6
--- /dev/null
+++ b/web/server/utils/rcon.js
@@ -0,0 +1,41 @@
+import { RCON } from 'minecraft-server-util';
+
+const client = new RCON()
+
+const config = useRuntimeConfig()
+
+let connected = false;
+
+export const sendRconCommand = async (command) => {
+ await connectRcon()
+
+ const message = await client.execute(command);
+
+ closeClient()
+
+ return message;
+}
+
+const connectRcon = async () => {
+ if (connected) return;
+
+ await client.connect(config.rconHost);
+ await client.login(config.rconPassword);
+
+ connected = true;
+}
+
+const debounce = (callback, wait) => {
+ let timeout = null;
+ return (...args) => {
+ clearTimeout(timeout);
+ timeout = setTimeout(() => {
+ callback.apply(null, args);
+ }, wait);
+ };
+}
+
+const closeClient = debounce(() => {
+ client.close();
+ connected = false;
+}, 5000)