39 lines
2.1 KiB
Plaintext
39 lines
2.1 KiB
Plaintext
def _message_index(message_path: Path) -> dict:
|
|
revision = _database_revision(message_path)
|
|
def build():
|
|
connection = connect_sqlite(str(message_path))
|
|
try:
|
|
columns = _columns(connection, "message_table")
|
|
result = {"columns": columns, "total_messages": 0, "conversations": {},
|
|
"ordered": [], "previews": {}, "revision": revision}
|
|
if not {"conversation_id", "send_time"}.issubset(columns):
|
|
return result
|
|
result["total_messages"] = _message_counts(message_path)[0]
|
|
# Sort/group inside SQLite instead of allocating one Python tuple
|
|
# per message. Only compact row IDs and one timestamp per chat are
|
|
# retained; message bodies are fetched for the visible page only.
|
|
cursor = connection.execute(
|
|
"SELECT conversation_id,GROUP_CONCAT(message_rowid),MAX(message_time) "
|
|
"FROM (SELECT rowid AS message_rowid,conversation_id,CAST(send_time AS REAL) AS message_time "
|
|
"FROM message_table WHERE conversation_id IS NOT NULL AND conversation_id<>'' "
|
|
"AND conversation_id NOT LIKE 'Y:%' "
|
|
"ORDER BY conversation_id,CAST(send_time AS REAL),rowid) GROUP BY conversation_id"
|
|
)
|
|
for conversation_id, encoded_rows, timestamp in cursor:
|
|
row_ids = array("q", map(int, str(encoded_rows).split(",")))
|
|
timestamp = float(timestamp or 0)
|
|
if not math.isfinite(timestamp):
|
|
timestamp = 0.0
|
|
result["conversations"][str(conversation_id)] = {
|
|
"rows": row_ids, "lastTimestamp": timestamp, "lastRowId": row_ids[-1],
|
|
}
|
|
result["ordered"] = sorted(result["conversations"], key=lambda key: (
|
|
result["conversations"][key]["lastTimestamp"],
|
|
result["conversations"][key]["lastRowId"], key), reverse=True)
|
|
return result
|
|
finally:
|
|
connection.close()
|
|
return _cached("index", revision[0], revision, build)
|
|
|
|
|