mirror of
https://github.com/discordjs/discord.js.git
synced 2026-03-09 16:13:31 +01:00
refactor(SnowflakeUtil): switch to @sapphire/snowflake (#7079)
This commit is contained in:
@@ -52,6 +52,7 @@
|
||||
"@discordjs/builders": "^0.11.0",
|
||||
"@discordjs/collection": "^0.4.0",
|
||||
"@sapphire/async-queue": "^1.1.9",
|
||||
"@sapphire/snowflake": "^3.0.0",
|
||||
"@types/node-fetch": "^2.5.12",
|
||||
"@types/ws": "^8.2.2",
|
||||
"discord-api-types": "^0.26.1",
|
||||
|
||||
@@ -525,6 +525,19 @@ class Client extends BaseClient {
|
||||
|
||||
module.exports = Client;
|
||||
|
||||
/**
|
||||
* A {@link https://developer.twitter.com/en/docs/twitter-ids Twitter snowflake},
|
||||
* except the epoch is 2015-01-01T00:00:00.000Z.
|
||||
*
|
||||
* If we have a snowflake '266241948824764416' we can represent it as binary:
|
||||
* ```
|
||||
* 64 22 17 12 0
|
||||
* 000000111011000111100001101001000101000000 00001 00000 000000000000
|
||||
* number of ms since Discord epoch worker pid increment
|
||||
* ```
|
||||
* @typedef {string} Snowflake
|
||||
*/
|
||||
|
||||
/**
|
||||
* Emitted for general warnings.
|
||||
* @event Client#warn
|
||||
|
||||
@@ -25,7 +25,7 @@ exports.MessageFlags = require('./util/MessageFlags');
|
||||
exports.Options = require('./util/Options');
|
||||
exports.Permissions = require('./util/Permissions');
|
||||
exports.RateLimitError = require('./rest/RateLimitError');
|
||||
exports.SnowflakeUtil = require('./util/SnowflakeUtil');
|
||||
exports.SnowflakeUtil = require('@sapphire/snowflake').DiscordSnowflake;
|
||||
exports.Sweepers = require('./util/Sweepers');
|
||||
exports.SystemChannelFlags = require('./util/SystemChannelFlags');
|
||||
exports.ThreadMemberFlags = require('./util/ThreadMemberFlags');
|
||||
|
||||
@@ -3,13 +3,13 @@
|
||||
const { Buffer } = require('node:buffer');
|
||||
const { setTimeout } = require('node:timers');
|
||||
const { Collection } = require('@discordjs/collection');
|
||||
const { DiscordSnowflake } = require('@sapphire/snowflake');
|
||||
const CachedManager = require('./CachedManager');
|
||||
const { Error, TypeError, RangeError } = require('../errors');
|
||||
const BaseGuildVoiceChannel = require('../structures/BaseGuildVoiceChannel');
|
||||
const { GuildMember } = require('../structures/GuildMember');
|
||||
const { Role } = require('../structures/Role');
|
||||
const { Events, Opcodes } = require('../util/Constants');
|
||||
const SnowflakeUtil = require('../util/SnowflakeUtil');
|
||||
|
||||
/**
|
||||
* Manages API methods for GuildMembers and stores their cache.
|
||||
@@ -414,7 +414,7 @@ class GuildMemberManager extends CachedManager {
|
||||
user: user_ids,
|
||||
query,
|
||||
time = 120e3,
|
||||
nonce = SnowflakeUtil.generate(),
|
||||
nonce = DiscordSnowflake.generate().toString(),
|
||||
} = {}) {
|
||||
return new Promise((resolve, reject) => {
|
||||
if (!query && !user_ids) query = '';
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
'use strict';
|
||||
|
||||
const { DiscordSnowflake } = require('@sapphire/snowflake');
|
||||
const Base = require('./Base');
|
||||
const ApplicationCommandPermissionsManager = require('../managers/ApplicationCommandPermissionsManager');
|
||||
const { ApplicationCommandOptionTypes, ApplicationCommandTypes, ChannelTypes } = require('../util/Constants');
|
||||
const SnowflakeUtil = require('../util/SnowflakeUtil');
|
||||
|
||||
/**
|
||||
* Represents an application command.
|
||||
@@ -103,7 +103,7 @@ class ApplicationCommand extends Base {
|
||||
* @readonly
|
||||
*/
|
||||
get createdTimestamp() {
|
||||
return SnowflakeUtil.timestampFrom(this.id);
|
||||
return DiscordSnowflake.timestampFrom(this.id);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
'use strict';
|
||||
|
||||
const { DiscordSnowflake } = require('@sapphire/snowflake');
|
||||
const Base = require('./Base');
|
||||
const SnowflakeUtil = require('../util/SnowflakeUtil');
|
||||
|
||||
/**
|
||||
* The base class for {@link Guild}, {@link OAuth2Guild} and {@link InviteGuild}.
|
||||
@@ -43,7 +43,7 @@ class BaseGuild extends Base {
|
||||
* @readonly
|
||||
*/
|
||||
get createdTimestamp() {
|
||||
return SnowflakeUtil.timestampFrom(this.id);
|
||||
return DiscordSnowflake.timestampFrom(this.id);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
'use strict';
|
||||
|
||||
const { DiscordSnowflake } = require('@sapphire/snowflake');
|
||||
const Base = require('./Base');
|
||||
let CategoryChannel;
|
||||
let DMChannel;
|
||||
@@ -10,7 +11,6 @@ let TextChannel;
|
||||
let ThreadChannel;
|
||||
let VoiceChannel;
|
||||
const { ChannelTypes, ThreadChannelTypes, VoiceBasedChannelTypes } = require('../util/Constants');
|
||||
const SnowflakeUtil = require('../util/SnowflakeUtil');
|
||||
|
||||
/**
|
||||
* Represents any channel on Discord.
|
||||
@@ -45,7 +45,7 @@ class Channel extends Base {
|
||||
* @readonly
|
||||
*/
|
||||
get createdTimestamp() {
|
||||
return SnowflakeUtil.timestampFrom(this.id);
|
||||
return DiscordSnowflake.timestampFrom(this.id);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
'use strict';
|
||||
|
||||
const { DiscordSnowflake } = require('@sapphire/snowflake');
|
||||
const Base = require('./Base');
|
||||
const SnowflakeUtil = require('../util/SnowflakeUtil');
|
||||
|
||||
/**
|
||||
* Represents raw emoji data from the API
|
||||
@@ -62,7 +62,7 @@ class Emoji extends Base {
|
||||
* @readonly
|
||||
*/
|
||||
get createdTimestamp() {
|
||||
return this.id && SnowflakeUtil.timestampFrom(this.id);
|
||||
return this.id && DiscordSnowflake.timestampFrom(this.id);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
'use strict';
|
||||
|
||||
const { Collection } = require('@discordjs/collection');
|
||||
const { DiscordSnowflake } = require('@sapphire/snowflake');
|
||||
const { GuildScheduledEvent } = require('./GuildScheduledEvent');
|
||||
const Integration = require('./Integration');
|
||||
const Invite = require('./Invite');
|
||||
@@ -8,7 +9,6 @@ const { StageInstance } = require('./StageInstance');
|
||||
const { Sticker } = require('./Sticker');
|
||||
const Webhook = require('./Webhook');
|
||||
const { OverwriteTypes, PartialTypes } = require('../util/Constants');
|
||||
const SnowflakeUtil = require('../util/SnowflakeUtil');
|
||||
const Util = require('../util/Util');
|
||||
|
||||
/**
|
||||
@@ -614,7 +614,7 @@ class GuildAuditLogsEntry {
|
||||
* @readonly
|
||||
*/
|
||||
get createdTimestamp() {
|
||||
return SnowflakeUtil.timestampFrom(this.id);
|
||||
return DiscordSnowflake.timestampFrom(this.id);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
'use strict';
|
||||
|
||||
const { Collection } = require('@discordjs/collection');
|
||||
const { DiscordSnowflake } = require('@sapphire/snowflake');
|
||||
const Base = require('./Base');
|
||||
const GuildPreviewEmoji = require('./GuildPreviewEmoji');
|
||||
const SnowflakeUtil = require('../util/SnowflakeUtil');
|
||||
|
||||
/**
|
||||
* Represents the data about the guild any bot can preview, connected to the specified guild.
|
||||
@@ -110,7 +110,7 @@ class GuildPreview extends Base {
|
||||
* @readonly
|
||||
*/
|
||||
get createdTimestamp() {
|
||||
return SnowflakeUtil.timestampFrom(this.id);
|
||||
return DiscordSnowflake.timestampFrom(this.id);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
'use strict';
|
||||
|
||||
const { DiscordSnowflake } = require('@sapphire/snowflake');
|
||||
const Base = require('./Base');
|
||||
const { InteractionTypes, MessageComponentTypes, ApplicationCommandTypes } = require('../util/Constants');
|
||||
const Permissions = require('../util/Permissions');
|
||||
const SnowflakeUtil = require('../util/SnowflakeUtil');
|
||||
|
||||
/**
|
||||
* Represents an interaction.
|
||||
@@ -82,7 +82,7 @@ class Interaction extends Base {
|
||||
* @readonly
|
||||
*/
|
||||
get createdTimestamp() {
|
||||
return SnowflakeUtil.timestampFrom(this.id);
|
||||
return DiscordSnowflake.timestampFrom(this.id);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
'use strict';
|
||||
|
||||
const { Collection } = require('@discordjs/collection');
|
||||
const { DiscordSnowflake } = require('@sapphire/snowflake');
|
||||
const Base = require('./Base');
|
||||
const BaseMessageComponent = require('./BaseMessageComponent');
|
||||
const ClientApplication = require('./ClientApplication');
|
||||
@@ -16,7 +17,6 @@ const ReactionManager = require('../managers/ReactionManager');
|
||||
const { InteractionTypes, MessageTypes, SystemMessageTypes } = require('../util/Constants');
|
||||
const MessageFlags = require('../util/MessageFlags');
|
||||
const Permissions = require('../util/Permissions');
|
||||
const SnowflakeUtil = require('../util/SnowflakeUtil');
|
||||
const Util = require('../util/Util');
|
||||
|
||||
/**
|
||||
@@ -53,7 +53,7 @@ class Message extends Base {
|
||||
* The timestamp the message was sent at
|
||||
* @type {number}
|
||||
*/
|
||||
this.createdTimestamp = SnowflakeUtil.timestampFrom(this.id);
|
||||
this.createdTimestamp = DiscordSnowflake.timestampFrom(this.id);
|
||||
|
||||
if ('type' in data) {
|
||||
/**
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
'use strict';
|
||||
|
||||
const { DiscordSnowflake } = require('@sapphire/snowflake');
|
||||
const Base = require('./Base');
|
||||
const { Error } = require('../errors');
|
||||
const Permissions = require('../util/Permissions');
|
||||
const SnowflakeUtil = require('../util/SnowflakeUtil');
|
||||
const Util = require('../util/Util');
|
||||
|
||||
/**
|
||||
@@ -128,7 +128,7 @@ class Role extends Base {
|
||||
* @readonly
|
||||
*/
|
||||
get createdTimestamp() {
|
||||
return SnowflakeUtil.timestampFrom(this.id);
|
||||
return DiscordSnowflake.timestampFrom(this.id);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
'use strict';
|
||||
|
||||
const { DiscordSnowflake } = require('@sapphire/snowflake');
|
||||
const Base = require('./Base');
|
||||
const { PrivacyLevels } = require('../util/Constants');
|
||||
const SnowflakeUtil = require('../util/SnowflakeUtil');
|
||||
|
||||
/**
|
||||
* Represents a stage instance.
|
||||
@@ -132,7 +132,7 @@ class StageInstance extends Base {
|
||||
* @readonly
|
||||
*/
|
||||
get createdTimestamp() {
|
||||
return SnowflakeUtil.timestampFrom(this.id);
|
||||
return DiscordSnowflake.timestampFrom(this.id);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
'use strict';
|
||||
|
||||
const { DiscordSnowflake } = require('@sapphire/snowflake');
|
||||
const Base = require('./Base');
|
||||
const { StickerFormatTypes, StickerTypes } = require('../util/Constants');
|
||||
const SnowflakeUtil = require('../util/SnowflakeUtil');
|
||||
|
||||
/**
|
||||
* Represents a Sticker.
|
||||
@@ -125,7 +125,7 @@ class Sticker extends Base {
|
||||
* @readonly
|
||||
*/
|
||||
get createdTimestamp() {
|
||||
return SnowflakeUtil.timestampFrom(this.id);
|
||||
return DiscordSnowflake.timestampFrom(this.id);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
'use strict';
|
||||
|
||||
const { Collection } = require('@discordjs/collection');
|
||||
const { DiscordSnowflake } = require('@sapphire/snowflake');
|
||||
const Base = require('./Base');
|
||||
const { Sticker } = require('./Sticker');
|
||||
const SnowflakeUtil = require('../util/SnowflakeUtil');
|
||||
|
||||
/**
|
||||
* Represents a pack of standard stickers.
|
||||
@@ -61,7 +61,7 @@ class StickerPack extends Base {
|
||||
* @readonly
|
||||
*/
|
||||
get createdTimestamp() {
|
||||
return SnowflakeUtil.timestampFrom(this.id);
|
||||
return DiscordSnowflake.timestampFrom(this.id);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
'use strict';
|
||||
|
||||
const { Collection } = require('@discordjs/collection');
|
||||
const { DiscordSnowflake } = require('@sapphire/snowflake');
|
||||
const Base = require('./Base');
|
||||
const TeamMember = require('./TeamMember');
|
||||
const SnowflakeUtil = require('../util/SnowflakeUtil');
|
||||
|
||||
/**
|
||||
* Represents a Client OAuth2 Application Team.
|
||||
@@ -76,7 +76,7 @@ class Team extends Base {
|
||||
* @readonly
|
||||
*/
|
||||
get createdTimestamp() {
|
||||
return SnowflakeUtil.timestampFrom(this.id);
|
||||
return DiscordSnowflake.timestampFrom(this.id);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
'use strict';
|
||||
|
||||
const { DiscordSnowflake } = require('@sapphire/snowflake');
|
||||
const Base = require('./Base');
|
||||
const TextBasedChannel = require('./interfaces/TextBasedChannel');
|
||||
const SnowflakeUtil = require('../util/SnowflakeUtil');
|
||||
const UserFlags = require('../util/UserFlags');
|
||||
|
||||
/**
|
||||
@@ -126,7 +126,7 @@ class User extends Base {
|
||||
* @readonly
|
||||
*/
|
||||
get createdTimestamp() {
|
||||
return SnowflakeUtil.timestampFrom(this.id);
|
||||
return DiscordSnowflake.timestampFrom(this.id);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
'use strict';
|
||||
|
||||
const process = require('node:process');
|
||||
const { DiscordSnowflake } = require('@sapphire/snowflake');
|
||||
const MessagePayload = require('./MessagePayload');
|
||||
const { Error } = require('../errors');
|
||||
const { WebhookTypes } = require('../util/Constants');
|
||||
const DataResolver = require('../util/DataResolver');
|
||||
const SnowflakeUtil = require('../util/SnowflakeUtil');
|
||||
|
||||
let deprecationEmittedForFetchMessage = false;
|
||||
|
||||
@@ -380,7 +380,7 @@ class Webhook {
|
||||
* @readonly
|
||||
*/
|
||||
get createdTimestamp() {
|
||||
return SnowflakeUtil.timestampFrom(this.id);
|
||||
return DiscordSnowflake.timestampFrom(this.id);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
'use strict';
|
||||
|
||||
const { DiscordSnowflake } = require('@sapphire/snowflake');
|
||||
const { ClientApplicationAssetTypes, Endpoints } = require('../../util/Constants');
|
||||
const SnowflakeUtil = require('../../util/SnowflakeUtil');
|
||||
const Base = require('../Base');
|
||||
|
||||
const AssetTypes = Object.keys(ClientApplicationAssetTypes);
|
||||
@@ -60,7 +60,7 @@ class Application extends Base {
|
||||
* @readonly
|
||||
*/
|
||||
get createdTimestamp() {
|
||||
return SnowflakeUtil.timestampFrom(this.id);
|
||||
return DiscordSnowflake.timestampFrom(this.id);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -3,8 +3,8 @@
|
||||
/* eslint-disable import/order */
|
||||
const MessageCollector = require('../MessageCollector');
|
||||
const MessagePayload = require('../MessagePayload');
|
||||
const SnowflakeUtil = require('../../util/SnowflakeUtil');
|
||||
const { Collection } = require('@discordjs/collection');
|
||||
const { DiscordSnowflake } = require('@sapphire/snowflake');
|
||||
const { InteractionTypes } = require('../../util/Constants');
|
||||
const { TypeError, Error } = require('../../errors');
|
||||
const InteractionCollector = require('../InteractionCollector');
|
||||
@@ -294,7 +294,7 @@ class TextBasedChannel {
|
||||
if (Array.isArray(messages) || messages instanceof Collection) {
|
||||
let messageIds = messages instanceof Collection ? [...messages.keys()] : messages.map(m => m.id ?? m);
|
||||
if (filterOld) {
|
||||
messageIds = messageIds.filter(id => Date.now() - SnowflakeUtil.timestampFrom(id) < 1_209_600_000);
|
||||
messageIds = messageIds.filter(id => Date.now() - DiscordSnowflake.timestampFrom(id) < 1_209_600_000);
|
||||
}
|
||||
if (messageIds.length === 0) return new Collection();
|
||||
if (messageIds.length === 1) {
|
||||
|
||||
@@ -1,92 +0,0 @@
|
||||
'use strict';
|
||||
|
||||
// Discord epoch (2015-01-01T00:00:00.000Z)
|
||||
const EPOCH = 1_420_070_400_000;
|
||||
let INCREMENT = BigInt(0);
|
||||
|
||||
/**
|
||||
* A container for useful snowflake-related methods.
|
||||
*/
|
||||
class SnowflakeUtil extends null {
|
||||
/**
|
||||
* A {@link https://developer.twitter.com/en/docs/twitter-ids Twitter snowflake},
|
||||
* except the epoch is 2015-01-01T00:00:00.000Z.
|
||||
*
|
||||
* If we have a snowflake '266241948824764416' we can represent it as binary:
|
||||
* ```
|
||||
* 64 22 17 12 0
|
||||
* 000000111011000111100001101001000101000000 00001 00000 000000000000
|
||||
* number of ms since Discord epoch worker pid increment
|
||||
* ```
|
||||
* @typedef {string} Snowflake
|
||||
*/
|
||||
|
||||
/**
|
||||
* Generates a Discord snowflake.
|
||||
* <info>This hardcodes the worker's id as 1 and the process's id as 0.</info>
|
||||
* @param {number|Date} [timestamp=Date.now()] Timestamp or date of the snowflake to generate
|
||||
* @returns {Snowflake} The generated snowflake
|
||||
*/
|
||||
static generate(timestamp = Date.now()) {
|
||||
if (timestamp instanceof Date) timestamp = timestamp.getTime();
|
||||
if (typeof timestamp !== 'number' || isNaN(timestamp)) {
|
||||
throw new TypeError(
|
||||
`"timestamp" argument must be a number (received ${isNaN(timestamp) ? 'NaN' : typeof timestamp})`,
|
||||
);
|
||||
}
|
||||
if (INCREMENT >= 4095n) INCREMENT = BigInt(0);
|
||||
|
||||
// Assign WorkerId as 1 and ProcessId as 0:
|
||||
return ((BigInt(timestamp - EPOCH) << 22n) | (1n << 17n) | INCREMENT++).toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* A deconstructed snowflake.
|
||||
* @typedef {Object} DeconstructedSnowflake
|
||||
* @property {number} timestamp Timestamp the snowflake was created
|
||||
* @property {Date} date Date the snowflake was created
|
||||
* @property {number} workerId The worker's id in the snowflake
|
||||
* @property {number} processId The process's id in the snowflake
|
||||
* @property {number} increment Increment in the snowflake
|
||||
* @property {string} binary Binary representation of the snowflake
|
||||
*/
|
||||
|
||||
/**
|
||||
* Deconstructs a Discord snowflake.
|
||||
* @param {Snowflake} snowflake Snowflake to deconstruct
|
||||
* @returns {DeconstructedSnowflake}
|
||||
*/
|
||||
static deconstruct(snowflake) {
|
||||
const bigIntSnowflake = BigInt(snowflake);
|
||||
return {
|
||||
timestamp: Number(bigIntSnowflake >> 22n) + EPOCH,
|
||||
get date() {
|
||||
return new Date(this.timestamp);
|
||||
},
|
||||
workerId: Number((bigIntSnowflake >> 17n) & 0b11111n),
|
||||
processId: Number((bigIntSnowflake >> 12n) & 0b11111n),
|
||||
increment: Number(bigIntSnowflake & 0b111111111111n),
|
||||
binary: bigIntSnowflake.toString(2).padStart(64, '0'),
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the timestamp field's value from a Discord snowflake.
|
||||
* @param {Snowflake} snowflake Snowflake to get the timestamp value from
|
||||
* @returns {number}
|
||||
*/
|
||||
static timestampFrom(snowflake) {
|
||||
return Number(BigInt(snowflake) >> 22n) + EPOCH;
|
||||
}
|
||||
|
||||
/**
|
||||
* Discord's epoch value (2015-01-01T00:00:00.000Z).
|
||||
* @type {number}
|
||||
* @readonly
|
||||
*/
|
||||
static get EPOCH() {
|
||||
return EPOCH;
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = SnowflakeUtil;
|
||||
21
packages/discord.js/typings/index.d.ts
vendored
21
packages/discord.js/typings/index.d.ts
vendored
@@ -2073,13 +2073,11 @@ export interface FetchRecommendedShardsOptions {
|
||||
multipleOf?: number;
|
||||
}
|
||||
|
||||
export class SnowflakeUtil extends null {
|
||||
private constructor();
|
||||
public static deconstruct(snowflake: Snowflake): DeconstructedSnowflake;
|
||||
public static generate(timestamp?: number | Date): Snowflake;
|
||||
public static timestampFrom(snowflake: Snowflake): number;
|
||||
public static readonly EPOCH: number;
|
||||
}
|
||||
export {
|
||||
DiscordSnowflake as SnowflakeUtil,
|
||||
SnowflakeGenerateOptions,
|
||||
DeconstructedSnowflake,
|
||||
} from '@sapphire/snowflake';
|
||||
|
||||
export class StageChannel extends BaseGuildVoiceChannel {
|
||||
public topic: string | null;
|
||||
@@ -4234,15 +4232,6 @@ export interface CrosspostedChannel {
|
||||
|
||||
export type DateResolvable = Date | number | string;
|
||||
|
||||
export interface DeconstructedSnowflake {
|
||||
timestamp: number;
|
||||
readonly date: Date;
|
||||
workerId: number;
|
||||
processId: number;
|
||||
increment: number;
|
||||
binary: string;
|
||||
}
|
||||
|
||||
export type DefaultMessageNotificationLevel = keyof typeof DefaultMessageNotificationLevels;
|
||||
|
||||
export type DynamicImageFormat = AllowedImageFormat | 'gif';
|
||||
|
||||
Reference in New Issue
Block a user