feat: recover missing conversations, fix media attachment, add manual inbox tab
Missing conversations: recipient Reddit accounts that are deleted or suspended left conversations unaccounted for. A new RecipientAccountStatusService polls Reddit for the users behind cached conversations and records their account status durably, with progressive backfill and delta-media fixes in ChatService so history and images are no longer dropped mid-sync. Media: attachMedia now surfaces download failures as MediaAttachmentError so the sync cursor can be retried instead of silently losing an image, recognizes image bytes when Matrix returns a generic content type, and keeps separate gallery occurrences when the same asset appears in more than one event. Manual inbox tab: the conversations list now carries the reply-loop status, so the inbox can separate conversations the operator is driving by hand from the ones automation is still handling. A Manual filter pill and a per-row chip explain why each conversation was handed over. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
1 parent
725b5fc4e6
commit
ac12a3146a
35 files changed
+1164
-129
No files matched your search
@@ -425,6 +425,37 @@ export function runMigrations(db: Database.Database): void {
|
||||
CREATE INDEX IF NOT EXISTS idx_conversation_read_state_status
|
||||
ON conversation_read_state(account_id, status, snoozed_until);
|
||||
`),
|
||||
() => db.exec(`
|
||||
CREATE TABLE reddit_media_occurrences (
|
||||
account_id TEXT NOT NULL,
|
||||
media_id TEXT NOT NULL,
|
||||
chat_username TEXT,
|
||||
chat_room_id TEXT,
|
||||
sender TEXT NOT NULL,
|
||||
timestamp INTEGER NOT NULL,
|
||||
original_url TEXT NOT NULL,
|
||||
file_name TEXT NOT NULL,
|
||||
relative_path TEXT NOT NULL,
|
||||
created_at INTEGER NOT NULL,
|
||||
PRIMARY KEY (account_id, media_id),
|
||||
FOREIGN KEY (account_id) REFERENCES reddit_accounts(account_id) ON DELETE CASCADE
|
||||
);
|
||||
INSERT INTO reddit_media_occurrences SELECT * FROM reddit_media;
|
||||
DROP TABLE reddit_media;
|
||||
ALTER TABLE reddit_media_occurrences RENAME TO reddit_media;
|
||||
CREATE INDEX idx_reddit_media_timestamp ON reddit_media(account_id, timestamp DESC);
|
||||
CREATE INDEX idx_reddit_media_room ON reddit_media(account_id, chat_room_id);
|
||||
CREATE INDEX idx_reddit_media_original_url ON reddit_media(account_id, original_url);
|
||||
`),
|
||||
() => db.exec(`
|
||||
CREATE TABLE IF NOT EXISTS reddit_recipient_account_status (
|
||||
username TEXT PRIMARY KEY COLLATE NOCASE,
|
||||
status TEXT NOT NULL CHECK(status IN ('active', 'suspended', 'deleted')),
|
||||
checked_at INTEGER NOT NULL
|
||||
);
|
||||
CREATE INDEX IF NOT EXISTS idx_reddit_recipient_account_status_due
|
||||
ON reddit_recipient_account_status(checked_at);
|
||||
`),
|
||||
];
|
||||
|
||||
let currentVersion = db.pragma('user_version', { simple: true }) as number;
|
||||
|
||||
Reference in new issue
Block a user