From 96bb1ed05c7da098a693ef781e0874b5f9d3ba5d Mon Sep 17 00:00:00 2001 From: Rory& Date: Fri, 12 Jun 2026 16:27:38 +0200 Subject: [PATCH] Move more extensions to extensions --- scripts/openapi.js | 3 +- scripts/schema.js | 2 +- src/api/routes/applications/index.ts | 3 +- src/api/routes/auth/register.ts | 3 +- .../routes/channels/#channel_id/webhooks.ts | 3 +- src/api/routes/guilds/#guild_id/templates.ts | 3 +- src/api/routes/users/#user_id/delete.ts | 7 ++-- src/api/routes/users/@me/mentions.ts | 3 +- src/api/util/handlers/Instance.ts | 4 +- src/api/util/handlers/Message.ts | 3 +- src/api/util/index.ts | 1 - src/api/util/utility/EmbedHandlers.ts | 4 +- src/api/util/utility/String.ts | 38 ------------------- src/bundle/start.ts | 3 +- src/database/entities/Channel.ts | 3 +- src/database/entities/Member.ts | 3 +- src/database/entities/Session.ts | 7 ++-- src/database/entities/User.ts | 4 +- .../util => extensions}/DateBuilder.test.ts | 0 src/{util/util => extensions}/DateBuilder.ts | 0 .../util => extensions}/ElapsedTime.test.ts | 0 src/{util/util => extensions}/ElapsedTime.ts | 0 src/{util/util => extensions}/Random.ts | 18 +++++++++ .../util => extensions}/Stopwatch.test.ts | 0 src/{util/util => extensions}/Stopwatch.ts | 0 src/{util/util => extensions}/String.ts | 24 +++++++++++- .../util => extensions}/Timespan.test.ts | 0 src/{util/util => extensions}/Timespan.ts | 0 src/{util/util => extensions}/Url.ts | 0 src/extensions/index.ts | 7 ++++ src/gateway/opcodes/GuildSync.ts | 3 +- src/gateway/opcodes/Identify.ts | 6 +-- src/gateway/opcodes/RequestGuildMembers.ts | 3 +- src/gateway/util/Utils.ts | 3 +- src/util/util/Token.ts | 2 +- src/util/util/index.ts | 7 ---- src/util/util/ipc/writer/UnixSocketWriter.ts | 9 +++-- src/util/util/json/JsonSerializer.test.ts | 2 +- .../networking/abuseipdb/AbuseIpDbClient.ts | 21 +++++++++- .../util/networking/ipdata/IpDataClient.ts | 21 +++++++++- .../stopforumspam/StopForumSpamClient.ts | 2 +- .../util/workers/bcrypt/BcryptWorkerPool.ts | 2 +- 42 files changed, 137 insertions(+), 90 deletions(-) delete mode 100644 src/api/util/utility/String.ts rename src/{util/util => extensions}/DateBuilder.test.ts (100%) rename src/{util/util => extensions}/DateBuilder.ts (100%) rename src/{util/util => extensions}/ElapsedTime.test.ts (100%) rename src/{util/util => extensions}/ElapsedTime.ts (100%) rename src/{util/util => extensions}/Random.ts (78%) rename src/{util/util => extensions}/Stopwatch.test.ts (100%) rename src/{util/util => extensions}/Stopwatch.ts (100%) rename src/{util/util => extensions}/String.ts (66%) rename src/{util/util => extensions}/Timespan.test.ts (100%) rename src/{util/util => extensions}/Timespan.ts (100%) rename src/{util/util => extensions}/Url.ts (100%) diff --git a/scripts/openapi.js b/scripts/openapi.js index a6033cd6a..64c7babbf 100644 --- a/scripts/openapi.js +++ b/scripts/openapi.js @@ -18,7 +18,7 @@ process.env.LOG_ROUTES = "false"; -const { Stopwatch } = require("../dist/util/util/Stopwatch"); +const { Stopwatch } = require("../dist/extensions/Stopwatch"); const totalSw = Stopwatch.startNew(); require("module-alias/register"); @@ -26,7 +26,6 @@ const getRouteDescriptions = require("./util/getRouteDescriptions"); const path = require("path"); const fs = require("fs"); const { NO_AUTHORIZATION_ROUTES } = require("../dist/api/middlewares/Authentication"); -require("../dist/extensions"); const { bgRedBright, bgYellow, black, bgYellowBright, blue, white } = require("picocolors"); const openapiPath = path.join(__dirname, "..", "assets", "openapi.json"); diff --git a/scripts/schema.js b/scripts/schema.js index f8733809b..54d9335d0 100644 --- a/scripts/schema.js +++ b/scripts/schema.js @@ -19,7 +19,7 @@ /* Regenerates the `spacebarchat/server/assets/schemas.json` file, used for API/Gateway input validation. */ -const { Stopwatch } = require("../dist/util/util/Stopwatch"); +const { Stopwatch } = require("../dist/extensions/Stopwatch"); const totalSw = Stopwatch.startNew(); const conWarn = console.warn; diff --git a/src/api/routes/applications/index.ts b/src/api/routes/applications/index.ts index 820716b5d..894f9331f 100644 --- a/src/api/routes/applications/index.ts +++ b/src/api/routes/applications/index.ts @@ -19,8 +19,9 @@ import { Request, Response, Router } from "express"; import { route } from "@spacebar/api"; import { Application } from "@spacebar/database"; -import { Config, createAppBotUser, trimSpecial } from "@spacebar/util"; +import { Config, createAppBotUser } from "@spacebar/util"; import { ApplicationCreateSchema } from "@spacebar/schemas"; +import { trimSpecial } from "@spacebar/extensions"; const router: Router = Router({ mergeParams: true }); diff --git a/src/api/routes/auth/register.ts b/src/api/routes/auth/register.ts index 13721c042..379d2775e 100644 --- a/src/api/routes/auth/register.ts +++ b/src/api/routes/auth/register.ts @@ -22,9 +22,10 @@ import { HTTPError } from "lambert-server/HTTPError"; import { MoreThan } from "typeorm"; import { route, verifyCaptcha } from "@spacebar/api"; import { Invite, User, ValidRegistrationToken } from "@spacebar/database"; -import { Config, FieldErrors, generateToken, IpDataClient, AbuseIpDbClient, TimeSpan, Stopwatch } from "@spacebar/util"; +import { Config, FieldErrors, generateToken, IpDataClient, AbuseIpDbClient } from "@spacebar/util"; import { RegisterSchema } from "@spacebar/schemas"; import { BcryptWorkerPool } from "../../../util/util/workers/bcrypt/BcryptWorkerPool"; +import { Stopwatch, TimeSpan } from "@spacebar/extensions"; const router: Router = Router({ mergeParams: true }); diff --git a/src/api/routes/channels/#channel_id/webhooks.ts b/src/api/routes/channels/#channel_id/webhooks.ts index b3efb1878..0dac75747 100644 --- a/src/api/routes/channels/#channel_id/webhooks.ts +++ b/src/api/routes/channels/#channel_id/webhooks.ts @@ -21,8 +21,9 @@ import { Request, Response, Router } from "express"; import { HTTPError } from "lambert-server/HTTPError"; import { route } from "@spacebar/api"; import { Application, Channel, User, Webhook } from "@spacebar/database"; -import { Config, DiscordApiErrors, handleFile, trimSpecial, ValidateName } from "@spacebar/util"; +import { Config, DiscordApiErrors, handleFile, ValidateName } from "@spacebar/util"; import { isTextChannel, WebhookCreateSchema, WebhookType } from "@spacebar/schemas"; +import { trimSpecial } from "@spacebar/extensions"; const router: Router = Router({ mergeParams: true }); diff --git a/src/api/routes/guilds/#guild_id/templates.ts b/src/api/routes/guilds/#guild_id/templates.ts index 9942fef16..f2782bb85 100644 --- a/src/api/routes/guilds/#guild_id/templates.ts +++ b/src/api/routes/guilds/#guild_id/templates.ts @@ -18,8 +18,9 @@ import { Request, Response, Router } from "express"; import { HTTPError } from "lambert-server/HTTPError"; -import { generateCode, route } from "@spacebar/api"; +import { route } from "@spacebar/api"; import { Guild, Template } from "@spacebar/database"; +import { generateCode } from "@spacebar/extensions"; const router: Router = Router({ mergeParams: true }); diff --git a/src/api/routes/users/#user_id/delete.ts b/src/api/routes/users/#user_id/delete.ts index 49be55e22..9b12c7bbb 100644 --- a/src/api/routes/users/#user_id/delete.ts +++ b/src/api/routes/users/#user_id/delete.ts @@ -16,12 +16,13 @@ along with this program. If not, see . */ +import { Request, Response, Router } from "express"; +import { Not } from "typeorm"; import { route } from "@spacebar/api"; import { Channel, Emoji, Guild, InstanceBan, Member, Recipient, Sticker, User, UserSettingsProtos } from "@spacebar/database"; -import { ChannelDeleteEvent, ChannelRecipientRemoveEvent, emitEvent, Stopwatch, UserDeleteEvent } from "@spacebar/util"; -import { Request, Response, Router } from "express"; +import { ChannelDeleteEvent, ChannelRecipientRemoveEvent, emitEvent, UserDeleteEvent } from "@spacebar/util"; import { ChannelType, InstanceUserDeleteSchema, PrivateUserProjection } from "@spacebar/schemas"; -import { Not } from "typeorm"; +import { Stopwatch } from "@spacebar/extensions"; const router = Router({ mergeParams: true }); diff --git a/src/api/routes/users/@me/mentions.ts b/src/api/routes/users/@me/mentions.ts index e09084582..88d7ebb0b 100644 --- a/src/api/routes/users/@me/mentions.ts +++ b/src/api/routes/users/@me/mentions.ts @@ -20,7 +20,8 @@ import { Request, Response, Router } from "express"; import { In, LessThan, FindOptionsWhere } from "typeorm"; import { route } from "@spacebar/api"; import { Message, Member, Channel, Attachment } from "@spacebar/database"; -import { Snowflake, Permissions, NewUrlUserSignatureData, Stopwatch } from "@spacebar/util"; +import { Snowflake, Permissions, NewUrlUserSignatureData } from "@spacebar/util"; +import { Stopwatch } from "@spacebar/extensions"; const router: Router = Router({ mergeParams: true }); diff --git a/src/api/util/handlers/Instance.ts b/src/api/util/handlers/Instance.ts index 52d241aa0..64c4ac961 100644 --- a/src/api/util/handlers/Instance.ts +++ b/src/api/util/handlers/Instance.ts @@ -16,9 +16,9 @@ along with this program. If not, see . */ -import { Session } from "@spacebar/database"; -import { TimeSpan } from "@spacebar/util"; import { setInterval } from "node:timers"; +import { Session } from "@spacebar/database"; +import { TimeSpan } from "@spacebar/extensions"; export async function initInstance() { // TODO: clean up database and delete tombstone data diff --git a/src/api/util/handlers/Message.ts b/src/api/util/handlers/Message.ts index 65d41e431..d0176693a 100644 --- a/src/api/util/handlers/Message.ts +++ b/src/api/util/handlers/Message.ts @@ -20,7 +20,7 @@ import { HTTPError } from "lambert-server/HTTPError"; import { Equal, In, Or } from "typeorm"; import { fillMessageUrlEmbeds, randomString } from "@spacebar/api"; import { getDatabase, Application, Attachment, Channel, CloudAttachment, Guild, Member, Message, ReadState, Role, Session, Sticker, User, Webhook } from "@spacebar/database"; -import { mathLogBase, arrayDistributeSequentially } from "@spacebar/extensions"; +import { mathLogBase, arrayDistributeSequentially, Stopwatch } from "@spacebar/extensions"; import { Config, DiscordApiErrors, @@ -36,7 +36,6 @@ import { Permissions, ROLE_MENTION, Snowflake, - Stopwatch, TraceNode, TraceRoot, TraceSubTree, diff --git a/src/api/util/index.ts b/src/api/util/index.ts index cb26d4f54..c7cbc535f 100644 --- a/src/api/util/index.ts +++ b/src/api/util/index.ts @@ -22,7 +22,6 @@ export * from "./handlers/Message"; export * from "./utility/passwordStrength"; export * from "./utility/RandomInviteID"; export * from "./handlers/route"; -export * from "./utility/String"; export * from "./handlers/Voice"; export * from "./utility/captcha"; export * from "./utility/EmbedHandlers"; diff --git a/src/api/util/utility/EmbedHandlers.ts b/src/api/util/utility/EmbedHandlers.ts index c18e4f791..9aedce119 100644 --- a/src/api/util/utility/EmbedHandlers.ts +++ b/src/api/util/utility/EmbedHandlers.ts @@ -22,8 +22,8 @@ import { yellow } from "picocolors"; import probe from "probe-image-size"; import { FindOptionsWhere, In } from "typeorm"; import { EmbedCache, Message } from "@spacebar/database"; -import { sleep, arrayDistinctBy, arrayGroupBy } from "@spacebar/extensions"; -import { Config, emitEvent, MessageUpdateEvent, normalizeUrl, OrmUtils } from "@spacebar/util"; +import { sleep, arrayDistinctBy, arrayGroupBy, normalizeUrl } from "@spacebar/extensions"; +import { Config, emitEvent, MessageUpdateEvent, OrmUtils } from "@spacebar/util"; import { Embed, EmbedImage, EmbedType } from "@spacebar/schemas"; export function getDefaultFetchOptions(): RequestInit { diff --git a/src/api/util/utility/String.ts b/src/api/util/utility/String.ts deleted file mode 100644 index e33613a37..000000000 --- a/src/api/util/utility/String.ts +++ /dev/null @@ -1,38 +0,0 @@ -/* - Spacebar: A FOSS re-implementation and extension of the Discord.com backend. - Copyright (C) 2023 Spacebar and Spacebar Contributors - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as published - by the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . -*/ - -import { Request } from "express"; -import { ntob } from "./Base64"; -import { FieldErrors, Random } from "@spacebar/util"; - -export function checkLength(str: string, min: number, max: number, key: string, req: Request) { - if (str.length < min || str.length > max) { - throw FieldErrors({ - [key]: { - code: "BASE_TYPE_BAD_LENGTH", - message: req.t("common:field.BASE_TYPE_BAD_LENGTH", { - length: `${min} - ${max}`, - }), - }, - }); - } -} - -export function generateCode() { - return ntob(Date.now() + Random.nextInt(0, 10000)); -} diff --git a/src/bundle/start.ts b/src/bundle/start.ts index 59cf3c659..b9eff51b0 100644 --- a/src/bundle/start.ts +++ b/src/bundle/start.ts @@ -29,7 +29,8 @@ import cluster, { Worker } from "node:cluster"; import os from "node:os"; import "reflect-metadata"; import { red, bold, yellow, cyan, blueBright, redBright } from "picocolors"; -import { centerString, getRevInfoOrFail, Logo } from "@spacebar/util"; +import { centerString } from "@spacebar/extensions"; +import { getRevInfoOrFail, Logo } from "@spacebar/util"; import { initStats } from "./stats"; const cores = process.env.THREADS ? parseInt(process.env.THREADS) : 1; diff --git a/src/database/entities/Channel.ts b/src/database/entities/Channel.ts index 17a2a6284..6771fc407 100644 --- a/src/database/entities/Channel.ts +++ b/src/database/entities/Channel.ts @@ -20,7 +20,7 @@ import { HTTPError } from "lambert-server/HTTPError"; import { Column, Entity, JoinColumn, ManyToOne, OneToMany, RelationId } from "typeorm"; import { DmChannelDTO } from "../../util/dtos"; import { ChannelCreateEvent, ChannelRecipientRemoveEvent, ThreadCreateEvent, ThreadMembersUpdateEvent } from "../../util/interfaces"; -import { InvisibleCharacters, Snowflake, emitEvent, getPermission, trimSpecial, Permissions, Config, DiscordApiErrors } from "../../util/util"; +import { InvisibleCharacters, Snowflake, emitEvent, getPermission, Permissions, Config, DiscordApiErrors } from "../../util/util"; import { BaseClass } from "./BaseClass"; import { Guild } from "./Guild"; import { Invite } from "./Invite"; @@ -35,6 +35,7 @@ import { Member } from "./Member"; import { ChannelPermissionOverwrite, ChannelType, PublicChannel, PublicUserProjection, ThreadMetadata } from "@spacebar/schemas"; import { OrmUtils } from "../../util/imports"; import { ThreadMember } from "./ThreadMember"; +import { trimSpecial } from "@spacebar/extensions"; @Entity({ name: "channels", diff --git a/src/database/entities/Member.ts b/src/database/entities/Member.ts index b9fbac3d6..b5b0b3982 100644 --- a/src/database/entities/Member.ts +++ b/src/database/entities/Member.ts @@ -21,13 +21,14 @@ import { BeforeInsert, BeforeUpdate, Column, Entity, Index, JoinColumn, JoinTabl import { Ban, Channel, PublicGuildRelations } from "./index"; import { ReadyGuildDTO } from "../../util/dtos"; import { GuildCreateEvent, GuildDeleteEvent, GuildMemberAddEvent, GuildMemberRemoveEvent, GuildMemberUpdateEvent, MessageCreateEvent } from "../../util/interfaces"; -import { Config, emitEvent, DiscordApiErrors, Stopwatch } from "../../util/util"; +import { Config, emitEvent, DiscordApiErrors } from "../../util/util"; import { BaseClassWithoutId } from "./BaseClass"; import { Guild } from "./Guild"; import { Message } from "./Message"; import { Role } from "./Role"; import { User } from "./User"; import { AvatarDecorationData, Collectibles, DisplayNameStyle, PublicMember, PublicMemberProjection, UserGuildSettings } from "@spacebar/schemas"; +import { Stopwatch } from "@spacebar/extensions"; export const MemberPrivateProjection: (keyof Member)[] = [ "id", diff --git a/src/database/entities/Session.ts b/src/database/entities/Session.ts index e0e622dbb..cfe7803c3 100644 --- a/src/database/entities/Session.ts +++ b/src/database/entities/Session.ts @@ -17,12 +17,13 @@ */ import crypto from "node:crypto"; +import { Column, CreateDateColumn, Entity, Index, JoinColumn, ManyToOne, PrimaryColumn, RelationId } from "typeorm"; +import { randomUpperString } from "@spacebar/api"; +import { DateBuilder, TimeSpan } from "@spacebar/extensions"; import { User } from "./User"; import { BaseClassWithoutId } from "./BaseClass"; -import { Column, CreateDateColumn, Entity, Index, JoinColumn, ManyToOne, PrimaryColumn, RelationId } from "typeorm"; import { Activity, ClientStatus, GatewaySession, GatewaySessionClientInfo, PrivateStatus } from "../../util/interfaces"; -import { randomUpperString } from "@spacebar/api"; -import { DateBuilder, IpDataClient, TimeSpan } from "../../util/util"; +import { IpDataClient } from "../../util/util"; @Entity({ name: "sessions", diff --git a/src/database/entities/User.ts b/src/database/entities/User.ts index 5f40adb36..5c2c4fe12 100644 --- a/src/database/entities/User.ts +++ b/src/database/entities/User.ts @@ -18,8 +18,8 @@ import { Request } from "express"; import { Column, Entity, JoinColumn, OneToMany, OneToOne } from "typeorm"; -import { Config, Email, FieldErrors, Snowflake, Stopwatch, trimSpecial } from "@spacebar/util"; -import { Random } from "@spacebar/util/util/Random"; +import { Config, Email, FieldErrors, Snowflake } from "@spacebar/util"; +import { Stopwatch, trimSpecial, Random } from "@spacebar/extensions"; import { BaseClass } from "./BaseClass"; import { Channel } from "./Channel"; import { ConnectedAccount } from "./ConnectedAccount"; diff --git a/src/util/util/DateBuilder.test.ts b/src/extensions/DateBuilder.test.ts similarity index 100% rename from src/util/util/DateBuilder.test.ts rename to src/extensions/DateBuilder.test.ts diff --git a/src/util/util/DateBuilder.ts b/src/extensions/DateBuilder.ts similarity index 100% rename from src/util/util/DateBuilder.ts rename to src/extensions/DateBuilder.ts diff --git a/src/util/util/ElapsedTime.test.ts b/src/extensions/ElapsedTime.test.ts similarity index 100% rename from src/util/util/ElapsedTime.test.ts rename to src/extensions/ElapsedTime.test.ts diff --git a/src/util/util/ElapsedTime.ts b/src/extensions/ElapsedTime.ts similarity index 100% rename from src/util/util/ElapsedTime.ts rename to src/extensions/ElapsedTime.ts diff --git a/src/util/util/Random.ts b/src/extensions/Random.ts similarity index 78% rename from src/util/util/Random.ts rename to src/extensions/Random.ts index b81e17cd7..212e1c9aa 100644 --- a/src/util/util/Random.ts +++ b/src/extensions/Random.ts @@ -1,3 +1,21 @@ +/* + Spacebar: A FOSS re-implementation and extension of the Discord.com backend. + Copyright (C) 2026 Spacebar and Spacebar Contributors + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published + by the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see . +*/ + // Inspired by dotnet: https://learn.microsoft.com/en-us/dotnet/api/system.random?view=net-9.0#methods export class Random { public static nextInt(min?: number, max?: number): number { diff --git a/src/util/util/Stopwatch.test.ts b/src/extensions/Stopwatch.test.ts similarity index 100% rename from src/util/util/Stopwatch.test.ts rename to src/extensions/Stopwatch.test.ts diff --git a/src/util/util/Stopwatch.ts b/src/extensions/Stopwatch.ts similarity index 100% rename from src/util/util/Stopwatch.ts rename to src/extensions/Stopwatch.ts diff --git a/src/util/util/String.ts b/src/extensions/String.ts similarity index 66% rename from src/util/util/String.ts rename to src/extensions/String.ts index d0e757003..5c623e307 100644 --- a/src/util/util/String.ts +++ b/src/extensions/String.ts @@ -16,7 +16,11 @@ along with this program. If not, see . */ -import { SPECIAL_CHAR } from "./Regex"; +import { Request } from "express"; +import { SPECIAL_CHAR } from "@spacebar/util/util/Regex"; +import { Random } from "@spacebar/extensions/Random"; +import { ntob } from "@spacebar/api"; +import { FieldErrors } from "@spacebar/util"; export function trimSpecial(str?: string): string { if (!str) return ""; @@ -44,3 +48,21 @@ export function stringGlobToRegexp(str: string, flags?: string): RegExp { const escaped = str.replace(".", "\\.").replace("?", ".").replace("*", ".*"); return new RegExp(escaped, flags); } + +export function stringCheckLength(str: string, min: number, max: number, key: string, req: Request) { + if (str.length < min || str.length > max) { + throw FieldErrors({ + [key]: { + code: "BASE_TYPE_BAD_LENGTH", + // TODO: remove dependency on request (add generic field?) + message: req.t("common:field.BASE_TYPE_BAD_LENGTH", { + length: `${min} - ${max}`, + }), + }, + }); + } +} + +export function generateCode() { + return ntob(Date.now() + Random.nextInt(0, 10000)); +} diff --git a/src/util/util/Timespan.test.ts b/src/extensions/Timespan.test.ts similarity index 100% rename from src/util/util/Timespan.test.ts rename to src/extensions/Timespan.test.ts diff --git a/src/util/util/Timespan.ts b/src/extensions/Timespan.ts similarity index 100% rename from src/util/util/Timespan.ts rename to src/extensions/Timespan.ts diff --git a/src/util/util/Url.ts b/src/extensions/Url.ts similarity index 100% rename from src/util/util/Url.ts rename to src/extensions/Url.ts diff --git a/src/extensions/index.ts b/src/extensions/index.ts index 53bd443c8..155637247 100644 --- a/src/extensions/index.ts +++ b/src/extensions/index.ts @@ -17,7 +17,14 @@ */ export * from "./Array"; +export * from "./DateBuilder"; +export * from "./ElapsedTime"; export * from "./Math"; +export * from "./Random"; +export * from "./Stopwatch"; +export * from "./String"; +export * from "./Timespan"; +export * from "./Url"; // TODO: move to a separate file export async function sleep(ms: number) { diff --git a/src/gateway/opcodes/GuildSync.ts b/src/gateway/opcodes/GuildSync.ts index f075028b6..f7c0dd0c9 100644 --- a/src/gateway/opcodes/GuildSync.ts +++ b/src/gateway/opcodes/GuildSync.ts @@ -18,9 +18,10 @@ import { In } from "typeorm"; import { Member, Session } from "@spacebar/database"; +import { Stopwatch, timePromise } from "@spacebar/extensions"; import { WebSocket, Payload, OPCODES, Send, handleOffloadedGatewayRequest } from "@spacebar/gateway"; import { PublicMember } from "@spacebar/schemas"; -import { Presence, timePromise, Stopwatch, Config, getMostRelevantSession } from "@spacebar/util"; +import { Presence, Config, getMostRelevantSession } from "@spacebar/util"; // TODO: only show roles/members that have access to this channel // TODO: config: to list all members (even those who are offline) sorted by role, or just those who are online diff --git a/src/gateway/opcodes/Identify.ts b/src/gateway/opcodes/Identify.ts index 9c87aec91..5da55b046 100644 --- a/src/gateway/opcodes/Identify.ts +++ b/src/gateway/opcodes/Identify.ts @@ -19,7 +19,7 @@ import { In, Not } from "typeorm"; import { PreloadedUserSettings } from "discord-protos"; import { Capabilities, CLOSECODES, OPCODES, Payload, Send, setupListener, WebSocket } from "@spacebar/gateway"; -import { arrayGroupBy } from "@spacebar/extensions"; +import { arrayGroupBy, ElapsedTime, Stopwatch, timeFunction, timePromise } from "@spacebar/extensions"; import { getDatabase, Application, @@ -43,7 +43,6 @@ import { checkToken, Config, CurrentTokenFormatVersion, - ElapsedTime, emitEvent, EVENTEnum, generateToken, @@ -55,9 +54,6 @@ import { ReadyGuildDTO, ReadyUserGuildSettingsEntries, SessionsReplace, - Stopwatch, - timeFunction, - timePromise, TraceNode, TraceRoot, } from "@spacebar/util"; diff --git a/src/gateway/opcodes/RequestGuildMembers.ts b/src/gateway/opcodes/RequestGuildMembers.ts index ec8e17cfb..db13ea8c1 100644 --- a/src/gateway/opcodes/RequestGuildMembers.ts +++ b/src/gateway/opcodes/RequestGuildMembers.ts @@ -18,9 +18,10 @@ import { FindManyOptions, ILike, In, MoreThan } from "typeorm"; import { getDatabase, Member, Session } from "@spacebar/database"; +import { DateBuilder } from "@spacebar/extensions"; import { WebSocket, Payload, OPCODES, Send, handleOffloadedGatewayRequest } from "@spacebar/gateway"; import { RequestGuildMembersSchema } from "@spacebar/schemas"; -import { Config, DateBuilder, getPermission, GuildMembersChunkEvent, Presence } from "@spacebar/util"; +import { Config, getPermission, GuildMembersChunkEvent, Presence } from "@spacebar/util"; import { check } from "./instanceOf"; export async function onRequestGuildMembers(this: WebSocket, { d }: Payload) { diff --git a/src/gateway/util/Utils.ts b/src/gateway/util/Utils.ts index 23e9569bf..ad5cd21f2 100644 --- a/src/gateway/util/Utils.ts +++ b/src/gateway/util/Utils.ts @@ -17,7 +17,8 @@ */ import { Session, VoiceState } from "@spacebar/database"; -import { Event, TimeSpan } from "@spacebar/util"; +import { TimeSpan } from "@spacebar/extensions"; +import { Event } from "@spacebar/util"; import { WebSocket } from "./WebSocket"; import { OPCODES } from "./Constants"; import { Send } from "./Send"; diff --git a/src/util/util/Token.ts b/src/util/util/Token.ts index 10bd5e2c5..e8cd9ecb2 100644 --- a/src/util/util/Token.ts +++ b/src/util/util/Token.ts @@ -25,7 +25,7 @@ import { existsSync } from "node:fs"; // TODO: dont use deprecated APIs lol import { FindOptionsRelationByString, FindOptionsSelectByString } from "typeorm"; import { randomUpperString } from "@spacebar/api"; -import { TimeSpan } from "./Timespan"; +import { TimeSpan } from "../../extensions/Timespan"; import { HTTPError } from "lambert-server/HTTPError"; import path from "node:path"; diff --git a/src/util/util/index.ts b/src/util/util/index.ts index d4f21d618..fb7c209c2 100644 --- a/src/util/util/index.ts +++ b/src/util/util/index.ts @@ -22,9 +22,7 @@ export * from "./BitField"; export * from "./cdn"; export * from "./Config"; export * from "./Constants"; -export * from "./DateBuilder"; export * from "./email"; -export * from "./ElapsedTime"; export * from "./ipc/Event"; export * from "./FieldError"; export * from "./Intents"; @@ -39,9 +37,6 @@ export * from "./ipc/RabbitMQ"; export * from "./Regex"; export * from "./Rights"; export * from "./Snowflake"; -export * from "./Stopwatch"; -export * from "./String"; -export * from "./Timespan"; export * from "./Token"; export * from "./TraverseDirectory"; export * from "./WebAuthn"; @@ -49,7 +44,5 @@ export * from "./ChannelFlags"; export * from "./Gifs"; export * from "./Application"; export * from "./NameValidation"; -export * from "./Random"; -export * from "./Url"; export * from "./Version"; export * from "./Presence"; diff --git a/src/util/util/ipc/writer/UnixSocketWriter.ts b/src/util/util/ipc/writer/UnixSocketWriter.ts index b50f53dcb..e8b810a8b 100644 --- a/src/util/util/ipc/writer/UnixSocketWriter.ts +++ b/src/util/util/ipc/writer/UnixSocketWriter.ts @@ -20,11 +20,12 @@ import net, { Socket } from "node:net"; import fs, { FSWatcher } from "node:fs"; import path from "node:path"; import { red } from "picocolors"; -import { BaseEventWriter } from "./BaseEventWriter"; -import { Event, Stopwatch } from "@spacebar/util"; -import { ProcessLifecycle } from "../../ProcessLifecycle"; -import { Monitoring } from "../../../monitoring/Monitoring"; import { Gauge } from "prom-client"; +import { Stopwatch } from "@spacebar/extensions"; +import { Event } from "@spacebar/util"; +import { Monitoring } from "../../../monitoring/Monitoring"; +import { ProcessLifecycle } from "../../ProcessLifecycle"; +import { BaseEventWriter } from "./BaseEventWriter"; export class UnixSocketWriter extends BaseEventWriter { private static openConnectionsMetric: Gauge; diff --git a/src/util/util/json/JsonSerializer.test.ts b/src/util/util/json/JsonSerializer.test.ts index 5adf6c1ee..ff5bb7440 100644 --- a/src/util/util/json/JsonSerializer.test.ts +++ b/src/util/util/json/JsonSerializer.test.ts @@ -2,7 +2,7 @@ import { JsonSerializer } from "./JsonSerializer"; import { describe, it } from "node:test"; import { strict as assert } from "node:assert"; import fs from "node:fs/promises"; -import { Stopwatch } from "../Stopwatch"; +import { Stopwatch } from "../../../extensions/Stopwatch"; import { JsonValue } from "@protobuf-ts/runtime"; describe("JsonSerializer", () => { diff --git a/src/util/util/networking/abuseipdb/AbuseIpDbClient.ts b/src/util/util/networking/abuseipdb/AbuseIpDbClient.ts index b001fc75f..327d052d0 100644 --- a/src/util/util/networking/abuseipdb/AbuseIpDbClient.ts +++ b/src/util/util/networking/abuseipdb/AbuseIpDbClient.ts @@ -1,4 +1,23 @@ -import { Config, DateBuilder } from "@spacebar/util"; +/* + Spacebar: A FOSS re-implementation and extension of the Discord.com backend. + Copyright (C) 2025 Spacebar and Spacebar Contributors + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published + by the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see . +*/ + +import { DateBuilder } from "@spacebar/extensions"; +import { Config } from "@spacebar/util"; import { AbuseIpDbBlacklistResponse, AbuseIpDbCheckResponse } from "./AbuseIpDbSampleResponses"; export class AbuseIpDbClient { diff --git a/src/util/util/networking/ipdata/IpDataClient.ts b/src/util/util/networking/ipdata/IpDataClient.ts index b15513890..f717e3306 100644 --- a/src/util/util/networking/ipdata/IpDataClient.ts +++ b/src/util/util/networking/ipdata/IpDataClient.ts @@ -1,4 +1,23 @@ -import { Config, DateBuilder } from "@spacebar/util"; +/* + Spacebar: A FOSS re-implementation and extension of the Discord.com backend. + Copyright (C) 2026 Spacebar and Spacebar Contributors + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published + by the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see . +*/ + +import { DateBuilder } from "@spacebar/extensions"; +import { Config } from "@spacebar/util"; import { IpDataIpLookupResponse } from "./IpDataSampleResponses"; export class IpDataClient { diff --git a/src/util/util/networking/stopforumspam/StopForumSpamClient.ts b/src/util/util/networking/stopforumspam/StopForumSpamClient.ts index 7767915ac..c64d6dc32 100644 --- a/src/util/util/networking/stopforumspam/StopForumSpamClient.ts +++ b/src/util/util/networking/stopforumspam/StopForumSpamClient.ts @@ -16,7 +16,7 @@ along with this program. If not, see . */ -import { DateBuilder } from "@spacebar/util"; +import { DateBuilder } from "@spacebar/extensions"; // https://www.stopforumspam.com/usage export class StopForumSpamClient { diff --git a/src/util/util/workers/bcrypt/BcryptWorkerPool.ts b/src/util/util/workers/bcrypt/BcryptWorkerPool.ts index 1d1705ef0..6316adac7 100644 --- a/src/util/util/workers/bcrypt/BcryptWorkerPool.ts +++ b/src/util/util/workers/bcrypt/BcryptWorkerPool.ts @@ -1,6 +1,6 @@ import { isMainThread, parentPort, Worker } from "node:worker_threads"; import { ProcessLifecycle } from "../../ProcessLifecycle"; -import { Stopwatch } from "../../Stopwatch"; +import { Stopwatch } from "../../../../extensions/Stopwatch"; import bcrypt from "bcrypt"; export class BcryptWorkerPool {