This repository has no description
Something went wrong. Try again.
11 kB · 298 lines
TypeScript
at main
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299// SPDX-License-Identifier: AGPL-3.0-or-later
import {HarvestIdParam, MessageIdParam} from '@fluxer/schema/src/domains/common/CommonParamSchemas';import {MessageListResponse} from '@fluxer/schema/src/domains/message/MessageResponseSchemas';import { HarvestCreationResponseSchema, HarvestDownloadUrlResponse, HarvestStatusResponseSchema, HarvestStatusResponseSchemaNullable,} from '@fluxer/schema/src/domains/user/UserHarvestSchemas';import { HarvestSelfDataRequest, MarkMentionsReadRequest, SaveMessageRequest, UserMentionsQueryRequest, UserSavedMessagesQueryRequest,} from '@fluxer/schema/src/domains/user/UserRequestSchemas';import {SavedMessageEntryListResponse} from '@fluxer/schema/src/domains/user/UserResponseSchemas';import {createChannelID, createMessageID} from '../../BrandedTypes';import {DefaultUserOnly, LoginRequired} from '../../middleware/AuthMiddleware';import {RateLimitMiddleware} from '../../middleware/RateLimitMiddleware';import {OpenAPI} from '../../middleware/ResponseTypeMiddleware';import {RateLimitConfigs} from '../../RateLimitConfig';import type {HonoApp} from '../../types/HonoEnv';import {Validator} from '../../Validator';
export function UserContentController(app: HonoApp) { app.get( '/users/@me/mentions', RateLimitMiddleware(RateLimitConfigs.USER_MENTIONS_READ), LoginRequired, DefaultUserOnly, Validator('query', UserMentionsQueryRequest), OpenAPI({ operationId: 'list_mentions_for_current_user', summary: 'List mentions for current user', responseSchema: MessageListResponse, statusCode: 200, security: ['bearerToken', 'sessionToken'], tags: ['Users'], description: 'Retrieves messages where the current user was mentioned. Supports filtering by role mentions, everyone mentions, and specific guilds. Returns paginated list of messages.', }), async (ctx) => { const {limit, roles, everyone, guilds, before} = ctx.req.valid('query'); const response = await ctx.get('userContentRequestService').listMentions({ userId: ctx.get('user').id, limit, everyone, roles, guilds, before: before ? createMessageID(before) : undefined, requestCache: ctx.get('requestCache'), }); return ctx.json(response); }, ); app.post( '/users/@me/mentions/read', RateLimitMiddleware(RateLimitConfigs.USER_MENTIONS_DELETE), LoginRequired, DefaultUserOnly, Validator('json', MarkMentionsReadRequest), OpenAPI({ operationId: 'mark_mentions_read', summary: 'Mark mentions read', requestSchema: MarkMentionsReadRequest, responseSchema: null, statusCode: 204, security: ['bearerToken', 'sessionToken'], tags: ['Users'], description: "Removes multiple messages from the current user's recent mention history. Does not delete the original messages.", }), async (ctx) => { await ctx.get('userContentRequestService').markMentionsRead({ userId: ctx.get('user').id, messageIds: ctx.req.valid('json').message_ids.map((messageId) => createMessageID(messageId)), }); return ctx.body(null, 204); }, ); app.delete( '/users/@me/mentions/:message_id', RateLimitMiddleware(RateLimitConfigs.USER_MENTIONS_DELETE), LoginRequired, DefaultUserOnly, Validator('param', MessageIdParam), OpenAPI({ operationId: 'delete_mention', summary: 'Delete mention', responseSchema: null, statusCode: 204, security: ['bearerToken', 'sessionToken'], tags: ['Users'], description: "Removes a mention from the current user's mention history. Does not delete the original message, only removes it from the user's personal mention list.", }), async (ctx) => { await ctx.get('userContentRequestService').deleteMention({ userId: ctx.get('user').id, messageId: createMessageID(ctx.req.valid('param').message_id), }); return ctx.body(null, 204); }, ); app.get( '/users/@me/saved-messages', RateLimitMiddleware(RateLimitConfigs.USER_SAVED_MESSAGES_READ), LoginRequired, DefaultUserOnly, Validator('query', UserSavedMessagesQueryRequest), OpenAPI({ operationId: 'list_saved_messages', summary: 'List saved messages', responseSchema: SavedMessageEntryListResponse, statusCode: 200, security: ['bearerToken', 'sessionToken'], tags: ['Users'], description: 'Retrieves all messages saved by the current user. Messages are saved privately for easy reference. Returns paginated list of saved messages with metadata.', }), async (ctx) => { const response = await ctx.get('userContentRequestService').listSavedMessages({ userId: ctx.get('user').id, limit: ctx.req.valid('query').limit, requestCache: ctx.get('requestCache'), }); return ctx.json(response, 200); }, ); app.post( '/users/@me/saved-messages', RateLimitMiddleware(RateLimitConfigs.USER_SAVED_MESSAGES_WRITE), LoginRequired, DefaultUserOnly, Validator('json', SaveMessageRequest), OpenAPI({ operationId: 'save_message', summary: 'Save message', responseSchema: null, statusCode: 204, security: ['bearerToken', 'sessionToken'], tags: ['Users'], description: 'Saves a message for the current user. Saved messages can be accessed later from the saved messages list. Messages are saved privately.', }), async (ctx) => { const {channel_id, message_id} = ctx.req.valid('json'); await ctx.get('userContentRequestService').saveMessage({ userId: ctx.get('user').id, channelId: createChannelID(channel_id), messageId: createMessageID(message_id), requestCache: ctx.get('requestCache'), }); return ctx.body(null, 204); }, ); app.delete( '/users/@me/saved-messages/:message_id', RateLimitMiddleware(RateLimitConfigs.USER_SAVED_MESSAGES_WRITE), LoginRequired, DefaultUserOnly, Validator('param', MessageIdParam), OpenAPI({ operationId: 'unsave_message', summary: 'Unsave message', responseSchema: null, statusCode: 204, security: ['bearerToken', 'sessionToken'], tags: ['Users'], description: "Removes a message from the current user's saved messages. Does not delete the original message, only removes it from the user's saved collection.", }), async (ctx) => { await ctx.get('userContentRequestService').unsaveMessage({ userId: ctx.get('user').id, messageId: createMessageID(ctx.req.valid('param').message_id), }); return ctx.body(null, 204); }, ); app.post( '/users/@me/harvest', RateLimitMiddleware(RateLimitConfigs.USER_DATA_HARVEST), LoginRequired, DefaultUserOnly, OpenAPI({ operationId: 'request_data_harvest', summary: 'Request data harvest', responseSchema: HarvestCreationResponseSchema, statusCode: 200, security: ['bearerToken', 'sessionToken'], tags: ['Users'], description: 'Requests a data harvest of all user data and content. Initiates an asynchronous process to compile and prepare all data for download in a portable format. Returns harvest ID and status.', }), async (ctx) => { const result = await ctx.get('userContentRequestService').requestHarvest({userId: ctx.get('user').id}); return ctx.json(result, 200); }, ); app.post( '/users/@me/harvest/filtered', RateLimitMiddleware(RateLimitConfigs.USER_DATA_HARVEST), LoginRequired, DefaultUserOnly, Validator('json', HarvestSelfDataRequest), OpenAPI({ operationId: 'request_filtered_data_harvest', summary: 'Request filtered data harvest', responseSchema: HarvestCreationResponseSchema, statusCode: 200, security: ['bearerToken', 'sessionToken'], tags: ['Users'], description: 'Requests a data harvest with the same optional scope and date-range filters offered by the bulk-delete endpoint. Settings, memberships, and other non-message data are always included; the filter only constrains which messages end up in the archive. Returns harvest ID and status.', }), async (ctx) => { const filter = ctx.req.valid('json'); const result = await ctx .get('userContentRequestService') .requestFilteredHarvest({userId: ctx.get('user').id, filter}); return ctx.json(result, 200); }, ); app.get( '/users/@me/harvest/latest', RateLimitMiddleware(RateLimitConfigs.USER_HARVEST_LATEST), LoginRequired, DefaultUserOnly, OpenAPI({ operationId: 'get_latest_data_harvest', summary: 'Get latest data harvest', responseSchema: HarvestStatusResponseSchemaNullable, statusCode: 200, security: ['bearerToken', 'sessionToken'], tags: ['Users'], description: 'Retrieves the status of the most recent data harvest request. Returns null if no harvest has been requested yet. Shows progress and estimated completion time.', }), async (ctx) => { const harvest = await ctx.get('userContentRequestService').getLatestHarvest({userId: ctx.get('user').id}); return ctx.json(harvest, 200); }, ); app.get( '/users/@me/harvest/:harvestId', RateLimitMiddleware(RateLimitConfigs.USER_HARVEST_STATUS), LoginRequired, DefaultUserOnly, Validator('param', HarvestIdParam), OpenAPI({ operationId: 'get_data_harvest_status', summary: 'Get data harvest status', responseSchema: HarvestStatusResponseSchema, statusCode: 200, security: ['bearerToken', 'sessionToken'], tags: ['Users'], description: 'Retrieves detailed status information for a specific data harvest. Shows progress, completion status, and other metadata about the harvest request.', }), async (ctx) => { const {harvestId} = ctx.req.valid('param'); const harvest = await ctx.get('userContentRequestService').getHarvestStatus({ userId: ctx.get('user').id, harvestId, }); return ctx.json(harvest, 200); }, ); app.get( '/users/@me/harvest/:harvestId/download', RateLimitMiddleware(RateLimitConfigs.USER_HARVEST_DOWNLOAD), LoginRequired, DefaultUserOnly, Validator('param', HarvestIdParam), OpenAPI({ operationId: 'get_data_harvest_download_url', summary: 'Get data harvest download URL', responseSchema: HarvestDownloadUrlResponse, statusCode: 200, security: ['bearerToken', 'sessionToken'], tags: ['Users'], description: 'Retrieves the download URL for a completed data harvest. The URL is temporary and expires after a set time. Can only be accessed for completed harvests.', }), async (ctx) => { const {harvestId} = ctx.req.valid('param'); const result = await ctx.get('userContentRequestService').getHarvestDownloadUrl({ userId: ctx.get('user').id, harvestId, storageService: ctx.get('storageService'), }); return ctx.json(result, 200); }, );}