feat(thread): upsert anonymous thread replies - #44
Merged
Merged
Conversation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
This overhauls anonymous thread handling so thread submissions behave like an app-level upsert instead of leaving orphaned persisted confessions when Discord thread creation runs into an already-existing thread. For
Reply as Anonymous Thread, Spectro now treats Discord's "thread already created for message" response as the existing thread target, records the managed thread mapping, and continues through the normal log/post or approval-dispatch flow.This closes #42 by ensuring the thread-reply failure mode no longer persists a confession that is neither logged nor published. The same thread machinery now also supports approval-enabled channels, where the Discord thread is intentionally created or resolved later during approval.
Implementation Notes
Thread Data Model
pending_channel_thread,pending_channel_thread_title, andapproved_channel_thread.pending_channel_threadand intopending_channel_thread_title, keyed by confession internal ID, so approval order determines the winning title.approved_channel_threadto the winning title row instead of storing a duplicated pending-thread pointer.Upsert Thread Resolution
resolveApprovedChannelThreadas the shared database primitive for idempotently resolving or inserting an approved Discord thread.Submission And Approval Flows
/threadand reply-as-thread submissions to resolve already-created message threads instead of failing with an orphaned confession.Query State Normalization
pending_channel_thread.approval.tsconsumes a shaped verdict object instead of raw nullable database rows.Logging And Payloads
Reply Toas a Discord message URL because it points to a specific message, while channel and thread fields stay channel-mention formatted.Breaking Changes
This changes the thread-related database model. Existing
pending_channel_thread.titledata is migrated into the new title-centric model by the included migrations.Test Cases
/threadin a non-approval channel and confirm the confession is logged and published into the created thread.Reply as Anonymous Threadfor a message that has no thread and confirm Spectro creates the message thread, logs the confession, and publishes into that thread.Reply as Anonymous Threadfor a message that already has a Discord thread and confirm Spectro resolves the existing thread instead of leaving an unlogged confession./threadin an approval-enabled channel and confirm the confession is logged as pending without creating the Discord thread immediately./threadconfession and confirm the Discord thread is created, registered, and receives the published confession.