mirror of
https://github.com/stoatchat/javascript-client-sdk.git
synced 2026-07-19 17:13:31 -04:00
chore: use explicit return types and fix imports
This commit is contained in:
+39
-44
@@ -1,44 +1,39 @@
|
||||
import { Accessor, Setter, batch, createSignal } from "solid-js";
|
||||
import type { Accessor, Setter } from "solid-js";
|
||||
import { batch, createSignal } from "solid-js";
|
||||
|
||||
import EventEmitter from "eventemitter3";
|
||||
import type { DataLogin, Error, RevoltConfig } from "revolt-api";
|
||||
import { API, Role } from "revolt-api";
|
||||
import type { DataLogin, RevoltConfig, Role } from "revolt-api";
|
||||
import { API } from "revolt-api";
|
||||
|
||||
import {
|
||||
Channel,
|
||||
Emoji,
|
||||
Message,
|
||||
Server,
|
||||
ServerMember,
|
||||
User,
|
||||
} from "./classes/index.js";
|
||||
import type { Channel } from "./classes/Channel.js";
|
||||
import type { Emoji } from "./classes/Emoji.js";
|
||||
import type { Message } from "./classes/Message.js";
|
||||
import type { Server } from "./classes/Server.js";
|
||||
import type { ServerMember } from "./classes/ServerMember.js";
|
||||
import type { User } from "./classes/User.js";
|
||||
import { AccountCollection } from "./collections/AccountCollection.js";
|
||||
import {
|
||||
BotCollection,
|
||||
ChannelCollection,
|
||||
ChannelUnreadCollection,
|
||||
ChannelWebhookCollection,
|
||||
EmojiCollection,
|
||||
MessageCollection,
|
||||
ServerCollection,
|
||||
ServerMemberCollection,
|
||||
SessionCollection,
|
||||
UserCollection,
|
||||
} from "./collections/index.js";
|
||||
import { BotCollection } from "./collections/BotCollection.js";
|
||||
import { ChannelCollection } from "./collections/ChannelCollection.js";
|
||||
import { ChannelUnreadCollection } from "./collections/ChannelUnreadCollection.js";
|
||||
import { ChannelWebhookCollection } from "./collections/ChannelWebhookCollection.js";
|
||||
import { EmojiCollection } from "./collections/EmojiCollection.js";
|
||||
import { MessageCollection } from "./collections/MessageCollection.js";
|
||||
import { ServerCollection } from "./collections/ServerCollection.js";
|
||||
import { ServerMemberCollection } from "./collections/ServerMemberCollection.js";
|
||||
import { SessionCollection } from "./collections/SessionCollection.js";
|
||||
import { UserCollection } from "./collections/UserCollection.js";
|
||||
import {
|
||||
ConnectionState,
|
||||
EventClient,
|
||||
EventClientOptions,
|
||||
handleEventV1,
|
||||
} from "./events/index.js";
|
||||
import {
|
||||
HydratedChannel,
|
||||
HydratedEmoji,
|
||||
HydratedMessage,
|
||||
HydratedServer,
|
||||
HydratedServerMember,
|
||||
HydratedUser,
|
||||
} from "./hydration/index.js";
|
||||
type EventClientOptions,
|
||||
} from "./events/EventClient.js";
|
||||
import { handleEvent } from "./events/v1.js";
|
||||
import type { HydratedChannel } from "./hydration/channel.js";
|
||||
import type { HydratedEmoji } from "./hydration/emoji.js";
|
||||
import type { HydratedMessage } from "./hydration/message.js";
|
||||
import type { HydratedServer } from "./hydration/server.js";
|
||||
import type { HydratedServerMember } from "./hydration/serverMember.js";
|
||||
import type { HydratedUser } from "./hydration/user.js";
|
||||
import { RE_CHANNELS, RE_MENTIONS, RE_SPOILER } from "./lib/regex.js";
|
||||
|
||||
export type Session = { _id: string; token: string; user_id: string } | string;
|
||||
@@ -275,21 +270,21 @@ export class Client extends EventEmitter<Events> {
|
||||
});
|
||||
|
||||
this.events.on("event", (event) =>
|
||||
handleEventV1(this, event, this.#setReady)
|
||||
handleEvent(this, event, this.#setReady)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Current session id
|
||||
*/
|
||||
get sessionId() {
|
||||
get sessionId(): string | undefined {
|
||||
return typeof this.#session === "string" ? undefined : this.#session?._id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get authentication header
|
||||
*/
|
||||
get authenticationHeader() {
|
||||
get authenticationHeader(): [string, string] {
|
||||
return typeof this.#session === "string"
|
||||
? ["X-Bot-Token", this.#session]
|
||||
: ["X-Session-Token", this.#session?.token as string];
|
||||
@@ -298,7 +293,7 @@ export class Client extends EventEmitter<Events> {
|
||||
/**
|
||||
* Connect to Revolt
|
||||
*/
|
||||
connect() {
|
||||
connect(): void {
|
||||
clearTimeout(this.#reconnectTimeout);
|
||||
this.events.disconnect();
|
||||
this.#setReady(false);
|
||||
@@ -311,7 +306,7 @@ export class Client extends EventEmitter<Events> {
|
||||
/**
|
||||
* Fetches the configuration of the server if it has not been already fetched.
|
||||
*/
|
||||
async #fetchConfiguration() {
|
||||
async #fetchConfiguration(): Promise<void> {
|
||||
if (!this.configuration) {
|
||||
this.configuration = await this.api.get("/");
|
||||
}
|
||||
@@ -320,7 +315,7 @@ export class Client extends EventEmitter<Events> {
|
||||
/**
|
||||
* Update API object to use authentication.
|
||||
*/
|
||||
#updateHeaders() {
|
||||
#updateHeaders(): void {
|
||||
(this.api as API) = new API({
|
||||
baseURL: this.options.baseURL,
|
||||
authentication: {
|
||||
@@ -334,7 +329,7 @@ export class Client extends EventEmitter<Events> {
|
||||
* @param details Login data object
|
||||
* @returns An on-boarding function if on-boarding is required, undefined otherwise
|
||||
*/
|
||||
async login(details: DataLogin) {
|
||||
async login(details: DataLogin): Promise<void> {
|
||||
await this.#fetchConfiguration();
|
||||
const data = await this.api.post("/auth/session/login", details);
|
||||
if (data.result === "Success") {
|
||||
@@ -348,7 +343,7 @@ export class Client extends EventEmitter<Events> {
|
||||
/**
|
||||
* Use an existing session
|
||||
*/
|
||||
async useExistingSession(session: Session) {
|
||||
useExistingSession(session: Session): void {
|
||||
this.#session = session;
|
||||
this.#updateHeaders();
|
||||
}
|
||||
@@ -357,7 +352,7 @@ export class Client extends EventEmitter<Events> {
|
||||
* Log in as a bot
|
||||
* @param token Bot token
|
||||
*/
|
||||
async loginBot(token: string) {
|
||||
async loginBot(token: string): Promise<void> {
|
||||
await this.#fetchConfiguration();
|
||||
this.#session = token;
|
||||
this.#updateHeaders();
|
||||
@@ -369,7 +364,7 @@ export class Client extends EventEmitter<Events> {
|
||||
* @param source Source markdown text
|
||||
* @returns Modified plain text
|
||||
*/
|
||||
markdownToText(source: string) {
|
||||
markdownToText(source: string): string {
|
||||
return source
|
||||
.replace(RE_MENTIONS, (sub: string, id: string) => {
|
||||
const user = this.users.get(id as string);
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
import { BannedUser as ApiBannedUser } from "revolt-api";
|
||||
import type { BannedUser as APIBannedUser } from "revolt-api";
|
||||
|
||||
import { Client, File } from "../index.js";
|
||||
import type { Client } from "../Client.js";
|
||||
|
||||
import { File } from "./File.js";
|
||||
|
||||
/**
|
||||
* Banned User
|
||||
@@ -16,7 +18,7 @@ export class BannedUser {
|
||||
* @param client Client
|
||||
* @param data Data
|
||||
*/
|
||||
constructor(client: Client, data: ApiBannedUser) {
|
||||
constructor(client: Client, data: APIBannedUser) {
|
||||
this.id = data._id;
|
||||
this.avatar = data.avatar ? new File(client, data.avatar) : undefined;
|
||||
this.username = data.username;
|
||||
|
||||
+21
-18
@@ -1,7 +1,10 @@
|
||||
import { DataEditBot } from "revolt-api";
|
||||
import type { DataEditBot } from "revolt-api";
|
||||
import { decodeTime } from "ulid";
|
||||
|
||||
import { BotCollection } from "../collections/index.js";
|
||||
import type { BotCollection } from "../collections/BotCollection.js";
|
||||
import type { BotFlags } from "../hydration/bot.js";
|
||||
|
||||
import type { User } from "./User.js";
|
||||
|
||||
/**
|
||||
* Bot Class
|
||||
@@ -24,98 +27,98 @@ export class Bot {
|
||||
* Convert to string
|
||||
* @returns String
|
||||
*/
|
||||
toString() {
|
||||
toString(): string {
|
||||
return `<@${this.id}>`;
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether this object exists
|
||||
*/
|
||||
get $exists() {
|
||||
get $exists(): boolean {
|
||||
return !!this.#collection.getUnderlyingObject(this.id).id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Time when this user created their account
|
||||
*/
|
||||
get createdAt() {
|
||||
get createdAt(): Date {
|
||||
return new Date(decodeTime(this.id));
|
||||
}
|
||||
|
||||
/**
|
||||
* Corresponding user
|
||||
*/
|
||||
get user() {
|
||||
get user(): User | undefined {
|
||||
return this.#collection.client.users.get(this.id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Owner's Id
|
||||
*/
|
||||
get ownerId() {
|
||||
get ownerId(): string {
|
||||
return this.#collection.getUnderlyingObject(this.id).ownerId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Owner
|
||||
*/
|
||||
get owner() {
|
||||
get owner(): User | undefined {
|
||||
return this.#collection.client.users.get(this.ownerId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Bot Token
|
||||
*/
|
||||
get token() {
|
||||
get token(): string {
|
||||
return this.#collection.getUnderlyingObject(this.id).token;
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether this bot can be invited by anyone
|
||||
*/
|
||||
get public() {
|
||||
get public(): boolean {
|
||||
return this.#collection.getUnderlyingObject(this.id).public;
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether this bot has analytics enabled
|
||||
*/
|
||||
get analytics() {
|
||||
get analytics(): boolean {
|
||||
return this.#collection.getUnderlyingObject(this.id).analytics;
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether this bot shows up on Discover
|
||||
*/
|
||||
get discoverable() {
|
||||
get discoverable(): boolean {
|
||||
return this.#collection.getUnderlyingObject(this.id).discoverable;
|
||||
}
|
||||
|
||||
/**
|
||||
* Interactions URL
|
||||
*/
|
||||
get interactionsUrl() {
|
||||
get interactionsUrl(): string | undefined {
|
||||
return this.#collection.getUnderlyingObject(this.id).interactionsUrl;
|
||||
}
|
||||
|
||||
/**
|
||||
* Link to terms of service
|
||||
*/
|
||||
get termsOfServiceUrl() {
|
||||
get termsOfServiceUrl(): string | undefined {
|
||||
return this.#collection.getUnderlyingObject(this.id).termsOfServiceUrl;
|
||||
}
|
||||
|
||||
/**
|
||||
* Link to privacy policy
|
||||
*/
|
||||
get privacyPolicyUrl() {
|
||||
get privacyPolicyUrl(): string | undefined {
|
||||
return this.#collection.getUnderlyingObject(this.id).privacyPolicyUrl;
|
||||
}
|
||||
|
||||
/**
|
||||
* Bot Flags
|
||||
*/
|
||||
get flags() {
|
||||
get flags(): BotFlags {
|
||||
return this.#collection.getUnderlyingObject(this.id).flags;
|
||||
}
|
||||
|
||||
@@ -123,14 +126,14 @@ export class Bot {
|
||||
* Edit a bot
|
||||
* @param data Changes
|
||||
*/
|
||||
async edit(data: DataEditBot) {
|
||||
async edit(data: DataEditBot): Promise<void> {
|
||||
await this.#collection.client.api.patch(`/bots/${this.id as ""}`, data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete a bot
|
||||
*/
|
||||
async delete() {
|
||||
async delete(): Promise<void> {
|
||||
await this.#collection.client.api.delete(`/bots/${this.id as ""}`);
|
||||
this.#collection.delete(this.id);
|
||||
}
|
||||
|
||||
+91
-67
@@ -1,25 +1,34 @@
|
||||
import { batch } from "solid-js";
|
||||
|
||||
import type { ReactiveSet } from "@solid-primitives/set";
|
||||
import type {
|
||||
Member as ApiMember,
|
||||
Message as ApiMessage,
|
||||
User as ApiUser,
|
||||
Channel as APIChannel,
|
||||
Member as APIMember,
|
||||
Message as APIMessage,
|
||||
User as APIUser,
|
||||
DataEditChannel,
|
||||
DataMessageSearch,
|
||||
DataMessageSend,
|
||||
Invite,
|
||||
Override,
|
||||
} from "revolt-api";
|
||||
import { APIRoutes } from "revolt-api/dist/routes";
|
||||
import type { APIRoutes } from "revolt-api/dist/routes";
|
||||
import { decodeTime, ulid } from "ulid";
|
||||
|
||||
import { ChannelCollection } from "../collections/index.js";
|
||||
import { Message } from "../index.js";
|
||||
import type { ChannelCollection } from "../collections/ChannelCollection.js";
|
||||
import {
|
||||
bitwiseAndEq,
|
||||
calculatePermission,
|
||||
} from "../permissions/calculator.js";
|
||||
import { Permission } from "../permissions/definitions.js";
|
||||
|
||||
import type { ChannelWebhook } from "./ChannelWebhook.js";
|
||||
import type { File } from "./File.js";
|
||||
import type { Message } from "./Message.js";
|
||||
import type { Server } from "./Server.js";
|
||||
import type { ServerMember } from "./ServerMember.js";
|
||||
import type { User } from "./User.js";
|
||||
|
||||
/**
|
||||
* Channel Class
|
||||
*/
|
||||
@@ -41,35 +50,35 @@ export class Channel {
|
||||
* Write to string as a channel mention
|
||||
* @returns Formatted String
|
||||
*/
|
||||
toString() {
|
||||
toString(): string {
|
||||
return `<#${this.id}>`;
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether this object exists
|
||||
*/
|
||||
get $exists() {
|
||||
get $exists(): boolean {
|
||||
return !!this.#collection.getUnderlyingObject(this.id).id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Time when this server was created
|
||||
*/
|
||||
get createdAt() {
|
||||
get createdAt(): Date {
|
||||
return new Date(decodeTime(this.id));
|
||||
}
|
||||
|
||||
/**
|
||||
* Channel type
|
||||
*/
|
||||
get type() {
|
||||
get type(): APIChannel["channel_type"] {
|
||||
return this.#collection.getUnderlyingObject(this.id).channelType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Absolute pathname to this channel in the client
|
||||
*/
|
||||
get path() {
|
||||
get path(): string {
|
||||
if (this.serverId) {
|
||||
return `/server/${this.serverId}/channel/${this.id}`;
|
||||
} else {
|
||||
@@ -80,21 +89,21 @@ export class Channel {
|
||||
/**
|
||||
* URL to this channel
|
||||
*/
|
||||
get url() {
|
||||
get url(): string {
|
||||
return this.#collection.client.configuration?.app + this.path;
|
||||
}
|
||||
|
||||
/**
|
||||
* Channel name
|
||||
*/
|
||||
get name() {
|
||||
get name(): string {
|
||||
return this.#collection.getUnderlyingObject(this.id).name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Display name
|
||||
*/
|
||||
get displayName() {
|
||||
get displayName(): string | undefined {
|
||||
return this.type === "SavedMessages"
|
||||
? this.user?.username
|
||||
: this.type === "DirectMessage"
|
||||
@@ -105,35 +114,35 @@ export class Channel {
|
||||
/**
|
||||
* Channel description
|
||||
*/
|
||||
get description() {
|
||||
get description(): string | undefined {
|
||||
return this.#collection.getUnderlyingObject(this.id).description;
|
||||
}
|
||||
|
||||
/**
|
||||
* Channel icon
|
||||
*/
|
||||
get icon() {
|
||||
get icon(): File | undefined {
|
||||
return this.#collection.getUnderlyingObject(this.id).icon;
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether the conversation is active
|
||||
*/
|
||||
get active() {
|
||||
get active(): boolean {
|
||||
return this.#collection.getUnderlyingObject(this.id).active;
|
||||
}
|
||||
|
||||
/**
|
||||
* User ids of people currently typing in channel
|
||||
*/
|
||||
get typingIds() {
|
||||
get typingIds(): ReactiveSet<string> {
|
||||
return this.#collection.getUnderlyingObject(this.id).typingIds;
|
||||
}
|
||||
|
||||
/**
|
||||
* Users currently trying in channel
|
||||
*/
|
||||
get typing() {
|
||||
get typing(): User[] {
|
||||
return [...this.typingIds.values()].map(
|
||||
(id) => this.#collection.client.users.get(id)!
|
||||
);
|
||||
@@ -142,14 +151,14 @@ export class Channel {
|
||||
/**
|
||||
* User ids of recipients of the group
|
||||
*/
|
||||
get recipientIds() {
|
||||
get recipientIds(): ReactiveSet<string> {
|
||||
return this.#collection.getUnderlyingObject(this.id).recipientIds;
|
||||
}
|
||||
|
||||
/**
|
||||
* Recipients of the group
|
||||
*/
|
||||
get recipients() {
|
||||
get recipients(): User[] {
|
||||
return [
|
||||
...this.#collection.getUnderlyingObject(this.id).recipientIds.values(),
|
||||
].map((id) => this.#collection.client.users.get(id)!);
|
||||
@@ -158,7 +167,7 @@ export class Channel {
|
||||
/**
|
||||
* Find recipient of this DM
|
||||
*/
|
||||
get recipient() {
|
||||
get recipient(): User | undefined {
|
||||
return this.type === "DirectMessage"
|
||||
? this.recipients?.find(
|
||||
(user) => user?.id !== this.#collection.client.user!.id
|
||||
@@ -169,14 +178,14 @@ export class Channel {
|
||||
/**
|
||||
* User ID
|
||||
*/
|
||||
get userId() {
|
||||
get userId(): string {
|
||||
return this.#collection.getUnderlyingObject(this.id).userId!;
|
||||
}
|
||||
|
||||
/**
|
||||
* User this channel belongs to
|
||||
*/
|
||||
get user() {
|
||||
get user(): User | undefined {
|
||||
return this.#collection.client.users.get(
|
||||
this.#collection.getUnderlyingObject(this.id).userId!
|
||||
);
|
||||
@@ -185,14 +194,14 @@ export class Channel {
|
||||
/**
|
||||
* Owner ID
|
||||
*/
|
||||
get ownerId() {
|
||||
get ownerId(): string {
|
||||
return this.#collection.getUnderlyingObject(this.id).ownerId!;
|
||||
}
|
||||
|
||||
/**
|
||||
* Owner of the group
|
||||
*/
|
||||
get owner() {
|
||||
get owner(): User | undefined {
|
||||
return this.#collection.client.users.get(
|
||||
this.#collection.getUnderlyingObject(this.id).ownerId!
|
||||
);
|
||||
@@ -201,14 +210,14 @@ export class Channel {
|
||||
/**
|
||||
* Server ID
|
||||
*/
|
||||
get serverId() {
|
||||
get serverId(): string {
|
||||
return this.#collection.getUnderlyingObject(this.id).serverId!;
|
||||
}
|
||||
|
||||
/**
|
||||
* Server this channel is in
|
||||
*/
|
||||
get server() {
|
||||
get server(): Server | undefined {
|
||||
return this.#collection.client.servers.get(
|
||||
this.#collection.getUnderlyingObject(this.id).serverId!
|
||||
);
|
||||
@@ -217,49 +226,49 @@ export class Channel {
|
||||
/**
|
||||
* Permissions allowed for users in this group
|
||||
*/
|
||||
get permissions() {
|
||||
get permissions(): number | undefined {
|
||||
return this.#collection.getUnderlyingObject(this.id).permissions;
|
||||
}
|
||||
|
||||
/**
|
||||
* Default permissions for this server channel
|
||||
*/
|
||||
get defaultPermissions() {
|
||||
get defaultPermissions(): { a: number; d: number } | undefined {
|
||||
return this.#collection.getUnderlyingObject(this.id).defaultPermissions;
|
||||
}
|
||||
|
||||
/**
|
||||
* Role permissions for this server channel
|
||||
*/
|
||||
get rolePermissions() {
|
||||
get rolePermissions(): Record<string, { a: number; d: number }> | undefined {
|
||||
return this.#collection.getUnderlyingObject(this.id).rolePermissions;
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether this channel is marked as mature
|
||||
*/
|
||||
get mature() {
|
||||
get mature(): boolean {
|
||||
return this.#collection.getUnderlyingObject(this.id).nsfw;
|
||||
}
|
||||
|
||||
/**
|
||||
* ID of the last message sent in this channel
|
||||
*/
|
||||
get lastMessageId() {
|
||||
get lastMessageId(): string | undefined {
|
||||
return this.#collection.getUnderlyingObject(this.id).lastMessageId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Last message sent in this channel
|
||||
*/
|
||||
get lastMessage() {
|
||||
get lastMessage(): Message | undefined {
|
||||
return this.#collection.client.messages.get(this.lastMessageId!);
|
||||
}
|
||||
|
||||
/**
|
||||
* Time when the last message was sent
|
||||
*/
|
||||
get lastMessageAt() {
|
||||
get lastMessageAt(): Date | undefined {
|
||||
return this.lastMessageId
|
||||
? new Date(decodeTime(this.lastMessageId))
|
||||
: undefined;
|
||||
@@ -268,14 +277,14 @@ export class Channel {
|
||||
/**
|
||||
* Time when the channel was last updated (either created or a message was sent)
|
||||
*/
|
||||
get updatedAt() {
|
||||
get updatedAt(): Date {
|
||||
return this.lastMessageAt ?? this.createdAt;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get whether this channel is unread.
|
||||
*/
|
||||
get unread() {
|
||||
get unread(): boolean {
|
||||
if (
|
||||
!this.lastMessageId ||
|
||||
this.type === "SavedMessages" ||
|
||||
@@ -295,7 +304,7 @@ export class Channel {
|
||||
/**
|
||||
* Get mentions in this channel for user.
|
||||
*/
|
||||
get mentions() {
|
||||
get mentions(): ReactiveSet<string> | undefined {
|
||||
if (this.type === "SavedMessages" || this.type === "VoiceChannel")
|
||||
return undefined;
|
||||
|
||||
@@ -306,21 +315,21 @@ export class Channel {
|
||||
/**
|
||||
* URL to the channel icon
|
||||
*/
|
||||
get iconURL() {
|
||||
get iconURL(): string | undefined {
|
||||
return this.icon?.createFileURL() ?? this.recipient?.avatarURL;
|
||||
}
|
||||
|
||||
/**
|
||||
* URL to the animated channel icon
|
||||
*/
|
||||
get animatedIconURL() {
|
||||
get animatedIconURL(): string | undefined {
|
||||
return this.icon?.createFileURL(true) ?? this.recipient?.animatedAvatarURL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether this channel may be hidden to some users
|
||||
*/
|
||||
get potentiallyRestrictedChannel() {
|
||||
get potentiallyRestrictedChannel(): string | boolean | undefined {
|
||||
if (!this.serverId) return false;
|
||||
return (
|
||||
bitwiseAndEq(this.defaultPermissions?.d ?? 0, Permission.ViewChannel) ||
|
||||
@@ -342,7 +351,7 @@ export class Channel {
|
||||
/**
|
||||
* Permission the currently authenticated user has against this channel
|
||||
*/
|
||||
get permission() {
|
||||
get permission(): number {
|
||||
return calculatePermission(this.#collection.client, this);
|
||||
}
|
||||
|
||||
@@ -351,7 +360,7 @@ export class Channel {
|
||||
* @param permission Permission Names
|
||||
* @returns Whether we have this permission
|
||||
*/
|
||||
havePermission(...permission: (keyof typeof Permission)[]) {
|
||||
havePermission(...permission: (keyof typeof Permission)[]): boolean {
|
||||
return bitwiseAndEq(
|
||||
this.permission,
|
||||
...permission.map((x) => Permission[x])
|
||||
@@ -363,7 +372,7 @@ export class Channel {
|
||||
* @param permission Permission Names
|
||||
* @returns Whether we have one of the permissions
|
||||
*/
|
||||
orPermission(...permission: (keyof typeof Permission)[]) {
|
||||
orPermission(...permission: (keyof typeof Permission)[]): boolean {
|
||||
return (
|
||||
permission.findIndex((x) =>
|
||||
bitwiseAndEq(this.permission, Permission[x])
|
||||
@@ -376,7 +385,7 @@ export class Channel {
|
||||
* @requires `Group`
|
||||
* @returns An array of the channel's members.
|
||||
*/
|
||||
async fetchMembers() {
|
||||
async fetchMembers(): Promise<User[]> {
|
||||
const members = await this.#collection.client.api.get(
|
||||
`/channels/${this.id as ""}/members`
|
||||
);
|
||||
@@ -393,7 +402,7 @@ export class Channel {
|
||||
* @requires `TextChannel`, `Group`
|
||||
* @returns Webhooks
|
||||
*/
|
||||
async fetchWebhooks() {
|
||||
async fetchWebhooks(): Promise<ChannelWebhook[]> {
|
||||
const webhooks = await this.#collection.client.api.get(
|
||||
`/channels/${this.id as ""}/webhooks`
|
||||
);
|
||||
@@ -409,7 +418,7 @@ export class Channel {
|
||||
* Edit a channel
|
||||
* @param data Changes
|
||||
*/
|
||||
async edit(data: DataEditChannel) {
|
||||
async edit(data: DataEditChannel): Promise<void> {
|
||||
await this.#collection.client.api.patch(`/channels/${this.id as ""}`, data);
|
||||
}
|
||||
|
||||
@@ -418,7 +427,7 @@ export class Channel {
|
||||
* @param leaveSilently Whether to not send a message on leave
|
||||
* @requires `DirectMessage`, `Group`, `TextChannel`, `VoiceChannel`
|
||||
*/
|
||||
async delete(leaveSilently?: boolean) {
|
||||
async delete(leaveSilently?: boolean): Promise<void> {
|
||||
await this.#collection.client.api.delete(`/channels/${this.id as ""}`, {
|
||||
leave_silently: leaveSilently,
|
||||
});
|
||||
@@ -436,7 +445,7 @@ export class Channel {
|
||||
* @param user_id ID of the target user
|
||||
* @requires `Group`
|
||||
*/
|
||||
async addMember(user_id: string) {
|
||||
async addMember(user_id: string): Promise<void> {
|
||||
return await this.#collection.client.api.put(
|
||||
`/channels/${this.id as ""}/recipients/${user_id as ""}`
|
||||
);
|
||||
@@ -447,7 +456,7 @@ export class Channel {
|
||||
* @param user_id ID of the target user
|
||||
* @requires `Group`
|
||||
*/
|
||||
async removeMember(user_id: string) {
|
||||
async removeMember(user_id: string): Promise<void> {
|
||||
return await this.#collection.client.api.delete(
|
||||
`/channels/${this.id as ""}/recipients/${user_id as ""}`
|
||||
);
|
||||
@@ -462,7 +471,7 @@ export class Channel {
|
||||
async sendMessage(
|
||||
data: string | DataMessageSend,
|
||||
idempotencyKey: string = ulid()
|
||||
) {
|
||||
): Promise<Message> {
|
||||
const msg: DataMessageSend =
|
||||
typeof data === "string" ? { content: data } : data;
|
||||
|
||||
@@ -496,7 +505,7 @@ export class Channel {
|
||||
* @requires `SavedMessages`, `DirectMessage`, `Group`, `TextChannel`
|
||||
* @returns Message
|
||||
*/
|
||||
async fetchMessage(messageId: string) {
|
||||
async fetchMessage(messageId: string): Promise<Message> {
|
||||
const message = await this.#collection.client.api.get(
|
||||
`/channels/${this.id as ""}/messages/${messageId as ""}`
|
||||
);
|
||||
@@ -518,11 +527,11 @@ export class Channel {
|
||||
})["params"],
|
||||
"include_users"
|
||||
>
|
||||
) {
|
||||
): Promise<Message[]> {
|
||||
const messages = (await this.#collection.client.api.get(
|
||||
`/channels/${this.id as ""}/messages`,
|
||||
{ ...params }
|
||||
)) as ApiMessage[];
|
||||
)) as APIMessage[];
|
||||
|
||||
return messages.map((message) =>
|
||||
this.#collection.client.messages.getOrCreate(message._id, message)
|
||||
@@ -543,11 +552,15 @@ export class Channel {
|
||||
})["params"],
|
||||
"include_users"
|
||||
>
|
||||
) {
|
||||
): Promise<{
|
||||
messages: Message[];
|
||||
users: User[];
|
||||
members: ServerMember[] | undefined;
|
||||
}> {
|
||||
const data = (await this.#collection.client.api.get(
|
||||
`/channels/${this.id as ""}/messages`,
|
||||
{ ...params, include_users: true }
|
||||
)) as { messages: ApiMessage[]; users: ApiUser[]; members?: ApiMember[] };
|
||||
)) as { messages: APIMessage[]; users: APIUser[]; members?: APIMember[] };
|
||||
|
||||
return batch(() => ({
|
||||
messages: data.messages.map((message) =>
|
||||
@@ -568,11 +581,13 @@ export class Channel {
|
||||
* @requires `SavedMessages`, `DirectMessage`, `Group`, `TextChannel`
|
||||
* @returns Messages
|
||||
*/
|
||||
async search(params: Omit<DataMessageSearch, "include_users">) {
|
||||
async search(
|
||||
params: Omit<DataMessageSearch, "include_users">
|
||||
): Promise<Message[]> {
|
||||
const messages = (await this.#collection.client.api.post(
|
||||
`/channels/${this.id as ""}/search`,
|
||||
params
|
||||
)) as ApiMessage[];
|
||||
)) as APIMessage[];
|
||||
|
||||
return batch(() =>
|
||||
messages.map((message) =>
|
||||
@@ -587,14 +602,20 @@ export class Channel {
|
||||
* @requires `SavedMessages`, `DirectMessage`, `Group`, `TextChannel`
|
||||
* @returns Object including messages and users
|
||||
*/
|
||||
async searchWithUsers(params: Omit<DataMessageSearch, "include_users">) {
|
||||
async searchWithUsers(
|
||||
params: Omit<DataMessageSearch, "include_users">
|
||||
): Promise<{
|
||||
messages: Message[];
|
||||
users: User[];
|
||||
members: ServerMember[] | undefined;
|
||||
}> {
|
||||
const data = (await this.#collection.client.api.post(
|
||||
`/channels/${this.id as ""}/search`,
|
||||
{
|
||||
...params,
|
||||
include_users: true,
|
||||
}
|
||||
)) as { messages: ApiMessage[]; users: ApiUser[]; members?: ApiMember[] };
|
||||
)) as { messages: APIMessage[]; users: APIUser[]; members?: APIMember[] };
|
||||
|
||||
return batch(() => ({
|
||||
messages: data.messages.map((message) =>
|
||||
@@ -614,7 +635,7 @@ export class Channel {
|
||||
* @param ids List of message IDs
|
||||
* @requires `SavedMessages`, `DirectMessage`, `Group`, `TextChannel`
|
||||
*/
|
||||
async deleteMessages(ids: string[]) {
|
||||
async deleteMessages(ids: string[]): Promise<void> {
|
||||
await this.#collection.client.api.delete(
|
||||
`/channels/${this.id as ""}/messages/bulk`,
|
||||
{
|
||||
@@ -628,7 +649,7 @@ export class Channel {
|
||||
* @requires `TextChannel`, `VoiceChannel`
|
||||
* @returns Newly created invite code
|
||||
*/
|
||||
async createInvite() {
|
||||
async createInvite(): Promise<Invite> {
|
||||
return await this.#collection.client.api.post(
|
||||
`/channels/${this.id as ""}/invites`
|
||||
);
|
||||
@@ -651,7 +672,7 @@ export class Channel {
|
||||
skipRateLimiter?: boolean,
|
||||
skipRequest?: boolean,
|
||||
skipNextMarking?: boolean
|
||||
) {
|
||||
): Promise<void> {
|
||||
if (!message && this.#manuallyMarked) {
|
||||
this.#manuallyMarked = false;
|
||||
return;
|
||||
@@ -684,7 +705,7 @@ export class Channel {
|
||||
/**
|
||||
* Send the actual acknowledgement request
|
||||
*/
|
||||
const performAck = () => {
|
||||
const performAck = (): void => {
|
||||
this.#ackLimit = undefined;
|
||||
this.#collection.client.api.put(
|
||||
`/channels/${this.id}/ack/${lastMessageId as ""}`
|
||||
@@ -712,7 +733,10 @@ export class Channel {
|
||||
* @param permissions Permission value
|
||||
* @requires `Group`, `TextChannel`, `VoiceChannel`
|
||||
*/
|
||||
async setPermissions(role_id = "default", permissions: Override) {
|
||||
async setPermissions(
|
||||
role_id = "default",
|
||||
permissions: Override
|
||||
): Promise<APIChannel> {
|
||||
return await this.#collection.client.api.put(
|
||||
`/channels/${this.id as ""}/permissions/${role_id as ""}`,
|
||||
{ permissions }
|
||||
@@ -723,7 +747,7 @@ export class Channel {
|
||||
* Start typing in this channel
|
||||
* @requires `DirectMessage`, `Group`, `TextChannel`
|
||||
*/
|
||||
startTyping() {
|
||||
startTyping(): void {
|
||||
this.#collection.client.events.send({
|
||||
type: "BeginTyping",
|
||||
channel: this.id,
|
||||
@@ -734,7 +758,7 @@ export class Channel {
|
||||
* Stop typing in this channel
|
||||
* @requires `DirectMessage`, `Group`, `TextChannel`
|
||||
*/
|
||||
stopTyping() {
|
||||
stopTyping(): void {
|
||||
this.#collection.client.events.send({
|
||||
type: "EndTyping",
|
||||
channel: this.id,
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
import { ChannelUnreadCollection } from "../collections/index.js";
|
||||
import type { ReactiveSet } from "@solid-primitives/set";
|
||||
|
||||
import type { ChannelUnreadCollection } from "../collections/ChannelUnreadCollection.js";
|
||||
|
||||
/**
|
||||
* Channel Unread Class
|
||||
@@ -20,21 +22,21 @@ export class ChannelUnread {
|
||||
/**
|
||||
* Whether this object exists
|
||||
*/
|
||||
get $exists() {
|
||||
get $exists(): boolean {
|
||||
return !!this.#collection.getUnderlyingObject(this.id).id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Last read message id
|
||||
*/
|
||||
get lastMessageId() {
|
||||
get lastMessageId(): string | undefined {
|
||||
return this.#collection.getUnderlyingObject(this.id).lastMessageId;
|
||||
}
|
||||
|
||||
/**
|
||||
* List of message IDs that we were mentioned in
|
||||
*/
|
||||
get messageMentionIds() {
|
||||
get messageMentionIds(): ReactiveSet<string> {
|
||||
return this.#collection.getUnderlyingObject(this.id).messageMentionIds;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
import { ChannelWebhookCollection } from "../collections/index.js";
|
||||
import type { ChannelWebhookCollection } from "../collections/ChannelWebhookCollection.js";
|
||||
import { hydrate } from "../hydration/index.js";
|
||||
|
||||
import type { Channel } from "./Channel.js";
|
||||
import type { File } from "./File.js";
|
||||
|
||||
/**
|
||||
* Channel Webhook Class
|
||||
*/
|
||||
@@ -21,28 +24,28 @@ export class ChannelWebhook {
|
||||
/**
|
||||
* Whether this object exists
|
||||
*/
|
||||
get $exists() {
|
||||
get $exists(): boolean {
|
||||
return !!this.#collection.getUnderlyingObject(this.id).id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Webhook name
|
||||
*/
|
||||
get name() {
|
||||
get name(): string {
|
||||
return this.#collection.getUnderlyingObject(this.id).name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Webhook avatar
|
||||
*/
|
||||
get avatar() {
|
||||
get avatar(): File | undefined {
|
||||
return this.#collection.getUnderlyingObject(this.id).avatar;
|
||||
}
|
||||
|
||||
/**
|
||||
* Webhook avatar URL
|
||||
*/
|
||||
get avatarURL() {
|
||||
get avatarURL(): string | undefined {
|
||||
return this.#collection
|
||||
.getUnderlyingObject(this.id)
|
||||
.avatar?.createFileURL();
|
||||
@@ -51,14 +54,14 @@ export class ChannelWebhook {
|
||||
/**
|
||||
* Channel ID this webhook belongs to
|
||||
*/
|
||||
get channelId() {
|
||||
get channelId(): string {
|
||||
return this.#collection.getUnderlyingObject(this.id).channelId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Channel this webhook belongs to
|
||||
*/
|
||||
get channel() {
|
||||
get channel(): Channel | undefined {
|
||||
return this.#collection.client.channels.get(
|
||||
this.#collection.getUnderlyingObject(this.id).channelId
|
||||
);
|
||||
@@ -67,7 +70,7 @@ export class ChannelWebhook {
|
||||
/**
|
||||
* Secret token for sending messages to this webhook
|
||||
*/
|
||||
get token() {
|
||||
get token(): string {
|
||||
return this.#collection.getUnderlyingObject(this.id).token;
|
||||
}
|
||||
|
||||
@@ -75,7 +78,7 @@ export class ChannelWebhook {
|
||||
* Edit this webhook
|
||||
* TODO: not in production
|
||||
*/
|
||||
async edit(data: any /*: DataEditWebhook*/) {
|
||||
async edit(data: any /*: DataEditWebhook*/): Promise<void> {
|
||||
const webhook = await this.#collection.client.api.patch(
|
||||
// @ts-expect-error not in prod
|
||||
`/webhooks/${this.id as ""}/${this.token as ""}`,
|
||||
@@ -93,7 +96,7 @@ export class ChannelWebhook {
|
||||
* Delete this webhook
|
||||
* TODO: not in production
|
||||
*/
|
||||
async delete() {
|
||||
async delete(): Promise<void> {
|
||||
await this.#collection.client.api.delete(
|
||||
// @ts-expect-error not in prod
|
||||
`/webhooks/${this.id}/${this.token}`
|
||||
|
||||
+13
-10
@@ -1,6 +1,9 @@
|
||||
import type { EmojiParent } from "revolt-api";
|
||||
import { decodeTime } from "ulid";
|
||||
|
||||
import { EmojiCollection } from "../collections/index.js";
|
||||
import type { EmojiCollection } from "../collections/EmojiCollection.js";
|
||||
|
||||
import type { User } from "./User.js";
|
||||
|
||||
/**
|
||||
* Emoji Class
|
||||
@@ -23,35 +26,35 @@ export class Emoji {
|
||||
* Convert to string
|
||||
* @returns String
|
||||
*/
|
||||
toString() {
|
||||
toString(): string {
|
||||
return `:${this.id}:`;
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether this object exists
|
||||
*/
|
||||
get $exists() {
|
||||
get $exists(): boolean {
|
||||
return !!this.#collection.getUnderlyingObject(this.id).id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Time when this emoji was created
|
||||
*/
|
||||
get createdAt() {
|
||||
get createdAt(): Date {
|
||||
return new Date(decodeTime(this.id));
|
||||
}
|
||||
|
||||
/**
|
||||
* Information about the parent of this emoji
|
||||
*/
|
||||
get parent() {
|
||||
get parent(): EmojiParent {
|
||||
return this.#collection.getUnderlyingObject(this.id).parent;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creator of the emoji
|
||||
*/
|
||||
get creator() {
|
||||
get creator(): User | undefined {
|
||||
return this.#collection.client.users.get(
|
||||
this.#collection.getUnderlyingObject(this.id).creatorId
|
||||
);
|
||||
@@ -60,28 +63,28 @@ export class Emoji {
|
||||
/**
|
||||
* Name
|
||||
*/
|
||||
get name() {
|
||||
get name(): string {
|
||||
return this.#collection.getUnderlyingObject(this.id).name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether the emoji is animated
|
||||
*/
|
||||
get animated() {
|
||||
get animated(): boolean {
|
||||
return this.#collection.getUnderlyingObject(this.id).animated;
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether the emoji is marked as mature
|
||||
*/
|
||||
get mature() {
|
||||
get mature(): boolean {
|
||||
return this.#collection.getUnderlyingObject(this.id).nsfw;
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete Emoji
|
||||
*/
|
||||
async delete() {
|
||||
async delete(): Promise<void> {
|
||||
await this.#collection.client.api.delete(`/custom/emoji/${this.id}`);
|
||||
|
||||
const emoji = this.#collection.getUnderlyingObject(this.id);
|
||||
|
||||
+8
-8
@@ -1,6 +1,6 @@
|
||||
import { Metadata } from "revolt-api";
|
||||
import type { File as APIFile, Metadata } from "revolt-api";
|
||||
|
||||
import { API, Client } from "../index.js";
|
||||
import type { Client } from "../Client.js";
|
||||
|
||||
/**
|
||||
* Uploaded File
|
||||
@@ -45,7 +45,7 @@ export class File {
|
||||
*/
|
||||
constructor(
|
||||
client: Client,
|
||||
file: Pick<API.File, "_id" | "tag" | "metadata"> & Partial<API.File>
|
||||
file: Pick<APIFile, "_id" | "tag" | "metadata"> & Partial<APIFile>
|
||||
) {
|
||||
this.#client = client;
|
||||
this.id = file._id;
|
||||
@@ -59,7 +59,7 @@ export class File {
|
||||
/**
|
||||
* Direct URL to the file
|
||||
*/
|
||||
get url() {
|
||||
get url(): string {
|
||||
return `${this.#client.configuration?.features.autumn.url}/${this.tag}/${
|
||||
this.id
|
||||
}/${this.filename}`;
|
||||
@@ -68,7 +68,7 @@ export class File {
|
||||
/**
|
||||
* Download URL for the file
|
||||
*/
|
||||
get downloadURL() {
|
||||
get downloadURL(): string {
|
||||
return `${this.#client.configuration?.features.autumn.url}/${
|
||||
this.tag
|
||||
}/download/${this.id}/${this.filename}`;
|
||||
@@ -77,7 +77,7 @@ export class File {
|
||||
/**
|
||||
* Human readable file size
|
||||
*/
|
||||
get humanReadableSize() {
|
||||
get humanReadableSize(): string {
|
||||
if (!this.size) return "Unknown size";
|
||||
|
||||
if (this.size > 1e6) {
|
||||
@@ -92,7 +92,7 @@ export class File {
|
||||
/**
|
||||
* Whether this file should have a spoiler
|
||||
*/
|
||||
get isSpoiler() {
|
||||
get isSpoiler(): boolean {
|
||||
return this.filename?.toLowerCase().startsWith("spoiler_") ?? false;
|
||||
}
|
||||
|
||||
@@ -101,7 +101,7 @@ export class File {
|
||||
* @param forceAnimation Returns GIF if applicable (for avatars/icons)
|
||||
* @returns Generated URL or nothing
|
||||
*/
|
||||
createFileURL(forceAnimation?: boolean) {
|
||||
createFileURL(forceAnimation?: boolean): string | undefined {
|
||||
const autumn = this.#client.configuration?.features.autumn;
|
||||
if (!autumn?.enabled) return;
|
||||
|
||||
|
||||
+15
-9
@@ -1,18 +1,24 @@
|
||||
import { API, Client } from "../index.js";
|
||||
import type { Invite } from "revolt-api";
|
||||
|
||||
import type { Client } from "../Client.js";
|
||||
|
||||
import type { Channel } from "./Channel.js";
|
||||
import type { Server } from "./Server.js";
|
||||
import type { User } from "./User.js";
|
||||
|
||||
/**
|
||||
* Channel Invite
|
||||
*/
|
||||
export abstract class ChannelInvite {
|
||||
protected client?: Client;
|
||||
readonly type: API.Invite["type"] | "None";
|
||||
readonly type: Invite["type"] | "None";
|
||||
|
||||
/**
|
||||
* Construct Channel Invite
|
||||
* @param client Client
|
||||
* @param type Type
|
||||
*/
|
||||
constructor(client?: Client, type: API.Invite["type"] | "None" = "None") {
|
||||
constructor(client?: Client, type: Invite["type"] | "None" = "None") {
|
||||
this.client = client;
|
||||
this.type = type;
|
||||
}
|
||||
@@ -23,7 +29,7 @@ export abstract class ChannelInvite {
|
||||
* @param invite Data
|
||||
* @returns Invite
|
||||
*/
|
||||
static from(client: Client, invite: API.Invite): ChannelInvite {
|
||||
static from(client: Client, invite: Invite): ChannelInvite {
|
||||
switch (invite.type) {
|
||||
case "Server":
|
||||
return new ServerInvite(client, invite);
|
||||
@@ -52,7 +58,7 @@ export class ServerInvite extends ChannelInvite {
|
||||
* @param client Client
|
||||
* @param invite Invite
|
||||
*/
|
||||
constructor(client: Client, invite: API.Invite & { type: "Server" }) {
|
||||
constructor(client: Client, invite: Invite & { type: "Server" }) {
|
||||
super(client, "Server");
|
||||
|
||||
this.id = invite._id;
|
||||
@@ -64,28 +70,28 @@ export class ServerInvite extends ChannelInvite {
|
||||
/**
|
||||
* Creator of the invite
|
||||
*/
|
||||
get creator() {
|
||||
get creator(): User | undefined {
|
||||
return this.client!.users.get(this.creatorId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Server this invite points to
|
||||
*/
|
||||
get server() {
|
||||
get server(): Server | undefined {
|
||||
return this.client!.servers.get(this.serverId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Channel this invite points to
|
||||
*/
|
||||
get channel() {
|
||||
get channel(): Channel | undefined {
|
||||
return this.client!.channels.get(this.channelId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete the invite
|
||||
*/
|
||||
async delete() {
|
||||
async delete(): Promise<void> {
|
||||
await this.client!.api.delete(`/invites/${this.id}`);
|
||||
}
|
||||
}
|
||||
|
||||
+24
-21
@@ -1,13 +1,14 @@
|
||||
import { SetStoreFunction, createStore } from "solid-js/store";
|
||||
import type { SetStoreFunction } from "solid-js/store";
|
||||
import { createStore } from "solid-js/store";
|
||||
|
||||
import {
|
||||
import type {
|
||||
MFAMethod,
|
||||
MFAResponse,
|
||||
MultiFactorStatus,
|
||||
MFATicket as TicketType,
|
||||
} from "revolt-api";
|
||||
|
||||
import { Client } from "../index.js";
|
||||
import type { Client } from "../Client.js";
|
||||
|
||||
/**
|
||||
* Multi-Factor Authentication
|
||||
@@ -29,14 +30,14 @@ export class MFA {
|
||||
/**
|
||||
* Whether authenticator app is enabled
|
||||
*/
|
||||
get authenticatorEnabled() {
|
||||
get authenticatorEnabled(): boolean {
|
||||
return this.#store[0].totp_mfa;
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether recovery codes are enabled
|
||||
*/
|
||||
get recoveryEnabled() {
|
||||
get recoveryEnabled(): boolean {
|
||||
return this.#store[0].recovery_active;
|
||||
}
|
||||
|
||||
@@ -56,17 +57,19 @@ export class MFA {
|
||||
* @param params
|
||||
* @returns Token
|
||||
*/
|
||||
createTicket(params: MFAResponse) {
|
||||
return this.#client.api
|
||||
.put("/auth/mfa/ticket", params)
|
||||
.then((ticket) => new MFATicket(this.#client, ticket, this.#store[1]));
|
||||
async createTicket(params: MFAResponse): Promise<MFATicket> {
|
||||
return new MFATicket(
|
||||
this.#client,
|
||||
await this.#client.api.put("/auth/mfa/ticket", params),
|
||||
this.#store[1]
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable authenticator using token generated from secret found earlier
|
||||
* @param token Token
|
||||
*/
|
||||
async enableAuthenticator(token: string) {
|
||||
async enableAuthenticator(token: string): Promise<void> {
|
||||
await this.#client.api.put("/auth/mfa/totp", { totp_code: token });
|
||||
this.#store[1]("totp_mfa", true);
|
||||
}
|
||||
@@ -100,14 +103,14 @@ export class MFATicket {
|
||||
/**
|
||||
* Token
|
||||
*/
|
||||
get token() {
|
||||
get token(): string {
|
||||
return this.#ticket.token;
|
||||
}
|
||||
|
||||
/**
|
||||
* Use the ticket
|
||||
*/
|
||||
#consume() {
|
||||
#consume(): void {
|
||||
if (this.#used) throw "Already used this ticket!";
|
||||
this.#used = true;
|
||||
}
|
||||
@@ -116,7 +119,7 @@ export class MFATicket {
|
||||
* Fetch recovery codes
|
||||
* @returns List of codes
|
||||
*/
|
||||
fetchRecoveryCodes() {
|
||||
fetchRecoveryCodes(): Promise<string[]> {
|
||||
this.#consume();
|
||||
return this.#client.api.post("/auth/mfa/recovery", undefined, {
|
||||
headers: {
|
||||
@@ -129,7 +132,7 @@ export class MFATicket {
|
||||
* Generate new set of recovery codes
|
||||
* @returns List of codes
|
||||
*/
|
||||
async generateRecoveryCodes() {
|
||||
async generateRecoveryCodes(): Promise<string[]> {
|
||||
this.#consume();
|
||||
|
||||
const codes = await this.#client.api.patch(
|
||||
@@ -150,21 +153,21 @@ export class MFATicket {
|
||||
* Generate new authenticator secret
|
||||
* @returns Secret
|
||||
*/
|
||||
generateAuthenticatorSecret() {
|
||||
async generateAuthenticatorSecret(): Promise<string> {
|
||||
this.#consume();
|
||||
return this.#client.api
|
||||
.post("/auth/mfa/totp", undefined, {
|
||||
return (
|
||||
await this.#client.api.post("/auth/mfa/totp", undefined, {
|
||||
headers: {
|
||||
"X-MFA-Ticket": this.token,
|
||||
},
|
||||
})
|
||||
.then((response) => response.secret);
|
||||
).secret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Disable authenticator
|
||||
*/
|
||||
async disableAuthenticator() {
|
||||
async disableAuthenticator(): Promise<void> {
|
||||
this.#consume();
|
||||
|
||||
await this.#client.api.delete("/auth/mfa/totp", undefined, {
|
||||
@@ -179,7 +182,7 @@ export class MFATicket {
|
||||
/**
|
||||
* Disable account
|
||||
*/
|
||||
disableAccount() {
|
||||
disableAccount(): Promise<void> {
|
||||
this.#consume();
|
||||
return this.#client.api.post("/auth/account/disable", undefined, {
|
||||
headers: {
|
||||
@@ -191,7 +194,7 @@ export class MFATicket {
|
||||
/**
|
||||
* Delete account
|
||||
*/
|
||||
deleteAccount() {
|
||||
deleteAccount(): Promise<void> {
|
||||
this.#consume();
|
||||
return this.#client.api.post("/auth/account/delete", undefined, {
|
||||
headers: {
|
||||
|
||||
+56
-44
@@ -1,12 +1,24 @@
|
||||
import {
|
||||
MessageWebhook as ApiMessageWebhook,
|
||||
import type { ReactiveMap } from "@solid-primitives/map";
|
||||
import type { ReactiveSet } from "@solid-primitives/set";
|
||||
import type {
|
||||
Message as APIMessage,
|
||||
MessageWebhook as APIMessageWebhook,
|
||||
DataEditMessage,
|
||||
DataMessageSend,
|
||||
Masquerade,
|
||||
} from "revolt-api";
|
||||
import { decodeTime } from "ulid";
|
||||
|
||||
import { MessageCollection } from "../collections/index.js";
|
||||
import { Client, File } from "../index.js";
|
||||
import type { Client } from "../Client.js";
|
||||
import type { MessageCollection } from "../collections/MessageCollection.js";
|
||||
|
||||
import type { Channel } from "./Channel.js";
|
||||
import { File } from "./File.js";
|
||||
import type { MessageEmbed } from "./MessageEmbed.js";
|
||||
import type { Server } from "./Server.js";
|
||||
import type { ServerMember } from "./ServerMember.js";
|
||||
import type { SystemMessage } from "./SystemMessage.js";
|
||||
import type { User } from "./User.js";
|
||||
|
||||
/**
|
||||
* Message Class
|
||||
@@ -28,49 +40,49 @@ export class Message {
|
||||
/**
|
||||
* Whether this object exists
|
||||
*/
|
||||
get $exists() {
|
||||
get $exists(): boolean {
|
||||
return !!this.#collection.getUnderlyingObject(this.id).id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Time when this message was posted
|
||||
*/
|
||||
get createdAt() {
|
||||
get createdAt(): Date {
|
||||
return new Date(decodeTime(this.id));
|
||||
}
|
||||
|
||||
/**
|
||||
* Absolute pathname to this message in the client
|
||||
*/
|
||||
get path() {
|
||||
get path(): string {
|
||||
return `${this.channel?.path}/${this.id}`;
|
||||
}
|
||||
|
||||
/**
|
||||
* URL to this message
|
||||
*/
|
||||
get url() {
|
||||
get url(): string | undefined {
|
||||
return this.#collection.client.configuration?.app + this.path;
|
||||
}
|
||||
|
||||
/**
|
||||
* Nonce value
|
||||
*/
|
||||
get nonce() {
|
||||
get nonce(): string | undefined {
|
||||
return this.#collection.getUnderlyingObject(this.id).nonce;
|
||||
}
|
||||
|
||||
/**
|
||||
* Id of channel this message was sent in
|
||||
*/
|
||||
get channelId() {
|
||||
get channelId(): string | undefined {
|
||||
return this.#collection.getUnderlyingObject(this.id).channelId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Channel this message was sent in
|
||||
*/
|
||||
get channel() {
|
||||
get channel(): Channel | undefined {
|
||||
return this.#collection.client.channels.get(
|
||||
this.#collection.getUnderlyingObject(this.id).channelId
|
||||
);
|
||||
@@ -79,14 +91,14 @@ export class Message {
|
||||
/**
|
||||
* Server this message was sent in
|
||||
*/
|
||||
get server() {
|
||||
get server(): Server | undefined {
|
||||
return this.channel?.server;
|
||||
}
|
||||
|
||||
/**
|
||||
* Member this message was sent by
|
||||
*/
|
||||
get member() {
|
||||
get member(): ServerMember | undefined {
|
||||
return this.#collection.client.serverMembers.getByKey({
|
||||
server: this.channel?.serverId as string,
|
||||
user: this.authorId!,
|
||||
@@ -96,14 +108,14 @@ export class Message {
|
||||
/**
|
||||
* Id of user or webhook this message was sent by
|
||||
*/
|
||||
get authorId() {
|
||||
get authorId(): string | undefined {
|
||||
return this.#collection.getUnderlyingObject(this.id).authorId;
|
||||
}
|
||||
|
||||
/**
|
||||
* User this message was sent by
|
||||
*/
|
||||
get author() {
|
||||
get author(): User | undefined {
|
||||
return this.#collection.client.users.get(
|
||||
this.#collection.getUnderlyingObject(this.id).authorId!
|
||||
);
|
||||
@@ -112,98 +124,98 @@ export class Message {
|
||||
/**
|
||||
* Webhook information for this message
|
||||
*/
|
||||
get webhook() {
|
||||
get webhook(): MessageWebhook | undefined {
|
||||
return this.#collection.getUnderlyingObject(this.id).webhook!;
|
||||
}
|
||||
|
||||
/**
|
||||
* Content
|
||||
*/
|
||||
get content() {
|
||||
get content(): string {
|
||||
return this.#collection.getUnderlyingObject(this.id).content ?? "";
|
||||
}
|
||||
|
||||
/**
|
||||
* System message content
|
||||
*/
|
||||
get systemMessage() {
|
||||
get systemMessage(): SystemMessage | undefined {
|
||||
return this.#collection.getUnderlyingObject(this.id).systemMessage;
|
||||
}
|
||||
|
||||
/**
|
||||
* Attachments
|
||||
*/
|
||||
get attachments() {
|
||||
get attachments(): File[] | undefined {
|
||||
return this.#collection.getUnderlyingObject(this.id).attachments;
|
||||
}
|
||||
|
||||
/**
|
||||
* Time at which this message was edited
|
||||
*/
|
||||
get editedAt() {
|
||||
get editedAt(): Date | undefined {
|
||||
return this.#collection.getUnderlyingObject(this.id).editedAt;
|
||||
}
|
||||
|
||||
/**
|
||||
* Embeds
|
||||
*/
|
||||
get embeds() {
|
||||
get embeds(): MessageEmbed[] | undefined {
|
||||
return this.#collection.getUnderlyingObject(this.id).embeds;
|
||||
}
|
||||
|
||||
/**
|
||||
* IDs of users this message mentions
|
||||
*/
|
||||
get mentionIds() {
|
||||
get mentionIds(): string[] | undefined {
|
||||
return this.#collection.getUnderlyingObject(this.id).mentionIds;
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether this message mentions us
|
||||
*/
|
||||
get mentioned() {
|
||||
return this.mentionIds?.includes(this.#collection.client.user!.id);
|
||||
get mentioned(): boolean {
|
||||
return this.mentionIds?.includes(this.#collection.client.user!.id) ?? false;
|
||||
}
|
||||
|
||||
/**
|
||||
* IDs of messages this message replies to
|
||||
*/
|
||||
get replyIds() {
|
||||
get replyIds(): string[] | undefined {
|
||||
return this.#collection.getUnderlyingObject(this.id).replyIds;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reactions
|
||||
*/
|
||||
get reactions() {
|
||||
get reactions(): ReactiveMap<string, ReactiveSet<string>> {
|
||||
return this.#collection.getUnderlyingObject(this.id).reactions;
|
||||
}
|
||||
|
||||
/**
|
||||
* Interactions
|
||||
*/
|
||||
get interactions() {
|
||||
get interactions(): APIMessage["interactions"] {
|
||||
return this.#collection.getUnderlyingObject(this.id).interactions;
|
||||
}
|
||||
|
||||
/**
|
||||
* Masquerade
|
||||
*/
|
||||
get masquerade() {
|
||||
get masquerade(): Masquerade | undefined {
|
||||
return this.#collection.getUnderlyingObject(this.id).masquerade;
|
||||
}
|
||||
|
||||
/**
|
||||
* Flags
|
||||
*/
|
||||
get flags() {
|
||||
get flags(): number {
|
||||
return this.#collection.getUnderlyingObject(this.id).flags || 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the username for this message
|
||||
*/
|
||||
get username() {
|
||||
get username(): string | undefined {
|
||||
const webhook = this.webhook;
|
||||
|
||||
return (
|
||||
@@ -215,14 +227,14 @@ export class Message {
|
||||
/**
|
||||
* Get the role colour for this message
|
||||
*/
|
||||
get roleColour() {
|
||||
get roleColour(): string | null | undefined {
|
||||
return this.masquerade?.colour ?? this.member?.roleColour;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the avatar URL for this message
|
||||
*/
|
||||
get avatarURL() {
|
||||
get avatarURL(): string | undefined {
|
||||
const webhook = this.webhook;
|
||||
|
||||
return (
|
||||
@@ -236,7 +248,7 @@ export class Message {
|
||||
/**
|
||||
* Get the animated avatar URL for this message
|
||||
*/
|
||||
get animatedAvatarURL() {
|
||||
get animatedAvatarURL(): string | undefined {
|
||||
const webhook = this.webhook;
|
||||
|
||||
return (
|
||||
@@ -252,7 +264,7 @@ export class Message {
|
||||
/**
|
||||
* Avatar URL from the masquerade
|
||||
*/
|
||||
get masqueradeAvatarURL() {
|
||||
get masqueradeAvatarURL(): string | undefined {
|
||||
const avatar = this.masquerade?.avatar;
|
||||
return avatar ? this.#collection.client.proxyFile(avatar) : undefined;
|
||||
}
|
||||
@@ -260,7 +272,7 @@ export class Message {
|
||||
/**
|
||||
* Whether this message has suppressed desktop/push notifications
|
||||
*/
|
||||
get isSuppressed() {
|
||||
get isSuppressed(): boolean {
|
||||
return (this.flags & 1) === 1;
|
||||
}
|
||||
|
||||
@@ -268,7 +280,7 @@ export class Message {
|
||||
* Edit a message
|
||||
* @param data Message edit route data
|
||||
*/
|
||||
async edit(data: DataEditMessage) {
|
||||
async edit(data: DataEditMessage): Promise<APIMessage> {
|
||||
return await this.#collection.client.api.patch(
|
||||
`/channels/${this.channelId as ""}/messages/${this.id as ""}`,
|
||||
data
|
||||
@@ -278,7 +290,7 @@ export class Message {
|
||||
/**
|
||||
* Delete a message
|
||||
*/
|
||||
async delete() {
|
||||
async delete(): Promise<void> {
|
||||
return await this.#collection.client.api.delete(
|
||||
`/channels/${this.channelId as ""}/messages/${this.id as ""}`
|
||||
);
|
||||
@@ -287,7 +299,7 @@ export class Message {
|
||||
/**
|
||||
* Acknowledge this message as read
|
||||
*/
|
||||
ack() {
|
||||
ack(): void {
|
||||
this.channel?.ack(this);
|
||||
}
|
||||
|
||||
@@ -301,7 +313,7 @@ export class Message {
|
||||
nonce?: string;
|
||||
}),
|
||||
mention = true
|
||||
) {
|
||||
): Promise<Message> | undefined {
|
||||
const obj = typeof data === "string" ? { content: data } : data;
|
||||
return this.channel?.sendMessage({
|
||||
...obj,
|
||||
@@ -312,7 +324,7 @@ export class Message {
|
||||
/**
|
||||
* Clear all reactions from this message
|
||||
*/
|
||||
async clearReactions() {
|
||||
async clearReactions(): Promise<void> {
|
||||
return await this.#collection.client.api.delete(
|
||||
`/channels/${this.channelId as ""}/messages/${this.id as ""}/reactions`
|
||||
);
|
||||
@@ -322,7 +334,7 @@ export class Message {
|
||||
* React to a message
|
||||
* @param emoji Unicode or emoji ID
|
||||
*/
|
||||
async react(emoji: string) {
|
||||
async react(emoji: string): Promise<void> {
|
||||
return await this.#collection.client.api.put(
|
||||
`/channels/${this.channelId as ""}/messages/${this.id as ""}/reactions/${
|
||||
emoji as ""
|
||||
@@ -334,7 +346,7 @@ export class Message {
|
||||
* Un-react from a message
|
||||
* @param emoji Unicode or emoji ID
|
||||
*/
|
||||
async unreact(emoji: string) {
|
||||
async unreact(emoji: string): Promise<void> {
|
||||
return await this.#collection.client.api.delete(
|
||||
`/channels/${this.channelId as ""}/messages/${this.id as ""}/reactions/${
|
||||
emoji as ""
|
||||
@@ -358,7 +370,7 @@ export class MessageWebhook {
|
||||
* @param client Client
|
||||
* @param webhook Webhook data
|
||||
*/
|
||||
constructor(client: Client, webhook: ApiMessageWebhook, id: string) {
|
||||
constructor(client: Client, webhook: APIMessageWebhook, id: string) {
|
||||
this.#client = client;
|
||||
this.id = id;
|
||||
this.name = webhook.name;
|
||||
@@ -378,7 +390,7 @@ export class MessageWebhook {
|
||||
/**
|
||||
* Get the avatar URL for this message webhook
|
||||
*/
|
||||
get avatarURL() {
|
||||
get avatarURL(): string {
|
||||
return (
|
||||
this.avatar?.createFileURL() ??
|
||||
`${this.#client.options.baseURL}/users/${this.id}/default_avatar`
|
||||
|
||||
+19
-24
@@ -1,18 +1,22 @@
|
||||
import { API, Client, File } from "../index.js";
|
||||
import type { Embed, ImageSize, Special } from "revolt-api";
|
||||
|
||||
import type { Client } from "../Client.js";
|
||||
|
||||
import { File } from "./File.js";
|
||||
|
||||
/**
|
||||
* Message Embed
|
||||
*/
|
||||
export abstract class MessageEmbed {
|
||||
protected client?: Client;
|
||||
readonly type: API.Embed["type"];
|
||||
readonly type: Embed["type"];
|
||||
|
||||
/**
|
||||
* Construct Embed
|
||||
* @param client Client
|
||||
* @param type Type
|
||||
*/
|
||||
constructor(client?: Client, type: API.Embed["type"] = "None") {
|
||||
constructor(client?: Client, type: Embed["type"] = "None") {
|
||||
this.client = client;
|
||||
this.type = type;
|
||||
}
|
||||
@@ -23,7 +27,7 @@ export abstract class MessageEmbed {
|
||||
* @param embed Data
|
||||
* @returns Embed
|
||||
*/
|
||||
static from(client: Client, embed: API.Embed): MessageEmbed {
|
||||
static from(client: Client, embed: Embed): MessageEmbed {
|
||||
switch (embed.type) {
|
||||
case "Image":
|
||||
return new ImageEmbed(client, embed);
|
||||
@@ -51,17 +55,14 @@ export class ImageEmbed extends MessageEmbed {
|
||||
readonly url: string;
|
||||
readonly width: number;
|
||||
readonly height: number;
|
||||
readonly size: API.ImageSize;
|
||||
readonly size: ImageSize;
|
||||
|
||||
/**
|
||||
* Construct Image Embed
|
||||
* @param client Client
|
||||
* @param embed Embed
|
||||
*/
|
||||
constructor(
|
||||
client: Client,
|
||||
embed: Omit<API.Embed & { type: "Image" }, "type">
|
||||
) {
|
||||
constructor(client: Client, embed: Omit<Embed & { type: "Image" }, "type">) {
|
||||
super(client, "Image");
|
||||
|
||||
this.url = embed.url;
|
||||
@@ -73,7 +74,7 @@ export class ImageEmbed extends MessageEmbed {
|
||||
/**
|
||||
* Proxied image URL
|
||||
*/
|
||||
get proxiedURL() {
|
||||
get proxiedURL(): string | undefined {
|
||||
return this.client?.proxyFile(this.url);
|
||||
}
|
||||
}
|
||||
@@ -91,10 +92,7 @@ export class VideoEmbed extends MessageEmbed {
|
||||
* @param client Client
|
||||
* @param embed Embed
|
||||
*/
|
||||
constructor(
|
||||
client: Client,
|
||||
embed: Omit<API.Embed & { type: "Video" }, "type">
|
||||
) {
|
||||
constructor(client: Client, embed: Omit<Embed & { type: "Video" }, "type">) {
|
||||
super(client, "Video");
|
||||
|
||||
this.url = embed.url;
|
||||
@@ -105,7 +103,7 @@ export class VideoEmbed extends MessageEmbed {
|
||||
/**
|
||||
* Proxied video URL
|
||||
*/
|
||||
get proxiedURL() {
|
||||
get proxiedURL(): string | undefined {
|
||||
return this.client?.proxyFile(this.url);
|
||||
}
|
||||
}
|
||||
@@ -116,7 +114,7 @@ export class VideoEmbed extends MessageEmbed {
|
||||
export class WebsiteEmbed extends MessageEmbed {
|
||||
readonly url?: string;
|
||||
readonly originalUrl?: string;
|
||||
readonly specialContent?: API.Special;
|
||||
readonly specialContent?: Special;
|
||||
readonly title?: string;
|
||||
readonly description?: string;
|
||||
readonly image?: ImageEmbed;
|
||||
@@ -132,7 +130,7 @@ export class WebsiteEmbed extends MessageEmbed {
|
||||
*/
|
||||
constructor(
|
||||
client: Client,
|
||||
embed: Omit<API.Embed & { type: "Website" }, "type">
|
||||
embed: Omit<Embed & { type: "Website" }, "type">
|
||||
) {
|
||||
super(client, "Website");
|
||||
|
||||
@@ -151,14 +149,14 @@ export class WebsiteEmbed extends MessageEmbed {
|
||||
/**
|
||||
* Proxied icon URL
|
||||
*/
|
||||
get proxiedIconURL() {
|
||||
get proxiedIconURL(): string | undefined {
|
||||
return this.iconUrl ? this.client?.proxyFile(this.iconUrl) : undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
* If special content is present, generate the embed URL
|
||||
*/
|
||||
get embedURL() {
|
||||
get embedURL(): string | undefined {
|
||||
switch (this.specialContent?.type) {
|
||||
case "YouTube": {
|
||||
let timestamp = "";
|
||||
@@ -209,10 +207,7 @@ export class TextEmbed extends MessageEmbed {
|
||||
* @param client Client
|
||||
* @param embed Embed
|
||||
*/
|
||||
constructor(
|
||||
client: Client,
|
||||
embed: Omit<API.Embed & { type: "Text" }, "type">
|
||||
) {
|
||||
constructor(client: Client, embed: Omit<Embed & { type: "Text" }, "type">) {
|
||||
super(client, "Text");
|
||||
|
||||
this.iconUrl = embed.icon_url!;
|
||||
@@ -226,7 +221,7 @@ export class TextEmbed extends MessageEmbed {
|
||||
/**
|
||||
* Proxied icon URL
|
||||
*/
|
||||
get proxiedIconURL() {
|
||||
get proxiedIconURL(): string | undefined {
|
||||
return this.iconUrl ? this.client?.proxyFile(this.iconUrl) : undefined;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,10 @@
|
||||
import { API, Channel, Client, File, Server } from "../index.js";
|
||||
import type { File as APIFile, PublicBot as APIPublicBot } from "revolt-api";
|
||||
|
||||
import type { Client } from "../Client.js";
|
||||
|
||||
import { Channel } from "./Channel.js";
|
||||
import { File } from "./File.js";
|
||||
import { Server } from "./Server.js";
|
||||
|
||||
/**
|
||||
* Public Bot Class
|
||||
@@ -16,7 +22,7 @@ export class PublicBot {
|
||||
* @param client Client
|
||||
* @param data Data
|
||||
*/
|
||||
constructor(client: Client, data: API.PublicBot) {
|
||||
constructor(client: Client, data: APIPublicBot) {
|
||||
this.#client = client;
|
||||
this.id = data._id;
|
||||
this.username = data.username;
|
||||
@@ -24,7 +30,7 @@ export class PublicBot {
|
||||
? new File(client, {
|
||||
_id: data.avatar,
|
||||
tag: "avatars",
|
||||
} as API.File)
|
||||
} as APIFile)
|
||||
: undefined;
|
||||
this.description = data.description!;
|
||||
}
|
||||
@@ -33,7 +39,7 @@ export class PublicBot {
|
||||
* Add the bot to a server
|
||||
* @param server Server
|
||||
*/
|
||||
addToServer(server: Server | string) {
|
||||
addToServer(server: Server | string): void {
|
||||
this.#client.api.post(`/bots/${this.id as ""}/invite`, {
|
||||
server: server instanceof Server ? server.id : server,
|
||||
});
|
||||
@@ -43,7 +49,7 @@ export class PublicBot {
|
||||
* Add the bot to a group
|
||||
* @param group Group
|
||||
*/
|
||||
addToGroup(group: Channel | string) {
|
||||
addToGroup(group: Channel | string): void {
|
||||
// TODO: should use GroupChannel once that is added
|
||||
this.#client.api.post(`/bots/${this.id as ""}/invite`, {
|
||||
group: group instanceof Channel ? group.id : group,
|
||||
|
||||
@@ -1,21 +1,26 @@
|
||||
import { batch } from "solid-js";
|
||||
|
||||
import { ServerFlags } from "../hydration/server.js";
|
||||
import { API, Client, File } from "../index.js";
|
||||
import type { Invite, InviteResponse } from "revolt-api";
|
||||
|
||||
import type { Client } from "../Client.js";
|
||||
import type { ServerFlags } from "../hydration/server.js";
|
||||
|
||||
import { File } from "./File.js";
|
||||
import type { Server } from "./Server.js";
|
||||
|
||||
/**
|
||||
* Public Channel Invite
|
||||
*/
|
||||
export abstract class PublicChannelInvite {
|
||||
protected client?: Client;
|
||||
readonly type: API.Invite["type"] | "None";
|
||||
readonly type: Invite["type"] | "None";
|
||||
|
||||
/**
|
||||
* Construct Channel Invite
|
||||
* @param client Client
|
||||
* @param type Type
|
||||
*/
|
||||
constructor(client?: Client, type: API.Invite["type"] | "None" = "None") {
|
||||
constructor(client?: Client, type: Invite["type"] | "None" = "None") {
|
||||
this.client = client;
|
||||
this.type = type;
|
||||
}
|
||||
@@ -26,7 +31,7 @@ export abstract class PublicChannelInvite {
|
||||
* @param invite Data
|
||||
* @returns Invite
|
||||
*/
|
||||
static from(client: Client, invite: API.InviteResponse): PublicChannelInvite {
|
||||
static from(client: Client, invite: InviteResponse): PublicChannelInvite {
|
||||
switch (invite.type) {
|
||||
case "Server":
|
||||
return new ServerPublicInvite(client, invite);
|
||||
@@ -65,7 +70,7 @@ export class ServerPublicInvite extends PublicChannelInvite {
|
||||
* @param client Client
|
||||
* @param invite Invite
|
||||
*/
|
||||
constructor(client: Client, invite: API.InviteResponse & { type: "Server" }) {
|
||||
constructor(client: Client, invite: InviteResponse & { type: "Server" }) {
|
||||
super(client, "Server");
|
||||
|
||||
this.code = invite.code;
|
||||
@@ -93,7 +98,7 @@ export class ServerPublicInvite extends PublicChannelInvite {
|
||||
/**
|
||||
* Join the server
|
||||
*/
|
||||
async join() {
|
||||
async join(): Promise<Server> {
|
||||
const existingServer = this.client!.servers.get(this.serverId);
|
||||
if (existingServer) return existingServer;
|
||||
|
||||
|
||||
+87
-58
@@ -1,6 +1,9 @@
|
||||
import { batch } from "solid-js";
|
||||
|
||||
import type { ReactiveMap } from "@solid-primitives/map";
|
||||
import type { ReactiveSet } from "@solid-primitives/set";
|
||||
import type {
|
||||
Server as APIServer,
|
||||
AllMemberResponse,
|
||||
BannedUser,
|
||||
Category,
|
||||
@@ -10,21 +13,27 @@ import type {
|
||||
DataEditRole,
|
||||
DataEditServer,
|
||||
Override,
|
||||
OverrideField,
|
||||
Role,
|
||||
} from "revolt-api";
|
||||
import { decodeTime } from "ulid";
|
||||
|
||||
import { ServerCollection } from "../collections/index.js";
|
||||
import type { ServerCollection } from "../collections/ServerCollection.js";
|
||||
import { hydrate } from "../hydration/index.js";
|
||||
import { ServerMember, User } from "../index.js";
|
||||
import type { ServerFlags } from "../hydration/server.js";
|
||||
import {
|
||||
bitwiseAndEq,
|
||||
calculatePermission,
|
||||
} from "../permissions/calculator.js";
|
||||
import { Permission } from "../permissions/definitions.js";
|
||||
|
||||
import { Channel } from "./Channel.js";
|
||||
import type { Channel } from "./Channel.js";
|
||||
import type { Emoji } from "./Emoji.js";
|
||||
import type { File } from "./File.js";
|
||||
import { ChannelInvite } from "./Invite.js";
|
||||
import { ServerBan } from "./ServerBan.js";
|
||||
import { ServerMember } from "./ServerMember.js";
|
||||
import { User } from "./User.js";
|
||||
|
||||
/**
|
||||
* Server Class
|
||||
@@ -42,40 +51,39 @@ export class Server {
|
||||
this.#collection = collection;
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert to string
|
||||
* @returns String
|
||||
*/
|
||||
toString() {
|
||||
toString(): string {
|
||||
return `<%${this.id}>`;
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether this object exists
|
||||
*/
|
||||
get $exists() {
|
||||
get $exists(): boolean {
|
||||
return !!this.#collection.getUnderlyingObject(this.id).id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Time when this server was created
|
||||
*/
|
||||
get createdAt() {
|
||||
get createdAt(): Date {
|
||||
return new Date(decodeTime(this.id));
|
||||
}
|
||||
|
||||
/**
|
||||
* Owner's user ID
|
||||
*/
|
||||
get ownerId() {
|
||||
get ownerId(): string {
|
||||
return this.#collection.getUnderlyingObject(this.id).ownerId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Owner
|
||||
*/
|
||||
get owner() {
|
||||
get owner(): User | undefined {
|
||||
return this.#collection.client.users.get(
|
||||
this.#collection.getUnderlyingObject(this.id).ownerId
|
||||
);
|
||||
@@ -84,42 +92,42 @@ export class Server {
|
||||
/**
|
||||
* Name
|
||||
*/
|
||||
get name() {
|
||||
get name(): string {
|
||||
return this.#collection.getUnderlyingObject(this.id).name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Description
|
||||
*/
|
||||
get description() {
|
||||
get description(): string | undefined {
|
||||
return this.#collection.getUnderlyingObject(this.id).description;
|
||||
}
|
||||
|
||||
/**
|
||||
* Icon
|
||||
*/
|
||||
get icon() {
|
||||
get icon(): File | undefined {
|
||||
return this.#collection.getUnderlyingObject(this.id).icon;
|
||||
}
|
||||
|
||||
/**
|
||||
* Banner
|
||||
*/
|
||||
get banner() {
|
||||
get banner(): File | undefined {
|
||||
return this.#collection.getUnderlyingObject(this.id).banner;
|
||||
}
|
||||
|
||||
/**
|
||||
* Channel IDs
|
||||
*/
|
||||
get channelIds() {
|
||||
get channelIds(): ReactiveSet<string> {
|
||||
return this.#collection.getUnderlyingObject(this.id).channelIds;
|
||||
}
|
||||
|
||||
/**
|
||||
* Channels
|
||||
*/
|
||||
get channels() {
|
||||
get channels(): Channel[] {
|
||||
return [
|
||||
...this.#collection.getUnderlyingObject(this.id).channelIds.values(),
|
||||
]
|
||||
@@ -130,56 +138,65 @@ export class Server {
|
||||
/**
|
||||
* Categories
|
||||
*/
|
||||
get categories() {
|
||||
get categories(): Category[] | undefined {
|
||||
return this.#collection.getUnderlyingObject(this.id).categories;
|
||||
}
|
||||
|
||||
/**
|
||||
* System message channels
|
||||
*/
|
||||
get systemMessages() {
|
||||
get systemMessages(): APIServer["system_messages"] {
|
||||
return this.#collection.getUnderlyingObject(this.id).systemMessages;
|
||||
}
|
||||
|
||||
/**
|
||||
* Roles
|
||||
*/
|
||||
get roles() {
|
||||
get roles(): ReactiveMap<
|
||||
string,
|
||||
{
|
||||
name: string;
|
||||
permissions: OverrideField;
|
||||
colour?: string | null;
|
||||
hoist?: boolean;
|
||||
rank?: number;
|
||||
}
|
||||
> {
|
||||
return this.#collection.getUnderlyingObject(this.id).roles;
|
||||
}
|
||||
|
||||
/**
|
||||
* Default permissions
|
||||
*/
|
||||
get defaultPermissions() {
|
||||
get defaultPermissions(): number {
|
||||
return this.#collection.getUnderlyingObject(this.id).defaultPermissions;
|
||||
}
|
||||
|
||||
/**
|
||||
* Server flags
|
||||
*/
|
||||
get flags() {
|
||||
get flags(): ServerFlags {
|
||||
return this.#collection.getUnderlyingObject(this.id).flags;
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether analytics are enabled for this server
|
||||
*/
|
||||
get analytics() {
|
||||
get analytics(): boolean {
|
||||
return this.#collection.getUnderlyingObject(this.id).analytics;
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether this server is publicly discoverable
|
||||
*/
|
||||
get discoverable() {
|
||||
get discoverable(): boolean {
|
||||
return this.#collection.getUnderlyingObject(this.id).discoverable;
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether this server is marked as mature
|
||||
*/
|
||||
get mature() {
|
||||
get mature(): boolean {
|
||||
return this.#collection.getUnderlyingObject(this.id).nsfw;
|
||||
}
|
||||
|
||||
@@ -252,7 +269,14 @@ export class Server {
|
||||
* ranking roles. This is dictated by the "rank" property
|
||||
* which is smaller for higher priority roles.
|
||||
*/
|
||||
get orderedRoles() {
|
||||
get orderedRoles(): {
|
||||
name: string;
|
||||
permissions: OverrideField;
|
||||
colour?: string | null;
|
||||
hoist?: boolean;
|
||||
rank?: number;
|
||||
id: string;
|
||||
}[] {
|
||||
const roles = this.roles;
|
||||
return roles
|
||||
? [...roles.entries()]
|
||||
@@ -265,15 +289,15 @@ export class Server {
|
||||
* Check whether the server is currently unread
|
||||
* @returns Whether the server is unread
|
||||
*/
|
||||
get unread() {
|
||||
return this.channels.find((channel) => channel.unread);
|
||||
get unread(): boolean {
|
||||
return !!this.channels.find((channel) => channel.unread);
|
||||
}
|
||||
|
||||
/**
|
||||
* Find all message IDs of unread messages
|
||||
* @returns Array of message IDs which are unread
|
||||
*/
|
||||
get mentions() {
|
||||
get mentions(): string[] {
|
||||
const arr = this.channels.map((channel) =>
|
||||
Array.from(channel.mentions?.values() ?? [])
|
||||
);
|
||||
@@ -284,28 +308,28 @@ export class Server {
|
||||
/**
|
||||
* URL to the server's icon
|
||||
*/
|
||||
get iconURL() {
|
||||
get iconURL(): string | undefined {
|
||||
return this.icon?.createFileURL();
|
||||
}
|
||||
|
||||
/**
|
||||
* URL to the server's animated icon
|
||||
*/
|
||||
get animatedIconURL() {
|
||||
get animatedIconURL(): string | undefined {
|
||||
return this.icon?.createFileURL(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* URL to the server's banner
|
||||
*/
|
||||
get bannerURL() {
|
||||
get bannerURL(): string | undefined {
|
||||
return this.banner?.createFileURL();
|
||||
}
|
||||
|
||||
/**
|
||||
* Own member object for this server
|
||||
*/
|
||||
get member() {
|
||||
get member(): ServerMember | undefined {
|
||||
return this.#collection.client.serverMembers.getByKey({
|
||||
server: this.id,
|
||||
user: this.#collection.client.user!.id,
|
||||
@@ -315,7 +339,7 @@ export class Server {
|
||||
/**
|
||||
* Permission the currently authenticated user has against this server
|
||||
*/
|
||||
get permission() {
|
||||
get permission(): number {
|
||||
return calculatePermission(this.#collection.client, this);
|
||||
}
|
||||
|
||||
@@ -324,7 +348,7 @@ export class Server {
|
||||
* @param permission Permission Names
|
||||
* @returns Whether we have this permission
|
||||
*/
|
||||
havePermission(...permission: (keyof typeof Permission)[]) {
|
||||
havePermission(...permission: (keyof typeof Permission)[]): boolean {
|
||||
return bitwiseAndEq(
|
||||
this.permission,
|
||||
...permission.map((x) => Permission[x])
|
||||
@@ -336,7 +360,7 @@ export class Server {
|
||||
* @param permission Permission Names
|
||||
* @returns Whether we have one of the permissions
|
||||
*/
|
||||
orPermission(...permission: (keyof typeof Permission)[]) {
|
||||
orPermission(...permission: (keyof typeof Permission)[]): boolean {
|
||||
return (
|
||||
permission.findIndex((x) =>
|
||||
bitwiseAndEq(this.permission, Permission[x])
|
||||
@@ -349,7 +373,7 @@ export class Server {
|
||||
* @param userId User's ID
|
||||
* @returns Server Member (if cached)
|
||||
*/
|
||||
getMember(userId: string) {
|
||||
getMember(userId: string): ServerMember | undefined {
|
||||
return this.#collection.client.serverMembers.getByKey({
|
||||
server: this.id,
|
||||
user: userId,
|
||||
@@ -361,7 +385,7 @@ export class Server {
|
||||
* @param data Channel create route data
|
||||
* @returns The newly-created channel
|
||||
*/
|
||||
async createChannel(data: DataCreateServerChannel) {
|
||||
async createChannel(data: DataCreateServerChannel): Promise<Channel> {
|
||||
const channel = await this.#collection.client.api.post(
|
||||
`/servers/${this.id as ""}/channels`,
|
||||
data
|
||||
@@ -374,7 +398,7 @@ export class Server {
|
||||
* Edit a server
|
||||
* @param data Changes
|
||||
*/
|
||||
async edit(data: DataEditServer) {
|
||||
async edit(data: DataEditServer): Promise<void> {
|
||||
this.#collection.updateUnderlyingObject(
|
||||
this.id,
|
||||
hydrate(
|
||||
@@ -393,7 +417,7 @@ export class Server {
|
||||
* Delete the underlying server
|
||||
* @param leaveEvent Whether we are leaving
|
||||
*/
|
||||
$delete(leaveEvent?: boolean) {
|
||||
$delete(leaveEvent?: boolean): void {
|
||||
batch(() => {
|
||||
const server = this.#collection.client.servers.getUnderlyingObject(
|
||||
this.id
|
||||
@@ -420,7 +444,7 @@ export class Server {
|
||||
* Delete or leave a server
|
||||
* @param leaveSilently Whether to not send a message on leave
|
||||
*/
|
||||
async delete(leaveSilently?: boolean) {
|
||||
async delete(leaveSilently?: boolean): Promise<void> {
|
||||
await this.#collection.client.api.delete(`/servers/${this.id as ""}`, {
|
||||
leave_silently: leaveSilently,
|
||||
});
|
||||
@@ -431,7 +455,7 @@ export class Server {
|
||||
/**
|
||||
* Mark a server as read
|
||||
*/
|
||||
async ack() {
|
||||
async ack(): Promise<void> {
|
||||
batch(() => {
|
||||
for (const channel of this.channels) {
|
||||
channel.ack(undefined, false, true);
|
||||
@@ -449,7 +473,7 @@ export class Server {
|
||||
async banUser(
|
||||
user: string | User | ServerMember,
|
||||
options: DataBanCreate = {}
|
||||
) {
|
||||
): Promise<ServerBan> {
|
||||
const userId =
|
||||
user instanceof User
|
||||
? user.id
|
||||
@@ -469,7 +493,7 @@ export class Server {
|
||||
* Kick user from this server
|
||||
* @param user User
|
||||
*/
|
||||
async kickUser(user: string | User | ServerMember) {
|
||||
async kickUser(user: string | User | ServerMember): Promise<void> {
|
||||
return await this.#collection.client.api.delete(
|
||||
`/servers/${this.id as ""}/members/${
|
||||
typeof user === "string"
|
||||
@@ -485,7 +509,7 @@ export class Server {
|
||||
* Pardon user's ban
|
||||
* @param user User
|
||||
*/
|
||||
async unbanUser(user: string | User) {
|
||||
async unbanUser(user: string | User): Promise<void> {
|
||||
const userId = user instanceof User ? user.id : user;
|
||||
return await this.#collection.client.api.delete(
|
||||
`/servers/${this.id as ""}/bans/${userId}`
|
||||
@@ -496,7 +520,7 @@ export class Server {
|
||||
* Fetch a server's invites
|
||||
* @returns An array of the server's invites
|
||||
*/
|
||||
async fetchInvites() {
|
||||
async fetchInvites(): Promise<ChannelInvite[]> {
|
||||
const invites = await this.#collection.client.api.get(
|
||||
`/servers/${this.id as ""}/invites`
|
||||
);
|
||||
@@ -510,7 +534,7 @@ export class Server {
|
||||
* Fetch a server's bans
|
||||
* @returns An array of the server's bans.
|
||||
*/
|
||||
async fetchBans() {
|
||||
async fetchBans(): Promise<ServerBan[]> {
|
||||
const { users, bans } = await this.#collection.client.api.get(
|
||||
`/servers/${this.id as ""}/bans`
|
||||
);
|
||||
@@ -531,7 +555,10 @@ export class Server {
|
||||
* @param roleId Role Id, set to 'default' to affect all users
|
||||
* @param permissions Permission value
|
||||
*/
|
||||
async setPermissions(roleId = "default", permissions: Override | number) {
|
||||
async setPermissions(
|
||||
roleId = "default",
|
||||
permissions: Override | number
|
||||
): Promise<APIServer> {
|
||||
return await this.#collection.client.api.put(
|
||||
`/servers/${this.id as ""}/permissions/${roleId as ""}`,
|
||||
{ permissions: permissions as Override }
|
||||
@@ -542,7 +569,7 @@ export class Server {
|
||||
* Create role
|
||||
* @param name Role name
|
||||
*/
|
||||
async createRole(name: string) {
|
||||
async createRole(name: string): Promise<{ id: string; role: Role }> {
|
||||
return await this.#collection.client.api.post(
|
||||
`/servers/${this.id as ""}/roles`,
|
||||
{
|
||||
@@ -556,7 +583,7 @@ export class Server {
|
||||
* @param roleId Role ID
|
||||
* @param data Role editing route data
|
||||
*/
|
||||
async editRole(roleId: string, data: DataEditRole) {
|
||||
async editRole(roleId: string, data: DataEditRole): Promise<Role> {
|
||||
return await this.#collection.client.api.patch(
|
||||
`/servers/${this.id as ""}/roles/${roleId as ""}`,
|
||||
data
|
||||
@@ -567,7 +594,7 @@ export class Server {
|
||||
* Delete role
|
||||
* @param roleId Role ID
|
||||
*/
|
||||
async deleteRole(roleId: string) {
|
||||
async deleteRole(roleId: string): Promise<void> {
|
||||
return await this.#collection.client.api.delete(
|
||||
`/servers/${this.id as ""}/roles/${roleId as ""}`
|
||||
);
|
||||
@@ -578,7 +605,7 @@ export class Server {
|
||||
* @param user User
|
||||
* @returns Server member object
|
||||
*/
|
||||
async fetchMember(user: User | string) {
|
||||
async fetchMember(user: User | string): Promise<ServerMember> {
|
||||
const userId = typeof user === "string" ? user : user.id;
|
||||
const existing = this.#collection.client.serverMembers.getByKey({
|
||||
server: this.id,
|
||||
@@ -595,7 +622,7 @@ export class Server {
|
||||
* Optimised member fetch route
|
||||
* @param excludeOffline
|
||||
*/
|
||||
async syncMembers(excludeOffline?: boolean) {
|
||||
async syncMembers(excludeOffline?: boolean): Promise<void> {
|
||||
if (this.#synced && (this.#synced === "full" || excludeOffline)) return;
|
||||
|
||||
const data = await this.#collection.client.api.get(
|
||||
@@ -633,7 +660,7 @@ export class Server {
|
||||
/**
|
||||
* Reset member sync status
|
||||
*/
|
||||
resetSyncStatus() {
|
||||
resetSyncStatus(): void {
|
||||
this.#synced = undefined;
|
||||
}
|
||||
|
||||
@@ -641,7 +668,7 @@ export class Server {
|
||||
* Fetch a server's members
|
||||
* @returns List of the server's members and their user objects
|
||||
*/
|
||||
async fetchMembers() {
|
||||
async fetchMembers(): Promise<{ members: ServerMember[]; users: User[] }> {
|
||||
const data = (await this.#collection.client.api.get(
|
||||
// @ts-expect-error TODO weird typing issue
|
||||
`/servers/${this.id as ""}/members`
|
||||
@@ -662,7 +689,9 @@ export class Server {
|
||||
* @param query Name
|
||||
* @returns List of the server's members and their user objects
|
||||
*/
|
||||
async queryMembersExperimental(query: string) {
|
||||
async queryMembersExperimental(
|
||||
query: string
|
||||
): Promise<{ members: ServerMember[]; users: User[] }> {
|
||||
const data = (await this.#collection.client.api.get(
|
||||
`/servers/${
|
||||
this.id as ""
|
||||
@@ -689,7 +718,7 @@ export class Server {
|
||||
async createEmoji(
|
||||
autumnId: string,
|
||||
options: Omit<DataCreateEmoji, "parent">
|
||||
) {
|
||||
): Promise<Emoji> {
|
||||
const emoji = await this.#collection.client.api.put(
|
||||
`/custom/emoji/${autumnId as ""}`,
|
||||
{
|
||||
@@ -708,7 +737,7 @@ export class Server {
|
||||
* Fetch a server's emoji
|
||||
* @returns List of server emoji
|
||||
*/
|
||||
async fetchEmojis() {
|
||||
async fetchEmojis(): Promise<Emoji[]> {
|
||||
const emojis = await this.#collection.client.api.get(
|
||||
`/servers/${this.id as ""}/emojis`
|
||||
);
|
||||
@@ -724,7 +753,7 @@ export class Server {
|
||||
* Delete emoji
|
||||
* @param emojiId Emoji ID
|
||||
*/
|
||||
async deleteEmoji(emojiId: string) {
|
||||
return await this.#collection.client.api.delete(`/custom/emoji/${emojiId}`);
|
||||
async deleteEmoji(emojiId: string): Promise<void> {
|
||||
await this.#collection.client.api.delete(`/custom/emoji/${emojiId}`);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,10 +1,13 @@
|
||||
import {
|
||||
BannedUser as ApiBannedUser,
|
||||
ServerBan as ApiServerBan,
|
||||
import type {
|
||||
BannedUser as APIBannedUser,
|
||||
ServerBan as APIServerBan,
|
||||
MemberCompositeKey,
|
||||
} from "revolt-api";
|
||||
|
||||
import { BannedUser, Client } from "../index.js";
|
||||
import type { Client } from "../Client.js";
|
||||
|
||||
import { BannedUser } from "./BannedUser.js";
|
||||
import type { Server } from "./Server.js";
|
||||
|
||||
/**
|
||||
* Server Ban
|
||||
@@ -20,7 +23,7 @@ export class ServerBan {
|
||||
* @param client Client
|
||||
* @param data Data
|
||||
*/
|
||||
constructor(client: Client, data: ApiServerBan, user?: ApiBannedUser) {
|
||||
constructor(client: Client, data: APIServerBan, user?: APIBannedUser) {
|
||||
this.client = client;
|
||||
this.id = data._id;
|
||||
this.reason = data.reason!;
|
||||
@@ -30,14 +33,14 @@ export class ServerBan {
|
||||
/**
|
||||
* Server
|
||||
*/
|
||||
get server() {
|
||||
get server(): Server | undefined {
|
||||
return this.client.servers.get(this.id.server);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove this server ban
|
||||
*/
|
||||
async pardon() {
|
||||
async pardon(): Promise<void> {
|
||||
await this.client.api.delete(
|
||||
`/servers/${this.id.server as ""}/bans/${this.id.user as ""}`
|
||||
);
|
||||
|
||||
+29
-26
@@ -2,24 +2,27 @@ import type {
|
||||
DataBanCreate,
|
||||
DataMemberEdit,
|
||||
MemberCompositeKey,
|
||||
Role,
|
||||
} from "revolt-api";
|
||||
|
||||
import { ServerMemberCollection } from "../collections/index.js";
|
||||
import type { ServerMemberCollection } from "../collections/ServerMemberCollection.js";
|
||||
import {
|
||||
bitwiseAndEq,
|
||||
calculatePermission,
|
||||
} from "../permissions/calculator.js";
|
||||
import { Permission } from "../permissions/definitions.js";
|
||||
|
||||
import { Channel } from "./Channel.js";
|
||||
import { Server } from "./Server.js";
|
||||
import type { Channel } from "./Channel.js";
|
||||
import type { File } from "./File.js";
|
||||
import type { Server } from "./Server.js";
|
||||
import type { User } from "./User.js";
|
||||
|
||||
/**
|
||||
* Deterministic conversion of member composite key to string ID
|
||||
* @param key Key
|
||||
* @returns String key
|
||||
*/
|
||||
function key(key: MemberCompositeKey) {
|
||||
function key(key: MemberCompositeKey): string {
|
||||
return key.server + key.user;
|
||||
}
|
||||
|
||||
@@ -44,70 +47,70 @@ export class ServerMember {
|
||||
* Convert to string
|
||||
* @returns String
|
||||
*/
|
||||
toString() {
|
||||
toString(): string {
|
||||
return `<@${this.id.user}>`;
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether this object exists
|
||||
*/
|
||||
get $exists() {
|
||||
get $exists(): boolean {
|
||||
return !this.#collection.getUnderlyingObject(key(this.id)).id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Server this member belongs to
|
||||
*/
|
||||
get server() {
|
||||
get server(): Server | undefined {
|
||||
return this.#collection.client.servers.get(this.id.server);
|
||||
}
|
||||
|
||||
/**
|
||||
* User corresponding to this member
|
||||
*/
|
||||
get user() {
|
||||
get user(): User | undefined {
|
||||
return this.#collection.client.users.get(this.id.user);
|
||||
}
|
||||
|
||||
/**
|
||||
* When this user joined the server
|
||||
*/
|
||||
get joinedAt() {
|
||||
get joinedAt(): Date {
|
||||
return this.#collection.getUnderlyingObject(key(this.id)).joinedAt;
|
||||
}
|
||||
|
||||
/**
|
||||
* Nickname
|
||||
*/
|
||||
get nickname() {
|
||||
get nickname(): string | undefined {
|
||||
return this.#collection.getUnderlyingObject(key(this.id)).nickname;
|
||||
}
|
||||
|
||||
/**
|
||||
* Avatar
|
||||
*/
|
||||
get avatar() {
|
||||
get avatar(): File | undefined {
|
||||
return this.#collection.getUnderlyingObject(key(this.id)).avatar;
|
||||
}
|
||||
|
||||
/**
|
||||
* List of role IDs
|
||||
*/
|
||||
get roles() {
|
||||
get roles(): string[] {
|
||||
return this.#collection.getUnderlyingObject(key(this.id)).roles;
|
||||
}
|
||||
|
||||
/**
|
||||
* Time at which timeout expires
|
||||
*/
|
||||
get timeout() {
|
||||
get timeout(): Date | undefined {
|
||||
return this.#collection.getUnderlyingObject(key(this.id)).timeout;
|
||||
}
|
||||
|
||||
/**
|
||||
* Ordered list of roles for this member, from lowest to highest priority.
|
||||
*/
|
||||
get orderedRoles() {
|
||||
get orderedRoles(): (Partial<Role> & { id: string })[] {
|
||||
const server = this.server!;
|
||||
return (
|
||||
this.roles
|
||||
@@ -122,7 +125,7 @@ export class ServerMember {
|
||||
/**
|
||||
* Member's currently hoisted role.
|
||||
*/
|
||||
get hoistedRole() {
|
||||
get hoistedRole(): Partial<Role> | null {
|
||||
const roles = this.orderedRoles.filter((x) => x.hoist);
|
||||
if (roles.length > 0) {
|
||||
return roles[roles.length - 1];
|
||||
@@ -134,7 +137,7 @@ export class ServerMember {
|
||||
/**
|
||||
* Member's current role colour.
|
||||
*/
|
||||
get roleColour() {
|
||||
get roleColour(): string | null | undefined {
|
||||
const roles = this.orderedRoles.filter((x) => x.colour);
|
||||
if (roles.length > 0) {
|
||||
return roles[roles.length - 1].colour;
|
||||
@@ -147,7 +150,7 @@ export class ServerMember {
|
||||
* Member's ranking
|
||||
* Smaller values are ranked as higher priority
|
||||
*/
|
||||
get ranking() {
|
||||
get ranking(): number {
|
||||
if (this.id.user === this.server?.ownerId) {
|
||||
return -Infinity;
|
||||
}
|
||||
@@ -165,7 +168,7 @@ export class ServerMember {
|
||||
* @param target Target object to check permissions against
|
||||
* @returns Permissions that this member has
|
||||
*/
|
||||
getPermissions(target: Server | Channel) {
|
||||
getPermissions(target: Server | Channel): number {
|
||||
return calculatePermission(this.#collection.client, target, {
|
||||
member: this,
|
||||
});
|
||||
@@ -180,7 +183,7 @@ export class ServerMember {
|
||||
hasPermission(
|
||||
target: Server | Channel,
|
||||
...permission: (keyof typeof Permission)[]
|
||||
) {
|
||||
): boolean {
|
||||
return bitwiseAndEq(
|
||||
this.getPermissions(target),
|
||||
...permission.map((x) => Permission[x])
|
||||
@@ -192,28 +195,28 @@ export class ServerMember {
|
||||
* @param target The member to compare against
|
||||
* @returns Whether this member is inferior to the target
|
||||
*/
|
||||
inferiorTo(target: ServerMember) {
|
||||
inferiorTo(target: ServerMember): boolean {
|
||||
return target.ranking < this.ranking;
|
||||
}
|
||||
|
||||
/**
|
||||
* Display name
|
||||
*/
|
||||
get displayName() {
|
||||
get displayName(): string | undefined {
|
||||
return this.nickname ?? this.user?.displayName;
|
||||
}
|
||||
|
||||
/**
|
||||
* URL to the member's avatar
|
||||
*/
|
||||
get avatarURL() {
|
||||
get avatarURL(): string | undefined {
|
||||
return this.avatar?.createFileURL() ?? this.user?.avatarURL;
|
||||
}
|
||||
|
||||
/**
|
||||
* URL to the member's animated avatar
|
||||
*/
|
||||
get animatedAvatarURL() {
|
||||
get animatedAvatarURL(): string | undefined {
|
||||
return this.avatar?.createFileURL(true) ?? this.user?.animatedAvatarURL;
|
||||
}
|
||||
|
||||
@@ -221,7 +224,7 @@ export class ServerMember {
|
||||
* Edit a member
|
||||
* @param data Changes
|
||||
*/
|
||||
async edit(data: DataMemberEdit) {
|
||||
async edit(data: DataMemberEdit): Promise<void> {
|
||||
await this.#collection.client.api.patch(
|
||||
`/servers/${this.id.server as ""}/members/${this.id.user as ""}`,
|
||||
data
|
||||
@@ -232,14 +235,14 @@ export class ServerMember {
|
||||
* Ban this member from the server
|
||||
* @param options Ban options
|
||||
*/
|
||||
async ban(options: DataBanCreate) {
|
||||
async ban(options: DataBanCreate): Promise<void> {
|
||||
this.server?.banUser(this, options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Kick this member from the server
|
||||
*/
|
||||
async kick() {
|
||||
async kick(): Promise<void> {
|
||||
this.server?.kickUser(this);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { decodeTime } from "ulid";
|
||||
|
||||
import { SessionCollection } from "../collections/index.js";
|
||||
import type { SessionCollection } from "../collections/SessionCollection.js";
|
||||
|
||||
/**
|
||||
* Session Class
|
||||
@@ -23,35 +23,35 @@ export class Session {
|
||||
* Convert to string
|
||||
* @returns String
|
||||
*/
|
||||
toString() {
|
||||
toString(): string {
|
||||
return this.name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether this object exists
|
||||
*/
|
||||
get $exists() {
|
||||
get $exists(): boolean {
|
||||
return !!this.#collection.getUnderlyingObject(this.id).id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Time when this session was created
|
||||
*/
|
||||
get createdAt() {
|
||||
get createdAt(): Date {
|
||||
return new Date(decodeTime(this.id));
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether this is the current session
|
||||
*/
|
||||
get current() {
|
||||
get current(): boolean {
|
||||
return this.id === this.#collection.client.sessionId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Name
|
||||
*/
|
||||
get name() {
|
||||
get name(): string {
|
||||
return this.#collection.getUnderlyingObject(this.id).name;
|
||||
}
|
||||
|
||||
@@ -59,7 +59,7 @@ export class Session {
|
||||
* Rename a session
|
||||
* @param name New name
|
||||
*/
|
||||
async rename(name: string) {
|
||||
async rename(name: string): Promise<void> {
|
||||
await this.#collection.client.api.patch(`/auth/session/${this.id}`, {
|
||||
friendly_name: name,
|
||||
});
|
||||
@@ -70,7 +70,7 @@ export class Session {
|
||||
/**
|
||||
* Delete a session
|
||||
*/
|
||||
async delete() {
|
||||
async delete(): Promise<void> {
|
||||
await this.#collection.client.api.delete(`/auth/session/${this.id as ""}`);
|
||||
this.#collection.delete(this.id);
|
||||
}
|
||||
|
||||
@@ -1,18 +1,22 @@
|
||||
import { API, Client } from "../index.js";
|
||||
import type { SystemMessage as APISystemMessage } from "revolt-api";
|
||||
|
||||
import type { Client } from "../Client.js";
|
||||
|
||||
import type { User } from "./User.js";
|
||||
|
||||
/**
|
||||
* System Message
|
||||
*/
|
||||
export abstract class SystemMessage {
|
||||
protected client?: Client;
|
||||
readonly type: API.SystemMessage["type"];
|
||||
readonly type: APISystemMessage["type"];
|
||||
|
||||
/**
|
||||
* Construct System Message
|
||||
* @param client Client
|
||||
* @param type Type
|
||||
*/
|
||||
constructor(client: Client, type: API.SystemMessage["type"]) {
|
||||
constructor(client: Client, type: APISystemMessage["type"]) {
|
||||
this.client = client;
|
||||
this.type = type;
|
||||
}
|
||||
@@ -23,7 +27,7 @@ export abstract class SystemMessage {
|
||||
* @param embed Data
|
||||
* @returns System Message
|
||||
*/
|
||||
static from(client: Client, message: API.SystemMessage): SystemMessage {
|
||||
static from(client: Client, message: APISystemMessage): SystemMessage {
|
||||
switch (message.type) {
|
||||
case "text":
|
||||
return new TextSystemMessage(client, message);
|
||||
@@ -64,7 +68,7 @@ export class TextSystemMessage extends SystemMessage {
|
||||
*/
|
||||
constructor(
|
||||
client: Client,
|
||||
systemMessage: API.SystemMessage & { type: "text" }
|
||||
systemMessage: APISystemMessage & { type: "text" }
|
||||
) {
|
||||
super(client, systemMessage.type);
|
||||
this.content = systemMessage.content;
|
||||
@@ -84,7 +88,7 @@ export class UserSystemMessage extends SystemMessage {
|
||||
*/
|
||||
constructor(
|
||||
client: Client,
|
||||
systemMessage: API.SystemMessage & {
|
||||
systemMessage: APISystemMessage & {
|
||||
type:
|
||||
| "user_added"
|
||||
| "user_remove"
|
||||
@@ -101,7 +105,7 @@ export class UserSystemMessage extends SystemMessage {
|
||||
/**
|
||||
* User this message concerns
|
||||
*/
|
||||
get user() {
|
||||
get user(): User | undefined {
|
||||
return this.client!.users.get(this.userId);
|
||||
}
|
||||
}
|
||||
@@ -119,7 +123,7 @@ export class UserModeratedSystemMessage extends UserSystemMessage {
|
||||
*/
|
||||
constructor(
|
||||
client: Client,
|
||||
systemMessage: API.SystemMessage & {
|
||||
systemMessage: APISystemMessage & {
|
||||
type: "user_added" | "user_remove";
|
||||
}
|
||||
) {
|
||||
@@ -130,8 +134,7 @@ export class UserModeratedSystemMessage extends UserSystemMessage {
|
||||
/**
|
||||
* User this action was performed by
|
||||
*/
|
||||
get by() {
|
||||
console.info("deez!", this.byId);
|
||||
get by(): User | undefined {
|
||||
return this.client!.users.get(this.byId);
|
||||
}
|
||||
}
|
||||
@@ -149,7 +152,7 @@ export class ChannelEditSystemMessage extends SystemMessage {
|
||||
*/
|
||||
constructor(
|
||||
client: Client,
|
||||
systemMessage: API.SystemMessage & {
|
||||
systemMessage: APISystemMessage & {
|
||||
type:
|
||||
| "channel_renamed"
|
||||
| "channel_description_changed"
|
||||
@@ -163,7 +166,7 @@ export class ChannelEditSystemMessage extends SystemMessage {
|
||||
/**
|
||||
* User this action was performed by
|
||||
*/
|
||||
get by() {
|
||||
get by(): User | undefined {
|
||||
return this.client!.users.get(this.byId);
|
||||
}
|
||||
}
|
||||
@@ -181,7 +184,7 @@ export class ChannelRenamedSystemMessage extends ChannelEditSystemMessage {
|
||||
*/
|
||||
constructor(
|
||||
client: Client,
|
||||
systemMessage: API.SystemMessage & {
|
||||
systemMessage: APISystemMessage & {
|
||||
type: "channel_renamed";
|
||||
}
|
||||
) {
|
||||
@@ -204,7 +207,7 @@ export class ChannelOwnershipChangeSystemMessage extends SystemMessage {
|
||||
*/
|
||||
constructor(
|
||||
client: Client,
|
||||
systemMessage: API.SystemMessage & {
|
||||
systemMessage: APISystemMessage & {
|
||||
type: "channel_ownership_changed";
|
||||
}
|
||||
) {
|
||||
@@ -216,14 +219,14 @@ export class ChannelOwnershipChangeSystemMessage extends SystemMessage {
|
||||
/**
|
||||
* User giving away channel ownership
|
||||
*/
|
||||
get from() {
|
||||
get from(): User | undefined {
|
||||
return this.client!.users.get(this.fromId);
|
||||
}
|
||||
|
||||
/**
|
||||
* User receiving channel ownership
|
||||
*/
|
||||
get to() {
|
||||
get to(): User | undefined {
|
||||
return this.client!.users.get(this.toId);
|
||||
}
|
||||
}
|
||||
|
||||
+40
-33
@@ -1,10 +1,13 @@
|
||||
import { DataEditUser, Presence } from "revolt-api";
|
||||
import type { User as APIUser, DataEditUser, Presence } from "revolt-api";
|
||||
import { decodeTime } from "ulid";
|
||||
|
||||
import { UserCollection } from "../collections/index.js";
|
||||
import { UserProfile } from "../index.js";
|
||||
import type { UserCollection } from "../collections/UserCollection.js";
|
||||
import { U32_MAX, UserPermission } from "../permissions/definitions.js";
|
||||
|
||||
import type { Channel } from "./Channel.js";
|
||||
import type { File } from "./File.js";
|
||||
import { UserProfile } from "./UserProfile.js";
|
||||
|
||||
/**
|
||||
* User Class
|
||||
*/
|
||||
@@ -26,42 +29,42 @@ export class User {
|
||||
* Write to string as a user mention
|
||||
* @returns Formatted String
|
||||
*/
|
||||
toString() {
|
||||
toString(): string {
|
||||
return `<@${this.id}>`;
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether this object exists
|
||||
*/
|
||||
get $exists() {
|
||||
get $exists(): boolean {
|
||||
return !!this.#collection.getUnderlyingObject(this.id).id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Time when this user created their account
|
||||
*/
|
||||
get createdAt() {
|
||||
get createdAt(): Date {
|
||||
return new Date(decodeTime(this.id));
|
||||
}
|
||||
|
||||
/**
|
||||
* Username
|
||||
*/
|
||||
get username() {
|
||||
get username(): string {
|
||||
return this.#collection.getUnderlyingObject(this.id).username;
|
||||
}
|
||||
|
||||
/**
|
||||
* Discriminator
|
||||
*/
|
||||
get discriminator() {
|
||||
get discriminator(): string {
|
||||
return this.#collection.getUnderlyingObject(this.id).discriminator;
|
||||
}
|
||||
|
||||
/**
|
||||
* Display Name
|
||||
*/
|
||||
get displayName() {
|
||||
get displayName(): string {
|
||||
return (
|
||||
this.#collection.getUnderlyingObject(this.id).displayName ??
|
||||
this.#collection.getUnderlyingObject(this.id).username
|
||||
@@ -71,21 +74,23 @@ export class User {
|
||||
/**
|
||||
* Avatar
|
||||
*/
|
||||
get avatar() {
|
||||
get avatar(): File | undefined {
|
||||
return this.#collection.getUnderlyingObject(this.id).avatar;
|
||||
}
|
||||
|
||||
/**
|
||||
* Badges
|
||||
*/
|
||||
get badges() {
|
||||
get badges(): number {
|
||||
return this.#collection.getUnderlyingObject(this.id).badges;
|
||||
}
|
||||
|
||||
/**
|
||||
* User Status
|
||||
*/
|
||||
get status() {
|
||||
get status():
|
||||
| { text?: string | null; presence?: Presence | null }
|
||||
| undefined {
|
||||
// TODO: issue with API, upstream fix required #319
|
||||
if (!this.online)
|
||||
return { text: undefined, presence: "Invisible" as const };
|
||||
@@ -95,49 +100,49 @@ export class User {
|
||||
/**
|
||||
* Relationship with user
|
||||
*/
|
||||
get relationship() {
|
||||
get relationship(): string {
|
||||
return this.#collection.getUnderlyingObject(this.id).relationship;
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether the user is online
|
||||
*/
|
||||
get online() {
|
||||
get online(): boolean {
|
||||
return this.#collection.getUnderlyingObject(this.id).online;
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether the user is privileged
|
||||
*/
|
||||
get privileged() {
|
||||
get privileged(): boolean {
|
||||
return this.#collection.getUnderlyingObject(this.id).privileged;
|
||||
}
|
||||
|
||||
/**
|
||||
* Flags
|
||||
*/
|
||||
get flags() {
|
||||
get flags(): number {
|
||||
return this.#collection.getUnderlyingObject(this.id).flags;
|
||||
}
|
||||
|
||||
/**
|
||||
* Bot information
|
||||
*/
|
||||
get bot() {
|
||||
get bot(): { owner: string } | undefined {
|
||||
return this.#collection.getUnderlyingObject(this.id).bot;
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether this user is ourselves
|
||||
*/
|
||||
get self() {
|
||||
get self(): boolean {
|
||||
return this.#collection.client.user === this;
|
||||
}
|
||||
|
||||
/**
|
||||
* URL to the user's default avatar
|
||||
*/
|
||||
get defaultAvatarURL() {
|
||||
get defaultAvatarURL(): string {
|
||||
return `${this.#collection.client.options.baseURL}/users/${
|
||||
this.id
|
||||
}/default_avatar`;
|
||||
@@ -146,21 +151,21 @@ export class User {
|
||||
/**
|
||||
* URL to the user's avatar
|
||||
*/
|
||||
get avatarURL() {
|
||||
get avatarURL(): string {
|
||||
return this.avatar?.createFileURL() ?? this.defaultAvatarURL;
|
||||
}
|
||||
|
||||
/**
|
||||
* URL to the user's animated avatar
|
||||
*/
|
||||
get animatedAvatarURL() {
|
||||
get animatedAvatarURL(): string {
|
||||
return this.avatar?.createFileURL(true) ?? this.defaultAvatarURL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Presence
|
||||
*/
|
||||
get presence() {
|
||||
get presence(): Presence {
|
||||
return this.online ? this.status?.presence ?? "Online" : "Invisible";
|
||||
}
|
||||
|
||||
@@ -169,7 +174,9 @@ export class User {
|
||||
* @param translate Translation function
|
||||
* @returns Status message
|
||||
*/
|
||||
statusMessage(translate: (presence: Presence) => string = (a) => a) {
|
||||
statusMessage(
|
||||
translate: (presence: Presence) => string = (a) => a
|
||||
): string | undefined {
|
||||
return this.online
|
||||
? this.status?.text ??
|
||||
(this.presence === "Focus" ? translate("Focus") : undefined)
|
||||
@@ -179,7 +186,7 @@ export class User {
|
||||
/**
|
||||
* Permissions against this user
|
||||
*/
|
||||
get permission() {
|
||||
get permission(): number {
|
||||
let permissions = 0;
|
||||
switch (this.relationship) {
|
||||
case "Friend":
|
||||
@@ -217,7 +224,7 @@ export class User {
|
||||
* Edit the user
|
||||
* @param data Changes
|
||||
*/
|
||||
async edit(data: DataEditUser) {
|
||||
async edit(data: DataEditUser): Promise<void> {
|
||||
await this.#collection.client.api.patch(
|
||||
`/users/${
|
||||
this.id === this.#collection.client.user?.id ? "@me" : this.id
|
||||
@@ -231,7 +238,7 @@ export class User {
|
||||
* @param username New username
|
||||
* @param password Current password
|
||||
*/
|
||||
async changeUsername(username: string, password: string) {
|
||||
async changeUsername(username: string, password: string): Promise<APIUser> {
|
||||
return await this.#collection.client.api.patch("/users/@me/username", {
|
||||
username,
|
||||
password,
|
||||
@@ -242,7 +249,7 @@ export class User {
|
||||
* Open a DM with a user
|
||||
* @returns DM Channel
|
||||
*/
|
||||
async openDM() {
|
||||
async openDM(): Promise<Channel> {
|
||||
let dm = [...this.#collection.client.channels.values()].find(
|
||||
(x) => x.type === "DirectMessage" && x.recipient == this
|
||||
);
|
||||
@@ -269,7 +276,7 @@ export class User {
|
||||
/**
|
||||
* Send a friend request to a user
|
||||
*/
|
||||
async addFriend() {
|
||||
async addFriend(): Promise<User> {
|
||||
const user = await this.#collection.client.api.post(`/users/friend`, {
|
||||
username: this.username + "#" + this.discriminator,
|
||||
});
|
||||
@@ -280,21 +287,21 @@ export class User {
|
||||
/**
|
||||
* Remove a user from the friend list
|
||||
*/
|
||||
async removeFriend() {
|
||||
async removeFriend(): Promise<void> {
|
||||
await this.#collection.client.api.delete(`/users/${this.id as ""}/friend`);
|
||||
}
|
||||
|
||||
/**
|
||||
* Block a user
|
||||
*/
|
||||
async blockUser() {
|
||||
async blockUser(): Promise<void> {
|
||||
await this.#collection.client.api.put(`/users/${this.id as ""}/block`);
|
||||
}
|
||||
|
||||
/**
|
||||
* Unblock a user
|
||||
*/
|
||||
async unblockUser() {
|
||||
async unblockUser(): Promise<void> {
|
||||
await this.#collection.client.api.delete(`/users/${this.id as ""}/block`);
|
||||
}
|
||||
|
||||
@@ -302,7 +309,7 @@ export class User {
|
||||
* Fetch the profile of a user
|
||||
* @returns The profile of the user
|
||||
*/
|
||||
async fetchProfile() {
|
||||
async fetchProfile(): Promise<UserProfile> {
|
||||
return new UserProfile(
|
||||
this.#collection.client,
|
||||
await this.#collection.client.api.get(`/users/${this.id as ""}/profile`)
|
||||
@@ -313,7 +320,7 @@ export class User {
|
||||
* Fetch the mutual connections of the current user and a target user
|
||||
* @returns The mutual connections of the current user and a target user
|
||||
*/
|
||||
async fetchMutual() {
|
||||
async fetchMutual(): Promise<{ users: string[]; servers: string[] }> {
|
||||
return await this.#collection.client.api.get(
|
||||
`/users/${this.id as ""}/mutual`
|
||||
);
|
||||
|
||||
@@ -1,4 +1,8 @@
|
||||
import { API, Client, File } from "../index.js";
|
||||
import type { UserProfile as APIUserProfile } from "revolt-api";
|
||||
|
||||
import type { Client } from "../Client.js";
|
||||
|
||||
import { File } from "./File.js";
|
||||
|
||||
/**
|
||||
* User Profile Class
|
||||
@@ -12,7 +16,7 @@ export class UserProfile {
|
||||
* @param client Client
|
||||
* @param data Data
|
||||
*/
|
||||
constructor(client: Client, data: API.UserProfile) {
|
||||
constructor(client: Client, data: APIUserProfile) {
|
||||
this.content = data.content!;
|
||||
this.banner = data.background
|
||||
? new File(client, data.background)
|
||||
@@ -22,14 +26,14 @@ export class UserProfile {
|
||||
/**
|
||||
* URL to the user's banner
|
||||
*/
|
||||
get bannerURL() {
|
||||
get bannerURL(): string | undefined {
|
||||
return this.banner?.createFileURL();
|
||||
}
|
||||
|
||||
/**
|
||||
* URL to the user's animated banner
|
||||
*/
|
||||
get animatedBannerURL() {
|
||||
get animatedBannerURL(): string | undefined {
|
||||
return this.banner?.createFileURL(true);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { DataCreateAccount, WebPushSubscription } from "revolt-api";
|
||||
import type { DataCreateAccount, WebPushSubscription } from "revolt-api";
|
||||
|
||||
import type { Client } from "../Client.js";
|
||||
import { MFA } from "../classes/MFA.js";
|
||||
import { Client } from "../index.js";
|
||||
|
||||
/**
|
||||
* Utility functions for working with accounts
|
||||
@@ -21,25 +21,22 @@ export class AccountCollection {
|
||||
* Fetch current account email
|
||||
* @returns Email
|
||||
*/
|
||||
fetchEmail() {
|
||||
return this.client.api
|
||||
.get("/auth/account/")
|
||||
.then((account) => account.email);
|
||||
async fetchEmail(): Promise<string> {
|
||||
return (await this.client.api.get("/auth/account/")).email;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a MFA helper
|
||||
*/
|
||||
async mfa() {
|
||||
const state = await this.client.api.get("/auth/mfa/");
|
||||
return new MFA(this.client, state);
|
||||
async mfa(): Promise<MFA> {
|
||||
return new MFA(this.client, await this.client.api.get("/auth/mfa/"));
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new account
|
||||
* @param data Account details
|
||||
*/
|
||||
create(data: DataCreateAccount) {
|
||||
create(data: DataCreateAccount): Promise<void> {
|
||||
return this.client.api.post("/auth/account/create", data);
|
||||
}
|
||||
|
||||
@@ -48,7 +45,7 @@ export class AccountCollection {
|
||||
* @param email Email
|
||||
* @param captcha Captcha if enabled
|
||||
*/
|
||||
reverify(email: string, captcha?: string) {
|
||||
reverify(email: string, captcha?: string): Promise<void> {
|
||||
return this.client.api.post("/auth/account/reverify", { email, captcha });
|
||||
}
|
||||
|
||||
@@ -57,7 +54,7 @@ export class AccountCollection {
|
||||
* @param email Email
|
||||
* @param captcha Captcha if enabled
|
||||
*/
|
||||
resetPassword(email: string, captcha?: string) {
|
||||
resetPassword(email: string, captcha?: string): Promise<void> {
|
||||
return this.client.api.post("/auth/account/reset_password", {
|
||||
email,
|
||||
captcha,
|
||||
@@ -68,7 +65,7 @@ export class AccountCollection {
|
||||
* Verify an account given the code
|
||||
* @param code Verification code
|
||||
*/
|
||||
verify(code: string) {
|
||||
verify(code: string): Promise<unknown> {
|
||||
return this.client.api.post(`/auth/account/verify/${code}`);
|
||||
}
|
||||
|
||||
@@ -76,7 +73,7 @@ export class AccountCollection {
|
||||
* Confirm account deletion
|
||||
* @param token Deletion token
|
||||
*/
|
||||
confirmDelete(token: string) {
|
||||
confirmDelete(token: string): Promise<void> {
|
||||
return this.client.api.put("/auth/account/delete", { token });
|
||||
}
|
||||
|
||||
@@ -90,7 +87,7 @@ export class AccountCollection {
|
||||
token: string,
|
||||
newPassword: string,
|
||||
removeSessions: boolean
|
||||
) {
|
||||
): Promise<void> {
|
||||
return this.client.api.patch("/auth/account/reset_password", {
|
||||
token,
|
||||
password: newPassword,
|
||||
@@ -103,7 +100,7 @@ export class AccountCollection {
|
||||
* @param newPassword New password
|
||||
* @param currentPassword Current password
|
||||
*/
|
||||
changePassword(newPassword: string, currentPassword: string) {
|
||||
changePassword(newPassword: string, currentPassword: string): Promise<void> {
|
||||
return this.client.api.patch("/auth/account/change/password", {
|
||||
password: newPassword,
|
||||
current_password: currentPassword,
|
||||
@@ -115,7 +112,7 @@ export class AccountCollection {
|
||||
* @param newEmail New email
|
||||
* @param currentPassword Current password
|
||||
*/
|
||||
changeEmail(newEmail: string, currentPassword: string) {
|
||||
changeEmail(newEmail: string, currentPassword: string): Promise<void> {
|
||||
return this.client.api.patch("/auth/account/change/email", {
|
||||
email: newEmail,
|
||||
current_password: currentPassword,
|
||||
@@ -127,7 +124,7 @@ export class AccountCollection {
|
||||
* @param keys Keys
|
||||
* @returns Settings
|
||||
*/
|
||||
fetchSettings(keys: string[]) {
|
||||
fetchSettings(keys: string[]): Promise<Record<string, [number, string]>> {
|
||||
return this.client.api.post("/sync/settings/fetch", { keys }) as Promise<
|
||||
Record<string, [number, string]>
|
||||
>;
|
||||
@@ -139,7 +136,10 @@ export class AccountCollection {
|
||||
* @param settings Settings
|
||||
* @param timestamp Timestamp
|
||||
*/
|
||||
setSettings(settings: Record<string, any>, timestamp = +new Date()) {
|
||||
setSettings(
|
||||
settings: Record<string, any>,
|
||||
timestamp = +new Date()
|
||||
): Promise<void> {
|
||||
return this.client.api.post("/sync/settings/set", {
|
||||
...settings,
|
||||
timestamp,
|
||||
@@ -151,14 +151,14 @@ export class AccountCollection {
|
||||
* Create a new Web Push subscription
|
||||
* @param subscription Subscription
|
||||
*/
|
||||
webPushSubscribe(subscription: WebPushSubscription) {
|
||||
webPushSubscribe(subscription: WebPushSubscription): Promise<void> {
|
||||
return this.client.api.post("/push/subscribe", subscription);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove existing Web Push subscription
|
||||
*/
|
||||
webPushUnsubscribe() {
|
||||
webPushUnsubscribe(): Promise<void> {
|
||||
return this.client.api.post("/push/unsubscribe");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
import { batch } from "solid-js";
|
||||
|
||||
import { OwnedBotsResponse } from "revolt-api";
|
||||
import type { Bot as APIBot, OwnedBotsResponse } from "revolt-api";
|
||||
|
||||
import { HydratedBot } from "../hydration/bot.js";
|
||||
import { API, Bot, PublicBot } from "../index.js";
|
||||
import { Bot } from "../classes/Bot.js";
|
||||
import { PublicBot } from "../classes/PublicBot.js";
|
||||
import type { HydratedBot } from "../hydration/bot.js";
|
||||
|
||||
import { ClassCollection } from "./index.js";
|
||||
import { ClassCollection } from "./Collection.js";
|
||||
|
||||
/**
|
||||
* Collection of Bots
|
||||
@@ -54,7 +55,7 @@ export class BotCollection extends ClassCollection<Bot, HydratedBot> {
|
||||
* @param data Data
|
||||
* @returns Bot
|
||||
*/
|
||||
getOrCreate(id: string, data: API.Bot) {
|
||||
getOrCreate(id: string, data: APIBot): Bot {
|
||||
if (this.has(id)) {
|
||||
return this.get(id)!;
|
||||
} else {
|
||||
@@ -69,7 +70,7 @@ export class BotCollection extends ClassCollection<Bot, HydratedBot> {
|
||||
* @param name Bot name
|
||||
* @returns The newly-created bot
|
||||
*/
|
||||
async createBot(name: string) {
|
||||
async createBot(name: string): Promise<Bot> {
|
||||
const bot = await this.client.api.post(`/bots/create`, {
|
||||
name,
|
||||
});
|
||||
|
||||
@@ -1,7 +1,10 @@
|
||||
import { HydratedChannel } from "../hydration/index.js";
|
||||
import { API, Channel, User } from "../index.js";
|
||||
import type { Channel as APIChannel } from "revolt-api";
|
||||
|
||||
import { ClassCollection } from "./index.js";
|
||||
import { Channel } from "../classes/Channel.js";
|
||||
import { User } from "../classes/User.js";
|
||||
import type { HydratedChannel } from "../hydration/channel.js";
|
||||
|
||||
import { ClassCollection } from "./Collection.js";
|
||||
|
||||
/**
|
||||
* Collection of Channels
|
||||
@@ -38,7 +41,7 @@ export class ChannelCollection extends ClassCollection<
|
||||
* @param data Data
|
||||
* @param isNew Whether this object is new
|
||||
*/
|
||||
getOrCreate(id: string, data: API.Channel, isNew = false) {
|
||||
getOrCreate(id: string, data: APIChannel, isNew = false): Channel {
|
||||
if (this.has(id) && !this.isPartial(id)) {
|
||||
return this.get(id)!;
|
||||
} else {
|
||||
@@ -53,7 +56,7 @@ export class ChannelCollection extends ClassCollection<
|
||||
* Get or return partial
|
||||
* @param id Id
|
||||
*/
|
||||
getOrPartial(id: string) {
|
||||
getOrPartial(id: string): Channel | undefined {
|
||||
if (this.has(id)) {
|
||||
return this.get(id)!;
|
||||
} else if (this.client.options.partials) {
|
||||
@@ -72,7 +75,7 @@ export class ChannelCollection extends ClassCollection<
|
||||
* @param users Users to add
|
||||
* @returns The newly-created group
|
||||
*/
|
||||
async createGroup(name: string, users: (User | string)[]) {
|
||||
async createGroup(name: string, users: (User | string)[]): Promise<Channel> {
|
||||
const group = await this.client.api.post(`/channels/create`, {
|
||||
name,
|
||||
users: users.map((user) => (user instanceof User ? user.id : user)),
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
import { batch } from "solid-js";
|
||||
|
||||
import { ChannelUnread } from "../classes/ChannelUnread.js";
|
||||
import { HydratedChannelUnread } from "../hydration/index.js";
|
||||
import { API } from "../index.js";
|
||||
import type { ChannelUnread as APIChannelUnread } from "revolt-api";
|
||||
|
||||
import { ClassCollection } from "./index.js";
|
||||
import { ChannelUnread } from "../classes/ChannelUnread.js";
|
||||
import type { HydratedChannelUnread } from "../hydration/channelUnread.js";
|
||||
|
||||
import { ClassCollection } from "./Collection.js";
|
||||
|
||||
/**
|
||||
* Collection of Channel Unreads
|
||||
@@ -16,7 +17,7 @@ export class ChannelUnreadCollection extends ClassCollection<
|
||||
/**
|
||||
* Load unread information from server
|
||||
*/
|
||||
async sync() {
|
||||
async sync(): Promise<void> {
|
||||
const unreads = await this.client.api.get("/sync/unreads");
|
||||
batch(() => {
|
||||
this.reset();
|
||||
@@ -29,7 +30,7 @@ export class ChannelUnreadCollection extends ClassCollection<
|
||||
/**
|
||||
* Clear all unread data
|
||||
*/
|
||||
reset() {
|
||||
reset(): void {
|
||||
this.updateUnderlyingObject({});
|
||||
}
|
||||
|
||||
@@ -38,7 +39,7 @@ export class ChannelUnreadCollection extends ClassCollection<
|
||||
* @param id Id
|
||||
* @param data Data
|
||||
*/
|
||||
getOrCreate(id: string, data: API.ChannelUnread) {
|
||||
getOrCreate(id: string, data: APIChannelUnread): ChannelUnread {
|
||||
if (this.has(id)) {
|
||||
return this.get(id)!;
|
||||
} else {
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
import { ChannelWebhook } from "../classes/ChannelWebhook.js";
|
||||
import { HydratedChannelWebhook } from "../hydration/channelWebhook.js";
|
||||
import { API } from "../index.js";
|
||||
import type { Webhook } from "revolt-api";
|
||||
|
||||
import { ClassCollection } from "./index.js";
|
||||
import { ChannelWebhook } from "../classes/ChannelWebhook.js";
|
||||
import type { HydratedChannelWebhook } from "../hydration/channelWebhook.js";
|
||||
|
||||
import { ClassCollection } from "./Collection.js";
|
||||
|
||||
/**
|
||||
* Collection of Channel Webhooks
|
||||
@@ -22,7 +23,7 @@ export class ChannelWebhookCollection extends ClassCollection<
|
||||
// @ts-expect-error not in prod
|
||||
const data = await this.client.api.get(`/webhooks/${id as ""}`);
|
||||
// @ts-expect-error not in prod
|
||||
return this.getOrCreate(data.id, data as API.Webhook);
|
||||
return this.getOrCreate(data.id, data as Webhook);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -47,7 +48,7 @@ export class ChannelWebhookCollection extends ClassCollection<
|
||||
* @param id Id
|
||||
* @param data Data
|
||||
*/
|
||||
getOrCreate(id: string, data: API.Webhook) {
|
||||
getOrCreate(id: string, data: Webhook): ChannelWebhook {
|
||||
if (this.has(id)) {
|
||||
return this.get(id)!;
|
||||
} else {
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import { SetStoreFunction } from "solid-js/store";
|
||||
import type { SetStoreFunction } from "solid-js/store";
|
||||
|
||||
import { ReactiveMap } from "@solid-primitives/map";
|
||||
|
||||
import { Hydrators } from "../hydration/index.js";
|
||||
import { Client } from "../index.js";
|
||||
import type { Client } from "../Client.js";
|
||||
import type { Hydrators } from "../hydration/index.js";
|
||||
import { ObjectStorage } from "../storage/ObjectStorage.js";
|
||||
|
||||
/**
|
||||
@@ -59,14 +59,14 @@ export abstract class Collection<T> {
|
||||
* @param cb Callback for each pair
|
||||
*/
|
||||
abstract forEach(
|
||||
cb: (value: T, key: string, map: ReactiveMap<string, T>) => void
|
||||
cb: (value: T, key: string, map: Map<string, T>) => void
|
||||
): void;
|
||||
|
||||
/**
|
||||
* List of values in the map
|
||||
* @returns List
|
||||
*/
|
||||
toList() {
|
||||
toList(): T[] {
|
||||
return [...this.values()];
|
||||
}
|
||||
|
||||
@@ -143,7 +143,7 @@ export abstract class StoreCollection<T, V> extends Collection<T> {
|
||||
* @param id Id
|
||||
* @returns Whether it exists
|
||||
*/
|
||||
has(id: string) {
|
||||
has(id: string): boolean {
|
||||
return this.#objects.has(id);
|
||||
}
|
||||
|
||||
@@ -170,7 +170,7 @@ export abstract class StoreCollection<T, V> extends Collection<T> {
|
||||
instance: T,
|
||||
context: unknown,
|
||||
data?: unknown
|
||||
) {
|
||||
): void {
|
||||
this.#storage.hydrate(id, type, context, data);
|
||||
this.#objects.set(id, instance);
|
||||
}
|
||||
@@ -188,7 +188,7 @@ export abstract class StoreCollection<T, V> extends Collection<T> {
|
||||
* Number of stored objects
|
||||
* @returns Size
|
||||
*/
|
||||
size() {
|
||||
size(): number {
|
||||
return this.#objects.size;
|
||||
}
|
||||
|
||||
@@ -196,7 +196,7 @@ export abstract class StoreCollection<T, V> extends Collection<T> {
|
||||
* Iterable of keys in the map
|
||||
* @returns Iterable
|
||||
*/
|
||||
keys() {
|
||||
keys(): IterableIterator<string> {
|
||||
return this.#objects.keys();
|
||||
}
|
||||
|
||||
@@ -204,7 +204,7 @@ export abstract class StoreCollection<T, V> extends Collection<T> {
|
||||
* Iterable of values in the map
|
||||
* @returns Iterable
|
||||
*/
|
||||
values() {
|
||||
values(): IterableIterator<T> {
|
||||
return this.#objects.values();
|
||||
}
|
||||
|
||||
@@ -212,7 +212,7 @@ export abstract class StoreCollection<T, V> extends Collection<T> {
|
||||
* Iterable of key, value pairs in the map
|
||||
* @returns Iterable
|
||||
*/
|
||||
entries() {
|
||||
entries(): IterableIterator<[string, T]> {
|
||||
return this.#objects.entries();
|
||||
}
|
||||
|
||||
@@ -221,7 +221,7 @@ export abstract class StoreCollection<T, V> extends Collection<T> {
|
||||
* @param cb Callback for each pair
|
||||
* @returns Iterable
|
||||
*/
|
||||
forEach(cb: (value: T, key: string, map: ReactiveMap<string, T>) => void) {
|
||||
forEach(cb: (value: T, key: string, map: Map<string, T>) => void): void {
|
||||
return this.#objects.forEach(cb);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
import { HydratedEmoji } from "../hydration/index.js";
|
||||
import { API, Emoji } from "../index.js";
|
||||
import type { Emoji as APIEmoji } from "revolt-api";
|
||||
|
||||
import { ClassCollection } from "./index.js";
|
||||
import { Emoji } from "../classes/Emoji.js";
|
||||
import type { HydratedEmoji } from "../hydration/emoji.js";
|
||||
|
||||
import { ClassCollection } from "./Collection.js";
|
||||
|
||||
/**
|
||||
* Collection of Emoji
|
||||
@@ -25,7 +27,7 @@ export class EmojiCollection extends ClassCollection<Emoji, HydratedEmoji> {
|
||||
* @param data Data
|
||||
* @param isNew Whether this object is new
|
||||
*/
|
||||
getOrCreate(id: string, data: API.Emoji, isNew = false) {
|
||||
getOrCreate(id: string, data: APIEmoji, isNew = false): Emoji {
|
||||
if (this.has(id) && !this.isPartial(id)) {
|
||||
return this.get(id)!;
|
||||
} else {
|
||||
@@ -40,7 +42,7 @@ export class EmojiCollection extends ClassCollection<Emoji, HydratedEmoji> {
|
||||
* Get or return partial
|
||||
* @param id Id
|
||||
*/
|
||||
getOrPartial(id: string) {
|
||||
getOrPartial(id: string): Emoji | undefined {
|
||||
if (this.has(id)) {
|
||||
return this.get(id)!;
|
||||
} else if (this.client.options.partials) {
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
import { HydratedMessage } from "../hydration";
|
||||
import { API, Message } from "../index.js";
|
||||
import type { Message as APIMessage } from "revolt-api";
|
||||
|
||||
import { ClassCollection } from "./index.js";
|
||||
import { Message } from "../classes/Message.js";
|
||||
import type { HydratedMessage } from "../hydration/message.js";
|
||||
|
||||
import { ClassCollection } from "./Collection.js";
|
||||
|
||||
/**
|
||||
* Collection of Messages
|
||||
@@ -33,7 +35,7 @@ export class MessageCollection extends ClassCollection<
|
||||
* @param data Data
|
||||
* @param isNew Whether this object is new
|
||||
*/
|
||||
getOrCreate(id: string, data: API.Message, isNew = false) {
|
||||
getOrCreate(id: string, data: APIMessage, isNew = false): Message {
|
||||
if (this.has(id) && !this.isPartial(id)) {
|
||||
return this.get(id)!;
|
||||
} else {
|
||||
@@ -48,7 +50,7 @@ export class MessageCollection extends ClassCollection<
|
||||
* Get or return partial
|
||||
* @param id Id
|
||||
*/
|
||||
getOrPartial(id: string) {
|
||||
getOrPartial(id: string): Message | undefined {
|
||||
if (this.has(id)) {
|
||||
return this.get(id)!;
|
||||
} else if (this.client.options.partials) {
|
||||
|
||||
@@ -1,11 +1,15 @@
|
||||
import { batch } from "solid-js";
|
||||
|
||||
import { DataCreateServer } from "revolt-api";
|
||||
import type {
|
||||
Server as APIServer,
|
||||
Channel,
|
||||
DataCreateServer,
|
||||
} from "revolt-api";
|
||||
|
||||
import { HydratedServer } from "../hydration/index.js";
|
||||
import { API, Server } from "../index.js";
|
||||
import { Server } from "../classes/Server.js";
|
||||
import type { HydratedServer } from "../hydration/server.js";
|
||||
|
||||
import { ClassCollection } from "./index.js";
|
||||
import { ClassCollection } from "./Collection.js";
|
||||
|
||||
/**
|
||||
* Collection of Servers
|
||||
@@ -26,7 +30,7 @@ export class ServerCollection extends ClassCollection<Server, HydratedServer> {
|
||||
});
|
||||
|
||||
return batch(() => {
|
||||
for (const channel of data.channels as unknown as API.Channel[]) {
|
||||
for (const channel of data.channels as unknown as Channel[]) {
|
||||
if (typeof channel !== "string") {
|
||||
this.client.channels.getOrCreate(channel._id, channel);
|
||||
}
|
||||
@@ -42,7 +46,7 @@ export class ServerCollection extends ClassCollection<Server, HydratedServer> {
|
||||
* @param data Data
|
||||
* @param isNew Whether this object is new
|
||||
*/
|
||||
getOrCreate(id: string, data: API.Server, isNew = false) {
|
||||
getOrCreate(id: string, data: APIServer, isNew = false): Server {
|
||||
if (this.has(id) && !this.isPartial(id)) {
|
||||
return this.get(id)!;
|
||||
} else {
|
||||
@@ -57,7 +61,7 @@ export class ServerCollection extends ClassCollection<Server, HydratedServer> {
|
||||
* Get or return partial
|
||||
* @param id Id
|
||||
*/
|
||||
getOrPartial(id: string) {
|
||||
getOrPartial(id: string): Server | undefined {
|
||||
if (this.has(id)) {
|
||||
return this.get(id)!;
|
||||
} else if (this.client.options.partials) {
|
||||
@@ -75,7 +79,7 @@ export class ServerCollection extends ClassCollection<Server, HydratedServer> {
|
||||
* @param data Server options
|
||||
* @returns The newly-created server
|
||||
*/
|
||||
async createServer(data: DataCreateServer) {
|
||||
async createServer(data: DataCreateServer): Promise<Server> {
|
||||
const { server, channels } = await this.client.api.post(
|
||||
`/servers/create`,
|
||||
data
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
import { HydratedServerMember } from "../hydration/index.js";
|
||||
import { API, ServerMember } from "../index.js";
|
||||
import type { Member, MemberCompositeKey } from "revolt-api";
|
||||
|
||||
import { ClassCollection } from "./index.js";
|
||||
import { ServerMember } from "../classes/ServerMember.js";
|
||||
import type { HydratedServerMember } from "../hydration/serverMember.js";
|
||||
|
||||
import { ClassCollection } from "./Collection.js";
|
||||
|
||||
/**
|
||||
* Collection of Server Members
|
||||
@@ -15,7 +17,7 @@ export class ServerMemberCollection extends ClassCollection<
|
||||
* @param id Id
|
||||
* @returns Whether it exists
|
||||
*/
|
||||
hasByKey(id: API.MemberCompositeKey) {
|
||||
hasByKey(id: MemberCompositeKey): boolean {
|
||||
return super.has(id.server + id.user);
|
||||
}
|
||||
|
||||
@@ -24,7 +26,7 @@ export class ServerMemberCollection extends ClassCollection<
|
||||
* @param id Id
|
||||
* @returns Member
|
||||
*/
|
||||
getByKey(id: API.MemberCompositeKey) {
|
||||
getByKey(id: MemberCompositeKey): ServerMember | undefined {
|
||||
return super.get(id.server + id.user);
|
||||
}
|
||||
|
||||
@@ -33,7 +35,7 @@ export class ServerMemberCollection extends ClassCollection<
|
||||
* @param id Id
|
||||
* @returns Member
|
||||
*/
|
||||
isPartialByKey(id: API.MemberCompositeKey) {
|
||||
isPartialByKey(id: MemberCompositeKey): boolean {
|
||||
return super.isPartial(id.server + id.user);
|
||||
}
|
||||
|
||||
@@ -53,7 +55,7 @@ export class ServerMemberCollection extends ClassCollection<
|
||||
roles: false,
|
||||
}
|
||||
// TODO: fix typings in revolt-api
|
||||
)) as API.Member;
|
||||
)) as Member;
|
||||
|
||||
return this.getOrCreate(data._id, data);
|
||||
}
|
||||
@@ -63,7 +65,7 @@ export class ServerMemberCollection extends ClassCollection<
|
||||
* @param id Id
|
||||
* @param data Data
|
||||
*/
|
||||
getOrCreate(id: API.MemberCompositeKey, data: API.Member) {
|
||||
getOrCreate(id: MemberCompositeKey, data: Member): ServerMember {
|
||||
if (this.hasByKey(id) && !this.isPartialByKey(id)) {
|
||||
return this.getByKey(id)!;
|
||||
} else {
|
||||
@@ -83,7 +85,7 @@ export class ServerMemberCollection extends ClassCollection<
|
||||
* Get or return partial
|
||||
* @param id Id
|
||||
*/
|
||||
getOrPartial(id: API.MemberCompositeKey) {
|
||||
getOrPartial(id: MemberCompositeKey): ServerMember | undefined {
|
||||
if (this.hasByKey(id)) {
|
||||
return this.getByKey(id)!;
|
||||
} else if (this.client.options.partials) {
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
import { batch } from "solid-js";
|
||||
|
||||
import { Session } from "../classes/index.js";
|
||||
import { HydratedSession } from "../hydration/session.js";
|
||||
import { API } from "../index.js";
|
||||
import type { SessionInfo } from "revolt-api";
|
||||
|
||||
import { ClassCollection } from "./index.js";
|
||||
import { Session } from "../classes/Session.js";
|
||||
import type { HydratedSession } from "../hydration/session.js";
|
||||
|
||||
import { ClassCollection } from "./Collection.js";
|
||||
|
||||
/**
|
||||
* Collection of Sessions
|
||||
@@ -28,7 +29,7 @@ export class SessionCollection extends ClassCollection<
|
||||
* Delete all sessions, optionally including self
|
||||
* @param revokeSelf Whether to remove current session too
|
||||
*/
|
||||
async deleteAll(revokeSelf = false) {
|
||||
async deleteAll(revokeSelf = false): Promise<void> {
|
||||
await this.client.api.delete("/auth/session/all", {
|
||||
revoke_self: revokeSelf,
|
||||
});
|
||||
@@ -45,7 +46,7 @@ export class SessionCollection extends ClassCollection<
|
||||
* @param data Data
|
||||
* @returns Session
|
||||
*/
|
||||
getOrCreate(id: string, data: API.SessionInfo) {
|
||||
getOrCreate(id: string, data: SessionInfo): Session {
|
||||
if (this.has(id)) {
|
||||
return this.get(id)!;
|
||||
} else {
|
||||
|
||||
@@ -1,7 +1,10 @@
|
||||
import { HydratedUser } from "../hydration/index.js";
|
||||
import { API, Client, User } from "../index.js";
|
||||
import type { User as APIUser } from "revolt-api";
|
||||
|
||||
import { ClassCollection } from "./index.js";
|
||||
import type { Client } from "../Client.js";
|
||||
import { User } from "../classes/User.js";
|
||||
import type { HydratedUser } from "../hydration/user.js";
|
||||
|
||||
import { ClassCollection } from "./Collection.js";
|
||||
|
||||
/**
|
||||
* Collection of Users
|
||||
@@ -41,7 +44,7 @@ export class UserCollection extends ClassCollection<User, HydratedUser> {
|
||||
* @param data Data
|
||||
* @param isNew Whether this object is new
|
||||
*/
|
||||
getOrCreate(id: string, data: API.User) {
|
||||
getOrCreate(id: string, data: APIUser): User {
|
||||
if (this.has(id) && !this.isPartial(id)) {
|
||||
return this.get(id)!;
|
||||
} else {
|
||||
@@ -55,7 +58,7 @@ export class UserCollection extends ClassCollection<User, HydratedUser> {
|
||||
* Get or return partial
|
||||
* @param id Id
|
||||
*/
|
||||
getOrPartial(id: string) {
|
||||
getOrPartial(id: string): User | undefined {
|
||||
if (this.has(id)) {
|
||||
return this.get(id)!;
|
||||
} else if (this.client.options.partials) {
|
||||
|
||||
@@ -1,10 +1,28 @@
|
||||
import { Accessor, Setter, createSignal } from "solid-js";
|
||||
import type { Accessor, Setter } from "solid-js";
|
||||
import { createSignal } from "solid-js";
|
||||
|
||||
import EventEmitter from "eventemitter3";
|
||||
import WebSocket from "isomorphic-ws";
|
||||
import { Error } from "revolt-api";
|
||||
import type { Error } from "revolt-api";
|
||||
|
||||
import type { AvailableProtocols, EventProtocol } from "./index.js";
|
||||
import type { ProtocolV1 } from "./v1.js";
|
||||
|
||||
/**
|
||||
* Available protocols to connect with
|
||||
*/
|
||||
export type AvailableProtocols = 1;
|
||||
|
||||
/**
|
||||
* Protocol mapping
|
||||
*/
|
||||
type Protocols = {
|
||||
1: ProtocolV1;
|
||||
};
|
||||
|
||||
/**
|
||||
* Select a protocol by its key
|
||||
*/
|
||||
export type EventProtocol<T extends AvailableProtocols> = Protocols[T];
|
||||
|
||||
/**
|
||||
* All possible event client states.
|
||||
@@ -118,7 +136,7 @@ export class EventClient<T extends AvailableProtocols> extends EventEmitter<
|
||||
* Set the current state
|
||||
* @param state state
|
||||
*/
|
||||
private setState(state: ConnectionState) {
|
||||
private setState(state: ConnectionState): void {
|
||||
this.#setStateSetter(state);
|
||||
this.emit("state", state);
|
||||
}
|
||||
@@ -128,7 +146,7 @@ export class EventClient<T extends AvailableProtocols> extends EventEmitter<
|
||||
* @param uri WebSocket URI
|
||||
* @param token Authentication token
|
||||
*/
|
||||
connect(uri: string, token: string) {
|
||||
connect(uri: string, token: string): void {
|
||||
this.disconnect();
|
||||
this.#lastError = undefined;
|
||||
this.setState(ConnectionState.Connecting);
|
||||
@@ -182,7 +200,7 @@ export class EventClient<T extends AvailableProtocols> extends EventEmitter<
|
||||
/**
|
||||
* Disconnect the websocket client.
|
||||
*/
|
||||
disconnect() {
|
||||
disconnect(): void {
|
||||
if (!this.#socket) return;
|
||||
clearInterval(this.#heartbeatIntervalReference);
|
||||
clearInterval(this.#connectTimeoutReference);
|
||||
@@ -196,7 +214,7 @@ export class EventClient<T extends AvailableProtocols> extends EventEmitter<
|
||||
* Send an event to the server.
|
||||
* @param event Event
|
||||
*/
|
||||
send(event: EventProtocol<T>["client"]) {
|
||||
send(event: EventProtocol<T>["client"]): void {
|
||||
this.options.debug && console.debug("[C->S]", event);
|
||||
if (!this.#socket) throw "Socket closed, trying to send.";
|
||||
this.#socket.send(JSON.stringify(event));
|
||||
@@ -206,7 +224,7 @@ export class EventClient<T extends AvailableProtocols> extends EventEmitter<
|
||||
* Handle events intended for client before passing them along.
|
||||
* @param event Event
|
||||
*/
|
||||
handle(event: EventProtocol<T>["server"]) {
|
||||
handle(event: EventProtocol<T>["server"]): void {
|
||||
this.options.debug && console.debug("[S->C]", event);
|
||||
switch (event.type) {
|
||||
case "Ping":
|
||||
@@ -258,7 +276,17 @@ export class EventClient<T extends AvailableProtocols> extends EventEmitter<
|
||||
/**
|
||||
* Last error encountered by events client
|
||||
*/
|
||||
get lastError() {
|
||||
get lastError():
|
||||
| {
|
||||
type: "socket";
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
data: any;
|
||||
}
|
||||
| {
|
||||
type: "revolt";
|
||||
data: Error;
|
||||
}
|
||||
| undefined {
|
||||
return this.#lastError;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,22 +0,0 @@
|
||||
import type { ProtocolV1 } from "./v1.js";
|
||||
|
||||
export { handleEvent as handleEventV1 } from "./v1.js";
|
||||
|
||||
export * from "./EventClient.js";
|
||||
|
||||
/**
|
||||
* Available protocols to connect with
|
||||
*/
|
||||
export type AvailableProtocols = 1;
|
||||
|
||||
/**
|
||||
* Protocol mapping
|
||||
*/
|
||||
type Protocols = {
|
||||
1: ProtocolV1;
|
||||
};
|
||||
|
||||
/**
|
||||
* Select a protocol by its key
|
||||
*/
|
||||
export type EventProtocol<T extends AvailableProtocols> = Protocols[T];
|
||||
+5
-3
@@ -1,4 +1,5 @@
|
||||
import { Setter, batch } from "solid-js";
|
||||
import type { Setter } from "solid-js";
|
||||
import { batch } from "solid-js";
|
||||
|
||||
import { ReactiveSet } from "@solid-primitives/set";
|
||||
import type {
|
||||
@@ -18,8 +19,9 @@ import type {
|
||||
User,
|
||||
} from "revolt-api";
|
||||
|
||||
import type { Client } from "../Client.js";
|
||||
import { MessageEmbed } from "../classes/MessageEmbed.js";
|
||||
import { hydrate } from "../hydration/index.js";
|
||||
import { Client, MessageEmbed } from "../index.js";
|
||||
|
||||
/**
|
||||
* Version 1 of the events protocol
|
||||
@@ -189,7 +191,7 @@ export async function handleEvent(
|
||||
client: Client,
|
||||
event: ServerMessage,
|
||||
setReady: Setter<boolean>
|
||||
) {
|
||||
): Promise<void> {
|
||||
if (client.options.debug) {
|
||||
console.debug("[S->C]", event);
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { Bot as ApiBot } from "revolt-api";
|
||||
import type { Bot as APIBot } from "revolt-api";
|
||||
|
||||
import { Hydrate } from "./index.js";
|
||||
import type { Hydrate } from "./index.js";
|
||||
|
||||
export type HydratedBot = {
|
||||
id: string;
|
||||
@@ -15,7 +15,7 @@ export type HydratedBot = {
|
||||
flags: BotFlags;
|
||||
};
|
||||
|
||||
export const botHydration: Hydrate<ApiBot, HydratedBot> = {
|
||||
export const botHydration: Hydrate<APIBot, HydratedBot> = {
|
||||
keyMapping: {
|
||||
_id: "id",
|
||||
owner: "ownerId",
|
||||
|
||||
@@ -1,14 +1,15 @@
|
||||
import { ReactiveSet } from "@solid-primitives/set";
|
||||
import { Channel as ApiChannel, OverrideField } from "revolt-api";
|
||||
import type { Channel as APIChannel, OverrideField } from "revolt-api";
|
||||
|
||||
import { Client, File } from "../index.js";
|
||||
import type { Client } from "../Client.js";
|
||||
import { File } from "../classes/File.js";
|
||||
import type { Merge } from "../lib/merge.js";
|
||||
|
||||
import { Hydrate } from "./index.js";
|
||||
import type { Hydrate } from "./index.js";
|
||||
|
||||
export type HydratedChannel = {
|
||||
id: string;
|
||||
channelType: ApiChannel["channel_type"];
|
||||
channelType: APIChannel["channel_type"];
|
||||
|
||||
name: string;
|
||||
description?: string;
|
||||
@@ -30,7 +31,7 @@ export type HydratedChannel = {
|
||||
lastMessageId?: string;
|
||||
};
|
||||
|
||||
export const channelHydration: Hydrate<Merge<ApiChannel>, HydratedChannel> = {
|
||||
export const channelHydration: Hydrate<Merge<APIChannel>, HydratedChannel> = {
|
||||
keyMapping: {
|
||||
_id: "id",
|
||||
channel_type: "channelType",
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import { ReactiveSet } from "@solid-primitives/set";
|
||||
import type { ChannelUnread } from "revolt-api";
|
||||
|
||||
import { API } from "../index.js";
|
||||
import type { Merge } from "../lib/merge.js";
|
||||
|
||||
import { Hydrate } from "./index.js";
|
||||
import type { Hydrate } from "./index.js";
|
||||
|
||||
export type HydratedChannelUnread = {
|
||||
id: string;
|
||||
@@ -12,7 +12,7 @@ export type HydratedChannelUnread = {
|
||||
};
|
||||
|
||||
export const channelUnreadHydration: Hydrate<
|
||||
Merge<API.ChannelUnread>,
|
||||
Merge<ChannelUnread>,
|
||||
HydratedChannelUnread
|
||||
> = {
|
||||
keyMapping: {
|
||||
|
||||
@@ -1,7 +1,10 @@
|
||||
import { API, Client, File } from "../index.js";
|
||||
import type { Webhook } from "revolt-api";
|
||||
|
||||
import type { Client } from "../Client.js";
|
||||
import { File } from "../classes/File.js";
|
||||
import type { Merge } from "../lib/merge.js";
|
||||
|
||||
import { Hydrate } from "./index.js";
|
||||
import type { Hydrate } from "./index.js";
|
||||
|
||||
export type HydratedChannelWebhook = {
|
||||
id: string;
|
||||
@@ -12,7 +15,7 @@ export type HydratedChannelWebhook = {
|
||||
};
|
||||
|
||||
export const channelWebhookHydration: Hydrate<
|
||||
Merge<API.Webhook>,
|
||||
Merge<Webhook>,
|
||||
HydratedChannelWebhook
|
||||
> = {
|
||||
keyMapping: {
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { Emoji as ApiEmoji, EmojiParent } from "revolt-api";
|
||||
import type { Emoji as APIEmoji, EmojiParent } from "revolt-api";
|
||||
|
||||
import type { Merge } from "../lib/merge.js";
|
||||
|
||||
import { Hydrate } from "./index.js";
|
||||
import type { Hydrate } from "./index.js";
|
||||
|
||||
export type HydratedEmoji = {
|
||||
id: string;
|
||||
@@ -13,7 +13,7 @@ export type HydratedEmoji = {
|
||||
nsfw: boolean;
|
||||
};
|
||||
|
||||
export const emojiHydration: Hydrate<Merge<ApiEmoji>, HydratedEmoji> = {
|
||||
export const emojiHydration: Hydrate<Merge<APIEmoji>, HydratedEmoji> = {
|
||||
keyMapping: {
|
||||
_id: "id",
|
||||
creator_id: "creatorId",
|
||||
|
||||
+1
-16
@@ -9,21 +9,6 @@ import { serverMemberHydration } from "./serverMember.js";
|
||||
import { sessionHydration } from "./session.js";
|
||||
import { userHydration } from "./user.js";
|
||||
|
||||
export { BotFlags } from "./bot.js";
|
||||
export { ServerFlags } from "./server.js";
|
||||
export { UserBadges, UserFlags } from "./user.js";
|
||||
|
||||
export type { HydratedBot } from "./bot.js";
|
||||
export type { HydratedChannel } from "./channel.js";
|
||||
export type { HydratedChannelUnread } from "./channelUnread.js";
|
||||
export type { HydratedChannelWebhook } from "./channelWebhook.js";
|
||||
export type { HydratedEmoji } from "./emoji.js";
|
||||
export type { HydratedMessage } from "./message.js";
|
||||
export type { HydratedServer } from "./server.js";
|
||||
export type { HydratedServerMember } from "./serverMember.js";
|
||||
export type { HydratedSession } from "./session.js";
|
||||
export type { HydratedUser } from "./user.js";
|
||||
|
||||
/**
|
||||
* Functions to map from one object to another
|
||||
*/
|
||||
@@ -113,7 +98,7 @@ export function hydrate<T extends keyof Hydrators>(
|
||||
input: Partial<ExtractInput<Hydrators[T]>>,
|
||||
context: unknown,
|
||||
initial?: boolean
|
||||
) {
|
||||
): ExtractOutput<Hydrators[T]> {
|
||||
return hydrateInternal(
|
||||
hydrators[type] as never,
|
||||
initial ? { ...hydrators[type].initialHydration(), ...input } : input,
|
||||
|
||||
+10
-12
@@ -1,17 +1,15 @@
|
||||
import { ReactiveMap } from "@solid-primitives/map";
|
||||
import { ReactiveSet } from "@solid-primitives/set";
|
||||
import type { Interactions, Masquerade, Message } from "revolt-api";
|
||||
|
||||
import {
|
||||
API,
|
||||
Client,
|
||||
File,
|
||||
MessageEmbed,
|
||||
MessageWebhook,
|
||||
SystemMessage,
|
||||
} from "../index.js";
|
||||
import type { Client } from "../Client.js";
|
||||
import { File } from "../classes/File.js";
|
||||
import { MessageWebhook } from "../classes/Message.js";
|
||||
import { MessageEmbed } from "../classes/MessageEmbed.js";
|
||||
import { SystemMessage } from "../classes/SystemMessage.js";
|
||||
import type { Merge } from "../lib/merge.js";
|
||||
|
||||
import { Hydrate } from "./index.js";
|
||||
import type { Hydrate } from "./index.js";
|
||||
|
||||
export type HydratedMessage = {
|
||||
id: string;
|
||||
@@ -27,12 +25,12 @@ export type HydratedMessage = {
|
||||
mentionIds?: string[];
|
||||
replyIds?: string[];
|
||||
reactions: ReactiveMap<string, ReactiveSet<string>>;
|
||||
interactions?: API.Interactions;
|
||||
masquerade?: API.Masquerade;
|
||||
interactions?: Interactions;
|
||||
masquerade?: Masquerade;
|
||||
flags?: number;
|
||||
};
|
||||
|
||||
export const messageHydration: Hydrate<Merge<API.Message>, HydratedMessage> = {
|
||||
export const messageHydration: Hydrate<Merge<Message>, HydratedMessage> = {
|
||||
keyMapping: {
|
||||
_id: "id",
|
||||
channel: "channelId",
|
||||
|
||||
@@ -1,15 +1,16 @@
|
||||
import { ReactiveMap } from "@solid-primitives/map";
|
||||
import { ReactiveSet } from "@solid-primitives/set";
|
||||
import {
|
||||
Server as ApiServer,
|
||||
import type {
|
||||
Server as APIServer,
|
||||
Category,
|
||||
Role,
|
||||
SystemMessageChannels,
|
||||
} from "revolt-api";
|
||||
|
||||
import { Client, File } from "../index.js";
|
||||
import type { Client } from "../Client.js";
|
||||
import { File } from "../classes/File.js";
|
||||
|
||||
import { Hydrate } from "./index.js";
|
||||
import type { Hydrate } from "./index.js";
|
||||
|
||||
export type HydratedServer = {
|
||||
id: string;
|
||||
@@ -34,7 +35,7 @@ export type HydratedServer = {
|
||||
nsfw: boolean;
|
||||
};
|
||||
|
||||
export const serverHydration: Hydrate<ApiServer, HydratedServer> = {
|
||||
export const serverHydration: Hydrate<APIServer, HydratedServer> = {
|
||||
keyMapping: {
|
||||
_id: "id",
|
||||
owner: "ownerId",
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
import { Member as ApiMember, MemberCompositeKey } from "revolt-api";
|
||||
import type { Member as APIMember, MemberCompositeKey } from "revolt-api";
|
||||
|
||||
import { Client, File } from "../index.js";
|
||||
import type { Client } from "../Client.js";
|
||||
import { File } from "../classes/File.js";
|
||||
import type { Merge } from "../lib/merge.js";
|
||||
|
||||
import { Hydrate } from "./index.js";
|
||||
import type { Hydrate } from "./index.js";
|
||||
|
||||
export type HydratedServerMember = {
|
||||
id: MemberCompositeKey;
|
||||
@@ -15,7 +16,7 @@ export type HydratedServerMember = {
|
||||
};
|
||||
|
||||
export const serverMemberHydration: Hydrate<
|
||||
Merge<ApiMember>,
|
||||
Merge<APIMember>,
|
||||
HydratedServerMember
|
||||
> = {
|
||||
keyMapping: {
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
import { SessionInfo as ApiSession } from "revolt-api";
|
||||
import type { SessionInfo as APISession } from "revolt-api";
|
||||
|
||||
import { Hydrate } from "./index.js";
|
||||
import type { Hydrate } from "./index.js";
|
||||
|
||||
export type HydratedSession = {
|
||||
id: string;
|
||||
name: string;
|
||||
};
|
||||
|
||||
export const sessionHydration: Hydrate<ApiSession, HydratedSession> = {
|
||||
export const sessionHydration: Hydrate<APISession, HydratedSession> = {
|
||||
keyMapping: {
|
||||
_id: "id",
|
||||
},
|
||||
|
||||
@@ -1,13 +1,14 @@
|
||||
import {
|
||||
User as ApiUser,
|
||||
import type {
|
||||
User as APIUser,
|
||||
BotInformation,
|
||||
RelationshipStatus,
|
||||
UserStatus,
|
||||
} from "revolt-api";
|
||||
|
||||
import { Client, File } from "../index.js";
|
||||
import type { Client } from "../Client.js";
|
||||
import { File } from "../classes/File.js";
|
||||
|
||||
import { Hydrate } from "./index.js";
|
||||
import type { Hydrate } from "./index.js";
|
||||
|
||||
export type HydratedUser = {
|
||||
id: string;
|
||||
@@ -28,7 +29,7 @@ export type HydratedUser = {
|
||||
bot?: BotInformation;
|
||||
};
|
||||
|
||||
export const userHydration: Hydrate<ApiUser, HydratedUser> = {
|
||||
export const userHydration: Hydrate<APIUser, HydratedUser> = {
|
||||
keyMapping: {
|
||||
_id: "id",
|
||||
display_name: "displayName",
|
||||
|
||||
+4
-7
@@ -3,11 +3,8 @@ export { Client } from "./Client.js";
|
||||
export type { ClientOptions, Session as PrivateSession } from "./Client.js";
|
||||
export * from "./classes/index.js";
|
||||
export * from "./collections/index.js";
|
||||
export { ConnectionState, EventClient } from "./events/index.js";
|
||||
export {
|
||||
BotFlags,
|
||||
ServerFlags,
|
||||
UserBadges,
|
||||
UserFlags,
|
||||
} from "./hydration/index.js";
|
||||
export { ConnectionState, EventClient } from "./events/EventClient.js";
|
||||
export { BotFlags } from "./hydration/bot.js";
|
||||
export { ServerFlags } from "./hydration/server.js";
|
||||
export { UserBadges, UserFlags } from "./hydration/user.js";
|
||||
export * from "./lib/regex.js";
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
import Long from "long";
|
||||
|
||||
import { Channel, Client, Server, ServerMember } from "../index.js";
|
||||
import type { Client } from "../Client.js";
|
||||
import type { Channel } from "../classes/Channel.js";
|
||||
import { Server } from "../classes/Server.js";
|
||||
import type { ServerMember } from "../classes/ServerMember.js";
|
||||
|
||||
import {
|
||||
ALLOW_IN_TIMEOUT,
|
||||
@@ -15,7 +18,7 @@ import {
|
||||
* @param a Input A
|
||||
* @param b Inputs (OR'd together)
|
||||
*/
|
||||
export function bitwiseAndEq(a: number, ...b: number[]) {
|
||||
export function bitwiseAndEq(a: number, ...b: number[]): boolean {
|
||||
const value = b.reduce((prev, cur) => prev.or(cur), Long.fromNumber(0));
|
||||
return value.and(a).eq(value);
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { SetStoreFunction, createStore } from "solid-js/store";
|
||||
import type { SetStoreFunction } from "solid-js/store";
|
||||
import { createStore } from "solid-js/store";
|
||||
|
||||
import { Hydrators, hydrate } from "../hydration/index.js";
|
||||
import { type Hydrators, hydrate } from "../hydration/index.js";
|
||||
|
||||
/**
|
||||
* Wrapper around Solid.js store
|
||||
@@ -24,7 +25,7 @@ export class ObjectStorage<T> {
|
||||
* @param id ID
|
||||
* @returns Object
|
||||
*/
|
||||
get(id: string) {
|
||||
get(id: string): T | undefined {
|
||||
return this.store[id];
|
||||
}
|
||||
|
||||
@@ -35,7 +36,12 @@ export class ObjectStorage<T> {
|
||||
* @param context Context
|
||||
* @param data Input Data
|
||||
*/
|
||||
hydrate(id: string, type: keyof Hydrators, context: unknown, data?: unknown) {
|
||||
hydrate(
|
||||
id: string,
|
||||
type: keyof Hydrators,
|
||||
context: unknown,
|
||||
data?: unknown
|
||||
): void {
|
||||
if (data) {
|
||||
data = { partial: false, ...data };
|
||||
this.set(id, hydrate(type, data as never, context, true) as T);
|
||||
|
||||
Reference in New Issue
Block a user