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

- Team Invites - Create Team + + Team Invites + + + Create Team +
You don't have any team invites @@ -12,6 +21,7 @@
Naam / Prefix +
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)