even more events done only few left

This commit is contained in:
Skillz
2020-03-02 16:16:43 -05:00
parent 5839d07ca7
commit c7054516b5
10 changed files with 334 additions and 72 deletions
+4
View File
@@ -8,3 +8,7 @@ export const handle_internal_guild_create = (guild: Guild) => {
export const handle_internal_guild_update = (guild: Guild) => {
cache.guilds.set(guild.id(), guild)
}
export const handle_internal_guild_delete = (guild: Guild) => {
cache.guilds.delete(guild.id())
}
+198 -5
View File
@@ -13,8 +13,21 @@ import { ClientOptions, FulfilledClientOptions, Event_Handlers } from "../types/
import { CollectedMessageType } from "../types/message-type.ts"
import { send_constant_heartbeats, update_previous_sequence_number } from "./gateway.ts"
import { create_guild } from "../structures/guild.ts"
import { handle_internal_guild_create, handle_internal_guild_update } from "../events/guilds.ts"
import { Create_Guild_Payload, Guild_Delete_Payload } from "../types/guild.ts"
import {
handle_internal_guild_create,
handle_internal_guild_update,
handle_internal_guild_delete
} from "../events/guilds.ts"
import {
Create_Guild_Payload,
Guild_Delete_Payload,
Guild_Ban_Payload,
Guild_Emojis_Update_Payload,
Guild_Member_Add_Payload,
Guild_Member_Update_Payload,
Guild_Member_Chunk_Payload,
Guild_Role_Payload
} from "../types/guild.ts"
import { create_channel } from "../structures/channel.ts"
import { Channel_Create_Payload, Channel_Types } from "../types/channel.ts"
import {
@@ -23,6 +36,11 @@ import {
handle_internal_channel_delete
} from "../events/channels.ts"
import { cache } from "../utils/cache.ts"
import { create_user } from "../structures/user.ts"
import { create_member } from "../structures/member.ts"
import { create_role } from "../structures/role.ts"
import { create_message } from "../structures/message.ts"
import { Message_Create_Options, Message_Delete_Payload, Message_Delete_Bulk_Payload } from "../types/message.ts"
const defaultOptions = {
properties: {
@@ -191,6 +209,10 @@ class Client {
if (data.t === "GUILD_CREATE") {
const guild = create_guild(data.d as Create_Guild_Payload, this)
handle_internal_guild_create(guild)
if (cache.unavailableGuilds.get(guild.id())) {
cache.unavailableGuilds.delete(guild.id())
return
}
return this.event_handlers.guild_create?.(guild)
}
@@ -204,16 +226,187 @@ class Client {
return this.event_handlers.guild_update?.(guild, cached_guild)
}
if (data.t === 'GUILD_DELETE') {
if (data.t === "GUILD_DELETE") {
const options = data.d as Guild_Delete_Payload
const guild = cache.guilds.get(options.id)
if (!guild) return
guild.channels.forEach((_channel, id) => cache.channels.delete(id))
return options.unavailable ? undefined : this.event_handlers.guild_delete?.(guild)
if (options.unavailable) return cache.unavailableGuilds.set(options.id, Date.now())
handle_internal_guild_delete(guild)
return this.event_handlers.guild_delete?.(guild)
}
return console.log("UNKNOWN EVENT:", data)
if (data.t && ["GUILD_BAN_ADD", "GUILD_BAN_REMOVE"].includes(data.t)) {
const options = data.d as Guild_Ban_Payload
const guild = cache.guilds.get(options.guild_id)
if (!guild) return
const user = create_user(options.user)
return data.t === "GUILD_BAN_ADD"
? this.event_handlers.guild_ban_add?.(guild, user)
: this.event_handlers.guild_ban_remove?.(guild, user)
}
if (data.t === "GUILD_EMOJIS_UPDATE") {
const options = data.d as Guild_Emojis_Update_Payload
const guild = cache.guilds.get(options.guild_id)
if (!guild) return
const cached_emojis = guild.emojis()
guild.emojis = () => options.emojis
return this.event_handlers.guild_emojis_update?.(guild, options.emojis, cached_emojis)
}
if (data.t === "GUILD_MEMBER_ADD") {
const options = data.d as Guild_Member_Add_Payload
const guild = cache.guilds.get(options.guild_id)
if (!guild) return
const member_count = guild.member_count() + 1
guild.member_count = () => member_count
const member = create_member(
options,
options.guild_id,
[...guild.roles().values()].map(role => role.raw()),
guild.owner_id(),
this
)
guild.members.set(options.user.id, member)
return this.event_handlers.guild_member_add?.(guild, member)
}
if (data.t === "GUILD_MEMBER_REMOVE") {
const options = data.d as Guild_Ban_Payload
const guild = cache.guilds.get(options.guild_id)
if (!guild) return
const member_count = guild.member_count() - 1
guild.member_count = () => member_count
const member = guild.members.get(options.user.id)
return this.event_handlers.guild_member_remove?.(guild, member || create_user(options.user))
}
if (data.t === "GUILD_MEMBER_UPDATE") {
const options = data.d as Guild_Member_Update_Payload
const guild = cache.guilds.get(options.guild_id)
if (!guild) return
const cached_member = guild.members.get(options.user.id)
const new_member_data = {
...options,
premium_since: options.premium_since || undefined,
joined_at: new Date(cached_member?.joined_at() || Date.now()).toISOString(),
deaf: cached_member?.deaf() || false,
mute: cached_member?.mute() || false
}
const member = create_member(
new_member_data,
options.guild_id,
[...guild.roles().values()].map(r => r.raw()),
guild.owner_id(),
this
)
guild.members.set(options.user.id, member)
if (cached_member?.nick() !== options.nick)
this.event_handlers.nickname_update?.(guild, member, options.nick, cached_member?.nick())
const role_ids = cached_member?.roles() || []
role_ids.forEach(id => {
if (!options.roles.includes(id)) this.event_handlers.role_lost?.(guild, member, id)
})
options.roles.forEach(id => {
if (!role_ids.includes(id)) this.event_handlers.role_gained?.(guild, member, id)
})
return this.event_handlers.guild_member_update?.(guild, member, cached_member)
}
if (data.t === "GUILD_MEMBERS_CHUNK") {
const options = data.d as Guild_Member_Chunk_Payload
const guild = cache.guilds.get(options.guild_id)
if (!guild) return
options.members.forEach(member =>
guild.members.set(
member.user.id,
create_member(
member,
options.guild_id,
[...guild.roles().values()].map(r => r.raw()),
guild.owner_id(),
this
)
)
)
}
if (data.t && ['GUILD_ROLE_CREATE', 'GUILD_ROLE_DELETE', 'GUILD_ROLE_UPDATE'].includes(data.t)) {
const options = data.d as Guild_Role_Payload
const guild = cache.guilds.get(options.guild_id)
if (!guild) return
if (data.t === 'GUILD_ROLE_CREATE') {
const role = create_role(options.role)
const roles = guild.roles().set(options.role.id, role)
guild.roles = () => roles
return this.event_handlers.role_create?.(guild, role)
}
const cached_role = guild.roles().get(options.role.id)
if (!cached_role) return
if (data.t === 'GUILD_ROLE_DELETE') {
const roles = guild.roles()
roles.delete(options.role.id)
guild.roles = () => roles
return this.event_handlers.role_delete?.(guild, cached_role)
}
if (data.t === 'GUILD_ROLE_UPDATE') {
const role = create_role(options.role)
return this.event_handlers.role_update?.(guild, role, cached_role)
}
}
if (data.t === 'MESSAGE_CREATE') {
const options = data.d as Message_Create_Options
const message = create_message(options, this)
const channel = message.channel()
if (channel) {
channel.last_message_id = () => options.id
if (channel.messages().size > 99) {
// TODO: LIMIT THIS TO 100 messages
}
}
return this.event_handlers.message_create?.(message)
}
if (data.t && ['MESSAGE_DELETE', 'MESSAGE_DELETE_BULK'].includes(data.t)) {
const options = data.d as Message_Delete_Payload
const deleted_messages = data.t === 'MESSAGE_DELETE' ? [options.id] : (data.d as Message_Delete_Bulk_Payload).ids
const channel = cache.channels.get(options.channel_id)
if (!channel) return
deleted_messages.forEach(id => {
const message = channel.messages().get(id)
if (message) {
// TODO: update the messages cache
}
return this.event_handlers.message_delete?.(message || { id, channel })
})
}
return this.event_handlers.raw?.(data)
default:
return
}
+3 -1
View File
@@ -3,11 +3,13 @@ import { Message_Create_Options } from '../types/message.ts'
import { endpoints } from '../constants/discord.ts'
import { Channel_Types, MessageContent } from '../types/channel.ts'
import { cache } from '../utils/cache.ts'
import { create_user, User_Payload } from './user.ts'
import { create_user } from './user.ts'
import { User_Payload } from '../types/guild.ts'
export const create_message = (data: Message_Create_Options, client: Client) => {
const base_message = {
raw: () => data,
id: () => data.id,
type: () => data.type,
timestamp: () => Date.parse(data.timestamp),
content: () => data.content,
+29 -29
View File
@@ -1,46 +1,46 @@
import { User_Payload } from "./user.ts";
import { ActivityPayload } from "./activity.ts";
import { StatusType } from "../types/discord.ts";
import { ActivityPayload } from "./activity.ts"
import { StatusType } from "../types/discord.ts"
import { User_Payload } from "../types/guild.ts"
export type PresencePayload = Partial<{
/** The user presence is being updated for */
user: User_Payload;
/** The user presence is being updated for */
user: User_Payload
/** Roles this user is in */
roles: string[];
/** Roles this user is in */
roles: string[]
/** Null, or the user's current activity */
game: ActivityPayload;
/** Null, or the user's current activity */
game: ActivityPayload
/** Id of the guild */
guild_id: string;
/** Id of the guild */
guild_id: string
// This is a deviation from the docs, as it pretty much says `: StatusType`.
/** The updated status */
status: StatusType;
// This is a deviation from the docs, as it pretty much says `: StatusType`.
/** The updated status */
status: StatusType
/** User's current activities */
activities: ActivityPayload[];
/** User's current activities */
activities: ActivityPayload[]
/** User's platform-dependent status */
client_status: ClientStatusPayload;
/** User's platform-dependent status */
client_status: ClientStatusPayload
/** When the user used their Nitro boost on the server */
premium_since: string;
/** When the user used their Nitro boost on the server */
premium_since: string
/** This users guild nickname (if one is set) */
nick: string;
}> & { id: string };
/** This users guild nickname (if one is set) */
nick: string
}> & { id: string }
export interface ClientStatusPayload {
/** The user's status set for an active desktop (Windows, Linux, Mac) application session */
desktop?: StatusType;
/** The user's status set for an active desktop (Windows, Linux, Mac) application session */
desktop?: StatusType
/** The user's status set for an active mobile (iOS, Android) application session */
mobile?: StatusType;
/** The user's status set for an active mobile (iOS, Android) application session */
mobile?: StatusType
/** The user's status set for an active web (browser, bot account) application session */
web?: StatusType;
/** The user's status set for an active web (browser, bot account) application session */
web?: StatusType
}
export const createPresence = (data: unknown) => {
+1 -30
View File
@@ -1,36 +1,7 @@
import { format_image_url } from '../utils/cdn.ts'
import { endpoints } from '../constants/discord.ts'
import { Image_Size, Image_Formats } from '../types/cdn.ts'
export interface User_Payload {
/** The user's id */
id: string
/** The user's username, not unique across the platform */
username: string
/** The user's 4-digit discord-tag */
discriminator: string
/** The user's avatar hash */
avatar: string
/** Whether the user belongs to an OAuth2 application */
bot?: boolean
/** Whether the user is an Official Discord System user (part of the urgent message system) */
system?: boolean
/** Whether the user has two factor enabled on their account */
mfa_enabled?: boolean
// Types with "email" scope intentionally left out.
/** The flags on a user's account */
flags?: number
/** The type of Nitro subscription on a user's account */
premium_type?: PremiumType
}
import { User_Payload } from '../types/guild.ts'
export const enum PremiumType {
NitroClassic = 1,
+52 -3
View File
@@ -7,8 +7,57 @@ import { Activity } from "./message.ts"
import { ClientStatusPayload } from "../structures/presence.ts"
import { Channel_Create_Payload } from "./channel.ts"
export interface Guild_Role_Payload {
/** The id of the guild */
guild_id: string
/** The role object of the role created, deleted, or updated */
role: Role_Data
}
export interface Guild_Member_Chunk_Payload {
/** The id of the guild */
guild_id: string
/** The set of guild members */
members: Member_Create_Payload[]
/** if passing an invalid id, it will be found here */
not_found?: string[]
/** if passing true, presences of the members will be here */
presences?: Presence[]
}
export interface Guild_Member_Update_Payload {
/** The id of the guild */
guild_id: string
/** The user's role ids */
roles: string[]
/** The user */
user: User_Payload
/** The nickname of the user in the guild */
nick: string
/** When the user used their nitro boost on the guild. */
premium_since: string | null
}
export interface Guild_Member_Add_Payload extends Member_Create_Payload {
guild_id: string
}
export interface Guild_Emojis_Update_Payload {
guild_id: string
emojis: Emoji[]
}
export interface Guild_Ban_Payload {
/** The id of the guild */
guild_id: string
/** The banned user. Not a member as you can ban users outside of your guild. */
user: User_Payload
}
export interface Guild_Delete_Payload {
/** The id of the guild */
id: string
/** Whether this guild went unavailable. */
unavailable?: boolean
}
@@ -181,7 +230,7 @@ export interface Guild_Integration {
/** The grace period before expiring subscribers */
expire_grace_period: number
/** The user for this integration */
user: User_Data
user: User_Payload
/** The integration account information */
account: Account
/** When this integration was last synced */
@@ -195,7 +244,7 @@ export interface Account {
name: string
}
export interface User_Data {
export interface User_Payload {
/** The user's id */
id: string
/** the user's username, not unique across the platform */
@@ -446,7 +495,7 @@ export interface Voice_State {
export interface Presence {
/** The user presence is being updated for */
user: User_Data
user: User_Payload
/** The roles this user is in */
roles: string[]
/** null, or the user's current activity */
+1 -1
View File
@@ -1,5 +1,5 @@
import { User_Payload } from "../structures/user.ts"
import { create_member } from "../structures/member.ts"
import { User_Payload } from "./guild.ts"
export interface Edit_Member_Options {
/** Value to set users nickname to. Requires MANAGE_NICKNAMES permission. */
+25 -2
View File
@@ -1,6 +1,7 @@
import { ChannelType, User_Data } from './guild.ts'
import { ChannelType, User_Payload } from './guild.ts'
import { User } from '../structures/user.ts'
import { Member } from './member.ts'
import { Channel } from './return-type.ts'
export interface MentionedUser extends User {
member: Member
@@ -224,7 +225,7 @@ export interface Message_Create_Options {
/** The id of the guild the message was sent in */
guild_id?: string
/** The author of this message (not guaranteed to be a valid user such as a webhook.) */
author: User_Data
author: User_Payload
/** The member properties for this message's author. Can be partial. */
member?: Member
/** The contents of the message */
@@ -266,3 +267,25 @@ export interface Message_Create_Options {
/** The message flags combined like permission bits describe extra features of the message */
flags?: 1 | 2 | 4 | 8 | 16
}
export interface Base_Message_Delete_Payload {
/** The id of the channel */
channel_id: string
/** The id of the guild */
guild_id?: string
}
export interface Message_Delete_Payload extends Base_Message_Delete_Payload {
/** The id of the message */
id: string
}
export interface Message_Delete_Bulk_Payload extends Base_Message_Delete_Payload {
/** The ids of the messages */
ids: string[]
}
export interface Partial_Message {
id: string,
channel: Channel
}
+20 -1
View File
@@ -1,6 +1,10 @@
import { Properties } from "./discord.ts"
import { Properties, Emoji, DiscordPayload } from "./discord.ts"
import { Channel, Guild } from "./return-type.ts"
import { Voice_State } from "./guild.ts"
import { User } from "../structures/user.ts"
import { Member } from "./member.ts"
import { Role } from "../structures/role.ts"
import { Message } from "../structures/message.ts"
export interface FulfilledClientOptions {
token: string
@@ -22,12 +26,27 @@ export interface Event_Handlers {
channel_create?: (channel: Channel) => unknown
channel_update?: (channel: Channel, cached_channel: Channel) => unknown
channel_delete?: (channel: Channel) => unknown
guild_ban_add?: (guild: Guild, user: User) => unknown
guild_ban_remove?: (guild: Guild, user: User) => unknown
guild_create?: (guild: Guild) => unknown
guild_update?: (guild: Guild, cached_guild: Guild) => unknown
guild_delete?: (guild: Guild) => unknown
guild_emojis_update?: (guild: Guild, emojis: Emoji[], cached_emojis: Emoji[]) => unknown
guild_member_add?: (guild: Guild, member: Member) => unknown
guild_member_remove?: (guild: Guild, member: Member | User) => unknown
guild_member_update?: (guild: Guild, member: Member, cached_member?: Member) => unknown
heartbeat?: () => unknown
message_create?: (message: Message) => unknown
message_delete?: (message: Message | Partial_Message) => unknown
nickname_update?: (guild: Guild, member: Member, nickname: string, old_nickname?: string) => unknown
ready?: () => unknown
role_create?: (guild: Guild, role: Role) => unknown
role_delete?: (guild: Guild, role: Role) => unknown
role_update?: (guild: Guild, role: Role, cached_role: Role) => unknown
role_gained?: (guild: Guild, member: Member, role_id: string) => unknown
role_lost?: (guild: Guild, member: Member, role_id: string) => unknown
voice_channel_leave?: (voice_state: Voice_State) => unknown
raw?: (data: DiscordPayload) => unknown
}
export enum Intents {
+1
View File
@@ -5,4 +5,5 @@ export const cache = {
guilds: new Map<string, Guild>(),
users: new Map<string, User>(),
channels: new Map<string, Channel>(),
unavailableGuilds: new Map<string, number>()
}