Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor: switch api and gateway to V8 #4879

Merged
merged 46 commits into from
Feb 11, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
46 commits
Select commit Hold shift + click to select a range
78e0776
feat: bigint compatibility for Permissions
NotSugden Oct 2, 2020
77413d7
fix: convert permissions to strings
NotSugden Oct 2, 2020
0fd08a5
refactor: serialize permissions
NotSugden Oct 2, 2020
8e769b4
docs: fix ci error
NotSugden Oct 2, 2020
3fff5fd
docs: stupid CI
NotSugden Oct 2, 2020
abdac04
fix: use default assignment
NotSugden Oct 2, 2020
97dcbc3
refactor(Guild): remove embed methods in favour of widget
NotSugden Oct 2, 2020
613d610
refactor: refactor presence changing for V8
NotSugden Oct 2, 2020
600f21e
feat: document ClientUser#edit
NotSugden Oct 2, 2020
3196853
refactor: use overwrite type number
NotSugden Oct 3, 2020
d41a4af
refactor: no longer emit channelCreate or channelDelete on DMChannels
NotSugden Oct 3, 2020
0cf3ef6
feat: document error codes
NotSugden Oct 3, 2020
4a4dfbf
fix: correctly parse presence
NotSugden Oct 3, 2020
66a398b
fix: dm channels emit delete
NotSugden Oct 3, 2020
bc051f8
chore: fix test
NotSugden Oct 3, 2020
75b2e3d
test: update tests
NotSugden Oct 3, 2020
71114f1
refactor: bigint literals can be used in some places
NotSugden Oct 3, 2020
e9fe747
refactor: bigint literals can be used in some places
NotSugden Oct 3, 2020
31cc44c
refactor: suggested changes
NotSugden Oct 3, 2020
fdc667d
refactor: default non-privileged intents
NotSugden Oct 3, 2020
120be29
fix: typo
NotSugden Oct 3, 2020
b2fe85a
fix: use enum correctly
NotSugden Oct 3, 2020
62f6fae
refactor: intents should be mandatory
NotSugden Oct 11, 2020
90b421c
refactor: use toJSON for permissions
NotSugden Oct 15, 2020
66d51dd
refactor: suggested changes
NotSugden Oct 15, 2020
fa6e941
refactor: remove integration fetch options
NotSugden Nov 14, 2020
4988667
docs(ClientUser): fix typo
NotSugden Oct 16, 2020
03aca36
fix(PermissionOverwrites): use toString instead of toJSON
NotSugden Nov 14, 2020
5738aef
fix(RequestHandler): retryAfter is in seconds
NotSugden Dec 10, 2020
4a5d1ec
fix(Permissions): don't instantly convert to BigInt
NotSugden Dec 14, 2020
99f3030
refactor: suggested changes
NotSugden Dec 15, 2020
603e02d
refactor: seperate type for WebhookClientOptions
NotSugden Dec 15, 2020
09a4dec
fix: im an idiot
NotSugden Dec 15, 2020
7c82808
fix: use correct type
NotSugden Dec 15, 2020
5fc9ed2
fix: use correct permissions type
NotSugden Dec 15, 2020
8b62bd5
typings/fix: use bigint instead of number
NotSugden Dec 16, 2020
2467bd4
feat: validate that intents are passed
NotSugden Dec 27, 2020
61c999a
style: use semi rather than comma
NotSugden Dec 27, 2020
58b86e0
fix: correctly add intents to identify options
NotSugden Jan 4, 2021
83c0e26
fix: use `bigint` over `number`
NotSugden Jan 4, 2021
843deb9
fix: cache dm channel
NotSugden Jan 22, 2021
f58056c
fix: dm channels emit delete
NotSugden Jan 22, 2021
a8ec046
refactor: change default bit to static declaration
NotSugden Jan 28, 2021
82fee0d
refactor: suggested changes
NotSugden Jan 28, 2021
7b4c9ad
refactor: suggested changes
NotSugden Jan 28, 2021
08c04a1
fix: don't use bigint literal
NotSugden Jan 31, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 6 additions & 4 deletions src/client/Client.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,9 @@ const Structures = require('../util/Structures');
*/
class Client extends BaseClient {
/**
* @param {ClientOptions} [options] Options for the client
* @param {ClientOptions} options Options for the client
*/
constructor(options = {}) {
constructor(options) {
super(Object.assign({ _tokenType: 'Bot' }, options));

// Obtain shard details from environment or if present, worker threads
Expand Down Expand Up @@ -444,8 +444,10 @@ class Client extends BaseClient {
* @private
*/
_validateOptions(options = this.options) {
if (typeof options.ws.intents !== 'undefined') {
options.ws.intents = Intents.resolve(options.ws.intents);
if (typeof options.intents === 'undefined') {
throw new TypeError('CLIENT_MISSING_INTENTS');
NotSugden marked this conversation as resolved.
Show resolved Hide resolved
} else {
options.intents = Intents.resolve(options.intents);
}
if (typeof options.shardCount !== 'number' || isNaN(options.shardCount) || options.shardCount < 1) {
throw new TypeError('CLIENT_INVALID_OPTION', 'shardCount', 'a number greater than or equal to 1');
Expand Down
4 changes: 2 additions & 2 deletions src/client/actions/ChannelCreate.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,9 @@ class ChannelCreateAction extends Action {
const channel = client.channels.add(data);
if (!existing && channel) {
/**
* Emitted whenever a channel is created.
* Emitted whenever a guild channel is created.
* @event Client#channelCreate
* @param {DMChannel|GuildChannel} channel The channel that was created
* @param {GuildChannel} channel The channel that was created
*/
client.emit(Events.CHANNEL_CREATE, channel);
}
Expand Down
2 changes: 1 addition & 1 deletion src/client/actions/MessageCreate.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ const { Events } = require('../../util/Constants');
class MessageCreateAction extends Action {
handle(data) {
const client = this.client;
const channel = client.channels.cache.get(data.channel_id);
const channel = this.getChannel(data);
NotSugden marked this conversation as resolved.
Show resolved Hide resolved
if (channel) {
const existing = channel.messages.cache.get(data.id);
if (existing) return { message: existing };
Expand Down
1 change: 0 additions & 1 deletion src/client/actions/PresenceUpdate.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ class PresenceUpdateAction extends Action {
if (!member && data.status !== 'offline') {
member = guild.members.add({
user,
roles: data.roles,
deaf: false,
mute: false,
});
Expand Down
2 changes: 2 additions & 0 deletions src/client/websocket/WebSocketShard.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
const EventEmitter = require('events');
const WebSocket = require('../../WebSocket');
const { Status, Events, ShardEvents, OPCodes, WSEvents } = require('../../util/Constants');
const Intents = require('../../util/Intents');

const STATUS_KEYS = Object.keys(Status);
const CONNECTION_STATE = Object.keys(WebSocket.WebSocket);
Expand Down Expand Up @@ -594,6 +595,7 @@ class WebSocketShard extends EventEmitter {
// Clone the identify payload and assign the token and shard info
const d = {
...client.options.ws,
intents: Intents.resolve(client.options.intents),
token: client.token,
shard: [this.id, Number(client.options.shardCount)],
};
Expand Down
1 change: 1 addition & 0 deletions src/errors/Messages.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ const { register } = require('./DJSError');
const Messages = {
CLIENT_INVALID_OPTION: (prop, must) => `The ${prop} option must be ${must}`,
CLIENT_INVALID_PROVIDED_SHARDS: 'None of the provided shards were valid.',
CLIENT_MISSING_INTENTS: 'Valid intents must be provided for the Client.',

TOKEN_INVALID: 'An invalid token was provided.',
TOKEN_MISSING: 'Request to use token, but token was unavailable to the client.',
Expand Down
2 changes: 1 addition & 1 deletion src/managers/GuildManager.js
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ class GuildManager extends BaseManager {
* @property {ColorResolvable} [color] The color of the role, either a hex string or a base 10 number
* @property {boolean} [hoist] Whether or not the role should be hoisted
* @property {number} [position] The position of the role
* @property {PermissionResolvable|number} [permissions] The permissions of the role
* @property {PermissionResolvable} [permissions] The permissions of the role
* @property {boolean} [mentionable] Whether or not the role should be mentionable
*/

Expand Down
2 changes: 1 addition & 1 deletion src/managers/RoleManager.js
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ class RoleManager extends BaseManager {
create(options = {}) {
let { name, color, hoist, permissions, position, mentionable, reason } = options;
if (color) color = resolveColor(color);
if (permissions) permissions = Permissions.resolve(permissions);
if (permissions) permissions = Permissions.resolve(permissions).toString();

return this.client.api
.guilds(this.guild.id)
Expand Down
2 changes: 1 addition & 1 deletion src/rest/RequestHandler.js
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ class RequestHandler {
this.limit = limit ? Number(limit) : Infinity;
this.remaining = remaining ? Number(remaining) : 1;
this.reset = reset ? calculateReset(reset, serverDate) : Date.now();
this.retryAfter = retryAfter ? Number(retryAfter) : -1;
this.retryAfter = retryAfter ? Number(retryAfter) * 1000 : -1;

// https://github.com/discordapp/discord-api-docs/issues/182
if (request.route.includes('reactions')) {
Expand Down
74 changes: 24 additions & 50 deletions src/structures/ClientPresence.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

const { Presence } = require('./Presence');
const { TypeError } = require('../errors');
const Collection = require('../util/Collection');
const { ActivityTypes, OPCodes } = require('../util/Constants');

class ClientPresence extends Presence {
Expand All @@ -14,8 +13,8 @@ class ClientPresence extends Presence {
super(client, Object.assign(data, { status: data.status || 'online', user: { id: null } }));
}

async set(presence) {
const packet = await this._parse(presence);
set(presence) {
const packet = this._parse(presence);
this.patch(packet);
if (typeof presence.shardID === 'undefined') {
this.client.ws.broadcast({ op: OPCodes.STATUS_UPDATE, d: packet });
Expand All @@ -29,58 +28,33 @@ class ClientPresence extends Presence {
return this;
}

async _parse({ status, since, afk, activity }) {
const applicationID = activity && (activity.application ? activity.application.id || activity.application : null);
let assets = new Collection();
if (activity) {
if (typeof activity.name !== 'string') throw new TypeError('INVALID_TYPE', 'name', 'string');
if (!activity.type) activity.type = 0;
if (activity.assets && applicationID) {
try {
const a = await this.client.api.oauth2.applications(applicationID).assets.get();
for (const asset of a) assets.set(asset.name, asset.id);
} catch {} // eslint-disable-line no-empty
}
}

const packet = {
afk: afk != null ? afk : false, // eslint-disable-line eqeqeq
since: since != null ? since : null, // eslint-disable-line eqeqeq
_parse({ status, since, afk, activities }) {
const data = {
activities: [],
afk: typeof afk === 'boolean' ? afk : false,
since: typeof since === 'number' && !Number.isNaN(since) ? since : null,
status: status || this.status,
game: activity
? {
type: activity.type,
name: activity.name,
url: activity.url,
details: activity.details || undefined,
state: activity.state || undefined,
assets: activity.assets
? {
large_text: activity.assets.largeText || undefined,
small_text: activity.assets.smallText || undefined,
large_image: assets.get(activity.assets.largeImage) || activity.assets.largeImage,
small_image: assets.get(activity.assets.smallImage) || activity.assets.smallImage,
}
: undefined,
timestamps: activity.timestamps || undefined,
party: activity.party || undefined,
application_id: applicationID || undefined,
secrets: activity.secrets || undefined,
instance: activity.instance || undefined,
}
: null,
};

if ((status || afk || since) && !activity) {
packet.game = this.activities[0] || null;
if (activities === null) {
data.activities = null;
return data;
}

if (packet.game) {
packet.game.type =
typeof packet.game.type === 'number' ? packet.game.type : ActivityTypes.indexOf(packet.game.type);
if (activities && activities.length) {
for (const [i, activity] of activities.entries()) {
if (typeof activity.name !== 'string') throw new TypeError('INVALID_TYPE', `activities[${i}].name`, 'string');
if (!activity.type) activity.type = 0;

data.activities.push({
type: typeof activity.type === 'number' ? activity.type : ActivityTypes.indexOf(activity.type),
name: activity.name,
url: activity.url,
});
}
} else if ((status || afk || since) && this.activities.length) {
data.activities.push(...this.activities);
}

return packet;
return data;
}
}

Expand Down
41 changes: 22 additions & 19 deletions src/structures/ClientUser.js
Original file line number Diff line number Diff line change
Expand Up @@ -46,16 +46,18 @@ class ClientUser extends Structures.get('User') {
return this.client.presence;
}

edit(data) {
return this.client.api
.users('@me')
.patch({ data })
.then(newData => {
this.client.token = newData.token;
const { updated } = this.client.actions.UserUpdate.handle(newData);
if (updated) return updated;
return this;
});
/**
* Edits the logged in client.
* @param {Object} data The new data
* @param {string} [data.username] The new username
* @param {BufferResolvable|Base64Resolvable} [data.avatar] The new avatar
*/
async edit(data) {
const newData = await this.client.api.users('@me').patch({ data });
NotSugden marked this conversation as resolved.
Show resolved Hide resolved
this.client.token = newData.token;
const { updated } = this.client.actions.UserUpdate.handle(newData);
if (updated) return updated;
return this;
}

/**
Expand Down Expand Up @@ -103,7 +105,7 @@ class ClientUser extends Structures.get('User') {
/**
* Sets the full presence of the client user.
* @param {PresenceData} data Data for the presence
* @returns {Promise<Presence>}
* @returns {Presence}
* @example
* // Set the client user's presence
* client.user.setPresence({ activity: { name: 'with discord.js' }, status: 'idle' })
Expand All @@ -127,7 +129,7 @@ class ClientUser extends Structures.get('User') {
* Sets the status of the client user.
* @param {PresenceStatusData} status Status to change to
* @param {?number|number[]} [shardID] Shard ID(s) to have the activity set on
* @returns {Promise<Presence>}
* @returns {Presence}
* @example
* // Set the client user's status
* client.user.setStatus('idle')
Expand All @@ -144,34 +146,35 @@ class ClientUser extends Structures.get('User') {
* @type {Object}
* @property {string} [url] Twitch / YouTube stream URL
* @property {ActivityType|number} [type] Type of the activity
* @property {?number|number[]} [shardID] Shard Id(s) to have the activity set on
* @property {number|number[]} [shardID] Shard Id(s) to have the activity set on
*/

/**
* Sets the activity the client user is playing.
* @param {string|ActivityOptions} [name] Activity being played, or options for setting the activity
* @param {ActivityOptions} [options] Options for setting the activity
* @returns {Promise<Presence>}
* @returns {Presence}
* @example
* // Set the client user's activity
* client.user.setActivity('discord.js', { type: 'WATCHING' })
* .then(presence => console.log(`Activity set to ${presence.activities[0].name}`))
* .catch(console.error);
*/
setActivity(name, options = {}) {
if (!name) return this.setPresence({ activity: null, shardID: options.shardID });
if (!name) return this.setPresence({ activities: null, shardID: options.shardID });

const activity = Object.assign({}, options, typeof name === 'object' ? name : { name });
return this.setPresence({ activity, shardID: activity.shardID });
return this.setPresence({ activities: [activity], shardID: activity.shardID });
}

/**
* Sets/removes the AFK flag for the client user.
* @param {boolean} afk Whether or not the user is AFK
* @returns {Promise<Presence>}
* @param {number|number[]} [shardID] Shard Id(s) to have the AFK flag set on
* @returns {Presence}
*/
setAFK(afk) {
return this.setPresence({ afk });
setAFK(afk, shardID) {
return this.setPresence({ afk, shardID });
}
}

Expand Down
Loading