mirror of
https://github.com/jaronpate/unicord.git
synced 2026-10-18 21:47:40 +00:00
Merge branch 'master' of github.com:jaronpate/unicord into ft/lru-cache
This commit is contained in:
@@ -173,3 +173,4 @@ dist
|
|||||||
|
|
||||||
# Finder (MacOS) folder config
|
# Finder (MacOS) folder config
|
||||||
.DS_Store
|
.DS_Store
|
||||||
|
.aider*
|
||||||
|
|||||||
+8
-1
@@ -5,6 +5,13 @@ export { Intent, Trait } from './types/common';
|
|||||||
export type { ClientConfig } from './types/common';
|
export type { ClientConfig } from './types/common';
|
||||||
export type { Context } from './types/context';
|
export type { Context } from './types/context';
|
||||||
export { Expectation } from './types/common';
|
export { Expectation } from './types/common';
|
||||||
|
export {
|
||||||
|
ChannelType,
|
||||||
|
ChannelFlags,
|
||||||
|
VideoQualityMode,
|
||||||
|
SortOrderType,
|
||||||
|
ForumLayoutType
|
||||||
|
} from './types/channel';
|
||||||
// Consumable util classes
|
// Consumable util classes
|
||||||
export { Guild } from './types/guild';
|
export { Guild } from './types/guild';
|
||||||
export { Role } from './types/role';
|
export { Role } from './types/role';
|
||||||
@@ -15,4 +22,4 @@ export { Embed } from './types/embed';
|
|||||||
export { Emoji } from './types/emoji';
|
export { Emoji } from './types/emoji';
|
||||||
// Other
|
// Other
|
||||||
export { createCommandHandler, type InteractionData, type InteractionCommpoentData, type InteractionCommandData, type InteractionHandlerFunction } from './types/handler';
|
export { createCommandHandler, type InteractionData, type InteractionCommpoentData, type InteractionCommandData, type InteractionHandlerFunction } from './types/handler';
|
||||||
export { ApplicationCommandType, ApplicationCommandOptionType as CommandOptionType } from './types/applicationCommand';
|
export { ApplicationCommandType, ApplicationCommandOptionType as CommandOptionType } from './types/applicationCommand';
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
|
import { API } from "../api";
|
||||||
|
import { Processor } from "../processor";
|
||||||
import { Channel } from "../../types/channel";
|
import { Channel } from "../../types/channel";
|
||||||
import type { API } from "../api";
|
|
||||||
import type { Processor } from "../processor";
|
|
||||||
import { ObjectCache } from "./cache";
|
import { ObjectCache } from "./cache";
|
||||||
|
|
||||||
export class Channels extends ObjectCache<Channel, Channel> {
|
export class Channels extends ObjectCache<Channel, Channel> {
|
||||||
constructor (api: API, processor: Processor) {
|
constructor(api: API, processor: Processor) {
|
||||||
super(api, processor, 'channels', Channel, ['CHANNEL_CREATE', 'CHANNEL_UPDATE']);
|
super(api, processor, 'channels', Channel, ['CHANNEL_CREATE', 'CHANNEL_UPDATE']);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,15 +1,15 @@
|
|||||||
import { API } from './api';
|
|
||||||
import { Gateway } from './connectors/gateway';
|
|
||||||
import { Processor } from './processor';
|
|
||||||
import { Expectation, HandlerType, Intent, type ClientConfig } from '../types/common';
|
import { Expectation, HandlerType, Intent, type ClientConfig } from '../types/common';
|
||||||
|
import { Message, type DiscordMessage } from '../types/message';
|
||||||
import { exists, isNil } from '../utils/index';
|
import { exists, isNil } from '../utils/index';
|
||||||
import { type DiscordMessage, Message } from '../types/message';
|
import { API } from './api';
|
||||||
|
import { EventBus, type Emitter } from './bus';
|
||||||
|
import { Channels } from './caches/channels';
|
||||||
import { Guilds } from './caches/guilds';
|
import { Guilds } from './caches/guilds';
|
||||||
import { Messages } from './caches/messages';
|
import { Messages } from './caches/messages';
|
||||||
import { Users } from './caches/users';
|
import { Users } from './caches/users';
|
||||||
import { Channels } from './caches/channels';
|
import { Gateway } from './connectors/gateway';
|
||||||
import { hydrate, hydrator, type Hydrateable, type Hydrated } from './hydrator';
|
import { hydrate, hydrator, type Hydrateable, type Hydrated } from './hydrator';
|
||||||
import { EventBus, type Emitter } from './bus';
|
import { Processor } from './processor';
|
||||||
|
|
||||||
export class Client {
|
export class Client {
|
||||||
readonly token: string;
|
readonly token: string;
|
||||||
@@ -141,4 +141,4 @@ export class Client {
|
|||||||
off = (event: string, handler: (...args: any[]) => void) => this.bus.off(event, handler);
|
off = (event: string, handler: (...args: any[]) => void) => this.bus.off(event, handler);
|
||||||
|
|
||||||
connect = () => this.gateway.connect();
|
connect = () => this.gateway.connect();
|
||||||
}
|
}
|
||||||
|
|||||||
+18
-10
@@ -1,15 +1,16 @@
|
|||||||
import { Expectation } from "../types/common";
|
import { Expectation } from "../types/common";
|
||||||
import { Context, type HydratedContext } from "../types/context";
|
import { Context, type HydratedContext } from "../types/context";
|
||||||
import { Message, type HydratedMessage } from "../types/message";
|
import { Message, type HydratedMessage } from "../types/message";
|
||||||
|
import { Channel } from "../types/channel";
|
||||||
import { exists } from "../utils";
|
import { exists } from "../utils";
|
||||||
import type { API } from "./api";
|
import type { API } from "./api";
|
||||||
import type { Client } from "./client";
|
import type { Client } from "./client";
|
||||||
|
|
||||||
export type GatewayObject = Message;
|
export type GatewayObject = Message | Channel;
|
||||||
export type Hydrateable = Context | GatewayObject
|
export type Hydrateable = Context | GatewayObject
|
||||||
export type Hydrated<T extends Hydrateable, K extends Array<Expectation>> =
|
export type Hydrated<T extends Hydrateable, K extends Array<Expectation>> =
|
||||||
T extends Message ? HydratedMessage<K> :
|
T extends Message ? HydratedMessage<K> & Omit<T, keyof HydratedMessage<K>> :
|
||||||
T extends Context ? HydratedContext<K> : never;
|
T extends Context ? HydratedContext<K> & Omit<T, keyof HydratedContext<K>> : never;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Hydrates a given data object based on the provided expectations.
|
* Hydrates a given data object based on the provided expectations.
|
||||||
@@ -26,12 +27,12 @@ export type Hydrated<T extends Hydrateable, K extends Array<Expectation>> =
|
|||||||
*
|
*
|
||||||
* @throws Will throw an error if an expectation cannot be resolved.
|
* @throws Will throw an error if an expectation cannot be resolved.
|
||||||
*/
|
*/
|
||||||
export async function hydrate<T extends Hydrateable | Hydrated<any, any>, K extends Array<Expectation>>(
|
export async function hydrate<T extends Hydrateable, K extends Array<Expectation>>(
|
||||||
data: T,
|
data: T,
|
||||||
expectations: K,
|
expectations: K,
|
||||||
client: Client,
|
client: Client,
|
||||||
api: API
|
api: API
|
||||||
): Promise<T extends Hydrated<infer U, infer H> ? Hydrated<T & U, [...H, ...K]> : Hydrated<T, K>> {
|
): Promise<Hydrated<T, K>> {
|
||||||
// TODO: add clone trait. Make it a requirement for hydrateable objects.
|
// TODO: add clone trait. Make it a requirement for hydrateable objects.
|
||||||
// Then clone the object and return the hydrated object.
|
// Then clone the object and return the hydrated object.
|
||||||
let hydrated: Hydrated<T, K>;
|
let hydrated: Hydrated<T, K>;
|
||||||
@@ -44,6 +45,9 @@ export async function hydrate<T extends Hydrateable | Hydrated<any, any>, K exte
|
|||||||
} else if (expectation === Expectation.Guild && exists(data.guild_id)) {
|
} else if (expectation === Expectation.Guild && exists(data.guild_id)) {
|
||||||
let context = data as unknown as HydratedContext<[Expectation.Guild, ...Expectation[]]>;
|
let context = data as unknown as HydratedContext<[Expectation.Guild, ...Expectation[]]>;
|
||||||
context.guild = await client.guilds.get(data.guild_id);
|
context.guild = await client.guilds.get(data.guild_id);
|
||||||
|
} else if (expectation === Expectation.Channel && exists(data.channel_id)) {
|
||||||
|
let context = data as unknown as HydratedContext<[Expectation.Channel, ...Expectation[]]>;
|
||||||
|
context.channel = await client.channels.get(data.channel_id);
|
||||||
} else {
|
} else {
|
||||||
throw new Error(`Invalid expectation requested for Context: ${expectation}`);
|
throw new Error(`Invalid expectation requested for Context: ${expectation}`);
|
||||||
}
|
}
|
||||||
@@ -65,7 +69,11 @@ export async function hydrate<T extends Hydrateable | Hydrated<any, any>, K exte
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return data as unknown as (T extends Hydrated<infer U, infer H> ? Hydrated<T & U, [...H, ...K]> : Hydrated<T, K>);
|
// Create a new object that preserves all existing properties
|
||||||
|
const result = { ...data } as any;
|
||||||
|
|
||||||
|
// Ensure the result is properly typed with both old and new hydrated properties
|
||||||
|
return result as T & Hydrated<T, K>;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -81,12 +89,12 @@ export async function hydrate<T extends Hydrateable | Hydrated<any, any>, K exte
|
|||||||
*
|
*
|
||||||
* @returns A promise that resolves to a type guard function. The type guard function returns `true` if the data object was successfully hydrated, otherwise `false`.
|
* @returns A promise that resolves to a type guard function. The type guard function returns `true` if the data object was successfully hydrated, otherwise `false`.
|
||||||
*/
|
*/
|
||||||
export async function hydrator<T extends Hydrateable | Hydrated<any, any>, K extends Array<Expectation>>(
|
export async function hydrator<T extends Hydrateable, K extends Array<Expectation>>(
|
||||||
data: T,
|
data: T,
|
||||||
expectations: K,
|
expectations: K,
|
||||||
client: Client,
|
client: Client,
|
||||||
api: API
|
api: API
|
||||||
): Promise<(data: unknown) => data is T extends Hydrated<infer U, infer H> ? Hydrated<T & U, [...H, ...K]> : Hydrated<T, K>> {
|
): Promise<(data: unknown) => data is Hydrated<T, K>> {
|
||||||
let hydrated = true;
|
let hydrated = true;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@@ -98,7 +106,7 @@ export async function hydrator<T extends Hydrateable | Hydrated<any, any>, K ext
|
|||||||
}
|
}
|
||||||
|
|
||||||
// BUG: Resolves to never after hydrations on an already hydrated object
|
// BUG: Resolves to never after hydrations on an already hydrated object
|
||||||
return function (data: unknown): data is T extends Hydrated<infer U, infer H> ? Hydrated<T & U, [...H, ...K]> : Hydrated<T, K> {
|
return function (data: unknown): data is Hydrated<T, K> {
|
||||||
return hydrated;
|
return hydrated;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+251
-52
@@ -1,79 +1,278 @@
|
|||||||
|
import { GatewayObject } from "./base";
|
||||||
import { Trait } from "./common";
|
import { Trait } from "./common";
|
||||||
|
import { User, type DiscordUser } from "./user";
|
||||||
|
|
||||||
export class Channel {
|
export enum ChannelType {
|
||||||
version: number;
|
GUILD_TEXT = 0,
|
||||||
type: number;
|
DM = 1,
|
||||||
position: number;
|
GUILD_VOICE = 2,
|
||||||
permission_overwrites: any[];
|
GROUP_DM = 3,
|
||||||
name: string;
|
GUILD_CATEGORY = 4,
|
||||||
|
GUILD_ANNOUNCEMENT = 5,
|
||||||
|
ANNOUNCEMENT_THREAD = 10,
|
||||||
|
PUBLIC_THREAD = 11,
|
||||||
|
PRIVATE_THREAD = 12,
|
||||||
|
GUILD_STAGE_VOICE = 13,
|
||||||
|
GUILD_DIRECTORY = 14,
|
||||||
|
GUILD_FORUM = 15,
|
||||||
|
GUILD_MEDIA = 16
|
||||||
|
}
|
||||||
|
|
||||||
|
export enum ChannelFlags {
|
||||||
|
PINNED = 1 << 1,
|
||||||
|
REQUIRE_TAG = 1 << 4,
|
||||||
|
HIDE_MEDIA_DOWNLOAD_OPTIONS = 1 << 15
|
||||||
|
}
|
||||||
|
|
||||||
|
export enum VideoQualityMode {
|
||||||
|
AUTO = 1,
|
||||||
|
FULL = 2
|
||||||
|
}
|
||||||
|
|
||||||
|
export enum SortOrderType {
|
||||||
|
LATEST_ACTIVITY = 0,
|
||||||
|
CREATION_DATE = 1
|
||||||
|
}
|
||||||
|
|
||||||
|
export enum ForumLayoutType {
|
||||||
|
NOT_SET = 0,
|
||||||
|
LIST_VIEW = 1,
|
||||||
|
GALLERY_VIEW = 2
|
||||||
|
}
|
||||||
|
|
||||||
|
export type PermissionOverwrite = {
|
||||||
id: string;
|
id: string;
|
||||||
flags: number;
|
type: 0 | 1; // 0 for role, 1 for member
|
||||||
topic?: string | null;
|
allow: string;
|
||||||
rate_limit_per_user?: number;
|
deny: string;
|
||||||
parent_id?: string;
|
}
|
||||||
last_message_id?: string | null;
|
|
||||||
user_limit?: number;
|
|
||||||
rtc_region?: string | null;
|
|
||||||
bitrate?: number;
|
|
||||||
last_pin_timestamp?: string;
|
|
||||||
|
|
||||||
constructor(data: any) {
|
export type ThreadMetadata = {
|
||||||
this.version = data.version;
|
archived: boolean;
|
||||||
this.type = data.type;
|
auto_archive_duration: number;
|
||||||
|
archive_timestamp: string;
|
||||||
|
locked: boolean;
|
||||||
|
invitable?: boolean;
|
||||||
|
create_timestamp?: string | null;
|
||||||
|
}
|
||||||
|
|
||||||
|
export type ThreadMember = {
|
||||||
|
id?: string;
|
||||||
|
user_id?: string;
|
||||||
|
join_timestamp: string;
|
||||||
|
flags: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export type ForumTag = {
|
||||||
|
id: string;
|
||||||
|
name: string;
|
||||||
|
moderated: boolean;
|
||||||
|
emoji_id?: string | null;
|
||||||
|
emoji_name?: string | null;
|
||||||
|
}
|
||||||
|
|
||||||
|
export type DefaultReaction = {
|
||||||
|
emoji_id?: string | null; // the id of a guild's custom emoji
|
||||||
|
emoji_name?: string | null; // the unicode character of the emoji
|
||||||
|
}
|
||||||
|
|
||||||
|
export class Channel extends GatewayObject {
|
||||||
|
id: string;
|
||||||
|
type: ChannelType;
|
||||||
|
guild_id?: string;
|
||||||
|
position?: number;
|
||||||
|
permission_overwrites?: PermissionOverwrite[];
|
||||||
|
name?: string;
|
||||||
|
topic?: string | null;
|
||||||
|
nsfw?: boolean;
|
||||||
|
last_message_id?: string | null;
|
||||||
|
bitrate?: number;
|
||||||
|
user_limit?: number;
|
||||||
|
rate_limit_per_user?: number;
|
||||||
|
recipients?: User[];
|
||||||
|
icon?: string | null;
|
||||||
|
owner_id?: string;
|
||||||
|
application_id?: string;
|
||||||
|
managed?: boolean;
|
||||||
|
parent_id?: string | null;
|
||||||
|
last_pin_timestamp?: Date | null;
|
||||||
|
rtc_region?: string | null;
|
||||||
|
video_quality_mode?: VideoQualityMode;
|
||||||
|
message_count?: number;
|
||||||
|
member_count?: number;
|
||||||
|
thread_metadata?: ThreadMetadata;
|
||||||
|
member?: ThreadMember;
|
||||||
|
default_auto_archive_duration?: number;
|
||||||
|
permissions?: string;
|
||||||
|
flags?: number;
|
||||||
|
total_message_sent?: number;
|
||||||
|
available_tags?: ForumTag[];
|
||||||
|
applied_tags?: string[];
|
||||||
|
default_reaction_emoji?: DefaultReaction;
|
||||||
|
default_thread_rate_limit_per_user?: number;
|
||||||
|
default_sort_order?: SortOrderType | null;
|
||||||
|
default_forum_layout?: ForumLayoutType;
|
||||||
|
|
||||||
|
constructor(data: Partial<Channel>) {
|
||||||
|
super();
|
||||||
|
this.id = data.id!;
|
||||||
|
this.type = data.type!;
|
||||||
|
this.guild_id = data.guild_id;
|
||||||
this.position = data.position;
|
this.position = data.position;
|
||||||
this.permission_overwrites = data.permission_overwrites;
|
this.permission_overwrites = data.permission_overwrites;
|
||||||
this.name = data.name;
|
this.name = data.name;
|
||||||
this.id = data.id;
|
|
||||||
this.flags = data.flags;
|
|
||||||
this.topic = data.topic;
|
this.topic = data.topic;
|
||||||
this.rate_limit_per_user = data.rate_limit_per_user;
|
this.nsfw = data.nsfw;
|
||||||
this.parent_id = data.parent_id;
|
|
||||||
this.last_message_id = data.last_message_id;
|
this.last_message_id = data.last_message_id;
|
||||||
this.user_limit = data.user_limit;
|
|
||||||
this.rtc_region = data.rtc_region;
|
|
||||||
this.bitrate = data.bitrate;
|
this.bitrate = data.bitrate;
|
||||||
this.last_pin_timestamp = data.last_pin_timestamp;
|
this.user_limit = data.user_limit;
|
||||||
|
this.rate_limit_per_user = data.rate_limit_per_user;
|
||||||
|
this.recipients = data.recipients;
|
||||||
|
this.icon = data.icon;
|
||||||
|
this.owner_id = data.owner_id;
|
||||||
|
this.application_id = data.application_id;
|
||||||
|
this.managed = data.managed;
|
||||||
|
this.parent_id = data.parent_id;
|
||||||
|
this.last_pin_timestamp = data.last_pin_timestamp instanceof Date
|
||||||
|
? data.last_pin_timestamp
|
||||||
|
: data.last_pin_timestamp
|
||||||
|
? new Date(data.last_pin_timestamp)
|
||||||
|
: null;
|
||||||
|
this.rtc_region = data.rtc_region;
|
||||||
|
this.video_quality_mode = data.video_quality_mode;
|
||||||
|
this.message_count = data.message_count;
|
||||||
|
this.member_count = data.member_count;
|
||||||
|
this.thread_metadata = data.thread_metadata;
|
||||||
|
this.member = data.member;
|
||||||
|
this.default_auto_archive_duration = data.default_auto_archive_duration;
|
||||||
|
this.permissions = data.permissions;
|
||||||
|
this.flags = data.flags;
|
||||||
|
this.total_message_sent = data.total_message_sent;
|
||||||
|
this.available_tags = data.available_tags;
|
||||||
|
this.applied_tags = data.applied_tags;
|
||||||
|
this.default_reaction_emoji = data.default_reaction_emoji;
|
||||||
|
this.default_thread_rate_limit_per_user = data.default_thread_rate_limit_per_user;
|
||||||
|
this.default_sort_order = data.default_sort_order;
|
||||||
|
this.default_forum_layout = data.default_forum_layout;
|
||||||
}
|
}
|
||||||
|
|
||||||
static [Trait.fromDiscord](data: DiscordChannel): Channel {
|
public static [Trait.fromDiscord]<T = Channel>(data: DiscordChannel): T {
|
||||||
return new Channel({
|
return new Channel({
|
||||||
version: data.version,
|
id: data.id,
|
||||||
type: data.type,
|
type: data.type,
|
||||||
|
guild_id: data.guild_id,
|
||||||
position: data.position,
|
position: data.position,
|
||||||
permission_overwrites: data.permission_overwrites,
|
permission_overwrites: data.permission_overwrites,
|
||||||
name: data.name,
|
name: data.name,
|
||||||
id: data.id,
|
|
||||||
flags: data.flags,
|
|
||||||
topic: data.topic,
|
topic: data.topic,
|
||||||
rate_limit_per_user: data.rate_limit_per_user,
|
nsfw: data.nsfw,
|
||||||
parent_id: data.parent_id,
|
|
||||||
last_message_id: data.last_message_id,
|
last_message_id: data.last_message_id,
|
||||||
user_limit: data.user_limit,
|
|
||||||
rtc_region: data.rtc_region,
|
|
||||||
bitrate: data.bitrate,
|
bitrate: data.bitrate,
|
||||||
last_pin_timestamp: data.last_pin_timestamp
|
user_limit: data.user_limit,
|
||||||
});
|
rate_limit_per_user: data.rate_limit_per_user,
|
||||||
}
|
recipients: data.recipients?.map(u => User.fromDiscord(u)),
|
||||||
|
icon: data.icon,
|
||||||
static fromAPIResponse(data: any): Channel {
|
owner_id: data.owner_id,
|
||||||
return new Channel(data);
|
application_id: data.application_id,
|
||||||
|
managed: data.managed,
|
||||||
|
parent_id: data.parent_id,
|
||||||
|
last_pin_timestamp: data.last_pin_timestamp ? new Date(data.last_pin_timestamp) : null,
|
||||||
|
rtc_region: data.rtc_region,
|
||||||
|
video_quality_mode: data.video_quality_mode,
|
||||||
|
message_count: data.message_count,
|
||||||
|
member_count: data.member_count,
|
||||||
|
thread_metadata: data.thread_metadata,
|
||||||
|
member: data.member,
|
||||||
|
default_auto_archive_duration: data.default_auto_archive_duration,
|
||||||
|
permissions: data.permissions,
|
||||||
|
flags: data.flags,
|
||||||
|
total_message_sent: data.total_message_sent,
|
||||||
|
available_tags: data.available_tags,
|
||||||
|
applied_tags: data.applied_tags,
|
||||||
|
default_reaction_emoji: data.default_reaction_emoji,
|
||||||
|
default_thread_rate_limit_per_user: data.default_thread_rate_limit_per_user,
|
||||||
|
default_sort_order: data.default_sort_order,
|
||||||
|
default_forum_layout: data.default_forum_layout
|
||||||
|
}) as T;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export type DiscordChannel = {
|
export class DiscordChannel {
|
||||||
version: number;
|
|
||||||
type: number;
|
|
||||||
position: number;
|
|
||||||
permission_overwrites: any[];
|
|
||||||
name: string;
|
|
||||||
id: string;
|
id: string;
|
||||||
flags: number;
|
type: number;
|
||||||
|
guild_id?: string;
|
||||||
|
position?: number;
|
||||||
|
permission_overwrites?: PermissionOverwrite[];
|
||||||
|
name?: string;
|
||||||
topic?: string | null;
|
topic?: string | null;
|
||||||
rate_limit_per_user?: number;
|
nsfw?: boolean;
|
||||||
parent_id?: string;
|
|
||||||
last_message_id?: string | null;
|
last_message_id?: string | null;
|
||||||
user_limit?: number;
|
|
||||||
rtc_region?: string | null;
|
|
||||||
bitrate?: number;
|
bitrate?: number;
|
||||||
last_pin_timestamp?: string;
|
user_limit?: number;
|
||||||
}
|
rate_limit_per_user?: number;
|
||||||
|
recipients?: DiscordUser[];
|
||||||
|
icon?: string | null;
|
||||||
|
owner_id?: string;
|
||||||
|
application_id?: string;
|
||||||
|
managed?: boolean;
|
||||||
|
parent_id?: string | null;
|
||||||
|
last_pin_timestamp?: string | null;
|
||||||
|
rtc_region?: string | null;
|
||||||
|
video_quality_mode?: number;
|
||||||
|
message_count?: number;
|
||||||
|
member_count?: number;
|
||||||
|
thread_metadata?: ThreadMetadata;
|
||||||
|
member?: ThreadMember;
|
||||||
|
default_auto_archive_duration?: number;
|
||||||
|
permissions?: string;
|
||||||
|
flags?: number;
|
||||||
|
total_message_sent?: number;
|
||||||
|
available_tags?: ForumTag[];
|
||||||
|
applied_tags?: string[];
|
||||||
|
default_reaction_emoji?: DefaultReaction;
|
||||||
|
default_thread_rate_limit_per_user?: number;
|
||||||
|
default_sort_order?: number | null;
|
||||||
|
default_forum_layout?: number;
|
||||||
|
|
||||||
|
constructor(data: any) {
|
||||||
|
this.id = data.id;
|
||||||
|
this.type = data.type;
|
||||||
|
this.guild_id = data.guild_id;
|
||||||
|
this.position = data.position;
|
||||||
|
this.permission_overwrites = data.permission_overwrites;
|
||||||
|
this.name = data.name;
|
||||||
|
this.topic = data.topic;
|
||||||
|
this.nsfw = data.nsfw;
|
||||||
|
this.last_message_id = data.last_message_id;
|
||||||
|
this.bitrate = data.bitrate;
|
||||||
|
this.user_limit = data.user_limit;
|
||||||
|
this.rate_limit_per_user = data.rate_limit_per_user;
|
||||||
|
this.recipients = data.recipients;
|
||||||
|
this.icon = data.icon;
|
||||||
|
this.owner_id = data.owner_id;
|
||||||
|
this.application_id = data.application_id;
|
||||||
|
this.managed = data.managed;
|
||||||
|
this.parent_id = data.parent_id;
|
||||||
|
this.last_pin_timestamp = data.last_pin_timestamp;
|
||||||
|
this.rtc_region = data.rtc_region;
|
||||||
|
this.video_quality_mode = data.video_quality_mode;
|
||||||
|
this.message_count = data.message_count;
|
||||||
|
this.member_count = data.member_count;
|
||||||
|
this.thread_metadata = data.thread_metadata;
|
||||||
|
this.member = data.member;
|
||||||
|
this.default_auto_archive_duration = data.default_auto_archive_duration;
|
||||||
|
this.permissions = data.permissions;
|
||||||
|
this.flags = data.flags;
|
||||||
|
this.total_message_sent = data.total_message_sent;
|
||||||
|
this.available_tags = data.available_tags;
|
||||||
|
this.applied_tags = data.applied_tags;
|
||||||
|
this.default_reaction_emoji = data.default_reaction_emoji;
|
||||||
|
this.default_thread_rate_limit_per_user = data.default_thread_rate_limit_per_user;
|
||||||
|
this.default_sort_order = data.default_sort_order;
|
||||||
|
this.default_forum_layout = data.default_forum_layout;
|
||||||
|
}
|
||||||
|
|
||||||
|
static fromAPIResponse(data: any): DiscordChannel {
|
||||||
|
return new DiscordChannel(data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import { hydrate, hydrator, type Hydrateable, type Hydrated } from "../services/
|
|||||||
import { isNil, exists } from "../utils";
|
import { isNil, exists } from "../utils";
|
||||||
import { fromDiscord, InteractionResponseType, type Expectation } from "./common";
|
import { fromDiscord, InteractionResponseType, type Expectation } from "./common";
|
||||||
import type { Guild } from "./guild";
|
import type { Guild } from "./guild";
|
||||||
|
import { Channel } from "./channel";
|
||||||
import type { InteractionPayload } from "./handler";
|
import type { InteractionPayload } from "./handler";
|
||||||
import { type DiscordMessage, Message, type MessagePayload } from "./message";
|
import { type DiscordMessage, Message, type MessagePayload } from "./message";
|
||||||
/**
|
/**
|
||||||
@@ -28,6 +29,7 @@ import { type DiscordMessage, Message, type MessagePayload } from "./message";
|
|||||||
export type HydratedContext<T extends Array<Expectation>> = Context & {
|
export type HydratedContext<T extends Array<Expectation>> = Context & {
|
||||||
guild: Extract<Expectation.Guild, T[number]> extends never ? undefined : Guild;
|
guild: Extract<Expectation.Guild, T[number]> extends never ? undefined : Guild;
|
||||||
message: Extract<Expectation.Message, T[number]> extends never ? undefined : Message;
|
message: Extract<Expectation.Message, T[number]> extends never ? undefined : Message;
|
||||||
|
channel: Extract<Expectation.Channel, T[number]> extends never ? undefined : Channel;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type ContextData =
|
export type ContextData =
|
||||||
@@ -92,7 +94,7 @@ export class Context<D extends ContextData = ContextData> {
|
|||||||
*
|
*
|
||||||
* @returns A promise that resolves to a type guard function. The type guard function returns `true` if the data object was successfully hydrated, otherwise `false`.
|
* @returns A promise that resolves to a type guard function. The type guard function returns `true` if the data object was successfully hydrated, otherwise `false`.
|
||||||
*/
|
*/
|
||||||
public hydrator = async <T extends Hydrateable | Hydrated<Hydrateable, Array<Expectation>>, K extends Array<Expectation>>(data: T, expectations: K) => {
|
public hydrator = async <T extends Hydrateable, K extends Array<Expectation>>(data: T, expectations: K) => {
|
||||||
return hydrator<T, K>(data, expectations, this.client, this.api);
|
return hydrator<T, K>(data, expectations, this.client, this.api);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -174,4 +176,4 @@ export class Context<D extends ContextData = ContextData> {
|
|||||||
public defer = async () => {
|
public defer = async () => {
|
||||||
return this.ack(InteractionResponseType.DeferredMessage);
|
return this.ack(InteractionResponseType.DeferredMessage);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -35,6 +35,11 @@ export type Component = Partial<Button | SelectMenu> & {
|
|||||||
// components?: Component[];
|
// components?: Component[];
|
||||||
// }
|
// }
|
||||||
|
|
||||||
|
export type DefaultReaction = {
|
||||||
|
emoji_id?: string | null; // the id of a guild's custom emoji
|
||||||
|
emoji_name?: string | null; // the unicode character of the emoji
|
||||||
|
};
|
||||||
|
|
||||||
export type Emoji = {
|
export type Emoji = {
|
||||||
name: string | null;
|
name: string | null;
|
||||||
id: string | null;
|
id: string | null;
|
||||||
@@ -275,4 +280,4 @@ export type DiscordMessage = {
|
|||||||
preview_asset?: string;
|
preview_asset?: string;
|
||||||
format_type: number;
|
format_type: number;
|
||||||
}[];
|
}[];
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { ApplicationCommandType, Client, CommandOptionType, ComponentStyle, type Context, createCommandHandler, Expectation, Intent, InteractionCommpoentData, type InteractionData, Message, type MessagePayload } from '../src/index';
|
import { ApplicationCommandType, ChannelType, Client, CommandOptionType, ComponentStyle, type Context, createCommandHandler, Expectation, Intent, InteractionCommpoentData, type InteractionData, Message, type MessagePayload } from '../src/index';
|
||||||
|
|
||||||
const client = new Client({
|
const client = new Client({
|
||||||
token: process.env.BOT_TOKEN!,
|
token: process.env.BOT_TOKEN!,
|
||||||
@@ -78,20 +78,18 @@ Nice to meet you, I'm ${context.self.username}!`
|
|||||||
// Repeated hydration
|
// Repeated hydration
|
||||||
client.chatCommands.register('me', async (context: Context, _args: any[]) => {
|
client.chatCommands.register('me', async (context: Context, _args: any[]) => {
|
||||||
// Note: Testing repeated hydration
|
// Note: Testing repeated hydration
|
||||||
const { message } = await context.hydrate(context, [Expectation.Message])
|
const { message } = await context.hydrate(context, [Expectation.Message]);
|
||||||
const hydrated = await context.hydrate(message, [Expectation.Channel])
|
const { channel } = await context.hydrate(message, [Expectation.Channel]);
|
||||||
// const rehydrated = await context.hydrate(hydrated, [Expectation.Guild]);
|
|
||||||
// rehydrated.guild.name
|
|
||||||
|
|
||||||
const hydrate = await context.hydrator(hydrated, [Expectation.Guild]);
|
const hydrate = await context.hydrator(context, [Expectation.Guild]);
|
||||||
const hasGuild = hydrate(hydrated);
|
const hasGuild = hydrate(context);
|
||||||
|
|
||||||
if (hasGuild) {
|
if (hasGuild) {
|
||||||
// Send a message stating the user that they are in a guild
|
// Send a message stating the user that they are in a guild
|
||||||
await context.reply(`You are ${message.author.username} and this is ${hydrated.guild.name}`, true);
|
await context.reply(`You are ${message.author.username} and this is ${context.guild.name}`, true);
|
||||||
} else {
|
} else {
|
||||||
// Send a message stating the user that they are not in a guild
|
// Send a message stating the user that they are not in a guild
|
||||||
await context.reply(`You are ${message.author.username} and we are in ${hydrated.channel.type === 1 ? 'our DM\'s <3' : 'a Group DM 👀'}`, true);
|
await context.reply(`You are ${message.author.username} and we are in ${channel.type === ChannelType.DM ? 'our DM\'s 😘' : 'a Group 👀'}`, true);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user