From b476466d533d3fb1e78046f5f1a6bf5ee59a6168 Mon Sep 17 00:00:00 2001 From: hippoz Date: Mon, 7 Dec 2020 23:25:59 +0200 Subject: [PATCH] fix message clumping and also add discord<->brainlet bridge bot --- .gitignore | 2 + app/resources/js/app.js | 13 ++-- config.js | 4 +- libbrainlet/bridgebot.js | 74 +++++++++++++++++++ libbrainlet/bridgebotsecret.js.template | 11 +++ libbrainlet/package-lock.json | 96 +++++++++++++++++++++++++ libbrainlet/package.json | 1 + libbrainlet/test.js | 73 +++++++++++++++---- 8 files changed, 252 insertions(+), 22 deletions(-) create mode 100644 libbrainlet/bridgebot.js create mode 100644 libbrainlet/bridgebotsecret.js.template diff --git a/.gitignore b/.gitignore index 9749b39..939e6af 100755 --- a/.gitignore +++ b/.gitignore @@ -3,3 +3,5 @@ node_modules/ node_modules/* secret.js + +bridgebotsecret.js \ No newline at end of file diff --git a/app/resources/js/app.js b/app/resources/js/app.js index 2387a64..af68af1 100755 --- a/app/resources/js/app.js +++ b/app/resources/js/app.js @@ -265,13 +265,16 @@ const app = new Vue({ if (!lastMessage) return; if (lastMessage.author._id === messageObject.author._id) { - if (lastMessage.nickAuthor && messageObject.nickAuthor && lastMessage.nickAuthor.username === messageObject.nickAuthor.username) { - return true; - } else { - return false; - } + if (lastMessage.nickAuthor && messageObject.nickAuthor) { + if (lastMessage.nickAuthor.username === messageObject.nickAuthor.username) { + return true; + } else { + return false; + } + } } if (lastMessage.author._id === messageObject.author._id) return true; + return false; }, processMessage: async function(messageObject) { if (!this.messages[messageObject.category._id]) this.$set(this.messages, messageObject.category._id, []); diff --git a/config.js b/config.js index 13bb3eb..25d55ea 100755 --- a/config.js +++ b/config.js @@ -1,8 +1,8 @@ module.exports = { ports: { - mainServerPort: 3005, + mainServerPort: 3000, }, - address: 'b.hippoz.xyz', + address: 'localhost', mongoUrl: 'mongodb://192.168.0.105:27017/app', bcryptRounds: 10, roleMap: { diff --git a/libbrainlet/bridgebot.js b/libbrainlet/bridgebot.js new file mode 100644 index 0000000..bf77764 --- /dev/null +++ b/libbrainlet/bridgebot.js @@ -0,0 +1,74 @@ +const Client = require('./index'); +const secret = require('./bridgebotsecret'); + +const fetch = require('node-fetch'); +const Discord = require('discord.js'); + +const LISTEN_ON = '5fce94aa37c98b23bcd140a0'; +const DISCORD_LISTEN_ON = '785494888766373909'; + +const PREFIX = '::'; +const ADMIN_ID = '5fc828ea4e96e00725c17fd7'; + +let discordWebhook; + +const main = async () => { + const client = new Client('http://localhost:3000', { + throwErrors: true + }); + const discord = new Discord.Client(); + + const res = await fetch(`${client.url}/api/v1/users/token/create`, { + method: 'POST', + headers: { + 'Accept': 'application/json', + 'Content-Type': 'application/json' + }, + body: JSON.stringify({ + username: secret.brainlet.user.username, + password: secret.brainlet.user.password + }) + }); + + const json = await res.json(); + + if (!res.ok || json.error) throw new Error('Failed to generate token from API endpoint'); + + await client.setToken(json.token); + await client.gatewayConnect(); + + client.gateway.on('connect', () => { + discord.on('ready', async () => { + const channel = discord.channels.cache.get(DISCORD_LISTEN_ON); + const webhooks = await channel.fetchWebhooks(); + discordWebhook = webhooks.first(); + + if (!discordWebhook) throw new Error('No webhook in selected channel'); + + console.log(`[*] [DISCORD] Logged in as ${discord.user.tag}!`); + }); + + discord.login(secret.discord.token); + + const category = client.gateway.subscribeToCategoryChat(LISTEN_ON); + + discord.on('message', (e) => { + if (e.webhookID) return; + if (e.author.bot) return; + + client.gateway.sendMessage(LISTEN_ON, e.content, { + nickAuthor: { username: e.author.username } + }); + }); + + client.gateway.on('message', async (e) => { + if (e.author._id === client.user._id) return; + + await discordWebhook.send(e.content, { + username: e.author.username + }); + }); + }); +}; + +main(); \ No newline at end of file diff --git a/libbrainlet/bridgebotsecret.js.template b/libbrainlet/bridgebotsecret.js.template new file mode 100644 index 0000000..6a38eb4 --- /dev/null +++ b/libbrainlet/bridgebotsecret.js.template @@ -0,0 +1,11 @@ +module.exports = { + discord: { + token: 'Nzg1NDk0MjgxOTI2MjEzNjYz.X84qjg.3gAdgnp_VmTSLvgwYmCBceLGHcA' + }, + brainlet: { + user: { + username: 'e', + password: 'e' + } + } +} \ No newline at end of file diff --git a/libbrainlet/package-lock.json b/libbrainlet/package-lock.json index 51c5ef8..6326649 100644 --- a/libbrainlet/package-lock.json +++ b/libbrainlet/package-lock.json @@ -4,11 +4,39 @@ "lockfileVersion": 1, "requires": true, "dependencies": { + "@discordjs/collection": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/@discordjs/collection/-/collection-0.1.6.tgz", + "integrity": "sha512-utRNxnd9kSS2qhyivo9lMlt5qgAUasH2gb7BEOn6p0efFh24gjGomHzWKMAPn2hEReOPQZCJaRKoURwRotKucQ==" + }, + "@discordjs/form-data": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@discordjs/form-data/-/form-data-3.0.1.tgz", + "integrity": "sha512-ZfFsbgEXW71Rw/6EtBdrP5VxBJy4dthyC0tpQKGKmYFImlmmrykO14Za+BiIVduwjte0jXEBlhSKf0MWbFp9Eg==", + "requires": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + } + }, "@types/component-emitter": { "version": "1.2.10", "resolved": "https://registry.npmjs.org/@types/component-emitter/-/component-emitter-1.2.10.tgz", "integrity": "sha512-bsjleuRKWmGqajMerkzox19aGbscQX5rmmvvXl3wlIp5gMG1HgkiwPxsN5p070fBDKTNSPgojVbuY1+HWMbFhg==" }, + "abort-controller": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz", + "integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==", + "requires": { + "event-target-shim": "^5.0.0" + } + }, + "asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=" + }, "backo2": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/backo2/-/backo2-1.0.2.tgz", @@ -19,6 +47,14 @@ "resolved": "https://registry.npmjs.org/base64-arraybuffer/-/base64-arraybuffer-0.1.4.tgz", "integrity": "sha1-mBjHngWbE1X5fgQooBfIOOkLqBI=" }, + "combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "requires": { + "delayed-stream": "~1.0.0" + } + }, "component-bind": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/component-bind/-/component-bind-1.0.0.tgz", @@ -37,6 +73,33 @@ "ms": "^2.1.1" } }, + "delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=" + }, + "discord.js": { + "version": "12.5.1", + "resolved": "https://registry.npmjs.org/discord.js/-/discord.js-12.5.1.tgz", + "integrity": "sha512-VwZkVaUAIOB9mKdca0I5MefPMTQJTNg0qdgi1huF3iwsFwJ0L5s/Y69AQe+iPmjuV6j9rtKoG0Ta0n9vgEIL6w==", + "requires": { + "@discordjs/collection": "^0.1.6", + "@discordjs/form-data": "^3.0.1", + "abort-controller": "^3.0.0", + "node-fetch": "^2.6.1", + "prism-media": "^1.2.2", + "setimmediate": "^1.0.5", + "tweetnacl": "^1.0.3", + "ws": "^7.3.1" + }, + "dependencies": { + "ws": { + "version": "7.4.1", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.4.1.tgz", + "integrity": "sha512-pTsP8UAfhy3sk1lSk/O/s4tjD0CRwvMnzvwr4OKGX7ZvqZtUyx4KIJB5JWbkykPoc55tixMGgTNoh3k4FkNGFQ==" + } + } + }, "engine.io-client": { "version": "4.0.4", "resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-4.0.4.tgz", @@ -59,11 +122,29 @@ "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-4.0.1.tgz", "integrity": "sha512-v5aZK1hlckcJDGmHz3W8xvI3NUHYc9t8QtTbqdR5OaH3S9iJZilPubauOm+vLWOMMWzpE3hiq92l9lTAHamRCg==" }, + "event-target-shim": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz", + "integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==" + }, "has-cors": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/has-cors/-/has-cors-1.1.0.tgz", "integrity": "sha1-XkdHk/fqmEPRu5nCPu9J/xJv/zk=" }, + "mime-db": { + "version": "1.44.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.44.0.tgz", + "integrity": "sha512-/NOTfLrsPBVeH7YtFPgsVWveuL+4SjjYxaQ1xtM1KMFj7HdxlBlxeyNLzhyJVx7r4rZGJAZ/6lkKCitSc/Nmpg==" + }, + "mime-types": { + "version": "2.1.27", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.27.tgz", + "integrity": "sha512-JIhqnCasI9yD+SsmkquHBxTSEuZdQX5BuQnS2Vc7puQQQ+8yiP5AY5uWhpdv4YL4VM5c6iliiYWPgJ/nJQLp7w==", + "requires": { + "mime-db": "1.44.0" + } + }, "ms": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", @@ -84,6 +165,16 @@ "resolved": "https://registry.npmjs.org/parseuri/-/parseuri-0.0.6.tgz", "integrity": "sha512-AUjen8sAkGgao7UyCX6Ahv0gIK2fABKmYjvP4xmy5JaKvcbTRueIqIPHLAfq30xJddqSE033IOMUSOMCcK3Sow==" }, + "prism-media": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/prism-media/-/prism-media-1.2.3.tgz", + "integrity": "sha512-fSrR66n0l6roW9Rx4rSLMyTPTjRTiXy5RVqDOurACQ6si1rKHHKDU5gwBJoCsIV0R3o9gi+K50akl/qyw1C74A==" + }, + "setimmediate": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", + "integrity": "sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU=" + }, "socket.io-client": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-3.0.3.tgz", @@ -109,6 +200,11 @@ "debug": "~4.1.0" } }, + "tweetnacl": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-1.0.3.tgz", + "integrity": "sha512-6rt+RN7aOi1nGMyC4Xa5DdYiukl2UWCbcJft7YhxReBGQD7OAM8Pbxw6YMo4r2diNEA8FEmu32YOn9rhaiE5yw==" + }, "ws": { "version": "7.2.5", "resolved": "https://registry.npmjs.org/ws/-/ws-7.2.5.tgz", diff --git a/libbrainlet/package.json b/libbrainlet/package.json index 48e55e1..74577cc 100644 --- a/libbrainlet/package.json +++ b/libbrainlet/package.json @@ -10,6 +10,7 @@ "author": "", "license": "ISC", "dependencies": { + "discord.js": "^12.5.1", "node-fetch": "^2.6.1", "socket.io-client": "^3.0.3" } diff --git a/libbrainlet/test.js b/libbrainlet/test.js index 97ec50f..8ad19e5 100644 --- a/libbrainlet/test.js +++ b/libbrainlet/test.js @@ -1,13 +1,36 @@ const Client = require('./index'); +const fetch = require('node-fetch'); + const LISTEN_ON = '5fcbf598b39160080e797ad6'; -const TOKEN = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6IlNTQm90IiwiaWF0IjoxNjA3MjAyMjUxLCJleHAiOjE2MDcyMTMwNTF9.V9dL3cTe37M5-QDftK4XQwLMnPKoUcaGqL_YVstGTYo'; const PREFIX = '::'; const ADMIN_ID = '5fc828ea4e96e00725c17fd7'; const joined = []; const selected = []; +// https://stackoverflow.com/questions/17619741/randomly-generating-unique-number-in-pairs-multiple-times + +const randomPairs = (players) => { + const pairs = []; + while(players.length) { + pairs.push([ + pluckRandomElement(players), + pluckRandomElement(players) + ]); + } + return pairs; +}; + +const pluckRandomElement = (array) => { + const i = randomInt(array.length); + return array.splice(i, 1)[0]; +}; + +const randomInt = (limit) => { + return Math.floor(Math.random() * limit); +}; + const getRandomUser = (self, count=0) => { if (count > 3) return joined[0]; count++; @@ -16,9 +39,9 @@ const getRandomUser = (self, count=0) => { let chosen = joined[Math.floor(Math.random() * joined.length)]; final = chosen; - if (chosen._id === self._id) final = getRandomUser(self, count); - if ((selected.indexOf(chosen)) !== 1) final = getRandomUser(self, count); - if (!final) final = getRandomUser(self, count); + if (chosen._id === self._id) return final = getRandomUser(self, count); + if ((selected.indexOf(chosen)) !== 1) return final = getRandomUser(self, count); + if (!final) return final = getRandomUser(self, count); @@ -29,7 +52,24 @@ const main = async () => { const client = new Client('https://b.hippoz.xyz', { throwErrors: true }); - await client.setToken(TOKEN); + + const res = await fetch(`${client.url}/api/v1/users/token/create`, { + method: 'POST', + headers: { + 'Accept': 'application/json', + 'Content-Type': 'application/json' + }, + body: JSON.stringify({ + username: 'D', + password: 'D' + }) + }); + + const json = await res.json(); + + if (!res.ok || json.error) throw new Error('Failed to generate token from API endpoint'); + + await client.setToken(json.token); await client.gatewayConnect(); client.gateway.on('connect', () => { @@ -79,16 +119,19 @@ const main = async () => { nickAuthor: { username: 'Woo' } }); - joined.forEach((e) => { - const chosen = getRandomUser(e); - - selected.push(chosen); - - client.gateway.sendMessage(category, `${e.username} - ${chosen.username}`, { - nickAuthor: { username: 'Your result' }, - destUser: { _id: e._id } - }); - }); + const pairs = randomPairs(joined); + + for (const pair of pairs) { + const p1 = pair[0]; + const p2 = pair[1]; + if (!p1 || !p2) continue; + for (const player of pair) { + client.gateway.sendMessage(category, `${p1.username} with ${p2.username}`, { + nickAuthor: { username: 'Your result' }, + destUser: { _id: player._id } + }); + } + } break; } }