mirror of
https://github.com/tiramisulabs/seyfert.git
synced 2025-07-02 04:56:07 +00:00
feat: remove dynamicAvatarURL, option exclude
added in GuildMember#avatarURL
This commit is contained in:
parent
9c2b37316a
commit
0fd02117ce
@ -1,83 +1,83 @@
|
||||
import { CDN_URL } from '../common';
|
||||
import type { APIRoutes, ApiHandler, CDNRoute } from './index';
|
||||
import type { HttpMethods, ImageExtension, ImageSize, StickerExtension } from './shared';
|
||||
|
||||
export enum ProxyRequestMethod {
|
||||
Delete = 'delete',
|
||||
Get = 'get',
|
||||
Patch = 'patch',
|
||||
Post = 'post',
|
||||
Put = 'put',
|
||||
}
|
||||
|
||||
const ArrRequestsMethods = Object.freeze(Object.values(ProxyRequestMethod)) as string[];
|
||||
|
||||
export class Router {
|
||||
noop = () => {
|
||||
return;
|
||||
};
|
||||
|
||||
constructor(private rest: ApiHandler) {}
|
||||
|
||||
createProxy(route = [] as string[]): APIRoutes {
|
||||
return new Proxy(this.noop, {
|
||||
get: (_, key: string) => {
|
||||
if (ArrRequestsMethods.includes(key)) {
|
||||
return (...options: any[]) =>
|
||||
this.rest.request(key.toUpperCase() as HttpMethods, `/${route.join('/')}`, ...options);
|
||||
}
|
||||
return this.createProxy([...route, key]);
|
||||
},
|
||||
apply: (...[, _, args]) => {
|
||||
return this.createProxy([...route, ...args]);
|
||||
},
|
||||
}) as unknown as APIRoutes;
|
||||
}
|
||||
}
|
||||
|
||||
export const CDNRouter = {
|
||||
createProxy(route = [] as string[]): CDNRoute {
|
||||
const noop = () => {
|
||||
return;
|
||||
};
|
||||
return new Proxy(noop, {
|
||||
get: (_, key: string) => {
|
||||
if (key === 'get') {
|
||||
return (value: string | CDNUrlOptions | undefined, options?: CDNUrlOptions) => {
|
||||
const lastRoute = `${CDN_URL}/${route.join('/')}`;
|
||||
let routeResult = lastRoute;
|
||||
if (typeof value === 'string') {
|
||||
routeResult = `${lastRoute}${value ? `/${value}` : ''}`;
|
||||
return parseCDNURL(routeResult, options);
|
||||
}
|
||||
return parseCDNURL(routeResult, value);
|
||||
};
|
||||
}
|
||||
return this.createProxy([...route, key]);
|
||||
},
|
||||
apply: (...[, _, args]) => {
|
||||
return this.createProxy([...route, ...args]);
|
||||
},
|
||||
}) as unknown as CDNRoute;
|
||||
},
|
||||
};
|
||||
|
||||
export interface BaseCDNUrlOptions {
|
||||
extension?: ImageExtension | StickerExtension | undefined;
|
||||
size?: ImageSize;
|
||||
}
|
||||
|
||||
export interface CDNUrlOptions extends BaseCDNUrlOptions {
|
||||
forceStatic?: boolean;
|
||||
}
|
||||
|
||||
export function parseCDNURL(route: string, options: CDNUrlOptions = {}) {
|
||||
if (options.forceStatic && route.includes('a_')) options.extension = 'png';
|
||||
if (!options.extension && route.includes('a_')) options.extension = 'gif';
|
||||
|
||||
const url = new URL(`${route}.${options.extension || 'png'}`);
|
||||
|
||||
if (options.size) url.searchParams.set('size', `${options.size}`);
|
||||
|
||||
return url.toString();
|
||||
}
|
||||
import { CDN_URL } from '../common';
|
||||
import type { APIRoutes, ApiHandler, CDNRoute } from './index';
|
||||
import type { HttpMethods, ImageExtension, ImageSize, StickerExtension } from './shared';
|
||||
|
||||
export enum ProxyRequestMethod {
|
||||
Delete = 'delete',
|
||||
Get = 'get',
|
||||
Patch = 'patch',
|
||||
Post = 'post',
|
||||
Put = 'put',
|
||||
}
|
||||
|
||||
const ArrRequestsMethods = Object.freeze(Object.values(ProxyRequestMethod)) as string[];
|
||||
|
||||
export class Router {
|
||||
noop = () => {
|
||||
return;
|
||||
};
|
||||
|
||||
constructor(private rest: ApiHandler) {}
|
||||
|
||||
createProxy(route = [] as string[]): APIRoutes {
|
||||
return new Proxy(this.noop, {
|
||||
get: (_, key: string) => {
|
||||
if (ArrRequestsMethods.includes(key)) {
|
||||
return (...options: any[]) =>
|
||||
this.rest.request(key.toUpperCase() as HttpMethods, `/${route.join('/')}`, ...options);
|
||||
}
|
||||
return this.createProxy([...route, key]);
|
||||
},
|
||||
apply: (...[, _, args]) => {
|
||||
return this.createProxy([...route, ...args]);
|
||||
},
|
||||
}) as unknown as APIRoutes;
|
||||
}
|
||||
}
|
||||
|
||||
export const CDNRouter = {
|
||||
createProxy(route = [] as string[]): CDNRoute {
|
||||
const noop = () => {
|
||||
return;
|
||||
};
|
||||
return new Proxy(noop, {
|
||||
get: (_, key: string) => {
|
||||
if (key === 'get') {
|
||||
return (value: string | CDNUrlOptions | undefined, options?: CDNUrlOptions) => {
|
||||
const lastRoute = `${CDN_URL}/${route.join('/')}`;
|
||||
let routeResult = lastRoute;
|
||||
if (typeof value === 'string' || typeof value === 'number') {
|
||||
routeResult = `${lastRoute}${value ? `/${value}` : ''}`;
|
||||
return parseCDNURL(routeResult, options);
|
||||
}
|
||||
return parseCDNURL(routeResult, value);
|
||||
};
|
||||
}
|
||||
return this.createProxy([...route, key]);
|
||||
},
|
||||
apply: (...[, _, args]) => {
|
||||
return this.createProxy([...route, ...args]);
|
||||
},
|
||||
}) as unknown as CDNRoute;
|
||||
},
|
||||
};
|
||||
|
||||
export interface BaseCDNUrlOptions {
|
||||
extension?: ImageExtension | StickerExtension | undefined;
|
||||
size?: ImageSize;
|
||||
}
|
||||
|
||||
export interface CDNUrlOptions extends BaseCDNUrlOptions {
|
||||
forceStatic?: boolean;
|
||||
}
|
||||
|
||||
export function parseCDNURL(route: string, options: CDNUrlOptions = {}) {
|
||||
if (options.forceStatic && route.includes('a_')) options.extension = 'png';
|
||||
if (!options.extension && route.includes('a_')) options.extension = 'gif';
|
||||
|
||||
const url = new URL(`${route}.${options.extension || 'png'}`);
|
||||
|
||||
if (options.size) url.searchParams.set('size', `${options.size}`);
|
||||
|
||||
return url.toString();
|
||||
}
|
||||
|
@ -266,6 +266,8 @@ export class CommandHandler extends BaseHandler {
|
||||
this.client.options?.commands?.defaults?.onPermissionsFail;
|
||||
option.botPermissions ??= commandInstance.botPermissions;
|
||||
option.defaultMemberPermissions ??= commandInstance.defaultMemberPermissions;
|
||||
option.contexts ??= commandInstance.contexts;
|
||||
option.integrationTypes ??= commandInstance.integrationTypes;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,257 +1,255 @@
|
||||
import { DiscordBase } from './extra/DiscordBase';
|
||||
|
||||
export type GuildMemberData =
|
||||
| APIGuildMember
|
||||
| GatewayGuildMemberUpdateDispatchData
|
||||
| GatewayGuildMemberAddDispatchData
|
||||
| APIInteractionDataResolvedGuildMember;
|
||||
|
||||
import type {
|
||||
APIGuildMember,
|
||||
APIInteractionDataResolvedGuildMember,
|
||||
APIUser,
|
||||
GatewayGuildMemberAddDispatchData,
|
||||
GatewayGuildMemberUpdateDispatchData,
|
||||
RESTGetAPIGuildMembersQuery,
|
||||
RESTGetAPIGuildMembersSearchQuery,
|
||||
RESTPatchAPIGuildMemberJSONBody,
|
||||
RESTPutAPIGuildBanJSONBody,
|
||||
RESTPutAPIGuildMemberJSONBody,
|
||||
} from 'discord-api-types/v10';
|
||||
import type { UsingClient } from '../commands';
|
||||
import type { MakeRequired, MessageCreateBodyRequest, ObjectToLower, ToClass } from '../common';
|
||||
import type { ImageOptions, MethodContext } from '../common/types/options';
|
||||
import type { GuildMemberResolvable } from '../common/types/resolvables';
|
||||
import { User } from './User';
|
||||
import { PermissionsBitField } from './extra/Permissions';
|
||||
|
||||
export type GatewayGuildMemberAddDispatchDataFixed<Pending extends boolean> = Pending extends true
|
||||
? Omit<GatewayGuildMemberAddDispatchData, 'user'> & { id: string }
|
||||
: MakeRequired<GatewayGuildMemberAddDispatchData, 'user'>;
|
||||
|
||||
export interface BaseGuildMember extends DiscordBase, ObjectToLower<Omit<APIGuildMember, 'user' | 'roles'>> {}
|
||||
export class BaseGuildMember extends DiscordBase {
|
||||
private _roles: string[];
|
||||
joinedTimestamp?: number;
|
||||
communicationDisabledUntilTimestamp?: number | null;
|
||||
constructor(
|
||||
client: UsingClient,
|
||||
data: GuildMemberData,
|
||||
id: string,
|
||||
/** the choosen guild id */
|
||||
readonly guildId: string,
|
||||
) {
|
||||
const { roles, ...dataN } = data;
|
||||
super(client, { ...dataN, id });
|
||||
this._roles = data.roles;
|
||||
this.patch(data);
|
||||
}
|
||||
|
||||
guild(force = false) {
|
||||
return this.client.guilds.fetch(this.id, force);
|
||||
}
|
||||
|
||||
fetch(force = false) {
|
||||
return this.client.members.fetch(this.guildId, this.id, force);
|
||||
}
|
||||
|
||||
ban(body?: RESTPutAPIGuildBanJSONBody, reason?: string) {
|
||||
return this.client.members.ban(this.guildId, this.id, body, reason);
|
||||
}
|
||||
|
||||
kick(reason?: string) {
|
||||
return this.client.members.kick(this.guildId, this.id, reason);
|
||||
}
|
||||
|
||||
edit(body: RESTPatchAPIGuildMemberJSONBody, reason?: string) {
|
||||
return this.client.members.edit(this.guildId, this.id, body, reason);
|
||||
}
|
||||
|
||||
presence() {
|
||||
return this.client.members.presence(this.id);
|
||||
}
|
||||
|
||||
voice() {
|
||||
return this.client.members.voice(this.guildId, this.id);
|
||||
}
|
||||
|
||||
toString() {
|
||||
return `<@${this.id}>`;
|
||||
}
|
||||
|
||||
private patch(data: GuildMemberData) {
|
||||
if ('joined_at' in data && data.joined_at) {
|
||||
this.joinedTimestamp = Date.parse(data.joined_at);
|
||||
}
|
||||
if ('communication_disabled_until' in data) {
|
||||
this.communicationDisabledUntilTimestamp = data.communication_disabled_until?.length
|
||||
? Date.parse(data.communication_disabled_until)
|
||||
: null;
|
||||
}
|
||||
}
|
||||
|
||||
get roles() {
|
||||
return {
|
||||
keys: Object.freeze(this._roles.concat(this.guildId)) as string[],
|
||||
list: (force = false) =>
|
||||
this.client.roles
|
||||
.list(this.guildId, force)
|
||||
.then(roles => roles.filter(role => this.roles.keys.includes(role.id))),
|
||||
add: (id: string) => this.client.members.addRole(this.guildId, this.id, id),
|
||||
remove: (id: string) => this.client.members.removeRole(this.guildId, this.id, id),
|
||||
permissions: (force = false) =>
|
||||
this.roles.list(force).then(roles => new PermissionsBitField(roles.map(x => BigInt(x.permissions.bits)))),
|
||||
sorted: (force = false) => this.roles.list(force).then(roles => roles.sort((a, b) => b.position - a.position)),
|
||||
highest: (force = false) => this.roles.sorted(force).then(roles => roles[0]),
|
||||
};
|
||||
}
|
||||
|
||||
static methods({ client, guildId }: MethodContext<{ guildId: string }>) {
|
||||
return {
|
||||
resolve: (resolve: GuildMemberResolvable) => client.members.resolve(guildId, resolve),
|
||||
search: (query?: RESTGetAPIGuildMembersSearchQuery) => client.members.search(guildId, query),
|
||||
unban: (id: string, body?: RESTPutAPIGuildBanJSONBody, reason?: string) =>
|
||||
client.members.unban(guildId, id, body, reason),
|
||||
ban: (id: string, body?: RESTPutAPIGuildBanJSONBody, reason?: string) =>
|
||||
client.members.ban(guildId, id, body, reason),
|
||||
kick: (id: string, reason?: string) => client.members.kick(guildId, id, reason),
|
||||
edit: (id: string, body: RESTPatchAPIGuildMemberJSONBody, reason?: string) =>
|
||||
client.members.edit(guildId, id, body, reason),
|
||||
add: (id: string, body: RESTPutAPIGuildMemberJSONBody) => client.members.add(guildId, id, body),
|
||||
fetch: (memberId: string, force = false) => client.members.fetch(guildId, memberId, force),
|
||||
list: (query?: RESTGetAPIGuildMembersQuery, force = false) => client.members.list(guildId, query, force),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
export interface GuildMember extends ObjectToLower<Omit<APIGuildMember, 'user' | 'roles'>> {}
|
||||
/**
|
||||
* Represents a guild member
|
||||
* @link https://discord.com/developers/docs/resources/guild#guild-member-object
|
||||
*/
|
||||
export class GuildMember extends BaseGuildMember {
|
||||
user: User;
|
||||
private __me?: GuildMember;
|
||||
constructor(
|
||||
client: UsingClient,
|
||||
data: GuildMemberData,
|
||||
user: APIUser | User,
|
||||
/** the choosen guild id */
|
||||
readonly guildId: string,
|
||||
) {
|
||||
super(client, data, user.id, guildId);
|
||||
this.user = user instanceof User ? user : new User(client, user);
|
||||
}
|
||||
|
||||
get tag() {
|
||||
return this.user.tag;
|
||||
}
|
||||
|
||||
get bot() {
|
||||
return this.user.bot;
|
||||
}
|
||||
|
||||
get name() {
|
||||
return this.user.name;
|
||||
}
|
||||
|
||||
get username() {
|
||||
return this.user.username;
|
||||
}
|
||||
|
||||
get globalName() {
|
||||
return this.user.globalName;
|
||||
}
|
||||
|
||||
/** gets the nickname or the username */
|
||||
get displayName() {
|
||||
return this.nick ?? this.globalName ?? this.username;
|
||||
}
|
||||
|
||||
dm(force = false) {
|
||||
return this.user.dm(force);
|
||||
}
|
||||
|
||||
write(body: MessageCreateBodyRequest) {
|
||||
return this.user.write(body);
|
||||
}
|
||||
|
||||
avatarURL(options?: ImageOptions) {
|
||||
if (!this.avatar) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return this.rest.cdn.guilds(this.guildId).users(this.id).avatars(this.avatar).get(options);
|
||||
}
|
||||
|
||||
dynamicAvatarURL(options?: ImageOptions) {
|
||||
if (!this.avatar) {
|
||||
return this.user.avatarURL(options);
|
||||
}
|
||||
|
||||
return this.rest.cdn.guilds(this.guildId).users(this.id).avatars(this.avatar).get(options);
|
||||
}
|
||||
|
||||
bannerURL(options?: ImageOptions) {
|
||||
return this.user.bannerURL(options);
|
||||
}
|
||||
|
||||
async fetchPermissions(force = false) {
|
||||
if ('permissions' in this) return this.permissions as PermissionsBitField;
|
||||
return this.roles.permissions(force);
|
||||
}
|
||||
|
||||
async manageable(force = false) {
|
||||
this.__me = await this.client.guilds.fetchSelf(this.guildId, force);
|
||||
const ownerId = (await this.client.guilds.fetch(this.guildId, force)).ownerId;
|
||||
if (this.user.id === ownerId) return false;
|
||||
if (this.user.id === this.client.botId) return false;
|
||||
if (this.client.botId === ownerId) return true;
|
||||
return (await this.__me!.roles.highest()).position > (await this.roles.highest(force)).position;
|
||||
}
|
||||
|
||||
async bannable(force = false) {
|
||||
return (await this.manageable(force)) && (await this.__me!.fetchPermissions(force)).has('BanMembers');
|
||||
}
|
||||
|
||||
async kickable(force = false) {
|
||||
return (await this.manageable(force)) && (await this.__me!.fetchPermissions(force)).has('KickMembers');
|
||||
}
|
||||
|
||||
async moderatable(force = false) {
|
||||
return (
|
||||
!(await this.roles.permissions(force)).has('Administrator') &&
|
||||
(await this.manageable(force)) &&
|
||||
(await this.__me!.fetchPermissions(force)).has('KickMembers')
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export interface UnavailableMember {
|
||||
pending: true;
|
||||
}
|
||||
|
||||
export class UnavailableMember extends BaseGuildMember {}
|
||||
|
||||
export interface InteractionGuildMember
|
||||
extends ObjectToLower<Omit<APIInteractionDataResolvedGuildMember, 'roles' | 'deaf' | 'mute' | 'permissions'>> {}
|
||||
/**
|
||||
* Represents a guild member
|
||||
* @link https://discord.com/developers/docs/resources/guild#guild-member-object
|
||||
*/
|
||||
export class InteractionGuildMember extends (GuildMember as unknown as ToClass<
|
||||
Omit<GuildMember, 'deaf' | 'mute'>,
|
||||
InteractionGuildMember
|
||||
>) {
|
||||
permissions: PermissionsBitField;
|
||||
constructor(
|
||||
client: UsingClient,
|
||||
data: APIInteractionDataResolvedGuildMember,
|
||||
user: APIUser | User,
|
||||
/** the choosen guild id */
|
||||
guildId: string,
|
||||
) {
|
||||
super(client, data, user, guildId);
|
||||
this.permissions = new PermissionsBitField(Number(data.permissions));
|
||||
}
|
||||
}
|
||||
import { DiscordBase } from './extra/DiscordBase';
|
||||
|
||||
export type GuildMemberData =
|
||||
| APIGuildMember
|
||||
| GatewayGuildMemberUpdateDispatchData
|
||||
| GatewayGuildMemberAddDispatchData
|
||||
| APIInteractionDataResolvedGuildMember;
|
||||
|
||||
import type {
|
||||
APIGuildMember,
|
||||
APIInteractionDataResolvedGuildMember,
|
||||
APIUser,
|
||||
GatewayGuildMemberAddDispatchData,
|
||||
GatewayGuildMemberUpdateDispatchData,
|
||||
RESTGetAPIGuildMembersQuery,
|
||||
RESTGetAPIGuildMembersSearchQuery,
|
||||
RESTPatchAPIGuildMemberJSONBody,
|
||||
RESTPutAPIGuildBanJSONBody,
|
||||
RESTPutAPIGuildMemberJSONBody,
|
||||
} from 'discord-api-types/v10';
|
||||
import type { UsingClient } from '../commands';
|
||||
import type { MakeRequired, MessageCreateBodyRequest, ObjectToLower, ToClass } from '../common';
|
||||
import type { ImageOptions, MethodContext } from '../common/types/options';
|
||||
import type { GuildMemberResolvable } from '../common/types/resolvables';
|
||||
import { User } from './User';
|
||||
import { PermissionsBitField } from './extra/Permissions';
|
||||
|
||||
export type GatewayGuildMemberAddDispatchDataFixed<Pending extends boolean> = Pending extends true
|
||||
? Omit<GatewayGuildMemberAddDispatchData, 'user'> & { id: string }
|
||||
: MakeRequired<GatewayGuildMemberAddDispatchData, 'user'>;
|
||||
|
||||
export interface BaseGuildMember extends DiscordBase, ObjectToLower<Omit<APIGuildMember, 'user' | 'roles'>> {}
|
||||
export class BaseGuildMember extends DiscordBase {
|
||||
private _roles: string[];
|
||||
joinedTimestamp?: number;
|
||||
communicationDisabledUntilTimestamp?: number | null;
|
||||
constructor(
|
||||
client: UsingClient,
|
||||
data: GuildMemberData,
|
||||
id: string,
|
||||
/** the choosen guild id */
|
||||
readonly guildId: string,
|
||||
) {
|
||||
const { roles, ...dataN } = data;
|
||||
super(client, { ...dataN, id });
|
||||
this._roles = data.roles;
|
||||
this.patch(data);
|
||||
}
|
||||
|
||||
guild(force = false) {
|
||||
return this.client.guilds.fetch(this.id, force);
|
||||
}
|
||||
|
||||
fetch(force = false) {
|
||||
return this.client.members.fetch(this.guildId, this.id, force);
|
||||
}
|
||||
|
||||
ban(body?: RESTPutAPIGuildBanJSONBody, reason?: string) {
|
||||
return this.client.members.ban(this.guildId, this.id, body, reason);
|
||||
}
|
||||
|
||||
kick(reason?: string) {
|
||||
return this.client.members.kick(this.guildId, this.id, reason);
|
||||
}
|
||||
|
||||
edit(body: RESTPatchAPIGuildMemberJSONBody, reason?: string) {
|
||||
return this.client.members.edit(this.guildId, this.id, body, reason);
|
||||
}
|
||||
|
||||
presence() {
|
||||
return this.client.members.presence(this.id);
|
||||
}
|
||||
|
||||
voice() {
|
||||
return this.client.members.voice(this.guildId, this.id);
|
||||
}
|
||||
|
||||
toString() {
|
||||
return `<@${this.id}>`;
|
||||
}
|
||||
|
||||
private patch(data: GuildMemberData) {
|
||||
if ('joined_at' in data && data.joined_at) {
|
||||
this.joinedTimestamp = Date.parse(data.joined_at);
|
||||
}
|
||||
if ('communication_disabled_until' in data) {
|
||||
this.communicationDisabledUntilTimestamp = data.communication_disabled_until?.length
|
||||
? Date.parse(data.communication_disabled_until)
|
||||
: null;
|
||||
}
|
||||
}
|
||||
|
||||
get roles() {
|
||||
return {
|
||||
keys: Object.freeze(this._roles.concat(this.guildId)) as string[],
|
||||
list: (force = false) =>
|
||||
this.client.roles
|
||||
.list(this.guildId, force)
|
||||
.then(roles => roles.filter(role => this.roles.keys.includes(role.id))),
|
||||
add: (id: string) => this.client.members.addRole(this.guildId, this.id, id),
|
||||
remove: (id: string) => this.client.members.removeRole(this.guildId, this.id, id),
|
||||
permissions: (force = false) =>
|
||||
this.roles.list(force).then(roles => new PermissionsBitField(roles.map(x => BigInt(x.permissions.bits)))),
|
||||
sorted: (force = false) => this.roles.list(force).then(roles => roles.sort((a, b) => b.position - a.position)),
|
||||
highest: (force = false) => this.roles.sorted(force).then(roles => roles[0]),
|
||||
};
|
||||
}
|
||||
|
||||
static methods({ client, guildId }: MethodContext<{ guildId: string }>) {
|
||||
return {
|
||||
resolve: (resolve: GuildMemberResolvable) => client.members.resolve(guildId, resolve),
|
||||
search: (query?: RESTGetAPIGuildMembersSearchQuery) => client.members.search(guildId, query),
|
||||
unban: (id: string, body?: RESTPutAPIGuildBanJSONBody, reason?: string) =>
|
||||
client.members.unban(guildId, id, body, reason),
|
||||
ban: (id: string, body?: RESTPutAPIGuildBanJSONBody, reason?: string) =>
|
||||
client.members.ban(guildId, id, body, reason),
|
||||
kick: (id: string, reason?: string) => client.members.kick(guildId, id, reason),
|
||||
edit: (id: string, body: RESTPatchAPIGuildMemberJSONBody, reason?: string) =>
|
||||
client.members.edit(guildId, id, body, reason),
|
||||
add: (id: string, body: RESTPutAPIGuildMemberJSONBody) => client.members.add(guildId, id, body),
|
||||
fetch: (memberId: string, force = false) => client.members.fetch(guildId, memberId, force),
|
||||
list: (query?: RESTGetAPIGuildMembersQuery, force = false) => client.members.list(guildId, query, force),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
export interface GuildMember extends ObjectToLower<Omit<APIGuildMember, 'user' | 'roles'>> {}
|
||||
/**
|
||||
* Represents a guild member
|
||||
* @link https://discord.com/developers/docs/resources/guild#guild-member-object
|
||||
*/
|
||||
export class GuildMember extends BaseGuildMember {
|
||||
user: User;
|
||||
private __me?: GuildMember;
|
||||
constructor(
|
||||
client: UsingClient,
|
||||
data: GuildMemberData,
|
||||
user: APIUser | User,
|
||||
/** the choosen guild id */
|
||||
readonly guildId: string,
|
||||
) {
|
||||
super(client, data, user.id, guildId);
|
||||
this.user = user instanceof User ? user : new User(client, user);
|
||||
}
|
||||
|
||||
get tag() {
|
||||
return this.user.tag;
|
||||
}
|
||||
|
||||
get bot() {
|
||||
return this.user.bot;
|
||||
}
|
||||
|
||||
get name() {
|
||||
return this.user.name;
|
||||
}
|
||||
|
||||
get username() {
|
||||
return this.user.username;
|
||||
}
|
||||
|
||||
get globalName() {
|
||||
return this.user.globalName;
|
||||
}
|
||||
|
||||
/** gets the nickname or the username */
|
||||
get displayName() {
|
||||
return this.nick ?? this.globalName ?? this.username;
|
||||
}
|
||||
|
||||
dm(force = false) {
|
||||
return this.user.dm(force);
|
||||
}
|
||||
|
||||
write(body: MessageCreateBodyRequest) {
|
||||
return this.user.write(body);
|
||||
}
|
||||
|
||||
defaultAvatarURL() {
|
||||
return this.user.defaultAvatarURL();
|
||||
}
|
||||
|
||||
avatarURL(options: ImageOptions & { exclude: true }): string | null;
|
||||
avatarURL(options?: ImageOptions & { exclude?: false }): string;
|
||||
avatarURL(options?: ImageOptions & { exclude?: boolean }): string | null {
|
||||
if (!this.avatar) {
|
||||
return options?.exclude ? null : this.user.avatarURL();
|
||||
}
|
||||
|
||||
return this.rest.cdn.guilds(this.guildId).users(this.id).avatars(this.avatar).get(options);
|
||||
}
|
||||
|
||||
bannerURL(options?: ImageOptions) {
|
||||
return this.user.bannerURL(options);
|
||||
}
|
||||
|
||||
async fetchPermissions(force = false) {
|
||||
if ('permissions' in this) return this.permissions as PermissionsBitField;
|
||||
return this.roles.permissions(force);
|
||||
}
|
||||
|
||||
async manageable(force = false) {
|
||||
this.__me = await this.client.guilds.fetchSelf(this.guildId, force);
|
||||
const ownerId = (await this.client.guilds.fetch(this.guildId, force)).ownerId;
|
||||
if (this.user.id === ownerId) return false;
|
||||
if (this.user.id === this.client.botId) return false;
|
||||
if (this.client.botId === ownerId) return true;
|
||||
return (await this.__me!.roles.highest()).position > (await this.roles.highest(force)).position;
|
||||
}
|
||||
|
||||
async bannable(force = false) {
|
||||
return (await this.manageable(force)) && (await this.__me!.fetchPermissions(force)).has('BanMembers');
|
||||
}
|
||||
|
||||
async kickable(force = false) {
|
||||
return (await this.manageable(force)) && (await this.__me!.fetchPermissions(force)).has('KickMembers');
|
||||
}
|
||||
|
||||
async moderatable(force = false) {
|
||||
return (
|
||||
!(await this.roles.permissions(force)).has('Administrator') &&
|
||||
(await this.manageable(force)) &&
|
||||
(await this.__me!.fetchPermissions(force)).has('KickMembers')
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export interface UnavailableMember {
|
||||
pending: true;
|
||||
}
|
||||
|
||||
export class UnavailableMember extends BaseGuildMember {}
|
||||
|
||||
export interface InteractionGuildMember
|
||||
extends ObjectToLower<Omit<APIInteractionDataResolvedGuildMember, 'roles' | 'deaf' | 'mute' | 'permissions'>> {}
|
||||
/**
|
||||
* Represents a guild member
|
||||
* @link https://discord.com/developers/docs/resources/guild#guild-member-object
|
||||
*/
|
||||
export class InteractionGuildMember extends (GuildMember as unknown as ToClass<
|
||||
Omit<GuildMember, 'deaf' | 'mute'>,
|
||||
InteractionGuildMember
|
||||
>) {
|
||||
permissions: PermissionsBitField;
|
||||
constructor(
|
||||
client: UsingClient,
|
||||
data: APIInteractionDataResolvedGuildMember,
|
||||
user: APIUser | User,
|
||||
/** the choosen guild id */
|
||||
guildId: string,
|
||||
) {
|
||||
super(client, data, user, guildId);
|
||||
this.permissions = new PermissionsBitField(Number(data.permissions));
|
||||
}
|
||||
}
|
||||
|
@ -1,61 +1,65 @@
|
||||
import type { APIUser } from 'discord-api-types/v10';
|
||||
import { calculateUserDefaultAvatarIndex } from '../api';
|
||||
import type { MessageCreateBodyRequest, ObjectToLower } from '../common';
|
||||
import type { ImageOptions } from '../common/types/options';
|
||||
import { DiscordBase } from './extra/DiscordBase';
|
||||
|
||||
export interface User extends ObjectToLower<APIUser> {}
|
||||
|
||||
export class User extends DiscordBase<APIUser> {
|
||||
get tag() {
|
||||
return this.globalName ?? `${this.username}#${this.discriminator}`;
|
||||
}
|
||||
|
||||
get name() {
|
||||
return this.globalName ?? this.username;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch user
|
||||
*/
|
||||
fetch(force = false) {
|
||||
return this.client.users.fetch(this.id, force);
|
||||
}
|
||||
|
||||
/**
|
||||
* Open a DM with the user
|
||||
*/
|
||||
dm(force = false) {
|
||||
return this.client.users.createDM(this.id, force);
|
||||
}
|
||||
|
||||
write(body: MessageCreateBodyRequest) {
|
||||
return this.client.users.write(this.id, body);
|
||||
}
|
||||
|
||||
avatarURL(options?: ImageOptions) {
|
||||
if (!this.avatar) {
|
||||
return this.rest.cdn.embed.avatars.get(calculateUserDefaultAvatarIndex(this.id, this.discriminator));
|
||||
}
|
||||
|
||||
return this.rest.cdn.avatars(this.id).get(this.avatar, options);
|
||||
}
|
||||
|
||||
avatarDecorationURL(options?: ImageOptions) {
|
||||
if (!this.avatarDecoration) return;
|
||||
return this.rest.cdn['avatar-decorations'](this.id).get(this.avatarDecoration, options);
|
||||
}
|
||||
|
||||
bannerURL(options?: ImageOptions) {
|
||||
if (!this.banner) return;
|
||||
return this.rest.cdn.banners(this.id).get(this.banner, options);
|
||||
}
|
||||
|
||||
presence() {
|
||||
return this.client.members.presence(this.id);
|
||||
}
|
||||
|
||||
toString() {
|
||||
return `<@${this.id}>`;
|
||||
}
|
||||
}
|
||||
import type { APIUser } from 'discord-api-types/v10';
|
||||
import { calculateUserDefaultAvatarIndex } from '../api';
|
||||
import type { MessageCreateBodyRequest, ObjectToLower } from '../common';
|
||||
import type { ImageOptions } from '../common/types/options';
|
||||
import { DiscordBase } from './extra/DiscordBase';
|
||||
|
||||
export interface User extends ObjectToLower<APIUser> {}
|
||||
|
||||
export class User extends DiscordBase<APIUser> {
|
||||
get tag() {
|
||||
return this.globalName ?? `${this.username}#${this.discriminator}`;
|
||||
}
|
||||
|
||||
get name() {
|
||||
return this.globalName ?? this.username;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch user
|
||||
*/
|
||||
fetch(force = false) {
|
||||
return this.client.users.fetch(this.id, force);
|
||||
}
|
||||
|
||||
/**
|
||||
* Open a DM with the user
|
||||
*/
|
||||
dm(force = false) {
|
||||
return this.client.users.createDM(this.id, force);
|
||||
}
|
||||
|
||||
write(body: MessageCreateBodyRequest) {
|
||||
return this.client.users.write(this.id, body);
|
||||
}
|
||||
|
||||
defaultAvatarURL() {
|
||||
return this.rest.cdn.embed.avatars.get(calculateUserDefaultAvatarIndex(this.id, this.discriminator));
|
||||
}
|
||||
|
||||
avatarURL(options?: ImageOptions) {
|
||||
if (!this.avatar) {
|
||||
return this.defaultAvatarURL();
|
||||
}
|
||||
|
||||
return this.rest.cdn.avatars(this.id).get(this.avatar, options);
|
||||
}
|
||||
|
||||
avatarDecorationURL(options?: ImageOptions) {
|
||||
if (!this.avatarDecoration) return;
|
||||
return this.rest.cdn['avatar-decorations'](this.id).get(this.avatarDecoration, options);
|
||||
}
|
||||
|
||||
bannerURL(options?: ImageOptions) {
|
||||
if (!this.banner) return;
|
||||
return this.rest.cdn.banners(this.id).get(this.banner, options);
|
||||
}
|
||||
|
||||
presence() {
|
||||
return this.client.members.presence(this.id);
|
||||
}
|
||||
|
||||
toString() {
|
||||
return `<@${this.id}>`;
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user