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**
A clear and concise description of what the bug is.
**Describe the bug** A clear and concise description of what the bug is.
**Biscuit Version**
eg: 0.1.0-rc7
**Biscuit Version** eg: 0.1.0-rc7
**To Reproduce** Steps to reproduce the behavior:
**To Reproduce**
Steps to reproduce the behavior:
1. Go to '...'
2. Click on '....'
3. Scroll down to '....'
4. See error
**Expected behavior**
A clear and concise description of what you expected to happen.
**Expected behavior** A clear and concise description of what you expected to happen.
**etc**
Whatever
**etc** Whatever

View File

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

View File

@ -1,32 +1,38 @@
# biscuit
## A brand new bleeding edge non bloated Discord library
### Install (for [node18](https://nodejs.org/en/download/))
```sh-session
npm install @oasisjs/biscuit
pnpm add @oasisjs/biscuit
yarn add @oasisjs/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.
Join our [Discord](https://discord.gg/zmuvzzEFz2)
The biscuit Discord library is built ontop of Discordeno and webspec APIs, we aim to provide portability. Join our
[Discord](https://discord.gg/zmuvzzEFz2)
### 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?:
* [Minimal](https://en.wikipedia.org/wiki/Unix_philosophy), non feature-rich!
* Crossplatform
* Consistent
* Performant
- [Minimal](https://en.wikipedia.org/wiki/Unix_philosophy), non feature-rich!
- Crossplatform
- Consistent
- Performant
### Example bot (TS/JS)
```js
import { GatewayIntents, Session } from "biscuit";
@ -49,23 +55,28 @@ session.start();
```
### Mininal style guide
* 4 spaces, no tabs
* Semi-colons are mandatory
* Run `deno fmt`
* Avoid circular dependencies
- 4 spaces, no tabs
- Semi-colons are mandatory
- Run `deno fmt`
- Avoid circular dependencies
### Contrib guide
* Install Deno extension [here](https://marketplace.visualstudio.com/items?itemName=denoland.vscode-deno)
* Run `deno check` to make sure the library works
* Avoid sharing state between classes
- Install Deno extension [here](https://marketplace.visualstudio.com/items?itemName=denoland.vscode-deno)
- Run `deno check` to make sure the library works
- Avoid sharing state between classes
### Compatibility
#### bun
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 WSL
- 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 WSL
#### 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({
shims: {
custom: [
{
package: {
name: 'ws',
version: '^8.4.0',
name: "ws",
version: "^8.4.0",
},
globalNames: [
{
name: 'WebSocket',
exportName: 'default',
name: "WebSocket",
exportName: "default",
},
],
},
],
},
package: {
author: 'Yuzuru',
name: '@oasisjs/biscuit',
author: "Yuzuru",
name: "@oasisjs/biscuit",
version: Deno.args[0],
description: 'the Biscuit library',
license: 'Apache License 2.0',
description: "the Biscuit library",
license: "Apache License 2.0",
repository: {
type: 'git',
url: 'git+https://github.com/deno-biscuit/biscuit.git',
type: "git",
url: "git+https://github.com/deno-biscuit/biscuit.git",
},
bugs: {
url: 'https://github.com/deno-biscuit/biscuit/issues',
url: "https://github.com/deno-biscuit/biscuit/issues",
},
typesVersions: {
'*': {
'*': ['./types/mod.d.ts'],
'biscuit': ['./types/packages/biscuit/mod.d.ts'],
'discordeno': ['./types/packages/discordeno/mod.d.ts'],
'cache': ['./types/packages/cache/mod.d.ts'],
"*": {
"*": ["./types/mod.d.ts"],
"biscuit": ["./types/packages/biscuit/mod.d.ts"],
"discordeno": ["./types/packages/discordeno/mod.d.ts"],
"cache": ["./types/packages/cache/mod.d.ts"],
},
},
},
entryPoints: [
'./mod.ts',
"./mod.ts",
{
name: './biscuit',
path: 'packages/biscuit/mod.ts',
name: "./biscuit",
path: "packages/biscuit/mod.ts",
},
{
name: './discordeno',
path: 'packages/discordeno/mod.ts',
name: "./discordeno",
path: "packages/discordeno/mod.ts",
},
{
name: './cache',
path: 'packages/cache/mod.ts',
name: "./cache",
path: "packages/cache/mod.ts",
},
],
outDir: './npm',
outDir: "./npm",
declaration: true,
typeCheck: false,
test: false,
});
// post build steps
Deno.copyFileSync('LICENSE', 'npm/LICENSE');
Deno.copyFileSync('README.md', 'npm/README.md');
Deno.copyFileSync("LICENSE", "npm/LICENSE");
Deno.copyFileSync("README.md", "npm/README.md");

View File

@ -31,9 +31,9 @@ import type {
DiscordScheduledEvent,
DiscordScheduledEventUserAdd,
DiscordScheduledEventUserRemove,
// DiscordThreadMemberUpdate,
// DiscordThreadMembersUpdate,
DiscordThreadListSync,
DiscordThreadMembersUpdate,
DiscordThreadMemberUpdate,
DiscordTypingStart,
DiscordUser,
DiscordWebhookUpdate,
@ -192,6 +192,28 @@ export const THREAD_DELETE: RawHandler<DiscordChannel> = (session, _shardId, cha
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) => {
session.emit("threadListSync", {
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) => {
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"> {
@ -386,6 +408,8 @@ export interface Events {
"threadUpdate": Handler<[ThreadChannel]>;
"threadDelete": Handler<[ThreadChannel]>;
"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]>;
"integrationCreate": Handler<[Integration]>;
"integrationUpdate": Handler<[Integration]>;

View File

@ -9,7 +9,7 @@ export interface MessageReactionAdd {
messageId: string;
guildId?: string;
member?: Member;
emoji: Partial<Emoji>
emoji: Partial<Emoji>;
}
export function NewMessageReactionAdd(session: Session, data: DiscordMessageReactionAdd): MessageReactionAdd {
@ -18,9 +18,11 @@ export function NewMessageReactionAdd(session: Session, data: DiscordMessageReac
channelId: data.channel_id,
messageId: data.message_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),
}
};
}
/**

View File

@ -210,19 +210,19 @@ export class Guild extends BaseGuild implements Model {
this.explicitContentFilterLevel = data.explicit_content_filter;
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(
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(
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(
data.channels?.map((guildChannel) => [guildChannel.id, new GuildChannel(session, guildChannel, data.id)])
data.channels?.map((guildChannel) => [guildChannel.id, new GuildChannel(session, guildChannel, data.id)]),
);
}

80
packages/cache/mod.ts vendored
View File

@ -1,13 +1,13 @@
import type {
DiscordMessage,
DiscordChannel,
DiscordEmoji,
DiscordGuild,
DiscordMemberWithUser,
DiscordMessage,
DiscordMessageReactionAdd,
DiscordMessageReactionRemove,
DiscordMessageReactionRemoveEmoji,
DiscordMessageReactionRemoveAll,
DiscordMessageReactionRemoveEmoji,
DiscordUser,
Session,
Snowflake,
@ -15,22 +15,22 @@ import type {
} from "./deps.ts";
import {
ChannelTypes,
ChannelFactory,
ChannelTypes,
DMChannel,
Emoji,
Guild,
GuildChannel,
GuildEmoji,
GuildTextChannel,
GuildChannel,
Member,
Message,
MessageReaction,
NewsChannel,
textBasedChannels,
ThreadChannel,
User,
VoiceChannel,
textBasedChannels,
} from "./deps.ts";
export const cache_sym = Symbol("@cache");
@ -323,8 +323,7 @@ export function reactionBootstrapperDeletions(cache: SessionCache, payload: Disc
});
});
});
}
else {
} else {
cache.dms.retrieve(payload.channel_id, (channel) => {
channel.messages.retrieve(payload.message_id, (message) => {
message.reactions = [];
@ -414,29 +413,34 @@ export function channelBootstrapper(cache: SessionCache, channel: DiscordChannel
cache.guilds.retrieve(channel.guild_id, (guild) => {
if (textBasedChannels.includes(channel.type)) {
// deno-lint-ignore no-explicit-any
guild.channels.set(channel.id, <any>Object.assign(
guild.channels.set(
channel.id,
<any> Object.assign(
ChannelFactory.fromGuildChannel(cache.session, channel),
{ messages: new StructCache<CachedMessage>(cache.session) }
));
}
else {
{ messages: new StructCache<CachedMessage>(cache.session) },
),
);
} else {
// 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) {
cache.guilds.retrieve(guildId, (guild) => {
guild.members.set(member.user.id, Object.assign(
guild.members.set(
member.user.id,
Object.assign(
new Member(cache.session, member, guildId),
{
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)) {
// is dm
cache.dms.retrieve(message.channel_id, (dm) => {
dm.messages[partial ? "updateFields" : "set"](message.id, Object.assign(
dm.messages[partial ? "updateFields" : "set"](
message.id,
Object.assign(
new Message(cache.session, message),
{
authorId: message.author.id,
get author(): User | undefined {
return cache.users.get(this.authorId);
},
}
));
},
),
);
});
} else {
// is not dm
cache.guilds.retrieve(message.guild_id!, (guild) => guild.channels.retrieve(message.channel_id, (dm) => {
dm.messages[partial ? "updateFields" : "set"](message.id, Object.assign(
cache.guilds.retrieve(message.guild_id!, (guild) =>
guild.channels.retrieve(message.channel_id, (dm) => {
dm.messages[partial ? "updateFields" : "set"](
message.id,
Object.assign(
new Message(cache.session, message),
{
authorId: message.author.id,
get author(): User | undefined {
return cache.users.get(this.authorId);
},
}
));
},
),
);
}));
}
}
export function guildBootstrapper(cache: SessionCache, guild: DiscordGuild) {
const members = new StructCache(cache.session, guild.members?.map((data) => {
const obj: CachedMember = Object.assign(new Member(cache.session, data as DiscordMemberWithUser, guild.id), {
const members = new StructCache(
cache.session,
guild.members?.map((data) => {
const obj: CachedMember = Object.assign(
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];
}));
}),
);
const channels = new StructCache(cache.session, guild.channels?.map((data) => {
const channels = new StructCache(
cache.session,
guild.channels?.map((data) => {
const obj = Object.assign(ChannelFactory.from(cache.session, data), {
messages: new Map(),
});
return [data.id, obj as CachedGuildChannel];
}));
}),
);
cache.guilds.set(
guild.id,

View File

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

View File

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