Update global profiles for sims
This commit is contained in:
@@ -152,16 +152,9 @@ async function syncUser(messageID, author, roomID, shouldActuallySync) {
|
|||||||
const mxid = await ensureSimJoined(pkMessage, roomID)
|
const mxid = await ensureSimJoined(pkMessage, roomID)
|
||||||
|
|
||||||
if (shouldActuallySync) {
|
if (shouldActuallySync) {
|
||||||
// Build current profile data
|
// Build current profile data and sync if the hash has changed
|
||||||
const content = await memberToStateContent(pkMessage, author)
|
const content = await memberToStateContent(pkMessage, author)
|
||||||
const currentHash = registerUser._hashProfileContent(content, 0)
|
await registerUser._sendSyncUser(roomID, mxid, content, null)
|
||||||
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)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return mxid
|
return mxid
|
||||||
|
|||||||
@@ -22,6 +22,8 @@ let hasher = null
|
|||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
require("xxhash-wasm")().then(h => hasher = h)
|
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.
|
* A sim is an account that is being simulated by the bridge to copy events from the other side.
|
||||||
* @param {DiscordTypes.APIUser} user
|
* @param {DiscordTypes.APIUser} user
|
||||||
@@ -97,6 +99,23 @@ async function ensureSimJoined(user, roomID) {
|
|||||||
return mxid
|
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 {DiscordTypes.APIUser} user
|
||||||
* @param {Omit<DiscordTypes.APIGuildMember, "user"> | undefined} member
|
* @param {Omit<DiscordTypes.APIGuildMember, "user"> | undefined} member
|
||||||
@@ -200,21 +219,45 @@ async function syncUser(user, member, channel, guild, roomID) {
|
|||||||
const mxid = await ensureSimJoined(user, roomID)
|
const mxid = await ensureSimJoined(user, roomID)
|
||||||
const content = await memberToStateContent(user, member, guild.id)
|
const content = await memberToStateContent(user, member, guild.id)
|
||||||
const powerLevel = memberToPowerLevel(user, member, guild, channel)
|
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()
|
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
|
// only do the actual sync if the hash has changed since we last looked
|
||||||
const hashHasChanged = existingHash !== currentHash
|
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
|
// always okay to add new data. for overwriting, restrict based on options.allowOverwrite, if present
|
||||||
const wouldOverwritePreExisting = existingHash && !member
|
const overwriteOkay = !existingHash || (options?.allowOverwrite ?? true)
|
||||||
if (hashHasChanged && !wouldOverwritePreExisting) {
|
if (hashHasChanged && overwriteOkay) {
|
||||||
|
const actions = []
|
||||||
// Update room member state
|
// 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
|
// 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
|
// Update cached hash
|
||||||
db.prepare("UPDATE sim_member SET hashed_profile_content = ? WHERE room_id = ? AND mxid = ?").run(currentHash, roomID, mxid)
|
db.prepare("UPDATE sim_member SET hashed_profile_content = ? WHERE room_id = ? AND mxid = ?").run(currentHash, roomID, mxid)
|
||||||
}
|
}
|
||||||
return mxid
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -251,5 +294,7 @@ 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._sendSyncUser = _sendSyncUser
|
||||||
module.exports.syncAllUsersInRoom = syncAllUsersInRoom
|
module.exports.syncAllUsersInRoom = syncAllUsersInRoom
|
||||||
module.exports._memberToPowerLevel = memberToPowerLevel
|
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)
|
const mxid = await ensureSimJoined(fakeUserID, author, roomID)
|
||||||
|
|
||||||
if (shouldActuallySync) {
|
if (shouldActuallySync) {
|
||||||
// Build current profile data
|
// Build current profile data and sync if the hash has changed
|
||||||
const content = await authorToStateContent(author)
|
const content = await authorToStateContent(author)
|
||||||
const currentHash = registerUser._hashProfileContent(content, 0)
|
await registerUser._sendSyncUser(roomID, mxid, content, null)
|
||||||
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)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return mxid
|
return mxid
|
||||||
|
|||||||
+27
-4
@@ -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
|
displayname
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
async function profileSetAvatarUrl(mxid, avatar_url) {
|
/**
|
||||||
await mreq.mreq("PUT", path(`/client/v3/profile/${mxid}/avatar_url`, mxid), {
|
* @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
|
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}`)
|
return mreq.mreq("GET", `/client/v3/profile/${mxid}`)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function versions() {
|
||||||
|
return mreq.mreq("GET", "/client/versions")
|
||||||
|
}
|
||||||
|
|
||||||
module.exports.path = path
|
module.exports.path = path
|
||||||
module.exports.register = register
|
module.exports.register = register
|
||||||
module.exports.createRoom = createRoom
|
module.exports.createRoom = createRoom
|
||||||
@@ -526,3 +548,4 @@ module.exports.getAccountData = getAccountData
|
|||||||
module.exports.setAccountData = setAccountData
|
module.exports.setAccountData = setAccountData
|
||||||
module.exports.setPresence = setPresence
|
module.exports.setPresence = setPresence
|
||||||
module.exports.getProfile = getProfile
|
module.exports.getProfile = getProfile
|
||||||
|
module.exports.versions = versions
|
||||||
|
|||||||
Reference in New Issue
Block a user