Copy Discord emojis/stickers to Matrix
This commit is contained in:
parent
d81aa51787
commit
807ab899be
4 changed files with 121 additions and 3 deletions
|
@ -12,6 +12,8 @@ const api = sync.require("../../matrix/api")
|
||||||
const file = sync.require("../../matrix/file")
|
const file = sync.require("../../matrix/file")
|
||||||
/** @type {import("./create-room")} */
|
/** @type {import("./create-room")} */
|
||||||
const createRoom = sync.require("./create-room")
|
const createRoom = sync.require("./create-room")
|
||||||
|
/** @type {import("../converters/expression")} */
|
||||||
|
const expression = sync.require("../converters/expression")
|
||||||
/** @type {import("../../matrix/kstate")} */
|
/** @type {import("../../matrix/kstate")} */
|
||||||
const ks = sync.require("../../matrix/kstate")
|
const ks = sync.require("../../matrix/kstate")
|
||||||
|
|
||||||
|
@ -186,8 +188,29 @@ async function syncSpaceFully(guildID) {
|
||||||
return spaceID
|
return spaceID
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {import("discord-api-types/v10").GatewayGuildEmojisUpdateDispatchData | import("discord-api-types/v10").GatewayGuildStickersUpdateDispatchData} data
|
||||||
|
*/
|
||||||
|
async function syncSpaceExpressions(data) {
|
||||||
|
// No need for kstate here. Each of these maps to a single state event, which will always overwrite what was there before. I can just send the state event.
|
||||||
|
|
||||||
|
const spaceID = select("guild_space", "space_id", "WHERE guild_id = ?").pluck().get(data.guild_id)
|
||||||
|
if (!spaceID) return
|
||||||
|
|
||||||
|
if ("emojis" in data && data.emojis.length) {
|
||||||
|
const content = await expression.emojisToState(data.emojis)
|
||||||
|
api.sendState(spaceID, "im.ponies.room_emotes", "moe.cadence.ooye.pack.emojis", content)
|
||||||
|
}
|
||||||
|
|
||||||
|
if ("stickers" in data && data.stickers.length) {
|
||||||
|
const content = await expression.stickersToState(data.stickers)
|
||||||
|
api.sendState(spaceID, "im.ponies.room_emotes", "moe.cadence.ooye.pack.stickers", content)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
module.exports.createSpace = createSpace
|
module.exports.createSpace = createSpace
|
||||||
module.exports.ensureSpace = ensureSpace
|
module.exports.ensureSpace = ensureSpace
|
||||||
module.exports.syncSpace = syncSpace
|
module.exports.syncSpace = syncSpace
|
||||||
module.exports.syncSpaceFully = syncSpaceFully
|
module.exports.syncSpaceFully = syncSpaceFully
|
||||||
module.exports.guildToKState = guildToKState
|
module.exports.guildToKState = guildToKState
|
||||||
|
module.exports.syncSpaceExpressions = syncSpaceExpressions
|
||||||
|
|
82
d2m/converters/expression.js
Normal file
82
d2m/converters/expression.js
Normal file
|
@ -0,0 +1,82 @@
|
||||||
|
// @ts-check
|
||||||
|
|
||||||
|
const assert = require("assert").strict
|
||||||
|
const DiscordTypes = require("discord-api-types/v10")
|
||||||
|
|
||||||
|
const passthrough = require("../../passthrough")
|
||||||
|
const {discord, sync, db, select} = passthrough
|
||||||
|
/** @type {import("../../matrix/file")} */
|
||||||
|
const file = sync.require("../../matrix/file")
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {DiscordTypes.APIEmoji[]} emojis
|
||||||
|
*/
|
||||||
|
async function emojisToState(emojis) {
|
||||||
|
const result = {
|
||||||
|
pack: {
|
||||||
|
display_name: "Discord Emojis",
|
||||||
|
usage: ["emoticon"] // we'll see...
|
||||||
|
},
|
||||||
|
images: {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
await Promise.all(emojis.map(emoji =>
|
||||||
|
// the homeserver can probably cope with doing this in parallel
|
||||||
|
file.uploadDiscordFileToMxc(file.emoji(emoji.id, emoji.animated)).then(url => {
|
||||||
|
result.images[emoji.name] = {
|
||||||
|
info: {
|
||||||
|
mimetype: emoji.animated ? "image/gif" : "image/png"
|
||||||
|
},
|
||||||
|
url
|
||||||
|
}
|
||||||
|
}).catch(e => {
|
||||||
|
if (e.data.errcode === "M_TOO_LARGE") { // Lol.
|
||||||
|
return
|
||||||
|
}
|
||||||
|
console.error(`Trying to handle emoji ${emoji.name} (${emoji.id}), but...`)
|
||||||
|
throw e
|
||||||
|
})
|
||||||
|
))
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {DiscordTypes.APISticker[]} stickers
|
||||||
|
*/
|
||||||
|
async function stickersToState(stickers) {
|
||||||
|
const result = {
|
||||||
|
pack: {
|
||||||
|
display_name: "Discord Stickers",
|
||||||
|
usage: ["sticker"] // we'll see...
|
||||||
|
},
|
||||||
|
images: {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const shortcodes = []
|
||||||
|
await Promise.all(stickers.map(sticker =>
|
||||||
|
// the homeserver can probably cope with doing this in parallel
|
||||||
|
file.uploadDiscordFileToMxc(file.sticker(sticker)).then(url => {
|
||||||
|
|
||||||
|
/** @type {string | undefined} */
|
||||||
|
let body = sticker.name
|
||||||
|
if (sticker && sticker.description) body += ` - ${sticker.description}`
|
||||||
|
if (!body) body = undefined
|
||||||
|
|
||||||
|
let shortcode = sticker.name.toLowerCase().replace(/[^a-zA-Z0-9-_]/g, "-").replace(/^-|-$/g, "").replace(/--+/g, "-")
|
||||||
|
while (shortcodes.includes(shortcode)) shortcode = shortcode + "~"
|
||||||
|
shortcodes.push(shortcode)
|
||||||
|
|
||||||
|
result.images[shortcodes] = {
|
||||||
|
info: {
|
||||||
|
mimetype: file.stickerFormat.get(sticker.format_type)?.mime || "image/png"
|
||||||
|
},
|
||||||
|
body,
|
||||||
|
url
|
||||||
|
}
|
||||||
|
})
|
||||||
|
))
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports.emojisToState = emojisToState
|
||||||
|
module.exports.stickersToState = stickersToState
|
|
@ -56,6 +56,18 @@ const utils = {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
} else if (message.t === "GUILD_EMOJIS_UPDATE") {
|
||||||
|
const guild = client.guilds.get(message.d.guild_id)
|
||||||
|
if (guild) {
|
||||||
|
guild.emojis = message.d.emojis
|
||||||
|
}
|
||||||
|
|
||||||
|
} else if (message.t === "GUILD_STICKERS_UPDATE") {
|
||||||
|
const guild = client.guilds.get(message.d.guild_id)
|
||||||
|
if (guild) {
|
||||||
|
guild.stickers = message.d.stickers
|
||||||
|
}
|
||||||
|
|
||||||
} else if (message.t === "THREAD_CREATE") {
|
} else if (message.t === "THREAD_CREATE") {
|
||||||
client.channels.set(message.d.id, message.d)
|
client.channels.set(message.d.id, message.d)
|
||||||
|
|
||||||
|
@ -98,6 +110,9 @@ const utils = {
|
||||||
if (message.t === "GUILD_UPDATE") {
|
if (message.t === "GUILD_UPDATE") {
|
||||||
await eventDispatcher.onGuildUpdate(client, message.d)
|
await eventDispatcher.onGuildUpdate(client, message.d)
|
||||||
|
|
||||||
|
} else if (message.t === "GUILD_EMOJIS_UPDATE" || message.t === "GUILD_STICKERS_UPDATE") {
|
||||||
|
await eventDispatcher.onExpressionsUpdate(client, message.d)
|
||||||
|
|
||||||
} else if (message.t === "CHANNEL_UPDATE") {
|
} else if (message.t === "CHANNEL_UPDATE") {
|
||||||
await eventDispatcher.onChannelOrThreadUpdate(client, message.d, false)
|
await eventDispatcher.onChannelOrThreadUpdate(client, message.d, false)
|
||||||
|
|
||||||
|
|
|
@ -239,8 +239,6 @@ module.exports = {
|
||||||
* @param {import("discord-api-types/v10").GatewayGuildEmojisUpdateDispatchData | import("discord-api-types/v10").GatewayGuildStickersUpdateDispatchData} data
|
* @param {import("discord-api-types/v10").GatewayGuildEmojisUpdateDispatchData | import("discord-api-types/v10").GatewayGuildStickersUpdateDispatchData} data
|
||||||
*/
|
*/
|
||||||
async onExpressionsUpdate(client, data) {
|
async onExpressionsUpdate(client, data) {
|
||||||
const spaceID = select("guild_space", "space_id", "WHERE guild_id = ?").pluck().get(guild.id)
|
await createSpace.syncSpaceExpressions(data)
|
||||||
if (!spaceID) return
|
|
||||||
await createSpace.syncSpaceExpressions(spaceID, data)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue