168 lines
5.2 KiB
Dart
168 lines
5.2 KiB
Dart
import 'dart:typed_data';
|
|
|
|
import '../../core/utils/parse.dart';
|
|
import '../../models/attachment.dart';
|
|
import 'messages.dart';
|
|
|
|
class MessageCopy {
|
|
final String text;
|
|
final List<Map<String, dynamic>> elements;
|
|
final List<Map<String, dynamic>> attaches;
|
|
final List<Map<String, dynamic>> wireAttaches;
|
|
|
|
const MessageCopy._({
|
|
required this.text,
|
|
required this.elements,
|
|
required this.attaches,
|
|
required this.wireAttaches,
|
|
});
|
|
|
|
static const _strippedTypes = {'INLINE_KEYBOARD', 'SHARE'};
|
|
|
|
static MessageCopy? of(CachedMessage message) {
|
|
if (message.isControl || message.e2ee != CachedMessage.e2eeNone) {
|
|
return null;
|
|
}
|
|
final source = _contentOf(message);
|
|
final text = source['text']?.toString() ?? '';
|
|
final attaches = <Map<String, dynamic>>[];
|
|
final wireAttaches = <Map<String, dynamic>>[];
|
|
for (final attach in _maps(source['attaches'])) {
|
|
final type = attach['_type']?.toString().toUpperCase();
|
|
if (_strippedTypes.contains(type)) continue;
|
|
final wire = _wireAttach(type, attach);
|
|
if (wire == null) return null;
|
|
attaches.add(attach);
|
|
wireAttaches.add(wire);
|
|
}
|
|
if (text.trim().isEmpty && wireAttaches.isEmpty) return null;
|
|
return MessageCopy._(
|
|
text: text,
|
|
elements: _maps(source['elements']),
|
|
attaches: attaches,
|
|
wireAttaches: wireAttaches,
|
|
);
|
|
}
|
|
|
|
CachedMessage toOutgoing({
|
|
required int accountId,
|
|
required int chatId,
|
|
required String tempId,
|
|
required int time,
|
|
}) {
|
|
final payload = <String, dynamic>{
|
|
'text': text,
|
|
'elements': elements,
|
|
'attaches': attaches,
|
|
};
|
|
final (attachments, isControl) = CachedMessage.parseAttachments(payload);
|
|
return CachedMessage(
|
|
id: tempId,
|
|
accountId: accountId,
|
|
chatId: chatId,
|
|
senderId: accountId,
|
|
text: text,
|
|
time: time,
|
|
status: 'sending',
|
|
payload: payload,
|
|
attachments: attachments,
|
|
isControl: isControl,
|
|
);
|
|
}
|
|
|
|
static Map<String, dynamic> _contentOf(CachedMessage message) {
|
|
final payload = message.payload;
|
|
final link = payload?['link'];
|
|
if (link is Map && link['type']?.toString().toUpperCase() == 'FORWARD') {
|
|
final original = link['message'];
|
|
return original is Map ? Map<String, dynamic>.from(original) : const {};
|
|
}
|
|
return {
|
|
'text': message.text,
|
|
'elements': payload?['elements'],
|
|
'attaches':
|
|
payload?['attaches'] ??
|
|
[
|
|
for (final attachment
|
|
in message.attachments ?? const <MessageAttachment>[])
|
|
attachment.toMap(),
|
|
],
|
|
};
|
|
}
|
|
|
|
static List<Map<String, dynamic>> _maps(Object? raw) => raw is List
|
|
? [
|
|
for (final item in raw.whereType<Map>())
|
|
Map<String, dynamic>.from(item),
|
|
]
|
|
: const [];
|
|
|
|
static Map<String, dynamic>? _wireAttach(
|
|
String? type,
|
|
Map<String, dynamic> attach,
|
|
) {
|
|
switch (type) {
|
|
case 'PHOTO':
|
|
final token = attach['photoToken'];
|
|
if (token == null) return null;
|
|
return {'_type': 'PHOTO', 'photoToken': token};
|
|
case 'VIDEO':
|
|
final token = attach['token'] ?? attach['videoToken'];
|
|
if (token == null) return null;
|
|
if (parseIntOrNull(attach['videoType']) != 1) {
|
|
return {'videoType': 0, '_type': 'VIDEO', 'token': token};
|
|
}
|
|
final thumbhash = attach['thumbhash'];
|
|
return {
|
|
'duration': ?parseIntOrNull(attach['duration']),
|
|
'videoType': 1,
|
|
'_type': 'VIDEO',
|
|
'wave': _wave(attach['wave']),
|
|
'token': token,
|
|
'thumbhash': ?thumbhash,
|
|
};
|
|
case 'AUDIO':
|
|
final token = attach['token'] ?? attach['audioToken'];
|
|
if (token == null) return null;
|
|
return {
|
|
'duration': ?parseIntOrNull(attach['duration']),
|
|
'_type': 'AUDIO',
|
|
'wave': _wave(attach['wave']),
|
|
'token': token,
|
|
};
|
|
case 'FILE':
|
|
final fileId = parseIntOrNull(attach['fileId']);
|
|
if (fileId != null) return {'_type': 'FILE', 'fileId': fileId};
|
|
final token = attach['token'] ?? attach['fileToken'];
|
|
if (token == null) return null;
|
|
return {'_type': 'FILE', 'token': token};
|
|
case 'STICKER':
|
|
final stickerId = parseIntOrNull(attach['stickerId']);
|
|
if (stickerId == null) return null;
|
|
return {'_type': 'STICKER', 'stickerId': stickerId};
|
|
case 'CONTACT':
|
|
final contactId = parseIntOrNull(attach['contactId']);
|
|
if (contactId == null) return null;
|
|
return {'_type': 'CONTACT', 'contactId': contactId};
|
|
case 'LOCATION':
|
|
final latitude = attach['latitude'];
|
|
final longitude = attach['longitude'];
|
|
if (latitude is! num || longitude is! num) return null;
|
|
final zoom = attach['zoom'];
|
|
return {
|
|
'_type': 'LOCATION',
|
|
'latitude': latitude.toDouble(),
|
|
'longitude': longitude.toDouble(),
|
|
'zoom': zoom is num ? zoom.toDouble() : 15.0,
|
|
};
|
|
default:
|
|
return null;
|
|
}
|
|
}
|
|
|
|
static Uint8List _wave(Object? raw) {
|
|
final samples = parseIntList(raw);
|
|
return samples.isEmpty ? Uint8List(80) : Uint8List.fromList(samples);
|
|
}
|
|
}
|