From b01103ad3e854659680322f0daed056ef0593a10 Mon Sep 17 00:00:00 2001 From: Jan Date: Tue, 2 Mar 2021 00:10:35 +0100 Subject: [PATCH] Init commit --- .gitignore | 3 + README.md | 12 ++ commands/donate.js | 25 +++ commands/help.js | 25 +++ commands/test.js | 20 ++ commands/whois.js | 30 +++ index.js | 69 +++++++ package-lock.json | 432 +++++++++++++++++++++++++++++++++++++++++ package.json | 16 ++ util/command_loader.js | 22 +++ util/friendships.js | 45 +++++ 11 files changed, 699 insertions(+) create mode 100644 .gitignore create mode 100644 README.md create mode 100644 commands/donate.js create mode 100644 commands/help.js create mode 100644 commands/test.js create mode 100644 commands/whois.js create mode 100644 index.js create mode 100644 package-lock.json create mode 100644 package.json create mode 100644 util/command_loader.js create mode 100644 util/friendships.js diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..9fab2e3 --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +node_modules +.env +.idea/ \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..ecab30c --- /dev/null +++ b/README.md @@ -0,0 +1,12 @@ +# Generic Revolt Bot +This is a generic bot for [Revolt](https://revolt.chat). +It currently does not offer any features apart from begging for donations. + +## Environment variables + NODE_ENV=production # Ensures the bot is running in production mode + PREFIX=/ # The bot's prefix + + # Get session info from Chrome debug console -> Application -> IndexedDB -> localforage -> state -> auth.accounts[user ID].session + SESSION_ID= + SESSION_TOKEN= + USER_ID= \ No newline at end of file diff --git a/commands/donate.js b/commands/donate.js new file mode 100644 index 0000000..1327f5b --- /dev/null +++ b/commands/donate.js @@ -0,0 +1,25 @@ +const Revolt = require('revolt.js'); +const { client, logger, config } = require('..'); + +module.exports.meta = { + name: 'donate', + aliases: [], + description: 'hm yes give me your money hm yes' +} + +/** + * + * @param { Revolt.Message } message + * @param { string[] } args + */ +module.exports.run = async (message, args) => new Promise(async (resolve, reject) => { + await client.channels.sendMessage(message.channel, { + content: + `Monero: **\`monero:87eQbhUqmtF3mZxXvNG6h5d8zognD1NMoFCUZndXyfzABh8UsKv5ikC4H5EMgDrYA7hK2SH1Sugw9PyGGg3fzjB4Sh5KBFJ\`**\n` + + `ETH/ETC: **\`0x72f9218ED66feC7F8deFea89B5998bE5A90Da489\`**\n` + + `Other ways of supporting me: **\`fuck off, either give me money or go piss yourself\`**\n\u200b\n* * *\n\u200b\n` + + `In return for sending any amount of money to one of these addresses, you receive literally nothing.`, + nonce: Date.now().toString() + } + ); +}); \ No newline at end of file diff --git a/commands/help.js b/commands/help.js new file mode 100644 index 0000000..fdb1321 --- /dev/null +++ b/commands/help.js @@ -0,0 +1,25 @@ +const Revolt = require('revolt.js'); +const { client, logger, config } = require('..'); + +module.exports.meta = { + name: 'help', + aliases: [], + description: 'List all commands.' +} + +/** + * + * @param { Revolt.Message } message + * @param { string[] } args + */ +module.exports.run = async (message, args) => new Promise(async (resolve, reject) => { + let msgContent = `My current prefix is \`${config.prefix}\`. To add me to a group, hit me up with a friend request first.\n\u200b\n* * *\n\u200b\n` + + `| Name | Aliases | Description |\n` + + `| ---- | ------- | ----------- |\n`; + require('../util/command_loader').commands + .forEach(command => { + msgContent += `| ${config.prefix}${command.meta.name} | ${command.meta.aliases?.join(', ') || 'None'} | ${command.meta.description || 'None'}\n`; + }); + + client.channels.sendMessage(message.channel, msgContent); +}); \ No newline at end of file diff --git a/commands/test.js b/commands/test.js new file mode 100644 index 0000000..882de7d --- /dev/null +++ b/commands/test.js @@ -0,0 +1,20 @@ +const Revolt = require('revolt.js'); +const { client, logger, config } = require('..'); + +module.exports.meta = { + name: 'test', + aliases: [ 'alias_test' ], + description: 'Test command.' +} + +/** + * + * @param { Revolt.Message } message + * @param { string[] } args + */ +module.exports.run = async (message, args) => new Promise(async (resolve, reject) => { + await client.channels.sendMessage(message.channel, { + content: `Test confirmed, consider donating with ${config.prefix}donate`, + nonce: Date.now().toString() + }); +}); \ No newline at end of file diff --git a/commands/whois.js b/commands/whois.js new file mode 100644 index 0000000..3981f2d --- /dev/null +++ b/commands/whois.js @@ -0,0 +1,30 @@ +const Revolt = require('revolt.js'); +const { client, logger, config } = require('..'); + +module.exports.meta = { + name: 'whois', + aliases: [ 'userinfo', 'who' ], + description: 'Shows user info in JSON.' +} + +/** + * + * @param { Revolt.Message } message + * @param { string[] } args + */ +module.exports.run = async (message, args) => new Promise(async (resolve, reject) => { + let uid = args[0]; + if (!uid) + return client.channels.sendMessage(message.channel, 'Please <@mention> the target user or type their ID.'); + + + if (uid.startsWith('<@') && uid.endsWith('>')) uid = uid.substr(2, uid.length - 3); + + const target = await client.users.fetch(uid) + .catch(e => { return reject(e) }); + + let msgContent = + `${JSON.stringify(target)}` + + await client.channels.sendMessage(message.channel, msgContent); +}); \ No newline at end of file diff --git a/index.js b/index.js new file mode 100644 index 0000000..b621423 --- /dev/null +++ b/index.js @@ -0,0 +1,69 @@ +require('dotenv').config(); +const Revolt = require('revolt.js'); +const { default: Logger, LogLevel } = require('log75'); + +const config = { + revoltClient: { + apiURL: process.env.API_URL || 'https://api.revolt.chat', + autoReconnect: true, + debug: false + }, + prefix: process.env.BOT_PREFIX || '/', + debug: process.env.NODE_ENV !== 'production', + creds: { + // chrome debug -> Application -> IndexedDB -> localforage -> state -> auth.accounts[user ID].session + session_token: process.env.SESSION_TOKEN, + user_id: process.env.USER_ID, + id: process.env.SESSION_ID + } +} + +const logger = new Logger(config.debug ? LogLevel.Debug : LogLevel.Standard); +const client = new Revolt.Client(config.revoltClient); + +client.on("message", async message => { + const author = await client.users.fetch(message.author); + const channel = await client.channels.fetch(message.channel); + + if (author._id === client.user._id) + return logger.debug(`Sent message -> ${channel.name} => ${message.content}`); + + const logPrefix = `${author.username} (${author._id}) in ${channel.name || 'Unnamed'} (${channel._id})`; + logger.debug(`${logPrefix} => ${message.content}`); + + if (!message.content.startsWith(config.prefix)) return; + let args = message.content.substr(config.prefix.length).split(' '); + let commandName = args.shift(); + + let command = commands.find(cmd => cmd.meta.name === commandName || cmd.meta.aliases?.indexOf(commandName) > -1); + if (!command) return; + + logger.info(`${logPrefix} -> COMMAND ${config.prefix}${commandName} ${args?.join(' ')}`) + + try { + command.run(message, args); + } catch(e) { + await client.channels.sendMessage(message.channel, `bot is death\n\`\`\`js\n${e}\`\`\``); + } +}); + + +// Log in +if (!config.creds.session_token) return logger.error('gimme token or die'); +if (!config.creds.user_id) return logger.error('gimme user id or die'); +if (!config.creds.id) return logger.error('gimme session id or die'); + +logger.info(`Attempting to continue session...`); +client.useExistingSession(config.creds) + .then(() => { + logger.done('Logged in'); + logger.info(`${client.user.username} (${client.user._id}): Ready`); + + require('./util/friendships'); // Manage relationships + }); + +module.exports.client = client; +module.exports.logger = logger; +module.exports.config = config; + +const { commands } = require('./util/command_loader'); diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..ccb49c6 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,432 @@ +{ + "name": "revolt-bot", + "version": "1.0.0", + "lockfileVersion": 1, + "requires": true, + "dependencies": { + "@insertish/mutable": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@insertish/mutable/-/mutable-1.0.3.tgz", + "integrity": "sha512-DDNdqs4r0KgdUxNFGlHDYVkyam27KsqEq+WQUNQA0+XA2g+VhowMmHjVA7Kxf70ONhhoE2R9XL4I4YMbxp43Dw==", + "requires": { + "@insertish/zangodb": "1.0.11", + "eventemitter3": "^4.0.7", + "lodash.isequal": "^4.5.0" + }, + "dependencies": { + "@insertish/zangodb": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@insertish/zangodb/-/zangodb-1.0.11.tgz", + "integrity": "sha512-ubHJQC1+2pBlsUqJFDtFnhqXfHxEoXS4zZIllVe3EQhfe/wvNjtL48peE6dE7nkKos6a1Dan831aldJeltIbuA==", + "requires": { + "clone": "^2.1.2", + "deepmerge": "^4.2.2", + "memoizee": "^0.4.15", + "object-hash": "^2.1.1", + "q": "^1.5.1" + } + } + } + }, + "@insertish/zangodb": { + "version": "1.0.10-patch.0", + "resolved": "https://registry.npmjs.org/@insertish/zangodb/-/zangodb-1.0.10-patch.0.tgz", + "integrity": "sha512-o6fEynGz/QMEIv/eZLmmzDaeJljGPq14XdrHQoNfKxNp53KkbGF6j+vIwQtNF+6osgXKBSC+BgeVEvFBN84QjA==", + "requires": { + "clone": "^2.1.2", + "deepmerge": "^4.2.2", + "memoizee": "^0.4.15", + "object-hash": "^2.1.1", + "q": "^1.5.1" + } + }, + "ansi-colors": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz", + "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==" + }, + "ansi-regex": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", + "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==" + }, + "axios": { + "version": "0.19.2", + "resolved": "https://registry.npmjs.org/axios/-/axios-0.19.2.tgz", + "integrity": "sha512-fjgm5MvRHLhx+osE2xoekY70AhARk3a6hkN+3Io1jc00jtquGvxYlKlsFUhmUET0V5te6CcZI7lcv2Ym61mjHA==", + "requires": { + "follow-redirects": "1.5.10" + } + }, + "clone": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz", + "integrity": "sha1-G39Ln1kfHo+DZwQBYANFoCiHQ18=" + }, + "cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "requires": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + } + }, + "d": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/d/-/d-1.0.1.tgz", + "integrity": "sha512-m62ShEObQ39CfralilEQRjH6oAMtNCV1xJyEx5LpRYUVN+EviphDgUc/F3hnYbADmkiNs67Y+3ylmlG7Lnu+FA==", + "requires": { + "es5-ext": "^0.10.50", + "type": "^1.0.1" + } + }, + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "requires": { + "ms": "2.0.0" + } + }, + "deepmerge": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.2.2.tgz", + "integrity": "sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg==" + }, + "dotenv": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-8.2.0.tgz", + "integrity": "sha512-8sJ78ElpbDJBHNeBzUbUVLsqKdccaa/BXF1uPTw3GrvQTBgrQrtObr2mUrE38vzYd8cEv+m/JBfDLioYcfXoaw==" + }, + "duplexer": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.2.tgz", + "integrity": "sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg==" + }, + "es5-ext": { + "version": "0.10.53", + "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.53.tgz", + "integrity": "sha512-Xs2Stw6NiNHWypzRTY1MtaG/uJlwCk8kH81920ma8mvN8Xq1gsfhZvpkImLQArw8AHnv8MT2I45J3c0R8slE+Q==", + "requires": { + "es6-iterator": "~2.0.3", + "es6-symbol": "~3.1.3", + "next-tick": "~1.0.0" + }, + "dependencies": { + "next-tick": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.0.0.tgz", + "integrity": "sha1-yobR/ogoFpsBICCOPchCS524NCw=" + } + } + }, + "es6-iterator": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz", + "integrity": "sha1-p96IkUGgWpSwhUQDstCg+/qY87c=", + "requires": { + "d": "1", + "es5-ext": "^0.10.35", + "es6-symbol": "^3.1.1" + } + }, + "es6-symbol": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.3.tgz", + "integrity": "sha512-NJ6Yn3FuDinBaBRWl/q5X/s4koRHBrgKAu+yGI6JCBeiu3qrcbJhwT2GeR/EXVfylRk8dpQVJoLEFhK+Mu31NA==", + "requires": { + "d": "^1.0.1", + "ext": "^1.1.2" + } + }, + "es6-weak-map": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/es6-weak-map/-/es6-weak-map-2.0.3.tgz", + "integrity": "sha512-p5um32HOTO1kP+w7PRnB+5lQ43Z6muuMuIMffvDN8ZB4GcnjLBV6zGStpbASIMk4DCAvEaamhe2zhyCb/QXXsA==", + "requires": { + "d": "1", + "es5-ext": "^0.10.46", + "es6-iterator": "^2.0.3", + "es6-symbol": "^3.1.1" + } + }, + "event-emitter": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/event-emitter/-/event-emitter-0.3.5.tgz", + "integrity": "sha1-34xp7vFkeSPHFXuc6DhAYQsCzDk=", + "requires": { + "d": "1", + "es5-ext": "~0.10.14" + } + }, + "event-stream": { + "version": "3.3.4", + "resolved": "https://registry.npmjs.org/event-stream/-/event-stream-3.3.4.tgz", + "integrity": "sha1-SrTJoPWlTbkzi0w02Gv86PSzVXE=", + "requires": { + "duplexer": "~0.1.1", + "from": "~0", + "map-stream": "~0.1.0", + "pause-stream": "0.0.11", + "split": "0.3", + "stream-combiner": "~0.0.4", + "through": "~2.3.1" + } + }, + "eventemitter3": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz", + "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==" + }, + "exponential-backoff": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/exponential-backoff/-/exponential-backoff-3.1.0.tgz", + "integrity": "sha512-oBuz5SYz5zzyuHINoe9ooePwSu0xApKWgeNzok4hZ5YKXFh9zrQBEM15CXqoZkJJPuI2ArvqjPQd8UKJA753XA==" + }, + "ext": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/ext/-/ext-1.4.0.tgz", + "integrity": "sha512-Key5NIsUxdqKg3vIsdw9dSuXpPCQ297y6wBjL30edxwPgt2E44WcWBZey/ZvUc6sERLTxKdyCu4gZFmUbk1Q7A==", + "requires": { + "type": "^2.0.0" + }, + "dependencies": { + "type": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/type/-/type-2.3.0.tgz", + "integrity": "sha512-rgPIqOdfK/4J9FhiVrZ3cveAjRRo5rsQBAIhnylX874y1DX/kEKSVdLsnuHB6l1KTjHyU01VjiMBHgU2adejyg==" + } + } + }, + "follow-redirects": { + "version": "1.5.10", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.5.10.tgz", + "integrity": "sha512-0V5l4Cizzvqt5D44aTXbFZz+FtyXV1vrDN6qrelxtfYQKW0KO0W2T/hkE8xvGa/540LkZlkaUjO4ailYTFtHVQ==", + "requires": { + "debug": "=3.1.0" + } + }, + "from": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/from/-/from-0.1.7.tgz", + "integrity": "sha1-g8YK/Fi5xWmXAH7Rp2izqzA6RP4=" + }, + "is-promise": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.2.2.tgz", + "integrity": "sha512-+lP4/6lKUBfQjZ2pdxThZvLUAafmZb8OAxFb8XXtiQmS35INgr85hdOGoEs124ez1FCnZJt6jau/T+alh58QFQ==" + }, + "isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=" + }, + "isomorphic-ws": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/isomorphic-ws/-/isomorphic-ws-4.0.1.tgz", + "integrity": "sha512-BhBvN2MBpWTaSHdWRb/bwdZJ1WaehQ2L1KngkCkfLUGF0mAWAT1sQUQacEmQ0jXkFw/czDXPNQSL5u2/Krsz1w==" + }, + "lodash.defaultsdeep": { + "version": "4.6.1", + "resolved": "https://registry.npmjs.org/lodash.defaultsdeep/-/lodash.defaultsdeep-4.6.1.tgz", + "integrity": "sha512-3j8wdDzYuWO3lM3Reg03MuQR957t287Rpcxp1njpEa8oDrikb+FwGdW3n+FELh/A6qib6yPit0j/pv9G/yeAqA==" + }, + "lodash.isequal": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz", + "integrity": "sha1-QVxEePK8wwEgwizhDtMib30+GOA=" + }, + "log75": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/log75/-/log75-2.0.1.tgz", + "integrity": "sha512-yoG7E0Hh2izZaZAhqL2WbwJ0PIkNcuEV09vFsX5owebLl4/xSmTaEd3gUle/j2ivUbuv2toUeEcJKUSG/MAO+A==", + "requires": { + "ansi-colors": "^4.1.1" + } + }, + "lru-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/lru-queue/-/lru-queue-0.1.0.tgz", + "integrity": "sha1-Jzi9nw089PhEkMVzbEhpmsYyzaM=", + "requires": { + "es5-ext": "~0.10.2" + } + }, + "map-stream": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/map-stream/-/map-stream-0.1.0.tgz", + "integrity": "sha1-5WqpTEyAVaFkBKBnS3jyFffI4ZQ=" + }, + "memoizee": { + "version": "0.4.15", + "resolved": "https://registry.npmjs.org/memoizee/-/memoizee-0.4.15.tgz", + "integrity": "sha512-UBWmJpLZd5STPm7PMUlOw/TSy972M+z8gcyQ5veOnSDRREz/0bmpyTfKt3/51DhEBqCZQn1udM/5flcSPYhkdQ==", + "requires": { + "d": "^1.0.1", + "es5-ext": "^0.10.53", + "es6-weak-map": "^2.0.3", + "event-emitter": "^0.3.5", + "is-promise": "^2.2.2", + "lru-queue": "^0.1.0", + "next-tick": "^1.1.0", + "timers-ext": "^0.1.7" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + }, + "next-tick": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.1.0.tgz", + "integrity": "sha512-CXdUiJembsNjuToQvxayPZF9Vqht7hewsvy2sOWafLvi2awflj9mOC6bHIg50orX8IJvWKY9wYQ/zB2kogPslQ==" + }, + "node-cleanup": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/node-cleanup/-/node-cleanup-2.1.2.tgz", + "integrity": "sha1-esGavSl+Caf3KnFUXZUbUX5N3iw=" + }, + "object-hash": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/object-hash/-/object-hash-2.1.1.tgz", + "integrity": "sha512-VOJmgmS+7wvXf8CjbQmimtCnEx3IAoLxI3fp2fbWehxrWBcAQFbk+vcwb6vzR0VZv/eNCJ/27j151ZTwqW/JeQ==" + }, + "path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==" + }, + "pause-stream": { + "version": "0.0.11", + "resolved": "https://registry.npmjs.org/pause-stream/-/pause-stream-0.0.11.tgz", + "integrity": "sha1-/lo0sMvOErWqaitAPuLnO2AvFEU=", + "requires": { + "through": "~2.3" + } + }, + "ps-tree": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/ps-tree/-/ps-tree-1.2.0.tgz", + "integrity": "sha512-0VnamPPYHl4uaU/nSFeZZpR21QAWRz+sRv4iW9+v/GS/J5U5iZB5BNN6J0RMoOvdx2gWM2+ZFMIm58q24e4UYA==", + "requires": { + "event-stream": "=3.3.4" + } + }, + "q": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/q/-/q-1.5.1.tgz", + "integrity": "sha1-fjL3W0E4EpHQRhHxvxQQmsAGUdc=" + }, + "revolt.js": { + "version": "4.0.0-alpha.12", + "resolved": "https://registry.npmjs.org/revolt.js/-/revolt.js-4.0.0-alpha.12.tgz", + "integrity": "sha512-7TgvlaKXm/IcdAKW2qDRzFB/ke4zXnkv7ouJ1OTK/C6zvaL/Wt3t8x1PzbRhNgioRvTMLR7nQXeTLsjqe1aCpQ==", + "requires": { + "@insertish/mutable": "1.0.3", + "@insertish/zangodb": "1.0.10-patch.0", + "axios": "^0.19.2", + "eventemitter3": "^4.0.7", + "exponential-backoff": "^3.1.0", + "isomorphic-ws": "^4.0.1", + "lodash.defaultsdeep": "^4.6.1", + "tsc-watch": "^4.1.0", + "ulid": "^2.3.0", + "ws": "^7.2.1" + } + }, + "shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "requires": { + "shebang-regex": "^3.0.0" + } + }, + "shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==" + }, + "split": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/split/-/split-0.3.3.tgz", + "integrity": "sha1-zQ7qXmOiEd//frDwkcQTPi0N0o8=", + "requires": { + "through": "2" + } + }, + "stream-combiner": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/stream-combiner/-/stream-combiner-0.0.4.tgz", + "integrity": "sha1-TV5DPBhSYd3mI8o/RMWGvPXErRQ=", + "requires": { + "duplexer": "~0.1.1" + } + }, + "string-argv": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/string-argv/-/string-argv-0.1.2.tgz", + "integrity": "sha512-mBqPGEOMNJKXRo7z0keX0wlAhbBAjilUdPW13nN0PecVryZxdHIeM7TqbsSUA7VYuS00HGC6mojP7DlQzfa9ZA==" + }, + "strip-ansi": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", + "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", + "requires": { + "ansi-regex": "^5.0.0" + } + }, + "through": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", + "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=" + }, + "timers-ext": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/timers-ext/-/timers-ext-0.1.7.tgz", + "integrity": "sha512-b85NUNzTSdodShTIbky6ZF02e8STtVVfD+fu4aXXShEELpozH+bCpJLYMPZbsABN2wDH7fJpqIoXxJpzbf0NqQ==", + "requires": { + "es5-ext": "~0.10.46", + "next-tick": "1" + } + }, + "tsc-watch": { + "version": "4.2.9", + "resolved": "https://registry.npmjs.org/tsc-watch/-/tsc-watch-4.2.9.tgz", + "integrity": "sha512-DlTaoDs74+KUpyWr7dCGhuscAUKCz6CiFduBN7R9RbLJSSN1moWdwoCLASE7+zLgGvV5AwXfYDiEMAsPGaO+Vw==", + "requires": { + "cross-spawn": "^7.0.3", + "node-cleanup": "^2.1.2", + "ps-tree": "^1.2.0", + "string-argv": "^0.1.1", + "strip-ansi": "^6.0.0" + } + }, + "type": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/type/-/type-1.2.0.tgz", + "integrity": "sha512-+5nt5AAniqsCnu2cEQQdpzCAh33kVx8n0VoFidKpB1dVVLAN/F+bgVOqOJqOnEnrhp222clB5p3vUlD+1QAnfg==" + }, + "ulid": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/ulid/-/ulid-2.3.0.tgz", + "integrity": "sha512-keqHubrlpvT6G2wH0OEfSW4mquYRcbe/J8NMmveoQOjUqmo+hXtO+ORCpWhdbZ7k72UtY61BL7haGxW6enBnjw==" + }, + "which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "requires": { + "isexe": "^2.0.0" + } + }, + "ws": { + "version": "7.4.3", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.4.3.tgz", + "integrity": "sha512-hr6vCR76GsossIRsr8OLR9acVVm1jyfEWvhbNjtgPOrfvAlKzvyeg/P6r8RuDjRyrcQoPQT7K0DGEPc7Ae6jzA==" + } + } +} diff --git a/package.json b/package.json new file mode 100644 index 0000000..b93c753 --- /dev/null +++ b/package.json @@ -0,0 +1,16 @@ +{ + "name": "revolt-bot", + "version": "1.0.0", + "description": "", + "main": "index.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "author": "", + "license": "ISC", + "dependencies": { + "dotenv": "^8.2.0", + "log75": "^2.0.1", + "revolt.js": "^4.0.0-alpha.12" + } +} diff --git a/util/command_loader.js b/util/command_loader.js new file mode 100644 index 0000000..8dcb48c --- /dev/null +++ b/util/command_loader.js @@ -0,0 +1,22 @@ +const fs = require('fs'); +const { logger } = require('../index'); + +(async () => { + const files = await fs.promises.readdir('commands'); + files + .filter(file => file.endsWith('.js')) + .forEach(file => { + try { + const mod = require(`../commands/${file}`); + this.commands.push(mod); + } catch(e) { + logger.error(`Failed to load '${file}':\n${e}`); + } + }); +})(); + +/** + * + * @type {Array<{ meta: { name: String, aliases: String[], description: String? }, run(import(revolt.js).Message, args: String[]): Promise }>} + */ +module.exports.commands = []; \ No newline at end of file diff --git a/util/friendships.js b/util/friendships.js new file mode 100644 index 0000000..ae2bfda --- /dev/null +++ b/util/friendships.js @@ -0,0 +1,45 @@ +/** + * Automatically accepts friend requests and + * sends requests to users messaging the bot. + * Required for users to add it to groups. + */ + +const { client, logger, config } = require('..'); + +client.on("packet", async packet => { + try { + if (packet.type !== 'UserRelationship') return; + if (packet.status === 'Incoming') { + // Incoming friend request + const user = await client.users.fetch(packet.user) + .catch(e => { + logger.error(`Failed to fetch author of friend request:\n${e}`); + }); + + logger.info(`Incoming friend request from ${user.username} (${user._id})`); + client.users.addFriend(user.username) + .catch(e => { + logger.error(`Failed to accept friend request:\n${e}`); + client.channels.sendMessage(packet.user, `Sorry, due to an error I was unable to process your friend request.`) + .catch(() => { + }); + }) + .then(() => logger.done(`Friend added`)); + } + } catch(e) { + console.error(e); + } +}); + +// Scan friend list for new friend requests created during downtime +client.user.relations + .filter(r => r.status === "Incoming") + .forEach(async relationship => { + try { + const user = await client.users.fetch(relationship._id); + await client.users.addFriend(user.username); + logger.info(`Accepted pending friend request from ${user.username}`); + } catch(e) { + console.error(e); + } + }); \ No newline at end of file