FUCKING REFACTOR

This commit is contained in:
ivan2282
2025-11-19 18:45:44 +03:00
parent 2d11f1cba2
commit 575c43ce63
41 changed files with 2915 additions and 2910 deletions

View File

@@ -0,0 +1,371 @@
part of 'api_service.dart';
extension ApiServiceMedia on ApiService {
void updateProfileText(
String firstName,
String lastName,
String description,
) {
final payload = {
"firstName": firstName,
"lastName": lastName,
"description": description,
};
_sendMessage(16, payload);
}
Future<void> updateProfilePhoto(String firstName, String lastName) async {
try {
final picker = ImagePicker();
final XFile? image = await picker.pickImage(source: ImageSource.gallery);
if (image == null) return;
print("Запрашиваем URL для загрузки фото...");
final int seq = _sendMessage(80, {"count": 1});
final response = await messages.firstWhere((msg) => msg['seq'] == seq);
final String uploadUrl = response['payload']['url'];
print("URL получен: $uploadUrl");
print("Загружаем фото на сервер...");
var request = http.MultipartRequest('POST', Uri.parse(uploadUrl));
request.files.add(await http.MultipartFile.fromPath('file', image.path));
var streamedResponse = await request.send();
var httpResponse = await http.Response.fromStream(streamedResponse);
if (httpResponse.statusCode != 200) {
throw Exception("Ошибка загрузки фото: ${httpResponse.body}");
}
final uploadResult = jsonDecode(httpResponse.body);
final String photoToken = uploadResult['photos'].values.first['token'];
print("Фото загружено, получен токен: $photoToken");
print("Привязываем фото к профилю...");
final payload = {
"firstName": firstName,
"lastName": lastName,
"photoToken": photoToken,
"avatarType": "USER_AVATAR",
};
_sendMessage(16, payload);
print("Запрос на смену аватара отправлен.");
} catch (e) {
print("!!! Ошибка в процессе смены аватара: $e");
}
}
Future<void> sendPhotoMessage(
int chatId, {
String? localPath,
String? caption,
int? cidOverride,
int? senderId,
}) async {
try {
XFile? image;
if (localPath != null) {
image = XFile(localPath);
} else {
final picker = ImagePicker();
image = await picker.pickImage(source: ImageSource.gallery);
if (image == null) return;
}
await waitUntilOnline();
final int seq80 = _sendMessage(80, {"count": 1});
final resp80 = await messages.firstWhere((m) => m['seq'] == seq80);
final String uploadUrl = resp80['payload']['url'];
var request = http.MultipartRequest('POST', Uri.parse(uploadUrl));
request.files.add(await http.MultipartFile.fromPath('file', image.path));
var streamed = await request.send();
var httpResp = await http.Response.fromStream(streamed);
if (httpResp.statusCode != 200) {
throw Exception(
'Ошибка загрузки фото: ${httpResp.statusCode} ${httpResp.body}',
);
}
final uploadJson = jsonDecode(httpResp.body) as Map<String, dynamic>;
final Map photos = uploadJson['photos'] as Map;
if (photos.isEmpty) throw Exception('Не получен токен фото');
final String photoToken = (photos.values.first as Map)['token'];
final int cid = cidOverride ?? DateTime.now().millisecondsSinceEpoch;
final payload = {
"chatId": chatId,
"message": {
"text": caption?.trim() ?? "",
"cid": cid,
"elements": [],
"attaches": [
{"_type": "PHOTO", "photoToken": photoToken},
],
},
"notify": true,
};
clearChatsCache();
if (localPath != null) {
_emitLocal({
'ver': 11,
'cmd': 1,
'seq': -1,
'opcode': 128,
'payload': {
'chatId': chatId,
'message': {
'id': 'local_$cid',
'sender': senderId ?? 0,
'time': DateTime.now().millisecondsSinceEpoch,
'text': caption?.trim() ?? '',
'type': 'USER',
'cid': cid,
'attaches': [
{'_type': 'PHOTO', 'url': 'file://$localPath'},
],
},
},
});
}
_sendMessage(64, payload);
} catch (e) {
print('Ошибка отправки фото-сообщения: $e');
}
}
Future<void> sendPhotoMessages(
int chatId, {
required List<String> localPaths,
String? caption,
int? senderId,
}) async {
if (localPaths.isEmpty) return;
try {
await waitUntilOnline();
final int cid = DateTime.now().millisecondsSinceEpoch;
_emitLocal({
'ver': 11,
'cmd': 1,
'seq': -1,
'opcode': 128,
'payload': {
'chatId': chatId,
'message': {
'id': 'local_$cid',
'sender': senderId ?? 0,
'time': DateTime.now().millisecondsSinceEpoch,
'text': caption?.trim() ?? '',
'type': 'USER',
'cid': cid,
'attaches': [
for (final p in localPaths)
{'_type': 'PHOTO', 'url': 'file://$p'},
],
},
},
});
final List<Map<String, String>> photoTokens = [];
for (final path in localPaths) {
final int seq80 = _sendMessage(80, {"count": 1});
final resp80 = await messages.firstWhere((m) => m['seq'] == seq80);
final String uploadUrl = resp80['payload']['url'];
var request = http.MultipartRequest('POST', Uri.parse(uploadUrl));
request.files.add(await http.MultipartFile.fromPath('file', path));
var streamed = await request.send();
var httpResp = await http.Response.fromStream(streamed);
if (httpResp.statusCode != 200) {
throw Exception(
'Ошибка загрузки фото: ${httpResp.statusCode} ${httpResp.body}',
);
}
final uploadJson = jsonDecode(httpResp.body) as Map<String, dynamic>;
final Map photos = uploadJson['photos'] as Map;
if (photos.isEmpty) throw Exception('Не получен токен фото');
final String photoToken = (photos.values.first as Map)['token'];
photoTokens.add({"token": photoToken});
}
final payload = {
"chatId": chatId,
"message": {
"text": caption?.trim() ?? "",
"cid": cid,
"elements": [],
"attaches": [
for (final t in photoTokens)
{"_type": "PHOTO", "photoToken": t["token"]},
],
},
"notify": true,
};
clearChatsCache();
_sendMessage(64, payload);
} catch (e) {
print('Ошибка отправки фото-сообщений: $e');
}
}
Future<void> sendFileMessage(
int chatId, {
String? caption,
int? senderId,
}) async {
try {
FilePickerResult? result = await FilePicker.platform.pickFiles(
type: FileType.any,
);
if (result == null || result.files.single.path == null) {
print("Выбор файла отменен");
return;
}
final String filePath = result.files.single.path!;
final String fileName = result.files.single.name;
final int fileSize = result.files.single.size;
await waitUntilOnline();
final int seq87 = _sendMessage(87, {"count": 1});
final resp87 = await messages.firstWhere((m) => m['seq'] == seq87);
if (resp87['payload'] == null ||
resp87['payload']['info'] == null ||
(resp87['payload']['info'] as List).isEmpty) {
throw Exception('Неверный ответ на Opcode 87: отсутствует "info"');
}
final uploadInfo = (resp87['payload']['info'] as List).first;
final String uploadUrl = uploadInfo['url'];
final int fileId = uploadInfo['fileId'];
print('Получен fileId: $fileId и URL: $uploadUrl');
var request = http.MultipartRequest('POST', Uri.parse(uploadUrl));
request.files.add(await http.MultipartFile.fromPath('file', filePath));
var streamed = await request.send();
var httpResp = await http.Response.fromStream(streamed);
if (httpResp.statusCode != 200) {
throw Exception(
'Ошибка загрузки файла: ${httpResp.statusCode} ${httpResp.body}',
);
}
print('Файл успешно загружен на сервер.');
final int cid = DateTime.now().millisecondsSinceEpoch;
final payload = {
"chatId": chatId,
"message": {
"text": caption?.trim() ?? "",
"cid": cid,
"elements": [],
"attaches": [
{"_type": "FILE", "fileId": fileId},
],
},
"notify": true,
};
clearChatsCache();
_emitLocal({
'ver': 11,
'cmd': 1,
'seq': -1,
'opcode': 128,
'payload': {
'chatId': chatId,
'message': {
'id': 'local_$cid',
'sender': senderId ?? 0,
'time': DateTime.now().millisecondsSinceEpoch,
'text': caption?.trim() ?? '',
'type': 'USER',
'cid': cid,
'attaches': [
{
'_type': 'FILE',
'name': fileName,
'size': fileSize,
'url': 'file://$filePath',
},
],
},
},
});
_sendMessage(64, payload);
print('Сообщение о файле (Opcode 64) отправлено.');
} catch (e) {
print('Ошибка отправки файла: $e');
}
}
Future<String> getVideoUrl(int videoId, int chatId, String messageId) async {
await waitUntilOnline();
final payload = {
"videoId": videoId,
"chatId": chatId,
"messageId": messageId,
};
final int seq = _sendMessage(83, payload);
print('Запрашиваем URL для videoId: $videoId (seq: $seq)');
try {
final response = await messages
.firstWhere((msg) => msg['seq'] == seq && msg['opcode'] == 83)
.timeout(const Duration(seconds: 15));
if (response['cmd'] == 3) {
throw Exception(
'Ошибка получения URL видео: ${response['payload']?['message']}',
);
}
final videoPayload = response['payload'] as Map<String, dynamic>?;
if (videoPayload == null) {
throw Exception('Получен пустой payload для видео');
}
String? videoUrl =
videoPayload['MP4_720'] as String? ??
videoPayload['MP4_480'] as String? ??
videoPayload['MP4_1080'] as String? ??
videoPayload['MP4_360'] as String?;
if (videoUrl == null) {
final mp4Key = videoPayload.keys.firstWhere(
(k) => k.startsWith('MP4_'),
orElse: () => '',
);
if (mp4Key.isNotEmpty) {
videoUrl = videoPayload[mp4Key] as String?;
}
}
if (videoUrl != null) {
print('URL для videoId: $videoId успешно получен.');
return videoUrl;
} else {
throw Exception('Не найден ни один MP4 URL в ответе');
}
} on TimeoutException {
print('Таймаут ожидания URL для videoId: $videoId');
throw Exception('Сервер не ответил на запрос видео вовремя');
} catch (e) {
print('Ошибка в getVideoUrl: $e');
rethrow;
}
}
}