diff --git a/src/d2m/actions/register-user.js b/src/d2m/actions/register-user.js index b914d41..94daa34 100644 --- a/src/d2m/actions/register-user.js +++ b/src/d2m/actions/register-user.js @@ -208,6 +208,34 @@ async function syncUser(user, member, channel, guild, roomID) { return mxid } +/** + * Sync profile data for a webhook user. The _ooye_webhook name will always be reused. + * 1. Join the sim to the room if needed + * 2. Make an object of what the new room member state content would be, including uploading the profile picture if it hasn't been done before + * 4. Compare against the previously known state content, which is helpfully stored in the database + * 5. If the state content has changed, send it to Matrix and update it in the database for next time + * @param {DiscordTypes.APIUser} user + * @param {DiscordTypes.APIGuildChannel} channel + * @param {DiscordTypes.APIGuild} guild + * @param {string} roomID + * @returns {Promise} mxid of the updated sim + */ +async function syncWebhook(user, channel, guild, roomID) { + const mxid = await ensureSimJoined(user, roomID) + // @ts-ignore + const content = await memberToStateContent(user, {}, guild.id) + const currentHash = _hashProfileContent(content, 0) + const existingHash = select("sim_member", "hashed_profile_content", {room_id: roomID, mxid}).safeIntegers().pluck().get() + // only do the actual sync if the hash has changed since we last looked + if (existingHash !== currentHash) { + // Update room member state + await api.sendState(roomID, "m.room.member", mxid, content, mxid) + // Update cached hash + db.prepare("UPDATE sim_member SET hashed_profile_content = ? WHERE room_id = ? AND mxid = ?").run(currentHash, roomID, mxid) + } + return mxid +} + /** * @param {string} roomID */ @@ -244,4 +272,5 @@ module.exports._hashProfileContent = _hashProfileContent module.exports.ensureSim = ensureSim module.exports.ensureSimJoined = ensureSimJoined module.exports.syncUser = syncUser +module.exports.syncWebhook = syncWebhook module.exports.syncAllUsersInRoom = syncAllUsersInRoom diff --git a/src/d2m/actions/send-message.js b/src/d2m/actions/send-message.js index 6d100d4..ac3378c 100644 --- a/src/d2m/actions/send-message.js +++ b/src/d2m/actions/send-message.js @@ -28,20 +28,20 @@ async function sendMessage(message, channel, guild, row) { const roomID = await createRoom.ensureRoom(message.channel_id) let senderMxid = null - if (!dUtils.isWebhookMessage(message)) { - if (message.author.id === discord.application.id) { - // no need to sync the bot's own user - } else if (message.member) { // available on a gateway message create event - senderMxid = await registerUser.syncUser(message.author, message.member, channel, guild, roomID) - } else { // well, good enough... - senderMxid = await registerUser.ensureSimJoined(message.author, roomID) - } - } else if (row && row.speedbump_webhook_id === message.webhook_id) { + if (row && row.speedbump_webhook_id === message.webhook_id) { // Handle the PluralKit public instance if (row.speedbump_id === "466378653216014359") { const pkMessage = await registerPkUser.fetchMessage(message.id) senderMxid = await registerPkUser.syncUser(message.author, pkMessage, roomID) } + } else if (message.author.id === discord.application.id) { + // no need to sync the bot's own user + } else if (dUtils.isWebhookMessage(message)) { + senderMxid = await registerUser.syncWebhook(message.author, channel, guild, roomID) + } else if (message.member) { // available on a gateway message create event + senderMxid = await registerUser.syncUser(message.author, message.member, channel, guild, roomID) + } else { // well, good enough... + senderMxid = await registerUser.ensureSimJoined(message.author, roomID) } const events = await messageToEvent.messageToEvent(message, guild, {}, {api}) diff --git a/src/d2m/converters/user-to-mxid.js b/src/d2m/converters/user-to-mxid.js index a619b36..3d7d834 100644 --- a/src/d2m/converters/user-to-mxid.js +++ b/src/d2m/converters/user-to-mxid.js @@ -60,7 +60,7 @@ function* generateLocalpartAlternatives(preferences) { */ function userToSimName(user) { if (!SPECIAL_USER_MAPPINGS.has(user.id)) { // skip this check for known special users - assert.notEqual(user.discriminator, "0000", `cannot create user for a webhook: ${JSON.stringify(user)}`) + if (user.discriminator === "0000") return "webhook" } // 1. Is sim user already registered?