From acfeab68e64d5cb975ea8efdf95246e0e03ea1df Mon Sep 17 00:00:00 2001 From: Papa Date: Tue, 6 Dec 2022 17:10:31 -0700 Subject: [PATCH] initial with Discord --- .gitignore | 4 +++ config.example.js | 3 ++ index.js | 39 +++++++++++++++++++++++++ modules/DiscordClient.js | 63 ++++++++++++++++++++++++++++++++++++++++ modules/DiscordEvents.js | 11 +++++++ package.json | 21 ++++++++++++++ types.d.ts | 1 + 7 files changed, 142 insertions(+) create mode 100644 .gitignore create mode 100644 config.example.js create mode 100644 index.js create mode 100644 modules/DiscordClient.js create mode 100644 modules/DiscordEvents.js create mode 100644 package.json create mode 100644 types.d.ts diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..d8f941b --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +/node_modules +package-lock.json + +/config.js diff --git a/config.example.js b/config.example.js new file mode 100644 index 0000000..0d1a29e --- /dev/null +++ b/config.example.js @@ -0,0 +1,3 @@ +module.exports = { + discordToken: "yes" +} diff --git a/index.js b/index.js new file mode 100644 index 0000000..2494282 --- /dev/null +++ b/index.js @@ -0,0 +1,39 @@ +const repl = require("repl") +const util = require("util") + +const DiscordClient = require("./modules/DiscordClient") + +const config = require("./config") + +const discord = new DiscordClient(config.discordToken) + +discord.cloud.connect().then(() => console.log("Discord gateway started")) + +/** + * @param {string} input + * @param {import("vm").Context} _context + * @param {string} _filename + * @param {(err: Error | null, result: unknown) => unknown} callback + * @returns + */ +async function customEval(input, _context, _filename, callback) { + let depth = 0 + if (input === "exit\n") return process.exit() + if (input.startsWith(":")) { + const depthOverwrite = input.split(" ")[0] + depth = +depthOverwrite.slice(1) + input = input.slice(depthOverwrite.length + 1) + } + /** @type {unknown} */ + let result + try { + result = await eval(input) + const output = util.inspect(result, false, depth, true) + return callback(null, output) + } catch (e) { + return callback(e, undefined) + } +} + +const cli = repl.start({ prompt: "", eval: customEval, writer: s => s }) +cli.once("exit", process.exit) diff --git a/modules/DiscordClient.js b/modules/DiscordClient.js new file mode 100644 index 0000000..651c52e --- /dev/null +++ b/modules/DiscordClient.js @@ -0,0 +1,63 @@ +const { SnowTransfer } = require("snowtransfer") +const { Client: CloudStorm } = require("cloudstorm") + +let wasReadyBefore = false + +class DiscordClient { + /** + * @param {string} discordToken + */ + constructor(discordToken) { + this.discordToken = discordToken + this.snow = new SnowTransfer(discordToken) + this.cloud = new CloudStorm(discordToken, { + shards: "auto", + reconnect: true, + snowtransferInstance: this.snow, + intents: [ + "DIRECT_MESSAGES", "DIRECT_MESSAGE_REACTIONS", "DIRECT_MESSAGE_TYPING", + "GUILDS", "GUILD_EMOJIS_AND_STICKERS", "GUILD_MESSAGES", "GUILD_MESSAGE_REACTIONS", "GUILD_MESSAGE_TYPING", "GUILD_WEBHOOKS", + "MESSAGE_CONTENT" + ], + ws: { + compress: false, + encoding: "json" + } + }) + /** @type {import("discord-typings").User | null} */ + this.user = null + /** @type {import("discord-typings").Application | null} */ + this.application = null + /** @type {Map} */ + this.channels = new Map() + this.cloud.on("event", this.onPacket.bind(this)) + } + + /** + * @param {import("cloudstorm").IGatewayMessage} message + * @private + */ + onPacket(message) { + if (message.t === "READY") { + if (wasReadyBefore) return + /** @type {import("discord-typings").ReadyPayload} */ + const typed = message.d + this.user = typed.user + this.application = typed.application + console.log(`Discord logged in as ${this.user.username}#${this.user.discriminator} (${this.user.id})`) + } else if (message.t === "GUILD_CREATE") { + /** @type {import("discord-typings").Guild} */ + const typed = message.d + for (const channel of typed.channels || []) { + this.channels.set(channel.id, channel) + } + } else if (message.t === "CHANNEL_CREATE" || message.t === "CHANNEL_DELETE") { + /** @type {import("discord-typings").Channel} */ + const typed = message.d + if (message.t === "CHANNEL_CREATE") this.channels.set(typed.id, typed) + else this.channels.delete(typed.id) + } + } +} + +module.exports = DiscordClient diff --git a/modules/DiscordEvents.js b/modules/DiscordEvents.js new file mode 100644 index 0000000..5927f4e --- /dev/null +++ b/modules/DiscordEvents.js @@ -0,0 +1,11 @@ +module.exports = { + /** + * Process Discord messages and convert to a message Matrix can understand + * + * @param {import("discord-typings").Message} message + * @returns {import("../types").MatrixMessage} + */ + onMessageCreate: message => { + return {} + } +} diff --git a/package.json b/package.json new file mode 100644 index 0000000..d635e14 --- /dev/null +++ b/package.json @@ -0,0 +1,21 @@ +{ + "name": "out-of-your-element", + "version": "1.0.0", + "description": "A bridge between Matrix and Discord", + "main": "index.js", + "repository": { + "type": "git", + "url": "git@ssh.gitdab.com:cadence/out-of-your-element.git" + }, + "keywords": [ + "matrix", + "discord", + "bridge" + ], + "author": "Cadence, PapiOphidian", + "license": "MIT", + "dependencies": { + "cloudstorm": "^0.6.1", + "snowtransfer": "^0.6.1" + } +} diff --git a/types.d.ts b/types.d.ts new file mode 100644 index 0000000..491622c --- /dev/null +++ b/types.d.ts @@ -0,0 +1 @@ +export type MatrixMessage = {}