def _conversation_rows( message_path: Path, account: str, users: dict[str, str], conversations: dict[str, str], query: str, limit: int, offset: int = 0, ) -> tuple[list[dict[str, Any]], int, int]: index = _message_index(message_path) ordered = index["ordered"] needle = str(query or "").strip().casefold() offset = max(0, int(offset)) candidates = ordered if needle else ordered[offset:offset + limit] _ensure_previews(message_path, index, candidates) result = [] matching = 0 for conversation_id in candidates: name = _conversation_name(account, conversation_id, users, conversations) preview = index["previews"][conversation_id] if needle and needle not in f"{name} {conversation_id} {preview['text']}".casefold(): continue if needle: matching += 1 if matching <= offset: continue group = index["conversations"][conversation_id] result.append({ "id": conversation_id, "name": name, "kind": _conversation_kind(conversation_id), "messageCount": len(group["rows"]), "lastTime": _format_time(group["lastTimestamp"]), "lastTimestamp": group["lastTimestamp"], "preview": preview["text"][:160], "lastDirection": "发出" if preview["sender"] == account else "收到", }) if len(result) >= limit: break return result, len(ordered), index["total_messages"] def _messages( message_path: Path, account: str, conversation_id: str, users: dict[str, str], limit: int, offset: int = 0, ) -> list[dict[str, Any]]: if not conversation_id: return [] index = _message_index(message_path) rows = (index["conversations"].get(conversation_id) or {}).get("rows", []) offset = max(0, int(offset)) limit = max(1, min(int(limit), 1000)) end = max(0, len(rows) - offset) row_ids = list(rows[max(0, end - limit):end]) revision = index["revision"] key = (revision[0], conversation_id, limit, offset) records = _cached("messages", key, revision, lambda: _read_message_rows(message_path, index, row_ids)) result = [] for row_id in row_ids: item = records.get(row_id) if item is None: continue sender_id = str(item.get("sender_id") or "") try: timestamp = float(item.get("send_time") or 0) if not math.isfinite(timestamp): timestamp = 0.0 except (ValueError, TypeError, OverflowError): timestamp = 0.0 result.append({ "id": str(item.get("server_id") or item.get("client_id") or ""), "senderId": sender_id, "sender": users.get(sender_id) or ("当前账号" if sender_id == account else sender_id), "direction": "outbound" if sender_id == account else "inbound", "time": _format_time(timestamp), "timestamp": timestamp, "type": get_msg_type_name(item.get("content_type")), "content": _content_label(item.get("content"), item.get("content_type")), }) return result