121 lines
4.1 KiB
Python
121 lines
4.1 KiB
Python
from .database import Database
|
|
|
|
|
|
class MessageHandler:
|
|
def __init__(self, db: Database):
|
|
self.db = db
|
|
|
|
def get_conversation_messages(
|
|
self,
|
|
local_hash,
|
|
destination_hash,
|
|
limit=100,
|
|
offset=0,
|
|
after_id=None,
|
|
before_id=None,
|
|
):
|
|
query = """
|
|
SELECT * FROM lxmf_messages
|
|
WHERE peer_hash = ?
|
|
"""
|
|
params = [destination_hash]
|
|
|
|
if after_id:
|
|
query += " AND id > ?"
|
|
params.append(after_id)
|
|
if before_id:
|
|
query += " AND id < ?"
|
|
params.append(before_id)
|
|
|
|
query += " ORDER BY id DESC LIMIT ? OFFSET ?"
|
|
params.extend([limit, offset])
|
|
|
|
return self.db.provider.fetchall(query, params)
|
|
|
|
def delete_conversation(self, local_hash, destination_hash):
|
|
query = "DELETE FROM lxmf_messages WHERE peer_hash = ?"
|
|
self.db.provider.execute(query, [destination_hash])
|
|
|
|
def search_messages(self, local_hash, search_term):
|
|
like_term = f"%{search_term}%"
|
|
query = """
|
|
SELECT peer_hash, MAX(timestamp) as max_ts
|
|
FROM lxmf_messages
|
|
WHERE title LIKE ? OR content LIKE ? OR peer_hash LIKE ?
|
|
GROUP BY peer_hash
|
|
"""
|
|
params = [like_term, like_term, like_term]
|
|
return self.db.provider.fetchall(query, params)
|
|
|
|
def get_conversations(
|
|
self,
|
|
local_hash,
|
|
search=None,
|
|
filter_unread=False,
|
|
filter_failed=False,
|
|
filter_has_attachments=False,
|
|
limit=None,
|
|
offset=0,
|
|
):
|
|
# Optimized using peer_hash column and JOINs to avoid N+1 queries
|
|
query = """
|
|
SELECT
|
|
m1.*,
|
|
a.app_data as peer_app_data,
|
|
c.display_name as custom_display_name,
|
|
con.custom_image as contact_image,
|
|
i.icon_name, i.foreground_colour, i.background_colour,
|
|
r.last_read_at,
|
|
(SELECT COUNT(*) FROM lxmf_messages m_failed
|
|
WHERE m_failed.peer_hash = m1.peer_hash AND m_failed.state = 'failed') as failed_count
|
|
FROM lxmf_messages m1
|
|
INNER JOIN (
|
|
SELECT peer_hash, MAX(timestamp) as max_ts
|
|
FROM lxmf_messages
|
|
WHERE peer_hash IS NOT NULL
|
|
GROUP BY peer_hash
|
|
) m2 ON m1.peer_hash = m2.peer_hash AND m1.timestamp = m2.max_ts
|
|
LEFT JOIN announces a ON a.destination_hash = m1.peer_hash
|
|
LEFT JOIN custom_destination_display_names c ON c.destination_hash = m1.peer_hash
|
|
LEFT JOIN contacts con ON con.remote_identity_hash = m1.peer_hash
|
|
LEFT JOIN lxmf_user_icons i ON i.destination_hash = m1.peer_hash
|
|
LEFT JOIN lxmf_conversation_read_state r ON r.destination_hash = m1.peer_hash
|
|
"""
|
|
params = []
|
|
where_clauses = []
|
|
|
|
if filter_unread:
|
|
where_clauses.append(
|
|
"(r.last_read_at IS NULL OR m1.timestamp > strftime('%s', r.last_read_at))"
|
|
)
|
|
|
|
if filter_failed:
|
|
where_clauses.append("m1.state = 'failed'")
|
|
|
|
if filter_has_attachments:
|
|
where_clauses.append(
|
|
"(m1.fields IS NOT NULL AND m1.fields != '{}' AND m1.fields != '')"
|
|
)
|
|
|
|
if search:
|
|
like_term = f"%{search}%"
|
|
# Search in latest message info OR search across ALL messages for this peer
|
|
where_clauses.append("""
|
|
(m1.title LIKE ? OR m1.content LIKE ? OR m1.peer_hash LIKE ? OR c.display_name LIKE ?
|
|
OR m1.peer_hash IN (SELECT peer_hash FROM lxmf_messages WHERE title LIKE ? OR content LIKE ?))
|
|
""")
|
|
params.extend(
|
|
[like_term, like_term, like_term, like_term, like_term, like_term]
|
|
)
|
|
|
|
if where_clauses:
|
|
query += " WHERE " + " AND ".join(where_clauses)
|
|
|
|
query += " GROUP BY m1.peer_hash ORDER BY m1.timestamp DESC"
|
|
|
|
if limit is not None:
|
|
query += " LIMIT ? OFFSET ?"
|
|
params.extend([limit, offset])
|
|
|
|
return self.db.provider.fetchall(query, params)
|