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/ban-ts-comment": 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);
}
[util.inspect.custom](depth, options) {
[util.inspect.custom]() {
return `Error: ${this.message}`;
}
}

View file

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

View file

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

View file

@ -4,7 +4,7 @@ export function unauthorized(res: Response) {
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 });
}

View file

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

View file

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

View file

@ -1,6 +1,6 @@
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>;
protected guildId: string;

View file

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

View file

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

View file

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

View file

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

View file

@ -126,7 +126,7 @@ export class GuildSavedMessages extends BaseGuildRepository<SavedMessage> {
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;
}

View file

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

View file

@ -19,8 +19,6 @@ export type RemoveApiPermissionEventData = {
target_id: string;
};
export type EditConfigEventData = {};
export interface AuditLogEventData extends Record<AuditLogEventType, unknown> {
ADD_API_PERMISSION: {
type: ApiPermissionTypes;
@ -41,7 +39,7 @@ export interface AuditLogEventData extends Record<AuditLogEventType, unknown> {
target_id: string;
};
EDIT_CONFIG: {};
EDIT_CONFIG: Record<string, never>;
}
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();
for (const [key, value] of Object.entries(data)) {
instance[key] = value;

View file

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

View file

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

View file

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

View file

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

View file

@ -35,6 +35,6 @@ export class Case {
*/
@Column({ type: String, nullable: true }) log_message_id: string | null;
@OneToMany((type) => CaseNote, (note) => note.case)
@OneToMany(() => CaseNote, (note) => note.case)
notes: CaseNote[];
}

View file

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

View file

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

View file

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

View file

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

View file

@ -1,4 +1,3 @@
import type { QueryRunner } from "typeorm";
import { AdvancedConsoleLogger } from "typeorm/logger/AdvancedConsoleLogger";
let groupedQueryStats: Map<string, number> = new Map();
@ -9,7 +8,7 @@ const deleteTableRegex = /FROM `?([^\s`]+)/;
const insertTableRegex = /INTO `?([^\s`]+)/;
export class QueryLogger extends AdvancedConsoleLogger {
logQuery(query: string, parameters?: any[], queryRunner?: QueryRunner): any {
logQuery(query: string): any {
let type: 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
(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 safe429MaxCount = 5;
const safe429Counter = new DecayingCounter(safe429DecayInterval);
@ -453,7 +448,7 @@ connect().then(async (connection) => {
logger.info("Received SIGINT, exiting...");
cleanupAndStop(0);
});
process.on("SIGTERM", (code) => {
process.on("SIGTERM", () => {
logger.info("Received SIGTERM, exiting...");
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)
}
}

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -20,7 +20,7 @@ export const ChangeNicknameAction = automodAction({
if (pluginData.state.recentNicknameChanges.has(member.id)) continue;
const newName = typeof actionConfig === "string" ? actionConfig : actionConfig.name;
member.edit({ nick: newName }).catch((err) => {
member.edit({ nick: newName }).catch(() => {
pluginData.getPlugin(LogsPlugin).logBotAlert({
body: `Failed to change the nickname of \`${member.id}\``,
});

View file

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

View file

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

View file

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

View file

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

View file

@ -31,7 +31,7 @@ export const StartThreadAction = automodAction({
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
const threads = contexts.filter((c) => {
if (!c.message || !c.user) return false;

View file

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

View file

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

View file

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

View file

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

View file

@ -2,7 +2,6 @@ import * as t from "io-ts";
import { tNullable } from "../../../utils";
import { automodTrigger } from "../helpers";
// tslint:disable-next-line
interface AntiraidLevelTriggerResult {}
export const AntiraidLevelTrigger = automodTrigger<AntiraidLevelTriggerResult>()({
@ -12,7 +11,7 @@ export const AntiraidLevelTrigger = automodTrigger<AntiraidLevelTriggerResult>()
defaultConfig: {},
async match({ triggerConfig, context, pluginData }) {
async match({ triggerConfig, context }) {
if (!context.antiraid) {
return;
}
@ -26,7 +25,7 @@ export const AntiraidLevelTrigger = automodTrigger<AntiraidLevelTriggerResult>()
};
},
renderMatchInformation({ matchResult, pluginData, contexts, triggerConfig }) {
renderMatchInformation({ contexts }) {
const newLevel = contexts[0].antiraid!.level;
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 { automodTrigger } from "../helpers";
// tslint:disable-next-line:no-empty-interface
interface AnyMessageResultType {}
export const AnyMessageTrigger = automodTrigger<AnyMessageResultType>()({
@ -11,7 +10,7 @@ export const AnyMessageTrigger = automodTrigger<AnyMessageResultType>()({
defaultConfig: {},
async match({ pluginData, context, triggerConfig: trigger }) {
async match({ context }) {
if (!context.message) {
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);
return `Matched message (\`${contexts[0].message!.id}\`) in ${
channel ? verboseChannelMention(channel) : "Unknown Channel"

View file

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

View file

@ -14,7 +14,7 @@ export const CounterTrigger = automodTrigger<CounterTriggerResult>()({
defaultConfig: {},
async match({ triggerConfig, context, pluginData }) {
async match({ triggerConfig, context }) {
if (!context.counterTrigger) {
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} / ${
contexts[0].counterTrigger!.prettyTrigger
}\``;

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -13,7 +13,7 @@ export const RestPerformanceCmd = botControlCmd({
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 stats = getTopRestCallStats(count);
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) {
for (const archiveId of archiveLinkMatch) {
pluginData.state.archives.makePermanent(archiveId);

View file

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

View file

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

View file

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

View file

@ -10,7 +10,7 @@ export const CountersListCmd = guildPluginMessageCommand<CountersPluginType>()({
signature: {},
async run({ pluginData, message, args }) {
async run({ pluginData, message }) {
const config = await pluginData.config.getForMessage(message);
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,
values: TemplateSafeValueContainer,
event: TCustomEvent,
eventData: any,
eventData: any, // eslint-disable-line @typescript-eslint/no-unused-vars
) {
const modId = await renderTemplate(action.mod, values, false);
const targetId = await renderTemplate(action.target, values, false);

View file

@ -18,7 +18,7 @@ export async function makeRoleMentionableAction(
action: TMakeRoleMentionableAction,
values: TemplateSafeValueContainer,
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);
if (!role) {

View file

@ -16,7 +16,7 @@ export async function makeRoleUnmentionableAction(
action: TMakeRoleUnmentionableAction,
values: TemplateSafeValueContainer,
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);
if (!role) {

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -9,13 +9,6 @@ import { InternalPosterPlugin } from "../../InternalPoster/InternalPosterPlugin"
import { ILogTypeData, LogsPluginType, TLogChannel, TLogChannelMap } from "../types";
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 {
userId?: Snowflake | null;
bot?: boolean | null;
@ -86,7 +79,7 @@ export async function log<TLogType extends keyof ILogTypeData>(
const logChannels: TLogChannelMap = pluginData.config.get().channels;
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);
if (!channel?.isTextBased()) continue;
if (pluginData.state.channelCooldowns.isOnCooldown(channelId)) continue;

View file

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

View file

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

View file

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

View file

@ -29,7 +29,7 @@ export async function clearMute(
try {
const defaultMuteRole = pluginData.config.get().mute_role;
if (mute) {
const muteRoleId = mute.mute_role || pluginData.config.get().mute_role;
const muteRoleId = mute.mute_role || defaultMuteRole;
if (mute.type === MuteTypes.Role) {
if (muteRoleId) {
@ -41,8 +41,7 @@ export async function clearMute(
if (mute.roles_to_restore) {
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) {
roleManagerPlugin.addRole(member.id, roleIdToRestore);
}
@ -50,7 +49,7 @@ export async function clearMute(
}
} else {
// 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)) {
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
try {
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 { canAssignRole } from "../../../utils/canAssignRole";
import { getMissingPermissions } from "../../../utils/getMissingPermissions";
@ -22,9 +22,6 @@ export const LoadDataEvt = persistEvt({
}
await pluginData.state.persistedData.clear(member.id);
const toRestore: GuildMemberEditOptions = {
reason: "Restored upon rejoin",
};
const config = await pluginData.config.getForMember(member);
const restoredData: string[] = [];

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -88,7 +88,7 @@ export const SpamPlugin = zeppelinGuildPlugin<SpamPluginType>()({
},
beforeUnload(pluginData) {
const { state, guild } = pluginData;
const { state } = pluginData;
state.savedMessages.events.off("create", state.onMessageCreateFn);
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 obtain this, post the emoji with a backslash in front of it.
- Example with a default emoji: "\:star:" => "⭐"
- Example with a custom emoji: "\:mrvnSmile:" => "<:mrvnSmile:543000534102310933>"
- Example with a default emoji: ":star:" => "⭐"
- Example with a custom emoji: ":mrvnSmile:" => "<:mrvnSmile:543000534102310933>"
### Basic starboard
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;
if (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) {
const { state, guild } = pluginData;
const { state } = pluginData;
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>) {
if (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
if (input.categories) {
for (const [name, opts] of Object.entries(input.categories)) {
const cat = input.categories[name];
if (cat.delete_with_command && cat.auto_delete_command) {
for (const [name, cat] of Object.entries(input.categories)) {
if ((cat as any).delete_with_command && (cat as any).auto_delete_command) {
throw new StrictValidationError([
`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) {
const { state, guild } = pluginData;
const { state } = pluginData;
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)) {
const regex = new RegExp(`^${escapeStringRegexp(tagName)}(?:\\s|$)`);
if (regex.test(withoutPrefix)) {
const renderedContent = await renderTagFromString(
pluginData,
str,
prefix,
tagName,
category.tags[tagName],
member,
);
const renderedContent = await renderTagFromString(pluginData, str, prefix, tagName, tagBody, member);
if (renderedContent == null) {
return null;

View file

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

View file

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

View file

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

View file

@ -1,9 +1,8 @@
import { Message } from "discord.js";
import { performance } from "perf_hooks";
import { noop, trimLines } from "../../../utils";
import { utilityCmd } from "../types";
const { performance } = require("perf_hooks");
export const PingCmd = utilityCmd({
trigger: ["ping", "pong"],
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.",
permission: "can_reload_guild",
async run({ message: msg, args, pluginData }) {
async run({ message: msg, pluginData }) {
if (activeReloads.has(pluginData.guild.id)) return;
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) => {
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const result = await renderTemplate("{foo} {bar()}");
// No "Unclosed function" exception = success
t.pass();

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