From 1632642b0d1df2590eced3069d1b0f2b4df5210c Mon Sep 17 00:00:00 2001 From: Rory& Date: Wed, 15 Oct 2025 10:07:33 +0200 Subject: [PATCH] More schema work, moved most stuff from entities to schemas, though messy --- .idea/workspace.xml | 10 +- assets/openapi.json | Bin 1325542 -> 1328781 bytes assets/schemas.json | Bin 3714234 -> 3715925 bytes src/api/routes/channels/#channel_id/index.ts | 3 +- .../routes/channels/#channel_id/invites.ts | 4 +- .../messages/#message_id/reactions.ts | 4 +- .../channels/#channel_id/messages/index.ts | 3 +- .../channels/#channel_id/permissions.ts | 4 +- src/api/routes/channels/#channel_id/purge.ts | 3 +- .../routes/channels/#channel_id/recipients.ts | 3 +- .../routes/channels/#channel_id/webhooks.ts | 4 +- .../#guild_id/members/#member_id/index.ts | 4 +- .../routes/guilds/#guild_id/members/index.ts | 3 +- src/api/routes/guilds/#guild_id/stickers.ts | 4 +- src/api/routes/guilds/#guild_id/vanity-url.ts | 3 +- .../#guild_id/voice-states/#user_id/index.ts | 3 +- src/api/routes/oauth2/applications/@me.ts | 2 +- src/api/routes/teams.ts | 4 +- src/api/routes/users/#user_id/delete.ts | 2 +- src/api/routes/users/#user_id/profile.ts | 5 +- src/api/routes/users/@me/index.ts | 3 +- src/api/routes/users/@me/relationships.ts | 3 +- src/gateway/opcodes/Identify.ts | 7 +- src/{util/util => schemas}/HelperTypes.ts | 0 src/schemas/api/channels/Channel.ts | 69 +++++++ src/schemas/api/channels/Webhook.ts | 5 + src/schemas/api/channels/index.ts | 19 ++ src/schemas/api/developers/Application.ts | 62 +++++++ src/schemas/api/developers/Team.ts | 9 + src/schemas/api/developers/index.ts | 2 + src/schemas/api/guilds/AuditLog.ts | 172 ++++++++++++++++++ src/schemas/api/guilds/Automod.ts | 37 ++++ .../guilds}/GuildProfileResponse.ts | 0 src/schemas/api/guilds/GuildSchema.ts | 24 +++ src/schemas/api/guilds/Role.ts | 13 ++ src/schemas/api/guilds/Sticker.ts | 11 ++ src/schemas/api/guilds/VoiceState.ts | 24 +++ src/schemas/api/guilds/index.ts | 24 +++ src/schemas/api/index.ts | 2 + src/schemas/api/messages/Message.ts | 10 +- src/schemas/api/users/ConnectedAccount.ts | 6 + src/schemas/api/users/Member.ts | 85 +++++++++ src/schemas/api/users/User.ts | 118 +++++++++++- src/schemas/api/users/index.ts | 2 + src/schemas/index.ts | 1 + .../CollectiblesCategoriesResponse.ts | 4 +- .../responses/GuildDiscoveryRequirements.ts | 2 +- .../responses/GuildMessagesSearchResponse.ts | 3 +- src/schemas/responses/TypedResponses.ts | 34 +--- src/schemas/responses/UserProfileResponse.ts | 6 +- .../responses/UserRelationshipsResponse.ts | 4 +- src/schemas/responses/index.ts | 1 - .../uncategorised/ChannelModifySchema.ts | 2 +- .../ChannelPermissionOverwriteSchema.ts | 2 +- .../uncategorised/UserGuildSettingsSchema.ts | 2 +- src/util/dtos/DmChannelDTO.ts | 3 +- src/util/dtos/ReadyGuildDTO.ts | 6 +- src/util/entities/Application.ts | 54 +----- src/util/entities/AuditLog.ts | 154 +--------------- src/util/entities/AutomodRule.ts | 24 +-- src/util/entities/Channel.ts | 70 +------ src/util/entities/ConnectedAccount.ts | 5 - src/util/entities/Member.ts | 86 +-------- src/util/entities/Role.ts | 15 +- src/util/entities/Sticker.ts | 13 +- src/util/entities/TeamMember.ts | 11 +- src/util/entities/User.ts | 78 +------- src/util/entities/UserSettings.ts | 1 - src/util/entities/VoiceState.ts | 24 +-- src/util/entities/Webhook.ts | 7 +- src/util/interfaces/Event.ts | 7 +- src/util/interfaces/Presence.ts | 2 +- src/util/util/Permissions.ts | 3 +- src/util/util/index.ts | 2 +- 74 files changed, 758 insertions(+), 643 deletions(-) rename src/{util/util => schemas}/HelperTypes.ts (100%) create mode 100644 src/schemas/api/channels/Channel.ts create mode 100644 src/schemas/api/channels/Webhook.ts create mode 100644 src/schemas/api/channels/index.ts create mode 100644 src/schemas/api/developers/Application.ts create mode 100644 src/schemas/api/developers/Team.ts create mode 100644 src/schemas/api/guilds/AuditLog.ts create mode 100644 src/schemas/api/guilds/Automod.ts rename src/schemas/{responses => api/guilds}/GuildProfileResponse.ts (100%) create mode 100644 src/schemas/api/guilds/GuildSchema.ts create mode 100644 src/schemas/api/guilds/Role.ts create mode 100644 src/schemas/api/guilds/Sticker.ts create mode 100644 src/schemas/api/guilds/VoiceState.ts create mode 100644 src/schemas/api/guilds/index.ts create mode 100644 src/schemas/api/users/ConnectedAccount.ts create mode 100644 src/schemas/api/users/Member.ts diff --git a/.idea/workspace.xml b/.idea/workspace.xml index 61c93ca2..0708f702 100644 --- a/.idea/workspace.xml +++ b/.idea/workspace.xml @@ -19,8 +19,8 @@ @@ -61,7 +61,7 @@ "RunOnceActivity.git.unshallow": "true", "javascript.nodejs.core.library.configured.version": "24.8.0", "javascript.nodejs.core.library.typings.version": "24.7.0", - "last_opened_file_path": "/home/Rory/git/spacebar/server-master/src/schemas", + "last_opened_file_path": "/home/Rory/git/spacebar/server-master/src/schemas/api/guilds", "node.js.detected.package.eslint": "true", "node.js.selected.package.eslint": "(autodetect)", "node.js.selected.package.tslint": "(autodetect)", @@ -86,18 +86,18 @@ }]]> + - + - @@ -144,7 +144,7 @@ - + diff --git a/assets/openapi.json b/assets/openapi.json index 6a4563a2c3d8675055f7f88526be394e59e57794..725a0004d69e25f2d312a6f4c9f8a1c528d95920 100644 GIT binary patch delta 1262 zcmcJOZ)h839LGuTa(B-?&t0!ex5jK~uN!5!*%({4IBU~7T9a8TSuM=AuDx^xQPVAz zS#Ta1k*=oOl;#a|!NugeabQCvqND808r!$QJ%9kb7nRr$iOjMOGyLa3j01 zY${o#BgJdy*p$rQ9%Vh`Kf-rF<1;QBZ2Nc9!{1>s z+2u{5n4oF6Iilc=SB!Ifw8Px*hy9JD^7gI9dg&06gM7mYqjsP?=O%GC^;58)msOr3 z=5DDxu*^>wW`n^mG?`fu)~k~Ba?F~DSw2C9KoZCTzd#YFJZ5RDN8tWp>J!N^Q&1_e O1XY3+JUJGaKL0n0OvySIuWEIjG|HH6dC57xD zX~fOdR17>CaPbM&?l68(-wIXjQ7g2tcRAad= zlT{S*g44XO6ZR)uDv4sJ3U7b7$8g0xJ*&R#C@9a zA)O>CMEpdZV^aO+E&K=P>31iNCy#83x2wFEznnqjAS+(P!ACm{nJxeSZp*F!8IuLO3n z4wN&#DAKCG0g;1&#rgflBY$mQdrghN?PQu*{U$pSmLj*}$OUF2$4DDoA6b<@AZr%F zCQf)cBf+6b3M$P zdO$%r$h~63{4sBpm)iBzI zsJentRV9NaI2in8v}a+I&I>(88#4vTQK-l7=R_DZpTt4>Tj zJGH+sNLTD=-}*}XCJ5D@wV3r*8KdJP8e;iG*~MVe%P27LxiU8z7dg>?voH_g5nCP_ zVxrdMP>#rDjSAr{o^-H}$z|Yc4C^}krezd4>6=zu{`I1^`wSxA&3OrtUzImN7|pCe z=z?AfcDMRDn0f1Ru-7uAoz@X0C6l5e))DolD@bhR3*df}-3s=AXD{ZvIW-AJJtYj8 zy5zVnKA=yJCUhEX8`WwNnQ#a13Si|wKkvj18BRY~foI1^>t(Y)R(L1+z|ojeWM zc#t(@KnQze7~iQ@VelX;jU8eoWcNGl28PV^vB$JaHlHZUj1hBv)lCUux0gaphF(<< zn2B()=;=dbsI;U%p9JTO_9G-Tnbnw05{=p?$~zzQXen6~9eL2BpP4{-t;vqS33)H# z16)a`&}yJ$Q;bAt&3U_zsYNd@*#LjH)JJ~In@;jf4W68<*@yLdlZMVx`K72(YlU!P zSqr9o8KsLem&+s;64skKq~C&)Q%vV^pNSmzamps#xMeg^o5`Z%pRGsYyuyG;zeEML zCY??C=LzK9lk*Qh5H2WkmV7|nW`%n@TO8}*RG_XiFSzrghLR$>CW8#^)|HYWQWN!8yPKNlq2HnFC;$2(~QSV_NV{pS@Q$px6=u%-D z^-EX;FF4kr`D0ESy)?qYzt^x5M-Ow^2;4QAsR}2A35Oc-JC21lNF3%i#(v7BW9SWb zA9j^^O2GbEUWA!jd~*9TxCcEu@Q-tRCc^!EY8ME;qI(uXC$l2?o&$fLH=sLV(c!`O zD=cv8ZAPrq+vqzbJ?8cEygr#hS=cqNG>~m?bN3i>`np0YPlnZ=+eCQETELO@W4Rq4 zAe5EGlG($#P7&PQ<_%B;`OS+#x-?%&D9C>%`KFoF87D)$3`74^EwPI`#H*0#*CbEC zV#>y7NyGQ}=hLGB3H9%5MkRuyOYJx_Xh_C{liEg1f;!6tgYJ5-G!inGkM;YR4?2j)%sqy{ zALw6%UHnQUe#f~G|H|Bu(iVJ~tAr4#u137YUXQ7{>N11|Olx7ubC)4dUsk&yh1u-7 zq~wmZ+K<8gSEUP<9)%ByE~SgaCzsh7_?`5y{)Xb!U`=!erX%$CW#i<2n_&$zcAAe%V#5jv89K||5h0RLZUU{EG6=VoUtqS^kV?gr7s!yx z*22KjSW=C^du6Vepo$@A$)r}%DGI=99QBBtD|CZBt?|TWEnkppef(81!he+PAT+1W zrjf*P&3}_2q$O6SxKBBZ2;Y%gl7-?22==RN zNc^y%4#L;YLK1XU{Vns~e&0zu9!fREL%W}vBM!`+RHiOUdNHiV?zSv0Wvc$oaw+M1 zxn}!MzLn;K{6_EHtBu*cUt*}yD@AZ~c|L?I;=CyPOBSb}wpt!Kj?CM$B0y|7qc)t6YPIj&l0=N|ZxIp}>+;U?ZEWgB}%^4I?b>kD*d delta 2448 zcmdUwe{37&8OL>J-}&r1_MM&BX`0yQi=8=%<2Xs}2DTD+^cT}gjk-ct1i55uHLa|5 z6R}Bywnh`qLbSxe%-QJOnV*E z!lX_7hqOOFr+eWDIub~yXf>XHna%mx3W{XD0fOFqvwh_K>p$CylWJZu7$!chTH=~ZiWoG**9KC zqFMMBifc_jMDEert*J{DI;dwH>j%a@VJRAlmW+MEJ^3c4FDVZ}PFm|H3(9sK!XGML zh%fVIj9d^*B=M25kB2&B;L!Ir-;;bGSUZ~c6URGzm4N6wJdZ5BkUR4HItI4|SsR%+ z&p%};@1MJgOCjAUsff(f_ag7Jm@u|j_x%C+Do^CAy5Aq(v&rz1ZQ$qufug4v$k7Ay ziboKY_{L=BiBX8h+|9_k%wt%6M(`pWW`mf$nW;cRU+G2m1N}GAebA>ME80b*uSg;6 zKIn6l&DbM~6X~;_YN!csQ+&`EAFPNEnkEO$osTggY<-OJBU%}1Lb^Y6BcjjhI7}#F zd&yZ(=6S>|b<9Gv{X7&xBhP&(Ie`}@lE1y8Dwhxb|NkpcX40m<^yzd8i4fNN{s0J%W>;khEEOGRgLCb z@VLtIkPq`qVLBqMz`0qW7BQ3F_3(@n;Vq&av0i6&GGKBbeN3uI@s`T}TvppPwR6kz zOVS@Oa#Y$3@t3@r?D&(klRG^{l?o%L01s<73nRO zbf44A>PdQy^T58zla6sG8GBlP%X`Saq3CgL*s3Bi<7-9c1&ebuFCx>=Sjd)9>z#b* zxetH2m#Lcz73q(CD@kOrZ9M((;^*o%_rtv)_WLI6dJqThz(oUk>4D&Ue=Tv?rvn~SxU9xD0gpE z&-JFF&UPejv$c}&xbYE|Y|dLxaVf9kN~tkb$j@`S)LEac+;7D-x^9Fu+-gMURUWzC zrc>xnc-3ThXakB(W<4UAniOJgyC2zz)(CY4qaq(@5a_=Yq9s=|c1%e%x{^@GV4>H+72OmQs_f^zwz71HMjzZUc5F7#2eh52*2viA?DTm z1mZ<6he)HwkK!TDPZEEuxx`{b!)-v|S1d=&r>)}*)GkSj@B>B_baLsDF>r68_4OL# zz_3wwuk#Kg+s*gD*N#Nb#dH|#73K8fZ1rH z*eTVN`IH*U0!l5Vj^dy=DKf=Hn2pM|dr~XCT&jw#F4g$GBk`d($_ zwH5+xp>~+2E9vC%I`R zctMF5>f;4>yx@r!8sdd-#0%cZLSyi*um0pK98R28c#>P)w2epXdrU8)9YQzKR#!J7 z2JPL*EH=-jGl=}N`kqpJ9Z0k>!LsPZmY6yrpHiw3@GvrRJ&pZ{F41(+((xqK%?c^5 zZz&wrjHAPFduuz2zpDr#!TRfwyQSqj z*!-EUru=f^RbIr2&vc$InbV)vD`it&nWvy`~rcda&7B ab}9}TM06eZcpyHxKu>IU`necu*!FL==c;4? diff --git a/src/api/routes/channels/#channel_id/index.ts b/src/api/routes/channels/#channel_id/index.ts index cc43790a..1535b005 100644 --- a/src/api/routes/channels/#channel_id/index.ts +++ b/src/api/routes/channels/#channel_id/index.ts @@ -20,14 +20,13 @@ import { route } from "@spacebar/api"; import { Channel, ChannelDeleteEvent, - ChannelType, ChannelUpdateEvent, Recipient, emitEvent, handleFile, } from "@spacebar/util"; import { Request, Response, Router } from "express"; -import { ChannelModifySchema } from "@spacebar/schemas" +import { ChannelModifySchema, ChannelType } from "@spacebar/schemas" const router: Router = Router({ mergeParams: true }); // TODO: delete channel diff --git a/src/api/routes/channels/#channel_id/invites.ts b/src/api/routes/channels/#channel_id/invites.ts index b6ce0721..fcf6f97c 100644 --- a/src/api/routes/channels/#channel_id/invites.ts +++ b/src/api/routes/channels/#channel_id/invites.ts @@ -17,10 +17,10 @@ */ import { randomString, route } from "@spacebar/api"; -import { Channel, Guild, Invite, InviteCreateEvent, PublicInviteRelation, User, emitEvent, isTextChannel } from "@spacebar/util"; +import { Channel, Guild, Invite, InviteCreateEvent, PublicInviteRelation, User, emitEvent } from "@spacebar/util"; import { Request, Response, Router } from "express"; import { HTTPError } from "lambert-server"; -import { InviteCreateSchema } from "@spacebar/schemas" +import { InviteCreateSchema, isTextChannel } from "@spacebar/schemas" const router: Router = Router({ mergeParams: true }); diff --git a/src/api/routes/channels/#channel_id/messages/#message_id/reactions.ts b/src/api/routes/channels/#channel_id/messages/#message_id/reactions.ts index 97e7e6b0..dcd98ff5 100644 --- a/src/api/routes/channels/#channel_id/messages/#message_id/reactions.ts +++ b/src/api/routes/channels/#channel_id/messages/#message_id/reactions.ts @@ -28,14 +28,12 @@ import { MessageReactionRemoveAllEvent, MessageReactionRemoveEmojiEvent, MessageReactionRemoveEvent, - PublicMemberProjection, - PublicUserProjection, User, } from "@spacebar/util"; import { Request, Response, Router } from "express"; import { HTTPError } from "lambert-server"; import { In } from "typeorm"; -import { PartialEmoji } from "@spacebar/schemas" +import { PartialEmoji, PublicMemberProjection, PublicUserProjection } from "@spacebar/schemas"; const router = Router({ mergeParams: true }); // TODO: check if emoji is really an unicode emoji or a properly encoded external emoji diff --git a/src/api/routes/channels/#channel_id/messages/index.ts b/src/api/routes/channels/#channel_id/messages/index.ts index 03d7ca54..391b7b6f 100644 --- a/src/api/routes/channels/#channel_id/messages/index.ts +++ b/src/api/routes/channels/#channel_id/messages/index.ts @@ -32,7 +32,6 @@ import { User, emitEvent, getPermission, - isTextChannel, getUrlSignature, uploadFile, NewUrlSignatureData, @@ -43,7 +42,7 @@ import { HTTPError } from "lambert-server"; import multer from "multer"; import { FindManyOptions, FindOperator, LessThan, MoreThan, MoreThanOrEqual } from "typeorm"; import { URL } from "url"; -import { MessageCreateAttachment, MessageCreateCloudAttachment, MessageCreateSchema, Reaction } from "@spacebar/schemas" +import { isTextChannel, MessageCreateAttachment, MessageCreateCloudAttachment, MessageCreateSchema, Reaction } from "@spacebar/schemas"; const router: Router = Router({ mergeParams: true }); diff --git a/src/api/routes/channels/#channel_id/permissions.ts b/src/api/routes/channels/#channel_id/permissions.ts index 62b265e3..e0feb3f9 100644 --- a/src/api/routes/channels/#channel_id/permissions.ts +++ b/src/api/routes/channels/#channel_id/permissions.ts @@ -16,12 +16,12 @@ along with this program. If not, see . */ -import { Channel, ChannelPermissionOverwrite, ChannelPermissionOverwriteType, ChannelUpdateEvent, emitEvent, Member, Role } from "@spacebar/util"; +import { Channel, ChannelUpdateEvent, emitEvent, Member, Role } from "@spacebar/util"; import { Request, Response, Router } from "express"; import { HTTPError } from "lambert-server"; import { route } from "@spacebar/api"; -import { ChannelPermissionOverwriteSchema } from "@spacebar/schemas" +import { ChannelPermissionOverwriteSchema, ChannelPermissionOverwrite, ChannelPermissionOverwriteType } from "@spacebar/schemas" const router: Router = Router({ mergeParams: true }); // TODO: Only permissions your bot has in the guild or channel can be allowed/denied (unless your bot has a MANAGE_ROLES overwrite in the channel) diff --git a/src/api/routes/channels/#channel_id/purge.ts b/src/api/routes/channels/#channel_id/purge.ts index c48a46ad..c8a2efab 100644 --- a/src/api/routes/channels/#channel_id/purge.ts +++ b/src/api/routes/channels/#channel_id/purge.ts @@ -24,12 +24,11 @@ import { emitEvent, getPermission, getRights, - isTextChannel, } from "@spacebar/util"; import { Request, Response, Router } from "express"; import { HTTPError } from "lambert-server"; import { Between, FindManyOptions, FindOperator, Not } from "typeorm"; -import { PurgeSchema } from "@spacebar/schemas" +import { isTextChannel, PurgeSchema } from "@spacebar/schemas"; const router: Router = Router({ mergeParams: true }); diff --git a/src/api/routes/channels/#channel_id/recipients.ts b/src/api/routes/channels/#channel_id/recipients.ts index 14ab28e5..65160274 100644 --- a/src/api/routes/channels/#channel_id/recipients.ts +++ b/src/api/routes/channels/#channel_id/recipients.ts @@ -20,15 +20,14 @@ import { route } from "@spacebar/api"; import { Channel, ChannelRecipientAddEvent, - ChannelType, DiscordApiErrors, DmChannelDTO, emitEvent, - PublicUserProjection, Recipient, User, } from "@spacebar/util"; import { Request, Response, Router } from "express"; +import { ChannelType, PublicUserProjection } from "@spacebar/schemas"; 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 2d0de323..cddff713 100644 --- a/src/api/routes/channels/#channel_id/webhooks.ts +++ b/src/api/routes/channels/#channel_id/webhooks.ts @@ -23,16 +23,14 @@ import { DiscordApiErrors, User, Webhook, - WebhookType, handleFile, - isTextChannel, trimSpecial, ValidateName, } from "@spacebar/util"; import crypto from "crypto"; import { Request, Response, Router } from "express"; import { HTTPError } from "lambert-server"; -import { WebhookCreateSchema } from "@spacebar/schemas" +import { isTextChannel, WebhookCreateSchema, WebhookType } from "@spacebar/schemas"; const router: Router = Router({ mergeParams: true }); diff --git a/src/api/routes/guilds/#guild_id/members/#member_id/index.ts b/src/api/routes/guilds/#guild_id/members/#member_id/index.ts index feb3bade..446d31d6 100644 --- a/src/api/routes/guilds/#guild_id/members/#member_id/index.ts +++ b/src/api/routes/guilds/#guild_id/members/#member_id/index.ts @@ -27,13 +27,11 @@ import { GuildMemberUpdateEvent, handleFile, Member, - PublicMemberProjection, - PublicUserProjection, Role, Sticker, } from "@spacebar/util"; import { Request, Response, Router } from "express"; -import { MemberChangeSchema } from "@spacebar/schemas" +import { MemberChangeSchema, PublicMemberProjection, PublicUserProjection } from "@spacebar/schemas"; const router = Router({ mergeParams: true }); diff --git a/src/api/routes/guilds/#guild_id/members/index.ts b/src/api/routes/guilds/#guild_id/members/index.ts index 0fa07f22..490d5b5e 100644 --- a/src/api/routes/guilds/#guild_id/members/index.ts +++ b/src/api/routes/guilds/#guild_id/members/index.ts @@ -17,10 +17,11 @@ */ import { route } from "@spacebar/api"; -import { Member, PublicMemberProjection } from "@spacebar/util"; +import { Member } from "@spacebar/util"; import { Request, Response, Router } from "express"; import { HTTPError } from "lambert-server"; import { MoreThan } from "typeorm"; +import { PublicMemberProjection } from "@spacebar/schemas"; const router = Router({ mergeParams: true }); diff --git a/src/api/routes/guilds/#guild_id/stickers.ts b/src/api/routes/guilds/#guild_id/stickers.ts index beccc7e8..b361f258 100644 --- a/src/api/routes/guilds/#guild_id/stickers.ts +++ b/src/api/routes/guilds/#guild_id/stickers.ts @@ -22,8 +22,6 @@ import { Member, Snowflake, Sticker, - StickerFormatType, - StickerType, emitEvent, uploadFile, Config, @@ -32,7 +30,7 @@ import { import { Request, Response, Router } from "express"; import { HTTPError } from "lambert-server"; import multer from "multer"; -import { ModifyGuildStickerSchema } from "@spacebar/schemas" +import { ModifyGuildStickerSchema, StickerFormatType, StickerType } from "@spacebar/schemas"; const router = Router({ mergeParams: true }); router.get( diff --git a/src/api/routes/guilds/#guild_id/vanity-url.ts b/src/api/routes/guilds/#guild_id/vanity-url.ts index 5261f679..ff4d5566 100644 --- a/src/api/routes/guilds/#guild_id/vanity-url.ts +++ b/src/api/routes/guilds/#guild_id/vanity-url.ts @@ -19,13 +19,12 @@ import { route } from "@spacebar/api"; import { Channel, - ChannelType, Guild, Invite, } from "@spacebar/util"; import { Request, Response, Router } from "express"; import { HTTPError } from "lambert-server"; -import { VanityUrlSchema } from "@spacebar/schemas" +import { ChannelType, VanityUrlSchema } from "@spacebar/schemas"; const router = Router({ mergeParams: true }); diff --git a/src/api/routes/guilds/#guild_id/voice-states/#user_id/index.ts b/src/api/routes/guilds/#guild_id/voice-states/#user_id/index.ts index 6966f705..1e602503 100644 --- a/src/api/routes/guilds/#guild_id/voice-states/#user_id/index.ts +++ b/src/api/routes/guilds/#guild_id/voice-states/#user_id/index.ts @@ -19,7 +19,6 @@ import { route } from "@spacebar/api"; import { Channel, - ChannelType, DiscordApiErrors, emitEvent, getPermission, @@ -27,7 +26,7 @@ import { VoiceStateUpdateEvent, } from "@spacebar/util"; import { Request, Response, Router } from "express"; -import { VoiceStateUpdateSchema } from "@spacebar/schemas" +import { ChannelType, VoiceStateUpdateSchema } from "@spacebar/schemas"; const router = Router({ mergeParams: true }); //TODO need more testing when community guild and voice stage channel are working diff --git a/src/api/routes/oauth2/applications/@me.ts b/src/api/routes/oauth2/applications/@me.ts index 82491e33..4dcf489e 100644 --- a/src/api/routes/oauth2/applications/@me.ts +++ b/src/api/routes/oauth2/applications/@me.ts @@ -20,9 +20,9 @@ import { route } from "@spacebar/api"; import { Application, DiscordApiErrors, - PublicUserProjection, } from "@spacebar/util"; import { Request, Response, Router } from "express"; +import { PublicUserProjection } from "@spacebar/schemas"; const router: Router = Router({ mergeParams: true }); diff --git a/src/api/routes/teams.ts b/src/api/routes/teams.ts index a936fe81..7353f107 100644 --- a/src/api/routes/teams.ts +++ b/src/api/routes/teams.ts @@ -21,12 +21,10 @@ import { route } from "@spacebar/api"; import { Team, TeamMember, - TeamMemberRole, - TeamMemberState, User, } from "@spacebar/util"; import { HTTPError } from "lambert-server"; -import { TeamCreateSchema } from "@spacebar/schemas" +import { TeamCreateSchema, TeamMemberRole, TeamMemberState } from "@spacebar/schemas"; 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 53af01eb..1a9d879c 100644 --- a/src/api/routes/users/#user_id/delete.ts +++ b/src/api/routes/users/#user_id/delete.ts @@ -20,11 +20,11 @@ import { route } from "@spacebar/api"; import { emitEvent, Member, - PrivateUserProjection, User, UserDeleteEvent, } from "@spacebar/util"; import { Request, Response, Router } from "express"; +import { PrivateUserProjection } from "@spacebar/schemas"; const router = Router({ mergeParams: true }); diff --git a/src/api/routes/users/#user_id/profile.ts b/src/api/routes/users/#user_id/profile.ts index 95940004..456f0cb7 100644 --- a/src/api/routes/users/#user_id/profile.ts +++ b/src/api/routes/users/#user_id/profile.ts @@ -24,16 +24,13 @@ import { FieldErrors, handleFile, Member, - PrivateUserProjection, - PublicUser, - PublicUserProjection, Relationship, User, UserUpdateEvent, } from "@spacebar/util"; import { Request, Response, Router } from "express"; import { In } from "typeorm"; -import { RelationshipType, UserProfileModifySchema } from "@spacebar/schemas" +import { PrivateUserProjection, PublicUser, PublicUserProjection, RelationshipType, UserProfileModifySchema } from "@spacebar/schemas"; const router: Router = Router({ mergeParams: true }); diff --git a/src/api/routes/users/@me/index.ts b/src/api/routes/users/@me/index.ts index 4d4c64b9..cb4bb442 100644 --- a/src/api/routes/users/@me/index.ts +++ b/src/api/routes/users/@me/index.ts @@ -23,13 +23,12 @@ import { FieldErrors, generateToken, handleFile, - PrivateUserProjection, User, UserUpdateEvent, } from "@spacebar/util"; import bcrypt from "bcrypt"; import { Request, Response, Router } from "express"; -import { UserModifySchema } from "@spacebar/schemas" +import { PrivateUserProjection, UserModifySchema } from "@spacebar/schemas"; const router: Router = Router({ mergeParams: true }); diff --git a/src/api/routes/users/@me/relationships.ts b/src/api/routes/users/@me/relationships.ts index 7b1780be..67555275 100644 --- a/src/api/routes/users/@me/relationships.ts +++ b/src/api/routes/users/@me/relationships.ts @@ -20,7 +20,6 @@ import { route } from "@spacebar/api"; import { Config, DiscordApiErrors, - PublicUserProjection, Relationship, RelationshipAddEvent, RelationshipRemoveEvent, @@ -29,7 +28,7 @@ import { } from "@spacebar/util"; import { Request, Response, Router } from "express"; import { HTTPError } from "lambert-server"; -import { RelationshipType } from "@spacebar/schemas" +import { PublicUserProjection, RelationshipType } from "@spacebar/schemas"; const router = Router({ mergeParams: true }); diff --git a/src/gateway/opcodes/Identify.ts b/src/gateway/opcodes/Identify.ts index 8b71840a..82b72f68 100644 --- a/src/gateway/opcodes/Identify.ts +++ b/src/gateway/opcodes/Identify.ts @@ -20,8 +20,6 @@ import { CLOSECODES, Capabilities, OPCODES, Payload, Send, WebSocket, setupListe import { Application, Config, - DMChannel, - DefaultUserGuildSettings, EVENTEnum, Guild, GuildOrUnavailable, @@ -31,9 +29,6 @@ import { OPCodes, PresenceUpdateEvent, PrivateSessionProjection, - PrivateUserProjection, - PublicUser, - PublicUserProjection, ReadState, ReadyEventData, ReadyGuildDTO, @@ -59,7 +54,7 @@ import { import { check } from "./instanceOf"; import { In } from "typeorm"; import { PreloadedUserSettings } from "discord-protos"; -import { IdentifySchema } from "@spacebar/schemas" +import { DefaultUserGuildSettings, DMChannel, IdentifySchema, PrivateUserProjection, PublicUser, PublicUserProjection } from "@spacebar/schemas"; // TODO: user sharding // TODO: check privileged intents, if defined in the config diff --git a/src/util/util/HelperTypes.ts b/src/schemas/HelperTypes.ts similarity index 100% rename from src/util/util/HelperTypes.ts rename to src/schemas/HelperTypes.ts diff --git a/src/schemas/api/channels/Channel.ts b/src/schemas/api/channels/Channel.ts new file mode 100644 index 00000000..7e447299 --- /dev/null +++ b/src/schemas/api/channels/Channel.ts @@ -0,0 +1,69 @@ +import { Channel, Recipient } from "@spacebar/util"; +import { HTTPError } from "lambert-server"; + +export enum ChannelType { + GUILD_TEXT = 0, // a text channel within a guild + DM = 1, // a direct message between users + GUILD_VOICE = 2, // a voice channel within a guild + GROUP_DM = 3, // a direct message between multiple users + GUILD_CATEGORY = 4, // an organizational category that contains zero or more channels + GUILD_NEWS = 5, // a channel that users can follow and crosspost into a guild or route + GUILD_STORE = 6, // a channel in which game developers can sell their things + ENCRYPTED = 7, // end-to-end encrypted channel + ENCRYPTED_THREAD = 8, // end-to-end encrypted thread channel + TRANSACTIONAL = 9, // event chain style transactional channel + GUILD_NEWS_THREAD = 10, // a temporary sub-channel within a GUILD_NEWS channel + GUILD_PUBLIC_THREAD = 11, // a temporary sub-channel within a GUILD_TEXT channel + GUILD_PRIVATE_THREAD = 12, // a temporary sub-channel within a GUILD_TEXT channel that is only viewable by those invited and those with the MANAGE_THREADS permission + GUILD_STAGE_VOICE = 13, // a voice channel for hosting events with an audience + DIRECTORY = 14, // guild directory listing channel + GUILD_FORUM = 15, // forum composed of IM threads + TICKET_TRACKER = 33, // ticket tracker, individual ticket items shall have type 12 + KANBAN = 34, // confluence like kanban board + VOICELESS_WHITEBOARD = 35, // whiteboard but without voice (whiteboard + voice is the same as stage) + CUSTOM_START = 64, // start custom channel types from here + UNHANDLED = 255, // unhandled unowned pass-through channel type +} + +export interface ChannelPermissionOverwrite { + allow: string; + deny: string; + id: string; + type: ChannelPermissionOverwriteType; +} + +export enum ChannelPermissionOverwriteType { + role = 0, + member = 1, + group = 2, +} + +export interface DMChannel extends Omit { + type: ChannelType.DM | ChannelType.GROUP_DM; + recipients: Recipient[]; +} + +// TODO: probably more props +export function isTextChannel(type: ChannelType): boolean { + switch (type) { + case ChannelType.GUILD_STORE: + case ChannelType.GUILD_STAGE_VOICE: + case ChannelType.GUILD_CATEGORY: + case ChannelType.GUILD_FORUM: + case ChannelType.DIRECTORY: + throw new HTTPError("not a text channel", 400); + case ChannelType.DM: + case ChannelType.GROUP_DM: + case ChannelType.GUILD_NEWS: + case ChannelType.GUILD_VOICE: + case ChannelType.GUILD_NEWS_THREAD: + case ChannelType.GUILD_PUBLIC_THREAD: + case ChannelType.GUILD_PRIVATE_THREAD: + case ChannelType.GUILD_TEXT: + case ChannelType.ENCRYPTED: + case ChannelType.ENCRYPTED_THREAD: + return true; + default: + throw new HTTPError("unimplemented", 400); + } +} diff --git a/src/schemas/api/channels/Webhook.ts b/src/schemas/api/channels/Webhook.ts new file mode 100644 index 00000000..7f200ec8 --- /dev/null +++ b/src/schemas/api/channels/Webhook.ts @@ -0,0 +1,5 @@ +export enum WebhookType { + Incoming = 1, + ChannelFollower = 2, + Application = 3, +} \ No newline at end of file diff --git a/src/schemas/api/channels/index.ts b/src/schemas/api/channels/index.ts new file mode 100644 index 00000000..cdd42bed --- /dev/null +++ b/src/schemas/api/channels/index.ts @@ -0,0 +1,19 @@ +/* + 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 . +*/ +export * from "./Channel"; +export * from "./Webhook"; diff --git a/src/schemas/api/developers/Application.ts b/src/schemas/api/developers/Application.ts new file mode 100644 index 00000000..8ef679e2 --- /dev/null +++ b/src/schemas/api/developers/Application.ts @@ -0,0 +1,62 @@ +/* + 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 . +*/ + +export interface ApplicationCommand { + id: string; + application_id: string; + name: string; + description: string; + options?: ApplicationCommandOption[]; +} + +export interface ApplicationCommandOption { + type: ApplicationCommandOptionType; + name: string; + description: string; + required?: boolean; + choices?: ApplicationCommandOptionChoice[]; + options?: ApplicationCommandOption[]; +} + +export interface ApplicationCommandOptionChoice { + name: string; + value: string | number; +} + +export enum ApplicationCommandOptionType { + SUB_COMMAND = 1, + SUB_COMMAND_GROUP = 2, + STRING = 3, + INTEGER = 4, + BOOLEAN = 5, + USER = 6, + CHANNEL = 7, + ROLE = 8, +} + +export interface ApplicationCommandInteractionData { + id: string; + name: string; + options?: ApplicationCommandInteractionDataOption[]; +} + +export interface ApplicationCommandInteractionDataOption { + name: string; + value?: unknown; + options?: ApplicationCommandInteractionDataOption[]; +} diff --git a/src/schemas/api/developers/Team.ts b/src/schemas/api/developers/Team.ts new file mode 100644 index 00000000..94ddb8a5 --- /dev/null +++ b/src/schemas/api/developers/Team.ts @@ -0,0 +1,9 @@ +export enum TeamMemberState { + INVITED = 1, + ACCEPTED = 2, +} +export enum TeamMemberRole { + ADMIN = "admin", + DEVELOPER = "developer", + READ_ONLY = "read_only", +} \ No newline at end of file diff --git a/src/schemas/api/developers/index.ts b/src/schemas/api/developers/index.ts index 10717b78..e9443067 100644 --- a/src/schemas/api/developers/index.ts +++ b/src/schemas/api/developers/index.ts @@ -15,5 +15,7 @@ You should have received a copy of the GNU Affero General Public License along with this program. If not, see . */ +export * from "./Application"; export * from "./ApplicationCreateSchema"; export * from "./ApplicationModifySchema"; +export * from "./Team"; diff --git a/src/schemas/api/guilds/AuditLog.ts b/src/schemas/api/guilds/AuditLog.ts new file mode 100644 index 00000000..0f8ee639 --- /dev/null +++ b/src/schemas/api/guilds/AuditLog.ts @@ -0,0 +1,172 @@ +/* + 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 { ChannelPermissionOverwrite } from "@spacebar/schemas"; + +export enum AuditLogEvents { + // guild level + GUILD_UPDATE = 1, + GUILD_IMPORT = 2, + GUILD_EXPORTED = 3, + GUILD_ARCHIVE = 4, + GUILD_UNARCHIVE = 5, + // join-leave + USER_JOIN = 6, + USER_LEAVE = 7, + // channels + CHANNEL_CREATE = 10, + CHANNEL_UPDATE = 11, + CHANNEL_DELETE = 12, + // permission overrides + CHANNEL_OVERWRITE_CREATE = 13, + CHANNEL_OVERWRITE_UPDATE = 14, + CHANNEL_OVERWRITE_DELETE = 15, + // kick and ban + MEMBER_KICK = 20, + MEMBER_PRUNE = 21, + MEMBER_BAN_ADD = 22, + MEMBER_BAN_REMOVE = 23, + // member updates + MEMBER_UPDATE = 24, + MEMBER_ROLE_UPDATE = 25, + MEMBER_MOVE = 26, + MEMBER_DISCONNECT = 27, + BOT_ADD = 28, + // roles + ROLE_CREATE = 30, + ROLE_UPDATE = 31, + ROLE_DELETE = 32, + ROLE_SWAP = 33, + // invites + INVITE_CREATE = 40, + INVITE_UPDATE = 41, + INVITE_DELETE = 42, + // webhooks + WEBHOOK_CREATE = 50, + WEBHOOK_UPDATE = 51, + WEBHOOK_DELETE = 52, + WEBHOOK_SWAP = 53, + // custom emojis + EMOJI_CREATE = 60, + EMOJI_UPDATE = 61, + EMOJI_DELETE = 62, + EMOJI_SWAP = 63, + // deletion + MESSAGE_CREATE = 70, // messages sent using non-primary seat of the user only + MESSAGE_EDIT = 71, // non-self edits only + MESSAGE_DELETE = 72, + MESSAGE_BULK_DELETE = 73, + // pinning + MESSAGE_PIN = 74, + MESSAGE_UNPIN = 75, + // integrations + INTEGRATION_CREATE = 80, + INTEGRATION_UPDATE = 81, + INTEGRATION_DELETE = 82, + // stage actions + STAGE_INSTANCE_CREATE = 83, + STAGE_INSTANCE_UPDATE = 84, + STAGE_INSTANCE_DELETE = 85, + // stickers + STICKER_CREATE = 90, + STICKER_UPDATE = 91, + STICKER_DELETE = 92, + STICKER_SWAP = 93, + // threads + THREAD_CREATE = 110, + THREAD_UPDATE = 111, + THREAD_DELETE = 112, + // application commands + APPLICATION_COMMAND_PERMISSION_UPDATE = 121, + // automod + POLICY_CREATE = 140, + POLICY_UPDATE = 141, + POLICY_DELETE = 142, + MESSAGE_BLOCKED_BY_POLICIES = 143, // in spacebar, blocked messages are stealth-dropped + // instance policies affecting the guild + GUILD_AFFECTED_BY_POLICIES = 216, + // message moves + IN_GUILD_MESSAGE_MOVE = 223, + CROSS_GUILD_MESSAGE_MOVE = 224, + // message routing + ROUTE_CREATE = 225, + ROUTE_UPDATE = 226, +} + +export interface AuditLogChange { + new_value?: AuditLogChangeValue; + old_value?: AuditLogChangeValue; + key: string; +} + +export interface AuditLogChangeValue { + name?: string; + description?: string; + icon_hash?: string; + splash_hash?: string; + discovery_splash_hash?: string; + banner_hash?: string; + owner_id?: string; + region?: string; + preferred_locale?: string; + afk_channel_id?: string; + afk_timeout?: number; + rules_channel_id?: string; + public_updates_channel_id?: string; + mfa_level?: number; + verification_level?: number; + explicit_content_filter?: number; + default_message_notifications?: number; + vanity_url_code?: string; + $add?: object[]; // TODO: These types are bad. + $remove?: object[]; + prune_delete_days?: number; + widget_enabled?: boolean; + widget_channel_id?: string; + system_channel_id?: string; + position?: number; + topic?: string; + bitrate?: number; + permission_overwrites?: ChannelPermissionOverwrite[]; + nsfw?: boolean; + application_id?: string; + rate_limit_per_user?: number; + permissions?: string; + color?: number; + hoist?: boolean; + mentionable?: boolean; + allow?: string; + deny?: string; + code?: string; + channel_id?: string; + inviter_id?: string; + max_uses?: number; + uses?: number; + max_age?: number; + temporary?: boolean; + deaf?: boolean; + mute?: boolean; + nick?: string; + avatar_hash?: string; + id?: string; + type?: number; + enable_emoticons?: boolean; + expire_behavior?: number; + expire_grace_period?: number; + user_limit?: number; +} diff --git a/src/schemas/api/guilds/Automod.ts b/src/schemas/api/guilds/Automod.ts new file mode 100644 index 00000000..4195fa52 --- /dev/null +++ b/src/schemas/api/guilds/Automod.ts @@ -0,0 +1,37 @@ +/* + 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 . +*/ + +export type AutomodRuleTriggerMetadata = AutomodMentionSpamRule | AutomodSuspectedSpamRule | AutomodCommonlyFlaggedWordsRule | AutomodCustomWordsRule; + +export class AutomodMentionSpamRule { + mention_total_limit: number; + mention_raid_protection_enabled: boolean; +} + +export class AutomodSuspectedSpamRule {} + +export class AutomodCommonlyFlaggedWordsRule { + allow_list: [string]; + presets: [number]; +} + +export class AutomodCustomWordsRule { + allow_list: [string]; + keyword_filter: [string]; + regex_patterns: [string]; +} diff --git a/src/schemas/responses/GuildProfileResponse.ts b/src/schemas/api/guilds/GuildProfileResponse.ts similarity index 100% rename from src/schemas/responses/GuildProfileResponse.ts rename to src/schemas/api/guilds/GuildProfileResponse.ts diff --git a/src/schemas/api/guilds/GuildSchema.ts b/src/schemas/api/guilds/GuildSchema.ts new file mode 100644 index 00000000..320ee36f --- /dev/null +++ b/src/schemas/api/guilds/GuildSchema.ts @@ -0,0 +1,24 @@ +/* + 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 { Snowflake } from "@spacebar/schemas"; + +export interface GuildAvailableSchema { + id: Snowflake; + available: boolean; +} diff --git a/src/schemas/api/guilds/Role.ts b/src/schemas/api/guilds/Role.ts new file mode 100644 index 00000000..3775b312 --- /dev/null +++ b/src/schemas/api/guilds/Role.ts @@ -0,0 +1,13 @@ +export class RoleColors { + primary_color: number; + secondary_color: number | undefined; // only used for "holographic" and "gradient" styles + tertiary_color?: number | undefined; // only used for "holographic" style + + toJSON(): RoleColors { + return { + ...this, + secondary_color: this.secondary_color ?? undefined, + tertiary_color: this.tertiary_color ?? undefined, + }; + } +} \ No newline at end of file diff --git a/src/schemas/api/guilds/Sticker.ts b/src/schemas/api/guilds/Sticker.ts new file mode 100644 index 00000000..89b11ccf --- /dev/null +++ b/src/schemas/api/guilds/Sticker.ts @@ -0,0 +1,11 @@ +export enum StickerType { + STANDARD = 1, + GUILD = 2, +} + +export enum StickerFormatType { + GIF = 0, // gif is a custom format type and not in discord spec + PNG = 1, + APNG = 2, + LOTTIE = 3, +} diff --git a/src/schemas/api/guilds/VoiceState.ts b/src/schemas/api/guilds/VoiceState.ts new file mode 100644 index 00000000..1c8d2222 --- /dev/null +++ b/src/schemas/api/guilds/VoiceState.ts @@ -0,0 +1,24 @@ +import { VoiceState } from "@spacebar/util"; + +export enum PublicVoiceStateEnum { + user_id, + suppress, + session_id, + self_video, + self_mute, + self_deaf, + self_stream, + request_to_speak_timestamp, + mute, + deaf, + channel_id, + guild_id, +} + +export type PublicVoiceStateKeys = keyof typeof PublicVoiceStateEnum; + +export const PublicVoiceStateProjection = Object.values( + PublicVoiceStateEnum, +).filter((x) => typeof x === "string") as PublicVoiceStateKeys[]; + +export type PublicVoiceState = Pick; diff --git a/src/schemas/api/guilds/index.ts b/src/schemas/api/guilds/index.ts new file mode 100644 index 00000000..eee86bce --- /dev/null +++ b/src/schemas/api/guilds/index.ts @@ -0,0 +1,24 @@ +/* + 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 . +*/ +export * from "./AuditLog"; +export * from "./Automod"; +export * from "./GuildProfileResponse"; +export * from "./GuildSchema"; +export * from "./Role"; +export * from "./Sticker"; +export * from "./VoiceState"; diff --git a/src/schemas/api/index.ts b/src/schemas/api/index.ts index 8e7520d1..06ee4ea5 100644 --- a/src/schemas/api/index.ts +++ b/src/schemas/api/index.ts @@ -15,6 +15,8 @@ You should have received a copy of the GNU Affero General Public License along with this program. If not, see . */ +export * from "./channels"; export * from "./developers"; +export * from "./guilds"; export * from "./messages"; export * from "./users"; diff --git a/src/schemas/api/messages/Message.ts b/src/schemas/api/messages/Message.ts index 64fbd27b..485e8642 100644 --- a/src/schemas/api/messages/Message.ts +++ b/src/schemas/api/messages/Message.ts @@ -16,7 +16,7 @@ along with this program. If not, see . */ -import { PartialUser } from "@spacebar/schemas"; +import { PartialUser, Snowflake } from "@spacebar/schemas"; export enum MessageType { DEFAULT = 0, @@ -65,7 +65,7 @@ export type PartialMessage = Pick */ export interface PartialMessage { - id: string; + id: Snowflake; channel_id: string; type: MessageType; content: string; @@ -80,7 +80,7 @@ export interface Reaction { count: number; //// not saved in the database // me: boolean; // whether the current user reacted using this emoji emoji: PartialEmoji; - user_ids: string[]; + user_ids: Snowflake[]; } export interface PartialEmoji { @@ -91,7 +91,7 @@ export interface PartialEmoji { export interface AllowedMentions { parse?: ("users" | "roles" | "everyone")[]; - roles?: string[]; - users?: string[]; + roles?: Snowflake[]; + users?: Snowflake[]; replied_user?: boolean; } diff --git a/src/schemas/api/users/ConnectedAccount.ts b/src/schemas/api/users/ConnectedAccount.ts new file mode 100644 index 00000000..66c9aea4 --- /dev/null +++ b/src/schemas/api/users/ConnectedAccount.ts @@ -0,0 +1,6 @@ +import { ConnectedAccount } from "@spacebar/util"; + +export type PublicConnectedAccount = Pick< + ConnectedAccount, + "name" | "type" | "verified" +>; \ No newline at end of file diff --git a/src/schemas/api/users/Member.ts b/src/schemas/api/users/Member.ts new file mode 100644 index 00000000..8436e62a --- /dev/null +++ b/src/schemas/api/users/Member.ts @@ -0,0 +1,85 @@ +import { PublicUser } from "@spacebar/schemas"; +import { Member } from "@spacebar/util"; + +export interface ChannelOverride { + message_notifications: number; + mute_config: MuteConfig; + muted: boolean; + channel_id: string | null; +} + +export interface UserGuildSettings { + // channel_overrides: { + // channel_id: string; + // message_notifications: number; + // mute_config: MuteConfig; + // muted: boolean; + // }[]; + + channel_overrides: { + [channel_id: string]: ChannelOverride; + } | null; + message_notifications: number; + mobile_push: boolean; + mute_config: MuteConfig | null; + muted: boolean; + suppress_everyone: boolean; + suppress_roles: boolean; + version: number; + guild_id: string | null; + flags: number; + mute_scheduled_events: boolean; + hide_muted_channels: boolean; + notify_highlights: 0; +} + +export const DefaultUserGuildSettings: UserGuildSettings = { + channel_overrides: null, + message_notifications: 1, + flags: 0, + hide_muted_channels: false, + mobile_push: true, + mute_config: null, + mute_scheduled_events: false, + muted: false, + notify_highlights: 0, + suppress_everyone: false, + suppress_roles: false, + version: 453, // ? + guild_id: null, +}; + +export interface MuteConfig { + end_time: number; + selected_time_window: number; +} + +export type PublicMemberKeys = + | "id" + | "guild_id" + | "nick" + | "roles" + | "joined_at" + | "pending" + | "deaf" + | "mute" + | "premium_since" + | "avatar"; + +export const PublicMemberProjection: PublicMemberKeys[] = [ + "id", + "guild_id", + "nick", + "roles", + "joined_at", + "pending", + "deaf", + "mute", + "premium_since", + "avatar", +]; + +export type PublicMember = Omit, "roles"> & { + user: PublicUser; + roles: string[]; // only role ids not objects +}; \ No newline at end of file diff --git a/src/schemas/api/users/User.ts b/src/schemas/api/users/User.ts index 89150655..ab2e98ed 100644 --- a/src/schemas/api/users/User.ts +++ b/src/schemas/api/users/User.ts @@ -16,7 +16,49 @@ along with this program. If not, see . */ -import { Snowflake } from "@spacebar/schemas"; +import { ConnectedAccountSchema, Snowflake, UserSettingsSchema } from "@spacebar/schemas"; +import { BitField } from "@spacebar/util/util"; +import { Relationship, Session } from "@spacebar/util/entities"; + +interface UserEntityPleaseRewriteThankYou { + id: Snowflake; + username: string; + discriminator: string; + avatar?: string; + accent_color?: number; + banner?: string; + theme_colors?: number[]; + pronouns?: string; + phone?: string; + desktop: boolean; + mobile: boolean; + premium: boolean; + premium_type: number; + bot: boolean; + bio: string; + system: boolean; + nsfw_allowed: boolean; + mfa_enabled: boolean; + webauthn_enabled: boolean; + created_at: Date; + premium_since: Date; + verified: boolean; + disabled: boolean; + deleted: boolean; + email?: string; + flags: number; + public_flags: number; + purchased_flags: number; + premium_usage_flags: number; + rights: string; + sessions: Session[]; + relationships: Relationship[]; + connected_accounts: ConnectedAccountSchema[]; + fingerprints: string[]; + settings?: UserSettingsSchema; + extended_settings: string; + badge_ids?: string[]; +} export interface PartialUser { id: Snowflake; @@ -66,3 +108,77 @@ export interface PrimaryGuild { badge: string | null; } +export enum PublicUserEnum { + username, + discriminator, + id, + public_flags, + avatar, + accent_color, + banner, + bio, + bot, + premium_since, + premium_type, + theme_colors, + pronouns, + badge_ids, +} +export type PublicUserKeys = keyof typeof PublicUserEnum; + +export enum PrivateUserEnum { + flags, + mfa_enabled, + email, + phone, + verified, + nsfw_allowed, + premium, + premium_type, + purchased_flags, + premium_usage_flags, + disabled, + settings, + // locale +} + +export type PrivateUserKeys = keyof typeof PrivateUserEnum | PublicUserKeys; + +export const PublicUserProjection = Object.values(PublicUserEnum).filter((x) => typeof x === "string") as PublicUserKeys[]; +export const PrivateUserProjection = [...PublicUserProjection, ...Object.values(PrivateUserEnum).filter((x) => typeof x === "string")] as PrivateUserKeys[]; + +// Private user data that should never get sent to the client +export type PublicUser = Pick; +export type PrivateUser = Pick; + +export interface UserPrivate extends Pick { + locale: string; +} + +export const CUSTOM_USER_FLAG_OFFSET = BigInt(1) << BigInt(32); + +// This causes a failure in openapi.js...? +export class UserFlags extends BitField { + static FLAGS = { + DISCORD_EMPLOYEE: BigInt(1) << BigInt(0), + PARTNERED_SERVER_OWNER: BigInt(1) << BigInt(1), + HYPESQUAD_EVENTS: BigInt(1) << BigInt(2), + BUGHUNTER_LEVEL_1: BigInt(1) << BigInt(3), + MFA_SMS: BigInt(1) << BigInt(4), + PREMIUM_PROMO_DISMISSED: BigInt(1) << BigInt(5), + HOUSE_BRAVERY: BigInt(1) << BigInt(6), + HOUSE_BRILLIANCE: BigInt(1) << BigInt(7), + HOUSE_BALANCE: BigInt(1) << BigInt(8), + EARLY_SUPPORTER: BigInt(1) << BigInt(9), + TEAM_USER: BigInt(1) << BigInt(10), + TRUST_AND_SAFETY: BigInt(1) << BigInt(11), + SYSTEM: BigInt(1) << BigInt(12), + HAS_UNREAD_URGENT_MESSAGES: BigInt(1) << BigInt(13), + BUGHUNTER_LEVEL_2: BigInt(1) << BigInt(14), + UNDERAGE_DELETED: BigInt(1) << BigInt(15), + VERIFIED_BOT: BigInt(1) << BigInt(16), + EARLY_VERIFIED_BOT_DEVELOPER: BigInt(1) << BigInt(17), + CERTIFIED_MODERATOR: BigInt(1) << BigInt(18), + BOT_HTTP_INTERACTIONS: BigInt(1) << BigInt(19), + }; +} diff --git a/src/schemas/api/users/index.ts b/src/schemas/api/users/index.ts index 44fa1c5d..abc763e4 100644 --- a/src/schemas/api/users/index.ts +++ b/src/schemas/api/users/index.ts @@ -15,4 +15,6 @@ You should have received a copy of the GNU Affero General Public License along with this program. If not, see . */ +export * from "./ConnectedAccount"; +export * from "./Member"; export * from "./User"; diff --git a/src/schemas/index.ts b/src/schemas/index.ts index e6428d54..99f4095c 100644 --- a/src/schemas/index.ts +++ b/src/schemas/index.ts @@ -20,5 +20,6 @@ export * from "./gateway"; export * from "./responses"; export * from "./uncategorised"; export * from "./webrtc"; +export * from "./HelperTypes"; export * from "./Identifiers"; export * from "./Validator"; diff --git a/src/schemas/responses/CollectiblesCategoriesResponse.ts b/src/schemas/responses/CollectiblesCategoriesResponse.ts index 8a26d897..97ade06e 100644 --- a/src/schemas/responses/CollectiblesCategoriesResponse.ts +++ b/src/schemas/responses/CollectiblesCategoriesResponse.ts @@ -16,9 +16,9 @@ along with this program. If not, see . */ -import { StringStringDictionary } from "../../util/util"; - // TODO: Clean up +import { StringStringDictionary } from "@spacebar/schemas"; + export type CollectiblesCategoriesResponse = CollectiblesCategoryItem[]; export interface CollectiblesCategoryStyle { diff --git a/src/schemas/responses/GuildDiscoveryRequirements.ts b/src/schemas/responses/GuildDiscoveryRequirements.ts index 1c1ea0ad..675cdc62 100644 --- a/src/schemas/responses/GuildDiscoveryRequirements.ts +++ b/src/schemas/responses/GuildDiscoveryRequirements.ts @@ -17,7 +17,7 @@ */ export interface GuildDiscoveryRequirementsResponse { - uild_id: string; + guild_id: string; safe_environment: boolean; healthy: boolean; health_score_pending: boolean; diff --git a/src/schemas/responses/GuildMessagesSearchResponse.ts b/src/schemas/responses/GuildMessagesSearchResponse.ts index d42683e3..9e7da5e4 100644 --- a/src/schemas/responses/GuildMessagesSearchResponse.ts +++ b/src/schemas/responses/GuildMessagesSearchResponse.ts @@ -18,10 +18,9 @@ import { Attachment, - PublicUser, Role, } from "../../util/entities"; -import { ActionRowComponent, Embed, MessageType, Poll } from "@spacebar/schemas"; +import { ActionRowComponent, Embed, MessageType, Poll, PublicUser } from "@spacebar/schemas"; export interface GuildMessagesSearchMessage { id: string; diff --git a/src/schemas/responses/TypedResponses.ts b/src/schemas/responses/TypedResponses.ts index bfab2255..609b0276 100644 --- a/src/schemas/responses/TypedResponses.ts +++ b/src/schemas/responses/TypedResponses.ts @@ -18,41 +18,15 @@ import { GeneralConfiguration, LimitsConfiguration } from "../../util/config"; import { DmChannelDTO } from "../../util/dtos"; -import { - Application, - BackupCode, - Categories, - Channel, - Emoji, - Guild, - Invite, - Member, - Message, - PrivateUser, - PublicMember, - PublicUser, - Role, - Sticker, - StickerPack, - Template, - Webhook, -} from "../../util/entities"; +import { Application, BackupCode, Categories, Channel, Emoji, Guild, Invite, Member, Message, Role, Sticker, StickerPack, Template, Webhook } from "../../util/entities"; import { GuildVoiceRegion } from "./GuildVoiceRegionsResponse"; -import { GuildBansResponse, GuildCreateResponse } from "@spacebar/schemas" +import { GuildBansResponse, GuildCreateResponse, PrivateUser, PublicMember, PublicUser } from "@spacebar/schemas"; // removes internal properties from the guild class -export type APIGuild = Omit< - Guild, - | "afk_channel" - | "template" - | "owner" - | "public_updates_channel" - | "rules_channel" - | "system_channel" - | "widget_channel" ->; +export type APIGuild = Omit; export type APIPublicUser = PublicUser; + export type APIPrivateUser = PrivateUser; export type APIGuildArray = APIGuild[]; diff --git a/src/schemas/responses/UserProfileResponse.ts b/src/schemas/responses/UserProfileResponse.ts index 7b63542e..1a5fdc97 100644 --- a/src/schemas/responses/UserProfileResponse.ts +++ b/src/schemas/responses/UserProfileResponse.ts @@ -19,11 +19,13 @@ import { Badge, Member, + User, +} from "@spacebar/util"; +import { PublicConnectedAccount, PublicMember, PublicUser, - User, -} from "@spacebar/util"; +} from "@spacebar/schemas"; export type MutualGuild = { id: string; diff --git a/src/schemas/responses/UserRelationshipsResponse.ts b/src/schemas/responses/UserRelationshipsResponse.ts index 5bfb8f88..a0f5ff5f 100644 --- a/src/schemas/responses/UserRelationshipsResponse.ts +++ b/src/schemas/responses/UserRelationshipsResponse.ts @@ -15,8 +15,8 @@ You should have received a copy of the GNU Affero General Public License along with this program. If not, see . */ -import { PublicUser } from "../../util/entities"; -import { RelationshipType } from "@spacebar/schemas" + +import { PublicUser, RelationshipType } from "@spacebar/schemas" export interface UserRelationshipsResponse { id: string; diff --git a/src/schemas/responses/index.ts b/src/schemas/responses/index.ts index 3263c7e2..690b1ec5 100644 --- a/src/schemas/responses/index.ts +++ b/src/schemas/responses/index.ts @@ -35,7 +35,6 @@ export * from "./GuildBansResponse"; export * from "./GuildCreateResponse"; export * from "./GuildDiscoveryRequirements"; export * from "./GuildMessagesSearchResponse"; -export * from "./GuildProfileResponse"; export * from "./GuildPruneResponse"; export * from "./GuildRecommendationsResponse"; export * from "./GuildVanityUrl"; diff --git a/src/schemas/uncategorised/ChannelModifySchema.ts b/src/schemas/uncategorised/ChannelModifySchema.ts index 088ac459..dcdecc0a 100644 --- a/src/schemas/uncategorised/ChannelModifySchema.ts +++ b/src/schemas/uncategorised/ChannelModifySchema.ts @@ -16,7 +16,7 @@ along with this program. If not, see . */ -import { ChannelPermissionOverwriteType, ChannelType } from "@spacebar/util"; +import { ChannelPermissionOverwriteType, ChannelType } from "@spacebar/schemas"; export interface ChannelModifySchema { /** diff --git a/src/schemas/uncategorised/ChannelPermissionOverwriteSchema.ts b/src/schemas/uncategorised/ChannelPermissionOverwriteSchema.ts index 6e8b3402..7382d276 100644 --- a/src/schemas/uncategorised/ChannelPermissionOverwriteSchema.ts +++ b/src/schemas/uncategorised/ChannelPermissionOverwriteSchema.ts @@ -16,6 +16,6 @@ along with this program. If not, see . */ -import { ChannelPermissionOverwrite } from "@spacebar/util"; +import { ChannelPermissionOverwrite } from "@spacebar/schemas"; export type ChannelPermissionOverwriteSchema = ChannelPermissionOverwrite; diff --git a/src/schemas/uncategorised/UserGuildSettingsSchema.ts b/src/schemas/uncategorised/UserGuildSettingsSchema.ts index 82edae9c..d0fe24fc 100644 --- a/src/schemas/uncategorised/UserGuildSettingsSchema.ts +++ b/src/schemas/uncategorised/UserGuildSettingsSchema.ts @@ -16,7 +16,7 @@ along with this program. If not, see . */ -import { ChannelOverride, UserGuildSettings } from "@spacebar/util"; +import { ChannelOverride, UserGuildSettings } from "@spacebar/schemas"; // This sucks. I would use a DeepPartial, my own or typeorms, but they both generate inncorect schema export interface UserGuildSettingsSchema diff --git a/src/util/dtos/DmChannelDTO.ts b/src/util/dtos/DmChannelDTO.ts index 8427f7f9..a1ec2e2d 100644 --- a/src/util/dtos/DmChannelDTO.ts +++ b/src/util/dtos/DmChannelDTO.ts @@ -17,7 +17,8 @@ */ import { MinimalPublicUserDTO } from "./UserDTO"; -import { Channel, PublicUserProjection, User } from "../entities"; +import { Channel, User } from "../entities"; +import { PublicUserProjection } from "@spacebar/schemas"; export class DmChannelDTO { icon: string | null; diff --git a/src/util/dtos/ReadyGuildDTO.ts b/src/util/dtos/ReadyGuildDTO.ts index 975c4f8b..b2541212 100644 --- a/src/util/dtos/ReadyGuildDTO.ts +++ b/src/util/dtos/ReadyGuildDTO.ts @@ -18,16 +18,12 @@ import { Channel, - ChannelOverride, - ChannelType, Emoji, Guild, - PublicUser, Role, Sticker, - UserGuildSettings, - PublicMember, } from "../entities"; +import { ChannelOverride, ChannelType, PublicMember, PublicUser, UserGuildSettings } from "@spacebar/schemas"; // TODO: this is not the best place for this type export type ReadyUserGuildSettingsEntries = Omit< diff --git a/src/util/entities/Application.ts b/src/util/entities/Application.ts index d81226d8..8ebe6ce8 100644 --- a/src/util/entities/Application.ts +++ b/src/util/entities/Application.ts @@ -16,14 +16,7 @@ along with this program. If not, see . */ -import { - Column, - Entity, - JoinColumn, - ManyToOne, - OneToOne, - RelationId, -} from "typeorm"; +import { Column, Entity, JoinColumn, ManyToOne, OneToOne, RelationId } from "typeorm"; import { BaseClass } from "./BaseClass"; import { Team } from "./Team"; import { User } from "./User"; @@ -143,48 +136,3 @@ export class Application extends BaseClass { }) team?: Team; } - -export interface ApplicationCommand { - id: string; - application_id: string; - name: string; - description: string; - options?: ApplicationCommandOption[]; -} - -export interface ApplicationCommandOption { - type: ApplicationCommandOptionType; - name: string; - description: string; - required?: boolean; - choices?: ApplicationCommandOptionChoice[]; - options?: ApplicationCommandOption[]; -} - -export interface ApplicationCommandOptionChoice { - name: string; - value: string | number; -} - -export enum ApplicationCommandOptionType { - SUB_COMMAND = 1, - SUB_COMMAND_GROUP = 2, - STRING = 3, - INTEGER = 4, - BOOLEAN = 5, - USER = 6, - CHANNEL = 7, - ROLE = 8, -} - -export interface ApplicationCommandInteractionData { - id: string; - name: string; - options?: ApplicationCommandInteractionDataOption[]; -} - -export interface ApplicationCommandInteractionDataOption { - name: string; - value?: unknown; - options?: ApplicationCommandInteractionDataOption[]; -} diff --git a/src/util/entities/AuditLog.ts b/src/util/entities/AuditLog.ts index cc23bf5e..c38398a5 100644 --- a/src/util/entities/AuditLog.ts +++ b/src/util/entities/AuditLog.ts @@ -18,98 +18,8 @@ import { Column, Entity, JoinColumn, ManyToOne, RelationId } from "typeorm"; import { BaseClass } from "./BaseClass"; -import { ChannelPermissionOverwrite } from "./Channel"; import { User } from "./User"; - -export enum AuditLogEvents { - // guild level - GUILD_UPDATE = 1, - GUILD_IMPORT = 2, - GUILD_EXPORTED = 3, - GUILD_ARCHIVE = 4, - GUILD_UNARCHIVE = 5, - // join-leave - USER_JOIN = 6, - USER_LEAVE = 7, - // channels - CHANNEL_CREATE = 10, - CHANNEL_UPDATE = 11, - CHANNEL_DELETE = 12, - // permission overrides - CHANNEL_OVERWRITE_CREATE = 13, - CHANNEL_OVERWRITE_UPDATE = 14, - CHANNEL_OVERWRITE_DELETE = 15, - // kick and ban - MEMBER_KICK = 20, - MEMBER_PRUNE = 21, - MEMBER_BAN_ADD = 22, - MEMBER_BAN_REMOVE = 23, - // member updates - MEMBER_UPDATE = 24, - MEMBER_ROLE_UPDATE = 25, - MEMBER_MOVE = 26, - MEMBER_DISCONNECT = 27, - BOT_ADD = 28, - // roles - ROLE_CREATE = 30, - ROLE_UPDATE = 31, - ROLE_DELETE = 32, - ROLE_SWAP = 33, - // invites - INVITE_CREATE = 40, - INVITE_UPDATE = 41, - INVITE_DELETE = 42, - // webhooks - WEBHOOK_CREATE = 50, - WEBHOOK_UPDATE = 51, - WEBHOOK_DELETE = 52, - WEBHOOK_SWAP = 53, - // custom emojis - EMOJI_CREATE = 60, - EMOJI_UPDATE = 61, - EMOJI_DELETE = 62, - EMOJI_SWAP = 63, - // deletion - MESSAGE_CREATE = 70, // messages sent using non-primary seat of the user only - MESSAGE_EDIT = 71, // non-self edits only - MESSAGE_DELETE = 72, - MESSAGE_BULK_DELETE = 73, - // pinning - MESSAGE_PIN = 74, - MESSAGE_UNPIN = 75, - // integrations - INTEGRATION_CREATE = 80, - INTEGRATION_UPDATE = 81, - INTEGRATION_DELETE = 82, - // stage actions - STAGE_INSTANCE_CREATE = 83, - STAGE_INSTANCE_UPDATE = 84, - STAGE_INSTANCE_DELETE = 85, - // stickers - STICKER_CREATE = 90, - STICKER_UPDATE = 91, - STICKER_DELETE = 92, - STICKER_SWAP = 93, - // threads - THREAD_CREATE = 110, - THREAD_UPDATE = 111, - THREAD_DELETE = 112, - // application commands - APPLICATION_COMMAND_PERMISSION_UPDATE = 121, - // automod - POLICY_CREATE = 140, - POLICY_UPDATE = 141, - POLICY_DELETE = 142, - MESSAGE_BLOCKED_BY_POLICIES = 143, // in spacebar, blocked messages are stealth-dropped - // instance policies affecting the guild - GUILD_AFFECTED_BY_POLICIES = 216, - // message moves - IN_GUILD_MESSAGE_MOVE = 223, - CROSS_GUILD_MESSAGE_MOVE = 224, - // message routing - ROUTE_CREATE = 225, - ROUTE_UPDATE = 226, -} +import { AuditLogChange, AuditLogEvents } from "@spacebar/schemas"; @Entity({ name: "audit_logs", @@ -150,65 +60,3 @@ export class AuditLog extends BaseClass { reason?: string; } -export interface AuditLogChange { - new_value?: AuditLogChangeValue; - old_value?: AuditLogChangeValue; - key: string; -} - -export interface AuditLogChangeValue { - name?: string; - description?: string; - icon_hash?: string; - splash_hash?: string; - discovery_splash_hash?: string; - banner_hash?: string; - owner_id?: string; - region?: string; - preferred_locale?: string; - afk_channel_id?: string; - afk_timeout?: number; - rules_channel_id?: string; - public_updates_channel_id?: string; - mfa_level?: number; - verification_level?: number; - explicit_content_filter?: number; - default_message_notifications?: number; - vanity_url_code?: string; - $add?: object[]; // TODO: These types are bad. - $remove?: object[]; - prune_delete_days?: number; - widget_enabled?: boolean; - widget_channel_id?: string; - system_channel_id?: string; - position?: number; - topic?: string; - bitrate?: number; - permission_overwrites?: ChannelPermissionOverwrite[]; - nsfw?: boolean; - application_id?: string; - rate_limit_per_user?: number; - permissions?: string; - color?: number; - hoist?: boolean; - mentionable?: boolean; - allow?: string; - deny?: string; - code?: string; - channel_id?: string; - inviter_id?: string; - max_uses?: number; - uses?: number; - max_age?: number; - temporary?: boolean; - deaf?: boolean; - mute?: boolean; - nick?: string; - avatar_hash?: string; - id?: string; - type?: number; - enable_emoticons?: boolean; - expire_behavior?: number; - expire_grace_period?: number; - user_limit?: number; -} diff --git a/src/util/entities/AutomodRule.ts b/src/util/entities/AutomodRule.ts index e30dd0c0..5765b662 100644 --- a/src/util/entities/AutomodRule.ts +++ b/src/util/entities/AutomodRule.ts @@ -19,24 +19,7 @@ import { BaseClass } from "./BaseClass"; import { Entity, JoinColumn, ManyToOne, Column } from "typeorm"; import { User } from "./User"; - -export class AutomodMentionSpamRule { - mention_total_limit: number; - mention_raid_protection_enabled: boolean; -} - -export class AutomodSuspectedSpamRule {} - -export class AutomodCommonlyFlaggedWordsRule { - allow_list: [string]; - presets: [number]; -} - -export class AutomodCustomWordsRule { - allow_list: [string]; - keyword_filter: [string]; - regex_patterns: [string]; -} +import { AutomodRuleTriggerMetadata } from "@spacebar/schemas"; @Entity({ name: "automod_rules", @@ -75,10 +58,7 @@ export class AutomodRule extends BaseClass { nullable: true, }) trigger_metadata?: // this is null for "Block suspected spam content" - | AutomodMentionSpamRule - | AutomodSuspectedSpamRule - | AutomodCommonlyFlaggedWordsRule - | AutomodCustomWordsRule; + | AutomodRuleTriggerMetadata; @Column({ type: "simple-json", diff --git a/src/util/entities/Channel.ts b/src/util/entities/Channel.ts index 0260db22..3c11de37 100644 --- a/src/util/entities/Channel.ts +++ b/src/util/entities/Channel.ts @@ -34,34 +34,11 @@ import { Invite } from "./Invite"; import { Message } from "./Message"; import { ReadState } from "./ReadState"; import { Recipient } from "./Recipient"; -import { PublicUserProjection, User } from "./User"; +import { User } from "./User"; import { VoiceState } from "./VoiceState"; import { Webhook } from "./Webhook"; import { Member } from "./Member"; - -export enum ChannelType { - GUILD_TEXT = 0, // a text channel within a guild - DM = 1, // a direct message between users - GUILD_VOICE = 2, // a voice channel within a guild - GROUP_DM = 3, // a direct message between multiple users - GUILD_CATEGORY = 4, // an organizational category that contains zero or more channels - GUILD_NEWS = 5, // a channel that users can follow and crosspost into a guild or route - GUILD_STORE = 6, // a channel in which game developers can sell their things - ENCRYPTED = 7, // end-to-end encrypted channel - ENCRYPTED_THREAD = 8, // end-to-end encrypted thread channel - TRANSACTIONAL = 9, // event chain style transactional channel - GUILD_NEWS_THREAD = 10, // a temporary sub-channel within a GUILD_NEWS channel - GUILD_PUBLIC_THREAD = 11, // a temporary sub-channel within a GUILD_TEXT channel - GUILD_PRIVATE_THREAD = 12, // a temporary sub-channel within a GUILD_TEXT channel that is only viewable by those invited and those with the MANAGE_THREADS permission - GUILD_STAGE_VOICE = 13, // a voice channel for hosting events with an audience - DIRECTORY = 14, // guild directory listing channel - GUILD_FORUM = 15, // forum composed of IM threads - TICKET_TRACKER = 33, // ticket tracker, individual ticket items shall have type 12 - KANBAN = 34, // confluence like kanban board - VOICELESS_WHITEBOARD = 35, // whiteboard but without voice (whiteboard + voice is the same as stage) - CUSTOM_START = 64, // start custom channel types from here - UNHANDLED = 255, // unhandled unowned pass-through channel type -} +import { ChannelPermissionOverwrite, ChannelPermissionOverwriteType, ChannelType, PublicUserProjection } from "@spacebar/schemas"; @Entity({ name: "channels", @@ -613,46 +590,3 @@ export class Channel extends BaseClass { }; } } - -export interface ChannelPermissionOverwrite { - allow: string; - deny: string; - id: string; - type: ChannelPermissionOverwriteType; -} - -export enum ChannelPermissionOverwriteType { - role = 0, - member = 1, - group = 2, -} - -export interface DMChannel extends Omit { - type: ChannelType.DM | ChannelType.GROUP_DM; - recipients: Recipient[]; -} - -// TODO: probably more props -export function isTextChannel(type: ChannelType): boolean { - switch (type) { - case ChannelType.GUILD_STORE: - case ChannelType.GUILD_STAGE_VOICE: - case ChannelType.GUILD_CATEGORY: - case ChannelType.GUILD_FORUM: - case ChannelType.DIRECTORY: - throw new HTTPError("not a text channel", 400); - case ChannelType.DM: - case ChannelType.GROUP_DM: - case ChannelType.GUILD_NEWS: - case ChannelType.GUILD_VOICE: - case ChannelType.GUILD_NEWS_THREAD: - case ChannelType.GUILD_PUBLIC_THREAD: - case ChannelType.GUILD_PRIVATE_THREAD: - case ChannelType.GUILD_TEXT: - case ChannelType.ENCRYPTED: - case ChannelType.ENCRYPTED_THREAD: - return true; - default: - throw new HTTPError("unimplemented", 400); - } -} diff --git a/src/util/entities/ConnectedAccount.ts b/src/util/entities/ConnectedAccount.ts index 51df3955..b2037cce 100644 --- a/src/util/entities/ConnectedAccount.ts +++ b/src/util/entities/ConnectedAccount.ts @@ -21,11 +21,6 @@ import { ConnectedAccountTokenData } from "../interfaces"; import { BaseClass } from "./BaseClass"; import { User } from "./User"; -export type PublicConnectedAccount = Pick< - ConnectedAccount, - "name" | "type" | "verified" ->; - @Entity({ name: "connected_accounts", }) diff --git a/src/util/entities/Member.ts b/src/util/entities/Member.ts index 44ccacfb..1e23cd58 100644 --- a/src/util/entities/Member.ts +++ b/src/util/entities/Member.ts @@ -47,7 +47,8 @@ import { BaseClassWithoutId } from "./BaseClass"; import { Guild } from "./Guild"; import { Message } from "./Message"; import { Role } from "./Role"; -import { PublicUser, User } from "./User"; +import { User } from "./User"; +import { PublicMember, PublicMemberProjection, UserGuildSettings } from "@spacebar/schemas"; export const MemberPrivateProjection: (keyof Member)[] = [ "id", @@ -472,86 +473,3 @@ export class Member extends BaseClassWithoutId { return member as PublicMember; } } - -export interface ChannelOverride { - message_notifications: number; - mute_config: MuteConfig; - muted: boolean; - channel_id: string | null; -} - -export interface UserGuildSettings { - // channel_overrides: { - // channel_id: string; - // message_notifications: number; - // mute_config: MuteConfig; - // muted: boolean; - // }[]; - - channel_overrides: { - [channel_id: string]: ChannelOverride; - } | null; - message_notifications: number; - mobile_push: boolean; - mute_config: MuteConfig | null; - muted: boolean; - suppress_everyone: boolean; - suppress_roles: boolean; - version: number; - guild_id: string | null; - flags: number; - mute_scheduled_events: boolean; - hide_muted_channels: boolean; - notify_highlights: 0; -} - -export const DefaultUserGuildSettings: UserGuildSettings = { - channel_overrides: null, - message_notifications: 1, - flags: 0, - hide_muted_channels: false, - mobile_push: true, - mute_config: null, - mute_scheduled_events: false, - muted: false, - notify_highlights: 0, - suppress_everyone: false, - suppress_roles: false, - version: 453, // ? - guild_id: null, -}; - -export interface MuteConfig { - end_time: number; - selected_time_window: number; -} - -export type PublicMemberKeys = - | "id" - | "guild_id" - | "nick" - | "roles" - | "joined_at" - | "pending" - | "deaf" - | "mute" - | "premium_since" - | "avatar"; - -export const PublicMemberProjection: PublicMemberKeys[] = [ - "id", - "guild_id", - "nick", - "roles", - "joined_at", - "pending", - "deaf", - "mute", - "premium_since", - "avatar", -]; - -export type PublicMember = Omit, "roles"> & { - user: PublicUser; - roles: string[]; // only role ids not objects -}; diff --git a/src/util/entities/Role.ts b/src/util/entities/Role.ts index f31c4b32..8ee3605f 100644 --- a/src/util/entities/Role.ts +++ b/src/util/entities/Role.ts @@ -20,20 +20,7 @@ import { Column, Entity, JoinColumn, ManyToOne, RelationId } from "typeorm"; import { BaseClass } from "./BaseClass"; import { Guild } from "./Guild"; - -export class RoleColors { - primary_color: number; - secondary_color: number | undefined; // only used for "holographic" and "gradient" styles - tertiary_color?: number | undefined; // only used for "holographic" style - - toJSON(): RoleColors { - return { - ...this, - secondary_color: this.secondary_color ?? undefined, - tertiary_color: this.tertiary_color ?? undefined, - }; - } -} +import { RoleColors } from "@spacebar/schemas"; @Entity({ name: "roles", diff --git a/src/util/entities/Sticker.ts b/src/util/entities/Sticker.ts index 4c950cbb..07fc8d37 100644 --- a/src/util/entities/Sticker.ts +++ b/src/util/entities/Sticker.ts @@ -20,18 +20,7 @@ import { Column, Entity, JoinColumn, ManyToOne, RelationId } from "typeorm"; import { BaseClass } from "./BaseClass"; import { Guild } from "./Guild"; import { User } from "./User"; - -export enum StickerType { - STANDARD = 1, - GUILD = 2, -} - -export enum StickerFormatType { - GIF = 0, // gif is a custom format type and not in discord spec - PNG = 1, - APNG = 2, - LOTTIE = 3, -} +import { StickerFormatType, StickerType } from "@spacebar/schemas"; @Entity({ name: "stickers", diff --git a/src/util/entities/TeamMember.ts b/src/util/entities/TeamMember.ts index d3d066bd..b552f773 100644 --- a/src/util/entities/TeamMember.ts +++ b/src/util/entities/TeamMember.ts @@ -19,16 +19,7 @@ import { Column, Entity, JoinColumn, ManyToOne, RelationId } from "typeorm"; import { BaseClass } from "./BaseClass"; import { User } from "./User"; - -export enum TeamMemberState { - INVITED = 1, - ACCEPTED = 2, -} -export enum TeamMemberRole { - ADMIN = "admin", - DEVELOPER = "developer", - READ_ONLY = "read_only", -} +import { TeamMemberRole, TeamMemberState } from "@spacebar/schemas"; @Entity({ name: "team_members", diff --git a/src/util/entities/User.ts b/src/util/entities/User.ts index 138a24c1..9cc3ff70 100644 --- a/src/util/entities/User.ts +++ b/src/util/entities/User.ts @@ -18,8 +18,8 @@ import { Request } from "express"; import { Column, Entity, FindOneOptions, JoinColumn, OneToMany, OneToOne } from "typeorm"; -import { Channel, ChannelType, Config, Email, FieldErrors, Snowflake, trimSpecial } from ".."; -import { BitField, Random } from "../util"; +import { Channel, Config, Email, FieldErrors, Snowflake, trimSpecial } from ".."; +import { Random } from "../util"; import { BaseClass } from "./BaseClass"; import { ConnectedAccount } from "./ConnectedAccount"; import { Member } from "./Member"; @@ -27,52 +27,7 @@ import { Relationship } from "./Relationship"; import { SecurityKey } from "./SecurityKey"; import { Session } from "./Session"; import { UserSettings } from "./UserSettings"; - -export enum PublicUserEnum { - username, - discriminator, - id, - public_flags, - avatar, - accent_color, - banner, - bio, - bot, - premium_since, - premium_type, - theme_colors, - pronouns, - badge_ids, -} -export type PublicUserKeys = keyof typeof PublicUserEnum; - -export enum PrivateUserEnum { - flags, - mfa_enabled, - email, - phone, - verified, - nsfw_allowed, - premium, - premium_type, - purchased_flags, - premium_usage_flags, - disabled, - settings, - // locale -} -export type PrivateUserKeys = keyof typeof PrivateUserEnum | PublicUserKeys; - -export const PublicUserProjection = Object.values(PublicUserEnum).filter((x) => typeof x === "string") as PublicUserKeys[]; -export const PrivateUserProjection = [...PublicUserProjection, ...Object.values(PrivateUserEnum).filter((x) => typeof x === "string")] as PrivateUserKeys[]; - -// Private user data that should never get sent to the client -export type PublicUser = Pick; -export type PrivateUser = Pick; - -export interface UserPrivate extends Pick { - locale: string; -} +import { ChannelType, PrivateUserProjection, PublicUser, PublicUserProjection, UserPrivate } from "@spacebar/schemas"; @Entity({ name: "users", @@ -396,30 +351,3 @@ export class User extends BaseClass { return qry.single((_) => true); } } - -export const CUSTOM_USER_FLAG_OFFSET = BigInt(1) << BigInt(32); - -export class UserFlags extends BitField { - static FLAGS = { - DISCORD_EMPLOYEE: BigInt(1) << BigInt(0), - PARTNERED_SERVER_OWNER: BigInt(1) << BigInt(1), - HYPESQUAD_EVENTS: BigInt(1) << BigInt(2), - BUGHUNTER_LEVEL_1: BigInt(1) << BigInt(3), - MFA_SMS: BigInt(1) << BigInt(4), - PREMIUM_PROMO_DISMISSED: BigInt(1) << BigInt(5), - HOUSE_BRAVERY: BigInt(1) << BigInt(6), - HOUSE_BRILLIANCE: BigInt(1) << BigInt(7), - HOUSE_BALANCE: BigInt(1) << BigInt(8), - EARLY_SUPPORTER: BigInt(1) << BigInt(9), - TEAM_USER: BigInt(1) << BigInt(10), - TRUST_AND_SAFETY: BigInt(1) << BigInt(11), - SYSTEM: BigInt(1) << BigInt(12), - HAS_UNREAD_URGENT_MESSAGES: BigInt(1) << BigInt(13), - BUGHUNTER_LEVEL_2: BigInt(1) << BigInt(14), - UNDERAGE_DELETED: BigInt(1) << BigInt(15), - VERIFIED_BOT: BigInt(1) << BigInt(16), - EARLY_VERIFIED_BOT_DEVELOPER: BigInt(1) << BigInt(17), - CERTIFIED_MODERATOR: BigInt(1) << BigInt(18), - BOT_HTTP_INTERACTIONS: BigInt(1) << BigInt(19), - }; -} diff --git a/src/util/entities/UserSettings.ts b/src/util/entities/UserSettings.ts index b5e91355..f1fc78b4 100644 --- a/src/util/entities/UserSettings.ts +++ b/src/util/entities/UserSettings.ts @@ -18,7 +18,6 @@ import { Column, Entity, PrimaryGeneratedColumn } from "typeorm"; import { BaseClassWithoutId } from "./BaseClass"; -import { User } from "./User"; import { CustomStatus, FriendSourceFlags, GuildFolder } from "@spacebar/schemas" @Entity({ diff --git a/src/util/entities/VoiceState.ts b/src/util/entities/VoiceState.ts index 475f0f6f..85fe27f2 100644 --- a/src/util/entities/VoiceState.ts +++ b/src/util/entities/VoiceState.ts @@ -22,29 +22,7 @@ import { Channel } from "./Channel"; import { Guild } from "./Guild"; import { Member } from "./Member"; import { User } from "./User"; - -export enum PublicVoiceStateEnum { - user_id, - suppress, - session_id, - self_video, - self_mute, - self_deaf, - self_stream, - request_to_speak_timestamp, - mute, - deaf, - channel_id, - guild_id, -} - -export type PublicVoiceStateKeys = keyof typeof PublicVoiceStateEnum; - -export const PublicVoiceStateProjection = Object.values( - PublicVoiceStateEnum, -).filter((x) => typeof x === "string") as PublicVoiceStateKeys[]; - -export type PublicVoiceState = Pick; +import { PublicVoiceState, PublicVoiceStateProjection } from "@spacebar/schemas"; //https://gist.github.com/vassjozsef/e482c65df6ee1facaace8b3c9ff66145#file-voice_state-ex @Entity({ diff --git a/src/util/entities/Webhook.ts b/src/util/entities/Webhook.ts index f28be1ce..6a124168 100644 --- a/src/util/entities/Webhook.ts +++ b/src/util/entities/Webhook.ts @@ -22,12 +22,7 @@ import { BaseClass } from "./BaseClass"; import { Channel } from "./Channel"; import { Guild } from "./Guild"; import { User } from "./User"; - -export enum WebhookType { - Incoming = 1, - ChannelFollower = 2, - Application = 3, -} +import { WebhookType } from "@spacebar/schemas"; @Entity({ name: "webhooks", diff --git a/src/util/interfaces/Event.ts b/src/util/interfaces/Event.ts index 2e9ba525..8be0dd39 100644 --- a/src/util/interfaces/Event.ts +++ b/src/util/interfaces/Event.ts @@ -19,14 +19,11 @@ import { ConnectedAccount, Interaction, - ApplicationCommand, Message, Invite, Role, Emoji, - PublicMember, Channel, - PublicUser, User, Sticker, Activity, @@ -35,14 +32,12 @@ import { UserSettings, IReadyGuildDTO, ReadState, - UserPrivate, ReadyUserGuildSettingsEntries, ReadyPrivateChannel, GuildOrUnavailable, - PublicVoiceState, } from "@spacebar/util"; import { JsonValue } from "@protobuf-ts/runtime"; -import { GuildCreateResponse, PartialEmoji, RelationshipType } from "@spacebar/schemas" +import { ApplicationCommand, GuildCreateResponse, PartialEmoji, PublicMember, PublicUser, PublicVoiceState, RelationshipType, UserPrivate } from "@spacebar/schemas"; export interface Event { guild_id?: string; diff --git a/src/util/interfaces/Presence.ts b/src/util/interfaces/Presence.ts index 056c19b7..d04a6e6f 100644 --- a/src/util/interfaces/Presence.ts +++ b/src/util/interfaces/Presence.ts @@ -18,7 +18,7 @@ import { ClientStatus, Status } from "./Status"; import { Activity } from "./Activity"; -import { PublicUser } from "../entities/User"; +import { PublicUser } from "@spacebar/schemas"; export interface Presence { user: PublicUser; diff --git a/src/util/util/Permissions.ts b/src/util/util/Permissions.ts index b81ce911..e1bae5c4 100644 --- a/src/util/util/Permissions.ts +++ b/src/util/util/Permissions.ts @@ -2,9 +2,10 @@ // Apache License Version 2.0 Copyright 2015 - 2021 Amish Shah // @fc-license-skip -import { Channel, ChannelPermissionOverwrite, ChannelPermissionOverwriteType, Guild, Member, Role } from "../entities"; +import { Channel, Guild, Member, Role } from "../entities"; import { BitField, BitFieldResolvable, BitFlag } from "./BitField"; import { HTTPError } from "lambert-server"; +import { ChannelPermissionOverwrite, ChannelPermissionOverwriteType } from "@spacebar/schemas"; export type PermissionResolvable = bigint | number | Permissions | PermissionResolvable[] | PermissionString; diff --git a/src/util/util/index.ts b/src/util/util/index.ts index f50db274..11c4899c 100644 --- a/src/util/util/index.ts +++ b/src/util/util/index.ts @@ -46,6 +46,6 @@ export * from "./WebAuthn"; export * from "./Gifs"; export * from "./Application"; export * from "./NameValidation"; -export * from "./HelperTypes"; +export * from "../../schemas/HelperTypes"; export * from "./extensions"; export * from "./Random"; \ No newline at end of file