mirror of
https://github.com/janderedev/automod.git
synced 2024-12-22 18:55:28 +00:00
global blacklist
This commit is contained in:
parent
88214057e5
commit
db3d9391fd
|
@ -1,4 +1,4 @@
|
||||||
import { app, logger } from '..';
|
import { app, db, logger } from '..';
|
||||||
import { Request, Response } from 'express';
|
import { Request, Response } from 'express';
|
||||||
import { botReq } from './internal/ws';
|
import { botReq } from './internal/ws';
|
||||||
|
|
||||||
|
@ -22,3 +22,16 @@ app.get('/stats', async (req: Request, res: Response) => {
|
||||||
servers: SERVER_COUNT,
|
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 SimpleCommand from "../../struct/commands/SimpleCommand";
|
||||||
import MessageCommandContext from "../../struct/MessageCommandContext";
|
import MessageCommandContext from "../../struct/MessageCommandContext";
|
||||||
import { client } from "../..";
|
import { client, dbs } from "../..";
|
||||||
import { commands, DEFAULT_PREFIX, ownerIDs } from "../modules/command_handler";
|
import { commands, DEFAULT_PREFIX, ownerIDs } from "../modules/command_handler";
|
||||||
import child_process from 'child_process';
|
import child_process from 'child_process';
|
||||||
import fs from 'fs';
|
import fs from 'fs';
|
||||||
|
@ -9,6 +9,11 @@ import { wordlist } from "../modules/user_scan";
|
||||||
import { User } from "@janderedev/revolt.js/dist/maps/Users";
|
import { User } from "@janderedev/revolt.js/dist/maps/Users";
|
||||||
import { adminBotLog } from "../logging";
|
import { adminBotLog } from "../logging";
|
||||||
import CommandCategory from "../../struct/commands/CommandCategory";
|
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
|
// id: expireDate
|
||||||
const sudoOverrides: { [key: string]: number|null } = {}
|
const sudoOverrides: { [key: string]: number|null } = {}
|
||||||
|
@ -30,6 +35,11 @@ const getCommitHash = (): Promise<string|null> => new Promise((resolve) => {
|
||||||
const SUBCOMMANDS: string[] = [
|
const SUBCOMMANDS: string[] = [
|
||||||
'stats',
|
'stats',
|
||||||
'sudo',
|
'sudo',
|
||||||
|
'userinfo',
|
||||||
|
'blacklist',
|
||||||
|
'unblacklist',
|
||||||
|
'ignore',
|
||||||
|
'unignore',
|
||||||
];
|
];
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
|
@ -126,6 +136,129 @@ export default {
|
||||||
break;
|
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:
|
default:
|
||||||
message.reply('Unknown subcommand. Available subcommands: ' + SUBCOMMANDS.join(', '));
|
message.reply('Unknown subcommand. Available subcommands: ' + SUBCOMMANDS.join(', '));
|
||||||
}
|
}
|
||||||
|
@ -133,4 +266,4 @@ export default {
|
||||||
}
|
}
|
||||||
} as SimpleCommand;
|
} 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);
|
userscans = userscans.filter(s => s != message.serverContext._id);
|
||||||
}
|
}
|
||||||
break;
|
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 undefined:
|
||||||
case '':
|
case '':
|
||||||
message.reply(`### Available subcommands\n`
|
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
|
break
|
||||||
default:
|
default:
|
||||||
message.reply(`Unknown option`);
|
message.reply(`Unknown option`);
|
||||||
|
|
|
@ -12,6 +12,8 @@ import CommandCategory from "../../struct/commands/CommandCategory";
|
||||||
|
|
||||||
Day.extend(RelativeTime);
|
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 {
|
export default {
|
||||||
name: 'warns',
|
name: 'warns',
|
||||||
aliases: [ 'warnings', 'infractions', 'infraction' ],
|
aliases: [ 'warnings', 'infractions', 'infraction' ],
|
||||||
|
@ -66,10 +68,18 @@ export default {
|
||||||
let user = await parseUserOrId(args[0]);
|
let user = await parseUserOrId(args[0]);
|
||||||
if (!user?._id) return message.reply('I can\'t find this user.');
|
if (!user?._id) return message.reply('I can\'t find this user.');
|
||||||
|
|
||||||
let infs = userInfractions.get(user._id);
|
const infs = userInfractions.get(user._id);
|
||||||
if (!infs) return message.reply(`There are no infractions stored for \`${await fetchUsername(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 {
|
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;
|
let attachSpreadsheet = false;
|
||||||
for (const i in infs) {
|
for (const i in infs) {
|
||||||
let inf = infs[i];
|
let inf = infs[i];
|
||||||
|
@ -111,12 +121,12 @@ export default {
|
||||||
let sheet = Xlsx.utils.aoa_to_sheet(csv_data);
|
let sheet = Xlsx.utils.aoa_to_sheet(csv_data);
|
||||||
let csv = Xlsx.utils.sheet_to_csv(sheet);
|
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) {
|
} catch(e) {
|
||||||
console.error(e);
|
console.error(e);
|
||||||
message.reply(msg);
|
message.reply(msg, false);
|
||||||
}
|
}
|
||||||
} else message.reply(msg);
|
} else message.reply(msg, false);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -61,10 +61,15 @@ let commands: SimpleCommand[];
|
||||||
if (!await antispam(msg)) return;
|
if (!await antispam(msg)) return;
|
||||||
checkCustomRules(msg);
|
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 args = msg.content.split(' ');
|
||||||
let cmdName = args.shift() ?? '';
|
let cmdName = args.shift() ?? '';
|
||||||
|
|
||||||
let config = await dbs.SERVERS.findOne({ id: msg.channel!.server_id! });
|
|
||||||
let guildPrefix = config?.prefix ?? DEFAULT_PREFIX;
|
let guildPrefix = config?.prefix ?? DEFAULT_PREFIX;
|
||||||
|
|
||||||
if (cmdName.startsWith(`<@${client.user?._id}>`)) {
|
if (cmdName.startsWith(`<@${client.user?._id}>`)) {
|
||||||
|
|
|
@ -1,7 +1,9 @@
|
||||||
|
import { ChannelPermission, ServerPermission } from "@janderedev/revolt.js";
|
||||||
import { ulid } from "ulid";
|
import { ulid } from "ulid";
|
||||||
import { client, dbs } from "../..";
|
import { client, dbs } from "../..";
|
||||||
import Infraction from "../../struct/antispam/Infraction";
|
import Infraction from "../../struct/antispam/Infraction";
|
||||||
import InfractionType from "../../struct/antispam/InfractionType";
|
import InfractionType from "../../struct/antispam/InfractionType";
|
||||||
|
import { BLACKLIST_BAN_REASON, BLACKLIST_MESSAGE } from "../commands/botadm";
|
||||||
import logger from "../logger";
|
import logger from "../logger";
|
||||||
import { hasPermForChannel, storeInfraction } from "../util";
|
import { hasPermForChannel, storeInfraction } from "../util";
|
||||||
import { DEFAULT_PREFIX } from "./command_handler";
|
import { DEFAULT_PREFIX } from "./command_handler";
|
||||||
|
@ -48,7 +50,34 @@ client.on('message', async message => {
|
||||||
} as Infraction).catch(console.warn);
|
} as Infraction).catch(console.warn);
|
||||||
} catch(e) { console.error(e) }
|
} catch(e) { console.error(e) }
|
||||||
break;
|
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;
|
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 { User } from "@janderedev/revolt.js/dist/maps/Users";
|
||||||
import { client, dbs } from "..";
|
import { client, dbs } from "..";
|
||||||
import Infraction from "../struct/antispam/Infraction";
|
import Infraction from "../struct/antispam/Infraction";
|
||||||
import ServerConfig from "../struct/ServerConfig";
|
|
||||||
import FormData from 'form-data';
|
import FormData from 'form-data';
|
||||||
import axios from 'axios';
|
import axios from 'axios';
|
||||||
import { Server } from "@janderedev/revolt.js/dist/maps/Servers";
|
import { Server } from "@janderedev/revolt.js/dist/maps/Servers";
|
||||||
|
|
|
@ -26,6 +26,7 @@ class ServerConfig {
|
||||||
userScan?: LogConfig // User profile matched word list
|
userScan?: LogConfig // User profile matched word list
|
||||||
};
|
};
|
||||||
enableUserScan?: boolean;
|
enableUserScan?: boolean;
|
||||||
|
allowBlacklistedUsers?: boolean; // Whether the server explicitly allows users that are globally blacklisted
|
||||||
}
|
}
|
||||||
|
|
||||||
export default ServerConfig;
|
export default ServerConfig;
|
||||||
|
|
Loading…
Reference in a new issue