from urllib.parse import urlparse def _safe_log(log_func, context, message): if not log_func: return try: log_func(context, message) except TypeError: log_func(f"{context}: {message}") def resolve_user_ids(vk_call_with_retry, vk_api, links): resolved_ids = [] failed_links = [] for link in links: try: path = urlparse(link).path screen_name = path.split("/")[-1] if path else "" if not screen_name and len(path.split("/")) > 1: screen_name = path.split("/")[-2] if not screen_name: failed_links.append((link, None)) continue resolved_object = vk_call_with_retry(vk_api.utils.resolveScreenName, screen_name=screen_name) if resolved_object and resolved_object.get("type") == "user": resolved_ids.append(resolved_object["object_id"]) else: failed_links.append((link, None)) except Exception as e: failed_links.append((link, e)) return resolved_ids, failed_links def load_chat_conversations(vk_call_with_retry, vk_api, log_func=None): conversations = [] start_from = None seen_start_tokens = set() total_count = None page_num = 0 while True: params = {"count": 200, "filter": "all"} if start_from: if start_from in seen_start_tokens: _safe_log(log_func, "load_chats_page", f"stop duplicate next_from={start_from}") break params["start_from"] = start_from seen_start_tokens.add(start_from) response = vk_call_with_retry(vk_api.messages.getConversations, **params) page_num += 1 if total_count is None: total_count = response.get("count") page_items = response.get("items", []) _safe_log( log_func, "load_chats_page", f"page={page_num} items={len(page_items)} next_from={response.get('next_from')} total={total_count}", ) if not page_items: break conversations.extend(page_items) start_from = response.get("next_from") if not start_from: break if total_count is not None and total_count > len(conversations): _safe_log( log_func, "load_chats_fallback", f"start offset pagination total={total_count} current={len(conversations)}", ) seen_keys = set() for conv in conversations: peer = (conv.get("conversation") or {}).get("peer", {}) key = (peer.get("type"), peer.get("id") or peer.get("local_id")) seen_keys.add(key) offset = len(conversations) safety_pages = 0 while offset < total_count: params = {"count": 200, "filter": "all", "offset": offset} response = vk_call_with_retry(vk_api.messages.getConversations, **params) page_items = response.get("items", []) _safe_log( log_func, "load_chats_fallback", f"offset={offset} items={len(page_items)} total={response.get('count')}", ) if not page_items: break for item in page_items: peer = (item.get("conversation") or {}).get("peer", {}) key = (peer.get("type"), peer.get("id") or peer.get("local_id")) if key in seen_keys: continue seen_keys.add(key) conversations.append(item) offset += len(page_items) safety_pages += 1 if safety_pages > 50: _safe_log(log_func, "load_chats_fallback", "stop safety_pages>50") break return conversations