mirror of
https://github.com/stoatchat/javascript-client-sdk.git
synced 2026-07-19 17:13:31 -04:00
merge: pull request #44 from revoltchat/quark/permissions
This commit is contained in:
@@ -7,7 +7,7 @@
|
||||
## Example Usage (Javascript / ES6)
|
||||
|
||||
```javascript
|
||||
import { Client } from "revolt.js";
|
||||
import { Client } from "revolt-api";
|
||||
|
||||
let client = new Client();
|
||||
|
||||
@@ -31,7 +31,7 @@ For example, `node --experimental-specifier-resolution=node index.js`.
|
||||
## Example Usage (Typescript)
|
||||
|
||||
```typescript
|
||||
import { Client } from "revolt.js";
|
||||
import { Client } from "revolt-api";
|
||||
|
||||
let client = new Client();
|
||||
|
||||
@@ -63,3 +63,7 @@ client.once('ready', () => {
|
||||
});
|
||||
});
|
||||
```
|
||||
|
||||
## Revolt API Types
|
||||
|
||||
All `revolt-api` types are re-exported from this library.
|
||||
|
||||
+3
-2
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"type": "module",
|
||||
"name": "revolt.js",
|
||||
"version": "5.2.8",
|
||||
"version": "6.0.0-rc.0",
|
||||
"main": "dist/index.js",
|
||||
"repository": "https://github.com/revoltchat/revolt.js",
|
||||
"author": "Paul Makles <insrt.uk>",
|
||||
@@ -14,8 +14,9 @@
|
||||
"lodash.defaultsdeep": "^4.6.1",
|
||||
"lodash.flatten": "^4.4.0",
|
||||
"lodash.isequal": "^4.5.0",
|
||||
"long": "^5.2.0",
|
||||
"mobx": "^6.3.2",
|
||||
"revolt-api": "0.5.3-alpha.12",
|
||||
"revolt-api": "0.5.3-rc.7",
|
||||
"ulid": "^2.3.0",
|
||||
"ws": "^8.2.2"
|
||||
},
|
||||
|
||||
+61
-128
@@ -1,13 +1,9 @@
|
||||
import Axios, { AxiosInstance, AxiosRequestConfig } from "axios";
|
||||
import EventEmitter from "eventemitter3";
|
||||
import defaultsDeep from "lodash.defaultsdeep";
|
||||
import { action, makeObservable, observable } from "mobx";
|
||||
import type { Session } from "revolt-api/types/Auth";
|
||||
import type { Attachment, AttachmentMetadata, SizeOptions } from "revolt-api/types/Autumn";
|
||||
import type { RevoltConfiguration } from "revolt-api/types/Core";
|
||||
import { MemberCompositeKey, Role } from "revolt-api/types/Servers";
|
||||
|
||||
import { Route, RoutePath, RouteMethod } from "./api/routes";
|
||||
import type { DataCreateAccount, DataLogin, DataOnboard, Session } from "revolt-api";
|
||||
import type { RevoltConfig, Metadata } from "revolt-api";
|
||||
import { API, MemberCompositeKey, Role } from "revolt-api";
|
||||
|
||||
import Bots from "./maps/Bots";
|
||||
import Channels, { Channel } from "./maps/Channels";
|
||||
@@ -66,14 +62,14 @@ export declare interface Client {
|
||||
|
||||
on(event: "message", listener: (message: Message) => void): this;
|
||||
on(event: "message/update", listener: (message: Message) => void): this;
|
||||
on(event: "message/delete", listener: (id: string) => void): this;
|
||||
on(event: "message/delete", listener: (id: string, message?: Message) => void): this;
|
||||
|
||||
on(event: "channel/create", listener: (channel: Channel) => void): this;
|
||||
on(event: "channel/update", listener: (channel: Channel) => void): this;
|
||||
on(event: "channel/delete", listener: (id: string) => void): this;
|
||||
on(event: "channel/delete", listener: (id: string, channel?: Channel) => void): this;
|
||||
|
||||
on(event: "server/update", listener: (server: Server) => void): this;
|
||||
on(event: "server/delete", listener: (id: string) => void): this;
|
||||
on(event: "server/delete", listener: (id: string, server?: Server) => void): this;
|
||||
|
||||
on(
|
||||
event: "role/update",
|
||||
@@ -102,7 +98,12 @@ export const RE_MENTIONS = /<@([A-z0-9]{26})>/g;
|
||||
export const RE_SPOILER = /!!.+!!/g;
|
||||
|
||||
export type FileArgs = [
|
||||
options?: SizeOptions,
|
||||
options?: {
|
||||
max_side?: number,
|
||||
size?: number,
|
||||
width?: number,
|
||||
height?: number
|
||||
},
|
||||
allowAnimation?: boolean,
|
||||
fallback?: string,
|
||||
];
|
||||
@@ -110,13 +111,13 @@ export type FileArgs = [
|
||||
export class Client extends EventEmitter {
|
||||
heartbeat: number;
|
||||
|
||||
api: API;
|
||||
session?: Session | string;
|
||||
user: Nullable<User> = null;
|
||||
|
||||
options: ClientOptions;
|
||||
websocket: WebSocketClient;
|
||||
private Axios: AxiosInstance;
|
||||
configuration?: RevoltConfiguration;
|
||||
configuration?: RevoltConfig;
|
||||
|
||||
users: Users;
|
||||
channels: Channels;
|
||||
@@ -160,103 +161,36 @@ export class Client extends EventEmitter {
|
||||
this.unreads = new Unreads(this);
|
||||
}
|
||||
|
||||
this.Axios = Axios.create({ baseURL: this.apiURL });
|
||||
this.api = new API({ baseURL: this.apiURL });
|
||||
this.websocket = new WebSocketClient(this);
|
||||
this.heartbeat = this.options.heartbeat;
|
||||
|
||||
if (options.debug) {
|
||||
this.Axios.interceptors.request.use((request) => {
|
||||
console.debug(
|
||||
"[<]",
|
||||
request.method?.toUpperCase(),
|
||||
request.url,
|
||||
);
|
||||
return request;
|
||||
});
|
||||
|
||||
this.Axios.interceptors.response.use((response) => {
|
||||
console.debug(
|
||||
"[>] (" + response.status + ":",
|
||||
response.statusText + ")",
|
||||
JSON.stringify(response.data),
|
||||
);
|
||||
return response;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* ? Configuration.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Get the current API base URL.
|
||||
*/
|
||||
get apiURL() {
|
||||
return this.options.apiURL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether debug mode is turned on.
|
||||
*/
|
||||
get debug() {
|
||||
return this.options.debug;
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether revolt.js should auto-reconnect
|
||||
*/
|
||||
get autoReconnect() {
|
||||
return this.options.autoReconnect;
|
||||
}
|
||||
|
||||
/**
|
||||
* ? Axios request wrapper.
|
||||
*/
|
||||
|
||||
req<M extends RouteMethod, T extends RoutePath>(
|
||||
method: M,
|
||||
url: T,
|
||||
): Promise<Route<M, T>["response"]>;
|
||||
req<M extends RouteMethod, T extends RoutePath>(
|
||||
method: M,
|
||||
url: T,
|
||||
data: Route<M, T>["data"],
|
||||
): Promise<Route<M, T>["response"]>;
|
||||
|
||||
/**
|
||||
* Perform an HTTP request using Axios, specifying a route data object.
|
||||
* @param method HTTP method
|
||||
* @param url Target route
|
||||
* @param data Route data object
|
||||
* @returns The response body
|
||||
*/
|
||||
async req<M extends RouteMethod, T extends RoutePath>(
|
||||
method: M,
|
||||
url: T,
|
||||
data?: Route<M, T>["data"],
|
||||
): Promise<Route<M, T>["response"]> {
|
||||
const res = await this.Axios.request({
|
||||
method,
|
||||
data,
|
||||
url,
|
||||
});
|
||||
|
||||
return res.data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform an HTTP request using Axios, specifying a request config.
|
||||
* @param method HTTP method
|
||||
* @param url Target route
|
||||
* @param data Axios request config object
|
||||
* @returns The response body
|
||||
*/
|
||||
async request<M extends RouteMethod, T extends RoutePath>(
|
||||
method: M,
|
||||
url: T,
|
||||
data: AxiosRequestConfig,
|
||||
): Promise<Route<M, T>["response"]> {
|
||||
const res = await this.Axios.request({
|
||||
...data,
|
||||
method,
|
||||
url,
|
||||
});
|
||||
|
||||
return res.data;
|
||||
}
|
||||
|
||||
/**
|
||||
* ? Authentication and connection.
|
||||
*/
|
||||
@@ -269,7 +203,7 @@ export class Client extends EventEmitter {
|
||||
* configuration if it has already been fetched before.
|
||||
*/
|
||||
async connect() {
|
||||
this.configuration = await this.req("GET", "/");
|
||||
this.configuration = await this.api.get("/");
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -279,22 +213,16 @@ export class Client extends EventEmitter {
|
||||
if (!this.configuration) await this.connect();
|
||||
}
|
||||
|
||||
private $generateHeaders(
|
||||
session: Session | string | undefined = this.session,
|
||||
) {
|
||||
if (typeof session === "string") {
|
||||
return {
|
||||
"x-bot-token": session,
|
||||
};
|
||||
} else {
|
||||
return {
|
||||
"x-session-token": session?.token,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Update API object to use authentication.
|
||||
*/
|
||||
private $updateHeaders() {
|
||||
this.Axios.defaults.headers = this.$generateHeaders();
|
||||
this.api = new API({
|
||||
baseURL: this.apiURL,
|
||||
authentication: {
|
||||
revolt: this.session
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -302,11 +230,15 @@ export class Client extends EventEmitter {
|
||||
* @param details Login data object
|
||||
* @returns An onboarding function if onboarding is required, undefined otherwise
|
||||
*/
|
||||
async login(details: Route<"POST", "/auth/session/login">["data"]) {
|
||||
async login(details: DataLogin) {
|
||||
await this.fetchConfiguration();
|
||||
this.session = await this.req("POST", "/auth/session/login", details);
|
||||
|
||||
return await this.$connect();
|
||||
const data = await this.api.post("/auth/session/login", details);
|
||||
if (data.result === 'Success') {
|
||||
this.session = data;
|
||||
return await this.$connect();
|
||||
} else {
|
||||
throw "MFA not implemented!";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -337,7 +269,7 @@ export class Client extends EventEmitter {
|
||||
*/
|
||||
private async $connect() {
|
||||
this.$updateHeaders();
|
||||
const { onboarding } = await this.req("GET", "/onboard/hello");
|
||||
const { onboarding } = await this.api.get("/onboard/hello");
|
||||
if (onboarding) {
|
||||
return (username: string, loginAfterSuccess?: boolean) =>
|
||||
this.completeOnboarding({ username }, loginAfterSuccess);
|
||||
@@ -352,10 +284,10 @@ export class Client extends EventEmitter {
|
||||
* @param loginAfterSuccess Defines whether to automatically log in and connect after onboarding finishes
|
||||
*/
|
||||
async completeOnboarding(
|
||||
data: Route<"POST", "/onboard/complete">["data"],
|
||||
data: DataOnboard,
|
||||
loginAfterSuccess?: boolean,
|
||||
) {
|
||||
await this.req("POST", "/onboard/complete", data);
|
||||
await this.api.post("/onboard/complete", data);
|
||||
if (loginAfterSuccess) {
|
||||
await this.websocket.connect();
|
||||
}
|
||||
@@ -371,7 +303,7 @@ export class Client extends EventEmitter {
|
||||
* @returns Invite information.
|
||||
*/
|
||||
async fetchInvite(code: string) {
|
||||
return await this.req("GET", `/invites/${code}` as "/invites/id");
|
||||
return await this.api.get(`/invites/${code}`);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -380,7 +312,7 @@ export class Client extends EventEmitter {
|
||||
* @returns Data provided by invite.
|
||||
*/
|
||||
async joinInvite(code: string) {
|
||||
return await this.req("POST", `/invites/${code}` as "/invites/id");
|
||||
return await this.api.post(`/invites/${code}`);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -388,7 +320,7 @@ export class Client extends EventEmitter {
|
||||
* @param code The invite code.
|
||||
*/
|
||||
async deleteInvite(code: string) {
|
||||
await this.req("DELETE", `/invites/${code}` as "/invites/id");
|
||||
await this.api.delete(`/invites/${code}`);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -397,7 +329,7 @@ export class Client extends EventEmitter {
|
||||
* @returns Key-value object of settings.
|
||||
*/
|
||||
async syncFetchSettings(keys: string[]) {
|
||||
return await this.req("POST", "/sync/settings/fetch", { keys });
|
||||
return await this.api.post("/sync/settings/fetch", { keys });
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -416,11 +348,12 @@ export class Client extends EventEmitter {
|
||||
typeof value === "string" ? value : JSON.stringify(value);
|
||||
}
|
||||
|
||||
const query = timestamp ? `?timestamp=${timestamp}` : "";
|
||||
await this.req(
|
||||
"POST",
|
||||
`/sync/settings/set${query}` as "/sync/settings/set",
|
||||
requestData,
|
||||
await this.api.post(
|
||||
`/sync/settings/set`,
|
||||
{
|
||||
...requestData,
|
||||
timestamp
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@@ -429,7 +362,7 @@ export class Client extends EventEmitter {
|
||||
* @returns Array of channel unreads.
|
||||
*/
|
||||
async syncFetchUnreads() {
|
||||
return await this.req("GET", "/sync/unreads");
|
||||
return await this.api.get("/sync/unreads");
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -442,7 +375,7 @@ export class Client extends EventEmitter {
|
||||
async logout(avoidRequest?: boolean) {
|
||||
this.user = null;
|
||||
this.emit("logout");
|
||||
!avoidRequest && (await this.req("POST", "/auth/session/logout"));
|
||||
!avoidRequest && (await this.api.post("/auth/session/logout"));
|
||||
this.reset();
|
||||
}
|
||||
|
||||
@@ -467,8 +400,8 @@ export class Client extends EventEmitter {
|
||||
* @param data Registration data object
|
||||
* @returns A promise containing a registration response object
|
||||
*/
|
||||
register(data: Route<"POST", "/auth/account/create">["data"]) {
|
||||
return this.request("POST", "/auth/account/create", { data });
|
||||
register(data: DataCreateAccount) {
|
||||
return this.api.post("/auth/account/create", data);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -512,7 +445,7 @@ export class Client extends EventEmitter {
|
||||
* @returns Generated URL or nothing
|
||||
*/
|
||||
generateFileURL(
|
||||
attachment?: { tag: string; _id: string; content_type?: string, metadata?: AttachmentMetadata },
|
||||
attachment?: { tag: string; _id: string; content_type?: string, metadata?: Metadata },
|
||||
...args: FileArgs
|
||||
) {
|
||||
const [options, allowAnimation, fallback] = args;
|
||||
@@ -537,7 +470,7 @@ export class Client extends EventEmitter {
|
||||
query =
|
||||
"?" +
|
||||
Object.keys(options)
|
||||
.map((k) => `${k}=${options[k as keyof SizeOptions]}`)
|
||||
.map((k) => `${k}=${options[k as keyof FileArgs[0]]}`)
|
||||
.join("&");
|
||||
}
|
||||
}
|
||||
|
||||
+98
-31
@@ -5,39 +5,106 @@ export const UserPermission = {
|
||||
Invite: 1 << 3,
|
||||
};
|
||||
|
||||
export const ChannelPermission = {
|
||||
View: 1 << 0,
|
||||
SendMessage: 1 << 1,
|
||||
ManageMessages: 1 << 2,
|
||||
ManageChannel: 1 << 3,
|
||||
VoiceCall: 1 << 4,
|
||||
InviteOthers: 1 << 5,
|
||||
EmbedLinks: 1 << 6,
|
||||
UploadFiles: 1 << 7,
|
||||
Masquerade: 1 << 8,
|
||||
};
|
||||
export const Permission = {
|
||||
// * Generic permissions
|
||||
/// Manage the channel or channels on the server
|
||||
ManageChannel: 2**0,
|
||||
/// Manage the server
|
||||
ManageServer: 2**1,
|
||||
/// Manage permissions on servers or channels
|
||||
ManagePermissions: 2**2,
|
||||
/// Manage roles on server
|
||||
ManageRole: 2**3,
|
||||
|
||||
export const ServerPermission = {
|
||||
View: 1 << 0,
|
||||
ManageRoles: 1 << 1,
|
||||
ManageChannels: 1 << 2,
|
||||
ManageServer: 1 << 3,
|
||||
KickMembers: 1 << 4,
|
||||
BanMembers: 1 << 5,
|
||||
ChangeNickname: 1 << 12,
|
||||
ManageNicknames: 1 << 13,
|
||||
ChangeAvatar: 1 << 14,
|
||||
RemoveAvatars: 1 << 15,
|
||||
// % 3 bits reserved
|
||||
|
||||
// * Member permissions
|
||||
/// Kick other members below their ranking
|
||||
KickMembers: 2**6,
|
||||
/// Ban other members below their ranking
|
||||
BanMembers: 2**7,
|
||||
/// Timeout other members below their ranking
|
||||
TimeoutMembers: 2**8,
|
||||
/// Assign roles to members below their ranking
|
||||
AssignRoles: 2**9,
|
||||
/// Change own nickname
|
||||
ChangeNickname: 2**10,
|
||||
/// Change or remove other's nicknames below their ranking
|
||||
ManageNicknames: 2**11,
|
||||
/// Change own avatar
|
||||
ChangeAvatar: 2**12,
|
||||
/// Remove other's avatars below their ranking
|
||||
RemoveAvatars: 2**13,
|
||||
|
||||
// % 7 bits reserved
|
||||
|
||||
// * Channel permissions
|
||||
/// View a channel
|
||||
ViewChannel: 2**20,
|
||||
/// Read a channel's past message history
|
||||
ReadMessageHistory: 2**21,
|
||||
/// Send a message in a channel
|
||||
SendMessage: 2**22,
|
||||
/// Delete messages in a channel
|
||||
ManageMessages: 2**23,
|
||||
/// Manage webhook entries on a channel
|
||||
ManageWebhooks: 2**24,
|
||||
/// Create invites to this channel
|
||||
InviteOthers: 2**25,
|
||||
/// Send embedded content in this channel
|
||||
SendEmbeds: 2**26,
|
||||
/// Send attachments and media in this channel
|
||||
UploadFiles: 2**27,
|
||||
/// Masquerade messages using custom nickname and avatar
|
||||
Masquerade: 2**28,
|
||||
|
||||
// % 1 bits reserved
|
||||
|
||||
// * Voice permissions
|
||||
/// Connect to a voice channel
|
||||
Connect: 2**30,
|
||||
/// Speak in a voice call
|
||||
Speak: 2**31,
|
||||
/// Share video in a voice call
|
||||
Video: 2**32,
|
||||
/// Mute other members with lower ranking in a voice call
|
||||
MuteMembers: 2**33,
|
||||
/// Deafen other members with lower ranking in a voice call
|
||||
DeafenMembers: 2**34,
|
||||
/// Move members between voice channels
|
||||
MoveMembers: 2**35,
|
||||
|
||||
// * Misc. permissions
|
||||
// % Bits 36 to 52: free area
|
||||
// % Bits 53 to 64: do not use
|
||||
|
||||
// * Grant all permissions
|
||||
/// Safely grant all permissions
|
||||
GrantAllSafe: 0x000F_FFFF_FFFF_FFFF,
|
||||
};
|
||||
|
||||
export const U32_MAX = 2 ** 32 - 1; // 4294967295
|
||||
|
||||
export const DEFAULT_PERMISSION_DM =
|
||||
ChannelPermission.View +
|
||||
ChannelPermission.SendMessage +
|
||||
ChannelPermission.ManageChannel +
|
||||
ChannelPermission.VoiceCall +
|
||||
ChannelPermission.InviteOthers +
|
||||
ChannelPermission.EmbedLinks +
|
||||
ChannelPermission.UploadFiles +
|
||||
ChannelPermission.Masquerade;
|
||||
export const DEFAULT_PERMISSION_VIEW_ONLY =
|
||||
Permission.ViewChannel +
|
||||
Permission.ReadMessageHistory;
|
||||
|
||||
export const DEFAULT_PERMISSION =
|
||||
DEFAULT_PERMISSION_VIEW_ONLY +
|
||||
Permission.SendMessage +
|
||||
Permission.InviteOthers +
|
||||
Permission.SendEmbeds +
|
||||
Permission.UploadFiles +
|
||||
Permission.Connect +
|
||||
Permission.Speak;
|
||||
|
||||
export const DEFAULT_PERMISSION_SAVED_MESSAGES = Permission.GrantAllSafe;
|
||||
|
||||
export const DEFAULT_PERMISSION_DIRECT_MESSAGE =
|
||||
DEFAULT_PERMISSION +
|
||||
Permission.ManageChannel;
|
||||
|
||||
export const DEFAULT_PERMISSION_SERVER =
|
||||
DEFAULT_PERMISSION +
|
||||
Permission.ChangeNickname +
|
||||
Permission.ChangeAvatar;
|
||||
|
||||
@@ -1,842 +0,0 @@
|
||||
import { Account, Session, SessionInfo } from "revolt-api/types/Auth";
|
||||
import type { Bot, PublicBot } from "revolt-api/types/Bots";
|
||||
import type {
|
||||
Channel,
|
||||
DirectMessageChannel,
|
||||
GroupChannel,
|
||||
Message,
|
||||
TextChannel,
|
||||
VoiceChannel,
|
||||
SendableEmbed
|
||||
} from "revolt-api/types/Channels";
|
||||
import type { RevoltConfiguration } from "revolt-api/types/Core";
|
||||
import type { RetrievedInvite, ServerInvite } from "revolt-api/types/Invites";
|
||||
import type {
|
||||
Ban,
|
||||
Category,
|
||||
Member,
|
||||
PermissionTuple,
|
||||
Server,
|
||||
SystemMessageChannels,
|
||||
} from "revolt-api/types/Servers";
|
||||
import type { UserSettings, ChannelUnread } from "revolt-api/types/Sync";
|
||||
import type {
|
||||
Profile,
|
||||
Relationship,
|
||||
RelationshipOnly,
|
||||
Status,
|
||||
User,
|
||||
} from "revolt-api/types/Users";
|
||||
|
||||
export type RemoveUserField =
|
||||
| "ProfileContent"
|
||||
| "ProfileBackground"
|
||||
| "StatusText"
|
||||
| "Avatar";
|
||||
export type RemoveChannelField = "Icon" | "Description";
|
||||
export type RemoveServerField = "Icon" | "Banner" | "Description";
|
||||
export type RemoveMemberField = "Nickname" | "Avatar";
|
||||
export type RemoveRoleField = "Colour";
|
||||
|
||||
type Id = "id";
|
||||
type Routes =
|
||||
/**
|
||||
* Core
|
||||
*/
|
||||
| {
|
||||
// Query Revolt node.
|
||||
method: "GET";
|
||||
route: `/`;
|
||||
data: undefined;
|
||||
response: RevoltConfiguration;
|
||||
}
|
||||
/**
|
||||
* Auth
|
||||
*/
|
||||
| {
|
||||
method: "GET";
|
||||
route: `/auth/account`;
|
||||
data: undefined;
|
||||
response: Account;
|
||||
}
|
||||
| {
|
||||
method: "POST";
|
||||
route: `/auth/account/create`;
|
||||
data: {
|
||||
email: string;
|
||||
password: string;
|
||||
invite?: string;
|
||||
captcha?: string;
|
||||
};
|
||||
response: undefined;
|
||||
}
|
||||
| {
|
||||
method: "POST";
|
||||
route: `/auth/account/reverify`;
|
||||
data: {
|
||||
email: string;
|
||||
captcha?: string;
|
||||
};
|
||||
response: undefined;
|
||||
}
|
||||
| {
|
||||
method: "POST";
|
||||
route: `/auth/account/verify/:code`;
|
||||
data: undefined;
|
||||
response: undefined;
|
||||
}
|
||||
| {
|
||||
method: "POST";
|
||||
route: `/auth/account/reset_password`;
|
||||
data: {
|
||||
email: string;
|
||||
captcha?: string;
|
||||
};
|
||||
response: undefined;
|
||||
}
|
||||
| {
|
||||
method: "PATCH";
|
||||
route: `/auth/account/reset_password`;
|
||||
data: {
|
||||
password: string;
|
||||
token: string;
|
||||
};
|
||||
response: undefined;
|
||||
}
|
||||
| {
|
||||
method: "PATCH";
|
||||
route: `/auth/account/change/password`;
|
||||
data: {
|
||||
password: string;
|
||||
current_password: string;
|
||||
};
|
||||
response: undefined;
|
||||
}
|
||||
| {
|
||||
method: "PATCH";
|
||||
route: `/auth/account/change/email`;
|
||||
data: {
|
||||
email: string;
|
||||
current_password: string;
|
||||
};
|
||||
response: undefined;
|
||||
}
|
||||
| {
|
||||
method: "POST";
|
||||
route: `/auth/session/login`;
|
||||
data: {
|
||||
email: string;
|
||||
password?: string;
|
||||
challenge?: string;
|
||||
friendly_name?: string;
|
||||
captcha?: string;
|
||||
};
|
||||
response: Session;
|
||||
}
|
||||
| {
|
||||
method: "POST";
|
||||
route: `/auth/session/logout`;
|
||||
data: undefined;
|
||||
response: undefined;
|
||||
}
|
||||
| {
|
||||
method: "PATCH";
|
||||
route: `/auth/session/${Id}`;
|
||||
data: {
|
||||
friendly_name: string;
|
||||
};
|
||||
response: undefined;
|
||||
}
|
||||
| {
|
||||
method: "DELETE";
|
||||
route: `/auth/session/${Id}`;
|
||||
data: undefined;
|
||||
response: undefined;
|
||||
}
|
||||
| {
|
||||
method: "GET";
|
||||
route: `/auth/session/all`;
|
||||
data: undefined;
|
||||
response: SessionInfo[];
|
||||
}
|
||||
| {
|
||||
method: "DELETE";
|
||||
route: `/auth/session/all`;
|
||||
data: undefined;
|
||||
response: undefined;
|
||||
}
|
||||
/**
|
||||
* Onboarding
|
||||
*/
|
||||
| {
|
||||
// Ask server for user status.
|
||||
method: "GET";
|
||||
route: `/onboard/hello`;
|
||||
data: undefined;
|
||||
response: {
|
||||
onboarding: boolean;
|
||||
id?: string;
|
||||
};
|
||||
}
|
||||
| {
|
||||
// Complete onboarding.
|
||||
method: "POST";
|
||||
route: `/onboard/complete`;
|
||||
data: {
|
||||
username: string;
|
||||
};
|
||||
response: {
|
||||
onboarding: boolean;
|
||||
};
|
||||
}
|
||||
/**
|
||||
* Users
|
||||
*/
|
||||
| {
|
||||
// Retrieve a user's information.
|
||||
method: "GET";
|
||||
route: `/users/${Id}`;
|
||||
data: undefined;
|
||||
response: User;
|
||||
}
|
||||
| {
|
||||
// Edit user.
|
||||
method: "PATCH";
|
||||
route: `/users/${Id}`;
|
||||
data: {
|
||||
status?: Status;
|
||||
profile?: {
|
||||
content?: string;
|
||||
background?: string;
|
||||
};
|
||||
avatar?: string;
|
||||
remove?: RemoveUserField;
|
||||
};
|
||||
response: undefined;
|
||||
}
|
||||
| {
|
||||
// Change username.
|
||||
method: "PATCH";
|
||||
route: `/users/${Id}/username`;
|
||||
data: {
|
||||
username: string;
|
||||
password: string;
|
||||
};
|
||||
response: undefined;
|
||||
}
|
||||
| {
|
||||
// Retrieve a user's profile.
|
||||
method: "GET";
|
||||
route: `/users/${Id}/profile`;
|
||||
data: undefined;
|
||||
response: Profile;
|
||||
}
|
||||
| {
|
||||
// Fetch all your DM conversations.
|
||||
method: "GET";
|
||||
route: `/users/dms`;
|
||||
data: undefined;
|
||||
response: (DirectMessageChannel | GroupChannel)[];
|
||||
}
|
||||
| {
|
||||
// Open a DM with another user.
|
||||
method: "GET";
|
||||
route: `/users/${Id}/dm`;
|
||||
data: undefined;
|
||||
response: DirectMessageChannel;
|
||||
}
|
||||
| {
|
||||
// Fetch all of your relationships with other users.
|
||||
method: "GET";
|
||||
route: `/users/relationships`;
|
||||
data: undefined;
|
||||
response: Relationship[];
|
||||
}
|
||||
| {
|
||||
// Fetch your relationship with another other user.
|
||||
method: "GET";
|
||||
route: `/users/${Id}/relationship`;
|
||||
data: undefined;
|
||||
response: RelationshipOnly;
|
||||
}
|
||||
| {
|
||||
// Fetch your mutual relationships with another user.
|
||||
method: "GET";
|
||||
route: `/users/${Id}/mutual`;
|
||||
data: undefined;
|
||||
response: {
|
||||
users: string[];
|
||||
servers: string[];
|
||||
};
|
||||
}
|
||||
| {
|
||||
// Send a friend request / accept a friend request.
|
||||
method: "PUT";
|
||||
route: `/users/${Id}/friend`;
|
||||
data: undefined;
|
||||
response: RelationshipOnly;
|
||||
}
|
||||
| {
|
||||
// Delete a friend request / remove a friend.
|
||||
method: "DELETE";
|
||||
route: `/users/${Id}/friend`;
|
||||
data: undefined;
|
||||
response: RelationshipOnly;
|
||||
}
|
||||
| {
|
||||
// Block a user.
|
||||
method: "PUT";
|
||||
route: `/users/${Id}/block`;
|
||||
data: undefined;
|
||||
response: RelationshipOnly;
|
||||
}
|
||||
| {
|
||||
// Unblock a user.
|
||||
method: "DELETE";
|
||||
route: `/users/${Id}/block`;
|
||||
data: undefined;
|
||||
response: RelationshipOnly;
|
||||
}
|
||||
| {
|
||||
// Fetch a user's avatar.
|
||||
method: "GET";
|
||||
route: `/users/${Id}/avatar`;
|
||||
data: undefined;
|
||||
response: unknown;
|
||||
}
|
||||
| {
|
||||
// Fetch default avatar for user.
|
||||
method: "GET";
|
||||
route: `/users/${Id}/default_avatar`;
|
||||
data: undefined;
|
||||
response: unknown;
|
||||
}
|
||||
/**
|
||||
* Channels
|
||||
*/
|
||||
| {
|
||||
// Fetch a channel by ID.
|
||||
method: "GET";
|
||||
route: `/channels/${Id}`;
|
||||
data: undefined;
|
||||
response: Channel;
|
||||
}
|
||||
| {
|
||||
// Fetch a channel's members by ID.
|
||||
method: "GET";
|
||||
route: `/channels/${Id}/members`;
|
||||
data: undefined;
|
||||
response: User[];
|
||||
}
|
||||
| {
|
||||
// Edit a channel.
|
||||
method: "PATCH";
|
||||
route: `/channels/${Id}`;
|
||||
data: {
|
||||
name?: string;
|
||||
description?: string;
|
||||
icon?: string;
|
||||
nsfw?: boolean;
|
||||
remove?: RemoveChannelField;
|
||||
};
|
||||
response: undefined;
|
||||
}
|
||||
| {
|
||||
// Close DM channel or leave group channel.
|
||||
method: "DELETE";
|
||||
route: `/channels/${Id}`;
|
||||
data: undefined;
|
||||
response: undefined;
|
||||
}
|
||||
| {
|
||||
// Create a group DM.
|
||||
method: "POST";
|
||||
route: `/channels/create`;
|
||||
data: {
|
||||
name: string;
|
||||
description?: string;
|
||||
nonce: string;
|
||||
users: string[];
|
||||
};
|
||||
response: GroupChannel;
|
||||
}
|
||||
| {
|
||||
// Create an invite to a channel.
|
||||
method: "POST";
|
||||
route: `/channels/${Id}/invites`;
|
||||
data: undefined;
|
||||
response: { code: string };
|
||||
}
|
||||
| {
|
||||
// Add member to group.
|
||||
method: "PUT";
|
||||
route: `/channels/${Id}/recipients/${Id}`;
|
||||
data: undefined;
|
||||
response: undefined;
|
||||
}
|
||||
| {
|
||||
// Remove member from group.
|
||||
method: "DELETE";
|
||||
route: `/channels/${Id}/recipients/${Id}`;
|
||||
data: undefined;
|
||||
response: undefined;
|
||||
}
|
||||
| {
|
||||
// Mark a channel as read at message.
|
||||
method: "PUT";
|
||||
route: `/channels/${Id}/ack/${Id}`;
|
||||
data: undefined;
|
||||
response: undefined;
|
||||
}
|
||||
| {
|
||||
// Set role permission for channel.
|
||||
method: "PUT";
|
||||
route: `/channels/${Id}/permissions/${Id}`;
|
||||
data: {
|
||||
permissions?: number;
|
||||
};
|
||||
response: undefined;
|
||||
}
|
||||
/**
|
||||
* Messaging
|
||||
*/
|
||||
| {
|
||||
// Send message to channel.
|
||||
method: "POST";
|
||||
route: `/channels/${Id}/messages`;
|
||||
data: {
|
||||
content: string;
|
||||
nonce: string;
|
||||
attachments?: string[];
|
||||
replies?: { id: string; mention: boolean }[];
|
||||
embeds?: SendableEmbed[];
|
||||
};
|
||||
response: Message;
|
||||
}
|
||||
| {
|
||||
// Fetch message from channel.
|
||||
method: "GET";
|
||||
route: `/channels/${Id}/messages/${Id}`;
|
||||
data: undefined;
|
||||
response: Message;
|
||||
}
|
||||
| {
|
||||
// Query messages from channel (optionally include users as well).
|
||||
method: "GET";
|
||||
route: `/channels/${Id}/messages`;
|
||||
data: {
|
||||
limit?: number;
|
||||
before?: string;
|
||||
after?: string;
|
||||
sort?: "Latest" | "Oldest";
|
||||
nearby?: string;
|
||||
include_users?: boolean;
|
||||
};
|
||||
response:
|
||||
| Message[]
|
||||
| {
|
||||
messages: Message[];
|
||||
users: User[];
|
||||
members?: Member[];
|
||||
};
|
||||
}
|
||||
| {
|
||||
// Search messages in a channel (optionally include users as well).
|
||||
method: "POST";
|
||||
route: `/channels/${Id}/search`;
|
||||
data: {
|
||||
query: string;
|
||||
|
||||
limit?: number;
|
||||
before?: string;
|
||||
after?: string;
|
||||
sort?: "Relevance" | "Latest" | "Oldest";
|
||||
include_users?: boolean;
|
||||
};
|
||||
response:
|
||||
| Message[]
|
||||
| {
|
||||
messages: Message[];
|
||||
users: User[];
|
||||
members?: Member[];
|
||||
};
|
||||
}
|
||||
| {
|
||||
// Query updated messages from channel.
|
||||
method: "POST";
|
||||
route: `/channels/${Id}/messages/stale`;
|
||||
data: {
|
||||
ids: string[];
|
||||
};
|
||||
response: {
|
||||
updated: Message[];
|
||||
deleted: string[];
|
||||
};
|
||||
}
|
||||
| {
|
||||
// Edit message.
|
||||
method: "PATCH";
|
||||
route: `/channels/${Id}/messages/${Id}`;
|
||||
data: {
|
||||
content?: string;
|
||||
embeds?: SendableEmbed[];
|
||||
};
|
||||
response: undefined;
|
||||
}
|
||||
| {
|
||||
// Delete message.
|
||||
method: "DELETE";
|
||||
route: `/channels/${Id}/messages/${Id}`;
|
||||
data: undefined;
|
||||
response: undefined;
|
||||
}
|
||||
/**
|
||||
* Servers
|
||||
*/
|
||||
| {
|
||||
// Create a server.
|
||||
method: "POST";
|
||||
route: `/servers/create`;
|
||||
data: {
|
||||
name: string;
|
||||
nonce: string;
|
||||
};
|
||||
response: Server;
|
||||
}
|
||||
| {
|
||||
// Fetch a server by ID.
|
||||
method: "GET";
|
||||
route: `/servers/${Id}`;
|
||||
data: undefined;
|
||||
response: Server;
|
||||
}
|
||||
| {
|
||||
// Delete or leave a server.
|
||||
method: "DELETE";
|
||||
route: `/servers/${Id}`;
|
||||
data: undefined;
|
||||
response: undefined;
|
||||
}
|
||||
| {
|
||||
// Edit a server.
|
||||
method: "PATCH";
|
||||
route: `/servers/${Id}`;
|
||||
data: {
|
||||
name?: string;
|
||||
description?: string;
|
||||
icon?: string;
|
||||
banner?: string;
|
||||
categories?: Category[];
|
||||
system_messages?: SystemMessageChannels;
|
||||
nsfw?: boolean;
|
||||
remove?: RemoveServerField;
|
||||
};
|
||||
response: undefined;
|
||||
}
|
||||
| {
|
||||
// Mark an entire server as read.
|
||||
method: "PUT";
|
||||
route: `/servers/${Id}/ack`;
|
||||
data: undefined;
|
||||
response: undefined;
|
||||
}
|
||||
| {
|
||||
// Fetch a server's members
|
||||
method: "GET";
|
||||
route: `/servers/${Id}/members`;
|
||||
data: undefined;
|
||||
response: {
|
||||
members: Member[];
|
||||
users: User[];
|
||||
};
|
||||
}
|
||||
| {
|
||||
// Fetch a server member by their ID
|
||||
method: "GET";
|
||||
route: `/servers/${Id}/members/${Id}`;
|
||||
data: undefined;
|
||||
response: Member;
|
||||
}
|
||||
| {
|
||||
// Edit a server member
|
||||
method: "PATCH";
|
||||
route: `/servers/${Id}/members/${Id}`;
|
||||
data: {
|
||||
nickname?: string;
|
||||
avatar?: string;
|
||||
roles?: string[];
|
||||
remove?: RemoveMemberField;
|
||||
};
|
||||
response: undefined;
|
||||
}
|
||||
| {
|
||||
// Kick a server member
|
||||
method: "DELETE";
|
||||
route: `/servers/${Id}/members/${Id}`;
|
||||
data: undefined;
|
||||
response: undefined;
|
||||
}
|
||||
| {
|
||||
// Ban a user from the server
|
||||
method: "PUT";
|
||||
route: `/servers/${Id}/bans/${Id}`;
|
||||
data: {
|
||||
reason?: string;
|
||||
};
|
||||
response: undefined;
|
||||
}
|
||||
| {
|
||||
// Unban a user from the server
|
||||
method: "DELETE";
|
||||
route: `/servers/${Id}/bans/${Id}`;
|
||||
data: undefined;
|
||||
response: undefined;
|
||||
}
|
||||
| {
|
||||
// Fetch a server's bans
|
||||
method: "GET";
|
||||
route: `/servers/${Id}/bans`;
|
||||
data: undefined;
|
||||
response: {
|
||||
users: Pick<User, "_id" | "username" | "avatar">[];
|
||||
bans: Ban[];
|
||||
};
|
||||
}
|
||||
| {
|
||||
// Create a new server channel
|
||||
method: "POST";
|
||||
route: `/servers/${Id}/channels`;
|
||||
data: {
|
||||
type?: "Text" | "Voice";
|
||||
name: string;
|
||||
description?: string;
|
||||
nonce: string;
|
||||
};
|
||||
response: TextChannel | VoiceChannel;
|
||||
}
|
||||
| {
|
||||
// Fetch a server's invites
|
||||
method: "GET";
|
||||
route: `/servers/${Id}/invites`;
|
||||
data: undefined;
|
||||
response: ServerInvite[];
|
||||
}
|
||||
| {
|
||||
// Create role
|
||||
method: "POST";
|
||||
route: `/servers/${Id}/roles`;
|
||||
data: {
|
||||
name: string;
|
||||
};
|
||||
response: {
|
||||
id: string;
|
||||
permissions: PermissionTuple;
|
||||
};
|
||||
}
|
||||
| {
|
||||
// Edit a role.
|
||||
method: "PATCH";
|
||||
route: `/servers/${Id}/roles/${Id}`;
|
||||
data: {
|
||||
name?: string;
|
||||
colour?: string;
|
||||
hoist?: boolean;
|
||||
rank?: number;
|
||||
remove?: RemoveRoleField;
|
||||
};
|
||||
response: undefined;
|
||||
}
|
||||
| {
|
||||
// Delete role
|
||||
method: "DELETE";
|
||||
route: `/servers/${Id}/roles/${Id}`;
|
||||
data: undefined;
|
||||
response: undefined;
|
||||
}
|
||||
| {
|
||||
// Set role permission for server.
|
||||
method: "PUT";
|
||||
route: `/servers/${Id}/permissions/${Id}`;
|
||||
data: {
|
||||
permissions?: {
|
||||
server: number;
|
||||
channel: number;
|
||||
};
|
||||
};
|
||||
response: undefined;
|
||||
}
|
||||
/**
|
||||
* Bots
|
||||
*/
|
||||
| {
|
||||
// Create Bot
|
||||
method: "POST";
|
||||
route: `/bots/create`;
|
||||
data: {
|
||||
name: string;
|
||||
};
|
||||
response: Bot;
|
||||
}
|
||||
| {
|
||||
// Fetch Owned Bots
|
||||
method: "GET";
|
||||
route: `/bots/@me`;
|
||||
data: undefined;
|
||||
response: {
|
||||
bots: Bot[];
|
||||
users: User[];
|
||||
};
|
||||
}
|
||||
| {
|
||||
// Fetch Bot
|
||||
method: "GET";
|
||||
route: `/bots/${Id}`;
|
||||
data: undefined;
|
||||
response: {
|
||||
bot: Bot;
|
||||
user: User;
|
||||
};
|
||||
}
|
||||
| {
|
||||
// Edit Bot
|
||||
method: "PATCH";
|
||||
route: `/bots/${Id}`;
|
||||
data: {
|
||||
name?: string;
|
||||
public?: boolean;
|
||||
interactionsURL?: string;
|
||||
remove?: "InteractionsURL";
|
||||
};
|
||||
response: undefined;
|
||||
}
|
||||
| {
|
||||
// Delete Bot
|
||||
method: "DELETE";
|
||||
route: `/bots/${Id}`;
|
||||
data: undefined;
|
||||
response: undefined;
|
||||
}
|
||||
| {
|
||||
// Fetch Public Bot
|
||||
method: "GET";
|
||||
route: `/bots/${Id}/invite`;
|
||||
data: undefined;
|
||||
response: PublicBot;
|
||||
}
|
||||
| {
|
||||
// Invite Public Bot
|
||||
method: "POST";
|
||||
route: `/bots/${Id}/invite`;
|
||||
data: { server: string } | { group: string };
|
||||
response: undefined;
|
||||
}
|
||||
/**
|
||||
* Invites
|
||||
*/
|
||||
| {
|
||||
// Fetch information about an invite.
|
||||
method: "GET";
|
||||
route: `/invites/${Id}`;
|
||||
data: undefined;
|
||||
response: RetrievedInvite;
|
||||
}
|
||||
| {
|
||||
// Use an invite.
|
||||
method: "POST";
|
||||
route: `/invites/${Id}`;
|
||||
data: undefined;
|
||||
response: {
|
||||
type: "Server";
|
||||
channel: TextChannel;
|
||||
server: Server;
|
||||
};
|
||||
}
|
||||
| {
|
||||
// Delete an invite.
|
||||
method: "DELETE";
|
||||
route: `/invites/${Id}`;
|
||||
data: undefined;
|
||||
response: undefined;
|
||||
}
|
||||
/**
|
||||
* Sync
|
||||
*/
|
||||
| {
|
||||
// Fetch user settings.
|
||||
method: "POST";
|
||||
route: `/sync/settings/fetch`;
|
||||
data: {
|
||||
keys: string[];
|
||||
};
|
||||
response: UserSettings;
|
||||
}
|
||||
| {
|
||||
// Set user settings.
|
||||
method: "POST";
|
||||
route: `/sync/settings/set`;
|
||||
data: {
|
||||
[key: string]: string;
|
||||
};
|
||||
response: undefined;
|
||||
}
|
||||
| {
|
||||
// Fetch unreads.
|
||||
method: "GET";
|
||||
route: `/sync/unreads`;
|
||||
data: undefined;
|
||||
response: ChannelUnread[];
|
||||
}
|
||||
/**
|
||||
* Push API
|
||||
*/
|
||||
| {
|
||||
method: "POST";
|
||||
route: `/push/subscribe`;
|
||||
data: {
|
||||
endpoint: string;
|
||||
p256dh: string;
|
||||
auth: string;
|
||||
};
|
||||
response: undefined;
|
||||
}
|
||||
| {
|
||||
method: "POST";
|
||||
route: `/push/unsubscribe`;
|
||||
data: undefined;
|
||||
response: undefined;
|
||||
}
|
||||
/**
|
||||
* Voice API
|
||||
*/
|
||||
| {
|
||||
// Join voice call for channel.
|
||||
method: "POST";
|
||||
route: `/channels/${Id}/join_call`;
|
||||
data: undefined;
|
||||
response: {
|
||||
token: string;
|
||||
};
|
||||
};
|
||||
|
||||
// ? Below are Typescript typings for extracting route data from the object above.
|
||||
// ? https://artsy.github.io/blog/2018/11/21/conditional-types-in-typescript/
|
||||
|
||||
export type RoutePath = Routes["route"];
|
||||
export type RouteMethod = Routes["method"];
|
||||
|
||||
type ExcludeRouteKey<K> = K extends "route" ? never : K;
|
||||
type ExcludeRouteField<A> = { [K in ExcludeRouteKey<keyof A>]: A[K] };
|
||||
type ExtractRouteParameters<A, T> = A extends { route: T }
|
||||
? ExcludeRouteField<A>
|
||||
: never;
|
||||
|
||||
type ExcludeMethodKey<K> = K extends "method" ? never : K;
|
||||
type ExcludeMethodField<A> = { [K in ExcludeMethodKey<keyof A>]: A[K] };
|
||||
type ExtractMethodParameters<A, T> = A extends { method: T }
|
||||
? ExcludeMethodField<A>
|
||||
: never;
|
||||
|
||||
export type Route<
|
||||
M extends RouteMethod,
|
||||
T extends RoutePath,
|
||||
> = ExtractMethodParameters<ExtractRouteParameters<Routes, T>, M>;
|
||||
+2
-2
@@ -2,6 +2,6 @@ export * from "./Client";
|
||||
export * from "./config";
|
||||
export {
|
||||
UserPermission,
|
||||
ChannelPermission,
|
||||
ServerPermission,
|
||||
Permission
|
||||
} from "./api/permissions";
|
||||
export * from "revolt-api";
|
||||
|
||||
+17
-20
@@ -1,9 +1,9 @@
|
||||
import { runInAction } from "mobx";
|
||||
|
||||
import { Route } from "../api/routes";
|
||||
|
||||
import { Client } from "../Client";
|
||||
|
||||
import { InviteBotDestination, DataEditBot, DataCreateBot, OwnedBotsResponse } from 'revolt-api';
|
||||
|
||||
export default class Bots {
|
||||
client: Client;
|
||||
|
||||
@@ -17,10 +17,10 @@ export default class Bots {
|
||||
* @returns Bot and User object
|
||||
*/
|
||||
async fetch(id: string) {
|
||||
const { bot, user } = await this.client.req(
|
||||
"GET",
|
||||
`/bots/${id}` as "/bots/id",
|
||||
const { bot, user } = await this.client.api.get(
|
||||
`/bots/${id as ''}`,
|
||||
);
|
||||
|
||||
return {
|
||||
bot,
|
||||
user: await this.client.users.fetch(user._id, user),
|
||||
@@ -32,7 +32,7 @@ export default class Bots {
|
||||
* @param id Bot ID
|
||||
*/
|
||||
async delete(id: string) {
|
||||
await this.client.req("DELETE", `/bots/${id}` as "/bots/id");
|
||||
await this.client.api.delete(`/bots/${id}`);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -41,9 +41,8 @@ export default class Bots {
|
||||
* @returns Public Bot object
|
||||
*/
|
||||
async fetchPublic(id: string) {
|
||||
return await this.client.req(
|
||||
"GET",
|
||||
`/bots/${id}/invite` as "/bots/id/invite",
|
||||
return await this.client.api.get(
|
||||
`/bots/${id}/invite`,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -54,11 +53,10 @@ export default class Bots {
|
||||
*/
|
||||
async invite(
|
||||
id: string,
|
||||
destination: Route<"POST", "/bots/id/invite">["data"],
|
||||
destination: InviteBotDestination,
|
||||
) {
|
||||
return await this.client.req(
|
||||
"POST",
|
||||
`/bots/${id}/invite` as "/bots/id/invite",
|
||||
return await this.client.api.post(
|
||||
`/bots/${id}/invite`,
|
||||
destination,
|
||||
);
|
||||
}
|
||||
@@ -69,10 +67,9 @@ export default class Bots {
|
||||
* @returns Bot and User objects
|
||||
*/
|
||||
async fetchOwned() {
|
||||
const { bots, users: userObjects } = await this.client.req(
|
||||
"GET",
|
||||
const { bots, users: userObjects } = await this.client.api.get(
|
||||
`/bots/@me`,
|
||||
);
|
||||
) as OwnedBotsResponse;
|
||||
|
||||
const users = [];
|
||||
for (const obj of userObjects) {
|
||||
@@ -87,8 +84,8 @@ export default class Bots {
|
||||
* @param id Bot ID
|
||||
* @param data Bot edit data object
|
||||
*/
|
||||
async edit(id: string, data: Route<"PATCH", "/bots/id">["data"]) {
|
||||
await this.client.req("PATCH", `/bots/${id}` as "/bots/id", data);
|
||||
async edit(id: string, data: DataEditBot) {
|
||||
await this.client.api.patch(`/bots/${id}`, data);
|
||||
|
||||
if (data.name) {
|
||||
const user = this.client.users.get(id);
|
||||
@@ -104,8 +101,8 @@ export default class Bots {
|
||||
* Create a bot
|
||||
* @param data Bot creation data
|
||||
*/
|
||||
async create(data: Route<"POST", "/bots/create">["data"]) {
|
||||
const bot = await this.client.req("POST", "/bots/create", data);
|
||||
async create(data: DataCreateBot) {
|
||||
const bot = await this.client.api.post("/bots/create", data);
|
||||
const user = await this.client.users.fetch(bot._id, {
|
||||
_id: bot._id,
|
||||
username: data.name,
|
||||
|
||||
+131
-103
@@ -1,11 +1,15 @@
|
||||
import type {
|
||||
Channel as ChannelI,
|
||||
DataCreateGroup,
|
||||
DataEditChannel,
|
||||
DataMessageSend,
|
||||
FieldsChannel,
|
||||
Message as MessageI,
|
||||
} from "revolt-api/types/Channels";
|
||||
import type { RemoveChannelField, Route } from "../api/routes";
|
||||
import type { Attachment } from "revolt-api/types/Autumn";
|
||||
import type { Member } from "revolt-api/types/Servers";
|
||||
import type { User } from "revolt-api/types/Users";
|
||||
OptionsMessageSearch,
|
||||
} from "revolt-api";
|
||||
import type { File } from "revolt-api";
|
||||
import type { Member } from "revolt-api";
|
||||
import type { User } from "revolt-api";
|
||||
|
||||
import { action, computed, makeAutoObservable, runInAction } from "mobx";
|
||||
import isEqual from "lodash.isequal";
|
||||
@@ -16,11 +20,13 @@ import Collection from "./Collection";
|
||||
import { Message } from "./Messages";
|
||||
import { Client, FileArgs } from "..";
|
||||
import {
|
||||
DEFAULT_PERMISSION_DM,
|
||||
U32_MAX,
|
||||
UserPermission,
|
||||
DEFAULT_PERMISSION_DIRECT_MESSAGE,
|
||||
DEFAULT_PERMISSION_VIEW_ONLY,
|
||||
Permission, UserPermission
|
||||
} from "../api/permissions";
|
||||
import { INotificationChecker } from "../util/Unreads";
|
||||
import { Override, OverrideField } from "revolt-api";
|
||||
import { APIRoutes } from "revolt-api/dist/routes";
|
||||
|
||||
export class Channel {
|
||||
client: Client;
|
||||
@@ -56,13 +62,13 @@ export class Channel {
|
||||
* Default server channel permissions.
|
||||
* @requires `TextChannel`, `VoiceChannel`
|
||||
*/
|
||||
default_permissions: Nullable<number> = null;
|
||||
default_permissions: Nullable<OverrideField> = null;
|
||||
|
||||
/**
|
||||
* Channel permissions for each role.
|
||||
* @requires `TextChannel`, `VoiceChannel`
|
||||
*/
|
||||
role_permissions: Nullable<{ [key: string]: number }> = null;
|
||||
role_permissions: Nullable<{ [key: string]: OverrideField }> = null;
|
||||
|
||||
/**
|
||||
* Channel name.
|
||||
@@ -74,7 +80,7 @@ export class Channel {
|
||||
* Channel icon.
|
||||
* @requires `Group`, `TextChannel`, `VoiceChannel`
|
||||
*/
|
||||
icon: Nullable<Attachment> = null;
|
||||
icon: Nullable<File> = null;
|
||||
|
||||
/**
|
||||
* Channel description.
|
||||
@@ -278,7 +284,7 @@ export class Channel {
|
||||
});
|
||||
}
|
||||
|
||||
@action update(data: Partial<ChannelI>, clear?: RemoveChannelField) {
|
||||
@action update(data: Partial<ChannelI>, clear: FieldsChannel[] = []) {
|
||||
const apply = (key: string, target?: string) => {
|
||||
if (
|
||||
// @ts-expect-error TODO: clean up types here
|
||||
@@ -291,13 +297,15 @@ export class Channel {
|
||||
}
|
||||
};
|
||||
|
||||
switch (clear) {
|
||||
case "Description":
|
||||
this.description = null;
|
||||
break;
|
||||
case "Icon":
|
||||
this.icon = null;
|
||||
break;
|
||||
for (const entry of clear) {
|
||||
switch (entry) {
|
||||
case "Description":
|
||||
this.description = null;
|
||||
break;
|
||||
case "Icon":
|
||||
this.icon = null;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
apply("active");
|
||||
@@ -337,24 +345,19 @@ export class Channel {
|
||||
* @returns An array of the channel's members.
|
||||
*/
|
||||
async fetchMembers() {
|
||||
const members = await this.client.req(
|
||||
"GET",
|
||||
`/channels/${this._id}/members` as "/channels/id/members",
|
||||
const members = await this.client.api.get(
|
||||
`/channels/${this._id as ''}/members`
|
||||
);
|
||||
|
||||
return members.map(this.client.users.createObj);
|
||||
}
|
||||
|
||||
/**
|
||||
* Edit a channel
|
||||
* @param data Channel editing route data
|
||||
* @param data Edit data
|
||||
*/
|
||||
async edit(data: Route<"PATCH", "/channels/id">["data"]) {
|
||||
return await this.client.req(
|
||||
"PATCH",
|
||||
`/channels/${this._id}` as "/channels/id",
|
||||
data,
|
||||
);
|
||||
// ! FIXME: return $set in req
|
||||
async edit(data: DataEditChannel) {
|
||||
this.update(await this.client.api.patch(`/channels/${this._id}`, data));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -363,14 +366,13 @@ export class Channel {
|
||||
*/
|
||||
async delete(avoidReq?: boolean) {
|
||||
if (!avoidReq)
|
||||
await this.client.req(
|
||||
"DELETE",
|
||||
`/channels/${this._id}` as "/channels/id",
|
||||
await this.client.api.delete(
|
||||
`/channels/${this._id}`
|
||||
);
|
||||
|
||||
runInAction(() => {
|
||||
if (this.channel_type === "DirectMessage") {
|
||||
this.active = true;
|
||||
this.active = false;
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -395,9 +397,8 @@ export class Channel {
|
||||
* @param user_id ID of the target user
|
||||
*/
|
||||
async addMember(user_id: string) {
|
||||
return await this.client.req(
|
||||
"PUT",
|
||||
`/channels/${this._id}/recipients/${user_id}` as "/channels/id/recipients/id",
|
||||
return await this.client.api.put(
|
||||
`/channels/${this._id}/recipients/${user_id as ''}`
|
||||
);
|
||||
}
|
||||
|
||||
@@ -406,9 +407,8 @@ export class Channel {
|
||||
* @param user_id ID of the target user
|
||||
*/
|
||||
async removeMember(user_id: string) {
|
||||
return await this.client.req(
|
||||
"DELETE",
|
||||
`/channels/${this._id}/recipients/${user_id}` as "/channels/id/recipients/id",
|
||||
return await this.client.api.delete(
|
||||
`/channels/${this._id}/recipients/${user_id as ''}`
|
||||
);
|
||||
}
|
||||
|
||||
@@ -420,20 +420,20 @@ export class Channel {
|
||||
async sendMessage(
|
||||
data:
|
||||
| string
|
||||
| (Omit<Route<"POST", "/channels/id/messages">["data"], "nonce"> & {
|
||||
| (Omit<DataMessageSend, "nonce"> & {
|
||||
nonce?: string;
|
||||
}),
|
||||
) {
|
||||
const msg: Route<"POST", "/channels/id/messages">["data"] = {
|
||||
const msg: DataMessageSend = {
|
||||
nonce: ulid(),
|
||||
...(typeof data === "string" ? { content: data } : data),
|
||||
};
|
||||
|
||||
const message = await this.client.req(
|
||||
"POST",
|
||||
`/channels/${this._id}/messages` as "/channels/id/messages",
|
||||
const message = await this.client.api.post(
|
||||
`/channels/${this._id as ''}/messages`,
|
||||
msg,
|
||||
);
|
||||
|
||||
return this.client.messages.createObj(message, true);
|
||||
}
|
||||
|
||||
@@ -443,10 +443,10 @@ export class Channel {
|
||||
* @returns The message
|
||||
*/
|
||||
async fetchMessage(message_id: string) {
|
||||
const message = await this.client.req(
|
||||
"GET",
|
||||
`/channels/${this._id}/messages/${message_id}` as "/channels/id/messages/id",
|
||||
const message = await this.client.api.get(
|
||||
`/channels/${this._id as ''}/messages/${message_id as ''}`,
|
||||
);
|
||||
|
||||
return this.client.messages.createObj(message);
|
||||
}
|
||||
|
||||
@@ -457,14 +457,13 @@ export class Channel {
|
||||
*/
|
||||
async fetchMessages(
|
||||
params?: Omit<
|
||||
Route<"GET", "/channels/id/messages">["data"],
|
||||
(APIRoutes & { method: 'get', path: '/channels/{target}/messages' })['params'],
|
||||
"include_users"
|
||||
>,
|
||||
) {
|
||||
const messages = (await this.client.request(
|
||||
"GET",
|
||||
`/channels/${this._id}/messages` as "/channels/id/messages",
|
||||
{ params },
|
||||
const messages = (await this.client.api.get(
|
||||
`/channels/${this._id}/messages`,
|
||||
{ ...params },
|
||||
)) as MessageI[];
|
||||
return runInAction(() => messages.map(this.client.messages.createObj));
|
||||
}
|
||||
@@ -476,14 +475,13 @@ export class Channel {
|
||||
*/
|
||||
async fetchMessagesWithUsers(
|
||||
params?: Omit<
|
||||
Route<"GET", "/channels/id/messages">["data"],
|
||||
(APIRoutes & { method: 'get', path: '/channels/{target}/messages' })['params'],
|
||||
"include_users"
|
||||
>,
|
||||
) {
|
||||
const data = (await this.client.request(
|
||||
"GET",
|
||||
`/channels/${this._id}/messages` as "/channels/id/messages",
|
||||
{ params: { ...params, include_users: true } },
|
||||
const data = (await this.client.api.get(
|
||||
`/channels/${this._id}/messages`,
|
||||
{ ...params, include_users: true },
|
||||
)) as { messages: MessageI[]; users: User[]; members?: Member[] };
|
||||
return runInAction(() => {
|
||||
return {
|
||||
@@ -501,13 +499,12 @@ export class Channel {
|
||||
*/
|
||||
async search(
|
||||
params: Omit<
|
||||
Route<"POST", "/channels/id/search">["data"],
|
||||
OptionsMessageSearch,
|
||||
"include_users"
|
||||
>,
|
||||
) {
|
||||
const messages = (await this.client.req(
|
||||
"POST",
|
||||
`/channels/${this._id}/search` as "/channels/id/search",
|
||||
const messages = (await this.client.api.post(
|
||||
`/channels/${this._id}/search`,
|
||||
params,
|
||||
)) as MessageI[];
|
||||
return runInAction(() => messages.map(this.client.messages.createObj));
|
||||
@@ -520,13 +517,12 @@ export class Channel {
|
||||
*/
|
||||
async searchWithUsers(
|
||||
params: Omit<
|
||||
Route<"POST", "/channels/id/search">["data"],
|
||||
OptionsMessageSearch,
|
||||
"include_users"
|
||||
>,
|
||||
) {
|
||||
const data = (await this.client.req(
|
||||
"POST",
|
||||
`/channels/${this._id}/search` as "/channels/id/search",
|
||||
const data = (await this.client.api.post(
|
||||
`/channels/${this._id}/search`,
|
||||
{ ...params, include_users: true },
|
||||
)) as { messages: MessageI[]; users: User[]; members?: Member[] };
|
||||
return runInAction(() => {
|
||||
@@ -544,9 +540,8 @@ export class Channel {
|
||||
* @returns The stale messages
|
||||
*/
|
||||
async fetchStale(ids: string[]) {
|
||||
const data = await this.client.req(
|
||||
"POST",
|
||||
`/channels/${this._id}/messages/stale` as "/channels/id/messages/stale",
|
||||
/*const data = await this.client.api.post(
|
||||
`/channels/${this._id}/messages/stale`,
|
||||
{ ids },
|
||||
);
|
||||
|
||||
@@ -557,7 +552,8 @@ export class Channel {
|
||||
);
|
||||
});
|
||||
|
||||
return data;
|
||||
return data;*/
|
||||
return { deprecated: ids };
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -565,11 +561,9 @@ export class Channel {
|
||||
* @returns Newly created invite code
|
||||
*/
|
||||
async createInvite() {
|
||||
const res = await this.client.req(
|
||||
"POST",
|
||||
`/channels/${this._id}/invites` as "/channels/id/invites",
|
||||
return await this.client.api.post(
|
||||
`/channels/${this._id}/invites`,
|
||||
);
|
||||
return res.code;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -577,9 +571,8 @@ export class Channel {
|
||||
* @returns Join call response data
|
||||
*/
|
||||
async joinCall() {
|
||||
return await this.client.req(
|
||||
"POST",
|
||||
`/channels/${this._id}/join_call` as "/channels/id/join_call",
|
||||
return await this.client.api.post(
|
||||
`/channels/${this._id as ''}/join_call`,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -598,9 +591,8 @@ export class Channel {
|
||||
ulid();
|
||||
const performAck = () => {
|
||||
delete this.ackLimit;
|
||||
this.client.req(
|
||||
"PUT",
|
||||
`/channels/${this._id}/ack/${id}` as "/channels/id/ack/id",
|
||||
this.client.api.put(
|
||||
`/channels/${this._id}/ack/${id as ''}`,
|
||||
);
|
||||
};
|
||||
|
||||
@@ -623,12 +615,11 @@ export class Channel {
|
||||
/**
|
||||
* Set role permissions
|
||||
* @param role_id Role Id, set to 'default' to affect all users
|
||||
* @param permissions Permission number, removes permission if unset
|
||||
* @param permissions Permission value
|
||||
*/
|
||||
async setPermissions(role_id = "default", permissions?: number) {
|
||||
return await this.client.req(
|
||||
"PUT",
|
||||
`/channels/${this._id}/permissions/${role_id}` as "/channels/id/permissions/id",
|
||||
async setPermissions(role_id = "default", permissions: Override) {
|
||||
return await this.client.api.put(
|
||||
`/channels/${this._id}/permissions/${role_id as ''}`,
|
||||
{ permissions },
|
||||
);
|
||||
}
|
||||
@@ -652,33 +643,41 @@ export class Channel {
|
||||
}
|
||||
|
||||
@computed get permission() {
|
||||
// 1. Check channel type.
|
||||
switch (this.channel_type) {
|
||||
case "SavedMessages":
|
||||
return U32_MAX;
|
||||
return Permission.GrantAllSafe;
|
||||
case "DirectMessage": {
|
||||
// 2. Determine user permissions.
|
||||
const user_permissions = this.recipient?.permission || 0;
|
||||
|
||||
// 3. Check if the user can send messages.
|
||||
if (user_permissions & UserPermission.SendMessage) {
|
||||
return DEFAULT_PERMISSION_DM;
|
||||
return DEFAULT_PERMISSION_DIRECT_MESSAGE;
|
||||
} else {
|
||||
return 0;
|
||||
return DEFAULT_PERMISSION_VIEW_ONLY;
|
||||
}
|
||||
}
|
||||
case "Group": {
|
||||
// 2. Check if user is owner.
|
||||
if (this.owner_id === this.client.user!._id) {
|
||||
return DEFAULT_PERMISSION_DM;
|
||||
return DEFAULT_PERMISSION_DIRECT_MESSAGE;
|
||||
} else {
|
||||
return this.permissions ?? DEFAULT_PERMISSION_DM;
|
||||
// 3. Pull out group permissions.
|
||||
return this.permissions ?? DEFAULT_PERMISSION_DIRECT_MESSAGE;
|
||||
}
|
||||
}
|
||||
case "TextChannel":
|
||||
case "VoiceChannel": {
|
||||
// 2. Get server.
|
||||
const server = this.server;
|
||||
if (typeof server === "undefined") return 0;
|
||||
|
||||
// 3. If server owner, just grant all permissions.
|
||||
if (server.owner === this.client.user?._id) {
|
||||
return U32_MAX;
|
||||
return Permission.GrantAllSafe;
|
||||
} else {
|
||||
// 4. Get member.
|
||||
const member = this.client.members.getKey({
|
||||
user: this.client.user!._id,
|
||||
server: server._id,
|
||||
@@ -686,16 +685,28 @@ export class Channel {
|
||||
|
||||
if (!member) return 0;
|
||||
|
||||
let perm =
|
||||
(this.default_permissions ??
|
||||
server.default_permissions[1]) >>> 0;
|
||||
// 5. Calculate server base permissions.
|
||||
let perm = server.permission;
|
||||
|
||||
if (member.roles) {
|
||||
for (const role of member.roles) {
|
||||
perm |= (this.role_permissions?.[role] ?? 0) >>> 0;
|
||||
perm |=
|
||||
(server.roles?.[role].permissions[1] ?? 0) >>>
|
||||
0;
|
||||
// 6. Apply default allows and denies for channel.
|
||||
if (this.default_permissions) {
|
||||
perm |= this.default_permissions.a;
|
||||
perm &= ~this.default_permissions.d;
|
||||
}
|
||||
|
||||
// 7. If user has roles, iterate in order.
|
||||
if (member.roles && this.role_permissions && server.roles) {
|
||||
// 5. Apply allows and denies from roles.
|
||||
const roles = member
|
||||
.orderedRoles
|
||||
.map(([id]) => id);
|
||||
|
||||
for (const id of roles) {
|
||||
const override = this.role_permissions[id];
|
||||
if (override) {
|
||||
perm |= override.a;
|
||||
perm &= ~override.d;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -718,6 +729,23 @@ export default class Channels extends Collection<string, Channel> {
|
||||
return channel;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether a channel should currently exist
|
||||
* @param id Channel ID
|
||||
* @returns Whether it should current exist
|
||||
*/
|
||||
exists(id: string) {
|
||||
const channel = this.get(id);
|
||||
if (channel) {
|
||||
switch (channel.channel_type) {
|
||||
case 'DirectMessage': return channel.active;
|
||||
default: return true;
|
||||
}
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch a channel
|
||||
* @param id Channel ID
|
||||
@@ -727,7 +755,7 @@ export default class Channels extends Collection<string, Channel> {
|
||||
if (this.has(id)) return this.$get(id);
|
||||
const res =
|
||||
data ??
|
||||
(await this.client.req("GET", `/channels/${id}` as "/channels/id"));
|
||||
(await this.client.api.get(`/channels/${id as ''}`));
|
||||
return this.createObj(res);
|
||||
}
|
||||
|
||||
@@ -755,8 +783,8 @@ export default class Channels extends Collection<string, Channel> {
|
||||
* @param data Group create route data
|
||||
* @returns The newly-created group
|
||||
*/
|
||||
async createGroup(data: Route<"POST", "/channels/create">["data"]) {
|
||||
const group = await this.client.req("POST", `/channels/create`, data);
|
||||
async createGroup(data: DataCreateGroup) {
|
||||
const group = await this.client.api.post(`/channels/create`, data);
|
||||
return (await this.fetch(group._id, group))!;
|
||||
}
|
||||
}
|
||||
|
||||
+40
-19
@@ -1,9 +1,11 @@
|
||||
import type {
|
||||
DataMemberEdit,
|
||||
FieldsMember,
|
||||
Member as MemberI,
|
||||
MemberCompositeKey,
|
||||
} from "revolt-api/types/Servers";
|
||||
import type { RemoveMemberField, Route } from "../api/routes";
|
||||
import type { Attachment } from "revolt-api/types/Autumn";
|
||||
Role,
|
||||
} from "revolt-api";
|
||||
import type { File } from "revolt-api";
|
||||
|
||||
import { makeAutoObservable, runInAction, action, computed } from "mobx";
|
||||
import isEqual from "lodash.isequal";
|
||||
@@ -18,7 +20,7 @@ export class Member {
|
||||
_id: MemberCompositeKey;
|
||||
|
||||
nickname: Nullable<string> = null;
|
||||
avatar: Nullable<Attachment> = null;
|
||||
avatar: Nullable<File> = null;
|
||||
roles: Nullable<string[]> = null;
|
||||
|
||||
/**
|
||||
@@ -49,7 +51,7 @@ export class Member {
|
||||
});
|
||||
}
|
||||
|
||||
@action update(data: Partial<MemberI>, clear?: RemoveMemberField) {
|
||||
@action update(data: Partial<MemberI>, clear: FieldsMember[] = []) {
|
||||
const apply = (key: string) => {
|
||||
// This code has been tested.
|
||||
if (
|
||||
@@ -63,13 +65,15 @@ export class Member {
|
||||
}
|
||||
};
|
||||
|
||||
switch (clear) {
|
||||
case "Nickname":
|
||||
this.nickname = null;
|
||||
break;
|
||||
case "Avatar":
|
||||
this.avatar = null;
|
||||
break;
|
||||
for (const field of clear) {
|
||||
switch (field) {
|
||||
case "Nickname":
|
||||
this.nickname = null;
|
||||
break;
|
||||
case "Avatar":
|
||||
this.avatar = null;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
apply("nickname");
|
||||
@@ -82,10 +86,9 @@ export class Member {
|
||||
* @param data Member editing route data
|
||||
* @returns Server member object
|
||||
*/
|
||||
async edit(data: Route<"PATCH", "/servers/id/members/id">["data"]) {
|
||||
return await this.client.req(
|
||||
"PATCH",
|
||||
`/servers/${this._id.server}/members/${this._id.user}` as "/servers/id/members/id",
|
||||
async edit(data: DataMemberEdit) {
|
||||
return await this.client.api.patch(
|
||||
`/servers/${this._id.server as ''}/members/${this._id.user}`,
|
||||
data,
|
||||
);
|
||||
}
|
||||
@@ -95,12 +98,30 @@ export class Member {
|
||||
* @param user_id User ID
|
||||
*/
|
||||
async kick() {
|
||||
return await this.client.req(
|
||||
"DELETE",
|
||||
`/servers/${this._id.server}/members/${this._id.user}` as "/servers/id/members/id",
|
||||
return await this.client.api.delete(
|
||||
`/servers/${this._id.server}/members/${this._id.user as ''}`,
|
||||
);
|
||||
}
|
||||
|
||||
@computed get orderedRoles() {
|
||||
const member_roles = new Set(this.roles);
|
||||
const server = this.server!;
|
||||
|
||||
return Object.keys(server.roles ?? {})
|
||||
.filter(x => member_roles.has(x))
|
||||
.map(role_id => [role_id, server.roles![role_id]] as [ string, Role ])
|
||||
.sort(([, a], [, b]) => (b.rank || 0) - (a.rank || 0));
|
||||
}
|
||||
|
||||
@computed get hoistedRole() {
|
||||
const roles = this.orderedRoles;
|
||||
if (roles.length > 0) {
|
||||
return roles[roles.length - 1];
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@computed generateAvatarURL(...args: FileArgs) {
|
||||
return this.client.generateFileURL(this.avatar ?? undefined, ...args);
|
||||
}
|
||||
|
||||
+13
-14
@@ -1,11 +1,12 @@
|
||||
import type {
|
||||
DataEditMessage,
|
||||
DataMessageSend,
|
||||
Embed,
|
||||
Masquerade,
|
||||
Message as MessageI,
|
||||
SystemMessage,
|
||||
} from "revolt-api/types/Channels";
|
||||
import type { Attachment } from "revolt-api/types/Autumn";
|
||||
import type { Route } from "../api/routes";
|
||||
} from "revolt-api";
|
||||
import type { File } from "revolt-api";
|
||||
|
||||
import { makeAutoObservable, runInAction, action, computed } from "mobx";
|
||||
import isEqual from "lodash.isequal";
|
||||
@@ -24,7 +25,7 @@ export class Message {
|
||||
author_id: string;
|
||||
|
||||
content: string | SystemMessage;
|
||||
attachments: Nullable<Attachment[]>;
|
||||
attachments: Nullable<File[]>;
|
||||
edited: Nullable<Date>;
|
||||
embeds: Nullable<Embed[]>;
|
||||
mention_ids: Nullable<string[]>;
|
||||
@@ -113,13 +114,13 @@ export class Message {
|
||||
constructor(client: Client, data: MessageI) {
|
||||
this.client = client;
|
||||
this._id = data._id;
|
||||
this.nonce = data.nonce;
|
||||
this.nonce = data.nonce ?? undefined;
|
||||
this.channel_id = data.channel;
|
||||
this.author_id = data.author;
|
||||
|
||||
this.content = data.content;
|
||||
this.attachments = toNullable(data.attachments);
|
||||
this.edited = toNullableDate(data.edited);
|
||||
this.edited = toNullableDate(data.edited as any);
|
||||
this.embeds = toNullable(data.embeds);
|
||||
this.mention_ids = toNullable(data.mentions);
|
||||
this.reply_ids = toNullable(data.replies);
|
||||
@@ -164,10 +165,9 @@ export class Message {
|
||||
* Edit a message
|
||||
* @param data Message edit route data
|
||||
*/
|
||||
async edit(data: Route<"PATCH", "/channels/id/messages/id">["data"]) {
|
||||
return await this.client.req(
|
||||
"PATCH",
|
||||
`/channels/${this.channel_id}/messages/${this._id}` as "/channels/id/messages/id",
|
||||
async edit(data: DataEditMessage) {
|
||||
return await this.client.api.patch(
|
||||
`/channels/${this.channel_id}/messages/${this._id as ''}`,
|
||||
data,
|
||||
);
|
||||
}
|
||||
@@ -176,9 +176,8 @@ export class Message {
|
||||
* Delete a message
|
||||
*/
|
||||
async delete() {
|
||||
return await this.client.req(
|
||||
"DELETE",
|
||||
`/channels/${this.channel_id}/messages/${this._id}` as "/channels/id/messages/id",
|
||||
return await this.client.api.delete(
|
||||
`/channels/${this.channel_id}/messages/${this._id as ''}`,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -195,7 +194,7 @@ export class Message {
|
||||
reply(
|
||||
data:
|
||||
| string
|
||||
| (Omit<Route<"POST", "/channels/id/messages">["data"], "nonce"> & {
|
||||
| (Omit<DataMessageSend, "nonce"> & {
|
||||
nonce?: string;
|
||||
}),
|
||||
mention = true,
|
||||
|
||||
+111
-85
@@ -1,24 +1,30 @@
|
||||
import type {
|
||||
Category,
|
||||
DataBanCreate,
|
||||
DataCreateChannel,
|
||||
DataCreateServer,
|
||||
DataEditRole,
|
||||
DataEditServer,
|
||||
FieldsServer,
|
||||
Member,
|
||||
PermissionTuple,
|
||||
Role,
|
||||
Server as ServerI,
|
||||
SystemMessageChannels,
|
||||
} from "revolt-api/types/Servers";
|
||||
import type { RemoveServerField, Route } from "../api/routes";
|
||||
import type { Attachment } from "revolt-api/types/Autumn";
|
||||
} from "revolt-api";
|
||||
import type { File } from "revolt-api";
|
||||
|
||||
import { makeAutoObservable, action, runInAction, computed } from "mobx";
|
||||
import isEqual from "lodash.isequal";
|
||||
|
||||
import { Nullable, toNullable } from "../util/null";
|
||||
import { U32_MAX } from "../api/permissions";
|
||||
import { Permission } from "../api/permissions";
|
||||
import Collection from "./Collection";
|
||||
import { User } from "./Users";
|
||||
import { Client, FileArgs } from "..";
|
||||
import { decodeTime } from "ulid";
|
||||
import { INotificationChecker } from "../util/Unreads";
|
||||
import { Override } from "revolt-api";
|
||||
import Long from "long";
|
||||
|
||||
export class Server {
|
||||
client: Client;
|
||||
@@ -33,16 +39,16 @@ export class Server {
|
||||
system_messages: Nullable<SystemMessageChannels> = null;
|
||||
|
||||
roles: Nullable<{ [key: string]: Role }> = null;
|
||||
default_permissions: PermissionTuple;
|
||||
default_permissions: number;
|
||||
|
||||
icon: Nullable<Attachment> = null;
|
||||
banner: Nullable<Attachment> = null;
|
||||
icon: Nullable<File> = null;
|
||||
banner: Nullable<File> = null;
|
||||
|
||||
nsfw: Nullable<boolean> = null;
|
||||
flags: Nullable<number> = null;
|
||||
|
||||
get channels() {
|
||||
return this.channel_ids.map((x) => this.client.channels.get(x));
|
||||
return this.channel_ids.map((x) => this.client.channels.get(x)).filter(x => x);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -66,6 +72,23 @@ export class Server {
|
||||
return this.client.configuration?.app + this.path;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get an ordered array of roles with their IDs attached.
|
||||
* The highest ranking roles will be first followed by lower
|
||||
* ranking roles. This is dictated by the "rank" property
|
||||
* which is smaller for higher priority roles.
|
||||
*/
|
||||
@computed get orderedRoles() {
|
||||
return Object.keys(this.roles ?? {})
|
||||
.map(id => {
|
||||
return {
|
||||
id,
|
||||
...this.roles![id]
|
||||
}
|
||||
})
|
||||
.sort((b, a) => (b.rank || 0) - (a.rank || 0));
|
||||
}
|
||||
|
||||
@computed isUnread(permit?: INotificationChecker) {
|
||||
if (permit?.isMuted(this)) return false;
|
||||
return this.channels.find((channel) =>
|
||||
@@ -108,7 +131,7 @@ export class Server {
|
||||
});
|
||||
}
|
||||
|
||||
@action update(data: Partial<ServerI>, clear?: RemoveServerField) {
|
||||
@action update(data: Partial<ServerI>, clear: FieldsServer[] = []) {
|
||||
const apply = (key: string, target?: string) => {
|
||||
// This code has been tested.
|
||||
if (
|
||||
@@ -122,16 +145,18 @@ export class Server {
|
||||
}
|
||||
};
|
||||
|
||||
switch (clear) {
|
||||
case "Banner":
|
||||
this.banner = null;
|
||||
break;
|
||||
case "Description":
|
||||
this.description = null;
|
||||
break;
|
||||
case "Icon":
|
||||
this.icon = null;
|
||||
break;
|
||||
for (const entry of clear) {
|
||||
switch (entry) {
|
||||
case "Banner":
|
||||
this.banner = null;
|
||||
break;
|
||||
case "Description":
|
||||
this.description = null;
|
||||
break;
|
||||
case "Icon":
|
||||
this.icon = null;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
apply("owner");
|
||||
@@ -153,10 +178,9 @@ export class Server {
|
||||
* @param data Channel create route data
|
||||
* @returns The newly-created channel
|
||||
*/
|
||||
async createChannel(data: Route<"POST", "/servers/id/channels">["data"]) {
|
||||
return await this.client.req(
|
||||
"POST",
|
||||
`/servers/${this._id}/channels` as "/servers/id/channels",
|
||||
async createChannel(data: DataCreateChannel) {
|
||||
return await this.client.api.post(
|
||||
`/servers/${this._id}/channels`,
|
||||
data,
|
||||
);
|
||||
}
|
||||
@@ -165,10 +189,9 @@ export class Server {
|
||||
* Edit a server
|
||||
* @param data Server editing route data
|
||||
*/
|
||||
async edit(data: Route<"PATCH", "/servers/id">["data"]) {
|
||||
return await this.client.req(
|
||||
"PATCH",
|
||||
`/servers/${this._id}` as "/servers/id",
|
||||
async edit(data: DataEditServer) {
|
||||
return await this.client.api.patch(
|
||||
`/servers/${this._id}`,
|
||||
data,
|
||||
);
|
||||
}
|
||||
@@ -178,9 +201,8 @@ export class Server {
|
||||
*/
|
||||
async delete(avoidReq?: boolean) {
|
||||
if (!avoidReq)
|
||||
await this.client.req(
|
||||
"DELETE",
|
||||
`/servers/${this._id}` as "/servers/id",
|
||||
await this.client.api.delete(
|
||||
`/servers/${this._id}`,
|
||||
);
|
||||
|
||||
runInAction(() => {
|
||||
@@ -192,9 +214,8 @@ export class Server {
|
||||
* Mark a server as read
|
||||
*/
|
||||
async ack() {
|
||||
return await this.client.req(
|
||||
"PUT",
|
||||
`/servers/${this._id}/ack` as "/servers/id/ack",
|
||||
return await this.client.api.put(
|
||||
`/servers/${this._id}/ack`,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -204,11 +225,10 @@ export class Server {
|
||||
*/
|
||||
async banUser(
|
||||
user_id: string,
|
||||
data: Route<"PUT", "/servers/id/bans/id">["data"],
|
||||
data: DataBanCreate,
|
||||
) {
|
||||
return await this.client.req(
|
||||
"PUT",
|
||||
`/servers/${this._id}/bans/${user_id}` as "/servers/id/bans/id",
|
||||
return await this.client.api.put(
|
||||
`/servers/${this._id as ''}/bans/${user_id}`,
|
||||
data,
|
||||
);
|
||||
}
|
||||
@@ -218,9 +238,8 @@ export class Server {
|
||||
* @param user_id User ID
|
||||
*/
|
||||
async unbanUser(user_id: string) {
|
||||
return await this.client.req(
|
||||
"DELETE",
|
||||
`/servers/${this._id}/bans/${user_id}` as "/servers/id/bans/id",
|
||||
return await this.client.api.delete(
|
||||
`/servers/${this._id as ''}/bans/${user_id}`,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -229,9 +248,8 @@ export class Server {
|
||||
* @returns An array of the server's invites
|
||||
*/
|
||||
async fetchInvites() {
|
||||
return await this.client.req(
|
||||
"GET",
|
||||
`/servers/${this._id}/invites` as "/servers/id/invites",
|
||||
return await this.client.api.get(
|
||||
`/servers/${this._id}/invites`,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -240,25 +258,23 @@ export class Server {
|
||||
* @returns An array of the server's bans.
|
||||
*/
|
||||
async fetchBans() {
|
||||
return await this.client.req(
|
||||
"GET",
|
||||
`/servers/${this._id}/bans` as "/servers/id/bans",
|
||||
return await this.client.api.get(
|
||||
`/servers/${this._id}/bans`
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set role permissions
|
||||
* @param role_id Role Id, set to 'default' to affect all users
|
||||
* @param permissions Permission number, removes permission if unset
|
||||
* @param permissions Permission value
|
||||
*/
|
||||
async setPermissions(
|
||||
role_id = "default",
|
||||
permissions?: { server: number; channel: number },
|
||||
permissions: Override | number
|
||||
) {
|
||||
return await this.client.req(
|
||||
"PUT",
|
||||
`/servers/${this._id}/permissions/${role_id}` as "/servers/id/permissions/id",
|
||||
{ permissions },
|
||||
return await this.client.api.put(
|
||||
`/servers/${this._id}/permissions/${role_id as ''}`,
|
||||
{ permissions: permissions as Override },
|
||||
);
|
||||
}
|
||||
|
||||
@@ -267,9 +283,8 @@ export class Server {
|
||||
* @param name Role name
|
||||
*/
|
||||
async createRole(name: string) {
|
||||
return await this.client.req(
|
||||
"POST",
|
||||
`/servers/${this._id}/roles` as "/servers/id/roles",
|
||||
return await this.client.api.post(
|
||||
`/servers/${this._id}/roles`,
|
||||
{ name },
|
||||
);
|
||||
}
|
||||
@@ -281,11 +296,10 @@ export class Server {
|
||||
*/
|
||||
async editRole(
|
||||
role_id: string,
|
||||
data: Route<"PATCH", "/servers/id/roles/id">["data"],
|
||||
data: DataEditRole,
|
||||
) {
|
||||
return await this.client.req(
|
||||
"PATCH",
|
||||
`/servers/${this._id}/roles/${role_id}` as "/servers/id/roles/id",
|
||||
return await this.client.api.patch(
|
||||
`/servers/${this._id}/roles/${role_id as ''}`,
|
||||
data,
|
||||
);
|
||||
}
|
||||
@@ -295,9 +309,8 @@ export class Server {
|
||||
* @param role_id Role ID
|
||||
*/
|
||||
async deleteRole(role_id: string) {
|
||||
return await this.client.req(
|
||||
"DELETE",
|
||||
`/servers/${this._id}/roles/${role_id}` as "/servers/id/roles/id",
|
||||
return await this.client.api.delete(
|
||||
`/servers/${this._id}/roles/${role_id as ''}`,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -314,9 +327,8 @@ export class Server {
|
||||
});
|
||||
if (existing) return existing;
|
||||
|
||||
const member = await this.client.req(
|
||||
"GET",
|
||||
`/servers/${this._id}/members/${user_id}` as "/servers/id/members/id",
|
||||
const member = await this.client.api.get(
|
||||
`/servers/${this._id as ''}/members/${user_id as ''}`,
|
||||
);
|
||||
return this.client.members.createObj(member);
|
||||
}
|
||||
@@ -326,16 +338,10 @@ export class Server {
|
||||
* ! OPTIMISATION
|
||||
*/
|
||||
async syncMembers(skipOffline?: boolean) {
|
||||
const data = await this.client.req(
|
||||
"GET",
|
||||
`/servers/${this._id}/members` as "/servers/id/members",
|
||||
const data = await this.client.api.get(
|
||||
`/servers/${this._id as ''}/members`,
|
||||
);
|
||||
|
||||
// ! FIXME: if we do this on the server, we can save 7ms locally
|
||||
// 7ms to sort both lists.
|
||||
// data.users.sort((a,b)=>b._id.localeCompare(a._id));
|
||||
// data.members.sort((a,b)=>b._id.user.localeCompare(a._id.user));
|
||||
|
||||
// This takes roughly 23ms.
|
||||
runInAction(() => {
|
||||
// This adds roughly 15ms to 23ms above.
|
||||
@@ -378,9 +384,8 @@ export class Server {
|
||||
* @returns An array of the server's members and their user objects.
|
||||
*/
|
||||
async fetchMembers() {
|
||||
const data = await this.client.req(
|
||||
"GET",
|
||||
`/servers/${this._id}/members` as "/servers/id/members",
|
||||
const data = await this.client.api.get(
|
||||
`/servers/${this._id as ''}/members`,
|
||||
);
|
||||
|
||||
// Note: this takes 986 ms (Testers server)
|
||||
@@ -401,9 +406,11 @@ export class Server {
|
||||
}
|
||||
|
||||
@computed get permission() {
|
||||
// 1. Check if owner.
|
||||
if (this.owner === this.client.user?._id) {
|
||||
return U32_MAX;
|
||||
return Permission.GrantAllSafe;
|
||||
} else {
|
||||
// 2. Get member.
|
||||
const member = this.client.members.getKey({
|
||||
user: this.client.user!._id,
|
||||
server: this._id,
|
||||
@@ -411,16 +418,35 @@ export class Server {
|
||||
|
||||
if (!member) return 0;
|
||||
|
||||
let perm = this.default_permissions[0] >>> 0;
|
||||
if (member.roles) {
|
||||
for (const role of member.roles) {
|
||||
perm |= (this.roles?.[role].permissions[0] ?? 0) >>> 0;
|
||||
// 3. Apply allows from default_permissions.
|
||||
let perm = this.default_permissions;
|
||||
|
||||
// 4. If user has roles, iterate in order.
|
||||
if (member.roles && this.roles) {
|
||||
// 5. Apply allows and denies from roles.
|
||||
const permissions = member
|
||||
.orderedRoles
|
||||
.map(([, role]) => role.permissions);
|
||||
|
||||
for (const permission of permissions) {
|
||||
perm |= permission.a;
|
||||
perm &= ~permission.d;
|
||||
}
|
||||
}
|
||||
|
||||
return perm;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if we have a certain permission in a server.
|
||||
* @param permission Relevant permission string
|
||||
*/
|
||||
havePermission(permission: keyof typeof Permission) {
|
||||
return Long.fromNumber(this.permission)
|
||||
.and(Permission[permission])
|
||||
.eq(Permission[permission]);
|
||||
}
|
||||
}
|
||||
|
||||
export default class Servers extends Collection<string, Server> {
|
||||
@@ -444,7 +470,7 @@ export default class Servers extends Collection<string, Server> {
|
||||
if (this.has(id)) return this.$get(id, data);
|
||||
const res =
|
||||
data ??
|
||||
(await this.client.req("GET", `/servers/${id}` as "/servers/id"));
|
||||
(await this.client.api.get(`/servers/${id as ''}`));
|
||||
|
||||
return runInAction(async () => {
|
||||
for (const channel of res.channels) {
|
||||
@@ -482,8 +508,8 @@ export default class Servers extends Collection<string, Server> {
|
||||
* @param data Server create route data
|
||||
* @returns The newly-created server
|
||||
*/
|
||||
async createServer(data: Route<"POST", "/servers/create">["data"]) {
|
||||
const server = await this.client.req("POST", `/servers/create`, data);
|
||||
async createServer(data: DataCreateServer) {
|
||||
const server = await this.client.api.post(`/servers/create`, data);
|
||||
return this.fetch(server._id, server);
|
||||
}
|
||||
}
|
||||
|
||||
+47
-63
@@ -1,10 +1,12 @@
|
||||
import type {
|
||||
BotInformation,
|
||||
Status,
|
||||
UserStatus,
|
||||
User as UserI,
|
||||
} from "revolt-api/types/Users";
|
||||
import type { RemoveUserField, Route } from "../api/routes";
|
||||
import type { Attachment } from "revolt-api/types/Autumn";
|
||||
RelationshipStatus,
|
||||
FieldsUser,
|
||||
DataEditUser,
|
||||
} from "revolt-api";
|
||||
import type { File } from "revolt-api";
|
||||
|
||||
import { makeAutoObservable, action, runInAction, computed } from "mobx";
|
||||
import isEqual from "lodash.isequal";
|
||||
@@ -16,25 +18,15 @@ import { Client, FileArgs } from "..";
|
||||
import _ from "lodash";
|
||||
import { decodeTime } from "ulid";
|
||||
|
||||
enum RelationshipStatus {
|
||||
None = "None",
|
||||
User = "User",
|
||||
Friend = "Friend",
|
||||
Outgoing = "Outgoing",
|
||||
Incoming = "Incoming",
|
||||
Blocked = "Blocked",
|
||||
BlockedOther = "BlockedOther",
|
||||
}
|
||||
|
||||
export class User {
|
||||
client: Client;
|
||||
|
||||
_id: string;
|
||||
username: string;
|
||||
|
||||
avatar: Nullable<Attachment>;
|
||||
avatar: Nullable<File>;
|
||||
badges: Nullable<number>;
|
||||
status: Nullable<Status>;
|
||||
status: Nullable<UserStatus>;
|
||||
relationship: Nullable<RelationshipStatus>;
|
||||
online: Nullable<boolean>;
|
||||
flags: Nullable<number>;
|
||||
@@ -67,7 +59,7 @@ export class User {
|
||||
});
|
||||
}
|
||||
|
||||
@action update(data: Partial<UserI>, clear?: RemoveUserField) {
|
||||
@action update(data: Partial<UserI>, clear: FieldsUser[] = []) {
|
||||
const apply = (key: string) => {
|
||||
// This code has been tested.
|
||||
if (
|
||||
@@ -85,13 +77,15 @@ export class User {
|
||||
}
|
||||
};
|
||||
|
||||
switch (clear) {
|
||||
case "Avatar":
|
||||
this.avatar = null;
|
||||
break;
|
||||
case "StatusText": {
|
||||
if (this.status) {
|
||||
this.status.text = undefined;
|
||||
for (const entry of clear) {
|
||||
switch (entry) {
|
||||
case "Avatar":
|
||||
this.avatar = null;
|
||||
break;
|
||||
case "StatusText": {
|
||||
if (this.status) {
|
||||
this.status.text = undefined;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -111,51 +105,46 @@ export class User {
|
||||
* @returns DM Channel
|
||||
*/
|
||||
async openDM() {
|
||||
const dm = await this.client.req(
|
||||
"GET",
|
||||
`/users/${this._id}/dm` as "/users/id/dm",
|
||||
);
|
||||
return (await this.client.channels.fetch(dm._id, dm))!;
|
||||
let dm = [...this.client.channels.values()].find(x => x.channel_type === 'DirectMessage' && x.recipient == this);
|
||||
|
||||
if (!dm) {
|
||||
const data = await this.client.api.get(`/users/${this._id as ''}/dm`);
|
||||
dm = await this.client.channels.fetch(data._id, data)!;
|
||||
}
|
||||
|
||||
runInAction(() => {
|
||||
dm!.active = true;
|
||||
});
|
||||
|
||||
return dm;
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a friend request to a user
|
||||
*/
|
||||
async addFriend() {
|
||||
await this.client.req(
|
||||
"PUT",
|
||||
`/users/${this.username}/friend` as "/users/id/friend",
|
||||
);
|
||||
await this.client.api.put(`/users/${this.username as ''}/friend`);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove a user from the friend list
|
||||
*/
|
||||
async removeFriend() {
|
||||
await this.client.req(
|
||||
"DELETE",
|
||||
`/users/${this._id}/friend` as "/users/id/friend",
|
||||
);
|
||||
await this.client.api.delete(`/users/${this._id}/friend`);
|
||||
}
|
||||
|
||||
/**
|
||||
* Block a user
|
||||
*/
|
||||
async blockUser() {
|
||||
await this.client.req(
|
||||
"PUT",
|
||||
`/users/${this._id}/block` as "/users/id/block",
|
||||
);
|
||||
await this.client.api.put(`/users/${this._id}/block`);
|
||||
}
|
||||
|
||||
/**
|
||||
* Unblock a user
|
||||
*/
|
||||
async unblockUser() {
|
||||
await this.client.req(
|
||||
"DELETE",
|
||||
`/users/${this._id}/block` as "/users/id/block",
|
||||
);
|
||||
await this.client.api.delete(`/users/${this._id}/block`);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -163,10 +152,7 @@ export class User {
|
||||
* @returns The profile of the user
|
||||
*/
|
||||
async fetchProfile() {
|
||||
return await this.client.req(
|
||||
"GET",
|
||||
`/users/${this._id}/profile` as "/users/id/profile",
|
||||
);
|
||||
return await this.client.api.get(`/users/${this._id}/profile`);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -174,10 +160,7 @@ export class User {
|
||||
* @returns The mutual connections of the current user and a target user
|
||||
*/
|
||||
async fetchMutual() {
|
||||
return await this.client.req(
|
||||
"GET",
|
||||
`/users/${this._id}/mutual` as "/users/id/mutual",
|
||||
);
|
||||
return await this.client.api.get(`/users/${this._id}/mutual`);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -197,14 +180,14 @@ export class User {
|
||||
@computed get permission() {
|
||||
let permissions = 0;
|
||||
switch (this.relationship) {
|
||||
case RelationshipStatus.Friend:
|
||||
case RelationshipStatus.User:
|
||||
case 'Friend':
|
||||
case 'User':
|
||||
return U32_MAX;
|
||||
case RelationshipStatus.Blocked:
|
||||
case RelationshipStatus.BlockedOther:
|
||||
case 'Blocked':
|
||||
case 'BlockedOther':
|
||||
return UserPermission.Access;
|
||||
case RelationshipStatus.Incoming:
|
||||
case RelationshipStatus.Outgoing:
|
||||
case 'Incoming':
|
||||
case 'Outgoing':
|
||||
permissions = UserPermission.Access;
|
||||
}
|
||||
|
||||
@@ -254,7 +237,8 @@ export default class Users extends Collection<string, User> {
|
||||
if (this.has(id)) return this.$get(id, data);
|
||||
const res =
|
||||
data ??
|
||||
(await this.client.req("GET", `/users/${id}` as "/users/id"));
|
||||
(await this.client.api.get(`/users/${id as ''}`));
|
||||
|
||||
return this.createObj(res);
|
||||
}
|
||||
|
||||
@@ -280,8 +264,8 @@ export default class Users extends Collection<string, User> {
|
||||
* Edit the current user
|
||||
* @param data User edit data object
|
||||
*/
|
||||
async edit(data: Route<"PATCH", "/users/id">["data"]) {
|
||||
await this.client.req("PATCH", "/users/id", data);
|
||||
async edit(data: DataEditUser) {
|
||||
await this.client.api.patch("/users/@me", data);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -290,7 +274,7 @@ export default class Users extends Collection<string, User> {
|
||||
* @param password Current password
|
||||
*/
|
||||
async changeUsername(username: string, password: string) {
|
||||
return await this.client.req("PATCH", "/users/id/username", {
|
||||
return await this.client.api.patch("/users/@me/username", {
|
||||
username,
|
||||
password,
|
||||
});
|
||||
|
||||
+10
-18
@@ -18,7 +18,6 @@ async function user() {
|
||||
|
||||
const group = await client.channels.createGroup({
|
||||
name: 'sussy',
|
||||
nonce: ''+Math.random(),
|
||||
users: []
|
||||
});
|
||||
|
||||
@@ -26,14 +25,13 @@ async function user() {
|
||||
content: "embed test",
|
||||
embeds: [
|
||||
{
|
||||
type: 'Text',
|
||||
title: 'We do a little!'
|
||||
}
|
||||
]
|
||||
});
|
||||
|
||||
await msg.edit({
|
||||
embeds: [{ type: 'Text', title: 'sus' }]
|
||||
embeds: [{ title: 'sus' }]
|
||||
});
|
||||
});
|
||||
|
||||
@@ -41,38 +39,32 @@ async function user() {
|
||||
if (message.content === "sus") {
|
||||
message.channel!.sendMessage("sus!");
|
||||
} else if (message.content === "bot") {
|
||||
const bot = await client.req("POST", "/bots/create", {
|
||||
const bot = await client.api.post("/bots/create", {
|
||||
name: "basedbot12",
|
||||
});
|
||||
message.channel!.sendMessage(JSON.stringify(bot));
|
||||
} else if (message.content === "my bots") {
|
||||
message.channel!.sendMessage(
|
||||
JSON.stringify(await client.req("GET", "/bots/@me")),
|
||||
JSON.stringify(await client.api.get("/bots/@me")),
|
||||
);
|
||||
} else if (message.content === "join bot") {
|
||||
await client.req(
|
||||
"POST",
|
||||
`/bots/01FCV7DCMRD9MT3JBYT5VEKVRD/invite` as "/bots/id/invite",
|
||||
await client.api.post(
|
||||
`/bots/${'01FCV7DCMRD9MT3JBYT5VEKVRD'}/invite`,
|
||||
{ group: message.channel_id },
|
||||
);
|
||||
// { server: '01FATEGMHEE2M1QGPA65NS6V8K' });
|
||||
} else if (message.content === "edit bot name") {
|
||||
await client.req(
|
||||
"PATCH",
|
||||
`/bots/01FCV7DCMRD9MT3JBYT5VEKVRD` as "/bots/id",
|
||||
await client.api.patch(
|
||||
`/bots/${'01FCV7DCMRD9MT3JBYT5VEKVRD'}`,
|
||||
{ name: "testingbkaka" },
|
||||
);
|
||||
} else if (message.content === "make bot public") {
|
||||
await client.req(
|
||||
"PATCH",
|
||||
`/bots/01FCV7DCMRD9MT3JBYT5VEKVRD` as "/bots/id",
|
||||
await client.api.patch(
|
||||
`/bots/${'01FCV7DCMRD9MT3JBYT5VEKVRD'}`,
|
||||
{ public: true },
|
||||
);
|
||||
} else if (message.content === "delete bot") {
|
||||
await client.req(
|
||||
"DELETE",
|
||||
`/bots/01FCV7DCMRD9MT3JBYT5VEKVRD` as "/bots/id",
|
||||
);
|
||||
await client.api.delete(`/bots/${'01FCV7DCMRD9MT3JBYT5VEKVRD'}`);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
+1
-1
@@ -6,7 +6,7 @@ import {
|
||||
ObservableMap,
|
||||
runInAction,
|
||||
} from "mobx";
|
||||
import type { ChannelUnread } from "revolt-api/types/Sync";
|
||||
import type { ChannelUnread } from "revolt-api";
|
||||
import { ulid } from "ulid";
|
||||
import { Channel } from "../maps/Channels";
|
||||
import { Server } from "../maps/Servers";
|
||||
|
||||
+31
-14
@@ -1,7 +1,7 @@
|
||||
import { backOff } from "@insertish/exponential-backoff";
|
||||
import WebSocket from "@insertish/isomorphic-ws";
|
||||
import { runInAction } from "mobx";
|
||||
import { Role } from "revolt-api/types/Servers";
|
||||
import { Role } from "revolt-api";
|
||||
|
||||
import { Client } from "..";
|
||||
import {
|
||||
@@ -105,16 +105,17 @@ export class WebSocketClient {
|
||||
}
|
||||
};
|
||||
|
||||
const timeouts: Record<string, number> = {};
|
||||
const handle = async (msg: WebSocket.MessageEvent) => {
|
||||
const data = msg.data;
|
||||
if (typeof data !== "string") return;
|
||||
|
||||
if (this.client.debug) console.debug("[>] PACKET", data);
|
||||
const packet = JSON.parse(data) as ClientboundNotification;
|
||||
const process = async (packet: ClientboundNotification) => {
|
||||
this.client.emit("packet", packet);
|
||||
try {
|
||||
switch (packet.type) {
|
||||
case "Bulk": {
|
||||
for (const entry of packet.v) {
|
||||
await process(entry);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case "Error": {
|
||||
reject(packet.error);
|
||||
break;
|
||||
@@ -276,8 +277,9 @@ export class WebSocketClient {
|
||||
}
|
||||
|
||||
case "MessageDelete": {
|
||||
const msg = this.client.messages.get(packet.id);
|
||||
this.client.messages.delete(packet.id);
|
||||
this.client.emit("message/delete", packet.id);
|
||||
this.client.emit("message/delete", packet.id, msg);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -310,8 +312,9 @@ export class WebSocketClient {
|
||||
}
|
||||
|
||||
case "ChannelDelete": {
|
||||
this.client.channels.get(packet.id)?.delete(true);
|
||||
this.client.emit("channel/delete", packet.id);
|
||||
const channel = this.client.channels.get(packet.id);
|
||||
channel?.delete(true);
|
||||
this.client.emit("channel/delete", packet.id, channel);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -339,8 +342,9 @@ export class WebSocketClient {
|
||||
}
|
||||
|
||||
case "ServerDelete": {
|
||||
this.client.servers.get(packet.id)?.delete(true);
|
||||
this.client.emit("server/delete", packet.id);
|
||||
const server = this.client.servers.get(packet.id);
|
||||
server?.delete(true);
|
||||
this.client.emit("server/delete", packet.id, server);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -451,7 +455,10 @@ export class WebSocketClient {
|
||||
case "UserRelationship": {
|
||||
const user = this.client.users.get(packet.user._id);
|
||||
if (user) {
|
||||
user.update({ relationship: packet.status });
|
||||
user.update({
|
||||
...packet.user,
|
||||
relationship: packet.status
|
||||
});
|
||||
} else {
|
||||
this.client.users.createObj(packet.user);
|
||||
}
|
||||
@@ -507,6 +514,16 @@ export class WebSocketClient {
|
||||
}
|
||||
};
|
||||
|
||||
const timeouts: Record<string, number> = {};
|
||||
const handle = async (msg: WebSocket.MessageEvent) => {
|
||||
const data = msg.data;
|
||||
if (typeof data !== "string") return;
|
||||
|
||||
if (this.client.debug) console.debug("[>] PACKET", data);
|
||||
const packet = JSON.parse(data) as ClientboundNotification;
|
||||
await process(packet);
|
||||
};
|
||||
|
||||
let processing = false;
|
||||
const queue: WebSocket.MessageEvent[] = [];
|
||||
ws.onmessage = async (data) => {
|
||||
|
||||
@@ -1,20 +1,12 @@
|
||||
import type { Session } from "revolt-api/types/Auth";
|
||||
import type { Channel, Message } from "revolt-api/types/Channels";
|
||||
import type { FieldsChannel, FieldsMember, FieldsServer, FieldsUser, Session } from "revolt-api";
|
||||
import type { Channel, Message } from "revolt-api";
|
||||
import type {
|
||||
Member,
|
||||
MemberCompositeKey,
|
||||
Role,
|
||||
Server,
|
||||
} from "revolt-api/types/Servers";
|
||||
import type { UserSettings } from "revolt-api/types/Sync";
|
||||
import type { RelationshipStatus, User } from "revolt-api/types/Users";
|
||||
|
||||
import type {
|
||||
RemoveChannelField,
|
||||
RemoveServerField,
|
||||
RemoveUserField,
|
||||
RemoveMemberField,
|
||||
} from "../api/routes";
|
||||
} from "revolt-api";
|
||||
import type { RelationshipStatus, User } from "revolt-api";
|
||||
|
||||
type WebSocketError = {
|
||||
error:
|
||||
@@ -41,6 +33,7 @@ export type ReadyPacket = {
|
||||
};
|
||||
|
||||
export type ClientboundNotification =
|
||||
| { type: "Bulk"; v: ClientboundNotification[] }
|
||||
| { type: "Ping"; data: number }
|
||||
| { type: "Pong"; data: number }
|
||||
| ({ type: "Error" } & WebSocketError)
|
||||
@@ -59,7 +52,7 @@ export type ClientboundNotification =
|
||||
type: "ChannelUpdate";
|
||||
id: string;
|
||||
data: Partial<Channel>;
|
||||
clear?: RemoveChannelField;
|
||||
clear?: FieldsChannel[];
|
||||
}
|
||||
| { type: "ChannelDelete"; id: string }
|
||||
| { type: "ChannelGroupJoin"; id: string; user: string }
|
||||
@@ -71,14 +64,14 @@ export type ClientboundNotification =
|
||||
type: "ServerUpdate";
|
||||
id: string;
|
||||
data: Partial<Server>;
|
||||
clear?: RemoveServerField;
|
||||
clear?: FieldsServer[];
|
||||
}
|
||||
| { type: "ServerDelete"; id: string }
|
||||
| {
|
||||
type: "ServerMemberUpdate";
|
||||
id: MemberCompositeKey;
|
||||
data: Partial<Member>;
|
||||
clear?: RemoveMemberField;
|
||||
clear?: FieldsMember[];
|
||||
}
|
||||
| { type: "ServerMemberJoin"; id: string; user: string }
|
||||
| { type: "ServerMemberLeave"; id: string; user: string }
|
||||
@@ -93,8 +86,8 @@ export type ClientboundNotification =
|
||||
type: "UserUpdate";
|
||||
id: string;
|
||||
data: Partial<User>;
|
||||
clear?: RemoveUserField;
|
||||
clear?: FieldsUser[];
|
||||
}
|
||||
| { type: "UserRelationship"; user: User; status: RelationshipStatus }
|
||||
| { type: "UserPresence"; id: string; online: boolean }
|
||||
| { type: "UserSettingsUpdate"; id: string; update: UserSettings };
|
||||
| { type: "UserSettingsUpdate"; id: string; update: { [key: string]: [number, string] } };
|
||||
|
||||
@@ -41,6 +41,16 @@
|
||||
resolved "https://registry.yarnpkg.com/@insertish/isomorphic-ws/-/isomorphic-ws-4.0.1.tgz#5bcd6f73b93efa9ccdb6abf887ae808d40827169"
|
||||
integrity sha512-kFD/p8T4Hkqr992QrdkbW/cQ/W/q2d9MPCobwzBv2PwTKLkCD9RaYDy6m17qRnSLQQ5PU0kHCG8kaOwAqzj1vQ==
|
||||
|
||||
"@insertish/oapi@0.1.13":
|
||||
version "0.1.13"
|
||||
resolved "https://registry.yarnpkg.com/@insertish/oapi/-/oapi-0.1.13.tgz#92579172bd6896152e9b68ef5bafcf8cc2048492"
|
||||
integrity sha512-yj1Jk3VlNCjp0hNOsknevyR7PwVzSzc5pbUTuyhtyPlbuHRTv1b9DWs8Ki7xbF/mrIy2DzkHoUu4Ik/Q4oS93w==
|
||||
dependencies:
|
||||
typescript "^4.6.2"
|
||||
optionalDependencies:
|
||||
axios "^0.26.1"
|
||||
openapi-typescript "^5.2.0"
|
||||
|
||||
"@nodelib/fs.scandir@2.1.5":
|
||||
version "2.1.5"
|
||||
resolved "https://registry.yarnpkg.com/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz#7619c2eb21b25483f6d167548b4cfd5a7488c3d5"
|
||||
@@ -234,6 +244,13 @@ axios@^0.21.4:
|
||||
dependencies:
|
||||
follow-redirects "^1.14.0"
|
||||
|
||||
axios@^0.26.1:
|
||||
version "0.26.1"
|
||||
resolved "https://registry.yarnpkg.com/axios/-/axios-0.26.1.tgz#1ede41c51fcf51bbbd6fd43669caaa4f0495aaa9"
|
||||
integrity sha512-fPwcX4EvnSHuInCMItEhAGnaSEXRBjtzh9fOtsE6E1G6p7vl7edEeZe11QHf18+6+9gR5PbKV/sGKNaD8YaMeA==
|
||||
dependencies:
|
||||
follow-redirects "^1.14.8"
|
||||
|
||||
balanced-match@^1.0.0:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee"
|
||||
@@ -539,6 +556,11 @@ follow-redirects@^1.14.0:
|
||||
resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.14.7.tgz#2004c02eb9436eee9a21446a6477debf17e81685"
|
||||
integrity sha512-+hbxoLbFMbRKDwohX8GkTataGqO6Jb7jGwpAlwgy2bIz25XtRm7KEzJM76R1WiNT5SwZkX4Y75SwBolkpmE7iQ==
|
||||
|
||||
follow-redirects@^1.14.8:
|
||||
version "1.14.9"
|
||||
resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.14.9.tgz#dd4ea157de7bfaf9ea9b3fbd85aa16951f78d8d7"
|
||||
integrity sha512-MQDfihBQYMcyy5dhRDJUHcw7lb2Pv/TuE6xP1vyraLukNDHKbDxDNaOE3NbCAdKQApno+GPRyo1YAp89yCjK4w==
|
||||
|
||||
from@~0:
|
||||
version "0.1.7"
|
||||
resolved "https://registry.yarnpkg.com/from/-/from-0.1.7.tgz#83c60afc58b9c56997007ed1a768b3ab303a44fe"
|
||||
@@ -599,6 +621,11 @@ globals@^13.6.0, globals@^13.9.0:
|
||||
dependencies:
|
||||
type-fest "^0.20.2"
|
||||
|
||||
globalyzer@0.1.0:
|
||||
version "0.1.0"
|
||||
resolved "https://registry.yarnpkg.com/globalyzer/-/globalyzer-0.1.0.tgz#cb76da79555669a1519d5a8edf093afaa0bf1465"
|
||||
integrity sha512-40oNTM9UfG6aBmuKxk/giHn5nQ8RVz/SS4Ir6zgzOv9/qC3kKZ9v4etGTcJbEl/NyVQH7FGU7d+X1egr57Md2Q==
|
||||
|
||||
globby@^11.0.4:
|
||||
version "11.0.4"
|
||||
resolved "https://registry.yarnpkg.com/globby/-/globby-11.0.4.tgz#2cbaff77c2f2a62e71e9b2813a67b97a3a3001a5"
|
||||
@@ -611,6 +638,11 @@ globby@^11.0.4:
|
||||
merge2 "^1.3.0"
|
||||
slash "^3.0.0"
|
||||
|
||||
globrex@^0.1.2:
|
||||
version "0.1.2"
|
||||
resolved "https://registry.yarnpkg.com/globrex/-/globrex-0.1.2.tgz#dd5d9ec826232730cd6793a5e33a9302985e6098"
|
||||
integrity sha512-uHJgbwAMwNFf5mLst7IWLNg14x1CkeqglJb/K3doi4dw6q2IvAAmM/Y81kevy83wP+Sst+nutFTYOGg3d1lsxg==
|
||||
|
||||
handlebars@^4.7.7:
|
||||
version "4.7.7"
|
||||
resolved "https://registry.yarnpkg.com/handlebars/-/handlebars-4.7.7.tgz#9ce33416aad02dbd6c8fafa8240d5d98004945a1"
|
||||
@@ -768,6 +800,11 @@ lodash@^4.17.10:
|
||||
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c"
|
||||
integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==
|
||||
|
||||
long@^5.2.0:
|
||||
version "5.2.0"
|
||||
resolved "https://registry.yarnpkg.com/long/-/long-5.2.0.tgz#2696dadf4b4da2ce3f6f6b89186085d94d52fd61"
|
||||
integrity sha512-9RTUNjK60eJbx3uz+TEGF7fUr29ZDxR5QzXcyDpeSfeH28S9ycINflOgOlppit5U+4kNTe83KQnMEerw7GmE8w==
|
||||
|
||||
lru-cache@^5.1.1:
|
||||
version "5.1.1"
|
||||
resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-5.1.1.tgz#1da27e6710271947695daf6848e847f01d84b920"
|
||||
@@ -810,6 +847,11 @@ micromatch@^4.0.4:
|
||||
braces "^3.0.1"
|
||||
picomatch "^2.2.3"
|
||||
|
||||
mime@^3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.yarnpkg.com/mime/-/mime-3.0.0.tgz#b374550dca3a0c18443b0c950a6a58f1931cf7a7"
|
||||
integrity sha512-jSCU7/VB1loIWBZe14aEYHU/+1UMEHoaO7qxCOVJOw9GgH72VAWppxNcjU+x9a2k3GSIBXNKxXQFqRvvZ7vr3A==
|
||||
|
||||
minimatch@^3.0.0, minimatch@^3.0.4:
|
||||
version "3.0.4"
|
||||
resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083"
|
||||
@@ -866,6 +908,18 @@ onigasm@^2.2.5:
|
||||
dependencies:
|
||||
lru-cache "^5.1.1"
|
||||
|
||||
openapi-typescript@^5.2.0:
|
||||
version "5.2.0"
|
||||
resolved "https://registry.yarnpkg.com/openapi-typescript/-/openapi-typescript-5.2.0.tgz#c0712d7a17e4502ac083162c42f946c0e966a505"
|
||||
integrity sha512-EGoPTmxrpiN40R6An5Wqol2l74sRb773pv/KXWYCQaMCXNtMGN7Jv+y/jY4B1Bd4hsIW2j9GFmQXxqfGmOXaxA==
|
||||
dependencies:
|
||||
js-yaml "^4.1.0"
|
||||
mime "^3.0.0"
|
||||
prettier "^2.5.1"
|
||||
tiny-glob "^0.2.9"
|
||||
undici "^4.14.1"
|
||||
yargs-parser "^21.0.0"
|
||||
|
||||
optionator@^0.9.1:
|
||||
version "0.9.1"
|
||||
resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.9.1.tgz#4f236a6373dae0566a6d43e1326674f50c291499"
|
||||
@@ -922,6 +976,11 @@ prettier@^2.4.1:
|
||||
resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.4.1.tgz#671e11c89c14a4cfc876ce564106c4a6726c9f5c"
|
||||
integrity sha512-9fbDAXSBcc6Bs1mZrDYb3XKzDLm4EXXL9sC1LqKP5rZkT6KRr/rf9amVUcODVXgguK/isJz0d0hP72WeaKWsvA==
|
||||
|
||||
prettier@^2.5.1:
|
||||
version "2.6.0"
|
||||
resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.6.0.tgz#12f8f504c4d8ddb76475f441337542fa799207d4"
|
||||
integrity sha512-m2FgJibYrBGGgQXNzfd0PuDGShJgRavjUoRCw1mZERIWVSXF0iLzLm+aOqTAbLnC3n6JzUhAA8uZnFVghHJ86A==
|
||||
|
||||
progress@^2.0.0, progress@^2.0.3:
|
||||
version "2.0.3"
|
||||
resolved "https://registry.yarnpkg.com/progress/-/progress-2.0.3.tgz#7e8cf8d8f5b8f239c1bc68beb4eb78567d572ef8"
|
||||
@@ -959,10 +1018,14 @@ reusify@^1.0.4:
|
||||
resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76"
|
||||
integrity sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==
|
||||
|
||||
revolt-api@0.5.3-alpha.12:
|
||||
version "0.5.3-alpha.12"
|
||||
resolved "https://registry.yarnpkg.com/revolt-api/-/revolt-api-0.5.3-alpha.12.tgz#78f25b567b840c1fd072595526592a422cb01f25"
|
||||
integrity sha512-MM42oI5+5JJMnAs3JiOwSQOy/SUYzYs3M8YRC5QI4G6HU7CfyB2HNWh5jFsyRlcLdSi13dGazHm31FUPHsxOzw==
|
||||
revolt-api@0.5.3-rc.7:
|
||||
version "0.5.3-rc.7"
|
||||
resolved "https://registry.yarnpkg.com/revolt-api/-/revolt-api-0.5.3-rc.7.tgz#eed82fcd014a25a4d080c4502c0ae4aa283adddb"
|
||||
integrity sha512-72SJ+P19nRRD+xE8bXAV8mFZNBgtKkXogQACDvNSIdATUmszYl91YRPqX+UQ1Oz4ePgKFwyWPxrnmfede7Q83g==
|
||||
dependencies:
|
||||
"@insertish/oapi" "0.1.13"
|
||||
axios "^0.26.1"
|
||||
lodash.defaultsdeep "^4.6.1"
|
||||
|
||||
rimraf@^3.0.2:
|
||||
version "3.0.2"
|
||||
@@ -1071,6 +1134,14 @@ through@2, through@~2.3, through@~2.3.1:
|
||||
resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5"
|
||||
integrity sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=
|
||||
|
||||
tiny-glob@^0.2.9:
|
||||
version "0.2.9"
|
||||
resolved "https://registry.yarnpkg.com/tiny-glob/-/tiny-glob-0.2.9.tgz#2212d441ac17928033b110f8b3640683129d31e2"
|
||||
integrity sha512-g/55ssRPUjShh+xkfx9UPDXqhckHEsHr4Vd9zX55oSdGZc/MD0m3sferOkwWtp98bv+kcVfEHtRJgBVJzelrzg==
|
||||
dependencies:
|
||||
globalyzer "0.1.0"
|
||||
globrex "^0.1.2"
|
||||
|
||||
to-regex-range@^5.0.1:
|
||||
version "5.0.1"
|
||||
resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4"
|
||||
@@ -1137,6 +1208,11 @@ typescript@^4.4.4:
|
||||
resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.4.4.tgz#2cd01a1a1f160704d3101fd5a58ff0f9fcb8030c"
|
||||
integrity sha512-DqGhF5IKoBl8WNf8C1gu8q0xZSInh9j1kJJMqT3a94w1JzVaBU4EXOSMrz9yDqMT0xt3selp83fuFMQ0uzv6qA==
|
||||
|
||||
typescript@^4.6.2:
|
||||
version "4.6.2"
|
||||
resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.6.2.tgz#fe12d2727b708f4eef40f51598b3398baa9611d4"
|
||||
integrity sha512-HM/hFigTBHZhLXshn9sN37H085+hQGeJHJ/X7LpBWLID/fbc2acUMfU+lGD98X81sKP+pFa9f0DZmCwB9GnbAg==
|
||||
|
||||
uglify-js@^3.1.4:
|
||||
version "3.13.10"
|
||||
resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.13.10.tgz#a6bd0d28d38f592c3adb6b180ea6e07e1e540a8d"
|
||||
@@ -1147,6 +1223,11 @@ ulid@^2.3.0:
|
||||
resolved "https://registry.yarnpkg.com/ulid/-/ulid-2.3.0.tgz#93063522771a9774121a84d126ecd3eb9804071f"
|
||||
integrity sha512-keqHubrlpvT6G2wH0OEfSW4mquYRcbe/J8NMmveoQOjUqmo+hXtO+ORCpWhdbZ7k72UtY61BL7haGxW6enBnjw==
|
||||
|
||||
undici@^4.14.1:
|
||||
version "4.16.0"
|
||||
resolved "https://registry.yarnpkg.com/undici/-/undici-4.16.0.tgz#469bb87b3b918818d3d7843d91a1d08da357d5ff"
|
||||
integrity sha512-tkZSECUYi+/T1i4u+4+lwZmQgLXd4BLGlrc7KZPcLIW7Jpq99+Xpc30ONv7nS6F5UNOxp/HBZSSL9MafUrvJbw==
|
||||
|
||||
uri-js@^4.2.2:
|
||||
version "4.4.1"
|
||||
resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.4.1.tgz#9b1a52595225859e55f669d928f88c6c57f2a77e"
|
||||
@@ -1200,3 +1281,8 @@ yallist@^4.0.0:
|
||||
version "4.0.0"
|
||||
resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72"
|
||||
integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==
|
||||
|
||||
yargs-parser@^21.0.0:
|
||||
version "21.0.1"
|
||||
resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-21.0.1.tgz#0267f286c877a4f0f728fceb6f8a3e4cb95c6e35"
|
||||
integrity sha512-9BK1jFpLzJROCI5TzwZL/TU4gqjK5xiHV/RfWLOahrjAko/e4DJkRDZQXfvqAsiZzzYhgAzbgz6lg48jcm4GLg==
|
||||
|
||||
Reference in New Issue
Block a user