mirror of
https://github.com/MarekWo/mc-webui.git
synced 2026-03-28 17:42:45 +01:00
fix(dm): refresh mc.contacts on approve, DB name fallback, relink orphans
Three fixes for DM sending after contact delete/re-add: 1. approve_contact() now calls ensure_contacts() to refresh mc.contacts so send_dm can find newly added contacts immediately 2. cli.send_dm() falls back to DB name lookup when mc.contacts misses, preventing the contact name from being passed as a pubkey string 3. approve_contact() re-links orphaned DMs (NULL contact_pubkey from ON DELETE SET NULL) back to the re-added contact New DB methods: get_contact_by_name(), relink_orphaned_dms() Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -137,6 +137,15 @@ class Database:
|
||||
).fetchone()
|
||||
return dict(row) if row else None
|
||||
|
||||
def get_contact_by_name(self, name: str) -> Optional[Dict]:
|
||||
"""Find a contact by exact name match."""
|
||||
with self._connect() as conn:
|
||||
row = conn.execute(
|
||||
"SELECT * FROM contacts WHERE name = ? AND length(public_key) = 64 LIMIT 1",
|
||||
(name,)
|
||||
).fetchone()
|
||||
return dict(row) if row else None
|
||||
|
||||
def delete_contact(self, public_key: str) -> bool:
|
||||
with self._connect() as conn:
|
||||
cursor = conn.execute(
|
||||
@@ -373,6 +382,26 @@ class Database:
|
||||
).fetchone()
|
||||
return dict(row) if row else None
|
||||
|
||||
def relink_orphaned_dms(self, public_key: str) -> int:
|
||||
"""Re-link DMs with NULL contact_pubkey back to this contact.
|
||||
|
||||
When a contact is deleted, ON DELETE SET NULL nullifies contact_pubkey.
|
||||
When the contact is re-added, re-link those orphaned DMs.
|
||||
Uses raw_json to match by pubkey_prefix.
|
||||
"""
|
||||
public_key = public_key.lower()
|
||||
prefix = public_key[:12] # Short prefix used in pubkey_prefix field
|
||||
with self._connect() as conn:
|
||||
cursor = conn.execute(
|
||||
"""UPDATE direct_messages SET contact_pubkey = ?
|
||||
WHERE contact_pubkey IS NULL
|
||||
AND (raw_json LIKE ? OR raw_json IS NULL)""",
|
||||
(public_key, f'%{prefix}%')
|
||||
)
|
||||
if cursor.rowcount > 0:
|
||||
logger.info(f"Re-linked {cursor.rowcount} orphaned DMs to {public_key[:12]}...")
|
||||
return cursor.rowcount
|
||||
|
||||
def find_dm_duplicate(self, contact_pubkey: str, content: str,
|
||||
sender_timestamp: int = None,
|
||||
window_seconds: int = 300) -> Optional[Dict]:
|
||||
|
||||
@@ -1167,6 +1167,10 @@ class DeviceManager:
|
||||
return {'success': False, 'error': 'Contact not in pending list'}
|
||||
|
||||
self.execute(self.mc.commands.add_contact(contact))
|
||||
|
||||
# Refresh mc.contacts so send_dm can find the new contact
|
||||
self.execute(self.mc.ensure_contacts(follow=True))
|
||||
|
||||
last_adv = contact.get('last_advert')
|
||||
last_advert_val = (
|
||||
str(int(last_adv))
|
||||
@@ -1182,6 +1186,9 @@ class DeviceManager:
|
||||
last_advert=last_advert_val,
|
||||
source='device',
|
||||
)
|
||||
# Re-link orphaned DMs (from previous ON DELETE SET NULL)
|
||||
self.db.relink_orphaned_dms(pubkey)
|
||||
|
||||
# Remove from pending list after successful approval
|
||||
self.mc.pending_contacts.pop(pubkey, None)
|
||||
return {'success': True, 'message': 'Contact approved'}
|
||||
|
||||
@@ -376,15 +376,25 @@ def send_dm(recipient: str, text: str) -> Tuple[bool, Dict]:
|
||||
|
||||
try:
|
||||
dm = _get_dm()
|
||||
# Try to find contact by name first
|
||||
recipient = recipient.strip()
|
||||
|
||||
# Try to find contact by name in mc.contacts (in-memory)
|
||||
contact = None
|
||||
if dm.mc:
|
||||
contact = dm.mc.get_contact_by_name(recipient.strip())
|
||||
contact = dm.mc.get_contact_by_name(recipient)
|
||||
|
||||
if contact:
|
||||
pubkey = contact.get('public_key', recipient)
|
||||
elif len(recipient) >= 12 and all(c in '0123456789abcdef' for c in recipient.lower()):
|
||||
# Looks like a pubkey/prefix already
|
||||
pubkey = recipient
|
||||
else:
|
||||
pubkey = recipient.strip()
|
||||
# Name not in mc.contacts — try DB lookup
|
||||
db_contact = dm.db.get_contact_by_name(recipient)
|
||||
if db_contact:
|
||||
pubkey = db_contact['public_key']
|
||||
else:
|
||||
pubkey = recipient
|
||||
|
||||
result = dm.send_dm(pubkey, text.strip())
|
||||
return result['success'], result
|
||||
|
||||
Reference in New Issue
Block a user