Sync with upstream spacebarchat/server and reintroduce ticket system#136
Sync with upstream spacebarchat/server and reintroduce ticket system#136
Conversation
- Add new limit configuration classes: EmbedLimits, ComponentLimits, AttachmentLimits, AutomodLimits, ApplicationLimits - Extend existing limit classes with new properties (UserLimits, ChannelLimits, MessageLimits, GuildLimits) - Update LimitConfigurations to include all new limit classes - Replace hardcoded username length limits with configurable values in bans.ts - Update TODO comment about message content/embed length limits This addresses 48 configuration-related issues by making hardcoded length limits configurable across the codebase. Co-Authored-By: Erkin Alp Güney <erkinalp9035@gmail.com>
- Add maxMembersRequestLimit property to GuildLimits class with default value of 100 - Update RequestGuildMembers.ts to use configurable limit instead of hardcoded value - Replace TODO comment about configurable limit with actual implementation - Resolves TypeScript compilation error in gateway opcodes Co-Authored-By: Erkin Alp Güney <erkinalp9035@gmail.com>
- Replace 'any' type with 'Record<string, string>' in stats.ts - Add ESLint disable comment for intentionally empty interface in AutomodRuleSchema.ts - These were pre-existing lint issues blocking CI, unrelated to configurable limits changes Co-Authored-By: Erkin Alp Güney <erkinalp9035@gmail.com>
- Apply prettier --write to 7 files with formatting violations - Fixes code style issues in pins/index.ts, start.ts, Identify.ts, Automod.ts, responses/index.ts, Logo.ts, and String.ts - All files now pass prettier --check validation - Resolves CI build failure in 'Run npx prettier --check .' step Co-Authored-By: Erkin Alp Güney <erkinalp9035@gmail.com>
- 5 new limit configuration classes created for different system components (embeds, components, attachments, automod, applications) - Extended existing limit classes with missing properties for users, channels, messages, and guilds - Updated configuration system to include all new limit classes in the main LimitConfigurations - Replaced hardcoded limits with configurable values where they were found (currently in ban search functionality)
- Add ConnectionsConfiguration for instance-level controls - Enhance ConnectedAccount entity with privacy fields (consent_given_at, data_sharing_level, last_activity_sync, privacy_override) - Add connection privacy settings to UserSettings (connections_default_visibility, connections_activity_sharing, connections_metadata_sharing, connections_require_approval) - Create ConnectionPrivacy utility for centralized filtering with visibility levels (0=private, 1=friends only, 2=mutual guilds, 3=public) - Update schemas and DTOs for new privacy fields - Implement privacy filtering in API routes and gateway events - Add admin endpoint for connection policy management - Create TypeORM migration for new database fields - Update all exposure points with privacy controls Addresses issue #31 Co-Authored-By: Erkin Alp Güney <erkinalp9035@gmail.com>
- Replace 'any' type with 'Record<string, any>' in connections index route - Fix Config import path in ConnectionPrivacy utility Co-Authored-By: Erkin Alp Güney <erkinalp9035@gmail.com>
…per typing Co-Authored-By: Erkin Alp Güney <erkinalp9035@gmail.com>
- Export ConnectionPrivacy from util/index.ts to fix import path issues - Update import statements to use @spacebar/util instead of relative paths - Fix const assignment issue in gateway listener by using opts.data - Remove unused @ts-expect-error directives that are no longer needed All TypeScript compilation errors are now resolved and code passes prettier formatting. Co-Authored-By: Erkin Alp Güney <erkinalp9035@gmail.com>
- Add reply_ids column to Message entity for forward links - Create database migrations for postgres, mariadb, and mysql - Implement lazy population of forward links from existing backlinks - Add new /channels/:id/messages/:id/replies API endpoint - Make reply_ids opt-in via x-client-capabilities and x-gateway-intents headers - Handle forward link updates during message creation and deletion - Support privileged deletion of messages with all replies - Addresses issue #13 Co-Authored-By: Erkin Alp Güney <erkinalp9035@gmail.com>
- Add BitFlag(12) for doubly-linked replies feature - Integrates with existing capabilities system - Maintains consistency with established patterns Co-Authored-By: Erkin Alp Güney <erkinalp9035@gmail.com>
- Move from BitFlag(12) to BitFlag(37) to avoid conflicts - Maintains compatibility with existing Discord clients - Places capability flag after bit 36 as requested Co-Authored-By: Erkin Alp Güney <erkinalp9035@gmail.com>
…ring - Add capability checking in gateway listener for MESSAGE_CREATE/MESSAGE_UPDATE - Remove REST API header-based capability checking from all endpoints - Simplify Message.toJSON to always include reply_ids - Gateway now handles filtering based on client capabilities - Centralizes capability logic in gateway following established patterns Co-Authored-By: Erkin Alp Güney <erkinalp9035@gmail.com>
The /replies endpoint should always include reply_ids since clients calling it already understand the doubly-linked replies concept Co-Authored-By: Erkin Alp Güney <erkinalp9035@gmail.com>
Use permissions.has() instead of rights.has() for MANAGE_MESSAGES check when deleting replies, consistent with other permission checks in the same function. Addresses GitHub comment by @erkinalp Co-Authored-By: Erkin Alp Güney <erkinalp9035@gmail.com>
- Add Channel and MessageDeleteBulkEvent imports - Fetch Channel entity to get proper guild_id context - Use MESSAGE_DELETE_BULK instead of individual MESSAGE_DELETE events - Follow existing bulk delete patterns from bulk-delete.ts and purge.ts Addresses GitHub comment by @erkinalp Co-Authored-By: Erkin Alp Güney <erkinalp9035@gmail.com>
- Remove hardcoded MANAGE_MESSAGES permission from route decorator - Add dynamic permission checking based on message ownership - Check SELF_DELETE_MESSAGES for user-owned replies - Check MANAGE_MESSAGES only for other users' replies - Follow existing patterns from individual message deletion endpoint Addresses GitHub feedback by @erkinalp Co-Authored-By: Erkin Alp Güney <erkinalp9035@gmail.com>
Added reply_ids column to Message entity to store forward links
Created database migrations for PostgreSQL, MariaDB, and MySQL
Implemented lazy population of forward links from existing backlinks during message retrieval
Added new /channels/:id/messages/:id/replies API endpoint to fetch replies to a message
Made reply data opt-in on client side
Added cleanup logic for forward links when messages are deleted
Support for privileged deletion of messages with all their replies (requires MANAGE_MESSAGES permission)
…ts\n\n- New entity: UserConsent { user_id, service_id, created_at }\n- Self endpoints:\n - GET /users/@me/consents\n - PUT /users/@me/consents/:service_id (idempotent)\n - DELETE /users/@me/consents/:service_id (silent if missing)\n- Admin endpoints (requires MANAGE_USERS):\n - GET /users/:id/consents\n - PUT /users/:id/consents/:service_id\n - DELETE /users/:id/consents/:service_id\n- OpenAPI updated
Co-Authored-By: Erkin Alp Güney <erkinalp9035@gmail.com>
…x route syntax and OpenAPI Co-Authored-By: Erkin Alp Güney <erkinalp9035@gmail.com>
Implements a comprehensive consent management system for Anticensor server based on requirements from spacebarchat#1003. This adds: New UserConsent entity with TypeORM, including unique constraint on (user_id, service_id) Self-service endpoints under /users/@me/consents for users to manage their own consents Admin endpoints under /users/:id/consents for admins to view and revoke user consents Operator-only bulk revoke endpoint to revoke all consents for a user Key design decisions: Admins can only view and revoke consents, not grant them on behalf of users Bulk "revoke all consents" requires OPERATOR permissions (highest privilege level) Individual consent revocation requires MANAGE_USERS permissions Self-service consent management has no special permission requirements
…channel with permissions continuity and ordering Co-Authored-By: Erkin Alp Güney <erkinalp9035@gmail.com>
Co-Authored-By: Erkin Alp Güney <erkinalp9035@gmail.com>
…OR && !PRESENCE) || (OPERATOR && PRESENCE); bypass Rights.has for PRESENCE checks Co-Authored-By: Erkin Alp Güney <erkinalp9035@gmail.com>
… defaults hidden; PRESENCE bit toggles)
- Fix formatting issues in Permissions.ts, pins.ts, and pins/index.ts - Resolve CI build failure caused by Prettier formatting checks Co-Authored-By: Erkin Alp Güney <erkinalp9035@gmail.com>
Implement Discord lobby feature with in-memory storage - Add LobbyStore for ephemeral lobby management with timeout cleanup - Implement all lobby API endpoints following Discord specification - Add lobby gateway events for real-time updates - Support metadata limits, member limits, and idle timeout functionality - Add proper TypeScript interfaces and schema validation - Integrate lobby routes into main API server - Add lobby event types to EVENT union for proper type safety * also fixes formatting errors in pins/index.ts Co-authored-by: Devin AI <devin@app.devin.ai> Co-authored-by: openhands <openhands@all-hands.dev>
…scord: and external: codes); reuse config flags for template usage Co-Authored-By: Erkin Alp Güney <erkinalp9035@gmail.com>
…T /guilds template logic Co-Authored-By: Erkin Alp Güney <erkinalp9035@gmail.com>
Implements support for the existing guild_template_code field in GuildCreateSchema for POST /guilds. Previously this field was ignored; now it honors discord:, external:, and local template codes by fetching the template data and merging it into guild creation, mirroring the logic from the existing GET/POST /guilds/templates/:code routes. This resolves spacebarchat#1282 by enabling guild creation from Discord templates directly through the main guild creation endpoint. Key changes: Added template fetching logic to POST /guilds route Supports discord: prefixed templates (fetches from Discord API) Supports external: prefixed templates (parses embedded JSON) Supports local template codes (looks up in database) Respects existing config flags (templates.enabled, allowDiscordTemplates, allowRaws) Template data is merged first, then request body overrides (preserving user customizations)
Merge 1165 commits from spacebarchat/server upstream/master into erkinalp/anticensor, preserving all 54 anticensor-specific commits and features. Resolved 62 conflicted files during merge. Post-merge fixes include: - Fix UserConsent entity (removed non-existent dbEngine import) - Fix ConnectionPrivacy to work with upstream ConnectedAccount - Add lobby event types to CUSTOMEVENTS in Event.ts - Export LobbyStore and ConnectionPrivacy from @spacebar/util - Export ChannelPromoteSchema from schemas index - Add reply_ids column to Message entity for doubly-linked replies - Fix promote.ts imports (ChannelType from schemas, remove ENCRYPTED) - Fix connections.ts (remove non-existent Config.connections ref) - Fix Express req.params type narrowing in all anticensor routes - Add @types/express-serve-static-core as direct dep (fix TS2742) - Patch discord-protos with runtime stub (npm package missing built output) - Remove deprecated husky v10 lines from pre-commit hook - Install missing direct dependencies (@protobuf-ts/runtime, @types/ms) Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Original prompt from Erkin
|
🤖 Devin AI EngineerI'll be helping with this pull request! Here's what you should know: ✅ I will automatically:
Note: I can only respond to comments from users who have write access to this repository. ⚙️ Control Options:
|
… default-only files Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
|
|
||
| if (this.session_id) { | ||
| await Session.delete({ session_id: this.session_id }); | ||
| // await Session.delete({ session_id: this.session_id }); |
There was a problem hiding this comment.
🔴 Session deletion commented out in gateway Close handler causes session leak
The Session.delete({ session_id: this.session_id }) call is commented out at src/gateway/events/Close.ts:31, meaning sessions are never cleaned up when a websocket connection closes. This will cause sessions to accumulate indefinitely in the database, leading to stale session data (e.g., incorrect presence information, inflated session counts in SESSIONS_REPLACE events) and eventually performance degradation.
| // await Session.delete({ session_id: this.session_id }); | |
| await Session.delete({ session_id: this.session_id }); |
Was this helpful? React with 👍 or 👎 to provide feedback.
There was a problem hiding this comment.
This is pre-existing code from the default branch — the comment-out and the "temporary hack" session creation in Token.ts appear to be intentional changes by the repo maintainer. Not modifying these in this sync PR.
| if (decoded.did && !session) { | ||
| // temporary hack: create new session | ||
| session = Session.create({ | ||
| session_id: decoded.did, | ||
| user_id: user.id, | ||
| is_admin_session: false, | ||
| client_status: {}, | ||
| status: "online", | ||
| client_info: {}, | ||
| }); | ||
| await session.save(); | ||
| logAuth("validateUser rejected: Session not found"); | ||
| return rejectAndLog(reject, 401, "Invalid Token"); | ||
| } |
There was a problem hiding this comment.
🔴 Token validation creates session then immediately rejects, leaving orphaned session
When decoded.did is present but no matching session is found, the code creates a new session, saves it to the database, and then immediately rejects the token as invalid (src/util/util/Token.ts:99-111). This orphaned session will persist in the database with no active websocket connection. Combined with BUG-0001 (session deletion commented out in Close handler), these sessions will never be cleaned up.
Prompt for agents
In src/util/util/Token.ts lines 99-112, the code creates a new Session and saves it to the database, then immediately rejects the token as invalid. This leaves an orphaned session in the database. Either remove the session creation (lines 100-109) to only reject, or don't reject after creating the session (remove lines 110-111). The comment says 'temporary hack' which suggests the intent was to auto-create missing sessions and continue validation, not reject. If the intent is to auto-create, remove lines 110-111 so validation continues with the newly created session.
Was this helpful? React with 👍 or 👎 to provide feedback.
There was a problem hiding this comment.
Pre-existing code from the default branch — not modifying in this sync PR.
…e.ts import Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
…ETS permission, and fix reactions DM guard - Add TICKET_TRACKER = 19 to ChannelType enum - Add MANAGE_TICKETS = BitFlag(53) guild permission - Update ticket.ts to use ChannelType.TICKET_TRACKER directly (was dead code with dynamic lookup) - Update ticket.ts permission checks from MANAGE_THREADS to MANAGE_TICKETS - Update tickets.ts to use ChannelType.TICKET_TRACKER directly - Wire ticket and tickets routes back into channel router (index.ts) - Export TicketSchemas from schemas/uncategorised/index.ts - Fix reactions.ts DM channel guard: skip Member lookup for non-guild channels Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
erkinalp
left a comment
There was a problem hiding this comment.
let's fix code to satisfy all checks, including the non-required ones; don't Volkswagen it
…in Nix build - Update discord-protos in package-lock.json from 1.2.102 to 1.2.121 to match package.json - Apply all patches in Nix configurePhase since postinstall scripts don't run in Nix builds - This fixes the ENOTCACHED error during npm prune --offline in the Nix build Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
…into devin/1773598801-sync-upstream
…hes already applied) The patch-package format patches (ajv, body-parser, express, typescript-json-schema) are already applied during npm install by the Nix importNpmLock hook. Only the discord-protos patch needs explicit application since it uses pnpm patch format. Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
The getRouteDescriptions.js script mocks express.Router with only get/post/put/delete/patch methods. router.use() is not supported. - Remove redundant lobbies.ts wrapper (auto-loader handles lobbies/ dir) - Remove router.use(tickets/ticket) from channel index.ts (auto-loaded) - Fix ticket route paths from '/tickets'/'/ticket' to '/' (auto-loader provides the prefix from filesystem path) - Regenerate openapi.json with correct ticket route paths Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
The qemu-vm.nix module provides required fileSystems and bootloader configuration that nix flake check expects for nixosConfigurations. Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
TypeORM requires migration class names to end with a valid JavaScript timestamp (milliseconds). Changed from 1755848356 (10-digit Unix seconds) to 1755848356000 (13-digit JS milliseconds) to match all other migrations in the codebase. Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Summary
Merges 1165 upstream commits from
spacebarchat/serverintoerkinalp/anticensor, resolving 62 conflicted files while preserving all anticensor-specific features. Also reintroduces the ticket system with proper enum values, guild permissions, and route wiring.Upstream sync
Major upstream changes incorporated: Express v5 upgrade, schema directory restructuring (
src/util/schemas→src/schemas/uncategorised), new WebRTC implementation, automod system, lambert-server internalization, bulk-ban, forum/media channels, application commands, and more.Anticensor features preserved
All 54 anticensor-specific commits were carried forward and adapted to the new upstream codebase:
LobbyStore, CRUD routes (/lobbies), channel linking, lobby events (LOBBY_CREATE,LOBBY_UPDATE,LOBBY_DELETE,LOBBY_MEMBER_ADD,LOBBY_MEMBER_REMOVE),LOBBYchannel type (17)TICKET_TRACKERchannel type (19),MANAGE_TICKETSguild permission (BitFlag(53)),TicketFlags(RESOLVED,ARCHIVED), POST/channels/:id/ticketsand PATCH/channels/:id/ticketendpointsreply_idscolumn onMessageentity,GET/DELETE /messages/:id/repliesroute,DOUBLY_LINKED_REPLIEScapability flagUserConsententity,GET/PUT/DELETE /users/@me/consents/:service_id, admin consent revocationConnectionPrivacyutility withVisibilityLevelenum, per-account visibility filteringPOST /channels/:id/promoteto convert thread → top-level channelBYPASS_SLOWMODEpermission (BitFlag(52))BitFlag(51))shouldRoutePresenceFromRights)AutomodEvaluator+AutomodActionExecutorwith keyword filtering, regex patterns, mention spam detectionPost-merge adaptation fixes
UserConsent.ts: Simplified entity to{user_id, service_id, created_at}(removed fields not compatible with upstream entity model)ConnectionPrivacy.ts: Usesshow_activity,metadata_visibility,visibilityfrom upstreamConnectedAccountpromote.ts: Updated imports (ChannelTypefrom@spacebar/schemas)Message.ts: Addedreply_idscolumn for doubly-linked repliesreq.paramstype narrowing (as stringcasts) in all anticensor routesLobbyStore,ConnectionPrivacy,ChannelPromoteSchema,TicketSchemasfrom package indexesBuild & CI fixes
@types/express-serve-static-coreas direct devDependency (fixes 153 TS2742 errors under pnpm)discord-protospatched with runtime stub viapnpm patch(npm package ships without built output)@protobuf-ts/runtimeand@types/msas direct dependenciesAutomodActionExecutor.ts:EmbedTypeimported from@spacebar/schemasinstead of entitypaper-recommender-extension/added to eslint ignoresdefault.nix: FixedconfigurePhaseto only apply discord-protos pnpm patch (patch-package format patches are already applied by npm postinstall)nix/testVm/vm.nix: Uncommentedqemu-vm.nixmodule import (provides requiredfileSystemsand bootloader config fornix flake check)DoublyLinkedRepliesmigration: Fixed timestamp from 10-digit Unix seconds (1755848356) to 13-digit JS milliseconds (1755848356000) — TypeORM requires valid JS timestamps in migration class namesRoute fixes
src/api/routes/lobbies.tswrapper file (conflicted with auto-loader which already mountslobbies/directory)router.use(tickets)androuter.use(ticket)fromchannels/#channel_id/index.ts— the auto-loader handles directory-based routing;router.use()calls causedTypeError: router.use is not a functionduring schema generation (the mock Router lacks.use())tickets.tsandticket.tsfrom/tickets//ticketto/to avoid double-prefixing (auto-loader already mounts them at/channels/:channel_id/ticketsand/channels/:channel_id/ticket)Bug fixes
Memberlookup now conditionally skipped for non-guild channels (DMs), preventing a crash whenguild_idis nullguild_id: channel.guild_idtoMember.findOneOrFailquery@spacebar/util*import; rewrote as stub endpointTICKET_TRACKERandLOBBYto thecreateChannelswitch statement — these types were falling through todefaultwhich throws "Not yet supported", making it impossible to create ticket tracker or lobby channels viaPOST /guilds/:guild_id/channelsReview & Testing Checklist for Human
memberis nowundefinedfor DM reactions (was previously crashing). Verify theMessageReactionAddEventtype and downstream clients acceptmember: undefinedfor DM reactions — this is a runtime behavior change on a common code path.EPHEMERAL_DM(type 18) is NOT in thecreateChannelswitch.TICKET_TRACKERandLOBBYwere added, butEPHEMERAL_DMstill falls through to "Not yet supported". Verify whether ephemeral DMs should be creatable via the guild channel creation endpoint or only through the social layer SDK (in which case the current behavior is correct).discord-protospatch uses JSON stub, NOT real protobuf. ThefromBase64/toBase64methods useJSON.stringify+ base64, not protobuf wire format./users/@me/settings-proto/1and/2will NOT interoperate with clients expecting real protobuf. The upstream npm package requires a Puppeteer-based build pipeline to generate real protobuf output.pnpm start, register a user, create a guild, send messages, add reactions in both a guild channel and a DM (verify no crash in DM), create a channel withtype: 19(TICKET_TRACKER), POST a ticket to it, PATCH the ticket, create a lobby channel (type: 17), and test lobby CRUD via the API.Notes
build-nixCI checks now pass, including the NixOS VM integration test (nix flake check).MANAGE_TICKETSdefinitions exist:Permissions.FLAGS.MANAGE_TICKETSatBitFlag(53)(guild-level, used by ticket routes) andRights.MANAGE_TICKETSatBitFlag(6)(instance-level admin right). These are different systems; the ticket routes correctly use the guild-level permission.location-info.tsandcountry-code.tsreturn"US".connections.tsreturns{}.defaultbranch issues carried forward: Session deletion is commented out inClose.ts(session leak);Token.tscreates a session then immediately rejects (orphaned session). These appear intentional by the repo maintainer.Link to Devin session: https://app.devin.ai/sessions/f545780544d4405180c5ff2dc94b892b
Requested by: @erkinalp