mirror of
https://github.com/ZeppelinBot/Zeppelin.git
synced 2025-05-21 08:45:03 +00:00
format: Prettier
This commit is contained in:
parent
70be2a2055
commit
517ce4f52f
161 changed files with 534 additions and 659 deletions
|
@ -14,7 +14,7 @@ export class Queue {
|
||||||
}
|
}
|
||||||
|
|
||||||
public add(fn) {
|
public add(fn) {
|
||||||
const promise = new Promise(resolve => {
|
const promise = new Promise((resolve) => {
|
||||||
this.queue.push(async () => {
|
this.queue.push(async () => {
|
||||||
await fn();
|
await fn();
|
||||||
resolve(undefined);
|
resolve(undefined);
|
||||||
|
@ -35,7 +35,7 @@ export class Queue {
|
||||||
}
|
}
|
||||||
|
|
||||||
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
|
||||||
fn().then(resolve);
|
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 = 1000; // ms
|
||||||
const INITIAL_REGEX_TIMEOUT_DURATION = 30 * SECONDS;
|
const INITIAL_REGEX_TIMEOUT_DURATION = 30 * SECONDS;
|
||||||
const FINAL_REGEX_TIMEOUT = 750; // ms
|
const FINAL_REGEX_TIMEOUT = 750; // ms
|
||||||
|
|
||||||
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,17 +33,17 @@ 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;
|
||||||
}
|
}
|
||||||
|
|
||||||
res.on("data", data => resolve(JSON.parse(data)));
|
res.on("data", (data) => resolve(JSON.parse(data)));
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
request.on("error", err => reject(err));
|
request.on("error", (err) => reject(err));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -20,21 +20,21 @@ function formatConfigSchema(schema) {
|
||||||
if (schema.name.startsWith("Nullable<")) {
|
if (schema.name.startsWith("Nullable<")) {
|
||||||
return `Nullable<${formatConfigSchema(schema.types[0])}>`;
|
return `Nullable<${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 } : {};
|
const thinInfo = plugin.info ? { prettyName: plugin.info.prettyName } : {};
|
||||||
return {
|
return {
|
||||||
name: plugin.name,
|
name: plugin.name,
|
||||||
|
@ -54,7 +54,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,
|
||||||
|
|
|
@ -66,10 +66,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(1, "day").format(DBDateFormat),
|
||||||
.utc()
|
|
||||||
.add(1, "day")
|
|
||||||
.format(DBDateFormat),
|
|
||||||
});
|
});
|
||||||
|
|
||||||
return `${loginId}.${token}`;
|
return `${loginId}.${token}`;
|
||||||
|
|
|
@ -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 });
|
||||||
|
|
|
@ -132,7 +132,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);
|
||||||
|
|
||||||
|
|
|
@ -45,19 +45,11 @@ const DELETE_UNUSED_COUNTER_TRIGGERS_AFTER = 1 * DAYS;
|
||||||
const MAX_COUNTER_VALUE = 2147483647; // 2^31-1, for MySQL INT
|
const MAX_COUNTER_VALUE = 2147483647; // 2^31-1, for MySQL INT
|
||||||
|
|
||||||
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);
|
||||||
|
@ -118,10 +110,7 @@ export class GuildCounters extends BaseGuildRepository {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
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(
|
await this.counters.update(
|
||||||
{
|
{
|
||||||
guild_id: this.guildId,
|
guild_id: this.guildId,
|
||||||
|
@ -135,11 +124,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(id: number, channelId: string | null, userId: string | null, change: number): Promise<void> {
|
async changeCounterValue(id: number, channelId: string | null, userId: string | null, change: number): Promise<void> {
|
||||||
|
@ -231,10 +216,7 @@ export class GuildCounters extends BaseGuildRepository {
|
||||||
}
|
}
|
||||||
|
|
||||||
async markAllTriggersTobeDeleted() {
|
async markAllTriggersTobeDeleted() {
|
||||||
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(
|
||||||
{},
|
{},
|
||||||
{
|
{
|
||||||
|
@ -244,11 +226,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(
|
||||||
|
@ -264,7 +242,7 @@ export class GuildCounters extends BaseGuildRepository {
|
||||||
throw new Error(`Invalid comparison value: ${comparisonValue}`);
|
throw new Error(`Invalid comparison value: ${comparisonValue}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
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,
|
||||||
comparison_op: comparisonOp,
|
comparison_op: comparisonOp,
|
||||||
|
@ -308,7 +286,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!,
|
||||||
|
@ -356,7 +334,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(
|
||||||
|
@ -373,7 +351,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,
|
||||||
channelId: row.channel_id,
|
channelId: row.channel_id,
|
||||||
userId: row.user_id,
|
userId: row.user_id,
|
||||||
|
@ -381,7 +359,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,
|
||||||
}));
|
}));
|
||||||
|
@ -407,7 +385,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 reverseOp = getReverseComparisonOp(counterTrigger.comparison_op);
|
const reverseOp = getReverseComparisonOp(counterTrigger.comparison_op);
|
||||||
const matchingValue = await entityManager
|
const matchingValue = await entityManager
|
||||||
.createQueryBuilder(CounterValue, "cv")
|
.createQueryBuilder(CounterValue, "cv")
|
||||||
|
@ -445,7 +423,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 reverseOp = getReverseComparisonOp(counterTrigger.comparison_op);
|
const reverseOp = getReverseComparisonOp(counterTrigger.comparison_op);
|
||||||
const matchingValues: Array<{
|
const matchingValues: Array<{
|
||||||
id: string;
|
id: string;
|
||||||
|
@ -472,11 +450,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)),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -31,10 +31,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,
|
||||||
|
@ -48,10 +45,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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,10 +18,7 @@ export class ApiPermissionAssignment {
|
||||||
@Column("simple-array")
|
@Column("simple-array")
|
||||||
permissions: string[];
|
permissions: string[];
|
||||||
|
|
||||||
@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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -139,8 +139,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;
|
||||||
|
@ -175,7 +175,7 @@ connect().then(async () => {
|
||||||
});
|
});
|
||||||
client.setMaxListeners(200);
|
client.setMaxListeners(200);
|
||||||
|
|
||||||
client.on("debug", message => {
|
client.on("debug", (message) => {
|
||||||
if (message.includes(" 429 ")) {
|
if (message.includes(" 429 ")) {
|
||||||
logger.info(`[429] ${message}`);
|
logger.info(`[429] ${message}`);
|
||||||
}
|
}
|
||||||
|
@ -209,9 +209,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;
|
||||||
});
|
});
|
||||||
|
|
|
@ -9,23 +9,23 @@ 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("result", row => {
|
stream.on("result", (row) => {
|
||||||
migratedUsernames.add(row.key);
|
migratedUsernames.add(row.key);
|
||||||
});
|
});
|
||||||
stream.on("end", resolve);
|
stream.on("end", resolve);
|
||||||
});
|
});
|
||||||
|
|
||||||
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[] = [];
|
||||||
|
|
||||||
const stream = await queryRunner.stream(
|
const stream = await queryRunner.stream(
|
||||||
`SELECT * FROM name_history WHERE type=1 ORDER BY timestamp ASC LIMIT ${BATCH_SIZE}`,
|
`SELECT * FROM name_history WHERE type=1 ORDER BY timestamp ASC LIMIT ${BATCH_SIZE}`,
|
||||||
);
|
);
|
||||||
stream.on("result", row => {
|
stream.on("result", (row) => {
|
||||||
const key = `${row.user_id}-${row.value}`;
|
const key = `${row.user_id}-${row.value}`;
|
||||||
|
|
||||||
if (!migratedUsernames.has(key)) {
|
if (!migratedUsernames.has(key)) {
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
import { MigrationInterface, QueryRunner, Table } from "typeorm";
|
import { MigrationInterface, QueryRunner, Table } from "typeorm";
|
||||||
|
|
||||||
export class AFKStatus1617410382003 implements MigrationInterface {
|
export class AFKStatus1617410382003 implements MigrationInterface {
|
||||||
|
|
||||||
public async up(queryRunner: QueryRunner): Promise<void> {
|
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||||
await queryRunner.createTable(
|
await queryRunner.createTable(
|
||||||
new Table({
|
new Table({
|
||||||
|
@ -22,9 +21,9 @@ export class AFKStatus1617410382003 implements MigrationInterface {
|
||||||
name: "status",
|
name: "status",
|
||||||
type: "varchar",
|
type: "varchar",
|
||||||
length: "255",
|
length: "255",
|
||||||
}
|
},
|
||||||
]
|
],
|
||||||
})
|
}),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -61,7 +61,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"),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -150,7 +150,7 @@ export function sendSuccessMessage(
|
||||||
: { content: formattedBody };
|
: { content: formattedBody };
|
||||||
return channel
|
return channel
|
||||||
.createMessage(content) // Force line break
|
.createMessage(content) // Force line break
|
||||||
.catch(err => {
|
.catch((err) => {
|
||||||
const channelInfo = (channel as GuildTextableChannel).guild
|
const channelInfo = (channel as GuildTextableChannel).guild
|
||||||
? `${channel.id} (${(channel as GuildTextableChannel).guild.id})`
|
? `${channel.id} (${(channel as GuildTextableChannel).guild.id})`
|
||||||
: `${channel.id}`;
|
: `${channel.id}`;
|
||||||
|
@ -172,7 +172,7 @@ export function sendErrorMessage(
|
||||||
: { content: formattedBody };
|
: { content: formattedBody };
|
||||||
return channel
|
return channel
|
||||||
.createMessage(content) // Force line break
|
.createMessage(content) // Force line break
|
||||||
.catch(err => {
|
.catch((err) => {
|
||||||
const channelInfo = (channel as GuildTextableChannel).guild
|
const channelInfo = (channel as GuildTextableChannel).guild
|
||||||
? `${channel.id} (${(channel as GuildTextableChannel).guild.id})`
|
? `${channel.id} (${(channel as GuildTextableChannel).guild.id})`
|
||||||
: `${channel.id}`;
|
: `${channel.id}`;
|
||||||
|
@ -206,7 +206,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);
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { PluginOptions } from "knub";
|
import { PluginOptions } from "knub";
|
||||||
import { AFKPluginType, ConfigSchema } from './types';
|
import { AFKPluginType, ConfigSchema } from "./types";
|
||||||
import { zeppelinGuildPlugin } from "../ZeppelinPluginBlueprint";
|
import { zeppelinGuildPlugin } from "../ZeppelinPluginBlueprint";
|
||||||
import { AFK } from "src/data/AFK";
|
import { AFK } from "src/data/AFK";
|
||||||
|
|
||||||
|
@ -14,15 +14,15 @@ const defaultOptions: PluginOptions<AFKPluginType> = {
|
||||||
},
|
},
|
||||||
overrides: [
|
overrides: [
|
||||||
{
|
{
|
||||||
level: '>=50',
|
level: ">=50",
|
||||||
config: {
|
config: {
|
||||||
can_afk: true,
|
can_afk: true,
|
||||||
allow_links: true,
|
allow_links: true,
|
||||||
allow_invites: true,
|
allow_invites: true,
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
]
|
],
|
||||||
}
|
};
|
||||||
|
|
||||||
export const AFKPlugin = zeppelinGuildPlugin<AFKPluginType>()("afk", {
|
export const AFKPlugin = zeppelinGuildPlugin<AFKPluginType>()("afk", {
|
||||||
showInDocs: true,
|
showInDocs: true,
|
||||||
|
@ -41,6 +41,5 @@ export const AFKPlugin = zeppelinGuildPlugin<AFKPluginType>()("afk", {
|
||||||
const { state } = pluginData;
|
const { state } = pluginData;
|
||||||
|
|
||||||
state.afkUsers = new AFK();
|
state.afkUsers = new AFK();
|
||||||
}
|
},
|
||||||
})
|
});
|
||||||
|
|
||||||
|
|
|
@ -4,8 +4,8 @@ import { sendErrorMessage, sendSuccessMessage } from "../../../pluginUtils";
|
||||||
import { parseStatusMessage } from "../functions/parseStatusMessage";
|
import { parseStatusMessage } from "../functions/parseStatusMessage";
|
||||||
|
|
||||||
export const AfkSetCmd = afkCmd({
|
export const AfkSetCmd = afkCmd({
|
||||||
trigger: ['afk', 'afk set'],
|
trigger: ["afk", "afk set"],
|
||||||
permission: 'can_afk',
|
permission: "can_afk",
|
||||||
|
|
||||||
signature: {
|
signature: {
|
||||||
status: ct.string({ rest: true, required: true }),
|
status: ct.string({ rest: true, required: true }),
|
||||||
|
@ -26,21 +26,18 @@ export const AfkSetCmd = afkCmd({
|
||||||
|
|
||||||
// Checks status based on configuration options
|
// Checks status based on configuration options
|
||||||
const parsed = parseStatusMessage(pluginData, msg.member, status);
|
const parsed = parseStatusMessage(pluginData, msg.member, status);
|
||||||
if (typeof parsed === 'string') {
|
if (typeof parsed === "string") {
|
||||||
sendErrorMessage(pluginData, msg.channel, parsed);
|
sendErrorMessage(pluginData, msg.channel, parsed);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set user status
|
// Set user status
|
||||||
const afk = await pluginData.state.afkUsers.setAfkStatus(
|
const afk = await pluginData.state.afkUsers.setAfkStatus(msg.author.id, status);
|
||||||
msg.author.id,
|
|
||||||
status,
|
|
||||||
);
|
|
||||||
|
|
||||||
sendSuccessMessage(pluginData, msg.channel, `AFK Status set to: **${afk.status}**`, {
|
sendSuccessMessage(pluginData, msg.channel, `AFK Status set to: **${afk.status}**`, {
|
||||||
roles: false,
|
roles: false,
|
||||||
everyone: false,
|
everyone: false,
|
||||||
users: false,
|
users: false,
|
||||||
});
|
});
|
||||||
}
|
},
|
||||||
})
|
});
|
||||||
|
|
|
@ -2,7 +2,7 @@ import { sendUserMentionMessage, sendWelcomeBackMessage } from "../functions/bui
|
||||||
import { afkEvt } from "../types";
|
import { afkEvt } from "../types";
|
||||||
|
|
||||||
export const AFKNotificationEvt = afkEvt({
|
export const AFKNotificationEvt = afkEvt({
|
||||||
event: 'messageCreate',
|
event: "messageCreate",
|
||||||
|
|
||||||
listener: async ({ pluginData, args: { message } }) => {
|
listener: async ({ pluginData, args: { message } }) => {
|
||||||
// Mention Check (if someone mentions the AFK user)
|
// Mention Check (if someone mentions the AFK user)
|
||||||
|
@ -24,5 +24,5 @@ export const AFKNotificationEvt = afkEvt({
|
||||||
} catch (err) {}
|
} catch (err) {}
|
||||||
|
|
||||||
sendWelcomeBackMessage(message);
|
sendWelcomeBackMessage(message);
|
||||||
}
|
},
|
||||||
});
|
});
|
|
@ -1,6 +1,6 @@
|
||||||
import * as t from 'io-ts';
|
import * as t from "io-ts";
|
||||||
import { BasePluginType, guildCommand, guildEventListener } from 'knub';
|
import { BasePluginType, guildCommand, guildEventListener } from "knub";
|
||||||
import { AFK } from '../../data/AFK';
|
import { AFK } from "../../data/AFK";
|
||||||
|
|
||||||
export const ConfigSchema = t.type({
|
export const ConfigSchema = t.type({
|
||||||
can_afk: t.boolean,
|
can_afk: t.boolean,
|
||||||
|
@ -13,7 +13,7 @@ export interface AFKPluginType extends BasePluginType {
|
||||||
config: TConfigSchema;
|
config: TConfigSchema;
|
||||||
state: {
|
state: {
|
||||||
afkUsers: AFK;
|
afkUsers: AFK;
|
||||||
}
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export const afkCmd = guildCommand<AFKPluginType>();
|
export const afkCmd = guildCommand<AFKPluginType>();
|
||||||
|
|
|
@ -39,13 +39,13 @@ export const AutoDeletePlugin = zeppelinGuildPlugin<AutoDeletePluginType>()("aut
|
||||||
|
|
||||||
state.maxDelayWarningSent = false;
|
state.maxDelayWarningSent = false;
|
||||||
|
|
||||||
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);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,7 @@ import { SavedMessage } from "../../../data/entities/SavedMessage";
|
||||||
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);
|
||||||
|
|
|
@ -61,7 +61,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)) {
|
||||||
|
@ -217,10 +217,10 @@ export const AutomodPlugin = zeppelinGuildPlugin<AutomodPluginType>()("automod",
|
||||||
pluginData.state.antiraidLevels = GuildAntiraidLevels.getGuildInstance(pluginData.guild.id);
|
pluginData.state.antiraidLevels = GuildAntiraidLevels.getGuildInstance(pluginData.guild.id);
|
||||||
pluginData.state.archives = GuildArchives.getGuildInstance(pluginData.guild.id);
|
pluginData.state.archives = GuildArchives.getGuildInstance(pluginData.guild.id);
|
||||||
|
|
||||||
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);
|
||||||
|
|
||||||
pluginData.state.cachedAntiraidLevel = await pluginData.state.antiraidLevels.get();
|
pluginData.state.cachedAntiraidLevel = await pluginData.state.antiraidLevels.get();
|
||||||
|
|
|
@ -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.get(pluginData.client.user.id)!;
|
const me = pluginData.guild.members.get(pluginData.client.user.id)!;
|
||||||
|
|
||||||
const missingPermissions = getMissingPermissions(me.permission, p.manageRoles);
|
const missingPermissions = getMissingPermissions(me.permission, p.manageRoles);
|
||||||
|
@ -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.get(roleId)?.name || roleId,
|
(roleId) => pluginData.guild.roles.get(roleId)?.name || roleId,
|
||||||
);
|
);
|
||||||
const logs = pluginData.getPlugin(LogsPlugin);
|
const logs = pluginData.getPlugin(LogsPlugin);
|
||||||
logs.log(LogType.BOT_ALERT, {
|
logs.log(LogType.BOT_ALERT, {
|
||||||
|
@ -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);
|
const memberRoles = new Set(member.roles);
|
||||||
for (const roleId of rolesToAssign) {
|
for (const roleId of rolesToAssign) {
|
||||||
memberRoles.add(roleId);
|
memberRoles.add(roleId);
|
||||||
|
|
|
@ -33,7 +33,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 && stripObjectToScalars(c.user)).filter(Boolean);
|
const safeUsers = contexts.map((c) => c.user && stripObjectToScalars(c.user)).filter(Boolean);
|
||||||
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(", ");
|
||||||
|
|
||||||
|
|
|
@ -27,7 +27,7 @@ export const BanAction = automodAction({
|
||||||
extraNotes: matchResult.fullSummary ? [matchResult.fullSummary] : [],
|
extraNotes: matchResult.fullSummary ? [matchResult.fullSummary] : [],
|
||||||
};
|
};
|
||||||
|
|
||||||
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).log(LogType.BOT_ALERT, {
|
pluginData.getPlugin(LogsPlugin).log(LogType.BOT_ALERT, {
|
||||||
body: `Failed to change the nickname of \`${member.id}\``,
|
body: `Failed to change the nickname of \`${member.id}\``,
|
||||||
});
|
});
|
||||||
|
|
|
@ -25,8 +25,8 @@ export const KickAction = automodAction({
|
||||||
extraNotes: matchResult.fullSummary ? [matchResult.fullSummary] : [],
|
extraNotes: matchResult.fullSummary ? [matchResult.fullSummary] : [],
|
||||||
};
|
};
|
||||||
|
|
||||||
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) {
|
||||||
|
|
|
@ -9,9 +9,9 @@ export const LogAction = automodAction({
|
||||||
defaultConfig: true,
|
defaultConfig: true,
|
||||||
|
|
||||||
async apply({ pluginData, contexts, ruleName, matchResult }) {
|
async apply({ pluginData, contexts, ruleName, matchResult }) {
|
||||||
const safeUsers = unique(contexts.map(c => c.user))
|
const safeUsers = unique(contexts.map((c) => c.user))
|
||||||
.filter(Boolean)
|
.filter(Boolean)
|
||||||
.map(user => stripObjectToScalars(user));
|
.map((user) => stripObjectToScalars(user));
|
||||||
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(", ");
|
||||||
|
|
||||||
|
|
|
@ -42,7 +42,7 @@ export const MuteAction = automodAction({
|
||||||
extraNotes: matchResult.fullSummary ? [matchResult.fullSummary] : [],
|
extraNotes: matchResult.fullSummary ? [matchResult.fullSummary] : [],
|
||||||
};
|
};
|
||||||
|
|
||||||
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) {
|
||||||
|
|
|
@ -19,7 +19,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.get(pluginData.client.user.id)!;
|
const me = pluginData.guild.members.get(pluginData.client.user.id)!;
|
||||||
|
|
||||||
const missingPermissions = getMissingPermissions(me.permission, p.manageRoles);
|
const missingPermissions = getMissingPermissions(me.permission, p.manageRoles);
|
||||||
|
@ -43,7 +43,7 @@ export const RemoveRolesAction = automodAction({
|
||||||
|
|
||||||
if (rolesWeCannotRemove.length) {
|
if (rolesWeCannotRemove.length) {
|
||||||
const roleNamesWeCannotRemove = rolesWeCannotRemove.map(
|
const roleNamesWeCannotRemove = rolesWeCannotRemove.map(
|
||||||
roleId => pluginData.guild.roles.get(roleId)?.name || roleId,
|
(roleId) => pluginData.guild.roles.get(roleId)?.name || roleId,
|
||||||
);
|
);
|
||||||
const logs = pluginData.getPlugin(LogsPlugin);
|
const logs = pluginData.getPlugin(LogsPlugin);
|
||||||
logs.log(LogType.BOT_ALERT, {
|
logs.log(LogType.BOT_ALERT, {
|
||||||
|
@ -54,7 +54,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);
|
const memberRoles = new Set(member.roles);
|
||||||
for (const roleId of rolesToRemove) {
|
for (const roleId of rolesToRemove) {
|
||||||
memberRoles.delete(roleId);
|
memberRoles.delete(roleId);
|
||||||
|
|
|
@ -27,8 +27,8 @@ export const ReplyAction = automodAction({
|
||||||
|
|
||||||
async apply({ pluginData, contexts, actionConfig }) {
|
async apply({ pluginData, contexts, actionConfig }) {
|
||||||
const contextsWithTextChannels = contexts
|
const contextsWithTextChannels = contexts
|
||||||
.filter(c => c.message?.channel_id)
|
.filter((c) => c.message?.channel_id)
|
||||||
.filter(c => pluginData.guild.channels.get(c.message!.channel_id) instanceof TextChannel);
|
.filter((c) => pluginData.guild.channels.get(c.message!.channel_id) instanceof TextChannel);
|
||||||
|
|
||||||
const contextsByChannelId = contextsWithTextChannels.reduce((map: Map<string, AutomodContext[]>, context) => {
|
const contextsByChannelId = contextsWithTextChannels.reduce((map: Map<string, AutomodContext[]>, context) => {
|
||||||
if (!map.has(context.message!.channel_id)) {
|
if (!map.has(context.message!.channel_id)) {
|
||||||
|
@ -40,10 +40,10 @@ 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))));
|
const users = unique(Array.from(new Set(_contexts.map((c) => c.user).filter(Boolean))));
|
||||||
const user = users[0];
|
const user = users[0];
|
||||||
|
|
||||||
const renderReplyText = async str =>
|
const renderReplyText = async (str) =>
|
||||||
renderTemplate(str, {
|
renderTemplate(str, {
|
||||||
user: stripObjectToScalars(user),
|
user: stripObjectToScalars(user),
|
||||||
});
|
});
|
||||||
|
|
|
@ -25,8 +25,8 @@ export const WarnAction = automodAction({
|
||||||
extraNotes: matchResult.fullSummary ? [matchResult.fullSummary] : [],
|
extraNotes: matchResult.fullSummary ? [matchResult.fullSummary] : [],
|
||||||
};
|
};
|
||||||
|
|
||||||
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 { RECENT_ACTION_EXPIRY_TIME } from "../constants";
|
||||||
|
|
||||||
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 { RECENT_SPAM_EXPIRY_TIME } from "../constants";
|
||||||
|
|
||||||
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;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,7 +8,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) &&
|
||||||
|
|
|
@ -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: {
|
||||||
|
|
|
@ -37,13 +37,10 @@ export const MatchAttachmentTypeTrigger = automodTrigger<MatchResultType>()({
|
||||||
const attachments: any[] = context.message.data.attachments;
|
const attachments: any[] = context.message.data.attachments;
|
||||||
|
|
||||||
for (const attachment of attachments) {
|
for (const attachment of attachments) {
|
||||||
const attachmentType = attachment.filename
|
const attachmentType = attachment.filename.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)) {
|
||||||
|
@ -56,7 +53,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)) {
|
||||||
|
|
|
@ -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({
|
||||||
}
|
}
|
||||||
|
|
||||||
const userNameList = args.users.map(
|
const userNameList = args.users.map(
|
||||||
user => `<@!${user.id}> (**${user.username}#${user.discriminator}**, \`${user.id}\`)`,
|
(user) => `<@!${user.id}> (**${user.username}#${user.discriminator}**, \`${user.id}\`)`,
|
||||||
);
|
);
|
||||||
sendSuccessMessage(
|
sendSuccessMessage(
|
||||||
pluginData,
|
pluginData,
|
||||||
|
|
|
@ -23,9 +23,9 @@ 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(dashboardUsers.map(perm => resolveUser(pluginData.client, perm.target_id)));
|
const users = await Promise.all(dashboardUsers.map((perm) => resolveUser(pluginData.client, perm.target_id)));
|
||||||
const userNameList = users.map(
|
const userNameList = users.map(
|
||||||
user => `<@!${user.id}> (**${user.username}#${user.discriminator}**, \`${user.id}\`)`,
|
(user) => `<@!${user.id}> (**${user.username}#${user.discriminator}**, \`${user.id}\`)`,
|
||||||
);
|
);
|
||||||
|
|
||||||
sendSuccessMessage(
|
sendSuccessMessage(
|
||||||
|
|
|
@ -35,7 +35,7 @@ export const RemoveDashboardUserCmd = botControlCmd({
|
||||||
}
|
}
|
||||||
|
|
||||||
const userNameList = args.users.map(
|
const userNameList = args.users.map(
|
||||||
user => `<@!${user.id}> (**${user.username}#${user.discriminator}**, \`${user.id}\`)`,
|
(user) => `<@!${user.id}> (**${user.username}#${user.discriminator}**, \`${user.id}\`)`,
|
||||||
);
|
);
|
||||||
sendSuccessMessage(
|
sendSuccessMessage(
|
||||||
pluginData,
|
pluginData,
|
||||||
|
|
|
@ -21,7 +21,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.values());
|
const joinedGuilds = Array.from(pluginData.client.guilds.values());
|
||||||
const loadedGuilds = pluginData.getKnubInstance().getLoadedGuilds();
|
const loadedGuilds = pluginData.getKnubInstance().getLoadedGuilds();
|
||||||
|
@ -31,21 +31,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.username}#${owner.discriminator}** \`${owner.id}\`)`;
|
return `\`${paddedId}\` **${g.name}** (${g.memberCount} members) (owner **${owner.username}#${owner.discriminator}** \`${owner.id}\`)`;
|
||||||
|
@ -56,7 +56,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.createMessage(
|
msg.channel.createMessage(
|
||||||
|
|
|
@ -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++;
|
||||||
}
|
}
|
||||||
|
|
|
@ -65,10 +65,10 @@ export const CensorPlugin = zeppelinGuildPlugin<CensorPluginType>()("censor", {
|
||||||
|
|
||||||
state.regexRunner = getRegExpRunner(`guild-${pluginData.guild.id}`);
|
state.regexRunner = getRegExpRunner(`guild-${pluginData.guild.id}`);
|
||||||
|
|
||||||
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);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
|
@ -20,7 +20,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 Embed[]).map(e => cloneDeep(e));
|
const embeds = (savedMessage.data.embeds as Embed[]).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
|
||||||
|
@ -53,7 +53,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) {
|
||||||
|
|
|
@ -66,9 +66,9 @@ export const ArchiveChannelCmd = channelArchiverCmd({
|
||||||
|
|
||||||
for (const message of messages) {
|
for (const message of messages) {
|
||||||
const ts = moment.utc(message.timestamp).format("YYYY-MM-DD HH:mm:ss");
|
const ts = moment.utc(message.timestamp).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.length) {
|
if (message.attachments.length) {
|
||||||
if (args["attachment-channel"]) {
|
if (args["attachment-channel"]) {
|
||||||
|
|
|
@ -14,9 +14,9 @@ export function getCompanionChannelOptsForVoiceChannelId(
|
||||||
const config = pluginData.config.getMatchingConfig({ userId, channelId: voiceChannel.id });
|
const config = 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));
|
||||||
}
|
}
|
||||||
|
|
|
@ -44,7 +44,7 @@ const defaultOptions: PluginOptions<CountersPluginType> = {
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
|
||||||
const configPreprocessor: ConfigPreprocessorFn<CountersPluginType> = options => {
|
const configPreprocessor: ConfigPreprocessorFn<CountersPluginType> = (options) => {
|
||||||
for (const counter of Object.values(options.config?.counters || {})) {
|
for (const counter of Object.values(options.config?.counters || {})) {
|
||||||
counter.per_user = counter.per_user ?? false;
|
counter.per_user = counter.per_user ?? false;
|
||||||
counter.per_channel = counter.per_channel ?? false;
|
counter.per_channel = counter.per_channel ?? false;
|
||||||
|
|
|
@ -37,10 +37,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)),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -24,8 +24,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();
|
||||||
|
|
|
@ -34,10 +34,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)),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,7 @@ export const GuildBanRemoveAlertsEvt = locateUserEvt({
|
||||||
|
|
||||||
async listener(meta) {
|
async listener(meta) {
|
||||||
const alerts = await meta.pluginData.state.alerts.getAlertsByUserId(meta.args.user.id);
|
const alerts = await meta.pluginData.state.alerts.getAlertsByUserId(meta.args.user.id);
|
||||||
alerts.forEach(alert => {
|
alerts.forEach((alert) => {
|
||||||
meta.pluginData.state.alerts.delete(alert.id);
|
meta.pluginData.state.alerts.delete(alert.id);
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
|
@ -29,7 +29,7 @@ export const ChannelLeaveAlertsEvt = locateUserEvt({
|
||||||
const triggeredAlerts = await meta.pluginData.state.alerts.getAlertsByUserId(meta.args.member.id);
|
const triggeredAlerts = await meta.pluginData.state.alerts.getAlertsByUserId(meta.args.member.id);
|
||||||
const voiceChannel = meta.args.oldChannel as VoiceChannel;
|
const voiceChannel = meta.args.oldChannel as VoiceChannel;
|
||||||
|
|
||||||
triggeredAlerts.forEach(alert => {
|
triggeredAlerts.forEach((alert) => {
|
||||||
const txtChannel = meta.pluginData.client.getChannel(alert.channel_id) as TextableChannel;
|
const txtChannel = meta.pluginData.client.getChannel(alert.channel_id) as TextableChannel;
|
||||||
txtChannel.createMessage(
|
txtChannel.createMessage(
|
||||||
`🔴 <@!${alert.requestor_id}> the user <@!${alert.user_id}> disconnected out of \`${voiceChannel.name}\``,
|
`🔴 <@!${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.client.getChannel(alert.channel_id) as TextableChannel;
|
const txtChannel = pluginData.client.getChannel(alert.channel_id) as TextableChannel;
|
||||||
sendWhere(pluginData, member, txtChannel, prepend);
|
sendWhere(pluginData, member, txtChannel, prepend);
|
||||||
|
|
|
@ -97,10 +97,10 @@ export const LogsPlugin = zeppelinGuildPlugin<LogsPluginType>()("logs", {
|
||||||
|
|
||||||
state.batches = new Map();
|
state.batches = new Map();
|
||||||
|
|
||||||
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);
|
||||||
|
|
|
@ -24,7 +24,7 @@ export const LogsGuildMemberAddEvt = logsEvt({
|
||||||
account_age: accountAge,
|
account_age: accountAge,
|
||||||
});
|
});
|
||||||
|
|
||||||
const cases = (await pluginData.state.cases.with("notes").getByUserId(member.id)).filter(c => !c.is_hidden);
|
const cases = (await pluginData.state.cases.with("notes").getByUserId(member.id)).filter((c) => !c.is_hidden);
|
||||||
cases.sort((a, b) => (a.created_at > b.created_at ? -1 : 1));
|
cases.sort((a, b) => (a.created_at > b.created_at ? -1 : 1));
|
||||||
|
|
||||||
if (cases.length) {
|
if (cases.length) {
|
||||||
|
|
|
@ -61,12 +61,12 @@ export const LogsGuildMemberUpdateEvt = logsEvt({
|
||||||
{
|
{
|
||||||
member: logMember,
|
member: logMember,
|
||||||
addedRoles: addedRoles
|
addedRoles: addedRoles
|
||||||
.map(roleId => pluginData.guild.roles.get(roleId) || { id: roleId, name: `Unknown (${roleId})` })
|
.map((roleId) => pluginData.guild.roles.get(roleId) || { id: roleId, name: `Unknown (${roleId})` })
|
||||||
.map(r => r.name)
|
.map((r) => r.name)
|
||||||
.join(", "),
|
.join(", "),
|
||||||
removedRoles: removedRoles
|
removedRoles: removedRoles
|
||||||
.map(roleId => pluginData.guild.roles.get(roleId) || { id: roleId, name: `Unknown (${roleId})` })
|
.map((roleId) => pluginData.guild.roles.get(roleId) || { id: roleId, name: `Unknown (${roleId})` })
|
||||||
.map(r => r.name)
|
.map((r) => r.name)
|
||||||
.join(", "),
|
.join(", "),
|
||||||
mod: stripObjectToScalars(mod),
|
mod: stripObjectToScalars(mod),
|
||||||
},
|
},
|
||||||
|
@ -79,8 +79,8 @@ export const LogsGuildMemberUpdateEvt = logsEvt({
|
||||||
{
|
{
|
||||||
member: logMember,
|
member: logMember,
|
||||||
roles: addedRoles
|
roles: addedRoles
|
||||||
.map(roleId => pluginData.guild.roles.get(roleId) || { id: roleId, name: `Unknown (${roleId})` })
|
.map((roleId) => pluginData.guild.roles.get(roleId) || { id: roleId, name: `Unknown (${roleId})` })
|
||||||
.map(r => r.name)
|
.map((r) => r.name)
|
||||||
.join(", "),
|
.join(", "),
|
||||||
mod: stripObjectToScalars(mod),
|
mod: stripObjectToScalars(mod),
|
||||||
},
|
},
|
||||||
|
@ -93,8 +93,8 @@ export const LogsGuildMemberUpdateEvt = logsEvt({
|
||||||
{
|
{
|
||||||
member: logMember,
|
member: logMember,
|
||||||
roles: removedRoles
|
roles: removedRoles
|
||||||
.map(roleId => pluginData.guild.roles.get(roleId) || { id: roleId, name: `Unknown (${roleId})` })
|
.map((roleId) => pluginData.guild.roles.get(roleId) || { id: roleId, name: `Unknown (${roleId})` })
|
||||||
.map(r => r.name)
|
.map((r) => r.name)
|
||||||
.join(", "),
|
.join(", "),
|
||||||
mod: stripObjectToScalars(mod),
|
mod: stripObjectToScalars(mod),
|
||||||
},
|
},
|
||||||
|
|
|
@ -41,7 +41,7 @@ export async function getLogMessage(
|
||||||
const values = {
|
const values = {
|
||||||
...data,
|
...data,
|
||||||
timestamp,
|
timestamp,
|
||||||
userMention: async inputUserOrMember => {
|
userMention: async (inputUserOrMember) => {
|
||||||
if (!inputUserOrMember) return "";
|
if (!inputUserOrMember) return "";
|
||||||
|
|
||||||
const usersOrMembers = Array.isArray(inputUserOrMember) ? inputUserOrMember : [inputUserOrMember];
|
const usersOrMembers = Array.isArray(inputUserOrMember) ? inputUserOrMember : [inputUserOrMember];
|
||||||
|
@ -71,7 +71,7 @@ export async function getLogMessage(
|
||||||
|
|
||||||
return mentions.join(", ");
|
return mentions.join(", ");
|
||||||
},
|
},
|
||||||
channelMention: channel => {
|
channelMention: (channel) => {
|
||||||
if (!channel) return "";
|
if (!channel) return "";
|
||||||
return verboseChannelMention(channel);
|
return verboseChannelMention(channel);
|
||||||
},
|
},
|
||||||
|
@ -83,12 +83,12 @@ export async function getLogMessage(
|
||||||
|
|
||||||
if (type === LogType.BOT_ALERT) {
|
if (type === LogType.BOT_ALERT) {
|
||||||
const valuesWithoutTmplEval = { ...values };
|
const valuesWithoutTmplEval = { ...values };
|
||||||
values.tmplEval = str => {
|
values.tmplEval = (str) => {
|
||||||
return renderTemplate(str, valuesWithoutTmplEval);
|
return renderTemplate(str, valuesWithoutTmplEval);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
const renderLogString = str => renderTemplate(str, values);
|
const renderLogString = (str) => renderTemplate(str, values);
|
||||||
|
|
||||||
let formatted;
|
let formatted;
|
||||||
try {
|
try {
|
||||||
|
|
|
@ -8,7 +8,7 @@ export async function onMessageDeleteBulk(pluginData: GuildPluginData<LogsPlugin
|
||||||
const channel = pluginData.guild.channels.get(savedMessages[0].channel_id);
|
const channel = pluginData.guild.channels.get(savedMessages[0].channel_id);
|
||||||
const archiveId = await pluginData.state.archives.createFromSavedMessages(savedMessages, pluginData.guild);
|
const archiveId = await pluginData.state.archives.createFromSavedMessages(savedMessages, pluginData.guild);
|
||||||
const archiveUrl = pluginData.state.archives.getUrl(getBaseUrl(pluginData), archiveId);
|
const archiveUrl = pluginData.state.archives.getUrl(getBaseUrl(pluginData), archiveId);
|
||||||
const authorIds = Array.from(new Set(savedMessages.map(item => `\`${item.user_id}\``))).join(", ");
|
const authorIds = Array.from(new Set(savedMessages.map((item) => `\`${item.user_id}\``))).join(", ");
|
||||||
|
|
||||||
pluginData.state.guildLogs.log(
|
pluginData.state.guildLogs.log(
|
||||||
LogType.MESSAGE_DELETE_BULK,
|
LogType.MESSAGE_DELETE_BULK,
|
||||||
|
|
|
@ -15,12 +15,12 @@ export async function onMessageUpdate(
|
||||||
let logUpdate = false;
|
let logUpdate = false;
|
||||||
|
|
||||||
const oldEmbedsToCompare = ((oldSavedMessage.data.embeds || []) as Embed[])
|
const oldEmbedsToCompare = ((oldSavedMessage.data.embeds || []) as Embed[])
|
||||||
.map(e => cloneDeep(e))
|
.map((e) => cloneDeep(e))
|
||||||
.filter(e => (e as Embed).type === "rich");
|
.filter((e) => (e as Embed).type === "rich");
|
||||||
|
|
||||||
const newEmbedsToCompare = ((savedMessage.data.embeds || []) as Embed[])
|
const newEmbedsToCompare = ((savedMessage.data.embeds || []) as Embed[])
|
||||||
.map(e => cloneDeep(e))
|
.map((e) => cloneDeep(e))
|
||||||
.filter(e => (e as Embed).type === "rich");
|
.filter((e) => (e as Embed).type === "rich");
|
||||||
|
|
||||||
for (const embed of [...oldEmbedsToCompare, ...newEmbedsToCompare]) {
|
for (const embed of [...oldEmbedsToCompare, ...newEmbedsToCompare]) {
|
||||||
if (embed.thumbnail) {
|
if (embed.thumbnail) {
|
||||||
|
|
|
@ -19,7 +19,7 @@ export const SavePinsToDBCmd = messageSaverCmd({
|
||||||
const { savedCount, failed } = await saveMessagesToDB(
|
const { savedCount, failed } = await saveMessagesToDB(
|
||||||
pluginData,
|
pluginData,
|
||||||
args.channel,
|
args.channel,
|
||||||
pins.map(m => m.id),
|
pins.map((m) => m.id),
|
||||||
);
|
);
|
||||||
|
|
||||||
if (failed.length) {
|
if (failed.length) {
|
||||||
|
|
|
@ -51,7 +51,7 @@ export const MessageDeleteBulkEvt = messageSaverEvt({
|
||||||
allowSelf: true,
|
allowSelf: true,
|
||||||
|
|
||||||
async listener(meta) {
|
async listener(meta) {
|
||||||
const ids = meta.args.messages.map(m => m.id);
|
const ids = meta.args.messages.map((m) => m.id);
|
||||||
await meta.pluginData.state.savedMessages.markBulkAsDeleted(ids);
|
await meta.pluginData.state.savedMessages.markBulkAsDeleted(ids);
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
|
@ -47,9 +47,9 @@ export const CasesModCmd = modActionsCmd({
|
||||||
pluginData.client,
|
pluginData.client,
|
||||||
msg.channel,
|
msg.channel,
|
||||||
totalPages,
|
totalPages,
|
||||||
async page => {
|
async (page) => {
|
||||||
const cases = await casesPlugin.getRecentCasesByMod(modId, casesPerPage, (page - 1) * casesPerPage);
|
const cases = await casesPlugin.getRecentCasesByMod(modId, casesPerPage, (page - 1) * casesPerPage);
|
||||||
const lines = await asyncMap(cases, c => casesPlugin.getCaseSummary(c, true, msg.author.id));
|
const lines = await asyncMap(cases, (c) => casesPlugin.getCaseSummary(c, true, msg.author.id));
|
||||||
|
|
||||||
const firstCaseNum = (page - 1) * casesPerPage + 1;
|
const firstCaseNum = (page - 1) * casesPerPage + 1;
|
||||||
const lastCaseNum = page * casesPerPage;
|
const lastCaseNum = page * casesPerPage;
|
||||||
|
|
|
@ -42,8 +42,8 @@ export const CasesUserCmd = modActionsCmd({
|
||||||
}
|
}
|
||||||
|
|
||||||
const cases = await pluginData.state.cases.with("notes").getByUserId(user.id);
|
const cases = await pluginData.state.cases.with("notes").getByUserId(user.id);
|
||||||
const normalCases = cases.filter(c => !c.is_hidden);
|
const normalCases = cases.filter((c) => !c.is_hidden);
|
||||||
const hiddenCases = cases.filter(c => c.is_hidden);
|
const hiddenCases = cases.filter((c) => c.is_hidden);
|
||||||
|
|
||||||
const userName =
|
const userName =
|
||||||
user instanceof UnknownUser && cases.length
|
user instanceof UnknownUser && cases.length
|
||||||
|
@ -70,7 +70,7 @@ export const CasesUserCmd = modActionsCmd({
|
||||||
} else {
|
} else {
|
||||||
// Compact view (= regular message with a preview of each case)
|
// Compact view (= regular message with a preview of each case)
|
||||||
const casesPlugin = pluginData.getPlugin(CasesPlugin);
|
const casesPlugin = pluginData.getPlugin(CasesPlugin);
|
||||||
const lines = await asyncMap(casesToDisplay, c => casesPlugin.getCaseSummary(c, true, msg.author.id));
|
const lines = await asyncMap(casesToDisplay, (c) => casesPlugin.getCaseSummary(c, true, msg.author.id));
|
||||||
|
|
||||||
const prefix = getGuildPrefix(pluginData);
|
const prefix = getGuildPrefix(pluginData);
|
||||||
const linesPerChunk = 10;
|
const linesPerChunk = 10;
|
||||||
|
|
|
@ -52,7 +52,7 @@ export const MassbanCmd = modActionsCmd({
|
||||||
|
|
||||||
// Ignore automatic ban cases and logs for these users
|
// Ignore automatic ban cases and logs for these users
|
||||||
// We'll create our own cases below and post a single "mass banned" log instead
|
// We'll create our own cases below and post a single "mass banned" log instead
|
||||||
args.userIds.forEach(userId => {
|
args.userIds.forEach((userId) => {
|
||||||
// Use longer timeouts since this can take a while
|
// Use longer timeouts since this can take a while
|
||||||
ignoreEvent(pluginData, IgnoredEventType.Ban, userId, 120 * 1000);
|
ignoreEvent(pluginData, IgnoredEventType.Ban, userId, 120 * 1000);
|
||||||
pluginData.state.serverLogs.ignoreLog(LogType.MEMBER_BAN, userId, 120 * 1000);
|
pluginData.state.serverLogs.ignoreLog(LogType.MEMBER_BAN, userId, 120 * 1000);
|
||||||
|
|
|
@ -41,7 +41,7 @@ export const MassunbanCmd = modActionsCmd({
|
||||||
|
|
||||||
// Ignore automatic unban cases and logs for these users
|
// Ignore automatic unban cases and logs for these users
|
||||||
// We'll create our own cases below and post a single "mass unbanned" log instead
|
// We'll create our own cases below and post a single "mass unbanned" log instead
|
||||||
args.userIds.forEach(userId => {
|
args.userIds.forEach((userId) => {
|
||||||
// Use longer timeouts since this can take a while
|
// Use longer timeouts since this can take a while
|
||||||
ignoreEvent(pluginData, IgnoredEventType.Unban, userId, 120 * 1000);
|
ignoreEvent(pluginData, IgnoredEventType.Unban, userId, 120 * 1000);
|
||||||
pluginData.state.serverLogs.ignoreLog(LogType.MEMBER_UNBAN, userId, 120 * 1000);
|
pluginData.state.serverLogs.ignoreLog(LogType.MEMBER_UNBAN, userId, 120 * 1000);
|
||||||
|
@ -90,19 +90,19 @@ export const MassunbanCmd = modActionsCmd({
|
||||||
});
|
});
|
||||||
|
|
||||||
if (failedUnbans.length) {
|
if (failedUnbans.length) {
|
||||||
const notBanned = failedUnbans.filter(x => x.reason === UnbanFailReasons.NOT_BANNED);
|
const notBanned = failedUnbans.filter((x) => x.reason === UnbanFailReasons.NOT_BANNED);
|
||||||
const unbanFailed = failedUnbans.filter(x => x.reason === UnbanFailReasons.UNBAN_FAILED);
|
const unbanFailed = failedUnbans.filter((x) => x.reason === UnbanFailReasons.UNBAN_FAILED);
|
||||||
|
|
||||||
let failedMsg = "";
|
let failedMsg = "";
|
||||||
if (notBanned.length > 0) {
|
if (notBanned.length > 0) {
|
||||||
failedMsg += `${notBanned.length}x ${UnbanFailReasons.NOT_BANNED}:`;
|
failedMsg += `${notBanned.length}x ${UnbanFailReasons.NOT_BANNED}:`;
|
||||||
notBanned.forEach(fail => {
|
notBanned.forEach((fail) => {
|
||||||
failedMsg += " " + fail.userId;
|
failedMsg += " " + fail.userId;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
if (unbanFailed.length > 0) {
|
if (unbanFailed.length > 0) {
|
||||||
failedMsg += `\n${unbanFailed.length}x ${UnbanFailReasons.UNBAN_FAILED}:`;
|
failedMsg += `\n${unbanFailed.length}x ${UnbanFailReasons.UNBAN_FAILED}:`;
|
||||||
unbanFailed.forEach(fail => {
|
unbanFailed.forEach((fail) => {
|
||||||
failedMsg += " " + fail.userId;
|
failedMsg += " " + fail.userId;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -52,7 +52,7 @@ export const MassmuteCmd = modActionsCmd({
|
||||||
|
|
||||||
// Ignore automatic mute cases and logs for these users
|
// Ignore automatic mute cases and logs for these users
|
||||||
// We'll create our own cases below and post a single "mass muted" log instead
|
// We'll create our own cases below and post a single "mass muted" log instead
|
||||||
args.userIds.forEach(userId => {
|
args.userIds.forEach((userId) => {
|
||||||
// Use longer timeouts since this can take a while
|
// Use longer timeouts since this can take a while
|
||||||
pluginData.state.serverLogs.ignoreLog(LogType.MEMBER_MUTE, userId, 120 * 1000);
|
pluginData.state.serverLogs.ignoreLog(LogType.MEMBER_MUTE, userId, 120 * 1000);
|
||||||
});
|
});
|
||||||
|
|
|
@ -7,7 +7,7 @@ export function clearIgnoredEvents(
|
||||||
userId: string,
|
userId: string,
|
||||||
) {
|
) {
|
||||||
pluginData.state.ignoredEvents.splice(
|
pluginData.state.ignoredEvents.splice(
|
||||||
pluginData.state.ignoredEvents.findIndex(info => type === info.type && userId === info.userId),
|
pluginData.state.ignoredEvents.findIndex((info) => type === info.type && userId === info.userId),
|
||||||
1,
|
1,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import { Attachment } from "eris";
|
import { Attachment } from "eris";
|
||||||
|
|
||||||
export function formatReasonWithAttachments(reason: string, attachments: Attachment[]) {
|
export function formatReasonWithAttachments(reason: string, attachments: Attachment[]) {
|
||||||
const attachmentUrls = attachments.map(a => a.url);
|
const attachmentUrls = attachments.map((a) => a.url);
|
||||||
return ((reason || "") + " " + attachmentUrls.join(" ")).trim();
|
return ((reason || "") + " " + attachmentUrls.join(" ")).trim();
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,7 +5,7 @@ import { isDiscordHTTPError } from "../../../utils";
|
||||||
export async function isBanned(pluginData: GuildPluginData<ModActionsPluginType>, userId: string): Promise<boolean> {
|
export async function isBanned(pluginData: GuildPluginData<ModActionsPluginType>, userId: string): Promise<boolean> {
|
||||||
try {
|
try {
|
||||||
const bans = await pluginData.guild.getBans();
|
const bans = await pluginData.guild.getBans();
|
||||||
return bans.some(b => b.user.id === userId);
|
return bans.some((b) => b.user.id === userId);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
if (isDiscordHTTPError(e) && e.code === 500) {
|
if (isDiscordHTTPError(e) && e.code === 500) {
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -6,5 +6,5 @@ export function isEventIgnored(
|
||||||
type: IgnoredEventType,
|
type: IgnoredEventType,
|
||||||
userId: string,
|
userId: string,
|
||||||
) {
|
) {
|
||||||
return pluginData.state.ignoredEvents.some(info => type === info.type && userId === info.userId);
|
return pluginData.state.ignoredEvents.some((info) => type === info.type && userId === info.userId);
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,7 +14,7 @@ export const ClearBannedMutesCmd = mutesCmd({
|
||||||
|
|
||||||
// Mismatch in Eris docs and actual result here, based on Eris's code comments anyway
|
// Mismatch in Eris docs and actual result here, based on Eris's code comments anyway
|
||||||
const bans: Array<{ reason: string; user: User }> = (await pluginData.guild.getBans()) as any;
|
const bans: Array<{ reason: string; user: User }> = (await pluginData.guild.getBans()) as any;
|
||||||
const bannedIds = bans.map(b => b.user.id);
|
const bannedIds = bans.map((b) => b.user.id);
|
||||||
|
|
||||||
await msg.channel.createMessage(
|
await msg.channel.createMessage(
|
||||||
`Found ${activeMutes.length} mutes and ${bannedIds.length} bans, cross-referencing...`,
|
`Found ${activeMutes.length} mutes and ${bannedIds.length} bans, cross-referencing...`,
|
||||||
|
|
|
@ -47,12 +47,12 @@ export const MutesCmd = mutesCmd({
|
||||||
|
|
||||||
if (args.manual) {
|
if (args.manual) {
|
||||||
// Show only manual mutes (i.e. "Muted" role added without a logged mute)
|
// Show only manual mutes (i.e. "Muted" role added without a logged mute)
|
||||||
const muteUserIds = new Set(activeMutes.map(m => m.user_id));
|
const muteUserIds = new Set(activeMutes.map((m) => m.user_id));
|
||||||
const manuallyMutedMembers: Member[] = [];
|
const manuallyMutedMembers: Member[] = [];
|
||||||
const muteRole = pluginData.config.get().mute_role;
|
const muteRole = pluginData.config.get().mute_role;
|
||||||
|
|
||||||
if (muteRole) {
|
if (muteRole) {
|
||||||
pluginData.guild.members.forEach(member => {
|
pluginData.guild.members.forEach((member) => {
|
||||||
if (muteUserIds.has(member.id)) return;
|
if (muteUserIds.has(member.id)) return;
|
||||||
if (member.roles.includes(muteRole)) manuallyMutedMembers.push(member);
|
if (member.roles.includes(muteRole)) manuallyMutedMembers.push(member);
|
||||||
});
|
});
|
||||||
|
@ -60,7 +60,7 @@ export const MutesCmd = mutesCmd({
|
||||||
|
|
||||||
totalMutes = manuallyMutedMembers.length;
|
totalMutes = manuallyMutedMembers.length;
|
||||||
|
|
||||||
lines = manuallyMutedMembers.map(member => {
|
lines = manuallyMutedMembers.map((member) => {
|
||||||
return `<@!${member.id}> (**${member.user.username}#${member.user.discriminator}**, \`${member.id}\`) 🔧 Manual mute`;
|
return `<@!${member.id}> (**${member.user.username}#${member.user.discriminator}**, \`${member.id}\`) 🔧 Manual mute`;
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
|
@ -70,11 +70,8 @@ export const MutesCmd = mutesCmd({
|
||||||
|
|
||||||
// Filter: mute age
|
// Filter: mute age
|
||||||
if (args.age) {
|
if (args.age) {
|
||||||
const cutoff = moment
|
const cutoff = moment.utc().subtract(args.age, "ms").format(DBDateFormat);
|
||||||
.utc()
|
filteredMutes = filteredMutes.filter((m) => m.created_at <= cutoff);
|
||||||
.subtract(args.age, "ms")
|
|
||||||
.format(DBDateFormat);
|
|
||||||
filteredMutes = filteredMutes.filter(m => m.created_at <= cutoff);
|
|
||||||
hasFilters = true;
|
hasFilters = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -87,7 +84,7 @@ export const MutesCmd = mutesCmd({
|
||||||
if (!member) {
|
if (!member) {
|
||||||
if (!bannedIds) {
|
if (!bannedIds) {
|
||||||
const bans = await pluginData.guild.getBans();
|
const bans = await pluginData.guild.getBans();
|
||||||
bannedIds = bans.map(u => u.user.id);
|
bannedIds = bans.map((u) => u.user.id);
|
||||||
}
|
}
|
||||||
|
|
||||||
muteWithDetails.banned = bannedIds.includes(mute.user_id);
|
muteWithDetails.banned = bannedIds.includes(mute.user_id);
|
||||||
|
@ -100,18 +97,18 @@ export const MutesCmd = mutesCmd({
|
||||||
|
|
||||||
// Filter: left the server
|
// Filter: left the server
|
||||||
if (args.left != null) {
|
if (args.left != null) {
|
||||||
filteredMutes = filteredMutes.filter(m => (args.left && !m.member) || (!args.left && m.member));
|
filteredMutes = filteredMutes.filter((m) => (args.left && !m.member) || (!args.left && m.member));
|
||||||
hasFilters = true;
|
hasFilters = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
totalMutes = filteredMutes.length;
|
totalMutes = filteredMutes.length;
|
||||||
|
|
||||||
// Create a message line for each mute
|
// Create a message line for each mute
|
||||||
const caseIds = filteredMutes.map(m => m.case_id).filter(v => !!v);
|
const caseIds = filteredMutes.map((m) => m.case_id).filter((v) => !!v);
|
||||||
const muteCases = caseIds.length ? await pluginData.state.cases.get(caseIds) : [];
|
const muteCases = caseIds.length ? await pluginData.state.cases.get(caseIds) : [];
|
||||||
const muteCasesById = muteCases.reduce((map, c) => map.set(c.id, c), new Map());
|
const muteCasesById = muteCases.reduce((map, c) => map.set(c.id, c), new Map());
|
||||||
|
|
||||||
lines = filteredMutes.map(mute => {
|
lines = filteredMutes.map((mute) => {
|
||||||
const user = pluginData.client.users.get(mute.user_id);
|
const user = pluginData.client.users.get(mute.user_id);
|
||||||
const username = user ? `${user.username}#${user.discriminator}` : "Unknown#0000";
|
const username = user ? `${user.username}#${user.discriminator}` : "Unknown#0000";
|
||||||
const theCase = muteCasesById.get(mute.case_id);
|
const theCase = muteCasesById.get(mute.case_id);
|
||||||
|
@ -146,7 +143,7 @@ export const MutesCmd = mutesCmd({
|
||||||
let currentPage = 1;
|
let currentPage = 1;
|
||||||
const totalPages = Math.ceil(lines.length / mutesPerPage);
|
const totalPages = Math.ceil(lines.length / mutesPerPage);
|
||||||
|
|
||||||
const drawListPage = async page => {
|
const drawListPage = async (page) => {
|
||||||
page = Math.max(1, Math.min(totalPages, page));
|
page = Math.max(1, Math.min(totalPages, page));
|
||||||
currentPage = page;
|
currentPage = page;
|
||||||
|
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue