import { DeconstructedDiscordooSnowflake } from '@src/utils/interfaces/DeconstructedSnowflake' ; import { DiscordooError } from '@src/utils/DiscordooError' ; import { DISCORDOO_EPOCH } from '@src/constants/common' ; import { is } from 'typescript-is' ; import { ValidationError } from '@src/utils/ValidationError' ; const EPOCH = DISCORDOO_EPOCH ; let INCREMENT = 0 ; /**
 * DiscordooSnowflake is a custom twitter snowflake used to identify ipc connections and messages.
 * */ export class DiscordooSnowflake { public static readonly SHARDING_MANAGER_ID = 1111111111 ; /**
     * Custom twitter snowflake: DiscordooSnowflake.
     * ```
     * If we have a snowflake '1128425170719486862453931925225603077' we can represent it as binary:
     *
     *  128                                        86                               54                               22
     *  000000001101100101010011101010000000011011 00000000000000000000000000001011 00000000000000000000000001100011 0000000000000000000101
     *     number of ms since Discordoo epoch                  worker id                       shard id                    increment
     *
     * getting a timestamp:
     *  (BigInt(snowflake) >> 86n) + BigInt(EPOCH) === 1624043753498n
     *
     * getting a worker id:
     *  (BigInt(snowflake) & 0x3FFFFFFFC0000000000000n) >> 54n === 11n
     *
     * getting a shard id:
     *  (BigInt(snowflake) & 0x3FFFFFFFC00000n) >> 22n === 99n
     *
     * getting a increment:
     *  BigInt(snowflake) & 0x3FFFFFn === 5n
     * ```
     * Why?
     * Discordoo uses DiscordooSnowflake to identify ipc connections and messages.
     * So, if your bot has more than 2,147,483,647 shards, you will unfortunately not be able to use Discordoo.
     */ static generate ( shardId , workerId = 0 , timestamp = Date . now ( ) ) { if ( timestamp instanceof Date ) timestamp = timestamp . getTime ( ) ; if ( INCREMENT >= 4194302 ) INCREMENT = 0 ; if ( ! is < number > ( shardId ) ) { throw new ValidationError ( 'DiscordooSnowflake#generate' , 'shardId must be number.' ) ; } if ( ! is < number > ( workerId ) ) { throw new ValidationError ( 'DiscordooSnowflake#generate' , 'workerId must be number.' ) ; } if ( ! is < number > ( timestamp ) ) { throw new ValidationError ( 'DiscordooSnowflake#generate' , 'timestamp must be number or Date.' ) ; } if ( shardId . toString ( 2 ) . length > 32 || workerId . toString ( 2 ) . length > 32 ) { throw new DiscordooError ( 'DiscordooSnowflake#generate' , 'cannot generate snowflake with shardId or workerId that take up more than 32 bits' ) ; } const b = BigInt ; const segments = [ b ( timestamp - EPOCH ) << b ( 86 ) , b ( workerId ) << b ( 54 ) , b ( shardId ) << b ( 22 ) , b ( INCREMENT ++ ) ] ; return segments . reduce ( ( prev , curr ) => prev + curr , b ( 0 ) ) . toString ( ) ; } static generatePartial ( timestamp = Date . now ( ) ) { if ( timestamp instanceof Date ) timestamp = timestamp . getTime ( ) ; const b = BigInt ; return ( b ( timestamp ) - b ( EPOCH ) << b ( 86 ) ) . toString ( ) ; } static deconstruct ( snowflake ) { const b = BigInt , n = Number , bigSnowflake = b ( snowflake ) ; return { timestamp : n ( ( bigSnowflake >> b ( 86 ) ) + b ( EPOCH ) ) , workerId : n ( ( bigSnowflake & b ( 0x3FFFFFFFC0000000000000 ) ) >> b ( 54 ) ) , shardId : n ( ( bigSnowflake & b ( 0x3FFFFFFFC00000 ) ) >> b ( 22 ) ) , increment : n ( bigSnowflake & b ( 0x3FFFFF ) ) , get date ( ) { return new Date ( this . timestamp ) ; } } ; } }