feat: add fromLocalStoreOnly to Event.downloadAndDecryptAttachment

Signed-off-by: Romain GUILLOT <romain.guillot@arche-mc2.fr>
This commit is contained in:
Romain GUILLOT 2024-02-15 11:17:55 +01:00 committed by Nicolas Werner
parent 2f95e41ee9
commit 22df8b39a8
No known key found for this signature in database
GPG Key ID: B38119FF80087618
2 changed files with 96 additions and 3 deletions

View File

@ -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<MatrixFile> downloadAndDecryptAttachment(
{bool getThumbnail = false,
Future<Uint8List> Function(Uri)? downloadCallback}) async {
Future<Uint8List> 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

View File

@ -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<Uint8List> 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<Uint8List> 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,