From ef28fbd8f5cf76b1084ac24ae02dbb8c215f0532 Mon Sep 17 00:00:00 2001
From: Kir_Antipov <kp.antipov@gmail.com>
Date: Tue, 7 Dec 2021 21:48:52 +0300
Subject: [PATCH] Made base class for metadata readers that deal with zip

---
 package-lock.json                          |  5 ++++
 package.json                               |  3 +-
 src/metadata/zipped-mod-metadata-reader.ts | 32 ++++++++++++++++++++++
 3 files changed, 39 insertions(+), 1 deletion(-)
 create mode 100644 src/metadata/zipped-mod-metadata-reader.ts

diff --git a/package-lock.json b/package-lock.json
index 7ed9d31..50f2115 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -4140,6 +4140,11 @@
       "integrity": "sha512-9/IECtNr8dXNmPWmFXepT0/7o5eolGesHUa3mtr0KlgnCvnZxwh2qensKL42JJY2vQKC3nIBXetFAqR+PW1CmA==",
       "dev": true
     },
+    "node-stream-zip": {
+      "version": "1.15.0",
+      "resolved": "https://registry.npmjs.org/node-stream-zip/-/node-stream-zip-1.15.0.tgz",
+      "integrity": "sha512-LN4fydt9TqhZhThkZIVQnF9cwjU3qmUH9h78Mx/K7d3VvfRqqwthLwJEUOEL0QPZ0XQmNN7be5Ggit5+4dq3Bw=="
+    },
     "normalize-path": {
       "version": "3.0.0",
       "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
diff --git a/package.json b/package.json
index ce5f737..e2da1f4 100644
--- a/package.json
+++ b/package.json
@@ -43,6 +43,7 @@
     "@actions/github": "^5.0.0",
     "fast-glob": "^3.2.7",
     "formdata-node": "^4.2.4",
-    "node-fetch": "^3.0.0"
+    "node-fetch": "^3.0.0",
+    "node-stream-zip": "^1.15.0"
   }
 }
diff --git a/src/metadata/zipped-mod-metadata-reader.ts b/src/metadata/zipped-mod-metadata-reader.ts
new file mode 100644
index 0000000..c8a203b
--- /dev/null
+++ b/src/metadata/zipped-mod-metadata-reader.ts
@@ -0,0 +1,32 @@
+import ModMetadata from "./mod-metadata";
+import ModMetadataReader from "./mod-metadata-reader";
+import { StreamZipAsync, async as ZipArchive } from "node-stream-zip";
+
+export default abstract class ZippedModMetadataReader<TConfig = Record<string, unknown>> implements ModMetadataReader {
+    private configEntryName: string;
+
+    protected constructor(configEntryName: string) {
+        this.configEntryName = configEntryName;
+    }
+
+    async readMetadata(modPath: string): Promise<ModMetadata | null> {
+        let zip = <StreamZipAsync>null;
+        try {
+            zip = new ZipArchive({ file: modPath });
+            const buffer = await zip.entryData(this.configEntryName).catch(_ => <Buffer>null);
+            if (buffer) {
+                return this.createMetadataFromConfig(this.loadConfig(buffer));
+            } else {
+                return null;
+            }
+        } catch {
+            return null;
+        } finally {
+            await zip?.close();
+        }
+    }
+
+    protected abstract loadConfig(buffer: Buffer): TConfig;
+
+    protected abstract createMetadataFromConfig(config: TConfig): ModMetadata;
+}