mirror of
https://github.com/discordjs/discord.js.git
synced 2026-03-09 16:13:31 +01:00
refactor: remove user bot methods (#2559)
* [WIP] Remove user bots * more backend userbot removal * Add mfaEnabled back * revert client presences store removal * partially revert getAuth changes * remove more no longer used children of ClientUserGuildSettings * fix a bug with this pr and TextBasedChannel.applyToClass * remove a syncGuilds reference * more user bot data handling * various guildSync cleanup * bots can't call logout Had the user/bot portions of the code mixed up. Though, does this need to be a promise anymore? * make ClientManager#destroy() sync It nolonger needs to be a promise, and nothing depended on it being a promise that I can tell. * requested change * Fix massive error * no longer used as it's userbot only
This commit is contained in:
@@ -97,8 +97,7 @@ class Client extends BaseClient {
|
||||
this.channels = new ChannelStore(this);
|
||||
|
||||
/**
|
||||
* Presences that have been received for the client user's friends, mapped by user IDs
|
||||
* <warn>This is only filled when using a user account.</warn>
|
||||
* Presences that have been received for the client user, mapped by user IDs
|
||||
* @type {ClientPresenceStore<Snowflake, Presence>}
|
||||
*/
|
||||
this.presences = new ClientPresenceStore(this);
|
||||
@@ -106,7 +105,7 @@ class Client extends BaseClient {
|
||||
Object.defineProperty(this, 'token', { writable: true });
|
||||
if (!browser && !this.token && 'CLIENT_TOKEN' in process.env) {
|
||||
/**
|
||||
* Authorization token for the logged in user/bot
|
||||
* Authorization token for the logged in bot
|
||||
* <warn>This should be kept private at all times.</warn>
|
||||
* @type {?string}
|
||||
*/
|
||||
@@ -240,10 +239,6 @@ class Client extends BaseClient {
|
||||
|
||||
/**
|
||||
* Logs the client in, establishing a websocket connection to Discord.
|
||||
* <info>Both bot and regular user accounts are supported, but it is highly recommended to use a bot account whenever
|
||||
* possible. User accounts are subject to harsher ratelimits and other restrictions that don't apply to bot accounts.
|
||||
* Bot accounts also have access to many features that user accounts cannot utilise. User accounts that are found to
|
||||
* be abusing/overusing the API will be banned, locking you out of Discord entirely.</info>
|
||||
* @param {string} token Token of the account to log in with
|
||||
* @returns {Promise<string>} Token of the account used
|
||||
* @example
|
||||
@@ -262,27 +257,13 @@ class Client extends BaseClient {
|
||||
|
||||
/**
|
||||
* Logs out, terminates the connection to Discord, and destroys the client.
|
||||
* @returns {Promise}
|
||||
* @returns {void}
|
||||
*/
|
||||
destroy() {
|
||||
super.destroy();
|
||||
return this.manager.destroy();
|
||||
}
|
||||
|
||||
/**
|
||||
* Requests a sync of guild data with Discord.
|
||||
* <info>This can be done automatically every 30 seconds by enabling {@link ClientOptions#sync}.</info>
|
||||
* <warn>This is only available when using a user account.</warn>
|
||||
* @param {Guild[]|Collection<Snowflake, Guild>} [guilds=this.guilds] An array or collection of guilds to sync
|
||||
*/
|
||||
syncGuilds(guilds = this.guilds) {
|
||||
if (this.user.bot) return;
|
||||
this.ws.send({
|
||||
op: 12,
|
||||
d: guilds instanceof Collection ? guilds.keyArray() : guilds.map(g => g.id),
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtains an invite from Discord.
|
||||
* @param {InviteResolvable} invite Invite code or URL
|
||||
@@ -369,22 +350,16 @@ class Client extends BaseClient {
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtains the OAuth Application of the bot from Discord.
|
||||
* @param {Snowflake} [id='@me'] ID of application to fetch
|
||||
* Obtains the OAuth Application of this bot from Discord.
|
||||
* @returns {Promise<ClientApplication>}
|
||||
* @example
|
||||
* client.fetchApplication('id')
|
||||
* .then(application => console.log(`Obtained application with name: ${application.name}`)
|
||||
* .catch(console.error);
|
||||
*/
|
||||
fetchApplication(id = '@me') {
|
||||
return this.api.oauth2.applications(id).get()
|
||||
fetchApplication() {
|
||||
return this.api.oauth2.applications('@me').get()
|
||||
.then(app => new ClientApplication(this, app));
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates a link that can be used to invite the bot to a guild.
|
||||
* <warn>This is only available when using a bot account.</warn>
|
||||
* @param {PermissionResolvable} [permissions] Permissions to request
|
||||
* @returns {Promise<string>}
|
||||
* @example
|
||||
|
||||
@@ -63,15 +63,7 @@ class ClientManager {
|
||||
|
||||
destroy() {
|
||||
this.client.ws.destroy();
|
||||
if (!this.client.user) return Promise.resolve();
|
||||
if (this.client.user.bot) {
|
||||
this.client.token = null;
|
||||
return Promise.resolve();
|
||||
} else {
|
||||
return this.client.api.logout.post().then(() => {
|
||||
this.client.token = null;
|
||||
});
|
||||
}
|
||||
if (this.client.user) this.client.token = null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -20,8 +20,6 @@ class ActionsManager {
|
||||
this.register(require('./GuildRoleDelete'));
|
||||
this.register(require('./GuildRoleUpdate'));
|
||||
this.register(require('./UserUpdate'));
|
||||
this.register(require('./UserNoteUpdate'));
|
||||
this.register(require('./GuildSync'));
|
||||
this.register(require('./GuildEmojiCreate'));
|
||||
this.register(require('./GuildEmojiDelete'));
|
||||
this.register(require('./GuildEmojiUpdate'));
|
||||
|
||||
@@ -1,29 +0,0 @@
|
||||
const Action = require('./Action');
|
||||
|
||||
class GuildSync extends Action {
|
||||
handle(data) {
|
||||
const client = this.client;
|
||||
|
||||
const guild = client.guilds.get(data.id);
|
||||
if (guild) {
|
||||
if (data.presences) {
|
||||
for (const presence of data.presences) guild.presences.add(presence);
|
||||
}
|
||||
|
||||
if (data.members) {
|
||||
for (const syncMember of data.members) {
|
||||
const member = guild.members.get(syncMember.user.id);
|
||||
if (member) {
|
||||
member._patch(syncMember);
|
||||
} else {
|
||||
guild.members.add(syncMember, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ('large' in data) guild.large = data.large;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = GuildSync;
|
||||
@@ -1,30 +0,0 @@
|
||||
const Action = require('./Action');
|
||||
const { Events } = require('../../util/Constants');
|
||||
|
||||
class UserNoteUpdateAction extends Action {
|
||||
handle(data) {
|
||||
const client = this.client;
|
||||
|
||||
const oldNote = client.user.notes.get(data.id);
|
||||
const note = data.note.length ? data.note : null;
|
||||
|
||||
client.user.notes.set(data.id, note);
|
||||
|
||||
client.emit(Events.USER_NOTE_UPDATE, data.id, oldNote, note);
|
||||
|
||||
return {
|
||||
old: oldNote,
|
||||
updated: note,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Emitted whenever a note is updated.
|
||||
* @event Client#userNoteUpdate
|
||||
* @param {User} user The user the note belongs to
|
||||
* @param {string} oldNote The note content before the update
|
||||
* @param {string} newNote The note content after the update
|
||||
*/
|
||||
|
||||
module.exports = UserNoteUpdateAction;
|
||||
@@ -37,9 +37,6 @@ class WebSocketPacketManager {
|
||||
this.register(WSEvents.CHANNEL_PINS_UPDATE, require('./handlers/ChannelPinsUpdate'));
|
||||
this.register(WSEvents.PRESENCE_UPDATE, require('./handlers/PresenceUpdate'));
|
||||
this.register(WSEvents.USER_UPDATE, require('./handlers/UserUpdate'));
|
||||
this.register(WSEvents.USER_NOTE_UPDATE, require('./handlers/UserNoteUpdate'));
|
||||
this.register(WSEvents.USER_SETTINGS_UPDATE, require('./handlers/UserSettingsUpdate'));
|
||||
this.register(WSEvents.USER_GUILD_SETTINGS_UPDATE, require('./handlers/UserGuildSettingsUpdate'));
|
||||
this.register(WSEvents.VOICE_STATE_UPDATE, require('./handlers/VoiceStateUpdate'));
|
||||
this.register(WSEvents.TYPING_START, require('./handlers/TypingStart'));
|
||||
this.register(WSEvents.MESSAGE_CREATE, require('./handlers/MessageCreate'));
|
||||
@@ -47,9 +44,6 @@ class WebSocketPacketManager {
|
||||
this.register(WSEvents.MESSAGE_UPDATE, require('./handlers/MessageUpdate'));
|
||||
this.register(WSEvents.MESSAGE_DELETE_BULK, require('./handlers/MessageDeleteBulk'));
|
||||
this.register(WSEvents.VOICE_SERVER_UPDATE, require('./handlers/VoiceServerUpdate'));
|
||||
this.register(WSEvents.GUILD_SYNC, require('./handlers/GuildSync'));
|
||||
this.register(WSEvents.RELATIONSHIP_ADD, require('./handlers/RelationshipAdd'));
|
||||
this.register(WSEvents.RELATIONSHIP_REMOVE, require('./handlers/RelationshipRemove'));
|
||||
this.register(WSEvents.MESSAGE_REACTION_ADD, require('./handlers/MessageReactionAdd'));
|
||||
this.register(WSEvents.MESSAGE_REACTION_REMOVE, require('./handlers/MessageReactionRemove'));
|
||||
this.register(WSEvents.MESSAGE_REACTION_REMOVE_ALL, require('./handlers/MessageReactionRemoveAll'));
|
||||
|
||||
@@ -1,11 +0,0 @@
|
||||
const AbstractHandler = require('./AbstractHandler');
|
||||
|
||||
class GuildSyncHandler extends AbstractHandler {
|
||||
handle(packet) {
|
||||
const client = this.packetManager.client;
|
||||
const data = packet.d;
|
||||
client.actions.GuildSync.handle(data);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = GuildSyncHandler;
|
||||
@@ -9,9 +9,6 @@ class ReadyHandler extends AbstractHandler {
|
||||
|
||||
client.ws.heartbeat();
|
||||
|
||||
data.user.user_settings = data.user_settings;
|
||||
data.user.user_guild_settings = data.user_guild_settings;
|
||||
|
||||
if (!ClientUser) ClientUser = require('../../../../structures/ClientUser');
|
||||
const clientUser = new ClientUser(client, data.user);
|
||||
client.user = clientUser;
|
||||
@@ -20,27 +17,8 @@ class ReadyHandler extends AbstractHandler {
|
||||
|
||||
for (const guild of data.guilds) client.guilds.add(guild);
|
||||
for (const privateDM of data.private_channels) client.channels.add(privateDM);
|
||||
|
||||
for (const relation of data.relationships) {
|
||||
const user = client.users.add(relation.user);
|
||||
if (relation.type === 1) {
|
||||
client.user.friends.set(user.id, user);
|
||||
} else if (relation.type === 2) {
|
||||
client.user.blocked.set(user.id, user);
|
||||
}
|
||||
}
|
||||
|
||||
for (const presence of data.presences || []) client.presences.add(presence);
|
||||
|
||||
if (data.notes) {
|
||||
for (const user in data.notes) {
|
||||
let note = data.notes[user];
|
||||
if (!note.length) note = null;
|
||||
|
||||
client.user.notes.set(user, note);
|
||||
}
|
||||
}
|
||||
|
||||
if (!client.users.has('1')) {
|
||||
client.users.add({
|
||||
id: '1',
|
||||
@@ -61,7 +39,6 @@ class ReadyHandler extends AbstractHandler {
|
||||
client.setMaxListeners(data.guilds.length + 10);
|
||||
|
||||
client.once('ready', () => {
|
||||
client.syncGuilds();
|
||||
client.setMaxListeners(10);
|
||||
client.clearTimeout(t);
|
||||
});
|
||||
|
||||
@@ -1,19 +0,0 @@
|
||||
const AbstractHandler = require('./AbstractHandler');
|
||||
|
||||
class RelationshipAddHandler extends AbstractHandler {
|
||||
handle(packet) {
|
||||
const client = this.packetManager.client;
|
||||
const data = packet.d;
|
||||
if (data.type === 1) {
|
||||
client.users.fetch(data.id).then(user => {
|
||||
client.user.friends.set(user.id, user);
|
||||
});
|
||||
} else if (data.type === 2) {
|
||||
client.users.fetch(data.id).then(user => {
|
||||
client.user.blocked.set(user.id, user);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = RelationshipAddHandler;
|
||||
@@ -1,19 +0,0 @@
|
||||
const AbstractHandler = require('./AbstractHandler');
|
||||
|
||||
class RelationshipRemoveHandler extends AbstractHandler {
|
||||
handle(packet) {
|
||||
const client = this.packetManager.client;
|
||||
const data = packet.d;
|
||||
if (data.type === 2) {
|
||||
if (client.user.blocked.has(data.id)) {
|
||||
client.user.blocked.delete(data.id);
|
||||
}
|
||||
} else if (data.type === 1) {
|
||||
if (client.user.friends.has(data.id)) {
|
||||
client.user.friends.delete(data.id);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = RelationshipRemoveHandler;
|
||||
@@ -1,21 +0,0 @@
|
||||
const AbstractHandler = require('./AbstractHandler');
|
||||
const { Events } = require('../../../../util/Constants');
|
||||
const ClientUserGuildSettings = require('../../../../structures/ClientUserGuildSettings');
|
||||
|
||||
class UserGuildSettingsUpdateHandler extends AbstractHandler {
|
||||
handle(packet) {
|
||||
const client = this.packetManager.client;
|
||||
const settings = client.user.guildSettings.get(packet.d.guild_id);
|
||||
if (settings) settings.patch(packet.d);
|
||||
else client.user.guildSettings.set(packet.d.guild_id, new ClientUserGuildSettings(this.client, packet.d));
|
||||
client.emit(Events.USER_GUILD_SETTINGS_UPDATE, client.user.guildSettings.get(packet.d.guild_id));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Emitted whenever the client user's settings update.
|
||||
* @event Client#clientUserGuildSettingsUpdate
|
||||
* @param {ClientUserGuildSettings} clientUserGuildSettings The new client user guild settings
|
||||
*/
|
||||
|
||||
module.exports = UserGuildSettingsUpdateHandler;
|
||||
@@ -1,12 +0,0 @@
|
||||
const AbstractHandler = require('./AbstractHandler');
|
||||
|
||||
class UserNoteUpdateHandler extends AbstractHandler {
|
||||
handle(packet) {
|
||||
const client = this.packetManager.client;
|
||||
const data = packet.d;
|
||||
|
||||
client.actions.UserNoteUpdate.handle(data);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = UserNoteUpdateHandler;
|
||||
@@ -1,18 +0,0 @@
|
||||
const AbstractHandler = require('./AbstractHandler');
|
||||
const { Events } = require('../../../../util/Constants');
|
||||
|
||||
class UserSettingsUpdateHandler extends AbstractHandler {
|
||||
handle(packet) {
|
||||
const client = this.packetManager.client;
|
||||
client.user.settings.patch(packet.d);
|
||||
client.emit(Events.USER_SETTINGS_UPDATE, client.user.settings);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Emitted whenever the client user's settings update.
|
||||
* @event Client#clientUserSettingsUpdate
|
||||
* @param {ClientUserSettings} clientUserSettings The new client user settings
|
||||
*/
|
||||
|
||||
module.exports = UserSettingsUpdateHandler;
|
||||
@@ -6,8 +6,6 @@ const Messages = {
|
||||
TOKEN_INVALID: 'An invalid token was provided.',
|
||||
TOKEN_MISSING: 'Request to use token, but token was unavailable to the client.',
|
||||
|
||||
FEATURE_USER_ONLY: 'Only user accounts are able to make use of this feature.',
|
||||
|
||||
WS_CONNECTION_TIMEOUT: 'The connection to the gateway timed out.',
|
||||
WS_CONNECTION_EXISTS: 'There is already an existing WebSocket connection.',
|
||||
WS_NOT_OPEN: (data = 'data') => `Websocket not open to send ${data}`,
|
||||
|
||||
@@ -56,9 +56,6 @@ module.exports = {
|
||||
// This is a getter so that it properly extends any custom User class
|
||||
return require('./structures/ClientUser');
|
||||
},
|
||||
ClientUserChannelOverride: require('./structures/ClientUserChannelOverride'),
|
||||
ClientUserGuildSettings: require('./structures/ClientUserGuildSettings'),
|
||||
ClientUserSettings: require('./structures/ClientUserSettings'),
|
||||
Collector: require('./structures/interfaces/Collector'),
|
||||
DMChannel: require('./structures/DMChannel'),
|
||||
Emoji: require('./structures/Emoji'),
|
||||
|
||||
@@ -25,7 +25,7 @@ class RESTManager {
|
||||
|
||||
getAuth() {
|
||||
const token = this.client.token || this.client.accessToken;
|
||||
const prefixed = !!this.client.application || (this.client.user && this.client.user.bot);
|
||||
const prefixed = !!this.client.application || this.client.user;
|
||||
if (token && prefixed) return `${this.tokenPrefix} ${token}`;
|
||||
else if (token) return token;
|
||||
throw new Error('TOKEN_MISSING');
|
||||
|
||||
@@ -39,7 +39,7 @@ class GuildStore extends DataStore {
|
||||
|
||||
/**
|
||||
* Creates a guild.
|
||||
* <warn>This is only available to bots in less than 10 guilds and user accounts.</warn>
|
||||
* <warn>This is only available to bots in fewer than 10 guilds.</warn>
|
||||
* @param {string} name The name of the guild
|
||||
* @param {Object} [options] Options for the creating
|
||||
* @param {string} [options.region] The region for the server, defaults to the closest one available
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
const DataStore = require('./DataStore');
|
||||
const Collection = require('../util/Collection');
|
||||
const Message = require('../structures/Message');
|
||||
const { Error } = require('../errors');
|
||||
|
||||
/**
|
||||
* Stores messages for text-based channels.
|
||||
@@ -80,12 +79,6 @@ class MessageStore extends DataStore {
|
||||
}
|
||||
|
||||
async _fetchId(messageID) {
|
||||
if (!this.client.user.bot) {
|
||||
const messages = await this._fetchMany({ limit: 1, around: messageID });
|
||||
const msg = messages.get(messageID);
|
||||
if (!msg) throw new Error('MESSAGE_MISSING');
|
||||
return msg;
|
||||
}
|
||||
const data = await this.client.api.channels[this.channel.id].messages[messageID].get();
|
||||
return this.add(data);
|
||||
}
|
||||
|
||||
@@ -45,7 +45,6 @@ class UserStore extends DataStore {
|
||||
|
||||
/**
|
||||
* Obtains a user from Discord, or the user cache if it's already available.
|
||||
* <warn>This is only available when using a bot account.</warn>
|
||||
* @param {Snowflake} id ID of the user
|
||||
* @param {boolean} [cache=true] Whether to cache the new user object if it isn't already
|
||||
* @returns {Promise<User>}
|
||||
|
||||
@@ -170,26 +170,6 @@ class ClientApplication extends Base {
|
||||
} });
|
||||
}
|
||||
|
||||
/**
|
||||
* Resets the app's secret.
|
||||
* <warn>This is only available when using a user account.</warn>
|
||||
* @returns {Promise<ClientApplication>}
|
||||
*/
|
||||
resetSecret() {
|
||||
return this.client.api.oauth2.applications[this.id].reset.post()
|
||||
.then(app => new ClientApplication(this.client, app));
|
||||
}
|
||||
|
||||
/**
|
||||
* Resets the app's bot token.
|
||||
* <warn>This is only available when using a user account.</warn>
|
||||
* @returns {Promise<ClientApplication>}
|
||||
*/
|
||||
resetToken() {
|
||||
return this.client.api.oauth2.applications[this.id].bot.reset.post()
|
||||
.then(app => new ClientApplication(this.client, Object.assign({}, this, { bot: app })));
|
||||
}
|
||||
|
||||
/**
|
||||
* When concatenated with a string, this automatically returns the application's name instead of the
|
||||
* ClientApplication object.
|
||||
|
||||
@@ -1,10 +1,5 @@
|
||||
const Structures = require('../util/Structures');
|
||||
const Collection = require('../util/Collection');
|
||||
const ClientUserSettings = require('./ClientUserSettings');
|
||||
const ClientUserGuildSettings = require('./ClientUserGuildSettings');
|
||||
const Util = require('../util/Util');
|
||||
const DataResolver = require('../util/DataResolver');
|
||||
const Guild = require('./Guild');
|
||||
|
||||
/**
|
||||
* Represents the logged in client's Discord user.
|
||||
@@ -20,75 +15,14 @@ class ClientUser extends Structures.get('User') {
|
||||
*/
|
||||
this.verified = data.verified;
|
||||
|
||||
/**
|
||||
* The email of this account
|
||||
* <warn>This is only filled when using a user account.</warn>
|
||||
* @type {?string}
|
||||
*/
|
||||
this.email = data.email;
|
||||
this._typing = new Map();
|
||||
|
||||
/**
|
||||
* A Collection of friends for the logged in user
|
||||
* <warn>This is only filled when using a user account.</warn>
|
||||
* @type {Collection<Snowflake, User>}
|
||||
*/
|
||||
this.friends = new Collection();
|
||||
|
||||
/**
|
||||
* A Collection of blocked users for the logged in user
|
||||
* <warn>This is only filled when using a user account.</warn>
|
||||
* @type {Collection<Snowflake, User>}
|
||||
*/
|
||||
this.blocked = new Collection();
|
||||
|
||||
/**
|
||||
* A Collection of notes for the logged in user
|
||||
* <warn>This is only filled when using a user account.</warn>
|
||||
* @type {Collection<Snowflake, string>}
|
||||
*/
|
||||
this.notes = new Collection();
|
||||
|
||||
/**
|
||||
* If the user has Discord premium (nitro)
|
||||
* <warn>This is only filled when using a user account.</warn>
|
||||
* @type {?boolean}
|
||||
*/
|
||||
this.premium = typeof data.premium === 'boolean' ? data.premium : null;
|
||||
|
||||
/**
|
||||
* If the user has MFA enabled on their account
|
||||
* <warn>This is only filled when using a user account.</warn>
|
||||
* If the bot's {@link ClientApplication#owner Owner} has MFA enabled on their account
|
||||
* @type {?boolean}
|
||||
*/
|
||||
this.mfaEnabled = typeof data.mfa_enabled === 'boolean' ? data.mfa_enabled : null;
|
||||
|
||||
/**
|
||||
* If the user has ever used a mobile device on Discord
|
||||
* <warn>This is only filled when using a user account.</warn>
|
||||
* @type {?boolean}
|
||||
*/
|
||||
this.mobile = typeof data.mobile === 'boolean' ? data.mobile : null;
|
||||
|
||||
/**
|
||||
* Various settings for this user
|
||||
* <warn>This is only filled when using a user account.</warn>
|
||||
* @type {?ClientUserSettings}
|
||||
*/
|
||||
this.settings = data.user_settings ? new ClientUserSettings(this, data.user_settings) : null;
|
||||
|
||||
/**
|
||||
* All of the user's guild settings
|
||||
* <warn>This is only filled when using a user account.</warn>
|
||||
* @type {Collection<Snowflake, ClientUserGuildSettings>}
|
||||
*/
|
||||
this.guildSettings = new Collection();
|
||||
if (data.user_guild_settings) {
|
||||
for (const settings of data.user_guild_settings) {
|
||||
this.guildSettings.set(settings.guild_id, new ClientUserGuildSettings(this.client, settings));
|
||||
}
|
||||
}
|
||||
|
||||
if (data.token) this.client.token = data.token;
|
||||
}
|
||||
|
||||
@@ -101,15 +35,7 @@ class ClientUser extends Structures.get('User') {
|
||||
return this.client.presences.clientPresence;
|
||||
}
|
||||
|
||||
edit(data, passcode) {
|
||||
if (!this.bot) {
|
||||
if (typeof passcode !== 'object') {
|
||||
data.password = passcode;
|
||||
} else {
|
||||
data.code = passcode.mfaCode;
|
||||
data.password = passcode.password;
|
||||
}
|
||||
}
|
||||
edit(data) {
|
||||
return this.client.api.users('@me').patch({ data })
|
||||
.then(newData => {
|
||||
this.client.token = newData.token;
|
||||
@@ -122,7 +48,6 @@ class ClientUser extends Structures.get('User') {
|
||||
* <info>Changing usernames in Discord is heavily rate limited, with only 2 requests
|
||||
* every hour. Use this sparingly!</info>
|
||||
* @param {string} username The new username
|
||||
* @param {string} [password] Current password (only for user accounts)
|
||||
* @returns {Promise<ClientUser>}
|
||||
* @example
|
||||
* // Set username
|
||||
@@ -130,43 +55,8 @@ class ClientUser extends Structures.get('User') {
|
||||
* .then(user => console.log(`My new username is ${user.username}`))
|
||||
* .catch(console.error);
|
||||
*/
|
||||
setUsername(username, password) {
|
||||
return this.edit({ username }, password);
|
||||
}
|
||||
|
||||
/**
|
||||
* Changes the email for the client user's account.
|
||||
* <warn>This is only available when using a user account.</warn>
|
||||
* @param {string} email New email to change to
|
||||
* @param {string} password Current password
|
||||
* @returns {Promise<ClientUser>}
|
||||
* @example
|
||||
* // Set email
|
||||
* client.user.setEmail('bob@gmail.com', 'some amazing password 123')
|
||||
* .then(user => console.log(`My new email is ${user.email}`))
|
||||
* .catch(console.error);
|
||||
*/
|
||||
setEmail(email, password) {
|
||||
return this.edit({ email }, password);
|
||||
}
|
||||
|
||||
/**
|
||||
* Changes the password for the client user's account.
|
||||
* <warn>This is only available when using a user account.</warn>
|
||||
* @param {string} newPassword New password to change to
|
||||
* @param {Object|string} options Object containing an MFA code, password or both.
|
||||
* Can be just a string for the password.
|
||||
* @param {string} [options.oldPassword] Current password
|
||||
* @param {string} [options.mfaCode] Timed MFA Code
|
||||
* @returns {Promise<ClientUser>}
|
||||
* @example
|
||||
* // Set password
|
||||
* client.user.setPassword('some new amazing password 456', 'some amazing password 123')
|
||||
* .then(user => console.log('New password set!'))
|
||||
* .catch(console.error);
|
||||
*/
|
||||
setPassword(newPassword, options) {
|
||||
return this.edit({ new_password: newPassword }, { password: options.oldPassword, mfaCode: options.mfaCode });
|
||||
setUsername(username) {
|
||||
return this.edit({ username });
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -262,36 +152,6 @@ class ClientUser extends Structures.get('User') {
|
||||
return this.setPresence({ afk });
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetches messages that mentioned the client's user.
|
||||
* <warn>This is only available when using a user account.</warn>
|
||||
* @param {Object} [options={}] Options for the fetch
|
||||
* @param {number} [options.limit=25] Maximum number of mentions to retrieve
|
||||
* @param {boolean} [options.roles=true] Whether to include role mentions
|
||||
* @param {boolean} [options.everyone=true] Whether to include everyone/here mentions
|
||||
* @param {GuildResolvable} [options.guild] Limit the search to a specific guild
|
||||
* @returns {Promise<Message[]>}
|
||||
* @example
|
||||
* // Fetch mentions
|
||||
* client.user.fetchMentions()
|
||||
* .then(console.log)
|
||||
* .catch(console.error);
|
||||
* @example
|
||||
* // Fetch mentions from a guild
|
||||
* client.user.fetchMentions({
|
||||
* guild: '222078108977594368'
|
||||
* })
|
||||
* .then(console.log)
|
||||
* .catch(console.error);
|
||||
*/
|
||||
fetchMentions(options = {}) {
|
||||
if (options.guild instanceof Guild) options.guild = options.guild.id;
|
||||
Util.mergeDefault({ limit: 25, roles: true, everyone: true, guild: null }, options);
|
||||
|
||||
return this.client.api.users('@me').mentions.get({ query: options })
|
||||
.then(data => data.map(m => this.client.channels.get(m.channel_id).messages.add(m, false)));
|
||||
}
|
||||
|
||||
/**
|
||||
* An object containing either a user or access token, and an optional nickname.
|
||||
* @typedef {Object} GroupDMRecipientOptions
|
||||
@@ -327,16 +187,6 @@ class ClientUser extends Structures.get('User') {
|
||||
return this.client.api.users('@me').channels.post({ data })
|
||||
.then(res => this.client.channels.add(res));
|
||||
}
|
||||
|
||||
toJSON() {
|
||||
return super.toJSON({
|
||||
friends: false,
|
||||
blocked: false,
|
||||
notes: false,
|
||||
settings: false,
|
||||
guildSettings: false,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = ClientUser;
|
||||
|
||||
@@ -1,28 +0,0 @@
|
||||
const { UserChannelOverrideMap } = require('../util/Constants');
|
||||
|
||||
/**
|
||||
* A wrapper around the ClientUser's channel overrides.
|
||||
*/
|
||||
class ClientUserChannelOverride {
|
||||
constructor(data) {
|
||||
this.patch(data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Patch the data contained in this class with new partial data.
|
||||
* @param {Object} data Data to patch this with
|
||||
* @private
|
||||
*/
|
||||
patch(data) {
|
||||
for (const [key, value] of Object.entries(UserChannelOverrideMap)) {
|
||||
if (!data.hasOwnProperty(key)) continue;
|
||||
if (typeof value === 'function') {
|
||||
this[value.name] = value(data[key]);
|
||||
} else {
|
||||
this[value] = data[key];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = ClientUserChannelOverride;
|
||||
@@ -1,60 +0,0 @@
|
||||
const { UserGuildSettingsMap } = require('../util/Constants');
|
||||
const Collection = require('../util/Collection');
|
||||
const ClientUserChannelOverride = require('./ClientUserChannelOverride');
|
||||
|
||||
/**
|
||||
* A wrapper around the ClientUser's guild settings.
|
||||
*/
|
||||
class ClientUserGuildSettings {
|
||||
constructor(client, data) {
|
||||
/**
|
||||
* The client that created the instance of the ClientUserGuildSettings
|
||||
* @name ClientUserGuildSettings#client
|
||||
* @type {Client}
|
||||
* @readonly
|
||||
*/
|
||||
Object.defineProperty(this, 'client', { value: client });
|
||||
/**
|
||||
* The ID of the guild these settings are for
|
||||
* @type {Snowflake}
|
||||
*/
|
||||
this.guildID = data.guild_id;
|
||||
this.channelOverrides = new Collection();
|
||||
this.patch(data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Patch the data contained in this class with new partial data.
|
||||
* @param {Object} data Data to patch this with
|
||||
* @private
|
||||
*/
|
||||
patch(data) {
|
||||
for (const [key, value] of Object.entries(UserGuildSettingsMap)) {
|
||||
if (!data.hasOwnProperty(key)) continue;
|
||||
if (key === 'channel_overrides') {
|
||||
for (const channel of data[key]) {
|
||||
const override = this.channelOverrides.get(channel.channel_id);
|
||||
if (override) override.patch(channel);
|
||||
else this.channelOverrides.set(channel.channel_id, new ClientUserChannelOverride(channel));
|
||||
}
|
||||
} else if (typeof value === 'function') {
|
||||
this[value.name] = value(data[key]);
|
||||
} else {
|
||||
this[value] = data[key];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Update a specific property of the guild settings.
|
||||
* @param {string} name Name of property
|
||||
* @param {*} value Value to patch
|
||||
* @returns {Promise<Object>}
|
||||
* @private
|
||||
*/
|
||||
update(name, value) {
|
||||
return this.client.api.users('@me').guilds(this.guildID).settings.patch({ data: { [name]: value } });
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = ClientUserGuildSettings;
|
||||
@@ -1,80 +0,0 @@
|
||||
const { UserSettingsMap } = require('../util/Constants');
|
||||
const Util = require('../util/Util');
|
||||
const { Error } = require('../errors');
|
||||
|
||||
/**
|
||||
* A wrapper around the ClientUser's settings.
|
||||
*/
|
||||
class ClientUserSettings {
|
||||
constructor(user, data) {
|
||||
this.user = user;
|
||||
this.patch(data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Patch the data contained in this class with new partial data.
|
||||
* @param {Object} data Data to patch this with
|
||||
* @private
|
||||
*/
|
||||
patch(data) {
|
||||
for (const [key, value] of Object.entries(UserSettingsMap)) {
|
||||
if (!data.hasOwnProperty(key)) continue;
|
||||
if (typeof value === 'function') {
|
||||
this[value.name] = value(data[key]);
|
||||
} else {
|
||||
this[value] = data[key];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Update a specific property of of user settings.
|
||||
* @param {string} name Name of property
|
||||
* @param {*} value Value to patch
|
||||
* @returns {Promise<Object>}
|
||||
* @private
|
||||
*/
|
||||
update(name, value) {
|
||||
return this.user.client.api.users['@me'].settings.patch({ data: { [name]: value } });
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the position of the guild in the guild listing.
|
||||
* @param {Guild} guild The guild to move
|
||||
* @param {number} position Absolute or relative position
|
||||
* @param {boolean} [relative=false] Whether to position relatively or absolutely
|
||||
* @returns {Promise<Guild>}
|
||||
*/
|
||||
setGuildPosition(guild, position, relative) {
|
||||
const temp = Object.assign([], this.guildPositions);
|
||||
Util.moveElementInArray(temp, guild.id, position, relative);
|
||||
return this.update('guild_positions', temp).then(() => guild);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a guild to the list of restricted guilds.
|
||||
* @param {Guild} guild The guild to add
|
||||
* @returns {Promise<Guild>}
|
||||
*/
|
||||
addRestrictedGuild(guild) {
|
||||
const temp = Object.assign([], this.restrictedGuilds);
|
||||
if (temp.includes(guild.id)) return Promise.reject(new Error('GUILD_RESTRICTED', true));
|
||||
temp.push(guild.id);
|
||||
return this.update('restricted_guilds', temp).then(() => guild);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes a guild from the list of restricted guilds.
|
||||
* @param {Guild} guild The guild to remove
|
||||
* @returns {Promise<Guild>}
|
||||
*/
|
||||
removeRestrictedGuild(guild) {
|
||||
const temp = Object.assign([], this.restrictedGuilds);
|
||||
const index = temp.indexOf(guild.id);
|
||||
if (index < 0) return Promise.reject(new Error('GUILD_RESTRICTED'));
|
||||
temp.splice(index, 1);
|
||||
return this.update('restricted_guilds', temp).then(() => guild);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = ClientUserSettings;
|
||||
@@ -184,16 +184,12 @@ class GroupDMChannel extends Channel {
|
||||
* @param {Object} options Options for this method
|
||||
* @param {UserResolvable} options.user User to add to this Group DM
|
||||
* @param {string} [options.accessToken] Access token to use to add the user to this Group DM
|
||||
* (only available under a bot account)
|
||||
* @param {string} [options.nick] Permanent nickname to give the user (only available under a bot account)
|
||||
* @param {string} [options.nick] Permanent nickname to give the user
|
||||
* @returns {Promise<GroupDMChannel>}
|
||||
*/
|
||||
addUser({ user, accessToken, nick }) {
|
||||
const id = this.client.users.resolveID(user);
|
||||
const data = this.client.user.bot ?
|
||||
{ nick, access_token: accessToken } :
|
||||
{ recipient: id };
|
||||
return this.client.api.channels[this.id].recipients[id].put({ data })
|
||||
return this.client.api.channels[this.id].recipients[id].put({ nick, access_token: accessToken })
|
||||
.then(() => this);
|
||||
}
|
||||
|
||||
|
||||
@@ -7,7 +7,6 @@ const Collection = require('../util/Collection');
|
||||
const Util = require('../util/Util');
|
||||
const DataResolver = require('../util/DataResolver');
|
||||
const Snowflake = require('../util/Snowflake');
|
||||
const Shared = require('./shared');
|
||||
const GuildMemberStore = require('../stores/GuildMemberStore');
|
||||
const RoleStore = require('../stores/RoleStore');
|
||||
const GuildEmojiStore = require('../stores/GuildEmojiStore');
|
||||
@@ -352,79 +351,6 @@ class Guild extends Base {
|
||||
return this.client.voice.connections.get(this.id) || null;
|
||||
}
|
||||
|
||||
/**
|
||||
* The position of this guild
|
||||
* <warn>This is only available when using a user account.</warn>
|
||||
* @type {?number}
|
||||
* @readonly
|
||||
*/
|
||||
get position() {
|
||||
if (this.client.user.bot) return null;
|
||||
if (!this.client.user.settings.guildPositions) return null;
|
||||
return this.client.user.settings.guildPositions.indexOf(this.id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether the guild is muted
|
||||
* <warn>This is only available when using a user account.</warn>
|
||||
* @type {?boolean}
|
||||
* @readonly
|
||||
*/
|
||||
get muted() {
|
||||
if (this.client.user.bot) return null;
|
||||
try {
|
||||
return this.client.user.guildSettings.get(this.id).muted;
|
||||
} catch (err) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The type of message that should notify you
|
||||
* one of `EVERYTHING`, `MENTIONS`, `NOTHING`
|
||||
* <warn>This is only available when using a user account.</warn>
|
||||
* @type {?string}
|
||||
* @readonly
|
||||
*/
|
||||
get messageNotifications() {
|
||||
if (this.client.user.bot) return null;
|
||||
try {
|
||||
return this.client.user.guildSettings.get(this.id).messageNotifications;
|
||||
} catch (err) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether to receive mobile push notifications
|
||||
* <warn>This is only available when using a user account.</warn>
|
||||
* @type {?boolean}
|
||||
* @readonly
|
||||
*/
|
||||
get mobilePush() {
|
||||
if (this.client.user.bot) return null;
|
||||
try {
|
||||
return this.client.user.guildSettings.get(this.id).mobilePush;
|
||||
} catch (err) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether to suppress everyone messages
|
||||
* <warn>This is only available when using a user account.</warn>
|
||||
* @type {?boolean}
|
||||
* @readonly
|
||||
*/
|
||||
get suppressEveryone() {
|
||||
if (this.client.user.bot) return null;
|
||||
try {
|
||||
return this.client.user.guildSettings.get(this.id).suppressEveryone;
|
||||
} catch (err) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The `@everyone` role of the guild
|
||||
* @type {?Role}
|
||||
@@ -597,26 +523,6 @@ class Guild extends Base {
|
||||
.then(data => this.members.add(data));
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs a search within the entire guild.
|
||||
* <warn>This is only available when using a user account.</warn>
|
||||
* @param {MessageSearchOptions} [options={}] Options to pass to the search
|
||||
* @returns {Promise<MessageSearchResult>}
|
||||
* @example
|
||||
* guild.search({
|
||||
* content: 'discord.js',
|
||||
* before: '2016-11-17'
|
||||
* })
|
||||
* .then(res => {
|
||||
* const hit = res.results[0].find(m => m.hit).content;
|
||||
* console.log(`I found: **${hit}**, total results: ${res.total}`);
|
||||
* })
|
||||
* .catch(console.error);
|
||||
*/
|
||||
search(options = {}) {
|
||||
return Shared.search(this, options);
|
||||
}
|
||||
|
||||
/**
|
||||
* The data for editing a guild.
|
||||
* @typedef {Object} GuildEditData
|
||||
@@ -831,55 +737,6 @@ class Guild extends Base {
|
||||
return this.edit({ splash: await DataResolver.resolveImage(splash), reason });
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the position of the guild in the guild listing.
|
||||
* <warn>This is only available when using a user account.</warn>
|
||||
* @param {number} position Absolute or relative position
|
||||
* @param {boolean} [relative=false] Whether to position relatively or absolutely
|
||||
* @returns {Promise<Guild>}
|
||||
*/
|
||||
setPosition(position, relative) {
|
||||
if (this.client.user.bot) {
|
||||
return Promise.reject(new Error('FEATURE_USER_ONLY'));
|
||||
}
|
||||
return this.client.user.settings.setGuildPosition(this, position, relative);
|
||||
}
|
||||
|
||||
/**
|
||||
* Marks all messages in this guild as read.
|
||||
* <warn>This is only available when using a user account.</warn>
|
||||
* @returns {Promise<Guild>}
|
||||
*/
|
||||
acknowledge() {
|
||||
return this.client.api.guilds(this.id).ack
|
||||
.post({ data: { token: this.client.rest._ackToken } })
|
||||
.then(res => {
|
||||
if (res.token) this.client.rest._ackToken = res.token;
|
||||
return this;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether to allow direct messages from guild members.
|
||||
* <warn>This is only available when using a user account.</warn>
|
||||
* @param {boolean} allow Whether to allow direct messages
|
||||
* @returns {Promise<Guild>}
|
||||
*/
|
||||
allowDMs(allow) {
|
||||
if (this.client.user.bot) return Promise.reject(new Error('FEATURE_USER_ONLY'));
|
||||
const settings = this.client.user.settings;
|
||||
if (allow) return settings.removeRestrictedGuild(this);
|
||||
else return settings.addRestrictedGuild(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Syncs this guild (already done automatically every 30 seconds).
|
||||
* <warn>This is only available when using a user account.</warn>
|
||||
*/
|
||||
sync() {
|
||||
if (!this.client.user.bot) this.client.syncGuilds([this]);
|
||||
}
|
||||
|
||||
/**
|
||||
* The data needed for updating a channel's position.
|
||||
* @typedef {Object} ChannelPosition
|
||||
|
||||
@@ -6,7 +6,6 @@ const PermissionOverwrites = require('./PermissionOverwrites');
|
||||
const Util = require('../util/Util');
|
||||
const Permissions = require('../util/Permissions');
|
||||
const Collection = require('../util/Collection');
|
||||
const { MessageNotificationTypes } = require('../util/Constants');
|
||||
const { Error, TypeError } = require('../errors');
|
||||
|
||||
/**
|
||||
@@ -564,37 +563,6 @@ class GuildChannel extends Channel {
|
||||
delete(reason) {
|
||||
return this.client.api.channels(this.id).delete({ reason }).then(() => this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether the channel is muted
|
||||
* <warn>This is only available when using a user account.</warn>
|
||||
* @type {?boolean}
|
||||
* @readonly
|
||||
*/
|
||||
get muted() {
|
||||
if (this.client.user.bot) return null;
|
||||
try {
|
||||
return this.client.user.guildSettings.get(this.guild.id).channelOverrides.get(this.id).muted;
|
||||
} catch (err) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The type of message that should notify you
|
||||
* one of `EVERYTHING`, `MENTIONS`, `NOTHING`, `INHERIT`
|
||||
* <warn>This is only available when using a user account.</warn>
|
||||
* @type {?string}
|
||||
* @readonly
|
||||
*/
|
||||
get messageNotifications() {
|
||||
if (this.client.user.bot) return null;
|
||||
try {
|
||||
return this.client.user.guildSettings.get(this.guild.id).channelOverrides.get(this.id).messageNotifications;
|
||||
} catch (err) {
|
||||
return MessageNotificationTypes[3];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = GuildChannel;
|
||||
|
||||
@@ -499,20 +499,6 @@ class Message extends Base {
|
||||
return this.channel.send(content, Object.assign(options, { reply: this.member || this.author }));
|
||||
}
|
||||
|
||||
/**
|
||||
* Marks the message as read.
|
||||
* <warn>This is only available when using a user account.</warn>
|
||||
* @returns {Promise<Message>}
|
||||
*/
|
||||
acknowledge() {
|
||||
return this.client.api.channels(this.channel.id).messages(this.id).ack
|
||||
.post({ data: { token: this.client.rest._ackToken } })
|
||||
.then(res => {
|
||||
if (res.token) this.client.rest._ackToken = res.token;
|
||||
return this;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetches the webhook used to create this message.
|
||||
* @returns {Promise<?Webhook>}
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
const TextBasedChannel = require('./interfaces/TextBasedChannel');
|
||||
const { Presence } = require('./Presence');
|
||||
const UserProfile = require('./UserProfile');
|
||||
const Snowflake = require('../util/Snowflake');
|
||||
const Base = require('./Base');
|
||||
const { Error } = require('../errors');
|
||||
@@ -151,16 +150,6 @@ class User extends Base {
|
||||
return `${this.username}#${this.discriminator}`;
|
||||
}
|
||||
|
||||
/**
|
||||
* The note that is set for the user
|
||||
* <warn>This is only available when using a user account.</warn>
|
||||
* @type {?string}
|
||||
* @readonly
|
||||
*/
|
||||
get note() {
|
||||
return this.client.user.notes.get(this.id) || null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether the user is typing in a channel.
|
||||
* @param {ChannelResolvable} channel The channel to check in
|
||||
@@ -222,26 +211,6 @@ class User extends Base {
|
||||
.then(data => this.client.actions.ChannelDelete.handle(data).channel);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the profile of the user.
|
||||
* <warn>This is only available when using a user account.</warn>
|
||||
* @returns {Promise<UserProfile>}
|
||||
*/
|
||||
fetchProfile() {
|
||||
return this.client.api.users(this.id).profile.get().then(data => new UserProfile(this, data));
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a note for the user.
|
||||
* <warn>This is only available when using a user account.</warn>
|
||||
* @param {string} note The note to set for the user
|
||||
* @returns {Promise<User>}
|
||||
*/
|
||||
setNote(note) {
|
||||
return this.client.api.users('@me').notes(this.id).put({ data: { note } })
|
||||
.then(() => this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the user is equal to another. It compares ID, username, discriminator, avatar, and bot flags.
|
||||
* It is recommended to compare equality by using `user.id === user2.id` unless you want to compare all properties.
|
||||
|
||||
@@ -1,83 +0,0 @@
|
||||
const Collection = require('../util/Collection');
|
||||
const { UserFlags } = require('../util/Constants');
|
||||
const UserConnection = require('./UserConnection');
|
||||
const Base = require('./Base');
|
||||
|
||||
/**
|
||||
* Represents a user's profile on Discord.
|
||||
* @extends {Base}
|
||||
*/
|
||||
class UserProfile extends Base {
|
||||
constructor(user, data) {
|
||||
super(user.client);
|
||||
|
||||
/**
|
||||
* The owner of the profile
|
||||
* @type {User}
|
||||
*/
|
||||
this.user = user;
|
||||
|
||||
/**
|
||||
* The guilds that the client user and the user share
|
||||
* @type {Collection<Snowflake, Guild>}
|
||||
*/
|
||||
this.mutualGuilds = new Collection();
|
||||
|
||||
/**
|
||||
* The user's connections
|
||||
* @type {Collection<Snowflake, UserConnection>}
|
||||
*/
|
||||
this.connections = new Collection();
|
||||
|
||||
this._patch(data);
|
||||
}
|
||||
|
||||
_patch(data) {
|
||||
/**
|
||||
* If the user has Discord Premium
|
||||
* @type {boolean}
|
||||
*/
|
||||
this.premium = Boolean(data.premium_since);
|
||||
|
||||
/**
|
||||
* The Bitfield of the users' flags
|
||||
* @type {number}
|
||||
* @private
|
||||
*/
|
||||
this._flags = data.user.flags;
|
||||
|
||||
/**
|
||||
* The date since which the user has had Discord Premium
|
||||
* @type {?Date}
|
||||
*/
|
||||
this.premiumSince = data.premium_since ? new Date(data.premium_since) : null;
|
||||
|
||||
for (const guild of data.mutual_guilds) {
|
||||
if (this.client.guilds.has(guild.id)) {
|
||||
this.mutualGuilds.set(guild.id, this.client.guilds.get(guild.id));
|
||||
}
|
||||
}
|
||||
for (const connection of data.connected_accounts) {
|
||||
this.connections.set(connection.id, new UserConnection(this.user, connection));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The flags the user has
|
||||
* @type {UserFlags[]}
|
||||
* @readonly
|
||||
*/
|
||||
get flags() {
|
||||
const flags = [];
|
||||
for (const [name, flag] of Object.entries(UserFlags)) {
|
||||
if ((this._flags & flag) === flag) flags.push(name);
|
||||
}
|
||||
return flags;
|
||||
}
|
||||
|
||||
toJSON() {
|
||||
return super.toJSON({ flags: true });
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = UserProfile;
|
||||
@@ -119,23 +119,6 @@ class TextBasedChannel {
|
||||
return Shared.sendMessage(this, options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs a search within the channel.
|
||||
* <warn>This is only available when using a user account.</warn>
|
||||
* @param {MessageSearchOptions} [options={}] Options to pass to the search
|
||||
* @returns {Promise<MessageSearchResult>}
|
||||
* @example
|
||||
* channel.search({ content: 'discord.js', before: '2016-11-17' })
|
||||
* .then(res => {
|
||||
* const hit = res.results[0].find(m => m.hit).content;
|
||||
* console.log(`I found: **${hit}**, total results: ${res.total}`);
|
||||
* })
|
||||
* .catch(console.error);
|
||||
*/
|
||||
search(options = {}) {
|
||||
return Shared.search(this, options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts a typing indicator in the channel.
|
||||
* @param {number} [count=1] The number of times startTyping should be considered to have been called
|
||||
@@ -273,7 +256,6 @@ class TextBasedChannel {
|
||||
|
||||
/**
|
||||
* Bulk deletes given messages that are newer than two weeks.
|
||||
* <warn>This is only available when using a bot account.</warn>
|
||||
* @param {Collection<Snowflake, Message>|Message[]|Snowflake[]|number} messages
|
||||
* Messages or number of messages to delete
|
||||
* @param {boolean} [filterOld=false] Filter messages to remove those which are older than two weeks automatically
|
||||
@@ -316,28 +298,11 @@ class TextBasedChannel {
|
||||
throw new TypeError('MESSAGE_BULK_DELETE_TYPE');
|
||||
}
|
||||
|
||||
/**
|
||||
* Marks all messages in this channel as read.
|
||||
* <warn>This is only available when using a user account.</warn>
|
||||
* @returns {Promise<TextChannel|GroupDMChannel|DMChannel>}
|
||||
*/
|
||||
acknowledge() {
|
||||
if (!this.lastMessageID) return Promise.resolve(this);
|
||||
return this.client.api.channels[this.id].messages[this.lastMessageID].ack
|
||||
.post({ data: { token: this.client.rest._ackToken } })
|
||||
.then(res => {
|
||||
if (res.token) this.client.rest._ackToken = res.token;
|
||||
return this;
|
||||
});
|
||||
}
|
||||
|
||||
static applyToClass(structure, full = false, ignore = []) {
|
||||
const props = ['send'];
|
||||
if (full) {
|
||||
props.push(
|
||||
'acknowledge',
|
||||
'lastMessage',
|
||||
'search',
|
||||
'bulkDelete',
|
||||
'startTyping',
|
||||
'stopTyping',
|
||||
|
||||
@@ -1,100 +0,0 @@
|
||||
const Util = require('../../util/Util');
|
||||
const { TypeError } = require('../../errors');
|
||||
|
||||
/**
|
||||
* @typedef {Object} MessageSearchOptions
|
||||
* @property {string} [content] Message content
|
||||
* @property {Snowflake} [maxID] Maximum ID for the filter
|
||||
* @property {Snowflake} [minID] Minimum ID for the filter
|
||||
* @property {string} [has] One of `link`, `embed`, `file`, `video`, `image`, or `sound`,
|
||||
* or add `-` to negate (e.g. `-file`)
|
||||
* @property {ChannelResolvable} [channel] Channel to limit search to (only for guild search endpoint)
|
||||
* @property {UserResolvable} [author] Author to limit search
|
||||
* @property {string} [authorType] One of `user`, `bot`, `webhook`, or add `-` to negate (e.g. `-webhook`)
|
||||
* @property {string} [sortBy='timestamp'] `timestamp` or `relevant`
|
||||
* @property {string} [sortOrder='descending'] `ascending` or `descending`
|
||||
* @property {number} [contextSize=2] How many messages to get around the matched message (0 to 2)
|
||||
* @property {number} [limit=25] Maximum number of results to get (1 to 25)
|
||||
* @property {number} [offset=0] Offset the "pages" of results (since you can only see 25 at a time)
|
||||
* @property {UserResolvable} [mentions] Mentioned user filter
|
||||
* @property {boolean} [mentionsEveryone] If everyone is mentioned
|
||||
* @property {string} [linkHostname] Filter links by hostname
|
||||
* @property {string} [embedProvider] The name of an embed provider
|
||||
* @property {string} [embedType] one of `image`, `video`, `url`, `rich`, or add `-` to negate (e.g. `-image`)
|
||||
* @property {string} [attachmentFilename] The name of an attachment
|
||||
* @property {string} [attachmentExtension] The extension of an attachment
|
||||
* @property {Date} [before] Date to find messages before
|
||||
* @property {Date} [after] Date to find messages before
|
||||
* @property {Date} [during] Date to find messages during (range of date to date + 24 hours)
|
||||
* @property {boolean} [nsfw=false] Include results from NSFW channels
|
||||
*/
|
||||
|
||||
/**
|
||||
* @typedef {Object} MessageSearchResult
|
||||
* @property {number} total Total result count
|
||||
* @property {Array<Message[]>} results Array of message results
|
||||
* The message which has triggered the result will have the `hit` property set to `true`
|
||||
*/
|
||||
|
||||
module.exports = function search(target, options) {
|
||||
if (typeof options === 'string') options = { content: options };
|
||||
if (options.before) {
|
||||
if (!(options.before instanceof Date)) options.before = new Date(options.before);
|
||||
options.maxID = Util.binaryToID((options.before.getTime() - 14200704e5).toString(2) + '0'.repeat(22));
|
||||
}
|
||||
if (options.after) {
|
||||
if (!(options.after instanceof Date)) options.after = new Date(options.after);
|
||||
options.minID = Util.binaryToID((options.after.getTime() - 14200704e5).toString(2) + '0'.repeat(22));
|
||||
}
|
||||
if (options.during) {
|
||||
if (!(options.during instanceof Date)) options.during = new Date(options.during);
|
||||
const t = options.during.getTime() - 14200704e5;
|
||||
options.minID = Util.binaryToID(t.toString(2) + '0'.repeat(22));
|
||||
options.maxID = Util.binaryToID((t + 864e5).toString(2) + '0'.repeat(22));
|
||||
}
|
||||
if (options.channel) options.channel = target.client.channels.resolveID(options.channel);
|
||||
if (options.author) options.author = target.client.users.resolveID(options.author);
|
||||
if (options.mentions) options.mentions = target.client.users.resolveID(options.options.mentions);
|
||||
if (options.sortOrder) {
|
||||
options.sortOrder = { ascending: 'asc', descending: 'desc' }[options.sortOrder] || options.sortOrder;
|
||||
}
|
||||
options = {
|
||||
content: options.content,
|
||||
max_id: options.maxID,
|
||||
min_id: options.minID,
|
||||
has: options.has,
|
||||
channel_id: options.channel,
|
||||
author_id: options.author,
|
||||
author_type: options.authorType,
|
||||
context_size: options.contextSize,
|
||||
sort_by: options.sortBy,
|
||||
sort_order: options.sortOrder,
|
||||
limit: options.limit,
|
||||
offset: options.offset,
|
||||
mentions: options.mentions,
|
||||
mentions_everyone: options.mentionsEveryone,
|
||||
link_hostname: options.linkHostname,
|
||||
embed_provider: options.embedProvider,
|
||||
embed_type: options.embedType,
|
||||
attachment_filename: options.attachmentFilename,
|
||||
attachment_extension: options.attachmentExtension,
|
||||
include_nsfw: options.nsfw,
|
||||
};
|
||||
|
||||
// Lazy load these because some of them use util
|
||||
const Channel = require('../Channel');
|
||||
const Guild = require('../Guild');
|
||||
|
||||
if (!(target instanceof Channel || target instanceof Guild)) throw new TypeError('SEARCH_CHANNEL_TYPE');
|
||||
|
||||
let endpoint = target.client.api[target instanceof Channel ? 'channels' : 'guilds'](target.id).messages().search;
|
||||
return endpoint.get({ query: options }).then(body => {
|
||||
const results = body.messages.map(x =>
|
||||
x.map(m => target.client.channels.get(m.channel_id).messages.add(m, false))
|
||||
);
|
||||
return {
|
||||
total: body.total_results,
|
||||
results,
|
||||
};
|
||||
});
|
||||
};
|
||||
@@ -1,5 +1,4 @@
|
||||
module.exports = {
|
||||
search: require('./Search'),
|
||||
sendMessage: require('./SendMessage'),
|
||||
createMessage: require('./CreateMessage'),
|
||||
};
|
||||
|
||||
@@ -21,7 +21,6 @@ const browser = exports.browser = typeof window !== 'undefined';
|
||||
* @property {boolean} [fetchAllMembers=false] Whether to cache all guild members and users upon startup, as well as
|
||||
* upon joining a guild (should be avoided whenever possible)
|
||||
* @property {boolean} [disableEveryone=false] Default value for {@link MessageOptions#disableEveryone}
|
||||
* @property {boolean} [sync=false] Whether to periodically sync guilds (for user accounts)
|
||||
* @property {number} [restWsBridgeTimeout=5000] Maximum time permitted between REST responses and their
|
||||
* corresponding websocket events
|
||||
* @property {number} [restTimeOffset=500] Extra time in millseconds to wait before continuing to make REST
|
||||
@@ -46,7 +45,6 @@ exports.DefaultOptions = {
|
||||
messageSweepInterval: 0,
|
||||
fetchAllMembers: false,
|
||||
disableEveryone: false,
|
||||
sync: false,
|
||||
restWsBridgeTimeout: 5000,
|
||||
disabledEvents: [],
|
||||
restTimeOffset: 500,
|
||||
@@ -246,7 +244,6 @@ exports.Events = {
|
||||
USER_UPDATE: 'userUpdate',
|
||||
USER_NOTE_UPDATE: 'userNoteUpdate',
|
||||
USER_SETTINGS_UPDATE: 'clientUserSettingsUpdate',
|
||||
USER_GUILD_SETTINGS_UPDATE: 'clientUserGuildSettingsUpdate',
|
||||
PRESENCE_UPDATE: 'presenceUpdate',
|
||||
VOICE_STATE_UPDATE: 'voiceStateUpdate',
|
||||
VOICE_BROADCAST_SUBSCRIBE: 'subscribe',
|
||||
@@ -264,7 +261,6 @@ exports.Events = {
|
||||
* The type of a websocket message event, e.g. `MESSAGE_CREATE`. Here are the available events:
|
||||
* * READY
|
||||
* * RESUMED
|
||||
* * GUILD_SYNC
|
||||
* * GUILD_CREATE
|
||||
* * GUILD_DELETE
|
||||
* * GUILD_UPDATE
|
||||
@@ -302,7 +298,6 @@ exports.Events = {
|
||||
exports.WSEvents = keyMirror([
|
||||
'READY',
|
||||
'RESUMED',
|
||||
'GUILD_SYNC',
|
||||
'GUILD_CREATE',
|
||||
'GUILD_DELETE',
|
||||
'GUILD_UPDATE',
|
||||
@@ -328,15 +323,10 @@ exports.WSEvents = keyMirror([
|
||||
'MESSAGE_REACTION_REMOVE',
|
||||
'MESSAGE_REACTION_REMOVE_ALL',
|
||||
'USER_UPDATE',
|
||||
'USER_NOTE_UPDATE',
|
||||
'USER_SETTINGS_UPDATE',
|
||||
'USER_GUILD_SETTINGS_UPDATE',
|
||||
'PRESENCE_UPDATE',
|
||||
'VOICE_STATE_UPDATE',
|
||||
'TYPING_START',
|
||||
'VOICE_SERVER_UPDATE',
|
||||
'RELATIONSHIP_ADD',
|
||||
'RELATIONSHIP_REMOVE',
|
||||
]);
|
||||
|
||||
/**
|
||||
@@ -392,13 +382,6 @@ exports.ExplicitContentFilterTypes = [
|
||||
'FRIENDS_AND_NON_FRIENDS',
|
||||
];
|
||||
|
||||
exports.MessageNotificationTypes = [
|
||||
'EVERYTHING',
|
||||
'MENTIONS',
|
||||
'NOTHING',
|
||||
'INHERIT',
|
||||
];
|
||||
|
||||
exports.UserSettingsMap = {
|
||||
/**
|
||||
* Automatically convert emoticons in your messages to emoji,
|
||||
@@ -532,60 +515,6 @@ exports.UserSettingsMap = {
|
||||
},
|
||||
};
|
||||
|
||||
exports.UserGuildSettingsMap = {
|
||||
message_notifications: function messageNotifications(type) { // eslint-disable-line func-name-matching
|
||||
/**
|
||||
* The type of message that should notify you.
|
||||
* One of `EVERYTHING`, `MENTIONS`, `NOTHING`
|
||||
* @name ClientUserGuildSettings#messageNotifications
|
||||
* @type {string}
|
||||
*/
|
||||
return exports.MessageNotificationTypes[type];
|
||||
},
|
||||
/**
|
||||
* Whether to receive mobile push notifications
|
||||
* @name ClientUserGuildSettings#mobilePush
|
||||
* @type {boolean}
|
||||
*/
|
||||
mobile_push: 'mobilePush',
|
||||
/**
|
||||
* Whether the guild is muted or not
|
||||
* @name ClientUserGuildSettings#muted
|
||||
* @type {boolean}
|
||||
*/
|
||||
muted: 'muted',
|
||||
/**
|
||||
* Whether to suppress everyone messages
|
||||
* @name ClientUserGuildSettings#suppressEveryone
|
||||
* @type {boolean}
|
||||
*/
|
||||
suppress_everyone: 'suppressEveryone',
|
||||
/**
|
||||
* A collection containing all the channel overrides
|
||||
* @name ClientUserGuildSettings#channelOverrides
|
||||
* @type {Collection<ClientUserChannelOverride>}
|
||||
*/
|
||||
channel_overrides: 'channelOverrides',
|
||||
};
|
||||
|
||||
exports.UserChannelOverrideMap = {
|
||||
message_notifications: function messageNotifications(type) { // eslint-disable-line func-name-matching
|
||||
/**
|
||||
* The type of message that should notify you.
|
||||
* One of `EVERYTHING`, `MENTIONS`, `NOTHING`, `INHERIT`
|
||||
* @name ClientUserChannelOverride#messageNotifications
|
||||
* @type {string}
|
||||
*/
|
||||
return exports.MessageNotificationTypes[type];
|
||||
},
|
||||
/**
|
||||
* Whether the channel is muted or not
|
||||
* @name ClientUserChannelOverride#muted
|
||||
* @type {boolean}
|
||||
*/
|
||||
muted: 'muted',
|
||||
};
|
||||
|
||||
/**
|
||||
* All flags users can have:
|
||||
* * STAFF
|
||||
|
||||
Reference in New Issue
Block a user