diff --git a/.github/update.log b/.github/update.log
index 0e5526b328..ef795daa55 100644
--- a/.github/update.log
+++ b/.github/update.log
@@ -601,3 +601,4 @@ Update On Mon Mar 25 19:35:07 CET 2024
Update On Tue Mar 26 19:28:27 CET 2024
Update On Wed Mar 27 19:27:19 CET 2024
Update On Thu Mar 28 19:29:20 CET 2024
+Update On Sat Mar 30 19:27:32 CET 2024
diff --git a/aliyunpan/.github/ISSUE_TEMPLATE/BUG-REPORT.yml b/aliyunpan/.github/ISSUE_TEMPLATE/BUG-REPORT.yml
new file mode 100644
index 0000000000..9e65209ff7
--- /dev/null
+++ b/aliyunpan/.github/ISSUE_TEMPLATE/BUG-REPORT.yml
@@ -0,0 +1,86 @@
+name: Bug report
+description: Problems with the software
+title: '[Bug] {{请输入标题,不要留空 - Please enter a title, do not leave it blank.}}'
+labels: ['bug']
+body:
+ - type: markdown
+ attributes:
+ value: |
+ **非常感谢您的反馈!Thank you very much for your feedback!**
+
+ 有关讨论、建议或者咨询的内容请去往[讨论区](https://github.com/gaozhangmin/aliyunpan/discussions)。
+
+ For suggestions or help, please consider using [Github Discussion](https://github.com/gaozhangmin/aliyunpan/discussions) instead.
+
+ - type: checkboxes
+ attributes:
+ label: Please search before asking
+ description: |
+ 辛苦提 Bug 前,检索一下 [问题](https://github.com/gaozhangmin/aliyunpan/issues?q=) 列表是否已经存在类似问题。麻烦提供系统版本、录屏或者截图、复现步骤,有助于更好的解决问题。
+
+ 非 Bug 相关,烦请移步 [讨论区](https://github.com/gaozhangmin/aliyunpan/discussions) 找寻有关讨论。
+
+ Please search [issues](https://github.com/gaozhangmin/aliyunpan/issues) to check if your issue has already been reported.
+
+ Not related to bugs, please go to the [discussion area](https://github.com/gaozhangmin/aliyunpan/discussions) for relevant discussions.
+
+ options:
+ - label: >
+ I searched in the [issues](https://github.com/gaozhangmin/aliyunpan/issues) and found nothing similar.
+ required: true
+ - type: checkboxes
+ attributes:
+ label: Please read README
+ description: |
+ 辛苦提 Bug 前,请仔细阅读一下 README 中的 [Troubleshooting](https://github.com/gaozhangmin/aliyunpan/tree/main#troubleshooting) 是否已经给出相关解决方案
+
+ Before reporting bugs (especially for issues such as missing icons in the desktop application, permission pop-ups, and damaged report files), please carefully read the [Troubleshooting](https://github.com/gaozhangmin/aliyunpan/tree/main#troubleshooting) section in README to see if relevant solutions have already been provided.
+
+ options:
+ - label: I have read the troubleshooting section in the README in detail.
+ required: true
+
+ - type: input
+ attributes:
+ label: 使用的版本
+ description: >
+ 请提供您正在使用的 小白羊 的版本。Please provide the version of 小白羊 you are using. For example, `3.11.7`.
+ validations:
+ required: true
+ - type: input
+ attributes:
+ label: 系统 System
+ description: >
+ 请提供您正在使用的系统。Please provide the version of the System you are using. For example, `macOS 11.2.3`.
+ validations:
+ required: true
+ - type: textarea
+ attributes:
+ label: 复现步骤 Reproduce step
+ description: >
+ 请提供完整且简明的复现步骤,以方便及时定位并解决问题。Please provide complete and concise reproduction steps to facilitate timely identification and resolution of the issue.
+ validations:
+ required: true
+ - type: textarea
+ attributes:
+ label: 你看到了什么错误?What errors do you see?
+ validations:
+ required: true
+ - type: textarea
+ attributes:
+ label: 你期望看到什么?What did you expect to see?
+ validations:
+ required: true
+ - type: textarea
+ attributes:
+ label: 还有其他的内容吗?Anything else?
+ - type: checkboxes
+ attributes:
+ label: 你是否愿意提交一份 PR 来修改这个错误?Are you willing to submit a PR?
+ description: >
+ 我们期待开发人员和用户的帮助,以解决在 小白羊 中发现的任何问题。 如果您愿意通过提交 PR 来解决此问题,请勾选。We eagerly anticipate developers' and users' support and collaboration in resolving any issues found in 小白羊. If you are willing to offer a solution by submitting a PR to fix this matter, kindly mark the checkbox provided.
+ options:
+ - label: 我愿意提供 PR! I'm willing to submit a PR!
+ - type: markdown
+ attributes:
+ value: '非常感谢您的反馈!Thank you very much for your feedback!'
diff --git a/aliyunpan/.github/ISSUE_TEMPLATE/feature.yml b/aliyunpan/.github/ISSUE_TEMPLATE/FEATURE-REQUEST.yml
similarity index 100%
rename from aliyunpan/.github/ISSUE_TEMPLATE/feature.yml
rename to aliyunpan/.github/ISSUE_TEMPLATE/FEATURE-REQUEST.yml
diff --git a/aliyunpan/.github/ISSUE_TEMPLATE/bug-report.yml b/aliyunpan/.github/ISSUE_TEMPLATE/bug-report.yml
deleted file mode 100644
index 33002c9d01..0000000000
--- a/aliyunpan/.github/ISSUE_TEMPLATE/bug-report.yml
+++ /dev/null
@@ -1,86 +0,0 @@
-name: Bug report
-description: Problems with the software
-title: '[Bug] {{请输入标题,不要留空 - Please enter a title, do not leave it blank.}}'
-labels: ['bug']
-body:
- - type: markdown
- attributes:
- value: |
- **非常感谢您的反馈!Thank you very much for your feedback!**
-
- 有关讨论、建议或者咨询的内容请去往[讨论区](https://github.com/gaozhangmin/aliyunpan/discussions)。
-
- For suggestions or help, please consider using [Github Discussion](https://github.com/gaozhangmin/aliyunpan/discussions) instead.
-
- - type: checkboxes
- attributes:
- label: Please search before asking
- description: |
- 辛苦提 Bug 前,检索一下 [问题](https://github.com/gaozhangmin/aliyunpan/issues?q=) 列表是否已经存在类似问题。麻烦提供系统版本、录屏或者截图、复现步骤,有助于更好的解决问题。
-
- 非 Bug 相关,烦请移步 [讨论区](https://github.com/gaozhangmin/aliyunpan/discussions) 找寻有关讨论。
-
- Please search [issues](https://github.com/gaozhangmin/aliyunpan/issues) to check if your issue has already been reported.
-
- Not related to bugs, please go to the [discussion area](https://github.com/gaozhangmin/aliyunpan/discussions) for relevant discussions.
-
- options:
- - label: >
- I searched in the [issues](https://github.com/gaozhangmin/aliyunpan/issues) and found nothing similar.
- required: true
- - type: checkboxes
- attributes:
- label: Please read README
- description: |
- 辛苦提 Bug 前,请仔细阅读一下 README 中的 [Troubleshooting](https://github.com/gaozhangmin/aliyunpan/tree/main#troubleshooting) 是否已经给出相关解决方案
-
- Before reporting bugs (especially for issues such as missing icons in the desktop application, permission pop-ups, and damaged report files), please carefully read the [Troubleshooting](https://github.com/gaozhangmin/aliyunpan/tree/main#troubleshooting) section in README to see if relevant solutions have already been provided.
-
- options:
- - label: I have read the troubleshooting section in the README in detail.
- required: true
-
- - type: input
- attributes:
- label: 使用的版本
- description: >
- 请提供您正在使用的 小白羊 的版本。Please provide the version of 小白羊 you are using. For example, `3.11.7`.
- validations:
- required: true
- - type: input
- attributes:
- label: 系统 System
- description: >
- 请提供您正在使用的系统。Please provide the version of the System you are using. For example, `macOS 11.2.3`.
- validations:
- required: true
- - type: textarea
- attributes:
- label: 复现步骤 Reproduce step
- description: >
- 请提供完整且简明的复现步骤,以方便及时定位并解决问题。Please provide complete and concise reproduction steps to facilitate timely identification and resolution of the issue.
- validations:
- required: true
- - type: textarea
- attributes:
- label: 你看到了什么错误?What errors do you see?
- validations:
- required: true
- - type: textarea
- attributes:
- label: 你期望看到什么?What did you expect to see?
- validations:
- required: true
- - type: textarea
- attributes:
- label: 还有其他的内容吗?Anything else?
- - type: checkboxes
- attributes:
- label: 你是否愿意提交一份 PR 来修改这个错误?Are you willing to submit a PR?
- description: >
- 我们期待开发人员和用户的帮助,以解决在 小白羊 中发现的任何问题。 如果您愿意通过提交 PR 来解决此问题,请勾选。We eagerly anticipate developers' and users' support and collaboration in resolving any issues found in 小白羊. If you are willing to offer a solution by submitting a PR to fix this matter, kindly mark the checkbox provided.
- options:
- - label: 我愿意提供 PR! I'm willing to submit a PR!
- - type: markdown
- attributes:
- value: '非常感谢您的反馈!Thank you very much for your feedback!'
\ No newline at end of file
diff --git a/aliyunpan/.github/ISSUE_TEMPLATE/config.yml b/aliyunpan/.github/ISSUE_TEMPLATE/config.yml
index 8d7bb4b274..1569e85530 100644
--- a/aliyunpan/.github/ISSUE_TEMPLATE/config.yml
+++ b/aliyunpan/.github/ISSUE_TEMPLATE/config.yml
@@ -2,4 +2,4 @@ blank_issues_enabled: false
contact_links:
- name: Ask a question or get support
url: https://github.com/gaozhangmin/aliyunpan/discussions/categories/q-a
- about: Ask a question or request support for XiaoBaiYang
\ No newline at end of file
+ about: Ask a question or request support for XiaoBaiYang
diff --git a/aliyunpan/.github/workflows/build.yml b/aliyunpan/.github/workflows/build.yml
deleted file mode 100644
index f4b0d06c8f..0000000000
--- a/aliyunpan/.github/workflows/build.yml
+++ /dev/null
@@ -1,92 +0,0 @@
-name: Build
-
-on:
- push:
- tags:
- - '*.*.*'
-
-jobs:
- create-release:
- permissions:
- contents: write
- runs-on: ubuntu-20.04
- outputs:
- release_id: ${{ steps.create-release.outputs.id }}
- release_upload_url: ${{ steps.create-release.outputs.upload_url }}
-
- steps:
- - uses: actions/checkout@v3
-
- - name: Get version
- id: get_version
- uses: battila7/get-version-action@v2
-
- - name: Create Release
- id: create-release
- uses: ncipollo/release-action@v1
- with:
- draft: true
- name: ${{ steps.get_version.outputs.version }}
- tag: ${{ steps.get_version.outputs.version }}
- body: "${{ steps.tag.outputs.message }}"
- release:
- needs: create-release
- name: build and release
- runs-on: ${{ matrix.os }}
-
- strategy:
- fail-fast: false
- matrix:
- os: [windows-latest, macos-latest, ubuntu-latest]
-
- permissions:
- contents: write
-
- steps:
- - name: Checkout Git repository
- uses: actions/checkout@v3
-
- - name: Install Node
- uses: actions/setup-node@v3
- with:
- node-version: 16
- registry-url: https://registry.npmjs.org/
-
- - name: Get yarn cache directory path
- id: yarn-cache-dir-path
- run: echo "::set-output name=dir::$(yarn cache dir)"
-
- - uses: actions/cache@v3
- id: cache-yarn-cache
- with:
- path: ${{ steps.yarn-cache-dir-path.outputs.dir }}
- key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }}
- restore-keys: |
- ${{ runner.os }}-yarn-
-
- - uses: actions/cache@v3
- id: cache-node-modules
- with:
- path: node_modules
- key: ${{ runner.os }}-${{ matrix.node-version }}-nodemodules-${{ hashFiles('**/yarn.lock') }}
- restore-keys: |
- ${{ runner.os }}-${{ matrix.node-version }}-nodemodules-
-
- - name: Install Dependencies
- if: |
- steps.cache-yarn-cache.outputs.cache-hit != 'true' ||
- steps.cache-node-modules.outputs.cache-hit != 'true'
- run: |
- npm install -g yarn
- yarn install
-
- - name: Make Aria2c Executable
- if: matrix.os != 'windows-latest'
- run: |
- chmod -R 777 ./static/engine/
-
- - name: Build Electron app
- uses: samuelmeuli/action-electron-builder@v1.6.0
- with:
- release: ${{ startsWith(github.ref, 'refs/tags') }}
- github_token: ${{ secrets.github_token }}
diff --git a/aliyunpan/.github/workflows/closeissue.yml b/aliyunpan/.github/workflows/closeissue.yml
new file mode 100644
index 0000000000..faac7cbdfc
--- /dev/null
+++ b/aliyunpan/.github/workflows/closeissue.yml
@@ -0,0 +1,23 @@
+# https://github.com/actions/stale
+name: autoCloseIssue
+
+on:
+ schedule:
+ # 每5天北京时间9点
+ - cron: '30 1 1/5 * *'
+ workflow_dispatch:
+
+jobs:
+ stale:
+ runs-on: ubuntu-latest
+ permissions:
+ issues: write
+
+ steps:
+ - uses: actions/stale@v9
+ with:
+ repo-token: ${{ secrets.GITHUB_TOKEN }}
+ stale-issue-message: '由于该问题长期没有更新,将于5天后自动关闭。如有需要可重新打开。'
+ days-before-stale: 30
+ days-before-close: 5
+ operations-per-run: 100
\ No newline at end of file
diff --git a/aliyunpan/.github/workflows/release.yml b/aliyunpan/.github/workflows/release.yml
new file mode 100644
index 0000000000..085806d0f3
--- /dev/null
+++ b/aliyunpan/.github/workflows/release.yml
@@ -0,0 +1,101 @@
+name: Build Release
+
+on:
+ push:
+ branches:
+ - main
+ paths:
+ - 'package.json'
+
+jobs:
+ release:
+ name: Build Release
+ strategy:
+ fail-fast: false
+ matrix:
+ os: [ windows-latest, macos-latest, ubuntu-latest ]
+ runs-on: ${{ matrix.os }}
+
+ permissions:
+ contents: write
+
+ steps:
+ - name: Checkout Git repository
+ uses: actions/checkout@v4
+
+ - name: Install Node
+ uses: actions/setup-node@v4
+ with:
+ node-version: 18
+ registry-url: https://registry.npmjs.org/
+
+ - uses: pnpm/action-setup@v3
+ name: Install pnpm
+ id: pnpm-install
+ with:
+ version: 8
+ run_install: false
+
+ - name: Get Pnpm Store Directory
+ shell: bash
+ run: |
+ echo "PNPM_STORE_PATH=$(pnpm store path)" >> $GITHUB_ENV
+
+ - name: Get Electron Store Directory
+ shell: bash
+ run: |
+ if [[ "${{ runner.os }}" == "Windows" ]]; then
+ echo "ELECTRON_STORE_PATH=$LOCALAPPDATA\\electron\\cache" >> $GITHUB_ENV
+ echo "ELECTRON_BUILDER_STORE_PATH=$LOCALAPPDATA\\electron-builder\\cache" >> $GITHUB_ENV
+ elif [[ "${{ runner.os }}" == "macOS" ]]; then
+ echo "ELECTRON_STORE_PATH=$HOME/Library/Caches/electron" >> $GITHUB_ENV
+ else
+ echo "ELECTRON_STORE_PATH=$HOME/.cache/electron" >> $GITHUB_ENV
+ echo "ELECTRON_BUILDER_STORE_PATH=$HOME/.cache/electron-builder" >> $GITHUB_ENV
+ fi
+
+ - name: Setup Pnpm Cache
+ uses: actions/cache@v4
+ with:
+ path: ${{ env.PNPM_STORE_PATH }}
+ key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }}
+ restore-keys: |
+ ${{ runner.os }}-pnpm-store-
+
+ - name: Setup Cache Electron
+ uses: actions/cache@v4
+ with:
+ path: ${{ env.ELECTRON_STORE_PATH }}
+ key: ${{ runner.os }}-electron-cache-${{ hashFiles('**/pnpm-lock.yaml') }}
+ restore-keys: |
+ ${{ runner.os }}-electron-cache-
+
+ - name: Setup Cache Electron Builder
+ uses: actions/cache@v4
+ if: matrix.os != 'macos-latest'
+ with:
+ path: ${{ env.ELECTRON_BUILDER_STORE_PATH }}
+ key: ${{ runner.os }}-electron-builder-cache-${{ hashFiles('**/pnpm-lock.yaml') }}
+ restore-keys: |
+ ${{ runner.os }}-electron-builder-cache-
+
+ - name: Install Dependencies
+ run: |
+ pnpm install
+
+ - name: Install Lib For Pacman Build
+ if: matrix.os == 'ubuntu-latest'
+ run: |
+ sudo apt-get install libarchive-tools
+
+ - name: Make Aria2c Executable
+ if: matrix.os != 'windows-latest'
+ run: |
+ chmod -R 777 ./static/engine/
+
+ - name: Build Electron App
+ uses: paneron/action-electron-builder@v1.8.1
+ with:
+ package_manager: pnpm
+ release: true
+ github_token: ${{ secrets.GITHUB_TOKEN }}
diff --git a/aliyunpan/.gitignore b/aliyunpan/.gitignore
index c314163426..463a10f202 100644
--- a/aliyunpan/.gitignore
+++ b/aliyunpan/.gitignore
@@ -9,6 +9,5 @@ tmp
release
.idea
-yarn.lock
-localVersion
+localVersion
diff --git a/aliyunpan/LICENSE b/aliyunpan/LICENSE
index af62d4018c..f288702d2f 100644
--- a/aliyunpan/LICENSE
+++ b/aliyunpan/LICENSE
@@ -1,21 +1,674 @@
-MIT License
+ GNU GENERAL PUBLIC LICENSE
+ Version 3, 29 June 2007
-Copyright (c) 2023 Zhangao
+ Copyright (C) 2007 Free Software Foundation, Inc.
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
+ Preamble
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
+ The GNU General Public License is a free, copyleft license for
+software and other kinds of works.
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
\ No newline at end of file
+ The licenses for most software and other practical works are designed
+to take away your freedom to share and change the works. By contrast,
+the GNU General Public License is intended to guarantee your freedom to
+share and change all versions of a program--to make sure it remains free
+software for all its users. We, the Free Software Foundation, use the
+GNU General Public License for most of our software; it applies also to
+any other work released this way by its authors. You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+them if you wish), that you receive source code or can get it if you
+want it, that you can change the software or use pieces of it in new
+free programs, and that you know you can do these things.
+
+ To protect your rights, we need to prevent others from denying you
+these rights or asking you to surrender the rights. Therefore, you have
+certain responsibilities if you distribute copies of the software, or if
+you modify it: responsibilities to respect the freedom of others.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must pass on to the recipients the same
+freedoms that you received. You must make sure that they, too, receive
+or can get the source code. And you must show them these terms so they
+know their rights.
+
+ Developers that use the GNU GPL protect your rights with two steps:
+(1) assert copyright on the software, and (2) offer you this License
+giving you legal permission to copy, distribute and/or modify it.
+
+ For the developers' and authors' protection, the GPL clearly explains
+that there is no warranty for this free software. For both users' and
+authors' sake, the GPL requires that modified versions be marked as
+changed, so that their problems will not be attributed erroneously to
+authors of previous versions.
+
+ Some devices are designed to deny users access to install or run
+modified versions of the software inside them, although the manufacturer
+can do so. This is fundamentally incompatible with the aim of
+protecting users' freedom to change the software. The systematic
+pattern of such abuse occurs in the area of products for individuals to
+use, which is precisely where it is most unacceptable. Therefore, we
+have designed this version of the GPL to prohibit the practice for those
+products. If such problems arise substantially in other domains, we
+stand ready to extend this provision to those domains in future versions
+of the GPL, as needed to protect the freedom of users.
+
+ Finally, every program is threatened constantly by software patents.
+States should not allow patents to restrict development and use of
+software on general-purpose computers, but in those that do, we wish to
+avoid the special danger that patents applied to a free program could
+make it effectively proprietary. To prevent this, the GPL assures that
+patents cannot be used to render the program non-free.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ TERMS AND CONDITIONS
+
+ 0. Definitions.
+
+ "This License" refers to version 3 of the GNU General Public License.
+
+ "Copyright" also means copyright-like laws that apply to other kinds of
+works, such as semiconductor masks.
+
+ "The Program" refers to any copyrightable work licensed under this
+License. Each licensee is addressed as "you". "Licensees" and
+"recipients" may be individuals or organizations.
+
+ To "modify" a work means to copy from or adapt all or part of the work
+in a fashion requiring copyright permission, other than the making of an
+exact copy. The resulting work is called a "modified version" of the
+earlier work or a work "based on" the earlier work.
+
+ A "covered work" means either the unmodified Program or a work based
+on the Program.
+
+ To "propagate" a work means to do anything with it that, without
+permission, would make you directly or secondarily liable for
+infringement under applicable copyright law, except executing it on a
+computer or modifying a private copy. Propagation includes copying,
+distribution (with or without modification), making available to the
+public, and in some countries other activities as well.
+
+ To "convey" a work means any kind of propagation that enables other
+parties to make or receive copies. Mere interaction with a user through
+a computer network, with no transfer of a copy, is not conveying.
+
+ An interactive user interface displays "Appropriate Legal Notices"
+to the extent that it includes a convenient and prominently visible
+feature that (1) displays an appropriate copyright notice, and (2)
+tells the user that there is no warranty for the work (except to the
+extent that warranties are provided), that licensees may convey the
+work under this License, and how to view a copy of this License. If
+the interface presents a list of user commands or options, such as a
+menu, a prominent item in the list meets this criterion.
+
+ 1. Source Code.
+
+ The "source code" for a work means the preferred form of the work
+for making modifications to it. "Object code" means any non-source
+form of a work.
+
+ A "Standard Interface" means an interface that either is an official
+standard defined by a recognized standards body, or, in the case of
+interfaces specified for a particular programming language, one that
+is widely used among developers working in that language.
+
+ The "System Libraries" of an executable work include anything, other
+than the work as a whole, that (a) is included in the normal form of
+packaging a Major Component, but which is not part of that Major
+Component, and (b) serves only to enable use of the work with that
+Major Component, or to implement a Standard Interface for which an
+implementation is available to the public in source code form. A
+"Major Component", in this context, means a major essential component
+(kernel, window system, and so on) of the specific operating system
+(if any) on which the executable work runs, or a compiler used to
+produce the work, or an object code interpreter used to run it.
+
+ The "Corresponding Source" for a work in object code form means all
+the source code needed to generate, install, and (for an executable
+work) run the object code and to modify the work, including scripts to
+control those activities. However, it does not include the work's
+System Libraries, or general-purpose tools or generally available free
+programs which are used unmodified in performing those activities but
+which are not part of the work. For example, Corresponding Source
+includes interface definition files associated with source files for
+the work, and the source code for shared libraries and dynamically
+linked subprograms that the work is specifically designed to require,
+such as by intimate data communication or control flow between those
+subprograms and other parts of the work.
+
+ The Corresponding Source need not include anything that users
+can regenerate automatically from other parts of the Corresponding
+Source.
+
+ The Corresponding Source for a work in source code form is that
+same work.
+
+ 2. Basic Permissions.
+
+ All rights granted under this License are granted for the term of
+copyright on the Program, and are irrevocable provided the stated
+conditions are met. This License explicitly affirms your unlimited
+permission to run the unmodified Program. The output from running a
+covered work is covered by this License only if the output, given its
+content, constitutes a covered work. This License acknowledges your
+rights of fair use or other equivalent, as provided by copyright law.
+
+ You may make, run and propagate covered works that you do not
+convey, without conditions so long as your license otherwise remains
+in force. You may convey covered works to others for the sole purpose
+of having them make modifications exclusively for you, or provide you
+with facilities for running those works, provided that you comply with
+the terms of this License in conveying all material for which you do
+not control copyright. Those thus making or running the covered works
+for you must do so exclusively on your behalf, under your direction
+and control, on terms that prohibit them from making any copies of
+your copyrighted material outside their relationship with you.
+
+ Conveying under any other circumstances is permitted solely under
+the conditions stated below. Sublicensing is not allowed; section 10
+makes it unnecessary.
+
+ 3. Protecting Users' Legal Rights From Anti-Circumvention Law.
+
+ No covered work shall be deemed part of an effective technological
+measure under any applicable law fulfilling obligations under article
+11 of the WIPO copyright treaty adopted on 20 December 1996, or
+similar laws prohibiting or restricting circumvention of such
+measures.
+
+ When you convey a covered work, you waive any legal power to forbid
+circumvention of technological measures to the extent such circumvention
+is effected by exercising rights under this License with respect to
+the covered work, and you disclaim any intention to limit operation or
+modification of the work as a means of enforcing, against the work's
+users, your or third parties' legal rights to forbid circumvention of
+technological measures.
+
+ 4. Conveying Verbatim Copies.
+
+ You may convey verbatim copies of the Program's source code as you
+receive it, in any medium, provided that you conspicuously and
+appropriately publish on each copy an appropriate copyright notice;
+keep intact all notices stating that this License and any
+non-permissive terms added in accord with section 7 apply to the code;
+keep intact all notices of the absence of any warranty; and give all
+recipients a copy of this License along with the Program.
+
+ You may charge any price or no price for each copy that you convey,
+and you may offer support or warranty protection for a fee.
+
+ 5. Conveying Modified Source Versions.
+
+ You may convey a work based on the Program, or the modifications to
+produce it from the Program, in the form of source code under the
+terms of section 4, provided that you also meet all of these conditions:
+
+ a) The work must carry prominent notices stating that you modified
+ it, and giving a relevant date.
+
+ b) The work must carry prominent notices stating that it is
+ released under this License and any conditions added under section
+ 7. This requirement modifies the requirement in section 4 to
+ "keep intact all notices".
+
+ c) You must license the entire work, as a whole, under this
+ License to anyone who comes into possession of a copy. This
+ License will therefore apply, along with any applicable section 7
+ additional terms, to the whole of the work, and all its parts,
+ regardless of how they are packaged. This License gives no
+ permission to license the work in any other way, but it does not
+ invalidate such permission if you have separately received it.
+
+ d) If the work has interactive user interfaces, each must display
+ Appropriate Legal Notices; however, if the Program has interactive
+ interfaces that do not display Appropriate Legal Notices, your
+ work need not make them do so.
+
+ A compilation of a covered work with other separate and independent
+works, which are not by their nature extensions of the covered work,
+and which are not combined with it such as to form a larger program,
+in or on a volume of a storage or distribution medium, is called an
+"aggregate" if the compilation and its resulting copyright are not
+used to limit the access or legal rights of the compilation's users
+beyond what the individual works permit. Inclusion of a covered work
+in an aggregate does not cause this License to apply to the other
+parts of the aggregate.
+
+ 6. Conveying Non-Source Forms.
+
+ You may convey a covered work in object code form under the terms
+of sections 4 and 5, provided that you also convey the
+machine-readable Corresponding Source under the terms of this License,
+in one of these ways:
+
+ a) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by the
+ Corresponding Source fixed on a durable physical medium
+ customarily used for software interchange.
+
+ b) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by a
+ written offer, valid for at least three years and valid for as
+ long as you offer spare parts or customer support for that product
+ model, to give anyone who possesses the object code either (1) a
+ copy of the Corresponding Source for all the software in the
+ product that is covered by this License, on a durable physical
+ medium customarily used for software interchange, for a price no
+ more than your reasonable cost of physically performing this
+ conveying of source, or (2) access to copy the
+ Corresponding Source from a network server at no charge.
+
+ c) Convey individual copies of the object code with a copy of the
+ written offer to provide the Corresponding Source. This
+ alternative is allowed only occasionally and noncommercially, and
+ only if you received the object code with such an offer, in accord
+ with subsection 6b.
+
+ d) Convey the object code by offering access from a designated
+ place (gratis or for a charge), and offer equivalent access to the
+ Corresponding Source in the same way through the same place at no
+ further charge. You need not require recipients to copy the
+ Corresponding Source along with the object code. If the place to
+ copy the object code is a network server, the Corresponding Source
+ may be on a different server (operated by you or a third party)
+ that supports equivalent copying facilities, provided you maintain
+ clear directions next to the object code saying where to find the
+ Corresponding Source. Regardless of what server hosts the
+ Corresponding Source, you remain obligated to ensure that it is
+ available for as long as needed to satisfy these requirements.
+
+ e) Convey the object code using peer-to-peer transmission, provided
+ you inform other peers where the object code and Corresponding
+ Source of the work are being offered to the general public at no
+ charge under subsection 6d.
+
+ A separable portion of the object code, whose source code is excluded
+from the Corresponding Source as a System Library, need not be
+included in conveying the object code work.
+
+ A "User Product" is either (1) a "consumer product", which means any
+tangible personal property which is normally used for personal, family,
+or household purposes, or (2) anything designed or sold for incorporation
+into a dwelling. In determining whether a product is a consumer product,
+doubtful cases shall be resolved in favor of coverage. For a particular
+product received by a particular user, "normally used" refers to a
+typical or common use of that class of product, regardless of the status
+of the particular user or of the way in which the particular user
+actually uses, or expects or is expected to use, the product. A product
+is a consumer product regardless of whether the product has substantial
+commercial, industrial or non-consumer uses, unless such uses represent
+the only significant mode of use of the product.
+
+ "Installation Information" for a User Product means any methods,
+procedures, authorization keys, or other information required to install
+and execute modified versions of a covered work in that User Product from
+a modified version of its Corresponding Source. The information must
+suffice to ensure that the continued functioning of the modified object
+code is in no case prevented or interfered with solely because
+modification has been made.
+
+ If you convey an object code work under this section in, or with, or
+specifically for use in, a User Product, and the conveying occurs as
+part of a transaction in which the right of possession and use of the
+User Product is transferred to the recipient in perpetuity or for a
+fixed term (regardless of how the transaction is characterized), the
+Corresponding Source conveyed under this section must be accompanied
+by the Installation Information. But this requirement does not apply
+if neither you nor any third party retains the ability to install
+modified object code on the User Product (for example, the work has
+been installed in ROM).
+
+ The requirement to provide Installation Information does not include a
+requirement to continue to provide support service, warranty, or updates
+for a work that has been modified or installed by the recipient, or for
+the User Product in which it has been modified or installed. Access to a
+network may be denied when the modification itself materially and
+adversely affects the operation of the network or violates the rules and
+protocols for communication across the network.
+
+ Corresponding Source conveyed, and Installation Information provided,
+in accord with this section must be in a format that is publicly
+documented (and with an implementation available to the public in
+source code form), and must require no special password or key for
+unpacking, reading or copying.
+
+ 7. Additional Terms.
+
+ "Additional permissions" are terms that supplement the terms of this
+License by making exceptions from one or more of its conditions.
+Additional permissions that are applicable to the entire Program shall
+be treated as though they were included in this License, to the extent
+that they are valid under applicable law. If additional permissions
+apply only to part of the Program, that part may be used separately
+under those permissions, but the entire Program remains governed by
+this License without regard to the additional permissions.
+
+ When you convey a copy of a covered work, you may at your option
+remove any additional permissions from that copy, or from any part of
+it. (Additional permissions may be written to require their own
+removal in certain cases when you modify the work.) You may place
+additional permissions on material, added by you to a covered work,
+for which you have or can give appropriate copyright permission.
+
+ Notwithstanding any other provision of this License, for material you
+add to a covered work, you may (if authorized by the copyright holders of
+that material) supplement the terms of this License with terms:
+
+ a) Disclaiming warranty or limiting liability differently from the
+ terms of sections 15 and 16 of this License; or
+
+ b) Requiring preservation of specified reasonable legal notices or
+ author attributions in that material or in the Appropriate Legal
+ Notices displayed by works containing it; or
+
+ c) Prohibiting misrepresentation of the origin of that material, or
+ requiring that modified versions of such material be marked in
+ reasonable ways as different from the original version; or
+
+ d) Limiting the use for publicity purposes of names of licensors or
+ authors of the material; or
+
+ e) Declining to grant rights under trademark law for use of some
+ trade names, trademarks, or service marks; or
+
+ f) Requiring indemnification of licensors and authors of that
+ material by anyone who conveys the material (or modified versions of
+ it) with contractual assumptions of liability to the recipient, for
+ any liability that these contractual assumptions directly impose on
+ those licensors and authors.
+
+ All other non-permissive additional terms are considered "further
+restrictions" within the meaning of section 10. If the Program as you
+received it, or any part of it, contains a notice stating that it is
+governed by this License along with a term that is a further
+restriction, you may remove that term. If a license document contains
+a further restriction but permits relicensing or conveying under this
+License, you may add to a covered work material governed by the terms
+of that license document, provided that the further restriction does
+not survive such relicensing or conveying.
+
+ If you add terms to a covered work in accord with this section, you
+must place, in the relevant source files, a statement of the
+additional terms that apply to those files, or a notice indicating
+where to find the applicable terms.
+
+ Additional terms, permissive or non-permissive, may be stated in the
+form of a separately written license, or stated as exceptions;
+the above requirements apply either way.
+
+ 8. Termination.
+
+ You may not propagate or modify a covered work except as expressly
+provided under this License. Any attempt otherwise to propagate or
+modify it is void, and will automatically terminate your rights under
+this License (including any patent licenses granted under the third
+paragraph of section 11).
+
+ However, if you cease all violation of this License, then your
+license from a particular copyright holder is reinstated (a)
+provisionally, unless and until the copyright holder explicitly and
+finally terminates your license, and (b) permanently, if the copyright
+holder fails to notify you of the violation by some reasonable means
+prior to 60 days after the cessation.
+
+ Moreover, your license from a particular copyright holder is
+reinstated permanently if the copyright holder notifies you of the
+violation by some reasonable means, this is the first time you have
+received notice of violation of this License (for any work) from that
+copyright holder, and you cure the violation prior to 30 days after
+your receipt of the notice.
+
+ Termination of your rights under this section does not terminate the
+licenses of parties who have received copies or rights from you under
+this License. If your rights have been terminated and not permanently
+reinstated, you do not qualify to receive new licenses for the same
+material under section 10.
+
+ 9. Acceptance Not Required for Having Copies.
+
+ You are not required to accept this License in order to receive or
+run a copy of the Program. Ancillary propagation of a covered work
+occurring solely as a consequence of using peer-to-peer transmission
+to receive a copy likewise does not require acceptance. However,
+nothing other than this License grants you permission to propagate or
+modify any covered work. These actions infringe copyright if you do
+not accept this License. Therefore, by modifying or propagating a
+covered work, you indicate your acceptance of this License to do so.
+
+ 10. Automatic Licensing of Downstream Recipients.
+
+ Each time you convey a covered work, the recipient automatically
+receives a license from the original licensors, to run, modify and
+propagate that work, subject to this License. You are not responsible
+for enforcing compliance by third parties with this License.
+
+ An "entity transaction" is a transaction transferring control of an
+organization, or substantially all assets of one, or subdividing an
+organization, or merging organizations. If propagation of a covered
+work results from an entity transaction, each party to that
+transaction who receives a copy of the work also receives whatever
+licenses to the work the party's predecessor in interest had or could
+give under the previous paragraph, plus a right to possession of the
+Corresponding Source of the work from the predecessor in interest, if
+the predecessor has it or can get it with reasonable efforts.
+
+ You may not impose any further restrictions on the exercise of the
+rights granted or affirmed under this License. For example, you may
+not impose a license fee, royalty, or other charge for exercise of
+rights granted under this License, and you may not initiate litigation
+(including a cross-claim or counterclaim in a lawsuit) alleging that
+any patent claim is infringed by making, using, selling, offering for
+sale, or importing the Program or any portion of it.
+
+ 11. Patents.
+
+ A "contributor" is a copyright holder who authorizes use under this
+License of the Program or a work on which the Program is based. The
+work thus licensed is called the contributor's "contributor version".
+
+ A contributor's "essential patent claims" are all patent claims
+owned or controlled by the contributor, whether already acquired or
+hereafter acquired, that would be infringed by some manner, permitted
+by this License, of making, using, or selling its contributor version,
+but do not include claims that would be infringed only as a
+consequence of further modification of the contributor version. For
+purposes of this definition, "control" includes the right to grant
+patent sublicenses in a manner consistent with the requirements of
+this License.
+
+ Each contributor grants you a non-exclusive, worldwide, royalty-free
+patent license under the contributor's essential patent claims, to
+make, use, sell, offer for sale, import and otherwise run, modify and
+propagate the contents of its contributor version.
+
+ In the following three paragraphs, a "patent license" is any express
+agreement or commitment, however denominated, not to enforce a patent
+(such as an express permission to practice a patent or covenant not to
+sue for patent infringement). To "grant" such a patent license to a
+party means to make such an agreement or commitment not to enforce a
+patent against the party.
+
+ If you convey a covered work, knowingly relying on a patent license,
+and the Corresponding Source of the work is not available for anyone
+to copy, free of charge and under the terms of this License, through a
+publicly available network server or other readily accessible means,
+then you must either (1) cause the Corresponding Source to be so
+available, or (2) arrange to deprive yourself of the benefit of the
+patent license for this particular work, or (3) arrange, in a manner
+consistent with the requirements of this License, to extend the patent
+license to downstream recipients. "Knowingly relying" means you have
+actual knowledge that, but for the patent license, your conveying the
+covered work in a country, or your recipient's use of the covered work
+in a country, would infringe one or more identifiable patents in that
+country that you have reason to believe are valid.
+
+ If, pursuant to or in connection with a single transaction or
+arrangement, you convey, or propagate by procuring conveyance of, a
+covered work, and grant a patent license to some of the parties
+receiving the covered work authorizing them to use, propagate, modify
+or convey a specific copy of the covered work, then the patent license
+you grant is automatically extended to all recipients of the covered
+work and works based on it.
+
+ A patent license is "discriminatory" if it does not include within
+the scope of its coverage, prohibits the exercise of, or is
+conditioned on the non-exercise of one or more of the rights that are
+specifically granted under this License. You may not convey a covered
+work if you are a party to an arrangement with a third party that is
+in the business of distributing software, under which you make payment
+to the third party based on the extent of your activity of conveying
+the work, and under which the third party grants, to any of the
+parties who would receive the covered work from you, a discriminatory
+patent license (a) in connection with copies of the covered work
+conveyed by you (or copies made from those copies), or (b) primarily
+for and in connection with specific products or compilations that
+contain the covered work, unless you entered into that arrangement,
+or that patent license was granted, prior to 28 March 2007.
+
+ Nothing in this License shall be construed as excluding or limiting
+any implied license or other defenses to infringement that may
+otherwise be available to you under applicable patent law.
+
+ 12. No Surrender of Others' Freedom.
+
+ If conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot convey a
+covered work so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you may
+not convey it at all. For example, if you agree to terms that obligate you
+to collect a royalty for further conveying from those to whom you convey
+the Program, the only way you could satisfy both those terms and this
+License would be to refrain entirely from conveying the Program.
+
+ 13. Use with the GNU Affero General Public License.
+
+ Notwithstanding any other provision of this License, you have
+permission to link or combine any covered work with a work licensed
+under version 3 of the GNU Affero General Public License into a single
+combined work, and to convey the resulting work. The terms of this
+License will continue to apply to the part which is the covered work,
+but the special requirements of the GNU Affero General Public License,
+section 13, concerning interaction through a network will apply to the
+combination as such.
+
+ 14. Revised Versions of this License.
+
+ The Free Software Foundation may publish revised and/or new versions of
+the GNU General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+ Each version is given a distinguishing version number. If the
+Program specifies that a certain numbered version of the GNU General
+Public License "or any later version" applies to it, you have the
+option of following the terms and conditions either of that numbered
+version or of any later version published by the Free Software
+Foundation. If the Program does not specify a version number of the
+GNU General Public License, you may choose any version ever published
+by the Free Software Foundation.
+
+ If the Program specifies that a proxy can decide which future
+versions of the GNU General Public License can be used, that proxy's
+public statement of acceptance of a version permanently authorizes you
+to choose that version for the Program.
+
+ Later license versions may give you additional or different
+permissions. However, no additional obligations are imposed on any
+author or copyright holder as a result of your choosing to follow a
+later version.
+
+ 15. Disclaimer of Warranty.
+
+ THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
+APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
+HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
+OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
+THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
+IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
+ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+ 16. Limitation of Liability.
+
+ IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
+THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
+GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
+USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
+DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
+PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
+EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGES.
+
+ 17. Interpretation of Sections 15 and 16.
+
+ If the disclaimer of warranty and limitation of liability provided
+above cannot be given local legal effect according to their terms,
+reviewing courts shall apply local law that most closely approximates
+an absolute waiver of all civil liability in connection with the
+Program, unless a warranty or assumption of liability accompanies a
+copy of the Program in return for a fee.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+state the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+
+ Copyright (C)
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see .
+
+Also add information on how to contact you by electronic and paper mail.
+
+ If the program does terminal interaction, make it output a short
+notice like this when it starts in an interactive mode:
+
+ Copyright (C)
+ This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, your program's commands
+might be different; for a GUI interface, you would use an "about box".
+
+ You should also get your employer (if you work as a programmer) or school,
+if any, to sign a "copyright disclaimer" for the program, if necessary.
+For more information on this, and how to apply and follow the GNU GPL, see
+ .
+
+ The GNU General Public License does not permit incorporating your program
+into proprietary programs. If your program is a subroutine library, you
+may consider it more useful to permit linking proprietary applications with
+the library. If this is what you want to do, use the GNU Lesser General
+Public License instead of this License. But first, please read
+.
diff --git a/aliyunpan/README.md b/aliyunpan/README.md
index 9140d28dc4..2a80d18dfb 100644
--- a/aliyunpan/README.md
+++ b/aliyunpan/README.md
@@ -1,5 +1,5 @@
-
+
English | 中文
@@ -44,12 +44,11 @@
-
[](#功能-) [](#界面-) [](#安装-) [](#小白羊公众号-) [](#交流社区-) [](#鸣谢-) [](#免责声明-)
# 功能 [](#功能-)
-1.根据阿里云盘Open平台api开发的网盘客户端,支持win7-11,macOS,linux
+1.基于阿里云盘Open平台api开发的网盘客户端,支持win7-11,macOS,linux
2.支持同时登录多个账号管理。
@@ -69,13 +68,21 @@
10.支持一次性上传/下载百万级的文件/文件夹。
+11. 支持M3u8下载。
+
+12. 影院模式支持自动刮削视频信息。
+
+13. 支持展示视频观看进度。
+
+更多功能见小白羊官网:https://xbysite.pages.dev/
+
# 界面 [](#界面-)
-
-
+
+
@@ -123,17 +130,17 @@
- - 点击 `Cancel` 按钮,然后去 `设置` -> `隐私与安全性` 页面,点击 `仍要打开` 按钮,然后在弹出窗口里点击 `打开` 按钮即可,以后就再也不会有任何弹窗告警了 🎉
+ - 点击 `Cancel` 按钮,然后去 `设置` -> `隐私与安全性` 页面,点击 `仍要打开` 按钮,然后在弹出窗口里点击 `打开` 按钮即可,以后就再也不会有任何弹窗告警了 🎉
-
-
-
+
+
+
- - 如果在 `隐私与安全性` 中找不到以上选项,或启动时提示文件损坏(Apple Silicon版本)。打开 `Terminal.app`,并输入以下命令(中途可能需要输入密码),然后重启 `小白羊云盘` 即可:
+ - 如果在 `隐私与安全性` 中找不到以上选项,或启动时提示文件损坏(Apple Silicon版本)。打开 `Terminal.app`,并输入以下命令(中途可能需要输入密码),然后重启 `小白羊云盘` 即可:
- ```sh
- sudo xattr -d com.apple.quarantine /Applications/小白羊云盘.app
- ```
+ ```sh
+ sudo xattr -d com.apple.quarantine /Applications/小白羊云盘.app
+ ```
@@ -185,7 +192,7 @@
4.在使用本程序之前,你应了解并承担相应的风险,包括但不限于账号被ban,下载限速等,与本程序无关;
-5.如有侵权,请通过邮件与我联系,会及时处理。
+5.如有侵权,请通过邮件zhangao456@proton.me与我联系,会及时处理。
-
\ No newline at end of file
+
diff --git a/aliyunpan/changelog.txt b/aliyunpan/changelog.txt
deleted file mode 100644
index 27de4cc6e9..0000000000
--- a/aliyunpan/changelog.txt
+++ /dev/null
@@ -1,329 +0,0 @@
-#### 2023/2/24
-1.修复UserDeviceIllegality问题
-2.修复下载功能
-3.修复打包问题
-
-#### 2022/10/24
-
-注:因上传下载功能尚未做完,本次仅同步代码不发布安装包
-0. 恢复文件上传功能,支持单次上传百万个文件/文件夹,优化上传任务的数据库文件体积过大的问题
-1. 优化sha1并发计算逻辑,增加文件sha1的缓存,提升上传大文件的性能
-2. Add 上传前弹窗,设置重名冲突(删除/覆盖/自动重命名/不上传)
-3. Add 单独的总上传速度限制设置
-4. Add 上传文件时只上传可以秒传的文件的设置
-5. Add 单独的上传文件时的并发执行数设置(最大50文件同时上传)
-6. Add 左侧文件树文件夹对拖放上传的支持
-7. Add 上传中列表里文件夹视图
-8. Add 优先上传小文件(100M)的支持
-9. Fix 按住Ctrl时,点击CheckBox和点击空白处,选中结果不一致的BUG
-10. Fix 右键菜单-打开文件位置,没有选中和滚动到指定文件的BUG
-11. Fix 断网时,重试上传任务,可能导致上传任务的断点续传进度丢失的BUG
-#### 2022/09/18
-
-注:因上传下载功能尚未做完,本次仅同步代码不发布安装包
-
-1. Fix v3.5.23alpha中的20余处小BUG
-2. Fix 登录时遇到二次短信验证时不能继续登录的BUG
-3. 完善批量重命名功能
-4. 完善颜色标记功能
-5. 优化文件列表加载显示逻辑,现在很优雅了
-6. 优化文件名排序,支持中文数字排序,按win习惯英文在前中文在后
-7. 优化文件夹树性能(全部文件夹列出速度加快3倍,20万文件夹不卡顿,树内存占用减少60%)
-8. 恢复显示文件夹体积(可按大小排序),优化计算文件夹体积的逻辑(速度加快计算量减少)
-9. 底部增加网盘空间信息和文件夹内文件总数量
-10. 增加复制文件名和复制目录树的功能
-11. 适配更新vite3.1.2,更新全部package到最新版
-
-
-#### 2022/05/23
-
-v3.5.23alpha 开发人员测试版本
-
-1. Fix 偶发的登录后显示空白窗口的 BUG
-2. Fix 登录太多账号时切换账号弹窗不能正确显示的 BUG
-3. 优化长时间不用后需要重新登录的问题
-4. Fix 偶发的下载中显示空白列表的 BUG
-5. Fix 多次弹出升级提示窗口的 BUG
-6. Fix 目录下超过 200 个文件夹不能显示的 BUG
-7. 重制 APP 设置页面,分组设置,配置保存到 setting.config
-8. 优化快捷键(现在很多操作都支持键盘快捷键)
-
---
-
-v3.05.23.alpha 新增加的功能
-
-文件恢复,放映室,网页版播放器,彻底删除菜单,文件属性菜单,所有列表支持右键菜单,
-整盘高级搜索,文件快速筛选,右侧文件拖放移动,文件标记,文件夹快捷方式,我订阅的公众号,
-重复文件清理,扫描大文件,扫描重复文件,扫描违规文件,扫描空文件夹,网盘相册间复制,
-批量重命名
-
-
-
-#### 2022/04/14
-
-
-1. 修正因阿里云盘官网升级导致的无法使用
-2. 优化访问频次问题
-3. 修正违禁视频详情BUG
-
-
-#### 2021/12/05
-
-
-1. 修正网盘内文件路径过长时下载失败 BUG
-2. 优化快捷键功能(帮助文档里有完整的快捷键说明)
-3. 增加收藏夹的搜索功能
-4. 优化后退按钮(以前是返回父文件夹,现在是后退,最多后退 20 步)
-5. 增加优先下载小文件选项
-6. 增加雪碧图里视频信息的显示和保存雪碧图按钮
-7. 网盘页顶部路径默认隐藏需要在设置里勾选显示
-8. 修正m3u8播放链接15分钟后失效的 BUG (现在4小时)
-9. 修正之前部分版本代理设置被覆盖的 BUG
-10. 增加自定义缓存位置功能
-11. 增加帮助文档
-
-
-#### 2021/11/29
-
-1. 修正 2.11.28 下载显示出错的 BUG
-1. 修正登录时遇到二次验证导致点击登录按钮无反应的 BUG
-2. 修正自 v2.11.07 开始不能上传体积为 0 的文件的 BUG
-3. 修正 v2.11.16 上传文件时占用内存过多的问题
-4. 11.16 里 60 文件同时上传会占用大量内存,11.28 里优化为只占用 400MB 以内的内存
-
-5. 修正传输完自动关机触发时机不准确的 BUG
-6. 修正上传时遇到没有访问权限的文件/文件夹时上传中队列卡住的 BUG
-7. 增加视频文件洗码功能
-8. 增加右侧文件拖动到左侧文件夹树(移动文件)功能
-9. 优化远程 Aria2 下载功能并修复断线后自动重连
-10. 优化本地 Aria2,无法连接时会尝试自动重启一次 Aria2 进程
-11. 增加任务栏的下载中上传中进度提示(win/mac)
-12. 底部状态栏显示总传输的预估剩余时间
-13. 增加上传时跳过同名文件的设置项
-14. 优化盘内文件搜索支持选择分类
-15. 一些细节优化
-
-
-
-#### 2021/11/14
-1. 增加创建分享、编辑分享、管理分享功能
-2. 完善导入分享功能,支持部分导入和完整导入
-3. 增加网盘内文件搜索功能
-4. 增加下载时自动过滤违规文件的设置
-5. 增加对禁止分享的文件的图标
-6. 增加文件/文件夹置顶功能
-7. 增加主题跟随系统
-8. 增加下载上传完成后自动关机设置
-9. 完善 mac 和 linux 下自定义播放软件功能
-10. 恢复视频文件雪碧图,增加复制 M3U8 链接和原始视频链接功能
-11. 修正 linux 下上传时会自动过滤软链接文件
-
-
-
-#### 2021/11/07
-
-1. 优化一次性上传或下载大量文件时的界面卡顿(参阅 挑战一百万.md)
-2. 创建日期文件夹支持编号了
-3. 新增定时清理回收站功能
-4. 新增我创建的分享列表功能(没做完)
-5. 增加文件列表显示限制(减少加载中)
-6. 恢复导入阿里云盘分享链接功能(仅全部导入)
-7. 恢复新建文件功能
-8. 恢复版本升级提示功能
-9. 修正 windows 下载位置不能选择根目录的 BUG
-10. 修正不能上传大于 97.6GB 的文件的问题
-11. 修正上传速度显示不准确的 BUG
-12. 修正不能同时下载同一个文件(下载到不同的位置)的 BUG
-13. 优化部分文件格式图标
-
-
-
-#### 2021/10/31
-
-1. 增加文件列表的缩略图模式
-2. 修正v2.10.17和v2.10.19版本里一个严重的BUG(删除文件时可能会错误选中父文件夹一起删除)
-3. 去除彻底删除按钮
-4. 回收站增加清理回收站按钮(一键删除回收站内全部文件)
-5. 增加上传和下载的文件过滤功能(自动跳过特定格式的文件)
-6. 修正左侧文件夹树和右侧文件列表的互动关联
-7. 恢复重命名功能和移动复制功能
-
-
-#### 2021/10/19
-
-1. 优化文件列出逻辑,节省一半的等待加载中时间
-
-2. 优化v2.9一个文件夹直接包含大量子文件夹时的卡顿和内存剧增问题
- 一个文件夹里直接包含 17000 个子文件夹时,打开文件夹 v2.9 需要占用 700MB 内存, v2.10 需要占用 190MB 内存
- v2.9 当一个文件夹里包含 3000 个以上的子文件夹时,小白羊文件夹树会卡顿
- v2.10 无所谓多少个子文件夹,不会卡顿
-
-3. 优化v2.9网盘包含有巨量文件夹时,启动后前几秒会卡顿的问题
-
-4. 优化v2.9上下传记录的本地数据库体积
- 长期大量上传下载会产生较大的本地记录数据,现在会自动清理
-
-5. 修正v2.9统计文件夹体积功能的本地缓存和运行时CPU内存占用
- 开启统计文件夹体积功能后,我网盘里有 2 万个文件夹和 31 万个文件,v2.9 会产生 167MB 的缓存,v2.10 会产生 8MB 的缓存
- 修正了一个会导致 CPU 和内存占用高的 BUG(用户账号 token 失效时,会因为定时统计功能导致 CPU 和内存占用很高)
-
-6. 优化在线预览视频现在支持很多种播放器了
- 当前只适配了 windows (测试了 MPV,Potplayer,VLC media player,KMPlayer,恒星播放器,SMPlayer)
- macos 和 linux 稍后会适配,现在仍旧只能用 mpv 播放器
-
-7. 增加在线预览 word/excel/ppt/pdf 文件的功能
- 当前,大部分音视频格式,大部分图片格式,word/excel/ppt/pdf/txt,200 余种常见文本格式 都可以在线预览了
-
-8. 修正在文件夹里搜索后,拖动搜索结果里的文件上传,上传文件名错误的 BUG
-
-9. 优化上传前的 sha1 校验速度,提升上传速度
-
-10. 美化了一下界面
-11. 增加是否按照完整网盘路径保存的设置
-12. 增加关闭窗口立即退出的设置
-13. 增加双击才打开文件、文件夹的设置
-14. 增加清理缓存的设置
-15. 增加运行日志的设置
-16. 文件夹树的宽度可以拖动调整了
-17. 图片、Office、文本预览现在是单独窗口了
-18. 修正一些文件格式识别不准确的 BUG
-
-#### 2021/09/24
-
-1. 修正上传 20GB 以上的文件时,断点续传时进度不准确的 BUG
-2. 取消文件列表的加载中状态提示,快速展现文件列表
-3. 更新文件列表缓存方式,数据库文件体积减少 73% (14 万个文件从 240MB 降低为 60MB)
-4. 增加是否统计文件夹体积的设置开关,减少网盘内文件过多时的白屏问题
-5. 同步 v2.9.24 源码到 github
-
-#### 2021/09/19
-
-1. 删除秒传相关功能
-2. 修正 v2.8.30 里 aria2 远程模式连接失败的 BUG
-3. 修正偶发文件列表只显示占位符不显示文件名的 BUG
-4. 修正移动文件后选中文件数显示错误的 BUG
-5. 修正批量重命名取消勾选文件夹时子文件名计算错误的 BUG
-6. 修正批量重命名点击刷新后因一直加载,不能关闭的 BUG
-7. 增加对文件名结尾的点和空格的清理,修正这些文件下载失败的 BUG
-8. 修正闲置长时间后上传文件可能出现获取上传地址失败的 BUG
-9. 减少因并发数太高容易出现的操作失败 BUG
-10. 修正等宽图片预览时,切换下一张后滚动条没有自动回到顶部的 BUG
-11. 增加文件列表(F5 键刷新文件,Back 键返回上级文件夹),等宽图片预览(← 上一张,→ 下一张)的快捷键
-12. 增加点击头像图片时自动刷新网盘空间用量
-13. 增加文件夹独立排序选项
-14. 增加直接彻底删除文件的右键菜单
-
-15. 升级数据库架构,提升了加载文件列表的性能,本周重点就是此项,性能提升涉及方方面面的细节,大部分以前加载慢的功能都有了极明显的提升,例如一次性上传包含 10 万个文件的文件夹,不会出现任何卡顿了
-
-16. 修正 v2.9.15 里长时间后上传文件时出现获取上传地址失败的 BUG
-17. 增加上传/下载任务出错后等 1 分钟自动重试功能,可以放心挂机下载、挂机上传了
-
-#### 2021/08/30
-1. Fix 修正 v1.6.29 大量上传下载后会生成大体积的 数据库 的 BUG
-2. Fix 修正 v1.6.29 导入阿里云盘分享链接失败的 BUG
-3. Fix 修正 v1.6.29 上传途中重启程序后,重新上传不会断点续传的 BUG
-4. Fix 修正部分违规视频不能播放的 BUG,现在可以使用"优先播放转码视频"模式播放了
-
-#
-
-1. Add 增加阿里云盘官方登录接口(手机短信、账号密码、APP 扫码登录)
-2. Add 增加多个账号同时登录、切换功能
-3. Add 增加 Aria 远程连接设置,可以把文件直接下载到远程电脑/VPS/NAS/Docker
-4. Add 增加文件名颜色标记,批量标记功能,观看视频自动标记功能
-5. Add 增加文件、文件夹详情功能(文件夹大小,包含文件数),视频文件的雪碧图
-6. Add 增加新的图片预览模式,可以放大/缩小/旋转/幻灯片播放
-7. Add 增加代码高亮/ json 格式化显示 / txt 在线预览功能
-8. Add 增加快速创建日期格式的文件夹
-9. Add 增加可选择文件夹是否和文件一起排序了
-10. Add 增加所有文件夹体积的显示,可以按照体积排序文件夹了
-11. Add windows 上支持 Potplayer 播放器了
-12. Add 顶部快捷路径跳转和区间选择功能
-
-#
-
-1. Pro 优化文件复制功能,可极速复制 TB 级/上万文件 到网盘的其他位置
-2. Pro 优化导入分享功能,在导入时可以选择网盘里的保存位置,可以勾选要保存的 文件/文件夹
-3. Pro 优化上传功能,现在部分不能秒传的大文件,上传前不再需要计算 sha1 了(减少上传时间)
-4. Pro 优化 sha1 计算逻辑和性能,同时最多 3 个文件计算 sha1,机械硬盘不会掉速,CPU 不会爆满
-5. Pro 现在 windows/macos/linux 都支持拖拽文件、文件夹上传了
-6. Pro 优化批量重命名功能,支持勾选文件,支持重命名多级子文件夹,支持 替换/删除/增加/序号/随机字符 等方式
-7. Pro 优化在线解压功能,支持全部解压和勾选文件解压,支持有密码的压缩包
-
-#### 2021/06/29
-Fix 优化重命名、搜索输入框大小
-Fix 修正下载中、上传中页面因进度条动画导致的GPU占用过高的BUG
-Fix 中文名导致偶有macos启动失败的BUG
-Add 导入阿里云盘分享链接的功能
-Add 导入115网盘分享链接的功能
-
-
-#### 2021/06/21
-Fix 显示用户昵称和头像
-Fix 完善对字体的支持(可以随意更换自己喜欢的字体了),完善文字大小设置功能
-Fix 完善在线预览图片功能(支持旋转,文件夹内全部图片上一张下一张查看)
-Fix 文件名是.(点)时导致的创建下载任务失败的BUG
-Fix 创建文件夹太快偶发点击文件夹名不能进入的BUG
-Add Windows上支持批量拖拽文件/文件夹上传
-Add 选择文件/文件夹计算秒传信息保存到网盘内txt文件的功能
-Add 导入txt文件类型的秒传链接(支持文件夹嵌套)
-Add 新增相册功能(文件可以在相册和网盘之间移动复制)
-
-
-#### 2021/06/13
-Fix 在下载大文件时Aria在某些系统上强制分配硬盘BUG导致下载进度卡死
-Fix 优化Aria的连接性,减少出错崩溃
-Fix Mac版输出大量无用日志的BUG
-Fix 一堆UI细节上的完善
-Add 复制文件到...的功能(官方只有移动到...)
-Add 批量重命名功能(替换/删除字符,增加前缀,正则表达式替换)
-Add 聚合搜索功能(当前搜不到什么,要等以后大家主动分享)
-Add 初步支持在线解压缩(zip,rar)
-Ver 更新到Flutter2.2.1
-
-
-#### 2021/06/10
-Fix 因阿里云盘API升级导致的无法加载文件列表的BUG
-Fix 选择上传文件夹时 可能 需要长时间等待的BUG
-Fix 批量下载大量子文件夹时 可能 需要长时间等待的BUG
-Fix 修正回收站内文件无法在线播放的BUG
-Fix 增加一些在线播放视频格式的支持(m2ts/hevc....)
-Add 增加对违规文件的标识
-Add 增加深色模式
-Add 下载失败时的一些错误提示
-Del 去除创建秒传链接的功能,仅支持导入秒传链接(115:// 、aliyun://)
-
-#### 2021/06/06
-1. Fix 批量下载时只解析了第一个选中的文件夹的严重BUG
-2. Fix 大量操作更新为异步操作,极大的减少了操作等待时间
-3. Fix 因阿里云盘升级导致扫码登陆失败的BUG
-4. Add 支持导入李恒道版本秒传链接
-
-
-
-#### 2021/06/05
-1. Add 秒传短链接功能(创建秒传链接、导入别人分享的短链接、短链接本地历史记录)
-2. Add 增加115链接批量导入功能(靠运气)
-3. Add 增加在线预览文本文件功能
-
-4. Fix 因阿里云盘升级导致扫码登陆失败的BUG
-5. Fix 阿里云盘对单次批量操作最多限制100条的限制
-6. Fix 在线预览图片时图片大小缩放BUG
-7. Fix 按文件名排序时不准确的BUG
-
-
-#### 2021/05/31
-1. Add 上传文件、文件夹功能
-2. Add 在线预览图片
-3. Add 移动文件、文件夹功能
-4. Fix 优化启动时启动后台提示
-5. Fix 延长下载链接时效(15分钟->4小时)
-6. Fix 文件夹内包含大量文件时多次操作可能回重复拉取的BUG
-
-
-
-#### 2021/05/25
-1. 上传第一个开发中版本仅供测试
-2. 支持 扫码登录/Cookie登录
-3. 支持 阿里云盘基本功能
-4. 支持 在线预览全格式原画视频(非转码)
-5. 支持 批量下载文件/文件夹,只要阿里云不限速,就是满速下载
diff --git a/aliyunpan/electron-builder.json b/aliyunpan/electron-builder.json
index 904948784b..ee0a30ab69 100644
--- a/aliyunpan/electron-builder.json
+++ b/aliyunpan/electron-builder.json
@@ -22,8 +22,9 @@
"hardenedRuntime": true,
"category": "public.app-category.utilities",
"extraResources": [
- { "from": "./static/engine/darwin/${arch}", "to": "./engine" },
- { "from": "./static/images/icon.icns", "to": "./images/icon.icns"}
+ { "from": "./static/images/icon.icns", "to": "./images/icon.icns"},
+ { "from": "./static/images/icon_24x24.png", "to": "./images/icon_24x24.png"},
+ { "from": "./static/engine/darwin/${arch}", "to": "./engine"}
],
"target": [
{ "target": "dmg", "arch": [ "x64", "arm64" ] }
@@ -34,11 +35,15 @@
"category": "Network",
"artifactName": "XBYDriver-${version}-linux-${arch}.${ext}",
"extraResources": [
+ { "from": "./static/images/icon_24x24.png", "to": "./images/icon_24x24.png"},
+ { "from": "./static/images/icon_64x64.png", "to": "./images/icon_64x64.png"},
+ { "from": "./static/images/icon_256x256.png", "to": "./images/icon_256x256.png"},
{ "from": "./static/engine/linux/${arch}", "to": "./engine"}
],
"target": [
{ "target": "AppImage", "arch": [ "x64", "arm64", "armv7l" ] },
- { "target": "deb", "arch": [ "x64", "arm64", "armv7l" ] }
+ { "target": "deb", "arch": [ "x64", "arm64", "armv7l" ] },
+ { "target": "pacman", "arch": [ "x64", "arm64", "armv7l" ] }
]
},
"win": {
@@ -46,11 +51,12 @@
"artifactName": "XBYDriver-${version}-win-${arch}.${ext}",
"requestedExecutionLevel": "asInvoker",
"extraResources": [
- { "from": "./static/engine/win32/${arch}", "to": "./engine"},
- { "from": "./static/images/icon_256x256.ico", "to": "./images/icon_256x256.ico"}
+ { "from": "./static/images/icon_64x64.png", "to": "./images/icon_64x64.png"},
+ { "from": "./static/images/icon_256x256.ico", "to": "./images/icon_256x256.ico"},
+ { "from": "./static/engine/win32/${arch}", "to": "./engine"}
],
"target": [
- { "target": "nsis", "arch": [ "x64", "ia32", "arm64"] }
+ { "target": "nsis", "arch": [ "x64", "ia32", "arm64" ] }
]
},
"dmg": {
@@ -69,7 +75,10 @@
},
"publish": [
{
+ "owner": "gaozhangmin",
+ "repo": "aliyunpan",
"provider": "github",
+ "publishAutoUpdate": false,
"releaseType": "draft"
}
]
diff --git a/aliyunpan/electron/main/core/ipcEvent.ts b/aliyunpan/electron/main/core/ipcEvent.ts
index babb399a55..a4888fb06c 100644
--- a/aliyunpan/electron/main/core/ipcEvent.ts
+++ b/aliyunpan/electron/main/core/ipcEvent.ts
@@ -1,14 +1,14 @@
import { AppWindow, createElectronWindow, Referer, ua } from './window'
import path from 'path'
import is from 'electron-is'
-import { app, BrowserWindow, dialog, ipcMain, session, shell } from 'electron'
+import { app, BrowserWindow, dialog, ipcMain, Menu, powerSaveBlocker, session, shell } from 'electron'
import { existsSync, writeFileSync } from 'fs'
import { exec, execFile, spawn, SpawnOptions } from 'child_process'
import { ShowError } from './dialog'
-// @ts-ignore
-import {getResourcesPath, getStaticPath, getUserDataPath} from '../utils/mainfile'
+import { getStaticPath, getUserDataPath } from '../utils/mainfile'
import { portIsOccupied } from '../utils'
+let psbId: any
export default class ipcEvent {
private constructor() {
}
@@ -16,6 +16,7 @@ export default class ipcEvent {
static handleEvents() {
this.handleWebToElectron()
this.handleWebToElectronCB()
+ this.handleShowContextMenu()
this.handleWebShowOpenDialogSync()
this.handleWebShowSaveDialogSync()
this.handleWebShowItemInFolder()
@@ -44,13 +45,23 @@ export default class ipcEvent {
let mainWindow = AppWindow.mainWindow
if (data.cmd && data.cmd === 'close') {
if (mainWindow && !mainWindow.isDestroyed()) mainWindow.hide()
+ } else if (data.cmd && data.cmd === 'relaunch') {
+ if (mainWindow && !mainWindow.isDestroyed()) {
+ mainWindow.destroy()
+ mainWindow = undefined
+ }
+ try {
+ app.relaunch({ args: process.argv.slice(1).concat(['--relaunch']) })
+ app.exit(0)
+ } catch {
+ }
} else if (data.cmd && data.cmd === 'exit') {
if (mainWindow && !mainWindow.isDestroyed()) {
mainWindow.destroy()
mainWindow = undefined
}
try {
- app.exit()
+ app.exit(0)
} catch {
}
} else if (data.cmd && data.cmd === 'minsize') {
@@ -63,6 +74,26 @@ export default class ipcEvent {
mainWindow.maximize()
}
}
+ } else if (data.cmd && data.cmd === 'minsizeAudio') {
+ if (AppWindow.auidoWindow && !AppWindow.auidoWindow.isDestroyed()) AppWindow.auidoWindow.minimize()
+ } else if (data.cmd && data.cmd === 'maxsizeAudio') {
+ if (AppWindow.auidoWindow && !AppWindow.auidoWindow.isDestroyed()) {
+ if (AppWindow.auidoWindow.isMaximized()) {
+ AppWindow.auidoWindow.unmaximize()
+ } else {
+ AppWindow.auidoWindow.maximize()
+ }
+ }
+ } else if (data.cmd && data.cmd === 'minsizeVideo') {
+ if (AppWindow.videoWindow && !AppWindow.videoWindow.isDestroyed()) AppWindow.videoWindow.minimize()
+ } else if (data.cmd && data.cmd === 'maxsizeVideo') {
+ if (AppWindow.videoWindow && !AppWindow.videoWindow.isDestroyed()) {
+ if (AppWindow.videoWindow.isMaximized()) {
+ AppWindow.videoWindow.unmaximize()
+ } else {
+ AppWindow.videoWindow.maximize()
+ }
+ }
} else if (data.cmd && (Object.hasOwn(data.cmd, 'launchStart')
|| Object.hasOwn(data.cmd, 'launchStartShow'))) {
const launchStart = data.cmd.launchStart
@@ -84,6 +115,19 @@ export default class ipcEvent {
!launchStartShow && settings.args.push('--openAsHidden')
}
app.setLoginItemSettings(settings)
+ } else if (data.cmd && data.cmd === 'preventSleep') {
+ if (data.flag) {
+ if (psbId && powerSaveBlocker.isStarted(psbId)) {
+ return
+ }
+ psbId = powerSaveBlocker.start('prevent-app-suspension')
+ } else {
+ if (typeof psbId === 'undefined' || !powerSaveBlocker.isStarted(psbId)) {
+ return
+ }
+ powerSaveBlocker.stop(psbId)
+ psbId = undefined
+ }
} else {
event.sender.send('ElectronToWeb', 'mainsenddata')
}
@@ -109,6 +153,25 @@ export default class ipcEvent {
})
}
+ private static handleShowContextMenu() {
+ ipcMain.on('show-context-menu', (event, params) => {
+ const { showCut, showCopy, showPaste } = params
+ const window = BrowserWindow.fromWebContents(event.sender)
+ // 制作右键菜单
+ let template: Array = [
+ // 设置选项是否可见
+ { role: 'selectAll', label: '全选' },
+ { role: 'copy', label: '复制', visible: showCopy },
+ { role: 'cut', label: '剪切', visible: showCut },
+ { role: 'paste', label: '粘贴', visible: showPaste },
+ { role: 'undo', label: '撤销' }
+ ]
+ // 显示菜单
+ const contextMenu = Menu.buildFromTemplate(template)
+ contextMenu.popup({ window })
+ })
+ }
+
private static handleWebShowOpenDialogSync() {
ipcMain.on('WebShowOpenDialogSync', (event, config) => {
dialog.showOpenDialog(AppWindow.mainWindow!, config).then((result) => {
@@ -174,11 +237,10 @@ export default class ipcEvent {
command = `${argsToStr(data.command)}`
}
const subProcess = spawn(command, data.args, options)
- const isRunning = process.kill(subProcess.pid, 0)
subProcess.unref()
event.returnValue = {
pid: subProcess.pid,
- isRunning: isRunning,
+ subProcess: subProcess,
execCmd: data,
options: options,
exitCode: subProcess.exitCode
@@ -292,9 +354,11 @@ export default class ipcEvent {
windowsHide: false,
windowsVerbatimArguments: true
}
+ const fileAllocation = is.macOS() ? 'none' : (is.windows() ? 'falloc' : 'trunc')
const args = [
`--stop-with-process=${argsToStr(process.pid)}`,
`--conf-path=${argsToStr(confPath)}`,
+ `--file-allocation=${argsToStr(fileAllocation)}`,
`--rpc-listen-port=${argsToStr(listenPort)}`,
'-D'
]
@@ -455,13 +519,20 @@ export default class ipcEvent {
}
private static handleWebOpenWindow() {
+ // let winWidth = AppWindow.winWidth
+ // if (winWidth < 1080) winWidth = 1080
ipcMain.on('WebOpenWindow', (event, data) => {
- const win = createElectronWindow(AppWindow.winWidth, AppWindow.winHeight, true, 'main2', data.theme)
+ const win = createElectronWindow(data.width || AppWindow.winWidth, data.height || AppWindow.winHeight, true, 'main2', data.theme)
win.on('ready-to-show', function() {
win.webContents.send('setPage', data)
win.setTitle('预览窗口')
win.show()
})
+ if (data.page === 'PageAudio') {
+ AppWindow.auidoWindow = win
+ } else if (data.page === 'PageVideo') {
+ AppWindow.videoWindow = win
+ }
})
}
diff --git a/aliyunpan/electron/main/core/window.ts b/aliyunpan/electron/main/core/window.ts
index ddd5dc018f..c77b25297f 100644
--- a/aliyunpan/electron/main/core/window.ts
+++ b/aliyunpan/electron/main/core/window.ts
@@ -1,17 +1,18 @@
-import { app, BrowserWindow, Menu, MenuItem, MessageChannelMain, nativeTheme, screen, session, Tray } from 'electron'
-// @ts-ignore
-import { getAsarPath, getResourcesPath, getStaticPath, getUserDataPath } from '../utils/mainfile'
-import fs, { existsSync, readFileSync, writeFileSync } from 'fs'
+import { app, BrowserWindow, ipcMain, Menu, MessageChannelMain, nativeTheme, screen, shell, Tray } from 'electron'
+import { getAsarPath, getStaticPath, getUserDataPath } from '../utils/mainfile'
+import { existsSync, readFileSync, writeFileSync } from 'fs'
import is from 'electron-is'
import { ShowErrorAndRelaunch } from './dialog'
-
-export const ua = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/102.0.5005.63 Safari/537.36 Edg/102.0.1245.33'
-export const Referer = 'https://www.aliyundrive.com/'
+const DEBUGGING = !app.isPackaged
+export const ua = 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) aDrive/4.12.0 Chrome/108.0.5359.215 Electron/22.3.24 Safari/537.36'
+export const Referer = 'https://www.alipan.com/'
export const AppWindow: {
mainWindow: BrowserWindow | undefined
uploadWindow: BrowserWindow | undefined
downloadWindow: BrowserWindow | undefined
+ videoWindow: BrowserWindow | undefined
+ auidoWindow: BrowserWindow | undefined
appTray: Tray | undefined
winWidth: number
winHeight: number
@@ -20,18 +21,13 @@ export const AppWindow: {
mainWindow: undefined,
uploadWindow: undefined,
downloadWindow: undefined,
+ videoWindow: undefined,
+ auidoWindow: undefined,
appTray: undefined,
winWidth: 0,
winHeight: 0,
winTheme: ''
}
-export const AppMenu: {
- menuEdit: Electron.Menu | undefined
- menuCopy: Electron.Menu | undefined
-} = {
- menuEdit: undefined,
- menuCopy: undefined
-}
let timerUpload: NodeJS.Timeout | undefined
const debounceUpload = (fn: any, wait: number) => {
@@ -107,7 +103,10 @@ export function createMainWindow() {
AppWindow.mainWindow.on('resize', () => {
debounceResize(function() {
try {
- if (AppWindow.mainWindow && AppWindow.mainWindow.isMaximized() == false && AppWindow.mainWindow.isMinimized() == false && AppWindow.mainWindow.isFullScreen() == false) {
+ if (AppWindow.mainWindow
+ && !AppWindow.mainWindow.isMaximized()
+ && !AppWindow.mainWindow.isMinimized()
+ && !AppWindow.mainWindow.isFullScreen()) {
const s = AppWindow.mainWindow!.getSize()
const configJson = getUserDataPath('config.json')
writeFileSync(configJson, `{"width":${s[0].toString()},"height": ${s[1].toString()}}`, 'utf-8')
@@ -133,6 +132,7 @@ export function createMainWindow() {
AppWindow.mainWindow.on('ready-to-show', function() {
AppWindow.mainWindow!.webContents.send('setPage', { page: 'PageMain' })
AppWindow.mainWindow!.webContents.send('setTheme', { dark: nativeTheme.shouldUseDarkColors })
+ AppWindow.mainWindow.maximize()
AppWindow.mainWindow!.setTitle('阿里云盘小白羊')
if (is.windows() && process.argv && process.argv.join(' ').indexOf('--openAsHidden') < 0) {
AppWindow.mainWindow!.show()
@@ -156,24 +156,11 @@ export function createMainWindow() {
createDownload()
}
-export function createMenu() {
- AppMenu.menuEdit = new Menu()
- AppMenu.menuEdit.append(new MenuItem({ label: '剪切', role: 'cut' }))
- AppMenu.menuEdit.append(new MenuItem({ label: '复制', role: 'copy' }))
- AppMenu.menuEdit.append(new MenuItem({ label: '粘贴', role: 'paste' }))
- AppMenu.menuEdit.append(new MenuItem({ label: '删除', role: 'delete' }))
- AppMenu.menuEdit.append(new MenuItem({ label: '全选', role: 'selectAll' }))
- AppMenu.menuCopy = new Menu()
- AppMenu.menuCopy.append(new MenuItem({ label: '复制', role: 'copy' }))
- AppMenu.menuCopy.append(new MenuItem({ label: '全选', role: 'selectAll' }))
-}
-
-
export function createTray() {
const trayMenuTemplate = [
{
label: '显示主界面',
- click: function () {
+ click: function() {
if (AppWindow.mainWindow && AppWindow.mainWindow.isDestroyed() == false) {
if (AppWindow.mainWindow.isMinimized()) AppWindow.mainWindow.restore()
AppWindow.mainWindow.show()
@@ -185,7 +172,7 @@ export function createTray() {
},
{
label: '彻底退出并停止下载',
- click: function () {
+ click: function() {
if (AppWindow.mainWindow) {
AppWindow.mainWindow.destroy()
AppWindow.mainWindow = undefined
@@ -242,12 +229,9 @@ export function createElectronWindow(width: number, height: number, center: bool
preload: getAsarPath('dist/electron/preload/index.js')
}
})
-
-
win.removeMenu()
- if (is.dev()) {
- const url = `http://localhost:${process.env.VITE_DEV_SERVER_PORT}`
- win.loadURL(url, { userAgent: ua, httpReferrer: Referer })
+ if (DEBUGGING) {
+ win.loadURL(process.env.VITE_DEV_SERVER_URL, { userAgent: ua, httpReferrer: Referer })
} else {
win.loadURL('file://' + getAsarPath('dist/' + page + '.html'), {
userAgent: ua,
@@ -255,8 +239,10 @@ export function createElectronWindow(width: number, height: number, center: bool
})
}
- if (is.dev() && devTools) {
- if (width < 100) win.setSize(800, 600)
+ if (DEBUGGING && devTools) {
+ if (width < 100) {
+ win.setSize(800, 680)
+ }
win.show()
win.webContents.openDevTools({ mode: 'bottom' })
} else {
@@ -266,11 +252,14 @@ export function createElectronWindow(width: number, height: number, center: bool
}
})
}
- win.webContents.on('before-input-event', (_, input: Electron.Input) => {
- if (input.type === 'keyDown' && input.control && input.shift && input.key === 'F12') {
- win.webContents.isDevToolsOpened()
- ? win.webContents.closeDevTools()
- : win.webContents.openDevTools({ mode: 'undocked' })
+ if (page == 'main2') {
+ handleWinCmd(win)
+ }
+ handleWebView(win)
+ win.webContents.on('will-navigate', (e, url) => {
+ e.preventDefault()
+ if (!url.includes(process.env.VITE_DEV_SERVER_URL)) {
+ shell.openExternal(url)
}
})
win.webContents.on('did-create-window', (childWindow) => {
@@ -281,8 +270,83 @@ export function createElectronWindow(width: number, height: number, center: bool
return win
}
+function handleWebView(win: BrowserWindow) {
+ // 处理DevTools
+ win.webContents.on('before-input-event', (_, input: Electron.Input) => {
+ if (input.type === 'keyDown' && input.control && input.shift && input.key === 'F12') {
+ win.webContents.isDevToolsOpened()
+ ? win.webContents.closeDevTools()
+ : win.webContents.openDevTools({ mode: 'undocked' })
+ }
+ })
+ // 处理webview跳转
+ win.webContents.addListener('did-attach-webview', (event, webContent) => {
+ webContent.on('before-input-event', (_, input: Electron.Input) => {
+ if (input.type === 'keyDown' && input.control && input.shift && input.key === 'F12') {
+ webContent.isDevToolsOpened()
+ ? webContent.closeDevTools()
+ : webContent.openDevTools({ mode: 'undocked' })
+ }
+ })
+ // 不允许的网址则阻止页面跳转并拉取浏览器展示页面
+ webContent.setWindowOpenHandler((details) => {
+ let url = details.url
+ if (!/(aliyundrive|alipan).com\/s\/[0-9a-zA-Z_]{11,}/.test(url)) {
+ webContent.loadURL(url)
+ } else {
+ win.webContents.send('webview-new-window', webContent.id, details)
+ }
+ return { action: 'deny' }
+ })
+ webContent.on('will-redirect', (e, url) => {
+ if (!/(aliyundrive|alipan).com\/s\/[0-9a-zA-Z_]{11,}/.test(url)) {
+ webContent.loadURL(url)
+ } else {
+ win.webContents.send('webview-redirect', webContent.id, url)
+ }
+ e.preventDefault()
+ })
+ // 拦截链接跳转
+ webContent.on('will-navigate', (e, url) => {
+ if (/(aliyundrive|alipan).com\/s\/[0-9a-zA-Z_]{11,}/.test(url)) {
+ e.preventDefault()
+ }
+ })
+ })
+}
+
+function handleWinCmd(win: BrowserWindow) {
+ ipcMain.on('WebToWindow', (event, data) => {
+ if (data.cmd && data.cmd === 'close') {
+ if (win && !win.isDestroyed()) win.close()
+ } else if (data.cmd && data.cmd === 'minsize') {
+ if (win && !win.isDestroyed()) win.minimize()
+ } else if (data.cmd && data.cmd === 'top') {
+ if (win && !win.isDestroyed()) {
+ if (win.isAlwaysOnTop()) {
+ event.returnValue = 'untop'
+ win.setAlwaysOnTop(false)
+ } else {
+ event.returnValue = 'top'
+ win.setAlwaysOnTop(true, 'status')
+ }
+ }
+ } else if (data.cmd && data.cmd === 'maxsize') {
+ if (win && !win.isDestroyed()) {
+ if (win.isMaximized()) {
+ event.returnValue = 'unmaximize'
+ win.unmaximize()
+ } else {
+ event.returnValue = 'maximize'
+ win.maximize()
+ }
+ }
+ }
+ })
+}
+
function creatUploadPort() {
- debounceUpload(function () {
+ debounceUpload(function() {
if (AppWindow.mainWindow && AppWindow.uploadWindow && AppWindow.uploadWindow.isDestroyed() == false) {
const { port1, port2 } = new MessageChannelMain()
AppWindow.mainWindow.webContents.postMessage('setUploadPort', undefined, [port1])
@@ -322,6 +386,7 @@ function createUpload() {
createUpload()
}
})
+ // AppWindow.uploadWindow.webContents.openDevTools({ mode: 'undocked' })
AppWindow.uploadWindow.hide()
}
@@ -348,4 +413,4 @@ function createDownload() {
AppWindow.downloadWindow.webContents.closeDevTools()
AppWindow.downloadWindow.hide()
-}
\ No newline at end of file
+}
diff --git a/aliyunpan/electron/main/index.ts b/aliyunpan/electron/main/index.ts
index 6f9601b0a2..5a82c64661 100644
--- a/aliyunpan/electron/main/index.ts
+++ b/aliyunpan/electron/main/index.ts
@@ -10,4 +10,4 @@ app.setAboutPanelOptions({
applicationVersion: '30'
})
-const appLaunch = new launch()
\ No newline at end of file
+const appLaunch = new launch()
diff --git a/aliyunpan/electron/main/launch.ts b/aliyunpan/electron/main/launch.ts
index 6141e9f7a8..d10f9559c2 100644
--- a/aliyunpan/electron/main/launch.ts
+++ b/aliyunpan/electron/main/launch.ts
@@ -1,4 +1,4 @@
-import { AppWindow, createMainWindow, createMenu, createTray } from './core/window'
+import { AppWindow, createMainWindow, createTray } from './core/window'
import { app, ipcMain, session } from 'electron'
import is from 'electron-is'
import fixPath from 'fix-path'
@@ -8,10 +8,11 @@ import { existsSync, readFileSync, writeFileSync } from 'fs'
import { EventEmitter } from 'node:events'
import exception from './core/exception'
import ipcEvent from './core/ipcEvent'
+import path from 'path'
type UserToken = {
access_token: string;
- access_token_v2: string;
+ open_api_access_token: string;
user_id: string;
refresh: boolean
}
@@ -19,7 +20,7 @@ type UserToken = {
export default class launch extends EventEmitter {
private userToken: UserToken = {
access_token: '',
- access_token_v2: '',
+ open_api_access_token: '',
user_id: '',
refresh: false
}
@@ -53,6 +54,7 @@ export default class launch extends EventEmitter {
start() {
exception.handler()
this.setInitArgv()
+ this.loadUserData()
this.handleEvents()
this.handleAppReady()
}
@@ -64,16 +66,22 @@ export default class launch extends EventEmitter {
}
process.env.ELECTRON_DISABLE_SECURITY_WARNINGS = 'true'
process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0'
+ process.env.DIST = path.join(__dirname, '../dist')
+ process.env.VITE_PUBLIC = app.isPackaged
+ ? process.env.DIST
+ : path.join(process.env.DIST, '../public')
app.commandLine.appendSwitch('no-sandbox')
app.commandLine.appendSwitch('disable-web-security')
app.commandLine.appendSwitch('disable-renderer-backgrounding')
app.commandLine.appendSwitch('disable-site-isolation-trials')
- app.commandLine.appendSwitch('disable-features', 'OutOfBlinkCors,SameSiteByDefaultCookies,CookiesWithoutSameSiteMustBeSecure')
- app.commandLine.appendSwitch('ignore-connections-limit', 'bj29.cn-beijing.data.alicloudccp.com,alicloudccp.com,api.aliyundrive.com,aliyundrive.com')
+ app.commandLine.appendSwitch('disable-features', 'OutOfBlinkCors,SameSiteByDefaultCookies,CookiesWithoutSameSiteMustBeSecure,BlockInsecurePrivateNetworkRequests')
+ app.commandLine.appendSwitch('ignore-connections-limit', 'bj29-enet.cn-beijing.data.alicloudccp.com,bj29-hz.cn-hangzhou.data.alicloudccp.com,bj29.cn-beijing.data.alicloudccp.com,alicloudccp.com,api.aliyundrive.com,aliyundrive.com,api.alipan.com,alipan.com')
app.commandLine.appendSwitch('ignore-certificate-errors')
- app.commandLine.appendSwitch('proxy-bypass-list', '')
+ app.commandLine.appendSwitch('proxy-bypass-list', '*')
app.commandLine.appendSwitch('wm-window-animations-disabled')
+ app.commandLine.appendSwitch('enable-features', 'PlatformHEVCDecoderSupport')
+ app.commandLine.appendSwitch('force_high_performance_gpu')
app.name = 'alixby3'
if (is.windows()) {
@@ -124,45 +132,51 @@ export default class launch extends EventEmitter {
} catch (err) {
}
session.defaultSession.webRequest.onBeforeSendHeaders((details, cb) => {
- const should115Referer = details.url.indexOf('.115.com') > 0
const shouldGieeReferer = details.url.indexOf('gitee.com') > 0
- const shouldAliOrigin = details.url.indexOf('.aliyundrive.com') > 0
- const shouldAliReferer = !should115Referer && !shouldGieeReferer && (!details.referrer || details.referrer.trim() === '' || /(\/localhost:)|(^file:\/\/)|(\/127.0.0.1:)/.exec(details.referrer) !== null)
- const shouldToken = details.url.includes('aliyundrive') && details.url.includes('download')
- const shouldOpenApiToken = details.url.includes('adrive/v1.0')
+ const shouldBiliBili = details.url.indexOf('bilibili.com') > 0
+ const shouldQQTv = details.url.indexOf('v.qq.com') > 0 || details.url.indexOf('video.qq.com') > 0
+ const shouldAliPanOrigin = details.url.indexOf('.aliyundrive.com') > 0 || details.url.indexOf('.alipan.com') > 0
+ const shouldAliReferer = !shouldQQTv && !shouldBiliBili && !shouldGieeReferer && (!details.referrer || details.referrer.trim() === '' || /(\/localhost:)|(^file:\/\/)|(\/127.0.0.1:)/.exec(details.referrer) !== null)
+ const shouldToken = details.url.includes('alipan') && details.url.includes('download')
+ const shouldOpenApiToken = details.url.includes('adrive/v1.0') || details.url.includes('adrive/v1.1')
cb({
cancel: false,
requestHeaders: {
...details.requestHeaders,
- ...(should115Referer && {
- Referer: 'http://115.com/s/swn4bs33z88',
- Origin: 'http://115.com'
- }),
...(shouldGieeReferer && {
Referer: 'https://gitee.com/'
}),
- ...(shouldAliOrigin && {
- Origin: 'https://www.aliyundrive.com'
+ ...(shouldAliPanOrigin && {
+ Origin: 'https://www.alipan.com'
}),
...(shouldAliReferer && {
- Referer: 'https://www.aliyundrive.com/'
+ Referer: 'https://www.alipan.com/'
+ }),
+ ...(shouldBiliBili && {
+ Referer: 'https://www.bilibili.com/',
+ Cookie: 'buvid_fp=4e5ab1b80f684b94efbf0d2f4721913e;buvid3=0679D9AB-1548-ED1E-B283-E0114517315E63379infoc;buvid4=990C4544-0943-1FBF-F13C-4C42A4EA97AA63379-024020214-83%2BAINcbQP917Ye0PjtrCg%3D%3D;',
+ 'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/121.0.0.0 Safari/537.36 Edg/121.0.0.0'
+ }),
+ ...(shouldQQTv && {
+ Referer: 'https://m.v.qq.com/',
+ Origin: 'https://m.v.qq.com',
+ 'user-agent': 'Mozilla/5.0 (Linux; Android 13; SM-G981B) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/116.0.0.0 Mobile Safari/537.36 Edg/121.0.0.0'
}),
...(shouldToken && {
Authorization: this.userToken.access_token
}),
- // ...(shouldOpenApiToken && {
- // Authorization: this.userToken.access_token_v2
- // }),
- 'user-agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) aDrive/4.1.0 Chrome/108.0.5359.215 Electron/22.3.1 Safari/537.36',
- 'X-Canary': 'client=windows,app=adrive,version=v4.1.0',
+ ...(shouldOpenApiToken && {
+ Authorization: this.userToken.open_api_access_token
+ }),
+ 'user-agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) aDrive/4.12.0 Chrome/108.0.5359.215 Electron/22.3.24 Safari/537.36',
+ 'X-Canary': 'client=windows,app=adrive,version=v4.12.0',
'Accept-Language': 'zh-CN,zh;q=0.9'
}
})
})
session.defaultSession.loadExtension(getStaticPath('crx'), { allowFileAccess: true }).then(() => {
createMainWindow()
- createMenu()
createTray()
})
})
@@ -186,9 +200,8 @@ export default class launch extends EventEmitter {
handleAppActivate() {
app.on('activate', () => {
- if (!AppWindow.mainWindow || AppWindow.mainWindow.isDestroyed()){
- createMainWindow()
- } else {
+ if (!AppWindow.mainWindow || AppWindow.mainWindow.isDestroyed()) createMainWindow()
+ else {
if (AppWindow.mainWindow.isMinimized()) AppWindow.mainWindow.restore()
AppWindow.mainWindow.show()
AppWindow.mainWindow.focus()
@@ -218,4 +231,4 @@ export default class launch extends EventEmitter {
}
})
}
-}
\ No newline at end of file
+}
diff --git a/aliyunpan/electron/preload/index.ts b/aliyunpan/electron/preload/index.ts
index ebbd767507..418816e572 100644
--- a/aliyunpan/electron/preload/index.ts
+++ b/aliyunpan/electron/preload/index.ts
@@ -4,96 +4,116 @@ window.Electron = Electron
process.noAsar = true
window.platform = process.platform
-window.WebToElectron = function (data: any) {
+window.WebToElectron = function(data: any) {
try {
ipcRenderer.send('WebToElectron', data)
- } catch {}
+ } catch {
+ }
}
-window.WebToElectronCB = function (data: any, callback: any) {
+window.WebToWindow = function(data: any, callback: any) {
+ try {
+ const backData = ipcRenderer.sendSync('WebToWindow', data)
+ callback && callback(backData)
+ } catch {
+ }
+}
+
+window.WebToElectronCB = function(data: any, callback: any) {
try {
const backData = ipcRenderer.sendSync('WebToElectronCB', data)
- callback(backData)
- } catch {}
+ callback(backData)
+ } catch {
+ }
}
-ipcRenderer.on('ElectronToWeb', function (event, arg) {
-
-})
-ipcRenderer.on('MainSendToken', function (event, arg) {
+ipcRenderer.on('MainSendToken', function(event, arg) {
try {
window.postMessage(arg)
- } catch {}
+ } catch {
+ }
})
-window.WebSpawnSync = function (data: any, callback: any) {
+window.WebSpawnSync = function(data: any, callback: any) {
try {
- const backData = ipcRenderer.sendSync('WebSpawnSync', data)
- callback(backData)
- } catch {}
+ const backData = ipcRenderer.sendSync('WebSpawnSync', data)
+ callback(backData)
+ } catch {
+ }
}
-window.WebExecSync = function (data: any, callback: any) {
+window.WebExecSync = function(data: any, callback: any) {
try {
- const backData = ipcRenderer.sendSync('WebExecSync', data)
- callback(backData)
- } catch {}
+ const backData = ipcRenderer.sendSync('WebExecSync', data)
+ callback(backData)
+ } catch {
+ }
}
-window.WebShowOpenDialogSync = function (config: any, callback: any) {
+window.WebShowOpenDialogSync = function(config: any, callback: any) {
try {
const backData = ipcRenderer.sendSync('WebShowOpenDialogSync', config)
- callback(backData)
- } catch {}
+ callback(backData)
+ } catch {
+ }
}
-window.WebShowSaveDialogSync = function (config: any, callback: any) {
+window.WebShowSaveDialogSync = function(config: any, callback: any) {
try {
const backData = ipcRenderer.sendSync('WebShowSaveDialogSync', config)
- callback(backData)
- } catch {}
+ callback(backData)
+ } catch {
+ }
}
-window.WebShowItemInFolder = function (fullPath: string) {
+window.WebShowItemInFolder = function(fullPath: string) {
try {
ipcRenderer.send('WebShowItemInFolder', fullPath)
- } catch {}
+ } catch {
+ }
}
-window.WebPlatformSync = function (callback: any) {
+window.WebPlatformSync = function(callback: any) {
try {
const backData = ipcRenderer.sendSync('WebPlatformSync')
- callback(backData)
- } catch {}
+ callback(backData)
+ } catch {
+ }
}
-window.WebClearCookies = function (data: any) {
+window.WebClearCookies = function(data: any) {
try {
ipcRenderer.send('WebClearCookies', data)
- } catch {}
+ } catch {
+ }
}
-window.WebClearCache = function (data: any) {
+window.WebClearCache = function(data: any) {
try {
ipcRenderer.send('WebClearCache', data)
- } catch {}
+ } catch {
+ }
}
-window.WebUserToken = function (data: any) {
+window.WebUserToken = function(data: any) {
try {
ipcRenderer.send('WebUserToken', data)
- } catch {}
+ } catch {
+ }
}
-window.WebSaveTheme = function (data: any) {
+window.WebSaveTheme = function(data: any) {
try {
ipcRenderer.send('WebSaveTheme', data)
- } catch {}
+ } catch {
+ }
}
-window.WebReload = function (data: any) {
+window.WebReload = function(data: any) {
try {
ipcRenderer.send('WebReload', data)
- } catch {}
+ } catch {
+ }
}
-window.WebRelaunch = function (data: any) {
+window.WebRelaunch = function(data: any) {
try {
ipcRenderer.send('WebRelaunch', data)
- } catch {}
+ } catch {
+ }
}
window.WebRelaunchAria = async function() {
try {
@@ -116,74 +136,95 @@ window.WebResetAlistPwd = async function(data: any) {
return 0
}
}
-window.WebSetProgressBar = function (data: any) {
+window.WebSetProgressBar = function(data: any) {
try {
- ipcRenderer.send('WebSetProgressBar', data)
- } catch {}
+ ipcRenderer.send('WebSetProgressBar', data)
+ } catch {
+ }
}
-window.WebGetCookies = async function (data: any) {
+window.WebGetCookies = async function(data: any) {
try {
return await ipcRenderer.invoke('WebGetCookies', data)
- } catch {}
+ } catch {
+ }
}
-window.WebSetCookies = function (cookies: any) {
+window.WebSetCookies = function(cookies: any) {
try {
- ipcRenderer.send('WebSetCookies', cookies)
- } catch {}
+ ipcRenderer.send('WebSetCookies', cookies)
+ } catch {
+ }
}
-window.WebOpenWindow = function (data: any) {
+window.WebOpenWindow = function(data: any) {
try {
ipcRenderer.send('WebOpenWindow', data)
- } catch {}
+ } catch {
+ }
}
-window.WebOpenUrl = function (data: any) {
+window.WebOpenUrl = function(data: any) {
try {
ipcRenderer.send('WebOpenUrl', data)
- } catch {}
+ } catch {
+ }
}
-window.WebShutDown = function (data: any) {
+window.WebShutDown = function(data: any) {
try {
- ipcRenderer.send('WebShutDown', data)
- } catch {}
+ ipcRenderer.send('WebShutDown', data)
+ } catch {
+ }
}
-window.WebSetProxy = function (data: { proxyUrl: string }) {
+window.WebSetProxy = function(data: { proxyUrl: string }) {
try {
ipcRenderer.send('WebSetProxy', data)
- } catch {}
+ } catch {
+ }
}
function createRightMenu() {
- window.addEventListener(
- 'contextmenu',
- (e) => {
- try {
- if (e) e.preventDefault()
- if (isEleEditable(e.target)) {
- ipcRenderer.send('WebToElectron', { cmd: 'menuedit' })
- } else {
-
- const selectText = window.getSelection()?.toString()
- if (selectText) ipcRenderer.send('WebToElectron', { cmd: 'menucopy' })
- }
- } catch {}
- },
- false
+ window.addEventListener('contextmenu', (e) => {
+ if (e) e.preventDefault()
+ const target = e.target as HTMLElement
+ // 检查页面是否是有选择的文本 这里显示复制和剪切选项是否可见
+ const selectText = !!window.getSelection().toString()
+ if (selectText || isEleEditable(target)) {
+ // 读取剪切板是否有文本 这里传递粘贴选项是否可见
+ const showPaste = !!navigator.clipboard.readText()
+ // 判断ReadOnly
+ const isReadOnly = target.hasAttribute('readonly')
+ // 发送给主进程让它显示菜单
+ ipcRenderer.send('show-context-menu', {
+ showPaste: !isReadOnly && showPaste,
+ showCopy: selectText,
+ showCut: !isReadOnly && selectText
+ })
+ }
+ }
)
}
function isEleEditable(e: any): boolean {
- if (!e) {
- return false
- }
-
- if ((e.tagName === 'INPUT' && e.type !== 'checkbox') || e.tagName === 'TEXTAREA' || e.contentEditable == 'true') {
+ if (!e) return false
+ if (e.tagName === 'TEXTAREA'
+ || (e.tagName === 'INPUT' && e.type !== 'checkbox')
+ || e.contentEditable == 'true') {
return true
} else {
-
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
return isEleEditable(e.parentNode)
}
}
createRightMenu()
+
+// fix: new-windows event
+ipcRenderer.on('webview-new-window', (e, webContentsId, details) => {
+ const webview = document.getElementById('webview') as any
+ const evt = new Event('new-window', { bubbles: true, cancelable: false })
+ webview.dispatchEvent(Object.assign(evt, details))
+})
+
+ipcRenderer.on('webview-redirect', (e, webContentsId, url) => {
+ const webview = document.getElementById('webview') as any
+ const evt = new Event('will-redirect', { bubbles: true, cancelable: false })
+ webview.dispatchEvent(Object.assign(evt, { url }))
+})
diff --git a/aliyunpan/electron/preload/preload-env.d.ts b/aliyunpan/electron/preload/preload-env.d.ts
index e2a2a4c0b6..78a4a166cd 100644
--- a/aliyunpan/electron/preload/preload-env.d.ts
+++ b/aliyunpan/electron/preload/preload-env.d.ts
@@ -2,6 +2,8 @@
declare namespace NodeJS {
interface ProcessEnv {
NODE_ENV: 'development' | 'production'
+ DIST: string
+ VITE_PUBLIC: string
readonly VITE_DEV_SERVER_HOST: string
readonly VITE_DEV_SERVER_PORT: string
}
@@ -11,6 +13,7 @@ declare interface Window {
platform: any
WinMsg: any
WebToElectron: any
+ WebToWindow: any
WebToElectronCB: any
WebSpawnSync: any
WebExecSync: any
diff --git a/aliyunpan/index.html b/aliyunpan/index.html
index 37786e7699..6ffeb85c4b 100644
--- a/aliyunpan/index.html
+++ b/aliyunpan/index.html
@@ -1,15 +1,6 @@
-
-
-
小白羊云盘
diff --git a/aliyunpan/nano-staged.mjs b/aliyunpan/nano-staged.mjs
index c6ce9aa3bb..8221c288ed 100644
--- a/aliyunpan/nano-staged.mjs
+++ b/aliyunpan/nano-staged.mjs
@@ -4,5 +4,5 @@ export default {
'*.{vue}': ['stylelint --fix', 'prettier --write', 'eslint --cache --fix'],
'*.{less,css}': ['stylelint --fix', 'prettier --write'],
// typecheck
- 'packages/renderer/**/{*.ts,*.tsx,*.vue,tsconfig.json}': ({ filenames }) => 'npm run typecheck'
+ 'src/**/{*.ts,*.tsx,*.vue,tsconfig.json}': ({ filenames }) => 'npm run typecheck'
}
diff --git a/aliyunpan/package.json b/aliyunpan/package.json
index 1f11cf59c2..d811080006 100644
--- a/aliyunpan/package.json
+++ b/aliyunpan/package.json
@@ -1,78 +1,103 @@
{
"name": "xbyyunpan",
- "description": "小白羊云盘",
- "version": "3.11.21",
- "license": "MIT",
+ "description": "阿里云盘小白羊",
+ "version": "3.13.1",
"main": "dist/electron/main/index.js",
"author": {
- "name": "gaozhangmin",
+ "name": "gavingaozhangmin",
"email": "gaozhangmin@gmail.com"
},
+ "homepage": "https://github.com/gaozhangmin/aliyunpan",
+ "license": "MIT",
"scripts": {
"dev": "vite",
- "build": "vue-tsc --noEmit && vite build && electron-builder -wml"
+ "build": "vue-tsc --noEmit && vite build && electron-builder -wml",
+ "build:version": "node version.mjs",
+ "build:electron": "pnpm run build && electron-builder",
+ "build:test": "pnpm run build && electron-builder --dir"
},
"engines": {
- "node": ">=16.0.0"
- },
- "dependencies": {
-
+ "node": ">=18.0.0"
},
"devDependencies": {
- "@arco-design/web-vue": "^2.45.3",
- "@electron/remote": "^2.0.9",
- "@types/crypto-js": "^4.1.1",
- "@types/fast-levenshtein": "^0.0.2",
- "@types/howler": "^2.2.7",
- "@types/lodash": "^4.14.184",
- "@types/node": "^17.0.45",
- "@types/secp256k1": "^4.0.3",
- "@types/uuid": "^9.0.1",
- "@vitejs/plugin-vue": "^3.1.0",
- "@vitejs/plugin-vue-jsx": "^2.0.1",
- "ant-design-vue": "^3.2.20",
- "aria2-lib": "1.0.1",
- "artplayer": "^5.0.9",
- "axios": "^1.4.0",
- "consola": "^3.1.0",
- "crypto-js": "^4.1.1",
- "dayjs": "^1.11.7",
- "dexie": "^3.2.4",
- "digest-fetch": "^3.0.4",
- "dom-to-image": "^2.6.0",
- "electron": "^21.4.4",
- "electron-builder": "^23.6.0",
- "electron-is": "^3.0.0",
- "electron-log": "^4.4.8",
- "fast-levenshtein": "^3.0.0",
- "fix-path": "^4.0.0",
+ "@arco-design/web-vue": "2.55.0",
+ "@arco-themes/vue-gi-demo": "^0.0.48",
+ "@types/crypto-js": "^4.2.2",
+ "@types/fast-levenshtein": "^0.0.4",
+ "@types/howler": "^2.2.11",
+ "@types/lodash": "^4.17.0",
+ "@types/markdown-it": "^13.0.7",
+ "@types/mime-types": "^2.1.4",
+ "@types/node": "^20.11.30",
+ "@types/node-ssdp": "^4.0.4",
+ "@types/secp256k1": "^4.0.6",
+ "@types/thunky": "^1.1.2",
+ "@types/uuid": "^9.0.8",
+ "@vitejs/plugin-vue": "^5.0.4",
+ "@vitejs/plugin-vue-jsx": "^3.1.0",
+ "@vue/runtime-core": "3.4.21",
+ "@vue/runtime-dom": "3.4.21",
"ass-html5": "^0.3.5",
- "fuzzysort": "^2.0.1",
- "hls.js": "^1.4.3",
- "howler": "^2.2.3",
+ "autoprefixer": "^10.4.16",
+ "ant-design-vue": "4.1.2",
+ "aria2-lib": "1.0.1",
+ "artplayer": "^5.1.1",
+ "axios": "^1.6.8",
+ "chinese-simple2traditional": "^1.2.0",
+ "consola": "^3.2.3",
+ "cookie": "^0.6.0",
+ "crypto-js": "^4.2.0",
+ "dayjs": "^1.11.10",
+ "dexie": "^3.2.7",
+ "dom-to-image": "^2.6.0",
+ "electron": "21.4.4",
+ "electron-builder": "^24.13.3",
+ "electron-is": "^3.0.0",
+ "fast-levenshtein": "^3.0.0",
+ "fast-xml-parser": "^4.3.6",
+ "fix-path": "^4.0.0",
+ "fuzzysort": "^2.0.4",
+ "hls.js": "^1.5.7",
+ "howler": "^2.2.4",
"isomorphic-fetch": "^3.0.0",
+ "jassub": "^1.7.15",
"jschardet": "^3.0.0",
+ "less": "^4.2.0",
"lodash": "^4.17.21",
- "pinia": "^2.0.35",
+ "markdown-it": "^14.1.0",
+ "mime-types": "^2.1.35",
+ "node-ssdp": "^4.0.1",
+ "pako": "^2.1.0",
+ "path-to-regexp": "^6.2.1",
+ "perf_hooks": "^0.0.1",
+ "pinia": "^2.1.7",
"secp256k1": "^5.0.0",
- "socks-proxy-agent": "^7.0.0",
- "sudo-prompt": "^9.2.1",
- "terser": "^5.15.0",
- "typescript": "^4.8.2",
- "uuid": "^9.0.0",
+ "semver": "^7.6.0",
+ "socks-proxy-agent": "^8.0.2",
+ "terser": "^5.29.2",
+ "thunky": "^1.1.0",
+ "tree-kill": "^1.2.2",
+ "tailwind-scrollbar": "^2.1.0",
+ "tailwindcss": "^3.3.5",
+ "typescript": "^5.4.2",
+ "upnp-client-ts": "^1.1.1",
+ "uuid": "^9.0.1",
"uuid-by-string": "^4.0.0",
- "viewerjs": "^1.10.5",
- "vite": "3.2.7",
- "vite-plugin-electron": "^0.9.2",
- "vite-plugin-resolve": "^2.1.2",
- "vue": "^3.2.47",
- "vue-tsc": "^1.6.4"
+ "viewerjs": "^1.11.6",
+ "vite": "5.2.2",
+ "vite-plugin-electron": "0.15.6",
+ "vite-plugin-electron-renderer": "0.14.5",
+ "vue": "3.4.21",
+ "vue-tsc": "^2.0.7",
+ "webdav-server": "^2.6.2",
+ "whacko": "^0.19.1",
+ "digest-fetch": "^3.0.4"
},
"debug": {
"env": {
"VITE_DEV_SERVER_HOSTNAME": "127.0.0.1",
- "VITE_DEV_SERVER_PORT": 3344,
- "VITE_DEV_SERVER_URL": "http://127.0.0.1:3344"
+ "VITE_DEV_SERVER_PORT": 5173,
+ "VITE_DEV_SERVER_URL": "http://127.0.0.1:5173"
}
},
"keywords": [
diff --git a/aliyunpan/pnpm-lock.yaml b/aliyunpan/pnpm-lock.yaml
new file mode 100644
index 0000000000..22ffd5423f
--- /dev/null
+++ b/aliyunpan/pnpm-lock.yaml
@@ -0,0 +1,4359 @@
+lockfileVersion: '6.0'
+
+settings:
+ autoInstallPeers: true
+ excludeLinksFromLockfile: false
+
+devDependencies:
+ '@arco-design/web-vue':
+ specifier: 2.55.0
+ version: 2.55.0(vue@3.4.21)
+ '@arco-themes/vue-gi-demo':
+ specifier: ^0.0.48
+ version: 0.0.48(@arco-design/web-vue@2.55.0)
+ '@types/crypto-js':
+ specifier: ^4.2.2
+ version: 4.2.2
+ '@types/fast-levenshtein':
+ specifier: ^0.0.4
+ version: 0.0.4
+ '@types/howler':
+ specifier: ^2.2.11
+ version: 2.2.11
+ '@types/lodash':
+ specifier: ^4.17.0
+ version: 4.17.0
+ '@types/markdown-it':
+ specifier: ^13.0.7
+ version: 13.0.7
+ '@types/mime-types':
+ specifier: ^2.1.4
+ version: 2.1.4
+ '@types/node':
+ specifier: ^20.11.30
+ version: 20.11.30
+ '@types/node-ssdp':
+ specifier: ^4.0.4
+ version: 4.0.4
+ '@types/secp256k1':
+ specifier: ^4.0.6
+ version: 4.0.6
+ '@types/thunky':
+ specifier: ^1.1.2
+ version: 1.1.2
+ '@types/uuid':
+ specifier: ^9.0.8
+ version: 9.0.8
+ '@vitejs/plugin-vue':
+ specifier: ^5.0.4
+ version: 5.0.4(vite@5.2.2)(vue@3.4.21)
+ '@vitejs/plugin-vue-jsx':
+ specifier: ^3.1.0
+ version: 3.1.0(vite@5.2.2)(vue@3.4.21)
+ '@vue/runtime-core':
+ specifier: 3.4.21
+ version: 3.4.21
+ '@vue/runtime-dom':
+ specifier: 3.4.21
+ version: 3.4.21
+ ant-design-vue:
+ specifier: 4.1.2
+ version: 4.1.2(vue@3.4.21)
+ aria2-lib:
+ specifier: 1.0.1
+ version: 1.0.1
+ artplayer:
+ specifier: ^5.1.1
+ version: 5.1.1
+ axios:
+ specifier: ^1.6.8
+ version: 1.6.8
+ chinese-simple2traditional:
+ specifier: ^1.2.0
+ version: 1.2.0
+ consola:
+ specifier: ^3.2.3
+ version: 3.2.3
+ cookie:
+ specifier: ^0.6.0
+ version: 0.6.0
+ crypto-js:
+ specifier: ^4.2.0
+ version: 4.2.0
+ dayjs:
+ specifier: ^1.11.10
+ version: 1.11.10
+ dexie:
+ specifier: ^3.2.7
+ version: 3.2.7
+ dom-to-image:
+ specifier: ^2.6.0
+ version: 2.6.0
+ electron:
+ specifier: 21.4.4
+ version: 21.4.4
+ electron-builder:
+ specifier: ^24.13.3
+ version: 24.13.3(electron-builder-squirrel-windows@24.13.3)
+ electron-is:
+ specifier: ^3.0.0
+ version: 3.0.0
+ fast-levenshtein:
+ specifier: ^3.0.0
+ version: 3.0.0
+ fast-xml-parser:
+ specifier: ^4.3.6
+ version: 4.3.6
+ fix-path:
+ specifier: ^4.0.0
+ version: 4.0.0
+ fuzzysort:
+ specifier: ^2.0.4
+ version: 2.0.4
+ hls.js:
+ specifier: ^1.5.7
+ version: 1.5.7
+ howler:
+ specifier: ^2.2.4
+ version: 2.2.4
+ isomorphic-fetch:
+ specifier: ^3.0.0
+ version: 3.0.0
+ jassub:
+ specifier: ^1.7.15
+ version: 1.7.15
+ jschardet:
+ specifier: ^3.0.0
+ version: 3.0.0
+ less:
+ specifier: ^4.2.0
+ version: 4.2.0
+ lodash:
+ specifier: ^4.17.21
+ version: 4.17.21
+ markdown-it:
+ specifier: ^14.1.0
+ version: 14.1.0
+ mime-types:
+ specifier: ^2.1.35
+ version: 2.1.35
+ node-ssdp:
+ specifier: ^4.0.1
+ version: 4.0.1
+ pako:
+ specifier: ^2.1.0
+ version: 2.1.0
+ path-to-regexp:
+ specifier: ^6.2.1
+ version: 6.2.1
+ perf_hooks:
+ specifier: ^0.0.1
+ version: 0.0.1
+ pinia:
+ specifier: ^2.1.7
+ version: 2.1.7(typescript@5.4.3)(vue@3.4.21)
+ secp256k1:
+ specifier: ^5.0.0
+ version: 5.0.0
+ semver:
+ specifier: ^7.6.0
+ version: 7.6.0
+ socks-proxy-agent:
+ specifier: ^8.0.2
+ version: 8.0.2
+ terser:
+ specifier: ^5.29.2
+ version: 5.29.2
+ thunky:
+ specifier: ^1.1.0
+ version: 1.1.0
+ tree-kill:
+ specifier: ^1.2.2
+ version: 1.2.2
+ typescript:
+ specifier: ^5.4.3
+ version: 5.4.3
+ upnp-client-ts:
+ specifier: ^1.1.1
+ version: 1.1.1
+ uuid:
+ specifier: ^9.0.1
+ version: 9.0.1
+ uuid-by-string:
+ specifier: ^4.0.0
+ version: 4.0.0
+ viewerjs:
+ specifier: ^1.11.6
+ version: 1.11.6
+ vite:
+ specifier: 5.2.2
+ version: 5.2.2(@types/node@20.11.30)(less@4.2.0)(terser@5.29.2)
+ vite-plugin-electron:
+ specifier: 0.15.6
+ version: 0.15.6(tree-kill@1.2.2)(vite-plugin-electron-renderer@0.14.5)
+ vite-plugin-electron-renderer:
+ specifier: 0.14.5
+ version: 0.14.5
+ vue:
+ specifier: 3.4.21
+ version: 3.4.21(typescript@5.4.3)
+ vue-tsc:
+ specifier: ^2.0.7
+ version: 2.0.7(typescript@5.4.3)
+ webdav-server:
+ specifier: ^2.6.2
+ version: 2.6.2
+ whacko:
+ specifier: ^0.19.1
+ version: 0.19.1
+
+packages:
+
+ /7zip-bin@5.2.0:
+ resolution: {integrity: sha512-ukTPVhqG4jNzMro2qA9HSCSSVJN3aN7tlb+hfqYCt3ER0yWroeA2VR38MNrOHLQ/cVj+DaIMad0kFCtWWowh/A==}
+ dev: true
+
+ /@ampproject/remapping@2.2.1:
+ resolution: {integrity: sha512-lFMjJTrFL3j7L9yBxwYfCq2k6qqwHyzuUl/XBnif78PWTJYyL/dfowQHWE3sp6U6ZzqWiiIZnpTMO96zhkjwtg==}
+ engines: {node: '>=6.0.0'}
+ dependencies:
+ '@jridgewell/gen-mapping': 0.3.3
+ '@jridgewell/trace-mapping': 0.3.20
+ dev: true
+
+ /@ant-design/colors@6.0.0:
+ resolution: {integrity: sha512-qAZRvPzfdWHtfameEGP2Qvuf838NhergR35o+EuVyB5XvSA98xod5r4utvi4TJ3ywmevm290g9nsCG5MryrdWQ==}
+ dependencies:
+ '@ctrl/tinycolor': 3.6.1
+ dev: true
+
+ /@ant-design/icons-svg@4.3.1:
+ resolution: {integrity: sha512-4QBZg8ccyC6LPIRii7A0bZUk3+lEDCLnhB+FVsflGdcWPPmV+j3fire4AwwoqHV/BibgvBmR9ZIo4s867smv+g==}
+ dev: true
+
+ /@ant-design/icons-vue@7.0.1(vue@3.4.21):
+ resolution: {integrity: sha512-eCqY2unfZK6Fe02AwFlDHLfoyEFreP6rBwAZMIJ1LugmfMiVgwWDYlp1YsRugaPtICYOabV1iWxXdP12u9U43Q==}
+ peerDependencies:
+ vue: '>=3.0.3'
+ dependencies:
+ '@ant-design/colors': 6.0.0
+ '@ant-design/icons-svg': 4.3.1
+ vue: 3.4.21(typescript@5.4.3)
+ dev: true
+
+ /@arco-design/color@0.4.0:
+ resolution: {integrity: sha512-s7p9MSwJgHeL8DwcATaXvWT3m2SigKpxx4JA1BGPHL4gfvaQsmQfrLBDpjOJFJuJ2jG2dMt3R3P8Pm9E65q18g==}
+ dependencies:
+ color: 3.2.1
+ dev: true
+
+ /@arco-design/web-vue@2.55.0(vue@3.4.21):
+ resolution: {integrity: sha512-aMfg9dHiDsiJsxU2Mpa0V4WKjtdAdETBBrrVEHj1E7rJYF+PmrfZcSgIvAJSbdJZC/euqSCHyYOQezi3esSzxA==}
+ peerDependencies:
+ vue: ^3.1.0
+ dependencies:
+ '@arco-design/color': 0.4.0
+ b-tween: 0.3.3
+ b-validate: 1.5.3
+ compute-scroll-into-view: 1.0.20
+ dayjs: 1.11.10
+ number-precision: 1.6.0
+ resize-observer-polyfill: 1.5.1
+ scroll-into-view-if-needed: 2.2.31
+ vue: 3.4.21(typescript@5.4.3)
+ dev: true
+
+ /@arco-themes/vue-gi-demo@0.0.48(@arco-design/web-vue@2.55.0):
+ resolution: {integrity: sha512-HUdIvGcKgHtmqMk1aMmRC1klDP2Ki1La/f+TUB4CpqkWNfiKtMmqpGcMyQeX7iNCE04m86DbCJL5v/BqGxcPuw==}
+ peerDependencies:
+ '@arco-design/web-vue': ^2.53.2
+ dependencies:
+ '@arco-design/web-vue': 2.55.0(vue@3.4.21)
+ dev: true
+
+ /@babel/code-frame@7.23.5:
+ resolution: {integrity: sha512-CgH3s1a96LipHCmSUmYFPwY7MNx8C3avkq7i4Wl3cfa662ldtUe4VM1TPXX70pfmrlWTb6jLqTYrZyT2ZTJBgA==}
+ engines: {node: '>=6.9.0'}
+ dependencies:
+ '@babel/highlight': 7.23.4
+ chalk: 2.4.2
+ dev: true
+
+ /@babel/compat-data@7.23.5:
+ resolution: {integrity: sha512-uU27kfDRlhfKl+w1U6vp16IuvSLtjAxdArVXPa9BvLkrr7CYIsxH5adpHObeAGY/41+syctUWOZ140a2Rvkgjw==}
+ engines: {node: '>=6.9.0'}
+ dev: true
+
+ /@babel/core@7.23.5:
+ resolution: {integrity: sha512-Cwc2XjUrG4ilcfOw4wBAK+enbdgwAcAJCfGUItPBKR7Mjw4aEfAFYrLxeRp4jWgtNIKn3n2AlBOfwwafl+42/g==}
+ engines: {node: '>=6.9.0'}
+ dependencies:
+ '@ampproject/remapping': 2.2.1
+ '@babel/code-frame': 7.23.5
+ '@babel/generator': 7.23.5
+ '@babel/helper-compilation-targets': 7.22.15
+ '@babel/helper-module-transforms': 7.23.3(@babel/core@7.23.5)
+ '@babel/helpers': 7.23.5
+ '@babel/parser': 7.23.5
+ '@babel/template': 7.22.15
+ '@babel/traverse': 7.23.5
+ '@babel/types': 7.23.5
+ convert-source-map: 2.0.0
+ debug: 4.3.4
+ gensync: 1.0.0-beta.2
+ json5: 2.2.3
+ semver: 6.3.1
+ transitivePeerDependencies:
+ - supports-color
+ dev: true
+
+ /@babel/generator@7.23.5:
+ resolution: {integrity: sha512-BPssCHrBD+0YrxviOa3QzpqwhNIXKEtOa2jQrm4FlmkC2apYgRnQcmPWiGZDlGxiNtltnUFolMe8497Esry+jA==}
+ engines: {node: '>=6.9.0'}
+ dependencies:
+ '@babel/types': 7.23.5
+ '@jridgewell/gen-mapping': 0.3.3
+ '@jridgewell/trace-mapping': 0.3.20
+ jsesc: 2.5.2
+ dev: true
+
+ /@babel/helper-annotate-as-pure@7.22.5:
+ resolution: {integrity: sha512-LvBTxu8bQSQkcyKOU+a1btnNFQ1dMAd0R6PyW3arXes06F6QLWLIrd681bxRPIXlrMGR3XYnW9JyML7dP3qgxg==}
+ engines: {node: '>=6.9.0'}
+ dependencies:
+ '@babel/types': 7.23.5
+ dev: true
+
+ /@babel/helper-compilation-targets@7.22.15:
+ resolution: {integrity: sha512-y6EEzULok0Qvz8yyLkCvVX+02ic+By2UdOhylwUOvOn9dvYc9mKICJuuU1n1XBI02YWsNsnrY1kc6DVbjcXbtw==}
+ engines: {node: '>=6.9.0'}
+ dependencies:
+ '@babel/compat-data': 7.23.5
+ '@babel/helper-validator-option': 7.23.5
+ browserslist: 4.22.2
+ lru-cache: 5.1.1
+ semver: 6.3.1
+ dev: true
+
+ /@babel/helper-create-class-features-plugin@7.23.5(@babel/core@7.23.5):
+ resolution: {integrity: sha512-QELlRWxSpgdwdJzSJn4WAhKC+hvw/AtHbbrIoncKHkhKKR/luAlKkgBDcri1EzWAo8f8VvYVryEHN4tax/V67A==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0
+ dependencies:
+ '@babel/core': 7.23.5
+ '@babel/helper-annotate-as-pure': 7.22.5
+ '@babel/helper-environment-visitor': 7.22.20
+ '@babel/helper-function-name': 7.23.0
+ '@babel/helper-member-expression-to-functions': 7.23.0
+ '@babel/helper-optimise-call-expression': 7.22.5
+ '@babel/helper-replace-supers': 7.22.20(@babel/core@7.23.5)
+ '@babel/helper-skip-transparent-expression-wrappers': 7.22.5
+ '@babel/helper-split-export-declaration': 7.22.6
+ semver: 6.3.1
+ dev: true
+
+ /@babel/helper-environment-visitor@7.22.20:
+ resolution: {integrity: sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA==}
+ engines: {node: '>=6.9.0'}
+ dev: true
+
+ /@babel/helper-function-name@7.23.0:
+ resolution: {integrity: sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw==}
+ engines: {node: '>=6.9.0'}
+ dependencies:
+ '@babel/template': 7.22.15
+ '@babel/types': 7.23.5
+ dev: true
+
+ /@babel/helper-hoist-variables@7.22.5:
+ resolution: {integrity: sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw==}
+ engines: {node: '>=6.9.0'}
+ dependencies:
+ '@babel/types': 7.23.5
+ dev: true
+
+ /@babel/helper-member-expression-to-functions@7.23.0:
+ resolution: {integrity: sha512-6gfrPwh7OuT6gZyJZvd6WbTfrqAo7vm4xCzAXOusKqq/vWdKXphTpj5klHKNmRUU6/QRGlBsyU9mAIPaWHlqJA==}
+ engines: {node: '>=6.9.0'}
+ dependencies:
+ '@babel/types': 7.23.5
+ dev: true
+
+ /@babel/helper-module-imports@7.22.15:
+ resolution: {integrity: sha512-0pYVBnDKZO2fnSPCrgM/6WMc7eS20Fbok+0r88fp+YtWVLZrp4CkafFGIp+W0VKw4a22sgebPT99y+FDNMdP4w==}
+ engines: {node: '>=6.9.0'}
+ dependencies:
+ '@babel/types': 7.23.5
+ dev: true
+
+ /@babel/helper-module-transforms@7.23.3(@babel/core@7.23.5):
+ resolution: {integrity: sha512-7bBs4ED9OmswdfDzpz4MpWgSrV7FXlc3zIagvLFjS5H+Mk7Snr21vQ6QwrsoCGMfNC4e4LQPdoULEt4ykz0SRQ==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0
+ dependencies:
+ '@babel/core': 7.23.5
+ '@babel/helper-environment-visitor': 7.22.20
+ '@babel/helper-module-imports': 7.22.15
+ '@babel/helper-simple-access': 7.22.5
+ '@babel/helper-split-export-declaration': 7.22.6
+ '@babel/helper-validator-identifier': 7.22.20
+ dev: true
+
+ /@babel/helper-optimise-call-expression@7.22.5:
+ resolution: {integrity: sha512-HBwaojN0xFRx4yIvpwGqxiV2tUfl7401jlok564NgB9EHS1y6QT17FmKWm4ztqjeVdXLuC4fSvHc5ePpQjoTbw==}
+ engines: {node: '>=6.9.0'}
+ dependencies:
+ '@babel/types': 7.23.5
+ dev: true
+
+ /@babel/helper-plugin-utils@7.22.5:
+ resolution: {integrity: sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg==}
+ engines: {node: '>=6.9.0'}
+ dev: true
+
+ /@babel/helper-replace-supers@7.22.20(@babel/core@7.23.5):
+ resolution: {integrity: sha512-qsW0In3dbwQUbK8kejJ4R7IHVGwHJlV6lpG6UA7a9hSa2YEiAib+N1T2kr6PEeUT+Fl7najmSOS6SmAwCHK6Tw==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0
+ dependencies:
+ '@babel/core': 7.23.5
+ '@babel/helper-environment-visitor': 7.22.20
+ '@babel/helper-member-expression-to-functions': 7.23.0
+ '@babel/helper-optimise-call-expression': 7.22.5
+ dev: true
+
+ /@babel/helper-simple-access@7.22.5:
+ resolution: {integrity: sha512-n0H99E/K+Bika3++WNL17POvo4rKWZ7lZEp1Q+fStVbUi8nxPQEBOlTmCOxW/0JsS56SKKQ+ojAe2pHKJHN35w==}
+ engines: {node: '>=6.9.0'}
+ dependencies:
+ '@babel/types': 7.23.5
+ dev: true
+
+ /@babel/helper-skip-transparent-expression-wrappers@7.22.5:
+ resolution: {integrity: sha512-tK14r66JZKiC43p8Ki33yLBVJKlQDFoA8GYN67lWCDCqoL6EMMSuM9b+Iff2jHaM/RRFYl7K+iiru7hbRqNx8Q==}
+ engines: {node: '>=6.9.0'}
+ dependencies:
+ '@babel/types': 7.23.5
+ dev: true
+
+ /@babel/helper-split-export-declaration@7.22.6:
+ resolution: {integrity: sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==}
+ engines: {node: '>=6.9.0'}
+ dependencies:
+ '@babel/types': 7.23.5
+ dev: true
+
+ /@babel/helper-string-parser@7.23.4:
+ resolution: {integrity: sha512-803gmbQdqwdf4olxrX4AJyFBV/RTr3rSmOj0rKwesmzlfhYNDEs+/iOcznzpNWlJlIlTJC2QfPFcHB6DlzdVLQ==}
+ engines: {node: '>=6.9.0'}
+ dev: true
+
+ /@babel/helper-validator-identifier@7.22.20:
+ resolution: {integrity: sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==}
+ engines: {node: '>=6.9.0'}
+ dev: true
+
+ /@babel/helper-validator-option@7.23.5:
+ resolution: {integrity: sha512-85ttAOMLsr53VgXkTbkx8oA6YTfT4q7/HzXSLEYmjcSTJPMPQtvq1BD79Byep5xMUYbGRzEpDsjUf3dyp54IKw==}
+ engines: {node: '>=6.9.0'}
+ dev: true
+
+ /@babel/helpers@7.23.5:
+ resolution: {integrity: sha512-oO7us8FzTEsG3U6ag9MfdF1iA/7Z6dz+MtFhifZk8C8o453rGJFFWUP1t+ULM9TUIAzC9uxXEiXjOiVMyd7QPg==}
+ engines: {node: '>=6.9.0'}
+ dependencies:
+ '@babel/template': 7.22.15
+ '@babel/traverse': 7.23.5
+ '@babel/types': 7.23.5
+ transitivePeerDependencies:
+ - supports-color
+ dev: true
+
+ /@babel/highlight@7.23.4:
+ resolution: {integrity: sha512-acGdbYSfp2WheJoJm/EBBBLh/ID8KDc64ISZ9DYtBmC8/Q204PZJLHyzeB5qMzJ5trcOkybd78M4x2KWsUq++A==}
+ engines: {node: '>=6.9.0'}
+ dependencies:
+ '@babel/helper-validator-identifier': 7.22.20
+ chalk: 2.4.2
+ js-tokens: 4.0.0
+ dev: true
+
+ /@babel/parser@7.23.5:
+ resolution: {integrity: sha512-hOOqoiNXrmGdFbhgCzu6GiURxUgM27Xwd/aPuu8RfHEZPBzL1Z54okAHAQjXfcQNwvrlkAmAp4SlRTZ45vlthQ==}
+ engines: {node: '>=6.0.0'}
+ hasBin: true
+ dependencies:
+ '@babel/types': 7.23.5
+ dev: true
+
+ /@babel/parser@7.23.9:
+ resolution: {integrity: sha512-9tcKgqKbs3xGJ+NtKF2ndOBBLVwPjl1SHxPQkd36r3Dlirw3xWUeGaTbqr7uGZcTaxkVNwc+03SVP7aCdWrTlA==}
+ engines: {node: '>=6.0.0'}
+ hasBin: true
+ dependencies:
+ '@babel/types': 7.23.5
+ dev: true
+
+ /@babel/plugin-syntax-jsx@7.23.3(@babel/core@7.23.5):
+ resolution: {integrity: sha512-EB2MELswq55OHUoRZLGg/zC7QWUKfNLpE57m/S2yr1uEneIgsTgrSzXP3NXEsMkVn76OlaVVnzN+ugObuYGwhg==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+ dependencies:
+ '@babel/core': 7.23.5
+ '@babel/helper-plugin-utils': 7.22.5
+ dev: true
+
+ /@babel/plugin-syntax-typescript@7.23.3(@babel/core@7.23.5):
+ resolution: {integrity: sha512-9EiNjVJOMwCO+43TqoTrgQ8jMwcAd0sWyXi9RPfIsLTj4R2MADDDQXELhffaUx/uJv2AYcxBgPwH6j4TIA4ytQ==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+ dependencies:
+ '@babel/core': 7.23.5
+ '@babel/helper-plugin-utils': 7.22.5
+ dev: true
+
+ /@babel/plugin-transform-typescript@7.23.5(@babel/core@7.23.5):
+ resolution: {integrity: sha512-2fMkXEJkrmwgu2Bsv1Saxgj30IXZdJ+84lQcKKI7sm719oXs0BBw2ZENKdJdR1PjWndgLCEBNXJOri0fk7RYQA==}
+ engines: {node: '>=6.9.0'}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+ dependencies:
+ '@babel/core': 7.23.5
+ '@babel/helper-annotate-as-pure': 7.22.5
+ '@babel/helper-create-class-features-plugin': 7.23.5(@babel/core@7.23.5)
+ '@babel/helper-plugin-utils': 7.22.5
+ '@babel/plugin-syntax-typescript': 7.23.3(@babel/core@7.23.5)
+ dev: true
+
+ /@babel/runtime@7.23.5:
+ resolution: {integrity: sha512-NdUTHcPe4C99WxPub+K9l9tK5/lV4UXIoaHSYgzco9BCyjKAAwzdBI+wWtYqHt7LJdbo74ZjRPJgzVweq1sz0w==}
+ engines: {node: '>=6.9.0'}
+ dependencies:
+ regenerator-runtime: 0.14.0
+ dev: true
+
+ /@babel/template@7.22.15:
+ resolution: {integrity: sha512-QPErUVm4uyJa60rkI73qneDacvdvzxshT3kksGqlGWYdOTIUOwJ7RDUL8sGqslY1uXWSL6xMFKEXDS3ox2uF0w==}
+ engines: {node: '>=6.9.0'}
+ dependencies:
+ '@babel/code-frame': 7.23.5
+ '@babel/parser': 7.23.5
+ '@babel/types': 7.23.5
+ dev: true
+
+ /@babel/traverse@7.23.5:
+ resolution: {integrity: sha512-czx7Xy5a6sapWWRx61m1Ke1Ra4vczu1mCTtJam5zRTBOonfdJ+S/B6HYmGYu3fJtr8GGET3si6IhgWVBhJ/m8w==}
+ engines: {node: '>=6.9.0'}
+ dependencies:
+ '@babel/code-frame': 7.23.5
+ '@babel/generator': 7.23.5
+ '@babel/helper-environment-visitor': 7.22.20
+ '@babel/helper-function-name': 7.23.0
+ '@babel/helper-hoist-variables': 7.22.5
+ '@babel/helper-split-export-declaration': 7.22.6
+ '@babel/parser': 7.23.5
+ '@babel/types': 7.23.5
+ debug: 4.3.4
+ globals: 11.12.0
+ transitivePeerDependencies:
+ - supports-color
+ dev: true
+
+ /@babel/types@7.23.5:
+ resolution: {integrity: sha512-ON5kSOJwVO6xXVRTvOI0eOnWe7VdUcIpsovGo9U/Br4Ie4UVFQTboO2cYnDhAGU6Fp+UxSiT+pMft0SMHfuq6w==}
+ engines: {node: '>=6.9.0'}
+ dependencies:
+ '@babel/helper-string-parser': 7.23.4
+ '@babel/helper-validator-identifier': 7.22.20
+ to-fast-properties: 2.0.0
+ dev: true
+
+ /@ctrl/tinycolor@3.6.1:
+ resolution: {integrity: sha512-SITSV6aIXsuVNV3f3O0f2n/cgyEDWoSqtZMYiAmcsYHydcKrOz3gUxB/iXd/Qf08+IZX4KpgNbvUdMBmWz+kcA==}
+ engines: {node: '>=10'}
+ dev: true
+
+ /@develar/schema-utils@2.6.5:
+ resolution: {integrity: sha512-0cp4PsWQ/9avqTVMCtZ+GirikIA36ikvjtHweU4/j8yLtgObI0+JUPhYFScgwlteveGB1rt3Cm8UhN04XayDig==}
+ engines: {node: '>= 8.9.0'}
+ dependencies:
+ ajv: 6.12.6
+ ajv-keywords: 3.5.2(ajv@6.12.6)
+ dev: true
+
+ /@electron/asar@3.2.8:
+ resolution: {integrity: sha512-cmskk5M06ewHMZAplSiF4AlME3IrnnZhKnWbtwKVLRkdJkKyUVjMLhDIiPIx/+6zQWVlKX/LtmK9xDme7540Sg==}
+ engines: {node: '>=10.12.0'}
+ hasBin: true
+ dependencies:
+ commander: 5.1.0
+ glob: 7.2.3
+ minimatch: 3.1.2
+ dev: true
+
+ /@electron/get@1.14.1:
+ resolution: {integrity: sha512-BrZYyL/6m0ZXz/lDxy/nlVhQz+WF+iPS6qXolEU8atw7h6v1aYkjwJZ63m+bJMBTxDE66X+r2tPS4a/8C82sZw==}
+ engines: {node: '>=8.6'}
+ dependencies:
+ debug: 4.3.4
+ env-paths: 2.2.1
+ fs-extra: 8.1.0
+ got: 9.6.0
+ progress: 2.0.3
+ semver: 6.3.1
+ sumchecker: 3.0.1
+ optionalDependencies:
+ global-agent: 3.0.0
+ global-tunnel-ng: 2.7.1
+ transitivePeerDependencies:
+ - supports-color
+ dev: true
+
+ /@electron/notarize@2.2.1:
+ resolution: {integrity: sha512-aL+bFMIkpR0cmmj5Zgy0LMKEpgy43/hw5zadEArgmAMWWlKc5buwFvFT9G/o/YJkvXAJm5q3iuTuLaiaXW39sg==}
+ engines: {node: '>= 10.0.0'}
+ dependencies:
+ debug: 4.3.4
+ fs-extra: 9.1.0
+ promise-retry: 2.0.1
+ transitivePeerDependencies:
+ - supports-color
+ dev: true
+
+ /@electron/osx-sign@1.0.5:
+ resolution: {integrity: sha512-k9ZzUQtamSoweGQDV2jILiRIHUu7lYlJ3c6IEmjv1hC17rclE+eb9U+f6UFlOOETo0JzY1HNlXy4YOlCvl+Lww==}
+ engines: {node: '>=12.0.0'}
+ hasBin: true
+ dependencies:
+ compare-version: 0.1.2
+ debug: 4.3.4
+ fs-extra: 10.1.0
+ isbinaryfile: 4.0.10
+ minimist: 1.2.8
+ plist: 3.1.0
+ transitivePeerDependencies:
+ - supports-color
+ dev: true
+
+ /@electron/universal@1.5.1:
+ resolution: {integrity: sha512-kbgXxyEauPJiQQUNG2VgUeyfQNFk6hBF11ISN2PNI6agUgPl55pv4eQmaqHzTAzchBvqZ2tQuRVaPStGf0mxGw==}
+ engines: {node: '>=8.6'}
+ dependencies:
+ '@electron/asar': 3.2.8
+ '@malept/cross-spawn-promise': 1.1.1
+ debug: 4.3.4
+ dir-compare: 3.3.0
+ fs-extra: 9.1.0
+ minimatch: 3.1.2
+ plist: 3.1.0
+ transitivePeerDependencies:
+ - supports-color
+ dev: true
+
+ /@emotion/hash@0.9.1:
+ resolution: {integrity: sha512-gJB6HLm5rYwSLI6PQa+X1t5CFGrv1J1TWG+sOyMCeKz2ojaj6Fnl/rZEspogG+cvqbt4AE/2eIyD2QfLKTBNlQ==}
+ dev: true
+
+ /@emotion/unitless@0.8.1:
+ resolution: {integrity: sha512-KOEGMu6dmJZtpadb476IsZBclKvILjopjUii3V+7MnXIQCYh8W3NgNcgwo21n9LXZX6EDIKvqfjYxXebDwxKmQ==}
+ dev: true
+
+ /@esbuild/aix-ppc64@0.20.2:
+ resolution: {integrity: sha512-D+EBOJHXdNZcLJRBkhENNG8Wji2kgc9AZ9KiPr1JuZjsNtyHzrsfLRrY0tk2H2aoFu6RANO1y1iPPUCDYWkb5g==}
+ engines: {node: '>=12'}
+ cpu: [ppc64]
+ os: [aix]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@esbuild/android-arm64@0.20.2:
+ resolution: {integrity: sha512-mRzjLacRtl/tWU0SvD8lUEwb61yP9cqQo6noDZP/O8VkwafSYwZ4yWy24kan8jE/IMERpYncRt2dw438LP3Xmg==}
+ engines: {node: '>=12'}
+ cpu: [arm64]
+ os: [android]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@esbuild/android-arm@0.20.2:
+ resolution: {integrity: sha512-t98Ra6pw2VaDhqNWO2Oph2LXbz/EJcnLmKLGBJwEwXX/JAN83Fym1rU8l0JUWK6HkIbWONCSSatf4sf2NBRx/w==}
+ engines: {node: '>=12'}
+ cpu: [arm]
+ os: [android]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@esbuild/android-x64@0.20.2:
+ resolution: {integrity: sha512-btzExgV+/lMGDDa194CcUQm53ncxzeBrWJcncOBxuC6ndBkKxnHdFJn86mCIgTELsooUmwUm9FkhSp5HYu00Rg==}
+ engines: {node: '>=12'}
+ cpu: [x64]
+ os: [android]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@esbuild/darwin-arm64@0.20.2:
+ resolution: {integrity: sha512-4J6IRT+10J3aJH3l1yzEg9y3wkTDgDk7TSDFX+wKFiWjqWp/iCfLIYzGyasx9l0SAFPT1HwSCR+0w/h1ES/MjA==}
+ engines: {node: '>=12'}
+ cpu: [arm64]
+ os: [darwin]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@esbuild/darwin-x64@0.20.2:
+ resolution: {integrity: sha512-tBcXp9KNphnNH0dfhv8KYkZhjc+H3XBkF5DKtswJblV7KlT9EI2+jeA8DgBjp908WEuYll6pF+UStUCfEpdysA==}
+ engines: {node: '>=12'}
+ cpu: [x64]
+ os: [darwin]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@esbuild/freebsd-arm64@0.20.2:
+ resolution: {integrity: sha512-d3qI41G4SuLiCGCFGUrKsSeTXyWG6yem1KcGZVS+3FYlYhtNoNgYrWcvkOoaqMhwXSMrZRl69ArHsGJ9mYdbbw==}
+ engines: {node: '>=12'}
+ cpu: [arm64]
+ os: [freebsd]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@esbuild/freebsd-x64@0.20.2:
+ resolution: {integrity: sha512-d+DipyvHRuqEeM5zDivKV1KuXn9WeRX6vqSqIDgwIfPQtwMP4jaDsQsDncjTDDsExT4lR/91OLjRo8bmC1e+Cw==}
+ engines: {node: '>=12'}
+ cpu: [x64]
+ os: [freebsd]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@esbuild/linux-arm64@0.20.2:
+ resolution: {integrity: sha512-9pb6rBjGvTFNira2FLIWqDk/uaf42sSyLE8j1rnUpuzsODBq7FvpwHYZxQ/It/8b+QOS1RYfqgGFNLRI+qlq2A==}
+ engines: {node: '>=12'}
+ cpu: [arm64]
+ os: [linux]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@esbuild/linux-arm@0.20.2:
+ resolution: {integrity: sha512-VhLPeR8HTMPccbuWWcEUD1Az68TqaTYyj6nfE4QByZIQEQVWBB8vup8PpR7y1QHL3CpcF6xd5WVBU/+SBEvGTg==}
+ engines: {node: '>=12'}
+ cpu: [arm]
+ os: [linux]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@esbuild/linux-ia32@0.20.2:
+ resolution: {integrity: sha512-o10utieEkNPFDZFQm9CoP7Tvb33UutoJqg3qKf1PWVeeJhJw0Q347PxMvBgVVFgouYLGIhFYG0UGdBumROyiig==}
+ engines: {node: '>=12'}
+ cpu: [ia32]
+ os: [linux]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@esbuild/linux-loong64@0.20.2:
+ resolution: {integrity: sha512-PR7sp6R/UC4CFVomVINKJ80pMFlfDfMQMYynX7t1tNTeivQ6XdX5r2XovMmha/VjR1YN/HgHWsVcTRIMkymrgQ==}
+ engines: {node: '>=12'}
+ cpu: [loong64]
+ os: [linux]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@esbuild/linux-mips64el@0.20.2:
+ resolution: {integrity: sha512-4BlTqeutE/KnOiTG5Y6Sb/Hw6hsBOZapOVF6njAESHInhlQAghVVZL1ZpIctBOoTFbQyGW+LsVYZ8lSSB3wkjA==}
+ engines: {node: '>=12'}
+ cpu: [mips64el]
+ os: [linux]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@esbuild/linux-ppc64@0.20.2:
+ resolution: {integrity: sha512-rD3KsaDprDcfajSKdn25ooz5J5/fWBylaaXkuotBDGnMnDP1Uv5DLAN/45qfnf3JDYyJv/ytGHQaziHUdyzaAg==}
+ engines: {node: '>=12'}
+ cpu: [ppc64]
+ os: [linux]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@esbuild/linux-riscv64@0.20.2:
+ resolution: {integrity: sha512-snwmBKacKmwTMmhLlz/3aH1Q9T8v45bKYGE3j26TsaOVtjIag4wLfWSiZykXzXuE1kbCE+zJRmwp+ZbIHinnVg==}
+ engines: {node: '>=12'}
+ cpu: [riscv64]
+ os: [linux]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@esbuild/linux-s390x@0.20.2:
+ resolution: {integrity: sha512-wcWISOobRWNm3cezm5HOZcYz1sKoHLd8VL1dl309DiixxVFoFe/o8HnwuIwn6sXre88Nwj+VwZUvJf4AFxkyrQ==}
+ engines: {node: '>=12'}
+ cpu: [s390x]
+ os: [linux]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@esbuild/linux-x64@0.20.2:
+ resolution: {integrity: sha512-1MdwI6OOTsfQfek8sLwgyjOXAu+wKhLEoaOLTjbijk6E2WONYpH9ZU2mNtR+lZ2B4uwr+usqGuVfFT9tMtGvGw==}
+ engines: {node: '>=12'}
+ cpu: [x64]
+ os: [linux]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@esbuild/netbsd-x64@0.20.2:
+ resolution: {integrity: sha512-K8/DhBxcVQkzYc43yJXDSyjlFeHQJBiowJ0uVL6Tor3jGQfSGHNNJcWxNbOI8v5k82prYqzPuwkzHt3J1T1iZQ==}
+ engines: {node: '>=12'}
+ cpu: [x64]
+ os: [netbsd]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@esbuild/openbsd-x64@0.20.2:
+ resolution: {integrity: sha512-eMpKlV0SThJmmJgiVyN9jTPJ2VBPquf6Kt/nAoo6DgHAoN57K15ZghiHaMvqjCye/uU4X5u3YSMgVBI1h3vKrQ==}
+ engines: {node: '>=12'}
+ cpu: [x64]
+ os: [openbsd]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@esbuild/sunos-x64@0.20.2:
+ resolution: {integrity: sha512-2UyFtRC6cXLyejf/YEld4Hajo7UHILetzE1vsRcGL3earZEW77JxrFjH4Ez2qaTiEfMgAXxfAZCm1fvM/G/o8w==}
+ engines: {node: '>=12'}
+ cpu: [x64]
+ os: [sunos]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@esbuild/win32-arm64@0.20.2:
+ resolution: {integrity: sha512-GRibxoawM9ZCnDxnP3usoUDO9vUkpAxIIZ6GQI+IlVmr5kP3zUq+l17xELTHMWTWzjxa2guPNyrpq1GWmPvcGQ==}
+ engines: {node: '>=12'}
+ cpu: [arm64]
+ os: [win32]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@esbuild/win32-ia32@0.20.2:
+ resolution: {integrity: sha512-HfLOfn9YWmkSKRQqovpnITazdtquEW8/SoHW7pWpuEeguaZI4QnCRW6b+oZTztdBnZOS2hqJ6im/D5cPzBTTlQ==}
+ engines: {node: '>=12'}
+ cpu: [ia32]
+ os: [win32]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@esbuild/win32-x64@0.20.2:
+ resolution: {integrity: sha512-N49X4lJX27+l9jbLKSqZ6bKNjzQvHaT8IIFUy+YIqmXQdjYCToGWwOItDrfby14c78aDd5NHQl29xingXfCdLQ==}
+ engines: {node: '>=12'}
+ cpu: [x64]
+ os: [win32]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@jridgewell/gen-mapping@0.3.3:
+ resolution: {integrity: sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==}
+ engines: {node: '>=6.0.0'}
+ dependencies:
+ '@jridgewell/set-array': 1.1.2
+ '@jridgewell/sourcemap-codec': 1.4.15
+ '@jridgewell/trace-mapping': 0.3.20
+ dev: true
+
+ /@jridgewell/resolve-uri@3.1.1:
+ resolution: {integrity: sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA==}
+ engines: {node: '>=6.0.0'}
+ dev: true
+
+ /@jridgewell/set-array@1.1.2:
+ resolution: {integrity: sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==}
+ engines: {node: '>=6.0.0'}
+ dev: true
+
+ /@jridgewell/source-map@0.3.5:
+ resolution: {integrity: sha512-UTYAUj/wviwdsMfzoSJspJxbkH5o1snzwX0//0ENX1u/55kkZZkcTZP6u9bwKGkv+dkk9at4m1Cpt0uY80kcpQ==}
+ dependencies:
+ '@jridgewell/gen-mapping': 0.3.3
+ '@jridgewell/trace-mapping': 0.3.20
+ dev: true
+
+ /@jridgewell/sourcemap-codec@1.4.15:
+ resolution: {integrity: sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==}
+ dev: true
+
+ /@jridgewell/trace-mapping@0.3.20:
+ resolution: {integrity: sha512-R8LcPeWZol2zR8mmH3JeKQ6QRCFb7XgUhV9ZlGhHLGyg4wpPiPZNQOOWhFZhxKw8u//yTbNGI42Bx/3paXEQ+Q==}
+ dependencies:
+ '@jridgewell/resolve-uri': 3.1.1
+ '@jridgewell/sourcemap-codec': 1.4.15
+ dev: true
+
+ /@malept/cross-spawn-promise@1.1.1:
+ resolution: {integrity: sha512-RTBGWL5FWQcg9orDOCcp4LvItNzUPcyEU9bwaeJX0rJ1IQxzucC48Y0/sQLp/g6t99IQgAlGIaesJS+gTn7tVQ==}
+ engines: {node: '>= 10'}
+ dependencies:
+ cross-spawn: 7.0.3
+ dev: true
+
+ /@malept/flatpak-bundler@0.4.0:
+ resolution: {integrity: sha512-9QOtNffcOF/c1seMCDnjckb3R9WHcG34tky+FHpNKKCW0wc/scYLwMtO+ptyGUfMW0/b/n4qRiALlaFHc9Oj7Q==}
+ engines: {node: '>= 10.0.0'}
+ dependencies:
+ debug: 4.3.4
+ fs-extra: 9.1.0
+ lodash: 4.17.21
+ tmp-promise: 3.0.3
+ transitivePeerDependencies:
+ - supports-color
+ dev: true
+
+ /@rollup/rollup-android-arm-eabi@4.13.0:
+ resolution: {integrity: sha512-5ZYPOuaAqEH/W3gYsRkxQATBW3Ii1MfaT4EQstTnLKViLi2gLSQmlmtTpGucNP3sXEpOiI5tdGhjdE111ekyEg==}
+ cpu: [arm]
+ os: [android]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@rollup/rollup-android-arm64@4.13.0:
+ resolution: {integrity: sha512-BSbaCmn8ZadK3UAQdlauSvtaJjhlDEjS5hEVVIN3A4bbl3X+otyf/kOJV08bYiRxfejP3DXFzO2jz3G20107+Q==}
+ cpu: [arm64]
+ os: [android]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@rollup/rollup-darwin-arm64@4.13.0:
+ resolution: {integrity: sha512-Ovf2evVaP6sW5Ut0GHyUSOqA6tVKfrTHddtmxGQc1CTQa1Cw3/KMCDEEICZBbyppcwnhMwcDce9ZRxdWRpVd6g==}
+ cpu: [arm64]
+ os: [darwin]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@rollup/rollup-darwin-x64@4.13.0:
+ resolution: {integrity: sha512-U+Jcxm89UTK592vZ2J9st9ajRv/hrwHdnvyuJpa5A2ngGSVHypigidkQJP+YiGL6JODiUeMzkqQzbCG3At81Gg==}
+ cpu: [x64]
+ os: [darwin]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@rollup/rollup-linux-arm-gnueabihf@4.13.0:
+ resolution: {integrity: sha512-8wZidaUJUTIR5T4vRS22VkSMOVooG0F4N+JSwQXWSRiC6yfEsFMLTYRFHvby5mFFuExHa/yAp9juSphQQJAijQ==}
+ cpu: [arm]
+ os: [linux]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@rollup/rollup-linux-arm64-gnu@4.13.0:
+ resolution: {integrity: sha512-Iu0Kno1vrD7zHQDxOmvweqLkAzjxEVqNhUIXBsZ8hu8Oak7/5VTPrxOEZXYC1nmrBVJp0ZcL2E7lSuuOVaE3+w==}
+ cpu: [arm64]
+ os: [linux]
+ libc: [glibc]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@rollup/rollup-linux-arm64-musl@4.13.0:
+ resolution: {integrity: sha512-C31QrW47llgVyrRjIwiOwsHFcaIwmkKi3PCroQY5aVq4H0A5v/vVVAtFsI1nfBngtoRpeREvZOkIhmRwUKkAdw==}
+ cpu: [arm64]
+ os: [linux]
+ libc: [musl]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@rollup/rollup-linux-riscv64-gnu@4.13.0:
+ resolution: {integrity: sha512-Oq90dtMHvthFOPMl7pt7KmxzX7E71AfyIhh+cPhLY9oko97Zf2C9tt/XJD4RgxhaGeAraAXDtqxvKE1y/j35lA==}
+ cpu: [riscv64]
+ os: [linux]
+ libc: [glibc]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@rollup/rollup-linux-x64-gnu@4.13.0:
+ resolution: {integrity: sha512-yUD/8wMffnTKuiIsl6xU+4IA8UNhQ/f1sAnQebmE/lyQ8abjsVyDkyRkWop0kdMhKMprpNIhPmYlCxgHrPoXoA==}
+ cpu: [x64]
+ os: [linux]
+ libc: [glibc]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@rollup/rollup-linux-x64-musl@4.13.0:
+ resolution: {integrity: sha512-9RyNqoFNdF0vu/qqX63fKotBh43fJQeYC98hCaf89DYQpv+xu0D8QFSOS0biA7cGuqJFOc1bJ+m2rhhsKcw1hw==}
+ cpu: [x64]
+ os: [linux]
+ libc: [musl]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@rollup/rollup-win32-arm64-msvc@4.13.0:
+ resolution: {integrity: sha512-46ue8ymtm/5PUU6pCvjlic0z82qWkxv54GTJZgHrQUuZnVH+tvvSP0LsozIDsCBFO4VjJ13N68wqrKSeScUKdA==}
+ cpu: [arm64]
+ os: [win32]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@rollup/rollup-win32-ia32-msvc@4.13.0:
+ resolution: {integrity: sha512-P5/MqLdLSlqxbeuJ3YDeX37srC8mCflSyTrUsgbU1c/U9j6l2g2GiIdYaGD9QjdMQPMSgYm7hgg0551wHyIluw==}
+ cpu: [ia32]
+ os: [win32]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@rollup/rollup-win32-x64-msvc@4.13.0:
+ resolution: {integrity: sha512-UKXUQNbO3DOhzLRwHSpa0HnhhCgNODvfoPWv2FCXme8N/ANFfhIPMGuOT+QuKd16+B5yxZ0HdpNlqPvTMS1qfw==}
+ cpu: [x64]
+ os: [win32]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@simonwep/pickr@1.8.2:
+ resolution: {integrity: sha512-/l5w8BIkrpP6n1xsetx9MWPWlU6OblN5YgZZphxan0Tq4BByTCETL6lyIeY8lagalS2Nbt4F2W034KHLIiunKA==}
+ dependencies:
+ core-js: 3.33.3
+ nanopop: 2.3.0
+ dev: true
+
+ /@sindresorhus/is@0.14.0:
+ resolution: {integrity: sha512-9NET910DNaIPngYnLLPeg+Ogzqsi9uM4mSboU5y6p8S5DzMTVEsJZrawi+BoDNUVBa2DhJqQYUFvMDfgU062LQ==}
+ engines: {node: '>=6'}
+ dev: true
+
+ /@szmarczak/http-timer@1.1.2:
+ resolution: {integrity: sha512-XIB2XbzHTN6ieIjfIMV9hlVcfPU26s2vafYWQcZHWXHOxiaRZYEDKEwdl129Zyg50+foYV2jCgtrqSA6qNuNSA==}
+ engines: {node: '>=6'}
+ dependencies:
+ defer-to-connect: 1.1.3
+ dev: true
+
+ /@tootallnate/once@2.0.0:
+ resolution: {integrity: sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==}
+ engines: {node: '>= 10'}
+ dev: true
+
+ /@types/crypto-js@4.2.2:
+ resolution: {integrity: sha512-sDOLlVbHhXpAUAL0YHDUUwDZf3iN4Bwi4W6a0W0b+QcAezUbRtH4FVb+9J4h+XFPW7l/gQ9F8qC7P+Ec4k8QVQ==}
+ dev: true
+
+ /@types/debug@4.1.12:
+ resolution: {integrity: sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ==}
+ dependencies:
+ '@types/ms': 0.7.34
+ dev: true
+
+ /@types/estree@1.0.5:
+ resolution: {integrity: sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==}
+ dev: true
+
+ /@types/fast-levenshtein@0.0.4:
+ resolution: {integrity: sha512-tkDveuitddQCxut1Db8eEFfMahTjOumTJGPHmT9E7KUH+DkVq9WTpVvlfenf3S+uCBeu8j5FP2xik/KfxOEjeA==}
+ dev: true
+
+ /@types/fs-extra@9.0.13:
+ resolution: {integrity: sha512-nEnwB++1u5lVDM2UI4c1+5R+FYaKfaAzS4OococimjVm3nQw3TuzH5UNsocrcTBbhnerblyHj4A49qXbIiZdpA==}
+ dependencies:
+ '@types/node': 20.11.30
+ dev: true
+
+ /@types/howler@2.2.11:
+ resolution: {integrity: sha512-7aBoUL6RbSIrqKnpEgfa1wSNUBK06mn08siP2QI0zYk7MXfEJAaORc4tohamQYqCqVESoDyRWSdQn2BOKWj2Qw==}
+ dev: true
+
+ /@types/keyv@3.1.4:
+ resolution: {integrity: sha512-BQ5aZNSCpj7D6K2ksrRCTmKRLEpnPvWDiLPfoGyhZ++8YtiK9d/3DBKPJgry359X/P1PfruyYwvnvwFjuEiEIg==}
+ dependencies:
+ '@types/node': 20.11.30
+ dev: true
+
+ /@types/linkify-it@3.0.5:
+ resolution: {integrity: sha512-yg6E+u0/+Zjva+buc3EIb+29XEg4wltq7cSmd4Uc2EE/1nUVmxyzpX6gUXD0V8jIrG0r7YeOGVIbYRkxeooCtw==}
+ dev: true
+
+ /@types/lodash@4.17.0:
+ resolution: {integrity: sha512-t7dhREVv6dbNj0q17X12j7yDG4bD/DHYX7o5/DbDxobP0HnGPgpRz2Ej77aL7TZT3DSw13fqUTj8J4mMnqa7WA==}
+ dev: true
+
+ /@types/markdown-it@13.0.7:
+ resolution: {integrity: sha512-U/CBi2YUUcTHBt5tjO2r5QV/x0Po6nsYwQU4Y04fBS6vfoImaiZ6f8bi3CjTCxBPQSO1LMyUqkByzi8AidyxfA==}
+ dependencies:
+ '@types/linkify-it': 3.0.5
+ '@types/mdurl': 1.0.5
+ dev: true
+
+ /@types/mdurl@1.0.5:
+ resolution: {integrity: sha512-6L6VymKTzYSrEf4Nev4Xa1LCHKrlTlYCBMTlQKFuddo1CvQcE52I0mwfOJayueUC7MJuXOeHTcIU683lzd0cUA==}
+ dev: true
+
+ /@types/mime-types@2.1.4:
+ resolution: {integrity: sha512-lfU4b34HOri+kAY5UheuFMWPDOI+OPceBSHZKp69gEyTL/mmJ4cnU6Y/rlme3UL3GyOn6Y42hyIEw0/q8sWx5w==}
+ dev: true
+
+ /@types/ms@0.7.34:
+ resolution: {integrity: sha512-nG96G3Wp6acyAgJqGasjODb+acrI7KltPiRxzHPXnP3NgI28bpQDRv53olbqGXbfcgF5aiiHmO3xpwEpS5Ld9g==}
+ dev: true
+
+ /@types/node-ssdp@4.0.4:
+ resolution: {integrity: sha512-k5gWpZYrNAZ1alW8RoAPaYlk6IYPad92FyeyOk1n2RIdwouNJZ4Ft8Fc2YxFUwty+bBqY4C/fWFEOxdso4jSoA==}
+ dependencies:
+ '@types/node': 20.11.30
+ dev: true
+
+ /@types/node@16.18.82:
+ resolution: {integrity: sha512-pcDZtkx9z8XYV+ius2P3Ot2VVrcYOfXffBQUBuiszrlUzKSmoDYqo+mV+IoL8iIiIjjtOMvNSmH1hwJ+Q+f96Q==}
+ dev: true
+
+ /@types/node@20.11.30:
+ resolution: {integrity: sha512-dHM6ZxwlmuZaRmUPfv1p+KrdD1Dci04FbdEm/9wEMouFqxYoFl5aMkt0VMAUtYRQDyYvD41WJLukhq/ha3YuTw==}
+ dependencies:
+ undici-types: 5.26.5
+ dev: true
+
+ /@types/plist@3.0.5:
+ resolution: {integrity: sha512-E6OCaRmAe4WDmWNsL/9RMqdkkzDCY1etutkflWk4c+AcjDU07Pcz1fQwTX0TQz+Pxqn9i4L1TU3UFpjnrcDgxA==}
+ requiresBuild: true
+ dependencies:
+ '@types/node': 20.11.30
+ xmlbuilder: 15.1.1
+ dev: true
+ optional: true
+
+ /@types/responselike@1.0.3:
+ resolution: {integrity: sha512-H/+L+UkTV33uf49PH5pCAUBVPNj2nDBXTN+qS1dOwyyg24l3CcicicCA7ca+HMvJBZcFgl5r8e+RR6elsb4Lyw==}
+ dependencies:
+ '@types/node': 20.11.30
+ dev: true
+
+ /@types/secp256k1@4.0.6:
+ resolution: {integrity: sha512-hHxJU6PAEUn0TP4S/ZOzuTUvJWuZ6eIKeNKb5RBpODvSl6hp1Wrw4s7ATY50rklRCScUDpHzVA/DQdSjJ3UoYQ==}
+ dependencies:
+ '@types/node': 20.11.30
+ dev: true
+
+ /@types/thunky@1.1.2:
+ resolution: {integrity: sha512-VI0UCE4siVMkLBLZBOls+ohv2uXcBYQvwD6IkseB4WAIXktRuMPE7FKZ13B5UlN3Q7/fLFDSgZ1/mkFEXpDY1g==}
+ dev: true
+
+ /@types/uuid@9.0.8:
+ resolution: {integrity: sha512-jg+97EGIcY9AGHJJRaaPVgetKDsrTgbRjQ5Msgjh/DQKEFl0DtyRr/VCOyD1T2R1MNeWPK/u7JoGhlDZnKBAfA==}
+ dev: true
+
+ /@types/verror@1.10.9:
+ resolution: {integrity: sha512-MLx9Z+9lGzwEuW16ubGeNkpBDE84RpB/NyGgg6z2BTpWzKkGU451cAY3UkUzZEp72RHF585oJ3V8JVNqIplcAQ==}
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /@types/yauzl@2.10.3:
+ resolution: {integrity: sha512-oJoftv0LSuaDZE3Le4DbKX+KS9G36NzOeSap90UIK0yMA/NhKJhqlSGtNDORNRaIbQfzjXDrQa0ytJ6mNRGz/Q==}
+ requiresBuild: true
+ dependencies:
+ '@types/node': 20.11.30
+ dev: true
+ optional: true
+
+ /@vitejs/plugin-vue-jsx@3.1.0(vite@5.2.2)(vue@3.4.21):
+ resolution: {integrity: sha512-w9M6F3LSEU5kszVb9An2/MmXNxocAnUb3WhRr8bHlimhDrXNt6n6D2nJQR3UXpGlZHh/EsgouOHCsM8V3Ln+WA==}
+ engines: {node: ^14.18.0 || >=16.0.0}
+ peerDependencies:
+ vite: ^4.0.0 || ^5.0.0
+ vue: ^3.0.0
+ dependencies:
+ '@babel/core': 7.23.5
+ '@babel/plugin-transform-typescript': 7.23.5(@babel/core@7.23.5)
+ '@vue/babel-plugin-jsx': 1.1.5(@babel/core@7.23.5)
+ vite: 5.2.2(@types/node@20.11.30)(less@4.2.0)(terser@5.29.2)
+ vue: 3.4.21(typescript@5.4.3)
+ transitivePeerDependencies:
+ - supports-color
+ dev: true
+
+ /@vitejs/plugin-vue@5.0.4(vite@5.2.2)(vue@3.4.21):
+ resolution: {integrity: sha512-WS3hevEszI6CEVEx28F8RjTX97k3KsrcY6kvTg7+Whm5y3oYvcqzVeGCU3hxSAn4uY2CLCkeokkGKpoctccilQ==}
+ engines: {node: ^18.0.0 || >=20.0.0}
+ peerDependencies:
+ vite: ^5.0.0
+ vue: ^3.2.25
+ dependencies:
+ vite: 5.2.2(@types/node@20.11.30)(less@4.2.0)(terser@5.29.2)
+ vue: 3.4.21(typescript@5.4.3)
+ dev: true
+
+ /@volar/language-core@2.1.4:
+ resolution: {integrity: sha512-ROfPepDxZ5Eq+Unbx3M9QcHT7MoE9tYdbkuzLTtxG5rfkEi5RwsDPncjANMOq/gHhIIDlWgqWwS2nXWMGsuj4w==}
+ dependencies:
+ '@volar/source-map': 2.1.4
+ dev: true
+
+ /@volar/source-map@2.1.4:
+ resolution: {integrity: sha512-mCg8IiPZmHZVzqL4Owg+BzQ5ZTG1cVwATxrkrFPZpcAin97Xa3MbchxVhHtHTWTT8ER8bJh5xVjeVxsSN++FUA==}
+ dependencies:
+ muggle-string: 0.4.1
+ dev: true
+
+ /@volar/typescript@2.1.4:
+ resolution: {integrity: sha512-Mt7wOLPkomFnUfVpb5IHlPhSpD7FJAn+FHSsovePmqFNQzFLz16wrpHjAkorPiAnP0847w71NL5fIJyWbAsR8Q==}
+ dependencies:
+ '@volar/language-core': 2.1.4
+ path-browserify: 1.0.1
+ dev: true
+
+ /@vue/babel-helper-vue-transform-on@1.1.5:
+ resolution: {integrity: sha512-SgUymFpMoAyWeYWLAY+MkCK3QEROsiUnfaw5zxOVD/M64KQs8D/4oK6Q5omVA2hnvEOE0SCkH2TZxs/jnnUj7w==}
+ dev: true
+
+ /@vue/babel-plugin-jsx@1.1.5(@babel/core@7.23.5):
+ resolution: {integrity: sha512-nKs1/Bg9U1n3qSWnsHhCVQtAzI6aQXqua8j/bZrau8ywT1ilXQbK4FwEJGmU8fV7tcpuFvWmmN7TMmV1OBma1g==}
+ peerDependencies:
+ '@babel/core': ^7.0.0-0
+ dependencies:
+ '@babel/core': 7.23.5
+ '@babel/helper-module-imports': 7.22.15
+ '@babel/plugin-syntax-jsx': 7.23.3(@babel/core@7.23.5)
+ '@babel/template': 7.22.15
+ '@babel/traverse': 7.23.5
+ '@babel/types': 7.23.5
+ '@vue/babel-helper-vue-transform-on': 1.1.5
+ camelcase: 6.3.0
+ html-tags: 3.3.1
+ svg-tags: 1.0.0
+ transitivePeerDependencies:
+ - supports-color
+ dev: true
+
+ /@vue/compiler-core@3.4.21:
+ resolution: {integrity: sha512-MjXawxZf2SbZszLPYxaFCjxfibYrzr3eYbKxwpLR9EQN+oaziSu3qKVbwBERj1IFIB8OLUewxB5m/BFzi613og==}
+ dependencies:
+ '@babel/parser': 7.23.9
+ '@vue/shared': 3.4.21
+ entities: 4.5.0
+ estree-walker: 2.0.2
+ source-map-js: 1.0.2
+ dev: true
+
+ /@vue/compiler-dom@3.4.21:
+ resolution: {integrity: sha512-IZC6FKowtT1sl0CR5DpXSiEB5ayw75oT2bma1BEhV7RRR1+cfwLrxc2Z8Zq/RGFzJ8w5r9QtCOvTjQgdn0IKmA==}
+ dependencies:
+ '@vue/compiler-core': 3.4.21
+ '@vue/shared': 3.4.21
+ dev: true
+
+ /@vue/compiler-sfc@3.4.21:
+ resolution: {integrity: sha512-me7epoTxYlY+2CUM7hy9PCDdpMPfIwrOvAXud2Upk10g4YLv9UBW7kL798TvMeDhPthkZ0CONNrK2GoeI1ODiQ==}
+ dependencies:
+ '@babel/parser': 7.23.9
+ '@vue/compiler-core': 3.4.21
+ '@vue/compiler-dom': 3.4.21
+ '@vue/compiler-ssr': 3.4.21
+ '@vue/shared': 3.4.21
+ estree-walker: 2.0.2
+ magic-string: 0.30.7
+ postcss: 8.4.35
+ source-map-js: 1.0.2
+ dev: true
+
+ /@vue/compiler-ssr@3.4.21:
+ resolution: {integrity: sha512-M5+9nI2lPpAsgXOGQobnIueVqc9sisBFexh5yMIMRAPYLa7+5wEJs8iqOZc1WAa9WQbx9GR2twgznU8LTIiZ4Q==}
+ dependencies:
+ '@vue/compiler-dom': 3.4.21
+ '@vue/shared': 3.4.21
+ dev: true
+
+ /@vue/devtools-api@6.5.1:
+ resolution: {integrity: sha512-+KpckaAQyfbvshdDW5xQylLni1asvNSGme1JFs8I1+/H5pHEhqUKMEQD/qn3Nx5+/nycBq11qAEi8lk+LXI2dA==}
+ dev: true
+
+ /@vue/language-core@2.0.7(typescript@5.4.3):
+ resolution: {integrity: sha512-Vh1yZX3XmYjn9yYLkjU8DN6L0ceBtEcapqiyclHne8guG84IaTzqtvizZB1Yfxm3h6m7EIvjerLO5fvOZO6IIQ==}
+ peerDependencies:
+ typescript: '*'
+ peerDependenciesMeta:
+ typescript:
+ optional: true
+ dependencies:
+ '@volar/language-core': 2.1.4
+ '@vue/compiler-dom': 3.4.21
+ '@vue/shared': 3.4.21
+ computeds: 0.0.1
+ minimatch: 9.0.3
+ path-browserify: 1.0.1
+ typescript: 5.4.3
+ vue-template-compiler: 2.7.15
+ dev: true
+
+ /@vue/reactivity@3.4.21:
+ resolution: {integrity: sha512-UhenImdc0L0/4ahGCyEzc/pZNwVgcglGy9HVzJ1Bq2Mm9qXOpP8RyNTjookw/gOCUlXSEtuZ2fUg5nrHcoqJcw==}
+ dependencies:
+ '@vue/shared': 3.4.21
+ dev: true
+
+ /@vue/runtime-core@3.4.21:
+ resolution: {integrity: sha512-pQthsuYzE1XcGZznTKn73G0s14eCJcjaLvp3/DKeYWoFacD9glJoqlNBxt3W2c5S40t6CCcpPf+jG01N3ULyrA==}
+ dependencies:
+ '@vue/reactivity': 3.4.21
+ '@vue/shared': 3.4.21
+ dev: true
+
+ /@vue/runtime-dom@3.4.21:
+ resolution: {integrity: sha512-gvf+C9cFpevsQxbkRBS1NpU8CqxKw0ebqMvLwcGQrNpx6gqRDodqKqA+A2VZZpQ9RpK2f9yfg8VbW/EpdFUOJw==}
+ dependencies:
+ '@vue/runtime-core': 3.4.21
+ '@vue/shared': 3.4.21
+ csstype: 3.1.3
+ dev: true
+
+ /@vue/server-renderer@3.4.21(vue@3.4.21):
+ resolution: {integrity: sha512-aV1gXyKSN6Rz+6kZ6kr5+Ll14YzmIbeuWe7ryJl5muJ4uwSwY/aStXTixx76TwkZFJLm1aAlA/HSWEJ4EyiMkg==}
+ peerDependencies:
+ vue: 3.4.21
+ dependencies:
+ '@vue/compiler-ssr': 3.4.21
+ '@vue/shared': 3.4.21
+ vue: 3.4.21(typescript@5.4.3)
+ dev: true
+
+ /@vue/shared@3.4.21:
+ resolution: {integrity: sha512-PuJe7vDIi6VYSinuEbUIQgMIRZGgM8e4R+G+/dQTk0X1NEdvgvvgv7m+rfmDH1gZzyA1OjjoWskvHlfRNfQf3g==}
+ dev: true
+
+ /@xmldom/xmldom@0.8.10:
+ resolution: {integrity: sha512-2WALfTl4xo2SkGCYRt6rDTFfk9R1czmBvUQy12gK2KuRKIpWEhcbbzy8EZXtz/jkRqHX8bFEc6FC1HjX4TUWYw==}
+ engines: {node: '>=10.0.0'}
+ requiresBuild: true
+ dev: true
+
+ /acorn@8.11.2:
+ resolution: {integrity: sha512-nc0Axzp/0FILLEVsm4fNwLCwMttvhEI263QtVPQcbpfZZ3ts0hLsZGOpE6czNlid7CJ9MlyH8reXkpsf3YUY4w==}
+ engines: {node: '>=0.4.0'}
+ hasBin: true
+ dev: true
+
+ /agent-base@6.0.2:
+ resolution: {integrity: sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==}
+ engines: {node: '>= 6.0.0'}
+ dependencies:
+ debug: 4.3.4
+ transitivePeerDependencies:
+ - supports-color
+ dev: true
+
+ /agent-base@7.1.0:
+ resolution: {integrity: sha512-o/zjMZRhJxny7OyEF+Op8X+efiELC7k7yOjMzgfzVqOzXqkBkWI79YoTdOtsuWd5BWhAGAuOY/Xa6xpiaWXiNg==}
+ engines: {node: '>= 14'}
+ dependencies:
+ debug: 4.3.4
+ transitivePeerDependencies:
+ - supports-color
+ dev: true
+
+ /ajv-keywords@3.5.2(ajv@6.12.6):
+ resolution: {integrity: sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==}
+ peerDependencies:
+ ajv: ^6.9.1
+ dependencies:
+ ajv: 6.12.6
+ dev: true
+
+ /ajv@6.12.6:
+ resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==}
+ dependencies:
+ fast-deep-equal: 3.1.3
+ fast-json-stable-stringify: 2.1.0
+ json-schema-traverse: 0.4.1
+ uri-js: 4.4.1
+ dev: true
+
+ /ansi-regex@5.0.1:
+ resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==}
+ engines: {node: '>=8'}
+ dev: true
+
+ /ansi-regex@6.0.1:
+ resolution: {integrity: sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==}
+ engines: {node: '>=12'}
+ dev: true
+
+ /ansi-styles@3.2.1:
+ resolution: {integrity: sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==}
+ engines: {node: '>=4'}
+ dependencies:
+ color-convert: 1.9.3
+ dev: true
+
+ /ansi-styles@4.3.0:
+ resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==}
+ engines: {node: '>=8'}
+ dependencies:
+ color-convert: 2.0.1
+ dev: true
+
+ /ant-design-vue@4.1.2(vue@3.4.21):
+ resolution: {integrity: sha512-ynFkDJLlHgumeK6Hr1UZ7PvQNZ1uBcri/pmejBdS3kRqHeA5VRsxneYDwa8YxA+uYB5YfT2jpYsSHsiMiCjRGg==}
+ engines: {node: '>=12.22.0'}
+ peerDependencies:
+ vue: '>=3.2.0'
+ dependencies:
+ '@ant-design/colors': 6.0.0
+ '@ant-design/icons-vue': 7.0.1(vue@3.4.21)
+ '@babel/runtime': 7.23.5
+ '@ctrl/tinycolor': 3.6.1
+ '@emotion/hash': 0.9.1
+ '@emotion/unitless': 0.8.1
+ '@simonwep/pickr': 1.8.2
+ array-tree-filter: 2.1.0
+ async-validator: 4.2.5
+ csstype: 3.1.3
+ dayjs: 1.11.10
+ dom-align: 1.12.4
+ dom-scroll-into-view: 2.0.1
+ lodash: 4.17.21
+ lodash-es: 4.17.21
+ resize-observer-polyfill: 1.5.1
+ scroll-into-view-if-needed: 2.2.31
+ shallow-equal: 1.2.1
+ stylis: 4.3.1
+ throttle-debounce: 5.0.0
+ vue: 3.4.21(typescript@5.4.3)
+ vue-types: 3.0.2(vue@3.4.21)
+ warning: 4.0.3
+ dev: true
+
+ /app-builder-bin@4.0.0:
+ resolution: {integrity: sha512-xwdG0FJPQMe0M0UA4Tz0zEB8rBJTRA5a476ZawAqiBkMv16GRK5xpXThOjMaEOFnZ6zabejjG4J3da0SXG63KA==}
+ dev: true
+
+ /app-builder-lib@24.13.3(dmg-builder@24.13.3)(electron-builder-squirrel-windows@24.13.3):
+ resolution: {integrity: sha512-FAzX6IBit2POXYGnTCT8YHFO/lr5AapAII6zzhQO3Rw4cEDOgK+t1xhLc5tNcKlicTHlo9zxIwnYCX9X2DLkig==}
+ engines: {node: '>=14.0.0'}
+ peerDependencies:
+ dmg-builder: 24.13.3
+ electron-builder-squirrel-windows: 24.13.3
+ dependencies:
+ '@develar/schema-utils': 2.6.5
+ '@electron/notarize': 2.2.1
+ '@electron/osx-sign': 1.0.5
+ '@electron/universal': 1.5.1
+ '@malept/flatpak-bundler': 0.4.0
+ '@types/fs-extra': 9.0.13
+ async-exit-hook: 2.0.1
+ bluebird-lst: 1.0.9
+ builder-util: 24.13.1
+ builder-util-runtime: 9.2.4
+ chromium-pickle-js: 0.2.0
+ debug: 4.3.4
+ dmg-builder: 24.13.3(electron-builder-squirrel-windows@24.13.3)
+ ejs: 3.1.9
+ electron-builder-squirrel-windows: 24.13.3(dmg-builder@24.13.3)
+ electron-publish: 24.13.1
+ form-data: 4.0.0
+ fs-extra: 10.1.0
+ hosted-git-info: 4.1.0
+ is-ci: 3.0.1
+ isbinaryfile: 5.0.0
+ js-yaml: 4.1.0
+ lazy-val: 1.0.5
+ minimatch: 5.1.6
+ read-config-file: 6.3.2
+ sanitize-filename: 1.6.3
+ semver: 7.6.0
+ tar: 6.2.0
+ temp-file: 3.4.0
+ transitivePeerDependencies:
+ - supports-color
+ dev: true
+
+ /archiver-utils@2.1.0:
+ resolution: {integrity: sha512-bEL/yUb/fNNiNTuUz979Z0Yg5L+LzLxGJz8x79lYmR54fmTIb6ob/hNQgkQnIUDWIFjZVQwl9Xs356I6BAMHfw==}
+ engines: {node: '>= 6'}
+ dependencies:
+ glob: 7.2.3
+ graceful-fs: 4.2.11
+ lazystream: 1.0.1
+ lodash.defaults: 4.2.0
+ lodash.difference: 4.5.0
+ lodash.flatten: 4.4.0
+ lodash.isplainobject: 4.0.6
+ lodash.union: 4.6.0
+ normalize-path: 3.0.0
+ readable-stream: 2.3.8
+ dev: true
+
+ /archiver-utils@3.0.4:
+ resolution: {integrity: sha512-KVgf4XQVrTjhyWmx6cte4RxonPLR9onExufI1jhvw/MQ4BB6IsZD5gT8Lq+u/+pRkWna/6JoHpiQioaqFP5Rzw==}
+ engines: {node: '>= 10'}
+ dependencies:
+ glob: 7.2.3
+ graceful-fs: 4.2.11
+ lazystream: 1.0.1
+ lodash.defaults: 4.2.0
+ lodash.difference: 4.5.0
+ lodash.flatten: 4.4.0
+ lodash.isplainobject: 4.0.6
+ lodash.union: 4.6.0
+ normalize-path: 3.0.0
+ readable-stream: 3.6.2
+ dev: true
+
+ /archiver@5.3.2:
+ resolution: {integrity: sha512-+25nxyyznAXF7Nef3y0EbBeqmGZgeN/BxHX29Rs39djAfaFalmQ89SE6CWyDCHzGL0yt/ycBtNOmGTW0FyGWNw==}
+ engines: {node: '>= 10'}
+ dependencies:
+ archiver-utils: 2.1.0
+ async: 3.2.5
+ buffer-crc32: 0.2.13
+ readable-stream: 3.6.2
+ readdir-glob: 1.1.3
+ tar-stream: 2.2.0
+ zip-stream: 4.1.1
+ dev: true
+
+ /argparse@2.0.1:
+ resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==}
+ dev: true
+
+ /aria2-lib@1.0.1:
+ resolution: {integrity: sha512-+kzXnMUEm1qANHkTmMjn4sWv9Bpc+DGSPbUHpAKFVdVgfZcT5kLsh2SGF+6j7NsXwkRfH8NDhkFtNQpZ4qSYZQ==}
+ dev: true
+
+ /array-tree-filter@2.1.0:
+ resolution: {integrity: sha512-4ROwICNlNw/Hqa9v+rk5h22KjmzB1JGTMVKP2AKJBOCgb0yL0ASf0+YvCcLNNwquOHNX48jkeZIJ3a+oOQqKcw==}
+ dev: true
+
+ /artplayer@5.1.1:
+ resolution: {integrity: sha512-pZ2/lB+Oo3g0CVLqkFuB86bMBPMtZaABaq5e1LPKubYDBW46+mzin2wzdVmk3tvFyfQoVnb+MBFU7nJYvI3qNg==}
+ dependencies:
+ option-validator: 2.0.6
+ dev: true
+
+ /assert-plus@1.0.0:
+ resolution: {integrity: sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw==}
+ engines: {node: '>=0.8'}
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /astral-regex@2.0.0:
+ resolution: {integrity: sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==}
+ engines: {node: '>=8'}
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /async-exit-hook@2.0.1:
+ resolution: {integrity: sha512-NW2cX8m1Q7KPA7a5M2ULQeZ2wR5qI5PAbw5L0UOMxdioVk9PMZ0h1TmyZEkPYrCvYjDlFICusOu1dlEKAAeXBw==}
+ engines: {node: '>=0.12.0'}
+ dev: true
+
+ /async-validator@4.2.5:
+ resolution: {integrity: sha512-7HhHjtERjqlNbZtqNqy2rckN/SpOOlmDliet+lP7k+eKZEjPk3DgyeU9lIXLdeLz0uBbbVp+9Qdow9wJWgwwfg==}
+ dev: true
+
+ /async@2.6.4:
+ resolution: {integrity: sha512-mzo5dfJYwAn29PeiJ0zvwTo04zj8HDJj0Mn8TD7sno7q12prdbnasKJHhkm2c1LgrhlJ0teaea8860oxi51mGA==}
+ dependencies:
+ lodash: 4.17.21
+ dev: true
+
+ /async@3.2.5:
+ resolution: {integrity: sha512-baNZyqaaLhyLVKm/DlvdW051MSgO6b8eVfIezl9E5PqWxFgzLm/wQntEW4zOytVburDEr0JlALEpdOFwvErLsg==}
+ dev: true
+
+ /asynckit@0.4.0:
+ resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==}
+ dev: true
+
+ /at-least-node@1.0.0:
+ resolution: {integrity: sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==}
+ engines: {node: '>= 4.0.0'}
+ dev: true
+
+ /axios@1.6.8:
+ resolution: {integrity: sha512-v/ZHtJDU39mDpyBoFVkETcd/uNdxrWRrg3bKpOKzXFA6Bvqopts6ALSMU3y6ijYxbw2B+wPrIv46egTzJXCLGQ==}
+ dependencies:
+ follow-redirects: 1.15.6
+ form-data: 4.0.0
+ proxy-from-env: 1.1.0
+ transitivePeerDependencies:
+ - debug
+ dev: true
+
+ /b-tween@0.3.3:
+ resolution: {integrity: sha512-oEHegcRpA7fAuc9KC4nktucuZn2aS8htymCPcP3qkEGPqiBH+GfqtqoG2l7LxHngg6O0HFM7hOeOYExl1Oz4ZA==}
+ dev: true
+
+ /b-validate@1.5.3:
+ resolution: {integrity: sha512-iCvCkGFskbaYtfQ0a3GmcQCHl/Sv1GufXFGuUQ+FE+WJa7A/espLOuFIn09B944V8/ImPj71T4+rTASxO2PAuA==}
+ dev: true
+
+ /balanced-match@1.0.2:
+ resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==}
+ dev: true
+
+ /base64-js@1.5.1:
+ resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==}
+ requiresBuild: true
+ dev: true
+
+ /bl@4.1.0:
+ resolution: {integrity: sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==}
+ dependencies:
+ buffer: 5.7.1
+ inherits: 2.0.4
+ readable-stream: 3.6.2
+ dev: true
+
+ /bluebird-lst@1.0.9:
+ resolution: {integrity: sha512-7B1Rtx82hjnSD4PGLAjVWeYH3tHAcVUmChh85a3lltKQm6FresXh9ErQo6oAv6CqxttczC3/kEg8SY5NluPuUw==}
+ dependencies:
+ bluebird: 3.7.2
+ dev: true
+
+ /bluebird@3.7.2:
+ resolution: {integrity: sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==}
+ dev: true
+
+ /bn.js@4.12.0:
+ resolution: {integrity: sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==}
+ dev: true
+
+ /boolbase@1.0.0:
+ resolution: {integrity: sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==}
+ dev: true
+
+ /boolean@3.2.0:
+ resolution: {integrity: sha512-d0II/GO9uf9lfUHH2BQsjxzRJZBdsjgsBiW4BvhWk/3qoKwQFjIDVN19PfX8F2D/r9PCMTtLWjYVCFrpeYUzsw==}
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /brace-expansion@1.1.11:
+ resolution: {integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==}
+ dependencies:
+ balanced-match: 1.0.2
+ concat-map: 0.0.1
+ dev: true
+
+ /brace-expansion@2.0.1:
+ resolution: {integrity: sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==}
+ dependencies:
+ balanced-match: 1.0.2
+ dev: true
+
+ /brorand@1.1.0:
+ resolution: {integrity: sha512-cKV8tMCEpQs4hK/ik71d6LrPOnpkpGBR0wzxqr68g2m/LB2GxVYQroAjMJZRVM1Y4BCjCKc3vAamxSzOY2RP+w==}
+ dev: true
+
+ /browserslist@4.22.2:
+ resolution: {integrity: sha512-0UgcrvQmBDvZHFGdYUehrCNIazki7/lUP3kkoi/r3YB2amZbFM9J43ZRkJTXBUZK4gmx56+Sqk9+Vs9mwZx9+A==}
+ engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7}
+ hasBin: true
+ dependencies:
+ caniuse-lite: 1.0.30001566
+ electron-to-chromium: 1.4.601
+ node-releases: 2.0.14
+ update-browserslist-db: 1.0.13(browserslist@4.22.2)
+ dev: true
+
+ /buffer-crc32@0.2.13:
+ resolution: {integrity: sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==}
+ dev: true
+
+ /buffer-equal@1.0.1:
+ resolution: {integrity: sha512-QoV3ptgEaQpvVwbXdSO39iqPQTCxSF7A5U99AxbHYqUdCizL/lH2Z0A2y6nbZucxMEOtNyZfG2s6gsVugGpKkg==}
+ engines: {node: '>=0.4'}
+ dev: true
+
+ /buffer-from@1.1.2:
+ resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==}
+ dev: true
+
+ /buffer@5.7.1:
+ resolution: {integrity: sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==}
+ requiresBuild: true
+ dependencies:
+ base64-js: 1.5.1
+ ieee754: 1.2.1
+ dev: true
+
+ /builder-util-runtime@9.2.4:
+ resolution: {integrity: sha512-upp+biKpN/XZMLim7aguUyW8s0FUpDvOtK6sbanMFDAMBzpHDqdhgVYm6zc9HJ6nWo7u2Lxk60i2M6Jd3aiNrA==}
+ engines: {node: '>=12.0.0'}
+ dependencies:
+ debug: 4.3.4
+ sax: 1.3.0
+ transitivePeerDependencies:
+ - supports-color
+ dev: true
+
+ /builder-util@24.13.1:
+ resolution: {integrity: sha512-NhbCSIntruNDTOVI9fdXz0dihaqX2YuE1D6zZMrwiErzH4ELZHE6mdiB40wEgZNprDia+FghRFgKoAqMZRRjSA==}
+ dependencies:
+ 7zip-bin: 5.2.0
+ '@types/debug': 4.1.12
+ app-builder-bin: 4.0.0
+ bluebird-lst: 1.0.9
+ builder-util-runtime: 9.2.4
+ chalk: 4.1.2
+ cross-spawn: 7.0.3
+ debug: 4.3.4
+ fs-extra: 10.1.0
+ http-proxy-agent: 5.0.0
+ https-proxy-agent: 5.0.1
+ is-ci: 3.0.1
+ js-yaml: 4.1.0
+ source-map-support: 0.5.21
+ stat-mode: 1.0.0
+ temp-file: 3.4.0
+ transitivePeerDependencies:
+ - supports-color
+ dev: true
+
+ /cacheable-request@6.1.0:
+ resolution: {integrity: sha512-Oj3cAGPCqOZX7Rz64Uny2GYAZNliQSqfbePrgAQ1wKAihYmCUnraBtJtKcGR4xz7wF+LoJC+ssFZvv5BgF9Igg==}
+ engines: {node: '>=8'}
+ dependencies:
+ clone-response: 1.0.3
+ get-stream: 5.2.0
+ http-cache-semantics: 4.1.1
+ keyv: 3.1.0
+ lowercase-keys: 2.0.0
+ normalize-url: 4.5.1
+ responselike: 1.0.2
+ dev: true
+
+ /camelcase@6.3.0:
+ resolution: {integrity: sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==}
+ engines: {node: '>=10'}
+ dev: true
+
+ /caniuse-lite@1.0.30001566:
+ resolution: {integrity: sha512-ggIhCsTxmITBAMmK8yZjEhCO5/47jKXPu6Dha/wuCS4JePVL+3uiDEBuhu2aIoT+bqTOR8L76Ip1ARL9xYsEJA==}
+ dev: true
+
+ /chalk@2.4.2:
+ resolution: {integrity: sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==}
+ engines: {node: '>=4'}
+ dependencies:
+ ansi-styles: 3.2.1
+ escape-string-regexp: 1.0.5
+ supports-color: 5.5.0
+ dev: true
+
+ /chalk@4.1.2:
+ resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==}
+ engines: {node: '>=10'}
+ dependencies:
+ ansi-styles: 4.3.0
+ supports-color: 7.2.0
+ dev: true
+
+ /chinese-simple2traditional@1.2.0:
+ resolution: {integrity: sha512-0DbXpBBOZzQBklJb/6ykZzsw0ykay95JK3byoQG+YAlFzJn+G6aIPNPQk3/T+whxSJm5J384xLsvQY77km6inA==}
+ dev: true
+
+ /chownr@2.0.0:
+ resolution: {integrity: sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==}
+ engines: {node: '>=10'}
+ dev: true
+
+ /chromium-pickle-js@0.2.0:
+ resolution: {integrity: sha512-1R5Fho+jBq0DDydt+/vHWj5KJNJCKdARKOCwZUen84I5BreWoLqRLANH1U87eJy1tiASPtMnGqJJq0ZsLoRPOw==}
+ dev: true
+
+ /ci-info@3.9.0:
+ resolution: {integrity: sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==}
+ engines: {node: '>=8'}
+ dev: true
+
+ /cli-truncate@2.1.0:
+ resolution: {integrity: sha512-n8fOixwDD6b/ObinzTrp1ZKFzbgvKZvuz/TvejnLn1aQfC6r52XEx85FmuC+3HI+JM7coBRXUvNqEU2PHVrHpg==}
+ engines: {node: '>=8'}
+ requiresBuild: true
+ dependencies:
+ slice-ansi: 3.0.0
+ string-width: 4.2.3
+ dev: true
+ optional: true
+
+ /cliui@8.0.1:
+ resolution: {integrity: sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==}
+ engines: {node: '>=12'}
+ dependencies:
+ string-width: 4.2.3
+ strip-ansi: 6.0.1
+ wrap-ansi: 7.0.0
+ dev: true
+
+ /clone-response@1.0.3:
+ resolution: {integrity: sha512-ROoL94jJH2dUVML2Y/5PEDNaSHgeOdSDicUyS7izcF63G6sTc/FTjLub4b8Il9S8S0beOfYt0TaA5qvFK+w0wA==}
+ dependencies:
+ mimic-response: 1.0.1
+ dev: true
+
+ /color-convert@1.9.3:
+ resolution: {integrity: sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==}
+ dependencies:
+ color-name: 1.1.3
+ dev: true
+
+ /color-convert@2.0.1:
+ resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==}
+ engines: {node: '>=7.0.0'}
+ dependencies:
+ color-name: 1.1.4
+ dev: true
+
+ /color-name@1.1.3:
+ resolution: {integrity: sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==}
+ dev: true
+
+ /color-name@1.1.4:
+ resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==}
+ dev: true
+
+ /color-string@1.9.1:
+ resolution: {integrity: sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg==}
+ dependencies:
+ color-name: 1.1.4
+ simple-swizzle: 0.2.2
+ dev: true
+
+ /color@3.2.1:
+ resolution: {integrity: sha512-aBl7dZI9ENN6fUGC7mWpMTPNHmWUSNan9tuWN6ahh5ZLNk9baLJOnSMlrQkHcrfFgz2/RigjUVAjdx36VcemKA==}
+ dependencies:
+ color-convert: 1.9.3
+ color-string: 1.9.1
+ dev: true
+
+ /combined-stream@1.0.8:
+ resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==}
+ engines: {node: '>= 0.8'}
+ dependencies:
+ delayed-stream: 1.0.0
+ dev: true
+
+ /commander@2.20.3:
+ resolution: {integrity: sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==}
+ dev: true
+
+ /commander@5.1.0:
+ resolution: {integrity: sha512-P0CysNDQ7rtVw4QIQtm+MRxV66vKFSvlsQvGYXZWR3qFU0jlMKHZZZgw8e+8DSah4UDKMqnknRDQz+xuQXQ/Zg==}
+ engines: {node: '>= 6'}
+ dev: true
+
+ /compare-version@0.1.2:
+ resolution: {integrity: sha512-pJDh5/4wrEnXX/VWRZvruAGHkzKdr46z11OlTPN+VrATlWWhSKewNCJ1futCO5C7eJB3nPMFZA1LeYtcFboZ2A==}
+ engines: {node: '>=0.10.0'}
+ dev: true
+
+ /compress-commons@4.1.2:
+ resolution: {integrity: sha512-D3uMHtGc/fcO1Gt1/L7i1e33VOvD4A9hfQLP+6ewd+BvG/gQ84Yh4oftEhAdjSMgBgwGL+jsppT7JYNpo6MHHg==}
+ engines: {node: '>= 10'}
+ dependencies:
+ buffer-crc32: 0.2.13
+ crc32-stream: 4.0.3
+ normalize-path: 3.0.0
+ readable-stream: 3.6.2
+ dev: true
+
+ /compute-scroll-into-view@1.0.20:
+ resolution: {integrity: sha512-UCB0ioiyj8CRjtrvaceBLqqhZCVP+1B8+NWQhmdsm0VXOJtobBCf1dBQmebCCo34qZmUwZfIH2MZLqNHazrfjg==}
+ dev: true
+
+ /computeds@0.0.1:
+ resolution: {integrity: sha512-7CEBgcMjVmitjYo5q8JTJVra6X5mQ20uTThdK+0kR7UEaDrAWEQcRiBtWJzga4eRpP6afNwwLsX2SET2JhVB1Q==}
+ dev: true
+
+ /concat-map@0.0.1:
+ resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==}
+ dev: true
+
+ /config-chain@1.1.13:
+ resolution: {integrity: sha512-qj+f8APARXHrM0hraqXYb2/bOVSV4PvJQlNZ/DVj0QrmNM2q2euizkeuVckQ57J+W0mRH6Hvi+k50M4Jul2VRQ==}
+ requiresBuild: true
+ dependencies:
+ ini: 1.3.8
+ proto-list: 1.2.4
+ dev: true
+ optional: true
+
+ /config-file-ts@0.2.4:
+ resolution: {integrity: sha512-cKSW0BfrSaAUnxpgvpXPLaaW/umg4bqg4k3GO1JqlRfpx+d5W0GDXznCMkWotJQek5Mmz1MJVChQnz3IVaeMZQ==}
+ dependencies:
+ glob: 7.2.3
+ typescript: 4.9.5
+ dev: true
+
+ /consola@3.2.3:
+ resolution: {integrity: sha512-I5qxpzLv+sJhTVEoLYNcTW+bThDCPsit0vLNKShZx6rLtpilNpmmeTPaeqJb9ZE9dV3DGaeby6Vuhrw38WjeyQ==}
+ engines: {node: ^14.18.0 || >=16.10.0}
+ dev: true
+
+ /convert-source-map@2.0.0:
+ resolution: {integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==}
+ dev: true
+
+ /cookie@0.6.0:
+ resolution: {integrity: sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==}
+ engines: {node: '>= 0.6'}
+ dev: true
+
+ /copy-anything@2.0.6:
+ resolution: {integrity: sha512-1j20GZTsvKNkc4BY3NpMOM8tt///wY3FpIzozTOFO2ffuZcV61nojHXVKIy3WM+7ADCy5FVhdZYHYDdgTU0yJw==}
+ dependencies:
+ is-what: 3.14.1
+ dev: true
+
+ /core-js@3.33.3:
+ resolution: {integrity: sha512-lo0kOocUlLKmm6kv/FswQL8zbkH7mVsLJ/FULClOhv8WRVmKLVcs6XPNQAzstfeJTCHMyButEwG+z1kHxHoDZw==}
+ requiresBuild: true
+ dev: true
+
+ /core-util-is@1.0.2:
+ resolution: {integrity: sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ==}
+ requiresBuild: true
+ dev: true
+
+ /crc-32@1.2.2:
+ resolution: {integrity: sha512-ROmzCKrTnOwybPcJApAA6WBWij23HVfGVNKqqrZpuyZOHqK2CwHSvpGuyt/UNNvaIjEd8X5IFGp4Mh+Ie1IHJQ==}
+ engines: {node: '>=0.8'}
+ hasBin: true
+ dev: true
+
+ /crc32-stream@4.0.3:
+ resolution: {integrity: sha512-NT7w2JVU7DFroFdYkeq8cywxrgjPHWkdX1wjpRQXPX5Asews3tA+Ght6lddQO5Mkumffp3X7GEqku3epj2toIw==}
+ engines: {node: '>= 10'}
+ dependencies:
+ crc-32: 1.2.2
+ readable-stream: 3.6.2
+ dev: true
+
+ /crc@3.8.0:
+ resolution: {integrity: sha512-iX3mfgcTMIq3ZKLIsVFAbv7+Mc10kxabAGQb8HvjA1o3T1PIYprbakQ65d3I+2HGHt6nSKkM9PYjgoJO2KcFBQ==}
+ requiresBuild: true
+ dependencies:
+ buffer: 5.7.1
+ dev: true
+ optional: true
+
+ /cross-spawn@7.0.3:
+ resolution: {integrity: sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==}
+ engines: {node: '>= 8'}
+ dependencies:
+ path-key: 3.1.1
+ shebang-command: 2.0.0
+ which: 2.0.2
+ dev: true
+
+ /crypto-js@4.2.0:
+ resolution: {integrity: sha512-KALDyEYgpY+Rlob/iriUtjV6d5Eq+Y191A5g4UqLAi8CyGP9N1+FdVbkc1SxKc2r4YAYqG8JzO2KGL+AizD70Q==}
+ dev: true
+
+ /css-select@1.2.0:
+ resolution: {integrity: sha512-dUQOBoqdR7QwV90WysXPLXG5LO7nhYBgiWVfxF80DKPF8zx1t/pUd2FYy73emg3zrjtM6dzmYgbHKfV2rxiHQA==}
+ dependencies:
+ boolbase: 1.0.0
+ css-what: 2.1.3
+ domutils: 1.5.1
+ nth-check: 1.0.2
+ dev: true
+
+ /css-what@2.1.3:
+ resolution: {integrity: sha512-a+EPoD+uZiNfh+5fxw2nO9QwFa6nJe2Or35fGY6Ipw1R3R4AGz1d1TEZrCegvw2YTmZ0jXirGYlzxxpYSHwpEg==}
+ dev: true
+
+ /csstype@3.1.3:
+ resolution: {integrity: sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==}
+ dev: true
+
+ /dayjs@1.11.10:
+ resolution: {integrity: sha512-vjAczensTgRcqDERK0SR2XMwsF/tSvnvlv6VcF2GIhg6Sx4yOIt/irsr1RDJsKiIyBzJDpCoXiWWq28MqH2cnQ==}
+ dev: true
+
+ /de-indent@1.0.2:
+ resolution: {integrity: sha512-e/1zu3xH5MQryN2zdVaF0OrdNLUbvWxzMbi+iNA6Bky7l1RoP8a2fIbRocyHclXt/arDrrR6lL3TqFD9pMQTsg==}
+ dev: true
+
+ /debug@3.2.7:
+ resolution: {integrity: sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==}
+ requiresBuild: true
+ peerDependencies:
+ supports-color: '*'
+ peerDependenciesMeta:
+ supports-color:
+ optional: true
+ dependencies:
+ ms: 2.1.3
+ dev: true
+
+ /debug@4.3.4:
+ resolution: {integrity: sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==}
+ engines: {node: '>=6.0'}
+ peerDependencies:
+ supports-color: '*'
+ peerDependenciesMeta:
+ supports-color:
+ optional: true
+ dependencies:
+ ms: 2.1.2
+ dev: true
+
+ /decompress-response@3.3.0:
+ resolution: {integrity: sha512-BzRPQuY1ip+qDonAOz42gRm/pg9F768C+npV/4JOsxRC2sq+Rlk+Q4ZCAsOhnIaMrgarILY+RMUIvMmmX1qAEA==}
+ engines: {node: '>=4'}
+ dependencies:
+ mimic-response: 1.0.1
+ dev: true
+
+ /default-shell@2.2.0:
+ resolution: {integrity: sha512-sPpMZcVhRQ0nEMDtuMJ+RtCxt7iHPAMBU+I4tAlo5dU1sjRpNax0crj6nR3qKpvVnckaQ9U38enXcwW9nZJeCw==}
+ engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
+ dev: true
+
+ /defer-to-connect@1.1.3:
+ resolution: {integrity: sha512-0ISdNousHvZT2EiFlZeZAHBUvSxmKswVCEf8hW7KWgG4a8MVEu/3Vb6uWYozkjylyCxe0JBIiRB1jV45S70WVQ==}
+ dev: true
+
+ /define-data-property@1.1.2:
+ resolution: {integrity: sha512-SRtsSqsDbgpJBbW3pABMCOt6rQyeM8s8RiyeSN8jYG8sYmt/kGJejbydttUsnDs1tadr19tvhT4ShwMyoqAm4g==}
+ engines: {node: '>= 0.4'}
+ requiresBuild: true
+ dependencies:
+ es-errors: 1.3.0
+ get-intrinsic: 1.2.4
+ gopd: 1.0.1
+ has-property-descriptors: 1.0.1
+ dev: true
+ optional: true
+
+ /define-properties@1.2.1:
+ resolution: {integrity: sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==}
+ engines: {node: '>= 0.4'}
+ requiresBuild: true
+ dependencies:
+ define-data-property: 1.1.2
+ has-property-descriptors: 1.0.1
+ object-keys: 1.1.1
+ dev: true
+ optional: true
+
+ /delayed-stream@1.0.0:
+ resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==}
+ engines: {node: '>=0.4.0'}
+ dev: true
+
+ /detect-node@2.1.0:
+ resolution: {integrity: sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g==}
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /dexie@3.2.7:
+ resolution: {integrity: sha512-2a+BXvVhY5op+smDRLxeBAivE7YcYaneXJ1la3HOkUfX9zKkE/AJ8CNgjiXbtXepFyFmJNGSbmjOwqbT749r/w==}
+ engines: {node: '>=6.0'}
+ dev: true
+
+ /dir-compare@3.3.0:
+ resolution: {integrity: sha512-J7/et3WlGUCxjdnD3HAAzQ6nsnc0WL6DD7WcwJb7c39iH1+AWfg+9OqzJNaI6PkBwBvm1mhZNL9iY/nRiZXlPg==}
+ dependencies:
+ buffer-equal: 1.0.1
+ minimatch: 3.1.2
+ dev: true
+
+ /dmg-builder@24.13.3(electron-builder-squirrel-windows@24.13.3):
+ resolution: {integrity: sha512-rcJUkMfnJpfCboZoOOPf4L29TRtEieHNOeAbYPWPxlaBw/Z1RKrRA86dOI9rwaI4tQSc/RD82zTNHprfUHXsoQ==}
+ dependencies:
+ app-builder-lib: 24.13.3(dmg-builder@24.13.3)(electron-builder-squirrel-windows@24.13.3)
+ builder-util: 24.13.1
+ builder-util-runtime: 9.2.4
+ fs-extra: 10.1.0
+ iconv-lite: 0.6.3
+ js-yaml: 4.1.0
+ optionalDependencies:
+ dmg-license: 1.0.11
+ transitivePeerDependencies:
+ - electron-builder-squirrel-windows
+ - supports-color
+ dev: true
+
+ /dmg-license@1.0.11:
+ resolution: {integrity: sha512-ZdzmqwKmECOWJpqefloC5OJy1+WZBBse5+MR88z9g9Zn4VY+WYUkAyojmhzJckH5YbbZGcYIuGAkY5/Ys5OM2Q==}
+ engines: {node: '>=8'}
+ os: [darwin]
+ hasBin: true
+ requiresBuild: true
+ dependencies:
+ '@types/plist': 3.0.5
+ '@types/verror': 1.10.9
+ ajv: 6.12.6
+ crc: 3.8.0
+ iconv-corefoundation: 1.1.7
+ plist: 3.1.0
+ smart-buffer: 4.2.0
+ verror: 1.10.1
+ dev: true
+ optional: true
+
+ /dom-align@1.12.4:
+ resolution: {integrity: sha512-R8LUSEay/68zE5c8/3BDxiTEvgb4xZTF0RKmAHfiEVN3klfIpXfi2/QCoiWPccVQ0J/ZGdz9OjzL4uJEP/MRAw==}
+ dev: true
+
+ /dom-scroll-into-view@2.0.1:
+ resolution: {integrity: sha512-bvVTQe1lfaUr1oFzZX80ce9KLDlZ3iU+XGNE/bz9HnGdklTieqsbmsLHe+rT2XWqopvL0PckkYqN7ksmm5pe3w==}
+ dev: true
+
+ /dom-serializer@0.2.2:
+ resolution: {integrity: sha512-2/xPb3ORsQ42nHYiSunXkDjPLBaEj/xTwUO4B7XCZQTRk7EBtTOPaygh10YAAh2OI1Qrp6NWfpAhzswj0ydt9g==}
+ dependencies:
+ domelementtype: 2.3.0
+ entities: 2.2.0
+ dev: true
+
+ /dom-to-image@2.6.0:
+ resolution: {integrity: sha512-Dt0QdaHmLpjURjU7Tnu3AgYSF2LuOmksSGsUcE6ItvJoCWTBEmiMXcqBdNSAm9+QbbwD7JMoVsuuKX6ZVQv1qA==}
+ dev: true
+
+ /domelementtype@1.3.1:
+ resolution: {integrity: sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w==}
+ dev: true
+
+ /domelementtype@2.3.0:
+ resolution: {integrity: sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==}
+ dev: true
+
+ /domutils@1.5.1:
+ resolution: {integrity: sha512-gSu5Oi/I+3wDENBsOWBiRK1eoGxcywYSqg3rR960/+EfY0CF4EX1VPkgHOZ3WiS/Jg2DtliF6BhWcHlfpYUcGw==}
+ dependencies:
+ dom-serializer: 0.2.2
+ domelementtype: 1.3.1
+ dev: true
+
+ /dotenv-expand@5.1.0:
+ resolution: {integrity: sha512-YXQl1DSa4/PQyRfgrv6aoNjhasp/p4qs9FjJ4q4cQk+8m4r6k4ZSiEyytKG8f8W9gi8WsQtIObNmKd+tMzNTmA==}
+ dev: true
+
+ /dotenv@9.0.2:
+ resolution: {integrity: sha512-I9OvvrHp4pIARv4+x9iuewrWycX6CcZtoAu1XrzPxc5UygMJXJZYmBsynku8IkrJwgypE5DGNjDPmPRhDCptUg==}
+ engines: {node: '>=10'}
+ dev: true
+
+ /duplexer3@0.1.5:
+ resolution: {integrity: sha512-1A8za6ws41LQgv9HrE/66jyC5yuSjQ3L/KOpFtoBilsAK2iA2wuS5rTt1OCzIvtS2V7nVmedsUU+DGRcjBmOYA==}
+ dev: true
+
+ /ejs@3.1.9:
+ resolution: {integrity: sha512-rC+QVNMJWv+MtPgkt0y+0rVEIdbtxVADApW9JXrUVlzHetgcyczP/E7DJmWJ4fJCZF2cPcBk0laWO9ZHMG3DmQ==}
+ engines: {node: '>=0.10.0'}
+ hasBin: true
+ dependencies:
+ jake: 10.8.7
+ dev: true
+
+ /electron-builder-squirrel-windows@24.13.3(dmg-builder@24.13.3):
+ resolution: {integrity: sha512-oHkV0iogWfyK+ah9ZIvMDpei1m9ZRpdXcvde1wTpra2U8AFDNNpqJdnin5z+PM1GbQ5BoaKCWas2HSjtR0HwMg==}
+ dependencies:
+ app-builder-lib: 24.13.3(dmg-builder@24.13.3)(electron-builder-squirrel-windows@24.13.3)
+ archiver: 5.3.2
+ builder-util: 24.13.1
+ fs-extra: 10.1.0
+ transitivePeerDependencies:
+ - dmg-builder
+ - supports-color
+ dev: true
+
+ /electron-builder@24.13.3(electron-builder-squirrel-windows@24.13.3):
+ resolution: {integrity: sha512-yZSgVHft5dNVlo31qmJAe4BVKQfFdwpRw7sFp1iQglDRCDD6r22zfRJuZlhtB5gp9FHUxCMEoWGq10SkCnMAIg==}
+ engines: {node: '>=14.0.0'}
+ hasBin: true
+ dependencies:
+ app-builder-lib: 24.13.3(dmg-builder@24.13.3)(electron-builder-squirrel-windows@24.13.3)
+ builder-util: 24.13.1
+ builder-util-runtime: 9.2.4
+ chalk: 4.1.2
+ dmg-builder: 24.13.3(electron-builder-squirrel-windows@24.13.3)
+ fs-extra: 10.1.0
+ is-ci: 3.0.1
+ lazy-val: 1.0.5
+ read-config-file: 6.3.2
+ simple-update-notifier: 2.0.0
+ yargs: 17.7.2
+ transitivePeerDependencies:
+ - electron-builder-squirrel-windows
+ - supports-color
+ dev: true
+
+ /electron-is-dev@0.3.0:
+ resolution: {integrity: sha512-jLttuuq8QK67n3mXmIe9pkrO7IH3LGIk12xJkhTmc852U2sCJaRAOpRGPSh+1Xnzck5v9escd9YXzuze9nGejg==}
+ dev: true
+
+ /electron-is@3.0.0:
+ resolution: {integrity: sha512-aQv1y3WrDZ+mtO8acbhiiip/8fa0Et7cvZyvlqJm2H7fih4hiJWEFRyYxzLgDG2kmiLdF8l3y5tbek5JFOPQkQ==}
+ dependencies:
+ electron-is-dev: 0.3.0
+ semver: 5.7.2
+ dev: true
+
+ /electron-publish@24.13.1:
+ resolution: {integrity: sha512-2ZgdEqJ8e9D17Hwp5LEq5mLQPjqU3lv/IALvgp+4W8VeNhryfGhYEQC/PgDPMrnWUp+l60Ou5SJLsu+k4mhQ8A==}
+ dependencies:
+ '@types/fs-extra': 9.0.13
+ builder-util: 24.13.1
+ builder-util-runtime: 9.2.4
+ chalk: 4.1.2
+ fs-extra: 10.1.0
+ lazy-val: 1.0.5
+ mime: 2.6.0
+ transitivePeerDependencies:
+ - supports-color
+ dev: true
+
+ /electron-to-chromium@1.4.601:
+ resolution: {integrity: sha512-SpwUMDWe9tQu8JX5QCO1+p/hChAi9AE9UpoC3rcHVc+gdCGlbT3SGb5I1klgb952HRIyvt9wZhSz9bNBYz9swA==}
+ dev: true
+
+ /electron@21.4.4:
+ resolution: {integrity: sha512-N5O7y7Gtt7mDgkJLkW49ETiT8M3myZ9tNIEvGTKhpBduX4WdgMj6c3hYeYBD6XW7SvbRkWEQaTl25RNday8Xpw==}
+ engines: {node: '>= 10.17.0'}
+ hasBin: true
+ requiresBuild: true
+ dependencies:
+ '@electron/get': 1.14.1
+ '@types/node': 16.18.82
+ extract-zip: 2.0.1
+ transitivePeerDependencies:
+ - supports-color
+ dev: true
+
+ /elementtree@0.1.7:
+ resolution: {integrity: sha512-wkgGT6kugeQk/P6VZ/f4T+4HB41BVgNBq5CDIZVbQ02nvTVqAiVTbskxxu3eA/X96lMlfYOwnLQpN2v5E1zDEg==}
+ engines: {node: '>= 0.4.0'}
+ dependencies:
+ sax: 1.1.4
+ dev: true
+
+ /elliptic@6.5.4:
+ resolution: {integrity: sha512-iLhC6ULemrljPZb+QutR5TQGB+pdW6KGD5RSegS+8sorOZT+rdQFbsQFJgvN3eRqNALqJer4oQ16YvJHlU8hzQ==}
+ dependencies:
+ bn.js: 4.12.0
+ brorand: 1.1.0
+ hash.js: 1.1.7
+ hmac-drbg: 1.0.1
+ inherits: 2.0.4
+ minimalistic-assert: 1.0.1
+ minimalistic-crypto-utils: 1.0.1
+ dev: true
+
+ /emoji-regex@8.0.0:
+ resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==}
+ dev: true
+
+ /encodeurl@1.0.2:
+ resolution: {integrity: sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==}
+ engines: {node: '>= 0.8'}
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /end-of-stream@1.4.4:
+ resolution: {integrity: sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==}
+ dependencies:
+ once: 1.4.0
+ dev: true
+
+ /entities@2.2.0:
+ resolution: {integrity: sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==}
+ dev: true
+
+ /entities@4.5.0:
+ resolution: {integrity: sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==}
+ engines: {node: '>=0.12'}
+ dev: true
+
+ /env-paths@2.2.1:
+ resolution: {integrity: sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==}
+ engines: {node: '>=6'}
+ dev: true
+
+ /err-code@2.0.3:
+ resolution: {integrity: sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA==}
+ dev: true
+
+ /errno@0.1.8:
+ resolution: {integrity: sha512-dJ6oBr5SQ1VSd9qkk7ByRgb/1SH4JZjCHSW/mr63/QcXO9zLVxvJ6Oy13nio03rxpSnVDDjFor75SjVeZWPW/A==}
+ hasBin: true
+ requiresBuild: true
+ dependencies:
+ prr: 1.0.1
+ dev: true
+ optional: true
+
+ /es-errors@1.3.0:
+ resolution: {integrity: sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==}
+ engines: {node: '>= 0.4'}
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /es6-error@4.1.1:
+ resolution: {integrity: sha512-Um/+FxMr9CISWh0bi5Zv0iOD+4cFh5qLeks1qhAopKVAJw3drgKbKySikp7wGhDL0HPeaja0P5ULZrxLkniUVg==}
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /esbuild@0.20.2:
+ resolution: {integrity: sha512-WdOOppmUNU+IbZ0PaDiTst80zjnrOkyJNHoKupIcVyU8Lvla3Ugx94VzkQ32Ijqd7UhHJy75gNWDMUekcrSJ6g==}
+ engines: {node: '>=12'}
+ hasBin: true
+ requiresBuild: true
+ optionalDependencies:
+ '@esbuild/aix-ppc64': 0.20.2
+ '@esbuild/android-arm': 0.20.2
+ '@esbuild/android-arm64': 0.20.2
+ '@esbuild/android-x64': 0.20.2
+ '@esbuild/darwin-arm64': 0.20.2
+ '@esbuild/darwin-x64': 0.20.2
+ '@esbuild/freebsd-arm64': 0.20.2
+ '@esbuild/freebsd-x64': 0.20.2
+ '@esbuild/linux-arm': 0.20.2
+ '@esbuild/linux-arm64': 0.20.2
+ '@esbuild/linux-ia32': 0.20.2
+ '@esbuild/linux-loong64': 0.20.2
+ '@esbuild/linux-mips64el': 0.20.2
+ '@esbuild/linux-ppc64': 0.20.2
+ '@esbuild/linux-riscv64': 0.20.2
+ '@esbuild/linux-s390x': 0.20.2
+ '@esbuild/linux-x64': 0.20.2
+ '@esbuild/netbsd-x64': 0.20.2
+ '@esbuild/openbsd-x64': 0.20.2
+ '@esbuild/sunos-x64': 0.20.2
+ '@esbuild/win32-arm64': 0.20.2
+ '@esbuild/win32-ia32': 0.20.2
+ '@esbuild/win32-x64': 0.20.2
+ dev: true
+
+ /escalade@3.1.1:
+ resolution: {integrity: sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==}
+ engines: {node: '>=6'}
+ dev: true
+
+ /escape-string-regexp@1.0.5:
+ resolution: {integrity: sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==}
+ engines: {node: '>=0.8.0'}
+ dev: true
+
+ /escape-string-regexp@4.0.0:
+ resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==}
+ engines: {node: '>=10'}
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /estree-walker@2.0.2:
+ resolution: {integrity: sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==}
+ dev: true
+
+ /execa@5.1.1:
+ resolution: {integrity: sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==}
+ engines: {node: '>=10'}
+ dependencies:
+ cross-spawn: 7.0.3
+ get-stream: 6.0.1
+ human-signals: 2.1.0
+ is-stream: 2.0.1
+ merge-stream: 2.0.0
+ npm-run-path: 4.0.1
+ onetime: 5.1.2
+ signal-exit: 3.0.7
+ strip-final-newline: 2.0.0
+ dev: true
+
+ /extend@3.0.2:
+ resolution: {integrity: sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==}
+ dev: true
+
+ /extract-zip@2.0.1:
+ resolution: {integrity: sha512-GDhU9ntwuKyGXdZBUgTIe+vXnWj0fppUEtMDL0+idd5Sta8TGpHssn/eusA9mrPr9qNDym6SxAYZjNvCn/9RBg==}
+ engines: {node: '>= 10.17.0'}
+ hasBin: true
+ dependencies:
+ debug: 4.3.4
+ get-stream: 5.2.0
+ yauzl: 2.10.0
+ optionalDependencies:
+ '@types/yauzl': 2.10.3
+ transitivePeerDependencies:
+ - supports-color
+ dev: true
+
+ /extsprintf@1.4.1:
+ resolution: {integrity: sha512-Wrk35e8ydCKDj/ArClo1VrPVmN8zph5V4AtHwIuHhvMXsKf73UT3BOD+azBIW+3wOJ4FhEH7zyaJCFvChjYvMA==}
+ engines: {'0': node >=0.6.0}
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /fast-deep-equal@3.1.3:
+ resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==}
+ requiresBuild: true
+ dev: true
+
+ /fast-json-stable-stringify@2.1.0:
+ resolution: {integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==}
+ requiresBuild: true
+ dev: true
+
+ /fast-levenshtein@3.0.0:
+ resolution: {integrity: sha512-hKKNajm46uNmTlhHSyZkmToAc56uZJwYq7yrciZjqOxnlfQwERDQJmHPUp7m1m9wx8vgOe8IaCKZ5Kv2k1DdCQ==}
+ dependencies:
+ fastest-levenshtein: 1.0.16
+ dev: true
+
+ /fast-xml-parser@4.3.6:
+ resolution: {integrity: sha512-M2SovcRxD4+vC493Uc2GZVcZaj66CCJhWurC4viynVSTvrpErCShNcDz1lAho6n9REQKvL/ll4A4/fw6Y9z8nw==}
+ hasBin: true
+ dependencies:
+ strnum: 1.0.5
+ dev: true
+
+ /fastest-levenshtein@1.0.16:
+ resolution: {integrity: sha512-eRnCtTTtGZFpQCwhJiUOuxPQWRXVKYDn0b2PeHfXL6/Zi53SLAzAHfVhVWK2AryC/WH05kGfxhFIPvTF0SXQzg==}
+ engines: {node: '>= 4.9.1'}
+ dev: true
+
+ /fd-slicer@1.1.0:
+ resolution: {integrity: sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g==}
+ dependencies:
+ pend: 1.2.0
+ dev: true
+
+ /filelist@1.0.4:
+ resolution: {integrity: sha512-w1cEuf3S+DrLCQL7ET6kz+gmlJdbq9J7yXCSjK/OZCPA+qEN1WyF4ZAf0YYJa4/shHJra2t/d/r8SV4Ji+x+8Q==}
+ dependencies:
+ minimatch: 5.1.6
+ dev: true
+
+ /fix-path@4.0.0:
+ resolution: {integrity: sha512-g31GX207Tt+psI53ZSaB1egprYbEN0ZYl90aKcO22A2LmCNnFsSq3b5YpoKp3E/QEiWByTXGJOkFQG4S07Bc1A==}
+ engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
+ dependencies:
+ shell-path: 3.0.0
+ dev: true
+
+ /follow-redirects@1.15.6:
+ resolution: {integrity: sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA==}
+ engines: {node: '>=4.0'}
+ peerDependencies:
+ debug: '*'
+ peerDependenciesMeta:
+ debug:
+ optional: true
+ dev: true
+
+ /form-data@4.0.0:
+ resolution: {integrity: sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==}
+ engines: {node: '>= 6'}
+ dependencies:
+ asynckit: 0.4.0
+ combined-stream: 1.0.8
+ mime-types: 2.1.35
+ dev: true
+
+ /fs-constants@1.0.0:
+ resolution: {integrity: sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==}
+ dev: true
+
+ /fs-extra@10.1.0:
+ resolution: {integrity: sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==}
+ engines: {node: '>=12'}
+ dependencies:
+ graceful-fs: 4.2.11
+ jsonfile: 6.1.0
+ universalify: 2.0.1
+ dev: true
+
+ /fs-extra@8.1.0:
+ resolution: {integrity: sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==}
+ engines: {node: '>=6 <7 || >=8'}
+ dependencies:
+ graceful-fs: 4.2.11
+ jsonfile: 4.0.0
+ universalify: 0.1.2
+ dev: true
+
+ /fs-extra@9.1.0:
+ resolution: {integrity: sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==}
+ engines: {node: '>=10'}
+ dependencies:
+ at-least-node: 1.0.0
+ graceful-fs: 4.2.11
+ jsonfile: 6.1.0
+ universalify: 2.0.1
+ dev: true
+
+ /fs-minipass@2.1.0:
+ resolution: {integrity: sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==}
+ engines: {node: '>= 8'}
+ dependencies:
+ minipass: 3.3.6
+ dev: true
+
+ /fs.realpath@1.0.0:
+ resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==}
+ dev: true
+
+ /fsevents@2.3.3:
+ resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==}
+ engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0}
+ os: [darwin]
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /function-bind@1.1.2:
+ resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==}
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /fuzzysort@2.0.4:
+ resolution: {integrity: sha512-Api1mJL+Ad7W7vnDZnWq5pGaXJjyencT+iKGia2PlHUcSsSzWwIQ3S1isiMpwpavjYtGd2FzhUIhnnhOULZgDw==}
+ dev: true
+
+ /gensync@1.0.0-beta.2:
+ resolution: {integrity: sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==}
+ engines: {node: '>=6.9.0'}
+ dev: true
+
+ /get-caller-file@2.0.5:
+ resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==}
+ engines: {node: 6.* || 8.* || >= 10.*}
+ dev: true
+
+ /get-intrinsic@1.2.4:
+ resolution: {integrity: sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==}
+ engines: {node: '>= 0.4'}
+ requiresBuild: true
+ dependencies:
+ es-errors: 1.3.0
+ function-bind: 1.1.2
+ has-proto: 1.0.1
+ has-symbols: 1.0.3
+ hasown: 2.0.0
+ dev: true
+ optional: true
+
+ /get-stream@4.1.0:
+ resolution: {integrity: sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==}
+ engines: {node: '>=6'}
+ dependencies:
+ pump: 3.0.0
+ dev: true
+
+ /get-stream@5.2.0:
+ resolution: {integrity: sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==}
+ engines: {node: '>=8'}
+ dependencies:
+ pump: 3.0.0
+ dev: true
+
+ /get-stream@6.0.1:
+ resolution: {integrity: sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==}
+ engines: {node: '>=10'}
+ dev: true
+
+ /glob@7.2.3:
+ resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==}
+ dependencies:
+ fs.realpath: 1.0.0
+ inflight: 1.0.6
+ inherits: 2.0.4
+ minimatch: 3.1.2
+ once: 1.4.0
+ path-is-absolute: 1.0.1
+ dev: true
+
+ /global-agent@3.0.0:
+ resolution: {integrity: sha512-PT6XReJ+D07JvGoxQMkT6qji/jVNfX/h364XHZOWeRzy64sSFr+xJ5OX7LI3b4MPQzdL4H8Y8M0xzPpsVMwA8Q==}
+ engines: {node: '>=10.0'}
+ requiresBuild: true
+ dependencies:
+ boolean: 3.2.0
+ es6-error: 4.1.1
+ matcher: 3.0.0
+ roarr: 2.15.4
+ semver: 7.6.0
+ serialize-error: 7.0.1
+ dev: true
+ optional: true
+
+ /global-tunnel-ng@2.7.1:
+ resolution: {integrity: sha512-4s+DyciWBV0eK148wqXxcmVAbFVPqtc3sEtUE/GTQfuU80rySLcMhUmHKSHI7/LDj8q0gDYI1lIhRRB7ieRAqg==}
+ engines: {node: '>=0.10'}
+ requiresBuild: true
+ dependencies:
+ encodeurl: 1.0.2
+ lodash: 4.17.21
+ npm-conf: 1.1.3
+ tunnel: 0.0.6
+ dev: true
+ optional: true
+
+ /globals@11.12.0:
+ resolution: {integrity: sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==}
+ engines: {node: '>=4'}
+ dev: true
+
+ /globalthis@1.0.3:
+ resolution: {integrity: sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA==}
+ engines: {node: '>= 0.4'}
+ requiresBuild: true
+ dependencies:
+ define-properties: 1.2.1
+ dev: true
+ optional: true
+
+ /gopd@1.0.1:
+ resolution: {integrity: sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==}
+ requiresBuild: true
+ dependencies:
+ get-intrinsic: 1.2.4
+ dev: true
+ optional: true
+
+ /got@9.6.0:
+ resolution: {integrity: sha512-R7eWptXuGYxwijs0eV+v3o6+XH1IqVK8dJOEecQfTmkncw9AV4dcw/Dhxi8MdlqPthxxpZyizMzyg8RTmEsG+Q==}
+ engines: {node: '>=8.6'}
+ dependencies:
+ '@sindresorhus/is': 0.14.0
+ '@szmarczak/http-timer': 1.1.2
+ '@types/keyv': 3.1.4
+ '@types/responselike': 1.0.3
+ cacheable-request: 6.1.0
+ decompress-response: 3.3.0
+ duplexer3: 0.1.5
+ get-stream: 4.1.0
+ lowercase-keys: 1.0.1
+ mimic-response: 1.0.1
+ p-cancelable: 1.1.0
+ to-readable-stream: 1.0.0
+ url-parse-lax: 3.0.0
+ dev: true
+
+ /graceful-fs@4.2.11:
+ resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==}
+ dev: true
+
+ /has-flag@3.0.0:
+ resolution: {integrity: sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==}
+ engines: {node: '>=4'}
+ dev: true
+
+ /has-flag@4.0.0:
+ resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==}
+ engines: {node: '>=8'}
+ dev: true
+
+ /has-property-descriptors@1.0.1:
+ resolution: {integrity: sha512-VsX8eaIewvas0xnvinAe9bw4WfIeODpGYikiWYLH+dma0Jw6KHYqWiWfhQlgOVK8D6PvjubK5Uc4P0iIhIcNVg==}
+ requiresBuild: true
+ dependencies:
+ get-intrinsic: 1.2.4
+ dev: true
+ optional: true
+
+ /has-proto@1.0.1:
+ resolution: {integrity: sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==}
+ engines: {node: '>= 0.4'}
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /has-symbols@1.0.3:
+ resolution: {integrity: sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==}
+ engines: {node: '>= 0.4'}
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /hash.js@1.1.7:
+ resolution: {integrity: sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==}
+ dependencies:
+ inherits: 2.0.4
+ minimalistic-assert: 1.0.1
+ dev: true
+
+ /hasown@2.0.0:
+ resolution: {integrity: sha512-vUptKVTpIJhcczKBbgnS+RtcuYMB8+oNzPK2/Hp3hanz8JmpATdmmgLgSaadVREkDm+e2giHwY3ZRkyjSIDDFA==}
+ engines: {node: '>= 0.4'}
+ requiresBuild: true
+ dependencies:
+ function-bind: 1.1.2
+ dev: true
+ optional: true
+
+ /he@1.2.0:
+ resolution: {integrity: sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==}
+ hasBin: true
+ dev: true
+
+ /hls.js@1.5.7:
+ resolution: {integrity: sha512-Hnyf7ojTBtXHeOW1/t6wCBJSiK1WpoKF9yg7juxldDx8u3iswrkPt2wbOA/1NiwU4j27DSIVoIEJRAhcdMef/A==}
+ dev: true
+
+ /hmac-drbg@1.0.1:
+ resolution: {integrity: sha512-Tti3gMqLdZfhOQY1Mzf/AanLiqh1WTiJgEj26ZuYQ9fbkLomzGchCws4FyrSd4VkpBfiNhaE1On+lOz894jvXg==}
+ dependencies:
+ hash.js: 1.1.7
+ minimalistic-assert: 1.0.1
+ minimalistic-crypto-utils: 1.0.1
+ dev: true
+
+ /hosted-git-info@4.1.0:
+ resolution: {integrity: sha512-kyCuEOWjJqZuDbRHzL8V93NzQhwIB71oFWSyzVo+KPZI+pnQPPxucdkrOZvkLRnrf5URsQM+IJ09Dw29cRALIA==}
+ engines: {node: '>=10'}
+ dependencies:
+ lru-cache: 6.0.0
+ dev: true
+
+ /howler@2.2.4:
+ resolution: {integrity: sha512-iARIBPgcQrwtEr+tALF+rapJ8qSc+Set2GJQl7xT1MQzWaVkFebdJhR3alVlSiUf5U7nAANKuj3aWpwerocD5w==}
+ dev: true
+
+ /html-tags@3.3.1:
+ resolution: {integrity: sha512-ztqyC3kLto0e9WbNp0aeP+M3kTt+nbaIveGmUxAtZa+8iFgKLUOD4YKM5j+f3QD89bra7UeumolZHKuOXnTmeQ==}
+ engines: {node: '>=8'}
+ dev: true
+
+ /http-cache-semantics@4.1.1:
+ resolution: {integrity: sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ==}
+ dev: true
+
+ /http-proxy-agent@5.0.0:
+ resolution: {integrity: sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w==}
+ engines: {node: '>= 6'}
+ dependencies:
+ '@tootallnate/once': 2.0.0
+ agent-base: 6.0.2
+ debug: 4.3.4
+ transitivePeerDependencies:
+ - supports-color
+ dev: true
+
+ /https-proxy-agent@5.0.1:
+ resolution: {integrity: sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==}
+ engines: {node: '>= 6'}
+ dependencies:
+ agent-base: 6.0.2
+ debug: 4.3.4
+ transitivePeerDependencies:
+ - supports-color
+ dev: true
+
+ /human-signals@2.1.0:
+ resolution: {integrity: sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==}
+ engines: {node: '>=10.17.0'}
+ dev: true
+
+ /iconv-corefoundation@1.1.7:
+ resolution: {integrity: sha512-T10qvkw0zz4wnm560lOEg0PovVqUXuOFhhHAkixw8/sycy7TJt7v/RrkEKEQnAw2viPSJu6iAkErxnzR0g8PpQ==}
+ engines: {node: ^8.11.2 || >=10}
+ os: [darwin]
+ requiresBuild: true
+ dependencies:
+ cli-truncate: 2.1.0
+ node-addon-api: 1.7.2
+ dev: true
+ optional: true
+
+ /iconv-lite@0.6.3:
+ resolution: {integrity: sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==}
+ engines: {node: '>=0.10.0'}
+ dependencies:
+ safer-buffer: 2.1.2
+ dev: true
+
+ /ieee754@1.2.1:
+ resolution: {integrity: sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==}
+ requiresBuild: true
+ dev: true
+
+ /image-size@0.5.5:
+ resolution: {integrity: sha512-6TDAlDPZxUFCv+fuOkIoXT/V/f3Qbq8e37p+YOiYrUv3v9cc3/6x78VdfPgFVaB9dZYeLUfKgHRebpkm/oP2VQ==}
+ engines: {node: '>=0.10.0'}
+ hasBin: true
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /inflight@1.0.6:
+ resolution: {integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==}
+ dependencies:
+ once: 1.4.0
+ wrappy: 1.0.2
+ dev: true
+
+ /inherits@2.0.4:
+ resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==}
+ dev: true
+
+ /ini@1.3.8:
+ resolution: {integrity: sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==}
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /ip@1.1.9:
+ resolution: {integrity: sha512-cyRxvOEpNHNtchU3Ln9KC/auJgup87llfQpQ+t5ghoC/UhL16SWzbueiCsdTnWmqAWl7LadfuwhlqmtOaqMHdQ==}
+ dev: true
+
+ /ip@2.0.1:
+ resolution: {integrity: sha512-lJUL9imLTNi1ZfXT+DU6rBBdbiKGBuay9B6xGSPVjUeQwaH1RIGqef8RZkUtHioLmSNpPR5M4HVKJGm1j8FWVQ==}
+ dev: true
+
+ /is-arrayish@0.3.2:
+ resolution: {integrity: sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==}
+ dev: true
+
+ /is-ci@3.0.1:
+ resolution: {integrity: sha512-ZYvCgrefwqoQ6yTyYUbQu64HsITZ3NfKX1lzaEYdkTDcfKzzCI/wthRRYKkdjHKFVgNiXKAKm65Zo1pk2as/QQ==}
+ hasBin: true
+ dependencies:
+ ci-info: 3.9.0
+ dev: true
+
+ /is-fullwidth-code-point@3.0.0:
+ resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==}
+ engines: {node: '>=8'}
+ dev: true
+
+ /is-plain-object@3.0.1:
+ resolution: {integrity: sha512-Xnpx182SBMrr/aBik8y+GuR4U1L9FqMSojwDQwPMmxyC6bvEqly9UBCxhauBF5vNh2gwWJNX6oDV7O+OM4z34g==}
+ engines: {node: '>=0.10.0'}
+ dev: true
+
+ /is-stream@2.0.1:
+ resolution: {integrity: sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==}
+ engines: {node: '>=8'}
+ dev: true
+
+ /is-what@3.14.1:
+ resolution: {integrity: sha512-sNxgpk9793nzSs7bA6JQJGeIuRBQhAaNGG77kzYQgMkrID+lS6SlK07K5LaptscDlSaIgH+GPFzf+d75FVxozA==}
+ dev: true
+
+ /isarray@1.0.0:
+ resolution: {integrity: sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==}
+ dev: true
+
+ /isbinaryfile@4.0.10:
+ resolution: {integrity: sha512-iHrqe5shvBUcFbmZq9zOQHBoeOhZJu6RQGrDpBgenUm/Am+F3JM2MgQj+rK3Z601fzrL5gLZWtAPH2OBaSVcyw==}
+ engines: {node: '>= 8.0.0'}
+ dev: true
+
+ /isbinaryfile@5.0.0:
+ resolution: {integrity: sha512-UDdnyGvMajJUWCkib7Cei/dvyJrrvo4FIrsvSFWdPpXSUorzXrDJ0S+X5Q4ZlasfPjca4yqCNNsjbCeiy8FFeg==}
+ engines: {node: '>= 14.0.0'}
+ dev: true
+
+ /isexe@2.0.0:
+ resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==}
+ dev: true
+
+ /isomorphic-fetch@3.0.0:
+ resolution: {integrity: sha512-qvUtwJ3j6qwsF3jLxkZ72qCgjMysPzDfeV240JHiGZsANBYd+EEuu35v7dfrJ9Up0Ak07D7GGSkGhCHTqg/5wA==}
+ dependencies:
+ node-fetch: 2.7.0
+ whatwg-fetch: 3.6.19
+ transitivePeerDependencies:
+ - encoding
+ dev: true
+
+ /jake@10.8.7:
+ resolution: {integrity: sha512-ZDi3aP+fG/LchyBzUM804VjddnwfSfsdeYkwt8NcbKRvo4rFkjhs456iLFn3k2ZUWvNe4i48WACDbza8fhq2+w==}
+ engines: {node: '>=10'}
+ hasBin: true
+ dependencies:
+ async: 3.2.5
+ chalk: 4.1.2
+ filelist: 1.0.4
+ minimatch: 3.1.2
+ dev: true
+
+ /jassub@1.7.15:
+ resolution: {integrity: sha512-8yKAJc++Y1gNfATOPRo3APk0JUhshKl5l7bRkT6WkJ8XP4RvYfVPb6ieH6WDxsMq523exwGzNvjjPEEWT+Z1nQ==}
+ dependencies:
+ rvfc-polyfill: 1.0.7
+ dev: true
+
+ /js-md5@0.7.3:
+ resolution: {integrity: sha512-ZC41vPSTLKGwIRjqDh8DfXoCrdQIyBgspJVPXHBGu4nZlAEvG3nf+jO9avM9RmLiGakg7vz974ms99nEV0tmTQ==}
+ dev: true
+
+ /js-sha1@0.6.0:
+ resolution: {integrity: sha512-01gwBFreYydzmU9BmZxpVk6svJJHrVxEN3IOiGl6VO93bVKYETJ0sIth6DASI6mIFdt7NmfX9UiByRzsYHGU9w==}
+ dev: true
+
+ /js-tokens@4.0.0:
+ resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==}
+ dev: true
+
+ /js-yaml@4.1.0:
+ resolution: {integrity: sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==}
+ hasBin: true
+ dependencies:
+ argparse: 2.0.1
+ dev: true
+
+ /jschardet@3.0.0:
+ resolution: {integrity: sha512-lJH6tJ77V8Nzd5QWRkFYCLc13a3vADkh3r/Fi8HupZGWk2OVVDfnZP8V/VgQgZ+lzW0kG2UGb5hFgt3V3ndotQ==}
+ engines: {node: '>=0.1.90'}
+ dev: true
+
+ /jsesc@2.5.2:
+ resolution: {integrity: sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==}
+ engines: {node: '>=4'}
+ hasBin: true
+ dev: true
+
+ /json-buffer@3.0.0:
+ resolution: {integrity: sha512-CuUqjv0FUZIdXkHPI8MezCnFCdaTAacej1TZYulLoAg1h/PhwkdXFN4V/gzY4g+fMBCOV2xF+rp7t2XD2ns/NQ==}
+ dev: true
+
+ /json-schema-traverse@0.4.1:
+ resolution: {integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==}
+ requiresBuild: true
+ dev: true
+
+ /json-stringify-safe@5.0.1:
+ resolution: {integrity: sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==}
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /json5@2.2.3:
+ resolution: {integrity: sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==}
+ engines: {node: '>=6'}
+ hasBin: true
+ dev: true
+
+ /jsonfile@4.0.0:
+ resolution: {integrity: sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==}
+ optionalDependencies:
+ graceful-fs: 4.2.11
+ dev: true
+
+ /jsonfile@6.1.0:
+ resolution: {integrity: sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==}
+ dependencies:
+ universalify: 2.0.1
+ optionalDependencies:
+ graceful-fs: 4.2.11
+ dev: true
+
+ /keyv@3.1.0:
+ resolution: {integrity: sha512-9ykJ/46SN/9KPM/sichzQ7OvXyGDYKGTaDlKMGCAlg2UK8KRy4jb0d8sFc+0Tt0YYnThq8X2RZgCg74RPxgcVA==}
+ dependencies:
+ json-buffer: 3.0.0
+ dev: true
+
+ /kind-of@6.0.3:
+ resolution: {integrity: sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==}
+ engines: {node: '>=0.10.0'}
+ dev: true
+
+ /lazy-val@1.0.5:
+ resolution: {integrity: sha512-0/BnGCCfyUMkBpeDgWihanIAF9JmZhHBgUhEqzvf+adhNGLoP6TaiI5oF8oyb3I45P+PcnrqihSf01M0l0G5+Q==}
+ dev: true
+
+ /lazystream@1.0.1:
+ resolution: {integrity: sha512-b94GiNHQNy6JNTrt5w6zNyffMrNkXZb3KTkCZJb2V1xaEGCk093vkZ2jk3tpaeP33/OiXC+WvK9AxUebnf5nbw==}
+ engines: {node: '>= 0.6.3'}
+ dependencies:
+ readable-stream: 2.3.8
+ dev: true
+
+ /less@4.2.0:
+ resolution: {integrity: sha512-P3b3HJDBtSzsXUl0im2L7gTO5Ubg8mEN6G8qoTS77iXxXX4Hvu4Qj540PZDvQ8V6DmX6iXo98k7Md0Cm1PrLaA==}
+ engines: {node: '>=6'}
+ hasBin: true
+ dependencies:
+ copy-anything: 2.0.6
+ parse-node-version: 1.0.1
+ tslib: 2.6.2
+ optionalDependencies:
+ errno: 0.1.8
+ graceful-fs: 4.2.11
+ image-size: 0.5.5
+ make-dir: 2.1.0
+ mime: 1.6.0
+ needle: 3.2.0
+ source-map: 0.6.1
+ transitivePeerDependencies:
+ - supports-color
+ dev: true
+
+ /linkify-it@5.0.0:
+ resolution: {integrity: sha512-5aHCbzQRADcdP+ATqnDuhhJ/MRIqDkZX5pyjFHRRysS8vZ5AbqGEoFIb6pYHPZ+L/OC2Lc+xT8uHVVR5CAK/wQ==}
+ dependencies:
+ uc.micro: 2.1.0
+ dev: true
+
+ /lodash-es@4.17.21:
+ resolution: {integrity: sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==}
+ dev: true
+
+ /lodash.defaults@4.2.0:
+ resolution: {integrity: sha512-qjxPLHd3r5DnsdGacqOMU6pb/avJzdh9tFX2ymgoZE27BmjXrNy/y4LoaiTeAb+O3gL8AfpJGtqfX/ae2leYYQ==}
+ dev: true
+
+ /lodash.difference@4.5.0:
+ resolution: {integrity: sha512-dS2j+W26TQ7taQBGN8Lbbq04ssV3emRw4NY58WErlTO29pIqS0HmoT5aJ9+TUQ1N3G+JOZSji4eugsWwGp9yPA==}
+ dev: true
+
+ /lodash.flatten@4.4.0:
+ resolution: {integrity: sha512-C5N2Z3DgnnKr0LOpv/hKCgKdb7ZZwafIrsesve6lmzvZIRZRGaZ/l6Q8+2W7NaT+ZwO3fFlSCzCzrDCFdJfZ4g==}
+ dev: true
+
+ /lodash.isplainobject@4.0.6:
+ resolution: {integrity: sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==}
+ dev: true
+
+ /lodash.union@4.6.0:
+ resolution: {integrity: sha512-c4pB2CdGrGdjMKYLA+XiRDO7Y0PRQbm/Gzg8qMj+QH+pFVAoTp5sBpO0odL3FjoPCGjK96p6qsP+yQoiLoOBcw==}
+ dev: true
+
+ /lodash@3.10.1:
+ resolution: {integrity: sha512-9mDDwqVIma6OZX79ZlDACZl8sBm0TEnkf99zV3iMA4GzkIT/9hiqP5mY0HoT1iNLCrKc/R1HByV+yJfRWVJryQ==}
+ dev: true
+
+ /lodash@4.17.21:
+ resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==}
+ dev: true
+
+ /loose-envify@1.4.0:
+ resolution: {integrity: sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==}
+ hasBin: true
+ dependencies:
+ js-tokens: 4.0.0
+ dev: true
+
+ /lowercase-keys@1.0.1:
+ resolution: {integrity: sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA==}
+ engines: {node: '>=0.10.0'}
+ dev: true
+
+ /lowercase-keys@2.0.0:
+ resolution: {integrity: sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==}
+ engines: {node: '>=8'}
+ dev: true
+
+ /lru-cache@5.1.1:
+ resolution: {integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==}
+ dependencies:
+ yallist: 3.1.1
+ dev: true
+
+ /lru-cache@6.0.0:
+ resolution: {integrity: sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==}
+ engines: {node: '>=10'}
+ dependencies:
+ yallist: 4.0.0
+ dev: true
+
+ /magic-string@0.30.7:
+ resolution: {integrity: sha512-8vBuFF/I/+OSLRmdf2wwFCJCz+nSn0m6DPvGH1fS/KiQoSaR+sETbov0eIk9KhEKy8CYqIkIAnbohxT/4H0kuA==}
+ engines: {node: '>=12'}
+ dependencies:
+ '@jridgewell/sourcemap-codec': 1.4.15
+ dev: true
+
+ /make-dir@2.1.0:
+ resolution: {integrity: sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==}
+ engines: {node: '>=6'}
+ requiresBuild: true
+ dependencies:
+ pify: 4.0.1
+ semver: 5.7.2
+ dev: true
+ optional: true
+
+ /markdown-it@14.1.0:
+ resolution: {integrity: sha512-a54IwgWPaeBCAAsv13YgmALOF1elABB08FxO9i+r4VFk5Vl4pKokRPeX8u5TCgSsPi6ec1otfLjdOpVcgbpshg==}
+ hasBin: true
+ dependencies:
+ argparse: 2.0.1
+ entities: 4.5.0
+ linkify-it: 5.0.0
+ mdurl: 2.0.0
+ punycode.js: 2.3.1
+ uc.micro: 2.1.0
+ dev: true
+
+ /matcher@3.0.0:
+ resolution: {integrity: sha512-OkeDaAZ/bQCxeFAozM55PKcKU0yJMPGifLwV4Qgjitu+5MoAfSQN4lsLJeXZ1b8w0x+/Emda6MZgXS1jvsapng==}
+ engines: {node: '>=10'}
+ requiresBuild: true
+ dependencies:
+ escape-string-regexp: 4.0.0
+ dev: true
+ optional: true
+
+ /mdurl@2.0.0:
+ resolution: {integrity: sha512-Lf+9+2r+Tdp5wXDXC4PcIBjTDtq4UKjCPMQhKIuzpJNW0b96kVqSwW0bT7FhRSfmAiFYgP+SCRvdrDozfh0U5w==}
+ dev: true
+
+ /merge-stream@2.0.0:
+ resolution: {integrity: sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==}
+ dev: true
+
+ /mime-db@1.52.0:
+ resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==}
+ engines: {node: '>= 0.6'}
+ dev: true
+
+ /mime-types@2.1.35:
+ resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==}
+ engines: {node: '>= 0.6'}
+ dependencies:
+ mime-db: 1.52.0
+ dev: true
+
+ /mime@1.6.0:
+ resolution: {integrity: sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==}
+ engines: {node: '>=4'}
+ hasBin: true
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /mime@2.6.0:
+ resolution: {integrity: sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg==}
+ engines: {node: '>=4.0.0'}
+ hasBin: true
+ dev: true
+
+ /mimic-fn@2.1.0:
+ resolution: {integrity: sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==}
+ engines: {node: '>=6'}
+ dev: true
+
+ /mimic-response@1.0.1:
+ resolution: {integrity: sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==}
+ engines: {node: '>=4'}
+ dev: true
+
+ /minimalistic-assert@1.0.1:
+ resolution: {integrity: sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==}
+ dev: true
+
+ /minimalistic-crypto-utils@1.0.1:
+ resolution: {integrity: sha512-JIYlbt6g8i5jKfJ3xz7rF0LXmv2TkDxBLUkiBeZ7bAx4GnnNMr8xFpGnOxn6GhTEHx3SjRrZEoU+j04prX1ktg==}
+ dev: true
+
+ /minimatch@3.1.2:
+ resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==}
+ dependencies:
+ brace-expansion: 1.1.11
+ dev: true
+
+ /minimatch@5.1.6:
+ resolution: {integrity: sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==}
+ engines: {node: '>=10'}
+ dependencies:
+ brace-expansion: 2.0.1
+ dev: true
+
+ /minimatch@9.0.3:
+ resolution: {integrity: sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==}
+ engines: {node: '>=16 || 14 >=14.17'}
+ dependencies:
+ brace-expansion: 2.0.1
+ dev: true
+
+ /minimist@1.2.8:
+ resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==}
+ dev: true
+
+ /minipass@3.3.6:
+ resolution: {integrity: sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==}
+ engines: {node: '>=8'}
+ dependencies:
+ yallist: 4.0.0
+ dev: true
+
+ /minipass@5.0.0:
+ resolution: {integrity: sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==}
+ engines: {node: '>=8'}
+ dev: true
+
+ /minizlib@2.1.2:
+ resolution: {integrity: sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==}
+ engines: {node: '>= 8'}
+ dependencies:
+ minipass: 3.3.6
+ yallist: 4.0.0
+ dev: true
+
+ /mkdirp@1.0.4:
+ resolution: {integrity: sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==}
+ engines: {node: '>=10'}
+ hasBin: true
+ dev: true
+
+ /ms@2.1.2:
+ resolution: {integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==}
+ dev: true
+
+ /ms@2.1.3:
+ resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==}
+ requiresBuild: true
+ dev: true
+
+ /muggle-string@0.4.1:
+ resolution: {integrity: sha512-VNTrAak/KhO2i8dqqnqnAHOa3cYBwXEZe9h+D5h/1ZqFSTEFHdM65lR7RoIqq3tBBYavsOXV84NoHXZ0AkPyqQ==}
+ dev: true
+
+ /nanoid@3.3.7:
+ resolution: {integrity: sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==}
+ engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1}
+ hasBin: true
+ dev: true
+
+ /nanopop@2.3.0:
+ resolution: {integrity: sha512-fzN+T2K7/Ah25XU02MJkPZ5q4Tj5FpjmIYq4rvoHX4yb16HzFdCO6JxFFn5Y/oBhQ8no8fUZavnyIv9/+xkBBw==}
+ dev: true
+
+ /needle@3.2.0:
+ resolution: {integrity: sha512-oUvzXnyLiVyVGoianLijF9O/RecZUf7TkBfimjGrLM4eQhXyeJwM6GeAWccwfQ9aa4gMCZKqhAOuLaMIcQxajQ==}
+ engines: {node: '>= 4.4.x'}
+ hasBin: true
+ requiresBuild: true
+ dependencies:
+ debug: 3.2.7
+ iconv-lite: 0.6.3
+ sax: 1.3.0
+ transitivePeerDependencies:
+ - supports-color
+ dev: true
+ optional: true
+
+ /node-addon-api@1.7.2:
+ resolution: {integrity: sha512-ibPK3iA+vaY1eEjESkQkM0BbCqFOaZMiXRTtdB0u7b4djtY6JnsjvPdUHVMg6xQt3B8fpTTWHI9A+ADjM9frzg==}
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /node-addon-api@5.1.0:
+ resolution: {integrity: sha512-eh0GgfEkpnoWDq+VY8OyvYhFEzBk6jIYbRKdIlyTiAXIVJ8PyBaKb0rp7oDtoddbdoHWhq8wwr+XZ81F1rpNdA==}
+ dev: true
+
+ /node-fetch@2.7.0:
+ resolution: {integrity: sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==}
+ engines: {node: 4.x || >=6.0.0}
+ peerDependencies:
+ encoding: ^0.1.0
+ peerDependenciesMeta:
+ encoding:
+ optional: true
+ dependencies:
+ whatwg-url: 5.0.0
+ dev: true
+
+ /node-gyp-build@4.7.1:
+ resolution: {integrity: sha512-wTSrZ+8lsRRa3I3H8Xr65dLWSgCvY2l4AOnaeKdPA9TB/WYMPaTcrzf3rXvFoVvjKNVnu0CcWSx54qq9GKRUYg==}
+ hasBin: true
+ dev: true
+
+ /node-releases@2.0.14:
+ resolution: {integrity: sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==}
+ dev: true
+
+ /node-ssdp@4.0.1:
+ resolution: {integrity: sha512-uJXkLZVuyaMg1qNbMbGQ6YzNzyOD+NLxYyxIJocPTKTVECPDokOiCZA686jTLXHMUnV34uY/lcUSJ+/5fhY43A==}
+ engines: {node: '>=0.10.0'}
+ dependencies:
+ async: 2.6.4
+ bluebird: 3.7.2
+ debug: 3.2.7
+ extend: 3.0.2
+ ip: 1.1.9
+ transitivePeerDependencies:
+ - supports-color
+ dev: true
+
+ /normalize-path@3.0.0:
+ resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==}
+ engines: {node: '>=0.10.0'}
+ dev: true
+
+ /normalize-url@4.5.1:
+ resolution: {integrity: sha512-9UZCFRHQdNrfTpGg8+1INIg93B6zE0aXMVFkw1WFwvO4SlZywU6aLg5Of0Ap/PgcbSw4LNxvMWXMeugwMCX0AA==}
+ engines: {node: '>=8'}
+ dev: true
+
+ /npm-conf@1.1.3:
+ resolution: {integrity: sha512-Yic4bZHJOt9RCFbRP3GgpqhScOY4HH3V2P8yBj6CeYq118Qr+BLXqT2JvpJ00mryLESpgOxf5XlFv4ZjXxLScw==}
+ engines: {node: '>=4'}
+ requiresBuild: true
+ dependencies:
+ config-chain: 1.1.13
+ pify: 3.0.0
+ dev: true
+ optional: true
+
+ /npm-run-path@4.0.1:
+ resolution: {integrity: sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==}
+ engines: {node: '>=8'}
+ dependencies:
+ path-key: 3.1.1
+ dev: true
+
+ /nth-check@1.0.2:
+ resolution: {integrity: sha512-WeBOdju8SnzPN5vTUJYxYUxLeXpCaVP5i5e0LF8fg7WORF2Wd7wFX/pk0tYZk7s8T+J7VLy0Da6J1+wCT0AtHg==}
+ dependencies:
+ boolbase: 1.0.0
+ dev: true
+
+ /number-precision@1.6.0:
+ resolution: {integrity: sha512-05OLPgbgmnixJw+VvEh18yNPUo3iyp4BEWJcrLu4X9W05KmMifN7Mu5exYvQXqxxeNWhvIF+j3Rij+HmddM/hQ==}
+ dev: true
+
+ /object-keys@1.1.1:
+ resolution: {integrity: sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==}
+ engines: {node: '>= 0.4'}
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /once@1.4.0:
+ resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==}
+ dependencies:
+ wrappy: 1.0.2
+ dev: true
+
+ /onetime@5.1.2:
+ resolution: {integrity: sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==}
+ engines: {node: '>=6'}
+ dependencies:
+ mimic-fn: 2.1.0
+ dev: true
+
+ /option-validator@2.0.6:
+ resolution: {integrity: sha512-tmZDan2LRIRQyhUGvkff68/O0R8UmF+Btmiiz0SmSw2ng3CfPZB9wJlIjHpe/MKUZqyIZkVIXCrwr1tIN+0Dzg==}
+ dependencies:
+ kind-of: 6.0.3
+ dev: true
+
+ /p-cancelable@1.1.0:
+ resolution: {integrity: sha512-s73XxOZ4zpt1edZYZzvhqFa6uvQc1vwUa0K0BdtIZgQMAJj9IbebH+JkgKZc9h+B05PKHLOTl4ajG1BmNrVZlw==}
+ engines: {node: '>=6'}
+ dev: true
+
+ /pako@2.1.0:
+ resolution: {integrity: sha512-w+eufiZ1WuJYgPXbV/PO3NCMEc3xqylkKHzp8bxp1uW4qaSNQUkwmLLEc3kKsfz8lpV1F8Ht3U1Cm+9Srog2ug==}
+ dev: true
+
+ /parse-node-version@1.0.1:
+ resolution: {integrity: sha512-3YHlOa/JgH6Mnpr05jP9eDG254US9ek25LyIxZlDItp2iJtwyaXQb57lBYLdT3MowkUFYEV2XXNAYIPlESvJlA==}
+ engines: {node: '>= 0.10'}
+ dev: true
+
+ /parse5@1.5.1:
+ resolution: {integrity: sha512-w2jx/0tJzvgKwZa58sj2vAYq/S/K1QJfIB3cWYea/Iu1scFPDQQ3IQiVZTHWtRBwAjv2Yd7S/xeZf3XqLDb3bA==}
+ dev: true
+
+ /path-browserify@1.0.1:
+ resolution: {integrity: sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==}
+ dev: true
+
+ /path-is-absolute@1.0.1:
+ resolution: {integrity: sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==}
+ engines: {node: '>=0.10.0'}
+ dev: true
+
+ /path-key@3.1.1:
+ resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==}
+ engines: {node: '>=8'}
+ dev: true
+
+ /path-to-regexp@6.2.1:
+ resolution: {integrity: sha512-JLyh7xT1kizaEvcaXOQwOc2/Yhw6KZOvPf1S8401UyLk86CU79LN3vl7ztXGm/pZ+YjoyAJ4rxmHwbkBXJX+yw==}
+ dev: true
+
+ /pend@1.2.0:
+ resolution: {integrity: sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==}
+ dev: true
+
+ /perf_hooks@0.0.1:
+ resolution: {integrity: sha512-qG/D9iA4KDme+KF4vCObJy6Bouu3BlQnmJ8jPydVPm32NJBD9ZK1ZNgXSYaZKHkVC1sKSqUiLgFvAZPUiIEnBw==}
+ dev: true
+
+ /picocolors@1.0.0:
+ resolution: {integrity: sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==}
+ dev: true
+
+ /pify@3.0.0:
+ resolution: {integrity: sha512-C3FsVNH1udSEX48gGX1xfvwTWfsYWj5U+8/uK15BGzIGrKoUpghX8hWZwa/OFnakBiiVNmBvemTJR5mcy7iPcg==}
+ engines: {node: '>=4'}
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /pify@4.0.1:
+ resolution: {integrity: sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==}
+ engines: {node: '>=6'}
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /pinia@2.1.7(typescript@5.4.3)(vue@3.4.21):
+ resolution: {integrity: sha512-+C2AHFtcFqjPih0zpYuvof37SFxMQ7OEG2zV9jRI12i9BOy3YQVAHwdKtyyc8pDcDyIc33WCIsZaCFWU7WWxGQ==}
+ peerDependencies:
+ '@vue/composition-api': ^1.4.0
+ typescript: '>=4.4.4'
+ vue: ^2.6.14 || ^3.3.0
+ peerDependenciesMeta:
+ '@vue/composition-api':
+ optional: true
+ typescript:
+ optional: true
+ dependencies:
+ '@vue/devtools-api': 6.5.1
+ typescript: 5.4.3
+ vue: 3.4.21(typescript@5.4.3)
+ vue-demi: 0.14.6(vue@3.4.21)
+ dev: true
+
+ /plist@3.1.0:
+ resolution: {integrity: sha512-uysumyrvkUX0rX/dEVqt8gC3sTBzd4zoWfLeS29nb53imdaXVvLINYXTI2GNqzaMuvacNx4uJQ8+b3zXR0pkgQ==}
+ engines: {node: '>=10.4.0'}
+ dependencies:
+ '@xmldom/xmldom': 0.8.10
+ base64-js: 1.5.1
+ xmlbuilder: 15.1.1
+ dev: true
+
+ /postcss@8.4.35:
+ resolution: {integrity: sha512-u5U8qYpBCpN13BsiEB0CbR1Hhh4Gc0zLFuedrHJKMctHCHAGrMdG0PRM/KErzAL3CU6/eckEtmHNB3x6e3c0vA==}
+ engines: {node: ^10 || ^12 || >=14}
+ dependencies:
+ nanoid: 3.3.7
+ picocolors: 1.0.0
+ source-map-js: 1.0.2
+ dev: true
+
+ /postcss@8.4.38:
+ resolution: {integrity: sha512-Wglpdk03BSfXkHoQa3b/oulrotAkwrlLDRSOb9D0bN86FdRyE9lppSp33aHNPgBa0JKCoB+drFLZkQoRRYae5A==}
+ engines: {node: ^10 || ^12 || >=14}
+ dependencies:
+ nanoid: 3.3.7
+ picocolors: 1.0.0
+ source-map-js: 1.2.0
+ dev: true
+
+ /prepend-http@2.0.0:
+ resolution: {integrity: sha512-ravE6m9Atw9Z/jjttRUZ+clIXogdghyZAuWJ3qEzjT+jI/dL1ifAqhZeC5VHzQp1MSt1+jxKkFNemj/iO7tVUA==}
+ engines: {node: '>=4'}
+ dev: true
+
+ /process-nextick-args@2.0.1:
+ resolution: {integrity: sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==}
+ dev: true
+
+ /progress@2.0.3:
+ resolution: {integrity: sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==}
+ engines: {node: '>=0.4.0'}
+ dev: true
+
+ /promise-retry@2.0.1:
+ resolution: {integrity: sha512-y+WKFlBR8BGXnsNlIHFGPZmyDf3DFMoLhaflAnyZgV6rG6xu+JwesTo2Q9R6XwYmtmwAFCkAk3e35jEdoeh/3g==}
+ engines: {node: '>=10'}
+ dependencies:
+ err-code: 2.0.3
+ retry: 0.12.0
+ dev: true
+
+ /proto-list@1.2.4:
+ resolution: {integrity: sha512-vtK/94akxsTMhe0/cbfpR+syPuszcuwhqVjJq26CuNDgFGj682oRBXOP5MJpv2r7JtE8MsiepGIqvvOTBwn2vA==}
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /proxy-from-env@1.1.0:
+ resolution: {integrity: sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==}
+ dev: true
+
+ /prr@1.0.1:
+ resolution: {integrity: sha512-yPw4Sng1gWghHQWj0B3ZggWUm4qVbPwPFcRG8KyxiU7J2OHFSoEHKS+EZ3fv5l1t9CyCiop6l/ZYeWbrgoQejw==}
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /pump@3.0.0:
+ resolution: {integrity: sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==}
+ dependencies:
+ end-of-stream: 1.4.4
+ once: 1.4.0
+ dev: true
+
+ /punycode.js@2.3.1:
+ resolution: {integrity: sha512-uxFIHU0YlHYhDQtV4R9J6a52SLx28BCjT+4ieh7IGbgwVJWO+km431c4yRlREUAsAmt/uMjQUyQHNEPf0M39CA==}
+ engines: {node: '>=6'}
+ dev: true
+
+ /punycode@2.3.1:
+ resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==}
+ engines: {node: '>=6'}
+ requiresBuild: true
+ dev: true
+
+ /read-config-file@6.3.2:
+ resolution: {integrity: sha512-M80lpCjnE6Wt6zb98DoW8WHR09nzMSpu8XHtPkiTHrJ5Az9CybfeQhTJ8D7saeBHpGhLPIVyA8lcL6ZmdKwY6Q==}
+ engines: {node: '>=12.0.0'}
+ dependencies:
+ config-file-ts: 0.2.4
+ dotenv: 9.0.2
+ dotenv-expand: 5.1.0
+ js-yaml: 4.1.0
+ json5: 2.2.3
+ lazy-val: 1.0.5
+ dev: true
+
+ /readable-stream@2.3.8:
+ resolution: {integrity: sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==}
+ dependencies:
+ core-util-is: 1.0.2
+ inherits: 2.0.4
+ isarray: 1.0.0
+ process-nextick-args: 2.0.1
+ safe-buffer: 5.1.2
+ string_decoder: 1.1.1
+ util-deprecate: 1.0.2
+ dev: true
+
+ /readable-stream@3.6.2:
+ resolution: {integrity: sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==}
+ engines: {node: '>= 6'}
+ dependencies:
+ inherits: 2.0.4
+ string_decoder: 1.3.0
+ util-deprecate: 1.0.2
+ dev: true
+
+ /readdir-glob@1.1.3:
+ resolution: {integrity: sha512-v05I2k7xN8zXvPD9N+z/uhXPaj0sUFCe2rcWZIpBsqxfP7xXFQ0tipAd/wjj1YxWyWtUS5IDJpOG82JKt2EAVA==}
+ dependencies:
+ minimatch: 5.1.6
+ dev: true
+
+ /regenerator-runtime@0.14.0:
+ resolution: {integrity: sha512-srw17NI0TUWHuGa5CFGGmhfNIeja30WMBfbslPNhf6JrqQlLN5gcrvig1oqPxiVaXb0oW0XRKtH6Nngs5lKCIA==}
+ dev: true
+
+ /require-directory@2.1.1:
+ resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==}
+ engines: {node: '>=0.10.0'}
+ dev: true
+
+ /resize-observer-polyfill@1.5.1:
+ resolution: {integrity: sha512-LwZrotdHOo12nQuZlHEmtuXdqGoOD0OhaxopaNFxWzInpEgaLWoVuAMbTzixuosCx2nEG58ngzW3vxdWoxIgdg==}
+ dev: true
+
+ /responselike@1.0.2:
+ resolution: {integrity: sha512-/Fpe5guzJk1gPqdJLJR5u7eG/gNY4nImjbRDaVWVMRhne55TCmj2i9Q+54PBRfatRC8v/rIiv9BN0pMd9OV5EQ==}
+ dependencies:
+ lowercase-keys: 1.0.1
+ dev: true
+
+ /retry@0.12.0:
+ resolution: {integrity: sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow==}
+ engines: {node: '>= 4'}
+ dev: true
+
+ /rimraf@3.0.2:
+ resolution: {integrity: sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==}
+ hasBin: true
+ dependencies:
+ glob: 7.2.3
+ dev: true
+
+ /roarr@2.15.4:
+ resolution: {integrity: sha512-CHhPh+UNHD2GTXNYhPWLnU8ONHdI+5DI+4EYIAOaiD63rHeYlZvyh8P+in5999TTSFgUYuKUAjzRI4mdh/p+2A==}
+ engines: {node: '>=8.0'}
+ requiresBuild: true
+ dependencies:
+ boolean: 3.2.0
+ detect-node: 2.1.0
+ globalthis: 1.0.3
+ json-stringify-safe: 5.0.1
+ semver-compare: 1.0.0
+ sprintf-js: 1.1.3
+ dev: true
+ optional: true
+
+ /rollup@4.13.0:
+ resolution: {integrity: sha512-3YegKemjoQnYKmsBlOHfMLVPPA5xLkQ8MHLLSw/fBrFaVkEayL51DilPpNNLq1exr98F2B1TzrV0FUlN3gWRPg==}
+ engines: {node: '>=18.0.0', npm: '>=8.0.0'}
+ hasBin: true
+ dependencies:
+ '@types/estree': 1.0.5
+ optionalDependencies:
+ '@rollup/rollup-android-arm-eabi': 4.13.0
+ '@rollup/rollup-android-arm64': 4.13.0
+ '@rollup/rollup-darwin-arm64': 4.13.0
+ '@rollup/rollup-darwin-x64': 4.13.0
+ '@rollup/rollup-linux-arm-gnueabihf': 4.13.0
+ '@rollup/rollup-linux-arm64-gnu': 4.13.0
+ '@rollup/rollup-linux-arm64-musl': 4.13.0
+ '@rollup/rollup-linux-riscv64-gnu': 4.13.0
+ '@rollup/rollup-linux-x64-gnu': 4.13.0
+ '@rollup/rollup-linux-x64-musl': 4.13.0
+ '@rollup/rollup-win32-arm64-msvc': 4.13.0
+ '@rollup/rollup-win32-ia32-msvc': 4.13.0
+ '@rollup/rollup-win32-x64-msvc': 4.13.0
+ fsevents: 2.3.3
+ dev: true
+
+ /rvfc-polyfill@1.0.7:
+ resolution: {integrity: sha512-seBl7J1J3/k0LuzW2T9fG6JIOpni5AbU+/87LA+zTYKgTVhsfShmS8K/yOo1eeEjGJHnAdkVAUUM+PEjN9Mpkw==}
+ dev: true
+
+ /safe-buffer@5.1.2:
+ resolution: {integrity: sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==}
+ dev: true
+
+ /safe-buffer@5.2.1:
+ resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==}
+ dev: true
+
+ /safer-buffer@2.1.2:
+ resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==}
+ dev: true
+
+ /sanitize-filename@1.6.3:
+ resolution: {integrity: sha512-y/52Mcy7aw3gRm7IrcGDFx/bCk4AhRh2eI9luHOQM86nZsqwiRkkq2GekHXBBD+SmPidc8i2PqtYZl+pWJ8Oeg==}
+ dependencies:
+ truncate-utf8-bytes: 1.0.2
+ dev: true
+
+ /sax@1.1.4:
+ resolution: {integrity: sha512-5f3k2PbGGp+YtKJjOItpg3P99IMD84E4HOvcfleTb5joCHNXYLsR9yWFPOYGgaeMPDubQILTCMdsFb2OMeOjtg==}
+ dev: true
+
+ /sax@1.3.0:
+ resolution: {integrity: sha512-0s+oAmw9zLl1V1cS9BtZN7JAd0cW5e0QH4W3LWEK6a4LaLEA2OTpGYWDY+6XasBLtz6wkm3u1xRw95mRuJ59WA==}
+ dev: true
+
+ /scroll-into-view-if-needed@2.2.31:
+ resolution: {integrity: sha512-dGCXy99wZQivjmjIqihaBQNjryrz5rueJY7eHfTdyWEiR4ttYpsajb14rn9s5d4DY4EcY6+4+U/maARBXJedkA==}
+ dependencies:
+ compute-scroll-into-view: 1.0.20
+ dev: true
+
+ /secp256k1@5.0.0:
+ resolution: {integrity: sha512-TKWX8xvoGHrxVdqbYeZM9w+izTF4b9z3NhSaDkdn81btvuh+ivbIMGT/zQvDtTFWhRlThpoz6LEYTr7n8A5GcA==}
+ engines: {node: '>=14.0.0'}
+ requiresBuild: true
+ dependencies:
+ elliptic: 6.5.4
+ node-addon-api: 5.1.0
+ node-gyp-build: 4.7.1
+ dev: true
+
+ /semver-compare@1.0.0:
+ resolution: {integrity: sha512-YM3/ITh2MJ5MtzaM429anh+x2jiLVjqILF4m4oyQB18W7Ggea7BfqdH/wGMK7dDiMghv/6WG7znWMwUDzJiXow==}
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /semver@5.7.2:
+ resolution: {integrity: sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==}
+ hasBin: true
+ dev: true
+
+ /semver@6.3.1:
+ resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==}
+ hasBin: true
+ dev: true
+
+ /semver@7.6.0:
+ resolution: {integrity: sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==}
+ engines: {node: '>=10'}
+ hasBin: true
+ dependencies:
+ lru-cache: 6.0.0
+ dev: true
+
+ /serialize-error@7.0.1:
+ resolution: {integrity: sha512-8I8TjW5KMOKsZQTvoxjuSIa7foAwPWGOts+6o7sgjz41/qMD9VQHEDxi6PBvK2l0MXUmqZyNpUK+T2tQaaElvw==}
+ engines: {node: '>=10'}
+ requiresBuild: true
+ dependencies:
+ type-fest: 0.13.1
+ dev: true
+ optional: true
+
+ /shallow-equal@1.2.1:
+ resolution: {integrity: sha512-S4vJDjHHMBaiZuT9NPb616CSmLf618jawtv3sufLl6ivK8WocjAo58cXwbRV1cgqxH0Qbv+iUt6m05eqEa2IRA==}
+ dev: true
+
+ /shebang-command@2.0.0:
+ resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==}
+ engines: {node: '>=8'}
+ dependencies:
+ shebang-regex: 3.0.0
+ dev: true
+
+ /shebang-regex@3.0.0:
+ resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==}
+ engines: {node: '>=8'}
+ dev: true
+
+ /shell-env@4.0.1:
+ resolution: {integrity: sha512-w3oeZ9qg/P6Lu6qqwavvMnB/bwfsz67gPB3WXmLd/n6zuh7TWQZtGa3iMEdmua0kj8rivkwl+vUjgLWlqZOMPw==}
+ engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
+ dependencies:
+ default-shell: 2.2.0
+ execa: 5.1.1
+ strip-ansi: 7.1.0
+ dev: true
+
+ /shell-path@3.0.0:
+ resolution: {integrity: sha512-HNIZ+W/3P0JuVTV03xjGqYKt3e3h0/Z4AH8TQWeth1LBtCusSjICgkdNdb3VZr6mI7ijE2AiFFpgkVMNKsALeQ==}
+ engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
+ dependencies:
+ shell-env: 4.0.1
+ dev: true
+
+ /signal-exit@3.0.7:
+ resolution: {integrity: sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==}
+ dev: true
+
+ /simple-swizzle@0.2.2:
+ resolution: {integrity: sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg==}
+ dependencies:
+ is-arrayish: 0.3.2
+ dev: true
+
+ /simple-update-notifier@2.0.0:
+ resolution: {integrity: sha512-a2B9Y0KlNXl9u/vsW6sTIu9vGEpfKu2wRV6l1H3XEas/0gUIzGzBoP/IouTcUQbm9JWZLH3COxyn03TYlFax6w==}
+ engines: {node: '>=10'}
+ dependencies:
+ semver: 7.6.0
+ dev: true
+
+ /slice-ansi@3.0.0:
+ resolution: {integrity: sha512-pSyv7bSTC7ig9Dcgbw9AuRNUb5k5V6oDudjZoMBSr13qpLBG7tB+zgCkARjq7xIUgdz5P1Qe8u+rSGdouOOIyQ==}
+ engines: {node: '>=8'}
+ requiresBuild: true
+ dependencies:
+ ansi-styles: 4.3.0
+ astral-regex: 2.0.0
+ is-fullwidth-code-point: 3.0.0
+ dev: true
+ optional: true
+
+ /smart-buffer@4.2.0:
+ resolution: {integrity: sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==}
+ engines: {node: '>= 6.0.0', npm: '>= 3.0.0'}
+ dev: true
+
+ /socks-proxy-agent@8.0.2:
+ resolution: {integrity: sha512-8zuqoLv1aP/66PHF5TqwJ7Czm3Yv32urJQHrVyhD7mmA6d61Zv8cIXQYPTWwmg6qlupnPvs/QKDmfa4P/qct2g==}
+ engines: {node: '>= 14'}
+ dependencies:
+ agent-base: 7.1.0
+ debug: 4.3.4
+ socks: 2.7.1
+ transitivePeerDependencies:
+ - supports-color
+ dev: true
+
+ /socks@2.7.1:
+ resolution: {integrity: sha512-7maUZy1N7uo6+WVEX6psASxtNlKaNVMlGQKkG/63nEDdLOWNbiUMoLK7X4uYoLhQstau72mLgfEWcXcwsaHbYQ==}
+ engines: {node: '>= 10.13.0', npm: '>= 3.0.0'}
+ dependencies:
+ ip: 2.0.1
+ smart-buffer: 4.2.0
+ dev: true
+
+ /source-map-js@1.0.2:
+ resolution: {integrity: sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==}
+ engines: {node: '>=0.10.0'}
+ dev: true
+
+ /source-map-js@1.2.0:
+ resolution: {integrity: sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg==}
+ engines: {node: '>=0.10.0'}
+ dev: true
+
+ /source-map-support@0.5.21:
+ resolution: {integrity: sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==}
+ dependencies:
+ buffer-from: 1.1.2
+ source-map: 0.6.1
+ dev: true
+
+ /source-map@0.6.1:
+ resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==}
+ engines: {node: '>=0.10.0'}
+ dev: true
+
+ /sprintf-js@1.1.3:
+ resolution: {integrity: sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA==}
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /stat-mode@1.0.0:
+ resolution: {integrity: sha512-jH9EhtKIjuXZ2cWxmXS8ZP80XyC3iasQxMDV8jzhNJpfDb7VbQLVW4Wvsxz9QZvzV+G4YoSfBUVKDOyxLzi/sg==}
+ engines: {node: '>= 6'}
+ dev: true
+
+ /string-width@4.2.3:
+ resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==}
+ engines: {node: '>=8'}
+ dependencies:
+ emoji-regex: 8.0.0
+ is-fullwidth-code-point: 3.0.0
+ strip-ansi: 6.0.1
+ dev: true
+
+ /string_decoder@1.1.1:
+ resolution: {integrity: sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==}
+ dependencies:
+ safe-buffer: 5.1.2
+ dev: true
+
+ /string_decoder@1.3.0:
+ resolution: {integrity: sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==}
+ dependencies:
+ safe-buffer: 5.2.1
+ dev: true
+
+ /strip-ansi@6.0.1:
+ resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==}
+ engines: {node: '>=8'}
+ dependencies:
+ ansi-regex: 5.0.1
+ dev: true
+
+ /strip-ansi@7.1.0:
+ resolution: {integrity: sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==}
+ engines: {node: '>=12'}
+ dependencies:
+ ansi-regex: 6.0.1
+ dev: true
+
+ /strip-final-newline@2.0.0:
+ resolution: {integrity: sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==}
+ engines: {node: '>=6'}
+ dev: true
+
+ /strnum@1.0.5:
+ resolution: {integrity: sha512-J8bbNyKKXl5qYcR36TIO8W3mVGVHrmmxsd5PAItGkmyzwJvybiw2IVq5nqd0i4LSNSkB/sx9VHllbfFdr9k1JA==}
+ dev: true
+
+ /stylis@4.3.1:
+ resolution: {integrity: sha512-EQepAV+wMsIaGVGX1RECzgrcqRRU/0sYOHkeLsZ3fzHaHXZy4DaOOX0vOlGQdlsjkh3mFHAIlVimpwAs4dslyQ==}
+ dev: true
+
+ /sumchecker@3.0.1:
+ resolution: {integrity: sha512-MvjXzkz/BOfyVDkG0oFOtBxHX2u3gKbMHIF/dXblZsgD3BWOFLmHovIpZY7BykJdAjcqRCBi1WYBNdEC9yI7vg==}
+ engines: {node: '>= 8.0'}
+ dependencies:
+ debug: 4.3.4
+ transitivePeerDependencies:
+ - supports-color
+ dev: true
+
+ /supports-color@5.5.0:
+ resolution: {integrity: sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==}
+ engines: {node: '>=4'}
+ dependencies:
+ has-flag: 3.0.0
+ dev: true
+
+ /supports-color@7.2.0:
+ resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==}
+ engines: {node: '>=8'}
+ dependencies:
+ has-flag: 4.0.0
+ dev: true
+
+ /svg-tags@1.0.0:
+ resolution: {integrity: sha512-ovssysQTa+luh7A5Weu3Rta6FJlFBBbInjOh722LIt6klpU2/HtdUbszju/G4devcvk8PGt7FCLv5wftu3THUA==}
+ dev: true
+
+ /tar-stream@2.2.0:
+ resolution: {integrity: sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==}
+ engines: {node: '>=6'}
+ dependencies:
+ bl: 4.1.0
+ end-of-stream: 1.4.4
+ fs-constants: 1.0.0
+ inherits: 2.0.4
+ readable-stream: 3.6.2
+ dev: true
+
+ /tar@6.2.0:
+ resolution: {integrity: sha512-/Wo7DcT0u5HUV486xg675HtjNd3BXZ6xDbzsCUZPt5iw8bTQ63bP0Raut3mvro9u+CUyq7YQd8Cx55fsZXxqLQ==}
+ engines: {node: '>=10'}
+ dependencies:
+ chownr: 2.0.0
+ fs-minipass: 2.1.0
+ minipass: 5.0.0
+ minizlib: 2.1.2
+ mkdirp: 1.0.4
+ yallist: 4.0.0
+ dev: true
+
+ /temp-file@3.4.0:
+ resolution: {integrity: sha512-C5tjlC/HCtVUOi3KWVokd4vHVViOmGjtLwIh4MuzPo/nMYTV/p1urt3RnMz2IWXDdKEGJH3k5+KPxtqRsUYGtg==}
+ dependencies:
+ async-exit-hook: 2.0.1
+ fs-extra: 10.1.0
+ dev: true
+
+ /terser@5.29.2:
+ resolution: {integrity: sha512-ZiGkhUBIM+7LwkNjXYJq8svgkd+QK3UUr0wJqY4MieaezBSAIPgbSPZyIx0idM6XWK5CMzSWa8MJIzmRcB8Caw==}
+ engines: {node: '>=10'}
+ hasBin: true
+ dependencies:
+ '@jridgewell/source-map': 0.3.5
+ acorn: 8.11.2
+ commander: 2.20.3
+ source-map-support: 0.5.21
+ dev: true
+
+ /throttle-debounce@5.0.0:
+ resolution: {integrity: sha512-2iQTSgkkc1Zyk0MeVrt/3BvuOXYPl/R8Z0U2xxo9rjwNciaHDG3R+Lm6dh4EeUci49DanvBnuqI6jshoQQRGEg==}
+ engines: {node: '>=12.22'}
+ dev: true
+
+ /thunky@1.1.0:
+ resolution: {integrity: sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA==}
+ dev: true
+
+ /tmp-promise@3.0.3:
+ resolution: {integrity: sha512-RwM7MoPojPxsOBYnyd2hy0bxtIlVrihNs9pj5SUvY8Zz1sQcQG2tG1hSr8PDxfgEB8RNKDhqbIlroIarSNDNsQ==}
+ dependencies:
+ tmp: 0.2.1
+ dev: true
+
+ /tmp@0.2.1:
+ resolution: {integrity: sha512-76SUhtfqR2Ijn+xllcI5P1oyannHNHByD80W1q447gU3mp9G9PSpGdWmjUOHRDPiHYacIk66W7ubDTuPF3BEtQ==}
+ engines: {node: '>=8.17.0'}
+ dependencies:
+ rimraf: 3.0.2
+ dev: true
+
+ /to-fast-properties@2.0.0:
+ resolution: {integrity: sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==}
+ engines: {node: '>=4'}
+ dev: true
+
+ /to-readable-stream@1.0.0:
+ resolution: {integrity: sha512-Iq25XBt6zD5npPhlLVXGFN3/gyR2/qODcKNNyTMd4vbm39HUaOiAM4PMq0eMVC/Tkxz+Zjdsc55g9yyz+Yq00Q==}
+ engines: {node: '>=6'}
+ dev: true
+
+ /tr46@0.0.3:
+ resolution: {integrity: sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==}
+ dev: true
+
+ /tree-kill@1.2.2:
+ resolution: {integrity: sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==}
+ hasBin: true
+ dev: true
+
+ /truncate-utf8-bytes@1.0.2:
+ resolution: {integrity: sha512-95Pu1QXQvruGEhv62XCMO3Mm90GscOCClvrIUwCM0PYOXK3kaF3l3sIHxx71ThJfcbM2O5Au6SO3AWCSEfW4mQ==}
+ dependencies:
+ utf8-byte-length: 1.0.4
+ dev: true
+
+ /tslib@2.6.2:
+ resolution: {integrity: sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==}
+ dev: true
+
+ /tunnel@0.0.6:
+ resolution: {integrity: sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg==}
+ engines: {node: '>=0.6.11 <=0.7.0 || >=0.7.3'}
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /type-fest@0.13.1:
+ resolution: {integrity: sha512-34R7HTnG0XIJcBSn5XhDd7nNFPRcXYRZrBB2O2jdKqYODldSzBAqzsWoZYYvduky73toYS/ESqxPvkDf/F0XMg==}
+ engines: {node: '>=10'}
+ requiresBuild: true
+ dev: true
+ optional: true
+
+ /typescript@4.9.5:
+ resolution: {integrity: sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==}
+ engines: {node: '>=4.2.0'}
+ hasBin: true
+ dev: true
+
+ /typescript@5.4.3:
+ resolution: {integrity: sha512-KrPd3PKaCLr78MalgiwJnA25Nm8HAmdwN3mYUYZgG/wizIo9EainNVQI9/yDavtVFRN2h3k8uf3GLHuhDMgEHg==}
+ engines: {node: '>=14.17'}
+ hasBin: true
+ dev: true
+
+ /uc.micro@2.1.0:
+ resolution: {integrity: sha512-ARDJmphmdvUk6Glw7y9DQ2bFkKBHwQHLi2lsaH6PPmz/Ka9sFOBsBluozhDltWmnv9u/cF6Rt87znRTPV+yp/A==}
+ dev: true
+
+ /undici-types@5.26.5:
+ resolution: {integrity: sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==}
+ dev: true
+
+ /universalify@0.1.2:
+ resolution: {integrity: sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==}
+ engines: {node: '>= 4.0.0'}
+ dev: true
+
+ /universalify@2.0.1:
+ resolution: {integrity: sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==}
+ engines: {node: '>= 10.0.0'}
+ dev: true
+
+ /update-browserslist-db@1.0.13(browserslist@4.22.2):
+ resolution: {integrity: sha512-xebP81SNcPuNpPP3uzeW1NYXxI3rxyJzF3pD6sH4jE7o/IX+WtSpwnVU+qIsDPyk0d3hmFQ7mjqc6AtV604hbg==}
+ hasBin: true
+ peerDependencies:
+ browserslist: '>= 4.21.0'
+ dependencies:
+ browserslist: 4.22.2
+ escalade: 3.1.1
+ picocolors: 1.0.0
+ dev: true
+
+ /upnp-client-ts@1.1.1:
+ resolution: {integrity: sha512-UTe5r/2sAth2g4lama6ETTJxYcIhcKRATZZmdb+BavPqPuY3GRSXPxLgDtbc64dqwvomKZecEEiwT+6vm8mWpw==}
+ engines: {node: '>=18.0.0'}
+ dependencies:
+ elementtree: 0.1.7
+ dev: true
+
+ /uri-js@4.4.1:
+ resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==}
+ requiresBuild: true
+ dependencies:
+ punycode: 2.3.1
+ dev: true
+
+ /url-parse-lax@3.0.0:
+ resolution: {integrity: sha512-NjFKA0DidqPa5ciFcSrXnAltTtzz84ogy+NebPvfEgAck0+TNg4UJ4IN+fB7zRZfbgUf0syOo9MDxFkDSMuFaQ==}
+ engines: {node: '>=4'}
+ dependencies:
+ prepend-http: 2.0.0
+ dev: true
+
+ /utf8-byte-length@1.0.4:
+ resolution: {integrity: sha512-4+wkEYLBbWxqTahEsWrhxepcoVOJ+1z5PGIjPZxRkytcdSUaNjIjBM7Xn8E+pdSuV7SzvWovBFA54FO0JSoqhA==}
+ dev: true
+
+ /util-deprecate@1.0.2:
+ resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==}
+ dev: true
+
+ /uuid-by-string@4.0.0:
+ resolution: {integrity: sha512-88ZSfcSkN04juiLqSsuyteqlSrXNFdsEPzSv3urnElDXNsZUXQN0smeTnh99x2DE15SCUQNgqKBfro54CuzHNQ==}
+ dependencies:
+ js-md5: 0.7.3
+ js-sha1: 0.6.0
+ dev: true
+
+ /uuid@9.0.1:
+ resolution: {integrity: sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==}
+ hasBin: true
+ dev: true
+
+ /verror@1.10.1:
+ resolution: {integrity: sha512-veufcmxri4e3XSrT0xwfUR7kguIkaxBeosDg00yDWhk49wdwkSUrvvsm7nc75e1PUyvIeZj6nS8VQRYz2/S4Xg==}
+ engines: {node: '>=0.6.0'}
+ requiresBuild: true
+ dependencies:
+ assert-plus: 1.0.0
+ core-util-is: 1.0.2
+ extsprintf: 1.4.1
+ dev: true
+ optional: true
+
+ /viewerjs@1.11.6:
+ resolution: {integrity: sha512-TlhdSp2oEOLFXvEp4psKaeTjR5zBjTRcM/sHUN8PkV1UWuY8HKC8n7GaVdW5Xqnwdr/F1OmzLik1QwDjI4w/nw==}
+ dev: true
+
+ /vite-plugin-electron-renderer@0.14.5:
+ resolution: {integrity: sha512-EQ7ORuPp8vFPCqfuGnVo7d36fXS0IFH4/RUlKb1drseix3TQEPcgwEuFADdXBxRgqMp70njz/1m0kdf5lEsm8w==}
+ dev: true
+
+ /vite-plugin-electron@0.15.6(tree-kill@1.2.2)(vite-plugin-electron-renderer@0.14.5):
+ resolution: {integrity: sha512-sbjzNiH8N6Was67oIUgglW6tefahkiCTItM3MsdOAQ0xhUMxizeQMF9DhSvEBwvLvUGKYboIdIYskSchV7Akrg==}
+ peerDependencies:
+ tree-kill: '*'
+ vite-plugin-electron-renderer: '*'
+ peerDependenciesMeta:
+ tree-kill:
+ optional: true
+ vite-plugin-electron-renderer:
+ optional: true
+ dependencies:
+ tree-kill: 1.2.2
+ vite-plugin-electron-renderer: 0.14.5
+ dev: true
+
+ /vite@5.2.2(@types/node@20.11.30)(less@4.2.0)(terser@5.29.2):
+ resolution: {integrity: sha512-FWZbz0oSdLq5snUI0b6sULbz58iXFXdvkZfZWR/F0ZJuKTSPO7v72QPXt6KqYeMFb0yytNp6kZosxJ96Nr/wDQ==}
+ engines: {node: ^18.0.0 || >=20.0.0}
+ hasBin: true
+ peerDependencies:
+ '@types/node': ^18.0.0 || >=20.0.0
+ less: '*'
+ lightningcss: ^1.21.0
+ sass: '*'
+ stylus: '*'
+ sugarss: '*'
+ terser: ^5.4.0
+ peerDependenciesMeta:
+ '@types/node':
+ optional: true
+ less:
+ optional: true
+ lightningcss:
+ optional: true
+ sass:
+ optional: true
+ stylus:
+ optional: true
+ sugarss:
+ optional: true
+ terser:
+ optional: true
+ dependencies:
+ '@types/node': 20.11.30
+ esbuild: 0.20.2
+ less: 4.2.0
+ postcss: 8.4.38
+ rollup: 4.13.0
+ terser: 5.29.2
+ optionalDependencies:
+ fsevents: 2.3.3
+ dev: true
+
+ /vue-demi@0.14.6(vue@3.4.21):
+ resolution: {integrity: sha512-8QA7wrYSHKaYgUxDA5ZC24w+eHm3sYCbp0EzcDwKqN3p6HqtTCGR/GVsPyZW92unff4UlcSh++lmqDWN3ZIq4w==}
+ engines: {node: '>=12'}
+ hasBin: true
+ requiresBuild: true
+ peerDependencies:
+ '@vue/composition-api': ^1.0.0-rc.1
+ vue: ^3.0.0-0 || ^2.6.0
+ peerDependenciesMeta:
+ '@vue/composition-api':
+ optional: true
+ dependencies:
+ vue: 3.4.21(typescript@5.4.3)
+ dev: true
+
+ /vue-template-compiler@2.7.15:
+ resolution: {integrity: sha512-yQxjxMptBL7UAog00O8sANud99C6wJF+7kgbcwqkvA38vCGF7HWE66w0ZFnS/kX5gSoJr/PQ4/oS3Ne2pW37Og==}
+ dependencies:
+ de-indent: 1.0.2
+ he: 1.2.0
+ dev: true
+
+ /vue-tsc@2.0.7(typescript@5.4.3):
+ resolution: {integrity: sha512-LYa0nInkfcDBB7y8jQ9FQ4riJTRNTdh98zK/hzt4gEpBZQmf30dPhP+odzCa+cedGz6B/guvJEd0BavZaRptjg==}
+ hasBin: true
+ peerDependencies:
+ typescript: '*'
+ dependencies:
+ '@volar/typescript': 2.1.4
+ '@vue/language-core': 2.0.7(typescript@5.4.3)
+ semver: 7.6.0
+ typescript: 5.4.3
+ dev: true
+
+ /vue-types@3.0.2(vue@3.4.21):
+ resolution: {integrity: sha512-IwUC0Aq2zwaXqy74h4WCvFCUtoV0iSWr0snWnE9TnU18S66GAQyqQbRf2qfJtUuiFsBf6qp0MEwdonlwznlcrw==}
+ engines: {node: '>=10.15.0'}
+ peerDependencies:
+ vue: ^3.0.0
+ dependencies:
+ is-plain-object: 3.0.1
+ vue: 3.4.21(typescript@5.4.3)
+ dev: true
+
+ /vue@3.4.21(typescript@5.4.3):
+ resolution: {integrity: sha512-5hjyV/jLEIKD/jYl4cavMcnzKwjMKohureP8ejn3hhEjwhWIhWeuzL2kJAjzl/WyVsgPY56Sy4Z40C3lVshxXA==}
+ peerDependencies:
+ typescript: '*'
+ peerDependenciesMeta:
+ typescript:
+ optional: true
+ dependencies:
+ '@vue/compiler-dom': 3.4.21
+ '@vue/compiler-sfc': 3.4.21
+ '@vue/runtime-dom': 3.4.21
+ '@vue/server-renderer': 3.4.21(vue@3.4.21)
+ '@vue/shared': 3.4.21
+ typescript: 5.4.3
+ dev: true
+
+ /warning@4.0.3:
+ resolution: {integrity: sha512-rpJyN222KWIvHJ/F53XSZv0Zl/accqHR8et1kpaMTD/fLCRxtV8iX8czMzY7sVZupTI3zcUTg8eycS2kNF9l6w==}
+ dependencies:
+ loose-envify: 1.4.0
+ dev: true
+
+ /webdav-server@2.6.2:
+ resolution: {integrity: sha512-0iHdrOzlKGFD96bTvPF8IIEfxw9Q7jB5LqWqhjyBYsofD6T6mOYqWtAvR88VY9Mq0xeg8bCRHC2Vifc9iuTYuw==}
+ engines: {node: '>= 4'}
+ dependencies:
+ mime-types: 2.1.35
+ xml-js-builder: 1.0.3
+ dev: true
+
+ /webidl-conversions@3.0.1:
+ resolution: {integrity: sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==}
+ dev: true
+
+ /whacko@0.19.1:
+ resolution: {integrity: sha512-OnO3ZX6wIC21GASyIl6ZcVYhu+BaIcaGNtads+O9U/gFqQ4dkUrpauAb3WMSWFK+2qzDfxEXnOxBqQnS1/NrXQ==}
+ engines: {node: '>= 0.6'}
+ dependencies:
+ css-select: 1.2.0
+ domutils: 1.5.1
+ lodash: 3.10.1
+ parse5: 1.5.1
+ dev: true
+
+ /whatwg-fetch@3.6.19:
+ resolution: {integrity: sha512-d67JP4dHSbm2TrpFj8AbO8DnL1JXL5J9u0Kq2xW6d0TFDbCA3Muhdt8orXC22utleTVj7Prqt82baN6RBvnEgw==}
+ dev: true
+
+ /whatwg-url@5.0.0:
+ resolution: {integrity: sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==}
+ dependencies:
+ tr46: 0.0.3
+ webidl-conversions: 3.0.1
+ dev: true
+
+ /which@2.0.2:
+ resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==}
+ engines: {node: '>= 8'}
+ hasBin: true
+ dependencies:
+ isexe: 2.0.0
+ dev: true
+
+ /wrap-ansi@7.0.0:
+ resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==}
+ engines: {node: '>=10'}
+ dependencies:
+ ansi-styles: 4.3.0
+ string-width: 4.2.3
+ strip-ansi: 6.0.1
+ dev: true
+
+ /wrappy@1.0.2:
+ resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==}
+ dev: true
+
+ /xml-js-builder@1.0.3:
+ resolution: {integrity: sha512-BoLgG/glT45M0jK5PGh9h+iGrQxa8jJk9ofR63GroRifl2tbGB3/yYiVY3wQWHrZgWWfl9+7fhEB/VoD9mWnSg==}
+ engines: {node: '>= 4'}
+ dependencies:
+ xml-js: 1.6.11
+ dev: true
+
+ /xml-js@1.6.11:
+ resolution: {integrity: sha512-7rVi2KMfwfWFl+GpPg6m80IVMWXLRjO+PxTq7V2CDhoGak0wzYzFgUY2m4XJ47OGdXd8eLE8EmwfAmdjw7lC1g==}
+ hasBin: true
+ dependencies:
+ sax: 1.3.0
+ dev: true
+
+ /xmlbuilder@15.1.1:
+ resolution: {integrity: sha512-yMqGBqtXyeN1e3TGYvgNgDVZ3j84W4cwkOXQswghol6APgZWaff9lnbvN7MHYJOiXsvGPXtjTYJEiC9J2wv9Eg==}
+ engines: {node: '>=8.0'}
+ requiresBuild: true
+ dev: true
+
+ /y18n@5.0.8:
+ resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==}
+ engines: {node: '>=10'}
+ dev: true
+
+ /yallist@3.1.1:
+ resolution: {integrity: sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==}
+ dev: true
+
+ /yallist@4.0.0:
+ resolution: {integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==}
+ dev: true
+
+ /yargs-parser@21.1.1:
+ resolution: {integrity: sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==}
+ engines: {node: '>=12'}
+ dev: true
+
+ /yargs@17.7.2:
+ resolution: {integrity: sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==}
+ engines: {node: '>=12'}
+ dependencies:
+ cliui: 8.0.1
+ escalade: 3.1.1
+ get-caller-file: 2.0.5
+ require-directory: 2.1.1
+ string-width: 4.2.3
+ y18n: 5.0.8
+ yargs-parser: 21.1.1
+ dev: true
+
+ /yauzl@2.10.0:
+ resolution: {integrity: sha512-p4a9I6X6nu6IhoGmBqAcbJy1mlC4j27vEPZX9F4L4/vZT3Lyq1VkFHw/V/PUcB9Buo+DG3iHkT0x3Qya58zc3g==}
+ dependencies:
+ buffer-crc32: 0.2.13
+ fd-slicer: 1.1.0
+ dev: true
+
+ /zip-stream@4.1.1:
+ resolution: {integrity: sha512-9qv4rlDiopXg4E69k+vMHjNN63YFMe9sZMrdlvKnCjlCRWeCBswPPMPUfx+ipsAWq1LXHe70RcbaHdJJpS6hyQ==}
+ engines: {node: '>= 10'}
+ dependencies:
+ archiver-utils: 3.0.4
+ compress-commons: 4.1.2
+ readable-stream: 3.6.2
+ dev: true
diff --git a/aliyunpan/postcss.config.js b/aliyunpan/postcss.config.js
new file mode 100644
index 0000000000..33ad091d26
--- /dev/null
+++ b/aliyunpan/postcss.config.js
@@ -0,0 +1,6 @@
+module.exports = {
+ plugins: {
+ tailwindcss: {},
+ autoprefixer: {},
+ },
+}
diff --git a/aliyunpan/public/audio/down_finished.mp3 b/aliyunpan/public/audio/download_finished.mp3
similarity index 100%
rename from aliyunpan/public/audio/down_finished.mp3
rename to aliyunpan/public/audio/download_finished.mp3
diff --git a/aliyunpan/public/comlink.js b/aliyunpan/public/comlink.js
deleted file mode 100644
index 4ba9504c53..0000000000
--- a/aliyunpan/public/comlink.js
+++ /dev/null
@@ -1,319 +0,0 @@
-(function (global, factory) {
- typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
- typeof define === 'function' && define.amd ? define(['exports'], factory) :
- (global = global || self, factory(global.Comlink = {}));
-}(this, (function (exports) { 'use strict';
-
- /**
- * Copyright 2019 Google Inc. All Rights Reserved.
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- * http://www.apache.org/licenses/LICENSE-2.0
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- const proxyMarker = Symbol("Comlink.proxy");
- const createEndpoint = Symbol("Comlink.endpoint");
- const releaseProxy = Symbol("Comlink.releaseProxy");
- const throwMarker = Symbol("Comlink.thrown");
- const isObject = (val) => (typeof val === "object" && val !== null) || typeof val === "function";
- /**
- * Internal transfer handle to handle objects marked to proxy.
- */
- const proxyTransferHandler = {
- canHandle: (val) => isObject(val) && val[proxyMarker],
- serialize(obj) {
- const { port1, port2 } = new MessageChannel();
- expose(obj, port1);
- return [port2, [port2]];
- },
- deserialize(port) {
- port.start();
- return wrap(port);
- },
- };
- /**
- * Internal transfer handler to handle thrown exceptions.
- */
- const throwTransferHandler = {
- canHandle: (value) => isObject(value) && throwMarker in value,
- serialize({ value }) {
- let serialized;
- if (value instanceof Error) {
- serialized = {
- isError: true,
- value: {
- message: value.message,
- name: value.name,
- stack: value.stack,
- },
- };
- }
- else {
- serialized = { isError: false, value };
- }
- return [serialized, []];
- },
- deserialize(serialized) {
- if (serialized.isError) {
- throw Object.assign(new Error(serialized.value.message), serialized.value);
- }
- throw serialized.value;
- },
- };
- /**
- * Allows customizing the serialization of certain values.
- */
- const transferHandlers = new Map([
- ["proxy", proxyTransferHandler],
- ["throw", throwTransferHandler],
- ]);
- function expose(obj, ep = self) {
- ep.addEventListener("message", function callback(ev) {
- if (!ev || !ev.data) {
- return;
- }
- const { id, type, path } = Object.assign({ path: [] }, ev.data);
- const argumentList = (ev.data.argumentList || []).map(fromWireValue);
- let returnValue;
- try {
- const parent = path.slice(0, -1).reduce((obj, prop) => obj[prop], obj);
- const rawValue = path.reduce((obj, prop) => obj[prop], obj);
- switch (type) {
- case "GET" /* GET */:
- {
- returnValue = rawValue;
- }
- break;
- case "SET" /* SET */:
- {
- parent[path.slice(-1)[0]] = fromWireValue(ev.data.value);
- returnValue = true;
- }
- break;
- case "APPLY" /* APPLY */:
- {
- returnValue = rawValue.apply(parent, argumentList);
- }
- break;
- case "CONSTRUCT" /* CONSTRUCT */:
- {
- const value = new rawValue(...argumentList);
- returnValue = proxy(value);
- }
- break;
- case "ENDPOINT" /* ENDPOINT */:
- {
- const { port1, port2 } = new MessageChannel();
- expose(obj, port2);
- returnValue = transfer(port1, [port1]);
- }
- break;
- case "RELEASE" /* RELEASE */:
- {
- returnValue = undefined;
- }
- break;
- default:
- return;
- }
- }
- catch (value) {
- returnValue = { value, [throwMarker]: 0 };
- }
- Promise.resolve(returnValue)
- .catch((value) => {
- return { value, [throwMarker]: 0 };
- })
- .then((returnValue) => {
- const [wireValue, transferables] = toWireValue(returnValue);
- ep.postMessage(Object.assign(Object.assign({}, wireValue), { id }), transferables);
- if (type === "RELEASE" /* RELEASE */) {
- // detach and deactive after sending release response above.
- ep.removeEventListener("message", callback);
- closeEndPoint(ep);
- }
- });
- });
- if (ep.start) {
- ep.start();
- }
- }
- function isMessagePort(endpoint) {
- return endpoint.constructor.name === "MessagePort";
- }
- function closeEndPoint(endpoint) {
- if (isMessagePort(endpoint))
- endpoint.close();
- }
- function wrap(ep, target) {
- return createProxy(ep, [], target);
- }
- function throwIfProxyReleased(isReleased) {
- if (isReleased) {
- throw new Error("Proxy has been released and is not useable");
- }
- }
- function createProxy(ep, path = [], target = function () { }) {
- let isProxyReleased = false;
- const proxy = new Proxy(target, {
- get(_target, prop) {
- throwIfProxyReleased(isProxyReleased);
- if (prop === releaseProxy) {
- return () => {
- return requestResponseMessage(ep, {
- type: "RELEASE" /* RELEASE */,
- path: path.map((p) => p.toString()),
- }).then(() => {
- closeEndPoint(ep);
- isProxyReleased = true;
- });
- };
- }
- if (prop === "then") {
- if (path.length === 0) {
- return { then: () => proxy };
- }
- const r = requestResponseMessage(ep, {
- type: "GET" /* GET */,
- path: path.map((p) => p.toString()),
- }).then(fromWireValue);
- return r.then.bind(r);
- }
- return createProxy(ep, [...path, prop]);
- },
- set(_target, prop, rawValue) {
- throwIfProxyReleased(isProxyReleased);
- // FIXME: ES6 Proxy Handler `set` methods are supposed to return a
- // boolean. To show good will, we return true asynchronously ¯\_(ツ)_/¯
- const [value, transferables] = toWireValue(rawValue);
- return requestResponseMessage(ep, {
- type: "SET" /* SET */,
- path: [...path, prop].map((p) => p.toString()),
- value,
- }, transferables).then(fromWireValue);
- },
- apply(_target, _thisArg, rawArgumentList) {
- throwIfProxyReleased(isProxyReleased);
- const last = path[path.length - 1];
- if (last === createEndpoint) {
- return requestResponseMessage(ep, {
- type: "ENDPOINT" /* ENDPOINT */,
- }).then(fromWireValue);
- }
- // We just pretend that `bind()` didn’t happen.
- if (last === "bind") {
- return createProxy(ep, path.slice(0, -1));
- }
- const [argumentList, transferables] = processArguments(rawArgumentList);
- return requestResponseMessage(ep, {
- type: "APPLY" /* APPLY */,
- path: path.map((p) => p.toString()),
- argumentList,
- }, transferables).then(fromWireValue);
- },
- construct(_target, rawArgumentList) {
- throwIfProxyReleased(isProxyReleased);
- const [argumentList, transferables] = processArguments(rawArgumentList);
- return requestResponseMessage(ep, {
- type: "CONSTRUCT" /* CONSTRUCT */,
- path: path.map((p) => p.toString()),
- argumentList,
- }, transferables).then(fromWireValue);
- },
- });
- return proxy;
- }
- function myFlat(arr) {
- return Array.prototype.concat.apply([], arr);
- }
- function processArguments(argumentList) {
- const processed = argumentList.map(toWireValue);
- return [processed.map((v) => v[0]), myFlat(processed.map((v) => v[1]))];
- }
- const transferCache = new WeakMap();
- function transfer(obj, transfers) {
- transferCache.set(obj, transfers);
- return obj;
- }
- function proxy(obj) {
- return Object.assign(obj, { [proxyMarker]: true });
- }
- function windowEndpoint(w, context = self, targetOrigin = "*") {
- return {
- postMessage: (msg, transferables) => w.postMessage(msg, targetOrigin, transferables),
- addEventListener: context.addEventListener.bind(context),
- removeEventListener: context.removeEventListener.bind(context),
- };
- }
- function toWireValue(value) {
- for (const [name, handler] of transferHandlers) {
- if (handler.canHandle(value)) {
- const [serializedValue, transferables] = handler.serialize(value);
- return [
- {
- type: "HANDLER" /* HANDLER */,
- name,
- value: serializedValue,
- },
- transferables,
- ];
- }
- }
- return [
- {
- type: "RAW" /* RAW */,
- value,
- },
- transferCache.get(value) || [],
- ];
- }
- function fromWireValue(value) {
- switch (value.type) {
- case "HANDLER" /* HANDLER */:
- return transferHandlers.get(value.name).deserialize(value.value);
- case "RAW" /* RAW */:
- return value.value;
- }
- }
- function requestResponseMessage(ep, msg, transfers) {
- return new Promise((resolve) => {
- const id = generateUUID();
- ep.addEventListener("message", function l(ev) {
- if (!ev.data || !ev.data.id || ev.data.id !== id) {
- return;
- }
- ep.removeEventListener("message", l);
- resolve(ev.data);
- });
- if (ep.start) {
- ep.start();
- }
- ep.postMessage(Object.assign({ id }, msg), transfers);
- });
- }
- function generateUUID() {
- return new Array(4)
- .fill(0)
- .map(() => Math.floor(Math.random() * Number.MAX_SAFE_INTEGER).toString(16))
- .join("-");
- }
-
- exports.createEndpoint = createEndpoint;
- exports.expose = expose;
- exports.proxy = proxy;
- exports.proxyMarker = proxyMarker;
- exports.releaseProxy = releaseProxy;
- exports.transfer = transfer;
- exports.transferHandlers = transferHandlers;
- exports.windowEndpoint = windowEndpoint;
- exports.wrap = wrap;
-
- Object.defineProperty(exports, '__esModule', { value: true });
-
-})));
-//# sourceMappingURL=comlink.js.map
\ No newline at end of file
diff --git a/aliyunpan/public/favicon.png b/aliyunpan/public/favicon.png
new file mode 100644
index 0000000000..5a9e9dfe6c
Binary files /dev/null and b/aliyunpan/public/favicon.png differ
diff --git a/aliyunpan/public/font/VideoJS.woff b/aliyunpan/public/font/VideoJS.woff
deleted file mode 100644
index 4b846ae5e0..0000000000
Binary files a/aliyunpan/public/font/VideoJS.woff and /dev/null differ
diff --git a/aliyunpan/public/iconfont.css b/aliyunpan/public/iconfont.css
index 687803b7a7..a70e770ec3 100644
--- a/aliyunpan/public/iconfont.css
+++ b/aliyunpan/public/iconfont.css
@@ -4,9 +4,8 @@
}
.iconfont {
- font-family: "iconfont" !important;
+ font-family: "iconfont", serif !important;
font-size: 16px;
- color: #0078D7;
font-style: normal;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
@@ -805,10 +804,6 @@
content: "\e842";
}
-.iconhistory:before {
- content: "\e6bb";
-}
-
.iconset:before {
content: "\e623";
}
diff --git a/aliyunpan/public/images/alicode.png b/aliyunpan/public/images/alicode.png
deleted file mode 100644
index f70a7a18a3..0000000000
Binary files a/aliyunpan/public/images/alicode.png and /dev/null differ
diff --git a/aliyunpan/public/images/indicator.svg b/aliyunpan/public/images/indicator.svg
new file mode 100644
index 0000000000..e0c134312f
--- /dev/null
+++ b/aliyunpan/public/images/indicator.svg
@@ -0,0 +1,5 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/aliyunpan/public/images/loading.svg b/aliyunpan/public/images/loading.svg
new file mode 100644
index 0000000000..197d5bd20c
--- /dev/null
+++ b/aliyunpan/public/images/loading.svg
@@ -0,0 +1,52 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/aliyunpan/public/images/music_bg.jpg b/aliyunpan/public/images/music_bg.jpg
new file mode 100644
index 0000000000..8d328fc77b
Binary files /dev/null and b/aliyunpan/public/images/music_bg.jpg differ
diff --git a/aliyunpan/public/images/pause.svg b/aliyunpan/public/images/pause.svg
new file mode 100644
index 0000000000..752d72ed85
--- /dev/null
+++ b/aliyunpan/public/images/pause.svg
@@ -0,0 +1,34 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/aliyunpan/public/images/ploading.gif b/aliyunpan/public/images/ploading.gif
new file mode 100644
index 0000000000..1a8c97d044
Binary files /dev/null and b/aliyunpan/public/images/ploading.gif differ
diff --git a/aliyunpan/public/images/sales.png b/aliyunpan/public/images/sales.png
index d4d0322b88..d75c01b46e 100644
Binary files a/aliyunpan/public/images/sales.png and b/aliyunpan/public/images/sales.png differ
diff --git a/aliyunpan/public/images/state.svg b/aliyunpan/public/images/state.svg
new file mode 100644
index 0000000000..8c8ab30185
--- /dev/null
+++ b/aliyunpan/public/images/state.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/aliyunpan/public/imgerror.png b/aliyunpan/public/imgerror.png
deleted file mode 100644
index d84bbd63b7..0000000000
Binary files a/aliyunpan/public/imgerror.png and /dev/null differ
diff --git a/aliyunpan/public/loading.png b/aliyunpan/public/loading.png
deleted file mode 100644
index 59e18d9ae2..0000000000
Binary files a/aliyunpan/public/loading.png and /dev/null differ
diff --git a/aliyunpan/public/main.html b/aliyunpan/public/main.html
index 1709205f94..023675c3fc 100644
--- a/aliyunpan/public/main.html
+++ b/aliyunpan/public/main.html
@@ -2,13 +2,13 @@
- 小白羊云盘
+ 阿里云盘小白羊
-
+
-
+
-
+
diff --git a/aliyunpan/public/main2.html b/aliyunpan/public/main2.html
index 7e77259084..4820a7a297 100644
--- a/aliyunpan/public/main2.html
+++ b/aliyunpan/public/main2.html
@@ -2,16 +2,16 @@
- 小白羊云盘
+ 阿里云盘小白羊
-
-
-
-
+
+
+
+
-
+
diff --git a/aliyunpan/public/notify.wav b/aliyunpan/public/notify.wav
deleted file mode 100644
index 6bf41a35d1..0000000000
Binary files a/aliyunpan/public/notify.wav and /dev/null differ
diff --git a/aliyunpan/public/userface.png b/aliyunpan/public/userface.png
deleted file mode 100644
index 0565d3db6f..0000000000
Binary files a/aliyunpan/public/userface.png and /dev/null differ
diff --git a/aliyunpan/src/App.vue b/aliyunpan/src/App.vue
index c7a627ac08..121d19fe27 100644
--- a/aliyunpan/src/App.vue
+++ b/aliyunpan/src/App.vue
@@ -10,7 +10,7 @@ import PageVideoXBTVue from './layout/PageVideoXBT.vue'
import PageCode from './layout/PageCode.vue'
import PageOffice from './layout/PageOffice.vue'
import PageImage from './layout/PageImage.vue'
-import PageHelp from './layout/PageHelp.vue'
+import PageAudio from './layout/PageAudio.vue'
import PageVideo from './layout/PageVideo.vue'
import PageWorker from './layout/PageWorker.vue'
@@ -20,12 +20,12 @@ export default {
return () => {
if (appStore.appPage == 'PageMain') return h(PageMain)
- if (appStore.appPage == 'PageHelp') return h(PageHelp)
if (appStore.appPage == 'PageOffice') return h(PageOffice)
if (appStore.appPage == 'PageVideoXBT') return h(PageVideoXBTVue)
if (appStore.appPage == 'PageCode') return h(PageCode)
if (appStore.appPage == 'PageImage') return h(PageImage)
if (appStore.appPage == 'PageVideo') return h(PageVideo)
+ if (appStore.appPage == 'PageAudio') return h(PageAudio)
if (appStore.appPage == 'PageWorker') return h(PageWorker)
return h(PageLoading)
}
diff --git a/aliyunpan/src/aliapi/album.ts b/aliyunpan/src/aliapi/album.ts
index 77ccc7c54a..82bf879358 100644
--- a/aliyunpan/src/aliapi/album.ts
+++ b/aliyunpan/src/aliapi/album.ts
@@ -1,289 +1,455 @@
-import {AliAlbumFileInfo, IAliAlbumsList, IAliAlubmCreateInfo, IAliAlubmListInfo} from './alimodels'
-import AliHttp, {IUrlRespData} from "./alihttp";
-import DebugLog from "../utils/debuglog";
-import {useSettingStore, useUserStore} from "../store";
-import {GetDriveID} from "./utils";
+import {
+ AliAlbumFileInfo,
+ IAliAlbumInfo,
+ IAliAlbumsList,
+ IAliAlubmCreateInfo,
+ IAliAlubmListInfo,
+ IAliGetDirModel
+} from './alimodels'
+import AliHttp, { IUrlRespData } from './alihttp'
+import DebugLog from '../utils/debuglog'
+import { HanToPin } from '../utils/utils'
+import { GetDriveID } from './utils'
+import { useSettingStore, useUserStore } from '../store'
export default class AliAlbum {
- static async ApiAlbumsList(): Promise {
- const url = 'adrive/v1/album/list'
- const albums: IAliAlbumsList[] = []
- if (!GetDriveID(useUserStore().user_id, 'pic')) {
- return albums
- }
- const userId = useUserStore().user_id
- let max: number = useSettingStore().debugFileListMax
- let next_marker = ''
- do {
- const resp = await AliHttp.Post(url, {next_marker: next_marker}, userId, '')
- if (AliHttp.IsSuccess(resp.code)) {
- const items = resp.body.items as IAliAlubmListInfo[]
- if (items) {
- items.forEach((item) => {
- if (item.cover && item.cover.list
- && item.cover.list.length > 0
- && item.cover.list[0].thumbnail) {
- albums.push({
- name: item.album_id,
- friendly_name: item.name,
- preview: item.cover.list[0].thumbnail,
- image_count: item.image_count
- })
- } else {
- albums.push({
- name: item.album_id,
- friendly_name: item.name,
- preview: '',
- image_count: item.image_count
- })
- }
-
- })
- next_marker = resp.body.next_marker
- } else {
- next_marker = ''
- }
-
+ static async ApiAlbumsList(): Promise {
+ const url = 'adrive/v1/album/list'
+ const albums: IAliAlbumsList[] = []
+ if (!GetDriveID(useUserStore().user_id, 'pic')) {
+ return albums
+ }
+ const userId = useUserStore().user_id
+ let max: number = useSettingStore().debugFileListMax
+ let next_marker = ''
+ do {
+ const resp = await AliHttp.Post(url, {next_marker: next_marker}, userId, '')
+ if (AliHttp.IsSuccess(resp.code)) {
+ const items = resp.body.items as IAliAlubmListInfo[]
+ if (items) {
+ items.forEach((item) => {
+ if (item.cover && item.cover.list
+ && item.cover.list.length > 0
+ && item.cover.list[0].thumbnail) {
+ albums.push({
+ name: item.album_id,
+ friendly_name: item.name,
+ preview: item.cover.list[0].thumbnail,
+ image_count: item.image_count
+ })
} else {
- next_marker = ''
- break
+ albums.push({
+ name: item.album_id,
+ friendly_name: item.name,
+ preview: '',
+ image_count: item.image_count
+ })
}
- if (albums.length >= max && max > 0) {
- next_marker = ''
- break
- }
- } while(next_marker)
- return albums
- }
- static async ApiAlbumGet(album_id: string): Promise {
- const userId = useUserStore().user_id
- const url = 'adrive/v1/album/get'
- const resp = await AliHttp.Post(url, {album_id}, userId, '')
- if (AliHttp.IsSuccess(resp.code)) {
- return resp.body as IAliAlubmListInfo
+ })
+ next_marker = resp.body.next_marker
} else {
- DebugLog.mSaveWarning('ApiAlbumsList err=' + (resp.code || ''))
+ next_marker = ''
}
- return undefined
+
+ } else {
+ next_marker = ''
+ break
+ }
+ if (albums.length >= max && max > 0) {
+ next_marker = ''
+ break
+ }
+ } while(next_marker)
+ return albums
+ }
+
+ static async ApiAlbumGet(album_id: string): Promise {
+ const userId = useUserStore().user_id
+ const url = 'adrive/v1/album/get'
+ const resp = await AliHttp.Post(url, {album_id}, userId, '')
+ if (AliHttp.IsSuccess(resp.code)) {
+ return resp.body as IAliAlubmListInfo
+ } else {
+ DebugLog.mSaveWarning('ApiAlbumsList err=' + (resp.code || ''))
+ }
+ return undefined
+ }
+
+ static async ApiTotalPhotosNum(): Promise {
+ const driver_id = GetDriveID(useUserStore().user_id, 'pic')
+ const userId = useUserStore().user_id
+ const url = 'adrive/v2/file/search'
+
+ if (!driver_id) {
+ return 0
+ }
+ const postData = {
+ "drive_id": driver_id,
+ "query": "type = \"file\"",
+ "limit": 1,
+ "return_total_count": true,
+ "marker":"",
+ }
+ const resp = await AliHttp.Post(url, postData, userId, '')
+ if (AliHttp.IsSuccess(resp.code)) {
+ return resp.body.total_count
+ }
+ return 0
+ }
+
+
+ static async ApiLimitedPhotos(marker="", limited=100): Promise {
+ const driver_id = GetDriveID(useUserStore().user_id, 'pic')
+ const userId = useUserStore().user_id
+ const url = 'adrive/v2/file/search'
+ let max: number = useSettingStore().debugFileListMax
+
+ const results:AliAlbumFileInfo[] = []
+ if (!driver_id) {
+ return results
}
- static async ApiTotalPhotosNum(): Promise {
- const driver_id = GetDriveID(useUserStore().user_id, 'pic')
- const userId = useUserStore().user_id
- const url = 'adrive/v1.0/openFile/search'
-
- if (!driver_id) {
- return 0
- }
- const postData = {
- "drive_id": driver_id,
- "query": "type = \"file\"",
- "limit": 1,
- "return_total_count": true,
- "marker":"",
- }
- const resp = await AliHttp.Post(url, postData, userId, '')
- if (AliHttp.IsSuccess(resp.code)) {
- return resp.body.total_count
- }
- return 0
+ const postData = {
+ "drive_id": driver_id,
+ "query": "type = \"file\"",
+ "image_thumbnail_process": "image/resize,w_400/format,jpeg",
+ "image_url_process": "image/resize,w_1920/format,jpeg",
+ "video_thumbnail_process": "video/snapshot,t_0,f_jpg,ar_auto,w_1000",
+ "limit": limited,
+ "marker":marker,
+ "order_by": "created_at DESC"
}
+ const resp = await AliHttp.Post(url, postData, userId, '')
+ if (AliHttp.IsSuccess(resp.code)) {
+ const items = resp.body.items as AliAlbumFileInfo[]
-
- static async ApiLimitedPhotos(marker="", limited=100): Promise {
- const driver_id = GetDriveID(useUserStore().user_id, 'pic')
- const userId = useUserStore().user_id
- const url = 'adrive/v1.0/openFile/search'
- let max: number = useSettingStore().debugFileListMax
-
- const results:AliAlbumFileInfo[] = []
- if (!driver_id) {
- return results
- }
-
- const postData = {
- "drive_id": driver_id,
- "query": "type = \"file\"",
- "image_thumbnail_process": "image/resize,w_400/format,jpeg",
- "image_url_process": "image/resize,w_1920/format,jpeg",
- "video_thumbnail_process": "video/snapshot,t_0,f_jpg,ar_auto,w_1000",
- "limit": limited,
- "marker":marker,
- "order_by": "created_at DESC"
- }
- const resp = await AliHttp.Post(url, postData, userId, '')
- if (AliHttp.IsSuccess(resp.code)) {
- const items = resp.body.items as AliAlbumFileInfo[]
-
- if (items) {
- items.forEach((item) => {
- item.next_marker = resp.body.next_marker
- })
- results.push(...items)
- return results
- }
- }
+ if (items) {
+ items.forEach((item) => {
+ item.next_marker = resp.body.next_marker
+ })
+ results.push(...items)
return results
+ }
+ }
+ return results
+ }
+
+
+ static async ApiAllPhotos(): Promise {
+ const driver_id = GetDriveID(useUserStore().user_id, 'pic')
+ const userId = useUserStore().user_id
+ const url = 'adrive/v1.0/openFile/search'
+ let marker = '';
+ let max: number = useSettingStore().debugFileListMax
+
+ const results:AliAlbumFileInfo[] = []
+ if (!driver_id) {
+ return results
}
-
- static async ApiAllPhotos(): Promise {
- const driver_id = GetDriveID(useUserStore().user_id, 'pic')
- const userId = useUserStore().user_id
- const url = 'adrive/v1.0/openFile/search'
- let marker = '';
- let max: number = useSettingStore().debugFileListMax
-
- const results:AliAlbumFileInfo[] = []
- if (!driver_id) {
- return results
- }
-
- do {
- const postData = {
- drive_id: driver_id,
- query: "type = \"file\"",
- image_thumbnail_process: "image/resize,w_400/format,jpeg",
- image_url_process: "image/resize,w_1920/format,jpeg",
- video_thumbnail_process: "video/snapshot,t_0,f_jpg,ar_auto,w_1000",
- marker:marker,
- order_by: "created_at DESC"
- }
- const resp = await AliHttp.Post(url, postData, userId, '')
- if (AliHttp.IsSuccess(resp.code)) {
- const items = resp.body.items as AliAlbumFileInfo[]
- if (items) {
- results.push(...items)
- marker = resp.body.next_marker
- } else {
- marker = ''
- }
- } else {
- marker = ''
- break
- }
- if (max > 0 && results.length >= max) {
- marker = ''
- break
- }
- } while (marker)
- return results
- }
-
- static async ApiAlbumListFiles(album_id: string, marker="", limited=100): Promise {
- const userId = useUserStore().user_id
- const url = 'adrive/v1/album/list_files'
- const postData = {
- album_id,
- image_thumbnail_process: "image/resize,w_400/format,jpeg",
- video_thumbnail_process: "video/snapshot,t_0,f_jpg,ar_auto,w_1000",
- image_url_process: "image/resize,w_1920/format,jpeg",
- limit: limited,
- marker:marker,
- order_direction: "DESC"
- }
- const results:AliAlbumFileInfo[] = []
- const driver_id = GetDriveID(useUserStore().user_id, 'pic')
- if (!driver_id) {
- return results
- }
- const resp = await AliHttp.Post(url, postData, userId, '')
- if (AliHttp.IsSuccess(resp.code)) {
- const items = resp.body.items as AliAlbumFileInfo[]
- if (items) {
- items.forEach((item) => {
- item.next_marker = resp.body.next_marker
- })
- results.push(...items)
- return results
- }
- }
- return results
- }
-
- static async ApiAlbumCreate(name: string, description: string): Promise<{ album_id: string; error: string }> {
- const userId = useUserStore().user_id
- const url = 'adrive/v1/album/create'
- const resp = await AliHttp.Post(url, {name, description}, userId, '')
- if (AliHttp.IsSuccess(resp.code)) {
- const item = resp.body as IAliAlubmCreateInfo
- return {album_id: item.album_id, error: ''}
+ do {
+ const postData = {
+ drive_id: driver_id,
+ query: "type = \"file\"",
+ image_thumbnail_process: "image/resize,w_400/format,jpeg",
+ image_url_process: "image/resize,w_1920/format,jpeg",
+ video_thumbnail_process: "video/snapshot,t_0,f_jpg,ar_auto,w_1000",
+ marker:marker,
+ order_by: "created_at DESC"
+ }
+ const resp = await AliHttp.Post(url, postData, userId, '')
+ if (AliHttp.IsSuccess(resp.code)) {
+ const items = resp.body.items as AliAlbumFileInfo[]
+ if (items) {
+ results.push(...items)
+ marker = resp.body.next_marker
} else {
- DebugLog.mSaveWarning('ApiAlbumCreate err=' + (resp.code || ''))
+ marker = ''
}
- return {album_id: '', error: resp.body?.code || '创建相册出错'}
- }
+ } else {
+ marker = ''
+ break
+ }
+ if (max > 0 && results.length >= max) {
+ marker = ''
+ break
+ }
+ } while (marker)
+ return results
+ }
- static async ApiAlbumUpdate(album_id:string, name: string, description: string): Promise {
- const userId = useUserStore().user_id
- // { "album_id": "cfe400000000478599575b69356c5a4962383669", "description": "ff", "name": "未命名" }
- const url = 'adrive/v1/album/update'
- return await AliHttp.Post(url, {name, album_id}, userId, '')
+ static async ApiAlbumListFiles(album_id: string, marker="", limited=100): Promise {
+ const userId = useUserStore().user_id
+ const url = 'adrive/v1/album/list_files'
+ const postData = {
+ album_id,
+ image_thumbnail_process: "image/resize,w_400/format,jpeg",
+ video_thumbnail_process: "video/snapshot,t_0,f_jpg,ar_auto,w_1000",
+ image_url_process: "image/resize,w_1920/format,jpeg",
+ limit: limited,
+ marker:marker,
+ order_direction: "DESC"
}
-
- static async ApiAlbumFilesDelete(album_id:string, file_list:string[]): Promise {
- const userId = useUserStore().user_id
- const drive_id = GetDriveID(userId, 'pic')
- const data:{drive_id:string, file_id:string}[] = []
- file_list.forEach((file_id) => {
- data.push({drive_id, file_id})
+ const results:AliAlbumFileInfo[] = []
+ const driver_id = GetDriveID(useUserStore().user_id, 'pic')
+ if (!driver_id) {
+ return results
+ }
+ const resp = await AliHttp.Post(url, postData, userId, '')
+ if (AliHttp.IsSuccess(resp.code)) {
+ const items = resp.body.items as AliAlbumFileInfo[]
+ if (items) {
+ items.forEach((item) => {
+ item.next_marker = resp.body.next_marker
})
- console.log("ApiAlbumFilesDelete data=", data, album_id)
- // { "album_id": "cfe400000000478599575b69356c5a4962383669", "drive_file_list": [{ "drive_id": "9600002", "file_id": "623b00000000d89ef21d4118838aed83de7575ba" }] }
- const url = 'adrive/v1/album/delete_files'
- return await AliHttp.Post(url, {album_id, "drive_file_list": data}, userId, '')
+ results.push(...items)
+ return results
+ }
}
+ return results
+ }
-
- static async ApiAlbumDelete(album_id:string): Promise {
- const userId = useUserStore().user_id
- const url = 'adrive/v1/album/delete'
- return await AliHttp.Post(url, {album_id}, userId, '')
+ static async ApiAlbumCreate_1(name: string, description: string): Promise<{ album_id: string; error: string }> {
+ const userId = useUserStore().user_id
+ const url = 'adrive/v1/album/create'
+ const resp = await AliHttp.Post(url, {name, description}, userId, '')
+ if (AliHttp.IsSuccess(resp.code)) {
+ const item = resp.body as IAliAlubmCreateInfo
+ return {album_id: item.album_id, error: ''}
+ } else {
+ DebugLog.mSaveWarning('ApiAlbumCreate err=' + (resp.code || ''))
}
+ return {album_id: '', error: resp.body?.code || '创建相册出错'}
+ }
- static async ApiAlbumAddExistPic(album_id:string, file_list:string[]): Promise {
- const userId = useUserStore().user_id
- const drive_id = GetDriveID(userId, 'pic')
- const data:{drive_id:string, file_id:string}[] = []
- file_list.forEach((file_id) => {
- data.push({drive_id, file_id})
- })
- const postData = {album_id, "drive_file_list": data}
- // { "album_id": "cfe400000000478599575b69356c5a4962383669", "drive_file_list": [{ "drive_id": "9600002", "file_id": "623b00000000d89ef21d4118838aed83de7575ba" }] }
- const url = 'adrive/v1/album/add_files'
- return await AliHttp.Post(url, postData, userId, '')
+ static async ApiAlbumUpdat_1(album_id:string, name: string, description: string): Promise {
+ const userId = useUserStore().user_id
+ // { "album_id": "cfe400000000478599575b69356c5a4962383669", "description": "ff", "name": "未命名" }
+ const url = 'adrive/v1/album/update'
+ return await AliHttp.Post(url, {name, album_id}, userId, '')
+ }
+
+ static async ApiAlbumFilesDelete(album_id:string, file_list:string[]): Promise {
+ const userId = useUserStore().user_id
+ const drive_id = GetDriveID(userId, 'pic')
+ const data:{drive_id:string, file_id:string}[] = []
+ file_list.forEach((file_id) => {
+ data.push({drive_id, file_id})
+ })
+ console.log("ApiAlbumFilesDelete data=", data, album_id)
+ // { "album_id": "cfe400000000478599575b69356c5a4962383669", "drive_file_list": [{ "drive_id": "9600002", "file_id": "623b00000000d89ef21d4118838aed83de7575ba" }] }
+ const url = 'adrive/v1/album/delete_files'
+ return await AliHttp.Post(url, {album_id, "drive_file_list": data}, userId, '')
+ }
+
+
+ static async ApiAlbumDelete_1(album_id:string): Promise {
+ const userId = useUserStore().user_id
+ const url = 'adrive/v1/album/delete'
+ return await AliHttp.Post(url, {album_id}, userId, '')
+ }
+
+ static async ApiAlbumAddExistPic(album_id:string, file_list:string[]): Promise {
+ const userId = useUserStore().user_id
+ const drive_id = GetDriveID(userId, 'pic')
+ const data:{drive_id:string, file_id:string}[] = []
+ file_list.forEach((file_id) => {
+ data.push({drive_id, file_id})
+ })
+ const postData = {album_id, "drive_file_list": data}
+ // { "album_id": "cfe400000000478599575b69356c5a4962383669", "drive_file_list": [{ "drive_id": "9600002", "file_id": "623b00000000d89ef21d4118838aed83de7575ba" }] }
+ const url = 'adrive/v1/album/add_files'
+ return await AliHttp.Post(url, postData, userId, '')
+ }
+
+ static async trashPhotos(file_ids: string[]): Promise {
+ const user_id = useUserStore().user_id
+ const drive_id = GetDriveID(user_id, 'pic')
+ // @ts-ignore
+ const requestData = []
+ file_ids.forEach((file_id) => {
+ requestData.push({
+ "body": {
+ "drive_id": drive_id,
+ "file_id": file_id
+ },
+ "headers": {
+ "Content-Type": "application/json"
+ },
+ "id": file_id,
+ "method": "POST",
+ "url": "/recyclebin/trash"
+ })
+ })
+ const url = 'v2/batch'
+ // @ts-ignore
+ const postData = { requests: requestData, resource: "file" }
+ const resp = await AliHttp.Post(url, postData, user_id, '')
+ if (AliHttp.IsSuccess(resp.code)) {
+ return true
+ } else {
+ DebugLog.mSaveWarning('UploadFileDelete err=' + (resp.code || ''))
+ return false
}
+ }
- static async trashPhotos(file_ids: string[]): Promise {
- const user_id = useUserStore().user_id
- const drive_id = GetDriveID(user_id, 'pic')
- // @ts-ignore
- const requestData = []
- file_ids.forEach((file_id) => {
- requestData.push({
- "body": {
- "drive_id": drive_id,
- "file_id": file_id
- },
- "headers": {
- "Content-Type": "application/json"
- },
- "id": file_id,
- "method": "POST",
- "url": "/recyclebin/trash"
- })
- })
- const url = 'v2/batch'
- // @ts-ignore
- const postData = { requests: requestData, resource: "file" }
- const resp = await AliHttp.Post(url, postData, user_id, '')
- if (AliHttp.IsSuccess(resp.code)) {
- return true
- } else {
- DebugLog.mSaveWarning('UploadFileDelete err=' + (resp.code || ''))
- return false
+ /**
+ * 创建相册
+ */
+ static async ApiAlbumCreate(user_id: string, album_name: string, album_description: string): Promise {
+ if (!user_id || !album_name) return '创建相册出错'
+ const url = 'adrive/v1/album/create'
+ const postData = { name: album_name, description: album_description }
+ const resp = await AliHttp.Post(url, postData, user_id, '')
+ if (AliHttp.IsSuccess(resp.code)) {
+ const result = resp.body as IAliAlbumInfo
+ if (result) return 'success'
+ else return '创建相册出错'
+ } else if (!AliHttp.HttpCodeBreak(resp.code)) {
+ DebugLog.mSaveWarning('ApiAlbumCreate err=' + (resp.code || ''))
+ }
+ return '创建相册出错'
+ }
+
+ /**
+ * 获取相册路径
+ */
+ static async ApiAlbumGetPath(user_id: string, drive_id: string, album_id: string): Promise {
+ if (!user_id || !drive_id || !album_id) return []
+ const url = 'adrive/v1/album/get'
+ const postData = { album_id: album_id }
+ const resp = await AliHttp.Post(url, postData, user_id, '')
+ if (AliHttp.IsSuccess(resp.code)) {
+ const list: IAliGetDirModel[] = []
+ list.push({
+ __v_skip: true,
+ drive_id: drive_id,
+ file_id: 'mypic',
+ parent_file_id: '',
+ name: '我的相册',
+ namesearch: '',
+ size: 0,
+ time: 0,
+ description: ''
+ } as IAliGetDirModel)
+ if (resp.body.name.length > 0) {
+ list.push({
+ __v_skip: true,
+ drive_id: drive_id,
+ file_id: resp.body.album_id,
+ album_id: resp.body.album_id,
+ parent_file_id: 'mypic',
+ name: resp.body.name,
+ namesearch: HanToPin(resp.body.name),
+ size: 0,
+ time: new Date(resp.body.updated_at).getTime(),
+ description: resp.body.description || ''
+ } as IAliGetDirModel)
+ }
+ return list
+ } else if (!AliHttp.HttpCodeBreak(resp.code)) {
+ DebugLog.mSaveWarning('ApiAlbumGetPath err=' + album_id + ' ' + (resp.code || ''), resp.body)
+ }
+ return []
+ }
+
+ /**
+ * 列出相册
+ */
+ static async ApiAlbumList(user_id: string, limit?: string, order_by?: string, order_direction?: string) {
+ if (!user_id) return []
+ const url = 'adrive/v1/album/list'
+ const postData = {
+ limit: limit || 20,
+ order_by: order_by || 'updated_at',
+ order_direction: order_direction || 'DESC'
+ }
+ const data: IAliAlbumInfo[] = []
+ const resp = await AliHttp.Post(url, postData, user_id, '')
+ if (AliHttp.IsSuccess(resp.code)) {
+ const items = resp.body.items
+ if (items && items.length > 0) {
+ for (let item of items) {
+ let coverUrl = ''
+ if (item.cover && item.cover.list.length > 0) {
+ coverUrl = item.cover.list[0].download_url || ''
+ }
+ data.push({ ...item, coverUrl })
}
+ }
+ return data
+ } else if (!AliHttp.HttpCodeBreak(resp.code)) {
+ DebugLog.mSaveWarning('ApiAlbumList err=' + (resp.code || ''))
}
-}
\ No newline at end of file
+ return []
+ }
+
+ /**
+ * 更新相册
+ */
+ static async ApiAlbumUpdate(user_id: string, album_id: string, name: string, description: string): Promise {
+ if (!user_id || !album_id) return undefined
+ const url = 'adrive/v1/album/update'
+ const postData = { name, album_id, description }
+ const resp = await AliHttp.Post(url, postData, user_id, '')
+ if (AliHttp.IsSuccess(resp.code)) {
+ return resp.body as IUrlRespData
+ } else if (!AliHttp.HttpCodeBreak(resp.code)) {
+ DebugLog.mSaveWarning('ApiAlbumUpdate err=' + (resp.code || ''))
+ }
+ return undefined
+ }
+
+ /**
+ * 删除相册(不会删除文件)
+ */
+ static async ApiAlbumDelete(user_id: string, album_id: string): Promise {
+ if (!user_id || !album_id) return undefined
+ const url = 'adrive/v1/album/delete'
+ const resp = await AliHttp.Post(url, { album_id }, user_id, '')
+ if (AliHttp.IsSuccess(resp.code)) {
+ return resp.body as IUrlRespData
+ } else if (!AliHttp.HttpCodeBreak(resp.code)) {
+ DebugLog.mSaveWarning('ApiAlbumDelete err=' + (resp.code || ''))
+ }
+ return undefined
+ }
+
+ /**
+ * 添加文件到相册
+ */
+ static async ApiAlbumAddFiles(user_id: string, album_id: string, drive_file_list: {
+ drive_id: string,
+ file_id: string
+ }[]): Promise {
+ if (!user_id || !album_id || !drive_file_list) return undefined
+ const url = 'adrive/v1/album/add_files'
+ const resp = await AliHttp.Post(url, { album_id, drive_file_list }, user_id, '')
+ if (AliHttp.IsSuccess(resp.code)) {
+ return resp.body as IUrlRespData
+ } else if (!AliHttp.HttpCodeBreak(resp.code)) {
+ DebugLog.mSaveWarning('ApiAlbumAddFiles err=' + (resp.code || ''))
+ }
+ return undefined
+ }
+
+ /**
+ * 文件移出相册(不会删除文件)
+ */
+ static async ApiAlbumDeleteFiles(user_id: string, album_id: string, drive_file_list: {
+ drive_id: string,
+ file_id: string
+ }[]): Promise {
+ if (!user_id || !album_id || !drive_file_list) return undefined
+ const url = 'adrive/v1/album/delete_files'
+ const resp = await AliHttp.Post(url, { album_id, drive_file_list }, user_id, '')
+ if (AliHttp.IsSuccess(resp.code)) {
+ return resp.body as IUrlRespData
+ } else if (!AliHttp.HttpCodeBreak(resp.code)) {
+ DebugLog.mSaveWarning('ApiAlbumDeleteFiles err=' + (resp.code || ''))
+ }
+ return undefined
+ }
+}
diff --git a/aliyunpan/src/aliapi/alihttp.ts b/aliyunpan/src/aliapi/alihttp.ts
index 15962ea867..15fbfe3063 100644
--- a/aliyunpan/src/aliapi/alihttp.ts
+++ b/aliyunpan/src/aliapi/alihttp.ts
@@ -19,7 +19,7 @@ function BlobToString(body: Blob, encoding: string): Promise {
return new Promise((resolve) => {
const reader = new FileReader()
reader.readAsText(body, encoding)
- reader.onload = function () {
+ reader.onload = function() {
resolve((reader.result as string) || '')
}
})
@@ -29,7 +29,7 @@ function BlobToBuff(body: Blob): Promise {
return new Promise((resolve) => {
const reader = new FileReader()
reader.readAsArrayBuffer(body)
- reader.onload = function () {
+ reader.onload = function() {
resolve(reader.result as ArrayBuffer)
}
})
@@ -50,8 +50,8 @@ function Sleep(msTime: number): Promise<{ success: true; time: number }> {
const IsDebugHttp = false
export default class AliHttp {
- static baseApi = 'https://api.aliyundrive.com/'
- static baseOpenApi = 'https://openapi.aliyundrive.com/'
+ static baseApi = 'https://api.alipan.com/'
+ static baseOpenApi = 'https://openapi.alipan.com/'
static IsSuccess(code: number): Boolean {
return code >= 200 && code <= 300
@@ -61,8 +61,7 @@ export default class AliHttp {
if (code >= 200 && code <= 300) return true
if (code == 400) return true
// if (code == 401) return true
- if (code >= 402 && code <= 428) return true
- if (code == 404) return true
+ if (code > 402 && code <= 428) return true
if (code == 409) return true
return false
}
@@ -72,15 +71,16 @@ export default class AliHttp {
if (IsDebugHttp) console.log('CALLURLError ', error)
const errorMessage = error.display_message || error.message || ''
if (error.response) {
- let { code, status, config, data = undefined, headers = undefined} = error.response
+ let { code, status, config, data = undefined, headers = undefined } = error.response
if (code == 'ERR_NETWORK' || (status == 0 && !headers)) {
DebugLog.mSaveWarning('HttpError0 message=' + errorMessage)
return { code: 600, header: '', body: 'NetError 网络无法连接' } as IUrlRespData
}
let isNeedLog = true
- if (status == 429) isNeedLog = false
+ if (status == 429 || status == 504 || status == 500) isNeedLog = false
if (data && data.code) {
let errCode = [
+ 'NotFound.File',
'InvalidParameter.Limit',
'ForbiddenFileInTheRecycleBin',
'PreHashMatched',
@@ -94,29 +94,26 @@ export default class AliHttp {
'UserDeviceOffline',
'DeviceSessionSignatureInvalid',
'AccessTokenInvalid',
- 'AccessTokenExpired',
- 'I400JD',
+ 'AccessTokenExpired'
]
if (errCode.includes(data.code)) isNeedLog = false
// 自动刷新Token
- if (data.code == 'AccessTokenInvalid'
- || data.code == 'AccessTokenExpired'
- || data.code == 'I400JD') {
+ if (data.code == 'AccessTokenInvalid' || data.code == 'AccessTokenExpired') {
if (token) {
- const isOpenApi = config.url.includes('adrive/v1.0')
+ const isOpenApi = config.url.includes('adrive/v1.0') || config.url.includes('adrive/v1.1')
if (!isOpenApi) {
- return await AliUser.ApiRefreshAccessTokenV1(token, true, true).then((isLogin: boolean) => {
+ return await AliUser.ApiTokenRefreshAccount(token, true, true).then((isLogin: boolean) => {
if (isLogin) {
return { code: 401, header: '', body: '' } as IUrlRespData
}
return { code: 403, header: '', body: 'NetError 账号需要重新登录' } as IUrlRespData
})
} else {
- return await AliUser.ApiRefreshAccessTokenV2(token, true, true).then((flag: boolean) => {
+ return await AliUser.OpenApiTokenRefreshAccount(token, true, true).then((flag: boolean) => {
if (flag) {
return { code: 401, header: '', body: '' } as IUrlRespData
}
- return { code: 403, header: '', body: '刷新OpenApiToken失败,请检查配置' } as IUrlRespData
+ return { code: 403, header: '', body: 'NetError 账号需要重新登录' } as IUrlRespData
})
}
} else {
@@ -126,10 +123,10 @@ export default class AliHttp {
// 自动刷新Session
if (data.code == 'UserDeviceIllegality'
- || data.code == 'UserDeviceOffline'
- || data.code == 'DeviceSessionSignatureInvalid') {
+ || data.code == 'UserDeviceOffline'
+ || data.code == 'DeviceSessionSignatureInvalid') {
if (token) {
- return await AliUser.ApiSessionRefreshAccount(token, true).then((flag: boolean) => {
+ return await AliUser.ApiSessionRefreshAccount(token, true, true).then((flag: boolean) => {
if (flag) {
return { code: 401, header: '', body: '' } as IUrlRespData
}
@@ -176,10 +173,16 @@ export default class AliHttp {
}
}
- static async Get(url: string, user_id: string): Promise {
- if (!url.startsWith('http') && !url.startsWith('https')) url = AliHttp.baseApi + url
+ static async Get(url: string, user_id: string, params?: any): Promise {
+ if (!url.startsWith('http') && !url.startsWith('https')) {
+ if (url.includes('adrive/v1.0') || url.includes('adrive/v1.1')) {
+ url = AliHttp.baseOpenApi + url
+ } else {
+ url = AliHttp.baseApi + url
+ }
+ }
for (let i = 0; i <= 5; i++) {
- const resp = await AliHttp._Get(url, user_id)
+ const resp = await AliHttp._Get(url, user_id, params)
if (AliHttp.HttpCodeBreak(resp.code)) return resp
else if (i == 5) return resp
else await Sleep(2000)
@@ -187,17 +190,26 @@ export default class AliHttp {
return { code: 607, header: '', body: 'NetError GetLost' }
}
- static _Get(url: string, user_id: string): Promise {
+ static _Get(url: string, user_id: string, params?: any): Promise {
return UserDAL.GetUserTokenFromDB(user_id).then((token) => {
const headers: any = {}
if (token) {
- headers['Authorization'] = token.token_type + ' ' + token.access_token
- headers['x-request-id'] = v4().toString()
- headers['x-device-id'] = token.device_id
- headers['x-signature'] = token.signature
+ let token_type = token.token_type
+ let access_token = token.access_token
+ let need_open_api = url.includes('openapi')
+ if (need_open_api && token.open_api_access_token) {
+ token_type = token.open_api_token_type || 'Bearer'
+ access_token = token.open_api_access_token
+ } else {
+ headers['x-device-id'] = token.device_id
+ headers['x-signature'] = token.signature
+ headers['x-request-id'] = v4().toString()
+ }
+ headers['Authorization'] = token_type + ' ' + access_token
}
return axios
.get(url, {
+ params: params,
withCredentials: false,
responseType: 'json',
timeout: 30000,
@@ -210,7 +222,7 @@ export default class AliHttp {
body: response.data
} as IUrlRespData
})
- .catch(function (err: any) {
+ .catch(function(err: any) {
return AliHttp.CatchError(err, token)
})
})
@@ -218,7 +230,13 @@ export default class AliHttp {
static async GetString(url: string, user_id: string, fileSize: number, maxSize: number): Promise {
- if (!url.startsWith('http') && !url.startsWith('https')) url = AliHttp.baseApi + url
+ if (!url.startsWith('http') && !url.startsWith('https')) {
+ if (url.includes('adrive/v1.0') || url.includes('adrive/v1.1')) {
+ url = AliHttp.baseOpenApi + url
+ } else {
+ url = AliHttp.baseApi + url
+ }
+ }
for (let i = 0; i <= 5; i++) {
const resp = await AliHttp._GetString(url, user_id, fileSize, maxSize)
if (AliHttp.HttpCodeBreak(resp.code)) return resp
@@ -232,14 +250,21 @@ export default class AliHttp {
return UserDAL.GetUserTokenFromDB(user_id).then((token) => {
const headers: any = {}
if (token) {
- headers['Authorization'] = token.token_type + ' ' + token.access_token
- headers['x-request-id'] = v4().toString()
- headers['x-device-id'] = token.device_id
- headers['x-signature'] = token.signature
- }
- if (maxSize > 0) {
- headers.Range = 'bytes=0-' + (Math.min(fileSize, maxSize) - 1).toString()
+ let token_type = token.token_type
+ let access_token = token.access_token
+ let need_open_api = url.includes('openapi')
+ if (need_open_api && token.open_api_access_token) {
+ token_type = token.open_api_token_type || 'Bearer'
+ access_token = token.open_api_access_token
+ } else {
+ headers['x-device-id'] = token.device_id
+ headers['x-signature'] = token.signature
+ headers['x-request-id'] = v4().toString()
+ }
+ headers['Authorization'] = token_type + ' ' + access_token
}
+ headers.Range = 'bytes=0-' + (Math.min(fileSize, maxSize) - 1).toString()
+
return axios
.get(url, {
withCredentials: false,
@@ -293,12 +318,13 @@ export default class AliHttp {
try {
resp.body = JSON.stringify(JSON.parse(resp.body), undefined, 2)
- } catch {}
+ } catch {
+ }
}
}
return resp
})
- .catch(function (err: any) {
+ .catch(function(err: any) {
return AliHttp.CatchError(err, token)
})
})
@@ -306,7 +332,13 @@ export default class AliHttp {
static async GetBlob(url: string, user_id: string): Promise {
- if (!url.startsWith('http') && !url.startsWith('https')) url = AliHttp.baseApi + url
+ if (!url.startsWith('http') && !url.startsWith('https')) {
+ if (url.includes('adrive/v1.0') || url.includes('adrive/v1.1')) {
+ url = AliHttp.baseOpenApi + url
+ } else {
+ url = AliHttp.baseApi + url
+ }
+ }
for (let i = 0; i <= 5; i++) {
const resp = await AliHttp._GetBlob(url, user_id)
if (AliHttp.HttpCodeBreak(resp.code)) return resp
@@ -320,10 +352,18 @@ export default class AliHttp {
return UserDAL.GetUserTokenFromDB(user_id).then((token) => {
const headers: any = {}
if (token) {
- headers['Authorization'] = token.token_type + ' ' + token.access_token
- headers['x-request-id'] = v4().toString()
- headers['x-device-id'] = token.device_id
- headers['x-signature'] = token.signature
+ let token_type = token.token_type
+ let access_token = token.access_token
+ let need_open_api = url.includes('openapi')
+ if (need_open_api && token.open_api_access_token) {
+ token_type = token.open_api_token_type || 'Bearer'
+ access_token = token.open_api_access_token
+ } else {
+ headers['x-device-id'] = token.device_id
+ headers['x-signature'] = token.signature
+ headers['x-request-id'] = v4().toString()
+ }
+ headers['Authorization'] = token_type + ' ' + access_token
}
return axios
.get(url, {
@@ -339,7 +379,7 @@ export default class AliHttp {
body: response.data
} as IUrlRespData
})
- .catch(function (err: any) {
+ .catch(function(err: any) {
return AliHttp.CatchError(err, token)
})
})
@@ -347,26 +387,65 @@ export default class AliHttp {
static async Post(url: string, postData: any, user_id: string, share_token: string): Promise {
if (!url.startsWith('http') && !url.startsWith('https')) {
- url = (url.includes('adrive/v1.0') ? AliHttp.baseOpenApi : AliHttp.baseApi) + url
+ if (url.includes('adrive/v1.0') || url.includes('adrive/v1.1')) {
+ url = AliHttp.baseOpenApi + url
+ } else {
+ url = AliHttp.baseApi + url
+ }
}
for (let i = 0; i <= 5; i++) {
const resp = await AliHttp._Post(url, postData, user_id, share_token)
+ if (resp.code == 429
+ && resp.body.display_message
+ && !url.includes('getDownloadUrl')
+ && !url.includes('get_download_url')) {
+ return resp
+ }
if (resp.code == 400 &&
- (url.includes('/file/search')
+ (url.includes('/file/search')
|| url.includes('/file/list')
|| url.includes('/file/walk')
- || url.includes('/file/scan'))
- && !resp.body?.code) await Sleep(2000)
- else if (AliHttp.HttpCodeBreak(resp.code)) return resp
+ || url.includes('/file/scan'))) {
+ await Sleep(2000)
+ } else if (AliHttp.HttpCodeBreak(resp.code)) return resp
else if (i == 5) return resp
else await Sleep(2000)
}
return { code: 608, header: '', body: 'NetError PostLost' } as IUrlRespData
}
- static async GetWithOutUserId(url: string): Promise {
- return axios
- .get(url)
+ private static _Post(url: string, postData: any, user_id: string, share_token: string): Promise {
+ return UserDAL.GetUserTokenFromDB(user_id).then((token) => {
+ const headers: any = {}
+ if (url.includes('aliyundrive') || url.includes('alipan')) {
+ headers['Content-Type'] = 'application/json'
+ }
+ if (token) {
+ let token_type = token.token_type
+ let access_token = token.access_token
+ let need_open_api = url.includes('openapi')
+ if (need_open_api && token.open_api_access_token) {
+ token_type = token.open_api_token_type || 'Bearer'
+ access_token = token.open_api_access_token
+ } else {
+ headers['x-device-id'] = token.device_id
+ headers['x-signature'] = token.signature
+ headers['x-request-id'] = v4().toString()
+ }
+ headers['Authorization'] = token_type + ' ' + access_token
+ }
+ if (share_token) {
+ headers['x-share-token'] = share_token
+ }
+ let timeout = 30000
+ if (url.includes('/batch')) timeout = 60000
+ return axios
+ .post(url, postData, {
+ withCredentials: false,
+ responseType: 'json',
+ timeout,
+ headers
+ })
.then((response: AxiosResponse) => {
return {
code: response.status,
@@ -374,9 +453,83 @@ export default class AliHttp {
body: response.data
} as IUrlRespData
})
- .catch(function (err: any) {
- return AliHttp.CatchError(err, undefined)
+ .catch(function(err: any) {
+ return AliHttp.CatchError(err, token)
})
+ })
+ }
+
+ static async PostString(url: string, postData: any, user_id: string, share_token: string): Promise {
+ if (!url.startsWith('http') && !url.startsWith('https')) {
+ if (url.includes('adrive/v1.0') || url.includes('adrive/v1.1')) {
+ url = AliHttp.baseOpenApi + url
+ } else {
+ url = AliHttp.baseApi + url
+ }
+ }
+ for (let i = 0; i <= 5; i++) {
+ const resp = await AliHttp._PostString(url, postData, user_id, share_token)
+ if (AliHttp.HttpCodeBreak(resp.code)) return resp
+ else if (i == 5) return resp
+ else await Sleep(2000)
+ }
+ return { code: 610, header: '', body: 'NetError PostStringLost' } as IUrlRespData
+ }
+
+ private static _PostString(url: string, postData: any, user_id: string, share_token: string): Promise {
+ const headers: any = {}
+ return UserDAL.GetUserTokenFromDB(user_id).then((token) => {
+ if (token) {
+ let token_type = token.token_type
+ let access_token = token.access_token
+ let need_open_api = url.includes('openapi')
+ if (need_open_api && token.open_api_access_token) {
+ token_type = token.open_api_token_type || 'Bearer'
+ access_token = token.open_api_access_token
+ } else {
+ headers['x-device-id'] = token.device_id
+ headers['x-signature'] = token.signature
+ headers['x-request-id'] = v4().toString()
+ }
+ headers['Authorization'] = token_type + ' ' + access_token
+ }
+ if (share_token) {
+ headers['x-share-token'] = share_token
+ }
+
+ return axios
+ .post(url, postData, {
+ withCredentials: false,
+ responseType: 'text',
+ timeout: 50000,
+ headers
+ })
+ .then((response: AxiosResponse) => {
+ return {
+ code: response.status,
+ header: JSON.stringify(response.headers),
+ body: response.data
+ } as IUrlRespData
+ })
+ .catch(function(err: any) {
+ return AliHttp.CatchError(err, token)
+ })
+ })
+ }
+
+ static async GetWithOutUserId(url: string): Promise {
+ return axios
+ .get(url)
+ .then((response: AxiosResponse) => {
+ return {
+ code: response.status,
+ header: JSON.stringify(response.headers),
+ body: response.data
+ } as IUrlRespData
+ })
+ .catch(function (err: any) {
+ return AliHttp.CatchError(err, undefined)
+ })
}
static async PostWithOutUserId(url: string, postData: any): Promise {
@@ -400,91 +553,4 @@ export default class AliHttp {
return AliHttp.CatchError(err, undefined)
})
}
-
- static _Post(url: string, postData: any, user_id: string, share_token: string): Promise {
- return UserDAL.GetUserTokenFromDB(user_id).then((token) => {
- const headers: any = {}
- if (url.includes('aliyundrive')) {
- headers['Content-Type'] = 'application/json'
- }
- if (token && url.startsWith(this.baseOpenApi)) {
- headers['Authorization'] = token.token_type + ' ' + token.access_token_v2
- headers['x-request-id'] = v4().toString()
- headers['x-device-id'] = token.device_id
- headers['x-signature'] = token.signature
- } else if (token) {
- headers['Authorization'] = token.token_type + ' ' + token.access_token
- headers['x-request-id'] = v4().toString()
- headers['x-device-id'] = token.device_id
- headers['x-signature'] = token.signature
- }
- if (share_token) {
- headers['x-share-token'] = share_token
- }
- if (url.includes('ali')) headers['content-type'] = 'application/json;charset-utf-8'
- let timeout = 30000
- if (url.includes('/batch')) timeout = 60000
- return axios
- .post(url, postData, {
- withCredentials: false,
- responseType: 'json',
- timeout,
- headers
- })
- .then((response: AxiosResponse) => {
- return {
- code: response.status,
- header: JSON.stringify(response.headers),
- body: response.data
- } as IUrlRespData
- })
- .catch(function (err: any) {
- return AliHttp.CatchError(err, token)
- })
- })
- }
-
- static async PostString(url: string, postData: any, user_id: string, share_token: string): Promise {
- if (!url.startsWith('http') && !url.startsWith('https')) url = AliHttp.baseApi + url
- for (let i = 0; i <= 5; i++) {
- const resp = await AliHttp._PostString(url, postData, user_id, share_token)
- if (AliHttp.HttpCodeBreak(resp.code)) return resp
- else if (i == 5) return resp
- else await Sleep(2000)
- }
- return { code: 610, header: '', body: 'NetError PostStringLost' } as IUrlRespData
- }
-
- private static _PostString(url: string, postData: any, user_id: string, share_token: string): Promise {
- const headers: any = {}
- return UserDAL.GetUserTokenFromDB(user_id).then((token) => {
- if (token) {
- headers['Authorization'] = token.token_type + ' ' + token.access_token
- headers['x-request-id'] = v4().toString()
- headers['x-device-id'] = token.device_id
- headers['x-signature'] = token.signature
- }
- if (share_token) {
- headers['x-share-token'] = share_token
- }
-
- return axios
- .post(url, postData, {
- withCredentials: false,
- responseType: 'text',
- timeout: 50000,
- headers
- })
- .then((response: AxiosResponse) => {
- return {
- code: response.status,
- header: JSON.stringify(response.headers),
- body: response.data
- } as IUrlRespData
- })
- .catch(function (err: any) {
- return AliHttp.CatchError(err, token)
- })
- })
- }
}
diff --git a/aliyunpan/src/aliapi/alimodels.ts b/aliyunpan/src/aliapi/alimodels.ts
index ea9d4fcb62..bb58ef42cd 100644
--- a/aliyunpan/src/aliapi/alimodels.ts
+++ b/aliyunpan/src/aliapi/alimodels.ts
@@ -5,6 +5,7 @@ export interface IAliFileVideoMeta {
duration?: string
fps?: string
}
+
export interface IAliFileAudioMeta {
bit_rate?: string
channel_layout?: string
@@ -14,6 +15,372 @@ export interface IAliFileAudioMeta {
sample_rate?: string
}
+export interface IAliAlbumInfo {
+ owner: string
+ name: string
+ description: string
+ coverUrl: string
+ album_id: string
+ file_count: number
+ image_count: number
+ video_count: number
+ created_at: number
+ updated_at: number,
+}
+
+export interface IAliFileItem {
+ drive_id: string
+ domain_id: string
+ description?: string
+ file_id: string
+ album_id?: string
+ compilation_id?: string
+ name: string
+ type: string
+ video_type?: string
+ content_type: string
+ created_at: string
+ updated_at: string
+ last_played_at?: string
+ gmt_cleaned?: string
+ gmt_deleted?: string
+ file_extension?: string
+ hidden: boolean
+ file_count?: number
+ image_count?: number
+ video_count?: number
+ size: number
+ starred: boolean
+ status: string
+ upload_id: string
+ parent_file_id: string
+ crc64_hash: string
+ content_hash: string
+ content_hash_name: string
+ download_url: string
+ url: string
+ category: string
+ encrypt_mode: string
+ punish_flag: number
+ from_share_id?: string
+ thumbnail?: string
+ mime_extension: string
+ mime_type: string
+ play_cursor: string
+ duration: string
+ video_media_metadata?: {
+ duration?: string | number
+ height?: number
+ width?: number
+ time?: string
+ video_media_video_stream?: IAliFileVideoMeta[] | IAliFileVideoMeta
+ video_media_audio_stream?: IAliFileAudioMeta[] | IAliFileAudioMeta
+ }
+
+ video_preview_metadata?: {
+ duration?: string | number
+ height?: number
+ width?: number
+ time?: string
+ audio_format?: string
+ bitrate?: string
+ frame_rate?: string
+ video_format?: string
+ template_list?: [{ template_id: string; status: string }]
+ audio_template_list?: [{ template_id: string; status: string }]
+ }
+
+ image_media_metadata?: {
+ height?: number
+ width?: number
+ time?: string
+ exif?: string
+ }
+
+ user_meta?: string
+}
+
+
+export interface IAliOtherFollowingModel {
+ avatar: string
+ description: string
+ is_following: boolean
+ nick_name: string
+ phone: string
+ user_id: string
+ follower_count: number
+}
+
+interface IAliMyFollowingMessageModel {
+ action: string
+ content: {
+ file_id_list: string[]
+ share: { popularity: number; popularity_emoji: string; popularity_str: string; share_id: string; share_pwd: string }
+ }
+ created: number
+ createdstr: string
+ creator: IAliOtherFollowingModel
+ creator_id: string
+ display_action: string
+ sequence_id: number
+}
+
+
+export interface IAliMyFollowingModel {
+ avatar: string
+ description: string
+ has_unread_message: boolean
+ is_following: boolean
+ latest_messages: IAliMyFollowingMessageModel[]
+ nick_name: string
+ phone: string
+ user_id: string
+ SearchName: string
+}
+
+export interface IAliShareBottleFish {
+ bottleId: string;
+ bottleName: string;
+ shareId: string;
+}
+
+export interface IAliShareItem {
+ created_at: string
+ creator: string
+ description: string
+ display_name: string
+ display_label: string
+ download_count: number
+ drive_id: string
+ expiration: string
+ expired: boolean
+ file_id: string
+ file_id_list: string[]
+ icon: string
+ first_file?: IAliFileItem
+ preview_count: number
+ save_count: number
+ share_id: string
+
+ share_msg: string
+ full_share_msg: string
+ share_name: string
+ share_policy: string
+ share_pwd: string
+ share_url: string
+ status: string
+ updated_at: string
+
+ is_share_saved: boolean
+ share_saved: string
+}
+
+export interface IAliShareRecentItem {
+ popularity: number;
+ browse_count: number;
+ share_id: string;
+ share_msg: string;
+ share_name: string;
+ share_url: string;
+ creator: string;
+ file_id_list: string[];
+ preview_count: number;
+ save_count: number;
+ status: string;
+ share_subtitle: string;
+ gmt_created: string;
+ gmt_modified: string;
+ is_public: boolean;
+ file_list: {
+ name: string;
+ type: string;
+ category: string;
+ parent_file_id: string;
+ drive_id: string;
+ file_id: string;
+ created_at: string;
+ updated_at: string;
+ trashed_at: string | null;
+ }[];
+ creator_name: string;
+ creator_uid: string;
+ file_count: number;
+ is_punished: boolean;
+ share_creator: {
+ userId: string;
+ avatar: string;
+ displayName: string;
+ };
+ popularity_str: string;
+ popularity_emoji: string;
+ full_share_msg: string;
+ share_title: string;
+ display_name: string;
+}
+
+export interface IAliShareBottleFishItem {
+ bottleId: string;
+ gmtCreate: number;
+ id: number;
+ name: string;
+ saved: boolean;
+ shareId: string;
+ gmt_created: string;
+ saved_msg: string;
+ share_name: string;
+ display_name: string;
+}
+
+export interface IAliShareAnonymous {
+ shareinfo: {
+ share_id: string
+ creator_id: string
+ creator_name: string
+ creator_phone: string
+ display_name: string
+ expiration: string
+ file_count: number
+ share_name: string
+ created_at: string
+ updated_at: string
+ vip: string
+ is_photo_collection: boolean
+ album_id: string
+ }
+ shareinfojson: string
+ error: string
+}
+
+
+export interface IAliShareFileItem {
+ drive_id: string
+ // domain_id: string
+ file_id: string
+ name: string
+ type: string
+ created_at: string
+ updated_at: string
+ // hidden: boolean
+ // starred: boolean
+ // status: string
+ parent_file_id: string
+ // encrypt_mode: string
+ // revision_id: string
+
+ file_extension?: string
+ mime_extension: string
+ mime_type: string
+ size: number
+ // content_hash: string
+ // content_hash_name: string
+ category: string
+ punish_flag: number
+
+
+ isDir: boolean
+ sizeStr: string
+ timeStr: string
+ icon: string
+}
+
+
+export interface IAliGetForderSizeModel {
+ size: number
+ folder_count: number
+ file_count: number
+ reach_limit?: boolean
+}
+
+
+export interface IAliGetDirModel {
+ __v_skip: true
+ drive_id: string
+ file_id: string
+ album_id?: string
+ album_type?: string
+ parent_file_id: string
+ name: string
+ namesearch: string
+ size: number
+ time: number
+ punish_flag?: number
+ description: string
+}
+
+
+export interface IAliGetFileModel {
+ __v_skip: true
+ drive_id: string
+ file_id: string
+ parent_file_id: string
+ name: string
+ namesearch: string
+ ext: string
+ mime_type: string
+ mime_extension: string
+ category: string
+ icon: string
+ file_count?: number
+ size: number
+ sizeStr: string
+ time: number
+ timeStr: string
+ starred: boolean
+ isDir: boolean
+ thumbnail: string
+ punish_flag?: number
+ from_share_id?: string
+ description: string
+ album_id?: string
+ compilation_id?: string
+ download_url?: string
+ media_width?: number
+ media_height?: number
+ media_duration?: string
+ media_play_cursor?: string
+ media_time?: string
+ user_meta?: string
+ duration?: number
+ play_cursor?: number
+ season_poster?:string
+ episode_name?:string
+ episode_poster?:string
+ season_num?:number
+ episode_num?:number
+ // tvSeason?:{
+ // "air_date": string,
+ // "episode_count": number,
+ // "id": number,
+ // "name": string,
+ // "overview": string,
+ // "poster_path": string,
+ // "season_number": number,
+ // "vote_average": number
+ // }[]
+ minfo?: {
+ cached?: boolean
+ adult: boolean
+ backdrop_path: string
+ id: number
+ title: string
+ name: string
+ original_language: string
+ original_title: string
+ origin_country?: string[]
+ overview: string
+ poster_path: string
+ media_type: string
+ genre_ids: number[]
+ popularity: string
+ release_date?: string
+ video?: boolean
+ first_air_date?: string
+ vote_average: number
+ vote_count: number
+ }
+ m3u8_total_file_nums?:number
+ m3u8_parent_file_name?:string
+}
export interface AliAlbumFileInfo {
album_name?:string
@@ -63,6 +430,7 @@ export interface AliAlbumFileInfo {
"next_marker"?: string
}
+
// [{"name": "cutecy", "friendly_name": "\u53ef\u53ef\u7231\u7231\n", "preview": ".DS_Store"}]
export interface IAliAlbumsList {
name:string
@@ -97,256 +465,3 @@ export interface IAliAlubmCreateInfo {
"created_at": number,
"updated_at": number,
}
-
-export interface IAliFileItem {
- trashed?: boolean
- drive_id: string
- domain_id: string
- description?: string
- file_id: string
- compilation_id?: string
- name: string
- type: string
- video_type?: string
- content_type: string
- created_at: string
- updated_at: string
- last_played_at?: string
- gmt_cleaned?: string
- gmt_deleted?: string
- file_extension?: string
- hidden: boolean
- user_tags?: {
- video_watch_progress?: string | number
- }
- labels?:[string]
- size: number
- starred: boolean
- status: string
- upload_id: string
- parent_file_id: string
- crc64_hash: string
- content_hash: string
- content_hash_name: string
- download_url: string
- url: string
- category: string
- encrypt_mode: string
- punish_flag: number
- thumbnail?: string
- mime_extension: string
- mime_type: string
- play_cursor?: number
- video_media_metadata?: {
- duration?: string | number
- height?: number
- width?: number
- time?: string
- video_media_video_stream?: IAliFileVideoMeta[] | IAliFileVideoMeta
- video_media_audio_stream?: IAliFileAudioMeta[] | IAliFileAudioMeta
- }
-
- video_preview_metadata?: {
- duration?: string | number
- height?: number
- width?: number
- time?: string
- audio_format?: string
- bitrate?: string
- frame_rate?: string
- video_format?: string
- template_list?: [{ template_id: string; status: string }]
- audio_template_list?: [{ template_id: string; status: string }]
- }
-
- image_media_metadata?: {
- height?: number
- width?: number
- time?: string
- exif?: string
- }
- cover_type?: string
- cover_url?: string
- grand_parent_file_id?: string
- user_meta?: string
- meta?: string
- location?: string
- deleted?: boolean
- channel?: string
- revision_id?: string
- local_created_at?: string
- local_modified_at?: string
- trashed_at?: string
-}
-
-
-export interface IAliOtherFollowingModel {
- avatar: string
- description: string
- is_following: boolean
- nick_name: string
- phone: string
- user_id: string
- follower_count: number
-}
-
-interface IAliMyFollowingMessageModel {
- action: string
- content: {
- file_id_list: string[]
- share: { popularity: number; popularity_emoji: string; popularity_str: string; share_id: string; share_pwd: string }
- }
- created: number
- createdstr: string
- creator: IAliOtherFollowingModel
- creator_id: string
- display_action: string
- sequence_id: number
-}
-
-
-export interface IAliMyFollowingModel {
- avatar: string
- description: string
- has_unread_message: boolean
- is_following: boolean
- latest_messages: IAliMyFollowingMessageModel[]
- nick_name: string
- phone: string
- user_id: string
- SearchName: string
-}
-
-
-export interface IAliShareItem {
- created_at: string
- creator: string
- description: string
- display_name: string
- display_label: string
- download_count: number
- drive_id: string
- expiration: string
- expired: boolean
- file_id: string
- file_id_list: string[]
- icon: string
- first_file?: IAliFileItem
- preview_count: number
- save_count: number
- share_id: string
-
- share_msg: string
- full_share_msg: string
- share_name: string
- share_policy: string
- share_pwd: string
- share_url: string
- status: string
- updated_at: string
-
- is_share_saved: boolean
- share_saved: string
-}
-
-export interface IAliShareAnonymous {
- shareinfo: {
- share_id: string
- creator_id: string
- creator_name: string
- creator_phone: string
- display_name: string
- expiration: string
- file_count: number
- share_name: string
- created_at: string
- updated_at: string
- vip: string
- is_photo_collection: boolean
- album_id: string
- }
- shareinfojson: string
- error: string
-}
-
-
-export interface IAliShareFileItem {
- drive_id: string
- // domain_id: string
- file_id: string
- name: string
- type: string
- // created_at: string
- // updated_at: string
- // hidden: boolean
- // starred: boolean
- // status: string
- parent_file_id: string
- // encrypt_mode: string
- // revision_id: string
-
- file_extension?: string
- mime_extension: string
- mime_type: string
- size: number
- // content_hash: string
- // content_hash_name: string
- category: string
- punish_flag: number
-
-
- isDir: boolean
- sizeStr: string
- icon: string
-}
-
-
-export interface IAliGetForderSizeModel {
- size: number
- folder_count: number
- file_count: number
- reach_limit?: boolean
-}
-
-
-export interface IAliGetDirModel {
- __v_skip: true
- drive_id: string
- file_id: string
- parent_file_id: string
- name: string
- namesearch: string
- size: number
- time: number
-
- description: string
-}
-
-
-export interface IAliGetFileModel {
- __v_skip: true
- drive_id: string
- file_id: string
- parent_file_id: string
- name: string
- namesearch: string
- ext: string
- category: string
- icon: string
- size: number
- sizeStr: string
- time: number
- timeStr: string
- starred: boolean
- isDir: boolean
- thumbnail: string
- description: string
- compilation_id?: string
- download_url?: string
- media_width?: number
- media_height?: number
- media_duration?: string
- media_time?: string
- m3u8_total_file_nums?:number
- m3u8_parent_file_name?:string
-}
diff --git a/aliyunpan/src/aliapi/archive.ts b/aliyunpan/src/aliapi/archive.ts
index c5cea7d890..21835a3bc0 100644
--- a/aliyunpan/src/aliapi/archive.ts
+++ b/aliyunpan/src/aliapi/archive.ts
@@ -139,6 +139,7 @@ export default class AliArchive {
static async ApiArchiveUncompress(user_id: string, drive_id: string, file_id: string, domain_id: string, archive_type: string, target_drive_id: string, target_file_id: string, password: string, file_list: string[]): Promise {
if (!user_id || !drive_id || !file_id || !target_drive_id || !target_file_id) return undefined
+ if (target_file_id.includes('root')) target_file_id = 'root'
const url = 'v2/archive/uncompress'
const postData: {
drive_id: string
diff --git a/aliyunpan/src/aliapi/dirfilelist.ts b/aliyunpan/src/aliapi/dirfilelist.ts
index aa7a839be8..00dbd78525 100644
--- a/aliyunpan/src/aliapi/dirfilelist.ts
+++ b/aliyunpan/src/aliapi/dirfilelist.ts
@@ -1,4 +1,4 @@
-import { usePanFileStore, useResPanFileStore, useSettingStore } from '../store'
+import { usePanFileStore, useServerStore, useSettingStore } from '../store'
import TreeStore from '../store/treestore'
import DebugLog from '../utils/debuglog'
import { OrderDir, OrderFile } from '../utils/filenameorder'
@@ -8,19 +8,24 @@ import { HanToPin, MapValueToArray } from '../utils/utils'
import AliHttp, { IUrlRespData } from './alihttp'
import { IAliFileItem, IAliGetFileModel } from './alimodels'
import getFileIcon from './fileicon'
+import { DecodeEncName, GetDriveID } from './utils'
+import DB from '../utils/db'
+import Config from '../config'
+
export interface IAliFileResp {
items: IAliGetFileModel[]
itemsKey: Set
punished_file_count: number
-
+
next_marker: string
- m_user_id: string
- m_drive_id: string
- dirID: string
- dirName: string
- itemsTotal?: number
+ m_user_id: string
+ m_drive_id: string
+ dirID: string
+ albumID?: string
+ dirName: string
+ itemsTotal?: number
}
export function NewIAliFileResp(user_id: string, drive_id: string, dirID: string, dirName: string): IAliFileResp {
@@ -39,94 +44,96 @@ export function NewIAliFileResp(user_id: string, drive_id: string, dirID: string
}
export default class AliDirFileList {
-
- static LimitMax = 100
- static ItemJsonmask = 'category%2Ccreated_at%2Cdomain_id%2Cdrive_id%2Cfile_extension%2Cfile_id%2Chidden%2Cmime_extension%2Cmime_type%2Cname%2Cparent_file_id%2Cpunish_flag%2Csize%2Cstarred%2Ctype%2Cupdated_at%2Cdescription'
-
- static getFileInfo(item: IAliFileItem, downUrl: string): IAliGetFileModel {
+ static ItemJsonmask = 'category%2Ccreated_at%2Cdrive_id%2Cfile_extension%2Cfile_id%2Chidden%2Cmime_extension%2Cmime_type%2Cname%2Cparent_file_id%2Cpunish_flag%2Csize%2Cstarred%2Ctype%2Cupdated_at%2Cdescription%2Cfrom_share_id'
+
+ static getFileInfo(user_id: string, item: IAliFileItem, downUrl: string): IAliGetFileModel {
const size = item.size ? item.size : 0
- const date = new Date(item.updated_at || item.gmt_deleted || item.last_played_at || '')
- const y = date.getFullYear().toString()
- let m: number | string = date.getMonth() + 1
- m = m < 10 ? '0' + m.toString() : m.toString()
- let d: number | string = date.getDate()
- d = d < 10 ? '0' + d.toString() : d.toString()
- let h: number | string = date.getHours()
- h = h < 10 ? '0' + h.toString() : h.toString()
- let minute: number | string = date.getMinutes()
- minute = minute < 10 ? '0' + minute.toString() : minute.toString()
- let second: number | string = date.getSeconds()
- second = second < 10 ? '0' + second.toString() : second.toString()
-
+ const file_count = item.file_count || item.image_count || item.video_count || 0
+ const time = new Date(item.updated_at || item.created_at || item.gmt_deleted || item.last_played_at || '')
+ const timeStr = humanDateTimeDateStr(item.updated_at || item.created_at || item.gmt_deleted || item.last_played_at || '')
const isDir = item.type == 'folder'
-
+ const { name, mine_type, ext } = DecodeEncName(user_id, item)
const add: IAliGetFileModel = {
__v_skip: true,
drive_id: item.drive_id,
file_id: item.file_id,
parent_file_id: item.parent_file_id || '',
- name: item.name,
- namesearch: HanToPin(item.name),
- ext: item.file_extension?.toLowerCase() || '',
+ name: name,
+ namesearch: HanToPin(name),
+ ext: ext || '',
+ mime_type: mine_type || '',
+ mime_extension: item.mime_extension,
category: item.category || '',
starred: item.starred || false,
- time: date.getTime() ,
+ time: time.getTime(),
+ file_count: file_count,
size: size,
sizeStr: humanSize(size),
- timeStr: y + '-' + m + '-' + d + ' ' + h + ':' + minute + ':' + second ,
+ timeStr: timeStr,
icon: 'iconfile-folder',
isDir: isDir,
thumbnail: '',
- description: item.description || ''
+ from_share_id: item.from_share_id,
+ punish_flag: item.punish_flag,
+ description: item.description || '',
+ user_meta: item.user_meta || ''
}
if (!isDir) {
- const icon = getFileIcon(add.category, add.ext, item.mime_extension, item.mime_type, add.size)
+ const icon = getFileIcon(add.category, add.ext, add.ext || item.mime_extension, add.mime_type, add.size)
add.category = icon[0]
add.icon = icon[1]
+
if (downUrl) {
if (downUrl == 'download_url') {
add.download_url = item.download_url || ''
} else if (add.category == 'image') {
- add.thumbnail = item?.thumbnail || ''
- // add.thumbnail = downUrl + '&drive_id=' + add.drive_id + '&file_id=' + add.file_id + '&image_thumbnail_process=image%2Fresize%2Cl_260%2Fformat%2Cjpg%2Fauto-orient%2C1'
+ add.thumbnail = downUrl + '&drive_id=' + add.drive_id + '&file_id=' + add.file_id + '&image_thumbnail_process=image%2Fresize%2Cl_260%2Fformat%2Cjpg%2Fauto-orient%2C1'
} else if (add.category == 'image2') {
- add.thumbnail = item?.thumbnail || ''
- // add.thumbnail = downUrl + '&drive_id=' + add.drive_id + '&file_id=' + add.file_id
+ add.thumbnail = downUrl + '&drive_id=' + add.drive_id + '&file_id=' + add.file_id
} else if (add.category.startsWith('video')) {
- add.thumbnail = item?.thumbnail || ''
- // add.thumbnail = downUrl + '&drive_id=' + add.drive_id + '&file_id=' + add.file_id + '&video_thumbnail_process=video%2Fsnapshot%2Ct_106000%2Cf_jpg%2Car_auto%2Cw_260%2Cm_fast'
+ add.thumbnail = downUrl + '&drive_id=' + add.drive_id + '&file_id=' + add.file_id + '&video_thumbnail_process=video%2Fsnapshot%2Ct_106000%2Cf_jpg%2Car_auto%2Cm_fast'
} else if (add.category == 'doc' || add.category == 'doc2') {
- add.thumbnail = item?.thumbnail || ''
- // if (add.ext != 'txt' && add.ext != 'epub' && add.ext != 'azw' && add.ext != 'azw3') {
- // add.thumbnail = downUrl + '&drive_id=' + add.drive_id + '&file_id=' + add.file_id + '&office_thumbnail_process=image%2Fresize%2Cl_260%2Fformat%2Cjpg%2Fauto-orient%2C1'
- // }
+ if (add.ext != 'txt' && add.ext != 'epub' && add.ext != 'azw' && add.ext != 'azw3') {
+ add.thumbnail = downUrl + '&drive_id=' + add.drive_id + '&file_id=' + add.file_id + '&office_thumbnail_process=image%2Fresize%2Cl_260%2Fformat%2Cjpg%2Fauto-orient%2C1'
+ }
}
}
- if (item.video_media_metadata) {
+ if (item.video_media_metadata && Object.keys(item.video_media_metadata).length > 0) {
add.media_width = item.video_media_metadata.width || 0
add.media_height = item.video_media_metadata.height || 0
add.media_time = humanDateTimeDateStr(item.video_media_metadata.time)
add.media_duration = humanTime(item.video_media_metadata.duration)
- } else if (item.video_preview_metadata) {
+ } else if (item.video_preview_metadata && Object.keys(item.video_preview_metadata).length > 0) {
add.media_width = item.video_preview_metadata.width || 0
add.media_height = item.video_preview_metadata.height || 0
- add.media_time = humanDateTimeDateStr(item.video_preview_metadata.time)
add.media_duration = humanTime(item.video_preview_metadata.duration)
- } else if (item.image_media_metadata) {
+ } else if (item.image_media_metadata && Object.keys(item.image_media_metadata).length > 0) {
add.media_width = item.image_media_metadata.width || 0
add.media_height = item.image_media_metadata.height || 0
add.media_time = humanDateTimeDateStr(item.image_media_metadata.time)
}
+ if (item.play_cursor) {
+ add.media_play_cursor = humanTime(item.play_cursor)
+ } else if (item.user_meta) {
+ const meta = JSON.parse(item.user_meta)
+ if (meta.play_cursor) {
+ add.media_play_cursor = humanTime(meta.play_cursor)
+ }
+ }
+ if (!add.media_duration && item.duration) {
+ add.media_duration = humanTime(item.duration)
+ }
}
+ // 完全违规和部分违规
if (item.punish_flag == 2) add.icon = 'iconweifa'
- else if (item.punish_flag > 0) add.icon = 'iconweixiang'
-
+ else if (item.punish_flag == 103) add.icon = 'iconpartweifa'
+ else if (item.punish_flag > 0) add.icon = 'iconweixiang'
return add
}
-
- static async ApiDirFileList(user_id: string, drive_id: string, dirID: string, dirName: string, order: string, type: string = '', openApi = false): Promise {
+
+ static async ApiDirFileList(user_id: string, drive_id: string, dirID: string, dirName: string, order: string, type: string = '', albumID?: string, refresh: boolean = true, openApi = false, search = true): Promise {
const dir: IAliFileResp = {
items: [],
itemsKey: new Set(),
@@ -135,23 +142,24 @@ export default class AliDirFileList {
m_user_id: user_id,
m_drive_id: drive_id,
dirID: dirID,
- dirName: dirName
+ dirName: dirName,
+ albumID: albumID
}
if (!user_id || !drive_id || !dirID) return dir
-
if (!order) order = 'updated_at asc'
+ if (dirID.includes('video')) order = 'updated_at desc'
order = order.replace(' desc', ' DESC').replace(' asc', ' ASC')
const orders = order.split(' ')
let pageIndex = 0
- // if (dirID == 'video') {
- // await AliDirFileList._ApiVideoListRecent(orders[0], orders[1], dir, pageIndex)
- // pageIndex++
- // }
let max: number = useSettingStore().debugFileListMax
- if (dirID == 'favorite' || dirID.startsWith('color') || dirID.startsWith('search') || dirID.startsWith('video')) max = useSettingStore().debugFavorListMax
+ if (dirID == 'favorite' || dirID.startsWith('color')
+ || dirID.startsWith('search') || dirID == 'trash'
+ || dirID.startsWith('video') || dirID == 'recover') {
+ max = useSettingStore().debugFavorListMax
+ }
let needTotal
do {
@@ -165,8 +173,7 @@ export default class AliDirFileList {
isGet = await AliDirFileList._ApiFavorFileListOnePage(orders[0], orders[1], dir, pageIndex)
} else if (dirID == 'trash') {
isGet = await AliDirFileList._ApiTrashFileListOnePage(orders[0], orders[1], dir, pageIndex)
- }
- else if (dirID == 'recover') {
+ } else if (dirID == 'recover') {
isGet = await AliDirFileList._ApiDeleteedFileListOnePage(orders[0], orders[1], dir, pageIndex)
} else if (dirID.startsWith('color')) {
if (!needTotal) {
@@ -182,60 +189,249 @@ export default class AliDirFileList {
})
}
isGet = await AliDirFileList._ApiSearchFileListOnePage(orders[0], orders[1], dir, pageIndex)
- } else if (dirID === 'video') {
- isGet = await AliDirFileList._ApiVideoListOnePage(orders[0], orders[1], dir, pageIndex)
+ } else if (dirID == 'video') {
+ isGet = await AliDirFileList._ApiVideoListRecent(orders[0], orders[1], dir, pageIndex)
} else if (dirID === 'video.recentplay') {
isGet = await AliDirFileList._ApiVideoListRecent(orders[0], orders[1], dir, pageIndex)
} else if (dirID === 'video.compilation') {
isGet = await AliDirFileList._ApiVideoListOnePage(orders[0], orders[1], dir, pageIndex)
- } else if (dirID.startsWith('video')) {
- isGet = await AliDirFileList._ApiVideoFileListOnePage(orders[0], orders[1], dir, pageIndex)
+ } else if (albumID && albumID.length > 0) {
+ isGet = await AliDirFileList._ApiAlbumListFilesOnePage(orders[0], orders[1], dir, pageIndex)
+ dir.itemsTotal = dir.items.length
+ } else if (dirID === 'mypic') {
+ isGet = await AliDirFileList._ApiAlbumListOnePage(orders[0], orders[1], dir, pageIndex)
} else {
if (!needTotal) {
- needTotal = AliDirFileList._ApiDirFileListCount(dir, type).then((total) => {
+ needTotal = AliDirFileList._ApiDirFileListCount(dir, dirID, type).then((total) => {
dir.itemsTotal = total
})
}
- if (openApi) {
- isGet = await AliDirFileList._ApiDirFileListOnePageOpenApi(orders[0], orders[1], dir, type, pageIndex)
+ if (openApi || useSettingStore().uiFileListMode === 'movie') {
+ isGet = await AliDirFileList._ApiDirFileListOnePageOpenApi(orders[0], orders[1], dir, type, pageIndex, search)
} else {
isGet = await AliDirFileList._ApiDirFileListOnePage(orders[0], orders[1], dir, type, pageIndex)
}
-
}
if (!isGet) {
if (needTotal) dir.itemsTotal = -1
- break
+ break
}
if (dir.next_marker == 'cancel') {
if (needTotal) dir.itemsTotal = -1
- break
+ break
}
if (dir.items.length >= max && max > 0) {
- dir.next_marker = ''
+ dir.next_marker = ''
break
}
pageIndex++
} while (dir.next_marker)
+ for (const fileItem of dir.items) {
+ const videoInfo = await DB.getVideoInfo(fileItem.file_id)
+ if (videoInfo) {
+ fileItem.duration = videoInfo.duration
+ fileItem.play_cursor = videoInfo.play_cursor
+ }
+ }
+
if (needTotal) await needTotal
+ if (useSettingStore().uiFileListMode === 'movie' && search) {
+ await this.searchTMDB(dir)
+ }
+
return dir
}
+ static seasonNumber(name: string): string {
+ const match = name.match(/(?:[sS](\d+)[ -]?[eE](\d+))|(?:[sS](\d+))|(?:[sS][eE](\d+))/)
+ if (match) {
+ return match[1] || match[3] || match[4] || "1";
+ } else {
+ const additionalMatch = name.match(/\s*(\d+)\s*第\s*\d+\s*集/);
+ if (additionalMatch) {
+ return additionalMatch[1] || "1";
+ }
+ }
+ return "1";
+ }
+
+ static episodeNumber(name: string) :string {
+ let match = name.match(/(?:[sS](\d+)[ -]?[eE](\d+))|(?:[sS](\d+))/)
+ if (match && match[2]) {
+ return match[2]
+ } else {
+ match = name.match(/[-\s]([0-9]+)[\s.\]]/)
+ if (match) {
+ return match[1] || "-1"
+ } else {
+ match = name.match(/第\s*(\d+)\s*集/)
+ if (match) {
+ return match[1] || "-1";
+ } else {
+ match = name.match(/(?:[sS][eE]?(\d+)[\.-](\d+))/)
+ if (match && match[2]) {
+ return match[2];
+ }
+ }
+ }
+ return "-1"
+ }
+ }
+
+ static async searchTMDB(dir: IAliFileResp): Promise {
+ const regex = /(?:s|S)(\d+)(?:(?:e|E)(\d+))?|(\d{4})|(\d{3,4}p)|([sS][eE]\d+)|(\d{4})|(\d{3,4}p)|([sS][eE]\d+)|(\d+)\s*第\s*(\d+)集/g;
+
+ for (const fileItem of dir.items) {
+ // const videoInfo = await DB.getVideoInfo(fileItem.file_id)
+ // if (videoInfo) {
+ // fileItem.duration = videoInfo.duration
+ // fileItem.play_cursor = videoInfo.play_cursor
+ // }
+ const tmdb_cache = await DB.getValueString(fileItem.file_id)
+ if (tmdb_cache) {
+ const media_type = tmdb_cache.split(",")[0]
+ const tmdb_id = tmdb_cache.split(",")[1]
+ if (media_type === 'tv') {
+ const cacheData = await DB.getValueString(fileItem.file_id + "movieinfo")
+ if (cacheData) {
+ // @ts-ignore
+ fileItem.minfo = cacheData
+ if (fileItem.minfo) {
+ fileItem.minfo.cached = true
+ fileItem.minfo.media_type = 'tv'
+ }
+ } else {
+ const urlTv = `${Config.tmdbProxyUrl}/3/tv/${tmdb_id}?api_key=87d8eb3d0895eaf37c2929fd5d9f7cce&language=zh-CN`
+ const resp = await AliHttp.GetWithOutUserId(urlTv)
+ if (AliHttp.IsSuccess(resp.code)) {
+ fileItem.minfo = resp.body
+ await DB.saveValueString(fileItem.file_id+"movieinfo", resp.body)
+ if (fileItem.minfo) {
+ fileItem.minfo.cached = true
+ fileItem.minfo.media_type = 'tv'
+ }
+ }
+ }
+
+ } else if (media_type === 'movie') {
+ const cacheData = await DB.getValueString(fileItem.file_id+"movieinfo")
+ if (cacheData) {
+ // @ts-ignore
+ fileItem.minfo = cacheData
+ if (fileItem.minfo) {
+ fileItem.minfo.cached = true
+ fileItem.minfo.media_type = 'movie'
+ }
+ } else {
+ const url = `${Config.tmdbProxyUrl}/3/movie/${tmdb_id}?api_key=87d8eb3d0895eaf37c2929fd5d9f7cce&language=zh-CN`
+ const resp = await AliHttp.GetWithOutUserId(url)
+ if (AliHttp.IsSuccess(resp.code)) {
+ fileItem.minfo = resp.body
+ await DB.saveValueString(fileItem.file_id+"movieinfo", resp.body)
+ if (fileItem.minfo) {
+ fileItem.minfo.cached = true
+ fileItem.minfo.media_type = 'movie'
+ }
+ }
+ }
+ }
+ }
+
+ if (!fileItem.minfo) {
+ const cacheData = await DB.getValueString(fileItem.file_id+"movieinfo")
+ if (cacheData) {
+ // @ts-ignore
+ fileItem.minfo = cacheData
+ } else {
+ const parts = fileItem.name.split(regex)
+ const searchName = parts[0].replaceAll('.', ' ').replace(/\[.*?\]/g, '').replaceAll('&', ' ').trimEnd()
+ if (searchName.toLowerCase() == '4k'
+ || searchName == '字幕' || searchName == 'test'
+ || searchName.toLowerCase().includes('season')) continue
+ const url = `${Config.tmdbProxyUrl}/3/search/multi?api_key=87d8eb3d0895eaf37c2929fd5d9f7cce&language=zh-CN&query=${searchName}&page=1&include_adult=false`
+ const resp = await AliHttp.GetWithOutUserId(url);
+ if (AliHttp.IsSuccess(resp.code) && resp.body.results && resp.body.results.length > 0) {
+ fileItem.minfo = resp.body.results[0]
+ if (fileItem.minfo) {
+ await DB.saveValueString(fileItem.file_id+"movieinfo", resp.body.results[0])
+ }
+ }
+ }
+ }
+
+ if (fileItem.minfo && fileItem.minfo.media_type === 'tv') {
+ const seasonNum = this.seasonNumber(fileItem.name)
+ const episodeNum = this.episodeNumber(fileItem.name)
+ fileItem.season_num = Number(seasonNum)
+ fileItem.episode_num = Number(episodeNum)
+ // if (Number(seasonNum) != -1) {
+ // if (Number(episodeNum) != -1) {
+ // const season_poster = await DB.getValueString(fileItem.file_id+"season_poster")
+ // const episode_name = await DB.getValueString(fileItem.file_id+"episode_name")
+ // if (season_poster && episode_name) {
+ // fileItem.season_poster = season_poster
+ // fileItem.episode_name = episode_name
+ // } else {
+ // const urlSeason = `${Config.tmdbProxyUrl}/3/tv/${fileItem.minfo.id}/season/${fileItem.season_num}?api_key=87d8eb3d0895eaf37c2929fd5d9f7cce&language=zh-CN`
+ // const resp = await AliHttp.GetWithOutUserId(urlSeason)
+ // if (AliHttp.IsSuccess(resp.code)) {
+ // fileItem.season_poster = resp.body.poster_path
+ // // fileItem.season_poster = resp.body.episodes.filter(episode => episode.episode_number === fileItem.episode_num)[0].still_path
+ // // @ts-ignore
+ // const episodeRes = resp.body.episodes.filter(episode => episode.episode_number === fileItem.episode_num)
+ // if (episodeRes.length > 0) {
+ // fileItem.episode_name = episodeRes[0].name
+ // }
+ // if ( fileItem.season_poster) {
+ // await DB.saveValueString(fileItem.file_id+"season_poster", fileItem.season_poster)
+ // }
+ // if (fileItem.episode_name) {
+ // await DB.saveValueString(fileItem.file_id+"episode_name", fileItem.episode_name)
+ // }
+ // }
+ // }
+ // } else {
+ // const season_poster = await DB.getValueString(fileItem.file_id+"season_poster")
+ // if (season_poster) {
+ // fileItem.season_poster = season_poster
+ // } else {
+ // const tvApi = `${Config.tmdbProxyUrl}/3/tv/${fileItem.minfo.id}?api_key=87d8eb3d0895eaf37c2929fd5d9f7cce&language=zh-CN`
+ // const tvResp = await AliHttp.GetWithOutUserId(tvApi)
+ // if (AliHttp.IsSuccess(tvResp.code) && tvResp.body.seasons && tvResp.body.seasons.length > 0) {
+ // // fileItem.tvSeason = tvResp.body.seasons
+ // // @ts-ignore
+ // const filteredSeasons = tvResp.body.seasons.filter(season => season.season_number === Number(seasonNum))
+ // if (filteredSeasons && filteredSeasons.length > 0) {
+ // fileItem.season_poster = filteredSeasons[0].poster_path
+ // if ( fileItem.season_poster) {
+ // await DB.saveValueString(fileItem.file_id+"season_poster", fileItem.season_poster)
+ // }
+ // }
+ // }
+ // }
+ // }
+ // }
+ }
+ }
+ }
+
private static async _ApiDirFileListOnePage(orderby: string, order: string, dir: IAliFileResp, type: string, pageIndex: number): Promise {
let url = 'adrive/v3/file/list'
- if (useSettingStore().uiShowPanMedia == false) url += '?jsonmask=next_marker%2Cpunished_file_count%2Ctotal_count%2Citems(' + AliDirFileList.ItemJsonmask + ')'
- else url += '?jsonmask=next_marker%2Cpunished_file_count%2Ctotal_count%2Citems(' + AliDirFileList.ItemJsonmask + '%2Cvideo_media_metadata(duration%2Cwidth%2Cheight%2Ctime)%2Cvideo_preview_metadata%2Fduration%2Cimage_media_metadata)'
-
- let postData = {
+ if (useSettingStore().uiShowPanMedia == false) {
+ url += '?jsonmask=next_marker%2Citems(' + AliDirFileList.ItemJsonmask + ')'
+ } else {
+ url += '?jsonmask=next_marker%2Citems(' + AliDirFileList.ItemJsonmask + '%2Cuser_meta%2Cvideo_media_metadata(duration%2Cwidth%2Cheight%2Ctime)%2Cvideo_preview_metadata%2Fduration%2Cimage_media_metadata)'
+ }
+ let postData: any = {
drive_id: dir.m_drive_id,
- parent_file_id: dir.dirID,
+ parent_file_id: dir.dirID.includes('root') ? 'root' : dir.dirID,
marker: dir.next_marker,
- limit: 200,
+ limit: 100,
all: false,
url_expire_sec: 14400,
fields: '*',
@@ -250,15 +446,28 @@ export default class AliDirFileList {
return await AliDirFileList._FileListOnePage(orderby, order, dir, resp, pageIndex, type)
}
- private static async _ApiDirFileListOnePageOpenApi(orderby: string, order: string, dir: IAliFileResp, type: string, pageIndex: number): Promise {
+ private static async _ApiDirFileListOnePageOpenApi(orderby: string, order: string, dir: IAliFileResp, type: string, pageIndex: number, search= true): Promise {
let url = 'adrive/v1.0/openFile/list'
- let postData = {
- drive_id: dir.m_drive_id,
- parent_file_id: dir.dirID,
- marker: dir.next_marker,
- limit: 200,
- order_by: orderby,
- order_direction: order.toUpperCase()
+ let postData
+ if (useSettingStore().uiFileListMode === 'movie' && search) {
+ postData = {
+ drive_id: dir.m_drive_id,
+ parent_file_id: dir.dirID.includes('root') ? 'root' : dir.dirID,
+ marker: dir.next_marker,
+ category: "video",
+ limit: 200,
+ order_by: orderby,
+ order_direction: order.toUpperCase()
+ }
+ } else {
+ postData = {
+ drive_id: dir.m_drive_id,
+ parent_file_id: dir.dirID,
+ marker: dir.next_marker,
+ limit: 200,
+ order_by: orderby,
+ order_direction: order.toUpperCase()
+ }
}
if (type) {
postData = Object.assign(postData, { type })
@@ -268,25 +477,37 @@ export default class AliDirFileList {
return AliDirFileList._FileListOnePage(orderby, order, dir, resp, pageIndex, type)
}
-
- private static async _ApiDirFileListCount(dir: IAliFileResp, type: string): Promise {
- const url = 'adrive/v1.0/openFile/search'
- const postData = {
+
+ private static async _ApiDirFileListCount(dir: IAliFileResp, dirID: string, type: string): Promise {
+ let isPic = dirID.includes('pic')
+ type = isPic ? 'file' : type
+ let url = ''
+ if (!isPic) {
+ url = 'adrive/v1.0/openFile/search'
+ } else {
+ url = 'adrive/v3/file/search'
+ }
+ let parent_file_id = dir.dirID.includes('_root') ? 'root' : dir.dirID
+ const postData: any = {
drive_id: dir.m_drive_id,
marker: '',
limit: 1,
all: false,
url_expire_sec: 14400,
fields: 'thumbnail',
- query: 'parent_file_id="' + dir.dirID + '"' + (type ? ' and type="' + type + '"' : ''),
+ query: 'parent_file_id="' + parent_file_id + '"' + (type ? ' and type="' + type + '"' : ''),
return_total_count: true
}
+ if (!isPic) {
+ delete postData.all
+ delete postData.url_expire_sec
+ }
const resp = await AliHttp.Post(url, postData, dir.m_user_id, '')
try {
if (AliHttp.IsSuccess(resp.code)) {
return resp.body.total_count || 0
- } else {
- DebugLog.mSaveWarning('_ApiDirFileListCount err=' + dir.dirID + ' ' + (resp.code || ''))
+ } else if (!AliHttp.HttpCodeBreak(resp.code)) {
+ DebugLog.mSaveWarning('_ApiDirFileListCount err=' + dir.dirID + ' ' + (resp.code || ''), resp.body)
}
} catch (err: any) {
DebugLog.mSaveDanger('_ApiDirFileListCount ' + dir.dirID, err)
@@ -294,7 +515,7 @@ export default class AliDirFileList {
return 0
}
-
+
private static async _ApiFavoriteFileListCount(dir: IAliFileResp): Promise {
const url = 'adrive/v3/file/search'
const postData = {
@@ -311,8 +532,8 @@ export default class AliDirFileList {
try {
if (AliHttp.IsSuccess(resp.code)) {
return resp.body.total_count || 0
- } else {
- DebugLog.mSaveWarning('_ApiFavoriteFileListCount err=' + dir.dirID + ' ' + (resp.code || ''))
+ } else if (!AliHttp.HttpCodeBreak(resp.code)) {
+ DebugLog.mSaveWarning('_ApiFavoriteFileListCount err=' + dir.dirID + ' ' + (resp.code || ''), resp.body)
}
} catch (err: any) {
DebugLog.mSaveDanger('_ApiFavoriteFileListCount ' + dir.dirID, err)
@@ -322,8 +543,8 @@ export default class AliDirFileList {
private static async _ApiFavorFileListOnePage(orderby: string, order: string, dir: IAliFileResp, pageIndex: number): Promise {
let url = 'v2/file/list_by_custom_index_key'
- if (useSettingStore().uiShowPanMedia == false) url += '?jsonmask=next_marker%2Cpunished_file_count%2Ctotal_count%2Citems(' + AliDirFileList.ItemJsonmask + ')'
- else url += '?jsonmask=next_marker%2Cpunished_file_count%2Ctotal_count%2Citems(' + AliDirFileList.ItemJsonmask + '%2Cvideo_media_metadata(duration%2Cwidth%2Cheight%2Ctime)%2Cvideo_preview_metadata%2Fduration%2Cimage_media_metadata)'
+ if (useSettingStore().uiShowPanMedia == false) url += '?jsonmask=next_marker%2Citems(' + AliDirFileList.ItemJsonmask + ')'
+ else url += '?jsonmask=next_marker%2Citems(' + AliDirFileList.ItemJsonmask + '%2Cuser_meta%2Cvideo_media_metadata(duration%2Cwidth%2Cheight%2Ctime)%2Cvideo_preview_metadata%2Fduration%2Cimage_media_metadata)'
const postData = {
drive_id: dir.m_drive_id,
@@ -341,7 +562,7 @@ export default class AliDirFileList {
}
private static async _ApiTrashFileListOnePage(orderby: string, order: string, dir: IAliFileResp, pageIndex: number): Promise {
- const url = 'v2/recyclebin/list?jsonmask=next_marker%2Cpunished_file_count%2Ctotal_count%2Citems(' + AliDirFileList.ItemJsonmask + ')'
+ const url = 'v2/recyclebin/list?jsonmask=next_marker%2Citems(' + AliDirFileList.ItemJsonmask + ')'
const postData = {
drive_id: dir.m_drive_id,
@@ -361,7 +582,9 @@ export default class AliDirFileList {
const url = 'adrive/v1/file/listDeleted'
const postData = {
drive_id: dir.m_drive_id,
- album_drive_id: dir.m_drive_id,
+ limit: 100,
+ order_by: 'gmt_deleted',
+ order_direction: 'DESC',
marker: dir.next_marker
}
const resp = await AliHttp.Post(url, postData, dir.m_user_id, '')
@@ -369,14 +592,17 @@ export default class AliDirFileList {
}
static async _ApiSearchFileListOnePage(orderby: string, order: string, dir: IAliFileResp, pageIndex: number): Promise {
- let url = 'adrive/v1.0/openFile/search'
+ let url = 'adrive/v3/file/search'
+ if (useSettingStore().uiShowPanMedia == false) url += '?jsonmask=next_marker%2Citems(' + AliDirFileList.ItemJsonmask + ')'
+ else url += '?jsonmask=next_marker%2Citems(' + AliDirFileList.ItemJsonmask + '%2Cuser_meta%2Cvideo_media_metadata(duration%2Cwidth%2Cheight%2Ctime)%2Cvideo_preview_metadata%2Fduration%2Cimage_media_metadata)'
+
let query = ''
+ let drive_id_list = []
if (dir.dirID.startsWith('color')) {
const color = dir.dirID.substring('color'.length).split(' ')[0].replace('#', 'c')
query = 'description="' + color + '"'
} else if (dir.dirID.startsWith('search')) {
- const search = dir.dirID.substring('search'.length).split(' ')
-
+ const search = dir.dirID.substring('search'.length).split(' ')
let word = ''
for (let i = 0; i < search.length; i++) {
const itemstr = search[i]
@@ -384,74 +610,78 @@ export default class AliDirFileList {
word += itemstr + ' '
continue
}
-
const kv = search[i].split(':')
const k = kv[0]
const v = kv[1]
- if (k == 'type') {
+ if (k == 'range') {
+ const arr = v.split(',')
+ for (let j = 0; j < arr.length; j++) {
+ drive_id_list.push(GetDriveID(dir.m_user_id, arr[j]))
+ }
+ } else if (k == 'type') {
const arr = v.split(',')
let type = ''
for (let j = 0; j < arr.length; j++) {
- if (arr[j] == 'folder') type += 'type="' + arr[j] + '" or '
- else if (arr[j]) type += 'category="' + arr[j] + '" or '
+ if (arr[j] == 'folder') type += 'type="' + arr[j] + '" or '
+ else if (arr[j]) type += 'category="' + arr[j] + '" or '
}
type = type.substring(0, type.length - 4).trim()
if (type && type.indexOf(' or ') > 0) query += '(' + type + ') and '
else if (type) query += type + ' and '
- }
- // else if (k == 'size') {
- // const size = parseInt(v)
- // if (size > 0) query += 'size = ' + v + ' and '
- // }
- // else if (k == 'max') {
- // const max = parseInt(v)
- // if (max > 0) query += 'size <= ' + v + ' and '
- // } else if (k == 'min') {
- // const min = parseInt(v)
- // if (min > 0) query += 'size >= ' + v + ' and '
- // }
- else if (k == 'begin') {
+ } else if (k == 'size') {
+ const size = parseInt(v)
+ if (size > 0) query += 'size = ' + v + ' and '
+ } else if (k == 'description') {
+ query += 'description = ' + v + ' and '
+ } else if (k == 'max') {
+ const max = parseInt(v)
+ if (max > 0) query += 'size <= ' + v + ' and '
+ } else if (k == 'min') {
+ const min = parseInt(v)
+ if (min > 0) query += 'size >= ' + v + ' and '
+ } else if (k == 'begin') {
const dt = new Date(v).toISOString()
- query += 'created_at >= "' + dt.substring(0, dt.lastIndexOf('.')) + '" and '
+ query += 'updated_at >= "' + dt.substring(0, dt.lastIndexOf('.')) + '" and '
} else if (k == 'end') {
const dt = new Date(v).toISOString()
- query += 'created_at <= "' + dt.substring(0, dt.lastIndexOf('.')) + '" and '
+ query += 'updated_at <= "' + dt.substring(0, dt.lastIndexOf('.')) + '" and '
} else if (k == 'ext') {
const arr = v.split(',')
let extin = ''
for (let j = 0; j < arr.length; j++) {
extin += '"' + arr[j] + '",'
}
- if (extin.length > 0) extin = extin.substring(0, extin.length - 1)
+ if (extin.length > 0) extin = extin.substring(0, extin.length - 1)
if (extin) query += 'file_extension in [' + extin + '] and '
} else if (k == 'fav') query += 'starred = ' + v + ' and '
}
word = word.trim()
if (word) query += 'name match "' + word.replaceAll('"', '\\"') + '" and '
- if (query.length > 0) query = query.substring(0, query.length - 5)
+ if (query.length > 0) query = query.substring(0, query.length - 5)
if (query.startsWith('(') && query.endsWith(')')) query = query.substring(1, query.length - 1)
}
- const postData = {
- drive_id: dir.m_drive_id,
+ const postData: any = {
marker: dir.next_marker,
- limit: 100 ,
+ limit: 100,
fields: '*',
query: query,
order_by: orderby + ' ' + order
}
+ if (drive_id_list.length > 0) postData.drive_id_list = drive_id_list
+ else postData.drive_id = dir.m_drive_id
const resp = await AliHttp.Post(url, postData, dir.m_user_id, '')
return AliDirFileList._FileListOnePage(orderby, order, dir, resp, pageIndex)
}
static async _ApiSearchFileListCount(dir: IAliFileResp): Promise {
- const url = 'adrive/v1.0/openFile/search'
-
+ const url = 'adrive/v3/file/search'
let query = ''
+ let drive_id_list = []
if (dir.dirID.startsWith('color')) {
const color = dir.dirID.substring('color'.length).split(' ')[0].replace('#', 'c')
query = 'description="' + color + '"'
} else if (dir.dirID.startsWith('search')) {
- const search = dir.dirID.substring('search'.length).split(' ')
+ const search = dir.dirID.substring('search'.length).split(' ')
let word = ''
for (let i = 0; i < search.length; i++) {
@@ -464,62 +694,68 @@ export default class AliDirFileList {
const kv = search[i].split(':')
const k = kv[0]
const v = kv[1]
- if (k == 'type') {
+ if (k == 'range') {
+ const arr = v.split(',')
+ for (let j = 0; j < arr.length; j++) {
+ drive_id_list.push(GetDriveID(dir.m_user_id, arr[j]))
+ }
+ } else if (k == 'type') {
const arr = v.split(',')
let type = ''
for (let j = 0; j < arr.length; j++) {
- if (arr[j] == 'folder') type += 'type="' + arr[j] + '" or '
- else if (arr[j]) type += 'category="' + arr[j] + '" or '
+ if (arr[j] == 'folder') type += 'type="' + arr[j] + '" or '
+ else if (arr[j]) type += 'category="' + arr[j] + '" or '
}
type = type.substring(0, type.length - 4).trim()
if (type && type.indexOf(' or ') > 0) query += '(' + type + ') and '
else if (type) query += type + ' and '
- }
- // else if (k == 'size') {
- // const size = parseInt(v)
- // if (size > 0) query += 'size = ' + v + ' and '
- // } else if (k == 'max') {
- // const max = parseInt(v)
- // if (max > 0) query += 'size <= ' + v + ' and '
- // } else if (k == 'min') {
- // const min = parseInt(v)
- // if (min > 0) query += 'size >= ' + v + ' and '
- // }
- else if (k == 'begin') {
+ } else if (k == 'size') {
+ const size = parseInt(v)
+ if (size > 0) query += 'size = ' + v + ' and '
+ } else if (k == 'description') {
+ query += 'description = ' + v + ' and '
+ } else if (k == 'max') {
+ const max = parseInt(v)
+ if (max > 0) query += 'size <= ' + v + ' and '
+ } else if (k == 'min') {
+ const min = parseInt(v)
+ if (min > 0) query += 'size >= ' + v + ' and '
+ } else if (k == 'begin') {
const dt = new Date(v).toISOString()
- query += 'created_at >= "' + dt.substring(0, dt.lastIndexOf('.')) + '" and '
+ query += 'updated_at >= "' + dt.substring(0, dt.lastIndexOf('.')) + '" and '
} else if (k == 'end') {
const dt = new Date(v).toISOString()
- query += 'created_at <= "' + dt.substring(0, dt.lastIndexOf('.')) + '" and '
+ query += 'updated_at <= "' + dt.substring(0, dt.lastIndexOf('.')) + '" and '
} else if (k == 'ext') {
const arr = v.split(',')
let extin = ''
for (let j = 0; j < arr.length; j++) {
extin += '"' + arr[j] + '",'
}
- if (extin.length > 0) extin = extin.substring(0, extin.length - 1)
+ if (extin.length > 0) extin = extin.substring(0, extin.length - 1)
if (extin) query += 'file_extension in [' + extin + '] and '
} else if (k == 'fav') query += 'starred = ' + v + ' and '
}
word = word.trim()
if (word) query += 'name match "' + word.replaceAll('"', '\\"') + '" and '
- if (query.length > 0) query = query.substring(0, query.length - 5)
+ if (query.length > 0) query = query.substring(0, query.length - 5)
if (query.startsWith('(') && query.endsWith(')')) query = query.substring(1, query.length - 1)
}
- const postData = {
- drive_id: dir.m_drive_id,
+ const postData: any = {
marker: dir.next_marker,
- limit: 1 ,
+ limit: 1,
fields: '*',
query: query,
return_total_count: true
}
+ if (drive_id_list.length > 0) postData.drive_id_list = drive_id_list
+ else postData.drive_id = dir.m_drive_id
const resp = await AliHttp.Post(url, postData, dir.m_user_id, '')
try {
if (AliHttp.IsSuccess(resp.code)) {
return (resp.body.total_count as number) || 0
- } else {
- DebugLog.mSaveWarning('_ApiSearchFileListCount err=' + dir.dirID + ' ' + (resp.code || ''))
+ } else if (!AliHttp.HttpCodeBreak(resp.code)) {
+ DebugLog.mSaveWarning('_ApiSearchFileListCount err=' + dir.dirID + ' ' + (resp.code || ''), resp.body)
}
} catch (err: any) {
DebugLog.mSaveDanger('_ApiSearchFileListCount ' + dir.dirID, err)
@@ -527,8 +763,42 @@ export default class AliDirFileList {
return 0
}
+ static async _ApiAlbumListOnePage(orderby: string, order: string, dir: IAliFileResp, pageIndex: number): Promise {
+ const url = 'adrive/v1/album/list'
+ const postData = {
+ limit: 100,
+ order_by: 'updated_at',
+ order_direction: 'DESC'
+ }
+ const resp = await AliHttp.Post(url, postData, dir.m_user_id, '')
+ return AliDirFileList._FileListOnePage(orderby, order, dir, resp, pageIndex)
+ }
+
+ static async _ApiAlbumListFilesOnePage(orderby: string, order: string, dir: IAliFileResp, pageIndex: number): Promise {
+ const url = 'adrive/v1/album/list_files'
+ const postData = {
+ album_id: dir.albumID,
+ fields: '*',
+ filter: '',
+ limit: 100,
+ order_by: 'joined_at',
+ order_direction: 'DESC',
+ image_thumbnail_process: 'image/resize,w_400/format,jpeg',
+ image_url_process: 'image/resize,w_1920/format,jpeg',
+ video_thumbnail_process: 'video/snapshot,t_0,f_jpg,ar_auto,w_1000'
+ }
+ const resp = await AliHttp.Post(url, postData, dir.m_user_id, '')
+ return AliDirFileList._FileListOnePage(orderby, order, dir, resp, pageIndex)
+ }
+
static async _ApiVideoListRecent(orderby: string, order: string, dir: IAliFileResp, pageIndex: number): Promise {
- const url = 'adrive/v1.0/openFile/video/recentList'
+ let need_open_api = true
+ let url = ''
+ if (need_open_api) {
+ url = 'adrive/v1.1/openFile/video/recentList'
+ } else {
+ url = 'adrive/v2/video/recentList'
+ }
const postData = {}
const resp = await AliHttp.Post(url, postData, dir.m_user_id, '')
return AliDirFileList._FileListOnePage(orderby, order, dir, resp, pageIndex)
@@ -565,8 +835,8 @@ export default class AliDirFileList {
return AliDirFileList._FileListOnePage(orderby, order, dir, resp, pageIndex)
}
-
- static _FileListOnePage(orderby: string, order: string, dir: IAliFileResp, resp: IUrlRespData, pageIndex: number, type: string = ''): boolean {
+
+ static _FileListOnePage(orderby: string, order: string, dir: IAliFileResp, resp: IUrlRespData, pageIndex: number, type: string = '', refresh: boolean = true): boolean {
try {
if (AliHttp.IsSuccess(resp.code)) {
const dirPart: IAliFileResp = {
@@ -582,48 +852,55 @@ export default class AliDirFileList {
dir.next_marker = resp.body.next_marker || ''
const isRecover = dir.dirID == 'recover'
- const isDirFile = dir.dirID == 'root' || (dir.dirID.length == 40 && !dir.dirID.startsWith('search'))
+ const isDirFile = dir.dirID.includes('root') || (dir.dirID.length == 40 && !dir.dirID.startsWith('search'))
const isVideo = dir.dirID.startsWith('video')
- // const issearch = dir.dirID.startsWith('search')
- // const iscolor = dir.dirID.startsWith('color')
- const downUrl = isRecover ? '' : 'https://api.aliyundrive.com/v2/file/download?t=' + Date.now().toString()
+ const isPic = dir.dirID.includes('pic')
+ const downUrl = isRecover ? '' : 'https://api.alipan.com/v2/file/download?t=' + Date.now().toString()
if (resp.body.items) {
+ let settingStore = useSettingStore()
const driverData = TreeStore.GetDriver(dir.m_drive_id)
const DirFileSizeMap = driverData?.DirFileSizeMap || {}
const DirTotalSizeMap = driverData?.DirTotalSizeMap || {}
- const isFolderSize = useSettingStore().uiFolderSize
+ const isFolderSize = settingStore.uiFolderSize
let dirList: IAliGetFileModel[] = []
let fileList: IAliGetFileModel[] = []
for (let i = 0, maxi = resp.body.items.length; i < maxi; i++) {
const item = resp.body.items[i] as IAliFileItem
if (isVideo) {
- if (!item.compilation_id && (!item.drive_id || !item.file_id)) continue
-
+ if (!item.compilation_id && (!item.drive_id || !item.file_id)) continue
if (!item.compilation_id) {
item.type = 'file'
+ item.category = 'video'
item.compilation_id = item.drive_id + '_' + item.file_id
}
-
if (item.video_type == 'COMPILATION') {
item.type = 'folder'
item.drive_id = item.compilation_id.split('_')[0]
item.file_id = item.compilation_id.split('_')[1]
+ } else {
+ item.category = 'video'
+ }
+ }
+ if (isPic) {
+ if (!item.album_id && (!item.drive_id || !item.file_id)) continue
+ if (item.album_id) {
+ item.type = 'folder'
+ item.file_id = item.album_id
}
}
if (dir.itemsKey.has(item.file_id)) continue
- const add = AliDirFileList.getFileInfo(item, downUrl)
+ const add = AliDirFileList.getFileInfo(dir.m_user_id, item, downUrl)
if (isRecover) add.description = item.content_hash
- if (isVideo) {
- add.compilation_id = item.compilation_id
- }
+ if (isVideo) add.compilation_id = item.compilation_id
+ if (isPic) add.album_id = item.album_id
if (add.isDir) {
if (isFolderSize) {
add.size = DirTotalSizeMap[add.file_id] || DirFileSizeMap[add.file_id] || 0
add.sizeStr = humanSize(add.size)
}
if (isDirFile) dirList.push(add)
- else fileList.push(add)
+ else fileList.push(add)
} else fileList.push(add)
dir.itemsKey.add(item.file_id)
}
@@ -638,34 +915,32 @@ export default class AliDirFileList {
dir.items.push(...fileList)
}
}
-
dirPart.punished_file_count = resp.body.punished_file_count || 0
dir.punished_file_count += resp.body.punished_file_count || 0
-
- if (pageIndex >= 0 && type == '') {
+ // 相册文件数
+ if (isPic && dir.dirID != 'pic_root') {
+ dir.itemsTotal = resp.body.totalCount
+ }
+ if (pageIndex >= 0 && type == '' && refresh) {
const pan = usePanFileStore()
if (pan.DriveID == dir.m_drive_id) {
pan.mSaveDirFileLoadingPart(pageIndex, dirPart, dir.itemsTotal || 0)
- } else {
- const resPan = useResPanFileStore();
- resPan.mSaveDirFileLoadingPart(pageIndex, dirPart, dir.itemsTotal || 0)
}
}
if (dirPart.next_marker == 'cancel') dir.next_marker = 'cancel'
if (isVideo && dir.items.length >= 500) dir.next_marker = ''
return true
} else if (resp.code == 404) {
-
dir.items.length = 0
dir.next_marker = ''
return true
} else if (resp.body && resp.body.code) {
dir.items.length = 0
- dir.next_marker = resp.body.code
+ dir.next_marker = resp.body.code
message.warning('列出文件出错 ' + resp.body.code, 2)
return false
- } else {
- DebugLog.mSaveWarning('_FileListOnePage err=' + dir.dirID + ' ' + (resp.code || ''))
+ } else if (!AliHttp.HttpCodeBreak(resp.code)) {
+ DebugLog.mSaveWarning('_FileListOnePage err=' + dir.dirID + ' ' + (resp.code || ''), resp.body)
}
} catch (err: any) {
DebugLog.mSaveDanger('_FileListOnePage ' + dir.dirID, err)
@@ -674,62 +949,43 @@ export default class AliDirFileList {
return false
}
-
- static async ApiDirFileSize(user_id: string, drive_id: string, file_idList: string[]): Promise<{ dirID: string; size: number }[] | undefined> {
- const list: Map = new Map()
- let postData = '{"requests":['
+ static async ApiDirFileSize(user_id: string, drive_id: string, file_idList: string[]): Promise<{
+ dirID: string;
+ size: number
+ }[] | undefined> {
+ const list: Map = new Map()
for (let i = 0, maxi = file_idList.length; i < maxi; i++) {
list.set(file_idList[i], { dirID: file_idList[i], size: 0 })
- if (i > 0) postData = postData + ','
let id = file_idList[i].includes('root') ? 'root' : file_idList[i]
- const data2 = {
- body: {
- drive_id: drive_id,
- query: 'parent_file_id="' + file_idList[i] + '" and type="file"',
- limit: 100,
- fields: 'thumbnail',
- order_by: 'size DESC'
- },
- headers: { 'Content-Type': 'application/json' },
- id: id,
- method: 'POST',
- url: '/file/search'
+ let postData = {
+ drive_id: drive_id,
+ limit: 100,
+ query: 'parent_file_id="' + id + '" and type="file"',
+ fields: 'thumbnail',
+ order_by: 'size DESC'
}
- postData = postData + JSON.stringify(data2)
- }
- postData += '],"resource":"file"}'
-
- const url = 'v2/batch?jsonmask=responses(id%2Cstatus%2Cbody(next_marker%2Citems(size)))'
- const resp = await AliHttp.Post(url, postData, user_id, '')
-
- try {
- if (AliHttp.IsSuccess(resp.code)) {
- const responses = resp.body.responses
- for (let j = 0, maxj = responses.length; j < maxj; j++) {
- const respi = responses[j]
-
- if (respi.id && respi.status && respi.status >= 200 && respi.status <= 205) {
- if (respi.body && respi.body.items && respi.body.items.length > 0) {
- let size = 0
- const items = respi.body.items
- for (let k = 0, maxk = items.length; k < maxk; k++) {
- size += items[k].size || 0
- }
- const find = list.get(respi.id)
- if (find) find.size = size
+ const url = 'adrive/v3/file/search?jsonmask=next_marker%2Citems(size)'
+ const resp = await AliHttp.Post(url, postData, user_id, '')
+ try {
+ if (AliHttp.IsSuccess(resp.code)) {
+ if (resp.body && resp.body.items && resp.body.items.length > 0) {
+ let size = 0
+ const items = resp.body.items
+ for (let k = 0, maxk = items.length; k < maxk; k++) {
+ size += items[k].size || 0
}
+ const find = list.get(id)
+ if (find) find.size = size
}
-
+ return MapValueToArray(list)
+ } else {
+ DebugLog.mSaveWarning('ApiDirFileSize err=' + (resp.code || ''), resp.body)
+ return undefined
}
- return MapValueToArray(list)
- } else {
-
- DebugLog.mSaveWarning('ApiDirFileSize err=' + (resp.code || ''))
- return undefined
+ } catch (err: any) {
+ DebugLog.mSaveWarning('ApiDirFileSize', err)
}
- } catch (err: any) {
- DebugLog.mSaveWarning('ApiDirFileSize', err)
}
return MapValueToArray(list)
}
diff --git a/aliyunpan/src/aliapi/dirlist.ts b/aliyunpan/src/aliapi/dirlist.ts
index ff96c07a37..691a655fab 100644
--- a/aliyunpan/src/aliapi/dirlist.ts
+++ b/aliyunpan/src/aliapi/dirlist.ts
@@ -1,43 +1,41 @@
import DebugLog from '../utils/debuglog'
import { MapValueToArray } from '../utils/utils'
import AliHttp from './alihttp'
-import {IAliFileItem, IAliGetDirModel, IAliGetFileModel} from './alimodels'
-import AliDirFileList from './dirfilelist'
+import { IAliGetDirModel, IAliGetFileModel } from './alimodels'
import dayjs from 'dayjs'
import AliTrash from './trash'
import { DirData } from '../store/treestore'
import AliUser from './user'
-import AliFile from "./file";
export interface IAliDirResp {
items: IAliGetDirModel[]
next_marker: string
- m_user_id: string
- m_drive_id: string
- dirID: string
- dirName: string
+ m_user_id: string
+ m_drive_id: string
+ dirID: string
+ dirName: string
}
export interface IDirDataResp {
items: DirData[]
next_marker: string
- m_user_id: string
- m_drive_id: string
- dirID: string
- dirName: string
+ m_user_id: string
+ m_drive_id: string
+ dirID: string
+ dirName: string
}
export interface IAliDirBatchResp {
items: IAliGetFileModel[]
itemsKey: Set
next_marker: string
- dirID: string
+ dirID: string
}
export default class AliDirList {
-
+
static async ApiFastAllDirList(user_id: string, drive_id: string): Promise {
const result: IAliDirResp = {
items: [],
@@ -88,7 +86,7 @@ export default class AliDirList {
namesearch: '',
size: item.size || 0,
time: new Date(item.updated_at).getTime(),
-
+
description: item.description || ''
}
allMap.set(add.file_id, add)
@@ -109,31 +107,30 @@ export default class AliDirList {
namesearch: '',
size: item.size || 0,
time: new Date(item.updated_at).getTime(),
-
+
description: item.description || ''
}
allMap.set(add.file_id, add)
lockSet.add(item.file_id)
}
}
- if (isFind) break
- if (resp1.body.next_marker == '' && resp2.body.next_marker == '') break
+ if (isFind) break
+ if (resp1.body.next_marker == '' && resp2.body.next_marker == '') break
} else {
-
+
errorMessage += 'err1' + (resp1.status || '')
errorMessage += 'err2' + (resp2.status || '')
break
}
} else if (resp.code == 402) {
-
- DebugLog.mSaveWarning('ApiFastAllDirList err=' + drive_id + ' ' + (resp.code || ''))
+ DebugLog.mSaveWarning('ApiFastAllDirList err=' + drive_id + ' ' + (resp.code || ''), resp.body)
break
- } else {
+ } else if (!AliHttp.HttpCodeBreak(resp.code)) {
errorMessage += 'err' + (resp.code || '')
- DebugLog.mSaveWarning('ApiFastAllDirList err=' + (resp.code || ''))
+ DebugLog.mSaveWarning('ApiFastAllDirList err=' + (resp.code || ''), resp.body)
}
} catch (err: any) {
-
+
errorMessage += 'err' + (err.message || '')
DebugLog.mSaveWarning('ApiFastAllDirList', err)
break
@@ -148,87 +145,6 @@ export default class AliDirList {
return result
}
-
- static async ApiBatchDirFileList(user_id: string, drive_id: string, dirList: IAliDirBatchResp[], limit: number, listTypeOrQuery: string): Promise {
- if (!user_id || !drive_id) return false
-
- let postData = '{"requests":['
- for (let i = 0, maxi = dirList.length; i < maxi; i++) {
- if (i > 0) postData = postData + ','
-
- let query = 'parent_file_id="' + dirList[i].dirID + '"'
- if (listTypeOrQuery == 'all') query = 'parent_file_id="' + dirList[i].dirID + '"'
- else if (listTypeOrQuery == 'folder') query = 'parent_file_id="' + dirList[i].dirID + '" and type = "folder"'
- else if (listTypeOrQuery == 'file') query = 'parent_file_id="' + dirList[i].dirID + '" and type = "file"'
- else query = query + listTypeOrQuery
- const data2 = {
- body: {
- drive_id: drive_id,
- query: query,
- marker: dirList[i].next_marker,
- url_expire_sec: 14400,
- limit: limit,
- // fields: 'thumbnail',
- image_thumbnail_process: '',
- video_thumbnail_process: '',
- image_url_process: ''
- },
- headers: { 'Content-Type': 'application/json' },
- id: dirList[i].dirID,
- method: 'POST',
- url: '/file/search'
- }
- postData = postData + JSON.stringify(data2)
- }
- postData += '],"resource":"file"}'
-
- const url = 'v2/batch'
- const resp = await AliHttp.Post(url, postData, user_id, '')
-
- try {
- if (AliHttp.IsSuccess(resp.code)) {
- const responses = resp.body.responses
- for (let j = 0, maxj = responses.length; j < maxj; j++) {
- const status = responses[j].status as number
- if (status >= 200 && status <= 205) {
- const respi = responses[j]
- const id = respi.id || ''
- for (let i = 0, maxi = dirList.length; i < maxi; i++) {
- if (dirList[i].dirID == id) {
- const dir = dirList[i]
- dir.next_marker = respi.body.next_marker
- const items = respi.body.items
- for (let i = 0, maxi = items.length; i < maxi; i++) {
- const fileItem = items[i] as IAliFileItem
- if (fileItem.type === 'file') {
- const fileDetails = await AliFile.ApiFileInfoOpenApi(user_id, drive_id, fileItem.file_id);
- fileItem.thumbnail = fileDetails?.thumbnail
- fileItem.url = fileDetails?.url || fileItem.url
- fileItem.download_url = fileDetails?.download_url || fileItem.download_url
- fileItem.starred = fileDetails?.starred || fileItem.starred
- fileItem.trashed = fileDetails?.trashed || fileItem.trashed
- fileItem.deleted = fileDetails?.deleted || fileItem.deleted
- fileItem.description = fileDetails?.description || fileItem.description
- }
- const add = AliDirFileList.getFileInfo(fileItem, '')
- dir.items.push(add)
- }
- break
- }
- }
- }
- }
- return true
- } else {
- DebugLog.mSaveWarning('ApiBatchDirFileList err=' + (resp.code || ''))
- }
- } catch (err: any) {
- DebugLog.mSaveWarning('ApiBatchDirFileList', err)
- }
- return false
- }
-
-
static async ApiFastAllDirListByTime(user_id: string, drive_id: string, created_at: Date): Promise {
const result: IAliDirResp = {
items: [],
@@ -240,7 +156,7 @@ export default class AliDirList {
}
if (!user_id || !drive_id) return result
-
+
const allMap = new Map()
let dirList: IAliDirBatchResp[] = []
@@ -301,7 +217,13 @@ export default class AliDirList {
const respi = responses[j]
const id = respi.id || ''
for (let i = 0, maxi = dirList.length; i < maxi; i++) {
- if (dirList[i].dirID.replaceAll('"', '').replaceAll(' ', '').replaceAll('-', '').replaceAll(':', '').replaceAll(',', '') == id) {
+ let pid = dirList[i].dirID
+ .replaceAll('"', '')
+ .replaceAll(' ', '')
+ .replaceAll('-', '')
+ .replaceAll(':', '')
+ .replaceAll(',', '')
+ if (pid == id) {
const dir = dirList[i]
const items = respi.body.items
dir.next_marker = respi.body.next_marker
@@ -318,7 +240,7 @@ export default class AliDirList {
namesearch: '',
size: item.size || 0,
time: new Date(item.updated_at).getTime(),
-
+
description: item.description || ''
}
allMap.set(add.file_id, add)
@@ -330,9 +252,9 @@ export default class AliDirList {
}
dirList.length = 0
dirList = list
- } else {
+ } else if (!AliHttp.HttpCodeBreak(resp.code)) {
errorMessage = (resp.code || '').toString()
- DebugLog.mSaveWarning('SSApiBatchDirFileList err=' + (resp.code || ''))
+ DebugLog.mSaveWarning('SSApiBatchDirFileList err=' + (resp.code || ''), resp.body)
}
} catch (err: any) {
errorMessage = err.message || ''
@@ -348,7 +270,7 @@ export default class AliDirList {
}
static async _ApiDirFileListInfo(user_id: string, drive_id: string) {
- const url = 'adrive/v1.0/openFile/search'
+ const url = 'adrive/v3/file/search'
const postData = {
drive_id: drive_id,
marker: '',
@@ -367,8 +289,8 @@ export default class AliDirList {
const created_at = items.length > 0 ? new Date(items[0].created_at) : new Date()
const total_count = resp.body.total_count || 0
return { created_at, total_count }
- } else {
- DebugLog.mSaveWarning('_ApiDirFileListInfo err=' + (resp.code || ''))
+ } else if (!AliHttp.HttpCodeBreak(resp.code)) {
+ DebugLog.mSaveWarning('_ApiDirFileListInfo err=' + (resp.code || ''), resp.body)
}
} catch (err: any) {
DebugLog.mSaveDanger('_ApiDirFileListInfo', err)
@@ -376,14 +298,14 @@ export default class AliDirList {
return { created_at: new Date(), total_count: 0 }
}
-
- static async ApiFastAllDirListByPID(user_id: string, drive_id: string): Promise {
+
+ static async ApiFastAllDirListByPID(user_id: string, drive_id: string, drive_root: string): Promise {
const result: IDirDataResp = {
items: [],
next_marker: '',
m_user_id: user_id,
m_drive_id: drive_id,
- dirID: 'root',
+ dirID: drive_root,
dirName: ''
}
if (!user_id || !drive_id) return result
@@ -391,25 +313,27 @@ export default class AliDirList {
const allMap = new Map()
const dirCount = await AliUser.ApiUserDriveFileCount(user_id, '', 'folder')
const PIDList: string[] = []
-
- const root = await AliTrash.ApiDirFileListNoLock(user_id, drive_id, 'root', '', 'name ASC', 'folder', 0)
+
+ const root = await AliTrash.ApiDirFileListNoLock(user_id, drive_id, drive_root, '', 'name ASC', 'folder', 0)
for (let i = 0, maxi = root.items.length; i < maxi; i++) {
const item = root.items[i]
+ if (item.parent_file_id === 'root') {
+ item.parent_file_id = drive_root
+ }
const add: DirData = {
file_id: item.file_id,
+ drive_id: item.drive_id,
parent_file_id: item.parent_file_id,
name: item.name,
time: item.time,
+ description: item.description,
size: 0
}
-
allMap.set(add.file_id, add)
PIDList.push(add.file_id)
}
-
-
- let dirList: IAliDirBatchResp[] = []
let errorMessage = ''
+ let dirList: IAliDirBatchResp[] = []
let index = 0
while (true) {
while (dirList.length < 30) {
@@ -417,7 +341,92 @@ export default class AliDirList {
let dirID = 'parent_file_id in ['
let add = 0
for (let maxj = PIDList.length; index < maxj; index++) {
- dirID += add == 0 ? '"' + PIDList[index] + '"' : ',"' + PIDList[index] + '"'
+ let PID = PIDList[index].includes('root') ? 'root' : PIDList[index]
+ dirID += add == 0 ? '"' + PID + '"' : ',"' + PID + '"'
+ add++
+ if (add >= 50) break
+ }
+ dirID += ']'
+ dirList.push({ dirID: dirID, next_marker: '', items: [], itemsKey: new Set() } as IAliDirBatchResp)
+ } else break
+ }
+ if (dirList.length == 0) break
+ for (let i = 0, maxi = dirList.length; i < maxi; i++) {
+ const dir = dirList[i]
+ if(!dir) break
+ const query = 'type="folder" and ' + dir.dirID
+ let postData = {
+ drive_id: drive_id,
+ limit: 100,
+ query: query,
+ fields: 'thumbnail',
+ order_by: 'name ASC',
+ marker: dir.next_marker
+ }
+ const url = 'adrive/v3/file/search?jsonmask=next_marker%2Citems(drive_id%2Ccreated_at%2Cfile_id%2Cname%2Cparent_file_id%2Cupdated_at%2Cdescription)'
+ const resp = await AliHttp.Post(url, postData, user_id, '')
+ try {
+ if (AliHttp.IsSuccess(resp.code)) {
+ const items = resp.body.items
+ const list: IAliDirBatchResp[] = []
+ dir.next_marker = resp.body.next_marker
+ if (dir.next_marker) {
+ list.push(dir)
+ }
+ for (let i = 0, maxi = items.length; i < maxi; i++) {
+ const item = items[i]
+ if (allMap.has(item.file_id)) continue
+ if (item.parent_file_id === 'root') {
+ item.parent_file_id = drive_root
+ }
+ const add: DirData = {
+ file_id: item.file_id,
+ drive_id: item.drive_id,
+ parent_file_id: item.parent_file_id,
+ name: item.name,
+ time: new Date(item.updated_at).getTime(),
+ description: item.description,
+ size: 0
+ }
+ allMap.set(add.file_id, add)
+ PIDList.push(add.file_id)
+ }
+ dirList.length = 0
+ dirList = list
+ if (window.WinMsgToMain) window.WinMsgToMain({
+ cmd: 'MainShowAllDirProgress',
+ drive_id,
+ index: allMap.size,
+ total: dirCount
+ })
+ } else if (!AliHttp.HttpCodeBreak(resp.code)) {
+ errorMessage = (resp.code || '').toString()
+ DebugLog.mSaveWarning('SSApiBatchDirFileList err=' + (resp.code || ''), resp.body)
+ }
+ } catch (err: any) {
+ errorMessage = err.message || ''
+ DebugLog.mSaveWarning('ApiBatchDirFileList', err)
+ }
+ }
+ }
+ const list = MapValueToArray(allMap)
+ console.log('listcount', list.length)
+ result.items = errorMessage ? [] : list
+ result.next_marker = errorMessage
+ return result
+ }
+
+ static async ApiBatchLoadDirListByPID(user_id: string, drive_root: string, drive_id: string, PIDList: string[], allMap: Map, dirCount: number, errorMessage: string = '') {
+ let dirList: IAliDirBatchResp[] = []
+ let index = 0
+ while (true) {
+ while (dirList.length < 30) {
+ if (PIDList.length > index) {
+ let dirID = 'parent_file_id in ['
+ let add = 0
+ for (let maxj = PIDList.length; index < maxj; index++) {
+ let PID = PIDList[index].includes('root') ? 'root' : PIDList[index]
+ dirID += add == 0 ? '"' + PID + '"' : ',"' + PID + '"'
add++
if (add >= 50) break
}
@@ -431,6 +440,12 @@ export default class AliDirList {
for (let i = 0, maxi = dirList.length; i < maxi; i++) {
if (i > 0) postData = postData + ','
const query = 'type="folder" and ' + dirList[i].dirID
+ let id = dirList[i].dirID
+ .replaceAll('"', '')
+ .replaceAll(' ', '')
+ .replaceAll(',', '')
+ .substring(0, 54)
+ if (id.includes('root')) id = 'root'
const data2 = {
body: {
drive_id: drive_id,
@@ -441,7 +456,7 @@ export default class AliDirList {
order_by: 'name ASC'
},
headers: { 'Content-Type': 'application/json' },
- id: dirList[i].dirID.replaceAll('"', '').replaceAll(' ', '').replaceAll(',', '').substring(0, 54),
+ id: id,
method: 'POST',
url: '/file/search'
}
@@ -462,19 +477,29 @@ export default class AliDirList {
const respi = responses[j]
const id = respi.id || ''
for (let i = 0, maxi = dirList.length; i < maxi; i++) {
- if (dirList[i].dirID.replaceAll('"', '').replaceAll(' ', '').replaceAll(',', '').substring(0, 54) == id) {
+ let pid = dirList[i].dirID
+ .replaceAll('"', '')
+ .replaceAll(' ', '')
+ .replaceAll(',', '')
+ .substring(0, 54)
+ if (pid == id) {
const dir = dirList[i]
const items = respi.body.items
dir.next_marker = respi.body.next_marker
if (dir.next_marker) list.push(dir)
for (let i = 0, maxi = items.length; i < maxi; i++) {
- if (allMap.has(items[i].file_id)) continue
const item = items[i]
+ if (allMap.has(item.file_id)) continue
+ if (item.parent_file_id === 'root') {
+ item.parent_file_id = drive_root
+ }
const add: DirData = {
file_id: item.file_id,
+ drive_id: item.drive_id,
parent_file_id: item.parent_file_id,
name: item.name,
time: new Date(item.updated_at).getTime(),
+ description: item.description,
size: 0
}
allMap.set(add.file_id, add)
@@ -487,22 +512,20 @@ export default class AliDirList {
}
dirList.length = 0
dirList = list
- if (window.WinMsgToMain) window.WinMsgToMain({ cmd: 'MainShowAllDirProgress', drive_id, index: allMap.size, total: dirCount })
- } else {
+ if (window.WinMsgToMain) window.WinMsgToMain({
+ cmd: 'MainShowAllDirProgress',
+ drive_id,
+ index: allMap.size,
+ total: dirCount
+ })
+ } else if (!AliHttp.HttpCodeBreak(resp.code)) {
errorMessage = (resp.code || '').toString()
- DebugLog.mSaveWarning('SSApiBatchDirFileList err=' + (resp.code || ''))
+ DebugLog.mSaveWarning('SSApiBatchDirFileList err=' + (resp.code || ''), resp.body)
}
} catch (err: any) {
errorMessage = err.message || ''
DebugLog.mSaveWarning('ApiBatchDirFileList', err)
}
}
-
- const list = MapValueToArray(allMap)
- console.log('listcount', list.length)
- result.items = errorMessage ? [] : list
- result.next_marker = errorMessage
-
- return result
}
}
diff --git a/aliyunpan/src/aliapi/file.ts b/aliyunpan/src/aliapi/file.ts
index 145d8ac436..6d902cdfc6 100644
--- a/aliyunpan/src/aliapi/file.ts
+++ b/aliyunpan/src/aliapi/file.ts
@@ -1,13 +1,50 @@
import { useSettingStore } from '../store'
import DebugLog from '../utils/debuglog'
-import message from '../utils/message'
-import { GetOssExpires, HanToPin } from '../utils/utils'
+import { GetExpiresTime, HanToPin } from '../utils/utils'
import AliHttp from './alihttp'
-import {IAliFileItem, IAliGetDirModel, IAliGetFileModel, IAliGetForderSizeModel} from './alimodels'
+import { IAliFileItem, IAliGetDirModel, IAliGetFileModel, IAliGetForderSizeModel } from './alimodels'
import AliDirFileList from './dirfilelist'
-import {ICompilationList, IDownloadUrl, IOfficePreViewUrl, IVideoPreviewUrl, IVideoXBTUrl} from './models'
+import { ICompilationList, IDownloadUrl, IOfficePreViewUrl, IVideoPreviewUrl, IVideoXBTUrl } from './models'
+import { DecodeEncName, GetDriveType } from './utils'
+import { getRawUrl } from '../utils/proxyhelper'
+import message from '../utils/message'
export default class AliFile {
+ static async ApiFileDownloadUrlOpenApi(user_id: string, drive_id: string, file_id: string, expire_sec= 14400): Promise {
+ if (!user_id || !drive_id || !file_id) return 'file_id错误'
+ const data: IDownloadUrl = {
+ drive_id: drive_id,
+ file_id: file_id,
+ expire_time: 0,
+ url: '',
+ size: 0
+ }
+
+ const url = 'adrive/v1.0/openFile/getDownloadUrl'
+ let postData = {
+ "expire_sec": 14400,
+ "drive_id": drive_id,
+ "file_id": file_id
+ }
+ const resp = await AliHttp.Post(url, postData, user_id, '')
+
+ if (AliHttp.IsSuccess(resp.code)) {
+ data.url = resp.body.url
+ data.size = resp.body.size
+ data.expire_time = GetExpiresTime(data.url)
+ console.log("ApiFileDownloadUrlOpenApi: ", data)
+ return data
+ } else if (resp.body.code == 'NotFound.FileId') {
+ return '文件已从网盘中彻底删除'
+ } else if (resp.body.code == 'ForbiddenFileInTheRecycleBin') {
+ return '文件已放入回收站'
+ } else if (resp.body.code) {
+ return resp.body.code as string
+ } else {
+ DebugLog.mSaveWarning('ApiFileDownloadUrl err=' + file_id + ' ' + (resp.code || ''))
+ }
+ return '网络错误'
+ }
static async ApiFileInfoOpenApi(user_id: string, drive_id: string, file_id: string,
image_thumbnail_width=100,
@@ -31,30 +68,55 @@ export default class AliFile {
}
return undefined
}
-
- static async ApiFileInfo(user_id: string, drive_id: string, file_id: string): Promise {
+
+ static async ApiFileInfo(user_id: string, drive_id: string, file_id: string, ispic: boolean = false): Promise {
if (!user_id || !drive_id || !file_id) return undefined
- const url = 'v2/file/get'
- const postData = {
- drive_id: drive_id,
- file_id: file_id,
- url_expire_sec: 14400,
- office_thumbnail_process: 'image/resize,w_400/format,jpeg',
- image_thumbnail_process: 'image/resize,w_400/format,jpeg',
- image_url_process: 'image/resize,w_1920/format,jpeg',
- video_thumbnail_process: 'video/snapshot,t_106000,f_jpg,ar_auto,m_fast,w_400'
+ let url = ''
+ let postData = {}
+ if (!ispic) {
+ url = 'adrive/v1.0/openFile/get'
+ postData = {
+ drive_id: drive_id,
+ file_id: file_id,
+ image_thumbnail_width: 100,
+ video_thumbnail_width: 100,
+ video_thumbnail_time: 120000
+ }
+ } else {
+ url = 'v2/file/get'
+ postData = {
+ drive_id: drive_id,
+ file_id: file_id,
+ url_expire_sec: 14400,
+ office_thumbnail_process: 'image/resize,w_400/format,jpeg',
+ image_thumbnail_process: 'image/resize,w_400/format,jpeg',
+ image_url_process: 'image/resize,w_1920/format,jpeg',
+ video_thumbnail_process: 'video/snapshot,t_106000,f_jpg,ar_auto,m_fast,w_400'
+ }
}
const resp = await AliHttp.Post(url, postData, user_id, '')
if (AliHttp.IsSuccess(resp.code)) {
- return resp.body as IAliFileItem
- } else {
- DebugLog.mSaveWarning('ApiFileInfo err=' + file_id + ' ' + (resp.code || ''))
+ let fileInfo = resp.body as IAliFileItem
+ if (fileInfo.name.toLowerCase() === 'default') {
+ fileInfo.name = '备份盘'
+ } else if (fileInfo.name.toLowerCase() === 'resource') {
+ fileInfo.name = '资源盘'
+ } else if (fileInfo.name.toLowerCase() === 'alibum') {
+ fileInfo.name = '相册'
+ } else {
+ fileInfo.name = DecodeEncName(user_id, fileInfo).name
+ }
+ return fileInfo
+ } else if (AliHttp.HttpCodeBreak(resp.code)) {
+ return (resp.body.message || resp.body) as string
+ } else if (!AliHttp.HttpCodeBreak(resp.code)) {
+ DebugLog.mSaveWarning('ApiFileInfo err=' + file_id + ' ' + (resp.code || ''), resp.body)
}
- return undefined
+ return '网络错误'
}
-
+
static async ApiFileInfoByPath(user_id: string, drive_id: string, file_path: string): Promise {
if (!user_id || !drive_id || !file_path) return undefined
if (!file_path.startsWith('/')) file_path = '/' + file_path
@@ -71,109 +133,94 @@ export default class AliFile {
const resp = await AliHttp.Post(url, postData, user_id, '')
if (AliHttp.IsSuccess(resp.code)) {
- return resp.body as IAliFileItem
- } else {
- DebugLog.mSaveWarning('ApiFileInfoByPath err=' + file_path + ' ' + (resp.code || ''))
+ let fileInfo = resp.body as IAliFileItem
+ fileInfo.name = DecodeEncName(user_id, fileInfo).name
+ return fileInfo
+ } else if (!AliHttp.HttpCodeBreak(resp.code)) {
+ DebugLog.mSaveWarning('ApiFileInfoByPath err=' + file_path + ' ' + (resp.code || ''), resp.body)
}
return undefined
}
- static async ApiFileDownloadUrlOpenApi(user_id: string, drive_id: string, file_id: string, expire_sec= 14400): Promise {
- if (!user_id || !drive_id || !file_id) return 'file_id错误'
- const data: IDownloadUrl = {
- drive_id: drive_id,
- file_id: file_id,
- expire_sec: 0,
- url: '',
- size: 0
- }
-
- const url = 'adrive/v1.0/openFile/getDownloadUrl'
- let postData = {
- "expire_sec": 36000,
- "drive_id": drive_id,
- "file_id": file_id
- }
- const resp = await AliHttp.Post(url, postData, user_id, '')
-
- if (AliHttp.IsSuccess(resp.code)) {
- data.url = resp.body.url
- data.size = resp.body.size
- data.expire_sec = GetOssExpires(data.url)
- console.log("ApiFileDownloadUrlOpenApi: ", data)
- return data
- } else if (resp.body.code == 'NotFound.FileId') {
- return '文件已从网盘中彻底删除'
- } else if (resp.body.code == 'ForbiddenFileInTheRecycleBin') {
- return '文件已放入回收站'
- } else if (resp.body.code) {
- return resp.body.code as string
- } else {
- DebugLog.mSaveWarning('ApiFileDownloadUrl err=' + file_id + ' ' + (resp.code || ''))
- }
- return '网络错误'
- }
-
static async ApiFileDownloadUrl(user_id: string, drive_id: string, file_id: string, expire_sec: number): Promise {
- if (!user_id || !drive_id || !file_id) return 'file_id错误'
+ if (!user_id || !drive_id || !file_id) return '参数错误'
const data: IDownloadUrl = {
drive_id: drive_id,
file_id: file_id,
- expire_sec: 0,
+ expire_time: 0,
url: '',
size: 0
}
- const url = 'v2/file/get_download_url'
- const postData = { drive_id: drive_id, file_id: file_id, expire_sec: expire_sec }
+ let url = ''
+ // 处理OpenApi无法访问相册
+ let isPic = GetDriveType(user_id, drive_id).name === 'pic'
+ if (!isPic) {
+ url = 'adrive/v1.0/openFile/getDownloadUrl'
+ } else {
+ url = 'v2/file/get_download_url'
+ }
+ const postData: any = {
+ drive_id: drive_id,
+ file_id: file_id,
+ expire_sec: expire_sec
+ }
+ if (isPic) {
+ delete postData.expire_sec
+ }
const resp = await AliHttp.Post(url, postData, user_id, '')
-
if (AliHttp.IsSuccess(resp.code)) {
- data.url = resp.body.url
+ data.url = resp.body.cdn_url || resp.body.url
data.size = resp.body.size
- data.expire_sec = GetOssExpires(data.url)
+ data.expire_time = GetExpiresTime(data.url)
return data
} else if (resp.body.code == 'NotFound.FileId') {
return '文件已从网盘中彻底删除'
} else if (resp.body.code == 'ForbiddenFileInTheRecycleBin') {
return '文件已放入回收站'
+ } else if (AliHttp.HttpCodeBreak(resp.code)) {
+ return (resp.body.message || resp.body) as string
} else if (resp.body.code) {
return resp.body.code as string
- } else {
- DebugLog.mSaveWarning('ApiFileDownloadUrl err=' + file_id + ' ' + (resp.code || ''))
+ } else if (!AliHttp.HttpCodeBreak(resp.code)) {
+ DebugLog.mSaveWarning('ApiFileDownloadUrl err=' + file_id + ' ' + (resp.code || ''), resp.body)
}
return '网络错误'
}
- static async ApiVideoPreviewUrlOpenApi(user_id: string, drive_id: string, file_id: string): Promise {
- if (!user_id || !drive_id || !file_id) return undefined
-
- const url = 'adrive/v1.0/openFile/getVideoPreviewPlayInfo'
- const postData = { drive_id: drive_id, file_id: file_id, category: 'live_transcoding', template_id: '', get_subtitle_info: true, url_expire_sec: 14400, with_play_cursor:true }
+ static async ApiVideoPreviewUrl(user_id: string, drive_id: string, file_id: string): Promise {
+ if (!user_id || !drive_id || !file_id) return '参数错误'
+ let url = ''
+ let need_open_api = true
+ if (need_open_api) {
+ url = 'adrive/v1.0/openFile/getVideoPreviewPlayInfo'
+ } else {
+ url = 'v2/file/get_video_preview_play_info'
+ }
+ const postData = {
+ drive_id: drive_id,
+ file_id: file_id,
+ category: 'live_transcoding',
+ template_id: '',
+ get_subtitle_info: true,
+ url_expire_sec: 14400
+ }
const resp = await AliHttp.Post(url, postData, user_id, '')
if (resp.body.code == 'VideoPreviewWaitAndRetry') {
- message.warning('视频正在转码中,稍后重试')
- return undefined
+ return '视频正在转码中,稍后重试'
}
if (resp.body.code == 'ExceedCapacityForbidden') {
- message.warning('容量超限, 请清理超出的容量')
- return undefined
+ return '容量超限限制播放,需要扩容或者删除不必要的文件释放空间'
}
-
const data: IVideoPreviewUrl = {
drive_id: drive_id,
file_id: file_id,
- expire_sec: 0,
+ size: 0,
+ expire_time: 0,
width: 0,
height: 0,
- url: '',
duration: 0,
- play_cursor: 0,
- urlQHD: '',
- urlFHD: '',
- urlHD: '',
- urlSD: '',
- urlLD: '',
+ qualities: [],
subtitles: []
}
if (AliHttp.IsSuccess(resp.code)) {
@@ -184,30 +231,41 @@ export default class AliFile {
}
}
const taskList = resp.body.video_preview_play_info?.live_transcoding_task_list || []
+ const qualityMap: any = {
+ 'LD': { label: '低清', value: '480p' },
+ 'SD': { label: '标清', value: '540P' },
+ 'HD': { label: '高清', value: '720P' },
+ 'FHD': { label: '全高清', value: '1080p' },
+ 'QHD': { label: '超高清', value: '2560p' }
+ }
for (let i = 0, maxi = taskList.length; i < maxi; i++) {
- if (taskList[i].template_id && taskList[i].template_id == 'QHD' && taskList[i].status == 'finished') {
- data.urlQHD = taskList[i].url
- } else if (taskList[i].template_id && taskList[i].template_id == 'FHD' && taskList[i].status == 'finished') {
- data.urlFHD = taskList[i].url
- } else if (taskList[i].template_id && taskList[i].template_id == 'HD' && taskList[i].status == 'finished') {
- data.urlHD = taskList[i].url
- } else if (taskList[i].template_id && taskList[i].template_id == 'SD' && taskList[i].status == 'finished') {
- data.urlSD = taskList[i].url
- } else if (taskList[i].template_id && taskList[i].template_id == 'LD' && taskList[i].status == 'finished') {
- data.urlLD = taskList[i].url
+ if (!taskList[i].url) {
+ continue
+ }
+ let templateId = taskList[i].template_id
+ if (templateId && taskList[i].status == 'finished') {
+ let quality = qualityMap[templateId]
+ data.qualities.push({
+ html: quality.label + ' ' + quality.value,
+ quality: templateId,
+ height: taskList[i].template_height || 0,
+ width: taskList[i].template_width || 0,
+ label: quality.label,
+ value: quality.value,
+ url: taskList[i].url
+ })
}
}
- data.url = data.urlQHD || data.urlFHD || data.urlHD || data.urlSD || data.urlLD || ''
+ data.qualities = data.qualities.sort((a, b) => b.width - a.width)
data.duration = Math.floor(resp.body.video_preview_play_info?.meta?.duration || 0)
data.width = resp.body.video_preview_play_info?.meta?.width || 0
data.height = resp.body.video_preview_play_info?.meta?.height || 0
- data.expire_sec = GetOssExpires(data.url)
- data.play_cursor = Number(resp.body.play_cursor)
+ data.expire_time = GetExpiresTime(data.qualities[0].url)
return data
- } else {
- DebugLog.mSaveWarning('ApiVideoPreviewUrl err=' + file_id + ' ' + (resp.code || ''))
+ } else if (!AliHttp.HttpCodeBreak(resp.code)) {
+ DebugLog.mSaveWarning('ApiVideoPreviewUrl err=' + file_id + ' ' + (resp.code || ''), resp.body)
}
- return undefined
+ return '网络错误'
}
static async ApiListByFileInfo(user_id: string, drive_id: string, file_id: string, limit?: number): Promise {
@@ -229,34 +287,35 @@ export default class AliFile {
category: item.category,
drive_id: item.drive_id,
file_id: item.file_id,
+ file_extension: item.file_extension,
url: item.url,
- expire_sec: GetOssExpires(item.url),
+ expire_time: GetExpiresTime(item.url),
play_cursor: Math.floor(item?.play_cursor || 0),
- compilation_id: item.compilation_id,
+ compilation_id: item.compilation_id
})
}
return data
- } else {
- DebugLog.mSaveWarning('ApiListByFileInfo err=' + file_id + ' ' + (resp.code || ''))
+ } else if (!AliHttp.HttpCodeBreak(resp.code)) {
+ DebugLog.mSaveWarning('ApiListByFileInfo err=' + file_id + ' ' + (resp.code || ''), resp.body)
}
}
- static async ApiAudioPreviewUrl(user_id: string, drive_id: string, file_id: string): Promise {
- if (!user_id || !drive_id || !file_id) return undefined
-
+ static async ApiAudioPreviewUrl(user_id: string, drive_id: string, file_id: string): Promise {
+ if (!user_id || !drive_id || !file_id) return '参数错误'
+
const url = 'v2/file/get_audio_play_info'
-
+
const postData = { drive_id: drive_id, file_id: file_id, url_expire_sec: 14400 }
const resp = await AliHttp.Post(url, postData, user_id, '')
if (resp.body.code == 'AudioPreviewWaitAndRetry') {
- message.warning('音频正在转码中,稍后重试')
+ return '音频正在转码中,稍后重试'
}
const data: IDownloadUrl = {
drive_id: drive_id,
file_id: file_id,
- expire_sec: 0,
+ expire_time: 0,
url: '',
size: 0
}
@@ -264,20 +323,28 @@ export default class AliFile {
const template_list = resp.body.template_list || []
if (!data.url) {
for (let i = 0, maxi = template_list.length; i < maxi; i++) {
- if (template_list[i].template_id && template_list[i].template_id == 'HQ' && template_list[i].status == 'finished') data.url = template_list[i].url
+ if (template_list[i].template_id
+ && template_list[i].template_id == 'HQ'
+ && template_list[i].status == 'finished') {
+ data.url = template_list[i].url
+ }
}
}
if (!data.url) {
for (let i = 0, maxi = template_list.length; i < maxi; i++) {
- if (template_list[i].template_id && template_list[i].template_id == 'LQ' && template_list[i].status == 'finished') data.url = template_list[i].url
+ if (template_list[i].template_id
+ && template_list[i].template_id == 'LQ'
+ && template_list[i].status == 'finished') {
+ data.url = template_list[i].url
+ }
}
}
return data
- } else {
- DebugLog.mSaveWarning('ApiAudioPreviewUrl err=' + file_id + ' ' + (resp.code || ''))
+ } else if (!AliHttp.HttpCodeBreak(resp.code)) {
+ DebugLog.mSaveWarning('ApiAudioPreviewUrl err=' + file_id + ' ' + (resp.code || ''), resp.body)
}
- return undefined
+ return '网络错误'
}
static async ApiOfficePreViewUrl(user_id: string, drive_id: string, file_id: string): Promise {
@@ -295,22 +362,35 @@ export default class AliFile {
data.access_token = resp.body.access_token
data.preview_url = resp.body.preview_url
return data
- } else {
- DebugLog.mSaveWarning('ApiOfficePreViewUrl err=' + file_id + ' ' + (resp.code || ''))
+ } else if (!AliHttp.HttpCodeBreak(resp.code)) {
+ DebugLog.mSaveWarning('ApiOfficePreViewUrl err=' + file_id + ' ' + (resp.code || ''), resp.body)
}
return undefined
}
static async ApiGetFile(user_id: string, drive_id: string, file_id: string): Promise {
if (!user_id || !drive_id || !file_id) return undefined
- const fileItem = await AliFile.ApiFileInfoOpenApi(user_id, drive_id, file_id);
- if (fileItem) {
- return AliDirFileList.getFileInfo(fileItem, '')
+ const url = 'v2/file/get'
+ const postData = {
+ drive_id: drive_id,
+ file_id: file_id,
+ url_expire_sec: 14400,
+ office_thumbnail_process: 'image/resize,w_400/format,jpeg',
+ image_thumbnail_process: 'image/resize,w_400/format,jpeg',
+ image_url_process: 'image/resize,w_1920/format,jpeg',
+ video_thumbnail_process: 'video/snapshot,t_106000,f_jpg,ar_auto,m_fast,w_400'
+ }
+ const resp = await AliHttp.Post(url, postData, user_id, '')
+
+ if (AliHttp.IsSuccess(resp.code)) {
+ return AliDirFileList.getFileInfo(user_id, resp.body as IAliFileItem, '')
+ } else if (!AliHttp.HttpCodeBreak(resp.code)) {
+ DebugLog.mSaveWarning('ApiGetFile err=' + file_id + ' ' + (resp.code || ''), resp.body)
}
return undefined
}
-
+
static async ApiFileGetPath(user_id: string, drive_id: string, file_id: string): Promise {
if (!user_id || !drive_id || !file_id) return []
const url = 'adrive/v1/file/get_path'
@@ -319,72 +399,84 @@ export default class AliFile {
file_id: file_id
}
const resp = await AliHttp.Post(url, postData, user_id, '')
-
- if (AliHttp.IsSuccess(resp.code) && resp.body.items && resp.body.items.length > 0) {
+ const driveType = GetDriveType(user_id, drive_id)
+ let items = resp.body.items
+ if (AliHttp.IsSuccess(resp.code) && items && items.length > 0) {
const list: IAliGetDirModel[] = []
- for (let i = resp.body.items.length - 1; i > 0; i--) {
- const item = resp.body.items[i]
- list.push({
- __v_skip: true,
- drive_id: item.drive_id,
- file_id: item.file_id,
- parent_file_id: item.parent_file_id || '',
- name: item.name,
- namesearch: HanToPin(item.name),
- size: item.size || 0,
- time: new Date(item.updated_at).getTime(),
-
- description: item.description || ''
- } as IAliGetDirModel)
- }
list.push({
__v_skip: true,
drive_id: drive_id,
- file_id: 'root',
+ album_id: '',
+ file_id: driveType.key,
parent_file_id: '',
- name: '根目录',
- namesearch: HanToPin('root'),
+ name: driveType.title,
+ namesearch: HanToPin(driveType.title),
size: 0,
time: 0,
-
description: ''
} as IAliGetDirModel)
+ for (let i = items.length - 1; i >= 0; i--) {
+ const item = items[i]
+ if (item.name === 'Default' || item.name === 'resource' || item.name === 'alibum') {
+ continue
+ }
+ list.push({
+ __v_skip: true,
+ drive_id: item.drive_id,
+ album_id: '',
+ file_id: item.file_id,
+ parent_file_id: item.parent_file_id || '',
+ name: DecodeEncName(user_id, item).name,
+ namesearch: HanToPin(item.name),
+ size: item.size || 0,
+ time: new Date(item.updated_at).getTime(),
+ description: item.description || ''
+ } as IAliGetDirModel)
+ }
return list
- } else {
- DebugLog.mSaveWarning('ApiFileGetPath err=' + file_id + ' ' + (resp.code || ''))
+ } else if (!AliHttp.HttpCodeBreak(resp.code)) {
+ DebugLog.mSaveWarning('ApiFileGetPath err=' + file_id + ' ' + (resp.code || ''), resp.body)
}
return []
}
-
+
static async ApiFileGetPathString(user_id: string, drive_id: string, file_id: string, dirsplit: string): Promise {
if (!user_id || !drive_id || !file_id) return ''
- if (file_id == 'root') return '根目录'
+ if (file_id.includes('root')) {
+ if (file_id.startsWith('backup')) {
+ return '备份盘'
+ } else if (file_id.startsWith('resource')) {
+ return '资源盘'
+ } else if (file_id.startsWith('pic')) {
+ return '相册'
+ }
+ }
const url = 'adrive/v1/file/get_path'
const postData = {
drive_id: drive_id,
file_id: file_id
}
const resp = await AliHttp.Post(url, postData, user_id, '')
-
if (AliHttp.IsSuccess(resp.code) && resp.body.items && resp.body.items.length > 0) {
- const list: string[] = []
+ const driveType = GetDriveType(user_id, drive_id)
+ const list: string[] = [driveType.title]
for (let i = resp.body.items.length - 1; i >= 0; i--) {
const item = resp.body.items[i]
- list.push(item.name)
+ list.push(DecodeEncName(user_id, item).name)
}
return list.join(dirsplit)
- } else {
- DebugLog.mSaveWarning('ApiFileGetPathString err=' + file_id + ' ' + (resp.code || ''))
+ } else if (!AliHttp.HttpCodeBreak(resp.code)) {
+ DebugLog.mSaveWarning('ApiFileGetPathString err=' + file_id + ' ' + (resp.code || ''), resp.body)
}
return ''
}
-
+
static async ApiFileGetFolderSize(user_id: string, drive_id: string, file_id: string): Promise {
if (!user_id || !drive_id || !file_id) return undefined
const url = 'adrive/v1/file/get_folder_size_info'
-
+
const postData = {
drive_id: drive_id,
file_id: file_id
@@ -393,31 +485,31 @@ export default class AliFile {
if (AliHttp.IsSuccess(resp.code)) {
return resp.body as IAliGetForderSizeModel
- } else {
- DebugLog.mSaveWarning('ApiFileGetFolderSize err=' + file_id + ' ' + (resp.code || ''))
+ } else if (!AliHttp.HttpCodeBreak(resp.code)) {
+ DebugLog.mSaveWarning('ApiFileGetFolderSize err=' + file_id + ' ' + (resp.code || ''), resp.body)
}
return { size: 0, folder_count: 0, file_count: 0, reach_limit: false }
}
-
- static async ApiFileDownText(user_id: string, drive_id: string, file_id: string, filesize: number, maxsize: number): Promise {
+
+ static async ApiFileDownText(user_id: string, drive_id: string, file_id: string, filesize: number, maxsize: number, encType: string = '', password: string = ''): Promise {
if (!user_id || !drive_id || !file_id) return ''
- const downUrl = await AliFile.ApiFileDownloadUrlOpenApi(user_id, drive_id, file_id, 14400)
+ const downUrl = await getRawUrl(user_id, drive_id, file_id, encType, password)
if (typeof downUrl == 'string') return downUrl
// 原始文件大小
if (filesize === -1) filesize = downUrl.size
if (maxsize === -1) maxsize = downUrl.size
- const resp = await AliHttp.GetString(downUrl.url, '', filesize, maxsize)
+ const resp = await AliHttp.GetString(downUrl.url, '', filesize, maxsize)
if (AliHttp.IsSuccess(resp.code)) {
if (typeof resp.body == 'string') return resp.body
return JSON.stringify(resp.body, undefined, 2)
- } else {
- DebugLog.mSaveWarning('ApiFileDownText err=' + file_id + ' ' + (resp.code || ''))
+ } else if (!AliHttp.HttpCodeBreak(resp.code)) {
+ DebugLog.mSaveWarning('ApiFileDownText err=' + file_id + ' ' + (resp.code || ''), resp.body)
}
return ''
}
-
+
static async ApiBiXueTuBatch(user_id: string, drive_id: string, file_id: string, duration: number, imageCount: number, imageWidth: number): Promise {
if (!user_id || !drive_id || !file_id) return []
if (duration <= 0) return []
@@ -431,7 +523,12 @@ export default class AliFile {
mtime += subtime
if (mtime > duration) break
const postData = {
- body: { drive_id: drive_id, file_id: file_id, url_expire_sec: 14400, video_thumbnail_process: 'video/snapshot,t_' + mtime.toString() + '000,f_jpg,ar_auto,m_fast,w_' + imageWidth.toString() },
+ body: {
+ drive_id: drive_id,
+ file_id: file_id,
+ url_expire_sec: 14400,
+ video_thumbnail_process: 'video/snapshot,t_' + mtime.toString() + '000,f_jpg,ar_auto,m_fast,w_' + imageWidth.toString()
+ },
headers: { 'Content-Type': 'application/json' },
id: (i.toString() + file_id).substr(0, file_id.length),
method: 'POST',
@@ -475,51 +572,33 @@ export default class AliFile {
console.log(responses[i])
}
}
- } else {
- DebugLog.mSaveWarning('ApiBiXueTuBatch err=' + file_id + ' ' + (resp.code || ''))
+ } else if (!AliHttp.HttpCodeBreak(resp.code)) {
+ DebugLog.mSaveWarning('ApiBiXueTuBatch err=' + file_id + ' ' + (resp.code || ''), resp.body)
}
return imgList
}
- static async ApiUpdateVideoTimeOpenApi(user_id: string, drive_id: string, file_id: string, play_cursor: number): Promise {
+
+ static async ApiUpdateVideoTime(user_id: string, drive_id: string, file_id: string, play_cursor: number): Promise {
if (!useSettingStore().uiAutoPlaycursorVideo) return
if (!user_id || !drive_id || !file_id) return undefined
- const upateCursorUrl = 'adrive/v1.0/openFile/video/updateRecord'
- const postData = {
- "drive_id": drive_id,
- "file_id": file_id,
- "play_cursor":play_cursor.toString()
+ let url = ''
+ let need_open_api = true
+ if (need_open_api) {
+ url = 'adrive/v1.0/openFile/video/updateRecord'
+ } else {
+ url = 'adrive/v2/video/update'
}
- const respvideo = await AliHttp.Post(upateCursorUrl, postData, user_id, '')
+ const postVideoData = {
+ drive_id: drive_id,
+ file_id: file_id,
+ play_cursor: Math.trunc(play_cursor).toString()
+ }
+ const respvideo = await AliHttp.Post(url, postVideoData, user_id, '')
if (AliHttp.IsSuccess(respvideo.code)) {
return respvideo.body as IAliFileItem
} else {
- DebugLog.mSaveWarning('ApiUpdateVideoTime2 err=' + file_id + ' ' + (respvideo.code || ''))
- }
- return undefined
- }
-
-
- static async ApiUpdateVideoTime(user_id: string, drive_id: string, file_id: string, play_cursor: number): Promise {
- if (!useSettingStore().uiAutoPlaycursorVideo) return
- if (!user_id || !drive_id || !file_id) return undefined
- const resp = await AliFile.ApiFileInfoOpenApi(user_id, drive_id, file_id)
- if (resp) {
- const urlvideo = 'adrive/v2/video/update'
- const postVideoData = {
- drive_id: drive_id,
- file_id: file_id,
- play_cursor: play_cursor.toString(),
- thumbnail: resp.thumbnail || ''
- }
- const respvideo = await AliHttp.Post(urlvideo, postVideoData, user_id, '')
- if (AliHttp.IsSuccess(respvideo.code)) {
- return respvideo.body as IAliFileItem
- } else {
- DebugLog.mSaveWarning('ApiUpdateVideoTime2 err=' + file_id + ' ' + (respvideo.code || ''))
- }
- } else {
- DebugLog.mSaveWarning('ApiUpdateVideoTime err=' + file_id)
+ DebugLog.mSaveWarning('ApiUpdateVideoTime err=' + file_id + ' ' + (respvideo.code || ''), respvideo.body)
}
return undefined
}
diff --git a/aliyunpan/src/aliapi/filecmd.ts b/aliyunpan/src/aliapi/filecmd.ts
index ff55e857e1..8a7d8fd84d 100644
--- a/aliyunpan/src/aliapi/filecmd.ts
+++ b/aliyunpan/src/aliapi/filecmd.ts
@@ -1,57 +1,44 @@
import DebugLog from '../utils/debuglog'
-import message from '../utils/message'
import AliHttp from './alihttp'
import { IAliFileItem, IAliGetFileModel } from './alimodels'
import AliDirFileList from './dirfilelist'
-import { ApiBatch, ApiBatchMaker, ApiBatchMaker2, ApiBatchSuccess } from './utils'
-import AliFile from "./file";
-import path from "path";
+import { ApiBatch, ApiBatchMaker, ApiBatchMaker2, ApiBatchSuccess, EncodeEncName } from './utils'
+import { IDownloadUrl } from './models'
+import AliFile from './file'
+import message from '../utils/message'
export default class AliFileCmd {
-
- static async ApiCreatNewForder(user_id: string, drive_id: string, parent_file_id: string, creatDirName: string): Promise<{ file_id: string; error: string }> {
+ static async ApiCreatNewForder(
+ user_id: string, drive_id: string,
+ parent_file_id: string, creatDirName: string,
+ encType: string = '', check_name_mode: string = 'refuse'
+ ): Promise<{ file_id: string; error: string }> {
const result = { file_id: '', error: '新建文件夹失败' }
if (!user_id || !drive_id || !parent_file_id) return result
- const url = 'adrive/v1.0/openFile/create'
- const pathSplitor = creatDirName.split(path.sep);
- if (pathSplitor.length > 1) {
- let parentFileId = parent_file_id;
- for (let i = 0; i < pathSplitor.length; i++) {
- const folderName = pathSplitor[i];
- const resp = await AliFileCmd.ApiCreatNewForder(user_id, drive_id, parentFileId, folderName);
- parentFileId = resp.file_id
- }
- return { file_id:parentFileId, error: '' }
- } else if (path.sep === '\\' && creatDirName.split('/').length > 1) {
- let parentFileId = parent_file_id;
- for (let i = 0; i < creatDirName.split('/').length; i++) {
- const folderName = creatDirName.split('/')[i];
- const resp = await AliFileCmd.ApiCreatNewForder(user_id, drive_id, parentFileId, folderName);
- parentFileId = resp.file_id
- }
- return { file_id:parentFileId, error: '' }
- }
-
+ if (parent_file_id.includes('root')) parent_file_id = 'root'
+ const url = 'adrive/v2/file/createWithFolders'
+ const name = EncodeEncName(user_id, creatDirName, true, encType)
const postData = JSON.stringify({
drive_id: drive_id,
parent_file_id: parent_file_id,
- name: creatDirName,
- check_name_mode: 'refuse',
- type: 'folder'
+ name: name,
+ check_name_mode: check_name_mode,
+ type: 'folder',
+ description: encType
})
const resp = await AliHttp.Post(url, postData, user_id, '')
if (AliHttp.IsSuccess(resp.code)) {
const file_id = resp.body.file_id as string | undefined
if (file_id) return { file_id, error: '' }
- } else {
- DebugLog.mSaveWarning('ApiCreatNewForder err=' + parent_file_id + ' ' + (resp.code || ''))
+ } else if (!AliHttp.HttpCodeBreak(resp.code)) {
+ DebugLog.mSaveWarning('ApiCreatNewForder err=' + parent_file_id + ' ' + (resp.code || ''), resp.body)
}
if (resp.body?.code == 'QuotaExhausted.Drive') return { file_id: '', error: '网盘空间已满,无法创建' }
if (resp.body?.code) return { file_id: '', error: resp.body?.code }
return result
}
-
+
static async ApiTrashBatch(user_id: string, drive_id: string, file_idList: string[]): Promise {
const batchList = ApiBatchMaker('/recyclebin/trash', file_idList, (file_id: string) => {
return { drive_id: drive_id, file_id: file_id }
@@ -59,7 +46,7 @@ export default class AliFileCmd {
return ApiBatchSuccess('放入回收站', batchList, user_id, '')
}
-
+
static async ApiDeleteBatch(user_id: string, drive_id: string, file_idList: string[]): Promise {
const batchList = ApiBatchMaker('/file/delete', file_idList, (file_id: string) => {
return { drive_id: drive_id, file_id: file_id }
@@ -67,8 +54,13 @@ export default class AliFileCmd {
return ApiBatchSuccess('彻底删除', batchList, user_id, '')
}
-
- static async ApiRenameBatch(user_id: string, drive_id: string, file_idList: string[], names: string[]): Promise<{ file_id: string; parent_file_id: string; name: string; isDir: boolean }[]> {
+
+ static async ApiRenameBatch(user_id: string, drive_id: string, file_idList: string[], names: string[]): Promise<{
+ file_id: string;
+ parent_file_id: string;
+ name: string;
+ isDir: boolean
+ }[]> {
const batchList = ApiBatchMaker2('/file/update', file_idList, names, (file_id: string, name: string) => {
return { drive_id: drive_id, file_id: file_id, name: name, check_name_mode: 'refuse' }
})
@@ -76,11 +68,16 @@ export default class AliFileCmd {
if (batchList.length == 0) return Promise.resolve([])
const successList: { file_id: string; parent_file_id: string; name: string; isDir: boolean }[] = []
const result = await ApiBatch(file_idList.length <= 1 ? '' : '批量重命名', batchList, user_id, '')
- result.reslut.map((t) => successList.push({ file_id: t.file_id!, name: t.name!, parent_file_id: t.parent_file_id!, isDir: t.type !== 'folder' }))
+ result.reslut.map((t) => successList.push({
+ file_id: t.file_id!,
+ name: t.name!,
+ parent_file_id: t.parent_file_id!,
+ isDir: t.type !== 'folder'
+ }))
return successList
}
-
+
static async ApiFavorBatch(user_id: string, drive_id: string, isfavor: boolean, ismessage: boolean, file_idList: string[]): Promise {
const batchList = ApiBatchMaker('/file/update', file_idList, (file_id: string) => {
return { drive_id: drive_id, file_id: file_id, custom_index_key: isfavor ? 'starred_yes' : '', starred: isfavor }
@@ -88,7 +85,7 @@ export default class AliFileCmd {
return ApiBatchSuccess(ismessage ? (isfavor ? '收藏文件' : '取消收藏') : '', batchList, user_id, '')
}
-
+
static async ApiTrashCleanBatch(user_id: string, drive_id: string, ismessage: boolean, file_idList: string[]): Promise {
const batchList = ApiBatchMaker('/file/delete', file_idList, (file_id: string) => {
return { drive_id: drive_id, file_id: file_id }
@@ -96,7 +93,7 @@ export default class AliFileCmd {
return ApiBatchSuccess(ismessage ? '从回收站删除' : '', batchList, user_id, '')
}
-
+
static async ApiTrashRestoreBatch(user_id: string, drive_id: string, ismessage: boolean, file_idList: string[]): Promise {
const batchList = ApiBatchMaker('/recyclebin/restore', file_idList, (file_id: string) => {
return { drive_id: drive_id, file_id: file_id }
@@ -104,16 +101,55 @@ export default class AliFileCmd {
return ApiBatchSuccess(ismessage ? '从回收站还原' : '', batchList, user_id, '')
}
-
- static async ApiFileColorBatch(user_id: string, drive_id: string, color: string, file_idList: string[]): Promise {
- const batchList = ApiBatchMaker('/file/update', file_idList, (file_id: string) => {
- return { drive_id: drive_id, file_id: file_id, description: color }
- })
- return ApiBatchSuccess(color == '' ? '清除文件标记' : color == 'c5b89b8' ? '' : '标记文件', batchList, user_id, '')
+ static async ApiFileHistoryBatch(user_id: string, drive_id: string, file_idList: string[]) {
+ let allTask = []
+ const loadingKey = 'filehistorybatch' + Date.now().toString()
+ message.loading('清除历史 执行中...', 60, loadingKey)
+ for (const file_id of file_idList) {
+ allTask.push(AliFile.ApiUpdateVideoTime(user_id, drive_id, file_id, 0))
+ if (allTask.length >= 3) {
+ await Promise.all(allTask).catch()
+ allTask = []
+ }
+ }
+ if (allTask.length > 0) {
+ await Promise.all(allTask).catch()
+ }
+ message.success('成功执行 清除历史', 1, loadingKey)
}
-
- static async ApiRecoverBatch(user_id: string, resumeList: { drive_id: string; file_id: string; content_hash: string; size: number; name: string }[]): Promise {
+ static async ApiFileColorBatch(user_id: string, drive_id: string, description: string, color: string, file_idList: string[]): Promise {
+ // 防止加密标记清空
+ if (color && color != 'notEncrypt') {
+ let parts = description.split(',') || []
+ let encryptPart = parts.find((part: any) => part.includes('xbyEncrypt')) || ''
+ let colorPart = color || parts.find((part: any) => /c.{6}$/.test(part)) || ''
+ color = color ? [encryptPart, colorPart].filter(Boolean).join(',') : encryptPart
+ } else {
+ color = ''
+ }
+ let batchList = ApiBatchMaker('/file/update', file_idList, (file_id: string) => {
+ return { drive_id: drive_id, file_id: file_id, description: color }
+ })
+ let title = ''
+ if (color == '') {
+ title = '清除标记'
+ } else if (color.includes('ce74c3c')) {
+ title = ''
+ } else if (color.includes('xbyEncrypt')) {
+ title = '标记加密'
+ }
+ return ApiBatchSuccess(title, batchList, user_id, '')
+ }
+
+
+ static async ApiRecoverBatch(user_id: string, resumeList: {
+ drive_id: string;
+ file_id: string;
+ content_hash: string;
+ size: number;
+ name: string
+ }[]): Promise {
const successList: string[] = []
if (!resumeList || resumeList.length == 0) return Promise.resolve(successList)
@@ -127,7 +163,7 @@ export default class AliFileCmd {
const url2 = 'adrive/v1/file/checkResumeTask'
const resp2 = await AliHttp.Post(url2, { task_id }, user_id, '')
if (AliHttp.IsSuccess(resp2.code)) {
-
+
if (resp2.body.state == 'running') continue
if (resp2.body.state == 'done') {
const results = resp2.body.results as any[]
@@ -137,60 +173,63 @@ export default class AliFileCmd {
return true
})
}
- return successList
+ return successList
}
}
}
} else if (resp.code && resp.code == 403) {
- if (resp.body?.code == 'UserNotVip') message.error('文件恢复功能需要开通阿里云盘会员')
- else message.error(resp.body?.code || '拒绝访问')
- } else {
- DebugLog.mSaveWarning('ApiRecoverBatch err=' + (resp.code || ''))
- message.error('操作失败')
+ if (resp.body?.code == 'UserNotVip') return '文件恢复功能需要开通阿里云盘会员'
+ else return resp.body?.code || '拒绝访问'
+ } else if (!AliHttp.HttpCodeBreak(resp.code)) {
+ DebugLog.mSaveWarning('ApiRecoverBatch err=' + (resp.code || ''), resp.body)
+ return '操作失败'
}
return successList
}
-
+
static async ApiMoveBatch(user_id: string, drive_id: string, file_idList: string[], to_drive_id: string, to_parent_file_id: string): Promise {
+ if (to_parent_file_id.includes('root')) to_parent_file_id = 'root'
const batchList = ApiBatchMaker('/file/move', file_idList, (file_id: string) => {
- if (drive_id == to_drive_id) return { drive_id: drive_id, file_id: file_id, to_parent_file_id: to_parent_file_id, auto_rename: true }
- else return { drive_id: drive_id, file_id: file_id, to_drive_id: to_drive_id, to_parent_file_id: to_parent_file_id, auto_rename: true }
+ if (drive_id == to_drive_id) return {
+ drive_id: drive_id,
+ file_id: file_id,
+ to_parent_file_id: to_parent_file_id,
+ auto_rename: true
+ }
+ else return {
+ drive_id: drive_id,
+ file_id: file_id,
+ to_drive_id: to_drive_id,
+ to_parent_file_id: to_parent_file_id,
+ auto_rename: true
+ }
})
return ApiBatchSuccess(file_idList.length <= 1 ? '移动' : '批量移动', batchList, user_id, '')
}
-
+
static async ApiCopyBatch(user_id: string, drive_id: string, file_idList: string[], to_drive_id: string, to_parent_file_id: string): Promise {
+ if (to_parent_file_id.includes('root')) to_parent_file_id = 'root'
const batchList = ApiBatchMaker('/file/copy', file_idList, (file_id: string) => {
- if (drive_id == to_drive_id) return { drive_id: drive_id, file_id: file_id, to_parent_file_id: to_parent_file_id, auto_rename: true }
- else return { drive_id: drive_id, file_id: file_id, to_drive_id: to_drive_id, to_parent_file_id: to_parent_file_id, auto_rename: true }
+ if (drive_id == to_drive_id) return {
+ drive_id: drive_id,
+ file_id: file_id,
+ to_parent_file_id: to_parent_file_id,
+ auto_rename: true
+ }
+ else return {
+ drive_id: drive_id,
+ file_id: file_id,
+ to_drive_id: to_drive_id,
+ to_parent_file_id: to_parent_file_id,
+ auto_rename: true
+ }
})
return ApiBatchSuccess(file_idList.length <= 1 ? '复制' : '批量复制', batchList, user_id, '')
}
- static async ApiGetFileBatchOpenApi(user_id: string, drive_id: string, file_idList: string[]): Promise {
- const url = "adrive/v1.0/openFile/batch/get"
- const file_list: { file_id: string, drive_id: string}[] = []
- file_idList.map((file_id) => {
- file_list.push({drive_id, file_id})
- })
- const postData = {
- file_list: file_list
- }
- const successList: IAliGetFileModel[] = []
- const result = await AliHttp.Post(url, postData, user_id, '')
- if (AliHttp.IsSuccess(result.code)) {
- const fileItems = result.body.items as IAliFileItem[]
- fileItems.forEach((fileItem) => {
- successList.push(AliDirFileList.getFileInfo(fileItem, 'download_url'))
- })
- }
- return successList
- }
-
-
static async ApiGetFileBatch(user_id: string, drive_id: string, file_idList: string[]): Promise {
const batchList = ApiBatchMaker('/file/get', file_idList, (file_id: string) => {
return {
@@ -205,21 +244,25 @@ export default class AliFileCmd {
})
const successList: IAliGetFileModel[] = []
const result = await ApiBatch('', batchList, user_id, '')
- result.reslut.map(async (t) => {
- if (t.body) {
- const fileItem = t.body as IAliFileItem
- if (fileItem.type === 'file') {
- const fileDetails = await AliFile.ApiFileInfoOpenApi(user_id, drive_id, fileItem.file_id);
- fileItem.thumbnail = fileDetails?.thumbnail
- fileItem.url = fileDetails?.url || fileItem.url
- fileItem.download_url = fileDetails?.download_url || fileItem.download_url
- fileItem.starred = fileDetails?.starred || fileItem.starred
- fileItem.trashed = fileDetails?.trashed || fileItem.trashed
- fileItem.deleted = fileDetails?.deleted || fileItem.deleted
- fileItem.description = fileDetails?.description || fileItem.description
- }
- successList.push(AliDirFileList.getFileInfo(t.body as IAliFileItem, 'download_url'))
+ result.reslut.map((t) => {
+ if (t.body) successList.push(AliDirFileList.getFileInfo(user_id, t.body as IAliFileItem, 'download_url'))
+ return true
+ })
+ return successList
+ }
+
+ static async ApiGetFileDownloadUrlBatch(user_id: string, drive_id: string, file_idList: string[]): Promise {
+ const batchList = ApiBatchMaker('/file/get_download_url', file_idList, (file_id: string) => {
+ return {
+ drive_id: drive_id,
+ file_id: file_id,
+ expire_sec: 14400
}
+ })
+ const successList: IDownloadUrl[] = []
+ const result = await ApiBatch('', batchList, user_id, '')
+ result.reslut.map((t) => {
+ if (t.body) successList.push(t.body as IDownloadUrl)
return true
})
return successList
diff --git a/aliyunpan/src/aliapi/fileicon.ts b/aliyunpan/src/aliapi/fileicon.ts
index 65481557d0..1b08c9fa74 100644
--- a/aliyunpan/src/aliapi/fileicon.ts
+++ b/aliyunpan/src/aliapi/fileicon.ts
@@ -52,11 +52,11 @@ export default function getFileIcon(category: string | undefined, ext: string |
if (';.apng.avif.ico.webp.gif.'.indexOf(ext) > 0) {
- return ['image2', 'iconfile-img']
+ return ['image2', 'iconfile-img']
}
if (category == 'image') {
- return ['image', 'iconfile-img']
+ return ['image', 'iconfile-img']
}
if (mime.startsWith('image/')) return ['image3', 'iconfile-image']
@@ -66,28 +66,24 @@ export default function getFileIcon(category: string | undefined, ext: string |
if (';.pot.ett.'.indexOf(ext) > 0) return ['doc2', 'iconfile-doc']
if ((mimext.startsWith('.txt') || mimext.startsWith('.doc') || mimext.startsWith('.ppt')) && ';.dps.dpt.potm.potx.pps.ppsm.ppsx.ppt.pptm.pptx.'.indexOf(ext) > 0) return ['doc', 'iconfile-ppt']
if ((mimext.startsWith('.txt') || mimext.startsWith('.xls')) && ';.xls.xlsx.et.xlsm.xlt.xltm.xltx.'.indexOf(ext) > 0) return ['doc', 'iconfile-xsl']
-
- if (mime.startsWith('text/')) return ['others', 'iconfile_txt2']
+ if (mime.startsWith('text/')) return ['others', 'iconfile_txt2']
if (ext == '.json.') return ['others', 'iconfile_txt2']
-
if (category == 'video') {
-
return ['video', 'iconfile_video']
}
- if (mime.startsWith('video/')) return ['video2', 'iconfile_video']
if (ext == '.ts.' && size > 5 * 1024 * 1024) return ['video2', 'iconfile_video']
if (';.3iv.cpk.divx.hdv.fli.f4v.f4p.m2t.m2ts.mts.trp.mkv.mp4.mpg4.nsv.nut.nuv.rm.rmvb.vob.wmv.mk3d.hevc.yuv.y4m.mov.avi.flv.mpg.3gp.m4v.mpeg.asf.wmz.webm.pmp.mpga'.indexOf(ext) > 0) {
return ['video2', 'iconfile_video']
}
if (ext == '.mp3.' && category == 'audio') return ['audio', 'iconfile-mp3']
if (category == 'audio' && mimext != '.unknown.') {
-
return ['audio', 'iconfile-audio']
}
if (mime.startsWith('audio/')) return ['audio', 'iconfile-audio']
if (';.ape.aac.cda.dsf.dtshd.eac3.m1a.m2a.m4a.mka.mpa.mpc.opus.ra.tak.tta.wma.wv.'.indexOf(ext) > 0) {
return ['audio2', 'iconfile-audio']
}
+ if (mime.startsWith('video/')) return ['video2', 'iconfile_video']
return ['others', 'iconwenjian']
}
diff --git a/aliyunpan/src/aliapi/filewalk.ts b/aliyunpan/src/aliapi/filewalk.ts
index c049657e8e..ca7a27a9bb 100644
--- a/aliyunpan/src/aliapi/filewalk.ts
+++ b/aliyunpan/src/aliapi/filewalk.ts
@@ -20,7 +20,7 @@ export default class AliFileWalk {
const orders = order.split(' ')
do {
const isGet = await AliFileWalk._ApiWalkFileListOnePage(orders[0], orders[1], dir, type)
- if (isGet != true) {
+ if (!isGet) {
break
}
if (dir.items.length >= max && max > 0) {
@@ -32,7 +32,7 @@ export default class AliFileWalk {
}
private static async _ApiWalkFileListOnePage(orderby: string, order: string, dir: IAliFileResp, type: string = '') {
- const url = 'v2/file/walk?jsonmask=next_marker%2Cpunished_file_count%2Ctotal_count%2Citems(category%2Ccreated_at%2Cdomain_id%2Cdrive_id%2Cfile_extension%2Cfile_id%2Chidden%2Cmime_extension%2Cmime_type%2Cname%2Cparent_file_id%2Cpunish_flag%2Csize%2Cstarred%2Ctype%2Cupdated_at%2Cdescription)'
+ const url = 'v2/file/walk?jsonmask=next_marker%2Citems(category%2Ccreated_at%2Cdrive_id%2Cfile_extension%2Cfile_id%2Chidden%2Cmime_extension%2Cmime_type%2Cname%2Cparent_file_id%2Cpunish_flag%2Csize%2Cstarred%2Ctype%2Cupdated_at%2Cdescription)'
let postData = {
drive_id: dir.m_drive_id,
parent_file_id: dir.dirID,
@@ -54,12 +54,12 @@ export default class AliFileWalk {
if (AliHttp.IsSuccess(resp.code)) {
dir.next_marker = resp.body.next_marker
const isRecover = dir.dirID == 'recover'
- const downUrl = isRecover ? '' : 'https://api.aliyundrive.com/v2/file/download?t=' + Date.now().toString()
+ const downUrl = isRecover ? '' : 'https://api.alipan.com/v2/file/download?t=' + Date.now().toString()
for (let i = 0, maxi = resp.body.items.length; i < maxi; i++) {
const item = resp.body.items[i] as IAliFileItem
if (dir.itemsKey.has(item.file_id)) continue
- const add = AliDirFileList.getFileInfo(item, downUrl)
+ const add = AliDirFileList.getFileInfo(dir.m_user_id, item, downUrl)
if (isRecover) add.description = item.content_hash
dir.items.push(add)
dir.itemsKey.add(item.file_id)
@@ -74,11 +74,11 @@ export default class AliFileWalk {
return true
} else if (resp.body && resp.body.code) {
dir.items.length = 0
- dir.next_marker = resp.body.code
+ dir.next_marker = resp.body.code
// message.warning('列出文件出错 ' + resp.body.code, 2)
return false
- } else {
- DebugLog.mSaveWarning('_FileListOnePage err=' + (resp.code || ''))
+ } else if (!AliHttp.HttpCodeBreak(resp.code)) {
+ DebugLog.mSaveWarning('_FileListOnePage err=' + (resp.code || ''), resp.body)
}
} catch (err: any) {
DebugLog.mSaveDanger('_FileListOnePage ' + dir.dirID, err)
diff --git a/aliyunpan/src/aliapi/following.ts b/aliyunpan/src/aliapi/following.ts
index 1e17bdbc98..116bda9bf0 100644
--- a/aliyunpan/src/aliapi/following.ts
+++ b/aliyunpan/src/aliapi/following.ts
@@ -2,7 +2,7 @@ import { humanTimeAgo } from '../utils/format'
import message from '../utils/message'
import DebugLog from '../utils/debuglog'
import AliHttp, { IUrlRespData } from './alihttp'
-import { IAliOtherFollowingModel, IAliMyFollowingModel } from './alimodels'
+import { IAliMyFollowingModel, IAliOtherFollowingModel } from './alimodels'
export interface IAliOtherFollowingResp {
items: IAliOtherFollowingModel[]
@@ -77,8 +77,8 @@ export default class AliFollowing {
dir.next_marker = resp.body.code
message.warning('列出官方推荐列表出错' + resp.body.code, 2)
return false
- } else {
- DebugLog.mSaveWarning('_OtherFollowingListOnePage err=' + (resp.code || ''))
+ } else if (!AliHttp.HttpCodeBreak(resp.code)) {
+ DebugLog.mSaveWarning('_OtherFollowingListOnePage err=' + (resp.code || ''), resp.body)
}
} catch (err: any) {
DebugLog.mSaveDanger('_OtherFollowingListOnePage', err)
@@ -101,8 +101,8 @@ export default class AliFollowing {
do {
const isGet = await AliFollowing.ApiMyFollowingListOnePage(dir)
- if (isGet != true) {
- break
+ if (!isGet) {
+ break
}
} while (dir.next_marker)
return dir
@@ -165,8 +165,8 @@ export default class AliFollowing {
dir.next_marker = resp.body.code
message.warning('列出订阅列表出错' + resp.body.code, 2)
return false
- } else {
- DebugLog.mSaveWarning('_MyFollowingListOnePage err=' + (resp.code || ''))
+ } else if (!AliHttp.HttpCodeBreak(resp.code)) {
+ DebugLog.mSaveWarning('_MyFollowingListOnePage err=' + (resp.code || ''), resp.body)
}
} catch (err: any) {
DebugLog.mSaveDanger('_MyFollowingListOnePage', err)
@@ -184,8 +184,8 @@ export default class AliFollowing {
const resp = await AliHttp.Post(url, postData, user_id, '')
if (AliHttp.IsSuccess(resp.code)) {
if (tip) message.success(isFollowing ? '订阅成功' : '取消订阅成功')
- } else {
- DebugLog.mSaveWarning('ApiSetFollowing err=' + followingid + ' ' + (resp.code || ''))
+ } else if (!AliHttp.HttpCodeBreak(resp.code)) {
+ DebugLog.mSaveWarning('ApiSetFollowing err=' + followingid + ' ' + (resp.code || ''), resp.body)
message.error((isFollowing ? '订阅' : '取消订阅') + ' 操作失败,请稍后重试')
}
}
@@ -198,10 +198,10 @@ export default class AliFollowing {
const resp = await AliHttp.Post(url, postData, user_id, '')
if (AliHttp.IsSuccess(resp.code)) {
return true
- } else {
- DebugLog.mSaveWarning('ApiSetFollowingMarkRead err=' + followingid + ' ' + (resp.code || ''))
- return false
+ } else if (!AliHttp.HttpCodeBreak(resp.code)) {
+ DebugLog.mSaveWarning('ApiSetFollowingMarkRead err=' + followingid + ' ' + (resp.code || ''), resp.body)
}
+ return false
}
diff --git a/aliyunpan/src/aliapi/models.ts b/aliyunpan/src/aliapi/models.ts
index ccc776a951..93594e57c0 100644
--- a/aliyunpan/src/aliapi/models.ts
+++ b/aliyunpan/src/aliapi/models.ts
@@ -1,12 +1,35 @@
-
export interface IDownloadUrl {
drive_id: string
file_id: string
- expire_sec: number
+ expire_time: number
url: string
size: number
}
+
+export interface IVideoPreviewUrl {
+ drive_id: string
+ file_id: string
+ size: number
+ duration: number
+ expire_time: number
+ width: number
+ height: number
+ qualities: {
+ html: string
+ quality: string
+ height: number
+ width: number
+ label: string
+ value: string
+ url: string
+ }[]
+ subtitles: {
+ language: string
+ url: string
+ }[]
+}
+
export interface ICompilationList {
name: string
type: string
@@ -16,36 +39,14 @@ export interface ICompilationList {
category: string
drive_id: string
file_id: string
+ file_extension: string
url: string
- expire_sec: number
+ expire_time: number
play_cursor: number
compilation_id: string
}
-export interface IVideoPreviewUrl {
- drive_id: string
- file_id: string
- expire_sec: number
- url: string
- duration: number
- width: number
- height: number
- urlQHD: string
- play_cursor: number
-
- urlFHD: string
- urlHD: string
- urlSD: string
- urlLD: string
- file_name?:string,
- subtitles: {
- language: string
- url: string
- }[]
-}
-
-
export interface IOfficePreViewUrl {
drive_id: string
file_id: string
@@ -102,17 +103,17 @@ export interface IAliBatchResult {
reslut: {
id: string
file_id?: string
-
+
name?: string
type?: string
parent_file_id?: string
-
+
share_id?: string
share_pwd?: string
share_url?: string
expiration?: string
share_name?: string
-
+
body?: any
}[]
error: {
@@ -143,15 +144,15 @@ export interface IBatchResult {
export interface IAliGetAlbumModel {
- album_id: string
- created_at: number
- description: string
- file_count: number
- image_count: number
- name: string
- owner: string
- updated_at: number
- video_count: number
+ album_id: string
+ created_at: number
+ description: string
+ file_count: number
+ image_count: number
+ name: string
+ owner: string
+ updated_at: number
+ video_count: number
}
export interface IAliUserDriveDetails {
@@ -167,12 +168,12 @@ export interface IAliUserDriveDetails {
}
export interface IAliUserDriveCapacity {
- type: string
+ type: string
size: number
sizeStr: string
- expired: string
- expiredstr: string
- description: string
+ expired: string
+ expiredstr: string
+ description: string
latest_receive_time: string /* "2022-05-02T00:50:51.379Z" */
}
@@ -181,29 +182,29 @@ export interface IStateUploadFile {
UploadID: string
Info: {
user_id: string
-
+
localFilePath: string
-
+
parent_file_id: string
drive_id: string
path: string
-
+
name: string
-
+
size: number
sizeStr: string
icon: string
isDir: boolean
isMiaoChuan: boolean
-
+
sha1: string
-
+
crc64: string
}
-
+
Upload: {
-
+
DownState: string
DownTime: number
DownSize: number
@@ -218,11 +219,11 @@ export interface IStateUploadFile {
failedCode: number
/** 失败的消息 */
failedMessage: string
-
+
AutoTry: number
-
+
upload_id: string
-
+
file_id: string
/** 是否覆盖上传 */
IsBreakExist: boolean
diff --git a/aliyunpan/src/aliapi/server.ts b/aliyunpan/src/aliapi/server.ts
new file mode 100644
index 0000000000..d1e86ed2ae
--- /dev/null
+++ b/aliyunpan/src/aliapi/server.ts
@@ -0,0 +1,256 @@
+import { b64decode, Sleep } from '../utils/format'
+import { getPkgVersion } from '../utils/utils'
+import axios, { AxiosResponse } from 'axios'
+import { IShareSiteGroupModel, IShareSiteModel, useServerStore, useSettingStore, useUserStore } from '../store'
+import ShareDAL from '../share/share/ShareDAL'
+import { modalShowPost, modalUpdate } from '../utils/modal'
+import { getResourcesPath } from '../utils/electronhelper'
+import { existsSync, readFileSync } from 'fs'
+import message from '../utils/message'
+import path from 'path'
+import DebugLog from '../utils/debuglog'
+
+export interface IServerRespData {
+ state: string
+ msg: string
+
+ [k: string]: any
+}
+
+export interface IServerVerData {
+ version: string
+ verName: string
+ verUrl: string
+ verInfo: string
+ verHtml: string
+ fileExt: string
+ fileSize: number
+}
+
+export default class ServerHttp {
+ static baseApi = b64decode('aHR0cDovLzEyMS41LjE0NC44NDo1MjgyLw==')
+ static configUrl = b64decode('aHR0cHM6Ly9naXRlZS5jb20vemhhbm5hby9yZXNvdXJjZS9yYXcvbWFzdGVyL2ltYWdlcy9zaGFyZV9jb25maWcuanNvbg==')
+ static updateUrl = b64decode('aHR0cHM6Ly9hcGkuZ2l0aHViLmNvbS9yZXBvcy9nYW96aGFuZ21pbi9hbGl5dW5wYW4vcmVsZWFzZXMvbGF0ZXN0')
+
+ static compareVer(version1: string, version2: string): number {
+ // Split version strings into arrays of numbers
+ const v1Parts = version1.split('.').map(Number)
+ const v2Parts = version2.split('.').map(Number)
+
+ // Pad the shorter version with zeros to make their lengths equal
+ const maxLength = Math.max(v1Parts.length, v2Parts.length)
+ v1Parts.push(...Array(maxLength - v1Parts.length).fill(0))
+ v2Parts.push(...Array(maxLength - v2Parts.length).fill(0))
+
+ // Compare each part of the version numbers
+ for (let i = 0; i < maxLength; i++) {
+ if (v1Parts[i] > v2Parts[i]) {
+ return 1
+ } else if (v1Parts[i] < v2Parts[i]) {
+ return -1
+ }
+ }
+
+ // Version numbers are equal
+ return 0
+ }
+
+ static compareVersions(version1: string, version2: string): number {
+ // Split version strings into arrays of numbers
+ const v1Parts = version1.split('.').map(Number);
+ const v2Parts = version2.split('.').map(Number);
+
+ // Pad the shorter version with zeros to make their lengths equal
+ const maxLength = Math.max(v1Parts.length, v2Parts.length);
+ v1Parts.push(...Array(maxLength - v1Parts.length).fill(0));
+ v2Parts.push(...Array(maxLength - v2Parts.length).fill(0));
+
+ // Compare each part of the version numbers
+ for (let i = 0; i < maxLength; i++) {
+ if (v1Parts[i] > v2Parts[i]) {
+ return 1;
+ } else if (v1Parts[i] < v2Parts[i]) {
+ return -1;
+ }
+ }
+
+ // Version numbers are equal
+ return 0;
+ }
+
+
+
+ static async Post(postData: any, isfirst = true): Promise {
+ const url = ServerHttp.baseApi + 'xby2'
+ return axios
+ .post(url, postData, {
+ responseType: 'arraybuffer',
+ timeout: 30000,
+ headers: {}
+ })
+ .then((response: AxiosResponse) => {
+ if (response.status != 200) return { state: 'error', msg: '网络错误' }
+ const buff = response.data as ArrayBuffer
+ const uint8array = new Uint8Array(buff)
+ for (let i = 0, maxi = uint8array.byteLength; i < maxi; i++) {
+ uint8array[i] ^= 9 + (i % 200)
+ }
+ const str = new TextDecoder().decode(uint8array)
+ return JSON.parse(str) as IServerRespData
+ })
+ .catch(() => {
+ return { state: 'error', msg: '网络错误' }
+ })
+ .then(async (resp) => {
+ if (resp.state == 'error' && resp.msg == '网络错误' && isfirst) {
+ await Sleep(2000)
+ return await ServerHttp.Post(postData, false)
+ } else return resp
+ })
+ }
+
+
+ static async PostToServer(postData: any): Promise {
+ postData.appVersion = getPkgVersion()
+ const str = JSON.stringify(postData)
+ if (window.postdataFunc) {
+ let enstr = ''
+ try {
+ enstr = window.postdataFunc(str)
+ console.log(enstr)
+ } catch {
+ return { state: 'error', msg: '联网失败' }
+ }
+ return ServerHttp.Post(enstr).catch(() => {
+ return { state: 'error', msg: '网络错误' }
+ })
+ } else {
+ return { state: 'error', msg: '程序错误' }
+ }
+ }
+
+ static async CheckConfigUpgrade(): Promise {
+ axios
+ .get(ServerHttp.configUrl, {
+ withCredentials: false,
+ responseType: 'json',
+ timeout: 30000
+ })
+ .then(async (response: AxiosResponse) => {
+ console.log('CheckConfigUpgrade', response)
+ let GroupList: IShareSiteGroupModel[] = []
+ if (response.data.GroupList && response.data.GroupList.length > 0) {
+ const list = response.data.GroupList
+ for (let item of list) {
+ GroupList.push({ group: item.group, title: item.title })
+ }
+ } else {
+ GroupList = [
+ { group: 'search', title: '搜索' },
+ { group: 'nav', title: '导航' },
+ { group: 'bbs', title: '论坛' }
+ ]
+ }
+ ShareDAL.SaveShareSiteGroup(GroupList)
+ if (response.data.SSList && response.data.SSList.length > 0) {
+ const list: IShareSiteModel[] = []
+ const SSList = response.data.SSList
+ for (let item of SSList) {
+ const add: any = {
+ title: item.title,
+ url: item.url,
+ tip: item.tip,
+ group: item.group,
+ color: item.color
+ }
+ if (add.url.length > 0) list.push(add)
+ }
+ ShareDAL.SaveShareSite(list)
+ }
+ if (response.data.HELP && response.data.HELP.length > 0) {
+ useServerStore().mSaveHelpUrl(response.data.HELP)
+ }
+ if (response.data.POST && response.data.POST.length > 0) {
+ let postId = localStorage.getItem('postmodal')
+ if (!postId || postId != response.data.POST_ID) {
+ modalShowPost(response.data.POST, response.data.POST_ID)
+ }
+ }
+ }).catch((err: any) => {
+ DebugLog.mSaveDanger('CheckConfigUpgrade', err)
+ })
+ }
+
+ static async CheckUpgrade(showMessage: boolean = true): Promise {
+ axios
+ .get(ServerHttp.updateUrl, {
+ withCredentials: false,
+ responseType: 'json',
+ timeout: 30000
+ })
+ .then(async (response: AxiosResponse) => {
+ console.log('CheckUpgrade', response)
+ if (!response.data || !response.data.assets || !response.data.html_url) {
+ showMessage && message.error('获取新版本出错')
+ return
+ }
+ let tagName = response.data.tag_name // 版本号
+ let remoteVer = tagName.replaceAll('v', '').trim()
+ let verHtml = response.data.html_url // 详情
+ let verInfo = response.data.body // 日志
+ let verData: IServerVerData = {
+ version: remoteVer,
+ verName: '',
+ verUrl: '',
+ verInfo: verInfo,
+ verHtml: verHtml,
+ fileExt: '',
+ fileSize: 0
+ }
+ let assets = response.data.assets // 文件
+ function isMatchingPlatformAndExtension(platform: string, fileName: string, extension: string): boolean {
+ return platform === window.platform && fileName.indexOf(process.arch) > 0 && fileName.endsWith(extension)
+ }
+
+ for (let asset of assets) {
+ if (asset.name.endsWith('.asar')) {
+ verData.fileSize = asset.size
+ verData.fileExt = path.extname(asset.name)
+ verData.verUrl = asset.browser_download_url
+ verData.verName = asset.name
+ break
+ }
+ if (isMatchingPlatformAndExtension('win32', asset.name, '.exe') ||
+ isMatchingPlatformAndExtension('darwin', asset.name, '.dmg')) {
+ verData.fileSize = asset.size
+ verData.fileExt = path.extname(asset.name)
+ verData.verUrl = asset.browser_download_url
+ verData.verName = asset.name
+ }
+ }
+ if (remoteVer) {
+ let configVer = getPkgVersion().replaceAll('v', '').trim()
+ if (window.platform !== 'linux') {
+ let localVersion = getResourcesPath('localVersion')
+ if (localVersion && existsSync(localVersion)) {
+ configVer = readFileSync(localVersion, 'utf-8').replaceAll('v', '').trim()
+ }
+ }
+ if (useSettingStore().uiUpdateProxyEnable &&
+ useSettingStore().uiUpdateProxyUrl.length > 0) {
+ verData.verUrl = useSettingStore().uiUpdateProxyUrl + '/' + verData.verUrl
+ }
+ if (this.compareVersions(remoteVer, configVer) > 0) {
+ // 打开更新弹窗
+ modalUpdate(verData)
+ } else if (showMessage) {
+ message.info('已经是最新版 ' + configVer, 6)
+ }
+ }
+ })
+ .catch((err: any) => {
+ showMessage && message.info('检查更新失败,请检查网络是否正常')
+ // DebugLog.mSaveDanger('CheckUpgrade', err)
+ })
+ }
+}
diff --git a/aliyunpan/src/aliapi/server.tsx b/aliyunpan/src/aliapi/server.tsx
deleted file mode 100644
index fd98ff911e..0000000000
--- a/aliyunpan/src/aliapi/server.tsx
+++ /dev/null
@@ -1,410 +0,0 @@
-import { B64decode, b64decode, humanSize } from '../utils/format'
-import { getPkgVersion } from '../utils/utils'
-import axios, { AxiosResponse } from 'axios'
-import message from '../utils/message'
-import { IShareSiteModel, useServerStore } from '../store'
-import { Modal, Button, Space } from '@arco-design/web-vue'
-import { h } from 'vue'
-import { getAppNewPath, getResourcesPath, getUserDataPath, openExternal } from '../utils/electronhelper'
-import ShareDAL from '../share/share/ShareDAL'
-import DebugLog from '../utils/debuglog'
-import { writeFile, rmSync, existsSync, readFileSync } from 'fs'
-import { execFile, SpawnOptions } from 'child_process'
-import path from 'path'
-
-const { shell } = require('electron')
-
-export interface IServerRespData {
- state: string
- msg: string
-
- [k: string]: any
-}
-
-export default class ServerHttp {
- static baseApi = b64decode('aHR0cDovLzEyMS41LjE0NC44NDo1MjgyLw==')
-
- static async PostToServer(postData: any): Promise {
- postData.appVersion = getPkgVersion()
- const str = JSON.stringify(postData)
- if (window.postdataFunc) {
- let enstr = ''
- try {
- enstr = window.postdataFunc(str)
- console.log(enstr)
- } catch {
- return { state: 'error', msg: '联网失败' }
- }
- return ServerHttp.Post(enstr).catch(() => {
- return { state: 'error', msg: '网络错误' }
- })
- } else {
- return { state: 'error', msg: '程序错误' }
- }
- }
-
- static async Post(postData: any, isfirst = true): Promise {
- const url = ServerHttp.baseApi + 'xby2'
- return axios
- .post(url, postData, {
- responseType: 'arraybuffer',
- timeout: 30000,
- headers: {}
- })
- .then((response: AxiosResponse) => {
- if (response.status != 200) return { state: 'error', msg: '网络错误' }
- const buff = response.data as ArrayBuffer
- const uint8array = new Uint8Array(buff)
- for (let i = 0, maxi = uint8array.byteLength; i < maxi; i++) {
- uint8array[i] ^= 9 + (i % 200)
- }
- const str = new TextDecoder().decode(uint8array)
- return JSON.parse(str) as IServerRespData
- })
- .catch(() => {
- return { state: 'error', msg: '网络错误' }
- })
- .then((resp) => {
- if (resp.state == 'error' && resp.msg == '网络错误' && isfirst) {
- return ServerHttp.Sleep(2000).then(() => {
- return ServerHttp.Post(postData, false)
- })
- } else return resp
- })
- }
-
- static Sleep(msTime: number) {
- return new Promise((resolve) =>
- setTimeout(
- () =>
- resolve({
- success: true,
- time: msTime
- }),
- msTime
- )
- )
- }
-
- static configUrl = b64decode('aHR0cHM6Ly9naXRlZS5jb20vemhhbm5hby9yZXNvdXJjZS9yYXcvbWFzdGVyL2ltYWdlcy9zaGFyZV9jb25maWcuanNvbg==')
- static updateUrl = b64decode('aHR0cHM6Ly9hcGkuZ2l0aHViLmNvbS9yZXBvcy9nYW96aGFuZ21pbi9hbGl5dW5wYW4vcmVsZWFzZXMvbGF0ZXN0')
-
- static async CheckConfigUpgrade(): Promise {
- axios
- .get(ServerHttp.configUrl, {
- withCredentials: false,
- responseType: 'json',
- timeout: 30000
- })
- .then(async (response: AxiosResponse) => {
- const content = B64decode(response.data.content)
- const config = JSON.parse(content)
- if (config.SIP) {
- ServerHttp.baseApi = B64decode(config.SIP)
- }
- if (config.SSList) {
- const list: IShareSiteModel[] = []
- for (let i = 0, maxi = config.SSList.length; i < maxi; i++) {
- const item = config.SSList[i]
- const add = { title: item.title, url: item.url, tip: item.tip }
- if (add.url.length > 0) list.push(add)
- }
- ShareDAL.SaveShareSite(list)
- }
- if (config.HELP) {
- useServerStore().mSaveHelpUrl(response.data.HELP)
- }
- })
- }
-
- static compareVersions(version1: string, version2: string): number {
- // Split version strings into arrays of numbers
- const v1Parts = version1.split('.').map(Number);
- const v2Parts = version2.split('.').map(Number);
-
- // Pad the shorter version with zeros to make their lengths equal
- const maxLength = Math.max(v1Parts.length, v2Parts.length);
- v1Parts.push(...Array(maxLength - v1Parts.length).fill(0));
- v2Parts.push(...Array(maxLength - v2Parts.length).fill(0));
-
- // Compare each part of the version numbers
- for (let i = 0; i < maxLength; i++) {
- if (v1Parts[i] > v2Parts[i]) {
- return 1;
- } else if (v1Parts[i] < v2Parts[i]) {
- return -1;
- }
- }
-
- // Version numbers are equal
- return 0;
- }
-
- static async CheckUpgrade(showMessage: boolean = true): Promise {
- axios
- .get(ServerHttp.updateUrl, {
- withCredentials: false,
- responseType: 'json',
- timeout: 30000
- })
- .then(async (response: AxiosResponse) => {
- console.log('CheckUpgrade', response)
- if (!response.data || !response.data.assets || !response.data.html_url) {
- showMessage && message.error('获取新版本出错')
- return
- }
- let platform = process.platform
- let tagName = response.data.tag_name // 版本号
- let assets = response.data.assets // 文件
- let html_url = response.data.html_url // 详情
- let asarFileUrl = ''
- let updateData = { name: '', url: '', size: 0 }
- for (let asset of assets) {
- const fileData = {
- name: asset.name,
- url: asset.browser_download_url,
- size: asset.size
- }
- if (platform === 'win32'
- && fileData.name.indexOf(process.arch) > 0
- && fileData.name.endsWith('.exe')) {
- updateData = fileData
- break
- } else if (platform === 'darwin'
- && fileData.name.indexOf(process.arch) > 0
- && fileData.name.endsWith('.dmg')) {
- updateData = fileData
- break
- } else if (fileData.name.endsWith('.asar')) {
- asarFileUrl = 'https://ghproxy.com/' + fileData.url
- break
- }
- }
- if (tagName) {
- let configVer = getPkgVersion().replaceAll('v', '').trim()
- if (process.platform !== 'linux') {
- let localVersion = getResourcesPath('localVersion')
- if (localVersion && existsSync(localVersion)) {
- configVer = readFileSync(localVersion, 'utf-8').replaceAll('v', '').trim()
- }
- }
- const remoteVer = tagName.replaceAll('v', '').trim()
- const verInfo = this.dealText(response.data.body as string)
- let verUrl = ''
- if (updateData.url) {
- verUrl = 'https://ghproxy.com/' + updateData.url
- }
- if (this.compareVersions(remoteVer, configVer) > 0) {
- Modal.confirm({
- mask: true,
- alignCenter: true,
- title: () => h('div', {
- innerHTML: `有新版本${tagName} `,
- class: { vermodalhead: true },
- style: { maxWidth: '540px' }
- }),
- content: () => h('div', {
- innerHTML: ' \n' +
- '
\n' +
- '
\n' +
- ' Github需要代理,如果下载失败,请关注公众号从网盘下载
' + verInfo,
- class: { vermodal: true }
- }),
- onClose: () => {
- if (updateData.name) {
- let resourcesPath = getResourcesPath(updateData.name)
- if (existsSync(resourcesPath)) {
- rmSync(resourcesPath, { force: true })
- }
- }
- return true
- },
- footer: () => h(Space, {}, () => [
- h(Button, {
- innerHTML: '取消',
- onClick: async () => {
- if (updateData.name) {
- let resourcesPath = getResourcesPath(updateData.name)
- if (existsSync(resourcesPath)) {
- rmSync(resourcesPath, { force: true })
- }
- }
- try {
- // @ts-ignore
- document.querySelector('.arco-overlay-modal').remove()
- } catch (err) {
- }
- return true
- }
- }),
- h(Button, {
- type: 'outline',
- style: asarFileUrl.length == 0 ? '' : 'display: none',
- innerHTML: platform !== 'linux' && verUrl.length > 0 ? '全量更新' : '详情',
- onClick: async () => {
- if (verUrl.length > 0 && platform !== 'linux') {
- // 下载安装
- const msgKey = 'download_' + Date.now().toString()
- await this.AutoDownload(verUrl, html_url, updateData.name, false, msgKey)
- } else {
- openExternal(html_url)
- }
- return true
- }
- }),
- h(Button, {
- type: 'primary',
- style: asarFileUrl.length > 0 && platform !== 'linux' ? '' : 'display: none',
- innerHTML: '热更新',
- onClick: async () => {
- if (asarFileUrl.length > 0 && platform !== 'linux') {
- // 下载安装
- const msgKey = 'download_' + Date.now().toString()
- const flag = await this.AutoDownload(asarFileUrl, html_url, updateData.name, true, msgKey)
- // 更新本地版本号
- if (flag && tagName) {
- const localVersion = getResourcesPath('localVersion')
- if (localVersion) {
- writeFile(localVersion, tagName, async (err)=> {
- if (err) {
- return false
- } else {
- message.info('热更新完毕,自动重启应用中...', 0, msgKey)
- await this.Sleep(2000)
- window.WebRelaunch()
- return true
- }
- })
- }
- }
- }
- return false
- }
- })
- ])
- })
- } else if (showMessage ) {
- message.info('已经是最新版 ', 6)
- }
- }
- })
- .catch((err: any) => {
- showMessage && message.info('检查更新失败,请检查网络是否正常')
- DebugLog.mSaveDanger('CheckUpgrade', err)
- })
- }
-
- static dealText(context: string): string {
- let splitTextArr = context.trim().split(/\r\n/g)
- let resultTextArr: string[] = []
- splitTextArr.forEach((item, i) => {
- let links = item.match(/!?\[.+?\]\(https?:\/\/.+\)/g)
- // 处理链接
- if (links != null) {
- for (let index = 0; index < links.length; index++) {
- const text_link = links[index].match(/[^!\[\(\]\)]+/g)//提取文字和链接
- if (text_link) {
- if (links[index][0] == '!') { //解析图片
- item = item.replace(links[index], ' ')
- } else { //解析超链接
- item = item.replace(links[index], `【${text_link[0]}】 `)
- }
- }
- }
- }
- if (item.indexOf('- ')) { // 无序列表
- item = item.replace(/.*-\s+(.*)/g, '$1 ')
- }
- if (item.indexOf('* ')) { // 无序列表
- item = item.replace(/.*\*\s+(.*)/g, '$1 ')
- }
- if (item.includes('**')) {
- item = item.replaceAll(/\*\*/g, '')
- }
- if (item.startsWith('# ')) { // 1 级标题(h1)
- resultTextArr.push(`${item.replace('# ', '')} `)
- } else if (item.startsWith('## ')) { // 2 级标题(h2)
- resultTextArr.push(`${item.replace('## ', '')} `)
- } else if (item.startsWith('### ')) { // 3 级标题(h3)
- resultTextArr.push(`${item.replace('### ', '')} `)
- } else if (item.indexOf('---') == 0) {
- resultTextArr.push(item.replace('---', ' '))
- } else { // 普通的段落
- resultTextArr.push(`${item}`)
- }
- })
- return resultTextArr.join(' ')
- }
-
- static async AutoDownload(appNewUrl: string, html_url: string, file_name: string, hot: boolean, msgKey: string): Promise {
- const resourcesPath = hot ? getAppNewPath() : getUserDataPath(file_name)
- if (!hot && existsSync(resourcesPath)) {
- await this.autoInstallNewVersion(resourcesPath, msgKey)
- return true
- }
- message.loading('新版本正在后台下载中,请耐心等待。。。', 0, msgKey)
- return axios
- .get(appNewUrl, {
- withCredentials: false,
- responseType: 'arraybuffer',
- timeout: 60000,
- headers: {
- 'Cache-Control': 'no-cache',
- Pragma: 'no-cache',
- Expires: '0'
- }
- })
- .then(async (response: AxiosResponse) => {
- writeFile(resourcesPath, Buffer.from(response.data), (err) => {
- if(err) {
- message.error('下载更新失败,请检查【Resources文件夹】是否有写入权限',5, msgKey)
- return false
- }
- })
- if (!hot) {
- await this.Sleep(2000)
- await this.autoInstallNewVersion(resourcesPath, msgKey)
- }
- return true
- })
- .catch(() => {
- message.error('新版本下载失败,关注公众号从网盘下载', 5)
- rmSync(resourcesPath, { force: true })
- openExternal(html_url)
- return false
- })
- }
-
- static async autoInstallNewVersion(resourcesPath: string, msgKey: string) {
- // 自动安装
- const options: SpawnOptions = { shell: true, windowsVerbatimArguments: true }
- if (process.platform === 'win32') {
- execFile('\"' + resourcesPath + '\"', options, error => {
- if(error) {
- message.info('安装失败,请前往文件夹手动安装', 5, msgKey)
- const resources = getResourcesPath('')
- shell.openPath(path.join(resources, '/'))
- } else {
- message.info('安装成功,请重新打开', 5, msgKey)
- window.WebToElectron({ cmd: 'exit' })
- }
- })
- } else if (process.platform === 'darwin') {
- execFile('open ' + '\"' + resourcesPath + '\"', options, error => {
- if(error) {
- message.info('安装失败,请前往文件夹手动安装', 5, msgKey)
- const resources = getResourcesPath('')
- shell.openPath(path.join(resources, '/'))
- } else {
- message.info('请手动移动到应用程序目录,完成安装', 5, msgKey)
- window.WebToElectron({ cmd: 'exit' })
- }
- })
- }
- }
-}
-
-
-
-
-
diff --git a/aliyunpan/src/aliapi/share.ts b/aliyunpan/src/aliapi/share.ts
index aef7cd1313..998bf87768 100644
--- a/aliyunpan/src/aliapi/share.ts
+++ b/aliyunpan/src/aliapi/share.ts
@@ -1,11 +1,11 @@
import DebugLog from '../utils/debuglog'
-import { humanDateTime, humanExpiration, humanSize } from '../utils/format'
+import { humanDateTime, humanDateTimeDateStr, humanExpiration, humanSize } from '../utils/format'
import message from '../utils/message'
import AliHttp, { IUrlRespData } from './alihttp'
import ServerHttp from './server'
import { ApiBatch, ApiBatchMaker, ApiBatchSuccess } from './utils'
import { useSettingStore } from '../store'
-import { IAliShareItem, IAliShareAnonymous, IAliShareFileItem } from './alimodels'
+import { IAliFileItem, IAliShareAnonymous, IAliShareBottleFish, IAliShareFileItem, IAliShareItem } from './alimodels'
import getFileIcon from './fileicon'
import { IAliBatchResult } from './models'
@@ -13,13 +13,13 @@ export interface IAliShareFileResp {
items: IAliShareFileItem[]
itemsKey: Set
punished_file_count: number
-
+
next_marker: string
- m_user_id: string
- m_share_id: string
- dirID: string
- dirName: string
+ m_user_id: string
+ m_share_id: string
+ dirID: string
+ dirName: string
}
export interface UpdateShareModel {
@@ -30,11 +30,21 @@ export interface UpdateShareModel {
}
export default class AliShare {
-
- static async ApiGetShareAnonymous(share_id: string): Promise {
-
-
+ static async ApiShareFileCheckAvailable(user_id: string, drive_id: string, file_id_list: string[]) {
+ if (!user_id || !drive_id || !file_id_list) return []
+ const url = 'adrive/v2/share_link/check_available'
+ const postData = { drive_id, file_id_list }
+ const resp = await AliHttp.Post(url, postData, user_id, '')
+ if (AliHttp.IsSuccess(resp.code)) {
+ return resp.body.invalid_items as IAliFileItem[]
+ } else if (!AliHttp.HttpCodeBreak(resp.code)) {
+ DebugLog.mSaveWarning('ApiShareFileCheckAvailable err=' + (resp.code || ''))
+ }
+ return []
+ }
+
+ static async ApiGetShareAnonymous(share_id: string): Promise {
const share: IAliShareAnonymous = {
shareinfo: {
share_id: share_id,
@@ -55,7 +65,7 @@ export default class AliShare {
error: '解析分享链接失败'
}
if (!share_id) return share
- const url = 'adrive/v2/share_link/get_share_by_anonymous?share_id=' + share_id
+ const url = 'adrive/v3/share_link/get_share_by_anonymous?share_id=' + share_id
const postData = { share_id: share_id }
const resp = await AliHttp.Post(url, postData, '', '')
if (AliHttp.IsSuccess(resp.code)) {
@@ -75,13 +85,14 @@ export default class AliShare {
share.shareinfo.album_id = resp.body.album_id || ''
share.shareinfojson = JSON.stringify(resp.body)
share.error = ''
- return share
+ return share
}
- } else {
- DebugLog.mSaveWarning('ApiGetShareAnonymous err=' + share_id + ' ' + (resp.code || ''))
+ } else if (resp.code != 429 && !AliHttp.HttpCodeBreak(resp.code)) {
+ DebugLog.mSaveWarning('ApiGetShareAnonymous err=' + share_id + ' ' + (resp.code || ''), resp.body)
}
-
- if (resp.body?.code == 'ShareLink.Cancelled') share.error = '分享链接被取消分享了'
+
+ if (resp.body?.code == 'TooManyRequests') share.error = '429'
+ else if (resp.body?.code == 'ShareLink.Cancelled') share.error = '分享链接被取消分享了'
else if (resp.body?.code == 'ShareLink.Expired') share.error = '分享链接过期失效了'
else if (resp.body?.code == 'ShareLink.Forbidden') share.error = '分享链接违规禁止访问'
else if (resp.body?.code) share.error = resp.body.code
@@ -89,7 +100,7 @@ export default class AliShare {
return share
}
-
+
static async ApisSubscription(user_id: string, share_id: string): Promise {
if (!user_id || !share_id) return false
const url = 'adrive/v1/share_link/subscription/update'
@@ -97,16 +108,14 @@ export default class AliShare {
const resp = await AliHttp.Post(url, postData, user_id, '')
if (AliHttp.IsSuccess(resp.code)) {
return true
- } else {
- DebugLog.mSaveWarning('ApisSubscription err=' + share_id + ' ' + (resp.code || ''))
+ } else if (!AliHttp.HttpCodeBreak(resp.code)) {
+ DebugLog.mSaveWarning('ApisSubscription err=' + share_id + ' ' + (resp.code || ''), resp.body)
}
return false
}
-
+
static async ApiGetShareToken(share_id: string, pwd: string): Promise {
-
-
if (!share_id) return ',分享链接错误'
const url = 'v2/share_link/get_share_token'
const postData = { share_id: share_id, share_pwd: pwd }
@@ -118,31 +127,32 @@ export default class AliShare {
if (useSettingStore().yinsiLinkPassword) {
const serdata = await ServerHttp.PostToServer({ cmd: 'GetAliSharePwd', shareid: share_id })
if (serdata.password) {
- isgetpwd = true
+ isgetpwd = true
postData.share_pwd = serdata.password
- resp = await AliHttp.Post(url, postData, '', '')
+ resp = await AliHttp.Post(url, postData, '', '')
}
}
}
-
-
if (resp.body?.code == 'InvalidResource.SharePwd') return ',提取码错误'
if (resp.body?.code == 'ShareLink.Cancelled') return ',分享链接被取消分享了'
if (resp.body?.code == 'ShareLink.Expired') return ',分享链接过期失效了'
if (resp.body?.code == 'ShareLink.Forbidden') return ',分享链接违规禁止访问'
if (resp.body?.code) return ',' + resp.body.code
-
if (AliHttp.IsSuccess(resp.code)) {
- if (useSettingStore().yinsiLinkPassword && isgetpwd == false) ServerHttp.PostToServer({ cmd: 'PostAliShare', shareid: share_id, password: postData.share_pwd })
+ if (useSettingStore().yinsiLinkPassword && !isgetpwd) ServerHttp.PostToServer({
+ cmd: 'PostAliShare',
+ shareid: share_id,
+ password: postData.share_pwd
+ })
return (resp.body.share_token as string | undefined) || ',share_token错误'
- } else {
- DebugLog.mSaveWarning('ApiGetShareToken err=' + share_id + ' ' + (resp.code || ''))
+ } else if (!AliHttp.HttpCodeBreak(resp.code)) {
+ DebugLog.mSaveWarning('ApiGetShareToken err=' + share_id + ' ' + (resp.code || ''), resp.body)
}
return ',网络错误请重试'
}
-
+
static async ApiShareFileList(share_id: string, share_token: string, dirID: string): Promise {
const dir: IAliShareFileResp = {
items: [],
@@ -156,18 +166,18 @@ export default class AliShare {
}
do {
const isGet = await AliShare.ApiShareFileListOnePage(dir, share_token)
- if (isGet != true) {
- break
+ if (!isGet) {
+ break
}
} while (dir.next_marker)
return dir
}
-
+
static async ApiShareFileListOnePage(dir: IAliShareFileResp, share_token: string): Promise {
const url =
- 'adrive/v3/file/list?jsonmask=next_marker%2Cpunished_file_count%2Ctotal_count%2Citems(category%2Ccreated_at%2Cdomain_id%2Cdrive_id%2Cfile_extension%2Cfile_id%2Chidden%2Cmime_extension%2Cmime_type%2Cname%2Cparent_file_id%2Cpunish_flag%2Csize%2Cstarred%2Ctype%2Cupdated_at%2Cdescription)'
+ 'adrive/v3/file/list?jsonmask=next_marker%2Citems(category%2Ccreated_at%2Cdrive_id%2Cfile_extension%2Cfile_id%2Chidden%2Cmime_extension%2Cmime_type%2Cname%2Cparent_file_id%2Cpunish_flag%2Csize%2Cstarred%2Ctype%2Cupdated_at%2Cdescription)'
let postData = {
share_id: dir.m_share_id,
parent_file_id: dir.dirID,
@@ -195,7 +205,6 @@ export default class AliShare {
name: item.name,
type: item.type,
parent_file_id: item.parent_file_id,
-
file_extension: item.file_extension || '',
mime_extension: item.mime_extension || '',
mime_type: item.mime_type || '',
@@ -203,6 +212,9 @@ export default class AliShare {
category: item.category || '',
punish_flag: item.punish_flag || 0,
isDir: item.type == 'folder',
+ created_at: item.created_at,
+ updated_at: item.updated_at,
+ timeStr: humanDateTimeDateStr(item.updated_at || item.created_at),
sizeStr: item.type == 'folder' ? '' : humanSize(item.size),
icon: getFileIcon(item.category, item.file_extension, item.mime_extension, item.mime_type, item.size)[1]
}
@@ -212,17 +224,17 @@ export default class AliShare {
dir.punished_file_count += resp.body.punished_file_count || 0
return true
} else if (resp.code == 404) {
-
+
dir.items.length = 0
dir.next_marker = ''
return true
} else if (resp.body && resp.body.code) {
dir.items.length = 0
- dir.next_marker = resp.body.code
+ dir.next_marker = resp.body.code
message.warning('列出分享链接内文件出错 ' + resp.body.code, 2)
return false
- } else {
- DebugLog.mSaveWarning('_ShareFileListOnePage err=' + (resp.code || ''))
+ } else if (!AliHttp.HttpCodeBreak(resp.code)) {
+ DebugLog.mSaveWarning('_ShareFileListOnePage err=' + (resp.code || ''), resp.body)
}
} catch (err: any) {
DebugLog.mSaveDanger('_ShareFileListOnePage ' + dir.dirID, err)
@@ -231,13 +243,12 @@ export default class AliShare {
return false
}
-
+
static async ApiCreatShare(user_id: string, drive_id: string, expiration: string, share_pwd: string, share_name: string, file_id_list: string[]): Promise {
if (!user_id || !drive_id || file_id_list.length == 0) return '创建分享链接失败数据错误'
const url = 'adrive/v2/share_link/create'
- const postData = JSON.stringify({ drive_id, expiration, share_pwd: share_pwd, share_name: share_name, file_id_list })
+ const postData = { drive_id, expiration, share_pwd, share_name, file_id_list }
const resp = await AliHttp.Post(url, postData, user_id, '')
-
if (AliHttp.IsSuccess(resp.code)) {
const item = resp.body as IAliShareItem
const add: IAliShareItem = Object.assign({}, item, { first_file: undefined, icon: 'iconwenjian' })
@@ -245,14 +256,15 @@ export default class AliShare {
if (item.updated_at) add.updated_at = humanDateTime(item.updated_at)
add.share_msg = humanExpiration(item.expiration)
return add
- } else {
- DebugLog.mSaveWarning('ApiCreatShare err=' + (resp.code || ''))
+ } else if (!AliHttp.HttpCodeBreak(resp.code)) {
+ DebugLog.mSaveWarning('ApiCreatShare err=' + (resp.code || ''), resp.body)
}
-
+
if (resp.body?.code.startsWith('UserPunished')) return '账号分享行为异常,无法分享'
else if (resp.body?.code == 'InvalidParameter.FileIdList') return '选择文件过多,无法分享'
else if (resp.body?.message && resp.body.message.indexOf('size of file_id_list') >= 0) return '选择文件过多,无法分享'
else if (resp.body?.code == 'FileShareNotAllowed') return '这个文件禁止分享'
+ else if (resp.body?.code == 'SharelinkCreateExceedDailyLimit') return '今日分享次数过多,请明天再试'
else if (resp.body?.code == 'FeatureTemporaryDisabled') return '分享功能维护中'
else if (resp.body?.code) return resp.body.code.toString()
else return '创建分享链接失败'
@@ -277,11 +289,10 @@ export default class AliShare {
}
batchList.push(JSON.stringify(postData))
}
- const result = await ApiBatch('', batchList, user_id, '')
- return result
+ return await ApiBatch('', batchList, user_id, '')
}
-
+
static async ApiCancelShareBatch(user_id: string, share_idList: string[]): Promise {
const batchList = ApiBatchMaker('/share_link/cancel', share_idList, (share_id: string) => {
return { share_id: share_id }
@@ -289,7 +300,7 @@ export default class AliShare {
return ApiBatchSuccess(share_idList.length > 1 ? '批量取消分享' : '取消分享', batchList, user_id, '')
}
-
+
static async ApiUpdateShareBatch(user_id: string, share_idList: string[], expirationList: string[], share_pwdList: string[], share_nameList: string[] | undefined): Promise {
if (!share_idList || share_idList.length == 0) return []
const batchList: string[] = []
@@ -297,7 +308,12 @@ export default class AliShare {
for (let i = 0, maxi = share_idList.length; i < maxi; i++) {
batchList.push(
JSON.stringify({
- body: { share_id: share_idList[i], share_pwd: share_pwdList[i], expiration: expirationList[i], share_name: share_nameList[i] },
+ body: {
+ share_id: share_idList[i],
+ share_pwd: share_pwdList[i],
+ expiration: expirationList[i],
+ share_name: share_nameList[i]
+ },
headers: { 'Content-Type': 'application/json' },
id: share_idList[i],
method: 'POST',
@@ -307,25 +323,36 @@ export default class AliShare {
}
} else {
for (let i = 0, maxi = share_idList.length; i < maxi; i++) {
- batchList.push(JSON.stringify({ body: { share_id: share_idList[i], share_pwd: share_pwdList[i], expiration: expirationList[i] }, headers: { 'Content-Type': 'application/json' }, id: share_idList[i], method: 'POST', url: '/share_link/update' }))
+ batchList.push(JSON.stringify({
+ body: {
+ share_id: share_idList[i],
+ share_pwd: share_pwdList[i],
+ expiration: expirationList[i]
+ },
+ headers: { 'Content-Type': 'application/json' },
+ id: share_idList[i],
+ method: 'POST',
+ url: '/share_link/update'
+ }))
}
}
const successList: UpdateShareModel[] = []
const result = await ApiBatch(share_idList.length > 1 ? '批量更新分享链接' : '更新分享链接', batchList, user_id, '')
- result.reslut.map((t) => successList.push({ share_id: t.share_id!, share_pwd: t.share_pwd!, expiration: t.expiration!, share_name: t.share_name! } as UpdateShareModel))
+ result.reslut.map((t) => successList.push({
+ share_id: t.share_id!,
+ share_pwd: t.share_pwd!,
+ expiration: t.expiration!,
+ share_name: t.share_name!
+ } as UpdateShareModel))
return successList
}
-
- static async ApiSaveShareFilesBatch(share_id: string, share_token: string, user_id: string, drive_id: string, parent_file_id: string, file_idList: string[]): Promise {
-
-
-
-
+ static async ApiSaveShareFilesBatch(share_id: string, share_token: string, user_id: string, drive_id: string, parent_file_id: string, file_idList: string[]): Promise {
if (!share_id || !share_token || !user_id || !drive_id || !parent_file_id) return 'error'
if (!file_idList || file_idList.length == 0) return 'success'
+ if (parent_file_id.includes('root')) parent_file_id = 'root'
const batchList: string[] = []
for (let i = 0, maxi = file_idList.length; i < maxi; i++) {
const postData =
@@ -355,6 +382,18 @@ export default class AliShare {
}
return 'error'
}
+ }
+ static async ApiShareBottleFish(user_id: string) {
+ if (!user_id) return '获取好运瓶失败'
+ const url = 'adrive/v1/bottle/fish'
+ const postData = {}
+ const resp = await AliHttp.Post(url, postData, user_id, '')
+ if (AliHttp.IsSuccess(resp.code)) {
+ return resp.body as IAliShareBottleFish
+ } else if (!AliHttp.HttpCodeBreak(resp.code)) {
+ return resp.body.display_message || '获取好运瓶失败'
+ }
+ return '获取好运瓶失败'
}
}
diff --git a/aliyunpan/src/aliapi/sharelist.ts b/aliyunpan/src/aliapi/sharelist.ts
index e8721a8c1e..e43876b9fa 100644
--- a/aliyunpan/src/aliapi/sharelist.ts
+++ b/aliyunpan/src/aliapi/sharelist.ts
@@ -1,20 +1,41 @@
import DebugLog from '../utils/debuglog'
-import { humanDateTime, humanExpiration, Sleep } from '../utils/format'
+import { humanDateTime, humanExpiration } from '../utils/format'
import message from '../utils/message'
import AliHttp, { IUrlRespData } from './alihttp'
-import { IAliShareItem } from './alimodels'
+import { IAliShareBottleFishItem, IAliShareItem, IAliShareRecentItem } from './alimodels'
import AliDirFileList from './dirfilelist'
+import { useSettingStore } from '../store'
export interface IAliShareResp {
items: IAliShareItem[]
itemsKey: Set
next_marker: string
- m_time: number
- m_user_id: string
+ m_time: number
+ m_user_id: string
}
+
+export interface IAliShareRecentResp {
+ items: IAliShareRecentItem[]
+ itemsKey: Set
+ next_marker: string
+
+ m_time: number
+ m_user_id: string
+}
+
+export interface IAliShareBottleFishResp {
+ items: IAliShareBottleFishItem[]
+ itemsKey: Set
+ next_marker: string
+
+ m_time: number
+ m_user_id: string
+}
+
+
export default class AliShareList {
-
+
static async ApiShareListAll(user_id: string): Promise {
const dir: IAliShareResp = {
items: [],
@@ -27,7 +48,7 @@ export default class AliShareList {
do {
const isGet = await AliShareList.ApiShareListOnePage(dir)
if (!isGet) {
- break
+ break
}
} while (dir.next_marker)
return dir
@@ -36,7 +57,6 @@ export default class AliShareList {
static async ApiShareListOnePage(dir: IAliShareResp): Promise {
const url = 'adrive/v3/share_link/list'
const postData = {
-
marker: dir.next_marker,
creator: dir.m_user_id,
include_canceled: false,
@@ -51,7 +71,7 @@ export default class AliShareList {
try {
if (AliHttp.IsSuccess(resp.code)) {
dir.next_marker = resp.body.next_marker
- const downUrl = 'https://api.aliyundrive.com/v2/file/download?t=' + Date.now().toString()
+ const downUrl = 'https://api.alipan.com/v2/file/download?t=' + Date.now().toString()
const timeNow = new Date().getTime()
for (let i = 0, maxi = resp.body.items.length; i < maxi; i++) {
const item = resp.body.items[i] as IAliShareItem
@@ -59,7 +79,7 @@ export default class AliShareList {
let icon = 'iconwenjian'
let first_file
if (item.first_file) {
- first_file = AliDirFileList.getFileInfo(item.first_file, downUrl)
+ first_file = AliDirFileList.getFileInfo(dir.m_user_id, item.first_file, downUrl)
icon = first_file.icon || 'iconwenjian'
}
const add = Object.assign({}, item, { first_file, icon }) as IAliShareItem
@@ -75,7 +95,6 @@ export default class AliShareList {
} else {
add.created_at = ''
}
-
add.share_msg = humanExpiration(item.expiration, timeNow)
if (item.status == 'forbidden') add.share_msg = '分享违规'
dir.items.push(add)
@@ -84,7 +103,6 @@ export default class AliShareList {
return true
} else if (resp.code == 404) {
-
dir.items.length = 0
dir.next_marker = ''
return true
@@ -93,8 +111,8 @@ export default class AliShareList {
dir.next_marker = resp.body.code
message.warning('列出分享列表出错' + resp.body.code, 2)
return false
- } else {
- DebugLog.mSaveWarning('_ShareListOnePage err=' + (resp.code || ''))
+ } else if (!AliHttp.HttpCodeBreak(resp.code)) {
+ DebugLog.mSaveWarning('_ShareListOnePage err=' + (resp.code || ''), resp.body)
}
} catch (err: any) {
DebugLog.mSaveDanger('_ShareListOnePage', err)
@@ -103,27 +121,160 @@ export default class AliShareList {
return false
}
+
+ static async ApiShareRecentListAll(user_id: string): Promise {
+ const dir: IAliShareRecentResp = {
+ items: [],
+ itemsKey: new Set(),
+ next_marker: '',
+ m_time: 0,
+ m_user_id: user_id
+ }
+ let max: number = useSettingStore().debugFavorListMax
+ do {
+ const isGet = await AliShareList.ApiShareRecentListOnePage(dir)
+ if (!isGet) {
+ break
+ }
+ if (dir.items.length >= max && max > 0) {
+ dir.next_marker = ''
+ break
+ }
+ } while (dir.next_marker)
+ return dir
+ }
+
+ static async ApiShareBottleFishListAll(user_id: string): Promise {
+ const dir: IAliShareBottleFishResp = {
+ items: [],
+ itemsKey: new Set(),
+ next_marker: '',
+ m_time: 0,
+ m_user_id: user_id
+ }
+ do {
+ const isGet = await AliShareList.ApiShareBottleFishListOnePage(dir)
+ if (!isGet) {
+ break
+ }
+ } while (dir.next_marker)
+ return dir
+ }
+
+ static async ApiShareRecentListOnePage(dir: IAliShareRecentResp): Promise {
+ const url = 'adrive/v2/share_link/recent_copy_list'
+ const postData = { limit: 50, marker: dir.next_marker, order_by: 'gmt_modified DESC' /* 更新时间 降序 */ }
+ const resp = await AliHttp.Post(url, postData, dir.m_user_id, '')
+ return AliShareList._ShareRecentListOnePage(dir, resp)
+ }
+
+ static async ApiShareBottleFishListOnePage(dir: IAliShareBottleFishResp): Promise {
+ const url = 'adrive/v1/bottle/list'
+ const postData = { limit: 100 }
+ const resp = await AliHttp.Post(url, postData, dir.m_user_id, '')
+ return AliShareList._ShareBottleFishListOnePage(dir, resp)
+ }
+
+ static _ShareRecentListOnePage(dir: IAliShareRecentResp, resp: IUrlRespData): boolean {
+ try {
+ if (AliHttp.IsSuccess(resp.code)) {
+ dir.next_marker = resp.body.next_marker
+ for (let i = 0, maxi = resp.body.items.length; i < maxi; i++) {
+ const item = resp.body.items[i] as IAliShareRecentItem
+ const add = Object.assign({}, item) as IAliShareRecentItem
+ if (dir.itemsKey.has(item.share_id)) continue
+ if (!add.share_msg) add.share_msg = ''
+ if (!add.share_name) add.share_name = 'share_name'
+ if (!add.preview_count) add.preview_count = 0
+ if (!add.file_count) add.file_count = 0
+ if (!add.save_count) add.save_count = 0
+ if (!add.browse_count) add.browse_count = 0
+ if (add.gmt_created) {
+ add.gmt_created = humanDateTime(new Date(add.gmt_created).getTime())
+ } else {
+ add.gmt_created = ''
+ }
+ if (add.gmt_modified) {
+ add.gmt_modified = humanDateTime(new Date(add.gmt_modified).getTime())
+ } else {
+ add.gmt_modified = ''
+ }
+ if (add.status == 'forbidden') add.share_msg = '分享违规'
+ dir.items.push(add)
+ dir.itemsKey.add(add.share_id)
+ }
+ return true
+ } else if (resp.code == 404) {
+ dir.items.length = 0
+ dir.next_marker = ''
+ return true
+ } else if (resp.body && resp.body.code) {
+ dir.items.length = 0
+ dir.next_marker = resp.body.code
+ message.warning('列出历史分享列表出错' + resp.body.code, 2)
+ return false
+ } else if (!AliHttp.HttpCodeBreak(resp.code)) {
+ DebugLog.mSaveWarning('_ShareRecentListOnePage err=' + (resp.code || ''), resp.body)
+ }
+ } catch (err: any) {
+ DebugLog.mSaveDanger('_ShareRecentListOnePage', err)
+ }
+ dir.next_marker = 'error ' + resp.code
+ return false
+ }
+
+ static _ShareBottleFishListOnePage(dir: IAliShareBottleFishResp, resp: IUrlRespData): boolean {
+ try {
+ if (AliHttp.IsSuccess(resp.code)) {
+ dir.next_marker = ''
+ for (let i = 0, maxi = resp.body.items.length; i < maxi; i++) {
+ const item = resp.body.items[i] as IAliShareBottleFishItem
+ const add = Object.assign({}, item) as IAliShareBottleFishItem
+ if (dir.itemsKey.has(item.bottleId)) continue
+ if (!add.share_name) add.share_name = 'share_name'
+ if (add.gmtCreate) {
+ add.gmt_created = humanDateTime(new Date(add.gmtCreate).getTime())
+ } else {
+ add.gmt_created = ''
+ }
+ if (add.saved) add.saved_msg = '已保存'
+ else add.saved_msg = '未保存'
+ dir.items.push(add)
+ dir.itemsKey.add(add.bottleId)
+ }
+ return true
+ } else if (resp.code == 404) {
+ dir.items.length = 0
+ dir.next_marker = ''
+ return true
+ } else if (resp.body && resp.body.code) {
+ dir.items.length = 0
+ dir.next_marker = resp.body.code
+ message.warning('列出好运瓶领取记录列表出错' + resp.body.code, 2)
+ return false
+ } else if (!AliHttp.HttpCodeBreak(resp.code)) {
+ DebugLog.mSaveWarning('_ShareBottleFishListOnePage err=' + (resp.code || ''), resp.body)
+ }
+ } catch (err: any) {
+ DebugLog.mSaveDanger('_ShareBottleFishListOnePage', err)
+ }
+ dir.next_marker = 'error ' + resp.code
+ return false
+ }
+
static async ApiShareListUntilShareID(user_id: string, share_id: string): Promise {
const url = 'adrive/v3/share_link/list'
const postData = {
-
marker: '',
creator: user_id,
include_canceled: false,
order_by: 'created_at',
order_direction: 'DESC'
}
- for (let j = 0; j < 10; j++) {
- const resp = await AliHttp.Post(url, postData, user_id, '')
- try {
- if (AliHttp.IsSuccess(resp.code)) {
- for (let i = 0, maxi = resp.body.items.length; i < maxi; i++) {
- const item = resp.body.items[i] as IAliShareItem
- if (item.share_id == share_id) return true
- }
- }
- } catch {}
- await Sleep(500)
+ const resp = await AliHttp.Post(url, postData, user_id, '')
+ for (let i = 0, maxi = resp.body.items.length; i < maxi; i++) {
+ const item = resp.body.items[i] as IAliShareItem
+ if (item.share_id == share_id) return true
}
return false
}
diff --git a/aliyunpan/src/aliapi/transfershare.ts b/aliyunpan/src/aliapi/transfershare.ts
index cbaa0a9aca..4af5b9e4d7 100644
--- a/aliyunpan/src/aliapi/transfershare.ts
+++ b/aliyunpan/src/aliapi/transfershare.ts
@@ -19,8 +19,8 @@ export default class AliTransferShare {
const add: IAliShareItem = Object.assign({}, item, { first_file: undefined, icon: 'iconwenjian' })
add.share_msg = humanExpiration(item.expiration)
return add
- } else {
- DebugLog.mSaveWarning('ApiCreatShare err=' + (resp.code || ''))
+ } else if (!AliHttp.HttpCodeBreak(resp.code)) {
+ DebugLog.mSaveWarning('ApiCreatShare err=' + (resp.code || ''), resp.body)
}
if (resp.body?.code.startsWith('UserPunished')) return '账号分享行为异常,无法分享'
else if (resp.body?.code == 'InvalidParameter.FileIdList') return '选择文件过多,无法分享'
diff --git a/aliyunpan/src/aliapi/transfersharelist.ts b/aliyunpan/src/aliapi/transfersharelist.ts
index f2dec1d51a..2692e3a287 100644
--- a/aliyunpan/src/aliapi/transfersharelist.ts
+++ b/aliyunpan/src/aliapi/transfersharelist.ts
@@ -40,10 +40,10 @@ export default class AliTransferShareList {
order_direction: 'DESC'
}
const resp = await AliHttp.Post(url, postData,user_id,'')
- return AliTransferShareList._TransferShareListOnePage(user_id, dir, resp)
+ return await AliTransferShareList._TransferShareListOnePage(user_id, dir, resp)
}
- static _TransferShareListOnePage(user_id: string, dir: IAliShareResp, resp: IUrlRespData): boolean {
+ static async _TransferShareListOnePage(user_id: string, dir: IAliShareResp, resp: IUrlRespData): Promise {
try {
if (AliHttp.IsSuccess(resp.code)) {
const timeNow = new Date().getTime()
@@ -51,7 +51,7 @@ export default class AliTransferShareList {
const item = resp.body.items[i] as IAliShareItem
if (dir.itemsKey.has(item.share_id)) continue
let icon = 'iconwenjian'
- let first_file: any = item.share_id && AliTransferShareList.ApiTransferShareFileStatus(user_id, item.share_id)
+ let first_file: any = item.share_id && await AliTransferShareList.ApiTransferShareFileStatus(user_id, item.share_id)
const add = Object.assign({}, item, { first_file, icon }) as IAliShareItem
if (!add.full_share_msg) add.full_share_msg = ''
if (!add.share_msg) add.share_msg = ''
@@ -77,8 +77,8 @@ export default class AliTransferShareList {
dir.items.length = 0
message.warning('列出分享列表出错' + resp.body.code, 2)
return false
- } else {
- DebugLog.mSaveWarning('_ShareListOnePage err=' + (resp.code || ''))
+ } else if (!AliHttp.HttpCodeBreak(resp.code)) {
+ DebugLog.mSaveWarning('_ShareListOnePage err=' + (resp.code || ''), resp.body)
}
} catch (err: any) {
DebugLog.mSaveDanger('_ShareListOnePage', err)
@@ -92,8 +92,8 @@ export default class AliTransferShareList {
const resp = await AliHttp.Post(url, postData, user_id, '')
if (AliHttp.IsSuccess(resp.code)) {
return resp.body as IAliShareItem
- } else {
- DebugLog.mSaveWarning('ApiTransferShareFileStatus err=' + (resp.code || ''))
+ } else if (!AliHttp.HttpCodeBreak(resp.code)) {
+ DebugLog.mSaveWarning('ApiTransferShareFileStatus err=' + (resp.code || ''), resp.body)
}
return false
}
diff --git a/aliyunpan/src/aliapi/trash.ts b/aliyunpan/src/aliapi/trash.ts
index d519c55a0f..00f1282f25 100644
--- a/aliyunpan/src/aliapi/trash.ts
+++ b/aliyunpan/src/aliapi/trash.ts
@@ -8,7 +8,7 @@ export default class AliTrash {
static async ApiTrashFileListOnePageForClean(orderby: string, order: string, dir: IAliFileResp): Promise {
const url =
- 'v2/recyclebin/list?jsonmask=next_marker%2Cpunished_file_count%2Ctotal_count%2Citems(category%2Ccreated_at%2Cdomain_id%2Cdrive_id%2Cfile_extension%2Cfile_id%2Chidden%2Cmime_extension%2Cmime_type%2Cname%2Cparent_file_id%2Cpunish_flag%2Csize%2Cstarred%2Ctype%2Cupdated_at%2Cdescription)'
+ 'v2/recyclebin/list?jsonmask=next_marker%2Citems(category%2Ccreated_at%2Cdrive_id%2Cfile_extension%2Cfile_id%2Chidden%2Cmime_extension%2Cmime_type%2Cname%2Cparent_file_id%2Cpunish_flag%2Csize%2Cstarred%2Ctype%2Cupdated_at%2Cdescription)'
const postData = {
drive_id: dir.m_drive_id,
marker: dir.next_marker,
@@ -26,7 +26,7 @@ export default class AliTrash {
static async ApiFavorFileListOnePageForClean(orderby: string, order: string, dir: IAliFileResp): Promise {
const url =
- 'v2/file/list_by_custom_index_key?jsonmask=next_marker%2Cpunished_file_count%2Ctotal_count%2Citems(category%2Ccreated_at%2Cdomain_id%2Cdrive_id%2Cfile_extension%2Cfile_id%2Chidden%2Cmime_extension%2Cmime_type%2Cname%2Cparent_file_id%2Cpunish_flag%2Csize%2Cstarred%2Ctype%2Cupdated_at%2Cdescription)'
+ 'v2/file/list_by_custom_index_key?jsonmask=next_marker%2Citems(category%2Ccreated_at%2Cdrive_id%2Cfile_extension%2Cfile_id%2Chidden%2Cmime_extension%2Cmime_type%2Cname%2Cparent_file_id%2Cpunish_flag%2Csize%2Cstarred%2Ctype%2Cupdated_at%2Cdescription)'
const postData = {
drive_id: dir.m_drive_id,
marker: dir.next_marker,
@@ -59,7 +59,7 @@ export default class AliTrash {
const orders = order.split(' ')
do {
const isGet = await AliTrash._ApiDirFileListOnePage(orders[0], orders[1], dir, type)
- if (isGet != true) {
+ if (!isGet) {
break
}
if (dir.items.length >= max && max > 0) {
@@ -72,10 +72,10 @@ export default class AliTrash {
static async _ApiDirFileListOnePage(orderby: string, order: string, dir: IAliFileResp, type: string = ''): Promise {
const url =
- 'adrive/v3/file/list?jsonmask=next_marker%2Cpunished_file_count%2Ctotal_count%2Citems(category%2Ccreated_at%2Cdomain_id%2Cdrive_id%2Cfile_extension%2Cfile_id%2Chidden%2Cmime_extension%2Cmime_type%2Cname%2Cparent_file_id%2Cpunish_flag%2Csize%2Cstarred%2Ctype%2Cupdated_at%2Cdescription)'
+ 'adrive/v3/file/list?jsonmask=next_marker%2Citems(category%2Ccreated_at%2Cdrive_id%2Cfile_extension%2Cfile_id%2Chidden%2Cmime_extension%2Cmime_type%2Cname%2Cparent_file_id%2Cpunish_flag%2Csize%2Cstarred%2Ctype%2Cupdated_at%2Cdescription)'
let postData = {
drive_id: dir.m_drive_id,
- parent_file_id: dir.dirID,
+ parent_file_id: dir.dirID.includes('root') ? 'root': dir.dirID,
marker: dir.next_marker,
limit: 100,
all: false,
@@ -94,12 +94,12 @@ export default class AliTrash {
if (AliHttp.IsSuccess(resp.code)) {
dir.next_marker = resp.body.next_marker
const isrecover = dir.dirID == 'recover'
- const downurl = isrecover ? '' : 'https://api.aliyundrive.com/v2/file/download?t=' + Date.now().toString()
+ const downurl = isrecover ? '' : 'https://api.alipan.com/v2/file/download?t=' + Date.now().toString()
for (let i = 0, maxi = resp.body.items.length; i < maxi; i++) {
const item = resp.body.items[i] as IAliFileItem
if (dir.itemsKey.has(item.file_id)) continue
- const add = AliDirFileList.getFileInfo(item, downurl)
+ const add = AliDirFileList.getFileInfo(dir.m_user_id, item, downurl)
if (isrecover) add.description = item.content_hash
dir.items.push(add)
dir.itemsKey.add(item.file_id)
@@ -108,7 +108,6 @@ export default class AliTrash {
return true
} else if (resp.code == 404) {
-
dir.items.length = 0
dir.next_marker = ''
return true
@@ -117,8 +116,8 @@ export default class AliTrash {
dir.next_marker = resp.body.code
message.warning('列出文件出错 ' + resp.body.code, 2)
return false
- } else {
- DebugLog.mSaveWarning('_FileListOnePage err=' + (resp.code || ''))
+ } else if (!AliHttp.HttpCodeBreak(resp.code)) {
+ DebugLog.mSaveWarning('_FileListOnePage err=' + (resp.code || ''), resp.body)
}
} catch (err: any) {
DebugLog.mSaveDanger('_FileListOnePage ' + dir.dirID, err)
@@ -141,8 +140,7 @@ export default class AliTrash {
order_direction: order
}
const resp = await AliHttp.Post(url, postdata, dir.m_user_id, '')
- //todo:: 这里不完善
+ // todo:: 这里不完善
return AliDirFileList._FileListOnePage(orderby, order, dir, resp, -1)
- //return Promise.resolve(false)
}
}
diff --git a/aliyunpan/src/aliapi/upload.ts b/aliyunpan/src/aliapi/upload.ts
index 8369bbeaf1..b9a0a472be 100644
--- a/aliyunpan/src/aliapi/upload.ts
+++ b/aliyunpan/src/aliapi/upload.ts
@@ -1,10 +1,14 @@
import DebugLog from '../utils/debuglog'
import AliHttp from './alihttp'
import { IUploadCreat, IUploadInfo } from './models'
+import { EncodeEncName } from './utils'
export default class AliUpload {
-
- static async UploadCreatFileWithPreHash(user_id: string, drive_id: string, parent_file_id: string, name: string, fileSize: number, prehash: string, check_name_mode: string): Promise {
+ static async UploadCreatFileWithPreHash(
+ user_id: string, drive_id: string, parent_file_id: string,
+ filename: string, fileSize: number,
+ prehash: string, check_name_mode: string, encType: string = ''
+ ): Promise {
const result: IUploadCreat = {
user_id,
drive_id,
@@ -15,11 +19,11 @@ export default class AliUpload {
part_info_list: [],
errormsg: ''
}
- if (!user_id || !drive_id || !parent_file_id || !name) {
+ if (!user_id || !drive_id || !parent_file_id || !filename) {
result.errormsg = '创建文件失败(数据错误)'
return result
}
-
+ if (parent_file_id.includes('root')) parent_file_id = 'root'
const url = 'adrive/v2/file/createWithFolders'
const postData: {
drive_id: string
@@ -34,7 +38,7 @@ export default class AliUpload {
} = {
drive_id,
parent_file_id: parent_file_id,
- name: name,
+ name: filename,
type: 'file',
check_name_mode: check_name_mode == 'ignore' ? 'refuse' : check_name_mode,
size: fileSize,
@@ -42,30 +46,25 @@ export default class AliUpload {
part_info_list: []
}
- let partSize = 10485760
+ let partSize = 10485760
if (fileSize > 0) {
let partIndex = 0
-
- while (fileSize > partSize * 8000) partSize = partSize + 10485760
-
+ while (fileSize > partSize * 8000) partSize = partSize + 10485760
while (partIndex * partSize < fileSize) {
postData.part_info_list.push({ part_number: partIndex + 1, part_size: partSize })
partIndex++
}
- postData.part_info_list[partIndex - 1].part_size = fileSize - (partIndex - 1) * partSize
+ postData.part_info_list[partIndex - 1].part_size = fileSize - (partIndex - 1) * partSize
}
const resp = await AliHttp.Post(url, postData, user_id, '')
-
if (typeof resp.body === 'object' && JSON.stringify(resp.body).indexOf('file size is exceed') > 0) {
result.errormsg = '创建文件失败(单文件最大100GB/2TB)'
return result
}
-
if (resp.body && resp.body.code) {
if (resp.body?.code == 'PreHashMatched') {
-
result.errormsg = 'PreHashMatched'
} else if (resp.body?.code == 'QuotaExhausted.Drive') {
result.errormsg = '出错暂停,网盘空间已满'
@@ -73,32 +72,33 @@ export default class AliUpload {
result.errormsg = resp.body?.code || '创建失败,网络错误'
DebugLog.mSaveDanger('createWithFolders', result.errormsg + ' ' + name)
}
-
return result
}
-
+
if (AliHttp.IsSuccess(resp.code)) {
result.file_id = resp.body.file_id
if (resp.body.exist) {
-
if (check_name_mode == 'ignore') {
-
- await AliUpload.UploadFileDelete(user_id, drive_id, result.file_id).catch(() => {})
- return await AliUpload.UploadCreatFileWithPreHash(user_id, drive_id, parent_file_id, name, fileSize, prehash, check_name_mode)
+ await AliUpload.UploadFileDelete(user_id, drive_id, result.file_id).catch()
+ return await AliUpload.UploadCreatFileWithPreHash(user_id, drive_id, parent_file_id, filename, fileSize, prehash, check_name_mode)
} else {
-
result.errormsg = '出错暂停,网盘内有重名文件'
}
}
- result.isexist = resp.body.exist || false
+ result.isexist = resp.body.exist || false
result.israpid = false
result.upload_id = resp.body.upload_id || ''
if (resp.body.part_info_list && resp.body.part_info_list.length > 0) {
const part_info_list = resp.body.part_info_list
for (let i = 0, maxi = part_info_list.length; i < maxi; i++) {
const item = part_info_list[i]
- result.part_info_list.push({ upload_url: item.upload_url, part_number: item.part_number, part_size: partSize, isupload: false })
+ result.part_info_list.push({
+ upload_url: item.upload_url,
+ part_number: item.part_number,
+ part_size: partSize,
+ isupload: false
+ })
}
}
return result
@@ -109,7 +109,12 @@ export default class AliUpload {
}
}
- static async UploadCreatFileWithFolders(user_id: string, drive_id: string, parent_file_id: string, name: string, fileSize: number, hash: string, proof_code: string, check_name_mode: string): Promise {
+ static async UploadCreatFileWithFolders(
+ user_id: string, drive_id: string,
+ parent_file_id: string, filename: string,
+ fileSize: number, hash: string, proof_code: string,
+ check_name_mode: string, encType: string = ''
+ ): Promise {
const result: IUploadCreat = {
user_id,
drive_id,
@@ -120,14 +125,13 @@ export default class AliUpload {
part_info_list: [],
errormsg: ''
}
- if (!user_id || !drive_id || !parent_file_id || !name) {
+ if (!user_id || !drive_id || !parent_file_id || !filename) {
result.errormsg = '创建文件失败(数据错误)'
return result
}
-
-
-
+ if (parent_file_id.includes('root')) parent_file_id = 'root'
const url = 'adrive/v2/file/createWithFolders'
+ const name = EncodeEncName(user_id, filename, false, encType)
const postData: {
drive_id: string
parent_file_id: string
@@ -140,7 +144,8 @@ export default class AliUpload {
proof_code?: string
proof_version?: string
part_info_list: { part_number: number; part_size: number }[]
- ignore_rapid?: boolean
+ ignore_rapid?: boolean,
+ description: string
} = {
drive_id,
parent_file_id: parent_file_id,
@@ -148,29 +153,33 @@ export default class AliUpload {
type: 'file',
check_name_mode: check_name_mode == 'ignore' ? 'refuse' : check_name_mode,
size: fileSize,
- part_info_list: []
+ part_info_list: [],
+ description: encType
}
-
if (hash) {
postData.content_hash = hash.toUpperCase()
postData.content_hash_name = 'sha1'
postData.proof_version = 'v1'
- postData.proof_code = proof_code
-
+ postData.proof_code = proof_code
+ } else {
+ postData.content_hash = ''
+ postData.content_hash_name = 'none'
+ postData.proof_version = 'v1'
+ postData.proof_code = ''
}
- let partSize = 10485760
+ let partSize = 10485760
if (fileSize > 0) {
let partIndex = 0
- while (fileSize > partSize * 8000) partSize = partSize + 10485760
+ while (fileSize > partSize * 8000) partSize = partSize + 10485760
while (partIndex * partSize < fileSize) {
postData.part_info_list.push({ part_number: partIndex + 1, part_size: partSize })
partIndex++
}
- postData.part_info_list[partIndex - 1].part_size = fileSize - (partIndex - 1) * partSize
+ postData.part_info_list[partIndex - 1].part_size = fileSize - (partIndex - 1) * partSize
}
const resp = await AliHttp.Post(url, postData, user_id, '')
@@ -180,23 +189,23 @@ export default class AliUpload {
return result
}
-
+
if (resp.body && resp.body.code) {
if (resp.body?.code == 'QuotaExhausted.Drive') {
result.errormsg = '出错暂停,网盘空间已满'
} else if (resp.body?.code == 'InvalidRapidProof') {
-
+
result.errormsg = resp.body.code
DebugLog.mSaveDanger('InvalidRapidProof', name)
} else {
result.errormsg = resp.body?.code || '创建失败,网络错误'
DebugLog.mSaveDanger('createWithFolders', result.errormsg + ' ' + name)
}
-
+
return result
}
-
+
if (AliHttp.IsSuccess(resp.code)) {
result.file_id = resp.body.file_id
if (resp.body.exist) {
@@ -205,23 +214,27 @@ export default class AliUpload {
result.errormsg = ''
} else {
if (check_name_mode == 'ignore') {
-
- await AliUpload.UploadFileDelete(user_id, drive_id, result.file_id).catch(() => {})
- return await AliUpload.UploadCreatFileWithFolders(user_id, drive_id, parent_file_id, name, fileSize, hash, proof_code, check_name_mode)
+ await AliUpload.UploadFileDelete(user_id, drive_id, result.file_id).catch()
+ return await AliUpload.UploadCreatFileWithFolders(user_id, drive_id, parent_file_id, name, fileSize, hash, proof_code, check_name_mode)
} else {
-
+
result.errormsg = '出错暂停,网盘内有重名文件'
}
}
}
- result.isexist = resp.body.exist || false
- result.israpid = result.israpid || resp.body.rapid_upload || false
+ result.isexist = resp.body.exist || false
+ result.israpid = result.israpid || resp.body.rapid_upload || false
result.upload_id = resp.body.upload_id || ''
if (resp.body.part_info_list && resp.body.part_info_list.length > 0) {
const part_info_list = resp.body.part_info_list
for (let i = 0, maxi = part_info_list.length; i < maxi; i++) {
const item = part_info_list[i]
- result.part_info_list.push({ upload_url: item.upload_url, part_number: item.part_number, part_size: partSize, isupload: false })
+ result.part_info_list.push({
+ upload_url: item.upload_url,
+ part_number: item.part_number,
+ part_size: partSize,
+ isupload: false
+ })
}
}
return result
@@ -232,7 +245,7 @@ export default class AliUpload {
}
}
-
+
static async UploadFileCheckHash(user_id: string, drive_id: string, file_id: string, hash: string): Promise {
if (!user_id || !drive_id || !file_id) return false
const url = 'v2/file/get?jsonmask=content_hash'
@@ -242,13 +255,14 @@ export default class AliUpload {
const content_hash = resp.body.content_hash.toUpperCase()
hash = hash.toUpperCase()
return hash === content_hash
- } else {
- DebugLog.mSaveWarning('UploadFileCheckHash err=' + (resp.code || ''))
+ } else if (!AliHttp.HttpCodeBreak(resp.code)) {
+ DebugLog.mSaveWarning('UploadFileCheckHash err=' + (resp.code || ''), resp.body)
return false
}
+ return false
}
-
+
static async UploadFileDelete(user_id: string, drive_id: string, file_id: string, permanently: boolean = false): Promise {
if (!user_id || !drive_id || !file_id) return false
const url = 'v2/recyclebin/trash'
@@ -256,13 +270,14 @@ export default class AliUpload {
const resp = await AliHttp.Post(url, postData, user_id, '')
if (AliHttp.IsSuccess(resp.code)) {
return true
- } else {
- DebugLog.mSaveWarning('UploadFileDelete err=' + (resp.code || ''))
+ } else if (!AliHttp.HttpCodeBreak(resp.code)) {
+ DebugLog.mSaveWarning('UploadFileDelete err=' + (resp.code || ''), resp.body)
return false
}
+ return false
}
-
+
static async UploadFileComplete(user_id: string, drive_id: string, file_id: string, upload_id: string, fileSize: number, fileSha1: string): Promise {
if (!user_id || !drive_id || !file_id || !upload_id) return false
const url = 'v2/file/complete'
@@ -270,30 +285,24 @@ export default class AliUpload {
let resp = await AliHttp.Post(url, postData, user_id, '')
if (resp.code == 400 || resp.code == 429) {
resp = await AliHttp.Post(url, postData, user_id, '')
-
-
}
-
if (AliHttp.IsSuccess(resp.code)) {
if (resp.body.size == fileSize) {
if (fileSha1) {
-
if (resp.body.content_hash && resp.body.content_hash == fileSha1) {
return true
} else {
-
- await AliUpload.UploadFileDelete(user_id, drive_id, file_id, true).catch(() => {})
+ await AliUpload.UploadFileDelete(user_id, drive_id, file_id, true).catch()
DebugLog.mSaveDanger('UploadFileComplete', '合并文件后发现SHA1不一致,删除已上传的文件,重新上传')
return false
}
} else if (fileSize < 10485760) {
- return true
+ return true
} else {
- return true
+ return true
}
} else {
-
- await AliUpload.UploadFileDelete(user_id, drive_id, file_id, true).catch(() => {})
+ await AliUpload.UploadFileDelete(user_id, drive_id, file_id, true).catch()
DebugLog.mSaveDanger('UploadFileComplete', '合并文件后发现大小不一致,删除已上传的文件,重新上传')
return false
}
@@ -303,7 +312,7 @@ export default class AliUpload {
}
}
-
+
static async UploadFilePartUrl(user_id: string, drive_id: string, file_id: string, upload_id: string, fileSize: number, uploadInfo: IUploadInfo): Promise<'neterror' | 'success' | 'error'> {
const url = 'v2/file/get_upload_url'
const postData: {
@@ -319,32 +328,37 @@ export default class AliUpload {
}
let partIndex = 0
- let partSize = 10485760
+ let partSize = 10485760
while (fileSize > partSize * 8000) partSize = partSize + 10485760
while (partIndex * partSize < fileSize) {
postData.part_info_list.push({ part_number: partIndex + 1, part_size: partSize })
partIndex++
}
- postData.part_info_list[partIndex - 1].part_size = fileSize - (partIndex - 1) * partSize
+ postData.part_info_list[partIndex - 1].part_size = fileSize - (partIndex - 1) * partSize
const resp = await AliHttp.Post(url, postData, user_id, '')
if (resp.code >= 600 && resp.code <= 610) {
- return 'neterror'
+ return 'neterror'
}
if (AliHttp.IsSuccess(resp.code)) {
if (resp.body.part_info_list && resp.body.part_info_list.length > 0) {
-
+
const part_info_list = resp.body.part_info_list
if (uploadInfo.part_info_list.length == 0) {
-
+
for (let i = 0, maxi = part_info_list.length; i < maxi; i++) {
const item = part_info_list[i]
- uploadInfo.part_info_list.push({ upload_url: item.upload_url, part_number: item.part_number, part_size: partSize, isupload: false })
+ uploadInfo.part_info_list.push({
+ upload_url: item.upload_url,
+ part_number: item.part_number,
+ part_size: partSize,
+ isupload: false
+ })
}
} else {
-
+
for (let i = 0, maxi = part_info_list.length; i < maxi; i++) {
const item = part_info_list[i]
uploadInfo.part_info_list[item.part_number - 1].upload_url = item.upload_url
@@ -354,12 +368,12 @@ export default class AliUpload {
return 'success'
} else {
uploadInfo.part_info_list = []
- DebugLog.mSaveWarning('UploadFilePartUrl err=' + upload_id + ' ' + (resp.code || ''))
+ DebugLog.mSaveWarning('UploadFilePartUrl err=' + upload_id + ' ' + (resp.code || ''), resp.body)
return 'error'
}
}
-
+
static async UploadFileListUploadedParts(user_id: string, drive_id: string, file_id: string, upload_id: string, part_number_marker: number, uploadInfo: IUploadInfo): Promise<'neterror' | 'success' | 'error'> {
if (!user_id || !drive_id || !file_id || !upload_id) return 'error'
@@ -367,7 +381,7 @@ export default class AliUpload {
const postData = { drive_id: drive_id, upload_id: upload_id, file_id: file_id, part_number_marker /* 1开始 */ }
const resp = await AliHttp.Post(url, postData, user_id, '')
if (resp.code >= 600 && resp.code <= 610) {
- return 'neterror'
+ return 'neterror'
}
if (AliHttp.IsSuccess(resp.code)) {
if (resp.body.uploaded_parts && resp.body.uploaded_parts.length > 0) {
@@ -377,7 +391,7 @@ export default class AliUpload {
const part_number = item.part_number
const uploadpart = uploadInfo.part_info_list[part_number - 1]
if (uploadpart.part_size != item.part_size) {
-
+
DebugLog.mSaveDanger('list_uploaded_parts', '分片数据错误 uploadpart=' + uploadpart.part_size + ' item=' + item.part_size)
return 'error'
}
@@ -386,11 +400,12 @@ export default class AliUpload {
}
if (resp.body.next_part_number_marker && parseInt(resp.body.next_part_number_marker) > 0) {
const next = parseInt(resp.body.next_part_number_marker)
- await AliUpload.UploadFileListUploadedParts(user_id, drive_id, file_id, upload_id, next, uploadInfo).catch(() => {})
+ await AliUpload.UploadFileListUploadedParts(user_id, drive_id, file_id, upload_id, next, uploadInfo).catch(() => {
+ })
}
return 'success'
} else {
- DebugLog.mSaveWarning('UploadFileListUploadedParts err=' + upload_id + ' ' + (resp.code || ''))
+ DebugLog.mSaveWarning('UploadFileListUploadedParts err=' + upload_id + ' ' + (resp.code || ''), resp.body)
return 'error'
}
}
diff --git a/aliyunpan/src/aliapi/uploadOpenApi.ts b/aliyunpan/src/aliapi/uploadOpenApi.ts
deleted file mode 100644
index 18baa70ebc..0000000000
--- a/aliyunpan/src/aliapi/uploadOpenApi.ts
+++ /dev/null
@@ -1,416 +0,0 @@
-import DebugLog from '../utils/debuglog'
-import AliHttp from './alihttp'
-import { IUploadCreat, IUploadInfo } from './models'
-import path from "path";
-import AliFileCmd from "./filecmd";
-import AliAlbum from './album'
-
-export default class AliUploadOpenApi {
-
- static async UploadCreatFileWithPreHash(user_id: string, drive_id: string, parent_file_id: string, name: string, fileSize: number, prehash: string, check_name_mode: string): Promise {
- const result: IUploadCreat = {
- user_id,
- drive_id,
- israpid: false,
- isexist: false,
- upload_id: '',
- file_id: '',
- part_info_list: [],
- errormsg: ''
- }
- if (!user_id || !drive_id || !parent_file_id || !name) {
- result.errormsg = '创建文件失败(数据错误)'
- return result
- }
-
- const pathSplitor = name.split(path.sep);
- let newFileName = name;
- if (pathSplitor.length > 1) {
- const dirFullName = pathSplitor.slice(0, pathSplitor.length - 1).join(path.sep);
- newFileName = pathSplitor[pathSplitor.length-1]
- const resp = await AliFileCmd.ApiCreatNewForder(user_id, drive_id, parent_file_id, dirFullName);
- parent_file_id = resp.file_id
- }
- let url = 'adrive/v1.0/openFile/create'
- if (name.includes('_album_id')) {
- url = 'adrive/v1/biz/albums/file/create'
- newFileName = name.split('album_id=')[0]
- }
- const postData: {
- drive_id: string
- parent_file_id: string
- name: string
- type: string
- check_name_mode: string
- size: number
- pre_hash: string
- part_info_list: { part_number: number; part_size: number }[]
- ignore_rapid?: boolean
- } = {
- drive_id,
- parent_file_id: parent_file_id,
- name: newFileName,
- type: 'file',
- check_name_mode: check_name_mode == 'ignore' ? 'refuse' : check_name_mode,
- size: fileSize,
- pre_hash: prehash,
- part_info_list: []
- }
-
- let partSize = 10485760
- if (fileSize > 0) {
- let partIndex = 0
-
- while (fileSize > partSize * 8000) partSize = partSize + 10485760
-
- while (partIndex * partSize < fileSize) {
- postData.part_info_list.push({ part_number: partIndex + 1, part_size: partSize })
- partIndex++
- }
- postData.part_info_list[partIndex - 1].part_size = fileSize - (partIndex - 1) * partSize
- }
-
- const resp = await AliHttp.Post(url, postData, user_id, '')
-
- if (typeof resp.body === 'object' && JSON.stringify(resp.body).indexOf('file size is exceed') > 0) {
- result.errormsg = '创建文件失败(单文件最大100GB/2TB)'
- return result
- }
-
-
- if (resp.body && resp.body.code) {
- if (resp.body?.code == 'PreHashMatched') {
-
- result.errormsg = 'PreHashMatched'
- } else if (resp.body?.code == 'QuotaExhausted.Drive') {
- result.errormsg = '出错暂停,网盘空间已满'
- } else {
- result.errormsg = resp.body?.code || '创建失败,网络错误'
- DebugLog.mSaveDanger('createWithFolders', result.errormsg + ' ' + name)
- }
-
- return result
- }
-
-
- if (AliHttp.IsSuccess(resp.code)) {
- result.file_id = resp.body.file_id
- if (resp.body.exist) {
- if (check_name_mode == 'ignore') {
- await this.UploadFileDelete(user_id, drive_id, result.file_id).catch(() => {})
- return await this.UploadCreatFileWithPreHash(user_id, drive_id, parent_file_id, name, fileSize, prehash, check_name_mode)
- } else {
- result.errormsg = '出错暂停,网盘内有重名文件'
- }
- }
- result.isexist = resp.body.exist || false
- result.israpid = false
- result.upload_id = resp.body.upload_id || ''
- if (resp.body.part_info_list && resp.body.part_info_list.length > 0) {
- const part_info_list = resp.body.part_info_list
- for (let i = 0, maxi = part_info_list.length; i < maxi; i++) {
- const item = part_info_list[i]
- result.part_info_list.push({ upload_url: item.upload_url, part_number: item.part_number, part_size: partSize, isupload: false })
- }
- }
- return result
- } else {
- DebugLog.mSaveWarning('UploadCreatFileWithFolders err=' + (resp.code || ''))
- result.errormsg = '创建文件失败' + resp.code.toString()
- return result
- }
- }
-
- static async UploadCreatFileWithFolders(user_id: string, drive_id: string,
- parent_file_id: string, name: string, fileSize: number,
- hash: string, proof_code: string, check_name_mode: string): Promise {
- const result: IUploadCreat = {
- user_id,
- drive_id,
- israpid: false,
- isexist: false,
- upload_id: '',
- file_id: '',
- part_info_list: [],
- errormsg: ''
- }
- if (!user_id || !drive_id || !parent_file_id || !name) {
- result.errormsg = '创建文件失败(数据错误)'
- return result
- }
- let newFileName = name
- const pathSplitor = name.split(path.sep);
- if (pathSplitor.length > 1) {
- newFileName = pathSplitor[pathSplitor.length-1]
- const dirFullName = pathSplitor.slice(0, pathSplitor.length - 1).join(path.sep);
- const resp = await AliFileCmd.ApiCreatNewForder(user_id, drive_id, parent_file_id, dirFullName);
- parent_file_id = resp.file_id
- }
-
- const url = 'adrive/v1.0/openFile/create'
- const postData: {
- drive_id: string
- parent_file_id: string
- name: string
- type: string
- check_name_mode: string
- size: number
- content_hash?: string
- content_hash_name?: string
- proof_code?: string
- proof_version?: string
- part_info_list: { part_number: number; part_size: number }[]
- } = {
- drive_id,
- parent_file_id: parent_file_id,
- name: newFileName,
- type: 'file',
- check_name_mode: check_name_mode == 'ignore' ? 'refuse' : check_name_mode,
- size: fileSize,
- part_info_list: []
- }
-
-
- if (hash) {
- postData.content_hash = hash.toUpperCase()
- postData.content_hash_name = 'sha1'
- postData.proof_version = 'v1'
- postData.proof_code = proof_code
-
- }
-
- let partSize = 10485760
- if (fileSize > 0) {
- let partIndex = 0
-
- while (fileSize > partSize * 8000) partSize = partSize + 10485760
-
- while (partIndex * partSize < fileSize) {
- postData.part_info_list.push({ part_number: partIndex + 1, part_size: partSize })
- partIndex++
- }
- postData.part_info_list[partIndex - 1].part_size = fileSize - (partIndex - 1) * partSize
- }
-
- const resp = await AliHttp.Post(url, postData, user_id, '')
-
- if (typeof resp.body === 'object' && JSON.stringify(resp.body).indexOf('file size is exceed') > 0) {
- result.errormsg = '创建文件失败(单文件最大100GB/2TB)'
- return result
- }
-
-
- if (resp.body && resp.body.code) {
- if (resp.body?.code == 'QuotaExhausted.Drive') {
- result.errormsg = '出错暂停,网盘空间已满'
- } else if (resp.body?.code == 'InvalidRapidProof') {
-
- result.errormsg = resp.body.code
- DebugLog.mSaveDanger('InvalidRapidProof', name)
- } else {
- result.errormsg = resp.body?.code || '创建失败,网络错误'
- DebugLog.mSaveDanger('createWithFolders', result.errormsg + ' ' + name)
- }
-
- return result
- }
-
-
- if (AliHttp.IsSuccess(resp.code)) {
- result.file_id = resp.body.file_id
- if (resp.body.exist) {
- const issame = await this.UploadFileCheckHash(user_id, drive_id, result.file_id, hash)
- if (issame) {
- result.errormsg = ''
- } else {
- if (check_name_mode == 'ignore') {
- await this.UploadFileDelete(user_id, drive_id, result.file_id).catch(() => {})
- return await this.UploadCreatFileWithFolders(user_id, drive_id, parent_file_id, name, fileSize, hash, proof_code, check_name_mode)
- } else {
-
- result.errormsg = '出错暂停,网盘内有重名文件'
- }
- }
- }
- result.isexist = resp.body.exist || false
- result.israpid = result.israpid || resp.body.rapid_upload || false
- result.upload_id = resp.body.upload_id || ''
- if (resp.body.part_info_list && resp.body.part_info_list.length > 0) {
- const part_info_list = resp.body.part_info_list
- for (let i = 0, maxi = part_info_list.length; i < maxi; i++) {
- const item = part_info_list[i]
- result.part_info_list.push({ upload_url: item.upload_url, part_number: item.part_number, part_size: partSize, isupload: false })
- }
- }
- return result
- } else {
- DebugLog.mSaveWarning('UploadCreatFileWithFolders err=' + (resp.code || ''))
- result.errormsg = '创建文件失败' + resp.code.toString()
- return result
- }
- }
-
-
- static async UploadFileCheckHash(user_id: string, drive_id: string, file_id: string, hash: string): Promise {
- if (!user_id || !drive_id || !file_id) return false
- const url = 'v2/file/get?jsonmask=content_hash'
- const postData = { drive_id: drive_id, file_id: file_id }
- const resp = await AliHttp.Post(url, postData, user_id, '')
- if (AliHttp.IsSuccess(resp.code) && resp.body.content_hash) {
- const content_hash = resp.body.content_hash.toUpperCase()
- hash = hash.toUpperCase()
- return hash === content_hash
- } else {
- DebugLog.mSaveWarning('UploadFileCheckHash err=' + (resp.code || ''))
- return false
- }
- }
-
-
- static async UploadFileDelete(user_id: string, drive_id: string, file_id: string, permanently: boolean = false): Promise {
- if (!user_id || !drive_id || !file_id) return false
- const url = 'adrive/v1.0/openFile/recyclebin/trash'
- const postData = { drive_id: drive_id, file_id: file_id }
- const resp = await AliHttp.Post(url, postData, user_id, '')
- if (AliHttp.IsSuccess(resp.code)) {
- return true
- } else {
- DebugLog.mSaveWarning('UploadFileDelete err=' + (resp.code || ''))
- return false
- }
- }
-
-
- static async UploadFileComplete(user_id: string, drive_id: string, file_id: string, upload_id: string, fileSize: number, fileSha1: string): Promise {
- if (!user_id || !drive_id || !file_id || !upload_id) return false
- const url = 'adrive/v1.0/openFile/complete'
- const postData = { drive_id: drive_id, upload_id: upload_id, file_id: file_id }
- let resp = await AliHttp.Post(url, postData, user_id, '')
- if (resp.code == 400 || resp.code == 429) {
- resp = await AliHttp.Post(url, postData, user_id, '')
- }
- if (AliHttp.IsSuccess(resp.code)) {
-
- if (resp.body.size == fileSize) {
- if (fileSha1) {
-
- if (resp.body.content_hash && resp.body.content_hash == fileSha1) {
- return true
- } else {
- await this.UploadFileDelete(user_id, drive_id, file_id, true).catch(() => {})
- DebugLog.mSaveDanger('UploadFileComplete', '合并文件后发现SHA1不一致,删除已上传的文件,重新上传')
- return false
- }
- } else if (fileSize < 10485760) {
- return true
- } else {
- return true
- }
- } else {
-
- await this.UploadFileDelete(user_id, drive_id, file_id, true).catch(() => {})
- DebugLog.mSaveDanger('UploadFileComplete', '合并文件后发现大小不一致,删除已上传的文件,重新上传')
- return false
- }
- } else {
- DebugLog.mSaveDanger('UploadFileComplete', '合并文件时出错' + resp.code + ' ' + JSON.stringify(resp.header || {}) + ' ' + JSON.stringify(resp.body || {}))
- return false
- }
- }
-
-
- static async UploadFilePartUrl(user_id: string, drive_id: string, file_id: string, upload_id: string, fileSize: number, uploadInfo: IUploadInfo): Promise<'neterror' | 'success' | 'error'> {
- const url = 'adrive/v1.0/openFile/getUploadUrl'
- const postData: {
- drive_id: string
- upload_id: string
- file_id: string
- part_info_list: { part_number: number; part_size: number }[]
- } = {
- drive_id: drive_id,
- upload_id: upload_id,
- file_id: file_id,
- part_info_list: []
- }
- let partIndex = 0
-
- let partSize = 10485760
- while (fileSize > partSize * 8000) partSize = partSize + 10485760
-
- while (partIndex * partSize < fileSize) {
- postData.part_info_list.push({ part_number: partIndex + 1, part_size: partSize })
- partIndex++
- }
- postData.part_info_list[partIndex - 1].part_size = fileSize - (partIndex - 1) * partSize
-
- const resp = await AliHttp.Post(url, postData, user_id, '')
- if (resp.code >= 600 && resp.code <= 610) {
- return 'neterror'
- }
-
- if (AliHttp.IsSuccess(resp.code)) {
- if (resp.body.part_info_list && resp.body.part_info_list.length > 0) {
-
- const part_info_list = resp.body.part_info_list
- if (uploadInfo.part_info_list.length == 0) {
-
- for (let i = 0, maxi = part_info_list.length; i < maxi; i++) {
- const item = part_info_list[i]
- uploadInfo.part_info_list.push({ upload_url: item.upload_url, part_number: item.part_number, part_size: partSize, isupload: false })
- }
- } else {
-
- for (let i = 0, maxi = part_info_list.length; i < maxi; i++) {
- const item = part_info_list[i]
- uploadInfo.part_info_list[item.part_number - 1].upload_url = item.upload_url
- }
- }
- }
- return 'success'
- } else {
- uploadInfo.part_info_list = []
- DebugLog.mSaveWarning('UploadFilePartUrl err=' + upload_id + ' ' + (resp.code || ''))
- return 'error'
- }
- }
-
-
- static async UploadFileListUploadedParts(user_id: string, drive_id: string, file_id: string, upload_id: string, part_number_marker: string, uploadInfo: IUploadInfo): Promise<'neterror' | 'success' | 'error'> {
- if (!user_id || !drive_id || !file_id || !upload_id) return 'error'
-
- const url = 'adrive/v1.0/openFile/listUploadedParts'
- const postData = { drive_id: drive_id, upload_id: upload_id, file_id: file_id, next_part_number_marker:part_number_marker /* 1开始 */ }
- const resp = await AliHttp.Post(url, postData, user_id, '')
- if (resp.code >= 600 && resp.code <= 610) {
- return 'neterror'
- }
- if (AliHttp.IsSuccess(resp.code)) {
- if (resp.body.uploaded_parts && resp.body.uploaded_parts.length > 0) {
- const uploaded_parts = resp.body.uploaded_parts
- for (let i = 0, maxi = uploaded_parts.length; i < maxi; i++) {
- const item = uploaded_parts[i]
- const part_number = item.part_number
- const uploadpart = uploadInfo.part_info_list[part_number - 1]
- if (uploadpart.part_size != item.part_size) {
-
- DebugLog.mSaveDanger('list_uploaded_parts', '分片数据错误 uploadpart=' + uploadpart.part_size + ' item=' + item.part_size)
- return 'error'
- }
- uploadInfo.part_info_list[part_number - 1].isupload = true
- }
- }
- if (resp.body.next_part_number_marker && parseInt(resp.body.next_part_number_marker) > 0) {
- const next = resp.body.next_part_number_marker
- await this.UploadFileListUploadedParts(user_id, drive_id, file_id, upload_id, next, uploadInfo).catch(() => {})
- }
- return 'success'
- } else {
- DebugLog.mSaveWarning('UploadFileListUploadedParts err=' + upload_id + ' ' + (resp.code || ''))
- return 'error'
- }
- }
-
- static isNetworkError(e: Error): boolean {
- return e.message == 'Network Error' || e.message.includes('socket hang up') || e.message.includes('getaddrinfo ENOTFOUND') || e.message.includes('timeout of') || e.message.includes('connect ECONNRESET') || e.message.includes('connect ETIMEDOUT') || e.message.includes('EPIPE')
- }
-}
diff --git a/aliyunpan/src/aliapi/uploaddisk.ts b/aliyunpan/src/aliapi/uploaddisk.ts
index f656a22ba6..44f2128d02 100644
--- a/aliyunpan/src/aliapi/uploaddisk.ts
+++ b/aliyunpan/src/aliapi/uploaddisk.ts
@@ -4,23 +4,22 @@ import { OpenFileHandle } from '../utils/filehelper'
import { FileHandle, FileReadResult } from 'fs/promises'
import { IUploadInfo } from './models'
import AliUpload from './upload'
-/*import HttpsProxyAgent from 'https-proxy-agent'
-import { SocksProxyAgent } from 'socks-proxy-agent'
-import { useSettingStore } from '../store'*/
import DBCache from '../utils/dbcache'
import UserDAL from '../user/userdal'
import { Sleep } from '../utils/format'
import AliUploadHashPool from './uploadhashpool'
import nodehttps from 'https'
+import type { ClientRequest } from 'http'
import path from 'path'
import { Howl } from 'howler'
import { useSettingStore } from '../store'
-import AliUploadOpenApi from "./uploadOpenApi";
+import FlowEnc from '../module/flow-enc'
+import { getFlowEnc } from '../utils/proxyhelper'
const sound = new Howl({
src: ['./audio/upload_finished.mp3'], // 音频文件路径
autoplay: false, // 是否自动播放
- volume: 1.0, // 音量,范围 0.0 ~ 1.0
+ volume: 1.0 // 音量,范围 0.0 ~ 1.0
})
const filePosMap = new Map()
@@ -28,35 +27,41 @@ let UploadSpeedTotal = 0
export default class AliUploadDisk {
static async UploadOneFile(uploadInfo: IUploadInfo, fileui: IUploadingUI): Promise {
- if (uploadInfo.part_info_list.length > 1) return AliUploadDisk.UploadOneFileBig(uploadInfo, fileui)
+ const flowEnc = getFlowEnc(fileui.user_id, fileui.File.size, fileui.encType)
+ if (uploadInfo.part_info_list.length > 1) {
+ return AliUploadDisk.UploadOneFileBig(uploadInfo, fileui, flowEnc)
+ }
const upload_url = uploadInfo.part_info_list[0].upload_url
const fileHandle = await OpenFileHandle(path.join(fileui.localFilePath, fileui.File.partPath))
if (fileHandle.error) return fileHandle.error
-
filePosMap.set(fileui.UploadID, 0)
let isok = ''
for (let i = 0; i < 3; i++) {
- isok = await AliUploadDisk.UploadOneFilePartNode(fileui.user_id, fileui.UploadID, fileHandle.handle, 0, fileui.File.size, upload_url)
+ isok = await AliUploadDisk.UploadOneFilePartNode(
+ fileui, flowEnc, fileHandle.handle,
+ 0, fileui.File.size, upload_url
+ )
if (isok == 'success') {
break
}
}
if (fileHandle.handle) await fileHandle.handle.close()
-
-
- return AliUploadOpenApi.UploadFileComplete(fileui.user_id, fileui.drive_id, fileui.Info.up_file_id, fileui.Info.up_upload_id, fileui.File.size, uploadInfo.sha1)
- .then((isSuccess) => {
+ return AliUpload.UploadFileComplete(
+ fileui.user_id, fileui.drive_id,
+ fileui.Info.up_file_id, fileui.Info.up_upload_id,
+ fileui.File.size, uploadInfo.sha1
+ )
+ .then(async (isSuccess) => {
fileui.File.uploaded_file_id = fileui.Info.up_file_id
fileui.File.uploaded_is_rapid = false
fileui.Info.up_file_id = ''
fileui.Info.up_upload_id = ''
if (isSuccess) {
- if (useSettingStore().downFinishAudio && !sound.playing()) {
+ if (useSettingStore().downFinishAudio && !sound.playing()) {
sound.play()
}
return 'success'
- }
- else return '合并文件时出错,请重试'
+ } else return '合并文件时出错,请重试'
})
.catch((err: any) => {
DebugLog.mSaveDanger('合并文件时出错', err)
@@ -64,43 +69,37 @@ export default class AliUploadDisk {
})
}
-
- static async UploadOneFileBig(uploadInfo: IUploadInfo, fileui: IUploadingUI): Promise {
+ static async UploadOneFileBig(uploadInfo: IUploadInfo, fileui: IUploadingUI, flowEnc: FlowEnc | null): Promise {
filePosMap.set(fileui.UploadID, 0)
const fileHandle = await OpenFileHandle(path.join(fileui.localFilePath, fileui.File.partPath))
if (fileHandle.error) return fileHandle.error
-
const fileSize = fileui.File.size
-
for (let i = 0, maxi = uploadInfo.part_info_list.length; i < maxi; i++) {
let part = uploadInfo.part_info_list[i]
-
const partStart = (part.part_number - 1) * part.part_size
const partEnd = partStart + part.part_size
- const part_size = partEnd > fileSize ? fileSize - partStart : part.part_size
-
+ const partSize = partEnd > fileSize ? fileSize - partStart : part.part_size
if (part.isupload) {
- filePosMap.set(fileui.UploadID, partStart + part_size)
+ filePosMap.set(fileui.UploadID, partStart + partSize)
} else {
-
-
-
const url = part.upload_url
let expires = url.substring(url.indexOf('x-oss-expires=') + 'x-oss-expires='.length)
expires = expires.substring(0, expires.indexOf('&'))
const lastTime = parseInt(expires) - Date.now() / 1000
-
if (lastTime < 5 * 60) {
-
- await AliUploadOpenApi.UploadFilePartUrl(fileui.user_id, fileui.drive_id, fileui.Info.up_file_id, fileui.Info.up_upload_id, fileui.File.size, uploadInfo).catch(() => {})
+ await AliUpload.UploadFilePartUrl(
+ fileui.user_id, fileui.drive_id, fileui.Info.up_file_id,
+ fileui.Info.up_upload_id, fileui.File.size, uploadInfo
+ ).catch()
if (uploadInfo.part_info_list.length == 0) return '获取分片信息失败,请重试'
part = uploadInfo.part_info_list[i]
}
let isok = ''
for (let j = 0; j < 3; j++) {
- isok = await AliUploadDisk.UploadOneFilePartNode(fileui.user_id, fileui.UploadID, fileHandle.handle, partStart, part_size, part.upload_url)
- // isok = await AliUploadDisk.UploadOneFilePartNodeXHR(file.File.user_id, file.UploadID, fileHandle.handle, partStart, part_size, part.upload_url)
-
+ isok = await AliUploadDisk.UploadOneFilePartNode(
+ fileui, flowEnc, fileHandle.handle,
+ partStart, partSize, part.upload_url
+ )
if (isok == 'success') {
part.isupload = true
break
@@ -108,7 +107,7 @@ export default class AliUploadDisk {
if (!fileui.IsRunning) break
}
if (!fileui.IsRunning) break
- if (part.isupload == false) {
+ if (!part.isupload) {
if (fileHandle.handle) await fileHandle.handle.close()
return isok
}
@@ -116,16 +115,14 @@ export default class AliUploadDisk {
}
if (fileHandle.handle) await fileHandle.handle.close()
if (!fileui.IsRunning) return '已暂停'
-
for (let i = 0, maxi = uploadInfo.part_info_list.length; i < maxi; i++) {
- if (uploadInfo.part_info_list[i].isupload == false) {
+ if (!uploadInfo.part_info_list[i].isupload) {
return '有分片上传失败,请重试'
}
}
- if (!uploadInfo.sha1) {
+ if (!fileui.encType && !uploadInfo.sha1) {
if (fileui.File.size >= 1024000) {
-
const prehash = await AliUploadHashPool.GetFilePreHash(path.join(fileui.localFilePath, fileui.File.partPath))
if (fileui.File.size >= 10240000 && !prehash.startsWith('error')) {
uploadInfo.sha1 = await DBCache.getFileHash(fileui.File.size, fileui.File.mtime, prehash, path.basename(fileui.File.name))
@@ -133,16 +130,14 @@ export default class AliUploadDisk {
}
}
-
- return AliUploadOpenApi.UploadFileComplete(fileui.user_id, fileui.drive_id, fileui.Info.up_file_id, fileui.Info.up_upload_id, fileui.File.size, uploadInfo.sha1)
- .then((isSuccess) => {
+ return AliUpload.UploadFileComplete(fileui.user_id, fileui.drive_id, fileui.Info.up_file_id, fileui.Info.up_upload_id, fileui.File.size, uploadInfo.sha1)
+ .then(async (isSuccess) => {
if (isSuccess) {
if (useSettingStore().downFinishAudio && !sound.playing()) {
sound.play()
}
return 'success'
- }
- else return '合并文件时出错,请重试'
+ } else return '合并文件时出错,请重试'
})
.catch((err: any) => {
DebugLog.mSaveDanger('合并文件时出错', err)
@@ -151,9 +146,9 @@ export default class AliUploadDisk {
}
- static UploadOneFilePartNode(user_id: string, UploadID: number, fileHandle: FileHandle, partStart: number, partSize: number, upload_url: string): Promise {
+ static UploadOneFilePartNode(fileui: IUploadingUI, flowEnc: FlowEnc | null, fileHandle: FileHandle, partStart: number, partSize: number, upload_url: string): Promise {
return new Promise(async (resolve) => {
- const token = await UserDAL.GetUserTokenFromDB(user_id)
+ const token = await UserDAL.GetUserTokenFromDB(fileui.user_id)
if (!token || !token.access_token) {
resolve('找不到上传token,请重试')
return
@@ -163,35 +158,28 @@ export default class AliUploadDisk {
method: 'PUT',
strictSSL: false,
rejectUnauthorized: false,
- timeout: 15000 ,
+ timeout: 15000,
headers: {
- 'Content-Type': '' ,
+ 'Content-Type': '',
'Content-Length': partSize,
- 'Transfer-Encoding': 'chunked' ,
+ 'Transfer-Encoding': 'chunked',
Authorization: token.token_type + ' ' + token.access_token,
Connection: 'keep-alive'
}
}
-
- /*const settingStore = useSettingStore()
- const proxy = settingStore.proxyUseProxy ? settingStore.getProxy() : undefined
- if (proxy) {
- if (settingStore.proxyType.startsWith('http')) {
- const agenth = HttpsProxyAgent(proxy)
- option = Object.assign(option, { agent: agenth })
- } else {
- const agents = new SocksProxyAgent(proxy)
- option = Object.assign(option, { agent: agents })
- }
- }*/
-
- const winfo = { UploadID, isstop: false, partSize, partStart, buff: Buffer.alloc(40960) }
- const req = nodehttps.request(upload_url, option, function (res: any) {
+ const winfo = {
+ UploadID: fileui.UploadID,
+ isstop: false,
+ partSize, partStart,
+ buff: Buffer.alloc(40960),
+ flowEnc: flowEnc
+ }
+ const req: ClientRequest = nodehttps.request(upload_url, option, function(res: any) {
let _data = ''
- res.on('data', function (chunk: string) {
+ res.on('data', function(chunk: string) {
_data += chunk
})
- res.on('end', function () {
+ res.on('end', function() {
winfo.isstop = true
if (res.statusCode == 200) {
resolve('success')
@@ -211,7 +199,7 @@ export default class AliUploadDisk {
resolve('分片上传失败,稍后重试' + message)
})
- while (winfo.partSize > 0 && winfo.isstop == false) {
+ while (winfo.partSize > 0 && !winfo.isstop) {
const result = await AliUploadDisk._WriteToRequest(req, fileHandle, winfo)
if (result != 'success') {
resolve('读取文件数据失败,请重试')
@@ -222,19 +210,28 @@ export default class AliUploadDisk {
})
}
- static async _WriteToRequest(req: any, fileHandle: FileHandle, winfo: { UploadID: number; isstop: boolean; partSize: number; partStart: number; buff: Buffer }): Promise {
+ static async _WriteToRequest(req: ClientRequest, fileHandle: FileHandle, winfo: {
+ UploadID: number;
+ isstop: boolean;
+ partSize: number;
+ partStart: number;
+ buff: Buffer,
+ flowEnc: FlowEnc | null
+ }): Promise {
return new Promise((resolve) => {
try {
+ const flowEnc = winfo.flowEnc
const redLen = Math.min(40960, winfo.partSize)
if (redLen != winfo.buff.length) winfo.buff = Buffer.alloc(redLen)
fileHandle
.read(winfo.buff, 0, redLen, winfo.partStart)
- .then((rbuff: FileReadResult) => {
+ .then(async (rbuff: FileReadResult) => {
if (redLen == rbuff.bytesRead) {
winfo.partStart += redLen
winfo.partSize -= redLen
const uploadpos = winfo.partStart
- req.write(rbuff.buffer, async function () {
+ const bufferData = winfo.flowEnc ? winfo.flowEnc.encryptBuff(rbuff.buffer) : rbuff.buffer
+ req.write(bufferData, async function() {
filePosMap.set(winfo.UploadID, uploadpos)
UploadSpeedTotal += redLen
window.speedLimte -= redLen
@@ -249,114 +246,19 @@ export default class AliUploadDisk {
resolve('读取文件数据失败,请重试')
}
})
- .catch(() => {
+ .catch((error) => {
+ console.error(error)
winfo.isstop = true
resolve('读取文件数据失败,请重试')
})
- } catch {
+ } catch (error) {
+ console.error(error)
winfo.isstop = true
resolve('读取文件数据失败,请重试')
}
})
}
- static UploadOneFilePartNodeXHR(user_id: string, UploadID: number, fileHandle: FileHandle, partStart: number, partSize: number, upload_url: string): Promise {
- return new Promise(async (resolve) => {
- const token = await UserDAL.GetUserTokenFromDB(user_id)
- if (!token || !token.access_token) {
- resolve('找不到上传token,请重试')
- return
- }
- const winfo = { UploadID, isstop: false, partSize: partSize, partStart: partStart, buff: Buffer.alloc(40960) }
- const client = new XMLHttpRequest()
- client.open('PUT', upload_url)
- client.timeout = 15000
- client.setRequestHeader('ContenpartSize', partSize.toString())
- client.setRequestHeader('Content-Type', '')
- client.onreadystatechange = function () {
- switch (client.readyState) {
- case 1: // OPENED
- // do something
- break
- case 2: // HEADERS_RECEIVED
- // do something
- break
- case 3: // LOADING
- // do something
- break
- case 4: // DONE
- // do something
- break
- }
- }
- client.upload.onprogress = function updateProgress(event) {
- if (event.lengthComputable) {
- const completedPercent = event.loaded / event.total
- console.log('onprogress', event, completedPercent)
- filePosMap.set(winfo.UploadID, partStart + event.loaded)
- }
- }
-
- client.onabort = function () {
- resolve('用户暂停')
- }
- client.ontimeout = function () {
- resolve('网络超时')
- }
- client.onerror = function () {
- resolve('网络出错')
- }
-
- client.onloadend = function () {
-
- if ((client.status >= 200 && client.status < 300) || client.status == 409) {
- resolve('success')
- } else {
- resolve('分片上传失败,稍后重试' + client.status)
- DebugLog.mSaveDanger('分片上传失败,稍后重试' + client.status)
- }
- }
-
- const data = await this._ReadPartBuffer(fileHandle, winfo)
- if (data != 'success') resolve(data)
- else {
- try {
- client.send(winfo.buff)
- } catch (err: any) {
- console.log('send', err)
- resolve('联网发送失败,请重试')
- }
- }
- })
- }
-
- static async _ReadPartBuffer(fileHandle: FileHandle, winfo: { UploadID: number; isstop: boolean; partSize: number; partStart: number; buff: Buffer }): Promise {
- return new Promise((resolve) => {
- try {
- const redLen = winfo.partSize
- if (redLen != winfo.buff.length) winfo.buff = Buffer.alloc(redLen)
- fileHandle
- .read(winfo.buff, 0, redLen, winfo.partStart)
- .then((rbuff: FileReadResult) => {
- if (redLen == rbuff.bytesRead) {
- resolve('success')
- } else {
- winfo.isstop = true
- resolve('读取文件数据失败,请重试')
- }
- })
- .catch(() => {
- winfo.isstop = true
- resolve('读取文件数据失败,请重试')
- })
- } catch {
- winfo.isstop = true
- resolve('读取文件数据失败,请重试')
- }
- })
- }
-
-
static GetFileUploadSpeed(UploadID: number): number {
return filePosMap.get(UploadID) || 0
}
@@ -368,7 +270,7 @@ export default class AliUploadDisk {
static GetFileUploadSpeedTotal(): number {
- const speed = UploadSpeedTotal + 0
+ const speed = Number(UploadSpeedTotal)
UploadSpeedTotal = 0
return speed
}
diff --git a/aliyunpan/src/aliapi/uploadhashpool.ts b/aliyunpan/src/aliapi/uploadhashpool.ts
index 50c6a0c2aa..f87a97e394 100644
--- a/aliyunpan/src/aliapi/uploadhashpool.ts
+++ b/aliyunpan/src/aliapi/uploadhashpool.ts
@@ -2,8 +2,8 @@ import { IUploadingUI } from '../utils/dbupload'
import { OpenFileHandle } from '../utils/filehelper'
import DBCache from '../utils/dbcache'
import Sha1WorkerPool from '../utils/sha1workerpool'
-const path = window.require('path')
-const crypto = window.require('crypto')
+import path from 'node:path'
+import crypto from 'crypto'
const sha1PosMap = new Map()
diff --git a/aliyunpan/src/aliapi/uploadmem.ts b/aliyunpan/src/aliapi/uploadmem.ts
index 3f797f6df3..5ca6e7bc0d 100644
--- a/aliyunpan/src/aliapi/uploadmem.ts
+++ b/aliyunpan/src/aliapi/uploadmem.ts
@@ -3,25 +3,29 @@ import DebugLog from '../utils/debuglog'
import axios from 'axios'
import AliUpload from './upload'
import AliUploadHashPool from './uploadhashpool'
-import AliUploadOpenApi from "./uploadOpenApi";
+import { getFlowEnc } from '../utils/proxyhelper'
export default class AliUploadMem {
- static async UploadMem(user_id: string, drive_id: string, parent_file_id: string, CreatFileName: string, context: string) {
+ static async UploadMem(user_id: string, drive_id: string, parent_file_id: string, CreatFileName: string, context: string, encType: string = '') {
const token = await UserDAL.GetUserTokenFromDB(user_id)
- if (!token || !token.access_token || !token.access_token_v2) return '账号失效,操作取消'
+ if (!token || !token.access_token) return '账号失效,操作取消'
let hash = 'DA39A3EE5E6B4B0D3255BFEF95601890AFD80709'
let proof = ''
let buff = Buffer.from([])
if (context.length > 0) {
buff = Buffer.from(context, 'utf-8')
- const dd = await AliUploadHashPool.GetBuffHashProof(token!.access_token_v2, buff)
+ if (encType) {
+ let flowEnc = getFlowEnc(user_id, buff.length, encType)
+ buff = flowEnc && flowEnc.encryptBuff(buff) || buff
+ }
+ const dd = await AliUploadHashPool.GetBuffHashProof(token!.access_token, buff)
hash = dd.sha1
proof = dd.proof_code
}
const size = buff.length
- const upinfo = await AliUploadOpenApi.UploadCreatFileWithFolders(user_id, drive_id, parent_file_id, CreatFileName, size, hash, proof, 'refuse')
+ const upinfo = await AliUpload.UploadCreatFileWithFolders(user_id, drive_id, parent_file_id, CreatFileName, size, hash, proof, 'refuse', encType)
if (upinfo.errormsg != '') {
return upinfo.errormsg
}
@@ -33,7 +37,6 @@ export default class AliUploadMem {
responseType: 'text',
timeout: 30000,
headers: {
-
'Content-Type': '',
Authorization: token!.token_type + ' ' + token!.access_token
}
@@ -41,7 +44,7 @@ export default class AliUploadMem {
.catch(function (err: any) {
DebugLog.mSaveDanger('UploadMemError', err)
})
- const result = await AliUploadOpenApi.UploadFileComplete(user_id, drive_id, upinfo.file_id, upinfo.upload_id, size, hash)
+ const result = await AliUpload.UploadFileComplete(user_id, drive_id, upinfo.file_id, upinfo.upload_id, size, hash)
if (result) return 'success'
else return '合并文件失败'
}
diff --git a/aliyunpan/src/aliapi/user.ts b/aliyunpan/src/aliapi/user.ts
index 51c6581bc3..d75d7ba75a 100644
--- a/aliyunpan/src/aliapi/user.ts
+++ b/aliyunpan/src/aliapi/user.ts
@@ -1,25 +1,30 @@
import UserDAL from '../user/userdal'
import { humanDateTime, humanDateTimeDateStr, humanSize, Sleep } from '../utils/format'
import { ITokenInfo } from '../user/userstore'
-import AliHttp, {IUrlRespData} from './alihttp'
+import AliHttp from './alihttp'
import message from '../utils/message'
import DebugLog from '../utils/debuglog'
import { IAliUserDriveCapacity, IAliUserDriveDetails } from './models'
import { GetSignature } from './utils'
import getUuid from 'uuid-by-string'
-import Config from "../utils/config";
+import { useSettingStore } from '../store'
+import Config from '../config'
export const TokenReTimeMap = new Map()
export const TokenLockMap = new Map()
-
-export const TokenReTimeMapV2 = new Map()
-export const TokenLockMapV2 = new Map()
+export const OpenApiTokenReTimeMap = new Map()
+export const OpenApiTokenLockMap = new Map()
export const SessionLockMap = new Map()
export const SessionReTimeMap = new Map()
export default class AliUser {
- static async ApiSessionRefreshAccount(token: ITokenInfo, showMessage: boolean): Promise {
- if(!token.user_id) return false
+ static async ApiSessionRefreshAccount(token: ITokenInfo, showMessage: boolean, forceRefresh: boolean = false): Promise {
+ if (!token.user_id) return false
+ if (!forceRefresh && new Date(token.session_expires_in).getTime() >= Date.now()) return true
+ if (forceRefresh) {
+ SessionLockMap.delete(token.user_id)
+ SessionReTimeMap.delete(token.user_id)
+ }
while (true) {
const lock = SessionLockMap.has(token.user_id)
if (lock) await Sleep(1000)
@@ -31,7 +36,7 @@ export default class AliUser {
SessionLockMap.delete(token.user_id)
return true
}
- const apiUrl = 'https://api.aliyundrive.com/users/v1/users/device/create_session'
+ const apiUrl = 'https://api.alipan.com/users/v1/users/device/create_session'
let { signature, publicKey } = GetSignature(0, token.user_id, token.device_id)
const postData = {
'deviceName': 'Edge浏览器',
@@ -42,11 +47,12 @@ export default class AliUser {
SessionLockMap.delete(token.user_id)
if (AliHttp.IsSuccess(resp.code)) {
SessionReTimeMap.set(token.user_id, Date.now())
+ token.session_expires_in = Date.now() + 30 * 60 * 1000
token.signature = signature
UserDAL.SaveUserToken(token)
return true
} else {
- DebugLog.mSaveWarning('ApiSessionRefreshAccount err=' + (resp.code || '') + ' ' + (resp.body?.code || ''))
+ DebugLog.mSaveWarning('ApiSessionRefreshAccount err=' + (resp.code || '') + ' ' + (resp.body?.code || ''), resp.body)
if (showMessage) {
message.error('刷新账号[' + token.user_name + '] session 失败')
}
@@ -54,84 +60,10 @@ export default class AliUser {
return false
}
- static async ApiTokenRefreshAccountV2(token: ITokenInfo): Promise {
- const postData = {
- refresh_token: token.refresh_token_v2,
- grant_type: 'refresh_token',
- client_secret: '',
- client_id: ''
- }
- return await AliHttp.Post(Config.accessTokenUrl, postData, '', '')
- }
-
-// {
-// "token_type": "Bearer",
-// "access_token": "",
-// "refresh_token": "",
-// "expires_in": 7200
-// }
- static async ApiTokenRefreshAccountV2_TMP(token: ITokenInfo): Promise {
- const postData = {
- refresh_token: token.refresh_token_v2,
- grant_type: 'refresh_token'
- }
- return await AliHttp._Post(Config.tmpUrl, postData, '', '')
- }
-
- static async ApiRefreshAccessTokenV2(token: ITokenInfo, showMessage: boolean, force: boolean = false): Promise {
- if (!token.refresh_token_v2) return false
- if (!force && token.expires_in_v2 && token.expires_in_v2 > Date.now()) {
- return true
- }
- if (force) {
- TokenLockMapV2.delete(token.user_id)
- TokenReTimeMapV2.delete(token.user_id)
- }
- while (true) {
- const lock = TokenLockMapV2.has(token.user_id)
- if (lock) await Sleep(1000)
- else break
- }
- TokenLockMapV2.set(token.user_id, Date.now())
- const time = TokenReTimeMapV2.get(token.user_id) || 0
- if (Date.now() - time < 1000 * 60 * 5) {
- TokenLockMapV2.delete(token.user_id)
- return true
- }
-
- const resp = await this.ApiTokenRefreshAccountV2(token)
- TokenLockMapV2.delete(token.user_id)
- if (AliHttp.IsSuccess(resp.code)) {
- TokenReTimeMapV2.set(token.user_id, Date.now())
- token.tokenfrom = 'account'
-
- token.refresh_token_v2 = resp.body.refresh_token
- token.access_token_v2 = resp.body.access_token
- token.expires_in_v2 = Date.now() + resp.body.expires_in * 1000
- token.token_type_v2 = resp.body.token_type
-
- UserDAL.SaveUserToken(token)
- return true
- } else {
- if (resp.body?.code != 'InvalidParameter.RefreshToken') {
- DebugLog.mSaveWarning('ApiTokenRefreshAccountV2 err=' + (resp.code || '') + ' ' + (resp.body?.code || ''))
- }
- if (showMessage) {
- message.error('刷新账号[' + token.user_name + '] v2 token 失败,需要重新登录')
- UserDAL.UserLogOff(token.user_id)
- } else {
- UserDAL.UserClearFromDB(token.user_id)
- }
- }
- return false
- }
-
- static async ApiRefreshAccessTokenV1(token: ITokenInfo, showMessage: boolean, force: boolean = false): Promise {
+ static async ApiTokenRefreshAccount(token: ITokenInfo, showMessage: boolean, forceRefresh: boolean = false): Promise {
if (!token.refresh_token) return false
- if (!force && token.expires_in && token.expires_in > Date.now()) {
- return true
- }
- if (force) {
+ if (!forceRefresh && new Date(token.expire_time).getTime() >= Date.now()) return true
+ if (forceRefresh) {
TokenLockMap.delete(token.user_id)
TokenReTimeMap.delete(token.user_id)
}
@@ -147,8 +79,7 @@ export default class AliUser {
return true
}
- const url = 'https://auth.aliyundrive.com/v2/account/token'
-
+ const url = 'https://auth.alipan.com/v2/account/token'
const postData = { refresh_token: token.refresh_token, grant_type: 'refresh_token' }
const resp = await AliHttp.Post(url, postData, '', '')
TokenLockMap.delete(token.user_id)
@@ -157,12 +88,13 @@ export default class AliUser {
token.tokenfrom = 'account'
token.access_token = resp.body.access_token
token.refresh_token = resp.body.refresh_token
- token.expires_in = Date.now() + resp.body.expires_in * 1000
+ token.expires_in = resp.body.expires_in
token.token_type = resp.body.token_type
token.user_id = resp.body.user_id
token.user_name = resp.body.user_name
token.avatar = resp.body.avatar
token.nick_name = resp.body.nick_name
+ token.default_drive_id = resp.body.default_drive_id
token.default_sbox_drive_id = resp.body.default_sbox_drive_id
token.role = resp.body.role
token.status = resp.body.status
@@ -182,10 +114,10 @@ export default class AliUser {
return true
} else {
if (resp.body?.code != 'InvalidParameter.RefreshToken') {
- DebugLog.mSaveWarning('ApiTokenRefreshAccount err=' + (resp.code || '') + ' ' + (resp.body?.code || ''))
+ DebugLog.mSaveWarning('ApiTokenRefreshAccount err=' + (resp.code || '') + ' ' + (resp.body?.code || ''), resp.body)
}
if (showMessage) {
- message.error('刷新账号[' + token.user_name + '] v1 token 失败,需要重新登录')
+ message.error('刷新账号[' + token.user_name + '] token 失败,需要重新登录')
UserDAL.UserLogOff(token.user_id)
} else {
UserDAL.UserClearFromDB(token.user_id)
@@ -195,40 +127,197 @@ export default class AliUser {
}
- static async ApiUserInfo(token: ITokenInfo): Promise {
- if (!token.user_id || !token.access_token_v2) return false
- const url = 'adrive/v1.0/user/getDriveInfo'
- const spaceUrl = 'adrive/v1.0/user/getSpaceInfo'
- const postData = ''
- const resp = await AliHttp.Post(url, postData, token.user_id, '')
- const spaceResp = await AliHttp.Post(spaceUrl, postData, token.user_id, '')
- if (AliHttp.IsSuccess(spaceResp.code)) {
- token.used_size = spaceResp.body.personal_space_info.used_size
- token.total_size = spaceResp.body.personal_space_info.total_size
- token.spaceinfo = humanSize(token.used_size) + ' / ' + humanSize(token.total_size)
- } else {
- DebugLog.mSaveWarning('getSpaceInfo err=' + (resp.code || ''))
+ static async OpenApiTokenRefreshAccount(token: ITokenInfo, showMessage: boolean, forceRefresh: boolean = false): Promise {
+ if (!token.open_api_refresh_token) return false
+ if (!forceRefresh && new Date(token.open_api_expires_in).getTime() >= Date.now()) return true
+ // 防止重复刷新
+ if (forceRefresh) {
+ OpenApiTokenLockMap.delete(token.user_id)
+ OpenApiTokenReTimeMap.delete(token.user_id)
}
+ while (true) {
+ const lock = OpenApiTokenLockMap.has(token.user_id)
+ if (lock) await Sleep(1000)
+ else break
+ }
+ OpenApiTokenLockMap.set(token.user_id, Date.now())
+ const time = OpenApiTokenReTimeMap.get(token.user_id) || 0
+ if (Date.now() - time < 1000 * 60 * 5) {
+ OpenApiTokenLockMap.delete(token.user_id)
+ return true
+ }
+ let { uiEnableOpenApiType, uiOpenApiClientId, uiOpenApiClientSecret } = useSettingStore()
+ let url = 'https://openapi.alipan.com/oauth/access_token'
+ let client_id = Config.client_id
+ let client_secret = Config.client_secret
+ if (uiEnableOpenApiType === 'custom') {
+ client_id = uiOpenApiClientId
+ client_secret = uiOpenApiClientSecret
+ }
+ const postData = {
+ refresh_token: token.open_api_refresh_token,
+ grant_type: 'refresh_token',
+ client_id: client_id,
+ client_secret: client_secret
+ }
+ const resp = await AliHttp.Post(url, postData, '', '')
+ OpenApiTokenLockMap.delete(token.user_id)
if (AliHttp.IsSuccess(resp.code)) {
- token.spu_id = ''
- token.phone = resp.body.phone
- token.backup_drive_id = resp.body.backup_drive_id || '';
- token.resource_drive_id = resp.body.resource_drive_id || ''
- if (token.backup_drive_id === '') {
- token.backup_drive_id = resp.body.default_drive_id
- }
- token.is_expires = resp.body.status === 'enabled'
- token.name = resp.body.nick_name===''?resp.body.phone:resp.body.nick_name
+ const { access_token, refresh_token, token_type, expires_in } = resp.body
+ OpenApiTokenReTimeMap.set(token.user_id, Date.now())
+ token.open_api_token_type = token_type
+ token.open_api_access_token = access_token
+ token.open_api_refresh_token = refresh_token
+ token.open_api_expires_in = Date.now() + expires_in * 1000
+ window.WebUserToken({
+ user_id: token.user_id,
+ name: token.user_name,
+ access_token: token.access_token,
+ open_api_access_token: token.open_api_access_token,
+ refresh: true
+ })
+ UserDAL.SaveUserToken(token)
return true
} else {
- DebugLog.mSaveWarning('ApiUserInfo err=' + (resp.code || ''))
+ DebugLog.mSaveWarning('OpenApiTokenRefreshAccount err=' + (resp.code || '') + ' ' + (resp.body?.code || ''), resp.body)
+ if (showMessage) {
+ message.error('刷新账号[' + token.user_name + '] OpenApiToken 失败, 请重新获取', 5)
+ }
+ }
+ return false
+ }
+
+ static async OpenApiQrCodeUrl(client_id: string, client_secret: string, width: number = 348, height: number = 348): Promise {
+ const postData = {
+ client_id: client_id,
+ client_secret: client_secret,
+ scopes: ['user:base', 'file:all:read', 'file:all:write'],
+ width: width,
+ height: height
+ }
+ const url = 'https://openapi.alipan.com/oauth/authorize/qrcode'
+ const resp = await AliHttp.Post(url, postData, '', '')
+ if (AliHttp.IsSuccess(resp.code)) {
+ return resp.body.qrCodeUrl
+ } else {
+ message.error('获取二维码失败,请重新输入')
+ return ''
+ }
+ }
+
+ static async OpenApiQrCodeStatus(qrCodeUrl: string): Promise {
+ const resp = await AliHttp.Get(qrCodeUrl + '/status', '')
+ const statusJudge = (status: string) => {
+ switch (status) {
+ case 'WaitLogin':
+ return { type: 'info', tips: '状态:等待扫码登录' }
+ case 'ScanSuccess':
+ return { type: 'warning', tips: '状态:扫码成功,点击允许' }
+ case 'LoginSuccess':
+ return { type: 'success', tips: '状态:登录成功' }
+ case 'QRCodeExpired':
+ return { type: 'error', tips: '状态:二维码过期,点击刷新' }
+ default:
+ return { type: 'error', tips: '状态:二维码过期,点击刷新' }
+ }
+ }
+ if (AliHttp.IsSuccess(resp.code)) {
+ let statusCode = resp.body.status
+ let statusData = statusJudge(statusCode)
+ return {
+ authCode: statusCode === 'LoginSuccess' ? resp.body.authCode : '',
+ statusCode: statusCode,
+ statusType: statusData.type || '',
+ statusTips: statusData.tips || ''
+ }
+ } else {
+ message.error('获取二维码状态失败[' + resp.body?.message + '],请检查配置')
+ }
+ return false
+ }
+
+ static async OpenApiLoginByAuthCode(token: ITokenInfo, client_id: string, client_secret: string, authCode: string, issave: boolean = false): Promise {
+ // 构造请求体
+ const postData: any = {
+ code: authCode,
+ grant_type: 'authorization_code',
+ client_id: client_id,
+ client_secret: client_secret
+ }
+ const url = 'https://openapi.alipan.com/oauth/access_token'
+ const resp = await AliHttp.Post(url, postData, '', '')
+ if (AliHttp.IsSuccess(resp.code)) {
+ const { access_token, refresh_token, token_type, expires_in } = resp.body
+ token.open_api_token_type = token_type
+ token.open_api_access_token = access_token
+ token.open_api_refresh_token = refresh_token
+ token.open_api_expires_in = Date.now() + expires_in * 1000
+ if (issave) {
+ window.WebUserToken({
+ user_id: token.user_id,
+ name: token.user_name,
+ access_token: token.access_token,
+ open_api_access_token: token.open_api_access_token,
+ refresh: true
+ })
+ UserDAL.SaveUserToken(token)
+ }
+ return true
+ } else {
+ if (resp.body?.code === 'InvalidCode') {
+ message.error('授权码无效, 请检查配置')
+ } else {
+ message.error('登录失败[' + resp.body?.message + ']')
+ }
+ }
+ return false
+ }
+
+ static async ApiUserInfo(token: ITokenInfo): Promise {
+ if (!token.user_id) return false
+ const url = 'v2/databox/get_personal_info'
+ const postData = ''
+ const resp = await AliHttp.Post(url, postData, token.user_id, '')
+ if (AliHttp.IsSuccess(resp.code)) {
+ token.used_size = resp.body.personal_space_info.used_size
+ token.total_size = resp.body.personal_space_info.total_size
+ token.spu_id = resp.body.personal_rights_info.spu_id
+ token.is_expires = resp.body.personal_rights_info.is_expires
+ token.name = resp.body.personal_rights_info.name
+ token.spaceinfo = humanSize(token.used_size) + ' / ' + humanSize(token.total_size)
+ return true
+ } else if (!AliHttp.HttpCodeBreak(resp.code)) {
+ DebugLog.mSaveWarning('ApiUserInfo err=' + (resp.code || ''), resp.body)
+ }
+ return false
+ }
+
+ static async ApiUserDriveInfo(token: ITokenInfo): Promise {
+ if (!token.user_id) return false
+ let url = ''
+ let need_open_api = false
+ if (need_open_api) {
+ url = 'https://openapi.alipan.com/adrive/v1.0/user/getDriveInfo'
+ } else {
+ url = 'https://user.alipan.com/v2/user/get'
+ }
+ const resp = await AliHttp.Post(url, {}, token.user_id, '')
+ if (AliHttp.IsSuccess(resp.code)) {
+ token.default_drive_id = resp.body.default_drive_id
+ token.backup_drive_id = resp.body.backup_drive_id || resp.body.default_drive_id
+ token.resource_drive_id = resp.body.resource_drive_id
+ token.sbox_drive_id = resp.body.sbox_drive_id || ''
+ token.phone = resp.body.user_name.replace('***', '')
+ return true
+ } else if (!AliHttp.HttpCodeBreak(resp.code)) {
+ DebugLog.mSaveWarning('ApiUserDriveInfo err=' + (resp.code || ''), resp.body)
}
return false
}
static async ApiUserSign(token: ITokenInfo): Promise {
if (!token.user_id) return -1
- const signUrl = 'https://member.aliyundrive.com/v1/activity/sign_in_list'
+ const signUrl = 'https://member.alipan.com/v1/activity/sign_in_list'
const signResp = await AliHttp.Post(signUrl, {}, token.user_id, '')
// console.log(JSON.stringify(resp))
if (AliHttp.IsSuccess(signResp.code)) {
@@ -252,7 +341,7 @@ export default class AliUser {
}
let reward = '无奖励'
if (!sign_data['isReward']) {
- const rewardUrl = 'https://member.aliyundrive.com/v1/activity/sign_in_reward'
+ const rewardUrl = 'https://member.alipan.com/v1/activity/sign_in_reward'
const rewardResp = await AliHttp.Post(rewardUrl, { signInDay: signInCount }, token.user_id, '')
if (AliHttp.IsSuccess(rewardResp.code)) {
if (!rewardResp.body || !rewardResp.body.result || !rewardResp.body.success) {
@@ -260,10 +349,10 @@ export default class AliUser {
return -1
}
const result = rewardResp.body.result
- reward = `获得【${result['name']}】 - ${result['description']}`
+ reward = `【${result['notice']}】`
}
} else {
- reward = `获得【${sign_data['reward']['name']}】 - ${sign_data['reward']['description']}`
+ reward = `【${sign_data['reward']['notice']}】`
}
message.info(`【${token.nick_name || token.user_name}】本月累计签到${signInCount}次,本次签到 ${reward}`)
return parseInt(sign_data['calendarDay'])
@@ -274,65 +363,64 @@ export default class AliUser {
}
+ static async ApiUserRewardSpace(user_id: string, gift_code: string) {
+ if (!user_id) return false
+ const url = 'https://member.alipan.com/v1/users/rewards'
+ const postData = { code: gift_code }
+ const resp = await AliHttp.Post(url, postData, user_id, '')
+ if (AliHttp.IsSuccess(resp.code)) {
+ if (!resp.body || !resp.body.result) {
+ return { status: false, message: resp.body?.message }
+ }
+ if (!resp.body.success) {
+ return { status: false, message: resp.body?.message }
+ } else {
+ return { status: true, message: resp.body.result?.message }
+ }
+ } else {
+ return { status: false, message: resp.body?.message }
+ }
+ }
+
static async ApiUserVip(token: ITokenInfo): Promise {
if (!token.user_id) return false
- const url = 'https://openapi.aliyundrive.com/v1.0/user/getVipInfo'
+ const url = 'business/v1.0/users/vip/info'
+
+
const postData = {}
const resp = await AliHttp.Post(url, postData, token.user_id, '')
if (AliHttp.IsSuccess(resp.code)) {
-
- token.vipname = resp.body.identity
- token.vipIcon = ''
- if (resp.body.identity === 'member') {
- token.vipexpire = ''
+ let vipList = resp.body.vipList || []
+ vipList = vipList.sort((a: any, b: any) => b.expire - a.expire)
+ if (vipList.length > 0 && new Date(vipList[0].expire * 1000) > new Date()) {
+ token.vipname = vipList[0].name
+ token.vipIcon = resp.body.mediumIcon
+ token.vipexpire = humanDateTime(vipList[0].expire)
} else {
- token.viplevel = resp.body.level
- token.vipexpire = humanDateTime(resp.body.expire)
+ token.vipname = '免费用户'
+ token.vipIcon = ''
+ token.vipexpire = ''
}
return true
- } else {
- DebugLog.mSaveWarning('ApiUserPic err=' + (resp.code || ''))
+ } else if (!AliHttp.HttpCodeBreak(resp.code)) {
+ DebugLog.mSaveWarning('ApiUserPic err=' + (resp.code || ''), resp.body)
}
return false
}
- // static async ApiUserVip(token: ITokenInfo): Promise {
- // if (!token.user_id) return false
- // const url = 'business/v1.0/users/vip/info'
- //
- //
- // const postData = {}
- // const resp = await AliHttp.Post(url, postData, token.user_id, '')
- // if (AliHttp.IsSuccess(resp.code)) {
- // let vipList = resp.body.vipList || []
- // vipList = vipList.sort((a: any, b: any) => b.expire - a.expire)
- // if (vipList.length > 0 && new Date(vipList[0].expire * 1000) > new Date()) {
- // token.vipname = vipList[0].name
- // token.vipIcon = resp.body.mediumIcon
- // token.vipexpire = humanDateTime(vipList[0].expire)
- // } else {
- // token.vipname = '免费用户'
- // token.vipIcon = ''
- // token.vipexpire = ''
- // }
- // return true
- // } else {
- // DebugLog.mSaveWarning('ApiUserPic err=' + (resp.code || ''))
- // }
- // return false
- // }
-
static async ApiUserPic(token: ITokenInfo): Promise {
if (!token.user_id) return false
const url = 'adrive/v1/user/albums_info'
+
+
const postData = {}
const resp = await AliHttp.Post(url, postData, token.user_id, '')
if (AliHttp.IsSuccess(resp.code)) {
token.pic_drive_id = resp.body.data.driveId
return true
- } else {
- DebugLog.mSaveWarning('ApiUserPic err=' + (resp.code || ''))
+ } else if (!AliHttp.HttpCodeBreak(resp.code)) {
+ DebugLog.mSaveWarning('ApiUserPic err=' + (resp.code || ''), resp.body)
}
return false
}
@@ -364,8 +452,8 @@ export default class AliUser {
detail.resource_drive_used_size = resp.body.resource_drive_used_size || 0
detail.sbox_drive_used_size = resp.body.sbox_drive_used_size || 0
detail.share_album_drive_used_size = resp.body.share_album_drive_used_size || 0
- } else {
- DebugLog.mSaveWarning('ApiUserDriveDetails err=' + (resp.code || ''))
+ } else if (!AliHttp.HttpCodeBreak(resp.code)) {
+ DebugLog.mSaveWarning('ApiUserDriveDetails err=' + (resp.code || ''), resp.body)
}
return detail
}
@@ -374,9 +462,9 @@ export default class AliUser {
if (!user_id) return 0
const token = await UserDAL.GetUserTokenFromDB(user_id)
if (!token) return 0
- const url = 'adrive/v1.0/openFile/search'
+ const url = 'adrive/v3/file/search'
const postData = {
- drive_id: token?.backup_drive_id,
+ drive_id_list: [token.backup_drive_id, token.resource_drive_id],
marker: '',
limit: 1,
all: false,
@@ -389,8 +477,8 @@ export default class AliUser {
try {
if (AliHttp.IsSuccess(resp.code)) {
return resp.body.total_count || 0
- } else {
- DebugLog.mSaveWarning('ApiUserDriveFileCount err=' + category + ' ' + (resp.code || ''))
+ } else if (!AliHttp.HttpCodeBreak(resp.code)) {
+ DebugLog.mSaveWarning('ApiUserDriveFileCount err=' + category + ' ' + (resp.code || ''), resp.body)
}
} catch (err: any) {
DebugLog.mSaveDanger('ApiUserDriveFileCount' + category, err)
@@ -432,8 +520,8 @@ export default class AliUser {
} as IAliUserDriveCapacity)
}
result = result.sort((a, b) => a.latest_receive_time.localeCompare(b.latest_receive_time))
- } else {
- DebugLog.mSaveWarning('ApiUserCapacityDetails err=' + (resp.code || ''))
+ } else if (!AliHttp.HttpCodeBreak(resp.code)) {
+ DebugLog.mSaveWarning('ApiUserCapacityDetails err=' + (resp.code || ''), resp.body)
}
return result
}
diff --git a/aliyunpan/src/aliapi/utils.ts b/aliyunpan/src/aliapi/utils.ts
index 8480bc70bc..e605cd1e06 100644
--- a/aliyunpan/src/aliapi/utils.ts
+++ b/aliyunpan/src/aliapi/utils.ts
@@ -1,4 +1,4 @@
-import { ITokenInfo, useFootStore } from '../store'
+import { useFootStore, useSettingStore } from '../store'
import UserDAL from '../user/userdal'
import DebugLog from '../utils/debuglog'
import { Sleep } from '../utils/format'
@@ -9,53 +9,45 @@ import { IAliBatchResult } from './models'
import { SHA256 } from 'crypto-js'
import { ecdsaSign, publicKeyCreate } from 'secp256k1'
+import { IAliFileItem, IAliGetFileModel } from './alimodels'
+import { decodeName, encodeName } from '../module/flow-enc/utils'
+import path from 'path'
+import mime from 'mime-types'
+import { getEncPassword, getEncType } from '../utils/proxyhelper'
-export declare type Drive = 'pan' | 'pic' | 'safe'
-
-
-export function GetDriveID(user_id: string, drive: Drive): string {
+export function GetDriveID(user_id: string, drive: string): string {
const token = UserDAL.GetUserToken(user_id)
if (token) {
- switch (drive) {
- case 'pan':
- return token.backup_drive_id
- case 'pic':
- return token.pic_drive_id
- case 'safe':
- return token.default_sbox_drive_id
+ if (drive.includes('backup')) {
+ return token.backup_drive_id
+ } else if (drive.includes('resource')) {
+ return token.resource_drive_id
+ } else if (drive.includes('pic')) {
+ return token.pic_drive_id
+ } else if (drive.includes('safe')) {
+ return token.default_sbox_drive_id
}
}
return ''
}
-
-export function GetDriveID2(token: ITokenInfo, driveName: string): string {
- if (token) {
- switch (driveName) {
- case 'pan':
- return token.backup_drive_id
- case 'pic':
- return token.pic_drive_id
- case 'safe':
- return token.default_sbox_drive_id
- }
- }
- return driveName
-}
-
export function GetDriveType(user_id: string, drive_id: string): any {
const token = UserDAL.GetUserToken(user_id)
if (token) {
switch (drive_id) {
case token.backup_drive_id:
- return { title: '备份盘', key: 'backup_root' }
+ return { title: '备份盘', name: 'backup', key: 'backup_root' }
case token.resource_drive_id:
- return { title: '资源盘', key: 'resource_root' }
+ return { title: '资源盘', name: 'resource', key: 'resource_root' }
+ case token.pic_drive_id:
+ return { title: '全部相册', name: 'pic', key: 'pic_root' }
case token.default_sbox_drive_id:
- return { title: '安全盘', key: 'safe_root' }
+ return { title: '安全盘', name: 'safe', key: 'safe_root' }
+ default:
+ return { title: '备份盘', name: 'backup', key: 'backup_root' }
}
}
- return { title: '', key: '' }
+ return { title: '备份盘', name: 'backup', key: 'backup_root' }
}
export function GetSignature(nonce: number, user_id: string, deviceId: string) {
@@ -63,8 +55,8 @@ export function GetSignature(nonce: number, user_id: string, deviceId: string) {
const hashArray = Array.from(bytes) // convert buffer to byte array
// convert bytes to hex string
return hashArray
- .map((b) => b.toString(16).padStart(2, '0'))
- .join('')
+ .map((b) => b.toString(16).padStart(2, '0'))
+ .join('')
}
const toU8 = (wordArray: CryptoJS.lib.WordArray) => {
const words = wordArray.words
@@ -83,6 +75,69 @@ export function GetSignature(nonce: number, user_id: string, deviceId: string) {
return { signature, publicKey }
}
+export function EncodeEncName(user_id: string, name: string, isDir: boolean, encType: string, inputpassword: string = '') {
+ let settingStore = useSettingStore()
+ if (encType && settingStore.securityEncFileName) {
+ // 加密名称
+ const splitFolder = name.split('/')
+ const securityPassword = getEncPassword(user_id, encType, inputpassword)
+ const securityEncType = settingStore.securityEncType
+ if (!isDir) {
+ return splitFolder.map(name => {
+ let plainName = ''
+ let basename = path.basename(name)
+ let extname = path.extname(name)
+ if (settingStore.securityEncFileNameHideExt) {
+ plainName = basename
+ extname = ''
+ } else {
+ plainName = basename.replace(extname, '')
+ }
+ return encodeName(securityPassword, securityEncType, plainName) + extname
+ }).join('/')
+ } else {
+ return splitFolder.map(name => encodeName(securityPassword, securityEncType, name)).join('/')
+ }
+ } else {
+ return name
+ }
+}
+
+export function DecodeEncName(user_id: string, item: IAliFileItem | IAliGetFileModel, inputpassword: string = '') {
+ // 自动解密文件名
+ let settingStore = useSettingStore()
+ const securityFileNameAutoDecrypt = settingStore.securityFileNameAutoDecrypt
+ const securityEncType = settingStore.securityEncType
+ let ext = ''
+ let mine_type = item.mime_type
+ if ('file_extension' in item) {
+ ext = item.file_extension || ''
+ } else if ('ext' in item) {
+ ext = item.ext
+ }
+ let name = item.name
+ let description = item.description
+ let need_decode = description && description.includes('xbyEncrypt')
+ if (need_decode && securityFileNameAutoDecrypt) {
+ let encType = getEncType(item)
+ let filename = item.name.replace(ext ? '.' + ext : '', '')
+ let password = getEncPassword(user_id, encType, inputpassword)
+ let realName = decodeName(password, securityEncType, filename) || item.name
+ if (ext) {
+ name = realName + '.' + ext
+ } else if (path.extname(realName)) {
+ // 修复加密后的扩展
+ name = realName
+ ext = path.extname(realName).replace('.', '')
+ mine_type = mime.lookup(ext) || 'application/oct-stream'
+ } else {
+ name = realName
+ }
+ return { name: name, mine_type, ext }
+ }
+ return { name: item.name, mine_type, ext }
+}
+
async function _ApiBatch(postData: string, user_id: string, share_token: string, result: IAliBatchResult): Promise {
if (!user_id && !share_token) return
const url = 'v2/batch'
@@ -97,24 +152,46 @@ async function _ApiBatch(postData: string, user_id: string, share_token: string,
if (respi.body && respi.body.async_task_id) {
- result.async_task.push({ drive_id: respi.body.drive_id || '', file_id: respi.id, task_id: respi.body.async_task_id, newdrive_id: respi.body.drive_id || '', newfile_id: respi.body.file_id || '' })
+ result.async_task.push({
+ drive_id: respi.body.drive_id || '',
+ file_id: respi.id,
+ task_id: respi.body.async_task_id,
+ newdrive_id: respi.body.drive_id || '',
+ newfile_id: respi.body.file_id || ''
+ })
} else if (respi.body && respi.body.share_id && respi.body.share_msg) {
- result.reslut.push({ id: respi.id, share_id: respi.body.share_id, share_pwd: respi.body.share_pwd || '', share_url: respi.body.share_url, expiration: respi.body.expiration || '', share_name: respi.body.share_name || '' })
+ result.reslut.push({
+ id: respi.id,
+ share_id: respi.body.share_id,
+ share_pwd: respi.body.share_pwd || '',
+ share_url: respi.body.share_url,
+ expiration: respi.body.expiration || '',
+ share_name: respi.body.share_name || ''
+ })
} else if (respi.body) {
- result.reslut.push({ id: respi.id, file_id: respi.body.file_id, name: respi.body.name || '', body: respi.body })
+ result.reslut.push({
+ id: respi.id,
+ file_id: respi.body.file_id,
+ name: respi.body.name || '',
+ body: respi.body
+ })
} else if (respi.id) {
result.reslut.push({ id: respi.id, file_id: respi.id })
}
} else {
const respi = responses[i]
const logmsg = (respi.body.code || '') + ' ' + (respi.body.message || '')
- if (logmsg.includes('File under sync control') == false) DebugLog.mSaveDanger(logmsg)
- if (respi.body && respi.body.code) result.error.push({ id: respi.body.id || respi.id, code: respi.body.code, message: respi.body.message })
+ if (!logmsg.includes('File under sync control')) DebugLog.mSaveDanger(logmsg)
+ if (respi.body && respi.body.code) result.error.push({
+ id: respi.body.id || respi.id,
+ code: respi.body.code,
+ message: respi.body.message
+ })
}
}
- } else {
- DebugLog.mSaveWarning('_ApiBatch err=' + (resp.code || ''))
+ } else if (!AliHttp.HttpCodeBreak(resp.code)) {
+ DebugLog.mSaveWarning('_ApiBatch err=' + (resp.code || ''), resp.body)
}
}
@@ -142,8 +219,7 @@ export async function ApiBatch(title: string, batchList: string[], user_id: stri
}
if (allTask.length >= 3) {
-
- await Promise.all(allTask).catch(() => {})
+ await Promise.all(allTask).catch()
allTask = []
if (title != '') message.loading(title + ' 执行中...(' + result.count.toString() + ')', 60, loadingKey)
}
@@ -152,7 +228,8 @@ export async function ApiBatch(title: string, batchList: string[], user_id: stri
postData += '],"resource":"file"}'
allTask.push(_ApiBatch(postData, user_id, share_token, result))
}
- if (allTask.length > 0) await Promise.all(allTask).catch(() => {})
+ if (allTask.length > 0) await Promise.all(allTask).catch(() => {
+ })
if (result.async_task.length > 0) {
if (title != '' || share_token != '') message.warning(title + ' 异步执行中(' + result.async_task.length + ')', 2, loadingKey)
@@ -218,7 +295,13 @@ export function ApiBatchMaker(url: string, idList: string[], bodymake: (file_id:
const id = idList[i]
if (batchSet.has(id)) continue
batchSet.add(id)
- batchList.push(JSON.stringify({ body: bodymake(id), headers: { 'Content-Type': 'application/json' }, id: id, method: 'POST', url }))
+ batchList.push(JSON.stringify({
+ body: bodymake(id),
+ headers: { 'Content-Type': 'application/json' },
+ id: id,
+ method: 'POST',
+ url
+ }))
}
batchSet.clear()
return batchList
@@ -232,7 +315,13 @@ export function ApiBatchMaker2(url: string, idList: string[], namelist: string[]
const id = idList[i]
if (batchSet.has(id)) continue
batchSet.add(id)
- batchList.push(JSON.stringify({ body: bodymake(id, namelist[i]), headers: { 'Content-Type': 'application/json' }, id: id, method: 'POST', url }))
+ batchList.push(JSON.stringify({
+ body: bodymake(id, namelist[i]),
+ headers: { 'Content-Type': 'application/json' },
+ id: id,
+ method: 'POST',
+ url
+ }))
}
batchSet.clear()
return batchList
@@ -279,8 +368,8 @@ export async function ApiGetAsyncTask(user_id: string, async_task_id: string): P
message.warning('操作部分成功 ' + resp.body.message?.replace('ErrQuotaExhausted', '网盘空间已满') || '', 5)
return 'error'
}
- } else {
- DebugLog.mSaveWarning('ApiGetAsyncTask err=' + (resp.code || ''))
+ } else if (!AliHttp.HttpCodeBreak(resp.code)) {
+ DebugLog.mSaveWarning('ApiGetAsyncTask err=' + (resp.code || ''), resp.body)
}
return 'error'
}
@@ -299,8 +388,8 @@ export async function ApiGetAsyncTaskUnzip(user_id: string, drive_id: string, fi
message.warning('操作部分成功 ' + resp.body.message?.replace('ErrQuotaExhausted', '网盘空间已满') || '', 5)
return 'error'
}
- } else {
- DebugLog.mSaveWarning('ApiGetAsyncTaskUnzip err=' + (resp.code || ''))
+ } else if (!AliHttp.HttpCodeBreak(resp.code)) {
+ DebugLog.mSaveWarning('ApiGetAsyncTaskUnzip err=' + (resp.code || ''), resp.body)
}
return 'error'
}
diff --git a/aliyunpan/src/assets/fileitem.css b/aliyunpan/src/assets/fileitem.css
index 1887382a3d..2ae1edc652 100644
--- a/aliyunpan/src/assets/fileitem.css
+++ b/aliyunpan/src/assets/fileitem.css
@@ -285,11 +285,8 @@ body[arco-theme='dark'] .fileitem.focus {
.cff5722 {
color: #ff5722;
}
-.c5b89b8 {
- color: #5b89b8;
-}
-.cvideo {
- color: #5b89b8;
+.ce74c3c {
+ color: #e74c3c;
}
.griditemparent {
@@ -318,7 +315,7 @@ body[arco-theme='dark'] .fileitem.focus {
}
.griditem {
- border-radius: 8px;
+ border-radius: 17.2px;
position: relative;
height: 100%;
border: 1px dotted transparent;
@@ -421,6 +418,126 @@ body[arco-theme='dark'] .griditem .select:hover {
overflow: hidden;
}
+.griditem.movie {
+ width: 200px;
+ height: 320px;
+ flex-shrink: 0;
+ flex-grow: 0;
+}
+
+.movieicon {
+ left: 2px;
+ right: 2px;
+ top: -10px;
+ position: absolute;
+ text-align: center;
+ height:100% !important;
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ flex-shrink: 0;
+ flex-grow: 0;
+}
+.movieicon i {
+ font-size: 56px;
+ opacity: 0.75;
+}
+.movieicon .iconfile-folder {
+ color: #ffb74d !important;
+}
+
+.movieicon img {
+ display: block;
+ width: 170px !important;
+ height: 240px !important;
+ border-radius: 20px;
+ position: relative;
+ border: 1px solid rgba(132, 133, 141, 0.16);
+}
+
+.movieicon .playicon {
+ cursor: pointer;
+ font-size: 20px;
+ height: 28px;
+ width: 28px;
+ background: rgba(37, 38, 43, 0.36);
+ backdrop-filter: blur(10px);
+ border-radius: 50%;
+ color: rgb(255, 255, 255);
+}
+.movieicon .playicon svg {
+ width: 1em;
+ height: 1em;
+ fill: currentColor;
+ overflow: hidden;
+}
+
+.movieprogress {
+ width: 100%;
+ text-align: center;
+ font-size: 14px;
+ line-height: 18px;
+ max-width: 100%;
+ display: -webkit-box;
+ -webkit-line-clamp: 2;
+ -webkit-box-orient: vertical;
+ overflow: hidden;
+ -o-text-overflow: ellipsis;
+ text-overflow: ellipsis;
+ overflow-wrap: break-word;
+ /*margin-bottom: 2px;*/
+ color: var(--color-text-1);
+ padding: 0 8px;
+ position: absolute;
+ bottom: 45px;
+ font-weight: bold;
+}
+.moviename {
+ width: 100%;
+ text-align: center;
+ font-size: 14px;
+ line-height: 18px;
+ max-width: 100%;
+ display: -webkit-box;
+ -webkit-line-clamp: 2;
+ -webkit-box-orient: vertical;
+ /*overflow: hidden;*/
+ -o-text-overflow: ellipsis;
+ text-overflow: ellipsis;
+ overflow-wrap: normal;
+ white-space: nowrap;
+ /* margin-bottom: 2px; */
+ color: var(--color-text-1);
+ padding: 0 8px;
+ position: absolute;
+ bottom: 25px;
+ font-weight: bold;
+}
+.moviename > div {
+ cursor: pointer;
+ text-align: center;
+ word-break: break-all;
+ width: 150px;
+ margin-left: 15px;
+ white-space: nowrap;
+ overflow: hidden;
+ text-overflow: ellipsis;
+}
+.moviename > div:hover {
+ color: #3482f0;
+}
+
+.movieinfo {
+ width: 100%;
+ text-align: center;
+ font-size: 12px;
+ color: var(--color-text-3);
+ position: absolute;
+ bottom: 0px;
+}
+
+
+
.gridname {
width: 100%;
text-align: center;
diff --git a/aliyunpan/src/assets/global.css b/aliyunpan/src/assets/global.css
index 601b219e49..a02e55059b 100644
--- a/aliyunpan/src/assets/global.css
+++ b/aliyunpan/src/assets/global.css
@@ -1,149 +1,167 @@
html {
- min-width: 100vw;
- min-height: 100vh;
- overflow: hidden;
+ min-width: 100vw;
+ min-height: 100vh;
+ overflow: hidden;
}
+
body {
- font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Helvetica Neue', Lato, Roboto, 'PingFang SC', 'Microsoft YaHei', sans-serif;
- min-width: 100vw;
- min-height: 100vh;
- overflow: hidden;
- background-color: transparent !important;
- -webkit-font-smoothing: antialiased;
- -moz-osx-font-smoothing: grayscale;
+ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Helvetica Neue', Lato, Roboto, 'PingFang SC', 'Microsoft YaHei', sans-serif, '黑体', '宋体', '方正黑体', '方正准圆';
+ min-width: 100vw;
+ min-height: 100vh;
+ overflow: hidden;
+ background-color: transparent !important;
+ -webkit-font-smoothing: antialiased;
+ -moz-osx-font-smoothing: grayscale;
}
+
::-webkit-scrollbar {
- width: 10px;
- height: 10px;
- cursor: pointer;
+ width: 8px;
+ height: 8px;
+ background: transparent;
}
::-webkit-scrollbar-thumb {
- background: rgb(201, 201, 202);
- border-radius: 5px;
- cursor: default;
-}
-::-webkit-scrollbar-thumb:vertical {
- width: 9px;
-}
-::-webkit-scrollbar-thumb:horizontal {
- height: 9px;
+ background: var(--color-fill-3) content-box;
+ border: 2px solid transparent;
+ border-radius: 5px;
}
::-webkit-scrollbar-thumb:hover {
- background: rgb(162, 162, 163);
+ background-color: var(--color-fill-4);
+}
+
+::-webkit-scrollbar-thumb:vertical {
+ width: 9px;
+}
+
+::-webkit-scrollbar-thumb:horizontal {
+ height: 9px;
+}
+
+::-webkit-scrollbar-thumb:hover {
+ background: rgb(162, 162, 163);
}
::-webkit-scrollbar-track {
- background-color: transparent;
+ background-color: transparent;
}
::-webkit-scrollbar-corner {
- background: transparent !important;
+ background: transparent !important;
}
::-webkit-resizer {
- background: transparent !important;
+ background: transparent !important;
}
::-webkit-scrollbar-button {
- display: none;
+ display: none;
}
+
.flex {
- display: flex;
- flex: 100% 1 1;
- flex-direction: row;
+ display: flex;
+ flex: 100% 1 1;
+ flex-direction: row;
}
+
.flexauto {
- flex-grow: 1 !important;
+ flex-grow: 1 !important;
}
+
.flexnoauto {
- flex-grow: 0 !important;
- flex-shrink: 0 !important;
- flex-basis: unset !important;
+ flex-grow: 0 !important;
+ flex-shrink: 0 !important;
+ flex-basis: unset !important;
}
+
.q-electron-drag {
- user-select: none;
- -webkit-app-region: drag;
+ user-select: none;
+ -webkit-app-region: drag;
}
+
.q-electron-drag--exception,
.q-electron-drag button,
.q-electron-drag ul,
.q-electron-drag li,
.q-electron-drag .arco-menu-item,
.q-electron-drag .arco-avatar {
- -webkit-app-region: no-drag;
+ -webkit-app-region: no-drag;
}
+
* {
- user-select: none;
- -webkit-user-drag: none;
- box-sizing: border-box;
- letter-spacing: 0.1px;
- -webkit-text-size-adjust: 100%;
- -webkit-font-smoothing: antialiased;
- font-feature-settings: 'tnum', 'zero', 'liga' 0;
+ user-select: none;
+ -webkit-user-drag: none;
+ box-sizing: border-box;
+ letter-spacing: 0.1px;
+ -webkit-text-size-adjust: 100%;
+ -webkit-font-smoothing: antialiased;
+ font-feature-settings: 'tnum', 'zero', 'liga' 0;
}
+
#app {
- height: 100vh;
- position: fixed;
- top: 0;
- left: 0;
- right: 0;
- bottom: 0;
+ height: 100vh;
+ position: fixed;
+ top: 0;
+ left: 0;
+ right: 0;
+ bottom: 0;
}
+
body {
- --arcoblue-1: 232, 240, 255 !important;
- --arcoblue-2: 205, 220, 255 !important;
- --arcoblue-3: 179, 199, 255 !important;
- --arcoblue-4: 152, 176, 255 !important;
- --arcoblue-5: 126, 151, 255 !important;
- --arcoblue-6: 99, 125, 255 !important;
- --arcoblue-7: 61, 81, 210 !important;
- --arcoblue-8: 32, 46, 166 !important;
- --arcoblue-9: 12, 19, 121 !important;
- --arcoblue-10: 0, 3, 77 !important;
+ --arcoblue-1: 232, 240, 255 !important;
+ --arcoblue-2: 205, 220, 255 !important;
+ --arcoblue-3: 179, 199, 255 !important;
+ --arcoblue-4: 152, 176, 255 !important;
+ --arcoblue-5: 126, 151, 255 !important;
+ --arcoblue-6: 99, 125, 255 !important;
+ --arcoblue-7: 61, 81, 210 !important;
+ --arcoblue-8: 32, 46, 166 !important;
+ --arcoblue-9: 12, 19, 121 !important;
+ --arcoblue-10: 0, 3, 77 !important;
- --foot-bg: #3c86f5;
- --foot-txt: rgb(245, 245, 246);
- --topshadow: rgba(0, 0, 0, 0.1);
- --leftshadow: rgba(29, 35, 41, 0.05);
- --rightbg2: #f2f3f5;
- --listhoverbg: rgba(247, 248, 250, 0.6);
- --listselectbg: rgb(240, 245, 255);
- --color-text-1: var(--color-neutral-9) !important;
- --color-mask-bg: rgba(29, 33, 41, 0.3) !important;
+ --foot-bg: #3c86f5;
+ --foot-txt: rgb(245, 245, 246);
+ --topshadow: rgba(0, 0, 0, 0.1);
+ --leftshadow: rgba(29, 35, 41, 0.05);
+ --rightbg2: #f2f3f5;
+ --listhoverbg: rgba(247, 248, 250, 0.6);
+ --listselectbg: rgb(240, 245, 255);
+ --color-text-1: var(--color-neutral-9) !important;
+ --color-mask-bg: rgba(29, 33, 41, 0.3) !important;
}
+
body[arco-theme='dark'] {
- color-scheme: dark;
- caret-color: rgba(255, 255, 255, 0.65);
- background: #23232e !important;
+ color-scheme: dark;
+ caret-color: rgba(255, 255, 255, 0.65);
+ background: #23232e !important;
- --color-text-2: rgba(255, 255, 255, 0.8) !important;
- color: var(--color-text-2) !important;
- --color-menu-light-bg: #30303d !important;
- --color-bg-1: #23232e !important;
- --color-bg-popup: #2d2d3b !important;
- --color-spin-layer-bg: rgba(51, 51, 51, 0.3) !important;
+ --color-text-2: rgba(255, 255, 255, 0.8) !important;
+ color: var(--color-text-2) !important;
+ --color-menu-light-bg: #30303d !important;
+ --color-bg-1: #23232e !important;
+ --color-bg-popup: #2d2d3b !important;
+ --color-spin-layer-bg: rgba(51, 51, 51, 0.3) !important;
- --foot-bg: #17171f;
- --foot-txt: rgb(210, 210, 211);
- --topshadow: rgba(0, 0, 0, 0.5);
- --leftshadow: rgba(0, 0, 0, 0.2);
- --rightbg2: rgba(255, 255, 255, 0.05);
- --listhoverbg: rgba(76, 77, 97, 0.3);
- --listselectbg: rgba(85, 86, 109, 0.7);
- --color-text-1: rgba(255, 255, 255, 0.8) !important;
- --color-mask-bg: rgba(29, 33, 41, 0.5) !important;
+ --foot-bg: #17171f;
+ --foot-txt: rgb(210, 210, 211);
+ --topshadow: rgba(0, 0, 0, 0.5);
+ --leftshadow: rgba(0, 0, 0, 0.2);
+ --rightbg2: rgba(255, 255, 255, 0.05);
+ --listhoverbg: rgba(76, 77, 97, 0.3);
+ --listselectbg: rgba(85, 86, 109, 0.7);
+ --color-text-1: rgba(255, 255, 255, 0.8) !important;
+ --color-mask-bg: rgba(29, 33, 41, 0.5) !important;
}
.arco-layout-sider .arco-menu-light .arco-menu-item.arco-menu-selected {
- background: #f0f5ff;
- color: var(--color-text-2);
+ background: #f0f5ff;
+ color: var(--color-text-2);
}
+
.arco-layout-sider .arco-menu-light .arco-menu-item .arco-menu-icon,
.arco-layout-sider .arco-menu-light .arco-menu-item:hover .arco-menu-icon,
.arco-layout-sider .arco-menu-light .arco-menu-item.arco-menu-selected .arco-menu-icon {
- color: var(--color-text-2);
+ color: var(--color-text-2);
}
body[arco-theme='dark'] .arco-layout-sider,
@@ -151,416 +169,564 @@ body[arco-theme='dark'] .arco-layout-sider-light,
body[arco-theme='dark'] .arco-layout-sider .arco-menu-light,
body[arco-theme='dark'] .arco-layout-sider .arco-menu-light .arco-menu-item,
body[arco-theme='dark'] .arco-card {
- background: #23232e;
+ background: #23232e;
}
+
body[arco-theme='dark'] .arco-layout-sider .arco-menu-light .arco-menu-item:hover {
- background: var(--color-fill-2);
+ background: var(--color-fill-2);
}
+
body[arco-theme='dark'] .arco-layout-sider .arco-menu-light .arco-menu-item.arco-menu-selected {
- background: #444457;
+ background: #444457;
}
.arco-alert-error {
- background-color: rgb(253, 237, 237) !important;
+ background-color: rgb(253, 237, 237) !important;
}
+
.arco-alert-error .arco-alert-icon svg {
- color: rgb(239, 83, 80) !important;
+ color: rgb(239, 83, 80) !important;
}
+
.arco-alert-error .arco-alert-content {
- color: rgb(112, 40, 39) !important;
+ color: rgb(112, 40, 39) !important;
}
.arco-alert-warning {
- background-color: rgb(255, 244, 229) !important;
+ background-color: rgb(255, 244, 229) !important;
}
+
.arco-alert-warning .arco-alert-icon svg {
- color: rgb(255, 152, 0) !important;
+ color: rgb(255, 152, 0) !important;
}
+
.arco-alert-warning .arco-alert-content {
- color: rgb(117, 69, 1) !important;
+ color: rgb(117, 69, 1) !important;
}
.arco-alert-success {
- background-color: rgb(237, 247, 237) !important;
+ background-color: rgb(237, 247, 237) !important;
}
+
.arco-alert-success .arco-alert-icon svg {
- color: rgb(76, 175, 80) !important;
+ color: rgb(76, 175, 80) !important;
}
+
.arco-alert-success .arco-alert-content {
- color: rgb(38, 87, 40) !important;
+ color: rgb(38, 87, 40) !important;
}
.arco-alert-info .arco-alert-content {
- color: rgb(14, 22, 136) !important;
+ color: rgb(14, 22, 136) !important;
}
body[arco-theme='dark'] .arco-alert-error {
- background-color: rgb(63, 32, 32) !important;
+ background-color: rgb(63, 32, 32) !important;
}
+
body[arco-theme='dark'] .arco-alert-error .arco-alert-icon svg {
- color: rgb(244, 67, 54) !important;
+ color: rgb(244, 67, 54) !important;
}
+
body[arco-theme='dark'] .arco-alert-error .arco-alert-content {
- color: rgb(244, 199, 199) !important;
+ color: rgb(244, 199, 199) !important;
}
body[arco-theme='dark'] .arco-alert-warning {
- background-color: rgb(66, 49, 20) !important;
+ background-color: rgb(66, 49, 20) !important;
}
+
body[arco-theme='dark'] .arco-alert-warning .arco-alert-icon svg {
- color: rgb(255, 167, 38) !important;
+ color: rgb(255, 167, 38) !important;
}
+
body[arco-theme='dark'] .arco-alert-warning .arco-alert-content {
- color: rgb(255, 226, 183) !important;
+ color: rgb(255, 226, 183) !important;
}
body[arco-theme='dark'] .arco-alert-success {
- background-color: rgb(39, 61, 42) !important;
+ background-color: rgb(39, 61, 42) !important;
}
+
body[arco-theme='dark'] .arco-alert-success .arco-alert-icon svg {
- color: rgb(102, 187, 106) !important;
+ color: rgb(102, 187, 106) !important;
}
+
body[arco-theme='dark'] .arco-alert-success .arco-alert-content {
- color: rgb(204, 232, 205) !important;
+ color: rgb(204, 232, 205) !important;
}
body[arco-theme='dark'] .arco-alert-info .arco-alert-content {
- color: rgb(205, 220, 255) !important;
+ color: rgb(205, 220, 255) !important;
}
.arco-select,
.arco-menu,
.arco-radio-group-button {
- user-select: none;
- -webkit-user-drag: none;
+ user-select: none;
+ -webkit-user-drag: none;
}
.arco-spin:focus,
.arco-list:focus {
- outline: none;
+ outline: none;
}
button1.arco-btn:focus,
button1:focus {
- outline-style: dotted !important;
- outline-width: 1px !important;
- outline-color: rgb(var(--primary-6)) !important;
- outline-offset: 2px !important;
+ outline-style: dotted !important;
+ outline-width: 1px !important;
+ outline-color: rgb(var(--primary-6)) !important;
+ outline-offset: 2px !important;
}
.arco-modal {
- width: auto !important;
+ width: auto !important;
}
+
.arco-modal.arco-modal-fullscreen {
- width: 100vw !important;
- height: 100vh !important;
- border-radius: 0 !important;
+ width: 100vw !important;
+ height: 100vh !important;
+ border-radius: 0 !important;
}
+
.arco-modal-wrapper {
- overflow: hidden !important;
+ overflow: hidden !important;
}
body[arco-theme='dark'] .arco-modal {
- background: #2d2d3b !important;
- box-shadow: 0 2px 20px 0 rgb(0 0 0 / 45%) !important;
+ background: #2d2d3b !important;
+ box-shadow: 0 2px 20px 0 rgb(0 0 0 / 45%) !important;
}
+
body[arco-theme='dark'] .arco-dropdown,
body[arco-theme='dark'] .arco-select-dropdown,
body[arco-theme='dark'] .arco-popover-popup-content {
- box-shadow: 0 4px 20px rgb(0 0 0 / 45%) !important;
- border: 1px solid transparent !important;
+ box-shadow: 0 4px 20px rgb(0 0 0 / 45%) !important;
+ border: 1px solid transparent !important;
}
.arco-radio-button.arco-radio-checked {
- background-color: rgb(var(--primary-6)) !important;
- color: var(--color-white) !important;
+ background-color: rgb(var(--primary-6)) !important;
+ color: var(--color-white) !important;
}
.arco-dropdown-option {
- line-height: 32px !important;
- width: calc(100% - 8px) !important;
- margin: 0 4px !important;
- border-radius: 3px !important;
+ line-height: 32px !important;
+ width: calc(100% - 8px) !important;
+ margin: 0 4px !important;
+ border-radius: 3px !important;
}
+
.arco-dropdown-option.danger {
- color: rgb(255, 77, 79) !important;
+ color: rgb(255, 77, 79) !important;
}
+
.arco-dropdown-option.danger:hover,
.arco-dropdown-option.danger:active {
- color: #fff !important;
- background: rgba(255, 77, 79, 0.85) !important;
+ color: #fff !important;
+ background: rgba(255, 77, 79, 0.85) !important;
}
.toppanbtn .arco-btn.danger:hover,
.toppanbtn .arco-btn.danger:active,
body[arco-theme='dark'] .toppanbtn .arco-btn.danger:hover,
body[arco-theme='dark'] .toppanbtn .arco-btn.danger:active {
- color: #fff !important;
- background: rgba(255, 77, 79, 0.85) !important;
- border-color: rgba(255, 77, 79, 0.2) !important;
+ color: #fff !important;
+ background: rgba(255, 77, 79, 0.85) !important;
+ border-color: rgba(255, 77, 79, 0.2) !important;
}
.arco-dropdown-option-suffix {
- color: var(--color-text-3);
- font-size: 12px;
- user-select: none;
+ color: var(--color-text-3);
+ font-size: 12px;
+ user-select: none;
}
.arco-list .arco-empty {
- margin-top: 15%;
+ margin-top: 15%;
}
.arco-modal {
- z-index: 1001;
+ z-index: 1001;
}
+
.arco-modal-close-btn {
- -webkit-app-region: no-drag;
- position: absolute;
- right: 20px;
+ -webkit-app-region: no-drag;
+ position: absolute;
+ right: 20px;
}
.arco-modal-close-btn .arco-icon-hover {
- width: 24px;
- height: 24px;
- line-height: 24px;
- border-radius: 50%;
+ width: 24px;
+ height: 24px;
+ line-height: 24px;
+ border-radius: 50%;
}
+
.arco-modal-close-btn .arco-icon-hover .arco-icon {
- left: 6px;
+ left: 6px;
}
+
.arco-modal-close-btn .arco-icon-hover::before {
- display: none;
+ display: none;
}
+
.arco-modal-close-btn .arco-icon-hover:hover {
- background-color: var(--color-fill-2);
+ background-color: var(--color-fill-2);
}
.toppanbtns {
- display: flex;
- flex-direction: row;
- flex-wrap: nowrap;
- padding: 0;
- max-width: 100%;
- min-width: 440px;
- user-select: none;
- padding-left: 6px;
+ display: flex;
+ flex-direction: row;
+ flex-wrap: nowrap;
+ padding: 0;
+ max-width: 100%;
+ min-width: 440px;
+ user-select: none;
+ padding-left: 6px;
}
+
.toppanbtn {
- display: flex;
- flex-direction: row;
- flex-grow: 0;
- flex-shrink: 0;
- flex-wrap: nowrap;
- border-radius: 4px;
- margin-right: 12px;
- user-select: none;
+ display: flex;
+ flex-direction: row;
+ flex-grow: 0;
+ flex-shrink: 0;
+ flex-wrap: nowrap;
+ border-radius: 4px;
+ margin-right: 12px;
+ user-select: none;
}
+
.toppanbtn:last-child {
- margin-right: 0;
+ margin-right: 0;
}
.toppanbtn .arco-btn {
- display: inline-flex;
- align-items: center;
- height: 26px !important;
- min-height: 26px !important;
- padding: 0px 6px !important;
+ display: inline-flex;
+ align-items: center;
+ height: 26px !important;
+ min-height: 26px !important;
+ padding: 0px 6px !important;
- font-size: 14px !important;
- line-height: 18px !important;
- white-space: nowrap !important;
- word-break: keep-all !important;
- color: rgb(var(--primary-6));
- border-color: rgba(var(--primary-6), 0.6) !important;
- border-radius: 4px !important;
+ font-size: 14px !important;
+ line-height: 18px !important;
+ white-space: nowrap !important;
+ word-break: keep-all !important;
+ color: rgb(var(--primary-6));
+ border-color: rgba(var(--primary-6), 0.6) !important;
+ border-radius: 4px !important;
}
.toppanbtn .arco-btn.iconbtn > .arco-btn-icon {
- padding-right: 4px;
+ padding-right: 4px;
}
.toppanbtn .arco-btn:hover,
.toppanbtn .arco-btn:active {
- background: rgba(var(--primary-6), 0.1) !important;
+ background: rgba(var(--primary-6), 0.1) !important;
}
.toppanbtn .searchpan {
- border: 1px solid rgb(var(--primary-6)) !important;
- border-right: none !important;
- border-radius: 4px !important;
+ border: 1px solid rgb(var(--primary-6)) !important;
+ border-right: none !important;
+ border-radius: 4px !important;
}
+
.toppanbtn .searchpan .arco-btn.arco-input-search-btn {
- border-radius: 4px !important;
+ border-radius: 4px !important;
}
+
.toppanbtn .arco-input-search .arco-input-wrapper {
- background: var(--color-bg-2);
- border: none !important;
+ background: var(--color-bg-2);
+ border: none !important;
}
+
.toppanbtn .arco-btn.arco-btn-primary {
- border-radius: 0 !important;
+ border-radius: 0 !important;
}
+
.toppanbtn .arco-btn.arco-btn-primary:hover {
- background: rgb(var(--primary-5)) !important;
+ background: rgb(var(--primary-5)) !important;
}
+
.toppanbtn .arco-btn.arco-btn-primary:active {
- background: rgb(var(--primary-7)) !important;
+ background: rgb(var(--primary-7)) !important;
}
.toppanbtn > .arco-btn + .arco-btn {
- border-left: 0 !important;
+ border-left: 0 !important;
}
+
.toppanbtn > .arco-btn:not(:last-child) {
- border-right: 0 !important;
+ border-right: 0 !important;
}
.toppanbtn > .arco-btn:not(:first-child) {
- border-top-left-radius: 0 !important;
- border-bottom-left-radius: 0 !important;
+ border-top-left-radius: 0 !important;
+ border-bottom-left-radius: 0 !important;
}
.toppanbtn > .arco-btn:not(:last-child) {
- border-top-right-radius: 0 !important;
- border-bottom-right-radius: 0 !important;
+ border-top-right-radius: 0 !important;
+ border-bottom-right-radius: 0 !important;
}
.toppanbtn .iconfont {
- font-size: 18px;
- line-height: 24px;
+ font-size: 18px;
+ line-height: 24px;
}
.toppanbtn .arco-btn > span {
- line-height: 24px;
+ line-height: 24px;
}
.toppanbtn .arco-btn > .arco-btn-icon {
- min-width: 18px;
- margin-right: 0 !important;
+ min-width: 18px;
+ margin-right: 0 !important;
}
.toppanbtn .arco-btn.arco-btn-dangerous:hover,
.toppanbtn .arco-btn.arco-btn-dangerous:focus {
- color: #fff !important;
- border-color: rgb(255, 77, 79) !important;
- background: rgb(255, 77, 79) !important;
+ color: #fff !important;
+ border-color: rgb(255, 77, 79) !important;
+ background: rgb(255, 77, 79) !important;
}
.toppanbtn .arco-input-search {
- width: 130px;
- transition: width 0.3s;
+ width: 130px;
+ transition: width 0.3s;
}
+
@media only screen and (max-width: 859px) {
- .arco-input-wrapper {
- padding-right: 6px !important;
- padding-left: 6px !important;
- }
+ .arco-input-wrapper {
+ padding-right: 6px !important;
+ padding-left: 6px !important;
+ }
}
+
@media only screen and (min-width: 820px) {
- .toppanbtn .arco-input-search {
- width: 140px;
- }
+ .toppanbtn .arco-input-search {
+ width: 140px;
+ }
}
+
@media only screen and (min-width: 860px) {
- .toppanbtn .arco-input-search {
- width: 160px;
- }
+ .toppanbtn .arco-input-search {
+ width: 160px;
+ }
}
+
@media only screen and (min-width: 960px) {
- .toppanbtn .arco-input-search {
- width: 180px;
- }
- .toppanbtn .arco-input-search.arco-input-focus {
- width: 200px;
- }
+ .toppanbtn .arco-input-search {
+ width: 180px;
+ }
+
+ .toppanbtn .arco-input-search.arco-input-focus {
+ width: 200px;
+ }
}
+
@media only screen and (min-width: 1000px) {
- .toppanbtn .arco-input-search.arco-input-focus {
- width: 220px;
- }
+ .toppanbtn .arco-input-search.arco-input-focus {
+ width: 220px;
+ }
}
+
@media only screen and (min-width: 1200px) {
- .toppanbtn .arco-input-search {
- width: 200px;
- }
- .toppanbtn .arco-input-search.arco-input-focus {
- width: 240px;
- }
+ .toppanbtn .arco-input-search {
+ width: 200px;
+ }
+
+ .toppanbtn .arco-input-search.arco-input-focus {
+ width: 240px;
+ }
}
body[arco-theme='dark'] .toppanbtn .arco-btn {
- background: none !important;
+ background: none !important;
}
+
body[arco-theme='dark'] .toppanbtn .arco-btn:hover,
body[arco-theme='dark'] .toppanbtn .arco-btn:active {
- background: #4c4c61 !important;
+ background: #4c4c61 !important;
}
+
body[arco-theme='dark'] .toppanbtn .arco-btn {
- color: #ffffffd9;
- background: #353544;
- border: 1px solid #444457;
- border-color: #444457 !important;
- box-shadow: 0 1px 5px rgb(0 0 0 / 20%), 0 2px 2px rgb(0 0 0 / 14%), 0 3px 1px -2px rgb(0 0 0 / 12%) !important;
+ color: #ffffffd9;
+ background: #353544;
+ border: 1px solid #444457;
+ border-color: #444457 !important;
+ box-shadow: 0 1px 5px rgb(0 0 0 / 20%), 0 2px 2px rgb(0 0 0 / 14%), 0 3px 1px -2px rgb(0 0 0 / 12%) !important;
}
+
+body[arco-theme='dark'] .toppanarea .cell {
+ color: rgba(211, 216, 241, 0.45);
+}
+
+.cell {
+ color: var(--color-text-3);
+ overflow: hidden;
+ text-align: center;
+ flex-grow: 0;
+ flex-shrink: 0;
+ display: inline-block;
+ line-height: 18px;
+ min-height: 18px;
+ padding: 0 4px;
+ justify-content: center;
+}
+
+.cell.tiquma {
+ width: 60px;
+ font-size: 12px;
+}
+
+.cell.filesize {
+ font-size: 16px;
+ width: 86px;
+ text-align: right;
+ flex-shrink: 0;
+ flex-grow: 0;
+ margin-right: 16px;
+}
+
+.cell.count {
+ width: 70px;
+ font-size: 12px;
+ line-height: 14px;
+ text-align: center;
+ word-wrap: break-word;
+ word-break: keep-all;
+}
+
+.cellcount {
+ align-items: center;
+ margin-right: 16px;
+}
+
+.cellcount .arco-badge .arco-badge-status-text {
+ margin-left: 4px;
+ color: var(--color-text-3);
+ line-height: 26px;
+}
+
+.cell.sharetime {
+ width: 80px;
+ font-size: 12px;
+ line-height: 14px;
+ text-align: right;
+ word-wrap: break-word;
+ word-break: keep-all;
+}
+
+.cell.sharetime.active {
+ color: rgb(217, 48, 37);
+}
+
+.cell.sharestate {
+ width: 60px;
+ font-size: 12px;
+ margin: 0 5px 0 5px;
+}
+
+.cell.sharestate.active {
+ color: rgb(var(--primary-6));
+}
+
+.cell.sharestate.forbidden {
+ color: rgb(217, 48, 37);
+}
+
+.cell.sharestate.deleted {
+ text-decoration: line-through;
+}
+
+.cell.p5 {
+ width: 5px;
+}
+
+.cell.pr {
+ width: 12px;
+}
+
.toppanarea {
- box-sizing: border-box;
- display: flex;
- flex-direction: row;
- flex-wrap: nowrap;
- height: 40px;
- color: var(--color-text-3);
- line-height: 38px;
- border-top: 1px solid #e5e8ed99;
- border-bottom: 1px solid #e5e8ed99;
+ box-sizing: border-box;
+ display: flex;
+ flex-direction: row;
+ flex-wrap: nowrap;
+ height: 40px;
+ color: var(--color-text-3);
+ line-height: 38px;
+ border-top: 1px solid #e5e8ed99;
+ border-bottom: 1px solid #e5e8ed99;
}
+
body[arco-theme='dark'] .toppanarea {
- border-top: 1px solid #e5e8ed22;
- border-bottom: 1px solid #e5e8ed22;
+ border-top: 1px solid #e5e8ed22;
+ border-bottom: 1px solid #e5e8ed22;
}
.toppanarea > div {
- display: flex;
- align-items: center;
- height: 38px;
+ display: flex;
+ align-items: center;
+ height: 38px;
}
+
.toppanarea .selectInfo {
- height: 38px;
- line-height: 38px;
- font-size: 14px;
- overflow: hidden;
- white-space: nowrap;
- word-break: keep-all;
+ height: 38px;
+ line-height: 38px;
+ font-size: 14px;
+ overflow: hidden;
+ white-space: nowrap;
+ word-break: keep-all;
}
+
.toppanarea .cell {
- font-size: 12px;
+ font-size: 12px;
}
+
.toppanarea .cell.active,
.toppanarea .cell.active .iconxia {
- color: rgb(var(--primary-6));
+ color: rgb(var(--primary-6));
}
+.toppanarea .cell.order {
+ cursor: pointer;
+}
+
+.toppanarea .cell.order:hover {
+ color: rgb(var(--primary-6));
+}
+
+
.select,
.select > button {
- min-width: 34px !important;
- height: 34px !important;
- min-height: 34px !important;
- padding: 0px !important;
- color: rgb(var(--primary-6)) !important;
- font-size: 14px;
- line-height: 34px !important;
- border: none !important;
+ min-width: 34px !important;
+ height: 34px !important;
+ min-height: 34px !important;
+ padding: 0px !important;
+ color: rgb(var(--primary-6)) !important;
+ font-size: 14px;
+ line-height: 34px !important;
+ border: none !important;
}
+
.select:hover,
.select:active,
.select.active {
- background: rgba(99, 125, 255, 0.1) !important;
- color: rgb(var(--primary-6)) !important;
+ background: rgba(99, 125, 255, 0.1) !important;
+ color: rgb(var(--primary-6)) !important;
}
+
.select .iconfont {
- font-size: 24px;
- line-height: 34px;
- color: rgb(var(--primary-6)) !important;
+ font-size: 24px;
+ line-height: 34px;
+ color: rgb(var(--primary-6)) !important;
}
+
.select .iconfont.iconrpic {
- opacity: 0.8;
+ opacity: 0.8;
}
.vermodalhead {
display: flex;
@@ -568,8 +734,8 @@ body[arco-theme='dark'] .toppanarea {
line-height: 48px;
}
.vermodal {
- height: 200px;
- width: 400px;
+ height: 50vh;
+ width: 520px;
flex-direction: column;
justify-content: center;
align-items: center;
@@ -590,137 +756,144 @@ body[arco-theme='dark'] .toppanarea {
}
.arco-tree-node-custom-icon {
- margin-right: 4px !important;
+ margin-right: 4px !important;
}
.xbyleft {
- box-shadow: 2px 0 8px 0 var(--leftshadow) !important;
+ box-shadow: 2px 0 8px 0 var(--leftshadow) !important;
}
+
.xbyright {
- padding-left: 16px;
+ padding-left: 16px;
}
+
.headdesc {
- box-sizing: border-box;
- height: 40px;
- padding: 0 0 0 12px;
- color: #8a9ca5;
- line-height: 40px;
- user-select: none;
- -webkit-user-drag: none;
- white-space: nowrap;
- word-break: keep-all;
- overflow: hidden;
+ box-sizing: border-box;
+ height: 40px;
+ padding: 0 0 0 12px;
+ color: #8a9ca5;
+ line-height: 40px;
+ user-select: none;
+ -webkit-user-drag: none;
+ white-space: nowrap;
+ word-break: keep-all;
+ overflow: hidden;
}
.xbyleftmenu.arco-menu .arco-menu-inner {
- padding: 0 2px 0 0 !important;
+ padding: 0 2px 0 0 !important;
}
+
.xbyleftmenu.arco-menu .arco-menu-item {
- padding: 0 8px;
- margin-bottom: 2px;
- line-height: 40px;
- height: 40px;
+ padding: 0 8px;
+ margin-bottom: 2px;
+ line-height: 40px;
+ height: 40px;
}
.xbyleftmenu.arco-menu .arco-menu-item::after {
- position: absolute;
- top: 0;
- left: 0;
- bottom: 0;
- transform: scaleY(0.0001);
- opacity: 0;
- transition: transform 0.15s cubic-bezier(0.215, 0.61, 0.355, 1), opacity 0.15s cubic-bezier(0.215, 0.61, 0.355, 1);
- content: '';
+ position: absolute;
+ top: 0;
+ left: 0;
+ bottom: 0;
+ transform: scaleY(0.0001);
+ opacity: 0;
+ transition: transform 0.15s cubic-bezier(0.215, 0.61, 0.355, 1), opacity 0.15s cubic-bezier(0.215, 0.61, 0.355, 1);
+ content: '';
}
+
.xbyleftmenu.arco-menu .arco-menu-item.arco-menu-selected::after {
- transform: scaleY(1);
- opacity: 1;
- transition: transform 0.15s cubic-bezier(0.645, 0.045, 0.355, 1), opacity 0.15s cubic-bezier(0.645, 0.045, 0.355, 1);
- border-right: 2px solid #637dff;
+ transform: scaleY(1);
+ opacity: 1;
+ transition: transform 0.15s cubic-bezier(0.645, 0.045, 0.355, 1), opacity 0.15s cubic-bezier(0.645, 0.045, 0.355, 1);
+ border-right: 2px solid #637dff;
}
+
.xbyleftmenu.arco-menu .arco-menu-item .arco-menu-icon {
- width: 30px;
- text-align: left;
- margin-right: 0;
- padding-left: 2px;
- display: inline-block;
- flex-shrink: 0;
- flex-grow: 0;
+ width: 30px;
+ text-align: left;
+ margin-right: 0;
+ padding-left: 2px;
+ display: inline-block;
+ flex-shrink: 0;
+ flex-grow: 0;
}
+
.xbyleftmenu.arco-menu .arco-menu-item .arco-menu-icon .iconfont {
- font-size: 20px;
+ font-size: 20px;
}
.arco-select-dropdown .arco-select-option,
.arco-autocomplete-popup .arco-select-popup .arco-select-option {
- line-height: 28px !important;
- height: 28px !important;
+ line-height: 28px !important;
+ height: 28px !important;
}
.arco-tabs {
- position: static !important;
+ position: static !important;
}
.messagebadge {
- background-color: #86909c;
- line-height: 14px;
- height: 14px;
- position: static;
- margin: 0 6px;
- min-width: 20px;
- padding: 0 6px;
- color: var(--color-white);
- font-weight: 500;
- font-size: 12px;
- box-shadow: 0 0 0 2px var(--color-bg-2);
- box-sizing: border-box;
- overflow: hidden;
- text-align: center;
- border-radius: 20px;
- transform: translate(50%, -50%);
- transform-origin: 100% 0%;
+ background-color: #86909c;
+ line-height: 14px;
+ height: 14px;
+ position: static;
+ margin: 0 6px;
+ min-width: 20px;
+ padding: 0 6px;
+ color: var(--color-white);
+ font-weight: 500;
+ font-size: 12px;
+ box-shadow: 0 0 0 2px var(--color-bg-2);
+ box-sizing: border-box;
+ overflow: hidden;
+ text-align: center;
+ border-radius: 20px;
+ transform: translate(50%, -50%);
+ transform-origin: 100% 0%;
}
.arco-modal {
- border-radius: 0.75rem !important;
- box-shadow: 0 2px 20px 0 rgba(0, 0, 0, 0.3) !important;
+ border-radius: 0.75rem !important;
+ box-shadow: 0 2px 20px 0 rgba(0, 0, 0, 0.3) !important;
}
.shortcut-key {
- display: inline-flex;
- font-family: 'Inter', sans-serif;
- font-size: 12px;
- background-color: #f3f4f6;
- border-radius: 0.25rem;
- margin-left: 0.5rem;
- padding-left: 0.25rem;
- padding-right: 0.25rem;
+ display: inline-flex;
+ font-family: 'Inter', sans-serif;
+ font-size: 12px;
+ background-color: #f3f4f6;
+ border-radius: 0.25rem;
+ margin-left: 0.5rem;
+ padding-left: 0.25rem;
+ padding-right: 0.25rem;
}
.arco-btn-text.arco-btn-status-warning:hover {
- color: rgb(var(--warning-6)) !important;
- background-color: var(--color-warning-light-1) !important;
- border-color: var(--color-warning-light-2) !important;
+ color: rgb(var(--warning-6)) !important;
+ background-color: var(--color-warning-light-1) !important;
+ border-color: var(--color-warning-light-2) !important;
}
.arco-modal-header {
- border-bottom: 1px solid transparent !important;
+ border-bottom: 1px solid transparent !important;
}
.arco-card {
- border-radius: 6px !important;
+ border-radius: 6px !important;
}
+
.arco-divider-text {
- border-radius: 4px !important;
+ border-radius: 4px !important;
}
.workertitle {
- margin-top: 64px;
- color: rgb(var(--primary-6));
+ margin-top: 64px;
+ color: rgb(var(--primary-6));
}
.arco-scrollbar {
- height: 100%;
+ height: 100%;
}
.settinghead {
color: var(--color-text-2);
diff --git a/aliyunpan/src/assets/style.css b/aliyunpan/src/assets/style.css
index 312b7923d6..c8c2d4ff28 100644
--- a/aliyunpan/src/assets/style.css
+++ b/aliyunpan/src/assets/style.css
@@ -6,7 +6,9 @@
-ms-user-select: none;
/*font-size: 16px;*/
}
-
+@tailwind base;
+@tailwind components;
+@tailwind utilities;
@media screen and (max-width: 500px) {
* {
font-size: 17px;
diff --git a/aliyunpan/src/axios.ts b/aliyunpan/src/axios.ts
index 97dff065bb..636a052d37 100644
--- a/aliyunpan/src/axios.ts
+++ b/aliyunpan/src/axios.ts
@@ -1,50 +1,52 @@
-import axios, { AxiosInstance } from 'axios'
+import axios from 'axios'
+import { performance } from 'perf_hooks'
-declare module '@vue/runtime-core' {
- interface ComponentCustomProperties {
- $axios: AxiosInstance;
- }
-}
-let QPS = 30
-let OFFSET = 0
+let QPS = 5
+// 校准本地和服务端之间的时间差
+let OFFSET = 250
+// 间隔时间
let INTERVAL = 1000
-const qpsMap = new Map()
+const qpsMap = new Map()
const qpsController = () => async (config: any) => {
- if (config.url.indexOf('api.aliyundrive.com') < 0
- && config.url.indexOf('openapi.aliyundrive.com') < 0) return config
- if (config.url.indexOf('openapi.aliyundrive.com') < 0) {
- QPS = 2
- OFFSET = 2500
- INTERVAL = 1000
+ if (config.url.indexOf('aliyundrive') < 0 && config.url.indexOf('alipan') < 0) return config
+ const now = Math.trunc(performance.timeOrigin + performance.now())
+ let { count, ts } = qpsMap.get(config.url) || { count: 1, ts: now }
+ // 通过位运算实现取整,提高效率
+ if ((now / INTERVAL) >> 0 <= (ts / INTERVAL) >> 0) {
+ // 如果当前时间 ≤ Map中该接口的ts时间,说明前面已经有超过并发后在等待的请求了
+ // 只比较秒,忽略毫秒,因为QPS是以秒为周期计算的,即每秒多少个请求数
+ if (count < QPS) {
+ // 如果当前url的请求数没有达到QPS的限制,则计数器+1
+ count++
} else {
- QPS = 30
- OFFSET = 0
- INTERVAL = 1000
- }
- const now = new Date().getTime()
- let { count, ts } = qpsMap.get(config.url) || { count: 1, ts: now }
- if ((now / INTERVAL) >> 0 <= (ts / INTERVAL) >> 0) {
- if (count < QPS) {
- count++
- } else {
- ts = INTERVAL * Math.ceil(ts / INTERVAL + 1)
- count = 1
- }
- } else {
- ts = now
+ // 否则,重置计数器,同时将时间戳设置为当前ts的下一整秒
+ // 这里需要将ts设置为当前ts的下一秒,而不是当前时间,因为当前ts可能已经远大于当前时间了
+ ts = INTERVAL * Math.ceil(ts / INTERVAL + 1)
count = 1
}
- qpsMap.set(config.url, { count, ts })
- let sleep = ts - now
- sleep = sleep > 0 ? sleep + OFFSET : 0
- if (sleep > 0) {
- await new Promise((resolve) => setTimeout(() => resolve(), sleep))
- }
- return config
+ } else {
+ // 否则:当前时间大于ts,说明已经没有排队的请求了(可能有未完成的,但是都已经请求了)
+ // 则将当前ts重置
+ ts = now
+ count = 1
}
+ qpsMap.set(config.url, { count, ts })
+ // 计算休眠时间:
+ // 由于本地服务器和远程服务器之间可能存在时间差会发生这种情况:
+ // 前5个请求在10:00:00.200时发送过去后,此时本地时间可能到了10:00:00.900到来的第六请求由于超出了QPS=5的限制,会休眠100ms
+ // 但是由于本地和服务端时间差的问题,第六个休眠100ms后发送了请求,服务端的时间可能才是10:00:00.950,导致了QPS超限报错
+ // 所以,这里添加一个OFFSET偏移值来纠正本地和服务端之间的时间差问题,默认为50ms,若出现QPS超限,请酌情增大此值
+ let sleep = ts - now
+ sleep = sleep > 0 ? sleep + OFFSET : 0
+ // 让当前的请求睡一会儿再请求
+ if (sleep > 0) {
+ await new Promise(resolve => setTimeout(() => resolve(), sleep))
+ }
+ return config
+}
+
axios.interceptors.request.use(qpsController())
axios.defaults.withCredentials = false
-
export default axios
\ No newline at end of file
diff --git a/aliyunpan/src/config.ts b/aliyunpan/src/config.ts
new file mode 100644
index 0000000000..7608e085d6
--- /dev/null
+++ b/aliyunpan/src/config.ts
@@ -0,0 +1,10 @@
+export default class Config {
+ static referer = 'https://www.alipan.com/drive'
+ static downAgent = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4577.63 Safari/537.36'
+ static userAgent = 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) aDrive/4.12.0 Chrome/108.0.5359.215 Electron/22.3.24 Safari/537.36'
+ static loginUrl = 'https://auth.aliyundrive.com/v2/oauth/authorize?login_type=custom&response_type=code&redirect_uri=https%3A%2F%2Fwww.aliyundrive.com%2Fsign%2Fcallback&client_id=25dzX3vbYqktVxyX&state=%7B%22origin%22%3A%22https%3A%2F%2Fwww.aliyundrive.com%2F%22%7D'
+ static loginUrlAccount = 'https://passport.aliyundrive.com/mini_login.htm?lang=zh_cn&appName=aliyun_drive&appEntrance=web&styleType=auto&bizParams=¬LoadSsoView=false¬KeepLogin=false&isMobile=false&&rnd=0.1100330129139'
+ static tmdbProxyUrl = 'http://api.themoviedb.org'
+ static client_id = ''
+ static client_secret = ''
+}
diff --git a/aliyunpan/src/down/DownDAL.ts b/aliyunpan/src/down/DownDAL.ts
index 0686e1c55f..802bcad863 100644
--- a/aliyunpan/src/down/DownDAL.ts
+++ b/aliyunpan/src/down/DownDAL.ts
@@ -17,6 +17,8 @@ import { humanSize, humanSizeSpeed } from '../utils/format'
import { Howl } from 'howler'
import DBDown from '../utils/dbdown'
import fsPromises from 'fs/promises'
+import { DecodeEncName } from '../aliapi/utils'
+import { getEncType } from '../utils/proxyhelper'
export interface IStateDownFile {
DownID: string
@@ -59,10 +61,14 @@ export interface IStateDownInfo {
sizestr: string
icon: string
isDir: boolean
+ encType: string
sha1: string
crc64: string
+
+ m3u8_total_file_nums?:number
+ m3u8_parent_file_name?:string
}
export interface IAriaDownProgress {
@@ -77,13 +83,8 @@ export interface IAriaDownProgress {
/** 存盘的时机:默认 10 时进行 */
let SaveTimeWait = 0
-/** 下载正在执行中的数据 */
-export let DownInExeMap = new Map()
-/** 下载正在队列中的数据 */
-export let DownInQueues: IStateDownFile[] = []
-
const sound = new Howl({
- src: ['./audio/down_finished.mp3'], // 音频文件路径
+ src: ['./audio/download_finished.mp3'], // 音频文件路径
autoplay: false, // 是否自动播放
volume: 1.0 // 音量,范围 0.0 ~ 1.0
})
@@ -159,7 +160,7 @@ export default class DownDAL {
const sep = settingStore.ariaSavePath.indexOf('/') >= 0 ? '/' : '\\'
for (let f = 0; f < fileList.length; f++) {
const file = fileList[f]
- const name = ClearFileName(file.name)
+ const name = ClearFileName(DecodeEncName(userID, file).name)
let fullPath = savePath
if (needPanPath) {
if (cPath != '' && cPid == file.parent_file_id) fullPath = cPath
@@ -168,7 +169,7 @@ export default class DownDAL {
const plist = TreeStore.GetDirPath(file.drive_id, file.parent_file_id)
for (let p = 0; p < plist.length; p++) {
const pName = ClearFileName(plist[p].name)
- if (pName == '根目录') continue
+ if (plist[p].file_id.includes('root')) continue
if (path.join(cPath2, pName, name).length > 250) break
cPath2 = path.join(cPath2, pName)
}
@@ -188,7 +189,6 @@ export default class DownDAL {
let downloadurl = ''
let crc64 = ''
-
const downitem: IStateDownFile = {
DownID: userID + '|' + file.file_id,
Info: {
@@ -203,6 +203,7 @@ export default class DownDAL {
sizestr: file.sizeStr,
isDir: file.isDir,
icon: file.icon,
+ encType: getEncType(file),
sha1: '',
crc64: crc64
},
@@ -240,9 +241,8 @@ export default class DownDAL {
const isOnline = await AriaConnect()
if (isOnline && downingStore.ListDataRaw.length) {
await AriaGetDowningList()
-
const ariaRemote = IsAria2cRemote()
- const DowningList: IStateDownFile[] = useDowningStore().ListDataRaw
+ const DowningList: IStateDownFile[] = downingStore.ListDataRaw
const timeThreshold = Date.now() - 60 * 1000
const downFileMax = settingStore.downFileMax
const shouldSkipDown = (Down: any) => {
@@ -253,7 +253,7 @@ export default class DownDAL {
(Down.IsFailed && timeThreshold <= Down.AutoTry)
)
}
- let downingCount = DowningList.filter((down: any) => down.Down.IsDowning).length
+ let addDowningCount = 0
for (let i = 0; i < DowningList.length; i++) {
const DownItem = DowningList[i]
const { DownID, Info, Down } = DownItem
@@ -263,20 +263,20 @@ export default class DownDAL {
const completedDownId = `${Date.now()}_${Down.DownTime}`
// 删除已完成的下载并更新数据库
DowningList.splice(i, 1)
- DBDown.deleteDowning(DownID)
+ await DBDown.deleteDowning(DownID)
// 将已完成的下载添加到下载文件列表中
const downedData = JSON.parse(JSON.stringify({ DownID: completedDownId, Down, Info }))
downedStore.ListDataRaw.unshift({ DownID: completedDownId, Down, Info })
downedStore.mRefreshListDataShow(true)
- DBDown.saveDowned(completedDownId, downedData)
+ await DBDown.saveDowned(completedDownId, downedData)
if (downedStore.ListSelected.has(completedDownId)) {
downedStore.ListSelected.delete(completedDownId)
}
// 移除Aria2已完成的任务
await AriaDeleteList([Info.GID])
i--
- } else if (downingCount < downFileMax && !shouldSkipDown(Down)) {
- downingCount++
+ } else if ((addDowningCount + downingStore.ListDataDowningCount) < downFileMax && !shouldSkipDown(Down)) {
+ addDowningCount++
downingStore.mUpdateDownState(DownItem, 'start')
let state = await AriaAddUrl(DownItem)
downingStore.mUpdateDownState(DownItem, state)
@@ -379,7 +379,7 @@ export default class DownDAL {
// 处理待删除文件
if (!isAll) {
const downIDList = deleteList.map(item => item.DownID)
- console.log('deleteDowning', deleteList)
+ // console.log('deleteDowning', deleteList)
await DBDown.deleteDownings(JSON.parse(JSON.stringify(downIDList)))
} else {
await DBDown.deleteDowningAll()
@@ -423,12 +423,6 @@ export default class DownDAL {
}
static QueryIsDowning() {
- const downingList = useDowningStore().ListDataRaw
- for (let i = 0, maxi = downingList.length; i < maxi; i++) {
- if (!downingList[i].Down.IsDowning) {
- return true
- }
- }
- return false
+ return useDowningStore().ListDataDowningCount > 0
}
-}
\ No newline at end of file
+}
diff --git a/aliyunpan/src/down/DownDowned.vue b/aliyunpan/src/down/DownDowned.vue
index 6486481038..233e0b7df7 100644
--- a/aliyunpan/src/down/DownDowned.vue
+++ b/aliyunpan/src/down/DownDowned.vue
@@ -1,6 +1,14 @@
-
+
+
@@ -120,7 +264,9 @@ const handleRightClick = (e: { event: MouseEvent; node: any }) => {
size='small'
title='Ctrl+F / F3 / Space'
placeholder='快速筛选'
- :model-value='downingStore.ListSearchKey'
+ allow-clear
+ v-model='downingStore.ListSearchKey'
+ @clear='(e:any)=>handleSearchInput("")'
@input='(val:any)=>handleSearchInput(val as string)'
@press-enter='handleSearchEnter'
@keydown.esc='($event.target as any).blur()'
@@ -137,7 +283,37 @@ const handleRightClick = (e: { event: MouseEvent; node: any }) => {
-
{{ downingStore.ListDataSelectCountInfo }}
+
{{ downingStore.ListDataSelectCountInfo }}
+
+
+
+ {{ rangIsSelecting ? '取消选择' : '区间选择' }}
+
+
+
+ 第1步: 点击 区间选择 这个按钮
+
+ 第2步: 鼠标点击一个文件
+
+ 第3步: 移动鼠标点击另外一个文件
+
+
+
+
+ 反向选择
+
+
+ 取消已选
+
+
true'>
{
handleRightClick({event,node:{key:item.DownID}} )'
>
-
+
+ @click.prevent.stop='handleSelect(item.DownID, $event, true)'>
@@ -222,117 +400,47 @@ const handleRightClick = (e: { event: MouseEvent; node: any }) => {
-
diff --git a/aliyunpan/src/down/DownUploaded.vue b/aliyunpan/src/down/DownUploaded.vue
index fa0846297e..988a5bc4c4 100644
--- a/aliyunpan/src/down/DownUploaded.vue
+++ b/aliyunpan/src/down/DownUploaded.vue
@@ -1,8 +1,17 @@
-
-
-
-
-
-
-
-
+
+
+
+
+
+
-
-
+
+
-
-
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- s
+
+
+
-
-
-
+
+ :withsave='modalStore.modalData.withsave || false'
+ :save_db='modalStore.modalData.save_db || false'
+ :file_id_list='modalStore.modalData.file_id_list || []' />
-
-
-
-
+
+
-
-
+
+
+
+
+
+
+
+
+
diff --git a/aliyunpan/src/layout/PageAudio.vue b/aliyunpan/src/layout/PageAudio.vue
new file mode 100644
index 0000000000..9bd0bac693
--- /dev/null
+++ b/aliyunpan/src/layout/PageAudio.vue
@@ -0,0 +1,679 @@
+
+
+
+
+
+
+
+
+
+
+
+ {{ audio.name }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/aliyunpan/src/layout/PageCode.vue b/aliyunpan/src/layout/PageCode.vue
index ee4347d29b..a0e6388ad6 100644
--- a/aliyunpan/src/layout/PageCode.vue
+++ b/aliyunpan/src/layout/PageCode.vue
@@ -1,66 +1,88 @@
-
@@ -74,8 +96,14 @@ export default defineComponent({
{{ appStore.pageCode?.file_name || '文档在线预览' }}
-
-
+
+
+
+
+
+
+
+
@@ -83,7 +111,7 @@ export default defineComponent({
- {{codeString}}
+ {{ codeString }}
{{ codeString }}
@@ -107,6 +135,7 @@ export default defineComponent({
white-space: pre-wrap;
min-width: 100%;
}
+
.fullwidthcode .noformat {
font-size: 14px;
color: rgb(217, 217, 217);
@@ -124,6 +153,7 @@ export default defineComponent({
.fullwidthcode pre:focus {
outline: none;
}
+
.fullwidthcode pre * {
user-select: text;
-webkit-user-drag: auto;
diff --git a/aliyunpan/src/layout/PageHelp.vue b/aliyunpan/src/layout/PageHelp.vue
deleted file mode 100644
index 11fc87f6df..0000000000
--- a/aliyunpan/src/layout/PageHelp.vue
+++ /dev/null
@@ -1,55 +0,0 @@
-
-
-
-
-
-
-
小白羊云盘
-
-
LoadObject
-
CreatMap
-
CreatObject
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/aliyunpan/src/layout/PageImage.vue b/aliyunpan/src/layout/PageImage.vue
index b4fa377eeb..8a1f24b669 100644
--- a/aliyunpan/src/layout/PageImage.vue
+++ b/aliyunpan/src/layout/PageImage.vue
@@ -1,12 +1,16 @@
-
@@ -280,8 +334,14 @@ export default defineComponent({
{{ showName }}
-
-
+
+
+
+
+
+
+
+
@@ -289,19 +349,23 @@ export default defineComponent({
-
上一张
-
下一张
+
上一张
+
+
下一张
+