Pushing changes
This commit is contained in:
12
node_modules/discordie/lib/collections/BaseArrayCollection.js
generated
vendored
Normal file
12
node_modules/discordie/lib/collections/BaseArrayCollection.js
generated
vendored
Normal file
@ -0,0 +1,12 @@
|
||||
"use strict";
|
||||
|
||||
class BaseArrayCollection extends Array {
|
||||
// avoid constructor, calling array mutation methods will call it (ES2015)
|
||||
static create() {
|
||||
const instance = new this();
|
||||
this._constructor.apply(instance, arguments);
|
||||
return instance;
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = BaseArrayCollection;
|
19
node_modules/discordie/lib/collections/BaseCollection.js
generated
vendored
Normal file
19
node_modules/discordie/lib/collections/BaseCollection.js
generated
vendored
Normal file
@ -0,0 +1,19 @@
|
||||
"use strict";
|
||||
|
||||
const BaseModel = require("../models/BaseModel");
|
||||
|
||||
class BaseCollection extends Map {
|
||||
constructor() {
|
||||
super();
|
||||
}
|
||||
mergeOrSet(key, value) {
|
||||
const old = this.get(key);
|
||||
let merged = value;
|
||||
if (old && old instanceof BaseModel) {
|
||||
merged = old.merge(value);
|
||||
}
|
||||
this.set(key, merged);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = BaseCollection;
|
97
node_modules/discordie/lib/collections/CallCollection.js
generated
vendored
Normal file
97
node_modules/discordie/lib/collections/CallCollection.js
generated
vendored
Normal file
@ -0,0 +1,97 @@
|
||||
"use strict";
|
||||
|
||||
const Constants = require("../Constants");
|
||||
const Events = Constants.Events;
|
||||
const Utils = require("../core/Utils");
|
||||
const BaseCollection = require("./BaseCollection");
|
||||
|
||||
const Call = require("../models/Call");
|
||||
|
||||
function emitRing(gw, channelId) {
|
||||
const channel = this._discordie.DirectMessageChannels.get(channelId);
|
||||
if (!channel) return;
|
||||
|
||||
this._discordie.Dispatcher.emit(Events.CALL_RING, {
|
||||
socket: gw,
|
||||
channel: channel
|
||||
});
|
||||
}
|
||||
|
||||
function checkRing(gw, prev, next) {
|
||||
const channelId = next.channel_id;
|
||||
const userId = this._discordie._user && this._discordie._user.id;
|
||||
if (!channelId || !userId) return;
|
||||
if (!next || !next.ringing) return;
|
||||
|
||||
const hasPrev = prev ? prev.ringing.indexOf(userId) >= 0 : false;
|
||||
const hasNext = next.ringing.indexOf(userId) >= 0;
|
||||
|
||||
if (!hasPrev && hasNext) emitRing.call(this, gw, channelId);
|
||||
}
|
||||
|
||||
function handleConnectionOpen(data) {
|
||||
this.clear();
|
||||
return true;
|
||||
}
|
||||
|
||||
function handleCallCreate(call, e) {
|
||||
this.set(call.channel_id, new Call(call));
|
||||
checkRing.call(this, e.socket, null, call);
|
||||
return true;
|
||||
}
|
||||
|
||||
function handleCallUpdate(call, e) {
|
||||
const prev = this.get(call.channel_id);
|
||||
this.mergeOrSet(call.channel_id, new Call(call));
|
||||
checkRing.call(this, e.socket, prev, call);
|
||||
return true;
|
||||
}
|
||||
|
||||
function handleCallDelete(call) {
|
||||
const _call = this.get(call.channel_id);
|
||||
if (!_call) return true;
|
||||
|
||||
if (call.unavailable === true) {
|
||||
this.mergeOrSet(call.channel_id, {unavailable: true});
|
||||
} else {
|
||||
this.delete(call.channel_id);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
class CallCollection extends BaseCollection {
|
||||
constructor(discordie, gateway) {
|
||||
super();
|
||||
|
||||
if (typeof gateway !== "function")
|
||||
throw new Error("Gateway parameter must be a function");
|
||||
|
||||
discordie.Dispatcher.on(Events.GATEWAY_DISPATCH, e => {
|
||||
if (e.socket != gateway()) return;
|
||||
|
||||
Utils.bindGatewayEventHandlers(this, e, {
|
||||
READY: handleConnectionOpen,
|
||||
CALL_CREATE: handleCallCreate,
|
||||
CALL_UPDATE: handleCallUpdate,
|
||||
CALL_DELETE: handleCallDelete
|
||||
});
|
||||
});
|
||||
|
||||
this._discordie = discordie;
|
||||
Utils.privatify(this);
|
||||
}
|
||||
isActive(channelId, messageId) {
|
||||
const call = this.get(channelId);
|
||||
if (messageId) {
|
||||
return call && !call.unavailable && call.message_id == messageId;
|
||||
}
|
||||
return call && !call.unavailable;
|
||||
}
|
||||
isUnavailable(channelId) {
|
||||
const call = this.get(channelId);
|
||||
return call && call.unavailable;
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = CallCollection;
|
193
node_modules/discordie/lib/collections/ChannelCollection.js
generated
vendored
Normal file
193
node_modules/discordie/lib/collections/ChannelCollection.js
generated
vendored
Normal file
@ -0,0 +1,193 @@
|
||||
"use strict";
|
||||
|
||||
const Constants = require("../Constants");
|
||||
const Events = Constants.Events;
|
||||
const ChannelTypes = Constants.ChannelTypes;
|
||||
const Utils = require("../core/Utils");
|
||||
const BaseCollection = require("./BaseCollection");
|
||||
|
||||
const Channel = require("../models/Channel");
|
||||
const PermissionOverwrite = require("../models/PermissionOverwrite");
|
||||
const IPermissions = require("../interfaces/IPermissions");
|
||||
|
||||
function convertOverwrites(channel) {
|
||||
const overwrites = channel.permission_overwrites || [];
|
||||
|
||||
// note: @everyone overwrite does not exist by default
|
||||
// this will add one locally
|
||||
if (channel.guild_id) {
|
||||
const everyone = overwrites.find(o => o.id == channel.guild_id);
|
||||
if (!everyone) {
|
||||
overwrites.push({
|
||||
id: channel.guild_id,
|
||||
type: "role",
|
||||
allow: IPermissions.NONE,
|
||||
deny: IPermissions.NONE
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return overwrites.map(o => new PermissionOverwrite(o));
|
||||
}
|
||||
|
||||
function createChannel(channel) {
|
||||
const channelRecipients =
|
||||
Array.isArray(channel.recipients) ? channel.recipients.map(r => r.id) : [];
|
||||
|
||||
return new Channel({
|
||||
id: channel.id,
|
||||
type: channel.type || ChannelTypes.GUILD_TEXT,
|
||||
name: channel.name || "",
|
||||
topic: channel.topic || "",
|
||||
position: channel.position || 0,
|
||||
recipients: new Set(channelRecipients),
|
||||
guild_id: channel.guild_id || null,
|
||||
permission_overwrites: convertOverwrites(channel),
|
||||
bitrate: channel.bitrate || Constants.BITRATE_DEFAULT,
|
||||
user_limit: channel.user_limit || 0,
|
||||
owner_id: channel.owner_id || null,
|
||||
icon: channel.icon || null
|
||||
});
|
||||
}
|
||||
|
||||
function handleConnectionOpen(data) {
|
||||
this.clear();
|
||||
data.guilds.forEach(guild => handleGuildCreate.call(this, guild));
|
||||
data.private_channels.forEach(channel => {
|
||||
this.set(channel.id, createChannel(channel));
|
||||
});
|
||||
return true;
|
||||
}
|
||||
|
||||
function handleCreateOrUpdateChannel(channel, e) {
|
||||
const prev = this.get(channel.id);
|
||||
const next = createChannel(channel);
|
||||
this.mergeOrSet(channel.id, next);
|
||||
if (e.type === Events.CHANNEL_UPDATE) {
|
||||
e.data._prev = prev;
|
||||
e.data._next = next;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
function handleChannelDelete(channel) {
|
||||
this.delete(channel.id);
|
||||
return true;
|
||||
}
|
||||
|
||||
function handleGuildCreate(guild) {
|
||||
if (!guild || guild.unavailable) return true;
|
||||
|
||||
guild.channels.forEach(channel => {
|
||||
channel.guild_id = guild.id;
|
||||
this.set(channel.id, createChannel(channel));
|
||||
});
|
||||
return true;
|
||||
}
|
||||
|
||||
function handleGuildDelete(guild) {
|
||||
this.forEach((channel, id) => {
|
||||
if (channel.guild_id == guild.id)
|
||||
this.delete(id);
|
||||
});
|
||||
return true;
|
||||
}
|
||||
|
||||
function processRecipientAddOrRemove(data, handler) {
|
||||
const user = data.user;
|
||||
const channel = this.get(data.channel_id);
|
||||
if (!channel) return;
|
||||
if (!this._discordie._user || this._discordie._user.id == user.id) return;
|
||||
handler(channel, user);
|
||||
}
|
||||
|
||||
function handleRecipientAdd(data) {
|
||||
const handler = (channel, user) => channel.recipients.add(user.id);
|
||||
processRecipientAddOrRemove.call(this, data, handler);
|
||||
return true;
|
||||
}
|
||||
|
||||
function handleRecipientRemove(data) {
|
||||
const handler = (channel, user) => channel.recipients.delete(user.id);
|
||||
processRecipientAddOrRemove.call(this, data, handler);
|
||||
return true;
|
||||
}
|
||||
|
||||
class ChannelCollection extends BaseCollection {
|
||||
constructor(discordie, gateway) {
|
||||
super();
|
||||
|
||||
if (typeof gateway !== "function")
|
||||
throw new Error("Gateway parameter must be a function");
|
||||
|
||||
discordie.Dispatcher.on(Events.GATEWAY_DISPATCH, e => {
|
||||
if (e.socket != gateway()) return;
|
||||
|
||||
Utils.bindGatewayEventHandlers(this, e, {
|
||||
READY: handleConnectionOpen,
|
||||
GUILD_CREATE: handleGuildCreate,
|
||||
GUILD_DELETE: handleGuildDelete,
|
||||
CHANNEL_CREATE: handleCreateOrUpdateChannel,
|
||||
CHANNEL_UPDATE: handleCreateOrUpdateChannel,
|
||||
CHANNEL_DELETE: handleChannelDelete,
|
||||
CHANNEL_RECIPIENT_ADD: handleRecipientAdd,
|
||||
CHANNEL_RECIPIENT_REMOVE: handleRecipientRemove
|
||||
});
|
||||
});
|
||||
|
||||
this._discordie = discordie;
|
||||
Utils.privatify(this);
|
||||
}
|
||||
*getPrivateChannelIterator() {
|
||||
for (let channel of this.values()) {
|
||||
if (this._isPrivate(channel))
|
||||
yield channel;
|
||||
}
|
||||
}
|
||||
*getGuildChannelIterator() {
|
||||
for (let channel of this.values()) {
|
||||
if (!this._isPrivate(channel))
|
||||
yield channel;
|
||||
}
|
||||
}
|
||||
getPrivateChannel(channelId) {
|
||||
var channel = this.get(channelId);
|
||||
if (!channel) return null;
|
||||
return this._isPrivate(channel) ? channel : null;
|
||||
}
|
||||
getGuildChannel(channelId) {
|
||||
var channel = this.get(channelId);
|
||||
if (!channel) return null;
|
||||
return !this._isPrivate(channel) ? channel : null;
|
||||
}
|
||||
isPrivate(channelId) {
|
||||
const channel = this.get(channelId);
|
||||
if (channel)
|
||||
return this._isPrivate(channel);
|
||||
return null;
|
||||
}
|
||||
_isPrivate(channel) {
|
||||
const type = channel.type;
|
||||
return (type === ChannelTypes.DM || type === ChannelTypes.GROUP_DM);
|
||||
}
|
||||
getChannelType(channelId) {
|
||||
const channel = this.get(channelId);
|
||||
if (channel) return channel.type;
|
||||
return null;
|
||||
}
|
||||
update(channel) {
|
||||
handleCreateOrUpdateChannel.call(this, channel, {});
|
||||
}
|
||||
updatePermissionOverwrite(channelId, overwrite) {
|
||||
const channel = this.get(channelId);
|
||||
if (!channel) return;
|
||||
const newOverwrites = channel.permission_overwrites
|
||||
.filter(o => o.id != overwrite.id && o.type != overwrite.type);
|
||||
newOverwrites.push(new PermissionOverwrite(overwrite));
|
||||
this.set(channelId, channel.merge({
|
||||
permission_overwrites: newOverwrites
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = ChannelCollection;
|
183
node_modules/discordie/lib/collections/GuildCollection.js
generated
vendored
Normal file
183
node_modules/discordie/lib/collections/GuildCollection.js
generated
vendored
Normal file
@ -0,0 +1,183 @@
|
||||
"use strict";
|
||||
|
||||
const Constants = require("../Constants");
|
||||
const Events = Constants.Events;
|
||||
const Utils = require("../core/Utils");
|
||||
const BaseCollection = require("./BaseCollection");
|
||||
|
||||
const MFALevels = Constants.MFALevels;
|
||||
const VerificationLevel = Constants.VerificationLevel;
|
||||
const UserNotificationSettings = Constants.UserNotificationSettings;
|
||||
|
||||
const Guild = require("../models/Guild");
|
||||
const Role = require("../models/Role");
|
||||
|
||||
function convertRoles(roles) {
|
||||
const map = new Map();
|
||||
roles.forEach(role => {
|
||||
map.set(role.id, new Role(role));
|
||||
});
|
||||
return map;
|
||||
}
|
||||
|
||||
function createGuild(guild, old) {
|
||||
return new Guild({
|
||||
id: guild.id,
|
||||
name: guild.name,
|
||||
region: guild.region,
|
||||
icon: guild.icon,
|
||||
splash: guild.splash,
|
||||
features: new Set(guild.features),
|
||||
emojis: (guild.emojis != null ? guild.emojis : old.emojis) || [],
|
||||
default_message_notifications:
|
||||
guild.default_message_notifications ||
|
||||
UserNotificationSettings.ALL_MESSAGES,
|
||||
owner_id: guild.owner_id,
|
||||
roles: convertRoles(guild.roles),
|
||||
afk_channel_id: guild.afk_channel_id,
|
||||
afk_timeout: guild.afk_timeout,
|
||||
verification_level: guild.verification_level || VerificationLevel.NONE,
|
||||
member_count:
|
||||
(guild.member_count != null ? guild.member_count : old.member_count),
|
||||
large: (guild.large != null ? guild.large : old.large) || false,
|
||||
mfa_level: guild.mfa_level || MFALevels.NONE,
|
||||
joined_at: guild.joined_at || old.joined_at
|
||||
});
|
||||
}
|
||||
|
||||
function handleConnectionOpen(data) {
|
||||
this.clear();
|
||||
data.guilds.forEach(guild => {
|
||||
if (guild.unavailable) return;
|
||||
this.set(guild.id, createGuild(guild, {}));
|
||||
});
|
||||
return true;
|
||||
}
|
||||
|
||||
function handleCreateOrUpdateGuild(guild, e) {
|
||||
if (!guild || guild.unavailable) return true;
|
||||
const prev = this.get(guild.id) || {};
|
||||
const next = createGuild(guild, prev);
|
||||
this.mergeOrSet(guild.id, next);
|
||||
if (e.type === Events.GUILD_UPDATE) {
|
||||
e.data._prev = prev;
|
||||
e.data._next = next;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
function handleDeleteGuild(guild, e) {
|
||||
const oldGuild = this.get(guild.id);
|
||||
if (oldGuild) e.data._cached = oldGuild;
|
||||
|
||||
this.delete(guild.id);
|
||||
return true;
|
||||
}
|
||||
|
||||
function handleGuildSync(guild) {
|
||||
let oldGuild = this.get(guild.id);
|
||||
if (!oldGuild) return true;
|
||||
this.mergeOrSet(guild.id, {
|
||||
large: (guild.large != null ? guild.large : oldGuild.large)
|
||||
});
|
||||
return true;
|
||||
}
|
||||
|
||||
function handleGuildRoleCreateOrUpdate(data, e) {
|
||||
let guild = this.get(data.guild_id);
|
||||
if (guild) {
|
||||
const prev = guild.roles.get(data.role.id);
|
||||
const next = new Role(data.role);
|
||||
guild.roles.set(data.role.id, next);
|
||||
if (e.type === Events.GUILD_ROLE_UPDATE) {
|
||||
e.data._prev = prev;
|
||||
e.data._next = next;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
function handleGuildRoleDelete(data, e) {
|
||||
let guild = this.get(data.guild_id);
|
||||
if (guild) {
|
||||
const oldRole = guild.roles.get(data.role_id);
|
||||
if (oldRole) e.data._cached = oldRole;
|
||||
|
||||
guild.roles.delete(data.role_id);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
function handleGuildMemberAdd(member) {
|
||||
updateMemberCount.call(this, member.guild_id, +1);
|
||||
return true;
|
||||
}
|
||||
|
||||
function handleGuildMemberRemove(member) {
|
||||
updateMemberCount.call(this, member.guild_id, -1);
|
||||
return true;
|
||||
}
|
||||
|
||||
function updateMemberCount(guildId, delta) {
|
||||
let guild = this.get(guildId);
|
||||
if (!guild) return true;
|
||||
this.mergeOrSet(guildId, { member_count: guild.member_count + delta });
|
||||
return true;
|
||||
}
|
||||
|
||||
function handleGuildEmojisUpdate(data, e) {
|
||||
if (!data || data.emojis == null) return true;
|
||||
|
||||
let guild = this.get(data.guild_id);
|
||||
if (!guild) return true;
|
||||
|
||||
const prev = guild.emojis;
|
||||
const next = data.emojis;
|
||||
this.mergeOrSet(data.guild_id, { emojis: data.emojis });
|
||||
if (e.type === Events.GUILD_EMOJIS_UPDATE) {
|
||||
e.data._prev = prev;
|
||||
e.data._next = next;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
class GuildCollection extends BaseCollection {
|
||||
constructor(discordie, gateway) {
|
||||
super();
|
||||
|
||||
if (typeof gateway !== "function")
|
||||
throw new Error("Gateway parameter must be a function");
|
||||
|
||||
discordie.Dispatcher.on(Events.GATEWAY_DISPATCH, e => {
|
||||
if (e.socket != gateway()) return;
|
||||
|
||||
Utils.bindGatewayEventHandlers(this, e, {
|
||||
READY: handleConnectionOpen,
|
||||
GUILD_SYNC: handleGuildSync,
|
||||
GUILD_CREATE: handleCreateOrUpdateGuild,
|
||||
GUILD_UPDATE: handleCreateOrUpdateGuild,
|
||||
GUILD_DELETE: handleDeleteGuild,
|
||||
GUILD_ROLE_CREATE: handleGuildRoleCreateOrUpdate,
|
||||
GUILD_ROLE_UPDATE: handleGuildRoleCreateOrUpdate,
|
||||
GUILD_ROLE_DELETE: handleGuildRoleDelete,
|
||||
GUILD_MEMBER_ADD: handleGuildMemberAdd,
|
||||
GUILD_MEMBER_REMOVE: handleGuildMemberRemove,
|
||||
GUILD_EMOJIS_UPDATE: handleGuildEmojisUpdate,
|
||||
});
|
||||
});
|
||||
|
||||
this._discordie = discordie;
|
||||
Utils.privatify(this);
|
||||
}
|
||||
update(guild) {
|
||||
handleCreateOrUpdateGuild.call(this, guild, {});
|
||||
}
|
||||
updateRole(guildId, role) {
|
||||
const guild = this.get(guildId);
|
||||
if (!guild || !guild.roles) return;
|
||||
guild.roles.set(role.id, new Role(role));
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = GuildCollection;
|
239
node_modules/discordie/lib/collections/GuildMemberCollection.js
generated
vendored
Normal file
239
node_modules/discordie/lib/collections/GuildMemberCollection.js
generated
vendored
Normal file
@ -0,0 +1,239 @@
|
||||
"use strict";
|
||||
|
||||
const Constants = require("../Constants");
|
||||
const StatusTypes = Constants.StatusTypes;
|
||||
const Events = Constants.Events;
|
||||
const Utils = require("../core/Utils");
|
||||
const BaseCollection = require("./BaseCollection");
|
||||
|
||||
const GuildMember = require("../models/GuildMember");
|
||||
|
||||
function createGuildMember(member) {
|
||||
if (member.user) member.id = member.user.id;
|
||||
|
||||
return new GuildMember({
|
||||
id: member.id,
|
||||
guild_id: member.guild_id,
|
||||
nick: member.nick || null,
|
||||
roles: member.roles || [],
|
||||
mute: member.mute || false,
|
||||
deaf: member.deaf || false,
|
||||
self_mute: member.self_mute || false,
|
||||
self_deaf: member.self_deaf || false,
|
||||
joined_at: member.joined_at
|
||||
});
|
||||
}
|
||||
|
||||
function handleConnectionOpen(data) {
|
||||
this.clear();
|
||||
data.guilds.forEach(guild => handleCreateGuild.call(this, guild));
|
||||
return true;
|
||||
}
|
||||
|
||||
function handleGuildMemberCreateOrUpdate(member, e) {
|
||||
const memberCollection = this.get(member.guild_id);
|
||||
if (!memberCollection) return true;
|
||||
|
||||
const prev = memberCollection.get(member.user.id);
|
||||
const next = createGuildMember(member);
|
||||
memberCollection.mergeOrSet(member.user.id, next);
|
||||
|
||||
if (e.type === Events.GUILD_MEMBER_UPDATE) {
|
||||
e.data._prev = prev;
|
||||
e.data._next = next;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
function handleGuildMemberRemove(member, e) {
|
||||
const memberCollection = this.get(member.guild_id);
|
||||
if (!memberCollection) return true;
|
||||
|
||||
const oldMember = memberCollection.get(member.user.id);
|
||||
if (oldMember) e.data._cached = oldMember;
|
||||
|
||||
memberCollection.delete(member.user.id);
|
||||
return true;
|
||||
}
|
||||
|
||||
function handleCreateGuild(guild) {
|
||||
if (!guild || guild.unavailable) return true;
|
||||
|
||||
if (!this._discordie._guilds.get(guild.id)) return true; // GUILD_SYNC case
|
||||
|
||||
const memberCollection = new BaseCollection();
|
||||
this.set(guild.id, memberCollection);
|
||||
|
||||
guild.members.forEach(member => {
|
||||
member.guild_id = guild.id;
|
||||
memberCollection.set(member.user.id, createGuildMember(member));
|
||||
});
|
||||
return true;
|
||||
}
|
||||
|
||||
function handleDeleteGuild(guild) {
|
||||
this.delete(guild.id);
|
||||
return true;
|
||||
}
|
||||
|
||||
function handleVoiceStateUpdate(data) {
|
||||
const memberCollection = this.get(data.guild_id);
|
||||
if (!memberCollection) return true;
|
||||
const member = memberCollection.get(data.user_id);
|
||||
if (!member) return true;
|
||||
memberCollection.set(data.user_id,
|
||||
member.merge({
|
||||
mute: data.mute,
|
||||
deaf: data.deaf,
|
||||
self_mute: data.self_mute,
|
||||
self_deaf: data.self_deaf
|
||||
})
|
||||
);
|
||||
return true;
|
||||
}
|
||||
|
||||
function handlePresenceUpdate(presence) {
|
||||
if (!presence.user || !presence.user.id) return true;
|
||||
|
||||
// add members only for online users and if presence is not partial
|
||||
if (presence.status == StatusTypes.OFFLINE || !presence.user.username)
|
||||
return true;
|
||||
|
||||
const memberCollection = this.get(presence.guild_id);
|
||||
if (!memberCollection) return true;
|
||||
|
||||
const cachedMember = memberCollection.get(presence.user.id);
|
||||
if (!cachedMember) {
|
||||
// note: presences only contain roles
|
||||
memberCollection.set(presence.user.id, createGuildMember(presence));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
function handleGuildMembersChunk(chunk) {
|
||||
var guildId = chunk.guild_id;
|
||||
if (!guildId || !chunk.members) return true;
|
||||
|
||||
var state = this._guildMemberChunks[guildId];
|
||||
if (!state) return true;
|
||||
|
||||
var guild = this._discordie._guilds.get(guildId);
|
||||
if (!guild) return true;
|
||||
|
||||
const memberCollection = this.get(guildId);
|
||||
if (!memberCollection) return true;
|
||||
|
||||
chunk.members.forEach(member => {
|
||||
member.guild_id = guildId;
|
||||
memberCollection.mergeOrSet(member.user.id, createGuildMember(member))
|
||||
});
|
||||
if (memberCollection.size >= guild.member_count) state.resolve();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
class GuildMemberCollection extends BaseCollection {
|
||||
constructor(discordie, gateway) {
|
||||
super();
|
||||
|
||||
if (typeof gateway !== "function")
|
||||
throw new Error("Gateway parameter must be a function");
|
||||
|
||||
discordie.Dispatcher.on(Events.GATEWAY_DISPATCH, e => {
|
||||
if (e.socket != gateway()) return;
|
||||
|
||||
Utils.bindGatewayEventHandlers(this, e, {
|
||||
READY: handleConnectionOpen,
|
||||
GUILD_SYNC: handleCreateGuild,
|
||||
GUILD_CREATE: handleCreateGuild,
|
||||
GUILD_DELETE: handleDeleteGuild,
|
||||
GUILD_MEMBER_ADD: handleGuildMemberCreateOrUpdate,
|
||||
GUILD_MEMBER_UPDATE: handleGuildMemberCreateOrUpdate,
|
||||
GUILD_MEMBER_REMOVE: handleGuildMemberRemove,
|
||||
VOICE_STATE_UPDATE: handleVoiceStateUpdate,
|
||||
PRESENCE_UPDATE: handlePresenceUpdate,
|
||||
GUILD_MEMBERS_CHUNK: handleGuildMembersChunk
|
||||
});
|
||||
});
|
||||
|
||||
discordie.Dispatcher.on(Events.GATEWAY_DISCONNECT, e => {
|
||||
if (e.socket != gateway()) return;
|
||||
|
||||
for (var guildId in this._guildMemberChunks) {
|
||||
var state = this._guildMemberChunks[guildId];
|
||||
if (!state) continue;
|
||||
state.reject(new Error("Gateway disconnect"));
|
||||
}
|
||||
this._guildMemberChunks = {};
|
||||
});
|
||||
|
||||
this._guildMemberChunks = {};
|
||||
|
||||
this._discordie = discordie;
|
||||
Utils.privatify(this);
|
||||
}
|
||||
fetchMembers(guilds){
|
||||
const gateway = this._discordie.gatewaySocket;
|
||||
if (!gateway || !gateway.connected)
|
||||
return Promise.reject(new Error("No gateway socket (not connected)"));
|
||||
|
||||
const largeGuilds =
|
||||
Array.from(this._discordie._guilds.values())
|
||||
.filter(guild => {
|
||||
if (!guild.large) return false;
|
||||
var cachedMembers = this._discordie._members.get(guild.id);
|
||||
if (!cachedMembers) return false;
|
||||
return guild.member_count > cachedMembers.size;
|
||||
})
|
||||
.map(guild => guild.id);
|
||||
|
||||
// filter out only requested guilds (if specified) from large ones
|
||||
// return a resolved promise if no large guilds in the list
|
||||
let targetGuilds =
|
||||
!guilds ?
|
||||
largeGuilds :
|
||||
largeGuilds.filter(guild => guilds.indexOf(guild) >= 0);
|
||||
|
||||
if (!targetGuilds.length) return Promise.resolve();
|
||||
|
||||
targetGuilds.forEach(guildId => {
|
||||
if (this._guildMemberChunks[guildId]) return;
|
||||
|
||||
var state = {promise: null, resolve: null, reject: null, timer: null};
|
||||
state.promise = new Promise((rs, rj) => {
|
||||
const destroyState = () => {
|
||||
if (!state.timer) return;
|
||||
clearTimeout(state.timer);
|
||||
state.timer = null;
|
||||
delete this._guildMemberChunks[guildId];
|
||||
};
|
||||
state.resolve = result => { destroyState(); return rs(result); };
|
||||
state.reject = reason => { destroyState(); return rj(reason); };
|
||||
});
|
||||
state.timer = setTimeout(() => {
|
||||
if (!this._guildMemberChunks[guildId]) return;
|
||||
state.reject(new Error(
|
||||
"Guild member request timed out (" + guildId + ")"
|
||||
));
|
||||
delete this._guildMemberChunks[guildId];
|
||||
}, 60000);
|
||||
this._guildMemberChunks[guildId] = state;
|
||||
});
|
||||
|
||||
gateway.requestGuildMembers(targetGuilds);
|
||||
|
||||
var targetPromises =
|
||||
targetGuilds.map(guildId => this._guildMemberChunks[guildId].promise);
|
||||
|
||||
return Promise.all(targetPromises);
|
||||
}
|
||||
getMember(guildId, userId) {
|
||||
const memberCollection = this.get(guildId);
|
||||
if (!memberCollection) return null;
|
||||
return memberCollection.get(userId);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = GuildMemberCollection;
|
174
node_modules/discordie/lib/collections/GuildSyncCollection.js
generated
vendored
Normal file
174
node_modules/discordie/lib/collections/GuildSyncCollection.js
generated
vendored
Normal file
@ -0,0 +1,174 @@
|
||||
"use strict";
|
||||
|
||||
const Constants = require("../Constants");
|
||||
const Events = Constants.Events;
|
||||
const Utils = require("../core/Utils");
|
||||
|
||||
const GUILD_SYNC_TIMEOUT = 3000;
|
||||
|
||||
function emitTaskFinished(gw) {
|
||||
this._syncingGuilds.clear();
|
||||
|
||||
this._discordie.Dispatcher.emit(Events.READY_TASK_FINISHED, {
|
||||
socket: gw,
|
||||
name: this.constructor.name,
|
||||
handler: this
|
||||
});
|
||||
}
|
||||
|
||||
function scheduleReadyTimeout(gw) {
|
||||
this._syncingGuildsTimeout = setTimeout(() => {
|
||||
this._syncingGuildsTimeout = null;
|
||||
if (!this._discordie.connected) return;
|
||||
|
||||
setImmediate(() => emitTaskFinished.call(this, gw));
|
||||
}, GUILD_SYNC_TIMEOUT);
|
||||
}
|
||||
|
||||
function maybeReady(gw) {
|
||||
if (this._syncingGuildsTimeout) {
|
||||
clearTimeout(this._syncingGuildsTimeout);
|
||||
}
|
||||
if (this._syncingGuilds.size) {
|
||||
scheduleReadyTimeout.call(this, gw);
|
||||
} else {
|
||||
setImmediate(() => emitTaskFinished.call(this, gw));
|
||||
}
|
||||
}
|
||||
|
||||
function handleExecuteReadyTask(data, e) {
|
||||
clearAll.call(this);
|
||||
|
||||
if (this.isSupported(e.socket)) {
|
||||
data.guilds.forEach(guild => {
|
||||
this.add(guild.id);
|
||||
this._syncingGuilds.add(guild.id);
|
||||
});
|
||||
commit.call(this);
|
||||
}
|
||||
|
||||
maybeReady.call(this, e.socket);
|
||||
return true;
|
||||
}
|
||||
|
||||
function handleGuildCreate(guild, e) {
|
||||
if (!this.isSupported(e.socket)) return true;
|
||||
|
||||
// ignore if became available
|
||||
if (this._discordie.UnavailableGuilds.isGuildAvailable(guild)) return true;
|
||||
|
||||
this.sync(guild);
|
||||
return true;
|
||||
}
|
||||
|
||||
function handleGuildSync(guild, e) {
|
||||
if (this._syncingGuilds.has(guild.id)) {
|
||||
this._syncingGuilds.delete(guild.id);
|
||||
|
||||
maybeReady.call(this, e.socket);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
function handleGuildDelete(guild, e) {
|
||||
if (!this.isSupported(e.socket)) return true;
|
||||
if (guild.unavailable) return true;
|
||||
this.unsync(guild);
|
||||
return true;
|
||||
}
|
||||
|
||||
function commit() {
|
||||
const gateway = this._gateway();
|
||||
if (!gateway || !gateway.connected) return;
|
||||
gateway.syncGuilds(Array.from(this));
|
||||
}
|
||||
|
||||
function clearAll() {
|
||||
this.clear();
|
||||
this._syncingGuilds.clear();
|
||||
}
|
||||
|
||||
class GuildSyncCollection extends Set {
|
||||
constructor(discordie, gateway) {
|
||||
super();
|
||||
|
||||
if (typeof gateway !== "function")
|
||||
throw new Error("Gateway parameter must be a function");
|
||||
|
||||
discordie.Dispatcher.on(Events.GATEWAY_DISPATCH, e => {
|
||||
if (e.socket != gateway()) return;
|
||||
|
||||
Utils.bindGatewayEventHandlers(this, e, {
|
||||
GUILD_SYNC: handleGuildSync,
|
||||
GUILD_CREATE: handleGuildCreate,
|
||||
GUILD_DELETE: handleGuildDelete,
|
||||
});
|
||||
});
|
||||
|
||||
this._discordie = discordie;
|
||||
this._gateway = gateway;
|
||||
|
||||
this._syncingGuilds = new Set();
|
||||
this._syncingGuildsTimeout = null;
|
||||
|
||||
Utils.privatify(this);
|
||||
}
|
||||
_executeReadyTask(data, socket) {
|
||||
handleExecuteReadyTask.call(this, data, {socket});
|
||||
}
|
||||
isSupported(socket) {
|
||||
if (!socket) socket = this._gateway();
|
||||
if (!socket) return false;
|
||||
return socket.remoteGatewayVersion >= 5 && !this._discordie._user.bot;
|
||||
}
|
||||
sync(guild) {
|
||||
if (!this.isSupported()) return false;
|
||||
if (!guild) return false;
|
||||
|
||||
if (Array.isArray(guild)) {
|
||||
const guilds = guild
|
||||
.map(g => g.id || g.valueOf())
|
||||
.filter(id => !this.has(id));
|
||||
if (!guilds.length) return false;
|
||||
guilds.forEach(id => this.add(id));
|
||||
} else {
|
||||
if (this.has(guild.id)) return false;
|
||||
this.add(guild.id);
|
||||
}
|
||||
|
||||
commit.call(this);
|
||||
return true;
|
||||
}
|
||||
unsync(guild) {
|
||||
if (!this.isSupported()) return false;
|
||||
if (!guild) return false;
|
||||
|
||||
if (Array.isArray(guild)) {
|
||||
const guilds = guild
|
||||
.map(g => g.id || g.valueOf())
|
||||
.filter(id => this.has(id));
|
||||
if (!guilds.length) return false;
|
||||
guilds.forEach(id => this.delete(id));
|
||||
} else {
|
||||
if (!this.delete(guild.id)) return false;
|
||||
}
|
||||
|
||||
commit.call(this);
|
||||
return true;
|
||||
}
|
||||
syncAll() {
|
||||
const available = this._discordie.Guilds.map(g => g.valueOf());
|
||||
const unavailable = this._discordie.UnavailableGuilds;
|
||||
const all = available.concat(unavailable);
|
||||
return this.sync(all);
|
||||
}
|
||||
unsyncAll() {
|
||||
if (!this.isSupported()) return false;
|
||||
if (!this.size) return false;
|
||||
this.clear();
|
||||
commit.call(this);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = GuildSyncCollection;
|
393
node_modules/discordie/lib/collections/MessageCollection.js
generated
vendored
Normal file
393
node_modules/discordie/lib/collections/MessageCollection.js
generated
vendored
Normal file
@ -0,0 +1,393 @@
|
||||
"use strict";
|
||||
|
||||
const Constants = require("../Constants");
|
||||
const Events = Constants.Events;
|
||||
const Utils = require("../core/Utils");
|
||||
const BaseCollection = require("./BaseCollection");
|
||||
const LimitedCache = require("../core/LimitedCache");
|
||||
|
||||
const Message = require("../models/Message");
|
||||
|
||||
function getOrCreateChannelCache(channelId) {
|
||||
return (
|
||||
this._messagesByChannel[channelId] =
|
||||
this._messagesByChannel[channelId] ||
|
||||
new LimitedCache(this._messageLimit)
|
||||
);
|
||||
}
|
||||
|
||||
function updatePinnedMessages(channelId, messageId, message) {
|
||||
if (message && message.pinned && !message.deleted) {
|
||||
var channelPinned =
|
||||
this._pinnedMessagesByChannel[channelId] =
|
||||
this._pinnedMessagesByChannel[channelId] || [];
|
||||
|
||||
// insert or replace
|
||||
const idx = channelPinned.findIndex(msg => msg.id === messageId);
|
||||
if (idx < 0) channelPinned.unshift(message);
|
||||
else channelPinned[idx] = message;
|
||||
} else {
|
||||
var channelPinned = this._pinnedMessagesByChannel[channelId];
|
||||
if (channelPinned) {
|
||||
// delete if exists
|
||||
const idx = channelPinned.findIndex(msg => msg.id === messageId);
|
||||
if (idx >= 0) channelPinned.splice(idx, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function updateMessages(channelId, messageId, msg) {
|
||||
const messages = getOrCreateChannelCache.call(this, channelId);
|
||||
|
||||
if (msg.nonce && messages.has(msg.nonce)) {
|
||||
messages.rename(msg.nonce, messageId);
|
||||
}
|
||||
|
||||
var edited = true;
|
||||
var message = null;
|
||||
if (messages.has(messageId)) {
|
||||
edited = !!msg.edited_timestamp;
|
||||
messages.set(messageId, message = messages.get(messageId).merge(msg));
|
||||
} else {
|
||||
messages.set(messageId, message = new Message(msg));
|
||||
}
|
||||
|
||||
if (edited) {
|
||||
const edits = this._messageEdits[messageId] || [];
|
||||
this._messageEdits[messageId] = edits;
|
||||
|
||||
var edit = message.merge({embeds: [], reactions: []});
|
||||
edits.push(edit);
|
||||
trimEdits.call(this, messageId);
|
||||
}
|
||||
}
|
||||
|
||||
function trimEdits(messageId) {
|
||||
if (!messageId) {
|
||||
for (var id in this._messageEdits)
|
||||
if (id) trimEdits.call(this, id);
|
||||
}
|
||||
const edits = this._messageEdits[messageId];
|
||||
if (!edits) return;
|
||||
if (edits.length > this._editsLimit)
|
||||
edits.splice(0, edits.length - this._editsLimit);
|
||||
}
|
||||
|
||||
function handleMessageCreate(msg) {
|
||||
msg.deleted = false;
|
||||
updateMessages.call(this, msg.channel_id, msg.id, msg);
|
||||
return true;
|
||||
}
|
||||
|
||||
function handleMessageUpdate(msg) {
|
||||
msg.deleted = false;
|
||||
|
||||
// update pinned cache only if pinned messages have been fetched
|
||||
var channelPinned = this._pinnedMessagesByChannel[msg.channel_id];
|
||||
if (channelPinned) {
|
||||
updatePinnedMessages.call(this, msg.channel_id, msg.id, msg);
|
||||
}
|
||||
|
||||
const channelCache = this._messagesByChannel[msg.channel_id];
|
||||
if (!channelCache || !channelCache.has(msg.id)) return true;
|
||||
|
||||
updateMessages.call(this, msg.channel_id, msg.id, msg);
|
||||
return true;
|
||||
}
|
||||
|
||||
function handleMessageDelete(msg) {
|
||||
msg.deleted = true;
|
||||
|
||||
updatePinnedMessages.call(this, msg.channel_id, msg.id, msg);
|
||||
|
||||
const channelCache = this._messagesByChannel[msg.channel_id];
|
||||
if (!channelCache || !channelCache.has(msg.id)) return true;
|
||||
|
||||
updateMessages.call(this, msg.channel_id, msg.id, msg);
|
||||
return true;
|
||||
}
|
||||
|
||||
function handleMessageDeleteBulk(msg) {
|
||||
const channelCache = this._messagesByChannel[msg.channel_id];
|
||||
if (!channelCache) return true;
|
||||
|
||||
const update = { deleted: true };
|
||||
|
||||
msg.ids.forEach(id => {
|
||||
updatePinnedMessages.call(this, msg.channel_id, id, update);
|
||||
|
||||
if (!channelCache.has(id)) return;
|
||||
updateMessages.call(this, msg.channel_id, id, update);
|
||||
});
|
||||
return true;
|
||||
}
|
||||
|
||||
function handleReaction(reaction, e) {
|
||||
const channelCache = this._messagesByChannel[reaction.channel_id];
|
||||
if (!channelCache) return true;
|
||||
|
||||
const localUser = this._discordie._user || {};
|
||||
const me = (localUser.id == reaction.user_id);
|
||||
|
||||
var message = channelCache.get(reaction.message_id);
|
||||
if (!message) return true;
|
||||
|
||||
const emoji = reaction.emoji;
|
||||
const idx = message.reactions
|
||||
.findIndex(r => r.emoji.id === emoji.id && r.emoji.name == emoji.name);
|
||||
const old = message.reactions[idx];
|
||||
|
||||
if (e.type === Events.MESSAGE_REACTION_ADD) {
|
||||
if (!message.reactions) {
|
||||
message = message.merge({reactions: []});
|
||||
channelCache.set(reaction.message_id, message);
|
||||
}
|
||||
|
||||
if (old) {
|
||||
old.count += 1;
|
||||
if (me) old.me = true;
|
||||
} else {
|
||||
message.reactions.push({emoji, me, count: 1});
|
||||
}
|
||||
}
|
||||
|
||||
if (e.type === Events.MESSAGE_REACTION_REMOVE) {
|
||||
if (old) {
|
||||
old.count -= 1;
|
||||
if (me) old.me = false;
|
||||
if (old.count <= 0) message.reactions.splice(idx, 1);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
function handleReactionRemoveAll(reaction, e) {
|
||||
const channelCache = this._messagesByChannel[reaction.channel_id];
|
||||
if (!channelCache) return true;
|
||||
|
||||
const message = channelCache.get(reaction.message_id);
|
||||
if (!message) return true;
|
||||
|
||||
if (!message.reactions || !message.reactions.length) return true;
|
||||
|
||||
e.data._cached = message.reactions;
|
||||
channelCache.set(reaction.message_id, message.merge({reactions: []}));
|
||||
}
|
||||
|
||||
function handleConnectionOpen(data) {
|
||||
this.purgeAllCache();
|
||||
}
|
||||
|
||||
function handleCleanup() {
|
||||
for (let channelId in this._messagesByChannel) {
|
||||
if (!this._messagesByChannel.hasOwnProperty(channelId)) continue;
|
||||
if (this._discordie._channels.get(channelId)) continue;
|
||||
|
||||
var messageIds = this._messagesByChannel[channelId]._keys;
|
||||
for (var i = 0, len = messageIds.length; i < len; i++)
|
||||
delete this._messageEdits[messageIds[i]];
|
||||
|
||||
delete this._pinnedMessagesByChannel[channelId];
|
||||
delete this._messagesByChannel[channelId];
|
||||
delete this._hasMoreByChannel[channelId];
|
||||
}
|
||||
}
|
||||
|
||||
function handleLoadedMoreMessages(e) {
|
||||
var messagesLength = e.messages.length;
|
||||
if (!messagesLength) return;
|
||||
|
||||
const channelId = e.messages[0].channel_id;
|
||||
if (!e.before && !e.after) {
|
||||
this._hasMoreByChannel[channelId] = (e.limit == messagesLength);
|
||||
}
|
||||
|
||||
const messages = getOrCreateChannelCache.call(this, channelId);
|
||||
|
||||
const limit = messages.limit;
|
||||
messages.setLimit(limit + messagesLength);
|
||||
|
||||
var i = messagesLength;
|
||||
while (i--) {
|
||||
var msg = e.messages[i];
|
||||
updateMessages.call(this, msg.channel_id, msg.id, msg);
|
||||
}
|
||||
|
||||
messages.setLimit(Math.max(messages.size + 500, limit));
|
||||
// increase channel cache limits
|
||||
// in case new messages arrive and invalidate old message references
|
||||
}
|
||||
|
||||
function handleLoadedPinnedMessages(e) {
|
||||
const channelId = e.channelId;
|
||||
const channelPinned =
|
||||
this._pinnedMessagesByChannel[channelId] =
|
||||
this._pinnedMessagesByChannel[channelId] || [];
|
||||
|
||||
var messagesLength = e.messages.length;
|
||||
if (!messagesLength) return;
|
||||
|
||||
const channelCache = this._messagesByChannel[channelId];
|
||||
e.messages.forEach(msg => {
|
||||
const cached = channelCache ? channelCache.get(msg.id) : null;
|
||||
channelPinned.push(cached || new Message(msg));
|
||||
});
|
||||
}
|
||||
|
||||
class MessageCollection {
|
||||
constructor(discordie, gateway) {
|
||||
if (typeof gateway !== "function")
|
||||
throw new Error("Gateway parameter must be a function");
|
||||
|
||||
discordie.Dispatcher.on(Events.GATEWAY_DISPATCH, e => {
|
||||
if (e.socket != gateway()) return;
|
||||
|
||||
Utils.bindGatewayEventHandlers(this, e, {
|
||||
READY: handleConnectionOpen,
|
||||
MESSAGE_CREATE: handleMessageCreate,
|
||||
MESSAGE_UPDATE: handleMessageUpdate,
|
||||
MESSAGE_DELETE: handleMessageDelete,
|
||||
MESSAGE_DELETE_BULK: handleMessageDeleteBulk,
|
||||
CHANNEL_DELETE: handleCleanup,
|
||||
GUILD_DELETE: handleCleanup,
|
||||
MESSAGE_REACTION_ADD: handleReaction,
|
||||
MESSAGE_REACTION_REMOVE: handleReaction,
|
||||
MESSAGE_REACTION_REMOVE_ALL: handleReactionRemoveAll
|
||||
});
|
||||
});
|
||||
|
||||
discordie.Dispatcher.on(Events.LOADED_MORE_MESSAGES,
|
||||
handleLoadedMoreMessages.bind(this));
|
||||
|
||||
discordie.Dispatcher.on(Events.LOADED_PINNED_MESSAGES,
|
||||
handleLoadedPinnedMessages.bind(this));
|
||||
|
||||
this.purgeAllCache();
|
||||
this._messageLimit = 1000;
|
||||
this._editsLimit = 50;
|
||||
|
||||
this._discordie = discordie;
|
||||
Utils.privatify(this);
|
||||
}
|
||||
|
||||
getChannelMessageLimit(channelId) {
|
||||
if (!this._discordie._channels.get(channelId)) return -1;
|
||||
if (!this._messagesByChannel.hasOwnProperty(channelId)) return -1;
|
||||
return this._messagesByChannel[channelId].limit;
|
||||
}
|
||||
setChannelMessageLimit(channelId, limit) {
|
||||
if (!limit) return false;
|
||||
if (!this._discordie._channels.get(channelId)) return false;
|
||||
const messages = getOrCreateChannelCache.call(this, channelId);
|
||||
messages.setLimit(limit);
|
||||
return true;
|
||||
}
|
||||
|
||||
getMessageLimit() { return this._messageLimit; }
|
||||
setMessageLimit(limit) {
|
||||
if (!limit) return;
|
||||
if (!(limit > 0)) limit = 1;
|
||||
var keys = Object.keys(this._messagesByChannel);
|
||||
for (var i = 0, len = keys.length; i < len; i++) {
|
||||
var cache = this._messagesByChannel[keys[i]];
|
||||
// decrease only for channels with default limit
|
||||
if (!cache) continue;
|
||||
if (cache.limit != this._messageLimit && limit < cache.limit)
|
||||
continue;
|
||||
var removed = cache.setLimit(limit);
|
||||
if (!removed) continue;
|
||||
for (var messageId of removed)
|
||||
delete this._messageEdits[messageId];
|
||||
}
|
||||
this._messageLimit = limit;
|
||||
}
|
||||
|
||||
getEditsLimit() { return this._editsLimit; }
|
||||
setEditsLimit(limit) {
|
||||
if (!limit) return;
|
||||
if (!(limit > 0)) limit = 1;
|
||||
this._editsLimit = limit;
|
||||
trimEdits.call(this);
|
||||
}
|
||||
|
||||
*getIterator() {
|
||||
for (var channelId in this._messagesByChannel) {
|
||||
if (!this._messagesByChannel.hasOwnProperty(channelId)) continue;
|
||||
if (!this._discordie._channels.get(channelId)) continue;
|
||||
var channelMessages = this._messagesByChannel[channelId];
|
||||
var keys = channelMessages._keys;
|
||||
for (var i = 0, len = keys.length; i < len; i++) {
|
||||
var message = channelMessages.get(keys[i]);
|
||||
if (message) yield message;
|
||||
}
|
||||
}
|
||||
}
|
||||
get(messageId) {
|
||||
for (var channelId in this._messagesByChannel) {
|
||||
if (!this._messagesByChannel.hasOwnProperty(channelId)) continue;
|
||||
if (!this._discordie._channels.get(channelId)) continue;
|
||||
var channelMessages = this._messagesByChannel[channelId];
|
||||
var message = channelMessages.get(messageId);
|
||||
if (message) return message;
|
||||
}
|
||||
for (var channelId in this._pinnedMessagesByChannel) {
|
||||
if (!this._pinnedMessagesByChannel.hasOwnProperty(channelId)) continue;
|
||||
if (!this._discordie._channels.get(channelId)) continue;
|
||||
var channelPinned = this._pinnedMessagesByChannel[channelId];
|
||||
var message = channelPinned.find(msg => msg.id === messageId);
|
||||
if (message) return message;
|
||||
}
|
||||
}
|
||||
|
||||
getChannelCache(channelId) {
|
||||
if (!this._discordie._channels.get(channelId)) return null;
|
||||
if (!this._messagesByChannel.hasOwnProperty(channelId)) return null;
|
||||
return this._messagesByChannel[channelId];
|
||||
}
|
||||
purgeChannelCache(channelId) {
|
||||
delete this._hasMoreByChannel[channelId];
|
||||
delete this._messagesByChannel[channelId];
|
||||
}
|
||||
|
||||
getChannelPinned(channelId) {
|
||||
if (!this._discordie._channels.get(channelId)) return null;
|
||||
if (!this._pinnedMessagesByChannel.hasOwnProperty(channelId)) return null;
|
||||
return this._pinnedMessagesByChannel[channelId];
|
||||
}
|
||||
purgeChannelPinned(channelId) {
|
||||
delete this._pinnedMessagesByChannel[channelId];
|
||||
}
|
||||
purgePinned() {
|
||||
this._pinnedMessagesByChannel = {};
|
||||
}
|
||||
|
||||
getEdits(messageId) {
|
||||
var edits = this._messageEdits[messageId];
|
||||
return edits ? edits.slice().reverse() : [];
|
||||
}
|
||||
purgeEdits() {
|
||||
this._messageEdits = {};
|
||||
}
|
||||
|
||||
purgeAllCache() {
|
||||
this._messagesByChannel = {};
|
||||
this._hasMoreByChannel = {};
|
||||
this.purgeEdits();
|
||||
this.purgePinned();
|
||||
}
|
||||
|
||||
create(message) {
|
||||
handleMessageCreate.call(this, message);
|
||||
}
|
||||
update(message) {
|
||||
handleMessageUpdate.call(this, message);
|
||||
}
|
||||
channelHasMore(channelId) {
|
||||
if (this._hasMoreByChannel[channelId] === undefined)
|
||||
return true;
|
||||
return this._hasMoreByChannel[channelId];
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = MessageCollection;
|
162
node_modules/discordie/lib/collections/PresenceCollection.js
generated
vendored
Normal file
162
node_modules/discordie/lib/collections/PresenceCollection.js
generated
vendored
Normal file
@ -0,0 +1,162 @@
|
||||
"use strict";
|
||||
|
||||
const Constants = require("../Constants");
|
||||
const Events = Constants.Events;
|
||||
const StatusTypes = Constants.StatusTypes;
|
||||
const Utils = require("../core/Utils");
|
||||
const BaseCollection = require("./BaseCollection");
|
||||
|
||||
const User = require("../models/User");
|
||||
|
||||
function updatePresence(guildId, userId, status, game) {
|
||||
if (userId === this._discordie._user.id) return;
|
||||
|
||||
// ignore friend list presences (without `guild_id`)
|
||||
if (!guildId) return;
|
||||
|
||||
// get presences in all guilds
|
||||
var presencesForUser =
|
||||
(this._presencesForGuilds[userId] =
|
||||
this._presencesForGuilds[userId] || {});
|
||||
|
||||
var previousPresencesForUser =
|
||||
(this._previousPresencesForGuilds[userId] =
|
||||
this._previousPresencesForGuilds[userId] || {});
|
||||
|
||||
var previousPresence = presencesForUser[guildId];
|
||||
|
||||
// copy current to previous
|
||||
previousPresencesForUser[guildId] =
|
||||
Object.assign(previousPresencesForUser[guildId] || {}, previousPresence);
|
||||
|
||||
if (!previousPresence)
|
||||
delete previousPresencesForUser[guildId];
|
||||
|
||||
if (status === StatusTypes.OFFLINE) {
|
||||
// delete current presence cache if user is not online anymore
|
||||
delete presencesForUser[guildId];
|
||||
if (!Object.keys(presencesForUser).length) {
|
||||
delete this._presencesForGuilds[userId];
|
||||
}
|
||||
delete this._statuses[userId];
|
||||
delete this._games[userId];
|
||||
} else {
|
||||
// set current presence
|
||||
presencesForUser[guildId] = {status, game};
|
||||
|
||||
// update global status and game (for user statuses in DM list)
|
||||
this._statuses[userId] = status;
|
||||
this._games[userId] = game || null;
|
||||
}
|
||||
}
|
||||
|
||||
function initializeCache() {
|
||||
this._presencesForGuilds = {};
|
||||
this._previousPresencesForGuilds = {};
|
||||
this._statuses = {};
|
||||
this._games = {};
|
||||
}
|
||||
|
||||
function handleConnectionOpen(data) {
|
||||
initializeCache.call(this);
|
||||
data.guilds.forEach(guild => handleGuildCreate.call(this, guild));
|
||||
return true;
|
||||
}
|
||||
|
||||
function handleGuildCreate(guild) {
|
||||
if (!guild || guild.unavailable) return true;
|
||||
guild.presences.forEach(presence => {
|
||||
updatePresence.call(this,
|
||||
guild.id,
|
||||
presence.user.id,
|
||||
presence.status,
|
||||
presence.game
|
||||
);
|
||||
});
|
||||
return true;
|
||||
}
|
||||
|
||||
function handleGuildDelete(guild) {
|
||||
for (let userId of Object.keys(this._presencesForGuilds)) {
|
||||
if (!this._presencesForGuilds[userId][guild.id]) continue;
|
||||
updatePresence.call(this, guild.id, userId, StatusTypes.OFFLINE, null);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
function handlePresenceUpdate(presence) {
|
||||
updatePresence.call(this,
|
||||
presence.guild_id,
|
||||
presence.user.id,
|
||||
presence.status,
|
||||
presence.game
|
||||
);
|
||||
return true;
|
||||
}
|
||||
|
||||
function getPresence(collection, userId, guildId) {
|
||||
if (collection.hasOwnProperty(userId)) {
|
||||
const presencesForUser = collection[userId];
|
||||
guildId = guildId || Object.keys(presencesForUser)[0];
|
||||
if (presencesForUser.hasOwnProperty(guildId)) {
|
||||
return presencesForUser[guildId];
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
class PresenceCollection {
|
||||
constructor(discordie, gateway) {
|
||||
if (typeof gateway !== "function")
|
||||
throw new Error("Gateway parameter must be a function");
|
||||
|
||||
discordie.Dispatcher.on(Events.GATEWAY_DISPATCH, e => {
|
||||
if (e.socket != gateway()) return;
|
||||
|
||||
Utils.bindGatewayEventHandlers(this, e, {
|
||||
READY: handleConnectionOpen,
|
||||
GUILD_SYNC: handleGuildCreate,
|
||||
GUILD_CREATE: handleGuildCreate,
|
||||
GUILD_DELETE: handleGuildDelete,
|
||||
PRESENCE_UPDATE: handlePresenceUpdate
|
||||
});
|
||||
});
|
||||
|
||||
initializeCache.call(this);
|
||||
|
||||
this._discordie = discordie;
|
||||
Utils.privatify(this);
|
||||
}
|
||||
getStatus(userId, guildId) {
|
||||
if (this._discordie._user && this._discordie._user.id == userId) {
|
||||
return this._discordie._user.status;
|
||||
}
|
||||
const presence = getPresence.call(this,
|
||||
this._presencesForGuilds, userId, guildId
|
||||
) || {};
|
||||
return presence.status || StatusTypes.OFFLINE;
|
||||
}
|
||||
getPreviousStatus(userId, guildId) {
|
||||
const presence = getPresence.call(this,
|
||||
this._previousPresencesForGuilds, userId, guildId
|
||||
) || {};
|
||||
return presence.status || StatusTypes.OFFLINE;
|
||||
}
|
||||
getGame(userId, guildId) {
|
||||
if (this._discordie._user && this._discordie._user.id == userId) {
|
||||
return this._discordie._user.game;
|
||||
}
|
||||
const presence = getPresence.call(this,
|
||||
this._presencesForGuilds, userId, guildId
|
||||
) || {};
|
||||
return presence.game || null;
|
||||
}
|
||||
getPreviousGame(userId, guildId) {
|
||||
const presence = getPresence.call(this,
|
||||
this._previousPresencesForGuilds, userId, guildId
|
||||
) || {};
|
||||
return presence.game || null;
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = PresenceCollection;
|
135
node_modules/discordie/lib/collections/UnavailableGuildCollection.js
generated
vendored
Normal file
135
node_modules/discordie/lib/collections/UnavailableGuildCollection.js
generated
vendored
Normal file
@ -0,0 +1,135 @@
|
||||
"use strict";
|
||||
|
||||
const Constants = require("../Constants");
|
||||
const Events = Constants.Events;
|
||||
const Utils = require("../core/Utils");
|
||||
const BaseArrayCollection = require("./BaseArrayCollection");
|
||||
|
||||
const GUILD_STREAMING_TIMEOUT = 3000;
|
||||
|
||||
function emitReady(gw) {
|
||||
const timedOut = Array.from(this._streamingGuilds);
|
||||
this._streamingGuilds.clear();
|
||||
|
||||
this._discordie.Dispatcher.emit(Events.COLLECTION_READY, {
|
||||
socket: gw,
|
||||
name: this.constructor.name,
|
||||
collection: this
|
||||
});
|
||||
|
||||
if (!timedOut.length) return;
|
||||
timedOut.forEach(id => {
|
||||
this._discordie.Dispatcher.emit(Events.GUILD_UNAVAILABLE, {
|
||||
socket: gw,
|
||||
guildId: id
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function scheduleReadyTimeout(gw) {
|
||||
this._streamingGuildsTimeout = setTimeout(() => {
|
||||
this._streamingGuildsTimeout = null;
|
||||
if (!this._discordie.connected) return;
|
||||
|
||||
setImmediate(() => emitReady.call(this, gw));
|
||||
}, GUILD_STREAMING_TIMEOUT);
|
||||
}
|
||||
|
||||
function maybeReady(gw) {
|
||||
if (this._streamingGuildsTimeout) {
|
||||
clearTimeout(this._streamingGuildsTimeout);
|
||||
}
|
||||
if (this._streamingGuilds.size) {
|
||||
scheduleReadyTimeout.call(this, gw);
|
||||
} else {
|
||||
setImmediate(() => emitReady.call(this, gw));
|
||||
}
|
||||
}
|
||||
|
||||
function handleConnectionOpen(data, e) {
|
||||
clearCollections.call(this);
|
||||
|
||||
data.guilds.forEach(guild => {
|
||||
if (!guild.unavailable) return;
|
||||
addUnavailable.call(this, guild.id);
|
||||
this._streamingGuilds.add(guild.id);
|
||||
});
|
||||
|
||||
maybeReady.call(this, e.socket);
|
||||
return true;
|
||||
}
|
||||
|
||||
function handleGuildCreate(guild, e) {
|
||||
handleUnavailable.call(this, guild);
|
||||
|
||||
if (this.isGuildAvailable(guild) && this._streamingGuilds.has(guild.id)) {
|
||||
e.suppress = true;
|
||||
this._streamingGuilds.delete(guild.id);
|
||||
|
||||
maybeReady.call(this, e.socket);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
function handleGuildDelete(guild) {
|
||||
handleUnavailable.call(this, guild);
|
||||
return true;
|
||||
}
|
||||
|
||||
function handleUnavailable(guild) {
|
||||
if (guild.unavailable) {
|
||||
addUnavailable.call(this, guild.id)
|
||||
} else {
|
||||
removeUnavailable.call(this, guild.id);
|
||||
}
|
||||
}
|
||||
|
||||
function addUnavailable(id) {
|
||||
if (this._set.has(id)) return;
|
||||
this._set.add(id);
|
||||
|
||||
this.push(id);
|
||||
}
|
||||
function removeUnavailable(id) {
|
||||
if (!this._set.has(id)) return;
|
||||
this._set.delete(id);
|
||||
|
||||
var idx = this.indexOf(id);
|
||||
this.splice(idx, 1);
|
||||
}
|
||||
function clearCollections() {
|
||||
this._streamingGuilds.clear();
|
||||
this._set.clear();
|
||||
this.length = 0;
|
||||
}
|
||||
|
||||
class UnavailableGuildCollection extends BaseArrayCollection {
|
||||
static _constructor(discordie, gateway) {
|
||||
if (typeof gateway !== "function")
|
||||
throw new Error("Gateway parameter must be a function");
|
||||
|
||||
discordie.Dispatcher.on(Events.GATEWAY_DISPATCH, e => {
|
||||
if (e.socket != gateway()) return;
|
||||
|
||||
Utils.bindGatewayEventHandlers(this, e, {
|
||||
READY: handleConnectionOpen,
|
||||
GUILD_CREATE: handleGuildCreate,
|
||||
GUILD_DELETE: handleGuildDelete,
|
||||
});
|
||||
});
|
||||
|
||||
this._discordie = discordie;
|
||||
this._set = new Set();
|
||||
|
||||
this._streamingGuilds = new Set();
|
||||
this._streamingGuildsTimeout = null;
|
||||
|
||||
Utils.privatify(this);
|
||||
}
|
||||
isGuildAvailable(guild) {
|
||||
// unavailable guilds that became available have key `unavailable`
|
||||
return guild.unavailable === false;
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = UnavailableGuildCollection;
|
191
node_modules/discordie/lib/collections/UserCollection.js
generated
vendored
Normal file
191
node_modules/discordie/lib/collections/UserCollection.js
generated
vendored
Normal file
@ -0,0 +1,191 @@
|
||||
"use strict";
|
||||
|
||||
const Constants = require("../Constants");
|
||||
const Events = Constants.Events;
|
||||
const Utils = require("../core/Utils");
|
||||
const BaseCollection = require("./BaseCollection");
|
||||
|
||||
const User = require("../models/User");
|
||||
const AuthenticatedUser = require("../models/AuthenticatedUser");
|
||||
|
||||
function handleConnectionOpen(data) {
|
||||
this.clear();
|
||||
this.set(data.user.id, new AuthenticatedUser(data.user));
|
||||
|
||||
data.guilds.forEach(guild => {
|
||||
if (guild.unavailable) return;
|
||||
guild.members.forEach(member => {
|
||||
if (member.user.id == data.user.id) return;
|
||||
this.set(member.user.id, new User(member.user));
|
||||
});
|
||||
});
|
||||
|
||||
data.private_channels.forEach(channel => {
|
||||
if (!channel.recipients) return;
|
||||
channel.recipients.forEach(u => {
|
||||
if (u.id === data.user.id) return;
|
||||
this.set(u.id, new User(u));
|
||||
});
|
||||
});
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
function handleUpdateUser(user) {
|
||||
const cachedUser = this._discordie._user;
|
||||
delete user.token;
|
||||
this._discordie._user = new AuthenticatedUser(
|
||||
cachedUser ? cachedUser.merge(user) : user
|
||||
);
|
||||
this.mergeOrSet(user.id, this._discordie._user);
|
||||
return true;
|
||||
}
|
||||
|
||||
function handleLoadedMoreOrPinnedMessages(e) {
|
||||
e.messages.forEach(message => {
|
||||
this.mergeOrSet(message.author.id, new User(message.author));
|
||||
message.mentions.forEach(mention => {
|
||||
this.mergeOrSet(mention.id, new User(mention));
|
||||
});
|
||||
});
|
||||
return true;
|
||||
}
|
||||
|
||||
function handleIncomingMessage(message) {
|
||||
if (message.author) {
|
||||
this.mergeOrSet(message.author.id, new User(message.author));
|
||||
}
|
||||
if (message.mentions) {
|
||||
message.mentions.forEach(mention => {
|
||||
this.mergeOrSet(mention.id, new User(mention));
|
||||
});
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
function handleCreateOrUpdateChannel(channel) {
|
||||
if (channel.recipient) {
|
||||
this.mergeOrSet(channel.recipient.id, new User(channel.recipient));
|
||||
}
|
||||
if (channel.recipients) {
|
||||
channel.recipients.forEach(u => this.mergeOrSet(u.id, new User(u)));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
function handlePresenceUpdate(presence, e) {
|
||||
if (!presence.user || !presence.user.id) return true;
|
||||
|
||||
const cachedUser = this.get(presence.user.id);
|
||||
if (!cachedUser) {
|
||||
// update 2015-10-22:
|
||||
// Discord client now creates local GUILD_MEMBER_ADD event
|
||||
// update 2015-12-01:
|
||||
// Discord client creates local GUILD_MEMBER_ADD event only for
|
||||
// online users with `user.username != null`
|
||||
this.set(presence.user.id, new User(presence.user));
|
||||
return true;
|
||||
}
|
||||
|
||||
const replacer = (hasChanges, key) => {
|
||||
if (presence.user.hasOwnProperty(key)) {
|
||||
hasChanges = hasChanges ||
|
||||
(cachedUser[key] != presence.user[key]);
|
||||
}
|
||||
return hasChanges;
|
||||
};
|
||||
const hasChanges =
|
||||
["username", "avatar", "discriminator"].reduce(replacer, false);
|
||||
|
||||
if (hasChanges) {
|
||||
const oldUser = this.get(cachedUser.id);
|
||||
this.mergeOrSet(cachedUser.id, new User(presence.user));
|
||||
const newUser = this.get(cachedUser.id);
|
||||
|
||||
this._discordie.Dispatcher.emit(Events.PRESENCE_MEMBER_INFO_UPDATE, {
|
||||
socket: e.socket,
|
||||
old: oldUser,
|
||||
new: newUser
|
||||
});
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
function handleLoadedGuildBans(bans) {
|
||||
bans.forEach(ban => {
|
||||
this.mergeOrSet(ban.user.id, new User(ban.user));
|
||||
});
|
||||
}
|
||||
|
||||
function handleBanOrMember(member) {
|
||||
this.mergeOrSet(member.user.id, new User(member.user));
|
||||
return true;
|
||||
}
|
||||
|
||||
function handleGuildCreate(guild) {
|
||||
if (!guild || guild.unavailable) return true;
|
||||
guild.members.forEach(member => {
|
||||
if (this._discordie._user.id == member.user.id) return;
|
||||
this.mergeOrSet(member.user.id, new User(member.user));
|
||||
});
|
||||
return true;
|
||||
}
|
||||
|
||||
function handleGuildMembersChunk(chunk) {
|
||||
if (!chunk.members) return true;
|
||||
handleGuildCreate.call(this, chunk);
|
||||
return true;
|
||||
}
|
||||
|
||||
class UserCollection extends BaseCollection {
|
||||
constructor(discordie, gateway) {
|
||||
super();
|
||||
|
||||
if (typeof gateway !== "function")
|
||||
throw new Error("Gateway parameter must be a function");
|
||||
|
||||
discordie.Dispatcher.on(Events.GATEWAY_DISPATCH, e => {
|
||||
if (e.socket != gateway()) return;
|
||||
|
||||
Utils.bindGatewayEventHandlers(this, e, {
|
||||
READY: handleConnectionOpen,
|
||||
USER_UPDATE: handleUpdateUser,
|
||||
PRESENCE_UPDATE: handlePresenceUpdate,
|
||||
MESSAGE_CREATE: handleIncomingMessage,
|
||||
MESSAGE_UPDATE: handleIncomingMessage,
|
||||
GUILD_SYNC: handleGuildCreate,
|
||||
GUILD_CREATE: handleGuildCreate,
|
||||
GUILD_BAN_ADD: handleBanOrMember,
|
||||
GUILD_BAN_REMOVE: handleBanOrMember,
|
||||
GUILD_MEMBER_ADD: handleBanOrMember,
|
||||
GUILD_MEMBER_REMOVE: handleBanOrMember,
|
||||
CHANNEL_RECIPIENT_ADD: handleBanOrMember,
|
||||
CHANNEL_RECIPIENT_REMOVE: handleBanOrMember,
|
||||
CHANNEL_CREATE: handleCreateOrUpdateChannel,
|
||||
CHANNEL_UPDATE: handleCreateOrUpdateChannel,
|
||||
GUILD_MEMBERS_CHUNK: handleGuildMembersChunk
|
||||
});
|
||||
});
|
||||
|
||||
discordie.Dispatcher.on(Events.LOADED_MORE_MESSAGES,
|
||||
handleLoadedMoreOrPinnedMessages.bind(this));
|
||||
|
||||
discordie.Dispatcher.on(Events.LOADED_PINNED_MESSAGES,
|
||||
handleLoadedMoreOrPinnedMessages.bind(this));
|
||||
|
||||
discordie.Dispatcher.on(Events.LOADED_GUILD_BANS,
|
||||
handleLoadedGuildBans.bind(this));
|
||||
|
||||
this._discordie = discordie;
|
||||
Utils.privatify(this);
|
||||
}
|
||||
updateAuthenticatedUser(user) {
|
||||
handleUpdateUser.call(this, user);
|
||||
}
|
||||
update(user) {
|
||||
this.mergeOrSet(user.id, new User(user));
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = UserCollection;
|
273
node_modules/discordie/lib/collections/VoiceConnectionCollection.js
generated
vendored
Normal file
273
node_modules/discordie/lib/collections/VoiceConnectionCollection.js
generated
vendored
Normal file
@ -0,0 +1,273 @@
|
||||
"use strict";
|
||||
|
||||
const Constants = require("../Constants");
|
||||
const Errors = Constants.Errors;
|
||||
const Events = Constants.Events;
|
||||
const Utils = require("../core/Utils");
|
||||
const BaseArrayCollection = require("./BaseArrayCollection");
|
||||
const IVoiceConnection = require("../interfaces/IVoiceConnection");
|
||||
|
||||
/**
|
||||
* @class
|
||||
*/
|
||||
class VoiceConnectionInfo {
|
||||
constructor(gatewaySocket, voiceSocket, voiceConnection) {
|
||||
/**
|
||||
* @instance
|
||||
* @memberOf VoiceConnectionInfo
|
||||
* @name gatewaySocket
|
||||
* @returns {GatewaySocket}
|
||||
*/
|
||||
this.gatewaySocket = gatewaySocket;
|
||||
|
||||
/**
|
||||
* @instance
|
||||
* @memberOf VoiceConnectionInfo
|
||||
* @name voiceSocket
|
||||
* @returns {VoiceSocket}
|
||||
*/
|
||||
this.voiceSocket = voiceSocket;
|
||||
|
||||
/**
|
||||
* @instance
|
||||
* @memberOf VoiceConnectionInfo
|
||||
* @name voiceConnection
|
||||
* @returns {IVoiceConnection}
|
||||
*/
|
||||
this.voiceConnection = voiceConnection;
|
||||
Object.freeze(this);
|
||||
}
|
||||
}
|
||||
|
||||
class VoiceConnectionCollection extends BaseArrayCollection {
|
||||
static _constructor(discordie, primaryGateway) {
|
||||
this._gateways = new Set();
|
||||
|
||||
this._pendingConnections = new Map();
|
||||
// handle pending disconnects first to avoid firing a rejected pending
|
||||
discordie.Dispatcher.on(Events.VOICESOCKET_DISCONNECT, e => {
|
||||
var voiceSocket = e.socket;
|
||||
var gatewaySocket = e.socket.gatewaySocket;
|
||||
|
||||
var guildId = voiceSocket.guildId;
|
||||
|
||||
const awaitingEndpoint =
|
||||
e.error && e.error.message == Errors.VOICE_CHANGING_SERVER;
|
||||
|
||||
if (awaitingEndpoint) {
|
||||
this._createPending(guildId);
|
||||
} else {
|
||||
var pending = this._pendingConnections.get(guildId);
|
||||
if (!pending) return;
|
||||
|
||||
gatewaySocket.disconnectVoice(guildId);
|
||||
|
||||
this._pendingConnections.delete(guildId);
|
||||
e ? pending.reject(e.error) : pending.reject();
|
||||
}
|
||||
});
|
||||
|
||||
// process voice connections
|
||||
discordie.Dispatcher.on(Events.VOICE_SESSION_DESCRIPTION, e => {
|
||||
const gw = e.socket.gatewaySocket;
|
||||
const voicews = e.socket;
|
||||
|
||||
const voiceConnection = new IVoiceConnection(discordie, gw, voicews);
|
||||
this.push(new VoiceConnectionInfo(gw, voicews, voiceConnection));
|
||||
|
||||
discordie.Dispatcher.emit(Events.VOICE_CONNECTED, {
|
||||
socket: voicews,
|
||||
voiceConnection: voiceConnection
|
||||
});
|
||||
});
|
||||
discordie.Dispatcher.on(Events.VOICESOCKET_DISCONNECT, e => {
|
||||
const idx = this.findIndex(c => c.voiceSocket == e.socket);
|
||||
if (idx < 0) return;
|
||||
|
||||
var info = this[idx];
|
||||
|
||||
// delete from this array
|
||||
this.splice(idx, 1);
|
||||
|
||||
var guildId = info.voiceSocket.guildId;
|
||||
|
||||
const awaitingEndpoint =
|
||||
e.error && e.error.message == Errors.VOICE_CHANGING_SERVER;
|
||||
|
||||
const manual =
|
||||
e.error && e.error.message == Errors.VOICE_MANUAL_DISCONNECT;
|
||||
|
||||
const endpointAwait =
|
||||
awaitingEndpoint ? this._createPending(guildId) : null;
|
||||
|
||||
discordie.Dispatcher.emit(Events.VOICE_DISCONNECTED, {
|
||||
socket: info.voiceSocket,
|
||||
voiceConnection: info.voiceConnection,
|
||||
error: (e.error instanceof Error) ? e.error : null,
|
||||
manual, endpointAwait
|
||||
});
|
||||
|
||||
if (guildId && !endpointAwait)
|
||||
info.gatewaySocket.disconnectVoice(guildId);
|
||||
info.voiceConnection.dispose();
|
||||
});
|
||||
|
||||
// resolve promise when we have a voice connection created
|
||||
discordie.Dispatcher.on(Events.VOICE_SESSION_DESCRIPTION, e => {
|
||||
var voiceSocket = e.socket;
|
||||
|
||||
var guildId = voiceSocket.guildId;
|
||||
var pending = this._pendingConnections.get(guildId);
|
||||
if (!pending) return;
|
||||
|
||||
this._pendingConnections.delete(guildId);
|
||||
pending.resolve(this.getForVoiceSocket(voiceSocket));
|
||||
});
|
||||
|
||||
discordie.Dispatcher.on(Events.GATEWAY_DISPATCH, e => {
|
||||
if (e.type === "READY" || e.type === "RESUMED") {
|
||||
this._gateways.add(e.socket);
|
||||
}
|
||||
|
||||
// process edge cases
|
||||
if (e.type === "CALL_DELETE") {
|
||||
const info = this.getForChannel(e.data.channel_id);
|
||||
if (!info) return;
|
||||
if (e.data.unavailable) {
|
||||
info.voiceConnection._disconnect(Errors.VOICE_CALL_UNAVAILABLE);
|
||||
} else {
|
||||
info.voiceConnection._disconnect();
|
||||
}
|
||||
}
|
||||
if (e.type === "GUILD_DELETE") {
|
||||
const info = this.getForGuild(e.data.id);
|
||||
if (!info) return;
|
||||
if (e.data.unavailable) {
|
||||
info.voiceConnection._disconnect(Errors.VOICE_GUILD_UNAVAILABLE);
|
||||
} else {
|
||||
info.voiceConnection._disconnect();
|
||||
}
|
||||
}
|
||||
if (e.type === "CHANNEL_DELETE") {
|
||||
const info = this.getForChannel(e.data.id);
|
||||
if (info) info.voiceConnection._disconnect();
|
||||
}
|
||||
});
|
||||
discordie.Dispatcher.on(Events.GATEWAY_DISCONNECT, e => {
|
||||
Array.from(this._pendingConnections.keys()).forEach(guildId => {
|
||||
var pending = this._pendingConnections.get(guildId);
|
||||
if (!pending) return;
|
||||
this._pendingConnections.delete(guildId);
|
||||
pending.reject(new Error("Gateway disconnected"));
|
||||
});
|
||||
this._gateways.delete(e.socket);
|
||||
});
|
||||
|
||||
this._discordie = discordie;
|
||||
Utils.privatify(this);
|
||||
}
|
||||
_createPending(guildId) {
|
||||
return this._getOrCreate(guildId, null, null, null, true);
|
||||
}
|
||||
_cancelPending(guildId) {
|
||||
let pending = this._pendingConnections.get(guildId);
|
||||
if (!pending) return;
|
||||
this._pendingConnections.delete(guildId);
|
||||
pending.reject(new Error("Cancelled"));
|
||||
}
|
||||
_isPending(guildId) {
|
||||
return this._pendingConnections.get(guildId);
|
||||
}
|
||||
_getOrCreate(guildId, channelId, selfMute, selfDeaf, silent) {
|
||||
const gateway = this._discordie.gatewaySocket;
|
||||
if (!gateway || !gateway.connected)
|
||||
return Promise.reject(new Error("No gateway socket (not connected)"));
|
||||
|
||||
// voiceStateUpdate triggers some events and can update pending connections
|
||||
var newState = {guildId, channelId, selfMute, selfDeaf};
|
||||
if (!silent && this.shouldUpdateVoiceState(newState)) {
|
||||
if (!channelId && this.shouldCancelPending(guildId)) {
|
||||
this._cancelPending(guildId);
|
||||
}
|
||||
gateway.voiceStateUpdate(guildId, channelId, selfMute, selfDeaf);
|
||||
}
|
||||
|
||||
if (!silent && !channelId) return;
|
||||
|
||||
let pending = this._pendingConnections.get(guildId);
|
||||
if (pending) return pending.promise;
|
||||
|
||||
const existing = this.getForGuild(guildId);
|
||||
if (existing) return Promise.resolve(existing);
|
||||
|
||||
pending = {gateway, promise: null, resolve: null, reject: null};
|
||||
this._pendingConnections.set(guildId, pending);
|
||||
|
||||
return (pending.promise = new Promise((rs, rj) => {
|
||||
pending.resolve = rs;
|
||||
pending.reject = rj;
|
||||
}));
|
||||
}
|
||||
getForGuild(guildId) {
|
||||
guildId = guildId ? guildId.valueOf() : null;
|
||||
return this.find(c => c.voiceSocket.guildId == guildId) || null;
|
||||
}
|
||||
getForChannel(channelId) {
|
||||
channelId = channelId.valueOf();
|
||||
for (var gatewaySocket of this._gateways.values()) {
|
||||
for (var voiceState of gatewaySocket.voiceStates.values()) {
|
||||
if (!voiceState || voiceState.channelId !== channelId) continue;
|
||||
return this.getForGuild(voiceState.guildId);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
getForVoiceSocket(voiceSocket) {
|
||||
return this.find(c => c.voiceSocket == voiceSocket) || null;
|
||||
}
|
||||
getForGatewaySocket(gatewaySocket) {
|
||||
return this.find(c => c.gatewaySocket == gatewaySocket) || null;
|
||||
}
|
||||
isLocalSession(sessionId) {
|
||||
return !!Array.from(this._gateways).find(gw => gw.sessionId == sessionId);
|
||||
}
|
||||
shouldUpdateVoiceState(newState) {
|
||||
var guildId = newState.guildId;
|
||||
|
||||
for (var gatewaySocket of this._gateways.values()) {
|
||||
var state = gatewaySocket.voiceStates.get(guildId);
|
||||
if (!state) continue;
|
||||
var hasChanges = Object.keys(state).reduce((r, key) => {
|
||||
return r ||
|
||||
(newState[key] !== undefined && newState[key] != state[key]);
|
||||
}, false);
|
||||
return hasChanges;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
shouldCancelPending(guildId) {
|
||||
// cancel pending connection only if there are no sockets open
|
||||
// otherwise disconnect existing socket and fire VOICESOCKET_DISCONNECT
|
||||
for (var gatewaySocket of this._gateways.values()) {
|
||||
var socket = gatewaySocket.voiceSockets.get(guildId);
|
||||
if (!socket) continue;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
getPendingChannel(guildId) {
|
||||
for (var gatewaySocket of this._gateways.values()) {
|
||||
var state = gatewaySocket.voiceStates.get(guildId);
|
||||
if (!state) continue;
|
||||
return state.channelId;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
cancelIfPending(guildId, channelId) {
|
||||
const pendingChannelId = this.getPendingChannel(guildId);
|
||||
if (pendingChannelId && pendingChannelId === channelId)
|
||||
this._getOrCreate(guildId, null);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = VoiceConnectionCollection;
|
352
node_modules/discordie/lib/collections/VoiceStateCollection.js
generated
vendored
Normal file
352
node_modules/discordie/lib/collections/VoiceStateCollection.js
generated
vendored
Normal file
@ -0,0 +1,352 @@
|
||||
"use strict";
|
||||
|
||||
const Constants = require("../Constants");
|
||||
const StatusTypes = Constants.StatusTypes;
|
||||
const Events = Constants.Events;
|
||||
const Utils = require("../core/Utils");
|
||||
const BaseCollection = require("./BaseCollection");
|
||||
|
||||
const User = require("../models/User");
|
||||
const AuthenticatedUser = require("../models/AuthenticatedUser");
|
||||
|
||||
function getUserStates(userId) {
|
||||
var states = [];
|
||||
var channels = this._channelsForUser.get(userId);
|
||||
if (!channels) return states;
|
||||
Array.from(channels).forEach(channelId => {
|
||||
var userMap = this._usersForChannel.get(channelId);
|
||||
if (!userMap || !userMap.has(userId)) return;
|
||||
states.push(userMap.get(userId));
|
||||
});
|
||||
return states;
|
||||
}
|
||||
function createChangeEvent(state, e) {
|
||||
return {
|
||||
socket: e.socket,
|
||||
user: this._discordie.Users.get(state.user_id),
|
||||
channel:
|
||||
this._discordie.Channels.get(state.channel_id) ||
|
||||
this._discordie.DirectMessageChannels.get(state.channel_id),
|
||||
channelId: state.channel_id,
|
||||
guildId: state.guild_id
|
||||
};
|
||||
}
|
||||
function emitMuteDeafUpdate(type, state, key, e) {
|
||||
var e = createChangeEvent.call(this, state, e);
|
||||
e.state = state[key];
|
||||
this._discordie.Dispatcher.emit(type, e);
|
||||
}
|
||||
function emitChanges(before, after, e) {
|
||||
if (!before.length && !after.length) return;
|
||||
var leave =
|
||||
before.filter(b => !after.find(a => a.channel_id == b.channel_id));
|
||||
var join =
|
||||
after.filter(a => !before.find(b => a.channel_id == b.channel_id));
|
||||
|
||||
var moved = leave.length === 1 && join.length === 1;
|
||||
|
||||
leave.forEach(state => {
|
||||
var event = createChangeEvent.call(this, state, e);
|
||||
event.newChannelId = moved ? join[0].channel_id : null;
|
||||
event.newGuildId = moved ? join[0].guild_id : null;
|
||||
|
||||
this._discordie.Dispatcher.emit(
|
||||
Events.VOICE_CHANNEL_LEAVE,
|
||||
event
|
||||
);
|
||||
});
|
||||
join.forEach(state => {
|
||||
this._discordie.Dispatcher.emit(
|
||||
Events.VOICE_CHANNEL_JOIN,
|
||||
createChangeEvent.call(this, state, e)
|
||||
);
|
||||
});
|
||||
|
||||
if (!leave.length && !join.length) {
|
||||
var sm = after.find(b => before.find(a => a.self_mute != b.self_mute));
|
||||
var sd = after.find(b => before.find(a => a.self_deaf != b.self_deaf));
|
||||
var m = after.find(b => before.find(a => a.mute != b.mute));
|
||||
var d = after.find(b => before.find(a => a.deaf != b.deaf));
|
||||
|
||||
var _emitMuteDeafUpdate = emitMuteDeafUpdate.bind(this);
|
||||
if (sm)_emitMuteDeafUpdate(Events.VOICE_USER_SELF_MUTE, sm, "self_mute", e);
|
||||
if (sd)_emitMuteDeafUpdate(Events.VOICE_USER_SELF_DEAF, sd, "self_deaf", e);
|
||||
if (m) _emitMuteDeafUpdate(Events.VOICE_USER_MUTE, m, "mute", e);
|
||||
if (d) _emitMuteDeafUpdate(Events.VOICE_USER_DEAF, d, "deaf", e);
|
||||
}
|
||||
}
|
||||
function shouldCalculateChanges() {
|
||||
var Dispatcher = this._discordie.Dispatcher;
|
||||
return Dispatcher.hasListeners(Events.VOICE_CHANNEL_JOIN) ||
|
||||
Dispatcher.hasListeners(Events.VOICE_CHANNEL_LEAVE) ||
|
||||
Dispatcher.hasListeners(Events.VOICE_USER_SELF_MUTE) ||
|
||||
Dispatcher.hasListeners(Events.VOICE_USER_SELF_DEAF) ||
|
||||
Dispatcher.hasListeners(Events.VOICE_USER_MUTE) ||
|
||||
Dispatcher.hasListeners(Events.VOICE_USER_DEAF);
|
||||
}
|
||||
|
||||
function getOrCreate(type, target, key) {
|
||||
const _T = target.get(key);
|
||||
const got = _T || new type();
|
||||
if (!_T) target.set(key, got);
|
||||
return got;
|
||||
}
|
||||
|
||||
function speakingDelete(userId, guildId) {
|
||||
if (guildId) {
|
||||
const info = this._discordie.VoiceConnections.getForGuild(guildId);
|
||||
if (!info) return;
|
||||
const speakingSet = this._speakingForVC.get(info.voiceConnection);
|
||||
if (speakingSet) speakingSet.delete(userId);
|
||||
return;
|
||||
}
|
||||
|
||||
for (var speakingSet of this._speakingForVC.values()) {
|
||||
speakingSet.delete(userId);
|
||||
}
|
||||
}
|
||||
|
||||
function ssrcDelete(userId, guildId) {
|
||||
function removeFromMap(ssrcMap) {
|
||||
for (var pair of ssrcMap.entries()) {
|
||||
var ssrc = pair[0];
|
||||
var user = pair[1];
|
||||
if (user == userId) ssrcMap.delete(ssrc);
|
||||
}
|
||||
}
|
||||
|
||||
if (guildId) {
|
||||
const info = this._discordie.VoiceConnections.getForGuild(guildId);
|
||||
if (!info) return;
|
||||
const ssrcMap = this._ssrcForVC.get(info.voiceConnection);
|
||||
if (ssrcMap) removeFromMap(ssrcMap);
|
||||
return;
|
||||
}
|
||||
|
||||
for (var ssrcMap of this._ssrcForVC.values()) {
|
||||
removeFromMap(ssrcMap);
|
||||
}
|
||||
}
|
||||
|
||||
function userDelete(userId, guildId) {
|
||||
var channels = this._channelsForUser.get(userId);
|
||||
if (!channels) return;
|
||||
|
||||
for (var channelId of channels.values()) {
|
||||
var userMap = this._usersForChannel.get(channelId);
|
||||
if (!userMap) continue;
|
||||
|
||||
if (guildId) {
|
||||
var state = userMap.get(userId);
|
||||
if (state.guild_id && state.guild_id !== guildId) continue;
|
||||
}
|
||||
|
||||
userMap.delete(userId);
|
||||
channels.delete(channelId);
|
||||
|
||||
if (!userMap.size) this._usersForChannel.delete(channelId);
|
||||
if (!channels.size) this._channelsForUser.delete(userId);
|
||||
}
|
||||
}
|
||||
function channelDelete(channelId) {
|
||||
var userMap = this._usersForChannel.get(channelId);
|
||||
this._usersForChannel.delete(channelId);
|
||||
if (!userMap) return;
|
||||
|
||||
for (var state of userMap.values()) {
|
||||
var channels = this._channelsForUser.get(state.user_id);
|
||||
channels.delete(state.channel_id);
|
||||
|
||||
if (!channels.size) this._channelsForUser.delete(state.user_id);
|
||||
}
|
||||
}
|
||||
|
||||
function initializeCache() {
|
||||
this._speakingForVC = new Map(); // Map<IVoiceConnection, Map<userId, bool>>
|
||||
this._ssrcForVC = new Map(); // Map<IVoiceConnection, Map<userId, ssrc>>
|
||||
this._usersForChannel = new Map(); // Map<channelId, Map<userId, voiceState>>
|
||||
this._channelsForUser = new Map(); // Map<userId, Set<channelId>>
|
||||
}
|
||||
|
||||
function handleConnectionOpen(data) {
|
||||
initializeCache.call(this);
|
||||
data.guilds.forEach(guild => handleGuildCreate.call(this, guild));
|
||||
return true;
|
||||
}
|
||||
|
||||
function handleGuildCreate(guild) {
|
||||
if (guild.unavailable) return;
|
||||
guild.voice_states.forEach(state => {
|
||||
// states in READY don't contain `guild_id`
|
||||
state.guild_id = guild.id;
|
||||
insertVoiceState.call(this, state);
|
||||
});
|
||||
}
|
||||
|
||||
function handleVoiceStateUpdateChanges(data, e) {
|
||||
// process only if we have event listeners for those events
|
||||
if (!shouldCalculateChanges.call(this)) {
|
||||
handleVoiceStateUpdate.call(this, data);
|
||||
return true;
|
||||
}
|
||||
|
||||
var before = getUserStates.call(this, data.user_id);
|
||||
|
||||
handleVoiceStateUpdate.call(this, data);
|
||||
|
||||
var after = getUserStates.call(this, data.user_id);
|
||||
process.nextTick(() => emitChanges.call(this, before, after, e));
|
||||
return true;
|
||||
}
|
||||
|
||||
function handleVoiceStateUpdate(data) {
|
||||
userDelete.call(this, data.user_id, data.guild_id);
|
||||
if (!data.channel_id) {
|
||||
speakingDelete.call(this, data.user_id, data.guild_id);
|
||||
ssrcDelete.call(this, data.user_id, data.guild_id);
|
||||
return true;
|
||||
}
|
||||
insertVoiceState.call(this, data);
|
||||
return true;
|
||||
}
|
||||
|
||||
function insertVoiceState(data) {
|
||||
getOrCreate(Map, this._usersForChannel, data.channel_id)
|
||||
.set(data.user_id, data);
|
||||
getOrCreate(Set, this._channelsForUser, data.user_id)
|
||||
.add(data.channel_id);
|
||||
}
|
||||
|
||||
function handleVoiceSpeaking(data, voiceSocket) {
|
||||
const info = this._discordie.VoiceConnections.getForVoiceSocket(voiceSocket);
|
||||
if (!info) return true;
|
||||
const vc = info.voiceConnection;
|
||||
|
||||
const speakingSet = getOrCreate(Set, this._speakingForVC, vc);
|
||||
data.speaking ?
|
||||
speakingSet.add(data.user_id) :
|
||||
speakingSet.delete(data.user_id);
|
||||
|
||||
getOrCreate(Map, this._ssrcForVC, vc)
|
||||
.set(data.ssrc, data.user_id);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
function handleChannelDelete(channel, e) {
|
||||
// just silently delete voice states as clients still stay connected to
|
||||
// deleted channels
|
||||
|
||||
//var userMap = this._usersForChannel.get(channel.id);
|
||||
//for (var userId of userMap.keys()) {
|
||||
// var event = createChangeEvent.call(this, {
|
||||
// user_id: userId,
|
||||
// channel_id: channel.id,
|
||||
// guild_id: channel.guild_id
|
||||
// }, e);
|
||||
// event.newChannelId = event.newGuildId = null;
|
||||
//
|
||||
// this._discordie.Dispatcher.emit(Events.VOICE_CHANNEL_LEAVE, event);
|
||||
//}
|
||||
|
||||
channelDelete.call(this, channel.id);
|
||||
return true;
|
||||
}
|
||||
|
||||
function handleGuildDelete(guild) {
|
||||
handleCleanup.call(this);
|
||||
return true;
|
||||
}
|
||||
|
||||
function handleCleanup() {
|
||||
for (var channelId of this._usersForChannel.keys()) {
|
||||
// delete all channel states if channel is no longer in cache
|
||||
if (!this._discordie._channels.get(channelId))
|
||||
channelDelete.call(this, channelId);
|
||||
}
|
||||
}
|
||||
|
||||
function handleCallCreate(call) {
|
||||
if (!call || !call.voice_states) return true;
|
||||
call.voice_states.forEach(state => {
|
||||
state.guild_id = null;
|
||||
insertVoiceState.call(this, state);
|
||||
})
|
||||
}
|
||||
|
||||
function handleCallDelete(call) {
|
||||
if (!call || !call.channel_id) return true;
|
||||
channelDelete.call(this, call.channel_id);
|
||||
}
|
||||
|
||||
class VoiceStateCollection {
|
||||
constructor(discordie, gateway) {
|
||||
if (typeof gateway !== "function")
|
||||
throw new Error("Gateway parameter must be a function");
|
||||
|
||||
discordie.Dispatcher.on(Events.GATEWAY_DISPATCH, e => {
|
||||
if (e.socket != gateway()) return;
|
||||
|
||||
Utils.bindGatewayEventHandlers(this, e, {
|
||||
READY: handleConnectionOpen,
|
||||
GUILD_CREATE: handleGuildCreate,
|
||||
GUILD_DELETE: handleGuildDelete,
|
||||
CHANNEL_DELETE: handleChannelDelete,
|
||||
VOICE_STATE_UPDATE: handleVoiceStateUpdateChanges,
|
||||
CALL_CREATE: handleCallCreate,
|
||||
CALL_DELETE: handleCallDelete
|
||||
});
|
||||
});
|
||||
discordie.Dispatcher.on(Events.VOICE_SPEAKING, e => {
|
||||
if (handleVoiceSpeaking.call(this, e.data, e.socket))
|
||||
e.handled = true;
|
||||
|
||||
if (e.data && e.data.user_id) {
|
||||
const user = this._discordie.Users.get(e.data.user_id);
|
||||
if (user) e.user = user;
|
||||
|
||||
const info = discordie.VoiceConnections.getForVoiceSocket(e.socket);
|
||||
if (info) e.voiceConnection = info.voiceConnection;
|
||||
}
|
||||
});
|
||||
discordie.Dispatcher.on(Events.VOICE_DISCONNECTED, e => {
|
||||
this._speakingForVC.delete(e.voiceConnection);
|
||||
this._ssrcForVC.delete(e.voiceConnection);
|
||||
});
|
||||
|
||||
initializeCache.call(this);
|
||||
|
||||
this._discordie = discordie;
|
||||
Utils.privatify(this);
|
||||
}
|
||||
getStatesInChannel(channelId) {
|
||||
channelId = channelId.valueOf();
|
||||
const userMap = this._usersForChannel.get(channelId);
|
||||
if (!userMap) return new Map();
|
||||
return userMap;
|
||||
}
|
||||
getUserStateInGuild(guildId, userId) {
|
||||
// note: there can be more than 1 voice member with same user id in guild
|
||||
// this will return only the first voice state registered
|
||||
var channels = this._channelsForUser.get(userId);
|
||||
if (!channels) return null;
|
||||
|
||||
for (var channelId of channels.values()) {
|
||||
const userMap = this._usersForChannel.get(channelId);
|
||||
if (!userMap) continue;
|
||||
|
||||
var state = userMap.get(userId);
|
||||
if (!state) continue;
|
||||
|
||||
if (state.guild_id == guildId) return state;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
ssrcToUserId(voiceConnection, ssrc) {
|
||||
const ssrcMap = this._ssrcForVC.get(voiceConnection);
|
||||
if (ssrcMap) return ssrcMap.get(ssrc) || null;
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = VoiceStateCollection;
|
Reference in New Issue
Block a user