3
0
Fork 0
mirror of https://github.com/ZeppelinBot/Zeppelin.git synced 2025-03-14 21:31:50 +00:00

chore: fix lint errors; tweak lint rules

This commit is contained in:
Dragory 2023-05-08 22:58:51 +03:00
parent 9b3d6f5d68
commit 5f194bf1ef
No known key found for this signature in database
GPG key ID: 5F387BA66DF8AAC1
115 changed files with 176 additions and 264 deletions

View file

@ -12,5 +12,17 @@ module.exports = {
"@typescript-eslint/no-explicit-any": 0, "@typescript-eslint/no-explicit-any": 0,
"@typescript-eslint/ban-ts-comment": 0, "@typescript-eslint/ban-ts-comment": 0,
"@typescript-eslint/no-non-null-assertion": 0, "@typescript-eslint/no-non-null-assertion": 0,
"no-async-promise-executor": 0,
"@typescript-eslint/no-empty-interface": 0,
"no-constant-condition": ["error", {
checkLoops: false,
}],
"prefer-const": ["error", {
destructuring: "all",
ignoreReadBeforeAssign: true,
}],
"@typescript-eslint/no-namespace": ["error", {
allowDeclarations: true,
}],
}, },
}; };

View file

@ -7,7 +7,7 @@ export class SimpleError extends Error {
super(message); super(message);
} }
[util.inspect.custom](depth, options) { [util.inspect.custom]() {
return `Error: ${this.message}`; return `Error: ${this.message}`;
} }
} }

View file

@ -18,7 +18,6 @@ interface IPassportApiUser {
declare global { declare global {
namespace Express { namespace Express {
// tslint:disable-next-line:no-empty-interface
interface User extends IPassportApiUser {} interface User extends IPassportApiUser {}
} }
} }
@ -151,6 +150,7 @@ export function initAuth(app: express.Express) {
export function apiTokenAuthHandlers() { export function apiTokenAuthHandlers() {
return [ return [
passport.authenticate("api-token", { failWithError: true }), passport.authenticate("api-token", { failWithError: true }),
// eslint-disable-next-line @typescript-eslint/no-unused-vars
(err, req: Request, res: Response, next) => { (err, req: Request, res: Response, next) => {
return res.status(401).json({ error: err.message }); return res.status(401).json({ error: err.message });
}, },

View file

@ -50,7 +50,7 @@ export function initGuildsImportExportAPI(guildRouter: express.Router) {
importExportRouter.get( importExportRouter.get(
"/:guildId/pre-import", "/:guildId/pre-import",
requireGuildPermission(ApiPermissions.ManageAccess), requireGuildPermission(ApiPermissions.ManageAccess),
async (req: Request, res: Response) => { async (req: Request) => {
const guildCases = GuildCases.getGuildInstance(req.params.guildId); const guildCases = GuildCases.getGuildInstance(req.params.guildId);
const minNum = await guildCases.getMinCaseNumber(); const minNum = await guildCases.getMinCaseNumber();
const maxNum = await guildCases.getMaxCaseNumber(); const maxNum = await guildCases.getMaxCaseNumber();

View file

@ -4,7 +4,7 @@ export function unauthorized(res: Response) {
res.status(403).json({ error: "Unauthorized" }); res.status(403).json({ error: "Unauthorized" });
} }
export function error(res: Response, message: string, statusCode: number = 500) { export function error(res: Response, message: string, statusCode = 500) {
res.status(statusCode).json({ error: message }); res.status(statusCode).json({ error: message });
} }

View file

@ -35,6 +35,7 @@ app.get("/", (req, res) => {
}); });
// Error response // Error response
// eslint-disable-next-line @typescript-eslint/no-unused-vars
app.use((err, req, res, next) => { app.use((err, req, res, next) => {
if (err instanceof TokenError) { if (err instanceof TokenError) {
clientError(res, "Invalid code"); clientError(res, "Invalid code");
@ -45,6 +46,7 @@ app.use((err, req, res, next) => {
}); });
// 404 response // 404 response
// eslint-disable-next-line @typescript-eslint/no-unused-vars
app.use((req, res, next) => { app.use((req, res, next) => {
return notFound(res); return notFound(res);
}); });

View file

@ -96,7 +96,7 @@ export const commandTypes = {
throw new TypeConversionError(`Could not parse ID: \`${escapeInlineCode(value)}\``); throw new TypeConversionError(`Could not parse ID: \`${escapeInlineCode(value)}\``);
}, },
regex(value: string, context: CommandContext<any>): RegExp { regex(value: string): RegExp {
try { try {
return inputPatternToRegExp(value); return inputPatternToRegExp(value);
} catch (e) { } catch (e) {

View file

@ -1,6 +1,6 @@
import { BaseRepository } from "./BaseRepository"; import { BaseRepository } from "./BaseRepository";
export class BaseGuildRepository<TEntity extends unknown = unknown> extends BaseRepository<TEntity> { export class BaseGuildRepository<TEntity = unknown> extends BaseRepository<TEntity> {
private static guildInstances: Map<string, any>; private static guildInstances: Map<string, any>;
protected guildId: string; protected guildId: string;

View file

@ -1,6 +1,6 @@
import { asyncMap } from "../utils/async"; import { asyncMap } from "../utils/async";
export class BaseRepository<TEntity extends unknown = unknown> { export class BaseRepository<TEntity = unknown> {
private nextRelations: string[]; private nextRelations: string[];
constructor() { constructor() {

View file

@ -6,15 +6,16 @@ import { cleanupConfigs } from "./cleanup/configs";
import { connection } from "./db"; import { connection } from "./db";
import { Config } from "./entities/Config"; import { Config } from "./entities/Config";
const CLEANUP_INTERVAL = 1 * HOURS;
async function cleanup() {
await cleanupConfigs();
setTimeout(cleanup, CLEANUP_INTERVAL);
}
if (isAPI()) { if (isAPI()) {
const CLEANUP_INTERVAL = 1 * HOURS;
async function cleanup() {
await cleanupConfigs();
setTimeout(cleanup, CLEANUP_INTERVAL);
}
// Start first cleanup 30 seconds after startup // Start first cleanup 30 seconds after startup
// TODO: Move to bot startup code
setTimeout(cleanup, 30 * SECONDS); setTimeout(cleanup, 30 * SECONDS);
} }

View file

@ -7,8 +7,6 @@ import { connection } from "./db";
import { Case } from "./entities/Case"; import { Case } from "./entities/Case";
import { CaseNote } from "./entities/CaseNote"; import { CaseNote } from "./entities/CaseNote";
const CASE_SUMMARY_REASON_MAX_LENGTH = 300;
export class GuildCases extends BaseGuildRepository { export class GuildCases extends BaseGuildRepository {
private cases: Repository<Case>; private cases: Repository<Case>;
private caseNotes: Repository<CaseNote>; private caseNotes: Repository<CaseNote>;

View file

@ -5,15 +5,16 @@ import { BaseGuildRepository } from "./BaseGuildRepository";
import { cleanupNicknames } from "./cleanup/nicknames"; import { cleanupNicknames } from "./cleanup/nicknames";
import { NicknameHistoryEntry } from "./entities/NicknameHistoryEntry"; import { NicknameHistoryEntry } from "./entities/NicknameHistoryEntry";
const CLEANUP_INTERVAL = 5 * MINUTES;
async function cleanup() {
await cleanupNicknames();
setTimeout(cleanup, CLEANUP_INTERVAL);
}
if (!isAPI()) { if (!isAPI()) {
const CLEANUP_INTERVAL = 5 * MINUTES;
async function cleanup() {
await cleanupNicknames();
setTimeout(cleanup, CLEANUP_INTERVAL);
}
// Start first cleanup 30 seconds after startup // Start first cleanup 30 seconds after startup
// TODO: Move to bot startup code
setTimeout(cleanup, 30 * SECONDS); setTimeout(cleanup, 30 * SECONDS);
} }

View file

@ -126,7 +126,7 @@ export class GuildSavedMessages extends BaseGuildRepository<SavedMessage> {
return entity; return entity;
} }
entity.data = await decryptJson(entity.data as unknown as string); entity.data = (await decryptJson(entity.data as unknown as string)) as ISavedMessageData;
return entity; return entity;
} }

View file

@ -5,15 +5,16 @@ import { BaseRepository } from "./BaseRepository";
import { cleanupUsernames } from "./cleanup/usernames"; import { cleanupUsernames } from "./cleanup/usernames";
import { UsernameHistoryEntry } from "./entities/UsernameHistoryEntry"; import { UsernameHistoryEntry } from "./entities/UsernameHistoryEntry";
const CLEANUP_INTERVAL = 5 * MINUTES;
async function cleanup() {
await cleanupUsernames();
setTimeout(cleanup, CLEANUP_INTERVAL);
}
if (!isAPI()) { if (!isAPI()) {
const CLEANUP_INTERVAL = 5 * MINUTES;
async function cleanup() {
await cleanupUsernames();
setTimeout(cleanup, CLEANUP_INTERVAL);
}
// Start first cleanup 30 seconds after startup // Start first cleanup 30 seconds after startup
// TODO: Move to bot startup code
setTimeout(cleanup, 30 * SECONDS); setTimeout(cleanup, 30 * SECONDS);
} }

View file

@ -19,8 +19,6 @@ export type RemoveApiPermissionEventData = {
target_id: string; target_id: string;
}; };
export type EditConfigEventData = {};
export interface AuditLogEventData extends Record<AuditLogEventType, unknown> { export interface AuditLogEventData extends Record<AuditLogEventType, unknown> {
ADD_API_PERMISSION: { ADD_API_PERMISSION: {
type: ApiPermissionTypes; type: ApiPermissionTypes;
@ -41,7 +39,7 @@ export interface AuditLogEventData extends Record<AuditLogEventType, unknown> {
target_id: string; target_id: string;
}; };
EDIT_CONFIG: {}; EDIT_CONFIG: Record<string, never>;
} }
export type AnyAuditLogEventData = AuditLogEventData[AuditLogEventType]; export type AnyAuditLogEventData = AuditLogEventData[AuditLogEventType];

View file

@ -1,4 +1,4 @@
export function buildEntity<T extends any>(Entity: new () => T, data: Partial<T>): T { export function buildEntity<T extends object>(Entity: new () => T, data: Partial<T>): T {
const instance = new Entity(); const instance = new Entity();
for (const [key, value] of Object.entries(data)) { for (const [key, value] of Object.entries(data)) {
instance[key] = value; instance[key] = value;

View file

@ -5,6 +5,7 @@ import { backendDir } from "../paths";
import { QueryLogger } from "./queryLogger"; import { QueryLogger } from "./queryLogger";
const ormconfigPath = path.join(backendDir, "ormconfig.js"); const ormconfigPath = path.join(backendDir, "ormconfig.js");
// eslint-disable-next-line @typescript-eslint/no-var-requires
const connectionOptions = require(ormconfigPath); const connectionOptions = require(ormconfigPath);
let connectionPromise: Promise<Connection>; let connectionPromise: Promise<Connection>;

View file

@ -19,7 +19,7 @@ export class ApiLogin {
@Column() @Column()
expires_at: string; expires_at: string;
@ManyToOne((type) => ApiUserInfo, (userInfo) => userInfo.logins) @ManyToOne(() => ApiUserInfo, (userInfo) => userInfo.logins)
@JoinColumn({ name: "user_id" }) @JoinColumn({ name: "user_id" })
userInfo: ApiUserInfo; userInfo: ApiUserInfo;
} }

View file

@ -22,7 +22,7 @@ export class ApiPermissionAssignment {
@Column({ type: String, nullable: true }) @Column({ type: String, nullable: true })
expires_at: string | null; expires_at: string | null;
@ManyToOne((type) => ApiUserInfo, (userInfo) => userInfo.permissionAssignments) @ManyToOne(() => ApiUserInfo, (userInfo) => userInfo.permissionAssignments)
@JoinColumn({ name: "target_id" }) @JoinColumn({ name: "target_id" })
userInfo: ApiUserInfo; userInfo: ApiUserInfo;
} }

View file

@ -20,9 +20,9 @@ export class ApiUserInfo {
@Column() @Column()
updated_at: string; updated_at: string;
@OneToMany((type) => ApiLogin, (login) => login.userInfo) @OneToMany(() => ApiLogin, (login) => login.userInfo)
logins: ApiLogin[]; logins: ApiLogin[];
@OneToMany((type) => ApiPermissionAssignment, (p) => p.userInfo) @OneToMany(() => ApiPermissionAssignment, (p) => p.userInfo)
permissionAssignments: ApiPermissionAssignment[]; permissionAssignments: ApiPermissionAssignment[];
} }

View file

@ -35,6 +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((type) => CaseNote, (note) => note.case) @OneToMany(() => CaseNote, (note) => note.case)
notes: CaseNote[]; notes: CaseNote[];
} }

View file

@ -15,7 +15,7 @@ export class CaseNote {
@Column() created_at: string; @Column() created_at: string;
@ManyToOne((type) => Case, (theCase) => theCase.notes) @ManyToOne(() => Case, (theCase) => theCase.notes)
@JoinColumn({ name: "case_id" }) @JoinColumn({ name: "case_id" })
case: Case; case: Case;
} }

View file

@ -22,7 +22,7 @@ export class Config {
@Column() @Column()
edited_at: string; edited_at: string;
@ManyToOne((type) => ApiUserInfo) @ManyToOne(() => ApiUserInfo)
@JoinColumn({ name: "edited_by" }) @JoinColumn({ name: "edited_by" })
userInfo: ApiUserInfo; userInfo: ApiUserInfo;
} }

View file

@ -16,7 +16,7 @@ export class StarboardMessage {
@Column() @Column()
guild_id: string; guild_id: string;
@OneToOne((type) => SavedMessage) @OneToOne(() => SavedMessage)
@JoinColumn({ name: "message_id" }) @JoinColumn({ name: "message_id" })
message: SavedMessage; message: SavedMessage;
} }

View file

@ -16,7 +16,7 @@ export class StarboardReaction {
@Column() @Column()
reactor_id: string; reactor_id: string;
@OneToOne((type) => SavedMessage) @OneToOne(() => SavedMessage)
@JoinColumn({ name: "message_id" }) @JoinColumn({ name: "message_id" })
message: SavedMessage; message: SavedMessage;
} }

View file

@ -1,4 +1,3 @@
import type { QueryRunner } from "typeorm";
import { AdvancedConsoleLogger } from "typeorm/logger/AdvancedConsoleLogger"; import { AdvancedConsoleLogger } from "typeorm/logger/AdvancedConsoleLogger";
let groupedQueryStats: Map<string, number> = new Map(); let groupedQueryStats: Map<string, number> = new Map();
@ -9,7 +8,7 @@ const deleteTableRegex = /FROM `?([^\s`]+)/;
const insertTableRegex = /INTO `?([^\s`]+)/; const insertTableRegex = /INTO `?([^\s`]+)/;
export class QueryLogger extends AdvancedConsoleLogger { export class QueryLogger extends AdvancedConsoleLogger {
logQuery(query: string, parameters?: any[], queryRunner?: QueryRunner): any { logQuery(query: string): any {
let type: string | undefined; let type: string | undefined;
let table: string | undefined; let table: string | undefined;

View file

@ -242,11 +242,6 @@ connect().then(async (connection) => {
// FIXME: TS doesn't see Client as a child of EventEmitter for some reason // FIXME: TS doesn't see Client as a child of EventEmitter for some reason
(client as unknown as EventEmitter).setMaxListeners(200); (client as unknown as EventEmitter).setMaxListeners(200);
client.rest.on(RESTEvents.RateLimited, (data) => {
// tslint:disable-next-line:no-console
// console.log(`[DEBUG] [RATE_LIMIT] ${JSON.stringify(data)}`);
});
const safe429DecayInterval = 5 * SECONDS; const safe429DecayInterval = 5 * SECONDS;
const safe429MaxCount = 5; const safe429MaxCount = 5;
const safe429Counter = new DecayingCounter(safe429DecayInterval); const safe429Counter = new DecayingCounter(safe429DecayInterval);
@ -453,7 +448,7 @@ connect().then(async (connection) => {
logger.info("Received SIGINT, exiting..."); logger.info("Received SIGINT, exiting...");
cleanupAndStop(0); cleanupAndStop(0);
}); });
process.on("SIGTERM", (code) => { process.on("SIGTERM", () => {
logger.info("Received SIGTERM, exiting..."); logger.info("Received SIGTERM, exiting...");
cleanupAndStop(0); cleanupAndStop(0);
}); });

View file

@ -106,7 +106,7 @@ export class CreatePreTypeORMTables1540519249973 implements MigrationInterface {
`); `);
} }
public async down(queryRunner: QueryRunner): Promise<any> { public async down(): Promise<any> {
// No down function since we're migrating (hehe) from another migration system (knex) // No down function since we're migrating (hehe) from another migration system (knex)
} }
} }

View file

@ -77,6 +77,6 @@ export class MigrateUsernamesToNewHistoryTable1556909512501 implements Migration
await queryRunner.query("START TRANSACTION"); await queryRunner.query("START TRANSACTION");
} }
// tslint:disable-next-line:no-empty // eslint-disable-next-line @typescript-eslint/no-empty-function
public async down(queryRunner: QueryRunner): Promise<any> {} public async down(): Promise<any> {}
} }

View file

@ -4,7 +4,7 @@ export class AddTypeAndPermissionsToApiPermissions1573158035867 implements Migra
public async up(queryRunner: QueryRunner): Promise<any> { public async up(queryRunner: QueryRunner): Promise<any> {
try { try {
await queryRunner.dropPrimaryKey("api_permissions"); await queryRunner.dropPrimaryKey("api_permissions");
} catch {} // tslint:disable-line } catch {} // eslint-disable-line no-empty
const table = (await queryRunner.getTable("api_permissions"))!; const table = (await queryRunner.getTable("api_permissions"))!;
if (table.indices.length) { if (table.indices.length) {

View file

@ -2,7 +2,7 @@ import { MigrationInterface, QueryRunner, Table, TableIndex } from "typeorm";
export class CreateTempBansTable1608753440716 implements MigrationInterface { export class CreateTempBansTable1608753440716 implements MigrationInterface {
public async up(queryRunner: QueryRunner): Promise<any> { public async up(queryRunner: QueryRunner): Promise<any> {
const table = await queryRunner.createTable( await queryRunner.createTable(
new Table({ new Table({
name: "tempbans", name: "tempbans",
columns: [ columns: [

View file

@ -77,28 +77,6 @@ const PluginOverrideCriteriaType: t.Type<PluginOverrideCriteria<unknown>> = t.re
}), }),
); );
const validTopLevelOverrideKeys = [
"channel",
"category",
"thread",
"is_thread",
"level",
"user",
"role",
"all",
"any",
"not",
"extra",
"config",
];
const BasicPluginStructureType = t.type({
enabled: tNullable(t.boolean),
config: tNullable(t.unknown),
overrides: tNullable(t.array(t.union([PluginOverrideCriteriaType, t.type({ config: t.unknown })]))),
replaceDefaultOverrides: tNullable(t.boolean),
});
export function strictValidationErrorToConfigValidationError(err: StrictValidationError) { export function strictValidationErrorToConfigValidationError(err: StrictValidationError) {
return new ConfigValidationError( return new ConfigValidationError(
err err

View file

@ -45,7 +45,7 @@ export const AutoDeletePlugin = zeppelinGuildPlugin<AutoDeletePluginType>()({
}, },
afterLoad(pluginData) { afterLoad(pluginData) {
const { state, guild } = pluginData; const { state } = pluginData;
state.onMessageCreateFn = (msg) => onMessageCreate(pluginData, msg); state.onMessageCreateFn = (msg) => onMessageCreate(pluginData, msg);
state.guildSavedMessages.events.on("create", state.onMessageCreateFn); state.guildSavedMessages.events.on("create", state.onMessageCreateFn);
@ -58,7 +58,7 @@ export const AutoDeletePlugin = zeppelinGuildPlugin<AutoDeletePluginType>()({
}, },
beforeUnload(pluginData) { beforeUnload(pluginData) {
const { state, guild } = pluginData; const { state } = pluginData;
state.guildSavedMessages.events.off("create", state.onMessageCreateFn); state.guildSavedMessages.events.off("create", state.onMessageCreateFn);
state.guildSavedMessages.events.off("delete", state.onMessageDeleteFn); state.guildSavedMessages.events.off("delete", state.onMessageDeleteFn);

View file

@ -248,7 +248,7 @@ export const AutomodPlugin = zeppelinGuildPlugin<AutomodPluginType>()({
}, },
async afterLoad(pluginData) { async afterLoad(pluginData) {
const { state, guild } = pluginData; const { state } = pluginData;
state.clearRecentActionsInterval = setInterval(() => clearOldRecentActions(pluginData), 1 * MINUTES); state.clearRecentActionsInterval = setInterval(() => clearOldRecentActions(pluginData), 1 * MINUTES);
state.clearRecentSpamInterval = setInterval(() => clearOldRecentSpam(pluginData), 1 * SECONDS); state.clearRecentSpamInterval = setInterval(() => clearOldRecentSpam(pluginData), 1 * SECONDS);

View file

@ -11,7 +11,7 @@ export const AddToCounterAction = automodAction({
defaultConfig: {}, defaultConfig: {},
async apply({ pluginData, contexts, actionConfig, matchResult, ruleName }) { async apply({ pluginData, contexts, actionConfig, ruleName }) {
const countersPlugin = pluginData.getPlugin(CountersPlugin); const countersPlugin = pluginData.getPlugin(CountersPlugin);
if (!countersPlugin.counterExists(actionConfig.counter)) { if (!countersPlugin.counterExists(actionConfig.counter)) {
pluginData.getPlugin(LogsPlugin).logBotAlert({ pluginData.getPlugin(LogsPlugin).logBotAlert({

View file

@ -20,7 +20,7 @@ export const ChangeNicknameAction = automodAction({
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(() => {
pluginData.getPlugin(LogsPlugin).logBotAlert({ pluginData.getPlugin(LogsPlugin).logBotAlert({
body: `Failed to change the nickname of \`${member.id}\``, body: `Failed to change the nickname of \`${member.id}\``,
}); });

View file

@ -70,7 +70,7 @@ export const ChangePermsAction = automodAction({
}), }),
defaultConfig: {}, defaultConfig: {},
async apply({ pluginData, contexts, actionConfig, ruleName }) { async apply({ pluginData, contexts, actionConfig }) {
const user = contexts.find((c) => c.user)?.user; const user = contexts.find((c) => c.user)?.user;
const message = contexts.find((c) => c.message)?.message; const message = contexts.find((c) => c.message)?.message;

View file

@ -8,6 +8,7 @@ export const ExampleAction = automodAction({
defaultConfig: {}, defaultConfig: {},
// eslint-disable-next-line @typescript-eslint/no-unused-vars
async apply({ pluginData, contexts, actionConfig }) { async apply({ pluginData, contexts, actionConfig }) {
// TODO: Everything // TODO: Everything
}, },

View file

@ -7,7 +7,7 @@ export const SetAntiraidLevelAction = automodAction({
configType: tNullable(t.string), configType: tNullable(t.string),
defaultConfig: "", defaultConfig: "",
async apply({ pluginData, contexts, actionConfig }) { async apply({ pluginData, actionConfig }) {
setAntiraidLevel(pluginData, actionConfig ?? null); setAntiraidLevel(pluginData, actionConfig ?? null);
}, },
}); });

View file

@ -11,7 +11,7 @@ export const SetCounterAction = automodAction({
defaultConfig: {}, defaultConfig: {},
async apply({ pluginData, contexts, actionConfig, matchResult, ruleName }) { async apply({ pluginData, contexts, actionConfig, ruleName }) {
const countersPlugin = pluginData.getPlugin(CountersPlugin); const countersPlugin = pluginData.getPlugin(CountersPlugin);
if (!countersPlugin.counterExists(actionConfig.counter)) { if (!countersPlugin.counterExists(actionConfig.counter)) {
pluginData.getPlugin(LogsPlugin).logBotAlert({ pluginData.getPlugin(LogsPlugin).logBotAlert({

View file

@ -31,7 +31,7 @@ export const StartThreadAction = automodAction({
limit_per_channel: 5, limit_per_channel: 5,
}, },
async apply({ pluginData, contexts, actionConfig, ruleName }) { async apply({ pluginData, contexts, actionConfig }) {
// check if the message still exists, we don't want to create threads for deleted messages // check if the message still exists, we don't want to create threads for deleted messages
const threads = contexts.filter((c) => { const threads = contexts.filter((c) => {
if (!c.message || !c.user) return false; if (!c.message || !c.user) return false;

View file

@ -9,7 +9,7 @@ export async function runAutomodOnModAction(
modAction: ModActionType, modAction: ModActionType,
userId: string, userId: string,
reason?: string, reason?: string,
isAutomodAction: boolean = false, isAutomodAction = false,
) { ) {
const [user, member] = await Promise.all([ const [user, member] = await Promise.all([
resolveUser(pluginData.client, userId), resolveUser(pluginData.client, userId),

View file

@ -1,13 +1,12 @@
import { GuildPluginData } from "knub"; import { GuildPluginData } from "knub";
import { getEmojiInString, getRoleMentions, getUrlsInString, getUserMentions } from "../../../utils"; import { getEmojiInString, getRoleMentions, getUrlsInString, getUserMentions } from "../../../utils";
import { RECENT_ACTION_EXPIRY_TIME, RecentActionType } from "../constants"; import { RecentActionType } from "../constants";
import { AutomodContext, AutomodPluginType } from "../types"; import { AutomodContext, AutomodPluginType } from "../types";
export function addRecentActionsFromMessage(pluginData: GuildPluginData<AutomodPluginType>, context: AutomodContext) { export function addRecentActionsFromMessage(pluginData: GuildPluginData<AutomodPluginType>, context: AutomodContext) {
const message = context.message!; const message = context.message!;
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}`;
const expiresAt = Date.now() + RECENT_ACTION_EXPIRY_TIME;
pluginData.state.recentActions.push({ pluginData.state.recentActions.push({
context, context,

View file

@ -14,7 +14,6 @@ const MessageSpamTriggerConfig = t.type({
within: tDelayString, within: tDelayString,
per_channel: tNullable(t.boolean), per_channel: tNullable(t.boolean),
}); });
type TMessageSpamTriggerConfig = t.TypeOf<typeof MessageSpamTriggerConfig>;
interface TMessageSpamMatchResultType { interface TMessageSpamMatchResultType {
archiveId: string; archiveId: string;

View file

@ -12,7 +12,7 @@ interface BaseAutomodTriggerMatchResult {
fullSummary?: string; fullSummary?: string;
} }
export type AutomodTriggerMatchResult<TExtra extends any = unknown> = unknown extends TExtra export type AutomodTriggerMatchResult<TExtra = unknown> = unknown extends TExtra
? BaseAutomodTriggerMatchResult ? BaseAutomodTriggerMatchResult
: BaseAutomodTriggerMatchResult & { extra: TExtra }; : BaseAutomodTriggerMatchResult & { extra: TExtra };

View file

@ -2,7 +2,6 @@ import * as t from "io-ts";
import { tNullable } from "../../../utils"; import { tNullable } from "../../../utils";
import { automodTrigger } from "../helpers"; import { automodTrigger } from "../helpers";
// tslint:disable-next-line
interface AntiraidLevelTriggerResult {} interface AntiraidLevelTriggerResult {}
export const AntiraidLevelTrigger = automodTrigger<AntiraidLevelTriggerResult>()({ export const AntiraidLevelTrigger = automodTrigger<AntiraidLevelTriggerResult>()({
@ -12,7 +11,7 @@ export const AntiraidLevelTrigger = automodTrigger<AntiraidLevelTriggerResult>()
defaultConfig: {}, defaultConfig: {},
async match({ triggerConfig, context, pluginData }) { async match({ triggerConfig, context }) {
if (!context.antiraid) { if (!context.antiraid) {
return; return;
} }
@ -26,7 +25,7 @@ export const AntiraidLevelTrigger = automodTrigger<AntiraidLevelTriggerResult>()
}; };
}, },
renderMatchInformation({ matchResult, pluginData, contexts, triggerConfig }) { renderMatchInformation({ contexts }) {
const newLevel = contexts[0].antiraid!.level; const newLevel = contexts[0].antiraid!.level;
return newLevel ? `Antiraid level was set to ${newLevel}` : `Antiraid was turned off`; return newLevel ? `Antiraid level was set to ${newLevel}` : `Antiraid was turned off`;
}, },

View file

@ -3,7 +3,6 @@ import * as t from "io-ts";
import { verboseChannelMention } from "../../../utils"; import { verboseChannelMention } from "../../../utils";
import { automodTrigger } from "../helpers"; import { automodTrigger } from "../helpers";
// tslint:disable-next-line:no-empty-interface
interface AnyMessageResultType {} interface AnyMessageResultType {}
export const AnyMessageTrigger = automodTrigger<AnyMessageResultType>()({ export const AnyMessageTrigger = automodTrigger<AnyMessageResultType>()({
@ -11,7 +10,7 @@ export const AnyMessageTrigger = automodTrigger<AnyMessageResultType>()({
defaultConfig: {}, defaultConfig: {},
async match({ pluginData, context, triggerConfig: trigger }) { async match({ context }) {
if (!context.message) { if (!context.message) {
return; return;
} }
@ -21,7 +20,7 @@ export const AnyMessageTrigger = automodTrigger<AnyMessageResultType>()({
}; };
}, },
renderMatchInformation({ pluginData, contexts, matchResult }) { renderMatchInformation({ pluginData, contexts }) {
const channel = pluginData.guild.channels.cache.get(contexts[0].message!.channel_id as Snowflake); const channel = pluginData.guild.channels.cache.get(contexts[0].message!.channel_id as Snowflake);
return `Matched message (\`${contexts[0].message!.id}\`) in ${ return `Matched message (\`${contexts[0].message!.id}\`) in ${
channel ? verboseChannelMention(channel) : "Unknown Channel" channel ? verboseChannelMention(channel) : "Unknown Channel"

View file

@ -30,7 +30,7 @@ export const BanTrigger = automodTrigger<BanTriggerResultType>()({
}; };
}, },
renderMatchInformation({ matchResult }) { renderMatchInformation() {
return `User was banned`; return `User was banned`;
}, },
}); });

View file

@ -14,7 +14,7 @@ export const CounterTrigger = automodTrigger<CounterTriggerResult>()({
defaultConfig: {}, defaultConfig: {},
async match({ triggerConfig, context, pluginData }) { async match({ triggerConfig, context }) {
if (!context.counterTrigger) { if (!context.counterTrigger) {
return; return;
} }
@ -37,7 +37,7 @@ export const CounterTrigger = automodTrigger<CounterTriggerResult>()({
}; };
}, },
renderMatchInformation({ matchResult, pluginData, contexts, triggerConfig }) { renderMatchInformation({ contexts }) {
let str = `Matched counter trigger \`${contexts[0].counterTrigger!.prettyCounter} / ${ let str = `Matched counter trigger \`${contexts[0].counterTrigger!.prettyCounter} / ${
contexts[0].counterTrigger!.prettyTrigger contexts[0].counterTrigger!.prettyTrigger
}\``; }\``;

View file

@ -29,7 +29,7 @@ export const KickTrigger = automodTrigger<KickTriggerResultType>()({
}; };
}, },
renderMatchInformation({ matchResult }) { renderMatchInformation() {
return `User was kicked`; return `User was kicked`;
}, },
}); });

View file

@ -23,7 +23,7 @@ export const MatchAttachmentTypeTrigger = automodTrigger<MatchResultType>()({
whitelist_enabled: false, whitelist_enabled: false,
}, },
async match({ pluginData, context, triggerConfig: trigger }) { async match({ context, triggerConfig: trigger }) {
if (!context.message) { if (!context.message) {
return; return;
} }

View file

@ -13,7 +13,7 @@ export const MemberJoinTrigger = automodTrigger<unknown>()({
new_threshold: "1h", new_threshold: "1h",
}, },
async match({ pluginData, context, triggerConfig }) { async match({ context, triggerConfig }) {
if (!context.joined || !context.member) { if (!context.joined || !context.member) {
return; return;
} }
@ -26,7 +26,7 @@ export const MemberJoinTrigger = automodTrigger<unknown>()({
return {}; return {};
}, },
renderMatchInformation({ pluginData, contexts, triggerConfig }) { renderMatchInformation() {
return ""; return "";
}, },
}); });

View file

@ -45,7 +45,7 @@ export const MemberJoinSpamTrigger = automodTrigger<unknown>()({
} }
}, },
renderMatchInformation({ pluginData, contexts, triggerConfig }) { renderMatchInformation() {
return ""; return "";
}, },
}); });

View file

@ -6,7 +6,7 @@ export const MemberLeaveTrigger = automodTrigger<unknown>()({
defaultConfig: {}, defaultConfig: {},
async match({ pluginData, context, triggerConfig }) { async match({ context }) {
if (!context.joined || !context.member) { if (!context.joined || !context.member) {
return; return;
} }
@ -14,7 +14,7 @@ export const MemberLeaveTrigger = automodTrigger<unknown>()({
return {}; return {};
}, },
renderMatchInformation({ pluginData, contexts, triggerConfig }) { renderMatchInformation() {
return ""; return "";
}, },
}); });

View file

@ -29,7 +29,7 @@ export const MuteTrigger = automodTrigger<MuteTriggerResultType>()({
}; };
}, },
renderMatchInformation({ matchResult }) { renderMatchInformation() {
return `User was muted`; return `User was muted`;
}, },
}); });

View file

@ -18,7 +18,7 @@ export const NoteTrigger = automodTrigger<NoteTriggerResultType>()({
}; };
}, },
renderMatchInformation({ matchResult }) { renderMatchInformation() {
return `Note was added on user`; return `Note was added on user`;
}, },
}); });

View file

@ -45,7 +45,7 @@ export const ThreadCreateSpamTrigger = automodTrigger<unknown>()({
} }
}, },
renderMatchInformation({ pluginData, contexts, triggerConfig }) { renderMatchInformation() {
return ""; return "";
}, },
}); });

View file

@ -18,7 +18,7 @@ export const UnbanTrigger = automodTrigger<UnbanTriggerResultType>()({
}; };
}, },
renderMatchInformation({ matchResult }) { renderMatchInformation() {
return `User was unbanned`; return `User was unbanned`;
}, },
}); });

View file

@ -18,7 +18,7 @@ export const UnmuteTrigger = automodTrigger<UnmuteTriggerResultType>()({
}; };
}, },
renderMatchInformation({ matchResult }) { renderMatchInformation() {
return `User was unmuted`; return `User was unmuted`;
}, },
}); });

View file

@ -29,7 +29,7 @@ export const WarnTrigger = automodTrigger<WarnTriggerResultType>()({
}; };
}, },
renderMatchInformation({ matchResult }) { renderMatchInformation() {
return `User was warned`; return `User was warned`;
}, },
}); });

View file

@ -10,7 +10,7 @@ export const RateLimitPerformanceCmd = botControlCmd({
signature: {}, signature: {},
async run({ pluginData, message: msg, args }) { async run({ pluginData, message: msg }) {
const logItems = getRateLimitStats(); const logItems = getRateLimitStats();
if (logItems.length === 0) { if (logItems.length === 0) {
sendSuccessMessage(pluginData, msg.channel, `No rate limits hit`); sendSuccessMessage(pluginData, msg.channel, `No rate limits hit`);

View file

@ -13,7 +13,7 @@ export const RestPerformanceCmd = botControlCmd({
count: ct.number({ required: false }), count: ct.number({ required: false }),
}, },
async run({ pluginData, message: msg, args }) { async run({ message: msg, args }) {
const count = Math.max(1, Math.min(25, args.count || 5)); const count = Math.max(1, Math.min(25, args.count || 5));
const stats = getTopRestCallStats(count); const stats = getTopRestCallStats(count);
const formatted = stats.map((callStats) => { const formatted = stats.map((callStats) => {

View file

@ -39,7 +39,7 @@ export async function createCaseNote(pluginData: GuildPluginData<CasesPluginType
}); });
} }
const archiveLinkMatch = body && body.match(/(?<=\/archives\/)[a-zA-Z0-9\-]+/g); const archiveLinkMatch = body && body.match(/(?<=\/archives\/)[a-zA-Z0-9-]+/g);
if (archiveLinkMatch) { if (archiveLinkMatch) {
for (const archiveId of archiveLinkMatch) { for (const archiveId of archiveLinkMatch) {
pluginData.state.archives.makePermanent(archiveId); pluginData.state.archives.makePermanent(archiveId);

View file

@ -2,7 +2,7 @@ import { GuildPluginData } from "knub";
import { splitMessageIntoChunks } from "knub/helpers"; import { splitMessageIntoChunks } from "knub/helpers";
import moment from "moment-timezone"; import moment from "moment-timezone";
import { Case } from "../../../data/entities/Case"; import { Case } from "../../../data/entities/Case";
import { convertDelayStringToMS, DAYS, DBDateFormat, disableLinkPreviews, messageLink } from "../../../utils"; import { convertDelayStringToMS, DBDateFormat, disableLinkPreviews, messageLink } from "../../../utils";
import { TimeAndDatePlugin } from "../../TimeAndDate/TimeAndDatePlugin"; import { TimeAndDatePlugin } from "../../TimeAndDate/TimeAndDatePlugin";
import { caseAbbreviations } from "../caseAbbreviations"; import { caseAbbreviations } from "../caseAbbreviations";
import { CasesPluginType } from "../types"; import { CasesPluginType } from "../types";
@ -12,8 +12,6 @@ const CASE_SUMMARY_REASON_MAX_LENGTH = 300;
const INCLUDE_MORE_NOTES_THRESHOLD = 20; const INCLUDE_MORE_NOTES_THRESHOLD = 20;
const UPDATE_STR = "**[Update]**"; const UPDATE_STR = "**[Update]**";
const RELATIVE_TIME_THRESHOLD = 7 * DAYS;
export async function getCaseSummary( export async function getCaseSummary(
pluginData: GuildPluginData<CasesPluginType>, pluginData: GuildPluginData<CasesPluginType>,
caseOrCaseId: Case | number, caseOrCaseId: Case | number,

View file

@ -68,7 +68,7 @@ export async function postCaseToCaseLogChannel(
} }
} }
return; return;
} catch {} // tslint:disable-line:no-empty } catch {} // eslint-disable-line no-empty
} }
try { try {

View file

@ -1,7 +1,5 @@
import { BasePluginType, guildPluginMessageCommand } from "knub"; import { BasePluginType, guildPluginMessageCommand } from "knub";
export interface ChannelArchiverPluginType extends BasePluginType { export interface ChannelArchiverPluginType extends BasePluginType {}
state: {};
}
export const channelArchiverCmd = guildPluginMessageCommand<ChannelArchiverPluginType>(); export const channelArchiverCmd = guildPluginMessageCommand<ChannelArchiverPluginType>();

View file

@ -10,7 +10,7 @@ export const CountersListCmd = guildPluginMessageCommand<CountersPluginType>()({
signature: {}, signature: {},
async run({ pluginData, message, args }) { async run({ pluginData, message }) {
const config = await pluginData.config.getForMessage(message); const config = await pluginData.config.getForMessage(message);
const countersToShow = Array.from(Object.values(config.counters)).filter((c) => c.can_view !== false); const countersToShow = Array.from(Object.values(config.counters)).filter((c) => c.can_view !== false);

View file

@ -20,7 +20,7 @@ export async function createCaseAction(
action: TCreateCaseAction, action: TCreateCaseAction,
values: TemplateSafeValueContainer, values: TemplateSafeValueContainer,
event: TCustomEvent, event: TCustomEvent,
eventData: any, eventData: any, // eslint-disable-line @typescript-eslint/no-unused-vars
) { ) {
const modId = await renderTemplate(action.mod, values, false); const modId = await renderTemplate(action.mod, values, false);
const targetId = await renderTemplate(action.target, values, false); const targetId = await renderTemplate(action.target, values, false);

View file

@ -18,7 +18,7 @@ export async function makeRoleMentionableAction(
action: TMakeRoleMentionableAction, action: TMakeRoleMentionableAction,
values: TemplateSafeValueContainer, values: TemplateSafeValueContainer,
event: TCustomEvent, event: TCustomEvent,
eventData: any, eventData: any, // eslint-disable-line @typescript-eslint/no-unused-vars
) { ) {
const role = pluginData.guild.roles.cache.get(action.role as Snowflake); const role = pluginData.guild.roles.cache.get(action.role as Snowflake);
if (!role) { if (!role) {

View file

@ -16,7 +16,7 @@ export async function makeRoleUnmentionableAction(
action: TMakeRoleUnmentionableAction, action: TMakeRoleUnmentionableAction,
values: TemplateSafeValueContainer, values: TemplateSafeValueContainer,
event: TCustomEvent, event: TCustomEvent,
eventData: any, eventData: any, // eslint-disable-line @typescript-eslint/no-unused-vars
) { ) {
const role = pluginData.guild.roles.cache.get(action.role as Snowflake); const role = pluginData.guild.roles.cache.get(action.role as Snowflake);
if (!role) { if (!role) {

View file

@ -22,9 +22,9 @@ export type TSetChannelPermissionOverridesAction = t.TypeOf<typeof SetChannelPer
export async function setChannelPermissionOverridesAction( export async function setChannelPermissionOverridesAction(
pluginData: GuildPluginData<CustomEventsPluginType>, pluginData: GuildPluginData<CustomEventsPluginType>,
action: TSetChannelPermissionOverridesAction, action: TSetChannelPermissionOverridesAction,
values: TemplateSafeValueContainer, values: TemplateSafeValueContainer, // eslint-disable-line @typescript-eslint/no-unused-vars
event: TCustomEvent, event: TCustomEvent, // eslint-disable-line @typescript-eslint/no-unused-vars
eventData: any, eventData: any, // eslint-disable-line @typescript-eslint/no-unused-vars
) { ) {
const channel = pluginData.guild.channels.cache.get(action.channel as Snowflake); const channel = pluginData.guild.channels.cache.get(action.channel as Snowflake);
if (!channel || channel.isThread() || !("guild" in channel)) { if (!channel || channel.isThread() || !("guild" in channel)) {

View file

@ -15,10 +15,8 @@ const CommandTrigger = t.type({
params: t.string, params: t.string,
can_use: t.boolean, can_use: t.boolean,
}); });
type TCommandTrigger = t.TypeOf<typeof CommandTrigger>;
const AnyTrigger = CommandTrigger; // TODO: Make into a union once we have more triggers const AnyTrigger = CommandTrigger; // TODO: Make into a union once we have more triggers
type TAnyTrigger = t.TypeOf<typeof AnyTrigger>;
const AnyAction = t.union([ const AnyAction = t.union([
AddRoleAction, AddRoleAction,
@ -29,7 +27,6 @@ const AnyAction = t.union([
MakeRoleUnmentionableAction, MakeRoleUnmentionableAction,
SetChannelPermissionOverridesAction, SetChannelPermissionOverridesAction,
]); ]);
type TAnyAction = t.TypeOf<typeof AnyAction>;
export const CustomEvent = t.type({ export const CustomEvent = t.type({
name: t.string, name: t.string,

View file

@ -8,7 +8,6 @@ import { makeIoTsConfigParser } from "../../pluginUtils";
import { zeppelinGlobalPlugin } from "../ZeppelinPluginBlueprint"; import { zeppelinGlobalPlugin } from "../ZeppelinPluginBlueprint";
interface GuildAccessMonitorPluginType extends BasePluginType { interface GuildAccessMonitorPluginType extends BasePluginType {
config: {};
state: { state: {
allowedGuilds: AllowedGuilds; allowedGuilds: AllowedGuilds;
}; };

View file

@ -3,7 +3,6 @@ import { Configs } from "../../data/Configs";
import Timeout = NodeJS.Timeout; import Timeout = NodeJS.Timeout;
export interface GuildConfigReloaderPluginType extends BasePluginType { export interface GuildConfigReloaderPluginType extends BasePluginType {
config: {};
state: { state: {
guildConfigs: Configs; guildConfigs: Configs;
unloaded: boolean; unloaded: boolean;

View file

@ -1,9 +1,6 @@
import { guildPluginEventListener } from "knub"; import { guildPluginEventListener } from "knub";
import { MINUTES } from "../../../utils";
import { GuildMemberCachePluginType } from "../types"; import { GuildMemberCachePluginType } from "../types";
const DELETION_DELAY = 2 * MINUTES;
export const removeMemberCacheOnMemberLeave = guildPluginEventListener<GuildMemberCachePluginType>()({ export const removeMemberCacheOnMemberLeave = guildPluginEventListener<GuildMemberCachePluginType>()({
event: "guildMemberRemove", event: "guildMemberRemove",
async listener({ pluginData, args: { member } }) { async listener({ pluginData, args: { member } }) {

View file

@ -7,9 +7,6 @@ import { Webhooks } from "../../data/Webhooks";
export const ConfigSchema = t.type({}); export const ConfigSchema = t.type({});
export type TConfigSchema = t.TypeOf<typeof ConfigSchema>; export type TConfigSchema = t.TypeOf<typeof ConfigSchema>;
// <channelId, webhookUrl>
type ChannelWebhookMap = Map<string, string>;
export interface InternalPosterPluginType extends BasePluginType { export interface InternalPosterPluginType extends BasePluginType {
config: TConfigSchema; config: TConfigSchema;

View file

@ -76,7 +76,7 @@ export const LocateUserPlugin = zeppelinGuildPlugin<LocateUserPluginType>()({
}, },
beforeUnload(pluginData) { beforeUnload(pluginData) {
const { state, guild } = pluginData; const { state } = pluginData;
state.unregisterGuildEventListener?.(); state.unregisterGuildEventListener?.();
}, },

View file

@ -9,13 +9,6 @@ import { InternalPosterPlugin } from "../../InternalPoster/InternalPosterPlugin"
import { ILogTypeData, LogsPluginType, TLogChannel, TLogChannelMap } from "../types"; import { ILogTypeData, LogsPluginType, TLogChannel, TLogChannelMap } from "../types";
import { getLogMessage } from "./getLogMessage"; import { getLogMessage } from "./getLogMessage";
const excludedUserProps = ["user", "member", "mod"];
const excludedRoleProps = ["message.member.roles", "member.roles"];
function isRoleArray(value: any): value is string[] {
return Array.isArray(value);
}
interface ExclusionData { interface ExclusionData {
userId?: Snowflake | null; userId?: Snowflake | null;
bot?: boolean | null; bot?: boolean | null;
@ -86,7 +79,7 @@ export async function log<TLogType extends keyof ILogTypeData>(
const logChannels: TLogChannelMap = pluginData.config.get().channels; const logChannels: TLogChannelMap = pluginData.config.get().channels;
const typeStr = LogType[type]; const typeStr = LogType[type];
logChannelLoop: for (const [channelId, opts] of Object.entries(logChannels)) { for (const [channelId, opts] of Object.entries(logChannels)) {
const channel = pluginData.guild.channels.cache.get(channelId as Snowflake); const channel = pluginData.guild.channels.cache.get(channelId as Snowflake);
if (!channel?.isTextBased()) continue; if (!channel?.isTextBased()) continue;
if (pluginData.state.channelCooldowns.isOnCooldown(channelId)) continue; if (pluginData.state.channelCooldowns.isOnCooldown(channelId)) continue;

View file

@ -219,7 +219,7 @@ export const ModActionsPlugin = zeppelinGuildPlugin<ModActionsPluginType>()({
}, },
beforeUnload(pluginData) { beforeUnload(pluginData) {
const { state, guild } = pluginData; const { state } = pluginData;
state.unloaded = true; state.unloaded = true;
state.unregisterGuildEventListener?.(); state.unregisterGuildEventListener?.();

View file

@ -60,8 +60,6 @@ const defaultOptions = {
], ],
}; };
const EXPIRED_MUTE_CHECK_INTERVAL = 60 * 1000;
export const MutesPlugin = zeppelinGuildPlugin<MutesPluginType>()({ export const MutesPlugin = zeppelinGuildPlugin<MutesPluginType>()({
name: "mutes", name: "mutes",
showInDocs: true, showInDocs: true,
@ -135,7 +133,7 @@ export const MutesPlugin = zeppelinGuildPlugin<MutesPluginType>()({
}, },
beforeUnload(pluginData) { beforeUnload(pluginData) {
const { state, guild } = pluginData; const { state } = pluginData;
state.unregisterExpiredRoleMuteListener?.(); state.unregisterExpiredRoleMuteListener?.();
state.unregisterTimeoutMuteToRenewListener?.(); state.unregisterTimeoutMuteToRenewListener?.();

View file

@ -6,7 +6,7 @@ import { mutesEvt } from "../types";
*/ */
export const ClearActiveMuteOnRoleRemovalEvt = mutesEvt({ export const ClearActiveMuteOnRoleRemovalEvt = mutesEvt({
event: "guildMemberUpdate", event: "guildMemberUpdate",
async listener({ pluginData, args: { oldMember, newMember: member } }) { async listener({ pluginData, args: { newMember: member } }) {
const muteRole = pluginData.config.get().mute_role; const muteRole = pluginData.config.get().mute_role;
if (!muteRole) return; if (!muteRole) return;

View file

@ -29,7 +29,7 @@ export async function clearMute(
try { try {
const defaultMuteRole = pluginData.config.get().mute_role; const defaultMuteRole = pluginData.config.get().mute_role;
if (mute) { if (mute) {
const muteRoleId = mute.mute_role || pluginData.config.get().mute_role; const muteRoleId = mute.mute_role || defaultMuteRole;
if (mute.type === MuteTypes.Role) { if (mute.type === MuteTypes.Role) {
if (muteRoleId) { if (muteRoleId) {
@ -41,8 +41,7 @@ export async function clearMute(
if (mute.roles_to_restore) { if (mute.roles_to_restore) {
const guildRoles = pluginData.guild.roles.cache; const guildRoles = pluginData.guild.roles.cache;
const newRoles = [...member.roles.cache.keys()].filter((roleId) => roleId !== muteRoleId); for (const roleIdToRestore of mute?.roles_to_restore ?? []) {
for (const roleIdToRestore of mute?.roles_to_restore) {
if (guildRoles.has(roleIdToRestore) && roleIdToRestore !== muteRoleId) { if (guildRoles.has(roleIdToRestore) && roleIdToRestore !== muteRoleId) {
roleManagerPlugin.addRole(member.id, roleIdToRestore); roleManagerPlugin.addRole(member.id, roleIdToRestore);
} }
@ -50,7 +49,7 @@ export async function clearMute(
} }
} else { } else {
// Unmuting someone without an active mute -> remove timeouts and/or mute role // Unmuting someone without an active mute -> remove timeouts and/or mute role
const muteRole = pluginData.config.get().mute_role; const muteRole = defaultMuteRole;
if (muteRole && member.roles.cache.has(muteRole)) { if (muteRole && member.roles.cache.has(muteRole)) {
roleManagerPlugin.removePriorityRole(member.id, muteRole); roleManagerPlugin.removePriorityRole(member.id, muteRole);
} }

View file

@ -127,7 +127,7 @@ export async function muteUser(
// TODO: Add back the voiceState check once we figure out how to get voice state for guild members that are loaded on-demand // TODO: Add back the voiceState check once we figure out how to get voice state for guild members that are loaded on-demand
try { try {
await member.edit({ channel: moveToVoiceChannel as Snowflake }); await member.edit({ channel: moveToVoiceChannel as Snowflake });
} catch {} // tslint:disable-line } catch {} // eslint-disable-line no-empty
} }
} }

View file

@ -1,4 +1,4 @@
import { GuildMemberEditOptions, PermissionFlagsBits } from "discord.js"; import { PermissionFlagsBits } from "discord.js";
import intersection from "lodash.intersection"; import intersection from "lodash.intersection";
import { canAssignRole } from "../../../utils/canAssignRole"; import { canAssignRole } from "../../../utils/canAssignRole";
import { getMissingPermissions } from "../../../utils/getMissingPermissions"; import { getMissingPermissions } from "../../../utils/getMissingPermissions";
@ -22,9 +22,6 @@ export const LoadDataEvt = persistEvt({
} }
await pluginData.state.persistedData.clear(member.id); await pluginData.state.persistedData.clear(member.id);
const toRestore: GuildMemberEditOptions = {
reason: "Restored upon rejoin",
};
const config = await pluginData.config.getForMember(member); const config = await pluginData.config.getForMember(member);
const restoredData: string[] = []; const restoredData: string[] = [];

View file

@ -7,8 +7,6 @@ import { rgbToInt } from "../../../utils/rgbToInt";
import { postCmd } from "../types"; import { postCmd } from "../types";
import { formatContent } from "../util/formatContent"; import { formatContent } from "../util/formatContent";
const COLOR_MATCH_REGEX = /^#?([0-9a-f]{6})$/;
export const EditEmbedCmd = postCmd({ export const EditEmbedCmd = postCmd({
trigger: "edit_embed", trigger: "edit_embed",
permission: "can_post", permission: "can_post",

View file

@ -12,7 +12,7 @@ export async function postMessage(
channel: GuildTextBasedChannel, channel: GuildTextBasedChannel,
content: MessageCreateOptions, content: MessageCreateOptions,
attachments: Attachment[] = [], attachments: Attachment[] = [],
enableMentions: boolean = false, enableMentions = false,
): Promise<Message> { ): Promise<Message> {
if (typeof content === "string") { if (typeof content === "string") {
content = { content }; content = { content };

View file

@ -81,7 +81,7 @@ export const ReactionRolesPlugin = zeppelinGuildPlugin<ReactionRolesPluginType>(
}, },
beforeUnload(pluginData) { beforeUnload(pluginData) {
const { state, guild } = pluginData; const { state } = pluginData;
if (state.autoRefreshTimeout) { if (state.autoRefreshTimeout) {
clearTimeout(state.autoRefreshTimeout); clearTimeout(state.autoRefreshTimeout);

View file

@ -9,7 +9,7 @@ export const RemindersCmd = remindersCmd({
trigger: "reminders", trigger: "reminders",
permission: "can_use", permission: "can_use",
async run({ message: msg, args, pluginData }) { async run({ message: msg, pluginData }) {
const reminders = await pluginData.state.reminders.getRemindersByUserId(msg.author.id); const reminders = await pluginData.state.reminders.getRemindersByUserId(msg.author.id);
if (reminders.length === 0) { if (reminders.length === 0) {
sendErrorMessage(pluginData, msg.channel, "No reminders"); sendErrorMessage(pluginData, msg.channel, "No reminders");

View file

@ -81,7 +81,7 @@ export const SlowmodePlugin = zeppelinGuildPlugin<SlowmodePluginType>()({
}, },
beforeUnload(pluginData) { beforeUnload(pluginData) {
const { state, guild } = pluginData; const { state } = pluginData;
state.savedMessages.events.off("create", state.onMessageCreateFn); state.savedMessages.events.off("create", state.onMessageCreateFn);
clearInterval(state.clearInterval); clearInterval(state.clearInterval);

View file

@ -88,7 +88,7 @@ export const SpamPlugin = zeppelinGuildPlugin<SpamPluginType>()({
}, },
beforeUnload(pluginData) { beforeUnload(pluginData) {
const { state, guild } = pluginData; const { state } = pluginData;
state.savedMessages.events.off("create", state.onMessageCreateFn); state.savedMessages.events.off("create", state.onMessageCreateFn);
clearInterval(state.expiryInterval); clearInterval(state.expiryInterval);

View file

@ -41,8 +41,8 @@ export const StarboardPlugin = zeppelinGuildPlugin<StarboardPluginType>()({
To specify emoji in the config, you need to use the emoji's "raw form". To specify emoji in the config, you need to use the emoji's "raw form".
To obtain this, post the emoji with a backslash in front of it. To obtain this, post the emoji with a backslash in front of it.
- Example with a default emoji: "\:star:" => "⭐" - Example with a default emoji: ":star:" => "⭐"
- Example with a custom emoji: "\:mrvnSmile:" => "<:mrvnSmile:543000534102310933>" - Example with a custom emoji: ":mrvnSmile:" => "<:mrvnSmile:543000534102310933>"
### Basic starboard ### Basic starboard
Any message on the server that gets 5 star reactions will be posted into the starboard channel (604342689038729226). Any message on the server that gets 5 star reactions will be posted into the starboard channel (604342689038729226).
@ -127,7 +127,7 @@ export const StarboardPlugin = zeppelinGuildPlugin<StarboardPluginType>()({
const boards = (input as any).boards; const boards = (input as any).boards;
if (boards) { if (boards) {
for (const [name, opts] of Object.entries(boards)) { for (const [name, opts] of Object.entries(boards)) {
boards[name] = Object.assign({}, defaultStarboardOpts, boards[name]); boards[name] = Object.assign({}, defaultStarboardOpts, opts);
} }
} }
@ -163,7 +163,7 @@ export const StarboardPlugin = zeppelinGuildPlugin<StarboardPluginType>()({
}, },
beforeUnload(pluginData) { beforeUnload(pluginData) {
const { state, guild } = pluginData; const { state } = pluginData;
state.savedMessages.events.off("delete", state.onMessageDeleteFn); state.savedMessages.events.off("delete", state.onMessageDeleteFn);
}, },

View file

@ -4,7 +4,7 @@ import { defaultStarboardOpts, PartialConfigSchema } from "../types";
export function preprocessStaticConfig(config: t.TypeOf<typeof PartialConfigSchema>) { export function preprocessStaticConfig(config: t.TypeOf<typeof PartialConfigSchema>) {
if (config.boards) { if (config.boards) {
for (const [name, opts] of Object.entries(config.boards)) { for (const [name, opts] of Object.entries(config.boards)) {
config.boards[name] = Object.assign({}, defaultStarboardOpts, config.boards[name]); config.boards[name] = Object.assign({}, defaultStarboardOpts, opts);
} }
} }

View file

@ -107,9 +107,8 @@ export const TagsPlugin = zeppelinGuildPlugin<TagsPluginType>()({
// Check each category for conflicting options // Check each category for conflicting options
if (input.categories) { if (input.categories) {
for (const [name, opts] of Object.entries(input.categories)) { for (const [name, cat] of Object.entries(input.categories)) {
const cat = input.categories[name]; if ((cat as any).delete_with_command && (cat as any).auto_delete_command) {
if (cat.delete_with_command && cat.auto_delete_command) {
throw new StrictValidationError([ throw new StrictValidationError([
`Cannot have both (category specific) delete_with_command and category_delete_invoke enabled at <categories/${name}>`, `Cannot have both (category specific) delete_with_command and category_delete_invoke enabled at <categories/${name}>`,
]); ]);
@ -279,7 +278,7 @@ export const TagsPlugin = zeppelinGuildPlugin<TagsPluginType>()({
}, },
beforeUnload(pluginData) { beforeUnload(pluginData) {
const { state, guild } = pluginData; const { state } = pluginData;
state.savedMessages.events.off("create", state.onMessageCreateFn); state.savedMessages.events.off("create", state.onMessageCreateFn);
}, },

View file

@ -46,14 +46,7 @@ export async function matchAndRenderTagFromString(
for (const [tagName, tagBody] of Object.entries(category.tags)) { for (const [tagName, tagBody] of Object.entries(category.tags)) {
const regex = new RegExp(`^${escapeStringRegexp(tagName)}(?:\\s|$)`); const regex = new RegExp(`^${escapeStringRegexp(tagName)}(?:\\s|$)`);
if (regex.test(withoutPrefix)) { if (regex.test(withoutPrefix)) {
const renderedContent = await renderTagFromString( const renderedContent = await renderTagFromString(pluginData, str, prefix, tagName, tagBody, member);
pluginData,
str,
prefix,
tagName,
category.tags[tagName],
member,
);
if (renderedContent == null) { if (renderedContent == null) {
return null; return null;

View file

@ -7,7 +7,7 @@ export const ViewTimezoneCmd = timeAndDateCmd({
signature: {}, signature: {},
async run({ pluginData, message, args }) { async run({ pluginData, message }) {
const memberTimezone = await pluginData.state.memberTimezones.get(message.author.id); const memberTimezone = await pluginData.state.memberTimezones.get(message.author.id);
if (memberTimezone) { if (memberTimezone) {
message.channel.send(`Your timezone is currently set to **${memberTimezone.timezone}**`); message.channel.send(`Your timezone is currently set to **${memberTimezone.timezone}**`);

View file

@ -25,7 +25,7 @@ export const AboutCmd = utilityCmd({
try { try {
const lcl = new LCL(rootDir); const lcl = new LCL(rootDir);
lastCommit = await lcl.getLastCommit(); lastCommit = await lcl.getLastCommit();
} catch {} // tslint:disable-line:no-empty } catch {} // eslint-disable-line no-empty
let lastUpdate; let lastUpdate;
let version; let version;

View file

@ -31,8 +31,6 @@ function resizeBuffer(input: Buffer, width: number, height: number): Buffer {
return photonImageToBuffer(photonImage); return photonImageToBuffer(photonImage);
} }
const CDN_URL = "https://twemoji.maxcdn.com/";
export const JumboCmd = utilityCmd({ export const JumboCmd = utilityCmd({
trigger: "jumbo", trigger: "jumbo",
description: "Makes an emoji jumbo", description: "Makes an emoji jumbo",
@ -75,7 +73,7 @@ export const JumboCmd = utilityCmd({
let image: Buffer | undefined; let image: Buffer | undefined;
try { try {
const downloadedBuffer = await getBufferFromUrl(url); const downloadedBuffer = await getBufferFromUrl(url);
image = resizeBuffer(await getBufferFromUrl(url), size, size); image = resizeBuffer(downloadedBuffer, size, size);
} catch (err) { } catch (err) {
if (url.toLocaleLowerCase().endsWith("fe0f.png")) { if (url.toLocaleLowerCase().endsWith("fe0f.png")) {
url = url.slice(0, url.lastIndexOf("-fe0f")) + ".png"; url = url.slice(0, url.lastIndexOf("-fe0f")) + ".png";

View file

@ -1,9 +1,8 @@
import { Message } from "discord.js"; import { Message } from "discord.js";
import { performance } from "perf_hooks";
import { noop, trimLines } from "../../../utils"; import { noop, trimLines } from "../../../utils";
import { utilityCmd } from "../types"; import { utilityCmd } from "../types";
const { performance } = require("perf_hooks");
export const PingCmd = utilityCmd({ export const PingCmd = utilityCmd({
trigger: ["ping", "pong"], trigger: ["ping", "pong"],
description: "Test the bot's ping to the Discord API", description: "Test the bot's ping to the Discord API",

View file

@ -7,7 +7,7 @@ export const ReloadGuildCmd = utilityCmd({
description: "Reload the Zeppelin configuration and all plugins for the server. This can sometimes fix issues.", description: "Reload the Zeppelin configuration and all plugins for the server. This can sometimes fix issues.",
permission: "can_reload_guild", permission: "can_reload_guild",
async run({ message: msg, args, pluginData }) { async run({ message: msg, pluginData }) {
if (activeReloads.has(pluginData.guild.id)) return; if (activeReloads.has(pluginData.guild.id)) return;
activeReloads.set(pluginData.guild.id, msg.channel as TextChannel); activeReloads.set(pluginData.guild.id, msg.channel as TextChannel);

View file

@ -97,6 +97,7 @@ test("Supports base values in renderTemplate", async (t) => {
}); });
test("Edge case #1", async (t) => { test("Edge case #1", async (t) => {
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const result = await renderTemplate("{foo} {bar()}"); const result = await renderTemplate("{foo} {bar()}");
// No "Unclosed function" exception = success // No "Unclosed function" exception = success
t.pass(); t.pass();

Some files were not shown because too many files have changed in this diff Show more