Sync webhook profiles to Matrix

This commit is contained in:
Cadence Ember 2024-09-26 02:34:30 +12:00
parent d6de57f0c3
commit 419d61cf82
3 changed files with 39 additions and 10 deletions

View file

@ -208,6 +208,34 @@ async function syncUser(user, member, channel, guild, roomID) {
return mxid 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<string>} 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 * @param {string} roomID
*/ */
@ -244,4 +272,5 @@ module.exports._hashProfileContent = _hashProfileContent
module.exports.ensureSim = ensureSim module.exports.ensureSim = ensureSim
module.exports.ensureSimJoined = ensureSimJoined module.exports.ensureSimJoined = ensureSimJoined
module.exports.syncUser = syncUser module.exports.syncUser = syncUser
module.exports.syncWebhook = syncWebhook
module.exports.syncAllUsersInRoom = syncAllUsersInRoom module.exports.syncAllUsersInRoom = syncAllUsersInRoom

View file

@ -28,20 +28,20 @@ async function sendMessage(message, channel, guild, row) {
const roomID = await createRoom.ensureRoom(message.channel_id) const roomID = await createRoom.ensureRoom(message.channel_id)
let senderMxid = null let senderMxid = null
if (!dUtils.isWebhookMessage(message)) { if (row && row.speedbump_webhook_id === message.webhook_id) {
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) {
// Handle the PluralKit public instance // Handle the PluralKit public instance
if (row.speedbump_id === "466378653216014359") { if (row.speedbump_id === "466378653216014359") {
const pkMessage = await registerPkUser.fetchMessage(message.id) const pkMessage = await registerPkUser.fetchMessage(message.id)
senderMxid = await registerPkUser.syncUser(message.author, pkMessage, roomID) 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}) const events = await messageToEvent.messageToEvent(message, guild, {}, {api})

View file

@ -60,7 +60,7 @@ function* generateLocalpartAlternatives(preferences) {
*/ */
function userToSimName(user) { function userToSimName(user) {
if (!SPECIAL_USER_MAPPINGS.has(user.id)) { // skip this check for known special users 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? // 1. Is sim user already registered?