diff --git a/db/migrations/0004-auto-emoji-guild.sql b/db/migrations/0004-auto-emoji-guild.sql new file mode 100644 index 0000000..6d92f2b --- /dev/null +++ b/db/migrations/0004-auto-emoji-guild.sql @@ -0,0 +1,10 @@ +BEGIN TRANSACTION; + +CREATE TABLE auto_emoji ( + name TEXT NOT NULL, + emoji_id TEXT NOT NULL, + guild_id TEXT NOT NULL, + PRIMARY KEY (name) +) WITHOUT ROWID; + +COMMIT; diff --git a/db/orm-defs.d.ts b/db/orm-defs.d.ts index 9524f20..ffb9728 100644 --- a/db/orm-defs.d.ts +++ b/db/orm-defs.d.ts @@ -75,6 +75,12 @@ export type Models = { message_id: string encoded_emoji: string } + + auto_emoji: { + name: string + emoji_id: string + guild_id: string + } } export type Prepared = { diff --git a/docs/img/L1.png b/docs/img/L1.png new file mode 100644 index 0000000..4e66a09 Binary files /dev/null and b/docs/img/L1.png differ diff --git a/docs/img/L2.png b/docs/img/L2.png new file mode 100644 index 0000000..a74f327 Binary files /dev/null and b/docs/img/L2.png differ diff --git a/package-lock.json b/package-lock.json index 15b4b76..2cf30c6 100644 --- a/package-lock.json +++ b/package-lock.json @@ -7,7 +7,7 @@ "": { "name": "out-of-your-element", "version": "1.0.0", - "license": "MIT", + "license": "AGPL-3.0-or-later", "dependencies": { "@chriscdn/promise-semaphore": "^2.0.1", "better-sqlite3": "^8.3.0", @@ -18,6 +18,7 @@ "heatsync": "^2.4.1", "js-yaml": "^4.1.0", "matrix-appservice": "^2.0.0", + "minimist": "^1.2.8", "mixin-deep": "github:cloudrac3r/mixin-deep#v3.0.0", "node-fetch": "^2.6.7", "pngjs": "^7.0.0", diff --git a/package.json b/package.json index e40e82c..333aae9 100644 --- a/package.json +++ b/package.json @@ -24,6 +24,7 @@ "heatsync": "^2.4.1", "js-yaml": "^4.1.0", "matrix-appservice": "^2.0.0", + "minimist": "^1.2.8", "mixin-deep": "github:cloudrac3r/mixin-deep#v3.0.0", "node-fetch": "^2.6.7", "pngjs": "^7.0.0", diff --git a/readme.md b/readme.md index f1a35c7..2a217e5 100644 --- a/readme.md +++ b/readme.md @@ -59,7 +59,6 @@ You'll need: * Administrative access to a homeserver * Discord bot -* Custom emojis named `L1` and `L2` for replies sent to Discord (TODO: provide) Follow these steps: @@ -148,6 +147,7 @@ Follow these steps: * (1) heatsync: Module hot-reloader that I trust. * (1) js-yaml: It seems to do what I want, and it's already pulled in by matrix-appservice. * (70) matrix-appservice: I wish it didn't pull in express :( +* (0) minimist: It's already pulled in by better-sqlite3->prebuild-install * (0) mixin-deep: This is my fork! It fixes a bug in regular mixin-deep. * (3) node-fetch@2: I like it and it does what I want. * (0) pngjs: Lottie stickers are converted to bitmaps with the vendored Rlottie WASM build, then the bitmaps are converted to PNG with pngjs. diff --git a/scripts/seed.js b/scripts/seed.js index 2a0c279..0f2f23d 100644 --- a/scripts/seed.js +++ b/scripts/seed.js @@ -1,10 +1,14 @@ // @ts-check +console.log("This could take up to 30 seconds. Please be patient.") + const assert = require("assert").strict const fs = require("fs") const sqlite = require("better-sqlite3") const HeatSync = require("heatsync") +const args = require("minimist")(process.argv.slice(2), {string: ["emoji-guild"]}) + const config = require("../config") const passthrough = require("../passthrough") const db = new sqlite("db/ooye.db") @@ -27,6 +31,24 @@ const file = require("../matrix/file") const reg = require("../matrix/read-registration") const utils = require("../m2d/converters/utils") +function die(message) { + console.error(message) + process.exit(1) +} + +async function uploadAutoEmoji(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 discord.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 () => { const mxid = `@${reg.sender_localpart}:${reg.ooye.server_name}` @@ -45,6 +67,43 @@ const utils = require("../m2d/converters/utils") console.log("✅ Database is ready...") + // 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.`) + } + // 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 seed.js 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(guild, "L1", "docs/img/L1.png") + await uploadAutoEmoji(guild, "L2", "docs/img/L2.png") + } + console.log("✅ Emojis are ready...") + // ensure homeserver well-known is valid and returns reg.ooye.server_name... // upload initial images...