From 19f8b44745242baeafaf53965fb2f6c49e11cd32 Mon Sep 17 00:00:00 2001
From: Michael Weimann <michaelw@matrix.org>
Date: Fri, 30 Aug 2024 16:45:25 +0200
Subject: [PATCH] Implement download_file in widget driver (#12931)

* Implement download_file in widget driver

Signed-off-by: Michael Weimann <michael.weimann@nordeck.net>

* Fix test URIs

Signed-off-by: Michael Weimann <michael.weimann@nordeck.net>

* Use download-file branch as widget-api source

Signed-off-by: Michael Weimann <michael.weimann@nordeck.net>

* bump matrix-widget-api to 1.9.0

Signed-off-by: Kim Brose <kim.brose@nordeck.net>

* prettier

Signed-off-by: Kim Brose <kim.brose@nordeck.net>

---------

Signed-off-by: Michael Weimann <michael.weimann@nordeck.net>
Signed-off-by: Kim Brose <kim.brose@nordeck.net>
Co-authored-by: Kim Brose <kim.brose@nordeck.net>
---
 package.json                                  |  2 +-
 src/stores/widgets/StopGapWidgetDriver.ts     | 15 ++++++++++
 .../widgets/StopGapWidgetDriver-test.ts       | 29 +++++++++++++++++++
 yarn.lock                                     |  8 +++++
 4 files changed, 53 insertions(+), 1 deletion(-)

diff --git a/package.json b/package.json
index 5bae5246de..02beac725c 100644
--- a/package.json
+++ b/package.json
@@ -115,7 +115,7 @@
         "matrix-encrypt-attachment": "^1.0.3",
         "matrix-events-sdk": "0.0.1",
         "matrix-js-sdk": "github:matrix-org/matrix-js-sdk#develop",
-        "matrix-widget-api": "^1.8.2",
+        "matrix-widget-api": "^1.9.0",
         "memoize-one": "^6.0.0",
         "minimist": "^1.2.5",
         "oidc-client-ts": "^3.0.1",
diff --git a/src/stores/widgets/StopGapWidgetDriver.ts b/src/stores/widgets/StopGapWidgetDriver.ts
index 6bb3e887da..b61fafbd52 100644
--- a/src/stores/widgets/StopGapWidgetDriver.ts
+++ b/src/stores/widgets/StopGapWidgetDriver.ts
@@ -73,6 +73,7 @@ import { navigateToPermalink } from "../../utils/permalinks/navigator";
 import { SdkContextClass } from "../../contexts/SDKContext";
 import { ModuleRunner } from "../../modules/ModuleRunner";
 import SettingsStore from "../../settings/SettingsStore";
+import { Media } from "../../customisations/Media";
 
 // TODO: Purge this from the universe
 
@@ -679,4 +680,18 @@ export class StopGapWidgetDriver extends WidgetDriver {
 
         return { contentUri: uploadResult.content_uri };
     }
+
+    /**
+     * Download a file from the media repository on the homeserver.
+     *
+     * @param contentUri - the MXC URI of the file to download
+     * @returns an object with: file - response contents as Blob
+     */
+    public async downloadFile(contentUri: string): Promise<{ file: XMLHttpRequestBodyInit }> {
+        const client = MatrixClientPeg.safeGet();
+        const media = new Media({ mxc: contentUri }, client);
+        const response = await media.downloadSource();
+        const blob = await response.blob();
+        return { file: blob };
+    }
 }
diff --git a/test/stores/widgets/StopGapWidgetDriver-test.ts b/test/stores/widgets/StopGapWidgetDriver-test.ts
index 282ce23d6f..960852e606 100644
--- a/test/stores/widgets/StopGapWidgetDriver-test.ts
+++ b/test/stores/widgets/StopGapWidgetDriver-test.ts
@@ -15,6 +15,7 @@ limitations under the License.
 */
 
 import { mocked, MockedObject } from "jest-mock";
+import fetchMockJest from "fetch-mock-jest";
 import {
     MatrixClient,
     ClientEvent,
@@ -616,4 +617,32 @@ describe("StopGapWidgetDriver", () => {
             expect(client.uploadContent).toHaveBeenCalledWith("data");
         });
     });
+
+    describe("downloadFile", () => {
+        let driver: WidgetDriver;
+
+        beforeEach(() => {
+            driver = mkDefaultDriver();
+        });
+
+        it("should download a file and return the blob", async () => {
+            // eslint-disable-next-line no-restricted-properties
+            client.mxcUrlToHttp.mockImplementation((mxcUrl) => {
+                if (mxcUrl === "mxc://example.com/test_file") {
+                    return "https://example.com/_matrix/media/v3/download/example.com/test_file";
+                }
+
+                return null;
+            });
+
+            fetchMockJest.get("https://example.com/_matrix/media/v3/download/example.com/test_file", "test contents");
+
+            const result = await driver.downloadFile("mxc://example.com/test_file");
+            // A type test is impossible here because of
+            // https://github.com/jefflau/jest-fetch-mock/issues/209
+            // Tell TypeScript that file is a blob.
+            const file = result.file as Blob;
+            await expect(file.text()).resolves.toEqual("test contents");
+        });
+    });
 });
diff --git a/yarn.lock b/yarn.lock
index 506384c384..2a6c27ea9c 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -7038,6 +7038,14 @@ matrix-widget-api@^1.8.2:
     "@types/events" "^3.0.0"
     events "^3.2.0"
 
+matrix-widget-api@^1.9.0:
+  version "1.9.0"
+  resolved "https://registry.yarnpkg.com/matrix-widget-api/-/matrix-widget-api-1.9.0.tgz#884136b405bd3c56e4ea285095c9e01ec52b6b1f"
+  integrity sha512-au8mqralNDqrEvaVAkU37bXOb8I9SCe+ACdPk11QWw58FKstVq31q2wRz+qWA6J+42KJ6s1DggWbG/S3fEs3jw==
+  dependencies:
+    "@types/events" "^3.0.0"
+    events "^3.2.0"
+
 md5@^2.3.0:
   version "2.3.0"
   resolved "https://registry.yarnpkg.com/md5/-/md5-2.3.0.tgz#c3da9a6aae3a30b46b7b0c349b87b110dc3bda4f"
-- 
GitLab