refactor(SnowflakeUtil): switch to @sapphire/snowflake (#7079)

This commit is contained in:
Antonio Román
2022-01-08 19:11:33 +01:00
committed by GitHub
parent ae876d9624
commit e082dfb158
23 changed files with 56 additions and 145 deletions

View File

@@ -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",

View File

@@ -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

View File

@@ -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');

View File

@@ -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 = '';

View File

@@ -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);
}
/**

View File

@@ -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);
}
/**

View File

@@ -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);
}
/**

View File

@@ -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);
}
/**

View File

@@ -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);
}
/**

View File

@@ -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);
}
/**

View File

@@ -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);
}
/**

View File

@@ -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) {
/**

View File

@@ -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);
}
/**

View File

@@ -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);
}
/**

View File

@@ -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);
}
/**

View File

@@ -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);
}
/**

View File

@@ -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);
}
/**

View File

@@ -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);
}
/**

View File

@@ -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);
}
/**

View File

@@ -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);
}
/**

View File

@@ -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) {

View File

@@ -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;

View File

@@ -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';