Files
Discord_bot/services/permissions.js
T

136 lines
4.1 KiB
JavaScript

const { connectToDatabase } = require('../db');
const DEFAULT_GUILD_PERMISSIONS = {
adminRoleIds: [],
adminUserIds: [],
commandPermissions: {},
};
const normalizePermissionConfig = (config = {}) => ({
...DEFAULT_GUILD_PERMISSIONS,
...config,
adminRoleIds: Array.isArray(config.adminRoleIds) ? config.adminRoleIds : [],
adminUserIds: Array.isArray(config.adminUserIds) ? config.adminUserIds : [],
commandPermissions: config.commandPermissions ?? {},
});
const sanitizePermissionPayload = (config = {}) => {
const adminRoleIds = Array.isArray(config.adminRoleIds)
? config.adminRoleIds.filter((entry) => typeof entry === 'string' && entry.trim())
: [];
const adminUserIds = Array.isArray(config.adminUserIds)
? config.adminUserIds.filter((entry) => typeof entry === 'string' && entry.trim())
: [];
const commandPermissions = {};
if (config.commandPermissions && typeof config.commandPermissions === 'object') {
Object.entries(config.commandPermissions).forEach(([commandName, entry]) => {
if (!commandName || typeof commandName !== 'string') {
return;
}
if (!entry || typeof entry !== 'object') {
return;
}
const allowedRoleIds = Array.isArray(entry.allowedRoleIds)
? entry.allowedRoleIds.filter((roleId) => typeof roleId === 'string' && roleId.trim())
: [];
const allowedUserIds = Array.isArray(entry.allowedUserIds)
? entry.allowedUserIds.filter((userId) => typeof userId === 'string' && userId.trim())
: [];
commandPermissions[commandName] = {
allowedRoleIds,
allowedUserIds,
};
});
}
return {
adminRoleIds,
adminUserIds,
commandPermissions,
};
};
const memberHasRole = (member, roleIds) =>
roleIds.some((roleId) => member.roles?.cache?.has(roleId));
const getGuildPermissions = async (guildId) => {
const dbClient = await connectToDatabase();
const db = dbClient.db('discord');
const collection = db.collection('guild_permissions');
const config = await collection.findOne({ guildId });
return normalizePermissionConfig(config);
};
const updateGuildPermissions = async ({ guildId, permissions }) => {
if (!guildId) {
throw new Error('Guild ID is required');
}
const dbClient = await connectToDatabase();
const db = dbClient.db('discord');
const collection = db.collection('guild_permissions');
const sanitizedPermissions = sanitizePermissionPayload(permissions);
const normalizedPermissions = normalizePermissionConfig(sanitizedPermissions);
const payload = {
guildId,
...normalizedPermissions,
updatedAt: new Date(),
};
await collection.updateOne({ guildId }, { $set: payload }, { upsert: true });
return payload;
};
const isCommandAllowed = async ({
guildId,
userId,
member,
commandName,
permissionGroup,
}) => {
if (!guildId) return true;
const permissions = await getGuildPermissions(guildId);
const isAdmin =
permissions.adminUserIds.includes(userId) ||
(member && memberHasRole(member, permissions.adminRoleIds));
if (isAdmin) {
return true;
}
const commandPermissions = permissions.commandPermissions?.[commandName];
if (!commandPermissions) {
return true;
}
const allowedUserIds = Array.isArray(commandPermissions.allowedUserIds)
? commandPermissions.allowedUserIds
: [];
const allowedRoleIds = Array.isArray(commandPermissions.allowedRoleIds)
? commandPermissions.allowedRoleIds
: [];
if (allowedUserIds.length === 0 && allowedRoleIds.length === 0) {
return true;
}
if (allowedUserIds.includes(userId)) {
return true;
}
return member ? memberHasRole(member, allowedRoleIds) : false;
};
module.exports = {
getGuildPermissions,
updateGuildPermissions,
isCommandAllowed,
normalizePermissionConfig,
sanitizePermissionPayload,
};