From 22df8b39a8d55491f1d906be86ea572ec72bfa81 Mon Sep 17 00:00:00 2001 From: Romain GUILLOT Date: Thu, 15 Feb 2024 11:17:55 +0100 Subject: [PATCH] feat: add fromLocalStoreOnly to Event.downloadAndDecryptAttachment Signed-off-by: Romain GUILLOT --- lib/src/event.dart | 12 ++++-- test/event_test.dart | 87 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 96 insertions(+), 3 deletions(-) diff --git a/lib/src/event.dart b/lib/src/event.dart index 650f3d93..8ba61892 100644 --- a/lib/src/event.dart +++ b/lib/src/event.dart @@ -586,10 +586,13 @@ class Event extends MatrixEvent { /// Downloads (and decrypts if necessary) the attachment of this /// event and returns it as a [MatrixFile]. If this event doesn't /// contain an attachment, this throws an error. Set [getThumbnail] to - /// true to download the thumbnail instead. + /// true to download the thumbnail instead. Set [fromLocalStoreOnly] to true + /// if you want to retrieve the attachment from the local store only without + /// making http request. Future downloadAndDecryptAttachment( {bool getThumbnail = false, - Future Function(Uri)? downloadCallback}) async { + Future Function(Uri)? downloadCallback, + bool fromLocalStoreOnly = false}) async { if (![EventTypes.Message, EventTypes.Sticker].contains(type)) { throw ("This event has the type '$type' and so it can't contain an attachment."); } @@ -621,7 +624,8 @@ class Event extends MatrixEvent { } // Download the file - if (uint8list == null) { + final canDownloadFileFromServer = uint8list == null && !fromLocalStoreOnly; + if (canDownloadFileFromServer) { final httpClient = room.client.httpClient; downloadCallback ??= (Uri url) async => (await httpClient.get(url)).bodyBytes; @@ -633,6 +637,8 @@ class Event extends MatrixEvent { await database.storeFile( mxcUrl, uint8list, DateTime.now().millisecondsSinceEpoch); } + } else if (uint8list == null) { + throw ('Unable to download file from local store.'); } // Decrypt the file diff --git a/test/event_test.dart b/test/event_test.dart index f387c427..5c925b4d 100644 --- a/test/event_test.dart +++ b/test/event_test.dart @@ -1549,6 +1549,93 @@ void main() { await room.client.dispose(closeDatabase: true); }); + + test('downloadAndDecryptAttachment store only', () async { + final FILE_BUFF = Uint8List.fromList([0]); + var serverHits = 0; + Future downloadCallback(Uri uri) async { + serverHits++; + return { + '/_matrix/media/v3/download/example.org/newfile': FILE_BUFF, + }[uri.path]!; + } + + await client.checkHomeserver(Uri.parse('https://fakeserver.notexisting'), + checkWellKnown: false); + final room = Room(id: '!localpart:server.abc', client: await getClient()); + final event = Event.fromJson({ + 'type': EventTypes.Message, + 'content': { + 'body': 'image', + 'msgtype': 'm.image', + 'url': 'mxc://example.org/newfile', + 'info': { + 'size': 5, + }, + }, + 'event_id': '\$edit2', + 'sender': '@alice:example.org', + }, room); + + var buffer = await event.downloadAndDecryptAttachment( + downloadCallback: downloadCallback); + expect(await event.isAttachmentInLocalStore(), + event.room.client.database?.supportsFileStoring); + expect(buffer.bytes, FILE_BUFF); + expect(serverHits, 1); + + if (event.room.client.database?.supportsFileStoring == true) { + buffer = await event.downloadAndDecryptAttachment( + downloadCallback: downloadCallback, fromLocalStoreOnly: true); + expect(buffer.bytes, FILE_BUFF); + } else { + expect( + () async => await event.downloadAndDecryptAttachment( + downloadCallback: downloadCallback, fromLocalStoreOnly: true), + throwsA(anything)); + } + expect(serverHits, 1); + + await room.client.dispose(closeDatabase: true); + }); + + test('downloadAndDecryptAttachment store only without file', () async { + final FILE_BUFF = Uint8List.fromList([0]); + var serverHits = 0; + Future downloadCallback(Uri uri) async { + serverHits++; + return { + '/_matrix/media/v3/download/example.org/newfile': FILE_BUFF, + }[uri.path]!; + } + + await client.checkHomeserver(Uri.parse('https://fakeserver.notexisting'), + checkWellKnown: false); + final room = Room(id: '!localpart:server.abc', client: await getClient()); + final event = Event.fromJson({ + 'type': EventTypes.Message, + 'content': { + 'body': 'image', + 'msgtype': 'm.image', + 'url': 'mxc://example.org/newfile', + 'info': { + 'size': 5, + }, + }, + 'event_id': '\$edit2', + 'sender': '@alice:example.org', + }, room); + + expect( + () async => await event.downloadAndDecryptAttachment( + downloadCallback: downloadCallback, fromLocalStoreOnly: true), + throwsA(anything)); + + expect(serverHits, 0); + + await room.client.dispose(closeDatabase: true); + }); + test('emote detection', () async { var event = Event.fromJson({ 'type': EventTypes.Message,