Reformat all files with Prettier
This commit is contained in:
parent
0cde0d46d2
commit
ac79eb09f5
206 changed files with 727 additions and 888 deletions
|
@ -1,24 +1,24 @@
|
||||||
const fs = require('fs');
|
const fs = require("fs");
|
||||||
const path = require('path');
|
const path = require("path");
|
||||||
|
|
||||||
try {
|
try {
|
||||||
fs.accessSync(path.resolve(__dirname, 'bot.env'));
|
fs.accessSync(path.resolve(__dirname, "bot.env"));
|
||||||
require('dotenv').config({ path: path.resolve(__dirname, 'bot.env') });
|
require("dotenv").config({ path: path.resolve(__dirname, "bot.env") });
|
||||||
} catch {
|
} catch {
|
||||||
try {
|
try {
|
||||||
fs.accessSync(path.resolve(__dirname, 'api.env'));
|
fs.accessSync(path.resolve(__dirname, "api.env"));
|
||||||
require('dotenv').config({ path: path.resolve(__dirname, 'api.env') });
|
require("dotenv").config({ path: path.resolve(__dirname, "api.env") });
|
||||||
} catch {
|
} catch {
|
||||||
throw new Error("bot.env or api.env required");
|
throw new Error("bot.env or api.env required");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const moment = require('moment-timezone');
|
const moment = require("moment-timezone");
|
||||||
moment.tz.setDefault('UTC');
|
moment.tz.setDefault("UTC");
|
||||||
|
|
||||||
const entities = path.relative(process.cwd(), path.resolve(__dirname, 'dist/backend/src/data/entities/*.js'));
|
const entities = path.relative(process.cwd(), path.resolve(__dirname, "dist/backend/src/data/entities/*.js"));
|
||||||
const migrations = path.relative(process.cwd(), path.resolve(__dirname, 'dist/backend/src/migrations/*.js'));
|
const migrations = path.relative(process.cwd(), path.resolve(__dirname, "dist/backend/src/migrations/*.js"));
|
||||||
const migrationsDir = path.relative(process.cwd(), path.resolve(__dirname, 'src/migrations'));
|
const migrationsDir = path.relative(process.cwd(), path.resolve(__dirname, "src/migrations"));
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
type: "mysql",
|
type: "mysql",
|
||||||
|
@ -26,7 +26,7 @@ module.exports = {
|
||||||
username: process.env.DB_USER,
|
username: process.env.DB_USER,
|
||||||
password: process.env.DB_PASSWORD,
|
password: process.env.DB_PASSWORD,
|
||||||
database: process.env.DB_DATABASE,
|
database: process.env.DB_DATABASE,
|
||||||
charset: 'utf8mb4',
|
charset: "utf8mb4",
|
||||||
supportBigNumbers: true,
|
supportBigNumbers: true,
|
||||||
bigNumberStrings: true,
|
bigNumberStrings: true,
|
||||||
dateStrings: true,
|
dateStrings: true,
|
||||||
|
@ -39,13 +39,13 @@ module.exports = {
|
||||||
// Pool options
|
// Pool options
|
||||||
extra: {
|
extra: {
|
||||||
typeCast(field, next) {
|
typeCast(field, next) {
|
||||||
if (field.type === 'DATETIME') {
|
if (field.type === "DATETIME") {
|
||||||
const val = field.string();
|
const val = field.string();
|
||||||
return val != null ? moment.utc(val).format('YYYY-MM-DD HH:mm:ss') : null;
|
return val != null ? moment.utc(val).format("YYYY-MM-DD HH:mm:ss") : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
return next();
|
return next();
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
// Migrations
|
// Migrations
|
||||||
|
|
|
@ -6,9 +6,9 @@
|
||||||
* https://github.com/TypeStrong/ts-node/pull/254
|
* https://github.com/TypeStrong/ts-node/pull/254
|
||||||
*/
|
*/
|
||||||
|
|
||||||
const path = require('path');
|
const path = require("path");
|
||||||
const tsconfig = require('./tsconfig.json');
|
const tsconfig = require("./tsconfig.json");
|
||||||
const tsconfigPaths = require('tsconfig-paths');
|
const tsconfigPaths = require("tsconfig-paths");
|
||||||
|
|
||||||
// E.g. ./dist/backend
|
// E.g. ./dist/backend
|
||||||
const baseUrl = path.resolve(tsconfig.compilerOptions.outDir, path.basename(__dirname));
|
const baseUrl = path.resolve(tsconfig.compilerOptions.outDir, path.basename(__dirname));
|
||||||
|
|
|
@ -29,7 +29,7 @@ export class Queue<TQueueFunction extends AnyFn = AnyFn> {
|
||||||
}
|
}
|
||||||
|
|
||||||
public add(fn: TQueueFunction): Promise<any> {
|
public add(fn: TQueueFunction): Promise<any> {
|
||||||
const promise = new Promise<any>(resolve => {
|
const promise = new Promise<any>((resolve) => {
|
||||||
this.queue.push(async () => {
|
this.queue.push(async () => {
|
||||||
const result = await fn();
|
const result = await fn();
|
||||||
resolve(result);
|
resolve(result);
|
||||||
|
@ -50,7 +50,7 @@ export class Queue<TQueueFunction extends AnyFn = AnyFn> {
|
||||||
}
|
}
|
||||||
|
|
||||||
const fn = this.queue.shift()!;
|
const fn = this.queue.shift()!;
|
||||||
new Promise(resolve => {
|
new Promise((resolve) => {
|
||||||
// Either fn() completes or the timeout is reached
|
// Either fn() completes or the timeout is reached
|
||||||
void fn().then(resolve);
|
void fn().then(resolve);
|
||||||
setTimeout(resolve, this._timeout);
|
setTimeout(resolve, this._timeout);
|
||||||
|
|
|
@ -42,7 +42,7 @@ export class QueuedEventEmitter {
|
||||||
const listeners = [...(this.listeners.get(eventName) || []), ...(this.listeners.get("*") || [])];
|
const listeners = [...(this.listeners.get(eventName) || []), ...(this.listeners.get("*") || [])];
|
||||||
|
|
||||||
let promise: Promise<any> = Promise.resolve();
|
let promise: Promise<any> = Promise.resolve();
|
||||||
listeners.forEach(listener => {
|
listeners.forEach((listener) => {
|
||||||
promise = this.queue.add(listener.bind(null, ...args));
|
promise = this.queue.add(listener.bind(null, ...args));
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -27,7 +27,7 @@ const INITIAL_REGEX_TIMEOUT = 5 * SECONDS;
|
||||||
const INITIAL_REGEX_TIMEOUT_DURATION = 30 * SECONDS;
|
const INITIAL_REGEX_TIMEOUT_DURATION = 30 * SECONDS;
|
||||||
const FINAL_REGEX_TIMEOUT = 5 * SECONDS;
|
const FINAL_REGEX_TIMEOUT = 5 * SECONDS;
|
||||||
|
|
||||||
const regexTimeoutUpgradePromise = new Promise(resolve => setTimeout(resolve, INITIAL_REGEX_TIMEOUT_DURATION));
|
const regexTimeoutUpgradePromise = new Promise((resolve) => setTimeout(resolve, INITIAL_REGEX_TIMEOUT_DURATION));
|
||||||
|
|
||||||
let newWorkerTimeout = INITIAL_REGEX_TIMEOUT;
|
let newWorkerTimeout = INITIAL_REGEX_TIMEOUT;
|
||||||
regexTimeoutUpgradePromise.then(() => (newWorkerTimeout = FINAL_REGEX_TIMEOUT));
|
regexTimeoutUpgradePromise.then(() => (newWorkerTimeout = FINAL_REGEX_TIMEOUT));
|
||||||
|
|
|
@ -33,21 +33,21 @@ function simpleDiscordAPIRequest(bearerToken, path): Promise<any> {
|
||||||
Authorization: `Bearer ${bearerToken}`,
|
Authorization: `Bearer ${bearerToken}`,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
res => {
|
(res) => {
|
||||||
if (res.statusCode !== 200) {
|
if (res.statusCode !== 200) {
|
||||||
reject(new Error(`Discord API error ${res.statusCode}`));
|
reject(new Error(`Discord API error ${res.statusCode}`));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let rawData = "";
|
let rawData = "";
|
||||||
res.on("data", data => (rawData += data));
|
res.on("data", (data) => (rawData += data));
|
||||||
res.on("end", () => {
|
res.on("end", () => {
|
||||||
resolve(JSON.parse(rawData));
|
resolve(JSON.parse(rawData));
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
request.on("error", err => reject(err));
|
request.on("error", (err) => reject(err));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -22,21 +22,21 @@ function formatConfigSchema(schema) {
|
||||||
} else if (schema.name.startsWith("Optional<")) {
|
} else if (schema.name.startsWith("Optional<")) {
|
||||||
return `Optional<${formatConfigSchema(schema.types[0])}>`;
|
return `Optional<${formatConfigSchema(schema.types[0])}>`;
|
||||||
} else {
|
} else {
|
||||||
return schema.types.map(t => formatConfigSchema(t)).join(" | ");
|
return schema.types.map((t) => formatConfigSchema(t)).join(" | ");
|
||||||
}
|
}
|
||||||
} else if (schema._tag === "IntersectionType") {
|
} else if (schema._tag === "IntersectionType") {
|
||||||
return schema.types.map(t => formatConfigSchema(t)).join(" & ");
|
return schema.types.map((t) => formatConfigSchema(t)).join(" & ");
|
||||||
} else {
|
} else {
|
||||||
return schema.name;
|
return schema.name;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function initDocs(app: express.Express) {
|
export function initDocs(app: express.Express) {
|
||||||
const docsPlugins = guildPlugins.filter(plugin => plugin.showInDocs);
|
const docsPlugins = guildPlugins.filter((plugin) => plugin.showInDocs);
|
||||||
|
|
||||||
app.get("/docs/plugins", (req: express.Request, res: express.Response) => {
|
app.get("/docs/plugins", (req: express.Request, res: express.Response) => {
|
||||||
res.json(
|
res.json(
|
||||||
docsPlugins.map(plugin => {
|
docsPlugins.map((plugin) => {
|
||||||
const thinInfo = plugin.info ? { prettyName: plugin.info.prettyName, legacy: plugin.info.legacy ?? false } : {};
|
const thinInfo = plugin.info ? { prettyName: plugin.info.prettyName, legacy: plugin.info.legacy ?? false } : {};
|
||||||
return {
|
return {
|
||||||
name: plugin.name,
|
name: plugin.name,
|
||||||
|
@ -56,7 +56,7 @@ export function initDocs(app: express.Express) {
|
||||||
const name = plugin.name;
|
const name = plugin.name;
|
||||||
const info = plugin.info || {};
|
const info = plugin.info || {};
|
||||||
|
|
||||||
const commands = (plugin.commands || []).map(cmd => ({
|
const commands = (plugin.commands || []).map((cmd) => ({
|
||||||
trigger: cmd.trigger,
|
trigger: cmd.trigger,
|
||||||
permission: cmd.permission,
|
permission: cmd.permission,
|
||||||
signature: cmd.signature,
|
signature: cmd.signature,
|
||||||
|
|
|
@ -131,7 +131,7 @@ export function initGuildsAPI(app: express.Express) {
|
||||||
}
|
}
|
||||||
const validPermissions = new Set(Object.values(ApiPermissions));
|
const validPermissions = new Set(Object.values(ApiPermissions));
|
||||||
validPermissions.delete(ApiPermissions.Owner);
|
validPermissions.delete(ApiPermissions.Owner);
|
||||||
if (!Array.isArray(permissions) || permissions.some(p => !validPermissions.has(p))) {
|
if (!Array.isArray(permissions) || permissions.some((p) => !validPermissions.has(p))) {
|
||||||
return clientError(res, "Invalid permissions");
|
return clientError(res, "Invalid permissions");
|
||||||
}
|
}
|
||||||
if (expiresAt != null && !moment.utc(expiresAt).isValid()) {
|
if (expiresAt != null && !moment.utc(expiresAt).isValid()) {
|
||||||
|
|
|
@ -36,7 +36,7 @@ export async function validateGuildConfig(config: any): Promise<string | null> {
|
||||||
const plugin = pluginNameToPlugin.get(pluginName)!;
|
const plugin = pluginNameToPlugin.get(pluginName)!;
|
||||||
try {
|
try {
|
||||||
const mergedOptions = configUtils.mergeConfig(plugin.defaultOptions || {}, pluginOptions);
|
const mergedOptions = configUtils.mergeConfig(plugin.defaultOptions || {}, pluginOptions);
|
||||||
await plugin.configPreprocessor?.((mergedOptions as unknown) as PluginOptions<any>, true);
|
await plugin.configPreprocessor?.(mergedOptions as unknown as PluginOptions<any>, true);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
if (err instanceof ConfigValidationError || err instanceof StrictValidationError) {
|
if (err instanceof ConfigValidationError || err instanceof StrictValidationError) {
|
||||||
return `${pluginName}: ${err.message}`;
|
return `${pluginName}: ${err.message}`;
|
||||||
|
|
|
@ -68,10 +68,7 @@ export class ApiLogins extends BaseRepository {
|
||||||
token: hashedToken,
|
token: hashedToken,
|
||||||
user_id: userId,
|
user_id: userId,
|
||||||
logged_in_at: moment.utc().format(DBDateFormat),
|
logged_in_at: moment.utc().format(DBDateFormat),
|
||||||
expires_at: moment
|
expires_at: moment.utc().add(LOGIN_EXPIRY_TIME, "ms").format(DBDateFormat),
|
||||||
.utc()
|
|
||||||
.add(LOGIN_EXPIRY_TIME, "ms")
|
|
||||||
.format(DBDateFormat),
|
|
||||||
});
|
});
|
||||||
|
|
||||||
return `${loginId}.${token}`;
|
return `${loginId}.${token}`;
|
||||||
|
@ -96,10 +93,7 @@ export class ApiLogins extends BaseRepository {
|
||||||
await this.apiLogins.update(
|
await this.apiLogins.update(
|
||||||
{ id: loginId },
|
{ id: loginId },
|
||||||
{
|
{
|
||||||
expires_at: moment()
|
expires_at: moment().utc().add(LOGIN_EXPIRY_TIME, "ms").format(DBDateFormat),
|
||||||
.utc()
|
|
||||||
.add(LOGIN_EXPIRY_TIME, "ms")
|
|
||||||
.format(DBDateFormat),
|
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,7 +22,7 @@ export class ApiUserInfo extends BaseRepository {
|
||||||
}
|
}
|
||||||
|
|
||||||
update(id, data: ApiUserInfoData) {
|
update(id, data: ApiUserInfoData) {
|
||||||
return connection.transaction(async entityManager => {
|
return connection.transaction(async (entityManager) => {
|
||||||
const repo = entityManager.getRepository(ApiUserInfoEntity);
|
const repo = entityManager.getRepository(ApiUserInfoEntity);
|
||||||
|
|
||||||
const existingInfo = await repo.findOne({ where: { id } });
|
const existingInfo = await repo.findOne({ where: { id } });
|
||||||
|
|
|
@ -41,11 +41,7 @@ export class Configs extends BaseRepository {
|
||||||
}
|
}
|
||||||
|
|
||||||
getActiveLargerThanId(id) {
|
getActiveLargerThanId(id) {
|
||||||
return this.configs
|
return this.configs.createQueryBuilder().where("id > :id", { id }).andWhere("is_active = 1").getMany();
|
||||||
.createQueryBuilder()
|
|
||||||
.where("id > :id", { id })
|
|
||||||
.andWhere("is_active = 1")
|
|
||||||
.getMany();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async hasConfig(key) {
|
async hasConfig(key) {
|
||||||
|
@ -65,7 +61,7 @@ export class Configs extends BaseRepository {
|
||||||
}
|
}
|
||||||
|
|
||||||
async saveNewRevision(key, config, editedBy) {
|
async saveNewRevision(key, config, editedBy) {
|
||||||
return connection.transaction(async entityManager => {
|
return connection.transaction(async (entityManager) => {
|
||||||
const repo = entityManager.getRepository(Config);
|
const repo = entityManager.getRepository(Config);
|
||||||
// Mark all old revisions inactive
|
// Mark all old revisions inactive
|
||||||
await repo.update({ key }, { is_active: false });
|
await repo.update({ key }, { is_active: false });
|
||||||
|
|
|
@ -88,10 +88,10 @@ export class GuildArchives extends BaseGuildRepository {
|
||||||
id: msg.id,
|
id: msg.id,
|
||||||
timestamp: moment.utc(msg.posted_at).format("YYYY-MM-DD HH:mm:ss"),
|
timestamp: moment.utc(msg.posted_at).format("YYYY-MM-DD HH:mm:ss"),
|
||||||
content: msg.data.content,
|
content: msg.data.content,
|
||||||
attachments: msg.data.attachments?.map(att => {
|
attachments: msg.data.attachments?.map((att) => {
|
||||||
return JSON.stringify({ name: att.name, url: att.url, type: att.contentType });
|
return JSON.stringify({ name: att.name, url: att.url, type: att.contentType });
|
||||||
}),
|
}),
|
||||||
stickers: msg.data.stickers?.map(sti => {
|
stickers: msg.data.stickers?.map((sti) => {
|
||||||
return JSON.stringify({ name: sti.name, id: sti.id, isDefault: isDefaultSticker(sti.id) });
|
return JSON.stringify({ name: sti.name, id: sti.id, isDefault: isDefaultSticker(sti.id) });
|
||||||
}),
|
}),
|
||||||
user: partialUser,
|
user: partialUser,
|
||||||
|
|
|
@ -123,7 +123,7 @@ export class GuildCases extends BaseGuildRepository {
|
||||||
guild_id: this.guildId,
|
guild_id: this.guildId,
|
||||||
case_number: () => `(SELECT IFNULL(MAX(case_number)+1, 1) FROM cases AS ma2 WHERE guild_id = ${this.guildId})`,
|
case_number: () => `(SELECT IFNULL(MAX(case_number)+1, 1) FROM cases AS ma2 WHERE guild_id = ${this.guildId})`,
|
||||||
})
|
})
|
||||||
.catch(err => {
|
.catch((err) => {
|
||||||
if (err?.code === "ER_DUP_ENTRY") {
|
if (err?.code === "ER_DUP_ENTRY") {
|
||||||
if (data.audit_log_id) {
|
if (data.audit_log_id) {
|
||||||
console.trace(`Tried to insert case with duplicate audit_log_id`);
|
console.trace(`Tried to insert case with duplicate audit_log_id`);
|
||||||
|
@ -148,7 +148,7 @@ export class GuildCases extends BaseGuildRepository {
|
||||||
}
|
}
|
||||||
|
|
||||||
async softDelete(id: number, deletedById: string, deletedByName: string, deletedByText: string) {
|
async softDelete(id: number, deletedById: string, deletedByName: string, deletedByText: string) {
|
||||||
return connection.transaction(async entityManager => {
|
return connection.transaction(async (entityManager) => {
|
||||||
const cases = entityManager.getRepository(Case);
|
const cases = entityManager.getRepository(Case);
|
||||||
const caseNotes = entityManager.getRepository(CaseNote);
|
const caseNotes = entityManager.getRepository(CaseNote);
|
||||||
|
|
||||||
|
|
|
@ -17,19 +17,11 @@ const MAX_COUNTER_VALUE = 2147483647; // 2^31-1, for MySQL INT
|
||||||
const decayQueue = new Queue();
|
const decayQueue = new Queue();
|
||||||
|
|
||||||
async function deleteCountersMarkedToBeDeleted(): Promise<void> {
|
async function deleteCountersMarkedToBeDeleted(): Promise<void> {
|
||||||
await getRepository(Counter)
|
await getRepository(Counter).createQueryBuilder().where("delete_at <= NOW()").delete().execute();
|
||||||
.createQueryBuilder()
|
|
||||||
.where("delete_at <= NOW()")
|
|
||||||
.delete()
|
|
||||||
.execute();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async function deleteTriggersMarkedToBeDeleted(): Promise<void> {
|
async function deleteTriggersMarkedToBeDeleted(): Promise<void> {
|
||||||
await getRepository(CounterTrigger)
|
await getRepository(CounterTrigger).createQueryBuilder().where("delete_at <= NOW()").delete().execute();
|
||||||
.createQueryBuilder()
|
|
||||||
.where("delete_at <= NOW()")
|
|
||||||
.delete()
|
|
||||||
.execute();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
setInterval(deleteCountersMarkedToBeDeleted, 1 * HOURS);
|
setInterval(deleteCountersMarkedToBeDeleted, 1 * HOURS);
|
||||||
|
@ -97,10 +89,7 @@ export class GuildCounters extends BaseGuildRepository {
|
||||||
criteria.id = Not(In(idsToKeep));
|
criteria.id = Not(In(idsToKeep));
|
||||||
}
|
}
|
||||||
|
|
||||||
const deleteAt = moment
|
const deleteAt = moment.utc().add(DELETE_UNUSED_COUNTERS_AFTER, "ms").format(DBDateFormat);
|
||||||
.utc()
|
|
||||||
.add(DELETE_UNUSED_COUNTERS_AFTER, "ms")
|
|
||||||
.format(DBDateFormat);
|
|
||||||
|
|
||||||
await this.counters.update(criteria, {
|
await this.counters.update(criteria, {
|
||||||
delete_at: deleteAt,
|
delete_at: deleteAt,
|
||||||
|
@ -108,11 +97,7 @@ export class GuildCounters extends BaseGuildRepository {
|
||||||
}
|
}
|
||||||
|
|
||||||
async deleteCountersMarkedToBeDeleted(): Promise<void> {
|
async deleteCountersMarkedToBeDeleted(): Promise<void> {
|
||||||
await this.counters
|
await this.counters.createQueryBuilder().where("delete_at <= NOW()").delete().execute();
|
||||||
.createQueryBuilder()
|
|
||||||
.where("delete_at <= NOW()")
|
|
||||||
.delete()
|
|
||||||
.execute();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async changeCounterValue(
|
async changeCounterValue(
|
||||||
|
@ -230,14 +215,11 @@ export class GuildCounters extends BaseGuildRepository {
|
||||||
const triggersToMark = await triggersToMarkQuery.getMany();
|
const triggersToMark = await triggersToMarkQuery.getMany();
|
||||||
|
|
||||||
if (triggersToMark.length) {
|
if (triggersToMark.length) {
|
||||||
const deleteAt = moment
|
const deleteAt = moment.utc().add(DELETE_UNUSED_COUNTER_TRIGGERS_AFTER, "ms").format(DBDateFormat);
|
||||||
.utc()
|
|
||||||
.add(DELETE_UNUSED_COUNTER_TRIGGERS_AFTER, "ms")
|
|
||||||
.format(DBDateFormat);
|
|
||||||
|
|
||||||
await this.counterTriggers.update(
|
await this.counterTriggers.update(
|
||||||
{
|
{
|
||||||
id: In(triggersToMark.map(t => t.id)),
|
id: In(triggersToMark.map((t) => t.id)),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
delete_at: deleteAt,
|
delete_at: deleteAt,
|
||||||
|
@ -247,11 +229,7 @@ export class GuildCounters extends BaseGuildRepository {
|
||||||
}
|
}
|
||||||
|
|
||||||
async deleteTriggersMarkedToBeDeleted(): Promise<void> {
|
async deleteTriggersMarkedToBeDeleted(): Promise<void> {
|
||||||
await this.counterTriggers
|
await this.counterTriggers.createQueryBuilder().where("delete_at <= NOW()").delete().execute();
|
||||||
.createQueryBuilder()
|
|
||||||
.where("delete_at <= NOW()")
|
|
||||||
.delete()
|
|
||||||
.execute();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async initCounterTrigger(
|
async initCounterTrigger(
|
||||||
|
@ -278,7 +256,7 @@ export class GuildCounters extends BaseGuildRepository {
|
||||||
throw new Error(`Invalid comparison value: ${reverseComparisonValue}`);
|
throw new Error(`Invalid comparison value: ${reverseComparisonValue}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
return connection.transaction(async entityManager => {
|
return connection.transaction(async (entityManager) => {
|
||||||
const existing = await entityManager.findOne(CounterTrigger, {
|
const existing = await entityManager.findOne(CounterTrigger, {
|
||||||
counter_id: counterId,
|
counter_id: counterId,
|
||||||
name: triggerName,
|
name: triggerName,
|
||||||
|
@ -330,7 +308,7 @@ export class GuildCounters extends BaseGuildRepository {
|
||||||
channelId = channelId || "0";
|
channelId = channelId || "0";
|
||||||
userId = userId || "0";
|
userId = userId || "0";
|
||||||
|
|
||||||
return connection.transaction(async entityManager => {
|
return connection.transaction(async (entityManager) => {
|
||||||
const previouslyTriggered = await entityManager.findOne(CounterTriggerState, {
|
const previouslyTriggered = await entityManager.findOne(CounterTriggerState, {
|
||||||
trigger_id: counterTrigger.id,
|
trigger_id: counterTrigger.id,
|
||||||
user_id: userId!,
|
user_id: userId!,
|
||||||
|
@ -378,7 +356,7 @@ export class GuildCounters extends BaseGuildRepository {
|
||||||
async checkAllValuesForTrigger(
|
async checkAllValuesForTrigger(
|
||||||
counterTrigger: CounterTrigger,
|
counterTrigger: CounterTrigger,
|
||||||
): Promise<Array<{ channelId: string; userId: string }>> {
|
): Promise<Array<{ channelId: string; userId: string }>> {
|
||||||
return connection.transaction(async entityManager => {
|
return connection.transaction(async (entityManager) => {
|
||||||
const matchingValues = await entityManager
|
const matchingValues = await entityManager
|
||||||
.createQueryBuilder(CounterValue, "cv")
|
.createQueryBuilder(CounterValue, "cv")
|
||||||
.leftJoin(
|
.leftJoin(
|
||||||
|
@ -395,7 +373,7 @@ export class GuildCounters extends BaseGuildRepository {
|
||||||
if (matchingValues.length) {
|
if (matchingValues.length) {
|
||||||
await entityManager.insert(
|
await entityManager.insert(
|
||||||
CounterTriggerState,
|
CounterTriggerState,
|
||||||
matchingValues.map(row => ({
|
matchingValues.map((row) => ({
|
||||||
trigger_id: counterTrigger.id,
|
trigger_id: counterTrigger.id,
|
||||||
channel_id: row.channel_id,
|
channel_id: row.channel_id,
|
||||||
user_id: row.user_id,
|
user_id: row.user_id,
|
||||||
|
@ -403,7 +381,7 @@ export class GuildCounters extends BaseGuildRepository {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return matchingValues.map(row => ({
|
return matchingValues.map((row) => ({
|
||||||
channelId: row.channel_id,
|
channelId: row.channel_id,
|
||||||
userId: row.user_id,
|
userId: row.user_id,
|
||||||
}));
|
}));
|
||||||
|
@ -429,7 +407,7 @@ export class GuildCounters extends BaseGuildRepository {
|
||||||
channelId = channelId || "0";
|
channelId = channelId || "0";
|
||||||
userId = userId || "0";
|
userId = userId || "0";
|
||||||
|
|
||||||
return connection.transaction(async entityManager => {
|
return connection.transaction(async (entityManager) => {
|
||||||
const matchingValue = await entityManager
|
const matchingValue = await entityManager
|
||||||
.createQueryBuilder(CounterValue, "cv")
|
.createQueryBuilder(CounterValue, "cv")
|
||||||
.innerJoin(
|
.innerJoin(
|
||||||
|
@ -468,7 +446,7 @@ export class GuildCounters extends BaseGuildRepository {
|
||||||
async checkAllValuesForReverseTrigger(
|
async checkAllValuesForReverseTrigger(
|
||||||
counterTrigger: CounterTrigger,
|
counterTrigger: CounterTrigger,
|
||||||
): Promise<Array<{ channelId: string; userId: string }>> {
|
): Promise<Array<{ channelId: string; userId: string }>> {
|
||||||
return connection.transaction(async entityManager => {
|
return connection.transaction(async (entityManager) => {
|
||||||
const matchingValues: Array<{
|
const matchingValues: Array<{
|
||||||
id: string;
|
id: string;
|
||||||
triggerStateId: string;
|
triggerStateId: string;
|
||||||
|
@ -496,11 +474,11 @@ export class GuildCounters extends BaseGuildRepository {
|
||||||
|
|
||||||
if (matchingValues.length) {
|
if (matchingValues.length) {
|
||||||
await entityManager.delete(CounterTriggerState, {
|
await entityManager.delete(CounterTriggerState, {
|
||||||
id: In(matchingValues.map(v => v.triggerStateId)),
|
id: In(matchingValues.map((v) => v.triggerStateId)),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
return matchingValues.map(row => ({
|
return matchingValues.map((row) => ({
|
||||||
channelId: row.channel_id,
|
channelId: row.channel_id,
|
||||||
userId: row.user_id,
|
userId: row.user_id,
|
||||||
}));
|
}));
|
||||||
|
|
|
@ -46,12 +46,12 @@ export class GuildLogs extends events.EventEmitter {
|
||||||
}
|
}
|
||||||
|
|
||||||
isLogIgnored(type: LogType, ignoreId: any) {
|
isLogIgnored(type: LogType, ignoreId: any) {
|
||||||
return this.ignoredLogs.some(info => type === info.type && ignoreId === info.ignoreId);
|
return this.ignoredLogs.some((info) => type === info.type && ignoreId === info.ignoreId);
|
||||||
}
|
}
|
||||||
|
|
||||||
clearIgnoredLog(type: LogType, ignoreId: any) {
|
clearIgnoredLog(type: LogType, ignoreId: any) {
|
||||||
this.ignoredLogs.splice(
|
this.ignoredLogs.splice(
|
||||||
this.ignoredLogs.findIndex(info => type === info.type && ignoreId === info.ignoreId),
|
this.ignoredLogs.findIndex((info) => type === info.type && ignoreId === info.ignoreId),
|
||||||
1,
|
1,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,7 +19,7 @@ export class GuildMemberTimezones extends BaseGuildRepository {
|
||||||
}
|
}
|
||||||
|
|
||||||
async set(memberId, timezone: string) {
|
async set(memberId, timezone: string) {
|
||||||
await connection.transaction(async entityManager => {
|
await connection.transaction(async (entityManager) => {
|
||||||
const repo = entityManager.getRepository(MemberTimezone);
|
const repo = entityManager.getRepository(MemberTimezone);
|
||||||
const existingRow = await repo.findOne({
|
const existingRow = await repo.findOne({
|
||||||
guild_id: this.guildId,
|
guild_id: this.guildId,
|
||||||
|
|
|
@ -35,12 +35,7 @@ export class GuildMutes extends BaseGuildRepository {
|
||||||
}
|
}
|
||||||
|
|
||||||
async addMute(userId, expiryTime, rolesToRestore?: string[]): Promise<Mute> {
|
async addMute(userId, expiryTime, rolesToRestore?: string[]): Promise<Mute> {
|
||||||
const expiresAt = expiryTime
|
const expiresAt = expiryTime ? moment.utc().add(expiryTime, "ms").format("YYYY-MM-DD HH:mm:ss") : null;
|
||||||
? moment
|
|
||||||
.utc()
|
|
||||||
.add(expiryTime, "ms")
|
|
||||||
.format("YYYY-MM-DD HH:mm:ss")
|
|
||||||
: null;
|
|
||||||
|
|
||||||
const result = await this.mutes.insert({
|
const result = await this.mutes.insert({
|
||||||
guild_id: this.guildId,
|
guild_id: this.guildId,
|
||||||
|
@ -53,12 +48,7 @@ export class GuildMutes extends BaseGuildRepository {
|
||||||
}
|
}
|
||||||
|
|
||||||
async updateExpiryTime(userId, newExpiryTime, rolesToRestore?: string[]) {
|
async updateExpiryTime(userId, newExpiryTime, rolesToRestore?: string[]) {
|
||||||
const expiresAt = newExpiryTime
|
const expiresAt = newExpiryTime ? moment.utc().add(newExpiryTime, "ms").format("YYYY-MM-DD HH:mm:ss") : null;
|
||||||
? moment
|
|
||||||
.utc()
|
|
||||||
.add(newExpiryTime, "ms")
|
|
||||||
.format("YYYY-MM-DD HH:mm:ss")
|
|
||||||
: null;
|
|
||||||
|
|
||||||
if (rolesToRestore && rolesToRestore.length) {
|
if (rolesToRestore && rolesToRestore.length) {
|
||||||
return this.mutes.update(
|
return this.mutes.update(
|
||||||
|
@ -89,7 +79,7 @@ export class GuildMutes extends BaseGuildRepository {
|
||||||
.createQueryBuilder("mutes")
|
.createQueryBuilder("mutes")
|
||||||
.where("guild_id = :guild_id", { guild_id: this.guildId })
|
.where("guild_id = :guild_id", { guild_id: this.guildId })
|
||||||
.andWhere(
|
.andWhere(
|
||||||
new Brackets(qb => {
|
new Brackets((qb) => {
|
||||||
qb.where("expires_at > NOW()").orWhere("expires_at IS NULL");
|
qb.where("expires_at > NOW()").orWhere("expires_at IS NULL");
|
||||||
}),
|
}),
|
||||||
)
|
)
|
||||||
|
|
|
@ -70,7 +70,7 @@ export class GuildNicknameHistory extends BaseGuildRepository {
|
||||||
|
|
||||||
if (toDelete.length > 0) {
|
if (toDelete.length > 0) {
|
||||||
await this.nicknameHistory.delete({
|
await this.nicknameHistory.delete({
|
||||||
id: In(toDelete.map(v => v.id)),
|
id: In(toDelete.map((v) => v.id)),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -46,7 +46,7 @@ export class GuildSavedMessages extends BaseGuildRepository {
|
||||||
};
|
};
|
||||||
|
|
||||||
if (msg.attachments.size) {
|
if (msg.attachments.size) {
|
||||||
data.attachments = Array.from(msg.attachments.values()).map(att => ({
|
data.attachments = Array.from(msg.attachments.values()).map((att) => ({
|
||||||
id: att.id,
|
id: att.id,
|
||||||
contentType: att.contentType,
|
contentType: att.contentType,
|
||||||
name: att.name,
|
name: att.name,
|
||||||
|
@ -59,14 +59,14 @@ export class GuildSavedMessages extends BaseGuildRepository {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (msg.embeds.length) {
|
if (msg.embeds.length) {
|
||||||
data.embeds = msg.embeds.map(embed => ({
|
data.embeds = msg.embeds.map((embed) => ({
|
||||||
title: embed.title,
|
title: embed.title,
|
||||||
description: embed.description,
|
description: embed.description,
|
||||||
url: embed.url,
|
url: embed.url,
|
||||||
timestamp: embed.timestamp,
|
timestamp: embed.timestamp,
|
||||||
color: embed.color,
|
color: embed.color,
|
||||||
|
|
||||||
fields: embed.fields.map(field => ({
|
fields: embed.fields.map((field) => ({
|
||||||
name: field.name,
|
name: field.name,
|
||||||
value: field.value,
|
value: field.value,
|
||||||
inline: field.inline,
|
inline: field.inline,
|
||||||
|
@ -119,7 +119,7 @@ export class GuildSavedMessages extends BaseGuildRepository {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (msg.stickers?.size) {
|
if (msg.stickers?.size) {
|
||||||
data.stickers = Array.from(msg.stickers.values()).map(sticker => ({
|
data.stickers = Array.from(msg.stickers.values()).map((sticker) => ({
|
||||||
format: sticker.format,
|
format: sticker.format,
|
||||||
guildId: sticker.guildId,
|
guildId: sticker.guildId,
|
||||||
id: sticker.id,
|
id: sticker.id,
|
||||||
|
|
|
@ -11,10 +11,7 @@ export class GuildScheduledPosts extends BaseGuildRepository {
|
||||||
}
|
}
|
||||||
|
|
||||||
all(): Promise<ScheduledPost[]> {
|
all(): Promise<ScheduledPost[]> {
|
||||||
return this.scheduledPosts
|
return this.scheduledPosts.createQueryBuilder().where("guild_id = :guildId", { guildId: this.guildId }).getMany();
|
||||||
.createQueryBuilder()
|
|
||||||
.where("guild_id = :guildId", { guildId: this.guildId })
|
|
||||||
.getMany();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
getDueScheduledPosts(): Promise<ScheduledPost[]> {
|
getDueScheduledPosts(): Promise<ScheduledPost[]> {
|
||||||
|
|
|
@ -67,10 +67,7 @@ export class GuildSlowmodes extends BaseGuildRepository {
|
||||||
const slowmode = await this.getChannelSlowmode(channelId);
|
const slowmode = await this.getChannelSlowmode(channelId);
|
||||||
if (!slowmode) return;
|
if (!slowmode) return;
|
||||||
|
|
||||||
const expiresAt = moment
|
const expiresAt = moment.utc().add(slowmode.slowmode_seconds, "seconds").format("YYYY-MM-DD HH:mm:ss");
|
||||||
.utc()
|
|
||||||
.add(slowmode.slowmode_seconds, "seconds")
|
|
||||||
.format("YYYY-MM-DD HH:mm:ss");
|
|
||||||
|
|
||||||
if (await this.userHasSlowmode(channelId, userId)) {
|
if (await this.userHasSlowmode(channelId, userId)) {
|
||||||
// Update existing
|
// Update existing
|
||||||
|
|
|
@ -30,10 +30,7 @@ export class GuildTempbans extends BaseGuildRepository {
|
||||||
}
|
}
|
||||||
|
|
||||||
async addTempban(userId, expiryTime, modId): Promise<Tempban> {
|
async addTempban(userId, expiryTime, modId): Promise<Tempban> {
|
||||||
const expiresAt = moment
|
const expiresAt = moment.utc().add(expiryTime, "ms").format("YYYY-MM-DD HH:mm:ss");
|
||||||
.utc()
|
|
||||||
.add(expiryTime, "ms")
|
|
||||||
.format("YYYY-MM-DD HH:mm:ss");
|
|
||||||
|
|
||||||
const result = await this.tempbans.insert({
|
const result = await this.tempbans.insert({
|
||||||
guild_id: this.guildId,
|
guild_id: this.guildId,
|
||||||
|
@ -47,10 +44,7 @@ export class GuildTempbans extends BaseGuildRepository {
|
||||||
}
|
}
|
||||||
|
|
||||||
async updateExpiryTime(userId, newExpiryTime, modId) {
|
async updateExpiryTime(userId, newExpiryTime, modId) {
|
||||||
const expiresAt = moment
|
const expiresAt = moment.utc().add(newExpiryTime, "ms").format("YYYY-MM-DD HH:mm:ss");
|
||||||
.utc()
|
|
||||||
.add(newExpiryTime, "ms")
|
|
||||||
.format("YYYY-MM-DD HH:mm:ss");
|
|
||||||
|
|
||||||
return this.tempbans.update(
|
return this.tempbans.update(
|
||||||
{
|
{
|
||||||
|
|
|
@ -19,10 +19,7 @@ export class GuildVCAlerts extends BaseGuildRepository {
|
||||||
}
|
}
|
||||||
|
|
||||||
async getAllGuildAlerts(): Promise<VCAlert[]> {
|
async getAllGuildAlerts(): Promise<VCAlert[]> {
|
||||||
return this.allAlerts
|
return this.allAlerts.createQueryBuilder().where("guild_id = :guildId", { guildId: this.guildId }).getMany();
|
||||||
.createQueryBuilder()
|
|
||||||
.where("guild_id = :guildId", { guildId: this.guildId })
|
|
||||||
.getMany();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async getAlertsByUserId(userId: string): Promise<VCAlert[]> {
|
async getAlertsByUserId(userId: string): Promise<VCAlert[]> {
|
||||||
|
|
|
@ -67,7 +67,7 @@ export class UsernameHistory extends BaseRepository {
|
||||||
|
|
||||||
if (toDelete.length > 0) {
|
if (toDelete.length > 0) {
|
||||||
await this.usernameHistory.delete({
|
await this.usernameHistory.delete({
|
||||||
id: In(toDelete.map(v => v.id)),
|
id: In(toDelete.map((v) => v.id)),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,10 +13,7 @@ export async function cleanupConfigs() {
|
||||||
let rows;
|
let rows;
|
||||||
|
|
||||||
// >1 month old: 1 config retained per month
|
// >1 month old: 1 config retained per month
|
||||||
const oneMonthCutoff = moment
|
const oneMonthCutoff = moment.utc().subtract(30, "days").format(DBDateFormat);
|
||||||
.utc()
|
|
||||||
.subtract(30, "days")
|
|
||||||
.format(DBDateFormat);
|
|
||||||
do {
|
do {
|
||||||
rows = await connection.query(
|
rows = await connection.query(
|
||||||
`
|
`
|
||||||
|
@ -46,7 +43,7 @@ export async function cleanupConfigs() {
|
||||||
|
|
||||||
if (rows.length > 0) {
|
if (rows.length > 0) {
|
||||||
await configRepository.delete({
|
await configRepository.delete({
|
||||||
id: In(rows.map(r => r.id)),
|
id: In(rows.map((r) => r.id)),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -54,10 +51,7 @@ export async function cleanupConfigs() {
|
||||||
} while (rows.length === CLEAN_PER_LOOP);
|
} while (rows.length === CLEAN_PER_LOOP);
|
||||||
|
|
||||||
// >2 weeks old: 1 config retained per day
|
// >2 weeks old: 1 config retained per day
|
||||||
const twoWeekCutoff = moment
|
const twoWeekCutoff = moment.utc().subtract(2, "weeks").format(DBDateFormat);
|
||||||
.utc()
|
|
||||||
.subtract(2, "weeks")
|
|
||||||
.format(DBDateFormat);
|
|
||||||
do {
|
do {
|
||||||
rows = await connection.query(
|
rows = await connection.query(
|
||||||
`
|
`
|
||||||
|
@ -87,7 +81,7 @@ export async function cleanupConfigs() {
|
||||||
|
|
||||||
if (rows.length > 0) {
|
if (rows.length > 0) {
|
||||||
await configRepository.delete({
|
await configRepository.delete({
|
||||||
id: In(rows.map(r => r.id)),
|
id: In(rows.map((r) => r.id)),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -18,18 +18,9 @@ export async function cleanupMessages(): Promise<number> {
|
||||||
|
|
||||||
const messagesRepository = getRepository(SavedMessage);
|
const messagesRepository = getRepository(SavedMessage);
|
||||||
|
|
||||||
const deletedAtThreshold = moment
|
const deletedAtThreshold = moment.utc().subtract(DELETED_MESSAGE_RETENTION_PERIOD, "ms").format(DBDateFormat);
|
||||||
.utc()
|
const postedAtThreshold = moment.utc().subtract(RETENTION_PERIOD, "ms").format(DBDateFormat);
|
||||||
.subtract(DELETED_MESSAGE_RETENTION_PERIOD, "ms")
|
const botPostedAtThreshold = moment.utc().subtract(BOT_MESSAGE_RETENTION_PERIOD, "ms").format(DBDateFormat);
|
||||||
.format(DBDateFormat);
|
|
||||||
const postedAtThreshold = moment
|
|
||||||
.utc()
|
|
||||||
.subtract(RETENTION_PERIOD, "ms")
|
|
||||||
.format(DBDateFormat);
|
|
||||||
const botPostedAtThreshold = moment
|
|
||||||
.utc()
|
|
||||||
.subtract(BOT_MESSAGE_RETENTION_PERIOD, "ms")
|
|
||||||
.format(DBDateFormat);
|
|
||||||
|
|
||||||
// SELECT + DELETE messages in batches
|
// SELECT + DELETE messages in batches
|
||||||
// This is to avoid deadlocks that happened frequently when deleting with the same criteria as the select below
|
// This is to avoid deadlocks that happened frequently when deleting with the same criteria as the select below
|
||||||
|
@ -60,7 +51,7 @@ export async function cleanupMessages(): Promise<number> {
|
||||||
|
|
||||||
if (rows.length > 0) {
|
if (rows.length > 0) {
|
||||||
await messagesRepository.delete({
|
await messagesRepository.delete({
|
||||||
id: In(rows.map(r => r.id)),
|
id: In(rows.map((r) => r.id)),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -11,10 +11,7 @@ export async function cleanupNicknames(): Promise<number> {
|
||||||
let cleaned = 0;
|
let cleaned = 0;
|
||||||
|
|
||||||
const nicknameHistoryRepository = getRepository(NicknameHistoryEntry);
|
const nicknameHistoryRepository = getRepository(NicknameHistoryEntry);
|
||||||
const dateThreshold = moment
|
const dateThreshold = moment.utc().subtract(NICKNAME_RETENTION_PERIOD, "ms").format(DBDateFormat);
|
||||||
.utc()
|
|
||||||
.subtract(NICKNAME_RETENTION_PERIOD, "ms")
|
|
||||||
.format(DBDateFormat);
|
|
||||||
|
|
||||||
// Clean old nicknames (NICKNAME_RETENTION_PERIOD)
|
// Clean old nicknames (NICKNAME_RETENTION_PERIOD)
|
||||||
let rows;
|
let rows;
|
||||||
|
@ -31,7 +28,7 @@ export async function cleanupNicknames(): Promise<number> {
|
||||||
|
|
||||||
if (rows.length > 0) {
|
if (rows.length > 0) {
|
||||||
await nicknameHistoryRepository.delete({
|
await nicknameHistoryRepository.delete({
|
||||||
id: In(rows.map(r => r.id)),
|
id: In(rows.map((r) => r.id)),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -11,10 +11,7 @@ export async function cleanupUsernames(): Promise<number> {
|
||||||
let cleaned = 0;
|
let cleaned = 0;
|
||||||
|
|
||||||
const usernameHistoryRepository = getRepository(UsernameHistoryEntry);
|
const usernameHistoryRepository = getRepository(UsernameHistoryEntry);
|
||||||
const dateThreshold = moment
|
const dateThreshold = moment.utc().subtract(USERNAME_RETENTION_PERIOD, "ms").format(DBDateFormat);
|
||||||
.utc()
|
|
||||||
.subtract(USERNAME_RETENTION_PERIOD, "ms")
|
|
||||||
.format(DBDateFormat);
|
|
||||||
|
|
||||||
// Clean old usernames (USERNAME_RETENTION_PERIOD)
|
// Clean old usernames (USERNAME_RETENTION_PERIOD)
|
||||||
let rows;
|
let rows;
|
||||||
|
@ -31,7 +28,7 @@ export async function cleanupUsernames(): Promise<number> {
|
||||||
|
|
||||||
if (rows.length > 0) {
|
if (rows.length > 0) {
|
||||||
await usernameHistoryRepository.delete({
|
await usernameHistoryRepository.delete({
|
||||||
id: In(rows.map(r => r.id)),
|
id: In(rows.map((r) => r.id)),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -7,9 +7,9 @@ export let connection: Connection;
|
||||||
|
|
||||||
export function connect() {
|
export function connect() {
|
||||||
if (!connectionPromise) {
|
if (!connectionPromise) {
|
||||||
connectionPromise = createConnection().then(newConnection => {
|
connectionPromise = createConnection().then((newConnection) => {
|
||||||
// Verify the DB timezone is set to UTC
|
// Verify the DB timezone is set to UTC
|
||||||
return newConnection.query("SELECT TIMEDIFF(NOW(), UTC_TIMESTAMP) AS tz").then(r => {
|
return newConnection.query("SELECT TIMEDIFF(NOW(), UTC_TIMESTAMP) AS tz").then((r) => {
|
||||||
if (r[0].tz !== "00:00:00") {
|
if (r[0].tz !== "00:00:00") {
|
||||||
throw new SimpleError(`Database timezone must be UTC (detected ${r[0].tz})`);
|
throw new SimpleError(`Database timezone must be UTC (detected ${r[0].tz})`);
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,10 +19,7 @@ export class ApiLogin {
|
||||||
@Column()
|
@Column()
|
||||||
expires_at: string;
|
expires_at: string;
|
||||||
|
|
||||||
@ManyToOne(
|
@ManyToOne((type) => ApiUserInfo, (userInfo) => userInfo.logins)
|
||||||
type => ApiUserInfo,
|
|
||||||
userInfo => userInfo.logins,
|
|
||||||
)
|
|
||||||
@JoinColumn({ name: "user_id" })
|
@JoinColumn({ name: "user_id" })
|
||||||
userInfo: ApiUserInfo;
|
userInfo: ApiUserInfo;
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,10 +22,7 @@ export class ApiPermissionAssignment {
|
||||||
@Column({ type: String, nullable: true })
|
@Column({ type: String, nullable: true })
|
||||||
expires_at: string | null;
|
expires_at: string | null;
|
||||||
|
|
||||||
@ManyToOne(
|
@ManyToOne((type) => ApiUserInfo, (userInfo) => userInfo.permissionAssignments)
|
||||||
type => ApiUserInfo,
|
|
||||||
userInfo => userInfo.permissionAssignments,
|
|
||||||
)
|
|
||||||
@JoinColumn({ name: "target_id" })
|
@JoinColumn({ name: "target_id" })
|
||||||
userInfo: ApiUserInfo;
|
userInfo: ApiUserInfo;
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,15 +20,9 @@ export class ApiUserInfo {
|
||||||
@Column()
|
@Column()
|
||||||
updated_at: string;
|
updated_at: string;
|
||||||
|
|
||||||
@OneToMany(
|
@OneToMany((type) => ApiLogin, (login) => login.userInfo)
|
||||||
type => ApiLogin,
|
|
||||||
login => login.userInfo,
|
|
||||||
)
|
|
||||||
logins: ApiLogin[];
|
logins: ApiLogin[];
|
||||||
|
|
||||||
@OneToMany(
|
@OneToMany((type) => ApiPermissionAssignment, (p) => p.userInfo)
|
||||||
type => ApiPermissionAssignment,
|
|
||||||
p => p.userInfo,
|
|
||||||
)
|
|
||||||
permissionAssignments: ApiPermissionAssignment[];
|
permissionAssignments: ApiPermissionAssignment[];
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,9 +35,6 @@ export class Case {
|
||||||
*/
|
*/
|
||||||
@Column({ type: String, nullable: true }) log_message_id: string | null;
|
@Column({ type: String, nullable: true }) log_message_id: string | null;
|
||||||
|
|
||||||
@OneToMany(
|
@OneToMany((type) => CaseNote, (note) => note.case)
|
||||||
type => CaseNote,
|
|
||||||
note => note.case,
|
|
||||||
)
|
|
||||||
notes: CaseNote[];
|
notes: CaseNote[];
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,10 +15,7 @@ export class CaseNote {
|
||||||
|
|
||||||
@Column() created_at: string;
|
@Column() created_at: string;
|
||||||
|
|
||||||
@ManyToOne(
|
@ManyToOne((type) => Case, (theCase) => theCase.notes)
|
||||||
type => Case,
|
|
||||||
theCase => theCase.notes,
|
|
||||||
)
|
|
||||||
@JoinColumn({ name: "case_id" })
|
@JoinColumn({ name: "case_id" })
|
||||||
case: Case;
|
case: Case;
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,7 +22,7 @@ export class Config {
|
||||||
@Column()
|
@Column()
|
||||||
edited_at: string;
|
edited_at: string;
|
||||||
|
|
||||||
@ManyToOne(type => ApiUserInfo)
|
@ManyToOne((type) => ApiUserInfo)
|
||||||
@JoinColumn({ name: "edited_by" })
|
@JoinColumn({ name: "edited_by" })
|
||||||
userInfo: ApiUserInfo;
|
userInfo: ApiUserInfo;
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,7 +16,7 @@ export class StarboardMessage {
|
||||||
@Column()
|
@Column()
|
||||||
guild_id: string;
|
guild_id: string;
|
||||||
|
|
||||||
@OneToOne(type => SavedMessage)
|
@OneToOne((type) => SavedMessage)
|
||||||
@JoinColumn({ name: "message_id" })
|
@JoinColumn({ name: "message_id" })
|
||||||
message: SavedMessage;
|
message: SavedMessage;
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,7 +16,7 @@ export class StarboardReaction {
|
||||||
@Column()
|
@Column()
|
||||||
reactor_id: string;
|
reactor_id: string;
|
||||||
|
|
||||||
@OneToOne(type => SavedMessage)
|
@OneToOne((type) => SavedMessage)
|
||||||
@JoinColumn({ name: "message_id" })
|
@JoinColumn({ name: "message_id" })
|
||||||
message: SavedMessage;
|
message: SavedMessage;
|
||||||
}
|
}
|
||||||
|
|
|
@ -144,8 +144,8 @@ if (process.env.NODE_ENV === "production") {
|
||||||
|
|
||||||
// Verify required Node.js version
|
// Verify required Node.js version
|
||||||
const REQUIRED_NODE_VERSION = "14.0.0";
|
const REQUIRED_NODE_VERSION = "14.0.0";
|
||||||
const requiredParts = REQUIRED_NODE_VERSION.split(".").map(v => parseInt(v, 10));
|
const requiredParts = REQUIRED_NODE_VERSION.split(".").map((v) => parseInt(v, 10));
|
||||||
const actualVersionParts = process.versions.node.split(".").map(v => parseInt(v, 10));
|
const actualVersionParts = process.versions.node.split(".").map((v) => parseInt(v, 10));
|
||||||
for (const [i, part] of actualVersionParts.entries()) {
|
for (const [i, part] of actualVersionParts.entries()) {
|
||||||
if (part > requiredParts[i]) break;
|
if (part > requiredParts[i]) break;
|
||||||
if (part === requiredParts[i]) continue;
|
if (part === requiredParts[i]) continue;
|
||||||
|
@ -188,7 +188,7 @@ connect().then(async () => {
|
||||||
});
|
});
|
||||||
client.setMaxListeners(200);
|
client.setMaxListeners(200);
|
||||||
|
|
||||||
client.on(Constants.Events.RATE_LIMIT, data => {
|
client.on(Constants.Events.RATE_LIMIT, (data) => {
|
||||||
// tslint:disable-next-line:no-console
|
// tslint:disable-next-line:no-console
|
||||||
// console.log(`[DEBUG] [RATE_LIMIT] ${JSON.stringify(data)}`);
|
// console.log(`[DEBUG] [RATE_LIMIT] ${JSON.stringify(data)}`);
|
||||||
});
|
});
|
||||||
|
@ -196,7 +196,7 @@ connect().then(async () => {
|
||||||
const safe429DecayInterval = 5 * SECONDS;
|
const safe429DecayInterval = 5 * SECONDS;
|
||||||
const safe429MaxCount = 5;
|
const safe429MaxCount = 5;
|
||||||
const safe429Counter = new DecayingCounter(safe429DecayInterval);
|
const safe429Counter = new DecayingCounter(safe429DecayInterval);
|
||||||
client.on(Constants.Events.DEBUG, errorText => {
|
client.on(Constants.Events.DEBUG, (errorText) => {
|
||||||
if (!errorText.includes("429")) {
|
if (!errorText.includes("429")) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -212,7 +212,7 @@ connect().then(async () => {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
client.on("error", err => {
|
client.on("error", (err) => {
|
||||||
errorHandler(new DiscordJSError(err.message, (err as any).code, 0));
|
errorHandler(new DiscordJSError(err.message, (err as any).code, 0));
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -240,9 +240,9 @@ connect().then(async () => {
|
||||||
}
|
}
|
||||||
|
|
||||||
const configuredPlugins = ctx.config.plugins;
|
const configuredPlugins = ctx.config.plugins;
|
||||||
const basePluginNames = baseGuildPlugins.map(p => p.name);
|
const basePluginNames = baseGuildPlugins.map((p) => p.name);
|
||||||
|
|
||||||
return Array.from(plugins.keys()).filter(pluginName => {
|
return Array.from(plugins.keys()).filter((pluginName) => {
|
||||||
if (basePluginNames.includes(pluginName)) return true;
|
if (basePluginNames.includes(pluginName)) return true;
|
||||||
return configuredPlugins[pluginName] && configuredPlugins[pluginName].enabled !== false;
|
return configuredPlugins[pluginName] && configuredPlugins[pluginName].enabled !== false;
|
||||||
});
|
});
|
||||||
|
@ -308,14 +308,14 @@ connect().then(async () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
const debugGuilds = ["877581055920603238", "348468156597010432", "134286179121102848"];
|
const debugGuilds = ["877581055920603238", "348468156597010432", "134286179121102848"];
|
||||||
bot.on("guildLoaded", guildId => {
|
bot.on("guildLoaded", (guildId) => {
|
||||||
if (!debugGuilds.includes(guildId)) {
|
if (!debugGuilds.includes(guildId)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log(`[!! DEBUG !!] LOADED GUILD ${guildId}`);
|
console.log(`[!! DEBUG !!] LOADED GUILD ${guildId}`);
|
||||||
});
|
});
|
||||||
bot.on("guildUnloaded", guildId => {
|
bot.on("guildUnloaded", (guildId) => {
|
||||||
if (!debugGuilds.includes(guildId)) {
|
if (!debugGuilds.includes(guildId)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,7 +9,7 @@ export class MigrateUsernamesToNewHistoryTable1556909512501 implements Migration
|
||||||
|
|
||||||
const migratedUsernames = new Set();
|
const migratedUsernames = new Set();
|
||||||
|
|
||||||
await new Promise(async resolve => {
|
await new Promise(async (resolve) => {
|
||||||
const stream = await queryRunner.stream("SELECT CONCAT(user_id, '-', username) AS `key` FROM username_history");
|
const stream = await queryRunner.stream("SELECT CONCAT(user_id, '-', username) AS `key` FROM username_history");
|
||||||
stream.on("data", (row: any) => {
|
stream.on("data", (row: any) => {
|
||||||
migratedUsernames.add(row.key);
|
migratedUsernames.add(row.key);
|
||||||
|
@ -18,7 +18,7 @@ export class MigrateUsernamesToNewHistoryTable1556909512501 implements Migration
|
||||||
});
|
});
|
||||||
|
|
||||||
const migrateNextBatch = (): Promise<{ finished: boolean; migrated?: number }> => {
|
const migrateNextBatch = (): Promise<{ finished: boolean; migrated?: number }> => {
|
||||||
return new Promise(async resolve => {
|
return new Promise(async (resolve) => {
|
||||||
const toInsert: any[][] = [];
|
const toInsert: any[][] = [];
|
||||||
const toDelete: number[] = [];
|
const toDelete: number[] = [];
|
||||||
|
|
||||||
|
|
|
@ -85,7 +85,7 @@ export function strictValidationErrorToConfigValidationError(err: StrictValidati
|
||||||
return new ConfigValidationError(
|
return new ConfigValidationError(
|
||||||
err
|
err
|
||||||
.getErrors()
|
.getErrors()
|
||||||
.map(e => e.toString())
|
.map((e) => e.toString())
|
||||||
.join("\n"),
|
.join("\n"),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -199,7 +199,7 @@ export async function sendSuccessMessage(
|
||||||
|
|
||||||
return channel
|
return channel
|
||||||
.send({ ...content }) // Force line break
|
.send({ ...content }) // Force line break
|
||||||
.catch(err => {
|
.catch((err) => {
|
||||||
const channelInfo = channel.guild ? `${channel.id} (${channel.guild.id})` : channel.id;
|
const channelInfo = channel.guild ? `${channel.id} (${channel.guild.id})` : channel.id;
|
||||||
logger.warn(`Failed to send success message to ${channelInfo}): ${err.code} ${err.message}`);
|
logger.warn(`Failed to send success message to ${channelInfo}): ${err.code} ${err.message}`);
|
||||||
return undefined;
|
return undefined;
|
||||||
|
@ -220,7 +220,7 @@ export async function sendErrorMessage(
|
||||||
|
|
||||||
return channel
|
return channel
|
||||||
.send({ ...content }) // Force line break
|
.send({ ...content }) // Force line break
|
||||||
.catch(err => {
|
.catch((err) => {
|
||||||
const channelInfo = channel.guild ? `${channel.id} (${channel.guild.id})` : channel.id;
|
const channelInfo = channel.guild ? `${channel.id} (${channel.guild.id})` : channel.id;
|
||||||
logger.warn(`Failed to send error message to ${channelInfo}): ${err.code} ${err.message}`);
|
logger.warn(`Failed to send error message to ${channelInfo}): ${err.code} ${err.message}`);
|
||||||
return undefined;
|
return undefined;
|
||||||
|
@ -252,7 +252,7 @@ type AnyFn = (...args: any[]) => any;
|
||||||
* Creates a public plugin function out of a function with pluginData as the first parameter
|
* Creates a public plugin function out of a function with pluginData as the first parameter
|
||||||
*/
|
*/
|
||||||
export function mapToPublicFn<T extends AnyFn>(inputFn: T) {
|
export function mapToPublicFn<T extends AnyFn>(inputFn: T) {
|
||||||
return pluginData => {
|
return (pluginData) => {
|
||||||
return (...args: Tail<Parameters<typeof inputFn>>): ReturnType<typeof inputFn> => {
|
return (...args: Tail<Parameters<typeof inputFn>>): ReturnType<typeof inputFn> => {
|
||||||
return inputFn(pluginData, ...args);
|
return inputFn(pluginData, ...args);
|
||||||
};
|
};
|
||||||
|
|
|
@ -45,13 +45,13 @@ export const AutoDeletePlugin = zeppelinGuildPlugin<AutoDeletePluginType>()({
|
||||||
afterLoad(pluginData) {
|
afterLoad(pluginData) {
|
||||||
const { state, guild } = pluginData;
|
const { state, guild } = pluginData;
|
||||||
|
|
||||||
state.onMessageCreateFn = msg => onMessageCreate(pluginData, msg);
|
state.onMessageCreateFn = (msg) => onMessageCreate(pluginData, msg);
|
||||||
state.guildSavedMessages.events.on("create", state.onMessageCreateFn);
|
state.guildSavedMessages.events.on("create", state.onMessageCreateFn);
|
||||||
|
|
||||||
state.onMessageDeleteFn = msg => onMessageDelete(pluginData, msg);
|
state.onMessageDeleteFn = (msg) => onMessageDelete(pluginData, msg);
|
||||||
state.guildSavedMessages.events.on("delete", state.onMessageDeleteFn);
|
state.guildSavedMessages.events.on("delete", state.onMessageDeleteFn);
|
||||||
|
|
||||||
state.onMessageDeleteBulkFn = msgs => onMessageDeleteBulk(pluginData, msgs);
|
state.onMessageDeleteBulkFn = (msgs) => onMessageDeleteBulk(pluginData, msgs);
|
||||||
state.guildSavedMessages.events.on("deleteBulk", state.onMessageDeleteBulkFn);
|
state.guildSavedMessages.events.on("deleteBulk", state.onMessageDeleteBulkFn);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
|
@ -45,7 +45,7 @@ export async function deleteNextItem(pluginData: GuildPluginData<AutoDeletePlugi
|
||||||
const timeAndDate = pluginData.getPlugin(TimeAndDatePlugin);
|
const timeAndDate = pluginData.getPlugin(TimeAndDatePlugin);
|
||||||
|
|
||||||
pluginData.state.guildLogs.ignoreLog(LogType.MESSAGE_DELETE, itemToDelete.message.id);
|
pluginData.state.guildLogs.ignoreLog(LogType.MESSAGE_DELETE, itemToDelete.message.id);
|
||||||
(channel as TextChannel).messages.delete(itemToDelete.message.id as Snowflake).catch(err => {
|
(channel as TextChannel).messages.delete(itemToDelete.message.id as Snowflake).catch((err) => {
|
||||||
if (err.code === 10008) {
|
if (err.code === 10008) {
|
||||||
// "Unknown Message", probably already deleted by automod or another bot, ignore
|
// "Unknown Message", probably already deleted by automod or another bot, ignore
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -4,7 +4,7 @@ import { AutoDeletePluginType } from "../types";
|
||||||
import { scheduleNextDeletion } from "./scheduleNextDeletion";
|
import { scheduleNextDeletion } from "./scheduleNextDeletion";
|
||||||
|
|
||||||
export function onMessageDelete(pluginData: GuildPluginData<AutoDeletePluginType>, msg: SavedMessage) {
|
export function onMessageDelete(pluginData: GuildPluginData<AutoDeletePluginType>, msg: SavedMessage) {
|
||||||
const indexToDelete = pluginData.state.deletionQueue.findIndex(item => item.message.id === msg.id);
|
const indexToDelete = pluginData.state.deletionQueue.findIndex((item) => item.message.id === msg.id);
|
||||||
if (indexToDelete > -1) {
|
if (indexToDelete > -1) {
|
||||||
pluginData.state.deletionQueue.splice(indexToDelete, 1);
|
pluginData.state.deletionQueue.splice(indexToDelete, 1);
|
||||||
scheduleNextDeletion(pluginData);
|
scheduleNextDeletion(pluginData);
|
||||||
|
|
|
@ -57,7 +57,7 @@ const defaultOptions = {
|
||||||
/**
|
/**
|
||||||
* Config preprocessor to set default values for triggers and perform extra validation
|
* Config preprocessor to set default values for triggers and perform extra validation
|
||||||
*/
|
*/
|
||||||
const configPreprocessor: ConfigPreprocessorFn<AutomodPluginType> = options => {
|
const configPreprocessor: ConfigPreprocessorFn<AutomodPluginType> = (options) => {
|
||||||
if (options.config?.rules) {
|
if (options.config?.rules) {
|
||||||
// Loop through each rule
|
// Loop through each rule
|
||||||
for (const [name, rule] of Object.entries(options.config.rules)) {
|
for (const [name, rule] of Object.entries(options.config.rules)) {
|
||||||
|
@ -232,10 +232,10 @@ export const AutomodPlugin = zeppelinGuildPlugin<AutomodPluginType>()({
|
||||||
30 * SECONDS,
|
30 * SECONDS,
|
||||||
);
|
);
|
||||||
|
|
||||||
pluginData.state.onMessageCreateFn = message => runAutomodOnMessage(pluginData, message, false);
|
pluginData.state.onMessageCreateFn = (message) => runAutomodOnMessage(pluginData, message, false);
|
||||||
pluginData.state.savedMessages.events.on("create", pluginData.state.onMessageCreateFn);
|
pluginData.state.savedMessages.events.on("create", pluginData.state.onMessageCreateFn);
|
||||||
|
|
||||||
pluginData.state.onMessageUpdateFn = message => runAutomodOnMessage(pluginData, message, true);
|
pluginData.state.onMessageUpdateFn = (message) => runAutomodOnMessage(pluginData, message, true);
|
||||||
pluginData.state.savedMessages.events.on("update", pluginData.state.onMessageUpdateFn);
|
pluginData.state.savedMessages.events.on("update", pluginData.state.onMessageUpdateFn);
|
||||||
|
|
||||||
const countersPlugin = pluginData.getPlugin(CountersPlugin);
|
const countersPlugin = pluginData.getPlugin(CountersPlugin);
|
||||||
|
|
|
@ -17,7 +17,7 @@ export const AddRolesAction = automodAction({
|
||||||
defaultConfig: [],
|
defaultConfig: [],
|
||||||
|
|
||||||
async apply({ pluginData, contexts, actionConfig, ruleName }) {
|
async apply({ pluginData, contexts, actionConfig, ruleName }) {
|
||||||
const members = unique(contexts.map(c => c.member).filter(nonNullish));
|
const members = unique(contexts.map((c) => c.member).filter(nonNullish));
|
||||||
const me = pluginData.guild.members.cache.get(pluginData.client.user!.id)!;
|
const me = pluginData.guild.members.cache.get(pluginData.client.user!.id)!;
|
||||||
|
|
||||||
const missingPermissions = getMissingPermissions(me.permissions, p.MANAGE_ROLES);
|
const missingPermissions = getMissingPermissions(me.permissions, p.MANAGE_ROLES);
|
||||||
|
@ -41,7 +41,7 @@ export const AddRolesAction = automodAction({
|
||||||
|
|
||||||
if (rolesWeCannotAssign.length) {
|
if (rolesWeCannotAssign.length) {
|
||||||
const roleNamesWeCannotAssign = rolesWeCannotAssign.map(
|
const roleNamesWeCannotAssign = rolesWeCannotAssign.map(
|
||||||
roleId => pluginData.guild.roles.cache.get(roleId as Snowflake)?.name || roleId,
|
(roleId) => pluginData.guild.roles.cache.get(roleId as Snowflake)?.name || roleId,
|
||||||
);
|
);
|
||||||
const logs = pluginData.getPlugin(LogsPlugin);
|
const logs = pluginData.getPlugin(LogsPlugin);
|
||||||
logs.logBotAlert({
|
logs.logBotAlert({
|
||||||
|
@ -52,7 +52,7 @@ export const AddRolesAction = automodAction({
|
||||||
}
|
}
|
||||||
|
|
||||||
await Promise.all(
|
await Promise.all(
|
||||||
members.map(async member => {
|
members.map(async (member) => {
|
||||||
const memberRoles = new Set(member.roles.cache.keys());
|
const memberRoles = new Set(member.roles.cache.keys());
|
||||||
for (const roleId of rolesToAssign) {
|
for (const roleId of rolesToAssign) {
|
||||||
memberRoles.add(roleId as Snowflake);
|
memberRoles.add(roleId as Snowflake);
|
||||||
|
|
|
@ -41,7 +41,7 @@ export const AlertAction = automodAction({
|
||||||
const theMessageLink =
|
const theMessageLink =
|
||||||
contexts[0].message && messageLink(pluginData.guild.id, contexts[0].message.channel_id, contexts[0].message.id);
|
contexts[0].message && messageLink(pluginData.guild.id, contexts[0].message.channel_id, contexts[0].message.id);
|
||||||
|
|
||||||
const safeUsers = contexts.map(c => (c.user ? userToTemplateSafeUser(c.user) : null)).filter(isTruthy);
|
const safeUsers = contexts.map((c) => (c.user ? userToTemplateSafeUser(c.user) : null)).filter(isTruthy);
|
||||||
const safeUser = safeUsers[0];
|
const safeUser = safeUsers[0];
|
||||||
const actionsTaken = Object.keys(pluginData.config.get().rules[ruleName].actions).join(", ");
|
const actionsTaken = Object.keys(pluginData.config.get().rules[ruleName].actions).join(", ");
|
||||||
|
|
||||||
|
|
|
@ -9,8 +9,8 @@ export const ArchiveThreadAction = automodAction({
|
||||||
|
|
||||||
async apply({ pluginData, contexts }) {
|
async apply({ pluginData, contexts }) {
|
||||||
const threads = contexts
|
const threads = contexts
|
||||||
.filter(c => c.message?.channel_id)
|
.filter((c) => c.message?.channel_id)
|
||||||
.map(c => pluginData.guild.channels.cache.get(c.message!.channel_id))
|
.map((c) => pluginData.guild.channels.cache.get(c.message!.channel_id))
|
||||||
.filter((c): c is ThreadChannel => c?.isThread() ?? false);
|
.filter((c): c is ThreadChannel => c?.isThread() ?? false);
|
||||||
|
|
||||||
for (const thread of threads) {
|
for (const thread of threads) {
|
||||||
|
|
|
@ -35,7 +35,7 @@ export const BanAction = automodAction({
|
||||||
hide: Boolean(actionConfig.hide_case),
|
hide: Boolean(actionConfig.hide_case),
|
||||||
};
|
};
|
||||||
|
|
||||||
const userIdsToBan = unique(contexts.map(c => c.user?.id).filter(nonNullish));
|
const userIdsToBan = unique(contexts.map((c) => c.user?.id).filter(nonNullish));
|
||||||
|
|
||||||
const modActions = pluginData.getPlugin(ModActionsPlugin);
|
const modActions = pluginData.getPlugin(ModActionsPlugin);
|
||||||
for (const userId of userIdsToBan) {
|
for (const userId of userIdsToBan) {
|
||||||
|
|
|
@ -15,13 +15,13 @@ export const ChangeNicknameAction = automodAction({
|
||||||
defaultConfig: {},
|
defaultConfig: {},
|
||||||
|
|
||||||
async apply({ pluginData, contexts, actionConfig }) {
|
async apply({ pluginData, contexts, actionConfig }) {
|
||||||
const members = unique(contexts.map(c => c.member).filter(nonNullish));
|
const members = unique(contexts.map((c) => c.member).filter(nonNullish));
|
||||||
|
|
||||||
for (const member of members) {
|
for (const member of members) {
|
||||||
if (pluginData.state.recentNicknameChanges.has(member.id)) continue;
|
if (pluginData.state.recentNicknameChanges.has(member.id)) continue;
|
||||||
const newName = typeof actionConfig === "string" ? actionConfig : actionConfig.name;
|
const newName = typeof actionConfig === "string" ? actionConfig : actionConfig.name;
|
||||||
|
|
||||||
member.edit({ nick: newName }).catch(err => {
|
member.edit({ nick: newName }).catch((err) => {
|
||||||
pluginData.getPlugin(LogsPlugin).logBotAlert({
|
pluginData.getPlugin(LogsPlugin).logBotAlert({
|
||||||
body: `Failed to change the nickname of \`${member.id}\``,
|
body: `Failed to change the nickname of \`${member.id}\``,
|
||||||
});
|
});
|
||||||
|
|
|
@ -31,8 +31,8 @@ export const KickAction = automodAction({
|
||||||
hide: Boolean(actionConfig.hide_case),
|
hide: Boolean(actionConfig.hide_case),
|
||||||
};
|
};
|
||||||
|
|
||||||
const userIdsToKick = unique(contexts.map(c => c.user?.id).filter(nonNullish));
|
const userIdsToKick = unique(contexts.map((c) => c.user?.id).filter(nonNullish));
|
||||||
const membersToKick = await asyncMap(userIdsToKick, id => resolveMember(pluginData.client, pluginData.guild, id));
|
const membersToKick = await asyncMap(userIdsToKick, (id) => resolveMember(pluginData.client, pluginData.guild, id));
|
||||||
|
|
||||||
const modActions = pluginData.getPlugin(ModActionsPlugin);
|
const modActions = pluginData.getPlugin(ModActionsPlugin);
|
||||||
for (const member of membersToKick) {
|
for (const member of membersToKick) {
|
||||||
|
|
|
@ -10,7 +10,7 @@ export const LogAction = automodAction({
|
||||||
defaultConfig: true,
|
defaultConfig: true,
|
||||||
|
|
||||||
async apply({ pluginData, contexts, ruleName, matchResult }) {
|
async apply({ pluginData, contexts, ruleName, matchResult }) {
|
||||||
const users = unique(contexts.map(c => c.user)).filter(isTruthy);
|
const users = unique(contexts.map((c) => c.user)).filter(isTruthy);
|
||||||
const user = users[0];
|
const user = users[0];
|
||||||
const actionsTaken = Object.keys(pluginData.config.get().rules[ruleName].actions).join(", ");
|
const actionsTaken = Object.keys(pluginData.config.get().rules[ruleName].actions).join(", ");
|
||||||
|
|
||||||
|
|
|
@ -40,7 +40,7 @@ export const MuteAction = automodAction({
|
||||||
hide: Boolean(actionConfig.hide_case),
|
hide: Boolean(actionConfig.hide_case),
|
||||||
};
|
};
|
||||||
|
|
||||||
const userIdsToMute = unique(contexts.map(c => c.user?.id).filter(nonNullish));
|
const userIdsToMute = unique(contexts.map((c) => c.user?.id).filter(nonNullish));
|
||||||
|
|
||||||
const mutes = pluginData.getPlugin(MutesPlugin);
|
const mutes = pluginData.getPlugin(MutesPlugin);
|
||||||
for (const userId of userIdsToMute) {
|
for (const userId of userIdsToMute) {
|
||||||
|
|
|
@ -18,7 +18,7 @@ export const RemoveRolesAction = automodAction({
|
||||||
defaultConfig: [],
|
defaultConfig: [],
|
||||||
|
|
||||||
async apply({ pluginData, contexts, actionConfig, ruleName }) {
|
async apply({ pluginData, contexts, actionConfig, ruleName }) {
|
||||||
const members = unique(contexts.map(c => c.member).filter(nonNullish));
|
const members = unique(contexts.map((c) => c.member).filter(nonNullish));
|
||||||
const me = pluginData.guild.members.cache.get(pluginData.client.user!.id)!;
|
const me = pluginData.guild.members.cache.get(pluginData.client.user!.id)!;
|
||||||
|
|
||||||
const missingPermissions = getMissingPermissions(me.permissions, p.MANAGE_ROLES);
|
const missingPermissions = getMissingPermissions(me.permissions, p.MANAGE_ROLES);
|
||||||
|
@ -42,7 +42,7 @@ export const RemoveRolesAction = automodAction({
|
||||||
|
|
||||||
if (rolesWeCannotRemove.length) {
|
if (rolesWeCannotRemove.length) {
|
||||||
const roleNamesWeCannotRemove = rolesWeCannotRemove.map(
|
const roleNamesWeCannotRemove = rolesWeCannotRemove.map(
|
||||||
roleId => pluginData.guild.roles.cache.get(roleId as Snowflake)?.name || roleId,
|
(roleId) => pluginData.guild.roles.cache.get(roleId as Snowflake)?.name || roleId,
|
||||||
);
|
);
|
||||||
const logs = pluginData.getPlugin(LogsPlugin);
|
const logs = pluginData.getPlugin(LogsPlugin);
|
||||||
logs.logBotAlert({
|
logs.logBotAlert({
|
||||||
|
@ -53,7 +53,7 @@ export const RemoveRolesAction = automodAction({
|
||||||
}
|
}
|
||||||
|
|
||||||
await Promise.all(
|
await Promise.all(
|
||||||
members.map(async member => {
|
members.map(async (member) => {
|
||||||
const memberRoles = new Set(member.roles.cache.keys());
|
const memberRoles = new Set(member.roles.cache.keys());
|
||||||
for (const roleId of rolesToRemove) {
|
for (const roleId of rolesToRemove) {
|
||||||
memberRoles.delete(roleId as Snowflake);
|
memberRoles.delete(roleId as Snowflake);
|
||||||
|
|
|
@ -32,8 +32,8 @@ export const ReplyAction = automodAction({
|
||||||
|
|
||||||
async apply({ pluginData, contexts, actionConfig, ruleName }) {
|
async apply({ pluginData, contexts, actionConfig, ruleName }) {
|
||||||
const contextsWithTextChannels = contexts
|
const contextsWithTextChannels = contexts
|
||||||
.filter(c => c.message?.channel_id)
|
.filter((c) => c.message?.channel_id)
|
||||||
.filter(c => {
|
.filter((c) => {
|
||||||
const channel = pluginData.guild.channels.cache.get(c.message!.channel_id as Snowflake);
|
const channel = pluginData.guild.channels.cache.get(c.message!.channel_id as Snowflake);
|
||||||
return channel instanceof TextChannel || channel instanceof ThreadChannel;
|
return channel instanceof TextChannel || channel instanceof ThreadChannel;
|
||||||
});
|
});
|
||||||
|
@ -48,7 +48,7 @@ export const ReplyAction = automodAction({
|
||||||
}, new Map());
|
}, new Map());
|
||||||
|
|
||||||
for (const [channelId, _contexts] of contextsByChannelId.entries()) {
|
for (const [channelId, _contexts] of contextsByChannelId.entries()) {
|
||||||
const users = unique(Array.from(new Set(_contexts.map(c => c.user).filter(Boolean)))) as User[];
|
const users = unique(Array.from(new Set(_contexts.map((c) => c.user).filter(Boolean)))) as User[];
|
||||||
const user = users[0];
|
const user = users[0];
|
||||||
|
|
||||||
const renderReplyText = async (str: string) =>
|
const renderReplyText = async (str: string) =>
|
||||||
|
|
|
@ -31,8 +31,8 @@ export const WarnAction = automodAction({
|
||||||
hide: Boolean(actionConfig.hide_case),
|
hide: Boolean(actionConfig.hide_case),
|
||||||
};
|
};
|
||||||
|
|
||||||
const userIdsToWarn = unique(contexts.map(c => c.user?.id).filter(nonNullish));
|
const userIdsToWarn = unique(contexts.map((c) => c.user?.id).filter(nonNullish));
|
||||||
const membersToWarn = await asyncMap(userIdsToWarn, id => resolveMember(pluginData.client, pluginData.guild, id));
|
const membersToWarn = await asyncMap(userIdsToWarn, (id) => resolveMember(pluginData.client, pluginData.guild, id));
|
||||||
|
|
||||||
const modActions = pluginData.getPlugin(ModActionsPlugin);
|
const modActions = pluginData.getPlugin(ModActionsPlugin);
|
||||||
for (const member of membersToWarn) {
|
for (const member of membersToWarn) {
|
||||||
|
|
|
@ -4,7 +4,7 @@ import { AutomodPluginType } from "../types";
|
||||||
|
|
||||||
export function clearOldRecentActions(pluginData: GuildPluginData<AutomodPluginType>) {
|
export function clearOldRecentActions(pluginData: GuildPluginData<AutomodPluginType>) {
|
||||||
const now = Date.now();
|
const now = Date.now();
|
||||||
pluginData.state.recentActions = pluginData.state.recentActions.filter(info => {
|
pluginData.state.recentActions = pluginData.state.recentActions.filter((info) => {
|
||||||
return info.context.timestamp + RECENT_ACTION_EXPIRY_TIME > now;
|
return info.context.timestamp + RECENT_ACTION_EXPIRY_TIME > now;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,7 +4,7 @@ import { AutomodPluginType } from "../types";
|
||||||
|
|
||||||
export function clearOldRecentSpam(pluginData: GuildPluginData<AutomodPluginType>) {
|
export function clearOldRecentSpam(pluginData: GuildPluginData<AutomodPluginType>) {
|
||||||
const now = Date.now();
|
const now = Date.now();
|
||||||
pluginData.state.recentSpam = pluginData.state.recentSpam.filter(spam => {
|
pluginData.state.recentSpam = pluginData.state.recentSpam.filter((spam) => {
|
||||||
return spam.timestamp + RECENT_SPAM_EXPIRY_TIME > now;
|
return spam.timestamp + RECENT_SPAM_EXPIRY_TIME > now;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,7 +6,7 @@ export function clearRecentActionsForMessage(pluginData: GuildPluginData<Automod
|
||||||
const globalIdentifier = message.user_id;
|
const globalIdentifier = message.user_id;
|
||||||
const perChannelIdentifier = `${message.channel_id}-${message.user_id}`;
|
const perChannelIdentifier = `${message.channel_id}-${message.user_id}`;
|
||||||
|
|
||||||
pluginData.state.recentActions = pluginData.state.recentActions.filter(act => {
|
pluginData.state.recentActions = pluginData.state.recentActions.filter((act) => {
|
||||||
return act.identifier !== globalIdentifier && act.identifier !== perChannelIdentifier;
|
return act.identifier !== globalIdentifier && act.identifier !== perChannelIdentifier;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -60,7 +60,7 @@ export function createMessageSpamTrigger(spamType: RecentActionType, prettyName:
|
||||||
|
|
||||||
if (matchedSpam) {
|
if (matchedSpam) {
|
||||||
const messages = matchedSpam.recentActions
|
const messages = matchedSpam.recentActions
|
||||||
.map(action => action.context.message)
|
.map((action) => action.context.message)
|
||||||
.filter(Boolean)
|
.filter(Boolean)
|
||||||
.sort(sorter("posted_at")) as SavedMessage[];
|
.sort(sorter("posted_at")) as SavedMessage[];
|
||||||
|
|
||||||
|
@ -75,8 +75,8 @@ export function createMessageSpamTrigger(spamType: RecentActionType, prettyName:
|
||||||
|
|
||||||
return {
|
return {
|
||||||
extraContexts: matchedSpam.recentActions
|
extraContexts: matchedSpam.recentActions
|
||||||
.map(action => action.context)
|
.map((action) => action.context)
|
||||||
.filter(_context => _context !== context),
|
.filter((_context) => _context !== context),
|
||||||
|
|
||||||
extra: {
|
extra: {
|
||||||
archiveId,
|
archiveId,
|
||||||
|
|
|
@ -7,7 +7,7 @@ export function findRecentSpam(
|
||||||
type: RecentActionType,
|
type: RecentActionType,
|
||||||
identifier?: string,
|
identifier?: string,
|
||||||
) {
|
) {
|
||||||
return pluginData.state.recentSpam.find(spam => {
|
return pluginData.state.recentSpam.find((spam) => {
|
||||||
return spam.type === type && (!identifier || spam.identifiers.includes(identifier));
|
return spam.type === type && (!identifier || spam.identifiers.includes(identifier));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,7 +11,7 @@ export function getMatchingRecentActions(
|
||||||
) {
|
) {
|
||||||
to = to || Date.now();
|
to = to || Date.now();
|
||||||
|
|
||||||
return pluginData.state.recentActions.filter(action => {
|
return pluginData.state.recentActions.filter((action) => {
|
||||||
return (
|
return (
|
||||||
action.type === type &&
|
action.type === type &&
|
||||||
(!identifier || action.identifier === identifier) &&
|
(!identifier || action.identifier === identifier) &&
|
||||||
|
|
|
@ -29,6 +29,6 @@ export function getTextMatchPartialSummary(
|
||||||
const visibleName = context.member?.nickname || context.user!.username;
|
const visibleName = context.member?.nickname || context.user!.username;
|
||||||
return `visible name: ${visibleName}`;
|
return `visible name: ${visibleName}`;
|
||||||
} else if (type === "customstatus") {
|
} else if (type === "customstatus") {
|
||||||
return `custom status: ${context.member!.presence?.activities.find(a => a.type === "CUSTOM")?.name}`;
|
return `custom status: ${context.member!.presence?.activities.find((a) => a.type === "CUSTOM")?.name}`;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,7 +15,7 @@ export const ExampleTrigger = automodTrigger<ExampleMatchResultType>()({
|
||||||
},
|
},
|
||||||
|
|
||||||
async match({ triggerConfig, context }) {
|
async match({ triggerConfig, context }) {
|
||||||
const foundFruit = triggerConfig.allowedFruits.find(fruit => context.message?.data.content === fruit);
|
const foundFruit = triggerConfig.allowedFruits.find((fruit) => context.message?.data.content === fruit);
|
||||||
if (foundFruit) {
|
if (foundFruit) {
|
||||||
return {
|
return {
|
||||||
extra: {
|
extra: {
|
||||||
|
|
|
@ -33,13 +33,10 @@ export const MatchAttachmentTypeTrigger = automodTrigger<MatchResultType>()({
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const attachment of context.message.data.attachments) {
|
for (const attachment of context.message.data.attachments) {
|
||||||
const attachmentType = attachment.url
|
const attachmentType = attachment.url.split(".").pop()!.toLowerCase();
|
||||||
.split(".")
|
|
||||||
.pop()!
|
|
||||||
.toLowerCase();
|
|
||||||
|
|
||||||
const blacklist = trigger.blacklist_enabled
|
const blacklist = trigger.blacklist_enabled
|
||||||
? (trigger.filetype_blacklist || []).map(_t => _t.toLowerCase())
|
? (trigger.filetype_blacklist || []).map((_t) => _t.toLowerCase())
|
||||||
: null;
|
: null;
|
||||||
|
|
||||||
if (blacklist && blacklist.includes(attachmentType)) {
|
if (blacklist && blacklist.includes(attachmentType)) {
|
||||||
|
@ -52,7 +49,7 @@ export const MatchAttachmentTypeTrigger = automodTrigger<MatchResultType>()({
|
||||||
}
|
}
|
||||||
|
|
||||||
const whitelist = trigger.whitelist_enabled
|
const whitelist = trigger.whitelist_enabled
|
||||||
? (trigger.filetype_whitelist || []).map(_t => _t.toLowerCase())
|
? (trigger.filetype_whitelist || []).map((_t) => _t.toLowerCase())
|
||||||
: null;
|
: null;
|
||||||
|
|
||||||
if (whitelist && !whitelist.includes(attachmentType)) {
|
if (whitelist && !whitelist.includes(attachmentType)) {
|
||||||
|
|
|
@ -34,7 +34,7 @@ export const MatchMimeTypeTrigger = automodTrigger<MatchResultType>()({
|
||||||
const contentType = (rawContentType || "").split(";")[0]; // Remove "; charset=utf8" and similar from the end
|
const contentType = (rawContentType || "").split(";")[0]; // Remove "; charset=utf8" and similar from the end
|
||||||
|
|
||||||
const blacklist = trigger.blacklist_enabled
|
const blacklist = trigger.blacklist_enabled
|
||||||
? (trigger.mime_type_blacklist ?? []).map(_t => _t.toLowerCase())
|
? (trigger.mime_type_blacklist ?? []).map((_t) => _t.toLowerCase())
|
||||||
: null;
|
: null;
|
||||||
|
|
||||||
if (contentType && blacklist?.includes(contentType)) {
|
if (contentType && blacklist?.includes(contentType)) {
|
||||||
|
@ -47,7 +47,7 @@ export const MatchMimeTypeTrigger = automodTrigger<MatchResultType>()({
|
||||||
}
|
}
|
||||||
|
|
||||||
const whitelist = trigger.whitelist_enabled
|
const whitelist = trigger.whitelist_enabled
|
||||||
? (trigger.mime_type_whitelist ?? []).map(_t => _t.toLowerCase())
|
? (trigger.mime_type_whitelist ?? []).map((_t) => _t.toLowerCase())
|
||||||
: null;
|
: null;
|
||||||
|
|
||||||
if (whitelist && (!contentType || !whitelist.includes(contentType))) {
|
if (whitelist && (!contentType || !whitelist.includes(contentType))) {
|
||||||
|
|
|
@ -64,7 +64,7 @@ export const MatchWordsTrigger = automodTrigger<MatchResultType>()({
|
||||||
// When performing loose matching, allow any amount of whitespace or up to looseMatchingThreshold number of other
|
// When performing loose matching, allow any amount of whitespace or up to looseMatchingThreshold number of other
|
||||||
// characters between the matched characters. E.g. if we're matching banana, a loose match could also match b a n a n a
|
// characters between the matched characters. E.g. if we're matching banana, a loose match could also match b a n a n a
|
||||||
let pattern = trigger.loose_matching
|
let pattern = trigger.loose_matching
|
||||||
? [...word].map(c => escapeStringRegexp(c)).join(`(?:\\s*|.{0,${looseMatchingThreshold})`)
|
? [...word].map((c) => escapeStringRegexp(c)).join(`(?:\\s*|.{0,${looseMatchingThreshold})`)
|
||||||
: escapeStringRegexp(word);
|
: escapeStringRegexp(word);
|
||||||
|
|
||||||
if (trigger.only_full_words) {
|
if (trigger.only_full_words) {
|
||||||
|
|
|
@ -30,7 +30,7 @@ export const MemberJoinSpamTrigger = automodTrigger<unknown>()({
|
||||||
const totalCount = sumRecentActionCounts(matchingActions);
|
const totalCount = sumRecentActionCounts(matchingActions);
|
||||||
|
|
||||||
if (totalCount >= triggerConfig.amount) {
|
if (totalCount >= triggerConfig.amount) {
|
||||||
const extraContexts = matchingActions.map(a => a.context).filter(c => c !== context);
|
const extraContexts = matchingActions.map((a) => a.context).filter((c) => c !== context);
|
||||||
|
|
||||||
pluginData.state.recentSpam.push({
|
pluginData.state.recentSpam.push({
|
||||||
type: RecentActionType.MemberJoin,
|
type: RecentActionType.MemberJoin,
|
||||||
|
|
|
@ -35,7 +35,7 @@ export const AddDashboardUserCmd = botControlCmd({
|
||||||
await pluginData.state.apiPermissionAssignments.addUser(args.guildId, user.id, [ApiPermissions.EditConfig]);
|
await pluginData.state.apiPermissionAssignments.addUser(args.guildId, user.id, [ApiPermissions.EditConfig]);
|
||||||
}
|
}
|
||||||
|
|
||||||
const userNameList = args.users.map(user => `<@!${user.id}> (**${user.tag}**, \`${user.id}\`)`);
|
const userNameList = args.users.map((user) => `<@!${user.id}> (**${user.tag}**, \`${user.id}\`)`);
|
||||||
sendSuccessMessage(
|
sendSuccessMessage(
|
||||||
pluginData,
|
pluginData,
|
||||||
msg.channel as TextChannel,
|
msg.channel as TextChannel,
|
||||||
|
|
|
@ -52,10 +52,7 @@ export const AddServerFromInviteCmd = botControlCmd({
|
||||||
invite.guild.id,
|
invite.guild.id,
|
||||||
msg.author.id,
|
msg.author.id,
|
||||||
[ApiPermissions.ManageAccess],
|
[ApiPermissions.ManageAccess],
|
||||||
moment
|
moment.utc().add(1, "hour").format(DBDateFormat),
|
||||||
.utc()
|
|
||||||
.add(1, "hour")
|
|
||||||
.format(DBDateFormat),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -48,10 +48,7 @@ export const AllowServerCmd = botControlCmd({
|
||||||
args.guildId,
|
args.guildId,
|
||||||
msg.author.id,
|
msg.author.id,
|
||||||
[ApiPermissions.ManageAccess],
|
[ApiPermissions.ManageAccess],
|
||||||
moment
|
moment.utc().add(1, "hour").format(DBDateFormat),
|
||||||
.utc()
|
|
||||||
.add(1, "hour")
|
|
||||||
.format(DBDateFormat),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -21,7 +21,7 @@ export const ListDashboardUsersCmd = botControlCmd({
|
||||||
|
|
||||||
const dashboardUsers = await pluginData.state.apiPermissionAssignments.getByGuildId(guild.id);
|
const dashboardUsers = await pluginData.state.apiPermissionAssignments.getByGuildId(guild.id);
|
||||||
const users = await Promise.all(
|
const users = await Promise.all(
|
||||||
dashboardUsers.map(async perm => ({
|
dashboardUsers.map(async (perm) => ({
|
||||||
user: await resolveUser(pluginData.client, perm.target_id),
|
user: await resolveUser(pluginData.client, perm.target_id),
|
||||||
permission: perm,
|
permission: perm,
|
||||||
})),
|
})),
|
||||||
|
|
|
@ -13,7 +13,7 @@ export const PerformanceCmd = botControlCmd({
|
||||||
async run({ pluginData, message: msg, args }) {
|
async run({ pluginData, message: msg, args }) {
|
||||||
const stats = pluginData.getKnubInstance().getPluginPerformanceStats();
|
const stats = pluginData.getKnubInstance().getPluginPerformanceStats();
|
||||||
const averageLoadTimeEntries = Object.entries(stats.averageLoadTimes);
|
const averageLoadTimeEntries = Object.entries(stats.averageLoadTimes);
|
||||||
averageLoadTimeEntries.sort(sorter(v => v[1].time, "DESC"));
|
averageLoadTimeEntries.sort(sorter((v) => v[1].time, "DESC"));
|
||||||
const lines = averageLoadTimeEntries.map(
|
const lines = averageLoadTimeEntries.map(
|
||||||
([pluginName, { time }]) => `${pluginName}: **${formatNumber(Math.round(time))}ms**`,
|
([pluginName, { time }]) => `${pluginName}: **${formatNumber(Math.round(time))}ms**`,
|
||||||
);
|
);
|
||||||
|
|
|
@ -34,7 +34,7 @@ export const RemoveDashboardUserCmd = botControlCmd({
|
||||||
await pluginData.state.apiPermissionAssignments.removeUser(args.guildId, user.id);
|
await pluginData.state.apiPermissionAssignments.removeUser(args.guildId, user.id);
|
||||||
}
|
}
|
||||||
|
|
||||||
const userNameList = args.users.map(user => `<@!${user.id}> (**${user.tag}**, \`${user.id}\`)`);
|
const userNameList = args.users.map((user) => `<@!${user.id}> (**${user.tag}**, \`${user.id}\`)`);
|
||||||
sendSuccessMessage(
|
sendSuccessMessage(
|
||||||
pluginData,
|
pluginData,
|
||||||
msg.channel as TextChannel,
|
msg.channel as TextChannel,
|
||||||
|
|
|
@ -22,7 +22,7 @@ export const ServersCmd = botControlCmd({
|
||||||
|
|
||||||
async run({ pluginData, message: msg, args }) {
|
async run({ pluginData, message: msg, args }) {
|
||||||
const showList = Boolean(args.all || args.initialized || args.uninitialized || args.search);
|
const showList = Boolean(args.all || args.initialized || args.uninitialized || args.search);
|
||||||
const search = args.search ? new RegExp([...args.search].map(s => escapeStringRegexp(s)).join(".*"), "i") : null;
|
const search = args.search ? new RegExp([...args.search].map((s) => escapeStringRegexp(s)).join(".*"), "i") : null;
|
||||||
|
|
||||||
const joinedGuilds = Array.from(pluginData.client.guilds.cache.values());
|
const joinedGuilds = Array.from(pluginData.client.guilds.cache.values());
|
||||||
const loadedGuilds = pluginData.getKnubInstance().getLoadedGuilds();
|
const loadedGuilds = pluginData.getKnubInstance().getLoadedGuilds();
|
||||||
|
@ -32,21 +32,21 @@ export const ServersCmd = botControlCmd({
|
||||||
let filteredGuilds = Array.from(joinedGuilds);
|
let filteredGuilds = Array.from(joinedGuilds);
|
||||||
|
|
||||||
if (args.initialized) {
|
if (args.initialized) {
|
||||||
filteredGuilds = filteredGuilds.filter(g => loadedGuildsMap.has(g.id));
|
filteredGuilds = filteredGuilds.filter((g) => loadedGuildsMap.has(g.id));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (args.uninitialized) {
|
if (args.uninitialized) {
|
||||||
filteredGuilds = filteredGuilds.filter(g => !loadedGuildsMap.has(g.id));
|
filteredGuilds = filteredGuilds.filter((g) => !loadedGuildsMap.has(g.id));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (args.search) {
|
if (args.search) {
|
||||||
filteredGuilds = filteredGuilds.filter(g => search!.test(`${g.id} ${g.name}`));
|
filteredGuilds = filteredGuilds.filter((g) => search!.test(`${g.id} ${g.name}`));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (filteredGuilds.length) {
|
if (filteredGuilds.length) {
|
||||||
filteredGuilds.sort(sorter(g => g.name.toLowerCase()));
|
filteredGuilds.sort(sorter((g) => g.name.toLowerCase()));
|
||||||
const longestId = filteredGuilds.reduce((longest, guild) => Math.max(longest, guild.id.length), 0);
|
const longestId = filteredGuilds.reduce((longest, guild) => Math.max(longest, guild.id.length), 0);
|
||||||
const lines = filteredGuilds.map(g => {
|
const lines = filteredGuilds.map((g) => {
|
||||||
const paddedId = g.id.padEnd(longestId, " ");
|
const paddedId = g.id.padEnd(longestId, " ");
|
||||||
const owner = getUser(pluginData.client, g.ownerId);
|
const owner = getUser(pluginData.client, g.ownerId);
|
||||||
return `\`${paddedId}\` **${g.name}** (${g.memberCount} members) (owner **${owner.tag}** \`${owner.id}\`)`;
|
return `\`${paddedId}\` **${g.name}** (${g.memberCount} members) (owner **${owner.tag}** \`${owner.id}\`)`;
|
||||||
|
@ -57,7 +57,7 @@ export const ServersCmd = botControlCmd({
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
const total = joinedGuilds.length;
|
const total = joinedGuilds.length;
|
||||||
const initialized = joinedGuilds.filter(g => loadedGuildsMap.has(g.id)).length;
|
const initialized = joinedGuilds.filter((g) => loadedGuildsMap.has(g.id)).length;
|
||||||
const unInitialized = total - initialized;
|
const unInitialized = total - initialized;
|
||||||
|
|
||||||
msg.channel.send(
|
msg.channel.send(
|
||||||
|
|
|
@ -22,7 +22,7 @@ export async function createCaseNote(pluginData: GuildPluginData<CasesPluginType
|
||||||
|
|
||||||
// Add note details to the beginning of the note
|
// Add note details to the beginning of the note
|
||||||
if (args.noteDetails && args.noteDetails.length) {
|
if (args.noteDetails && args.noteDetails.length) {
|
||||||
body = args.noteDetails.map(d => `__[${d}]__`).join(" ") + " " + body;
|
body = args.noteDetails.map((d) => `__[${d}]__`).join(" ") + " " + body;
|
||||||
}
|
}
|
||||||
|
|
||||||
await pluginData.state.cases.createNote(theCase.id, {
|
await pluginData.state.cases.createNote(theCase.id, {
|
||||||
|
|
|
@ -7,11 +7,11 @@ export async function getCaseTypeAmountForUserId(
|
||||||
userID: string,
|
userID: string,
|
||||||
type: CaseTypes,
|
type: CaseTypes,
|
||||||
): Promise<number> {
|
): Promise<number> {
|
||||||
const cases = (await pluginData.state.cases.getByUserId(userID)).filter(c => !c.is_hidden);
|
const cases = (await pluginData.state.cases.getByUserId(userID)).filter((c) => !c.is_hidden);
|
||||||
let typeAmount = 0;
|
let typeAmount = 0;
|
||||||
|
|
||||||
if (cases.length > 0) {
|
if (cases.length > 0) {
|
||||||
cases.forEach(singleCase => {
|
cases.forEach((singleCase) => {
|
||||||
if (singleCase.type === type.valueOf()) {
|
if (singleCase.type === type.valueOf()) {
|
||||||
typeAmount++;
|
typeAmount++;
|
||||||
}
|
}
|
||||||
|
|
|
@ -71,10 +71,10 @@ export const CensorPlugin = zeppelinGuildPlugin<CensorPluginType>()({
|
||||||
afterLoad(pluginData) {
|
afterLoad(pluginData) {
|
||||||
const { state, guild } = pluginData;
|
const { state, guild } = pluginData;
|
||||||
|
|
||||||
state.onMessageCreateFn = msg => onMessageCreate(pluginData, msg);
|
state.onMessageCreateFn = (msg) => onMessageCreate(pluginData, msg);
|
||||||
state.savedMessages.events.on("create", state.onMessageCreateFn);
|
state.savedMessages.events.on("create", state.onMessageCreateFn);
|
||||||
|
|
||||||
state.onMessageUpdateFn = msg => onMessageUpdate(pluginData, msg);
|
state.onMessageUpdateFn = (msg) => onMessageUpdate(pluginData, msg);
|
||||||
state.savedMessages.events.on("update", state.onMessageUpdateFn);
|
state.savedMessages.events.on("update", state.onMessageUpdateFn);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
|
@ -19,7 +19,7 @@ export async function applyFiltersToMsg(
|
||||||
let messageContent = savedMessage.data.content || "";
|
let messageContent = savedMessage.data.content || "";
|
||||||
if (savedMessage.data.attachments) messageContent += " " + JSON.stringify(savedMessage.data.attachments);
|
if (savedMessage.data.attachments) messageContent += " " + JSON.stringify(savedMessage.data.attachments);
|
||||||
if (savedMessage.data.embeds) {
|
if (savedMessage.data.embeds) {
|
||||||
const embeds = (savedMessage.data.embeds as MessageEmbed[]).map(e => cloneDeep(e));
|
const embeds = (savedMessage.data.embeds as MessageEmbed[]).map((e) => cloneDeep(e));
|
||||||
for (const embed of embeds) {
|
for (const embed of embeds) {
|
||||||
if (embed.type === "video") {
|
if (embed.type === "video") {
|
||||||
// Ignore video descriptions as they're not actually shown on the embed
|
// Ignore video descriptions as they're not actually shown on the embed
|
||||||
|
@ -52,7 +52,7 @@ export async function applyFiltersToMsg(
|
||||||
const inviteCodes = getInviteCodesInString(messageContent);
|
const inviteCodes = getInviteCodesInString(messageContent);
|
||||||
|
|
||||||
const invites: Array<Invite | null> = await Promise.all(
|
const invites: Array<Invite | null> = await Promise.all(
|
||||||
inviteCodes.map(code => resolveInvite(pluginData.client, code)),
|
inviteCodes.map((code) => resolveInvite(pluginData.client, code)),
|
||||||
);
|
);
|
||||||
|
|
||||||
for (const invite of invites) {
|
for (const invite of invites) {
|
||||||
|
|
|
@ -14,5 +14,5 @@ export const ChannelArchiverPlugin = zeppelinGuildPlugin<ChannelArchiverPluginTy
|
||||||
// prettier-ignore
|
// prettier-ignore
|
||||||
commands: [
|
commands: [
|
||||||
ArchiveChannelCmd,
|
ArchiveChannelCmd,
|
||||||
]
|
],
|
||||||
});
|
});
|
||||||
|
|
|
@ -68,9 +68,9 @@ export const ArchiveChannelCmd = channelArchiverCmd({
|
||||||
|
|
||||||
for (const message of messages.values()) {
|
for (const message of messages.values()) {
|
||||||
const ts = moment.utc(message.createdTimestamp).format("YYYY-MM-DD HH:mm:ss");
|
const ts = moment.utc(message.createdTimestamp).format("YYYY-MM-DD HH:mm:ss");
|
||||||
let content = `[${ts}] [${message.author.id}] [${message.author.username}#${
|
let content = `[${ts}] [${message.author.id}] [${message.author.username}#${message.author.discriminator}]: ${
|
||||||
message.author.discriminator
|
message.content || "<no text content>"
|
||||||
}]: ${message.content || "<no text content>"}`;
|
}`;
|
||||||
|
|
||||||
if (message.attachments.size) {
|
if (message.attachments.size) {
|
||||||
if (args["attachment-channel"]) {
|
if (args["attachment-channel"]) {
|
||||||
|
|
|
@ -14,9 +14,9 @@ export async function getCompanionChannelOptsForVoiceChannelId(
|
||||||
const config = await pluginData.config.getMatchingConfig({ userId, channelId: voiceChannel.id });
|
const config = await pluginData.config.getMatchingConfig({ userId, channelId: voiceChannel.id });
|
||||||
return Object.values(config.entries)
|
return Object.values(config.entries)
|
||||||
.filter(
|
.filter(
|
||||||
opts =>
|
(opts) =>
|
||||||
opts.voice_channel_ids.includes(voiceChannel.id) ||
|
opts.voice_channel_ids.includes(voiceChannel.id) ||
|
||||||
(voiceChannel.parentId && opts.voice_channel_ids.includes(voiceChannel.parentId)),
|
(voiceChannel.parentId && opts.voice_channel_ids.includes(voiceChannel.parentId)),
|
||||||
)
|
)
|
||||||
.map(opts => Object.assign({}, defaultCompanionChannelOpts, opts));
|
.map((opts) => Object.assign({}, defaultCompanionChannelOpts, opts));
|
||||||
}
|
}
|
||||||
|
|
|
@ -65,7 +65,7 @@ export async function handleCompanionPermissions(
|
||||||
if (!channel || !(channel instanceof TextChannel)) continue;
|
if (!channel || !(channel instanceof TextChannel)) continue;
|
||||||
pluginData.state.serverLogs.ignoreLog(LogType.CHANNEL_UPDATE, channelId, 3 * 1000);
|
pluginData.state.serverLogs.ignoreLog(LogType.CHANNEL_UPDATE, channelId, 3 * 1000);
|
||||||
const fullSerialized = new Permissions(BigInt(permissions)).serialize();
|
const fullSerialized = new Permissions(BigInt(permissions)).serialize();
|
||||||
const onlyAllowed = filterObject(fullSerialized, v => v === true);
|
const onlyAllowed = filterObject(fullSerialized, (v) => v === true);
|
||||||
await channel.permissionOverwrites.create(userId, onlyAllowed, {
|
await channel.permissionOverwrites.create(userId, onlyAllowed, {
|
||||||
reason: `Companion Channel for ${voiceChannel!.id} | User Joined`,
|
reason: `Companion Channel for ${voiceChannel!.id} | User Joined`,
|
||||||
});
|
});
|
||||||
|
|
|
@ -48,8 +48,9 @@ export async function muteAction(
|
||||||
|
|
||||||
const muteMessage = `Muted **${result.case.user_name}** ${
|
const muteMessage = `Muted **${result.case.user_name}** ${
|
||||||
durationMs ? `for ${humanizeDuration(durationMs)}` : "indefinitely"
|
durationMs ? `for ${humanizeDuration(durationMs)}` : "indefinitely"
|
||||||
} (Case #${result.case.case_number}) (user notified via ${result.notifyResult.method ??
|
} (Case #${result.case.case_number}) (user notified via ${
|
||||||
"dm"})\nPlease update the new case with the \`update\` command`;
|
result.notifyResult.method ?? "dm"
|
||||||
|
})\nPlease update the new case with the \`update\` command`;
|
||||||
|
|
||||||
interaction.followUp({ ephemeral: true, content: muteMessage });
|
interaction.followUp({ ephemeral: true, content: muteMessage });
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
|
|
@ -26,7 +26,7 @@ export async function loadAllCommands(pluginData: GuildPluginData<ContextMenuPlu
|
||||||
newCommands.push(data);
|
newCommands.push(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
const setCommands = await comms.set(newCommands, pluginData.guild.id).catch(e => {
|
const setCommands = await comms.set(newCommands, pluginData.guild.id).catch((e) => {
|
||||||
pluginData.getPlugin(LogsPlugin).logBotAlert({ body: `Unable to overwrite context menus: ${e}` });
|
pluginData.getPlugin(LogsPlugin).logBotAlert({ body: `Unable to overwrite context menus: ${e}` });
|
||||||
return undefined;
|
return undefined;
|
||||||
});
|
});
|
||||||
|
|
|
@ -55,7 +55,7 @@ const defaultOptions: PluginOptions<CountersPluginType> = {
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
|
||||||
const configPreprocessor: ConfigPreprocessorFn<CountersPluginType> = options => {
|
const configPreprocessor: ConfigPreprocessorFn<CountersPluginType> = (options) => {
|
||||||
for (const [counterName, counter] of Object.entries(options.config?.counters || {})) {
|
for (const [counterName, counter] of Object.entries(options.config?.counters || {})) {
|
||||||
counter.name = counterName;
|
counter.name = counterName;
|
||||||
counter.per_user = counter.per_user ?? false;
|
counter.per_user = counter.per_user ?? false;
|
||||||
|
|
|
@ -13,13 +13,13 @@ export const CountersListCmd = typedGuildCommand<CountersPluginType>()({
|
||||||
async run({ pluginData, message, args }) {
|
async run({ pluginData, message, args }) {
|
||||||
const config = await pluginData.config.getForMessage(message);
|
const config = await pluginData.config.getForMessage(message);
|
||||||
|
|
||||||
const countersToShow = Array.from(Object.values(config.counters)).filter(c => c.can_view !== false);
|
const countersToShow = Array.from(Object.values(config.counters)).filter((c) => c.can_view !== false);
|
||||||
if (!countersToShow.length) {
|
if (!countersToShow.length) {
|
||||||
sendErrorMessage(pluginData, message.channel, "No counters are configured for this server");
|
sendErrorMessage(pluginData, message.channel, "No counters are configured for this server");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const counterLines = countersToShow.map(counter => {
|
const counterLines = countersToShow.map((counter) => {
|
||||||
const title = counter.pretty_name ? `**${counter.pretty_name}** (\`${counter.name}\`)` : `\`${counter.name}\``;
|
const title = counter.pretty_name ? `**${counter.pretty_name}** (\`${counter.name}\`)` : `\`${counter.name}\``;
|
||||||
|
|
||||||
const types: string[] = [];
|
const types: string[] = [];
|
||||||
|
|
|
@ -38,10 +38,10 @@ export async function changeCounterValue(
|
||||||
if (triggers) {
|
if (triggers) {
|
||||||
const triggersArr = Array.from(triggers.values());
|
const triggersArr = Array.from(triggers.values());
|
||||||
await Promise.all(
|
await Promise.all(
|
||||||
triggersArr.map(trigger => checkCounterTrigger(pluginData, counterName, trigger, channelId, userId)),
|
triggersArr.map((trigger) => checkCounterTrigger(pluginData, counterName, trigger, channelId, userId)),
|
||||||
);
|
);
|
||||||
await Promise.all(
|
await Promise.all(
|
||||||
triggersArr.map(trigger => checkReverseCounterTrigger(pluginData, counterName, trigger, channelId, userId)),
|
triggersArr.map((trigger) => checkReverseCounterTrigger(pluginData, counterName, trigger, channelId, userId)),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -25,8 +25,8 @@ export async function decayCounter(
|
||||||
const triggers = pluginData.state.counterTriggersByCounterId.get(counterId);
|
const triggers = pluginData.state.counterTriggersByCounterId.get(counterId);
|
||||||
if (triggers) {
|
if (triggers) {
|
||||||
const triggersArr = Array.from(triggers.values());
|
const triggersArr = Array.from(triggers.values());
|
||||||
await Promise.all(triggersArr.map(trigger => checkAllValuesForTrigger(pluginData, counterName, trigger)));
|
await Promise.all(triggersArr.map((trigger) => checkAllValuesForTrigger(pluginData, counterName, trigger)));
|
||||||
await Promise.all(triggersArr.map(trigger => checkAllValuesForReverseTrigger(pluginData, counterName, trigger)));
|
await Promise.all(triggersArr.map((trigger) => checkAllValuesForReverseTrigger(pluginData, counterName, trigger)));
|
||||||
}
|
}
|
||||||
|
|
||||||
lock.unlock();
|
lock.unlock();
|
||||||
|
|
|
@ -35,10 +35,10 @@ export async function setCounterValue(
|
||||||
if (triggers) {
|
if (triggers) {
|
||||||
const triggersArr = Array.from(triggers.values());
|
const triggersArr = Array.from(triggers.values());
|
||||||
await Promise.all(
|
await Promise.all(
|
||||||
triggersArr.map(trigger => checkCounterTrigger(pluginData, counterName, trigger, channelId, userId)),
|
triggersArr.map((trigger) => checkCounterTrigger(pluginData, counterName, trigger, channelId, userId)),
|
||||||
);
|
);
|
||||||
await Promise.all(
|
await Promise.all(
|
||||||
triggersArr.map(trigger => checkReverseCounterTrigger(pluginData, counterName, trigger, channelId, userId)),
|
triggersArr.map((trigger) => checkReverseCounterTrigger(pluginData, counterName, trigger, channelId, userId)),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -29,7 +29,7 @@ export async function addRoleAction(
|
||||||
throw new ActionError("Missing permissions");
|
throw new ActionError("Missing permissions");
|
||||||
}
|
}
|
||||||
const rolesToAdd = (Array.isArray(action.role) ? action.role : [action.role]).filter(
|
const rolesToAdd = (Array.isArray(action.role) ? action.role : [action.role]).filter(
|
||||||
id => !target.roles.cache.has(id),
|
(id) => !target.roles.cache.has(id),
|
||||||
);
|
);
|
||||||
if (rolesToAdd.length === 0) {
|
if (rolesToAdd.length === 0) {
|
||||||
throw new ActionError("Target already has the role(s) specified");
|
throw new ActionError("Target already has the role(s) specified");
|
||||||
|
|
|
@ -5,7 +5,7 @@ export const GuildBanRemoveAlertsEvt = locateUserEvt({
|
||||||
|
|
||||||
async listener(meta) {
|
async listener(meta) {
|
||||||
const alerts = await meta.pluginData.state.alerts.getAlertsByUserId(meta.args.ban.user.id);
|
const alerts = await meta.pluginData.state.alerts.getAlertsByUserId(meta.args.ban.user.id);
|
||||||
alerts.forEach(alert => {
|
alerts.forEach((alert) => {
|
||||||
meta.pluginData.state.alerts.delete(alert.id);
|
meta.pluginData.state.alerts.delete(alert.id);
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
|
@ -19,7 +19,7 @@ export const VoiceStateUpdateAlertEvt = locateUserEvt({
|
||||||
const triggeredAlerts = await meta.pluginData.state.alerts.getAlertsByUserId(memberId);
|
const triggeredAlerts = await meta.pluginData.state.alerts.getAlertsByUserId(memberId);
|
||||||
const voiceChannel = meta.args.oldState.channel!;
|
const voiceChannel = meta.args.oldState.channel!;
|
||||||
|
|
||||||
triggeredAlerts.forEach(alert => {
|
triggeredAlerts.forEach((alert) => {
|
||||||
const txtChannel = meta.pluginData.guild.channels.resolve(alert.channel_id as Snowflake) as TextChannel;
|
const txtChannel = meta.pluginData.guild.channels.resolve(alert.channel_id as Snowflake) as TextChannel;
|
||||||
txtChannel.send({
|
txtChannel.send({
|
||||||
content: `🔴 <@!${alert.requestor_id}> the user <@!${alert.user_id}> disconnected out of \`${voiceChannel.name}\``,
|
content: `🔴 <@!${alert.requestor_id}> the user <@!${alert.user_id}> disconnected out of \`${voiceChannel.name}\``,
|
||||||
|
|
|
@ -4,7 +4,7 @@ import { LocateUserPluginType } from "../types";
|
||||||
export async function fillActiveAlertsList(pluginData: GuildPluginData<LocateUserPluginType>) {
|
export async function fillActiveAlertsList(pluginData: GuildPluginData<LocateUserPluginType>) {
|
||||||
const allAlerts = await pluginData.state.alerts.getAllGuildAlerts();
|
const allAlerts = await pluginData.state.alerts.getAllGuildAlerts();
|
||||||
|
|
||||||
allAlerts.forEach(alert => {
|
allAlerts.forEach((alert) => {
|
||||||
if (!pluginData.state.usersWithAlerts.includes(alert.user_id)) {
|
if (!pluginData.state.usersWithAlerts.includes(alert.user_id)) {
|
||||||
pluginData.state.usersWithAlerts.push(alert.user_id);
|
pluginData.state.usersWithAlerts.push(alert.user_id);
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,7 +10,7 @@ export async function sendAlerts(pluginData: GuildPluginData<LocateUserPluginTyp
|
||||||
const member = await resolveMember(pluginData.client, pluginData.guild, userId);
|
const member = await resolveMember(pluginData.client, pluginData.guild, userId);
|
||||||
if (!member) return;
|
if (!member) return;
|
||||||
|
|
||||||
triggeredAlerts.forEach(alert => {
|
triggeredAlerts.forEach((alert) => {
|
||||||
const prepend = `<@!${alert.requestor_id}>, an alert requested by you has triggered!\nReminder: \`${alert.body}\`\n`;
|
const prepend = `<@!${alert.requestor_id}>, an alert requested by you has triggered!\nReminder: \`${alert.body}\`\n`;
|
||||||
const txtChannel = pluginData.guild.channels.resolve(alert.channel_id as Snowflake) as TextChannel;
|
const txtChannel = pluginData.guild.channels.resolve(alert.channel_id as Snowflake) as TextChannel;
|
||||||
sendWhere(pluginData, member, txtChannel, prepend);
|
sendWhere(pluginData, member, txtChannel, prepend);
|
||||||
|
|
|
@ -177,7 +177,7 @@ export const LogsPlugin = zeppelinGuildPlugin<LogsPluginType>()({
|
||||||
],
|
],
|
||||||
|
|
||||||
public: {
|
public: {
|
||||||
getLogMessage: pluginData => {
|
getLogMessage: (pluginData) => {
|
||||||
return <TLogType extends keyof ILogTypeData>(
|
return <TLogType extends keyof ILogTypeData>(
|
||||||
type: TLogType,
|
type: TLogType,
|
||||||
data: TypedTemplateSafeValueContainer<ILogTypeData[TLogType]>,
|
data: TypedTemplateSafeValueContainer<ILogTypeData[TLogType]>,
|
||||||
|
@ -277,10 +277,10 @@ export const LogsPlugin = zeppelinGuildPlugin<LogsPluginType>()({
|
||||||
state.logListener = ({ type, data }) => log(pluginData, type, data);
|
state.logListener = ({ type, data }) => log(pluginData, type, data);
|
||||||
state.guildLogs.on("log", state.logListener);
|
state.guildLogs.on("log", state.logListener);
|
||||||
|
|
||||||
state.onMessageDeleteFn = msg => onMessageDelete(pluginData, msg);
|
state.onMessageDeleteFn = (msg) => onMessageDelete(pluginData, msg);
|
||||||
state.savedMessages.events.on("delete", state.onMessageDeleteFn);
|
state.savedMessages.events.on("delete", state.onMessageDeleteFn);
|
||||||
|
|
||||||
state.onMessageDeleteBulkFn = msg => onMessageDeleteBulk(pluginData, msg);
|
state.onMessageDeleteBulkFn = (msg) => onMessageDeleteBulk(pluginData, msg);
|
||||||
state.savedMessages.events.on("deleteBulk", state.onMessageDeleteBulkFn);
|
state.savedMessages.events.on("deleteBulk", state.onMessageDeleteBulkFn);
|
||||||
|
|
||||||
state.onMessageUpdateFn = (newMsg, oldMsg) => onMessageUpdate(pluginData, newMsg, oldMsg);
|
state.onMessageUpdateFn = (newMsg, oldMsg) => onMessageUpdate(pluginData, newMsg, oldMsg);
|
||||||
|
|
|
@ -58,10 +58,10 @@ export const LogsGuildMemberUpdateEvt = logsEvt({
|
||||||
logMemberRoleChanges(pluginData, {
|
logMemberRoleChanges(pluginData, {
|
||||||
member,
|
member,
|
||||||
addedRoles: addedRoles.map(
|
addedRoles: addedRoles.map(
|
||||||
roleId => pluginData.guild.roles.cache.get(roleId) ?? { id: roleId, name: `Unknown (${roleId})` },
|
(roleId) => pluginData.guild.roles.cache.get(roleId) ?? { id: roleId, name: `Unknown (${roleId})` },
|
||||||
),
|
),
|
||||||
removedRoles: removedRoles.map(
|
removedRoles: removedRoles.map(
|
||||||
roleId => pluginData.guild.roles.cache.get(roleId) ?? { id: roleId, name: `Unknown (${roleId})` },
|
(roleId) => pluginData.guild.roles.cache.get(roleId) ?? { id: roleId, name: `Unknown (${roleId})` },
|
||||||
),
|
),
|
||||||
mod: null,
|
mod: null,
|
||||||
});
|
});
|
||||||
|
@ -70,7 +70,7 @@ export const LogsGuildMemberUpdateEvt = logsEvt({
|
||||||
logMemberRoleAdd(pluginData, {
|
logMemberRoleAdd(pluginData, {
|
||||||
member,
|
member,
|
||||||
roles: addedRoles.map(
|
roles: addedRoles.map(
|
||||||
roleId => pluginData.guild.roles.cache.get(roleId) ?? { id: roleId, name: `Unknown (${roleId})` },
|
(roleId) => pluginData.guild.roles.cache.get(roleId) ?? { id: roleId, name: `Unknown (${roleId})` },
|
||||||
),
|
),
|
||||||
mod: null,
|
mod: null,
|
||||||
});
|
});
|
||||||
|
@ -79,7 +79,7 @@ export const LogsGuildMemberUpdateEvt = logsEvt({
|
||||||
logMemberRoleRemove(pluginData, {
|
logMemberRoleRemove(pluginData, {
|
||||||
member,
|
member,
|
||||||
roles: removedRoles.map(
|
roles: removedRoles.map(
|
||||||
roleId => pluginData.guild.roles.cache.get(roleId) ?? { id: roleId, name: `Unknown (${roleId})` },
|
(roleId) => pluginData.guild.roles.cache.get(roleId) ?? { id: roleId, name: `Unknown (${roleId})` },
|
||||||
),
|
),
|
||||||
mod: null,
|
mod: null,
|
||||||
});
|
});
|
||||||
|
|
|
@ -21,7 +21,7 @@ export function logAutomodAction(pluginData: GuildPluginData<LogsPluginType>, da
|
||||||
createTypedTemplateSafeValueContainer({
|
createTypedTemplateSafeValueContainer({
|
||||||
rule: data.rule,
|
rule: data.rule,
|
||||||
user: data.user ? userToTemplateSafeUser(data.user) : null,
|
user: data.user ? userToTemplateSafeUser(data.user) : null,
|
||||||
users: data.users.map(user => userToTemplateSafeUser(user)),
|
users: data.users.map((user) => userToTemplateSafeUser(user)),
|
||||||
actionsTaken: data.actionsTaken,
|
actionsTaken: data.actionsTaken,
|
||||||
matchSummary: data.matchSummary ?? "",
|
matchSummary: data.matchSummary ?? "",
|
||||||
}),
|
}),
|
||||||
|
|
|
@ -19,7 +19,7 @@ export function logMemberRoleAdd(pluginData: GuildPluginData<LogsPluginType>, da
|
||||||
createTypedTemplateSafeValueContainer({
|
createTypedTemplateSafeValueContainer({
|
||||||
mod: data.mod ? userToTemplateSafeUser(data.mod) : null,
|
mod: data.mod ? userToTemplateSafeUser(data.mod) : null,
|
||||||
member: memberToTemplateSafeMember(data.member),
|
member: memberToTemplateSafeMember(data.member),
|
||||||
roles: data.roles.map(r => r.name).join(", "),
|
roles: data.roles.map((r) => r.name).join(", "),
|
||||||
}),
|
}),
|
||||||
{
|
{
|
||||||
userId: data.member.id,
|
userId: data.member.id,
|
||||||
|
|
|
@ -21,8 +21,8 @@ export function logMemberRoleChanges(pluginData: GuildPluginData<LogsPluginType>
|
||||||
createTypedTemplateSafeValueContainer({
|
createTypedTemplateSafeValueContainer({
|
||||||
mod: data.mod ? userToTemplateSafeUser(data.mod) : null,
|
mod: data.mod ? userToTemplateSafeUser(data.mod) : null,
|
||||||
member: memberToTemplateSafeMember(data.member),
|
member: memberToTemplateSafeMember(data.member),
|
||||||
addedRoles: data.addedRoles.map(r => r.name).join(", "),
|
addedRoles: data.addedRoles.map((r) => r.name).join(", "),
|
||||||
removedRoles: data.removedRoles.map(r => r.name).join(", "),
|
removedRoles: data.removedRoles.map((r) => r.name).join(", "),
|
||||||
}),
|
}),
|
||||||
{
|
{
|
||||||
userId: data.member.id,
|
userId: data.member.id,
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Reference in a new issue