fix: prevent duplicate DMs at creation time, clean up corrupted read states

Replace the unreliable client-side DM dedup loop in populateFromReady with
a creation-time guard (findExistingDmForUser) that checks all instances
before opening a new DM. Guards added to FriendsPage, NewDmModal, and
UserProfilePopout.

Also fixes: corrupted read_states from temp_ optimistic message IDs (server
migration + client-side validation), federation-aware closeDm/addDmMember
API routing, isSelf-based DM member filtering in sidebar/header, and WS
event error isolation.
This commit is contained in:
Jannis Braun
2026-03-04 20:04:15 +01:00
parent 33ae79bae9
commit 65e9ee5203
12 changed files with 108 additions and 12 deletions
+13
View File
@@ -138,6 +138,9 @@ export function runMigrations(db: Database.Database): void {
// ─── Admin flag: ensure at least one admin exists (first registered user) ──
migrateFirstAdmin(db);
// ─── Clean up corrupted read_states (temp_ IDs leaked from optimistic messages) ─
migrateCorruptedReadStates(db);
console.log('Migrations complete.');
}
@@ -236,6 +239,16 @@ function migrateEveryoneRoles(db: Database.Database): void {
}
}
/** Delete corrupted read_states rows where last_read_message_id is not a valid snowflake (numeric string) */
function migrateCorruptedReadStates(db: Database.Database): void {
const deleted = db.prepare(
"DELETE FROM read_states WHERE last_read_message_id NOT GLOB '[0-9]*' OR last_read_message_id GLOB '*[^0-9]*'"
).run();
if (deleted.changes > 0) {
console.log(`Migrating: Cleaned up ${deleted.changes} corrupted read_states rows`);
}
}
/**
* Rename non-namespaced replicated users: e.g. "test" → "test@nova.ddns.net"
* Frees plain usernames for native user creation and makes all federated users