Give sims enough power to send to read-only rooms
This commit is contained in:
@@ -40,6 +40,8 @@ const PRIVACY_ENUMS = {
|
|||||||
|
|
||||||
const DEFAULT_PRIVACY_LEVEL = 0
|
const DEFAULT_PRIVACY_LEVEL = 0
|
||||||
|
|
||||||
|
const READ_ONLY_ROOM_EVENTS_DEFAULT_POWER = 50
|
||||||
|
|
||||||
/** @type {Map<string, Promise<string>>} channel ID -> Promise<room ID> */
|
/** @type {Map<string, Promise<string>>} channel ID -> Promise<room ID> */
|
||||||
const inflightRoomCreate = new Map()
|
const inflightRoomCreate = new Map()
|
||||||
|
|
||||||
@@ -146,7 +148,7 @@ async function channelToKState(channel, guild, di) {
|
|||||||
"m.room.join_rules/": join_rules,
|
"m.room.join_rules/": join_rules,
|
||||||
/** @type {Ty.Event.M_Power_Levels} */
|
/** @type {Ty.Event.M_Power_Levels} */
|
||||||
"m.room.power_levels/": {
|
"m.room.power_levels/": {
|
||||||
events_default: everyoneCanSend ? 0 : 50,
|
events_default: everyoneCanSend ? 0 : READ_ONLY_ROOM_EVENTS_DEFAULT_POWER,
|
||||||
events: {
|
events: {
|
||||||
"m.reaction": 0,
|
"m.reaction": 0,
|
||||||
"m.room.redaction": 0 // only affects redactions of own events, required to be able to un-react
|
"m.room.redaction": 0 // only affects redactions of own events, required to be able to un-react
|
||||||
@@ -557,6 +559,7 @@ async function createAllForGuild(guildID) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
module.exports.DEFAULT_PRIVACY_LEVEL = DEFAULT_PRIVACY_LEVEL
|
module.exports.DEFAULT_PRIVACY_LEVEL = DEFAULT_PRIVACY_LEVEL
|
||||||
|
module.exports.READ_ONLY_ROOM_EVENTS_DEFAULT_POWER = READ_ONLY_ROOM_EVENTS_DEFAULT_POWER
|
||||||
module.exports.PRIVACY_ENUMS = PRIVACY_ENUMS
|
module.exports.PRIVACY_ENUMS = PRIVACY_ENUMS
|
||||||
module.exports.createRoom = createRoom
|
module.exports.createRoom = createRoom
|
||||||
module.exports.ensureRoom = ensureRoom
|
module.exports.ensureRoom = ensureRoom
|
||||||
|
@@ -15,6 +15,8 @@ const file = sync.require("../../matrix/file")
|
|||||||
const utils = sync.require("../../discord/utils")
|
const utils = sync.require("../../discord/utils")
|
||||||
/** @type {import("../converters/user-to-mxid")} */
|
/** @type {import("../converters/user-to-mxid")} */
|
||||||
const userToMxid = sync.require("../converters/user-to-mxid")
|
const userToMxid = sync.require("../converters/user-to-mxid")
|
||||||
|
/** @type {import("./create-room")} */
|
||||||
|
const createRoom = sync.require("./create-room")
|
||||||
/** @type {import("xxhash-wasm").XXHashAPI} */ // @ts-ignore
|
/** @type {import("xxhash-wasm").XXHashAPI} */ // @ts-ignore
|
||||||
let hasher = null
|
let hasher = null
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
@@ -139,6 +141,7 @@ function memberToPowerLevel(user, member, guild, channel) {
|
|||||||
if (!member) return 0
|
if (!member) return 0
|
||||||
|
|
||||||
const permissions = utils.getPermissions(member.roles, guild.roles, user.id, channel.permission_overwrites)
|
const permissions = utils.getPermissions(member.roles, guild.roles, user.id, channel.permission_overwrites)
|
||||||
|
const everyonePermissions = utils.getPermissions([], guild.roles, undefined, channel.permission_overwrites)
|
||||||
/*
|
/*
|
||||||
* PL 100 = Administrator = People who can brick the room. RATIONALE:
|
* PL 100 = Administrator = People who can brick the room. RATIONALE:
|
||||||
* - Administrator.
|
* - Administrator.
|
||||||
@@ -158,8 +161,14 @@ function memberToPowerLevel(user, member, guild, channel) {
|
|||||||
* - Moderate Members.
|
* - Moderate Members.
|
||||||
*/
|
*/
|
||||||
if (utils.hasSomePermissions(permissions, ["ManageMessages", "ManageNicknames", "ManageThreads", "KickMembers", "BanMembers", "MuteMembers", "DeafenMembers", "ModerateMembers"])) return 50
|
if (utils.hasSomePermissions(permissions, ["ManageMessages", "ManageNicknames", "ManageThreads", "KickMembers", "BanMembers", "MuteMembers", "DeafenMembers", "ModerateMembers"])) return 50
|
||||||
|
/* PL 50 = if room is read-only but the user has been specially allowed to send messages */
|
||||||
|
const everyoneCanSend = utils.hasPermission(everyonePermissions, DiscordTypes.PermissionFlagsBits.SendMessages)
|
||||||
|
const userCanSend = utils.hasPermission(permissions, DiscordTypes.PermissionFlagsBits.SendMessages)
|
||||||
|
if (!everyoneCanSend && userCanSend) return createRoom.READ_ONLY_ROOM_EVENTS_DEFAULT_POWER
|
||||||
/* PL 20 = Mention Everyone for technical reasons. */
|
/* PL 20 = Mention Everyone for technical reasons. */
|
||||||
if (utils.hasSomePermissions(permissions, ["MentionEveryone"])) return 20
|
const everyoneCanMentionEveryone = utils.hasPermission(everyonePermissions, DiscordTypes.PermissionFlagsBits.MentionEveryone)
|
||||||
|
const userCanMentionEveryone = utils.hasPermission(permissions, DiscordTypes.PermissionFlagsBits.MentionEveryone)
|
||||||
|
if (!everyoneCanMentionEveryone && userCanMentionEveryone) return 20
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -250,3 +259,4 @@ module.exports.ensureSim = ensureSim
|
|||||||
module.exports.ensureSimJoined = ensureSimJoined
|
module.exports.ensureSimJoined = ensureSimJoined
|
||||||
module.exports.syncUser = syncUser
|
module.exports.syncUser = syncUser
|
||||||
module.exports.syncAllUsersInRoom = syncAllUsersInRoom
|
module.exports.syncAllUsersInRoom = syncAllUsersInRoom
|
||||||
|
module.exports._memberToPowerLevel = memberToPowerLevel
|
||||||
|
@@ -1,10 +1,12 @@
|
|||||||
const {_memberToStateContent} = require("./register-user")
|
const {_memberToStateContent, _memberToPowerLevel} = require("./register-user")
|
||||||
const {test} = require("supertape")
|
const {test} = require("supertape")
|
||||||
const testData = require("../../../test/data")
|
const data = require("../../../test/data")
|
||||||
|
const mixin = require("@cloudrac3r/mixin-deep")
|
||||||
|
const DiscordTypes = require("discord-api-types/v10")
|
||||||
|
|
||||||
test("member2state: without member nick or avatar", async t => {
|
test("member2state: without member nick or avatar", async t => {
|
||||||
t.deepEqual(
|
t.deepEqual(
|
||||||
await _memberToStateContent(testData.member.kumaccino.user, testData.member.kumaccino, testData.guild.general.id),
|
await _memberToStateContent(data.member.kumaccino.user, data.member.kumaccino, data.guild.general.id),
|
||||||
{
|
{
|
||||||
avatar_url: "mxc://cadence.moe/UpAeIqeclhKfeiZNdIWNcXXL",
|
avatar_url: "mxc://cadence.moe/UpAeIqeclhKfeiZNdIWNcXXL",
|
||||||
displayname: "kumaccino",
|
displayname: "kumaccino",
|
||||||
@@ -24,7 +26,7 @@ test("member2state: without member nick or avatar", async t => {
|
|||||||
|
|
||||||
test("member2state: with global name, without member nick or avatar", async t => {
|
test("member2state: with global name, without member nick or avatar", async t => {
|
||||||
t.deepEqual(
|
t.deepEqual(
|
||||||
await _memberToStateContent(testData.member.papiophidian.user, testData.member.papiophidian, testData.guild.general.id),
|
await _memberToStateContent(data.member.papiophidian.user, data.member.papiophidian, data.guild.general.id),
|
||||||
{
|
{
|
||||||
avatar_url: "mxc://cadence.moe/JPzSmALLirnIprlSMKohSSoX",
|
avatar_url: "mxc://cadence.moe/JPzSmALLirnIprlSMKohSSoX",
|
||||||
displayname: "PapiOphidian",
|
displayname: "PapiOphidian",
|
||||||
@@ -44,7 +46,7 @@ test("member2state: with global name, without member nick or avatar", async t =>
|
|||||||
|
|
||||||
test("member2state: with member nick and avatar", async t => {
|
test("member2state: with member nick and avatar", async t => {
|
||||||
t.deepEqual(
|
t.deepEqual(
|
||||||
await _memberToStateContent(testData.member.sheep.user, testData.member.sheep, testData.guild.general.id),
|
await _memberToStateContent(data.member.sheep.user, data.member.sheep, data.guild.general.id),
|
||||||
{
|
{
|
||||||
avatar_url: "mxc://cadence.moe/rfemHmAtcprjLEiPiEuzPhpl",
|
avatar_url: "mxc://cadence.moe/rfemHmAtcprjLEiPiEuzPhpl",
|
||||||
displayname: "The Expert's Submarine",
|
displayname: "The Expert's Submarine",
|
||||||
@@ -61,3 +63,57 @@ test("member2state: with member nick and avatar", async t => {
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
test("member2power: default to zero if member roles unknown", async t => {
|
||||||
|
const power = _memberToPowerLevel(data.user.clyde_ai, null, data.guild.data_horde, data.channel.saving_the_world)
|
||||||
|
t.equal(power, 0)
|
||||||
|
})
|
||||||
|
|
||||||
|
test("member2power: unremarkable = 0", async t => {
|
||||||
|
const power = _memberToPowerLevel(data.user.clyde_ai, {
|
||||||
|
roles: []
|
||||||
|
}, data.guild.data_horde, data.channel.general)
|
||||||
|
t.equal(power, 0)
|
||||||
|
})
|
||||||
|
|
||||||
|
test("member2power: can mention everyone = 20", async t => {
|
||||||
|
const power = _memberToPowerLevel(data.user.clyde_ai, {
|
||||||
|
roles: ["684524730274807911"]
|
||||||
|
}, data.guild.data_horde, data.channel.general)
|
||||||
|
t.equal(power, 20)
|
||||||
|
})
|
||||||
|
|
||||||
|
test("member2power: can send messages in protected channel due to role = 50", async t => {
|
||||||
|
const power = _memberToPowerLevel(data.user.clyde_ai, {
|
||||||
|
roles: ["684524730274807911"]
|
||||||
|
}, data.guild.data_horde, data.channel.saving_the_world)
|
||||||
|
t.equal(power, 50)
|
||||||
|
})
|
||||||
|
|
||||||
|
test("member2power: can send messages in protected channel due to user override = 50", async t => {
|
||||||
|
const power = _memberToPowerLevel(data.user.clyde_ai, {
|
||||||
|
roles: []
|
||||||
|
}, data.guild.data_horde, mixin({}, data.channel.saving_the_world, {
|
||||||
|
permission_overwrites: data.channel.saving_the_world.permission_overwrites.concat({
|
||||||
|
type: DiscordTypes.OverwriteType.member,
|
||||||
|
id: data.user.clyde_ai.id,
|
||||||
|
allow: String(DiscordTypes.PermissionFlagsBits.SendMessages),
|
||||||
|
deny: "0"
|
||||||
|
})
|
||||||
|
}))
|
||||||
|
t.equal(power, 50)
|
||||||
|
})
|
||||||
|
|
||||||
|
test("member2power: can kick users = 50", async t => {
|
||||||
|
const power = _memberToPowerLevel(data.user.clyde_ai, {
|
||||||
|
roles: ["682789592390281245"]
|
||||||
|
}, data.guild.data_horde, data.channel.general)
|
||||||
|
t.equal(power, 50)
|
||||||
|
})
|
||||||
|
|
||||||
|
test("member2power: can manage channels = 100", async t => {
|
||||||
|
const power = _memberToPowerLevel(data.user.clyde_ai, {
|
||||||
|
roles: ["665290147377578005"]
|
||||||
|
}, data.guild.data_horde, data.channel.saving_the_world)
|
||||||
|
t.equal(power, 100)
|
||||||
|
})
|
||||||
|
34
test/data.js
34
test/data.js
@@ -37,18 +37,31 @@ module.exports = {
|
|||||||
id: "1161864271370666075",
|
id: "1161864271370666075",
|
||||||
guild_id: "112760669178241024"
|
guild_id: "112760669178241024"
|
||||||
},
|
},
|
||||||
|
/** @type {DiscordTypes.APITextChannel} */
|
||||||
saving_the_world: {
|
saving_the_world: {
|
||||||
type: 0,
|
type: 0,
|
||||||
topic: "Anything and everything archiving/preservation related",
|
topic: "Anything and everything archiving/preservation related",
|
||||||
rate_limit_per_user: 0,
|
rate_limit_per_user: 0,
|
||||||
position: 0,
|
position: 0,
|
||||||
permission_overwrites: [],
|
permission_overwrites: [
|
||||||
|
{
|
||||||
|
id: "665289423482519565",
|
||||||
|
type: DiscordTypes.OverwriteType.Role,
|
||||||
|
allow: "0",
|
||||||
|
deny: String(DiscordTypes.PermissionFlagsBits.SendMessages)
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "684524730274807911",
|
||||||
|
type: DiscordTypes.OverwriteType.Role,
|
||||||
|
allow: String(DiscordTypes.PermissionFlagsBits.SendMessages),
|
||||||
|
deny: "0"
|
||||||
|
}
|
||||||
|
],
|
||||||
parent_id: null,
|
parent_id: null,
|
||||||
name: "saving-the-world",
|
name: "saving-the-world",
|
||||||
last_pin_timestamp: "2021-04-14T18:39:41+00:00",
|
last_pin_timestamp: "2021-04-14T18:39:41+00:00",
|
||||||
last_message_id: "1335828749479837750",
|
last_message_id: "1335828749479837750",
|
||||||
id: "665310973967597573",
|
id: "665310973967597573",
|
||||||
flags: 0,
|
|
||||||
guild_id: "665289423482519565"
|
guild_id: "665289423482519565"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -349,7 +362,7 @@ module.exports = {
|
|||||||
unicode_emoji: null,
|
unicode_emoji: null,
|
||||||
tags: {},
|
tags: {},
|
||||||
position: 0,
|
position: 0,
|
||||||
permissions: "2221982107557441",
|
permissions: "968619318849",
|
||||||
name: "@everyone",
|
name: "@everyone",
|
||||||
mentionable: false,
|
mentionable: false,
|
||||||
managed: false,
|
managed: false,
|
||||||
@@ -374,6 +387,21 @@ module.exports = {
|
|||||||
flags: 0,
|
flags: 0,
|
||||||
color: 1752220
|
color: 1752220
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
version: 1683791258594,
|
||||||
|
unicode_emoji: null,
|
||||||
|
tags: {},
|
||||||
|
position: 22,
|
||||||
|
permissions: "8194",
|
||||||
|
name: "Moderator",
|
||||||
|
mentionable: true,
|
||||||
|
managed: false,
|
||||||
|
id: "682789592390281245",
|
||||||
|
icon: null,
|
||||||
|
hoist: false,
|
||||||
|
flags: 0,
|
||||||
|
color: 1752220
|
||||||
|
},
|
||||||
{
|
{
|
||||||
version: 1683791258580,
|
version: 1683791258580,
|
||||||
unicode_emoji: null,
|
unicode_emoji: null,
|
||||||
|
Reference in New Issue
Block a user