diff --git a/src/d2m/actions/register-user.js b/src/d2m/actions/register-user.js index a545b6d..530ce6d 100644 --- a/src/d2m/actions/register-user.js +++ b/src/d2m/actions/register-user.js @@ -211,14 +211,7 @@ async function syncUser(user, member, channel, guild, roomID) { // Update room member state await api.sendState(roomID, "m.room.member", mxid, content, mxid) // Update power levels (only if we can actually access the member roles) - /** @type {Ty.Event.M_Power_Levels} */ - const powerLevelsStateContent = await api.getStateEvent(roomID, "m.room.power_levels", "") - const oldPowerLevel = powerLevelsStateContent.users?.[mxid] || powerLevelsStateContent.events_default || 0 - mixin(powerLevelsStateContent, {users: {[mxid]: powerLevel}}) - if (powerLevel === powerLevelsStateContent.events_default || 0) delete powerLevelsStateContent.users?.[mxid] // keep the event compact - const botPowerLevel = powerLevelsStateContent.users?.[`@${reg.sender_localpart}:${reg.ooye.server_name}`] || 100 - const sendPowerLevelAs = oldPowerLevel === botPowerLevel ? mxid : undefined // bridge bot can't demote equal power users, so do this action as themselves - await api.sendState(roomID, "m.room.power_levels", "", powerLevelsStateContent, sendPowerLevelAs) + await api.setUserPower(roomID, mxid, powerLevel) // Update cached hash db.prepare("UPDATE sim_member SET hashed_profile_content = ? WHERE room_id = ? AND mxid = ?").run(currentHash, roomID, mxid) } diff --git a/src/d2m/actions/register-user.test.js b/src/d2m/actions/register-user.test.js index f1934cf..13971b3 100644 --- a/src/d2m/actions/register-user.test.js +++ b/src/d2m/actions/register-user.test.js @@ -117,3 +117,10 @@ test("member2power: can manage channels = 100", async t => { }, data.guild.data_horde, data.channel.saving_the_world) t.equal(power, 100) }) + +test("member2power: pathfinder use case", async t => { + const power = _memberToPowerLevel(data.user.jerassicore, { + roles: ["1235396773510647810", "1359752622130593802", "1249165855632265267", "1380768596929806356", "1380756348190462015"] + }, data.guild.pathfinder, data.channel.character_art) + t.equal(power, 50) +}) diff --git a/src/matrix/api.js b/src/matrix/api.js index 1e3f607..e913d0d 100644 --- a/src/matrix/api.js +++ b/src/matrix/api.js @@ -308,21 +308,29 @@ async function profileSetAvatarUrl(mxid, avatar_url) { * Set a user's power level within a room. * @param {string} roomID * @param {string} mxid - * @param {number} power + * @param {number} newPower */ -async function setUserPower(roomID, mxid, power) { +async function setUserPower(roomID, mxid, newPower) { assert(roomID[0] === "!") assert(mxid[0] === "@") // Yes there's no shortcut https://github.com/matrix-org/matrix-appservice-bridge/blob/2334b0bae28a285a767fe7244dad59f5a5963037/src/components/intent.ts#L352 - const powerLevels = await getStateEvent(roomID, "m.room.power_levels", "") - powerLevels.users = powerLevels.users || {} - if (power != null) { - powerLevels.users[mxid] = power + const power = await getStateEvent(roomID, "m.room.power_levels", "") + power.users = power.users || {} + + // Bridge bot can't demote equal power users, so need to decide which user will send the event + const oldPowerLevel = power.users?.[mxid] || power.events_default || 0 + const botPowerLevel = power.users?.[`@${reg.sender_localpart}:${reg.ooye.server_name}`] || 100 + const eventSender = oldPowerLevel >= botPowerLevel ? mxid : undefined + + // Update the event content + if (newPower == null || newPower === (power.events_default || 0)) { + delete power.users[mxid] } else { - delete powerLevels.users[mxid] + power.users[mxid] = newPower } - await sendState(roomID, "m.room.power_levels", "", powerLevels) - return powerLevels + + await sendState(roomID, "m.room.power_levels", "", power, eventSender) + return power } /** diff --git a/test/data.js b/test/data.js index f460f88..a8ff8a8 100644 --- a/test/data.js +++ b/test/data.js @@ -63,6 +63,40 @@ module.exports = { last_message_id: "1335828749479837750", id: "665310973967597573", guild_id: "665289423482519565" + }, + character_art: { + version: 1749274266694, + type: 0, + topic: null, + rate_limit_per_user: 0, + position: 22, + permission_overwrites: [ + { + type: 0, + id: "1235396773510647810", + deny: "0", + allow: "3072" + }, + { + type: 0, + id: "1236581109391949875", + deny: "0", + allow: "0" + }, + { + type: 0, + id: "1234728422044074064", + deny: "3072", + allow: "309237645312" + } + ], + parent_id: "1234730744291528714", + nsfw: false, + name: "character-art", + last_message_id: "1384358176106872924", + id: "1235072132095021096", + flags: 0, + guild_id: "1234728422044074064" } }, room: { @@ -442,6 +476,601 @@ module.exports = { version: 1717720047590, emojis: [], presences: [] + }, + pathfinder: { + activity_instances: [], + max_video_channel_users: 25, + mfa_level: 0, + owner_id: "182266888003256320", + stage_instances: [], + profile: null, + rules_channel_id: null, + splash: null, + inventory_settings: null, + max_members: 25000000, + icon: "ec42ae174a7c246568da98983b611f64", + safety_alerts_channel_id: null, + latest_onboarding_question_id: null, + id: "1234728422044074064", + name: "Hub Pathfinder", + embedded_activities: [], + banner: null, + hub_type: null, + threads: [], + lazy: true, + system_channel_id: "1234728422475829318", + member_count: 21, + region: "deprecated", + description: null, + premium_features: null, + verification_level: 0, + unavailable: false, + stickers: [], + application_command_counts: {}, + roles: [ + { + version: 1741255049095, + unicode_emoji: null, + tags: {}, + position: 0, + permissions: "2173706675146305", + name: "@everyone", + mentionable: false, + managed: false, + id: "1234728422044074064", + icon: null, + hoist: false, + flags: 0, + colors: { tertiary_color: null, secondary_color: null, primary_color: 0 }, + color: 0 + }, + { + version: 1749271325117, + unicode_emoji: null, + tags: { bot_id: "684280192553844747" }, + position: 8, + permissions: "1610883072", + name: "Matrix Bridge", + mentionable: false, + managed: true, + id: "1235117664326783049", + icon: null, + hoist: false, + flags: 0, + colors: { tertiary_color: null, secondary_color: null, primary_color: 0 }, + color: 0 + }, + { + version: 1749271325132, + unicode_emoji: null, + tags: {}, + position: 12, + permissions: "0", + name: "Tuesday", + mentionable: false, + managed: false, + id: "1235396773510647810", + icon: null, + hoist: false, + flags: 0, + colors: { tertiary_color: null, secondary_color: null, primary_color: 0 }, + color: 0 + }, + { + version: 1749271325129, + unicode_emoji: null, + tags: {}, + position: 11, + permissions: "0", + name: "Thursday", + mentionable: false, + managed: false, + id: "1235397020919926844", + icon: null, + hoist: false, + flags: 0, + colors: { tertiary_color: null, secondary_color: null, primary_color: 0 }, + color: 0 + }, + { + version: 1749271325174, + unicode_emoji: null, + tags: {}, + position: 20, + permissions: "0", + name: "Fighter", + mentionable: false, + managed: false, + id: "1236579627615518720", + icon: null, + hoist: false, + flags: 0, + colors: { + tertiary_color: null, + secondary_color: null, + primary_color: 12657443 + }, + color: 12657443 + }, + { + version: 1749271325189, + unicode_emoji: null, + tags: {}, + position: 24, + permissions: "0", + name: "Bard", + mentionable: false, + managed: false, + id: "1236579780544036904", + icon: null, + hoist: false, + flags: 0, + colors: { + tertiary_color: null, + secondary_color: null, + primary_color: 12468701 + }, + color: 12468701 + }, + { + version: 1749271325179, + unicode_emoji: null, + tags: {}, + position: 22, + permissions: "0", + name: "Cleric", + mentionable: false, + managed: false, + id: "1236579861997555763", + icon: null, + hoist: false, + flags: 0, + colors: { + tertiary_color: null, + secondary_color: null, + primary_color: 14186005 + }, + color: 14186005 + }, + { + version: 1749271325138, + unicode_emoji: null, + tags: {}, + position: 14, + permissions: "0", + name: "Wizard", + mentionable: false, + managed: false, + id: "1236579900731822110", + icon: null, + hoist: false, + flags: 0, + colors: { + tertiary_color: null, + secondary_color: null, + primary_color: 3106806 + }, + color: 3106806 + }, + { + version: 1749271325176, + unicode_emoji: null, + tags: {}, + position: 21, + permissions: "0", + name: "Druid", + mentionable: false, + managed: false, + id: "1236579988254232606", + icon: null, + hoist: false, + flags: 0, + colors: { + tertiary_color: null, + secondary_color: null, + primary_color: 8248698 + }, + color: 8248698 + }, + { + version: 1749271325147, + unicode_emoji: null, + tags: {}, + position: 15, + permissions: "0", + name: "Witch", + mentionable: false, + managed: false, + id: "1236580304232255581", + icon: null, + hoist: false, + flags: 0, + colors: { + tertiary_color: null, + secondary_color: null, + primary_color: 1737848 + }, + color: 1737848 + }, + { + version: 1749271325206, + unicode_emoji: null, + tags: {}, + position: 28, + permissions: "8", + name: "DM", + mentionable: false, + managed: false, + id: "1236581109391949875", + icon: null, + hoist: false, + flags: 0, + colors: { + tertiary_color: null, + secondary_color: null, + primary_color: 6507441 + }, + color: 6507441 + }, + { + version: 1749271325156, + unicode_emoji: null, + tags: {}, + position: 17, + permissions: "0", + name: "Ranger", + mentionable: false, + managed: false, + id: "1240571725914312825", + icon: null, + hoist: false, + flags: 0, + colors: { + tertiary_color: null, + secondary_color: null, + primary_color: 2067276 + }, + color: 2067276 + }, + { + version: 1749271325151, + unicode_emoji: null, + tags: {}, + position: 16, + permissions: "0", + name: "Rogue", + mentionable: false, + managed: false, + id: "1249165855632265267", + icon: null, + hoist: false, + flags: 0, + colors: { + tertiary_color: null, + secondary_color: null, + primary_color: 9936031 + }, + color: 9936031 + }, + { + version: 1749271325123, + unicode_emoji: null, + tags: {}, + position: 10, + permissions: "0", + name: "Questions Ping!", + mentionable: false, + managed: false, + id: "1249167820571541534", + icon: null, + hoist: false, + flags: 0, + colors: { + tertiary_color: null, + secondary_color: null, + primary_color: 13297400 + }, + color: 13297400 + }, + { + version: 1749271325198, + unicode_emoji: null, + tags: {}, + position: 25, + permissions: "0", + name: "Barbarian", + mentionable: false, + managed: false, + id: "1344484288241991730", + icon: null, + hoist: false, + flags: 0, + colors: { + tertiary_color: null, + secondary_color: null, + primary_color: 8145454 + }, + color: 8145454 + }, + { + version: 1749271325200, + unicode_emoji: null, + tags: {}, + position: 26, + permissions: "0", + name: "Alchemist", + mentionable: false, + managed: false, + id: "1352190431944900628", + icon: null, + hoist: false, + flags: 0, + colors: { + tertiary_color: null, + secondary_color: null, + primary_color: 15844367 + }, + color: 15844367 + }, + { + version: 1749271325168, + unicode_emoji: null, + tags: {}, + position: 19, + permissions: "0", + name: "Investigator", + mentionable: false, + managed: false, + id: "1353890353391866028", + icon: null, + hoist: false, + flags: 0, + colors: { + tertiary_color: null, + secondary_color: null, + primary_color: 10068223 + }, + color: 10068223 + }, + { + version: 1749271325134, + unicode_emoji: null, + tags: {}, + position: 13, + permissions: "0", + name: "Monday", + mentionable: false, + managed: false, + id: "1359752622130593802", + icon: null, + hoist: false, + flags: 0, + colors: { tertiary_color: null, secondary_color: null, primary_color: 0 }, + color: 0 + }, + { + version: 1749271325162, + unicode_emoji: null, + tags: {}, + position: 18, + permissions: "0", + name: "Monk", + mentionable: false, + managed: false, + id: "1359753361963880590", + icon: null, + hoist: false, + flags: 0, + colors: { + tertiary_color: null, + secondary_color: null, + primary_color: 3447003 + }, + color: 3447003 + }, + { + version: 1749271325183, + unicode_emoji: null, + tags: {}, + position: 23, + permissions: "0", + name: "Champion", + mentionable: false, + managed: false, + id: "1359753472186122320", + icon: null, + hoist: false, + flags: 0, + colors: { + tertiary_color: null, + secondary_color: null, + primary_color: 15277667 + }, + color: 15277667 + }, + { + version: 1749271325114, + unicode_emoji: null, + tags: { bot_id: "431544605209788416" }, + position: 7, + permissions: "275415166016", + name: "Tupperbox", + mentionable: false, + managed: true, + id: "1377128320814153862", + icon: null, + hoist: false, + flags: 0, + colors: { tertiary_color: null, secondary_color: null, primary_color: 0 }, + color: 0 + }, + { + version: 1749271325120, + unicode_emoji: null, + tags: {}, + position: 9, + permissions: "0", + name: "PbD ping", + mentionable: false, + managed: false, + id: "1377139953510907995", + icon: null, + hoist: false, + flags: 0, + colors: { tertiary_color: null, secondary_color: null, primary_color: 0 }, + color: 0 + }, + { + version: 1749271325109, + unicode_emoji: null, + tags: { bot_id: "644942473315090434" }, + position: 6, + permissions: "535529122897", + name: "RPG Sage", + mentionable: false, + managed: true, + id: "1377144599310503959", + icon: null, + hoist: false, + flags: 0, + colors: { tertiary_color: null, secondary_color: null, primary_color: 0 }, + color: 0 + }, + { + version: 1749271325106, + unicode_emoji: null, + tags: { bot_id: "572698679618568193" }, + position: 5, + permissions: "278528", + name: "Dicecord", + mentionable: false, + managed: true, + id: "1378726921990307974", + icon: null, + hoist: false, + flags: 0, + colors: { tertiary_color: null, secondary_color: null, primary_color: 0 }, + color: 0 + }, + { + version: 1749271325203, + unicode_emoji: null, + tags: { bot_id: "443545183997657120" }, + position: 27, + permissions: "2097540216", + name: "ChannelBot", + mentionable: false, + managed: true, + id: "1380744875108204658", + icon: null, + hoist: false, + flags: 0, + colors: { tertiary_color: null, secondary_color: null, primary_color: 0 }, + color: 0 + }, + { + version: 1749271325101, + unicode_emoji: null, + tags: {}, + position: 4, + permissions: "0", + name: "Play-by-Discord", + mentionable: false, + managed: false, + id: "1380748596537720872", + icon: null, + hoist: false, + flags: 0, + colors: { + tertiary_color: null, + secondary_color: null, + primary_color: 16377559 + }, + color: 16377559 + }, + { + version: 1749271325098, + unicode_emoji: null, + tags: {}, + position: 3, + permissions: "0", + name: "Boredom Busters", + mentionable: false, + managed: false, + id: "1380756348190462015", + icon: null, + hoist: false, + flags: 0, + colors: { + tertiary_color: null, + secondary_color: null, + primary_color: 14542591 + }, + color: 14542591 + }, + { + version: 1749271361998, + unicode_emoji: null, + tags: {}, + position: 1, + permissions: "0", + name: "Bots", + mentionable: false, + managed: false, + id: "1380767647578460311", + icon: null, + hoist: true, + flags: 0, + colors: { tertiary_color: null, secondary_color: null, primary_color: 0 }, + color: 0 + }, + { + version: 1749271362001, + unicode_emoji: null, + tags: {}, + position: 2, + permissions: "0", + name: "Players", + mentionable: false, + managed: false, + id: "1380768596929806356", + icon: null, + hoist: true, + flags: 0, + colors: { tertiary_color: null, secondary_color: null, primary_color: 0 }, + color: 0 + } + ], + vanity_url_code: null, + afk_timeout: 300, + premium_tier: 0, + joined_at: "2024-05-01T06:36:38.605000+00:00", + public_updates_channel_id: null, + premium_subscription_count: 0, + soundboard_sounds: [], + home_header: null, + discovery_splash: null, + guild_scheduled_events: [], + system_channel_flags: 0, + preferred_locale: "en-US", + large: false, + explicit_content_filter: 0, + moderator_reporting: null, + features: [ + "TIERLESS_BOOSTING_SYSTEM_MESSAGE", + "ACTIVITY_FEED_DISABLED_BY_USER" + ], + version: 1750145431881, + owner_configured_content_level: null, + voice_states: [], + default_message_notifications: 1, + application_id: null, + incidents_data: null, + nsfw_level: 0, + premium_progress_bar_enabled: false, + afk_channel_id: null, + max_stage_video_channel_users: 50, + nsfw: false } }, user: { @@ -459,6 +1088,19 @@ module.exports = { global_name: "Clyde", avatar_decoration_data: null, banner_color: null + }, + jerassicore: { + username: "ser_jurassicore", + public_flags: 0, + primary_guild: null, + id: "493801948345139202", + global_name: "Jurassicore", + display_name_styles: null, + discriminator: "0", + collectibles: null, + clan: null, + avatar_decoration_data: null, + avatar: "2a4fa0de3aaea30f457ed7bba64176aa" } }, member: {