Просмотр исходного кода

build: try support fixed webview2 runtime

MystiPanda 1 год назад
Родитель
Сommit
5bb30ad28f

+ 82 - 29
.github/workflows/alpha.yml

@@ -115,55 +115,108 @@ jobs:
           echo "VERSION=$(cat package.json | jq '.version' | tr -d '"')" >> $GITHUB_ENV
           echo "BUILDTIME=$(TZ=Asia/Shanghai date)" >> $GITHUB_ENV
 
-      - run: |
-          cat > release.txt << 'EOF'
-          ### 我应该下载哪个版本?
-
-          - Windows 64位: x64-setup.exe (不支持win7)
-          - Windows 32位: x86-setup.exe (不支持win7)
-          - Windows arm64架构: arm64-setup.exe
-          - MacOS intel芯片: x64.dmg
-          - MacOS apple M芯片: aarch64.dmg (提示文件损坏看下面FAQ)
-          - Linux 64位: amd64.AppImage/amd64.deb
-          - Linux 32位: i386.deb
-          - Linux arm64架构: arm64.deb
-          - Linux armv7架构: armhf.deb
-          - Windows 便携板 64位: x64_portable.zip (不推荐使用,无法自动更新)
-          - Windows 便携板 32位: x86_portable.zip (不推荐使用,无法自动更新)
-          - Windows 便携板 arm64架构: arm64_portable.zip (不推荐使用,无法自动更新)
-
-          ### FAQ
-
-          - [FAQ](https://clash-verge-rev.github.io/faq/install/)
-
-          Created at  ${{ env.BUILDTIME }}.
-          EOF
-
       - name: Upload Release
         if: startsWith(matrix.target, 'x86_64')
         uses: softprops/action-gh-release@v1
         with:
           tag_name: alpha
           name: "Clash Verge Rev Alpha"
-          body_path: release.txt
+          body: "More new features are now supported."
           prerelease: true
           token: ${{ secrets.GITHUB_TOKEN }}
           files: src-tauri/target/${{ matrix.target }}/release/bundle/appimage/*.AppImage*
 
       - name: Upload Release
-        uses: softprops/action-gh-release@v1
+        uses: softprops/action-gh-release@v2
         with:
           tag_name: alpha
           name: "Clash Verge Rev Alpha"
-          body_path: release.txt
+          body: "More new features are now supported."
           prerelease: true
           token: ${{ secrets.GITHUB_TOKEN }}
           files: src-tauri/target/${{ matrix.target }}/release/bundle/deb/*.deb
 
+  alpha-for-fixed-webview2:
+    strategy:
+      fail-fast: false
+      matrix:
+        include:
+          - os: windows-latest
+            target: x86_64-pc-windows-msvc
+            arch: x64
+          - os: windows-latest
+            target: i686-pc-windows-msvc
+            arch: x86
+          - os: windows-latest
+            target: aarch64-pc-windows-msvc
+            arch: arm64
+    runs-on: ${{ matrix.os }}
+    steps:
+      - name: Checkout Repository
+        uses: actions/checkout@v4
+
+      - name: Add Rust Target
+        run: rustup target add ${{ matrix.target }}
+
+      - name: Rust Cache
+        uses: Swatinem/rust-cache@v2
+        with:
+          workspaces: src-tauri
+
+      - name: Install Node
+        uses: actions/setup-node@v4
+        with:
+          node-version: "20"
+
+      - uses: pnpm/action-setup@v3
+        name: Install pnpm
+        with:
+          version: 9
+          run_install: false
+
+      - name: Pnpm install and check
+        run: |
+          pnpm i
+          pnpm check ${{ matrix.target }}
+
+      - name: Download WebView2 Runtime
+        run: |
+          invoke-webrequest -uri https://github.com/westinyang/WebView2RuntimeArchive/releases/download/109.0.1518.78/Microsoft.WebView2.FixedVersionRuntime.109.0.1518.78.${{ matrix.arch }}.cab -outfile Microsoft.WebView2.FixedVersionRuntime.109.0.1518.78.${{ matrix.arch }}.cab
+          Expand .\Microsoft.WebView2.FixedVersionRuntime.109.0.1518.78.${{ matrix.arch }}.cab -F:* ./src-tauri
+          Remove-Item .\src-tauri\tauri.windows.conf.json
+          Rename-Item .\src-tauri\webview2.${{ matrix.arch }}.json tauri.windows.conf.json
+
+      - name: Tauri build
+        id: build
+        uses: tauri-apps/tauri-action@v0
+        env:
+          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+          TAURI_PRIVATE_KEY: ${{ secrets.TAURI_PRIVATE_KEY }}
+          TAURI_KEY_PASSWORD: ${{ secrets.TAURI_KEY_PASSWORD }}
+        with:
+          tauriScript: pnpm
+          args: --target ${{ matrix.target }}
+
+      - name: Rename
+        run: |
+          Rename-Item '.\src-tauri\target\${{ matrix.target }}\release\bundle\nsis\Clash Verge_${{steps.build.outputs.appVersion}}_${{ matrix.arch }}-setup.exe' 'Clash Verge_${{steps.build.outputs.appVersion}}_${{ matrix.arch }}_fixed_webview2-setup.exe'
+          Rename-Item '.\src-tauri\target\${{ matrix.target }}\release\bundle\nsis\Clash Verge_${{steps.build.outputs.appVersion}}_${{ matrix.arch }}-setup.nsis.zip' 'Clash Verge_${{steps.build.outputs.appVersion}}_${{ matrix.arch }}_fixed_webview2-setup.nsis.zip'
+          Rename-Item '.\src-tauri\target\${{ matrix.target }}\release\bundle\nsis\Clash Verge_${{steps.build.outputs.appVersion}}_${{ matrix.arch }}-setup.nsis.zip.sig' 'Clash Verge_${{steps.build.outputs.appVersion}}_${{ matrix.arch }}_fixed_webview2-setup.nsis.zip.sig'
+
+      - name: Upload Release
+        uses: softprops/action-gh-release@v2
+        with:
+          tag_name: alpha
+          name: "Clash Verge Rev Alpha"
+          body: "More new features are now supported."
+          prerelease: true
+          token: ${{ secrets.GITHUB_TOKEN }}
+          files: src-tauri/target/${{ matrix.target }}/release/bundle/nsis/*setup*
+
   update_tag:
     name: Update tag
     runs-on: ubuntu-latest
-    needs: [alpha, alpha-for-linux]
+    needs: [alpha, alpha-for-linux, alpha-for-fixed-webview2]
     steps:
       - name: Checkout repository
         uses: actions/checkout@v4
@@ -205,7 +258,7 @@ jobs:
           EOF
 
       - name: Upload Release
-        uses: softprops/action-gh-release@v1
+        uses: softprops/action-gh-release@v2
         with:
           tag_name: alpha
           name: "Clash Verge Rev Alpha"

+ 109 - 3
.github/workflows/release.yml

@@ -15,6 +15,8 @@ jobs:
         include:
           - os: windows-latest
             target: x86_64-pc-windows-msvc
+          - os: windows-latest
+            target: i686-pc-windows-msvc
           - os: windows-latest
             target: aarch64-pc-windows-msvc
           - os: macos-latest
@@ -84,6 +86,8 @@ jobs:
         include:
           - os: ubuntu-latest
             target: x86_64-unknown-linux-gnu
+          - os: ubuntu-latest
+            target: i686-unknown-linux-gnu
           - os: ubuntu-latest
             target: aarch64-unknown-linux-gnu
           - os: ubuntu-latest
@@ -126,22 +130,98 @@ jobs:
           token: ${{ secrets.GITHUB_TOKEN }}
           files: src-tauri/target/${{ matrix.target }}/release/bundle/deb/*.deb
 
+  release-for-fixed-webview2:
+    strategy:
+      fail-fast: false
+      matrix:
+        include:
+          - os: windows-latest
+            target: x86_64-pc-windows-msvc
+            arch: x64
+          - os: windows-latest
+            target: i686-pc-windows-msvc
+            arch: x86
+          - os: windows-latest
+            target: aarch64-pc-windows-msvc
+            arch: arm64
+    runs-on: ${{ matrix.os }}
+    steps:
+      - name: Checkout Repository
+        uses: actions/checkout@v4
+
+      - name: Add Rust Target
+        run: rustup target add ${{ matrix.target }}
+
+      - name: Rust Cache
+        uses: Swatinem/rust-cache@v2
+        with:
+          workspaces: src-tauri
+
+      - name: Install Node
+        uses: actions/setup-node@v4
+        with:
+          node-version: "20"
+
+      - uses: pnpm/action-setup@v3
+        name: Install pnpm
+        with:
+          version: 9
+          run_install: false
+
+      - name: Pnpm install and check
+        run: |
+          pnpm i
+          pnpm check ${{ matrix.target }}
+
+      - name: Download WebView2 Runtime
+        run: |
+          invoke-webrequest -uri https://github.com/westinyang/WebView2RuntimeArchive/releases/download/109.0.1518.78/Microsoft.WebView2.FixedVersionRuntime.109.0.1518.78.${{ matrix.arch }}.cab -outfile Microsoft.WebView2.FixedVersionRuntime.109.0.1518.78.${{ matrix.arch }}.cab
+          Expand .\Microsoft.WebView2.FixedVersionRuntime.109.0.1518.78.${{ matrix.arch }}.cab -F:* ./src-tauri
+          Remove-Item .\src-tauri\tauri.windows.conf.json
+          Rename-Item .\src-tauri\webview2.${{ matrix.arch }}.json tauri.windows.conf.json
+
+      - name: Tauri build
+        id: build
+        uses: tauri-apps/tauri-action@v0
+        env:
+          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+          TAURI_PRIVATE_KEY: ${{ secrets.TAURI_PRIVATE_KEY }}
+          TAURI_KEY_PASSWORD: ${{ secrets.TAURI_KEY_PASSWORD }}
+        with:
+          tauriScript: pnpm
+          args: --target ${{ matrix.target }}
+
+      - name: Rename
+        run: |
+          Rename-Item '.\src-tauri\target\${{ matrix.target }}\release\bundle\nsis\Clash Verge_${{steps.build.outputs.appVersion}}_${{ matrix.arch }}-setup.exe' 'Clash Verge_${{steps.build.outputs.appVersion}}_${{ matrix.arch }}_fixed_webview2-setup.exe'
+          Rename-Item '.\src-tauri\target\${{ matrix.target }}\release\bundle\nsis\Clash Verge_${{steps.build.outputs.appVersion}}_${{ matrix.arch }}-setup.nsis.zip' 'Clash Verge_${{steps.build.outputs.appVersion}}_${{ matrix.arch }}_fixed_webview2-setup.nsis.zip'
+          Rename-Item '.\src-tauri\target\${{ matrix.target }}\release\bundle\nsis\Clash Verge_${{steps.build.outputs.appVersion}}_${{ matrix.arch }}-setup.nsis.zip.sig' 'Clash Verge_${{steps.build.outputs.appVersion}}_${{ matrix.arch }}_fixed_webview2-setup.nsis.zip.sig'
+
+      - name: Upload Release
+        uses: softprops/action-gh-release@v1
+        with:
+          tag_name: v${{steps.build.outputs.appVersion}}
+          name: "Clash Verge Rev v${{steps.build.outputs.appVersion}}"
+          body: "More new features are now supported."
+          token: ${{ secrets.GITHUB_TOKEN }}
+          files: src-tauri/target/${{ matrix.target }}/release/bundle/nsis/*setup*
+
   release-update:
     runs-on: ubuntu-latest
     needs: [release, release-for-linux]
     steps:
       - name: Checkout repository
-        uses: actions/checkout@v3
+        uses: actions/checkout@v4
 
       - name: Install Node
-        uses: actions/setup-node@v3
+        uses: actions/setup-node@v4
         with:
           node-version: "20"
 
       - uses: pnpm/action-setup@v2
         name: Install pnpm
         with:
-          version: 8
+          version: 9
           run_install: false
 
       - name: Pnpm install
@@ -151,3 +231,29 @@ jobs:
         run: pnpm updater
         env:
           GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+
+  release-update-for-fixed-webview2:
+    runs-on: ubuntu-latest
+    needs: [release-for-fixed-webview2]
+    steps:
+      - name: Checkout repository
+        uses: actions/checkout@v4
+
+      - name: Install Node
+        uses: actions/setup-node@v4
+        with:
+          node-version: "20"
+
+      - uses: pnpm/action-setup@v2
+        name: Install pnpm
+        with:
+          version: 9
+          run_install: false
+
+      - name: Pnpm install
+        run: pnpm i
+
+      - name: Release updater file
+        run: pnpm updater-fixed-webview2
+        env:
+          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

+ 27 - 2
.github/workflows/updater.yml

@@ -10,14 +10,14 @@ jobs:
         uses: actions/checkout@v3
 
       - name: Install Node
-        uses: actions/setup-node@v3
+        uses: actions/setup-node@v4
         with:
           node-version: "20"
 
       - uses: pnpm/action-setup@v2
         name: Install pnpm
         with:
-          version: 8
+          version: 9
           run_install: false
 
       - name: Pnpm install
@@ -27,3 +27,28 @@ jobs:
         run: pnpm updater
         env:
           GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+
+  release-update-for-fixed-webview2:
+    runs-on: ubuntu-latest
+    steps:
+      - name: Checkout repository
+        uses: actions/checkout@v4
+
+      - name: Install Node
+        uses: actions/setup-node@v4
+        with:
+          node-version: "20"
+
+      - uses: pnpm/action-setup@v2
+        name: Install pnpm
+        with:
+          version: 9
+          run_install: false
+
+      - name: Pnpm install
+        run: pnpm i
+
+      - name: Release updater file
+        run: pnpm updater-fixed-webview2
+        env:
+          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

+ 1 - 0
package.json

@@ -12,6 +12,7 @@
     "web:serve": "vite preview",
     "check": "node scripts/check.mjs",
     "updater": "node scripts/updater.mjs",
+    "updater-fixed-webview2": "node scripts/updater-fixed-webview2.mjs",
     "portable": "node scripts/portable.mjs",
     "prepare": "husky install"
   },

+ 154 - 0
scripts/updater-fixed-webview2.mjs

@@ -0,0 +1,154 @@
+import fetch from "node-fetch";
+import { getOctokit, context } from "@actions/github";
+import { resolveUpdateLog } from "./updatelog.mjs";
+
+const UPDATE_TAG_NAME = "updater";
+const UPDATE_JSON_FILE = "update-fixed-webview2.json";
+const UPDATE_JSON_PROXY = "update-fixed-webview2-proxy.json";
+
+/// generate update.json
+/// upload to update tag's release asset
+async function resolveUpdater() {
+  if (process.env.GITHUB_TOKEN === undefined) {
+    throw new Error("GITHUB_TOKEN is required");
+  }
+
+  const options = { owner: context.repo.owner, repo: context.repo.repo };
+  const github = getOctokit(process.env.GITHUB_TOKEN);
+
+  const { data: tags } = await github.rest.repos.listTags({
+    ...options,
+    per_page: 10,
+    page: 1,
+  });
+
+  // get the latest publish tag
+  const tag = tags.find((t) => t.name.startsWith("v"));
+
+  console.log(tag);
+  console.log();
+
+  const { data: latestRelease } = await github.rest.repos.getReleaseByTag({
+    ...options,
+    tag: tag.name,
+  });
+
+  const updateData = {
+    name: tag.name,
+    notes: await resolveUpdateLog(tag.name), // use updatelog.md
+    pub_date: new Date().toISOString(),
+    platforms: {
+      "windows-x86_64": { signature: "", url: "" },
+      "windows-aarch64": { signature: "", url: "" },
+      "windows-x86": { signature: "", url: "" },
+    },
+  };
+
+  const promises = latestRelease.assets.map(async (asset) => {
+    const { name, browser_download_url } = asset;
+
+    // win64 url
+    if (name.endsWith("x64_fixed_webview2-setup.nsis.zip")) {
+      updateData.platforms["windows-x86_64"].url = browser_download_url;
+    }
+    // win64 signature
+    if (name.endsWith("x64_fixed_webview2-setup.nsis.zip.sig")) {
+      const sig = await getSignature(browser_download_url);
+      updateData.platforms["windows-x86_64"].signature = sig;
+    }
+
+    // win32 url
+    if (name.endsWith("x86_fixed_webview2-setup.nsis.zip")) {
+      updateData.platforms["windows-x86"].url = browser_download_url;
+    }
+    // win32 signature
+    if (name.endsWith("x86_fixed_webview2-setup.nsis.zip.sig")) {
+      const sig = await getSignature(browser_download_url);
+      updateData.platforms["windows-x86"].signature = sig;
+    }
+
+    // win arm url
+    if (name.endsWith("arm64_fixed_webview2-setup.nsis.zip")) {
+      updateData.platforms["windows-aarch64"].url = browser_download_url;
+    }
+    // win arm signature
+    if (name.endsWith("arm64_fixed_webview2-setup.nsis.zip.sig")) {
+      const sig = await getSignature(browser_download_url);
+      updateData.platforms["windows-aarch64"].signature = sig;
+    }
+  });
+
+  await Promise.allSettled(promises);
+  console.log(updateData);
+
+  // maybe should test the signature as well
+  // delete the null field
+  Object.entries(updateData.platforms).forEach(([key, value]) => {
+    if (!value.url) {
+      console.log(`[Error]: failed to parse release for "${key}"`);
+      delete updateData.platforms[key];
+    }
+  });
+
+  // 生成一个代理github的更新文件
+  // 使用 https://hub.fastgit.xyz/ 做github资源的加速
+  const updateDataNew = JSON.parse(JSON.stringify(updateData));
+
+  Object.entries(updateDataNew.platforms).forEach(([key, value]) => {
+    if (value.url) {
+      updateDataNew.platforms[key].url =
+        "https://mirror.ghproxy.com/" + value.url;
+    } else {
+      console.log(`[Error]: updateDataNew.platforms.${key} is null`);
+    }
+  });
+
+  // update the update.json
+  const { data: updateRelease } = await github.rest.repos.getReleaseByTag({
+    ...options,
+    tag: UPDATE_TAG_NAME,
+  });
+
+  // delete the old assets
+  for (let asset of updateRelease.assets) {
+    if (asset.name === UPDATE_JSON_FILE) {
+      await github.rest.repos.deleteReleaseAsset({
+        ...options,
+        asset_id: asset.id,
+      });
+    }
+
+    if (asset.name === UPDATE_JSON_PROXY) {
+      await github.rest.repos
+        .deleteReleaseAsset({ ...options, asset_id: asset.id })
+        .catch(console.error); // do not break the pipeline
+    }
+  }
+
+  // upload new assets
+  await github.rest.repos.uploadReleaseAsset({
+    ...options,
+    release_id: updateRelease.id,
+    name: UPDATE_JSON_FILE,
+    data: JSON.stringify(updateData, null, 2),
+  });
+
+  await github.rest.repos.uploadReleaseAsset({
+    ...options,
+    release_id: updateRelease.id,
+    name: UPDATE_JSON_PROXY,
+    data: JSON.stringify(updateDataNew, null, 2),
+  });
+}
+
+// get the signature file content
+async function getSignature(url) {
+  const response = await fetch(url, {
+    method: "GET",
+    headers: { "Content-Type": "application/octet-stream" },
+  });
+
+  return response.text();
+}
+
+resolveUpdater().catch(console.error);

+ 38 - 0
src-tauri/webview2.arm64.json

@@ -0,0 +1,38 @@
+{
+  "$schema": "../node_modules/@tauri-apps/cli/schema.json",
+  "tauri": {
+    "systemTray": {
+      "iconPath": "icons/tray-icon.png"
+    },
+    "bundle": {
+      "identifier": "io.github.clash-verge-rev.clash-verge-rev",
+      "targets": ["nsis", "updater"],
+      "windows": {
+        "certificateThumbprint": null,
+        "digestAlgorithm": "sha256",
+        "timestampUrl": "",
+        "webviewInstallMode": {
+          "type": "fixedRuntime",
+          "path": "./Microsoft.WebView2.FixedVersionRuntime.109.0.1518.78.arm64/"
+        },
+        "nsis": {
+          "displayLanguageSelector": true,
+          "installerIcon": "icons/icon.ico",
+          "languages": ["SimpChinese", "English"],
+          "license": "../LICENSE",
+          "installMode": "perMachine",
+          "template": "./template/installer.nsi"
+        }
+      }
+    },
+    "updater": {
+      "active": true,
+      "dialog": false,
+      "endpoints": [
+        "https://mirror.ghproxy.com/https://github.com/clash-verge-rev/clash-verge-rev/releases/download/updater/update-fixed-webview2-proxy.json",
+        "https://github.com/clash-verge-rev/clash-verge-rev/releases/download/updater/update-fixed-webview2.json"
+      ],
+      "pubkey": "dW50cnVzdGVkIGNvbW1lbnQ6IG1pbmlzaWduIHB1YmxpYyBrZXk6IEQyOEMyRjBCQkVGOUJEREYKUldUZnZmbStDeStNMHU5Mmo1N24xQXZwSVRYbXA2NUpzZE5oVzlqeS9Bc0t6RVV4MmtwVjBZaHgK"
+    }
+  }
+}

+ 38 - 0
src-tauri/webview2.x64.json

@@ -0,0 +1,38 @@
+{
+  "$schema": "../node_modules/@tauri-apps/cli/schema.json",
+  "tauri": {
+    "systemTray": {
+      "iconPath": "icons/tray-icon.png"
+    },
+    "bundle": {
+      "identifier": "io.github.clash-verge-rev.clash-verge-rev",
+      "targets": ["nsis", "updater"],
+      "windows": {
+        "certificateThumbprint": null,
+        "digestAlgorithm": "sha256",
+        "timestampUrl": "",
+        "webviewInstallMode": {
+          "type": "fixedRuntime",
+          "path": "./Microsoft.WebView2.FixedVersionRuntime.109.0.1518.78.x64/"
+        },
+        "nsis": {
+          "displayLanguageSelector": true,
+          "installerIcon": "icons/icon.ico",
+          "languages": ["SimpChinese", "English"],
+          "license": "../LICENSE",
+          "installMode": "perMachine",
+          "template": "./template/installer.nsi"
+        }
+      }
+    },
+    "updater": {
+      "active": true,
+      "dialog": false,
+      "endpoints": [
+        "https://mirror.ghproxy.com/https://github.com/clash-verge-rev/clash-verge-rev/releases/download/updater/update-fixed-webview2-proxy.json",
+        "https://github.com/clash-verge-rev/clash-verge-rev/releases/download/updater/update-fixed-webview2.json"
+      ],
+      "pubkey": "dW50cnVzdGVkIGNvbW1lbnQ6IG1pbmlzaWduIHB1YmxpYyBrZXk6IEQyOEMyRjBCQkVGOUJEREYKUldUZnZmbStDeStNMHU5Mmo1N24xQXZwSVRYbXA2NUpzZE5oVzlqeS9Bc0t6RVV4MmtwVjBZaHgK"
+    }
+  }
+}

+ 38 - 0
src-tauri/webview2.x86.json

@@ -0,0 +1,38 @@
+{
+  "$schema": "../node_modules/@tauri-apps/cli/schema.json",
+  "tauri": {
+    "systemTray": {
+      "iconPath": "icons/tray-icon.png"
+    },
+    "bundle": {
+      "identifier": "io.github.clash-verge-rev.clash-verge-rev",
+      "targets": ["nsis", "updater"],
+      "windows": {
+        "certificateThumbprint": null,
+        "digestAlgorithm": "sha256",
+        "timestampUrl": "",
+        "webviewInstallMode": {
+          "type": "fixedRuntime",
+          "path": "./Microsoft.WebView2.FixedVersionRuntime.109.0.1518.78.x86/"
+        },
+        "nsis": {
+          "displayLanguageSelector": true,
+          "installerIcon": "icons/icon.ico",
+          "languages": ["SimpChinese", "English"],
+          "license": "../LICENSE",
+          "installMode": "perMachine",
+          "template": "./template/installer.nsi"
+        }
+      }
+    },
+    "updater": {
+      "active": true,
+      "dialog": false,
+      "endpoints": [
+        "https://mirror.ghproxy.com/https://github.com/clash-verge-rev/clash-verge-rev/releases/download/updater/update-fixed-webview2-proxy.json",
+        "https://github.com/clash-verge-rev/clash-verge-rev/releases/download/updater/update-fixed-webview2.json"
+      ],
+      "pubkey": "dW50cnVzdGVkIGNvbW1lbnQ6IG1pbmlzaWduIHB1YmxpYyBrZXk6IEQyOEMyRjBCQkVGOUJEREYKUldUZnZmbStDeStNMHU5Mmo1N24xQXZwSVRYbXA2NUpzZE5oVzlqeS9Bc0t6RVV4MmtwVjBZaHgK"
+    }
+  }
+}