From 724ebe1792e2cd2c5d35780cd5c3ce32b457c29a Mon Sep 17 00:00:00 2001 From: Puyodead1 Date: Wed, 24 Dec 2025 23:46:38 -0500 Subject: [PATCH] Initial work on quests --- assets/locales/en/common.json | 3 +- assets/schemas.json | Bin 386391 -> 437331 bytes src/api/middlewares/Authentication.ts | 2 + .../routes/quests/#quest_id/claim-reward.ts | 86 +++++ src/api/routes/quests/#quest_id/enroll.ts | 62 ++++ src/api/routes/quests/#quest_id/index.ts | 141 ++++++++ .../routes/quests/#quest_id/reward-code.ts | 50 +++ .../routes/quests/#quest_id/video-progress.ts | 68 ++++ src/api/routes/quests/@me.ts | 340 ++++++++++++++++++ src/api/routes/quests/decision.ts | 63 ++++ .../users/@me/virtual-currency/balance.ts | 39 ++ src/schemas/index.ts | 7 +- src/schemas/quests/ClaimedQuestSchema.ts | 26 ++ .../quests/QuestAdIdentifiersSchema.ts | 30 ++ src/schemas/quests/QuestApplicationSchema.ts | 26 ++ src/schemas/quests/QuestAssignmentMethod.ts | 22 ++ .../quests/QuestClaimRewardRequestSchema.ts | 24 ++ src/schemas/quests/QuestConfigSchema.ts | 77 ++++ .../quests/QuestEnrollRequestSchema.ts | 24 ++ ...uestEntitlementExpirationMetadataSchema.ts | 24 ++ src/schemas/quests/QuestEventType.ts | 30 ++ src/schemas/quests/QuestFeature.ts | 53 +++ src/schemas/quests/QuestJoinOperator.ts | 22 ++ src/schemas/quests/QuestPlacementArea.ts | 24 ++ src/schemas/quests/QuestPlatformType.ts | 25 ++ src/schemas/quests/QuestRewardCodeSchema.ts | 34 ++ src/schemas/quests/QuestRewardConfigSchema.ts | 28 ++ .../quests/QuestRewardExpirationMode.ts | 23 ++ src/schemas/quests/QuestRewardSchema.ts | 46 +++ src/schemas/quests/QuestRewardType.ts | 25 ++ src/schemas/quests/QuestSchema.ts | 33 ++ src/schemas/quests/QuestSharePolicy.ts | 22 ++ src/schemas/quests/QuestTaskConfigV2Schema.ts | 25 ++ src/schemas/quests/QuestTaskSchema.ts | 40 +++ .../quests/QuestUserStatusProgressSchema.ts | 30 ++ src/schemas/quests/QuestUserStatusSchema.ts | 42 +++ src/schemas/quests/QuestVideoAssetSchema.ts | 26 ++ .../quests/QuestVideoProgressRequestSchema.ts | 22 ++ src/schemas/quests/index.ts | 44 +++ .../responses/ClaimedQuestsResponseSchema.ts | 23 ++ .../QuestClaimRewardResponseSchema.ts | 26 ++ .../responses/QuestConfigResponseSchema.ts | 21 ++ .../responses/QuestPlacementResponseSchema.ts | 33 ++ .../QuestRewardCodeResponseSchema.ts | 21 ++ .../QuestUserStatusResponseSchema.ts | 21 ++ src/schemas/responses/QuestsResponseSchema.ts | 28 ++ .../VirtualCurrencyResponseSchema.ts | 21 ++ src/schemas/responses/index.ts | 12 +- .../uncategorised/EntitlementSchema.ts | 49 +++ .../EntitlementSpecialSourceType.ts | 30 ++ src/schemas/uncategorised/EntitlementType.ts | 33 ++ src/schemas/uncategorised/index.ts | 5 +- src/util/entities/User.ts | 3 + src/util/interfaces/Event.ts | 14 +- 54 files changed, 2039 insertions(+), 9 deletions(-) create mode 100644 src/api/routes/quests/#quest_id/claim-reward.ts create mode 100644 src/api/routes/quests/#quest_id/enroll.ts create mode 100644 src/api/routes/quests/#quest_id/index.ts create mode 100644 src/api/routes/quests/#quest_id/reward-code.ts create mode 100644 src/api/routes/quests/#quest_id/video-progress.ts create mode 100644 src/api/routes/quests/@me.ts create mode 100644 src/api/routes/quests/decision.ts create mode 100644 src/api/routes/users/@me/virtual-currency/balance.ts create mode 100644 src/schemas/quests/ClaimedQuestSchema.ts create mode 100644 src/schemas/quests/QuestAdIdentifiersSchema.ts create mode 100644 src/schemas/quests/QuestApplicationSchema.ts create mode 100644 src/schemas/quests/QuestAssignmentMethod.ts create mode 100644 src/schemas/quests/QuestClaimRewardRequestSchema.ts create mode 100644 src/schemas/quests/QuestConfigSchema.ts create mode 100644 src/schemas/quests/QuestEnrollRequestSchema.ts create mode 100644 src/schemas/quests/QuestEntitlementExpirationMetadataSchema.ts create mode 100644 src/schemas/quests/QuestEventType.ts create mode 100644 src/schemas/quests/QuestFeature.ts create mode 100644 src/schemas/quests/QuestJoinOperator.ts create mode 100644 src/schemas/quests/QuestPlacementArea.ts create mode 100644 src/schemas/quests/QuestPlatformType.ts create mode 100644 src/schemas/quests/QuestRewardCodeSchema.ts create mode 100644 src/schemas/quests/QuestRewardConfigSchema.ts create mode 100644 src/schemas/quests/QuestRewardExpirationMode.ts create mode 100644 src/schemas/quests/QuestRewardSchema.ts create mode 100644 src/schemas/quests/QuestRewardType.ts create mode 100644 src/schemas/quests/QuestSchema.ts create mode 100644 src/schemas/quests/QuestSharePolicy.ts create mode 100644 src/schemas/quests/QuestTaskConfigV2Schema.ts create mode 100644 src/schemas/quests/QuestTaskSchema.ts create mode 100644 src/schemas/quests/QuestUserStatusProgressSchema.ts create mode 100644 src/schemas/quests/QuestUserStatusSchema.ts create mode 100644 src/schemas/quests/QuestVideoAssetSchema.ts create mode 100644 src/schemas/quests/QuestVideoProgressRequestSchema.ts create mode 100644 src/schemas/quests/index.ts create mode 100644 src/schemas/responses/ClaimedQuestsResponseSchema.ts create mode 100644 src/schemas/responses/QuestClaimRewardResponseSchema.ts create mode 100644 src/schemas/responses/QuestConfigResponseSchema.ts create mode 100644 src/schemas/responses/QuestPlacementResponseSchema.ts create mode 100644 src/schemas/responses/QuestRewardCodeResponseSchema.ts create mode 100644 src/schemas/responses/QuestUserStatusResponseSchema.ts create mode 100644 src/schemas/responses/QuestsResponseSchema.ts create mode 100644 src/schemas/responses/VirtualCurrencyResponseSchema.ts create mode 100644 src/schemas/uncategorised/EntitlementSchema.ts create mode 100644 src/schemas/uncategorised/EntitlementSpecialSourceType.ts create mode 100644 src/schemas/uncategorised/EntitlementType.ts diff --git a/assets/locales/en/common.json b/assets/locales/en/common.json index edcafa1da..f35197b86 100644 --- a/assets/locales/en/common.json +++ b/assets/locales/en/common.json @@ -13,7 +13,8 @@ "BASE_TYPE_CONSTANT": "This field must be {{value}}", "EMAIL_TYPE_INVALID_EMAIL": "Not a well-formed email address", "DATE_TYPE_PARSE": "Could not parse {{date}}. Should be ISO8601", - "BASE_TYPE_BAD_LENGTH": "Must be between {{length}} in length" + "BASE_TYPE_BAD_LENGTH": "Must be between {{length}} in length", + "ENUM_TYPE_COERCE": "Value \"{{value}}\" is not a valid enum value." }, "body": { "INVALID_BODY": "Invalid Body", diff --git a/assets/schemas.json b/assets/schemas.json index f691b79e860b925ec07d81e838b1cd23b1fdda34..f8c67c15885aaf6e29b51256063df9d9f34e2cbc 100644 GIT binary patch delta 10432 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 diff --git a/src/api/middlewares/Authentication.ts b/src/api/middlewares/Authentication.ts index ad949b25a..188338a94 100644 --- a/src/api/middlewares/Authentication.ts +++ b/src/api/middlewares/Authentication.ts @@ -51,6 +51,8 @@ export const NO_AUTHORIZATION_ROUTES = [ "GET /policies/instance/", // Oauth callback "/oauth2/callback", + // get quest config + /^GET \/quests\/\d+/, // Asset delivery /^(GET|HEAD) \/guilds\/\d+\/widget\.(json|png)/, /^(GET|HEAD) \/guilds\/\d+\/shield\.svg/, diff --git a/src/api/routes/quests/#quest_id/claim-reward.ts b/src/api/routes/quests/#quest_id/claim-reward.ts new file mode 100644 index 000000000..345380209 --- /dev/null +++ b/src/api/routes/quests/#quest_id/claim-reward.ts @@ -0,0 +1,86 @@ +/* + Spacebar: A FOSS re-implementation and extension of the Discord.com backend. + Copyright (C) 2023 Spacebar and Spacebar Contributors + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published + by the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see . +*/ + +import { route } from "@spacebar/api"; +import { EntitlementSpecialSourceType, EntitlementType, QuestClaimRewardRequestSchema, QuestClaimRewardResponseSchema } from "@spacebar/schemas/quests"; +import { emitEvent } from "@spacebar/util"; +import { Request, Response, Router } from "express"; +const router = Router({ mergeParams: true }); + +router.post( + "/", + route({ + description: + "Claims the quest's rewards, setting the completed_at and claimed_at fields of the quest user status to the current timestamp. Fires a Quests User Status Update Gateway event.", + requestBody: "QuestClaimRewardRequestSchema", + responses: { + 200: { + body: "QuestClaimRewardResponseSchema", + }, + }, + }), + async (req: Request, res: Response) => { + const { quest_id } = req.params; + const { location, platform } = req.body as QuestClaimRewardRequestSchema; + + // TODO: implement + console.debug(`POST /quests/${quest_id}/claim-reward is incomplete`); + + await emitEvent({ + event: "QUESTS_USER_STATUS_UPDATE", + data: { + user_status: { + claimed_at: null, + claimed_tier: null, + completed_at: null, + dismissed_quest_content: 0, + enrolled_at: new Date().toISOString(), + last_stream_heartbeat_at: null, + progress: {}, + quest_id, + stream_progress_seconds: 0, + user_id: req.user.id, + }, + }, + }); + + res.json({ + claimed_at: new Date().toISOString(), + entitlement_expiration_metadata: {}, + entitlements: [ + { + id: "1453600390154162249", + sku_id: "1287881739531976815", + application_id: "1287870191526613112", + user_id: req.user.id, + deleted: false, + starts_at: null, + ends_at: null, + type: EntitlementType.QUEST_REWARD, + tenant_metadata: {}, + source_type: EntitlementSpecialSourceType.QUEST_REWARD, + gift_code_flags: 0, // PAYMENT_SOURCE_REQUIRED, todo: make a bitfield enum + promotion_id: null, + }, + ], + errors: [], + } as QuestClaimRewardResponseSchema); + }, +); + +export default router; diff --git a/src/api/routes/quests/#quest_id/enroll.ts b/src/api/routes/quests/#quest_id/enroll.ts new file mode 100644 index 000000000..4ca3fa273 --- /dev/null +++ b/src/api/routes/quests/#quest_id/enroll.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 . +*/ + +import { route } from "@spacebar/api"; +import { QuestEnrollRequestSchema, QuestUserStatusSchema } from "@spacebar/schemas"; +import { emitEvent } from "@spacebar/util"; +import { Request, Response, Router } from "express"; +const router = Router({ mergeParams: true }); + +router.post( + "/", + route({ + description: "Accepts a quest and returns a quest user status object. Fires a Quests User Status Update Gateway event.", + requestBody: "QuestEnrollRequestSchema", + }), + async (req: Request, res: Response) => { + const { quest_id } = req.params; + const { location } = req.body as QuestEnrollRequestSchema; + + // TODO: implement + console.debug(`POST /quests/${quest_id}/enroll is incomplete`); + + const status: QuestUserStatusSchema = { + claimed_at: null, + claimed_tier: null, + completed_at: null, + dismissed_quest_content: 0, + enrolled_at: new Date().toISOString(), + last_stream_heartbeat_at: null, + progress: {}, + quest_id, + stream_progress_seconds: 0, + user_id: req.user.id, + }; + + await emitEvent({ + event: "QUESTS_USER_STATUS_UPDATE", + data: { + user_status: status, + }, + }); + + res.json(status); + }, +); + +export default router; diff --git a/src/api/routes/quests/#quest_id/index.ts b/src/api/routes/quests/#quest_id/index.ts new file mode 100644 index 000000000..af435f02f --- /dev/null +++ b/src/api/routes/quests/#quest_id/index.ts @@ -0,0 +1,141 @@ +/* + Spacebar: A FOSS re-implementation and extension of the Discord.com backend. + Copyright (C) 2023 Spacebar and Spacebar Contributors + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published + by the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see . +*/ + +import { route } from "@spacebar/api"; +import { QuestAssignmentMethod, QuestConfigResponseSchema, QuestEventType, QuestFeature, QuestPlatformType, QuestRewardType, QuestSharePolicy } from "@spacebar/schemas"; +import { Request, Response, Router } from "express"; +const router = Router({ mergeParams: true }); + +router.get( + "/", + route({ + description: "Returns a quest config object for the specified quest. Quest must be currently active.", + responses: { + 200: { + body: "QuestConfigResponseSchema", + }, + }, + }), + async (req: Request, res: Response) => { + const { quest_id } = req.params; + // TODO: implement + console.debug(`GET /quests/${quest_id} is incomplete`); + + // just a dummy response for now + res.json({ + id: "1333839522189938740", + config_version: 2, + starts_at: "2025-07-14T14:00:00+00:00", + expires_at: "2099-08-15T23:00:00+00:00", + features: [QuestFeature.QUEST_BAR_V2, QuestFeature.REWARD_HIGHLIGHTING, QuestFeature.DISMISSAL_SURVEY, QuestFeature.QUESTS_CDN, QuestFeature.PACING_CONTROLLER], + application: { + link: "https://spacebar.chat", + id: "545364944258990091", + name: "Spacebar", + }, + colors: { + primary: "#5865F2", + secondary: "#000000", + }, + assets: { + hero: "quests/1333839522189938740/orbs_quest_card_banner_4.jpeg", + hero_video: null, + quest_bar_hero: "quests/1333839522189938740/orbs_quest_bar.png", + quest_bar_hero_video: null, + game_tile: "discord_game_tile.png", + logotype: "discord_logo.png", + game_tile_light: "quests/1333839522189938740/1417603112168067182.png", + game_tile_dark: "quests/1333839522189938740/1417603112742551603.png", + logotype_light: "quests/1333839522189938740/1417603113304719540.png", + logotype_dark: "quests/1333839522189938740/1417603113791131668.png", + }, + messages: { + quest_name: "Spacebar Bars Intro", + game_title: "Spacebar", + game_publisher: "Spacebar", + }, + task_config_v2: { + tasks: { + [QuestEventType.WATCH_VIDEO]: { + type: QuestEventType.WATCH_VIDEO, + target: 31, + assets: { + video: { + url: "quests/1410358070831480904/1420884840815005717_1080.mp4", + width: 1080, + height: 1920, + thumbnail: "quests/1410358070831480904/1421253196549984267.png", + caption: "quests/1410358070831480904/1410370389451866112.vtt", + transcript: "quests/1410358070831480904/1410370413032374293.txt", + }, + video_low_res: { + url: "quests/1410358070831480904/1420884840815005717_720.mp4", + width: 1080, + height: 1920, + thumbnail: "quests/1410358070831480904/1421253196549984267.png", + caption: "quests/1410358070831480904/1410370389451866112.vtt", + transcript: "quests/1410358070831480904/1410370413032374293.txt", + }, + video_hls: { + url: "quests/1410358070831480904/1420884840815005717.m3u8", + width: 1080, + height: 1920, + thumbnail: "quests/1410358070831480904/1421253196549984267.png", + caption: "quests/1410358070831480904/1410370389451866112.vtt", + transcript: "quests/1410358070831480904/1410370413032374293.txt", + }, + }, + messages: { + video_title: "Intro to Spacebar Bars", + // video_end_cta_title: "Learn more about Bars", + // video_end_cta_subtitle: "Head to our Help Center for more information.", + }, + }, + }, + join_operator: "or", + }, + rewards_config: { + assignment_method: QuestAssignmentMethod.ALL, + rewards: [ + { + type: QuestRewardType.VIRTUAL_CURRENCY, + sku_id: "1287881739531976815", + messages: { + name: "150 Bars", + name_with_article: "150 Bars", + redemption_instructions_by_platform: { + [QuestPlatformType.CROSS_PLATFORM]: "Default", + }, + }, + orb_quantity: 150, + }, + ], + rewards_expire_at: "2099-02-01T00:00:27+00:00", + platforms: [QuestPlatformType.CROSS_PLATFORM], + }, + share_policy: QuestSharePolicy.SHAREABLE_EVERYWHERE, + cta_config: { + link: "https://spacebar.chat", + button_label: "Learn More", + subtitle: "Head to our Help Center for more information.", + }, + } as QuestConfigResponseSchema); + }, +); + +export default router; diff --git a/src/api/routes/quests/#quest_id/reward-code.ts b/src/api/routes/quests/#quest_id/reward-code.ts new file mode 100644 index 000000000..c9d1e18ea --- /dev/null +++ b/src/api/routes/quests/#quest_id/reward-code.ts @@ -0,0 +1,50 @@ +/* + Spacebar: A FOSS re-implementation and extension of the Discord.com backend. + Copyright (C) 2023 Spacebar and Spacebar Contributors + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published + by the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see . +*/ + +import { route } from "@spacebar/api"; +import { QuestPlatformType, QuestRewardCodeResponseSchema } from "@spacebar/schemas/quests"; +import { Request, Response, Router } from "express"; +const router = Router({ mergeParams: true }); + +router.get( + "/", + route({ + description: "Retrieves the reward code for the specified platform. Returns a quest reward code object on success.", + responses: { + 200: { + body: "QuestRewardCodeResponseSchema", + }, + }, + }), + async (req: Request, res: Response) => { + const { quest_id } = req.params; + + // TODO: implement + console.debug(`GET /quests/${quest_id}/reward-code is incomplete`); + + res.json({ + quest_id, + claimed_at: "2025-08-01T12:00:00+00:00", + code: "REWARD-CODE-1234", + platform: QuestPlatformType.CROSS_PLATFORM, + user_id: req.user.id, + } as QuestRewardCodeResponseSchema); + }, +); + +export default router; diff --git a/src/api/routes/quests/#quest_id/video-progress.ts b/src/api/routes/quests/#quest_id/video-progress.ts new file mode 100644 index 000000000..7c1417044 --- /dev/null +++ b/src/api/routes/quests/#quest_id/video-progress.ts @@ -0,0 +1,68 @@ +/* + Spacebar: A FOSS re-implementation and extension of the Discord.com backend. + Copyright (C) 2023 Spacebar and Spacebar Contributors + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published + by the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see . +*/ + +import { route } from "@spacebar/api"; +import { QuestUserStatusSchema, QuestVideoProgressRequestSchema } from "@spacebar/schemas/quests"; +import { emitEvent } from "@spacebar/util"; +import { Request, Response, Router } from "express"; +const router = Router({ mergeParams: true }); + +router.post( + "/", + route({ + description: + "Tells the server to update the value field of the current video task. Used for keeping track of how long the video has been watched for, and for checking if the user has met the task duration requirement. Returns a quest user status object on success. Fires a Quests User Status Update Gateway event.", + requestBody: "QuestVideoProgressRequestSchema", + responses: { + 200: { + body: "QuestVideoProgressResponseSchema", + }, + }, + }), + async (req: Request, res: Response) => { + const { quest_id } = req.params; + const { timestamp } = req.body as QuestVideoProgressRequestSchema; + + // TODO: implement + console.debug(`POST /quests/${quest_id}/video-progress is incomplete`); + + const status: QuestUserStatusSchema = { + claimed_at: null, + claimed_tier: null, + completed_at: null, + dismissed_quest_content: 0, + enrolled_at: new Date().toISOString(), + last_stream_heartbeat_at: null, + progress: {}, + quest_id, + stream_progress_seconds: 0, + user_id: req.user.id, + }; + + await emitEvent({ + event: "QUESTS_USER_STATUS_UPDATE", + data: { + user_status: status, + }, + }); + + res.json(status); + }, +); + +export default router; diff --git a/src/api/routes/quests/@me.ts b/src/api/routes/quests/@me.ts new file mode 100644 index 000000000..51093b577 --- /dev/null +++ b/src/api/routes/quests/@me.ts @@ -0,0 +1,340 @@ +/* + Spacebar: A FOSS re-implementation and extension of the Discord.com backend. + Copyright (C) 2023 Spacebar and Spacebar Contributors + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published + by the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see . +*/ + +import { route } from "@spacebar/api"; +import { ClaimedQuestsResponseSchema, QuestAssignmentMethod, QuestEventType, QuestFeature, QuestPlatformType, QuestRewardType, QuestSharePolicy } from "@spacebar/schemas"; +import { QuestsResponseSchema } from "@spacebar/schemas/responses"; +import { Request, Response, Router } from "express"; +const router = Router({ mergeParams: true }); + +router.get( + "/", + route({ + description: "Returns information on the current quests for the current user.", + responses: { + 200: { + body: "QuestsResponseSchema", + }, + }, + }), + async (req: Request, res: Response) => { + // TODO: pull quests from config + + console.debug("GET /quests/@me is incomplete"); + + res.json({ + excluded_quests: [], + quest_enrollment_blocked_until: null, + quests: [ + { + id: "1333839522189938740", + config: { + id: "1333839522189938740", + config_version: 2, + starts_at: "2025-07-14T14:00:00+00:00", + expires_at: "2099-08-15T23:00:00+00:00", + features: [ + QuestFeature.QUEST_BAR_V2, + QuestFeature.REWARD_HIGHLIGHTING, + QuestFeature.DISMISSAL_SURVEY, + QuestFeature.QUESTS_CDN, + QuestFeature.PACING_CONTROLLER, + ], + application: { + link: "https://spacebar.chat", + id: "545364944258990091", + name: "Spacebar", + }, + colors: { + primary: "#5865F2", + secondary: "#000000", + }, + assets: { + hero: "quests/1333839522189938740/orbs_quest_card_banner_4.jpeg", + hero_video: null, + quest_bar_hero: "quests/1333839522189938740/orbs_quest_bar.png", + quest_bar_hero_video: null, + game_tile: "discord_game_tile.png", + logotype: "discord_logo.png", + game_tile_light: "quests/1333839522189938740/1417603112168067182.png", + game_tile_dark: "quests/1333839522189938740/1417603112742551603.png", + logotype_light: "quests/1333839522189938740/1417603113304719540.png", + logotype_dark: "quests/1333839522189938740/1417603113791131668.png", + }, + messages: { + quest_name: "Spacebar Bars Intro", + game_title: "Spacebar", + game_publisher: "Spacebar", + }, + task_config_v2: { + tasks: { + [QuestEventType.WATCH_VIDEO]: { + type: QuestEventType.WATCH_VIDEO, + target: 31, + assets: { + video: { + url: "quests/1410358070831480904/1420884840815005717_1080.mp4", + width: 1080, + height: 1920, + thumbnail: "quests/1410358070831480904/1421253196549984267.png", + caption: "quests/1410358070831480904/1410370389451866112.vtt", + transcript: "quests/1410358070831480904/1410370413032374293.txt", + }, + video_low_res: { + url: "quests/1410358070831480904/1420884840815005717_720.mp4", + width: 1080, + height: 1920, + thumbnail: "quests/1410358070831480904/1421253196549984267.png", + caption: "quests/1410358070831480904/1410370389451866112.vtt", + transcript: "quests/1410358070831480904/1410370413032374293.txt", + }, + video_hls: { + url: "quests/1410358070831480904/1420884840815005717.m3u8", + width: 1080, + height: 1920, + thumbnail: "quests/1410358070831480904/1421253196549984267.png", + caption: "quests/1410358070831480904/1410370389451866112.vtt", + transcript: "quests/1410358070831480904/1410370413032374293.txt", + }, + }, + messages: { + video_title: "Intro to Spacebar Bars", + // video_end_cta_title: "Learn more about Bars", + // video_end_cta_subtitle: "Head to our Help Center for more information.", + }, + }, + }, + join_operator: "or", + }, + rewards_config: { + assignment_method: QuestAssignmentMethod.ALL, + rewards: [ + { + type: QuestRewardType.VIRTUAL_CURRENCY, + sku_id: "1287881739531976815", + messages: { + name: "150 Bars", + name_with_article: "150 Bars", + redemption_instructions_by_platform: { + [QuestPlatformType.CROSS_PLATFORM]: "Default", + }, + }, + orb_quantity: 150, + }, + ], + rewards_expire_at: "2099-02-01T00:00:27+00:00", + platforms: [QuestPlatformType.CROSS_PLATFORM], + }, + share_policy: QuestSharePolicy.SHAREABLE_EVERYWHERE, + cta_config: { + link: "https://spacebar.chat", + button_label: "Learn More", + subtitle: "Head to our Help Center for more information.", + }, + }, + // user_status: { + // user_id: "498989696412549120", + // quest_id: "1333839522189938740", + // enrolled_at: "2025-07-14T21:20:04.640772+00:00", + // completed_at: "2025-07-14T21:21:05.941315+00:00", + // claimed_at: "2025-07-14T21:21:26.983570+00:00", + // claimed_tier: null, + // last_stream_heartbeat_at: null, + // stream_progress_seconds: 0, + // dismissed_quest_content: 0, + // progress: { + // WATCH_VIDEO: { + // value: 31, + // event_name: "WATCH_VIDEO", + // updated_at: "2025-07-14T21:21:05.941317+00:00", + // completed_at: "2025-07-14T21:21:05.941315+00:00", + // heartbeat: null, + // }, + // }, + // }, + user_status: null, + }, + { + id: "1410358070831480904", + config: { + id: "1410358070831480904", + config_version: 2, + starts_at: "2025-11-17T16:30:27+00:00", + expires_at: "2099-01-02T00:00:27+00:00", + features: [ + QuestFeature.QUEST_BAR_V2, + QuestFeature.REWARD_HIGHLIGHTING, + QuestFeature.DISMISSAL_SURVEY, + QuestFeature.MOBILE_QUEST_DOCK, + QuestFeature.QUESTS_CDN, + QuestFeature.PACING_CONTROLLER, + QuestFeature.VIDEO_QUEST_FORCE_HLS_VIDEO, + QuestFeature.VIDEO_QUEST_FORCE_END_CARD_CTA_SWAP, + QuestFeature.MOBILE_ONLY_QUEST_PUSH_TO_MOBILE, + ], + application: { + link: "https://spacebar.chat", + id: "545364944258990091", + name: "Spacebar", + }, + assets: { + hero: "quests/1410358070831480904/1440427094801911919.jpg", + hero_video: null, + quest_bar_hero: "quests/1410358070831480904/1440368088196579358.jpg", + quest_bar_hero_video: null, + game_tile: "687100d5-5958-43aa-b221-dfe4f2b79e14.png", + logotype: "0c58c77e-4ab4-482e-b784-ea4646b992ca.png", + game_tile_light: "quests/1410358070831480904/1417602409018163210.png", + game_tile_dark: "quests/1410358070831480904/1417602409668153406.png", + logotype_light: "quests/1410358070831480904/1417602410142105680.png", + logotype_dark: "quests/1410358070831480904/1417602410733375498.png", + }, + colors: { + primary: "#4752C4", + secondary: "#000000", + }, + messages: { + quest_name: "Mobile Bars Intro", + game_title: "Earn from Quests. Spend in Shop. Reward Your Play.", + game_publisher: "Spacebar", + }, + // task_config: { + // type: 1, + // join_operator: "or", + // tasks: { + // WATCH_VIDEO_ON_MOBILE: { + // event_name: "WATCH_VIDEO_ON_MOBILE", + // target: 31, + // external_ids: [], + // }, + // }, + // }, + task_config_v2: { + tasks: { + [QuestEventType.WATCH_VIDEO_ON_MOBILE]: { + type: QuestEventType.WATCH_VIDEO_ON_MOBILE, + target: 31, + assets: { + video: { + url: "quests/1410358070831480904/1420884840815005717_1080.mp4", + width: 1080, + height: 1920, + thumbnail: "quests/1410358070831480904/1421253196549984267.png", + caption: "quests/1410358070831480904/1410370389451866112.vtt", + transcript: "quests/1410358070831480904/1410370413032374293.txt", + }, + video_low_res: { + url: "quests/1410358070831480904/1420884840815005717_720.mp4", + width: 1080, + height: 1920, + thumbnail: "quests/1410358070831480904/1421253196549984267.png", + caption: "quests/1410358070831480904/1410370389451866112.vtt", + transcript: "quests/1410358070831480904/1410370413032374293.txt", + }, + video_hls: { + url: "quests/1410358070831480904/1420884840815005717.m3u8", + width: 1080, + height: 1920, + thumbnail: "quests/1410358070831480904/1421253196549984267.png", + caption: "quests/1410358070831480904/1410370389451866112.vtt", + transcript: "quests/1410358070831480904/1410370413032374293.txt", + }, + }, + messages: { + video_title: "Intro to Spacebar Bars", + // video_end_cta_title: "Learn more about Bars", + // video_end_cta_subtitle: "Head to our Help Center for more information.", + }, + }, + }, + join_operator: "or", + }, + rewards_config: { + assignment_method: QuestAssignmentMethod.ALL, + rewards: [ + { + type: QuestRewardType.VIRTUAL_CURRENCY, + sku_id: "1287881739531976815", + messages: { + name: "150 Bars", + name_with_article: "150 Bars", + redemption_instructions_by_platform: { + [QuestPlatformType.CROSS_PLATFORM]: "Default", + }, + }, + orb_quantity: 150, + }, + ], + rewards_expire_at: "2099-02-01T00:00:27+00:00", + platforms: [QuestPlatformType.CROSS_PLATFORM], + }, + share_policy: QuestSharePolicy.SHAREABLE_EVERYWHERE, + cta_config: { + link: "https://spacebar.chat", + button_label: "Learn More", + subtitle: "Head to our Help Center for more information.", + }, + }, + // user_status: { + // user_id: "498989696412549120", + // quest_id: "1410358070831480904", + // enrolled_at: "2025-11-19T04:17:07.950593+00:00", + // completed_at: "2025-11-19T04:17:45.920547+00:00", + // claimed_at: "2025-11-19T04:17:51.972621+00:00", + // claimed_tier: null, + // last_stream_heartbeat_at: null, + // stream_progress_seconds: 0, + // dismissed_quest_content: 0, + // progress: { + // WATCH_VIDEO_ON_MOBILE: { + // value: 31, + // event_name: "WATCH_VIDEO_ON_MOBILE", + // updated_at: "2025-11-19T04:17:45.920548+00:00", + // completed_at: "2025-11-19T04:17:45.920547+00:00", + // heartbeat: null, + // }, + // }, + // }, + user_status: null, + targeted_content: [], + preview: false, + }, + ], + } as QuestsResponseSchema); + }, +); + +router.get( + "/claimed", + route({ + description: "Returns information on the claimed quests for the current user.", + responses: { + 200: { + body: "ClaimedQuestsResponseSchema", + }, + }, + }), + async (req: Request, res: Response) => { + // TODO: implement + res.json({ + quests: [], + } as ClaimedQuestsResponseSchema); + }, +); + +export default router; diff --git a/src/api/routes/quests/decision.ts b/src/api/routes/quests/decision.ts new file mode 100644 index 000000000..3d0be82e9 --- /dev/null +++ b/src/api/routes/quests/decision.ts @@ -0,0 +1,63 @@ +/* + Spacebar: A FOSS re-implementation and extension of the Discord.com backend. + Copyright (C) 2023 Spacebar and Spacebar Contributors + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published + by the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see . +*/ + +import { route } from "@spacebar/api"; +import { QuestPlacementArea, QuestPlacementResponseSchema } from "@spacebar/schemas"; +import { FieldErrors } from "@spacebar/util"; +import { Request, Response, Router } from "express"; +const router = Router({ mergeParams: true }); + +router.get( + "/", + route({ + description: "Returns the sponsored quest that should be shown to the user in a specific placement.", + query: { + placement: { + type: "number", + description: "The quest placement area to get the quest for", + }, + client_heartbeat_session_id: { + type: "string", + description: "A client-generated UUID representing the current persisted analytics heartbeat", + }, + }, + responses: { + 200: { + body: "QuestPlacementResponseSchema", + }, + }, + }), + async (req: Request, res: Response) => { + const { placement, client_heartbeat_session_id } = req.query; + // check if placement is a valid QuestPlacementArea + if (!Object.values(QuestPlacementArea).includes(placement as unknown as number)) { + throw FieldErrors({ + placement: { + code: "ENUM_TYPE_COERCE", + message: req.t("common:field.ENUM_TYPE_COERCE", { + value: placement, + }), + }, + }); + } + + res.json({} as QuestPlacementResponseSchema); + }, +); + +export default router; diff --git a/src/api/routes/users/@me/virtual-currency/balance.ts b/src/api/routes/users/@me/virtual-currency/balance.ts new file mode 100644 index 000000000..fd4577e30 --- /dev/null +++ b/src/api/routes/users/@me/virtual-currency/balance.ts @@ -0,0 +1,39 @@ +/* + Spacebar: A FOSS re-implementation and extension of the Discord.com backend. + Copyright (C) 2023 Spacebar and Spacebar Contributors + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published + by the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see . +*/ + +import { route } from "@spacebar/api"; +import { Request, Response, Router } from "express"; +const router = Router({ mergeParams: true }); + +router.get( + "/", + route({ + responses: { + 200: { + body: "VirtualCurrencyResponseSchema", + }, + }, + }), + async (req: Request, res: Response) => { + res.json({ + balance: req.user.currency, + }); + }, +); + +export default router; diff --git a/src/schemas/index.ts b/src/schemas/index.ts index 99f4095c6..0a0d87999 100644 --- a/src/schemas/index.ts +++ b/src/schemas/index.ts @@ -17,9 +17,10 @@ */ export * from "./api"; export * from "./gateway"; -export * from "./responses"; -export * from "./uncategorised"; -export * from "./webrtc"; export * from "./HelperTypes"; export * from "./Identifiers"; +export * from "./quests"; +export * from "./responses"; +export * from "./uncategorised"; export * from "./Validator"; +export * from "./webrtc"; diff --git a/src/schemas/quests/ClaimedQuestSchema.ts b/src/schemas/quests/ClaimedQuestSchema.ts new file mode 100644 index 000000000..657a7e421 --- /dev/null +++ b/src/schemas/quests/ClaimedQuestSchema.ts @@ -0,0 +1,26 @@ +/* + 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 { QuestConfigSchema } from "./QuestConfigSchema"; +import { QuestUserStatusSchema } from "./QuestUserStatusSchema"; + +export interface ClaimedQuestSchema { + id: string; + config: QuestConfigSchema; + user_status: QuestUserStatusSchema; +} diff --git a/src/schemas/quests/QuestAdIdentifiersSchema.ts b/src/schemas/quests/QuestAdIdentifiersSchema.ts new file mode 100644 index 000000000..9f81cdd60 --- /dev/null +++ b/src/schemas/quests/QuestAdIdentifiersSchema.ts @@ -0,0 +1,30 @@ +/* + 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 QuestAdIdentifiersSchema { + // The ID of the advertisement campaign + campaign_id: string; + // The ID of the advertisement set + ad_set_id: string; + // The ID of the advertisement + ad_id: string; + // The ID of the advertisement creative + creative_id: string; + // The type of advertisement creative + creative_type: string; +} diff --git a/src/schemas/quests/QuestApplicationSchema.ts b/src/schemas/quests/QuestApplicationSchema.ts new file mode 100644 index 000000000..14680c879 --- /dev/null +++ b/src/schemas/quests/QuestApplicationSchema.ts @@ -0,0 +1,26 @@ +/* + 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 QuestApplicationSchema { + // The ID of the application + id: string; + // The link to the game's page + link?: string; + // The name of the application + name: string; +} diff --git a/src/schemas/quests/QuestAssignmentMethod.ts b/src/schemas/quests/QuestAssignmentMethod.ts new file mode 100644 index 000000000..e1e5d386b --- /dev/null +++ b/src/schemas/quests/QuestAssignmentMethod.ts @@ -0,0 +1,22 @@ +/* + 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 enum QuestAssignmentMethod { + ALL = 1, + TIERED, +} diff --git a/src/schemas/quests/QuestClaimRewardRequestSchema.ts b/src/schemas/quests/QuestClaimRewardRequestSchema.ts new file mode 100644 index 000000000..908cc5049 --- /dev/null +++ b/src/schemas/quests/QuestClaimRewardRequestSchema.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 { QuestPlatformType } from "./QuestPlatformType"; + +export interface QuestClaimRewardRequestSchema { + location: number; // https://docs.discord.food/resources/quests#quest-content-type + platform: QuestPlatformType; +} diff --git a/src/schemas/quests/QuestConfigSchema.ts b/src/schemas/quests/QuestConfigSchema.ts new file mode 100644 index 000000000..a44cfb38b --- /dev/null +++ b/src/schemas/quests/QuestConfigSchema.ts @@ -0,0 +1,77 @@ +/* + Spacebar: A FOSS re-implementation and extension of the Discord.com backend. + Copyright (C) 2023 Spacebar and Spacebar Contributors + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published + by the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see . +*/ + +import { QuestRewardConfigSchema } from "./QuestRewardConfigSchema"; + +import { QuestFeature, QuestSharePolicy } from "."; +import { QuestApplicationSchema } from "./QuestApplicationSchema"; +import { QuestTaskConfigV2Schema } from "./QuestTaskConfigV2Schema"; + +export interface QuestConfigSchema { + id: string; + config_version: number; // as of now (12/24/2025) its 2 + starts_at: string; // ISO date + expires_at: string; // ISO date + features: QuestFeature[]; + application: QuestApplicationSchema; + assets: { + // The quest's hero image + hero: string | null; + // A video representation of the hero image + hero_video?: string | null; + // The hero image used in the quest popup that appears when launching the game before accepting the quest + quest_bar_hero: string | null; + // A video representation of the quest bar hero image + quest_bar_hero_video?: string | null; + // The game's icon + game_tile: string | null; + game_tile_dark: string | null; + game_tile_light: string | null; + // The game's logo + logotype: string | null; + logotype_dark: string | null; + logotype_light: string | null; + }; + colors: { + primary: string; // hex color + secondary: string; // hex color + }; + messages: { + // The name of the quest + quest_name: string; + // The title of the game the quest is for + game_title: string; + // The publisher of the game the quest is for + game_publisher: string; + }; + task_config?: unknown; // seems to be unused now in favor of task_config_v2 + task_config_v2: QuestTaskConfigV2Schema; + rewards_config: QuestRewardConfigSchema; + share_policy: QuestSharePolicy; + cta_config: { + button_label: string; + link: string; + subtitle?: string; + android?: { + android_app_id: string; + }; + ios?: { + ios_app_id: string; + }; + }; +} diff --git a/src/schemas/quests/QuestEnrollRequestSchema.ts b/src/schemas/quests/QuestEnrollRequestSchema.ts new file mode 100644 index 000000000..44a38f1ad --- /dev/null +++ b/src/schemas/quests/QuestEnrollRequestSchema.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 interface QuestEnrollRequestSchema { + location: number; // https://docs.discord.food/resources/quests#quest-content- + is_targeted?: boolean; + metadata_raw?: string | null; + metadata_sealed?: string | null; +} diff --git a/src/schemas/quests/QuestEntitlementExpirationMetadataSchema.ts b/src/schemas/quests/QuestEntitlementExpirationMetadataSchema.ts new file mode 100644 index 000000000..8244a32d6 --- /dev/null +++ b/src/schemas/quests/QuestEntitlementExpirationMetadataSchema.ts @@ -0,0 +1,24 @@ +/* + 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 QuestEntitlementExpirationMetadataSchema { + // Whether the entitlement expiration has been extended due to a premium subscription + extended: boolean; + // Whether the entitlement expiration can be extended due to a premium subscription + extendable: boolean; +} diff --git a/src/schemas/quests/QuestEventType.ts b/src/schemas/quests/QuestEventType.ts new file mode 100644 index 000000000..410903ed9 --- /dev/null +++ b/src/schemas/quests/QuestEventType.ts @@ -0,0 +1,30 @@ +/* + 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 enum QuestEventType { + STREAM_ON_DESKTOP = "STREAM_ON_DESKTOP", + PLAY_ON_DESKTOP = "PLAY_ON_DESKTOP", + PLAY_ON_XBOX = "PLAY_ON_XBOX", + PLAY_ON_PLAYSTATION = "PLAY_ON_PLAYSTATION", + PLAY_ON_DESKTOP_V2 = "PLAY_ON_DESKTOP_V2", + WATCH_VIDEO = "WATCH_VIDEO", + WATCH_VIDEO_ON_MOBILE = "WATCH_VIDEO_ON_MOBILE", + PLAY_ACTIVITY = "PLAY_ACTIVITY", + ACHIEVEMENT_IN_GAME = "ACHIEVEMENT_IN_GAME", + ACHIEVEMENT_IN_ACTIVITY = "ACHIEVEMENT_IN_ACTIVITY", +} diff --git a/src/schemas/quests/QuestFeature.ts b/src/schemas/quests/QuestFeature.ts new file mode 100644 index 000000000..b3d8123b1 --- /dev/null +++ b/src/schemas/quests/QuestFeature.ts @@ -0,0 +1,53 @@ +/* + 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 enum QuestFeature { + POST_ENROLLMENT_CTA = 1, + QUEST_BAR_V2 = 3, + EXCLUDE_MINORS = 4, // removed from the client apparently + EXCLUDE_RUSSIA = 5, + IN_HOUSE_CONSOLE_QUEST = 6, + MOBILE_CONSOLE_QUEST = 7, + START_QUEST_CTA = 8, + REWARD_HIGHLIGHTING = 9, + FRACTIONS_QUEST = 10, + ADDITIONAL_REDEMPTION_INSTRUCTIONS = 11, + PACING_V2 = 12, + DISMISSAL_SURVEY = 13, + MOBILE_QUEST_DOCK = 14, + QUESTS_CDN = 15, + PACING_CONTROLLER = 16, + QUEST_HOME_FORCE_STATIC_IMAGE = 17, + VIDEO_QUEST_FORCE_HLS_VIDEO = 18, + VIDEO_QUEST_FORCE_END_CARD_CTA_SWAP = 19, + EXPERIMENTAL_TARGETING_TRAITS = 20, + DO_NOT_DISPLAY = 21, + EXTERNAL_DIALOG = 22, + MOBILE_ONLY_QUEST_PUSH_TO_MOBILE = 23, + MANUAL_HEARTBEAT_INITIALIZATION = 24, + CLOUD_GAMING_ACTIVITY = 25, + NON_GAMING_PLAY_QUEST = 26, + ACTIVITY_QUEST_AUTO_ENROLLMENT = 27, + PACKAGE_ACTION_ADVENTURE = 28, + PACKAGE_RPG_MMO = 29, + PACKAGE_RACING_SPORTS = 30, + PACKAGE_SANDBOX_CREATIVE = 31, + PACKAGE_FAMILY_FRIENDLY = 32, + PACKAGE_HOLIDAY_SEASON = 33, + PACKAGE_NEW_YEARS = 34, +} diff --git a/src/schemas/quests/QuestJoinOperator.ts b/src/schemas/quests/QuestJoinOperator.ts new file mode 100644 index 000000000..74984e7af --- /dev/null +++ b/src/schemas/quests/QuestJoinOperator.ts @@ -0,0 +1,22 @@ +/* + 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 enum QuestJoinOperator { + AND = "and", + OR = "or", +} diff --git a/src/schemas/quests/QuestPlacementArea.ts b/src/schemas/quests/QuestPlacementArea.ts new file mode 100644 index 000000000..8b19b7b30 --- /dev/null +++ b/src/schemas/quests/QuestPlacementArea.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 enum QuestPlacementArea { + // Account panel on desktop + DESKTOP_ACCOUNT_PANEL_AREA = 1, + // Home dock on mobile + MOBILE_HOME_DOCK_AREA, +} diff --git a/src/schemas/quests/QuestPlatformType.ts b/src/schemas/quests/QuestPlatformType.ts new file mode 100644 index 000000000..b99fbfc7c --- /dev/null +++ b/src/schemas/quests/QuestPlatformType.ts @@ -0,0 +1,25 @@ +/* + 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 enum QuestPlatformType { + CROSS_PLATFORM = 0, + XBOX, + PLAYSTATION, + SWITCH, + PC, +} diff --git a/src/schemas/quests/QuestRewardCodeSchema.ts b/src/schemas/quests/QuestRewardCodeSchema.ts new file mode 100644 index 000000000..a559258b2 --- /dev/null +++ b/src/schemas/quests/QuestRewardCodeSchema.ts @@ -0,0 +1,34 @@ +/* + Spacebar: A FOSS re-implementation and extension of the Discord.com backend. + Copyright (C) 2023 Spacebar and Spacebar Contributors + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published + by the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see . +*/ + +import { QuestPlatformType } from "."; + +export interface QuestRewardCodeSchema { + // The ID of the quest + quest_id: string; + // The redeem code + code: string; + // The platform this redeem code applies to + platform: QuestPlatformType; + // The ID of the user who this code belongs to + user_id: string; + // When the user claimed the quest's reward + claimed_at: string; + // Which reward tier the code belongs to, if the quest's assignment_method is set to TIERED + tier: number | null; +} diff --git a/src/schemas/quests/QuestRewardConfigSchema.ts b/src/schemas/quests/QuestRewardConfigSchema.ts new file mode 100644 index 000000000..b9ae7dc2d --- /dev/null +++ b/src/schemas/quests/QuestRewardConfigSchema.ts @@ -0,0 +1,28 @@ +/* + Spacebar: A FOSS re-implementation and extension of the Discord.com backend. + Copyright (C) 2023 Spacebar and Spacebar Contributors + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published + by the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see . +*/ + +import { QuestAssignmentMethod } from "./QuestAssignmentMethod"; +import { QuestPlatformType } from "./QuestPlatformType"; +import { QuestRewardSchema } from "./QuestRewardSchema"; + +export interface QuestRewardConfigSchema { + assignment_method: QuestAssignmentMethod; + platforms: QuestPlatformType[]; + rewards: QuestRewardSchema[]; + rewards_expire_at: string; // ISO8601 timestamp +} diff --git a/src/schemas/quests/QuestRewardExpirationMode.ts b/src/schemas/quests/QuestRewardExpirationMode.ts new file mode 100644 index 000000000..b9821a225 --- /dev/null +++ b/src/schemas/quests/QuestRewardExpirationMode.ts @@ -0,0 +1,23 @@ +/* + 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 enum QuestRewardExpirationMode { + NORMAL = 1, + PREMIUM_EXTENSION, + PREMIUM_PERMANENT, +} diff --git a/src/schemas/quests/QuestRewardSchema.ts b/src/schemas/quests/QuestRewardSchema.ts new file mode 100644 index 000000000..56ca9d64c --- /dev/null +++ b/src/schemas/quests/QuestRewardSchema.ts @@ -0,0 +1,46 @@ +/* + Spacebar: A FOSS re-implementation and extension of the Discord.com backend. + Copyright (C) 2023 Spacebar and Spacebar Contributors + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published + by the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see . +*/ + +import { QuestRewardExpirationMode } from "./QuestRewardExpirationMode"; +import { QuestRewardType } from "./QuestRewardType"; + +export interface QuestRewardSchema { + type: QuestRewardType; + sku_id: string; + asset?: string; + asset_video?: string | null; + messages: { + name: string; + name_with_article: string; + redemption_instructions_by_platform: Record; + }; + // An approximate count of how many users can claim the reward + approximate_count?: number | null; + // The link to redeem the reward + redemption_link?: string | null; + // When the reward expires + expires_at?: string | null; + // When the reward expires for premium users + expires_at_premium?: string | null; + // The expiration mode + expiration_mode?: QuestRewardExpirationMode; + // The amount of virtual currency awarded + orb_quantity?: number; + // The days of fractional premium awarded + quantity?: number; +} diff --git a/src/schemas/quests/QuestRewardType.ts b/src/schemas/quests/QuestRewardType.ts new file mode 100644 index 000000000..2bfd7d77d --- /dev/null +++ b/src/schemas/quests/QuestRewardType.ts @@ -0,0 +1,25 @@ +/* + 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 enum QuestRewardType { + REWARD_CODE = 1, + IN_GAME, + COLLECTIBLE, + VIRTUAL_CURRENCY, + FRACTIONAL_PREMIUM, +} diff --git a/src/schemas/quests/QuestSchema.ts b/src/schemas/quests/QuestSchema.ts new file mode 100644 index 000000000..0f5b3b467 --- /dev/null +++ b/src/schemas/quests/QuestSchema.ts @@ -0,0 +1,33 @@ +/* + Spacebar: A FOSS re-implementation and extension of the Discord.com backend. + Copyright (C) 2023 Spacebar and Spacebar Contributors + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published + by the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see . +*/ + +import { QuestConfigSchema } from "./QuestConfigSchema"; +import { QuestUserStatusSchema } from "./QuestUserStatusSchema"; + +export interface QuestSchema { + // The ID of the quest + id: string; + // The configuration and metadata for the quest + config: QuestConfigSchema; + // Whether the quest is unreleased and in preview for Discord employees + preview: boolean; + // The content areas where the quest can be shown, deprecated + targeted_content: unknown[]; + // The user's quest progress, if it has been accepted + user_status: null | QuestUserStatusSchema; +} diff --git a/src/schemas/quests/QuestSharePolicy.ts b/src/schemas/quests/QuestSharePolicy.ts new file mode 100644 index 000000000..1cfc02ccb --- /dev/null +++ b/src/schemas/quests/QuestSharePolicy.ts @@ -0,0 +1,22 @@ +/* + 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 enum QuestSharePolicy { + SHAREABLE_EVERYWHERE = "shareable_everywhere", + NOT_SHAREABLE = "not_shareable", +} diff --git a/src/schemas/quests/QuestTaskConfigV2Schema.ts b/src/schemas/quests/QuestTaskConfigV2Schema.ts new file mode 100644 index 000000000..f4789b1b5 --- /dev/null +++ b/src/schemas/quests/QuestTaskConfigV2Schema.ts @@ -0,0 +1,25 @@ +/* + Spacebar: A FOSS re-implementation and extension of the Discord.com backend. + Copyright (C) 2023 Spacebar and Spacebar Contributors + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published + by the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see . +*/ + +import { QuestEventType, QuestJoinOperator } from "."; +import { QuestTaskSchema } from "./QuestTaskSchema"; + +export interface QuestTaskConfigV2Schema { + join_operator: QuestJoinOperator; + tasks: Partial>; +} diff --git a/src/schemas/quests/QuestTaskSchema.ts b/src/schemas/quests/QuestTaskSchema.ts new file mode 100644 index 000000000..0c76f6e5a --- /dev/null +++ b/src/schemas/quests/QuestTaskSchema.ts @@ -0,0 +1,40 @@ +/* + Spacebar: A FOSS re-implementation and extension of the Discord.com backend. + Copyright (C) 2023 Spacebar and Spacebar Contributors + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published + by the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see . +*/ + +import { QuestEventType } from "."; +import { QuestVideoAssetSchema } from "./QuestVideoAssetSchema"; + +export interface QuestTaskSchema { + type: QuestEventType; + target: number; // seconds the task requires + assets?: { + video: QuestVideoAssetSchema; // pretty sure this is always present + video_low_res?: QuestVideoAssetSchema; + video_hls?: QuestVideoAssetSchema; + }; // WATCH_VIDEO, WATCH_VIDEO_ON_MOBILE + applications?: { + id: string; + }[]; // All except watch video types + external_ids?: string[]; // game id on the external platform im pretty sure. PLAY_ON_XBOX, PLAY_ON_PLAYSTATION + messages?: { + video_title?: string; // WATCH_VIDEO, WATCH_VIDEO_ON_MOBILE + task_title?: string; // ACHIEVEMENT_IN_GAME, ACHIEVEMENT_IN_ACTIVITY + task_description?: string; // ACHIEVEMENT_IN_GAME, ACHIEVEMENT_IN_ACTIVITY + }; // ACHIEVEMENT_IN_GAME, ACHIEVEMENT_IN_ACTIVITY, WATCH_VIDEO, WATCH_VIDEO_ON_MOBILE + event_name?: string; // ?? seems to be used in a request. ACHIEVEMENT_IN_GAME, ACHIEVEMENT_IN_ACTIVITY +} diff --git a/src/schemas/quests/QuestUserStatusProgressSchema.ts b/src/schemas/quests/QuestUserStatusProgressSchema.ts new file mode 100644 index 000000000..b05e87da2 --- /dev/null +++ b/src/schemas/quests/QuestUserStatusProgressSchema.ts @@ -0,0 +1,30 @@ +/* + Spacebar: A FOSS re-implementation and extension of the Discord.com backend. + Copyright (C) 2023 Spacebar and Spacebar Contributors + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published + by the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see . +*/ + +import { QuestEventType } from "."; + +export interface QuestUserStatusProgressSchema { + value: number; + event_name: QuestEventType; + updated_at: string; // ISO8601 timestamp + completed_at: string | null; // ISO8601 timestamp + heartbeat: { + last_beat_at: string; // ISO8601 timestamp + expires_at: null | string; // ISO8601 timestamp + } | null; +} diff --git a/src/schemas/quests/QuestUserStatusSchema.ts b/src/schemas/quests/QuestUserStatusSchema.ts new file mode 100644 index 000000000..bf4afad6c --- /dev/null +++ b/src/schemas/quests/QuestUserStatusSchema.ts @@ -0,0 +1,42 @@ +/* + Spacebar: A FOSS re-implementation and extension of the Discord.com backend. + Copyright (C) 2023 Spacebar and Spacebar Contributors + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published + by the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see . +*/ + +import { QuestUserStatusProgressSchema } from "./QuestUserStatusProgressSchema"; + +export interface QuestUserStatusSchema { + // The ID of the user + user_id: string; + // The ID of the quest + quest_id: string; + // When the user accepted the quest + enrolled_at: null | string; + // When the user completed the quest + completed_at: null | string; + // When the user claimed the quest's reward + claimed_at: null | string; + // Which reward tier the user has claimed, if the quest's assignment_method is TIERED + claimed_tier?: number | null; + // When the last heartbeat was received. only used for quest config version 1, where the event is always STREAM_ON_DESKTOP. + last_stream_heartbeat_at?: null | string; + // Duration (in seconds) the user has streamed the game for since the quest was accepted. only used for quest config version 1, where the event is always STREAM_ON_DESKTOP. + stream_progress_seconds: number; + // The content areas the user has dismissed for the quest + dismissed_quest_content?: number; + // The user's progress for each task in the quest, keyed by their event name + progress?: Record; // ive only seen this for watch video, watch video on mobile, and play on desktop +} diff --git a/src/schemas/quests/QuestVideoAssetSchema.ts b/src/schemas/quests/QuestVideoAssetSchema.ts new file mode 100644 index 000000000..52209a468 --- /dev/null +++ b/src/schemas/quests/QuestVideoAssetSchema.ts @@ -0,0 +1,26 @@ +/* + 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 QuestVideoAssetSchema { + url: string; + width: number; + height: number; + thumbnail: string; + caption?: string; + transcript?: string; +} diff --git a/src/schemas/quests/QuestVideoProgressRequestSchema.ts b/src/schemas/quests/QuestVideoProgressRequestSchema.ts new file mode 100644 index 000000000..f31e04be8 --- /dev/null +++ b/src/schemas/quests/QuestVideoProgressRequestSchema.ts @@ -0,0 +1,22 @@ +/* + 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 interface QuestVideoProgressRequestSchema { + // How far into the video the user is (in seconds) + timestamp: number; +} diff --git a/src/schemas/quests/index.ts b/src/schemas/quests/index.ts new file mode 100644 index 000000000..72ba6645d --- /dev/null +++ b/src/schemas/quests/index.ts @@ -0,0 +1,44 @@ +/* + 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 "./ClaimedQuestSchema"; +export * from "./QuestAdIdentifiersSchema"; +export * from "./QuestApplicationSchema"; +export * from "./QuestAssignmentMethod"; +export * from "./QuestClaimRewardRequestSchema"; +export * from "./QuestConfigSchema"; +export * from "./QuestEnrollRequestSchema"; +export * from "./QuestEntitlementExpirationMetadataSchema"; +export * from "./QuestEventType"; +export * from "./QuestFeature"; +export * from "./QuestJoinOperator"; +export * from "./QuestPlacementArea"; +export * from "./QuestPlatformType"; +export * from "./QuestRewardCodeSchema"; +export * from "./QuestRewardConfigSchema"; +export * from "./QuestRewardExpirationMode"; +export * from "./QuestRewardSchema"; +export * from "./QuestRewardType"; +export * from "./QuestSchema"; +export * from "./QuestSharePolicy"; +export * from "./QuestTaskConfigV2Schema"; +export * from "./QuestTaskSchema"; +export * from "./QuestUserStatusProgressSchema"; +export * from "./QuestUserStatusSchema"; +export * from "./QuestVideoAssetSchema"; +export * from "./QuestVideoProgressRequestSchema"; diff --git a/src/schemas/responses/ClaimedQuestsResponseSchema.ts b/src/schemas/responses/ClaimedQuestsResponseSchema.ts new file mode 100644 index 000000000..f6da01d25 --- /dev/null +++ b/src/schemas/responses/ClaimedQuestsResponseSchema.ts @@ -0,0 +1,23 @@ +/* + Spacebar: A FOSS re-implementation and extension of the Discord.com backend. + Copyright (C) 2023 Spacebar and Spacebar Contributors + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published + by the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see . +*/ + +import { ClaimedQuestSchema } from "@spacebar/schemas"; + +export interface ClaimedQuestsResponseSchema { + quests: ClaimedQuestSchema[]; +} diff --git a/src/schemas/responses/QuestClaimRewardResponseSchema.ts b/src/schemas/responses/QuestClaimRewardResponseSchema.ts new file mode 100644 index 000000000..72540f8d0 --- /dev/null +++ b/src/schemas/responses/QuestClaimRewardResponseSchema.ts @@ -0,0 +1,26 @@ +/* + Spacebar: A FOSS re-implementation and extension of the Discord.com backend. + Copyright (C) 2023 Spacebar and Spacebar Contributors + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published + by the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see . +*/ + +import { EntitlementSchema, QuestEntitlementExpirationMetadataSchema } from "@spacebar/schemas"; + +export interface QuestClaimRewardResponseSchema { + claimed_at: string; + entitlement_expiration_metadata: Record; + entitlements: EntitlementSchema[]; + errors: { message: string; code: number }[]; +} diff --git a/src/schemas/responses/QuestConfigResponseSchema.ts b/src/schemas/responses/QuestConfigResponseSchema.ts new file mode 100644 index 000000000..697c1a008 --- /dev/null +++ b/src/schemas/responses/QuestConfigResponseSchema.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 . +*/ + +import { QuestConfigSchema } from "@spacebar/schemas"; + +export type QuestConfigResponseSchema = QuestConfigSchema; diff --git a/src/schemas/responses/QuestPlacementResponseSchema.ts b/src/schemas/responses/QuestPlacementResponseSchema.ts new file mode 100644 index 000000000..7927b5c0f --- /dev/null +++ b/src/schemas/responses/QuestPlacementResponseSchema.ts @@ -0,0 +1,33 @@ +/* + Spacebar: A FOSS re-implementation and extension of the Discord.com backend. + Copyright (C) 2023 Spacebar and Spacebar Contributors + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published + by the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see . +*/ + +import { QuestAdIdentifiersSchema, QuestSchema } from "@spacebar/schemas"; + +export interface QuestPlacementResponseSchema { + // The advertisement decision ID + request_id: string; + // The quest to show to the user + quest: QuestSchema | null; + // The advertisement identifiers for the delivered quest + ad_identifiers: QuestAdIdentifiersSchema | null; + // The advertisement context for the delivered quest + ad_context: { is_campaign_ias_enabled: boolean } | null; + response_ttl_seconds: number; + // Base64-encoded protobuf metadata for the advertisement + metadata_raw: string | null; +} diff --git a/src/schemas/responses/QuestRewardCodeResponseSchema.ts b/src/schemas/responses/QuestRewardCodeResponseSchema.ts new file mode 100644 index 000000000..446c071b9 --- /dev/null +++ b/src/schemas/responses/QuestRewardCodeResponseSchema.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 . +*/ + +import { QuestRewardCodeSchema } from "@spacebar/schemas"; + +export type QuestRewardCodeResponseSchema = QuestRewardCodeSchema; diff --git a/src/schemas/responses/QuestUserStatusResponseSchema.ts b/src/schemas/responses/QuestUserStatusResponseSchema.ts new file mode 100644 index 000000000..4ce547caf --- /dev/null +++ b/src/schemas/responses/QuestUserStatusResponseSchema.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 . +*/ + +import { QuestUserStatusSchema } from "@spacebar/schemas"; + +export type QuestUserStatusResponseSchema = QuestUserStatusSchema; diff --git a/src/schemas/responses/QuestsResponseSchema.ts b/src/schemas/responses/QuestsResponseSchema.ts new file mode 100644 index 000000000..e243c9c98 --- /dev/null +++ b/src/schemas/responses/QuestsResponseSchema.ts @@ -0,0 +1,28 @@ +/* + Spacebar: A FOSS re-implementation and extension of the Discord.com backend. + Copyright (C) 2023 Spacebar and Spacebar Contributors + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published + by the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see . +*/ + +import { QuestSchema } from "@spacebar/schemas"; + +export interface QuestsResponseSchema { + excluded_quests: { + id: string; + replacement_id?: string; + }[]; + quest_enrollment_blocked_until: unknown; // idk, i assume null | ISO8601 timestamp? + quests: QuestSchema[]; +} diff --git a/src/schemas/responses/VirtualCurrencyResponseSchema.ts b/src/schemas/responses/VirtualCurrencyResponseSchema.ts new file mode 100644 index 000000000..094686fa4 --- /dev/null +++ b/src/schemas/responses/VirtualCurrencyResponseSchema.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 interface VirtualCurrencyResponseSchema { + balance: number; +} diff --git a/src/schemas/responses/index.ts b/src/schemas/responses/index.ts index 690b1ec53..b7d44c9fe 100644 --- a/src/schemas/responses/index.ts +++ b/src/schemas/responses/index.ts @@ -15,11 +15,12 @@ You should have received a copy of the GNU Affero General Public License along with this program. If not, see . */ +export * from "./AccountStandingResponse"; export * from "./APIErrorOrCaptchaResponse"; export * from "./APIErrorResponse"; -export * from "./AccountStandingResponse"; export * from "./BackupCodesChallengeResponse"; export * from "./CaptchaRequiredResponse"; +export * from "./ClaimedQuestsResponseSchema"; export * from "./CollectiblesCategoriesResponse"; export * from "./CollectiblesMarketingResponse"; export * from "./CollectiblesShopResponse"; @@ -50,6 +51,12 @@ export * from "./LocationMetadataResponse"; export * from "./MemberJoinGuildResponse"; export * from "./OAuthAuthorizeResponse"; export * from "./PreloadMessagesResponseSchema"; +export * from "./QuestClaimRewardResponseSchema"; +export * from "./QuestConfigResponseSchema"; +export * from "./QuestPlacementResponseSchema"; +export * from "./QuestRewardCodeResponseSchema"; +export * from "./QuestsResponseSchema"; +export * from "./QuestUserStatusResponseSchema"; export * from "./RefreshUrlsResponse"; export * from "./SettingsProtoUpdateResponse"; export * from "./TeamListResponse"; @@ -60,7 +67,8 @@ export * from "./UpdatesResponse"; export * from "./UploadAttachmentResponseSchema"; export * from "./UserNoteResponse"; export * from "./UserProfileResponse"; -export * from "./UserRelationsResponse"; export * from "./UserRelationshipsResponse"; +export * from "./UserRelationsResponse"; +export * from "./VirtualCurrencyResponseSchema"; export * from "./WebAuthnCreateResponse"; export * from "./WebhookCreateResponse"; diff --git a/src/schemas/uncategorised/EntitlementSchema.ts b/src/schemas/uncategorised/EntitlementSchema.ts new file mode 100644 index 000000000..3dfc76f9d --- /dev/null +++ b/src/schemas/uncategorised/EntitlementSchema.ts @@ -0,0 +1,49 @@ +/* + Spacebar: A FOSS re-implementation and extension of the Discord.com backend. + Copyright (C) 2023 Spacebar and Spacebar Contributors + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published + by the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see . +*/ + +import { User } from "@spacebar/util"; +import { EntitlementSpecialSourceType } from "./EntitlementSpecialSourceType"; +import { EntitlementType } from "./EntitlementType"; + +export interface EntitlementSchema { + id: string; + type: EntitlementType; + sku_id: string; + application_id: string; + user_id: string; + user?: Partial; + guild_id?: string; + parent_id?: string; + deleted: boolean; + consumed?: boolean; + branches?: string[]; + starts_at: string | null; + ends_at: string | null; + promotion_id: string | null; + subscription_id?: string; + gift_code_flags: number; + gift_code_batch_id?: string; + gifter_user_id?: string; + gift_style?: number; + fulfillment_status?: number; + fulfilled_at?: string; + source_type?: EntitlementSpecialSourceType; + tenant_metadata?: Record; + sku?: unknown; + subscription_plan?: Partial; +} diff --git a/src/schemas/uncategorised/EntitlementSpecialSourceType.ts b/src/schemas/uncategorised/EntitlementSpecialSourceType.ts new file mode 100644 index 000000000..ec542d064 --- /dev/null +++ b/src/schemas/uncategorised/EntitlementSpecialSourceType.ts @@ -0,0 +1,30 @@ +/* + 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 enum EntitlementSpecialSourceType { + QUEST_REWARD = 1, + DEVELOPER_GIFT, + INVOICE, + REVERSE_TRIAL, + USER_GIFT, + GUILD_POWERUP, + HOLIDAY_PROMOTION, + FRACTIONAL_PREMIUM_GIVEBACK, + SUBSCRIPTION, + SUBSCRIPTION_MEMBER = 11, +} diff --git a/src/schemas/uncategorised/EntitlementType.ts b/src/schemas/uncategorised/EntitlementType.ts new file mode 100644 index 000000000..5c098e0d3 --- /dev/null +++ b/src/schemas/uncategorised/EntitlementType.ts @@ -0,0 +1,33 @@ +/* + 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 enum EntitlementType { + PURCHASE = 1, + PREMIUM_SUBSCRIPTION, + DEVELOPER_GIFT, + TEST_MODE_PURCHASE, + FREE_PURCHASE, + USER_GIFT, + PREMIUM_PURCHASE, + APPLICATION_SUBSCRIPTION, + FREE_STAFF_PURCHASE, + QUEST_REWARD, + FRACTIONAL_REDEMPTION, + VIRTUAL_CURRENCY_REDEMPTION, + GUILD_POWERUP, +} diff --git a/src/schemas/uncategorised/index.ts b/src/schemas/uncategorised/index.ts index 603151e5e..5a63b99c7 100644 --- a/src/schemas/uncategorised/index.ts +++ b/src/schemas/uncategorised/index.ts @@ -38,6 +38,9 @@ export * from "./EmailDomainLookupSchema"; export * from "./EmailDomainLookupVerifyCodeSchema"; export * from "./EmojiCreateSchema"; export * from "./EmojiModifySchema"; +export * from "./EntitlementSchema"; +export * from "./EntitlementSpecialSourceType"; +export * from "./EntitlementType"; export * from "./ForgotPasswordSchema"; export * from "./GreetRequestSchema"; export * from "./GuildCreateSchema"; @@ -63,8 +66,8 @@ export * from "./PruneSchema"; export * from "./PurgeSchema"; export * from "./RefreshUrlsRequestSchema"; export * from "./RegisterSchema"; -export * from "./RelationshipPostSchema"; export * from "./RelationshipPatchSchema"; +export * from "./RelationshipPostSchema"; export * from "./RelationshipPutSchema"; export * from "./RequestGuildMembersSchema"; export * from "./RoleModifySchema"; diff --git a/src/util/entities/User.ts b/src/util/entities/User.ts index 84471e0d4..ba008e12d 100644 --- a/src/util/entities/User.ts +++ b/src/util/entities/User.ts @@ -168,6 +168,9 @@ export class User extends BaseClass { @Column({ type: "simple-array", nullable: true }) badge_ids?: string[]; + @Column() + currency: number = 0; // virtual currency amount + // TODO: I don't like this method? validate() { if (this.discriminator) { diff --git a/src/util/interfaces/Event.ts b/src/util/interfaces/Event.ts index d72a8e213..e53adcd2c 100644 --- a/src/util/interfaces/Event.ts +++ b/src/util/interfaces/Event.ts @@ -38,7 +38,7 @@ import { Snowflake, } from "@spacebar/util"; import { JsonValue } from "@protobuf-ts/runtime"; -import { ApplicationCommand, GuildCreateResponse, PartialEmoji, PublicMember, PublicUser, PublicVoiceState, RelationshipType, UserPrivate } from "@spacebar/schemas"; +import { ApplicationCommand, GuildCreateResponse, PartialEmoji, PublicMember, PublicUser, PublicVoiceState, QuestUserStatusSchema, RelationshipType, UserPrivate } from "@spacebar/schemas"; export interface Event { guild_id?: string; @@ -608,6 +608,13 @@ export interface GuildMemberListUpdate extends Event { }; } +export interface QuestsUserStatusUpdate extends Event { + event: "QUESTS_USER_STATUS_UPDATE"; + data: { + user_status: QuestUserStatusSchema; + }; +} + export type EventData = | InvalidatedEvent | ReadyEvent @@ -658,7 +665,8 @@ export type EventData = | InteractionFailureEvent | MessageAckEvent | RelationshipAddEvent - | RelationshipRemoveEvent; + | RelationshipRemoveEvent + | QuestsUserStatusUpdate; // located in collection events @@ -712,6 +720,7 @@ export enum EVENTEnum { ApplicationCommandUpdate = "APPLICATION_COMMAND_UPDATE", ApplicationCommandDelete = "APPLICATION_COMMAND_DELETE", SessionsReplace = "SESSIONS_REPLACE", + QuestsUserStatusUpdate = "QUESTS_USER_STATUS_UPDATE", } export type EVENT = @@ -775,6 +784,7 @@ export type EVENT = | "RELATIONSHIP_UPDATE" | "SESSIONS_REPLACE" | "USER_SETTINGS_PROTO_UPDATE" + | "QUESTS_USER_STATUS_UPDATE" | CUSTOMEVENTS; export type CUSTOMEVENTS = "INVALIDATED" | "RATELIMIT";