mirror of
https://github.com/discordjs/discord.js.git
synced 2026-03-09 16:13:31 +01:00
Change how presences are handled
This commit is contained in:
@@ -9,6 +9,7 @@ const ClientVoiceManager = require('./voice/ClientVoiceManager');
|
||||
const WebSocketManager = require('./websocket/WebSocketManager');
|
||||
const ActionsManager = require('./actions/ActionsManager');
|
||||
const Collection = require('../util/Collection');
|
||||
const Presence = require('../structures/Presence');
|
||||
|
||||
/**
|
||||
* The starting point for making a Discord Bot.
|
||||
@@ -102,6 +103,13 @@ class Client extends EventEmitter {
|
||||
*/
|
||||
this.channels = new Collection();
|
||||
|
||||
/**
|
||||
* A Collection of presences for friends of the logged in user.
|
||||
* <warn>This is only present for user accounts, not bot accounts!</warn>
|
||||
* @type {Collection<string, Presence>}
|
||||
*/
|
||||
this.presences = new Collection();
|
||||
|
||||
/**
|
||||
* The authorization token for the logged in user/bot.
|
||||
* @type {?string}
|
||||
@@ -333,6 +341,14 @@ class Client extends EventEmitter {
|
||||
clearInterval(interval);
|
||||
this._intervals.delete(interval);
|
||||
}
|
||||
|
||||
_setPresence(id, presence) {
|
||||
if (this.presences.get(id)) {
|
||||
this.presences.get(id).update(presence);
|
||||
return;
|
||||
}
|
||||
this.presences.set(id, new Presence(presence));
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = Client;
|
||||
|
||||
@@ -8,11 +8,7 @@ class GuildSync extends Action {
|
||||
if (guild) {
|
||||
data.presences = data.presences || [];
|
||||
for (const presence of data.presences) {
|
||||
const user = client.users.get(presence.user.id);
|
||||
if (user) {
|
||||
user.status = presence.status;
|
||||
user.game = presence.game;
|
||||
}
|
||||
guild._setPresence(presence.user.id, presence);
|
||||
}
|
||||
|
||||
data.members = data.members || [];
|
||||
|
||||
@@ -19,9 +19,9 @@ class PresenceUpdateHandler extends AbstractHandler {
|
||||
}
|
||||
|
||||
if (guild) {
|
||||
const memberInGuild = guild.members.get(user.id);
|
||||
if (!memberInGuild && data.status !== 'offline') {
|
||||
const member = guild._addMember({
|
||||
let member = guild.members.get(user.id);
|
||||
if (!member && data.status !== 'offline') {
|
||||
member = guild._addMember({
|
||||
user,
|
||||
roles: data.roles,
|
||||
deaf: false,
|
||||
@@ -29,26 +29,12 @@ class PresenceUpdateHandler extends AbstractHandler {
|
||||
}, false);
|
||||
client.emit(Constants.Events.GUILD_MEMBER_AVAILABLE, guild, member);
|
||||
}
|
||||
guild._setPresence(user.id, data);
|
||||
}
|
||||
|
||||
data.user.username = data.user.username || user.username;
|
||||
data.user.id = data.user.id || user.id;
|
||||
data.user.discriminator = data.user.discriminator || user.discriminator;
|
||||
data.user.status = data.status || user.status;
|
||||
data.user.game = data.game;
|
||||
|
||||
const same = data.user.username === user.username &&
|
||||
data.user.id === user.id &&
|
||||
data.user.discriminator === user.discriminator &&
|
||||
data.user.avatar === user.avatar &&
|
||||
data.user.status === user.status &&
|
||||
JSON.stringify(data.user.game) === JSON.stringify(user.game);
|
||||
|
||||
if (!same) {
|
||||
const oldUser = cloneObject(user);
|
||||
user.patch(data.user);
|
||||
client.emit(Constants.Events.PRESENCE_UPDATE, oldUser, user);
|
||||
}
|
||||
const oldUser = cloneObject(user);
|
||||
user.patch(data.user);
|
||||
client.emit(Constants.Events.PRESENCE_UPDATE, oldUser, user);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -16,6 +16,12 @@ class ReadyHandler extends AbstractHandler {
|
||||
for (const guild of data.guilds) client.dataManager.newGuild(guild);
|
||||
for (const privateDM of data.private_channels) client.dataManager.newChannel(privateDM);
|
||||
|
||||
data.presences = data.presences || [];
|
||||
for (const presence of data.presences) {
|
||||
client.dataManager.newUser(presence.user);
|
||||
client._setPresence(presence.user.id, presence);
|
||||
}
|
||||
|
||||
if (!client.user.bot) client.setInterval(client.syncGuilds.bind(client), 30000);
|
||||
client.once('ready', client.syncGuilds.bind(client));
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
const User = require('./User');
|
||||
const Role = require('./Role');
|
||||
const Emoji = require('./Emoji');
|
||||
const Presence = require('./Presence');
|
||||
const GuildMember = require('./GuildMember');
|
||||
const Constants = require('../util/Constants');
|
||||
const Collection = require('../util/Collection');
|
||||
@@ -58,6 +59,14 @@ class Guild {
|
||||
}
|
||||
}
|
||||
|
||||
_setPresence(id, presence) {
|
||||
if (this.presences.get(id)) {
|
||||
this.presences.get(id).update(presence);
|
||||
return;
|
||||
}
|
||||
this.presences.set(id, new Presence(presence));
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets up the Guild
|
||||
* @param {*} data The raw data of the guild
|
||||
@@ -100,6 +109,12 @@ class Guild {
|
||||
*/
|
||||
this.large = data.large || this.large;
|
||||
|
||||
/**
|
||||
* A collection of presences in this Guild
|
||||
* @type {Collection<string, Presence>}
|
||||
*/
|
||||
this.presences = new Collection();
|
||||
|
||||
/**
|
||||
* An array of guild features.
|
||||
* @type {Object[]}
|
||||
@@ -170,11 +185,7 @@ class Guild {
|
||||
|
||||
if (data.presences) {
|
||||
for (const presence of data.presences) {
|
||||
const user = this.client.users.get(presence.user.id);
|
||||
if (user) {
|
||||
user.status = presence.status;
|
||||
user.game = presence.game;
|
||||
}
|
||||
this._setPresence(presence.user.id, presence);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -87,6 +87,15 @@ class GuildMember {
|
||||
this._joinDate = new Date(data.joined_at).getTime();
|
||||
}
|
||||
|
||||
/**
|
||||
* The presence of this Guild Member
|
||||
* @type {Presence}
|
||||
* @readonly
|
||||
*/
|
||||
get presence() {
|
||||
return this.guild.presences.get(this.id);
|
||||
}
|
||||
|
||||
/**
|
||||
* The date this member joined the guild
|
||||
* @type {Date}
|
||||
|
||||
89
src/structures/Presence.js
Normal file
89
src/structures/Presence.js
Normal file
@@ -0,0 +1,89 @@
|
||||
/**
|
||||
* Represents a Game that is part of a User's presence.
|
||||
*/
|
||||
class Game {
|
||||
constructor(data) {
|
||||
/**
|
||||
* The name of the game being played
|
||||
* @type {string}
|
||||
*/
|
||||
this.name = data.name;
|
||||
/**
|
||||
* The type of the game status
|
||||
* @type {number}
|
||||
*/
|
||||
this.type = data.type;
|
||||
/**
|
||||
* If the game is being streamed, a link to the stream
|
||||
* @type {string}
|
||||
*/
|
||||
this.url = data.url;
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether or not the game is being streamed
|
||||
* @readonly
|
||||
*/
|
||||
get streaming() {
|
||||
return this.type === 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether this game is equal to another game
|
||||
* @param {Game} other the other game to compare
|
||||
* @returns {boolean}
|
||||
*/
|
||||
equals(other) {
|
||||
return (
|
||||
this.name === other.name &&
|
||||
this.type === other.type &&
|
||||
this.url === other.url
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class Presence {
|
||||
constructor(data) {
|
||||
/**
|
||||
* The status of the presence:
|
||||
*
|
||||
* * **`online`** - user is online
|
||||
* * **`offline`** - user is offline
|
||||
* * **`idle`** - user is AFK
|
||||
* @type {string}
|
||||
*/
|
||||
this.status = data.status || 'offline';
|
||||
if (data.game) {
|
||||
/**
|
||||
* The game that the user is playing, `null` if they aren't playing a game.
|
||||
* @type {Game}
|
||||
*/
|
||||
this.game = new Game(data.game);
|
||||
} else {
|
||||
this.game = null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether this presence is equal to another
|
||||
* @param {Presence} other the presence to compare
|
||||
* @returns {boolean}
|
||||
*/
|
||||
equals(other) {
|
||||
return (
|
||||
this.status === other.status &&
|
||||
this.game ? this.game.equals(other.game) : !other.game
|
||||
);
|
||||
}
|
||||
|
||||
update(data) {
|
||||
this.status = data.status || this.status;
|
||||
if (data.game) {
|
||||
this.game = new Game(data.game);
|
||||
} else {
|
||||
this.game = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = Presence;
|
||||
@@ -1,5 +1,6 @@
|
||||
const TextBasedChannel = require('./interface/TextBasedChannel');
|
||||
const Constants = require('../util/Constants');
|
||||
const Presence = require('./Presence');
|
||||
|
||||
/**
|
||||
* Represents a User on Discord.
|
||||
@@ -47,34 +48,26 @@ class User {
|
||||
* @type {boolean}
|
||||
*/
|
||||
this.bot = Boolean(data.bot);
|
||||
}
|
||||
|
||||
/**
|
||||
* The status of the user:
|
||||
*
|
||||
* * **`online`** - user is online
|
||||
* * **`offline`** - user is offline
|
||||
* * **`idle`** - user is AFK
|
||||
* @type {string}
|
||||
*/
|
||||
this.status = data.status || this.status || 'offline';
|
||||
|
||||
/**
|
||||
* Represents data about a Game
|
||||
* @property {string} name the name of the game being played.
|
||||
* @property {string} [url] the URL of the stream, if the game is being streamed.
|
||||
* @property {number} [type] if being streamed, this is `1`.
|
||||
* @typedef {object} Game
|
||||
*/
|
||||
|
||||
/**
|
||||
* The game that the user is playing, `null` if they aren't playing a game.
|
||||
* @type {Game}
|
||||
*/
|
||||
this.game = data.game;
|
||||
/**
|
||||
* The presence of this user
|
||||
* @readonly
|
||||
*/
|
||||
get presence() {
|
||||
if (this.client.presences.has(this.id)) {
|
||||
return this.client.presences.get(this.id);
|
||||
}
|
||||
for (const guild of this.client.guilds.values()) {
|
||||
if (guild.presences.has(this.id)) {
|
||||
return guild.presences.get(this.id);
|
||||
}
|
||||
}
|
||||
return new Presence();
|
||||
}
|
||||
|
||||
patch(data) {
|
||||
for (const prop of ['id', 'username', 'discriminator', 'status', 'game', 'avatar', 'bot']) {
|
||||
for (const prop of ['id', 'username', 'discriminator', 'avatar', 'bot']) {
|
||||
if (typeof data[prop] !== 'undefined') this[prop] = data[prop];
|
||||
}
|
||||
}
|
||||
@@ -150,16 +143,6 @@ class User {
|
||||
this.avatar === user.avatar &&
|
||||
this.bot === Boolean(user.bot);
|
||||
|
||||
if (equal) {
|
||||
if (user.status) equal = this.status === user.status;
|
||||
if (equal && user.game) {
|
||||
equal = this.game &&
|
||||
this.game.name === user.game.name &&
|
||||
this.game.type === user.game.type &&
|
||||
this.game.url === user.game.url;
|
||||
}
|
||||
}
|
||||
|
||||
return equal;
|
||||
}
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ const fs = require('fs');
|
||||
|
||||
const client = new Discord.Client({ fetch_all_members: false, api_request_method: 'sequential' });
|
||||
|
||||
const { email, password, token } = require('./auth.json');
|
||||
const { email, password, token, usertoken } = require('./auth.json');
|
||||
|
||||
client.login(token).then(atoken => console.log('logged in with token ' + atoken)).catch(console.log);
|
||||
|
||||
@@ -18,28 +18,6 @@ client.on('channelCreate', channel => {
|
||||
console.log(`made ${channel.name}`);
|
||||
});
|
||||
|
||||
client.on('guildMemberAdd', (g, m) => {
|
||||
console.log(`${m.user.username} joined ${g.name}`);
|
||||
})
|
||||
|
||||
let c = 0;
|
||||
|
||||
client.on('channelUpdate', () => {
|
||||
c++; console.log(c);
|
||||
});
|
||||
|
||||
client.on('guildMemberUpdate', () => {
|
||||
c++; console.log(c);
|
||||
});
|
||||
|
||||
client.on('channelPinsUpdate', () => {
|
||||
c++; console.log(c);
|
||||
});
|
||||
|
||||
client.on('presenceUpdate', () => {
|
||||
c++; console.log(c);
|
||||
});
|
||||
|
||||
client.on('debug', console.log);
|
||||
|
||||
client.on('message', message => {
|
||||
|
||||
@@ -20,7 +20,12 @@ client.on('message', msg => {
|
||||
process.send(123);
|
||||
|
||||
client.on('ready', () => {
|
||||
console.log('Ready');
|
||||
console.log('Ready', client.options.shard_id);
|
||||
if (client.options.shard_id === '0')
|
||||
setTimeout(() => {
|
||||
console.log('kek dying');
|
||||
client.destroy();
|
||||
}, 5000);
|
||||
});
|
||||
|
||||
client.login(token).catch(console.log);
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
const Discord = require('../');
|
||||
|
||||
const sharder = new Discord.ShardingManager(`${process.cwd()}/test/shard.js`);
|
||||
const sharder = new Discord.ShardingManager(`${process.cwd()}/test/shard.js`, 5, false);
|
||||
|
||||
sharder.on('launch', id => console.log(`launched ${id}`));
|
||||
|
||||
|
||||
Reference in New Issue
Block a user