From 7a59f48c0ad3631b1b3ceaab43d5134965faaa53 Mon Sep 17 00:00:00 2001 From: Cadence Ember Date: Mon, 12 May 2025 14:28:19 +1200 Subject: [PATCH] New emoji storage and bug fixes in setup --- docs/developer-orientation.md | 1 - package-lock.json | 5 +- package.json | 3 +- scripts/setup.js | 81 +++++++------------ .../0022-auto-emoji-without-guild.sql | 11 +++ test/ooye-test-data.sql | 7 +- 6 files changed, 48 insertions(+), 60 deletions(-) create mode 100644 src/db/migrations/0022-auto-emoji-without-guild.sql diff --git a/docs/developer-orientation.md b/docs/developer-orientation.md index 02b5c52..94a420c 100644 --- a/docs/developer-orientation.md +++ b/docs/developer-orientation.md @@ -121,7 +121,6 @@ Total transitive production dependencies: 137 * (1) heatsync: Module hot-reloader that I trust. * (1) js-yaml: Will be removed in the future after registration.yaml is converted to JSON. * (0) lru-cache: For holding unused nonce in memory and letting them be overwritten later if never used. -* (0) minimist: It's already pulled in by better-sqlite3->prebuild-install. * (0) prettier-bytes: It does what I want and has no dependencies. * (0) snowtransfer: Discord API library with bring-your-own-caching that I trust. * (0) try-to-catch: Not strictly necessary, but it's already pulled in by supertape, so I may as well. diff --git a/package-lock.json b/package-lock.json index eb1ac29..fbb9d93 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "out-of-your-element", - "version": "3.0.0", + "version": "3.1.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "out-of-your-element", - "version": "3.0.0", + "version": "3.1.0", "license": "AGPL-3.0-or-later", "dependencies": { "@chriscdn/promise-semaphore": "^2.0.1", @@ -33,7 +33,6 @@ "heatsync": "^2.7.2", "htmx.org": "^2.0.4", "lru-cache": "^11.0.2", - "minimist": "^1.2.8", "prettier-bytes": "^1.0.4", "sharp": "^0.33.4", "snowtransfer": "^0.13.1", diff --git a/package.json b/package.json index 335ea87..3799b87 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "out-of-your-element", - "version": "3.0.0", + "version": "3.1.0", "description": "A bridge between Matrix and Discord", "main": "index.js", "repository": { @@ -42,7 +42,6 @@ "heatsync": "^2.7.2", "htmx.org": "^2.0.4", "lru-cache": "^11.0.2", - "minimist": "^1.2.8", "prettier-bytes": "^1.0.4", "sharp": "^0.33.4", "snowtransfer": "^0.13.1", diff --git a/scripts/setup.js b/scripts/setup.js index 15c17cd..d907c66 100644 --- a/scripts/setup.js +++ b/scripts/setup.js @@ -17,8 +17,6 @@ const {SnowTransfer} = require("snowtransfer") const DiscordTypes = require("discord-api-types/v10") const {createApp, defineEventHandler, toNodeListener} = require("h3") -const args = require("minimist")(process.argv.slice(2), {string: ["emoji-guild"]}) - // Move database file if it's still in the old location if (fs.existsSync("db")) { if (fs.existsSync("db/ooye.db")) { @@ -55,19 +53,6 @@ function die(message) { process.exit(1) } -async function uploadAutoEmoji(snow, guild, name, filename) { - let emoji = guild.emojis.find(e => e.name === name) - if (!emoji) { - console.log(` Uploading ${name}...`) - const data = fs.readFileSync(filename, null) - emoji = await snow.guildAssets.createEmoji(guild.id, {name, image: "data:image/png;base64," + data.toString("base64")}) - } else { - console.log(` Reusing ${name}...`) - } - db.prepare("REPLACE INTO auto_emoji (name, emoji_id, guild_id) VALUES (?, ?, ?)").run(emoji.name, emoji.id, guild.id) - return emoji -} - async function suggestWellKnown(serverUrlPrompt, url, otherwise) { try { var json = await fetch(`${url}/.well-known/matrix/client`).then(res => res.json()) @@ -170,7 +155,7 @@ function defineEchoHandler() { console.log("Go to https://discord.com/developers, create or pick an app, go to the Bot section, and reset the token.") /** @type {SnowTransfer} */ // @ts-ignore let snow = null - /** @type {{id: string, flags: number, redirect_uris: string[]}} */ // @ts-ignore + /** @type {{id: string, flags: number, redirect_uris: string[], description: string}} */ // @ts-ignore let client = null /** @type {{discord_token: string}} */ const discordTokenResponse = await prompt({ @@ -217,6 +202,25 @@ function defineEchoHandler() { message: "Choose a simple password (optional)" }) + console.log("To fulfill license obligations, I recommend mentioning Out Of Your Element in your Discord bot's profile.") + console.log("On the Discord bot configuration page, go to General and add something like this to the description:") + console.log(cyan("Powered by **Out Of Your Element**")) + console.log(cyan("https://gitdab.com/cadence/out-of-your-element")) + await prompt({ + type: "invisible", + name: "description", + message: "Press Enter to acknowledge", + validate: async token => { + process.stdout.write(magenta("checking, please wait...")) + client = await snow.requestHandler.request(`/applications/@me`, {}, "get", "json") + if (client.description?.match(/out.of.your.element/i)) { + return true + } else { + return "Description must name or link Out Of Your Element" + } + } + }) + console.log("What is your Discord client secret?") console.log(`You can find it in the application's OAuth2 section: https://discord.com/developers/applications/${client.id}/oauth2`) /** @type {{discord_client_secret: string}} */ @@ -342,47 +346,24 @@ function defineEchoHandler() { console.log("✅ Matrix appservice login works...") - // upload the L1 L2 emojis to some guild - const emojis = db.prepare("SELECT name FROM auto_emoji WHERE name = 'L1' OR name = 'L2'").pluck().all() - if (emojis.length !== 2) { - // If an argument was supplied, always use that one - let guild = null - if (args["emoji-guild"]) { - if (typeof args["emoji-guild"] === "string") { - guild = await discord.snow.guild.getGuild(args["emoji-guild"]) - } - if (!guild) return die(`Error: You asked emojis to be uploaded to guild ID ${args["emoji-guild"]}, but the bot isn't in that guild.`) + // upload the L1 L2 emojis to user emojis + const emojis = await discord.snow.assets.getAppEmojis(client.id) + for (const name of ["L1", "L2"]) { + const existing = emojis.items.find(e => e.name === name) + if (existing) { + db.prepare("REPLACE INTO auto_emoji (name, emoji_id) VALUES (?, ?)").run(existing.name, existing.id) + } else { + const filename = join(__dirname, "../docs/img", `${name}.png`) + const data = fs.readFileSync(filename, null) + const uploaded = await discord.snow.assets.createAppEmoji(client.id, {name, image: "data:image/png;base64," + data.toString("base64")}) + db.prepare("REPLACE INTO auto_emoji (name, emoji_id) VALUES (?, ?)").run(uploaded.name, uploaded.id) } - // Otherwise, check if we have already registered an auto emoji guild - if (!guild) { - const guildID = passthrough.select("auto_emoji", "guild_id", {name: "_"}).pluck().get() - if (guildID) { - guild = await discord.snow.guild.getGuild(guildID, false) - } - } - // Otherwise, check if we should create a new guild - if (!guild) { - const guilds = await discord.snow.user.getGuilds({limit: 11, with_counts: false}) - if (guilds.length < 10) { - console.log(" Creating a guild for emojis...") - guild = await discord.snow.guild.createGuild({name: "OOYE Emojis"}) - } - } - // Otherwise, it's the user's problem - if (!guild) { - return die(`Error: The bot needs to upload some emojis. Please say where to upload them to. Run setup again with --emoji-guild=GUILD_ID`) - } - // Upload those emojis to the chosen location - db.prepare("REPLACE INTO auto_emoji (name, emoji_id, guild_id) VALUES ('_', '_', ?)").run(guild.id) - await uploadAutoEmoji(discord.snow, guild, "L1", join(__dirname, "../docs/img/L1.png")) - await uploadAutoEmoji(discord.snow, guild, "L2", join(__dirname, "../docs/img/L2.png")) } console.log("✅ Emojis are ready...") // set profile data on discord... const avatarImageBuffer = await fetch("https://cadence.moe/friends/out_of_your_element.png").then(res => res.arrayBuffer()) await discord.snow.user.updateSelf({avatar: "data:image/png;base64," + Buffer.from(avatarImageBuffer).toString("base64")}) - await discord.snow.bot.updateApplicationInfo({description: "Powered by **Out Of Your Element**\nhttps://gitdab.com/cadence/out-of-your-element"}) console.log("✅ Discord profile updated...") // set profile data on homeserver... diff --git a/src/db/migrations/0022-auto-emoji-without-guild.sql b/src/db/migrations/0022-auto-emoji-without-guild.sql new file mode 100644 index 0000000..1d23c0d --- /dev/null +++ b/src/db/migrations/0022-auto-emoji-without-guild.sql @@ -0,0 +1,11 @@ +BEGIN TRANSACTION; + +DROP TABLE auto_emoji; + +CREATE TABLE auto_emoji ( + name TEXT NOT NULL, + emoji_id TEXT NOT NULL, + PRIMARY KEY (name) +) WITHOUT ROWID; + +COMMIT; diff --git a/test/ooye-test-data.sql b/test/ooye-test-data.sql index e3f0478..caac692 100644 --- a/test/ooye-test-data.sql +++ b/test/ooye-test-data.sql @@ -166,10 +166,9 @@ INSERT INTO member_power (mxid, room_id, power_level) VALUES INSERT INTO lottie (sticker_id, mxc_url) VALUES ('860171525772279849', 'mxc://cadence.moe/ZtvvVbwMIdUZeovWVyGVFCeR'); -INSERT INTO auto_emoji (name, emoji_id, guild_id) VALUES -('L1', '1144820033948762203', '529176156398682115'), -('L2', '1144820084079087647', '529176156398682115'), -('_', '_', '529176156398682115'); +INSERT INTO auto_emoji (name, emoji_id) VALUES +('L1', '1144820033948762203'), +('L2', '1144820084079087647'); INSERT INTO media_proxy (permitted_hash) VALUES (-429802515645771439),