twonly-app/lib/src/services/api/client2client/media.c2c.dart

174 lines
5.9 KiB
Dart

import 'dart:async';
import 'package:drift/drift.dart';
import 'package:twonly/globals.dart';
import 'package:twonly/src/database/tables/mediafiles.table.dart';
import 'package:twonly/src/database/tables/messages.table.dart';
import 'package:twonly/src/database/twonly.db.dart';
import 'package:twonly/src/model/protobuf/client/generated/messages.pb.dart';
import 'package:twonly/src/services/api/mediafiles/download.service.dart';
import 'package:twonly/src/services/api/utils.dart';
import 'package:twonly/src/services/mediafiles/mediafile.service.dart';
import 'package:twonly/src/utils/log.dart';
Future<void> handleMedia(
int fromUserId,
String groupId,
EncryptedContent_Media media,
) async {
Log.info(
'Got a media message: ${media.senderMessageId} from $groupId with type ${media.type}',
);
late MediaType mediaType;
switch (media.type) {
case EncryptedContent_Media_Type.REUPLOAD:
final message = await twonlyDB.messagesDao
.getMessageById(media.senderMessageId)
.getSingleOrNull();
if (message == null ||
message.senderId != fromUserId ||
message.mediaId == null) {
return;
}
// in case there was already a downloaded file delete it...
final mediaService = await MediaFileService.fromMediaId(message.mediaId!);
if (mediaService != null) {
mediaService.tempPath.deleteSync();
}
await twonlyDB.mediaFilesDao.updateMedia(
message.mediaId!,
MediaFilesCompanion(
downloadState: const Value(DownloadState.pending),
downloadToken: Value(Uint8List.fromList(media.downloadToken)),
encryptionKey: Value(Uint8List.fromList(media.encryptionKey)),
encryptionMac: Value(Uint8List.fromList(media.encryptionMac)),
encryptionNonce: Value(Uint8List.fromList(media.encryptionNonce)),
),
);
final mediaFile =
await twonlyDB.mediaFilesDao.getMediaFileById(message.mediaId!);
if (mediaFile != null) {
unawaited(startDownloadMedia(mediaFile, false));
}
return;
case EncryptedContent_Media_Type.IMAGE:
mediaType = MediaType.image;
case EncryptedContent_Media_Type.VIDEO:
mediaType = MediaType.video;
case EncryptedContent_Media_Type.GIF:
mediaType = MediaType.gif;
case EncryptedContent_Media_Type.AUDIO:
mediaType = MediaType.audio;
}
int? displayLimitInMilliseconds;
if (media.hasDisplayLimitInMilliseconds()) {
if (media.displayLimitInMilliseconds.toInt() < 1000) {
displayLimitInMilliseconds =
media.displayLimitInMilliseconds.toInt() * 1000;
} else {
displayLimitInMilliseconds = media.displayLimitInMilliseconds.toInt();
}
}
final mediaFile = await twonlyDB.mediaFilesDao.insertMedia(
MediaFilesCompanion(
downloadState: const Value(DownloadState.pending),
type: Value(mediaType),
requiresAuthentication: Value(media.requiresAuthentication),
displayLimitInMilliseconds: Value(
displayLimitInMilliseconds,
),
downloadToken: Value(Uint8List.fromList(media.downloadToken)),
encryptionKey: Value(Uint8List.fromList(media.encryptionKey)),
encryptionMac: Value(Uint8List.fromList(media.encryptionMac)),
encryptionNonce: Value(Uint8List.fromList(media.encryptionNonce)),
createdAt: Value(fromTimestamp(media.timestamp)),
),
);
if (mediaFile == null) {
Log.error('Could not insert media file into database');
return;
}
final message = await twonlyDB.messagesDao.insertMessage(
MessagesCompanion(
messageId: Value(media.senderMessageId),
senderId: Value(fromUserId),
groupId: Value(groupId),
mediaId: Value(mediaFile.mediaId),
type: const Value(MessageType.media),
quotesMessageId: Value(
media.hasQuoteMessageId() ? media.quoteMessageId : null,
),
createdAt: Value(fromTimestamp(media.timestamp)),
),
);
if (message != null) {
await twonlyDB.groupsDao
.increaseLastMessageExchange(groupId, fromTimestamp(media.timestamp));
Log.info('Inserted a new media message with ID: ${message.messageId}');
await twonlyDB.groupsDao.incFlameCounter(
message.groupId,
true,
fromTimestamp(media.timestamp),
);
unawaited(startDownloadMedia(mediaFile, false));
}
}
Future<void> handleMediaUpdate(
int fromUserId,
EncryptedContent_MediaUpdate mediaUpdate,
) async {
final message = await twonlyDB.messagesDao
.getMessageById(mediaUpdate.targetMessageId)
.getSingleOrNull();
if (message == null) {
Log.error(
'Got media update to message ${mediaUpdate.targetMessageId} but message not found.',
);
}
final mediaFile =
await twonlyDB.mediaFilesDao.getMediaFileById(message!.mediaId!);
if (mediaFile == null) {
Log.info(
'Got media file update, but media file was not found ${message.mediaId}',
);
return;
}
switch (mediaUpdate.type) {
case EncryptedContent_MediaUpdate_Type.REOPENED:
Log.info('Got media file reopened ${mediaFile.mediaId}');
await twonlyDB.mediaFilesDao.updateMedia(
mediaFile.mediaId,
const MediaFilesCompanion(
reopenByContact: Value(true),
),
);
case EncryptedContent_MediaUpdate_Type.STORED:
Log.info('Got media file stored ${mediaFile.mediaId}');
final mediaService = await MediaFileService.fromMedia(mediaFile);
await mediaService.storeMediaFile();
case EncryptedContent_MediaUpdate_Type.DECRYPTION_ERROR:
Log.info('Got media file decryption error ${mediaFile.mediaId}');
final reuploadRequestedBy = mediaFile.reuploadRequestedBy ?? [];
reuploadRequestedBy.add(fromUserId);
await twonlyDB.mediaFilesDao.updateMedia(
mediaFile.mediaId,
MediaFilesCompanion(
uploadState: const Value(UploadState.uploading),
reuploadRequestedBy: Value(reuploadRequestedBy),
),
);
}
}