Make permissions command apply recursively
This commit is contained in:
parent
3a84658e8b
commit
ddb211f8f3
5 changed files with 69 additions and 36 deletions
|
@ -57,6 +57,9 @@ class DiscordClient {
|
||||||
addEventLogger("error", "Error")
|
addEventLogger("error", "Error")
|
||||||
addEventLogger("disconnected", "Disconnected")
|
addEventLogger("disconnected", "Disconnected")
|
||||||
addEventLogger("ready", "Ready")
|
addEventLogger("ready", "Ready")
|
||||||
|
this.snow.requestHandler.on("requestError", (requestID, error) => {
|
||||||
|
console.error("request error:", error)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -5,23 +5,27 @@ const Ty = require("../../types")
|
||||||
const {discord, sync, db, select, from} = require("../../passthrough")
|
const {discord, sync, db, select, from} = require("../../passthrough")
|
||||||
const assert = require("assert/strict")
|
const assert = require("assert/strict")
|
||||||
|
|
||||||
|
|
||||||
/** @type {import("../../matrix/api")} */
|
/** @type {import("../../matrix/api")} */
|
||||||
const api = sync.require("../../matrix/api")
|
const api = sync.require("../../matrix/api")
|
||||||
|
|
||||||
/** @param {DiscordTypes.APIContextMenuGuildInteraction} interaction */
|
/**
|
||||||
async function interact({data, channel, id, token, guild_id}) {
|
* @param {DiscordTypes.APIContextMenuGuildInteraction} interaction
|
||||||
|
* @returns {Promise<DiscordTypes.APIInteractionResponse>}
|
||||||
|
*/
|
||||||
|
async function _interact({data, channel, guild_id}) {
|
||||||
const row = select("event_message", ["event_id", "source"], {message_id: data.target_id}).get()
|
const row = select("event_message", ["event_id", "source"], {message_id: data.target_id}).get()
|
||||||
assert(row)
|
assert(row)
|
||||||
|
|
||||||
// Can't operate on Discord users
|
// Can't operate on Discord users
|
||||||
if (row.source === 1) { // discord
|
if (row.source === 1) { // discord
|
||||||
return discord.snow.interaction.createInteractionResponse(id, token, {
|
return {
|
||||||
type: DiscordTypes.InteractionResponseType.ChannelMessageWithSource,
|
type: DiscordTypes.InteractionResponseType.ChannelMessageWithSource,
|
||||||
data: {
|
data: {
|
||||||
content: `This command is only meaningful for Matrix users.`,
|
content: `This command is only meaningful for Matrix users.`,
|
||||||
flags: DiscordTypes.MessageFlags.Ephemeral
|
flags: DiscordTypes.MessageFlags.Ephemeral
|
||||||
}
|
}
|
||||||
})
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get the message sender, the person that will be inspected/edited
|
// Get the message sender, the person that will be inspected/edited
|
||||||
|
@ -42,16 +46,16 @@ async function interact({data, channel, id, token, guild_id}) {
|
||||||
|
|
||||||
// Administrators equal to the bot cannot be demoted
|
// Administrators equal to the bot cannot be demoted
|
||||||
if (userPower >= 100) {
|
if (userPower >= 100) {
|
||||||
return discord.snow.interaction.createInteractionResponse(id, token, {
|
return {
|
||||||
type: DiscordTypes.InteractionResponseType.ChannelMessageWithSource,
|
type: DiscordTypes.InteractionResponseType.ChannelMessageWithSource,
|
||||||
data: {
|
data: {
|
||||||
content: `\`${sender}\` has administrator permissions. This cannot be edited.`,
|
content: `\`${sender}\` has administrator permissions. This cannot be edited.`,
|
||||||
flags: DiscordTypes.MessageFlags.Ephemeral
|
flags: DiscordTypes.MessageFlags.Ephemeral
|
||||||
}
|
}
|
||||||
})
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
await discord.snow.interaction.createInteractionResponse(id, token, {
|
return {
|
||||||
type: DiscordTypes.InteractionResponseType.ChannelMessageWithSource,
|
type: DiscordTypes.InteractionResponseType.ChannelMessageWithSource,
|
||||||
data: {
|
data: {
|
||||||
content: `Showing permissions for \`${sender}\`. Click to edit.`,
|
content: `Showing permissions for \`${sender}\`. Click to edit.`,
|
||||||
|
@ -79,30 +83,47 @@ async function interact({data, channel, id, token, guild_id}) {
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
})
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** @param {DiscordTypes.APIMessageComponentSelectMenuInteraction} interaction */
|
/**
|
||||||
async function interactEdit({data, channel, id, token, guild_id, message}) {
|
* @param {DiscordTypes.APIMessageComponentSelectMenuInteraction} interaction
|
||||||
|
*/
|
||||||
|
async function interactEdit({data, id, token, guild_id, message}) {
|
||||||
// Get the person that will be inspected/edited
|
// Get the person that will be inspected/edited
|
||||||
const mxid = message.content.match(/`(@(?:[^:]+):(?:[a-z0-9:-]+\.[a-z0-9.:-]+))`/)?.[1]
|
const mxid = message.content.match(/`(@(?:[^:]+):(?:[a-z0-9:-]+\.[a-z0-9.:-]+))`/)?.[1]
|
||||||
assert(mxid)
|
assert(mxid)
|
||||||
|
|
||||||
|
const permission = data.values[0]
|
||||||
|
const power = permission === "moderator" ? 50 : 0
|
||||||
|
|
||||||
|
await discord.snow.interaction.createInteractionResponse(id, token, {
|
||||||
|
type: DiscordTypes.InteractionResponseType.UpdateMessage,
|
||||||
|
data: {
|
||||||
|
content: `Updating \`${mxid}\` to **${permission}**, please wait...`,
|
||||||
|
components: []
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
// Get the space, where the power levels will be inspected/edited
|
// Get the space, where the power levels will be inspected/edited
|
||||||
const spaceID = select("guild_space", "space_id", {guild_id}).pluck().get()
|
const spaceID = select("guild_space", "space_id", {guild_id}).pluck().get()
|
||||||
assert(spaceID)
|
assert(spaceID)
|
||||||
|
|
||||||
// Do it
|
// Do it
|
||||||
const permission = data.values[0]
|
await api.setUserPowerCascade(spaceID, mxid, power)
|
||||||
const power = permission === "moderator" ? 50 : 0
|
|
||||||
await api.setUserPower(spaceID, mxid, power)
|
|
||||||
// TODO: Cascade permissions through room hierarchy (make a helper for this already, geez...)
|
|
||||||
|
|
||||||
// ACK
|
// ACK
|
||||||
await discord.snow.interaction.createInteractionResponse(id, token, {
|
await discord.snow.interaction.editOriginalInteractionResponse(discord.application.id, token, {
|
||||||
type: DiscordTypes.InteractionResponseType.DeferredMessageUpdate
|
content: `Updated \`${mxid}\` to **${permission}**.`,
|
||||||
|
components: []
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** @param {DiscordTypes.APIContextMenuGuildInteraction} interaction */
|
||||||
|
async function interact(interaction) {
|
||||||
|
await discord.snow.interaction.createInteractionResponse(interaction.id, interaction.token, await _interact(interaction))
|
||||||
|
}
|
||||||
|
|
||||||
module.exports.interact = interact
|
module.exports.interact = interact
|
||||||
module.exports.interactEdit = interactEdit
|
module.exports.interactEdit = interactEdit
|
||||||
|
module.exports._interact = _interact
|
||||||
|
|
|
@ -48,23 +48,23 @@ discord.snow.interaction.bulkOverwriteApplicationCommands(id, [{
|
||||||
}])
|
}])
|
||||||
|
|
||||||
async function dispatchInteraction(interaction) {
|
async function dispatchInteraction(interaction) {
|
||||||
const id = interaction.data.custom_id || interaction.data.name
|
const interactionId = interaction.data.custom_id || interaction.data.name
|
||||||
try {
|
try {
|
||||||
console.log(interaction)
|
console.log(interaction)
|
||||||
if (id === "Matrix info") {
|
if (interactionId === "Matrix info") {
|
||||||
await matrixInfo.interact(interaction)
|
await matrixInfo.interact(interaction)
|
||||||
} else if (id === "invite") {
|
} else if (interactionId === "invite") {
|
||||||
await invite.interact(interaction)
|
await invite.interact(interaction)
|
||||||
} else if (id === "invite_channel") {
|
} else if (interactionId === "invite_channel") {
|
||||||
await invite.interactButton(interaction)
|
await invite.interactButton(interaction)
|
||||||
} else if (id === "Permissions") {
|
} else if (interactionId === "Permissions") {
|
||||||
await permissions.interact(interaction)
|
await permissions.interact(interaction)
|
||||||
} else if (id === "permissions_edit") {
|
} else if (interactionId === "permissions_edit") {
|
||||||
await permissions.interactEdit(interaction)
|
await permissions.interactEdit(interaction)
|
||||||
} else if (id === "bridge") {
|
} else if (interactionId === "bridge") {
|
||||||
await bridge.interact(interaction)
|
await bridge.interact(interaction)
|
||||||
} else {
|
} else {
|
||||||
throw new Error(`Unknown interaction ${id}`)
|
throw new Error(`Unknown interaction ${interactionId}`)
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
let stackLines = null
|
let stackLines = null
|
||||||
|
@ -75,14 +75,11 @@ async function dispatchInteraction(interaction) {
|
||||||
stackLines = stackLines.slice(0, cloudstormLine - 2)
|
stackLines = stackLines.slice(0, cloudstormLine - 2)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
discord.snow.interaction.createInteractionResponse(interaction.id, interaction.token, {
|
await discord.snow.interaction.createFollowupMessage(id, interaction.token, {
|
||||||
type: DiscordTypes.InteractionResponseType.ChannelMessageWithSource,
|
content: `Interaction failed: **${interactionId}**`
|
||||||
data: {
|
|
||||||
content: `Interaction failed: **${id}**`
|
|
||||||
+ `\nError trace:\n\`\`\`\n${stackLines.join("\n")}\`\`\``
|
+ `\nError trace:\n\`\`\`\n${stackLines.join("\n")}\`\`\``
|
||||||
+ `Interaction data:\n\`\`\`\n${JSON.stringify(interaction.data, null, 2)}\`\`\``,
|
+ `Interaction data:\n\`\`\`\n${JSON.stringify(interaction.data, null, 2)}\`\`\``,
|
||||||
flags: DiscordTypes.MessageFlags.Ephemeral
|
flags: DiscordTypes.MessageFlags.Ephemeral
|
||||||
}
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -260,6 +260,21 @@ async function setUserPower(roomID, mxid, power) {
|
||||||
return powerLevels
|
return powerLevels
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set a user's power level for a whole room hierarchy.
|
||||||
|
* @param {string} roomID
|
||||||
|
* @param {string} mxid
|
||||||
|
* @param {number} power
|
||||||
|
*/
|
||||||
|
async function setUserPowerCascade(roomID, mxid, power) {
|
||||||
|
assert(roomID[0] === "!")
|
||||||
|
assert(mxid[0] === "@")
|
||||||
|
const rooms = await getFullHierarchy(roomID)
|
||||||
|
for (const room of rooms) {
|
||||||
|
await setUserPower(room.room_id, mxid, power)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
module.exports.path = path
|
module.exports.path = path
|
||||||
module.exports.register = register
|
module.exports.register = register
|
||||||
module.exports.createRoom = createRoom
|
module.exports.createRoom = createRoom
|
||||||
|
@ -281,3 +296,4 @@ module.exports.sendTyping = sendTyping
|
||||||
module.exports.profileSetDisplayname = profileSetDisplayname
|
module.exports.profileSetDisplayname = profileSetDisplayname
|
||||||
module.exports.profileSetAvatarUrl = profileSetAvatarUrl
|
module.exports.profileSetAvatarUrl = profileSetAvatarUrl
|
||||||
module.exports.setUserPower = setUserPower
|
module.exports.setUserPower = setUserPower
|
||||||
|
module.exports.setUserPowerCascade = setUserPowerCascade
|
||||||
|
|
4
start.js
4
start.js
|
@ -27,10 +27,6 @@ passthrough.select = orm.select
|
||||||
|
|
||||||
sync.require("./m2d/event-dispatcher")
|
sync.require("./m2d/event-dispatcher")
|
||||||
|
|
||||||
discord.snow.requestHandler.on("requestError", data => {
|
|
||||||
console.error("request error", data)
|
|
||||||
})
|
|
||||||
|
|
||||||
;(async () => {
|
;(async () => {
|
||||||
await migrate.migrate(db)
|
await migrate.migrate(db)
|
||||||
await discord.cloud.connect()
|
await discord.cloud.connect()
|
||||||
|
|
Loading…
Reference in a new issue