Update global profiles for sims
This commit is contained in:
@@ -151,16 +151,9 @@ async function syncUser(messageID, author, roomID, shouldActuallySync) {
|
||||
const mxid = await ensureSimJoined(pkMessage, roomID)
|
||||
|
||||
if (shouldActuallySync) {
|
||||
// Build current profile data
|
||||
// Build current profile data and sync if the hash has changed
|
||||
const content = await memberToStateContent(pkMessage, author)
|
||||
const currentHash = registerUser._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) {
|
||||
await api.sendState(roomID, "m.room.member", mxid, content, mxid)
|
||||
db.prepare("UPDATE sim_member SET hashed_profile_content = ? WHERE room_id = ? AND mxid = ?").run(currentHash, roomID, mxid)
|
||||
}
|
||||
await registerUser._sendSyncUser(roomID, mxid, content, null)
|
||||
}
|
||||
|
||||
return mxid
|
||||
|
||||
@@ -23,6 +23,8 @@ let hasher = null
|
||||
// @ts-ignore
|
||||
require("xxhash-wasm")().then(h => hasher = h)
|
||||
|
||||
const supportsMsc4069 = api.versions().then(v => !!v?.unstable_features?.["org.matrix.msc4069"]).catch(() => false)
|
||||
|
||||
/**
|
||||
* A sim is an account that is being simulated by the bridge to copy events from the other side.
|
||||
* @param {DiscordTypes.APIUser} user
|
||||
@@ -98,6 +100,23 @@ async function ensureSimJoined(user, roomID) {
|
||||
return mxid
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {DiscordTypes.APIUser} user
|
||||
*/
|
||||
async function userToGlobalProfile(user) {
|
||||
const globalProfile = {}
|
||||
|
||||
globalProfile.displayname = user.username
|
||||
if (user.global_name) globalProfile.displayname = user.global_name
|
||||
|
||||
if (user.avatar) {
|
||||
const avatarPath = file.userAvatar(user) // the user avatar only
|
||||
globalProfile.avatar_url = await file.uploadDiscordFileToMxc(avatarPath)
|
||||
}
|
||||
|
||||
return globalProfile
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {DiscordTypes.APIUser} user
|
||||
* @param {Omit<DiscordTypes.APIGuildMember, "user"> | undefined} member
|
||||
@@ -201,21 +220,45 @@ async function syncUser(user, member, channel, guild, roomID) {
|
||||
const mxid = await ensureSimJoined(user, roomID)
|
||||
const content = await memberToStateContent(user, member, guild.id)
|
||||
const powerLevel = memberToPowerLevel(user, member, guild, channel)
|
||||
const currentHash = _hashProfileContent(content, powerLevel)
|
||||
await _sendSyncUser(roomID, mxid, content, powerLevel, {
|
||||
// do not overwrite pre-existing data if we already have data and `member` is not accessible, because this would replace good data with bad data
|
||||
allowOverwrite: !!member,
|
||||
globalProfile: await userToGlobalProfile(user)
|
||||
})
|
||||
return mxid
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} roomID
|
||||
* @param {string} mxid
|
||||
* @param {{displayname: string, avatar_url?: string}} content
|
||||
* @param {number | null} powerLevel
|
||||
* @param {{allowOverwrite?: boolean, globalProfile?: {displayname: string, avatar_url?: string}}} [options]
|
||||
*/
|
||||
async function _sendSyncUser(roomID, mxid, content, powerLevel, options) {
|
||||
const currentHash = _hashProfileContent(content, powerLevel ?? 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
|
||||
const hashHasChanged = existingHash !== currentHash
|
||||
// however, do not overwrite pre-existing data if we already have data and `member` is not accessible, because this would replace good data with bad data
|
||||
const wouldOverwritePreExisting = existingHash && !member
|
||||
if (hashHasChanged && !wouldOverwritePreExisting) {
|
||||
// always okay to add new data. for overwriting, restrict based on options.allowOverwrite, if present
|
||||
const overwriteOkay = !existingHash || (options?.allowOverwrite ?? true)
|
||||
if (hashHasChanged && overwriteOkay) {
|
||||
const actions = []
|
||||
// Update room member state
|
||||
await api.sendState(roomID, "m.room.member", mxid, content, mxid)
|
||||
actions.push(api.sendState(roomID, "m.room.member", mxid, content, mxid))
|
||||
// Update power levels
|
||||
await api.setUserPower(roomID, mxid, powerLevel)
|
||||
if (powerLevel != null) {
|
||||
actions.push(api.setUserPower(roomID, mxid, powerLevel))
|
||||
}
|
||||
// Update global profile (if supported by server)
|
||||
if (await supportsMsc4069) {
|
||||
actions.push(api.profileSetDisplayname(mxid, options?.globalProfile?.displayname || content.displayname, true))
|
||||
actions.push(api.profileSetAvatarUrl(mxid, options?.globalProfile?.avatar_url || content.avatar_url, true))
|
||||
}
|
||||
await Promise.all(actions)
|
||||
// Update cached hash
|
||||
db.prepare("UPDATE sim_member SET hashed_profile_content = ? WHERE room_id = ? AND mxid = ?").run(currentHash, roomID, mxid)
|
||||
}
|
||||
return mxid
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -254,5 +297,7 @@ module.exports._hashProfileContent = _hashProfileContent
|
||||
module.exports.ensureSim = ensureSim
|
||||
module.exports.ensureSimJoined = ensureSimJoined
|
||||
module.exports.syncUser = syncUser
|
||||
module.exports._sendSyncUser = _sendSyncUser
|
||||
module.exports.syncAllUsersInRoom = syncAllUsersInRoom
|
||||
module.exports._memberToPowerLevel = memberToPowerLevel
|
||||
module.exports.supportsMsc4069 = supportsMsc4069
|
||||
|
||||
@@ -128,16 +128,9 @@ async function syncUser(author, roomID, shouldActuallySync) {
|
||||
const mxid = await ensureSimJoined(fakeUserID, author, roomID)
|
||||
|
||||
if (shouldActuallySync) {
|
||||
// Build current profile data
|
||||
// Build current profile data and sync if the hash has changed
|
||||
const content = await authorToStateContent(author)
|
||||
const currentHash = registerUser._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) {
|
||||
await api.sendState(roomID, "m.room.member", mxid, content, mxid)
|
||||
db.prepare("UPDATE sim_member SET hashed_profile_content = ? WHERE room_id = ? AND mxid = ?").run(currentHash, roomID, mxid)
|
||||
}
|
||||
await registerUser._sendSyncUser(roomID, mxid, content, null)
|
||||
}
|
||||
|
||||
return mxid
|
||||
|
||||
@@ -317,16 +317,34 @@ async function sendTyping(roomID, isTyping, mxid, duration) {
|
||||
})
|
||||
}
|
||||
|
||||
async function profileSetDisplayname(mxid, displayname) {
|
||||
await mreq.mreq("PUT", path(`/client/v3/profile/${mxid}/displayname`, mxid), {
|
||||
/**
|
||||
* @param {string} mxid
|
||||
* @param {string} displayname
|
||||
* @param {boolean} [inhibitPropagate]
|
||||
*/
|
||||
async function profileSetDisplayname(mxid, displayname, inhibitPropagate) {
|
||||
const params = {}
|
||||
if (inhibitPropagate) params["org.matrix.msc4069.propagate"] = false
|
||||
await mreq.mreq("PUT", path(`/client/v3/profile/${mxid}/displayname`, mxid, params), {
|
||||
displayname
|
||||
})
|
||||
}
|
||||
|
||||
async function profileSetAvatarUrl(mxid, avatar_url) {
|
||||
await mreq.mreq("PUT", path(`/client/v3/profile/${mxid}/avatar_url`, mxid), {
|
||||
avatar_url
|
||||
})
|
||||
/**
|
||||
* @param {string} mxid
|
||||
* @param {string} avatar_url
|
||||
* @param {boolean} [inhibitPropagate]
|
||||
*/
|
||||
async function profileSetAvatarUrl(mxid, avatar_url, inhibitPropagate) {
|
||||
const params = {}
|
||||
if (inhibitPropagate) params["org.matrix.msc4069.propagate"] = false
|
||||
if (avatar_url) {
|
||||
await mreq.mreq("PUT", path(`/client/v3/profile/${mxid}/avatar_url`, mxid, params), {
|
||||
avatar_url
|
||||
})
|
||||
} else {
|
||||
await mreq.mreq("DELETE", path(`/client/v3/profile/${mxid}/avatar_url`, mxid, params))
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -490,6 +508,10 @@ function getProfile(mxid) {
|
||||
return mreq.mreq("GET", `/client/v3/profile/${mxid}`)
|
||||
}
|
||||
|
||||
function versions() {
|
||||
return mreq.mreq("GET", "/client/versions")
|
||||
}
|
||||
|
||||
module.exports.path = path
|
||||
module.exports.register = register
|
||||
module.exports.createRoom = createRoom
|
||||
@@ -526,3 +548,4 @@ module.exports.getAccountData = getAccountData
|
||||
module.exports.setAccountData = setAccountData
|
||||
module.exports.setPresence = setPresence
|
||||
module.exports.getProfile = getProfile
|
||||
module.exports.versions = versions
|
||||
|
||||
Reference in New Issue
Block a user