mirror of
https://github.com/discordjs/discord.js.git
synced 2026-05-30 23:50:07 +00:00
* Fix documentation for GuildAuditLogEntry.target * Update documentation for CategoryChannel#children * Add EntryTarget for audit logs I've done this to "fulfill" devsneks request while also showing all the possible results for the target of an AuditLogEntry * Oops Eslint * Private timeout sets gets set by BaseClient not WebhookClient * Fix the "Missing Docs" for Presence#activity * Small doc inconsistency Array<Number> instead of Array<number> for Activity * Client#emojis is an EmojiStore not a Collection * Document ClientPresenceStore Just so its clickable through the wiki, nothing else is documented * Small fix for BaseClient#setInterval You don't wait before executing, you execute every X ms * GuildChannelResolvable takes a GuildChannel/Snowflake * Typo in UserResolvable * Another typo for UserResolvable * Add the number to the Status and VoiceStatus docs Its probably not needed, but just so the user knows what each number means, its now documented.
330 lines
8.5 KiB
JavaScript
330 lines
8.5 KiB
JavaScript
const Collection = require('../util/Collection');
|
|
const Snowflake = require('../util/Snowflake');
|
|
const Webhook = require('./Webhook');
|
|
|
|
const Targets = {
|
|
ALL: 'ALL',
|
|
GUILD: 'GUILD',
|
|
CHANNEL: 'CHANNEL',
|
|
USER: 'USER',
|
|
ROLE: 'ROLE',
|
|
INVITE: 'INVITE',
|
|
WEBHOOK: 'WEBHOOK',
|
|
EMOJI: 'EMOJI',
|
|
MESSAGE: 'MESSAGE',
|
|
UNKNOWN: 'UNKNOWN',
|
|
};
|
|
|
|
const Actions = {
|
|
ALL: null,
|
|
GUILD_UPDATE: 1,
|
|
CHANNEL_CREATE: 10,
|
|
CHANNEL_UPDATE: 11,
|
|
CHANNEL_DELETE: 12,
|
|
CHANNEL_OVERWRITE_CREATE: 13,
|
|
CHANNEL_OVERWRITE_UPDATE: 14,
|
|
CHANNEL_OVERWRITE_DELETE: 15,
|
|
MEMBER_KICK: 20,
|
|
MEMBER_PRUNE: 21,
|
|
MEMBER_BAN_ADD: 22,
|
|
MEMBER_BAN_REMOVE: 23,
|
|
MEMBER_UPDATE: 24,
|
|
MEMBER_ROLE_UPDATE: 25,
|
|
ROLE_CREATE: 30,
|
|
ROLE_UPDATE: 31,
|
|
ROLE_DELETE: 32,
|
|
INVITE_CREATE: 40,
|
|
INVITE_UPDATE: 41,
|
|
INVITE_DELETE: 42,
|
|
WEBHOOK_CREATE: 50,
|
|
WEBHOOK_UPDATE: 51,
|
|
WEBHOOK_DELETE: 52,
|
|
EMOJI_CREATE: 60,
|
|
EMOJI_UPDATE: 61,
|
|
EMOJI_DELETE: 62,
|
|
MESSAGE_DELETE: 72,
|
|
};
|
|
|
|
|
|
/**
|
|
* Audit logs entries are held in this class.
|
|
*/
|
|
class GuildAuditLogs {
|
|
constructor(guild, data) {
|
|
if (data.users) for (const user of data.users) guild.client.users.create(user);
|
|
/**
|
|
* Cached webhooks
|
|
* @type {Collection<Snowflake, Webhook>}
|
|
* @private
|
|
*/
|
|
this.webhooks = new Collection();
|
|
if (data.webhooks) {
|
|
for (const hook of data.webhooks) {
|
|
this.webhooks.set(hook.id, new Webhook(guild.client, hook));
|
|
}
|
|
}
|
|
|
|
/**
|
|
* The entries for this guild's audit logs
|
|
* @type {Collection<Snowflake, GuildAuditLogsEntry>}
|
|
*/
|
|
this.entries = new Collection();
|
|
for (const item of data.audit_log_entries) {
|
|
const entry = new GuildAuditLogsEntry(guild, item);
|
|
this.entries.set(entry.id, entry);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Handles possible promises for entry targets.
|
|
* @returns {Promise<GuildAuditLogs>}
|
|
*/
|
|
static build(...args) {
|
|
const logs = new GuildAuditLogs(...args);
|
|
return Promise.all(logs.entries.map(e => e.target)).then(() => logs);
|
|
}
|
|
|
|
/**
|
|
* The target type of an entry, e.g. `GUILD`. Here are the available types:
|
|
* * GUILD
|
|
* * CHANNEL
|
|
* * USER
|
|
* * ROLE
|
|
* * INVITE
|
|
* * WEBHOOK
|
|
* * EMOJI
|
|
* * MESSAGE
|
|
* @typedef {string} TargetType
|
|
*/
|
|
|
|
/**
|
|
* The target for an audit log entry. It can be one of:
|
|
* * A guild
|
|
* * A user
|
|
* * A role
|
|
* * An emoji
|
|
* * An invite
|
|
* * A webhook
|
|
* * An object where the keys represent either the new value or the old value
|
|
* @typedef {?Object|Guild|User|Role|Emoji|Invite|Webhook} EntryTarget
|
|
*/
|
|
|
|
/**
|
|
* Find target type from entry action.
|
|
* @param {number} target The action target
|
|
* @returns {?string}
|
|
*/
|
|
static targetType(target) {
|
|
if (target < 10) return Targets.GUILD;
|
|
if (target < 20) return Targets.CHANNEL;
|
|
if (target < 30) return Targets.USER;
|
|
if (target < 40) return Targets.ROLE;
|
|
if (target < 50) return Targets.INVITE;
|
|
if (target < 60) return Targets.WEBHOOK;
|
|
if (target < 70) return Targets.EMOJI;
|
|
if (target < 80) return Targets.MESSAGE;
|
|
return Targets.UNKNOWN;
|
|
}
|
|
|
|
/**
|
|
* The action type of an entry, e.g. `CREATE`. Here are the available types:
|
|
* * CREATE
|
|
* * DELETE
|
|
* * UPDATE
|
|
* @typedef {string} ActionType
|
|
*/
|
|
|
|
/**
|
|
* Find action type from entry action.
|
|
* @param {string} action The action target
|
|
* @returns {string}
|
|
*/
|
|
static actionType(action) {
|
|
if ([
|
|
Actions.CHANNEL_CREATE,
|
|
Actions.CHANNEL_OVERWRITE_CREATE,
|
|
Actions.MEMBER_BAN_REMOVE,
|
|
Actions.ROLE_CREATE,
|
|
Actions.INVITE_CREATE,
|
|
Actions.WEBHOOK_CREATE,
|
|
Actions.EMOJI_CREATE,
|
|
].includes(action)) return 'CREATE';
|
|
|
|
if ([
|
|
Actions.CHANNEL_DELETE,
|
|
Actions.CHANNEL_OVERWRITE_DELETE,
|
|
Actions.MEMBER_KICK,
|
|
Actions.MEMBER_PRUNE,
|
|
Actions.MEMBER_BAN_ADD,
|
|
Actions.ROLE_DELETE,
|
|
Actions.INVITE_DELETE,
|
|
Actions.WEBHOOK_DELETE,
|
|
Actions.EMOJI_DELETE,
|
|
Actions.MESSAGE_DELETE,
|
|
].includes(action)) return 'DELETE';
|
|
|
|
if ([
|
|
Actions.GUILD_UPDATE,
|
|
Actions.CHANNEL_UPDATE,
|
|
Actions.CHANNEL_OVERWRITE_UPDATE,
|
|
Actions.MEMBER_UPDATE,
|
|
Actions.MEMBER_ROLE_UPDATE,
|
|
Actions.ROLE_UPDATE,
|
|
Actions.INVITE_UPDATE,
|
|
Actions.WEBHOOK_UPDATE,
|
|
Actions.EMOJI_UPDATE,
|
|
].includes(action)) return 'UPDATE';
|
|
|
|
return 'ALL';
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Audit logs entry.
|
|
*/
|
|
class GuildAuditLogsEntry {
|
|
constructor(guild, data) {
|
|
const targetType = GuildAuditLogs.targetType(data.action_type);
|
|
/**
|
|
* The target type of this entry
|
|
* @type {TargetType}
|
|
*/
|
|
this.targetType = targetType;
|
|
|
|
/**
|
|
* The action type of this entry
|
|
* @type {ActionType}
|
|
*/
|
|
this.actionType = GuildAuditLogs.actionType(data.action_type);
|
|
|
|
/**
|
|
* Specific action type of this entry
|
|
* @type {string}
|
|
*/
|
|
this.action = Object.keys(Actions).find(k => Actions[k] === data.action_type);
|
|
|
|
/**
|
|
* The reason of this entry
|
|
* @type {?string}
|
|
*/
|
|
this.reason = data.reason || null;
|
|
|
|
/**
|
|
* The user that executed this entry
|
|
* @type {User}
|
|
*/
|
|
this.executor = guild.client.users.get(data.user_id);
|
|
|
|
/**
|
|
* An entry in the audit log representing a specific change.
|
|
* @typedef {object} AuditLogChange
|
|
* @property {string} key The property that was changed, e.g. `nick` for nickname changes
|
|
* @property {*} [old] The old value of the change, e.g. for nicknames, the old nickname
|
|
* @property {*} [new] The new value of the change, e.g. for nicknames, the new nickname
|
|
*/
|
|
|
|
/**
|
|
* Specific property changes
|
|
* @type {AuditLogChange[]}
|
|
*/
|
|
this.changes = data.changes ? data.changes.map(c => ({ key: c.key, old: c.old_value, new: c.new_value })) : null;
|
|
|
|
/**
|
|
* The ID of this entry
|
|
* @type {Snowflake}
|
|
*/
|
|
this.id = data.id;
|
|
|
|
/**
|
|
* Any extra data from the entry
|
|
* @type {?Object|Role|GuildMember}
|
|
*/
|
|
this.extra = null;
|
|
if (data.options) {
|
|
if (data.action_type === Actions.MEMBER_PRUNE) {
|
|
this.extra = {
|
|
removed: data.options.members_removed,
|
|
days: data.options.delete_member_days,
|
|
};
|
|
} else if (data.action_type === Actions.MESSAGE_DELETE) {
|
|
this.extra = {
|
|
count: data.options.count,
|
|
channel: guild.channels.get(data.options.channel_id),
|
|
};
|
|
} else {
|
|
switch (data.options.type) {
|
|
case 'member':
|
|
this.extra = guild.members.get(data.options.id);
|
|
if (!this.extra) this.extra = { id: data.options.id };
|
|
break;
|
|
case 'role':
|
|
this.extra = guild.roles.get(data.options.id);
|
|
if (!this.extra) this.extra = { id: data.options.id, name: data.options.role_name };
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
if (targetType === Targets.UNKNOWN) {
|
|
/**
|
|
* The target of this entry
|
|
* @type {EntryTarget}
|
|
*/
|
|
this.target = this.changes.reduce((o, c) => {
|
|
o[c.key] = c.new || c.old;
|
|
return o;
|
|
}, {});
|
|
this.target.id = data.target_id;
|
|
} else if ([Targets.USER, Targets.GUILD].includes(targetType)) {
|
|
this.target = guild.client[`${targetType.toLowerCase()}s`].get(data.target_id);
|
|
} else if (targetType === Targets.WEBHOOK) {
|
|
this.target = this.webhooks.get(data.target_id);
|
|
} else if (targetType === Targets.INVITE) {
|
|
if (guild.me.permissions.has('MANAGE_GUILD')) {
|
|
const change = this.changes.find(c => c.key === 'code');
|
|
this.target = guild.fetchInvites()
|
|
.then(invites => {
|
|
this.target = invites.find(i => i.code === (change.new || change.old));
|
|
return this.target;
|
|
});
|
|
} else {
|
|
this.target = this.changes.reduce((o, c) => {
|
|
o[c.key] = c.new || c.old;
|
|
return o;
|
|
}, {});
|
|
}
|
|
} else if (targetType === Targets.MESSAGE) {
|
|
this.target = guild.client.users.get(data.target_id);
|
|
} else {
|
|
this.target = guild[`${targetType.toLowerCase()}s`].get(data.target_id);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* The timestamp this entry was created at
|
|
* @type {number}
|
|
* @readonly
|
|
*/
|
|
get createdTimestamp() {
|
|
return Snowflake.deconstruct(this.id).timestamp;
|
|
}
|
|
|
|
/**
|
|
* The time this entry was created
|
|
* @type {Date}
|
|
* @readonly
|
|
*/
|
|
get createdAt() {
|
|
return new Date(this.createdTimestamp);
|
|
}
|
|
}
|
|
|
|
GuildAuditLogs.Actions = Actions;
|
|
GuildAuditLogs.Targets = Targets;
|
|
GuildAuditLogs.Entry = GuildAuditLogsEntry;
|
|
|
|
module.exports = GuildAuditLogs;
|