Copy power levels from spaces to new rooms
This commit is contained in:
parent
ee266f844a
commit
7afe3e7591
4 changed files with 142 additions and 12 deletions
|
@ -2,6 +2,7 @@
|
|||
|
||||
const assert = require("assert").strict
|
||||
const DiscordTypes = require("discord-api-types/v10")
|
||||
const Ty = require("../../types")
|
||||
const reg = require("../../matrix/read-registration")
|
||||
|
||||
const passthrough = require("../../passthrough")
|
||||
|
@ -89,8 +90,9 @@ function convertNameAndTopic(channel, guild, customName) {
|
|||
* Async because it may create the guild and/or upload the guild icon to mxc.
|
||||
* @param {DiscordTypes.APIGuildTextChannel | DiscordTypes.APIThreadChannel} channel
|
||||
* @param {DiscordTypes.APIGuild} guild
|
||||
* @param {{api: {getStateEvent: typeof api.getStateEvent}}} di simple-as-nails dependency injection for the matrix API
|
||||
*/
|
||||
async function channelToKState(channel, guild) {
|
||||
async function channelToKState(channel, guild, di) {
|
||||
// @ts-ignore
|
||||
const parentChannel = discord.channels.get(channel.parent_id)
|
||||
/** Used for membership/permission checks. */
|
||||
|
@ -142,6 +144,11 @@ async function channelToKState(channel, guild) {
|
|||
const everyoneCanMentionEveryone = utils.hasAllPermissions(everyonePermissions, ["MentionEveryone"])
|
||||
|
||||
const globalAdmins = select("member_power", ["mxid", "power_level"], {room_id: "*"}).all()
|
||||
const globalAdminPower = globalAdmins.reduce((a, c) => (a[c.mxid] = c.power_level, a), {})
|
||||
|
||||
/** @type {Ty.Event.M_Power_Levels} */
|
||||
const spacePowerEvent = await di.api.getStateEvent(guildSpaceID, "m.room.power_levels", "")
|
||||
const spacePower = spacePowerEvent.users
|
||||
|
||||
const channelKState = {
|
||||
"m.room.name/": {name: convertedName},
|
||||
|
@ -162,7 +169,7 @@ async function channelToKState(channel, guild) {
|
|||
notifications: {
|
||||
room: everyoneCanMentionEveryone ? 0 : 20
|
||||
},
|
||||
users: globalAdmins.reduce((a, c) => (a[c.mxid] = c.power_level, a), {})
|
||||
users: {...spacePower, ...globalAdminPower}
|
||||
},
|
||||
"chat.schildi.hide_ui/read_receipts": {
|
||||
hidden: true
|
||||
|
@ -311,7 +318,7 @@ async function _syncRoom(channelID, shouldActuallySync) {
|
|||
|
||||
if (!existing) {
|
||||
const creation = (async () => {
|
||||
const {spaceID, privacyLevel, channelKState} = await channelToKState(channel, guild)
|
||||
const {spaceID, privacyLevel, channelKState} = await channelToKState(channel, guild, {api})
|
||||
const roomID = await createRoom(channel, guild, spaceID, channelKState, privacyLevel)
|
||||
inflightRoomCreate.delete(channelID) // OK to release inflight waiters now. they will read the correct `existing` row
|
||||
return roomID
|
||||
|
@ -328,7 +335,7 @@ async function _syncRoom(channelID, shouldActuallySync) {
|
|||
|
||||
console.log(`[room sync] to matrix: ${channel.name}`)
|
||||
|
||||
const {spaceID, channelKState} = await channelToKState(channel, guild) // calling this in both branches because we don't want to calculate this if not syncing
|
||||
const {spaceID, channelKState} = await channelToKState(channel, guild, {api}) // calling this in both branches because we don't want to calculate this if not syncing
|
||||
|
||||
// sync channel state to room
|
||||
const roomKState = await roomToKState(roomID)
|
||||
|
|
|
@ -9,45 +9,89 @@ const testData = require("../../test/data")
|
|||
const passthrough = require("../../passthrough")
|
||||
const {db} = passthrough
|
||||
|
||||
|
||||
test("channel2room: discoverable privacy room", async t => {
|
||||
let called = 0
|
||||
async function getStateEvent(roomID, type, key) { // getting power levels from space to apply to room
|
||||
called++
|
||||
t.equal(roomID, "!jjWAGMeQdNrVZSSfvz:cadence.moe")
|
||||
t.equal(type, "m.room.power_levels")
|
||||
t.equal(key, "")
|
||||
return {users: {"@example:matrix.org": 50}}
|
||||
}
|
||||
db.prepare("UPDATE guild_space SET privacy_level = 2").run()
|
||||
t.deepEqual(
|
||||
kstateStripConditionals(await channelToKState(testData.channel.general, testData.guild.general).then(x => x.channelKState)),
|
||||
kstateStripConditionals(await channelToKState(testData.channel.general, testData.guild.general, {api: {getStateEvent}}).then(x => x.channelKState)),
|
||||
Object.assign({}, testData.room.general, {
|
||||
"m.room.guest_access/": {guest_access: "forbidden"},
|
||||
"m.room.join_rules/": {join_rule: "public"},
|
||||
"m.room.history_visibility/": {history_visibility: "world_readable"}
|
||||
"m.room.history_visibility/": {history_visibility: "world_readable"},
|
||||
"m.room.power_levels/": mixin({users: {"@example:matrix.org": 50}}, testData.room.general["m.room.power_levels/"])
|
||||
})
|
||||
)
|
||||
t.equal(called, 1)
|
||||
})
|
||||
|
||||
test("channel2room: linkable privacy room", async t => {
|
||||
let called = 0
|
||||
async function getStateEvent(roomID, type, key) { // getting power levels from space to apply to room
|
||||
called++
|
||||
t.equal(roomID, "!jjWAGMeQdNrVZSSfvz:cadence.moe")
|
||||
t.equal(type, "m.room.power_levels")
|
||||
t.equal(key, "")
|
||||
return {users: {"@example:matrix.org": 50}}
|
||||
}
|
||||
db.prepare("UPDATE guild_space SET privacy_level = 1").run()
|
||||
t.deepEqual(
|
||||
kstateStripConditionals(await channelToKState(testData.channel.general, testData.guild.general).then(x => x.channelKState)),
|
||||
kstateStripConditionals(await channelToKState(testData.channel.general, testData.guild.general, {api: {getStateEvent}}).then(x => x.channelKState)),
|
||||
Object.assign({}, testData.room.general, {
|
||||
"m.room.guest_access/": {guest_access: "forbidden"},
|
||||
"m.room.join_rules/": {join_rule: "public"}
|
||||
"m.room.join_rules/": {join_rule: "public"},
|
||||
"m.room.power_levels/": mixin({users: {"@example:matrix.org": 50}}, testData.room.general["m.room.power_levels/"])
|
||||
})
|
||||
)
|
||||
t.equal(called, 1)
|
||||
})
|
||||
|
||||
test("channel2room: invite-only privacy room", async t => {
|
||||
let called = 0
|
||||
async function getStateEvent(roomID, type, key) { // getting power levels from space to apply to room
|
||||
called++
|
||||
t.equal(roomID, "!jjWAGMeQdNrVZSSfvz:cadence.moe")
|
||||
t.equal(type, "m.room.power_levels")
|
||||
t.equal(key, "")
|
||||
return {users: {"@example:matrix.org": 50}}
|
||||
}
|
||||
db.prepare("UPDATE guild_space SET privacy_level = 0").run()
|
||||
t.deepEqual(
|
||||
kstateStripConditionals(await channelToKState(testData.channel.general, testData.guild.general).then(x => x.channelKState)),
|
||||
testData.room.general
|
||||
kstateStripConditionals(await channelToKState(testData.channel.general, testData.guild.general, {api: {getStateEvent}}).then(x => x.channelKState)),
|
||||
Object.assign({}, testData.room.general, {
|
||||
"m.room.power_levels/": mixin({users: {"@example:matrix.org": 50}}, testData.room.general["m.room.power_levels/"])
|
||||
})
|
||||
)
|
||||
t.equal(called, 1)
|
||||
})
|
||||
|
||||
test("channel2room: room where limited people can mention everyone", async t => {
|
||||
let called = 0
|
||||
async function getStateEvent(roomID, type, key) { // getting power levels from space to apply to room
|
||||
called++
|
||||
t.equal(roomID, "!jjWAGMeQdNrVZSSfvz:cadence.moe")
|
||||
t.equal(type, "m.room.power_levels")
|
||||
t.equal(key, "")
|
||||
return {users: {"@example:matrix.org": 50}}
|
||||
}
|
||||
const limitedGuild = mixin({}, testData.guild.general)
|
||||
limitedGuild.roles[0].permissions = (BigInt(limitedGuild.roles[0].permissions) - 131072n).toString()
|
||||
const limitedRoom = mixin({}, testData.room.general, {"m.room.power_levels/": {notifications: {room: 20}}})
|
||||
const limitedRoom = mixin({}, testData.room.general, {"m.room.power_levels/": {
|
||||
notifications: {room: 20},
|
||||
users: {"@example:matrix.org": 50}
|
||||
}})
|
||||
t.deepEqual(
|
||||
kstateStripConditionals(await channelToKState(testData.channel.general, limitedGuild).then(x => x.channelKState)),
|
||||
kstateStripConditionals(await channelToKState(testData.channel.general, limitedGuild, {api: {getStateEvent}}).then(x => x.channelKState)),
|
||||
limitedRoom
|
||||
)
|
||||
t.equal(called, 1)
|
||||
})
|
||||
|
||||
test("convertNameAndTopic: custom name and topic", t => {
|
||||
|
|
12
matrix/power.test.js
Normal file
12
matrix/power.test.js
Normal file
|
@ -0,0 +1,12 @@
|
|||
// @ts-check
|
||||
|
||||
const {test} = require("supertape")
|
||||
const power = require("./power")
|
||||
|
||||
test("power: get affected rooms", t => {
|
||||
t.deepEqual(power._getAffectedRooms(), [{
|
||||
mxid: "@test_auto_invite:example.org",
|
||||
power_level: 100,
|
||||
room_id: "!kLRqKKUQXcibIMtOpl:cadence.moe",
|
||||
}])
|
||||
})
|
67
test/data.js
67
test/data.js
|
@ -4065,6 +4065,73 @@ module.exports = {
|
|||
guild_id: "372271956562542592"
|
||||
}
|
||||
},
|
||||
reply_with_missing_referenced_message: {
|
||||
type: 19,
|
||||
content: "there must have been 2 different thumbnails used - the other one was this I think: https://lostmediawiki.com/w/images/6/6d/YOUTUBE_HACKED%21.jpg",
|
||||
mentions: [
|
||||
{
|
||||
id: "112816036671184896",
|
||||
username: "accavish",
|
||||
avatar: "0efadd2b09568c89e81f47d321c1db9f",
|
||||
discriminator: "0",
|
||||
public_flags: 0,
|
||||
flags: 0,
|
||||
banner: null,
|
||||
accent_color: null,
|
||||
global_name: "Yuv.yuv",
|
||||
avatar_decoration_data: null,
|
||||
banner_color: null,
|
||||
clan: null
|
||||
}
|
||||
],
|
||||
mention_roles: [],
|
||||
attachments: [],
|
||||
embeds: [
|
||||
{
|
||||
type: "image",
|
||||
url: "https://lostmediawiki.com/w/images/6/6d/YOUTUBE_HACKED%21.jpg",
|
||||
reference_id: "1277081824962809919",
|
||||
thumbnail: {
|
||||
url: "https://lostmediawiki.com/w/images/6/6d/YOUTUBE_HACKED%21.jpg",
|
||||
proxy_url: "https://images-ext-1.discordapp.net/external/DqHSi6Hsvkn8CeYqcpNsgcPun_yykRNdKzyPTLxkrJ8/https/lostmediawiki.com/w/images/6/6d/YOUTUBE_HACKED%2521.jpg",
|
||||
width: 898,
|
||||
height: 459,
|
||||
placeholder: "MPcFLIoEgndse3pydlUHeZSQZw==",
|
||||
placeholder_version: 1
|
||||
}
|
||||
}
|
||||
],
|
||||
timestamp: "2024-08-25T01:47:14.104000+00:00",
|
||||
edited_timestamp: null,
|
||||
flags: 0,
|
||||
components: [],
|
||||
id: "1277081824962809919",
|
||||
channel_id: "112760669178241024",
|
||||
author: {
|
||||
id: "628334893109215263",
|
||||
username: "thecracksoverhead",
|
||||
avatar: "e4eaad082f5ff0359cafa8d3ad5ddd4f",
|
||||
discriminator: "0",
|
||||
public_flags: 0,
|
||||
flags: 0,
|
||||
banner: null,
|
||||
accent_color: null,
|
||||
global_name: "jdl",
|
||||
avatar_decoration_data: null,
|
||||
banner_color: null,
|
||||
clan: null
|
||||
},
|
||||
pinned: false,
|
||||
mention_everyone: false,
|
||||
tts: false,
|
||||
message_reference: {
|
||||
type: 0,
|
||||
channel_id: "112760669178241024",
|
||||
message_id: "1277081326008143934",
|
||||
guild_id: "112760669178241024"
|
||||
},
|
||||
position: 0
|
||||
}
|
||||
},
|
||||
interaction_message: {
|
||||
thinking_interaction_without_bot_user: {
|
||||
|
|
Loading…
Reference in a new issue