Threads Members Update (#46)

* PresenceUpdate

* Thread Members Events

* fix: fmt

* fix: all fmt
This commit is contained in:
Marcos Susaña 2022-07-12 16:08:40 -04:00 committed by GitHub
parent f5e3eaaafc
commit 107374725b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 203 additions and 150 deletions

View File

@ -7,21 +7,17 @@ assignees: ''
--- ---
**Describe the bug** **Describe the bug** A clear and concise description of what the bug is.
A clear and concise description of what the bug is.
**Biscuit Version** **Biscuit Version** eg: 0.1.0-rc7
eg: 0.1.0-rc7
**To Reproduce** Steps to reproduce the behavior:
**To Reproduce**
Steps to reproduce the behavior:
1. Go to '...' 1. Go to '...'
2. Click on '....' 2. Click on '....'
3. Scroll down to '....' 3. Scroll down to '....'
4. See error 4. See error
**Expected behavior** **Expected behavior** A clear and concise description of what you expected to happen.
A clear and concise description of what you expected to happen.
**etc** **etc** Whatever
Whatever

View File

@ -7,14 +7,12 @@ assignees: ''
--- ---
**Is your feature request related to a problem? Please describe.** **Is your feature request related to a problem? Please describe.** A clear and concise description of what the problem
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] is. Ex. I'm always frustrated when [...]
**Describe the solution you'd like** **Describe the solution you'd like** A clear and concise description of what you want to happen.
A clear and concise description of what you want to happen.
**Describe alternatives you've considered** **Describe alternatives you've considered** A clear and concise description of any alternative solutions or features
A clear and concise description of any alternative solutions or features you've considered. you've considered.
**Limitations** **Limitations** A set of limitations of the API or the library by itself
A set of limitations of the API or the library by itself

View File

@ -1,38 +1,44 @@
# biscuit # biscuit
## A brand new bleeding edge non bloated Discord library ## A brand new bleeding edge non bloated Discord library
### Install (for [node18](https://nodejs.org/en/download/)) ### Install (for [node18](https://nodejs.org/en/download/))
```sh-session ```sh-session
npm install @oasisjs/biscuit npm install @oasisjs/biscuit
pnpm add @oasisjs/biscuit pnpm add @oasisjs/biscuit
yarn add @oasisjs/biscuit yarn add @oasisjs/biscuit
``` ```
> or via [cdn](https://nest.land/package/biscuit) > or via [cdn](https://nest.land/package/biscuit)
The biscuit Discord library is built ontop of Discordeno and webspec APIs, we aim to provide portability. The biscuit Discord library is built ontop of Discordeno and webspec APIs, we aim to provide portability. Join our
Join our [Discord](https://discord.gg/zmuvzzEFz2) [Discord](https://discord.gg/zmuvzzEFz2)
### Most importantly, biscuit is: ### Most importantly, biscuit is:
* A modular [Discordeno](https://github.com/discordeno/discordeno) fork
* A framework to build Discord bots
* A bleeding edge API to contact Discord
Biscuit is primarly inspired by Discord.js and Discordeno but it does not include a cache layer by default, we believe that you should not make software that does things it is not supposed to do. - A modular [Discordeno](https://github.com/discordeno/discordeno) fork
- A framework to build Discord bots
- A bleeding edge API to contact Discord
Biscuit is primarly inspired by Discord.js and Discordeno but it does not include a cache layer by default, we believe
that you should not make software that does things it is not supposed to do.
### Why biscuit?: ### Why biscuit?:
* [Minimal](https://en.wikipedia.org/wiki/Unix_philosophy), non feature-rich!
* Crossplatform - [Minimal](https://en.wikipedia.org/wiki/Unix_philosophy), non feature-rich!
* Consistent - Crossplatform
* Performant - Consistent
- Performant
### Example bot (TS/JS) ### Example bot (TS/JS)
```js ```js
import { GatewayIntents, Session } from "biscuit"; import { GatewayIntents, Session } from "biscuit";
const token = "your token goes here"; const token = "your token goes here";
const intents = GatewayIntents.MessageContent | GatewayIntents.Guilds | GatewayIntents.GuildMessages; const intents = GatewayIntents.MessageContent | GatewayIntents.Guilds | GatewayIntents.GuildMessages;
const session = new Session({ token, intents }); const session = new Session({ token, intents });
session.on("ready", ({ user }) => { session.on("ready", ({ user }) => {
@ -49,23 +55,28 @@ session.start();
``` ```
### Mininal style guide ### Mininal style guide
* 4 spaces, no tabs
* Semi-colons are mandatory - 4 spaces, no tabs
* Run `deno fmt` - Semi-colons are mandatory
* Avoid circular dependencies - Run `deno fmt`
- Avoid circular dependencies
### Contrib guide ### Contrib guide
* Install Deno extension [here](https://marketplace.visualstudio.com/items?itemName=denoland.vscode-deno)
* Run `deno check` to make sure the library works - Install Deno extension [here](https://marketplace.visualstudio.com/items?itemName=denoland.vscode-deno)
* Avoid sharing state between classes - Run `deno check` to make sure the library works
- Avoid sharing state between classes
### Compatibility ### Compatibility
#### bun #### bun
since bun is unestable I highly recommend running biscuit on node! since bun is unestable I highly recommend running biscuit on node!
* We got the library running on EndeavourOS but it spams the ready event multiple times
* We got the library running on Arch/Artix Linux but breaks when sending fetch requests - We got the library running on EndeavourOS but it spams the ready event multiple times
* We got the library running on WSL - We got the library running on Arch/Artix Linux but breaks when sending fetch requests
- We got the library running on WSL
#### node #### node
* all DNT shims work properly
- all DNT shims work properly

View File

@ -1,67 +1,67 @@
import { build } from 'https://deno.land/x/dnt@0.23.0/mod.ts'; import { build } from "https://deno.land/x/dnt@0.23.0/mod.ts";
await Deno.remove('npm', { recursive: true }).catch((_) => {}); await Deno.remove("npm", { recursive: true }).catch((_) => {});
await build({ await build({
shims: { shims: {
custom: [ custom: [
{ {
package: { package: {
name: 'ws', name: "ws",
version: '^8.4.0', version: "^8.4.0",
}, },
globalNames: [ globalNames: [
{ {
name: 'WebSocket', name: "WebSocket",
exportName: 'default', exportName: "default",
}, },
], ],
}, },
], ],
}, },
package: { package: {
author: 'Yuzuru', author: "Yuzuru",
name: '@oasisjs/biscuit', name: "@oasisjs/biscuit",
version: Deno.args[0], version: Deno.args[0],
description: 'the Biscuit library', description: "the Biscuit library",
license: 'Apache License 2.0', license: "Apache License 2.0",
repository: { repository: {
type: 'git', type: "git",
url: 'git+https://github.com/deno-biscuit/biscuit.git', url: "git+https://github.com/deno-biscuit/biscuit.git",
}, },
bugs: { bugs: {
url: 'https://github.com/deno-biscuit/biscuit/issues', url: "https://github.com/deno-biscuit/biscuit/issues",
}, },
typesVersions: { typesVersions: {
'*': { "*": {
'*': ['./types/mod.d.ts'], "*": ["./types/mod.d.ts"],
'biscuit': ['./types/packages/biscuit/mod.d.ts'], "biscuit": ["./types/packages/biscuit/mod.d.ts"],
'discordeno': ['./types/packages/discordeno/mod.d.ts'], "discordeno": ["./types/packages/discordeno/mod.d.ts"],
'cache': ['./types/packages/cache/mod.d.ts'], "cache": ["./types/packages/cache/mod.d.ts"],
}, },
}, },
}, },
entryPoints: [ entryPoints: [
'./mod.ts', "./mod.ts",
{ {
name: './biscuit', name: "./biscuit",
path: 'packages/biscuit/mod.ts', path: "packages/biscuit/mod.ts",
}, },
{ {
name: './discordeno', name: "./discordeno",
path: 'packages/discordeno/mod.ts', path: "packages/discordeno/mod.ts",
}, },
{ {
name: './cache', name: "./cache",
path: 'packages/cache/mod.ts', path: "packages/cache/mod.ts",
}, },
], ],
outDir: './npm', outDir: "./npm",
declaration: true, declaration: true,
typeCheck: false, typeCheck: false,
test: false, test: false,
}); });
// post build steps // post build steps
Deno.copyFileSync('LICENSE', 'npm/LICENSE'); Deno.copyFileSync("LICENSE", "npm/LICENSE");
Deno.copyFileSync('README.md', 'npm/README.md'); Deno.copyFileSync("README.md", "npm/README.md");

View File

@ -31,9 +31,9 @@ import type {
DiscordScheduledEvent, DiscordScheduledEvent,
DiscordScheduledEventUserAdd, DiscordScheduledEventUserAdd,
DiscordScheduledEventUserRemove, DiscordScheduledEventUserRemove,
// DiscordThreadMemberUpdate,
// DiscordThreadMembersUpdate,
DiscordThreadListSync, DiscordThreadListSync,
DiscordThreadMembersUpdate,
DiscordThreadMemberUpdate,
DiscordTypingStart, DiscordTypingStart,
DiscordUser, DiscordUser,
DiscordWebhookUpdate, DiscordWebhookUpdate,
@ -192,6 +192,28 @@ export const THREAD_DELETE: RawHandler<DiscordChannel> = (session, _shardId, cha
session.emit("threadDelete", new ThreadChannel(session, channel, channel.guild_id)); session.emit("threadDelete", new ThreadChannel(session, channel, channel.guild_id));
}; };
export const THREAD_MEMBER_UPDATE: RawHandler<DiscordThreadMemberUpdate> = (session, _shardId, payload) => {
session.emit("threadMemberUpdate", {
guildId: payload.guild_id,
id: payload.id,
userId: payload.user_id,
joinedAt: payload.joined_at,
flags: payload.flags,
});
};
export const THREAD_MEMBERS_UPDATE: RawHandler<DiscordThreadMembersUpdate> = (session, _shardId, payload) => {
session.emit("threadMembersUpdate", {
memberCount: payload.member_count,
addedMembers: payload.added_members
? payload.added_members.map((tm) => new ThreadMember(session, tm))
: undefined,
removedMemberIds: payload.removed_member_ids ? payload.removed_member_ids : undefined,
guildId: payload.guild_id,
id: payload.id,
});
};
export const THREAD_LIST_SYNC: RawHandler<DiscordThreadListSync> = (session, _shardId, payload) => { export const THREAD_LIST_SYNC: RawHandler<DiscordThreadListSync> = (session, _shardId, payload) => {
session.emit("threadListSync", { session.emit("threadListSync", {
guildId: payload.guild_id, guildId: payload.guild_id,
@ -346,7 +368,7 @@ export const GUILD_SCHEDULED_EVENT_USER_REMOVE: RawHandler<DiscordScheduledEvent
}; };
export const raw: RawHandler<unknown> = (session, shardId, data) => { export const raw: RawHandler<unknown> = (session, shardId, data) => {
session.emit("raw", data as { t: string, d: unknown }, shardId); session.emit("raw", data as { t: string; d: unknown }, shardId);
}; };
export interface Ready extends Omit<DiscordReady, "user"> { export interface Ready extends Omit<DiscordReady, "user"> {
@ -386,6 +408,8 @@ export interface Events {
"threadUpdate": Handler<[ThreadChannel]>; "threadUpdate": Handler<[ThreadChannel]>;
"threadDelete": Handler<[ThreadChannel]>; "threadDelete": Handler<[ThreadChannel]>;
"threadListSync": Handler<[{ guildId: Snowflake, channelIds: Snowflake[], threads: ThreadChannel[], members: ThreadMember[] }]> "threadListSync": Handler<[{ guildId: Snowflake, channelIds: Snowflake[], threads: ThreadChannel[], members: ThreadMember[] }]>
"threadMemberUpdate": Handler<[{id: Snowflake, userId: Snowflake, guildId: Snowflake, joinedAt: string, flags: number }]>
"threadMembersUpdate": Handler<[{id: Snowflake, memberCount: number, addedMembers?: ThreadMember[], guildId: Snowflake, removedMemberIds?: Snowflake[]}]>
"interactionCreate": Handler<[Interaction]>; "interactionCreate": Handler<[Interaction]>;
"integrationCreate": Handler<[Integration]>; "integrationCreate": Handler<[Integration]>;
"integrationUpdate": Handler<[Integration]>; "integrationUpdate": Handler<[Integration]>;

View File

@ -9,7 +9,7 @@ export interface MessageReactionAdd {
messageId: string; messageId: string;
guildId?: string; guildId?: string;
member?: Member; member?: Member;
emoji: Partial<Emoji> emoji: Partial<Emoji>;
} }
export function NewMessageReactionAdd(session: Session, data: DiscordMessageReactionAdd): MessageReactionAdd { export function NewMessageReactionAdd(session: Session, data: DiscordMessageReactionAdd): MessageReactionAdd {
@ -18,9 +18,11 @@ export function NewMessageReactionAdd(session: Session, data: DiscordMessageReac
channelId: data.channel_id, channelId: data.channel_id,
messageId: data.message_id, messageId: data.message_id,
guildId: data.guild_id, guildId: data.guild_id,
member: data.member ? new Member(session, (data.member as DiscordMemberWithUser), (data.guild_id || "")) : undefined, member: data.member
? new Member(session, data.member as DiscordMemberWithUser, data.guild_id || "")
: undefined,
emoji: new Emoji(session, data.emoji), emoji: new Emoji(session, data.emoji),
} };
} }
/** /**

View File

@ -210,19 +210,19 @@ export class Guild extends BaseGuild implements Model {
this.explicitContentFilterLevel = data.explicit_content_filter; this.explicitContentFilterLevel = data.explicit_content_filter;
this.members = new Map( this.members = new Map(
data.members?.map((member) => [data.id, new Member(session, { ...member, user: member.user! }, data.id)]) data.members?.map((member) => [data.id, new Member(session, { ...member, user: member.user! }, data.id)]),
); );
this.roles = new Map( this.roles = new Map(
data.roles.map((role) => [data.id, new Role(session, role, data.id)]) data.roles.map((role) => [data.id, new Role(session, role, data.id)]),
); );
this.emojis = new Map( this.emojis = new Map(
data.emojis.map((guildEmoji) => [guildEmoji.id!, new GuildEmoji(session, guildEmoji, data.id)]) data.emojis.map((guildEmoji) => [guildEmoji.id!, new GuildEmoji(session, guildEmoji, data.id)]),
); );
this.channels = new Map( this.channels = new Map(
data.channels?.map((guildChannel) => [guildChannel.id, new GuildChannel(session, guildChannel, data.id)]) data.channels?.map((guildChannel) => [guildChannel.id, new GuildChannel(session, guildChannel, data.id)]),
); );
} }

152
packages/cache/mod.ts vendored
View File

@ -1,13 +1,13 @@
import type { import type {
DiscordMessage,
DiscordChannel, DiscordChannel,
DiscordEmoji, DiscordEmoji,
DiscordGuild, DiscordGuild,
DiscordMemberWithUser, DiscordMemberWithUser,
DiscordMessage,
DiscordMessageReactionAdd, DiscordMessageReactionAdd,
DiscordMessageReactionRemove, DiscordMessageReactionRemove,
DiscordMessageReactionRemoveEmoji,
DiscordMessageReactionRemoveAll, DiscordMessageReactionRemoveAll,
DiscordMessageReactionRemoveEmoji,
DiscordUser, DiscordUser,
Session, Session,
Snowflake, Snowflake,
@ -15,22 +15,22 @@ import type {
} from "./deps.ts"; } from "./deps.ts";
import { import {
ChannelTypes,
ChannelFactory, ChannelFactory,
ChannelTypes,
DMChannel, DMChannel,
Emoji, Emoji,
Guild, Guild,
GuildChannel,
GuildEmoji, GuildEmoji,
GuildTextChannel, GuildTextChannel,
GuildChannel,
Member, Member,
Message, Message,
MessageReaction, MessageReaction,
NewsChannel, NewsChannel,
textBasedChannels,
ThreadChannel, ThreadChannel,
User, User,
VoiceChannel, VoiceChannel,
textBasedChannels,
} from "./deps.ts"; } from "./deps.ts";
export const cache_sym = Symbol("@cache"); export const cache_sym = Symbol("@cache");
@ -99,32 +99,32 @@ export default function (session: Session): SessionCache {
switch (data.t) { switch (data.t) {
case "MESSAGE_CREATE": case "MESSAGE_CREATE":
messageBootstrapper(cache, raw, false); messageBootstrapper(cache, raw, false);
break; break;
case "MESSAGE_UPDATE": case "MESSAGE_UPDATE":
messageBootstrapper(cache, raw, !raw.edited_timestamp); messageBootstrapper(cache, raw, !raw.edited_timestamp);
break; break;
case "CHANNEL_UPDATE": case "CHANNEL_UPDATE":
case "CHANNEL_CREATE": case "CHANNEL_CREATE":
channelBootstrapper(cache, raw); channelBootstrapper(cache, raw);
break; break;
case "GUILD_MEMBER_ADD": case "GUILD_MEMBER_ADD":
memberBootstrapper(cache, raw, raw.guild_id); memberBootstrapper(cache, raw, raw.guild_id);
break; break;
case "GUILD_CREATE": case "GUILD_CREATE":
guildBootstrapper(cache, raw); guildBootstrapper(cache, raw);
break; break;
case "GUILD_DELETE": case "GUILD_DELETE":
cache.guilds.delete(raw.id); cache.guilds.delete(raw.id);
break; break;
case "MESSAGE_REACTION_ADD": case "MESSAGE_REACTION_ADD":
reactionBootstrapper(cache, raw, false); reactionBootstrapper(cache, raw, false);
break; break;
case "MESSAGE_REACTION_REMOVE": case "MESSAGE_REACTION_REMOVE":
reactionBootstrapper(cache, raw, false); reactionBootstrapper(cache, raw, false);
break; break;
case "MESSAGE_REACTION_REMOVE_ALL": case "MESSAGE_REACTION_REMOVE_ALL":
reactionBootstrapperDeletions(cache, raw); reactionBootstrapperDeletions(cache, raw);
break; break;
} }
}); });
@ -323,8 +323,7 @@ export function reactionBootstrapperDeletions(cache: SessionCache, payload: Disc
}); });
}); });
}); });
} } else {
else {
cache.dms.retrieve(payload.channel_id, (channel) => { cache.dms.retrieve(payload.channel_id, (channel) => {
channel.messages.retrieve(payload.message_id, (message) => { channel.messages.retrieve(payload.message_id, (message) => {
message.reactions = []; message.reactions = [];
@ -414,29 +413,34 @@ export function channelBootstrapper(cache: SessionCache, channel: DiscordChannel
cache.guilds.retrieve(channel.guild_id, (guild) => { cache.guilds.retrieve(channel.guild_id, (guild) => {
if (textBasedChannels.includes(channel.type)) { if (textBasedChannels.includes(channel.type)) {
// deno-lint-ignore no-explicit-any // deno-lint-ignore no-explicit-any
guild.channels.set(channel.id, <any>Object.assign( guild.channels.set(
ChannelFactory.fromGuildChannel(cache.session, channel), channel.id,
{ messages: new StructCache<CachedMessage>(cache.session) } <any> Object.assign(
)); ChannelFactory.fromGuildChannel(cache.session, channel),
} { messages: new StructCache<CachedMessage>(cache.session) },
else { ),
);
} else {
// deno-lint-ignore no-explicit-any // deno-lint-ignore no-explicit-any
guild.channels.set(channel.id, <any>ChannelFactory.fromGuildChannel(cache.session, channel)); guild.channels.set(channel.id, <any> ChannelFactory.fromGuildChannel(cache.session, channel));
} }
}); });
} }
export function memberBootstrapper(cache: SessionCache, member: DiscordMemberWithUser, guildId: Snowflake) { export function memberBootstrapper(cache: SessionCache, member: DiscordMemberWithUser, guildId: Snowflake) {
cache.guilds.retrieve(guildId, (guild) => { cache.guilds.retrieve(guildId, (guild) => {
guild.members.set(member.user.id, Object.assign( guild.members.set(
new Member(cache.session, member, guildId), member.user.id,
{ Object.assign(
userId: member.user.id, new Member(cache.session, member, guildId),
get user(): User | undefined { {
return cache.users.get(this.userId); userId: member.user.id,
} get user(): User | undefined {
} return cache.users.get(this.userId);
)); },
},
),
);
}); });
} }
@ -450,51 +454,67 @@ export function messageBootstrapper(cache: SessionCache, message: DiscordMessage
if (cache.dms.has(message.channel_id)) { if (cache.dms.has(message.channel_id)) {
// is dm // is dm
cache.dms.retrieve(message.channel_id, (dm) => { cache.dms.retrieve(message.channel_id, (dm) => {
dm.messages[partial ? "updateFields" : "set"](message.id, Object.assign( dm.messages[partial ? "updateFields" : "set"](
new Message(cache.session, message), message.id,
{ Object.assign(
authorId: message.author.id, new Message(cache.session, message),
get author(): User | undefined { {
return cache.users.get(this.authorId); authorId: message.author.id,
get author(): User | undefined {
return cache.users.get(this.authorId);
},
}, },
} ),
)); );
}); });
} else { } else {
// is not dm // is not dm
cache.guilds.retrieve(message.guild_id!, (guild) => guild.channels.retrieve(message.channel_id, (dm) => { cache.guilds.retrieve(message.guild_id!, (guild) =>
dm.messages[partial ? "updateFields" : "set"](message.id, Object.assign( guild.channels.retrieve(message.channel_id, (dm) => {
new Message(cache.session, message), dm.messages[partial ? "updateFields" : "set"](
{ message.id,
authorId: message.author.id, Object.assign(
get author(): User | undefined { new Message(cache.session, message),
return cache.users.get(this.authorId); {
}, authorId: message.author.id,
} get author(): User | undefined {
)); return cache.users.get(this.authorId);
})); },
},
),
);
}));
} }
} }
export function guildBootstrapper(cache: SessionCache, guild: DiscordGuild) { export function guildBootstrapper(cache: SessionCache, guild: DiscordGuild) {
const members = new StructCache(cache.session, guild.members?.map((data) => { const members = new StructCache(
const obj: CachedMember = Object.assign(new Member(cache.session, data as DiscordMemberWithUser, guild.id), { cache.session,
userId: data.user!.id, guild.members?.map((data) => {
get user(): User | undefined { const obj: CachedMember = Object.assign(
return cache.users.get(this.userId); new Member(cache.session, data as DiscordMemberWithUser, guild.id),
}, {
}); userId: data.user!.id,
get user(): User | undefined {
return cache.users.get(this.userId);
},
},
);
return [data.user!.id, obj as CachedMember]; return [data.user!.id, obj as CachedMember];
})); }),
);
const channels = new StructCache(cache.session, guild.channels?.map((data) => { const channels = new StructCache(
const obj = Object.assign(ChannelFactory.from(cache.session, data), { cache.session,
messages: new Map(), guild.channels?.map((data) => {
}); const obj = Object.assign(ChannelFactory.from(cache.session, data), {
messages: new Map(),
});
return [data.id, obj as CachedGuildChannel]; return [data.id, obj as CachedGuildChannel];
})); }),
);
cache.guilds.set( cache.guilds.set(
guild.id, guild.id,

View File

@ -23,11 +23,11 @@ export async function connect(shard: Shard): Promise<void> {
socket.onclose = (event) => shard.handleClose(event); socket.onclose = (event) => shard.handleClose(event);
socket.onmessage = (message) => { socket.onmessage = (message) => {
// START WSL GATEWAY PATCH // START WSL GATEWAY PATCH
gotHello = true; gotHello = true;
// END WSL GATEWAY PATCH // END WSL GATEWAY PATCH
shard.handleMessage(message); shard.handleMessage(message);
} };
return new Promise((resolve) => { return new Promise((resolve) => {
socket.onopen = () => { socket.onopen = () => {

View File

@ -17,7 +17,7 @@ export interface RestSendRequestOptions {
} }
export async function sendRequest<T>(rest: RestManager, options: RestSendRequestOptions): Promise<T> { export async function sendRequest<T>(rest: RestManager, options: RestSendRequestOptions): Promise<T> {
try { try {
// CUSTOM HANDLER FOR USER TO LOG OR WHATEVER WHENEVER A FETCH IS MADE // CUSTOM HANDLER FOR USER TO LOG OR WHATEVER WHENEVER A FETCH IS MADE
rest.debug(`[REST - fetching] URL: ${options.url} | ${JSON.stringify(options)}`); rest.debug(`[REST - fetching] URL: ${options.url} | ${JSON.stringify(options)}`);

View File

@ -2268,6 +2268,8 @@ export interface DiscordThreadMembersUpdate {
export interface DiscordThreadMemberUpdate { export interface DiscordThreadMemberUpdate {
/** The id of the thread */ /** The id of the thread */
id: string; id: string;
/** The id of the user */
user_id: string;
/** The id of the guild */ /** The id of the guild */
guild_id: string; guild_id: string;
/** The timestamp when the bot joined this thread. */ /** The timestamp when the bot joined this thread. */

View File

@ -1,6 +1,6 @@
import { GatewayIntents, Session } from "./deps.ts"; import { GatewayIntents, Session } from "./deps.ts";
const token = process.env.TOKEN; const token = process.env.TOKEN;
const intents = GatewayIntents.MessageContent | GatewayIntents.Guilds | GatewayIntents.GuildMessages; const intents = GatewayIntents.MessageContent | GatewayIntents.Guilds | GatewayIntents.GuildMessages;
const session = new Session({ token, intents }); const session = new Session({ token, intents });