diff --git a/.husky/pre-commit b/.husky/pre-commit
index 6d2e7f07..631b169f 100755
--- a/.husky/pre-commit
+++ b/.husky/pre-commit
@@ -18,7 +18,7 @@ if [ -x "$(/usr/bin/env which nix-shell 2>/dev/null)" ]; then
elif [ ! -n "$(git status --porcelain=v1 2>/dev/null | grep -E '^M package-lock.json')" ]; then
echo "package-lock.json has no changes. Skipping update of nix dependencies."
else
- nix run .#nix-update || exit $?
+ nix run .#nix-update-hashes || exit $?
fi
fi
else
diff --git a/.prettierrc.json b/.prettierrc.json
index e3daf5f8..cbb8af09 100644
--- a/.prettierrc.json
+++ b/.prettierrc.json
@@ -8,5 +8,6 @@
"quoteProps": "as-needed",
"useTabs": true,
"singleQuote": false,
- "endOfLine": "auto"
+ "endOfLine": "auto",
+ "printWidth": 180
}
diff --git a/assets/schemas.json b/assets/schemas.json
index 65a85c20..cf774c91 100755
Binary files a/assets/schemas.json and b/assets/schemas.json differ
diff --git a/flake.nix b/flake.nix
index b6b93954..da179f51 100644
--- a/flake.nix
+++ b/flake.nix
@@ -63,7 +63,24 @@
passthru.tests = pkgs.testers.runNixOSTest (import ./nix/tests/test_1.nix self);
};
- update-nix = pkgs.writeShellApplication {
+ update-nix-hashes = pkgs.writeShellApplication {
+ name = "update-nix";
+ runtimeInputs = with pkgs; [
+ prefetch-npm-deps
+ nix
+ jq
+ ];
+ text = ''
+ rm -rf node_modules
+ ${pkgs.nodejs}/bin/npm install --save
+ DEPS_HASH=$(prefetch-npm-deps package-lock.json)
+ TMPFILE=$(mktemp)
+ jq '.npmDepsHash = "'"$DEPS_HASH"'"' hashes.json > "$TMPFILE"
+ mv -- "$TMPFILE" hashes.json
+ '';
+ };
+
+ update-nix-flake = pkgs.writeShellApplication {
name = "update-nix";
runtimeInputs = with pkgs; [
prefetch-npm-deps
@@ -72,10 +89,6 @@
];
text = ''
nix flake update --extra-experimental-features 'nix-command flakes'
- DEPS_HASH=$(prefetch-npm-deps package-lock.json)
- TMPFILE=$(mktemp)
- jq '.npmDepsHash = "'"$DEPS_HASH"'"' hashes.json > "$TMPFILE"
- mv -- "$TMPFILE" hashes.json
'';
};
};
diff --git a/src/util/schemas/responses/CollectiblesCategoriesResponse.ts b/src/util/schemas/responses/CollectiblesCategoriesResponse.ts
new file mode 100644
index 00000000..57dbf47a
--- /dev/null
+++ b/src/util/schemas/responses/CollectiblesCategoriesResponse.ts
@@ -0,0 +1,120 @@
+/*
+ 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 { StringStringDictionary } from "../../util";
+
+// TODO: Clean up
+export type CollectiblesCategoriesResponse = CollectiblesCategoryItem[];
+
+export interface CollectiblesCategoryStyle {
+ background_colors: number[];
+ button_colors: number[];
+ confetti_colors: number[];
+}
+
+export interface CollectiblesCategoryItem {
+ sku_id: string;
+ name: string;
+ summary: string;
+ store_listing_id: string;
+ banner: string;
+ unpublished_at: string | null;
+ styles: CollectiblesCategoryStyle;
+ logo: string;
+ hero_ranking: string[] | null;
+ mobile_bg: string | null;
+ pdp_bg: string | null;
+ success_modal_bg: string | null;
+ mobile_banner: string | null;
+ featured_block: string | null;
+ hero_banner: string | null;
+ wide_banner: string | null;
+ hero_logo: string | null;
+ products: CollectiblesCategoryProductItem[];
+ banner_asset?: StaticAnimatedAsset;
+ hero_banner_asset?: StaticAnimatedAsset;
+}
+
+export interface StaticAnimatedAsset {
+ // CDN URLs
+ animated: string | null;
+ static: string;
+}
+
+export interface CollectiblesCategoryProductItem {
+ sku_id: string;
+ name: string;
+ summary: string;
+ store_listing_id: string;
+ banner: string;
+ unpublished_at: string | null;
+ styles: CollectiblesCategoryStyle;
+ prices: PriceMap;
+ items: ProductItem[];
+ type: number;
+ premium_type: number;
+ category_sku_id: string;
+ google_sku_ids: StringStringDictionary;
+ variants?: ProductItemVariant[];
+}
+
+export interface ProductItemVariant {
+ sku_id: string;
+ name: string;
+ name_localizations: null;
+ summary: string;
+ summary_localizations: null;
+ store_listing_id: string;
+ banner?: string;
+ unpublished_at?: string | null;
+ styles?: CollectiblesCategoryStyle;
+ prices: PriceMap;
+ items: ProductItem[];
+ type: number;
+ premium_type: number;
+ category_sku_id: string;
+ google_sku_ids?: StringStringDictionary;
+ base_variant_sku_id: string;
+ base_variant_name: string;
+ variant_label: string;
+ variant_value: string; // hex string
+}
+
+export interface ProductItem {
+ type: number;
+ id: string;
+ sku_id: string;
+ asset?: string;
+ label?: string;
+ palette?: string;
+}
+
+export type PriceMap = {
+ [key: string]: { country_prices: CountryPrice };
+};
+
+export interface CountryPrice {
+ country_code: string;
+ prices: PriceEntry[];
+}
+
+export interface PriceEntry {
+ amount: number;
+ currency: string;
+ exponent: number;
+}
diff --git a/src/util/schemas/responses/CollectiblesMarketingResponse.ts b/src/util/schemas/responses/CollectiblesMarketingResponse.ts
new file mode 100644
index 00000000..5fda9760
--- /dev/null
+++ b/src/util/schemas/responses/CollectiblesMarketingResponse.ts
@@ -0,0 +1,60 @@
+/*
+ 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 class CollectiblesMarketingResponse {
+ marketings: {
+ [key: string]: CollectiblesMarketingItem;
+ };
+}
+
+export class CollectiblesMarketingItem {
+ type: number;
+ version: number;
+ title: string;
+ body: string;
+}
+
+export class AvatarDecorationMarketingItem extends CollectiblesMarketingItem {
+ declare type: 0;
+ // CDN URL to the avatar decoration
+ avatar: string;
+ // Asset IDs
+ decorations: string[];
+ dismissible_content: number; // Is this a generic property?
+ ref_target_background: RefTargetBackground;
+}
+
+export class NameplateMarketingItem extends CollectiblesMarketingItem {
+ declare type: 2;
+ asset: string;
+ popout_asset: string;
+}
+
+export class TargetBackgroundReference {
+ light: string | null;
+ dark: string | null;
+}
+export class TargetBackgroundReferenceInteraction {
+ resting: TargetBackgroundReference;
+ hovered: TargetBackgroundReference;
+}
+
+export class RefTargetBackground {
+ style: TargetBackgroundReferenceInteraction;
+ asset: TargetBackgroundReferenceInteraction;
+}
diff --git a/src/util/schemas/responses/CollectiblesShopResponse.ts b/src/util/schemas/responses/CollectiblesShopResponse.ts
new file mode 100644
index 00000000..ece12d40
--- /dev/null
+++ b/src/util/schemas/responses/CollectiblesShopResponse.ts
@@ -0,0 +1,67 @@
+/*
+ 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 { StringStringDictionary } from "../../util";
+import { CollectiblesCategoryItem, StaticAnimatedAsset } from "./CollectiblesCategoriesResponse";
+
+export interface CollectiblesShopResponse {
+ shop_blocks: AnyShopBlock[];
+ categories: CollectiblesCategoryItem[];
+}
+
+export type AnyShopBlock = ItemRowShopBlock | BundleTileRowShopBlock | ItemCollectionShopBlock;
+
+export interface BaseShopBlock {
+ type: number;
+}
+
+export interface ItemRowShopBlock extends BaseShopBlock {
+ type: 0;
+ category_sku_id: string;
+ name: string;
+ category_store_listing_id: string;
+ banner_asset: StaticAnimatedAsset;
+ logo_url: string;
+ unpublished_at: string | null;
+ summary: string;
+ ranked_sku_ids: string[];
+}
+
+export interface BundleTileRowShopBlock extends BaseShopBlock {
+ type: 1;
+ subblocks: ShopBlockSubBlock[];
+}
+
+export interface ShopBlockSubBlock {
+ type: number;
+ category_store_listing_id: string;
+ name: string;
+ unpublished_at: string | null;
+ banner_url: string;
+ body_text: string | null;
+ banner_text_color: number | null;
+}
+
+export interface ItemCollectionShopBlock extends BaseShopBlock {
+ type: 2;
+ ranked_sku_ids: string[];
+ sorted_sku_ids: {
+ recommended: string[] | null;
+ popular: string[];
+ };
+}
diff --git a/src/util/schemas/responses/index.ts b/src/util/schemas/responses/index.ts
index 8949924b..cf589bac 100644
--- a/src/util/schemas/responses/index.ts
+++ b/src/util/schemas/responses/index.ts
@@ -21,10 +21,13 @@ export * from "./APIErrorOrCaptchaResponse";
export * from "./APIErrorResponse";
export * from "./BackupCodesChallengeResponse";
export * from "./CaptchaRequiredResponse";
+export * from "./CollectiblesCategoriesResponse";
+export * from "./CollectiblesMarketingResponse";
+export * from "./CollectiblesShopResponse";
export * from "./DiscoverableGuildsResponse";
export * from "./EmailDomainLookupResponse";
export * from "./EmailDomainLookupVerifyCodeResponse";
-export * from "./EmojiSourceResponse"
+export * from "./EmojiSourceResponse";
export * from "./GatewayBotResponse";
export * from "./GatewayResponse";
export * from "./GenerateRegistrationTokensResponse";
diff --git a/src/util/util/HelperTypes.ts b/src/util/util/HelperTypes.ts
new file mode 100644
index 00000000..252d0a65
--- /dev/null
+++ b/src/util/util/HelperTypes.ts
@@ -0,0 +1,21 @@
+/*
+ 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 type StringStringDictionary = {
+ [key: string]: string;
+};
diff --git a/src/util/util/index.ts b/src/util/util/index.ts
index da3fe0f3..096db326 100644
--- a/src/util/util/index.ts
+++ b/src/util/util/index.ts
@@ -48,3 +48,4 @@ export * from "./Url";
export * from "./Gifs";
export * from "./Application";
export * from "./NameValidation";
+export * from "./HelperTypes";