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

eriss #17

Closed
wants to merge 39 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
39 commits
Select commit Hold shift + click to select a range
6ba5b05
fix(threads): nullable m.presence in THREAD_MEMBERS_UPDATE (#1306)
ZixeSea Feb 10, 2022
4c631f5
fix(typings): extra messageID param in Message#createThreadWithMessag…
frobinsonj Feb 10, 2022
6619b17
fix(Member): User property reference (#1313)
Feb 10, 2022
1a79ef6
fix(threads): pass guild when updating member on THREAD_MEMBERS_UPDAT…
GweeKwee Feb 10, 2022
4ca306d
fix(threads): Snake case discord payload owner id (#1326)
dd-pardal Feb 10, 2022
c6b380b
fix(interactions): static function client reference (#1334)
doomestee Feb 10, 2022
f4db90e
fix(docs): editStatus url type (#1337)
DonovanDMC Feb 10, 2022
98c5c8b
fix(typings): static keyword for Interaction.from (#1305)
bsian03 Feb 11, 2022
9a55be5
Fix missing file redirect in interaction createMessage (#1314)
bsian03 Feb 11, 2022
90fad3a
fix(interactions): Snake case defaultPermissions in payload (#1325)
bsian03 Feb 11, 2022
bb8a45e
Add position to `CreateChannelOptions` (#1340)
frobinsonj Mar 9, 2022
c1f1f86
Use maxShards instead of lastShardID (#1339)
GweeKwee Mar 9, 2022
072db2e
presence update ratelimit (#1345)
Awoocado Mar 9, 2022
52db153
fix(voice): avoid bitwise overflow error (#1323)
james58899 Mar 27, 2022
44dba49
chore(typings): reorganise (#1303)
bsian03 Apr 12, 2022
cb8971a
fix(typings): presence offline/invisible indicators
reinacchi Apr 13, 2022
a9b8ad4
fix(gateway): remove message listener on disconnect (#1364)
davidffa Apr 19, 2022
42e713b
fix(typings): Added "proxy_url" to EmbedVideo (#1361)
ray-1337 Apr 19, 2022
f163a56
fix(typings): Outdated channelCreate event typings (#1351)
May 10, 2022
b485352
fix(constants): Include manageThreads, manageEvents in Permissions.al…
eritbh May 10, 2022
c223725
fix(userUpdate): Uncached users throwing undefined (#1366)
Dramex May 10, 2022
017c18a
fix(deleteMessages): Pass reason param into subsequent calls (#1373)
DonovanDMC May 10, 2022
b7a1189
docs(Voice state): Update to new caveat URL (#1375)
frobinsonj May 15, 2022
2f7526a
fix(Message): Jumplink throwing on DM messages (#1359)
bsian03 May 27, 2022
e963166
feat(Permissions): Add bigint support for perm check (#1374)
bsian03 May 27, 2022
65b1850
fix(Member): Parse Member#premiumSince to timestamp (#1318)
bsian03 May 27, 2022
d6df49a
feat: Text-in-Voice (#1298)
beanjo55 Jun 1, 2022
2712a85
fix(rl): shared rl and retryAfter behaviour, header getter on httperr…
curtisf Jun 1, 2022
36e7a76
feat(ShardManager): concurrency support (#1370)
HcgRandon Jun 2, 2022
d6b6aa8
0.17.0
abalabahaha Jun 3, 2022
172a0a2
chore: bump dev version to 0.17.1-dev
abalabahaha Jun 3, 2022
a9ad12f
fix(voice): re-add receive listener on connect (#1332)
jimchen5209 Jun 5, 2022
f7a8e50
fix(getAllUsers): request presences if intent is enabled (#1378)
A5rocks Jun 5, 2022
d0099b1
chore(Base): document props, static methods (#1380)
eritbh Jun 5, 2022
b8dcd62
fix(Guild#editCommandPermissions): fix alias typo (#1350)
Chris8889 Mar 13, 2022
e888253
fix(getGuildAuditLog): cache users & threads earlier (#1367)
DonovanDMC Jun 5, 2022
a2e3a00
fix(messageUpdate): fix oldMessage#mentions type (#1377)
DonovanDMC Jun 5, 2022
162d4ef
fix(joinVoiceChannel): skip permission check if Member uncached (#1383)
abalabahaha Jun 5, 2022
05a932a
fix(ShardManager): refactor concurrency check, add option (#1382)
abalabahaha Jun 5, 2022
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
1 change: 1 addition & 0 deletions esm.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ export const {
StageInstance,
StoreChannel,
TextChannel,
TextVoiceChannel,
ThreadChannel,
ThreadMember,
UnavailableGuild,
Expand Down
26 changes: 26 additions & 0 deletions examples/sharding.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
const Eris = require("eris");

// Replace TOKEN with your bot account's token
const bot = new Eris("Bot TOKEN", {
firstShardID: 0,
lastShardID: 15,
maxShards: 16,
getAllUsers: false,
intents: ["guilds", "guildMembers", "guildPresences"]
});

bot.on("ready", () => { // When the bot is ready
console.log("Ready!"); // Log "Ready!"
console.timeEnd("ready");
});

bot.on("error", (err) => {
console.error(err); // or your preferred logger
});

bot.on("shardReady", (id) => {
console.log(`Shard ${id} ready!`);
});

console.time("ready");
bot.connect(); // Get the bot to connect to Discord
519 changes: 279 additions & 240 deletions index.d.ts

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ Eris.StageChannel = require("./lib/structures/StageChannel");
Eris.StageInstance = require("./lib/structures/StageInstance");
Eris.StoreChannel = require("./lib/structures/StoreChannel");
Eris.TextChannel = require("./lib/structures/TextChannel");
Eris.TextVoiceChannel = require("./lib/structures/TextVoiceChannel");
Eris.ThreadChannel = require("./lib/structures/ThreadChannel");
Eris.ThreadMember = require("./lib/structures/ThreadMember");
Eris.UnavailableGuild = require("./lib/structures/UnavailableGuild");
Expand Down
52 changes: 36 additions & 16 deletions lib/Client.js
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,7 @@ class Client extends EventEmitter {
* @arg {Number} [options.rest.requestTimeout=15000] A number of milliseconds before REST requests are considered timed out
* @arg {Boolean} [options.restMode=false] Whether to enable getting objects over REST. Even with this option enabled, it is recommended that you check the cache first before using REST
* @arg {Boolean} [options.seedVoiceConnections=false] Whether to populate bot.voiceConnections with existing connections the bot account has during startup. Note that this will disconnect connections from other bot sessions
* @arg {Number | String} [options.shardConcurrency="auto"] The number of shards that can start simultaneously. If "auto" Eris will use Discord's recommended shard concurrency.
* @arg {Object} [options.ws] An object of WebSocket options to pass to the shard WebSocket constructors
*/
constructor(token, options) {
Expand Down Expand Up @@ -149,6 +150,7 @@ class Client extends EventEmitter {
rest: {},
restMode: false,
seedVoiceConnections: false,
shardConcurrency: "auto",
ws: {},
reconnectDelay: (lastDelay, attempts) => Math.pow(attempts + 1, 0.7) * 20000
}, options);
Expand Down Expand Up @@ -202,13 +204,18 @@ class Client extends EventEmitter {
this.requestHandler = new RequestHandler(this, this.options.rest);
delete this.options.rest;

const shardManagerOptions = {};
if(typeof this.options.shardConcurrency === "number") {
shardManagerOptions.concurrency = this.options.shardConcurrency;
}
this.shards = new ShardManager(this, shardManagerOptions);

this.ready = false;
this.bot = this._token.startsWith("Bot ");
this.startTime = 0;
this.lastConnect = 0;
this.channelGuildMap = {};
this.threadGuildMap = {};
this.shards = new ShardManager(this);
this.groupChannels = new Collection(GroupChannel);
this.guilds = new Collection(Guild);
this.privateChannelMap = {};
Expand Down Expand Up @@ -413,12 +420,12 @@ class Client extends EventEmitter {
}

/**
* Tells all shards to connect.
* Tells all shards to connect. This will call `getBotGateway()`, which is ratelimited.
* @returns {Promise} Resolves when all shards are initialized
*/
async connect() {
try {
const data = await (this.options.maxShards === "auto" ? this.getBotGateway() : this.getGateway());
const data = await (this.options.maxShards === "auto" || (this.options.shardConcurrency === "auto" && this.bot) ? this.getBotGateway() : this.getGateway());
if(!data.url || (this.options.maxShards === "auto" && !data.shards)) {
throw new Error("Invalid response from gateway REST call");
}
Expand All @@ -444,6 +451,10 @@ class Client extends EventEmitter {
}
}

if(this.options.shardConcurrency === "auto" && typeof data.session_start_limit?.max_concurrency === "number") {
this.shards.setConcurrency(data.session_start_limit.max_concurrency);
}

for(let i = this.options.firstShardID; i <= this.options.lastShardID; ++i) {
this.shards.spawn(i);
}
Expand All @@ -469,11 +480,12 @@ class Client extends EventEmitter {
* @arg {Boolean} [options.nsfw] The nsfw status of the channel
* @arg {String?} [options.parentID] The ID of the parent category channel for this channel
* @arg {Array} [options.permissionOverwrites] An array containing permission overwrite objects
* @arg {Number} [options.position] The sorting position of the channel
* @arg {Number} [options.rateLimitPerUser] The time in seconds a user has to wait before sending another message (does not affect bots or users with manageMessages/manageChannel permissions) (text channels only)
* @arg {String} [options.reason] The reason to be displayed in audit logs
* @arg {String} [options.topic] The topic of the channel (text channels only)
* @arg {Number} [options.userLimit] The channel user limit (voice channels only)
* @returns {Promise<CategoryChannel | TextChannel | VoiceChannel>}
* @returns {Promise<CategoryChannel | TextChannel | TextVoiceChannel>}
*/
createChannel(guildID, name, type, reason, options = {}) {
if(typeof options === "string") { // This used to be parentID, back-compat
Expand All @@ -497,6 +509,7 @@ class Client extends EventEmitter {
nsfw: options.nsfw,
parent_id: options.parentID,
permission_overwrites: options.permissionOverwrites,
position: options.position,
rate_limit_per_user: options.rateLimitPerUser,
reason: options.reason,
topic: options.topic,
Expand Down Expand Up @@ -564,6 +577,7 @@ class Client extends EventEmitter {
}
}
}
command.default_permission = command.defaultPermission;
return this.requestHandler.request("POST", Endpoints.COMMANDS(this.application.id), true, command);
}

Expand Down Expand Up @@ -633,6 +647,7 @@ class Client extends EventEmitter {
}
}
}
command.default_permission = command.defaultPermission;
return this.requestHandler.request("POST", Endpoints.GUILD_COMMANDS(this.application.id, guildID), true, command);
}

Expand Down Expand Up @@ -1089,7 +1104,7 @@ class Client extends EventEmitter {
return Promise.resolve();
}
if(messageIDs.length === 1) {
return this.deleteMessage(channelID, messageIDs[0]);
return this.deleteMessage(channelID, messageIDs[0], reason);
}

const oldestAllowedSnowflake = (Date.now() - 1421280000000) * 4194304;
Expand All @@ -1102,7 +1117,7 @@ class Client extends EventEmitter {
return this.requestHandler.request("POST", Endpoints.CHANNEL_BULK_DELETE(channelID), true, {
messages: messageIDs.splice(0, 100),
reason: reason
}).then(() => this.deleteMessages(channelID, messageIDs));
}).then(() => this.deleteMessages(channelID, messageIDs, reason));
}
return this.requestHandler.request("POST", Endpoints.CHANNEL_BULK_DELETE(channelID), true, {
messages: messageIDs,
Expand Down Expand Up @@ -1237,13 +1252,14 @@ class Client extends EventEmitter {
* @arg {Boolean} [options.nsfw] The nsfw status of the channel (guild channels only)
* @arg {String} [options.ownerID] The ID of the channel owner (group channels only)
* @arg {String?} [options.parentID] The ID of the parent channel category for this channel (guild text/voice channels only)
* @arg {Number} [options.position] The sorting position of the channel (guild channels only)
* @arg {Number} [options.rateLimitPerUser] The time in seconds a user has to wait before sending another message (does not affect bots or users with manageMessages/manageChannel permissions) (guild text and thread channels only)
* @arg {String?} [options.rtcRegion] The RTC region ID of the channel (automatic if `null`) (guild voice channels only)
* @arg {String} [options.topic] The topic of the channel (guild text channels only)
* @arg {Number} [options.userLimit] The channel user limit (guild voice channels only)
* @arg {Number} [options.videoQualityMode] The camera video quality mode of the channel (guild voice channels only). `1` is auto, `2` is 720p
* @arg {String} [reason] The reason to be displayed in audit logs
* @returns {Promise<CategoryChannel | GroupChannel | TextChannel | VoiceChannel | NewsChannel | NewsThreadChannel | PrivateThreadChannel | PublicThreadChannel>}
* @returns {Promise<CategoryChannel | GroupChannel | TextChannel | TextVoiceChannel | NewsChannel | NewsThreadChannel | PrivateThreadChannel | PublicThreadChannel>}
*/
editChannel(channelID, options, reason) {
return this.requestHandler.request("PATCH", Endpoints.CHANNEL(channelID), true, {
Expand All @@ -1258,6 +1274,7 @@ class Client extends EventEmitter {
nsfw: options.nsfw,
owner_id: options.ownerID,
parent_id: options.parentID,
position: options.position,
rate_limit_per_user: options.rateLimitPerUser,
rtc_region: options.rtcRegion,
topic: options.topic,
Expand Down Expand Up @@ -1350,6 +1367,7 @@ class Client extends EventEmitter {
}
}
}
command.default_permission = command.defaultPermission;
return this.requestHandler.request("PATCH", Endpoints.COMMAND(this.application.id, commandID), true, command);
}

Expand Down Expand Up @@ -1442,6 +1460,7 @@ class Client extends EventEmitter {
}
}
}
command.default_permission = command.defaultPermission;
return this.requestHandler.request("PATCH", Endpoints.GUILD_COMMAND(this.application.id, guildID, commandID), true, command);
}

Expand Down Expand Up @@ -1563,7 +1582,7 @@ class Client extends EventEmitter {
});
}
/**
* Update a user's voice state - See [caveats](https://discord.com/developers/docs/resources/guild#update-others-voice-state-caveats)
* Update a user's voice state - See [caveats](https://discord.com/developers/docs/resources/guild#modify-user-voice-state-caveats)
* @arg {String} guildID The ID of the guild
* @arg {Object} options The properties to edit
* @arg {String} options.channelID The ID of the channel the user is currently in
Expand Down Expand Up @@ -1848,8 +1867,7 @@ class Client extends EventEmitter {
* @arg {Array | Object} [activities] Sets the bot's activities. A single activity object is also accepted for backwards compatibility
* @arg {String} activities[].name The name of the activity
* @arg {Number} activities[].type The type of the activity. 0 is playing, 1 is streaming (Twitch only), 2 is listening, 3 is watching, 5 is competing in
* @arg {Number} [activities[].url] The URL of the activity
* @arg {String} [game.url] Sets the url of the shard's active game
* @arg {String} [activities[].url] The URL of the activity
*/
editStatus(status, activities) {
if(activities === undefined && typeof status === "object") {
Expand Down Expand Up @@ -2140,7 +2158,7 @@ class Client extends EventEmitter {
/**
* Get a Channel object from a channel ID
* @arg {String} channelID The ID of the channel
* @returns {CategoryChannel | GroupChannel | PrivateChannel | TextChannel | VoiceChannel | NewsChannel | NewsThreadChannel | PrivateThreadChannel | PublicThreadChannel}
* @returns {CategoryChannel | GroupChannel | PrivateChannel | TextChannel | TextVoiceChannel | NewsChannel | NewsThreadChannel | PrivateThreadChannel | PublicThreadChannel}
*/
getChannel(channelID) {
if(!channelID) {
Expand Down Expand Up @@ -2286,11 +2304,13 @@ class Client extends EventEmitter {
}
return this.requestHandler.request("GET", Endpoints.GUILD_AUDIT_LOGS(guildID), true, options).then((data) => {
const guild = this.guilds.get(guildID);
const users = data.users.map((user) => this.users.add(user, this));
const threads = data.threads.map((thread) => guild.threads.update(thread, this));
return {
entries: data.audit_log_entries.map((entry) => new GuildAuditLogEntry(entry, guild)),
integrations: data.integrations.map((integration) => new GuildIntegration(integration, guild)),
threads: data.threads.map((thread) => guild.threads.update(thread, this)),
users: data.users.map((user) => this.users.add(user, this)),
threads: threads,
users: users,
webhooks: data.webhooks
};
});
Expand Down Expand Up @@ -2654,7 +2674,7 @@ class Client extends EventEmitter {
/**
* Get a channel's data via the REST API. REST mode is required to use this endpoint.
* @arg {String} channelID The ID of the channel
* @returns {Promise<CategoryChannel | GroupChannel | PrivateChannel | TextChannel | VoiceChannel | NewsChannel | NewsThreadChannel | PrivateThreadChannel | PublicThreadChannel>}
* @returns {Promise<CategoryChannel | GroupChannel | PrivateChannel | TextChannel | TextVoiceChannel | NewsChannel | NewsThreadChannel | PrivateThreadChannel | PublicThreadChannel>}
*/
getRESTChannel(channelID) {
if(!this.options.restMode) {
Expand Down Expand Up @@ -2682,7 +2702,7 @@ class Client extends EventEmitter {
/**
* Get a guild's channels via the REST API. REST mode is required to use this endpoint.
* @arg {String} guildID The ID of the guild
* @returns {Promise<Array<CategoryChannel> | Array<TextChannel> | Array<VoiceChannel> | Array<NewsChannel>>}
* @returns {Promise<Array<CategoryChannel> | Array<TextChannel> | Array<TextVoiceChannel> | Array<NewsChannel>>}
*/
getRESTGuildChannels(guildID) {
if(!this.options.restMode) {
Expand Down Expand Up @@ -2979,7 +2999,7 @@ class Client extends EventEmitter {
if(!channel) {
return Promise.reject(new Error("Channel not found"));
}
if(channel.guild && !(channel.permissionsOf(this.user.id).allow & Constants.Permissions.voiceConnect)) {
if(channel.guild && channel.guild.members.has(this.user.id) && !(channel.permissionsOf(this.user.id).allow & Constants.Permissions.voiceConnect)) {
return Promise.reject(new Error("Insufficient permission to connect to voice channel"));
}
this.shards.get(this.guildShardMap[this.channelGuildMap[channelID]] || 0).sendWS(Constants.GatewayOPCodes.VOICE_STATE_UPDATE, {
Expand Down
2 changes: 2 additions & 0 deletions lib/Constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -396,6 +396,7 @@ Permissions.allGuild = Permissions.kickMembers
| Permissions.manageRoles
| Permissions.manageWebhooks
| Permissions.manageEmojisAndStickers
| Permissions.manageEvents
| Permissions.moderateMembers;
Permissions.allText = Permissions.createInstantInvite
| Permissions.manageChannels
Expand All @@ -412,6 +413,7 @@ Permissions.allText = Permissions.createInstantInvite
| Permissions.manageRoles
| Permissions.manageWebhooks
| Permissions.useApplicationCommands
| Permissions.manageThreads
| Permissions.createPublicThreads
| Permissions.createPrivateThreads
| Permissions.useExternalStickers
Expand Down
4 changes: 4 additions & 0 deletions lib/errors/DiscordHTTPError.js
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,10 @@ class DiscordHTTPError extends Error {
}
}

get headers() {
return this.response.headers;
}

get name() {
return this.constructor.name;
}
Expand Down
4 changes: 4 additions & 0 deletions lib/errors/DiscordRESTError.js
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,10 @@ class DiscordRESTError extends Error {
}
}

get headers() {
return this.response.headers;
}

get name() {
return `${this.constructor.name} [${this.code}]`;
}
Expand Down
Loading