Кэширование ID пользователей из чатов (на 24 часа)
This commit is contained in:
@@ -190,7 +190,6 @@ extension ApiServiceAuth on ApiService {
|
||||
authToken = currentAccount.token;
|
||||
userId = currentAccount.userId;
|
||||
|
||||
_messageCache.clear();
|
||||
_messageQueue.clear();
|
||||
_lastChatsPayload = null;
|
||||
_chatsFetchedInThisSession = false;
|
||||
@@ -257,4 +256,3 @@ extension ApiServiceAuth on ApiService {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,119 @@
|
||||
part of 'api_service.dart';
|
||||
|
||||
extension ApiServiceChats on ApiService {
|
||||
Future<void> _sendAuthRequestAfterHandshake() async {
|
||||
if (authToken == null) {
|
||||
print("Токен не найден, пропускаем автоматическую авторизацию");
|
||||
return;
|
||||
}
|
||||
|
||||
if (_chatsFetchedInThisSession) {
|
||||
print("Авторизация уже выполнена в этой сессии, пропускаем");
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
await _ensureCacheServicesInitialized();
|
||||
|
||||
final prefs = await SharedPreferences.getInstance();
|
||||
final deviceId =
|
||||
prefs.getString('spoof_deviceid') ?? generateRandomDeviceId();
|
||||
|
||||
if (prefs.getString('spoof_deviceid') == null) {
|
||||
await prefs.setString('spoof_deviceid', deviceId);
|
||||
}
|
||||
|
||||
final payload = {
|
||||
"chatsCount": 100,
|
||||
"chatsSync": 0,
|
||||
"contactsSync": 0,
|
||||
"draftsSync": 0,
|
||||
"interactive": true,
|
||||
"presenceSync": 0,
|
||||
"token": authToken,
|
||||
};
|
||||
|
||||
if (userId != null) {
|
||||
payload["userId"] = userId;
|
||||
}
|
||||
|
||||
print("Автоматически отправляем opcode 19 для авторизации...");
|
||||
final int chatSeq = _sendMessage(19, payload);
|
||||
final chatResponse = await messages.firstWhere(
|
||||
(msg) => msg['seq'] == chatSeq,
|
||||
);
|
||||
|
||||
if (chatResponse['cmd'] == 1) {
|
||||
print("✅ Авторизация (opcode 19) успешна. Сессия ГОТОВА.");
|
||||
_isSessionReady = true;
|
||||
|
||||
_connectionStatusController.add("ready");
|
||||
_updateConnectionState(
|
||||
conn_state.ConnectionState.ready,
|
||||
message: 'Авторизация успешна',
|
||||
);
|
||||
|
||||
final profile = chatResponse['payload']?['profile'];
|
||||
final contactProfile = profile?['contact'];
|
||||
|
||||
if (contactProfile != null && contactProfile['id'] != null) {
|
||||
print(
|
||||
"[_sendAuthRequestAfterHandshake] ✅ Профиль и ID пользователя найдены. ID: ${contactProfile['id']}. ЗАПУСКАЕМ АНАЛИТИКУ.",
|
||||
);
|
||||
_userId = contactProfile['id'];
|
||||
_sessionId = DateTime.now().millisecondsSinceEpoch;
|
||||
_lastActionTime = _sessionId;
|
||||
|
||||
sendNavEvent('COLD_START');
|
||||
|
||||
_sendInitialSetupRequests();
|
||||
}
|
||||
|
||||
if (_onlineCompleter != null && !_onlineCompleter!.isCompleted) {
|
||||
_onlineCompleter!.complete();
|
||||
}
|
||||
|
||||
final chatListJson = chatResponse['payload']?['chats'] ?? [];
|
||||
final contactListJson = chatResponse['payload']?['contacts'] ?? [];
|
||||
final presence = chatResponse['payload']?['presence'];
|
||||
final config = chatResponse['payload']?['config'];
|
||||
|
||||
if (presence != null) {
|
||||
updatePresenceData(presence);
|
||||
}
|
||||
|
||||
if (config != null) {
|
||||
_processServerPrivacyConfig(config);
|
||||
}
|
||||
|
||||
final result = {
|
||||
'chats': chatListJson,
|
||||
'contacts': contactListJson,
|
||||
'profile': profile,
|
||||
'presence': presence,
|
||||
'config': config,
|
||||
};
|
||||
_lastChatsPayload = result;
|
||||
|
||||
final contacts = contactListJson
|
||||
.map((json) => Contact.fromJson(json))
|
||||
.toList();
|
||||
updateContactCache(contacts);
|
||||
_lastChatsAt = DateTime.now();
|
||||
_preloadContactAvatars(contacts);
|
||||
unawaited(
|
||||
_chatCacheService.cacheChats(
|
||||
chatListJson.cast<Map<String, dynamic>>(),
|
||||
),
|
||||
);
|
||||
unawaited(_chatCacheService.cacheContacts(contacts));
|
||||
_chatsFetchedInThisSession = true;
|
||||
}
|
||||
} catch (e) {
|
||||
print("Ошибка при автоматической авторизации: $e");
|
||||
}
|
||||
}
|
||||
|
||||
void createGroup(String name, List<int> participantIds) {
|
||||
final payload = {"name": name, "participantIds": participantIds};
|
||||
_sendMessage(48, payload);
|
||||
@@ -357,22 +470,29 @@ extension ApiServiceChats on ApiService {
|
||||
return result;
|
||||
}
|
||||
|
||||
final contactIds = <int>{};
|
||||
for (var chatJson in chatListJson) {
|
||||
final participants = chatJson['participants'] as Map<String, dynamic>;
|
||||
contactIds.addAll(participants.keys.map((id) => int.parse(id)));
|
||||
List<dynamic> contactListJson =
|
||||
chatResponse['payload']?['contacts'] ?? [];
|
||||
|
||||
if (contactListJson.isEmpty) {
|
||||
final contactIds = <int>{};
|
||||
for (var chatJson in chatListJson) {
|
||||
final participants =
|
||||
chatJson['participants'] as Map<String, dynamic>? ?? {};
|
||||
contactIds.addAll(participants.keys.map((id) => int.parse(id)));
|
||||
}
|
||||
|
||||
if (contactIds.isNotEmpty) {
|
||||
final int contactSeq = _sendMessage(32, {
|
||||
"contactIds": contactIds.toList(),
|
||||
});
|
||||
final contactResponse = await messages.firstWhere(
|
||||
(msg) => msg['seq'] == contactSeq,
|
||||
);
|
||||
|
||||
contactListJson = contactResponse['payload']?['contacts'] ?? [];
|
||||
}
|
||||
}
|
||||
|
||||
final int contactSeq = _sendMessage(32, {
|
||||
"contactIds": contactIds.toList(),
|
||||
});
|
||||
final contactResponse = await messages.firstWhere(
|
||||
(msg) => msg['seq'] == contactSeq,
|
||||
);
|
||||
|
||||
final List<dynamic> contactListJson =
|
||||
contactResponse['payload']?['contacts'] ?? [];
|
||||
|
||||
if (presence != null) {
|
||||
updatePresenceData(presence);
|
||||
}
|
||||
|
||||
@@ -363,11 +363,15 @@ extension ApiServiceConnection on ApiService {
|
||||
);
|
||||
_startHealthMonitoring();
|
||||
|
||||
if (_onlineCompleter != null && !_onlineCompleter!.isCompleted) {
|
||||
_onlineCompleter!.complete();
|
||||
}
|
||||
_startPinging();
|
||||
_processMessageQueue();
|
||||
|
||||
if (authToken != null && !_chatsFetchedInThisSession) {
|
||||
print(
|
||||
"Токен найден, автоматически запускаем авторизацию (opcode 19)...",
|
||||
);
|
||||
unawaited(_sendAuthRequestAfterHandshake());
|
||||
}
|
||||
}
|
||||
|
||||
if (decodedMessage is Map && decodedMessage['cmd'] == 3) {
|
||||
@@ -670,8 +674,6 @@ extension ApiServiceConnection on ApiService {
|
||||
_onlineCompleter = Completer<void>();
|
||||
_chatsFetchedInThisSession = false;
|
||||
|
||||
clearAllCaches();
|
||||
|
||||
_currentUrlIndex = 0;
|
||||
|
||||
_reconnectDelaySeconds = (_reconnectDelaySeconds * 2).clamp(1, 30);
|
||||
@@ -721,7 +723,6 @@ extension ApiServiceConnection on ApiService {
|
||||
_currentUrlIndex = 0;
|
||||
_onlineCompleter = Completer<void>();
|
||||
|
||||
clearAllCaches();
|
||||
_messageQueue.clear();
|
||||
_presenceData.clear();
|
||||
|
||||
|
||||
@@ -105,6 +105,20 @@ extension ApiServiceContacts on ApiService {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!_isSessionOnline || !_isSessionReady) {
|
||||
print(
|
||||
'ApiService: сессия еще не готова для запроса заблокированных контактов, ждем...',
|
||||
);
|
||||
await waitUntilOnline();
|
||||
|
||||
if (!_isSessionReady) {
|
||||
print(
|
||||
'ApiService: сессия все еще не готова после ожидания, отменяем запрос',
|
||||
);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
_isLoadingBlockedContacts = true;
|
||||
print('ApiService: запрашиваем заблокированные контакты');
|
||||
_sendMessage(36, {'status': 'BLOCKED', 'count': 100, 'from': 0});
|
||||
@@ -278,12 +292,23 @@ extension ApiServiceContacts on ApiService {
|
||||
|
||||
Future<List<Contact>> fetchContactsByIds(List<int> contactIds) async {
|
||||
if (contactIds.isEmpty) {
|
||||
print(
|
||||
'⚠️ [fetchContactsByIds] Пустой список contactIds - пропускаем запрос',
|
||||
);
|
||||
return [];
|
||||
}
|
||||
|
||||
print('Запрашиваем данные для ${contactIds.length} контактов...');
|
||||
print(
|
||||
'📡 [fetchContactsByIds] Запрашиваем данные для ${contactIds.length} контактов...',
|
||||
);
|
||||
print(
|
||||
'📡 [fetchContactsByIds] IDs: ${contactIds.take(10).join(', ')}${contactIds.length > 10 ? '...' : ''}',
|
||||
);
|
||||
try {
|
||||
final int contactSeq = _sendMessage(32, {"contactIds": contactIds});
|
||||
print(
|
||||
'📤 [fetchContactsByIds] Отправлен опкод 32 с seq=$contactSeq и ${contactIds.length} ID',
|
||||
);
|
||||
|
||||
final contactResponse = await messages
|
||||
.firstWhere((msg) => msg['seq'] == contactSeq)
|
||||
@@ -291,7 +316,7 @@ extension ApiServiceContacts on ApiService {
|
||||
|
||||
if (contactResponse['cmd'] == 3) {
|
||||
print(
|
||||
"Ошибка при получении контактов по ID: ${contactResponse['payload']}",
|
||||
"❌ [fetchContactsByIds] Ошибка при получении контактов: ${contactResponse['payload']}",
|
||||
);
|
||||
return [];
|
||||
}
|
||||
@@ -302,13 +327,29 @@ extension ApiServiceContacts on ApiService {
|
||||
.map((json) => Contact.fromJson(json))
|
||||
.toList();
|
||||
|
||||
print(
|
||||
'📦 [fetchContactsByIds] Получено ${contacts.length} контактов из ${contactIds.length} запрошенных',
|
||||
);
|
||||
|
||||
if (contacts.length < contactIds.length) {
|
||||
final receivedIds = contacts.map((c) => c.id).toSet();
|
||||
final missingIds = contactIds
|
||||
.where((id) => !receivedIds.contains(id))
|
||||
.toList();
|
||||
print(
|
||||
'⚠️ [fetchContactsByIds] Отсутствуют ${missingIds.length} контактов: ${missingIds.take(5).join(', ')}${missingIds.length > 5 ? '...' : ''}',
|
||||
);
|
||||
}
|
||||
|
||||
for (final contact in contacts) {
|
||||
_contactCache[contact.id] = contact;
|
||||
}
|
||||
print("Получены и закэшированы данные для ${contacts.length} контактов.");
|
||||
print(
|
||||
"✅ [fetchContactsByIds] Закэшированы данные для ${contacts.length} контактов",
|
||||
);
|
||||
return contacts;
|
||||
} catch (e) {
|
||||
print('Исключение при получении контактов по ID: $e');
|
||||
print('❌ [fetchContactsByIds] Исключение при получении контактов: $e');
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user