feat(GuildMemberManager): _fetchMany

This commit is contained in:
March 7th 2022-08-09 10:43:16 +07:00
parent de5fe927a3
commit 19dc2ee263
5 changed files with 49 additions and 31 deletions

File diff suppressed because one or more lines are too long

View File

@ -27,7 +27,7 @@ class ThreadListSyncAction extends Action {
return coll.set(thread.id, thread); return coll.set(thread.id, thread);
}, new Collection()); }, new Collection());
for (const rawMember of Object.values(data.members)) { for (const rawMember of Object.values(data.members || {})) {
// Discord sends the thread id as id in this object // Discord sends the thread id as id in this object
const thread = client.channels.cache.get(rawMember.id); const thread = client.channels.cache.get(rawMember.id);
if (thread) { if (thread) {

View File

@ -4,8 +4,6 @@ const { Collection } = require('@discordjs/collection');
const { Events } = require('../../../util/Constants'); const { Events } = require('../../../util/Constants');
module.exports = (client, { d: data }) => { module.exports = (client, { d: data }) => {
// Console.log(data);
// console.log(data.ops[0])
const guild = client.guilds.cache.get(data.guild_id); const guild = client.guilds.cache.get(data.guild_id);
if (!guild) return; if (!guild) return;
const members = new Collection(); const members = new Collection();
@ -21,7 +19,10 @@ module.exports = (client, { d: data }) => {
} }
} }
} else if (object.op == 'INVALIDATE') { } else if (object.op == 'INVALIDATE') {
client.emit(Events.DEBUG, `Invalidate [${object.range[0]}, ${object.range[1]}]`); client.emit(
Events.DEBUG,
`Invalidate [${object.range[0]}, ${object.range[1]}], Fetching GuildId: ${data.guild_id}`,
);
} else if (object.op == 'UPDATE' || object.op == 'INSERT') { } else if (object.op == 'UPDATE' || object.op == 'INSERT') {
const member = object.item.member; const member = object.item.member;
if (!member) continue; if (!member) continue;
@ -33,5 +34,13 @@ module.exports = (client, { d: data }) => {
// Nothing; // Nothing;
} }
} }
client.emit(Events.GUILD_MEMBER_LIST_UPDATE, members, guild, data); /**
* Emitted whenever a guild member list (sidebar) is updated.
* @event Client#guildMemberListUpdate
* @param {Collection<Snowflake, GuildMember>} members Members that were updated
* @param {Guild} guild Guild
* @param {string} type Type of update (INVALIDATE | UPDATE | INSERT | DELETE | SYNC)
* @param {data} raw Raw data
*/
client.emit(Events.GUILD_MEMBER_LIST_UPDATE, members, guild, data.ops[0].op, data);
}; };

View File

@ -170,7 +170,7 @@ module.exports = (client, { d: data }, shard) => {
d: { d: {
guild_id: guild.id, guild_id: guild.id,
typing: true, typing: true,
threads: false, threads: true,
activities: true, activities: true,
thread_member_lists: [], thread_member_lists: [],
members: [], members: [],

View File

@ -425,14 +425,13 @@ class GuildMemberManager extends CachedManager {
_fetchMany({ _fetchMany({
limit = 0, limit = 0,
withPresences: presences = false, withPresences: presences = true,
user: user_ids, user: user_ids,
query, query,
time = 120e3, time = 120e3,
nonce = SnowflakeUtil.generate(), nonce = SnowflakeUtil.generate(),
sleepTime = 2e3, // 2 seconds
} = {}) { } = {}) {
let type; let type, sendGateway, stopped;
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
if (!query && !user_ids) query = ''; if (!query && !user_ids) query = '';
if (nonce.length > 32) throw new RangeError('MEMBER_FETCH_NONCE_LENGTH'); if (nonce.length > 32) throw new RangeError('MEMBER_FETCH_NONCE_LENGTH');
@ -446,7 +445,7 @@ class GuildMemberManager extends CachedManager {
this.guild.shard.send({ this.guild.shard.send({
op: type, op: type,
d: { d: {
guild_id: this.guild.id, guild_id: [this.guild.id],
presences, presences,
user_ids, user_ids,
query, query,
@ -455,10 +454,11 @@ class GuildMemberManager extends CachedManager {
}, },
}); });
} else { } else {
type = Opcodes.LAZY_REQUEST; // This is opcode type = Opcodes.LAZY_REQUEST;
let channel; let channel;
let channels = this.guild.channels.cache.filter(c => c.isText()); const channels = this.guild.channels.cache
channels = channels.filter(c => c.permissionsFor(this.guild.me).has('VIEW_CHANNEL')); .filter(c => c.isText())
.filter(c => c.permissionsFor(this.guild.me).has('VIEW_CHANNEL'));
if (!channels.size) { if (!channels.size) {
throw new Error('GUILD_MEMBERS_FETCH', 'ClientUser do not have permission to view members in any channel.'); throw new Error('GUILD_MEMBERS_FETCH', 'ClientUser do not have permission to view members in any channel.');
} }
@ -468,7 +468,7 @@ class GuildMemberManager extends CachedManager {
channel = channels_allowed_everyone.random() ?? channels.random(); channel = channels_allowed_everyone.random() ?? channels.random();
// Create array limit [0, 99] // Create array limit [0, 99]
const list = []; const list = [];
const allMember = this.guild.memberCount; let allMember = this.guild.memberCount;
if (allMember < 100) { if (allMember < 100) {
list.push([[0, 99]]); list.push([[0, 99]]);
} else if (allMember < 200) { } else if (allMember < 200) {
@ -488,7 +488,8 @@ class GuildMemberManager extends CachedManager {
`[WARN] Guild ${this.guild.id} has ${allMember} > 1000 members. Can't get offline members (Opcode 14)\n> https://discordpy-self.readthedocs.io/en/latest/migrating_from_dpy.html#guild-members`, `[WARN] Guild ${this.guild.id} has ${allMember} > 1000 members. Can't get offline members (Opcode 14)\n> https://discordpy-self.readthedocs.io/en/latest/migrating_from_dpy.html#guild-members`,
); );
if (allMember > 75_000) { if (allMember > 75_000) {
console.warn(`[WARN] Can't get enough members because the guild is large (Opcode 14)`); allMember = 75_000;
console.warn(`[WARN] Can't get enough members [Maximum = 75000] because the guild is large (Opcode 14)`);
} }
} }
let x = 100; let x = 100;
@ -505,46 +506,54 @@ class GuildMemberManager extends CachedManager {
x += 200; x += 200;
} }
} }
const sendTime = Date.now(); // Caculate sleepTime
for (const l of list) { let indexSend = list.length - 1;
this.guild.shard.send({ sendGateway = async () => {
if (indexSend == 0) {
stopped = true;
return true;
}
const d = {
op: type, op: type,
d: { d: {
guild_id: this.guild.id, guild_id: this.guild.id,
typing: true, typing: true,
threads: false, threads: true,
activities: true, activities: true,
channels: { channels: {
[channel.id]: l, [channel.id]: list[indexSend],
}, },
thread_member_lists: [], thread_member_lists: [],
members: [], members: [],
}, },
}); };
} this.guild.shard.send(d);
console.warn(`Gateway Rate Limit Warning: Sending ${list.length} Requests / ${Date.now() - sendTime || 1} ms`); indexSend--;
await this.guild.client.sleep(500);
return sendGateway();
};
console.warn(`[WARN] Gateway Rate Limit Warning: Sending ${list.length} Requests`);
sendGateway();
} }
const fetchedMembers = new Collection(); const fetchedMembers = new Collection();
let i = 0; let i = 0;
const handler = (members, _, chunk) => { const handler = (members, _, chunk) => {
timeout.refresh(); timeout.refresh();
if (chunk.nonce !== nonce && type === 8) return; // eslint-disable-next-line no-unused-expressions
Opcodes.REQUEST_GUILD_MEMBERS === type ? (stopped = true) : stopped;
if (chunk?.nonce !== nonce && type === Opcodes.REQUEST_GUILD_MEMBERS) return;
i++; i++;
for (const member of members.values()) { for (const member of members.values()) {
fetchedMembers.set(member.id, member); fetchedMembers.set(member.id, member);
} }
if (members.size < 1_000 || (limit && fetchedMembers.size >= limit) || i === chunk.count) { if (stopped && (members.size < 1_000 || (limit && fetchedMembers.size >= limit) || i === chunk?.count)) {
clearTimeout(timeout); clearTimeout(timeout);
this.client.removeListener(Events.GUILD_MEMBERS_CHUNK, handler); this.client.removeListener(Events.GUILD_MEMBERS_CHUNK, handler);
this.client.removeListener(Events.GUILD_MEMBER_LIST_UPDATE, handler); this.client.removeListener(Events.GUILD_MEMBER_LIST_UPDATE, handler);
this.client.decrementMaxListeners(); this.client.decrementMaxListeners();
let fetched = fetchedMembers.size < this.guild.members.cache.size ? this.guild.members.cache : fetchedMembers; let fetched = fetchedMembers.size < this.guild.members.cache.size ? this.guild.members.cache : fetchedMembers;
if (user_ids && !Array.isArray(user_ids) && fetched.size) fetched = fetched.first(); if (user_ids && !Array.isArray(user_ids) && fetched.size) fetched = fetched.first();
if (type == Opcodes.LAZY_REQUEST) { resolve(fetched);
this.guild.client.sleep(sleepTime).then(() => resolve(fetched));
} else {
resolve(fetched);
}
} }
}; };
const timeout = setTimeout(() => { const timeout = setTimeout(() => {