members and roles to controllers

This commit is contained in:
Skillz
2020-09-12 12:27:34 -04:00
parent a0251568f7
commit 2ff52d96e1
7 changed files with 220 additions and 179 deletions

View File

@@ -1,6 +1,11 @@
import { cache } from "../utils/cache.ts";
import { DiscordPayload } from "../types/discord.ts";
import { CreateGuildPayload, GuildDeletePayload, UpdateGuildPayload } from "../types/guild.ts";
import {
CreateGuildPayload,
GuildDeletePayload,
GuildEmojisUpdatePayload,
UpdateGuildPayload,
} from "../types/guild.ts";
import { structures } from "../structures/mod.ts";
import { eventHandlers } from "../module/client.ts";
import { GuildUpdateChange } from "../types/options.ts";
@@ -46,7 +51,6 @@ export function handleInternalGuildDelete(data: DiscordPayload) {
return cache.unavailableGuilds.set(payload.id, Date.now());
}
const guild = cache.guilds.get(payload.id);
if (!guild) return;
return eventHandlers.guildDelete?.(guild);
@@ -93,6 +97,21 @@ export function handleInternalGuildUpdate(data: DiscordPayload) {
}).filter((change) => change) as GuildUpdateChange[];
return eventHandlers.guildUpdate?.(cachedGuild, changes);
}
export function handleInternalGuildEmojisUpdate(data: DiscordPayload) {
if (data.t !== "GUILD_EMOJIS_UPDATE") return;
const payload = data.d as GuildEmojisUpdatePayload;
const guild = cache.guilds.get(payload.guild_id);
if (!guild) return;
const cachedEmojis = guild.emojis;
guild.emojis = payload.emojis;
return eventHandlers.guildEmojisUpdate?.(
guild,
payload.emojis,
cachedEmojis,
);
}

128
src/controllers/members.ts Normal file
View File

@@ -0,0 +1,128 @@
import { eventHandlers } from "../module/client.ts";
import { structures } from "../structures/mod.ts";
import { DiscordPayload } from "../types/discord.ts";
import {
GuildBanPayload,
GuildMemberAddPayload,
GuildMemberChunkPayload,
GuildMemberUpdatePayload,
} from "../types/guild.ts";
import { cache } from "../utils/cache.ts";
export function handleInternalGuildMemberAdd(data: DiscordPayload) {
if (data.t !== "GUILD_MEMBER_ADD") return;
const payload = data.d as GuildMemberAddPayload;
const guild = cache.guilds.get(payload.guild_id);
if (!guild) return;
guild.memberCount++;
const member = structures.createMember(
payload,
guild,
);
guild.members.set(payload.user.id, member);
eventHandlers.guildMemberAdd?.(guild, member);
}
export function handleInternalGuildMemberRemove(data: DiscordPayload) {
if (data.t !== "GUILD_MEMBER_REMOVE") return;
const payload = data.d as GuildBanPayload;
const guild = cache.guilds.get(payload.guild_id);
if (!guild) return;
guild.memberCount--;
const member = guild.members.get(payload.user.id);
eventHandlers.guildMemberRemove?.(
guild,
member || payload.user,
);
eventHandlers.guildMemberRemove?.(
guild,
member || payload.user,
);
guild.members.delete(payload.user.id);
}
export function handleInternalGuildMemberUpdate(data: DiscordPayload) {
if (data.t !== "GUILD_MEMBER_UPDATE") return;
const payload = data.d as GuildMemberUpdatePayload;
const guild = cache.guilds.get(payload.guild_id);
if (!guild) return;
const cachedMember = guild.members.get(payload.user.id);
const newMemberData = {
...payload,
premium_since: payload.premium_since || undefined,
joined_at: new Date(cachedMember?.joinedAt || Date.now())
.toISOString(),
deaf: cachedMember?.deaf || false,
mute: cachedMember?.mute || false,
};
const member = structures.createMember(
newMemberData,
guild,
);
guild.members.set(payload.user.id, member);
if (cachedMember?.nick !== payload.nick) {
eventHandlers.nicknameUpdate?.(
guild,
member,
payload.nick,
cachedMember?.nick,
);
}
const roleIDs = cachedMember?.roles || [];
roleIDs.forEach((id) => {
if (!payload.roles.includes(id)) {
eventHandlers.roleLost?.(guild, member, id);
}
});
payload.roles.forEach((id) => {
if (!roleIDs.includes(id)) {
eventHandlers.roleGained?.(guild, member, id);
}
});
eventHandlers.guildMemberUpdate?.(guild, member, cachedMember);
}
export function handleInternalGuildMembersChunk(data: DiscordPayload) {
if (data.t !== "GUILD_MEMBERS_CHUNK") return;
const payload = data.d as GuildMemberChunkPayload;
const guild = cache.guilds.get(payload.guild_id);
if (!guild) return;
payload.members.forEach((member) => {
guild.members.set(
member.user.id,
structures.createMember(
member,
guild,
),
);
});
// Check if its necessary to resolve the fetchmembers promise for this chunk or if more chunks will be coming
if (
payload.nonce
) {
const resolve = cache.fetchAllMembersProcessingRequests.get(payload.nonce);
if (!resolve) return;
if (payload.chunk_index + 1 === payload.chunk_count) {
cache.fetchAllMembersProcessingRequests.delete(payload.nonce);
resolve(guild.members);
}
}
}

View File

@@ -10,8 +10,15 @@ import {
import {
handleInternalGuildCreate,
handleInternalGuildDelete,
handleInternalGuildEmojisUpdate,
handleInternalGuildUpdate,
} from "./guilds.ts";
import {
handleInternalGuildMemberAdd,
handleInternalGuildMemberRemove,
handleInternalGuildMembersChunk,
handleInternalGuildMemberUpdate,
} from "./members.ts";
import { handleInternalReady } from "./misc.ts";
export let controllers = {
@@ -24,4 +31,9 @@ export let controllers = {
GUILD_UPDATE: handleInternalGuildUpdate,
GUILD_BAN_ADD: handleInternalGuildBanAdd,
GUILD_BAN_REMOVE: handleInternalGuildBanRemove,
GUILD_EMOJIS_UPDATE: handleInternalGuildEmojisUpdate,
GUILD_MEMBER_ADD: handleInternalGuildMemberAdd,
GUILD_MEMBER_REMOVE: handleInternalGuildMemberRemove,
GUILD_MEMBER_UPDATE: handleInternalGuildMemberUpdate,
GUILD_MEMBERS_CHUNK: handleInternalGuildMembersChunk,
};

44
src/controllers/roles.ts Normal file
View File

@@ -0,0 +1,44 @@
import { eventHandlers } from "../module/client.ts";
import { structures } from "../structures/mod.ts";
import { DiscordPayload } from "../types/discord.ts";
import { GuildRoleDeletePayload, GuildRolePayload } from "../types/guild.ts";
import { cache } from "../utils/cache.ts";
export function handleInternalGuildRoleCreate(data: DiscordPayload) {
if (data.t !== "GUILD_ROLE_CREATE") return;
const payload = data.d as GuildRolePayload;
const guild = cache.guilds.get(payload.guild_id);
if (!guild) return;
const role = structures.createRole(payload.role);
const roles = guild.roles.set(payload.role.id, role);
guild.roles = roles;
return eventHandlers.roleCreate?.(guild, role);
}
export function handleInternalGuildRoleDelete(data: DiscordPayload) {
if (data.t !== "GUILD_ROLE_DELETE") return;
const payload = data.d as GuildRoleDeletePayload;
const guild = cache.guilds.get(payload.guild_id);
if (!guild) return;
const cachedRole = guild.roles.get(payload.role_id)!;
guild.roles.delete(payload.role_id);
eventHandlers.roleDelete?.(guild, cachedRole);
}
export function handleInternalGuildRoleUpdate(data: DiscordPayload) {
if (data.t !== "GUILD_ROLE_UPDATE") return;
const payload = data.d as GuildRolePayload;
const guild = cache.guilds.get(payload.guild_id);
if (!guild) return;
const cachedRole = guild.roles.get(payload.role.id);
if (!cachedRole) return;
const role = structures.createRole(payload.role);
eventHandlers.roleUpdate?.(guild, role, cachedRole);
}

View File

@@ -17,11 +17,6 @@ import {
import { delay } from "https://deno.land/std@0.67.0/async/delay.ts";
import { Guild } from "../structures/guild.ts";
import {
GuildBanPayload,
GuildEmojisUpdatePayload,
GuildMemberAddPayload,
GuildMemberUpdatePayload,
GuildMemberChunkPayload,
GuildRolePayload,
UserPayload,
FetchMembersOptions,
@@ -48,16 +43,6 @@ import { controllers } from "../controllers/mod.ts";
let shardCounter = 0;
let basicSharding = false;
export interface FetchAllMembersRequest {
resolve: Function;
requestedMax: number;
receivedAmount: number;
}
const fetchAllMembersProcessingRequests = new Map<
string,
Function
>();
const shards: Worker[] = [];
let createNextShard = true;
@@ -134,163 +119,6 @@ export async function handleDiscordPayload(
// Run the appropriate controller for this event.
controllers[data.t]?.(data, shardID);
if (data.t === "GUILD_EMOJIS_UPDATE") {
const options = data.d as GuildEmojisUpdatePayload;
const guild = cache.guilds.get(options.guild_id);
if (!guild) return;
const cachedEmojis = guild.emojis;
guild.emojis = options.emojis;
return eventHandlers.guildEmojisUpdate?.(
guild,
options.emojis,
cachedEmojis,
);
}
if (data.t === "GUILD_MEMBER_ADD") {
const options = data.d as GuildMemberAddPayload;
const guild = cache.guilds.get(options.guild_id);
if (!guild) return;
const memberCount = guild.memberCount + 1;
guild.memberCount = memberCount;
const member = structures.createMember(
options,
guild,
);
guild.members.set(options.user.id, member);
return eventHandlers.guildMemberAdd?.(guild, member);
}
if (data.t === "GUILD_MEMBER_REMOVE") {
const options = data.d as GuildBanPayload;
const guild = cache.guilds.get(options.guild_id);
if (!guild) return;
const memberCount = guild.memberCount - 1;
guild.memberCount = memberCount;
const member = guild.members.get(options.user.id);
eventHandlers.guildMemberRemove?.(
guild,
member || options.user,
);
return guild.members.delete(options.user.id);
}
if (data.t === "GUILD_MEMBER_UPDATE") {
const options = data.d as GuildMemberUpdatePayload;
const guild = cache.guilds.get(options.guild_id);
if (!guild) return;
const cachedMember = guild.members.get(options.user.id);
const newMemberData = {
...options,
premium_since: options.premium_since || undefined,
joined_at: new Date(cachedMember?.joinedAt || Date.now())
.toISOString(),
deaf: cachedMember?.deaf || false,
mute: cachedMember?.mute || false,
};
const member = structures.createMember(
newMemberData,
guild,
);
guild.members.set(options.user.id, member);
if (cachedMember?.nick !== options.nick) {
eventHandlers.nicknameUpdate?.(
guild,
member,
options.nick,
cachedMember?.nick,
);
}
const roleIDs = cachedMember?.roles || [];
roleIDs.forEach((id) => {
if (!options.roles.includes(id)) {
eventHandlers.roleLost?.(guild, member, id);
}
});
options.roles.forEach((id) => {
if (!roleIDs.includes(id)) {
eventHandlers.roleGained?.(guild, member, id);
}
});
return eventHandlers.guildMemberUpdate?.(guild, member, cachedMember);
}
if (data.t === "GUILD_MEMBERS_CHUNK") {
const options = data.d as GuildMemberChunkPayload;
const guild = cache.guilds.get(options.guild_id);
if (!guild) return;
options.members.forEach((member) => {
guild.members.set(
member.user.id,
structures.createMember(
member,
guild,
),
);
});
// Check if its necessary to resolve the fetchmembers promise for this chunk or if more chunks will be coming
if (
options.nonce
) {
const resolve = fetchAllMembersProcessingRequests.get(options.nonce);
if (!resolve) return;
if (options.chunk_index + 1 === options.chunk_count) {
fetchAllMembersProcessingRequests.delete(options.nonce);
resolve(guild.members);
}
}
}
if (data.t === "GUILD_ROLE_DELETE") {
const options = data.d as GuildRoleDeletePayload;
const guild = cache.guilds.get(options.guild_id);
if (!guild) return;
const cachedRole = guild.roles.get(options.role_id)!;
guild.roles.delete(options.role_id);
return eventHandlers.roleDelete?.(guild, cachedRole);
}
if (
data.t &&
["GUILD_ROLE_CREATE", "GUILD_ROLE_UPDATE"]
.includes(data.t)
) {
const options = data.d as GuildRolePayload;
const guild = cache.guilds.get(options.guild_id);
if (!guild) return;
if (data.t === "GUILD_ROLE_CREATE") {
const role = structures.createRole(options.role);
const roles = guild.roles.set(options.role.id, role);
guild.roles = roles;
return eventHandlers.roleCreate?.(guild, role);
}
const cachedRole = guild.roles.get(options.role.id);
if (!cachedRole) return;
if (data.t === "GUILD_ROLE_UPDATE") {
const role = structures.createRole(options.role);
return eventHandlers.roleUpdate?.(guild, role, cachedRole);
}
}
if (data.t === "MESSAGE_CREATE") {
const options = data.d as MessageCreateOptions;
const channel = cache.channels.get(options.channel_id);
@@ -550,7 +378,7 @@ export async function requestAllMembers(
options?: FetchMembersOptions,
) {
const nonce = `${guild.id}-${Math.random().toString()}`;
fetchAllMembersProcessingRequests.set(nonce, resolve);
cache.fetchAllMembersProcessingRequests.set(nonce, resolve);
if (basicSharding) {
return requestGuildMembers(guild.id, guild.shardID, nonce, options);

View File

@@ -14,13 +14,21 @@ export interface DiscordPayload {
t?:
| "READY"
| "CHANNEL_CREATE"
| "CHANNEL_UPDATE"
| "CHANNEL_DELETE"
| "CHANNEL_UPDATE"
| "GUILD_CREATE"
| "GUILD_DELETE"
| "GUILD_UPDATE"
| "GUILD_BAN_ADD"
| "GUILD_BAN_REMOVE";
| "GUILD_BAN_REMOVE"
| "GUILD_EMOJIS_UPDATE"
| "GUILD_MEMBER_ADD"
| "GUILD_MEMBER_REMOVE"
| "GUILD_MEMBER_UPDATE"
| "GUILD_MEMBERS_CHUNK"
| "GUILD_ROLE_CREATE"
| "GUILD_ROLE_DELETE"
| "GUILD_ROLE_UPDATE";
}
export interface DiscordBotGatewayData {

View File

@@ -12,6 +12,7 @@ export interface CacheData {
messages: Collection<string, Message>;
unavailableGuilds: Collection<string, number>;
presences: Collection<string, PresenceUpdatePayload>;
fetchAllMembersProcessingRequests: Collection<string, Function>;
}
export const cache: CacheData = {
@@ -21,6 +22,7 @@ export const cache: CacheData = {
messages: new Collection(),
unavailableGuilds: new Collection(),
presences: new Collection(),
fetchAllMembersProcessingRequests: new Collection<string, Function>(),
};
async function cleanMessageCache() {