mirror of
https://github.com/ZeppelinBot/Zeppelin.git
synced 2025-03-16 22:21:51 +00:00
Add bot alerts for missing audit log permissions; ignore internal server errors on discord's side when fetching audit logs
This commit is contained in:
parent
fb481aa583
commit
ee58769460
3 changed files with 52 additions and 18 deletions
|
@ -1,16 +1,15 @@
|
||||||
import { decorators as d, IPluginOptions, logger } from "knub";
|
import { decorators as d, IPluginOptions, logger } from "knub";
|
||||||
import { GuildLogs } from "../data/GuildLogs";
|
import { GuildLogs } from "../data/GuildLogs";
|
||||||
import { LogType } from "../data/LogType";
|
import { LogType } from "../data/LogType";
|
||||||
import { Attachment, Channel, Constants as ErisConstants, Embed, Member, TextChannel, User } from "eris";
|
import { Attachment, Channel, Constants as ErisConstants, Embed, Guild, Member, TextChannel, User } from "eris";
|
||||||
|
import DiscordRESTError from "eris/lib/errors/DiscordRESTError"; // tslint:disable-line
|
||||||
import {
|
import {
|
||||||
createChunkedMessage,
|
createChunkedMessage,
|
||||||
deactivateMentions,
|
|
||||||
disableCodeBlocks,
|
disableCodeBlocks,
|
||||||
disableLinkPreviews,
|
disableLinkPreviews,
|
||||||
findRelevantAuditLogEntry,
|
findRelevantAuditLogEntry,
|
||||||
noop,
|
noop,
|
||||||
stripObjectToScalars,
|
stripObjectToScalars,
|
||||||
trimLines,
|
|
||||||
UnknownUser,
|
UnknownUser,
|
||||||
useMediaUrls,
|
useMediaUrls,
|
||||||
} from "../utils";
|
} from "../utils";
|
||||||
|
@ -249,6 +248,20 @@ export class LogsPlugin extends ZeppelinPlugin<TConfigSchema> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async findRelevantAuditLogEntry(actionType: number, userId: string, attempts?: number, attemptDelay?: number) {
|
||||||
|
try {
|
||||||
|
return await findRelevantAuditLogEntry(this.guild, actionType, userId, attempts, attemptDelay);
|
||||||
|
} catch (e) {
|
||||||
|
if (e instanceof DiscordRESTError && e.code === 50013) {
|
||||||
|
this.guildLogs.log(LogType.BOT_ALERT, {
|
||||||
|
body: "Missing permissions to read audit log",
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@d.event("guildMemberAdd")
|
@d.event("guildMemberAdd")
|
||||||
async onMemberJoin(_, member) {
|
async onMemberJoin(_, member) {
|
||||||
const newThreshold = moment().valueOf() - 1000 * 60 * 60;
|
const newThreshold = moment().valueOf() - 1000 * 60 * 60;
|
||||||
|
@ -299,8 +312,7 @@ export class LogsPlugin extends ZeppelinPlugin<TConfigSchema> {
|
||||||
|
|
||||||
@d.event("guildBanAdd")
|
@d.event("guildBanAdd")
|
||||||
async onMemberBan(_, user) {
|
async onMemberBan(_, user) {
|
||||||
const relevantAuditLogEntry = await findRelevantAuditLogEntry(
|
const relevantAuditLogEntry = await this.findRelevantAuditLogEntry(
|
||||||
this.guild,
|
|
||||||
ErisConstants.AuditLogActions.MEMBER_BAN_ADD,
|
ErisConstants.AuditLogActions.MEMBER_BAN_ADD,
|
||||||
user.id,
|
user.id,
|
||||||
);
|
);
|
||||||
|
@ -318,8 +330,7 @@ export class LogsPlugin extends ZeppelinPlugin<TConfigSchema> {
|
||||||
|
|
||||||
@d.event("guildBanRemove")
|
@d.event("guildBanRemove")
|
||||||
async onMemberUnban(_, user) {
|
async onMemberUnban(_, user) {
|
||||||
const relevantAuditLogEntry = await findRelevantAuditLogEntry(
|
const relevantAuditLogEntry = await this.findRelevantAuditLogEntry(
|
||||||
this.guild,
|
|
||||||
ErisConstants.AuditLogActions.MEMBER_BAN_REMOVE,
|
ErisConstants.AuditLogActions.MEMBER_BAN_REMOVE,
|
||||||
user.id,
|
user.id,
|
||||||
);
|
);
|
||||||
|
@ -351,8 +362,7 @@ export class LogsPlugin extends ZeppelinPlugin<TConfigSchema> {
|
||||||
const addedRoles = diff(member.roles, oldMember.roles);
|
const addedRoles = diff(member.roles, oldMember.roles);
|
||||||
const removedRoles = diff(oldMember.roles, member.roles);
|
const removedRoles = diff(oldMember.roles, member.roles);
|
||||||
|
|
||||||
const relevantAuditLogEntry = await findRelevantAuditLogEntry(
|
const relevantAuditLogEntry = await this.findRelevantAuditLogEntry(
|
||||||
this.guild,
|
|
||||||
ErisConstants.AuditLogActions.MEMBER_ROLE_UPDATE,
|
ErisConstants.AuditLogActions.MEMBER_ROLE_UPDATE,
|
||||||
member.id,
|
member.id,
|
||||||
);
|
);
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
import { decorators as d, IPluginOptions, logger, waitForReaction, waitForReply } from "knub";
|
import { decorators as d, IPluginOptions, logger, waitForReaction, waitForReply } from "knub";
|
||||||
import { Attachment, Constants as ErisConstants, Guild, Member, Message, TextChannel, User } from "eris";
|
import { Attachment, Constants as ErisConstants, Guild, Member, Message, TextChannel, User } from "eris";
|
||||||
|
import DiscordRESTError from "eris/lib/errors/DiscordRESTError"; // tslint:disable-line
|
||||||
import humanizeDuration from "humanize-duration";
|
import humanizeDuration from "humanize-duration";
|
||||||
import { GuildCases } from "../data/GuildCases";
|
import { GuildCases } from "../data/GuildCases";
|
||||||
import {
|
import {
|
||||||
|
@ -164,6 +165,20 @@ export class ModActionsPlugin extends ZeppelinPlugin<TConfigSchema> {
|
||||||
return bans.some(b => b.user.id === userId);
|
return bans.some(b => b.user.id === userId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async findRelevantAuditLogEntry(actionType: number, userId: string, attempts?: number, attemptDelay?: number) {
|
||||||
|
try {
|
||||||
|
return await findRelevantAuditLogEntry(this.guild, actionType, userId, attempts, attemptDelay);
|
||||||
|
} catch (e) {
|
||||||
|
if (e instanceof DiscordRESTError && e.code === 50013) {
|
||||||
|
this.serverLogs.log(LogType.BOT_ALERT, {
|
||||||
|
body: "Missing permissions to read audit log",
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add a BAN action automatically when a user is banned.
|
* Add a BAN action automatically when a user is banned.
|
||||||
* Attempts to find the ban's details in the audit log.
|
* Attempts to find the ban's details in the audit log.
|
||||||
|
@ -175,8 +190,7 @@ export class ModActionsPlugin extends ZeppelinPlugin<TConfigSchema> {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const relevantAuditLogEntry = await findRelevantAuditLogEntry(
|
const relevantAuditLogEntry = await this.findRelevantAuditLogEntry(
|
||||||
this.guild,
|
|
||||||
ErisConstants.AuditLogActions.MEMBER_BAN_ADD,
|
ErisConstants.AuditLogActions.MEMBER_BAN_ADD,
|
||||||
user.id,
|
user.id,
|
||||||
);
|
);
|
||||||
|
@ -214,8 +228,7 @@ export class ModActionsPlugin extends ZeppelinPlugin<TConfigSchema> {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const relevantAuditLogEntry = await findRelevantAuditLogEntry(
|
const relevantAuditLogEntry = await this.findRelevantAuditLogEntry(
|
||||||
this.guild,
|
|
||||||
ErisConstants.AuditLogActions.MEMBER_BAN_REMOVE,
|
ErisConstants.AuditLogActions.MEMBER_BAN_REMOVE,
|
||||||
user.id,
|
user.id,
|
||||||
);
|
);
|
||||||
|
@ -273,8 +286,7 @@ export class ModActionsPlugin extends ZeppelinPlugin<TConfigSchema> {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const kickAuditLogEntry = await findRelevantAuditLogEntry(
|
const kickAuditLogEntry = await this.findRelevantAuditLogEntry(
|
||||||
this.guild,
|
|
||||||
ErisConstants.AuditLogActions.MEMBER_KICK,
|
ErisConstants.AuditLogActions.MEMBER_KICK,
|
||||||
member.id,
|
member.id,
|
||||||
);
|
);
|
||||||
|
|
18
src/utils.ts
18
src/utils.ts
|
@ -3,12 +3,14 @@ import {
|
||||||
EmbedOptions,
|
EmbedOptions,
|
||||||
Emoji,
|
Emoji,
|
||||||
Guild,
|
Guild,
|
||||||
|
GuildAuditLog,
|
||||||
GuildAuditLogEntry,
|
GuildAuditLogEntry,
|
||||||
Member,
|
Member,
|
||||||
TextableChannel,
|
TextableChannel,
|
||||||
TextChannel,
|
TextChannel,
|
||||||
User,
|
User,
|
||||||
} from "eris";
|
} from "eris";
|
||||||
|
import DiscordHTTPError from "eris/lib/errors/DiscordHTTPError"; // tslint:disable-line
|
||||||
import url from "url";
|
import url from "url";
|
||||||
import tlds from "tlds";
|
import tlds from "tlds";
|
||||||
import emojiRegex from "emoji-regex";
|
import emojiRegex from "emoji-regex";
|
||||||
|
@ -129,9 +131,19 @@ export async function findRelevantAuditLogEntry(
|
||||||
attempts: number = 3,
|
attempts: number = 3,
|
||||||
attemptDelay: number = 3000,
|
attemptDelay: number = 3000,
|
||||||
): Promise<GuildAuditLogEntry> {
|
): Promise<GuildAuditLogEntry> {
|
||||||
const auditLogEntries = await guild.getAuditLogs(5, null, actionType);
|
let auditLogs: GuildAuditLog;
|
||||||
|
try {
|
||||||
|
auditLogs = await guild.getAuditLogs(5, null, actionType);
|
||||||
|
} catch (e) {
|
||||||
|
// Ignore internal server errors which seem to be pretty common with audit log requests
|
||||||
|
if (!(e instanceof DiscordHTTPError) || e.code !== 500) {
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
auditLogEntries.entries.sort((a, b) => {
|
const entries = auditLogs ? auditLogs.entries : [];
|
||||||
|
|
||||||
|
entries.sort((a, b) => {
|
||||||
if (a.createdAt > b.createdAt) return -1;
|
if (a.createdAt > b.createdAt) return -1;
|
||||||
if (a.createdAt > b.createdAt) return 1;
|
if (a.createdAt > b.createdAt) return 1;
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -139,7 +151,7 @@ export async function findRelevantAuditLogEntry(
|
||||||
|
|
||||||
const cutoffTS = Date.now() - 1000 * 60 * 2;
|
const cutoffTS = Date.now() - 1000 * 60 * 2;
|
||||||
|
|
||||||
const relevantEntry = auditLogEntries.entries.find(entry => {
|
const relevantEntry = entries.find(entry => {
|
||||||
return entry.targetID === userId && entry.createdAt >= cutoffTS;
|
return entry.targetID === userId && entry.createdAt >= cutoffTS;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue