global blacklist
This commit is contained in:
parent
88214057e5
commit
db3d9391fd
8 changed files with 224 additions and 15 deletions
|
@ -1,4 +1,4 @@
|
|||
import { app, logger } from '..';
|
||||
import { app, db, logger } from '..';
|
||||
import { Request, Response } from 'express';
|
||||
import { botReq } from './internal/ws';
|
||||
|
||||
|
@ -21,4 +21,17 @@ app.get('/stats', async (req: Request, res: Response) => {
|
|||
res.send({
|
||||
servers: SERVER_COUNT,
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
app.get('/stats/global_blacklist', async (req: Request, res: Response) => {
|
||||
try {
|
||||
const users = await db.get('users').find({ globalBlacklist: true });
|
||||
|
||||
res.send({
|
||||
total: users.length,
|
||||
blacklist: users.map(u => ({ id: u.id?.toUpperCase() })),
|
||||
});
|
||||
} catch(e) {
|
||||
console.error(''+e);
|
||||
}
|
||||
});
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import SimpleCommand from "../../struct/commands/SimpleCommand";
|
||||
import MessageCommandContext from "../../struct/MessageCommandContext";
|
||||
import { client } from "../..";
|
||||
import { client, dbs } from "../..";
|
||||
import { commands, DEFAULT_PREFIX, ownerIDs } from "../modules/command_handler";
|
||||
import child_process from 'child_process';
|
||||
import fs from 'fs';
|
||||
|
@ -9,6 +9,11 @@ import { wordlist } from "../modules/user_scan";
|
|||
import { User } from "@janderedev/revolt.js/dist/maps/Users";
|
||||
import { adminBotLog } from "../logging";
|
||||
import CommandCategory from "../../struct/commands/CommandCategory";
|
||||
import { parseUserOrId } from "../util";
|
||||
import { ChannelPermission, ServerPermission } from "@janderedev/revolt.js";
|
||||
|
||||
const BLACKLIST_BAN_REASON = `This user is globally blacklisted and has been banned automatically. If you wish to opt out of the global blacklist, run '/botctl ignore_blacklist yes'.`;
|
||||
const BLACKLIST_MESSAGE = (username: string) => `\`@${username}\` has been banned automatically. Check the ban reason for more info.`;
|
||||
|
||||
// id: expireDate
|
||||
const sudoOverrides: { [key: string]: number|null } = {}
|
||||
|
@ -30,6 +35,11 @@ const getCommitHash = (): Promise<string|null> => new Promise((resolve) => {
|
|||
const SUBCOMMANDS: string[] = [
|
||||
'stats',
|
||||
'sudo',
|
||||
'userinfo',
|
||||
'blacklist',
|
||||
'unblacklist',
|
||||
'ignore',
|
||||
'unignore',
|
||||
];
|
||||
|
||||
export default {
|
||||
|
@ -126,6 +136,129 @@ export default {
|
|||
break;
|
||||
}
|
||||
|
||||
case 'userinfo': {
|
||||
const target = await parseUserOrId(args.shift() || '');
|
||||
if (!target) return message.reply('Specified user could not be found.');
|
||||
|
||||
const res = await dbs.USERS.findOne({ id: target._id });
|
||||
|
||||
if (!res) await message.reply(`Nothing stored about this user.`);
|
||||
else await message.reply(`\`\`\`json\n${JSON.stringify(res, null, 4)}\n\`\`\``);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case 'blacklist': {
|
||||
const target = await parseUserOrId(args.shift() || '');
|
||||
if (!target) return message.reply('Specified user could not be found.');
|
||||
if (target._id == message.author_id) return message.reply(`no`);
|
||||
|
||||
await dbs.USERS.update({
|
||||
id: target._id,
|
||||
}, {
|
||||
$setOnInsert: { id: target._id },
|
||||
$set: { globalBlacklist: true }
|
||||
}, { upsert: true });
|
||||
|
||||
try {
|
||||
// Ban the user from all shared servers (unless those who opted out)
|
||||
if (target instanceof User) {
|
||||
const msg = await message.reply(`User update stored.`);
|
||||
let bannedServers = 0;
|
||||
|
||||
const mutuals = await target.fetchMutual();
|
||||
for (const serverid of mutuals.servers) {
|
||||
const server = client.servers.get(serverid);
|
||||
if (!server) continue;
|
||||
|
||||
if (server.permission & ServerPermission.BanMembers) {
|
||||
const config = await dbs.SERVERS.findOne({ id: server._id });
|
||||
if (config?.allowBlacklistedUsers) continue;
|
||||
|
||||
try {
|
||||
await server.banUser(target._id, {
|
||||
reason: BLACKLIST_BAN_REASON,
|
||||
});
|
||||
bannedServers++;
|
||||
|
||||
if (server.system_messages?.user_banned) {
|
||||
const channel = server.channels.find(c => c!._id == server.system_messages!.user_banned);
|
||||
if (channel && channel.permission & ChannelPermission.SendMessage) {
|
||||
await channel.sendMessage(BLACKLIST_MESSAGE(target.username));
|
||||
}
|
||||
}
|
||||
} catch(e) {
|
||||
console.error(`Failed to ban in ${serverid}: ${e}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (bannedServers) {
|
||||
msg?.edit({ content: `User update stored. User has been banned from ${bannedServers} servers.` });
|
||||
}
|
||||
} else await message.reply(`User update stored. No servers are currently shared with this user.`);
|
||||
} catch(e) {
|
||||
console.error(''+e);
|
||||
await message.reply(`Failed to ban target from mutual servers: ${e}\n`);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case 'unblacklist': {
|
||||
const target = await parseUserOrId(args.shift() || '');
|
||||
if (!target) return message.reply('Specified user could not be found.');
|
||||
|
||||
await dbs.USERS.update({
|
||||
id: target._id,
|
||||
}, {
|
||||
$setOnInsert: { id: target._id },
|
||||
$set: { globalBlacklist: false }
|
||||
}, { upsert: true });
|
||||
|
||||
await message.reply(`User update stored. Existing bans will not be lifted automatically.`);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case 'ignore': {
|
||||
const target = await parseUserOrId(args.shift() || '');
|
||||
if (!target) return message.reply('Specified user could not be found.');
|
||||
if (target._id == message.author_id) return message.reply(`no`);
|
||||
|
||||
await dbs.USERS.update(
|
||||
{ id: target._id },
|
||||
{
|
||||
$setOnInsert: { id: target._id },
|
||||
$set: { ignore: true },
|
||||
},
|
||||
{ upsert: true }
|
||||
);
|
||||
|
||||
await message.reply(`User update stored.`);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case 'unignore': {
|
||||
const target = await parseUserOrId(args.shift() || '');
|
||||
if (!target) return message.reply('Specified user could not be found.');
|
||||
if (target._id == message.author_id) return message.reply(`no`);
|
||||
|
||||
await dbs.USERS.update(
|
||||
{ id: target._id },
|
||||
{
|
||||
$setOnInsert: { id: target._id },
|
||||
$set: { ignore: false },
|
||||
},
|
||||
{ upsert: true }
|
||||
);
|
||||
|
||||
await message.reply(`User update stored.`);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
message.reply('Unknown subcommand. Available subcommands: ' + SUBCOMMANDS.join(', '));
|
||||
}
|
||||
|
@ -133,4 +266,4 @@ export default {
|
|||
}
|
||||
} as SimpleCommand;
|
||||
|
||||
export { isSudo, updateSudoTimeout }
|
||||
export { isSudo, updateSudoTimeout, BLACKLIST_BAN_REASON, BLACKLIST_MESSAGE }
|
||||
|
|
|
@ -47,10 +47,29 @@ export default {
|
|||
userscans = userscans.filter(s => s != message.serverContext._id);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'ignore_blacklist':
|
||||
try {
|
||||
if (args[0] == 'yes') {
|
||||
await dbs.SERVERS.update({ id: message.serverContext._id }, { $set: { allowBlacklistedUsers: true } });
|
||||
await message.reply('Globally blacklisted users will no longer get banned in this server. Previously banned users will need to be unbanned manually.');
|
||||
} else if (args[0] == 'no') {
|
||||
await dbs.SERVERS.update({ id: message.serverContext._id }, { $set: { allowBlacklistedUsers: false } });
|
||||
await message.reply('Globally blacklisted users will now get banned in this server.');
|
||||
} else {
|
||||
await message.reply(`Please specify either 'yes' or 'no' to toggle this setting.`);
|
||||
}
|
||||
} catch(e) {
|
||||
console.error(''+e);
|
||||
message.reply('Something went wrong: ' + e);
|
||||
}
|
||||
break;
|
||||
|
||||
case undefined:
|
||||
case '':
|
||||
message.reply(`### Available subcommands\n`
|
||||
+ `- \`scan_userlist\` - If user scanning is enabled, this will scan the entire user list.`);
|
||||
+ `- \`scan_userlist\` - If user scanning is enabled, this will scan the entire user list.\n`
|
||||
+ `- \`ignore_blacklist\` - Ignore the bot's global blacklist.`);
|
||||
break
|
||||
default:
|
||||
message.reply(`Unknown option`);
|
||||
|
|
|
@ -12,6 +12,8 @@ import CommandCategory from "../../struct/commands/CommandCategory";
|
|||
|
||||
Day.extend(RelativeTime);
|
||||
|
||||
const GLOBAL_BLACKLIST_TEXT = `> :warning: This user has been flagged and is globally blacklisted. [Learn more.](https://github.com/janderedev/automod/wiki/Global-Blacklist)\n\n`;
|
||||
|
||||
export default {
|
||||
name: 'warns',
|
||||
aliases: [ 'warnings', 'infractions', 'infraction' ],
|
||||
|
@ -66,10 +68,18 @@ export default {
|
|||
let user = await parseUserOrId(args[0]);
|
||||
if (!user?._id) return message.reply('I can\'t find this user.');
|
||||
|
||||
let infs = userInfractions.get(user._id);
|
||||
if (!infs) return message.reply(`There are no infractions stored for \`${await fetchUsername(user._id)}\`.`);
|
||||
const infs = userInfractions.get(user._id);
|
||||
const userConfig = await dbs.USERS.findOne({ id: user._id });
|
||||
|
||||
if (!infs) return message.reply(`There are no infractions stored for \`${await fetchUsername(user._id)}\`.`
|
||||
+ (userConfig?.globalBlacklist ? '\n' + GLOBAL_BLACKLIST_TEXT : ''), false);
|
||||
else {
|
||||
let msg = `## ${infs.length} infractions stored for ${await fetchUsername(user._id)}\n\u200b\n`;
|
||||
let msg = `## ${infs.length} infractions stored for ${await fetchUsername(user._id)}\n`;
|
||||
|
||||
if (userConfig?.globalBlacklist) {
|
||||
msg += GLOBAL_BLACKLIST_TEXT;
|
||||
} else msg += '\u200b\n';
|
||||
|
||||
let attachSpreadsheet = false;
|
||||
for (const i in infs) {
|
||||
let inf = infs[i];
|
||||
|
@ -111,12 +121,12 @@ export default {
|
|||
let sheet = Xlsx.utils.aoa_to_sheet(csv_data);
|
||||
let csv = Xlsx.utils.sheet_to_csv(sheet);
|
||||
|
||||
message.reply({ content: msg, attachments: [ await uploadFile(csv, `${user._id}.csv`) ] });
|
||||
message.reply({ content: msg, attachments: [ await uploadFile(csv, `${user._id}.csv`) ] }, false);
|
||||
} catch(e) {
|
||||
console.error(e);
|
||||
message.reply(msg);
|
||||
message.reply(msg, false);
|
||||
}
|
||||
} else message.reply(msg);
|
||||
} else message.reply(msg, false);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -61,10 +61,15 @@ let commands: SimpleCommand[];
|
|||
if (!await antispam(msg)) return;
|
||||
checkCustomRules(msg);
|
||||
|
||||
let [ config, userConfig ] = await Promise.all([
|
||||
dbs.SERVERS.findOne({ id: msg.channel!.server_id! }),
|
||||
dbs.USERS.findOne({ id: msg.author_id }),
|
||||
]);
|
||||
|
||||
if (userConfig?.ignore) return;
|
||||
|
||||
let args = msg.content.split(' ');
|
||||
let cmdName = args.shift() ?? '';
|
||||
|
||||
let config = await dbs.SERVERS.findOne({ id: msg.channel!.server_id! });
|
||||
let guildPrefix = config?.prefix ?? DEFAULT_PREFIX;
|
||||
|
||||
if (cmdName.startsWith(`<@${client.user?._id}>`)) {
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
import { ChannelPermission, ServerPermission } from "@janderedev/revolt.js";
|
||||
import { ulid } from "ulid";
|
||||
import { client, dbs } from "../..";
|
||||
import Infraction from "../../struct/antispam/Infraction";
|
||||
import InfractionType from "../../struct/antispam/InfractionType";
|
||||
import { BLACKLIST_BAN_REASON, BLACKLIST_MESSAGE } from "../commands/botadm";
|
||||
import logger from "../logger";
|
||||
import { hasPermForChannel, storeInfraction } from "../util";
|
||||
import { DEFAULT_PREFIX } from "./command_handler";
|
||||
|
@ -48,7 +50,34 @@ client.on('message', async message => {
|
|||
} as Infraction).catch(console.warn);
|
||||
} catch(e) { console.error(e) }
|
||||
break;
|
||||
case 'user_joined': break;
|
||||
case 'user_joined': {
|
||||
if (!sysMsg.user) break;
|
||||
|
||||
try {
|
||||
const [ serverConfig, userConfig ] = await Promise.all([
|
||||
dbs.SERVERS.findOne({ id: message.channel!.server_id! }),
|
||||
dbs.USERS.findOne({ id: sysMsg.user._id }),
|
||||
]);
|
||||
|
||||
if (userConfig?.globalBlacklist && !serverConfig?.allowBlacklistedUsers) {
|
||||
const server = message.channel?.server;
|
||||
if (server && (server?.permission ?? 0) & ServerPermission.BanMembers) {
|
||||
await server.banUser(sysMsg.user._id, { reason: BLACKLIST_BAN_REASON });
|
||||
|
||||
if (server.system_messages?.user_banned) {
|
||||
const channel = server.channels.find(c => c?._id == server.system_messages?.user_banned);
|
||||
if (channel && channel.permission & ChannelPermission.SendMessage) {
|
||||
await channel.sendMessage(BLACKLIST_MESSAGE(sysMsg.user.username));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch(e) {
|
||||
console.error(''+e);
|
||||
}
|
||||
|
||||
break;
|
||||
};
|
||||
case 'user_left' : break;
|
||||
}
|
||||
});
|
||||
|
|
|
@ -2,7 +2,6 @@ import { Member } from "@janderedev/revolt.js/dist/maps/Members";
|
|||
import { User } from "@janderedev/revolt.js/dist/maps/Users";
|
||||
import { client, dbs } from "..";
|
||||
import Infraction from "../struct/antispam/Infraction";
|
||||
import ServerConfig from "../struct/ServerConfig";
|
||||
import FormData from 'form-data';
|
||||
import axios from 'axios';
|
||||
import { Server } from "@janderedev/revolt.js/dist/maps/Servers";
|
||||
|
|
|
@ -26,6 +26,7 @@ class ServerConfig {
|
|||
userScan?: LogConfig // User profile matched word list
|
||||
};
|
||||
enableUserScan?: boolean;
|
||||
allowBlacklistedUsers?: boolean; // Whether the server explicitly allows users that are globally blacklisted
|
||||
}
|
||||
|
||||
export default ServerConfig;
|
||||
|
|
Loading…
Reference in a new issue