mirror of
https://github.com/OpenListTeam/OpenList.git
synced 2025-07-19 01:48:42 +08:00
Compare commits
76 Commits
v4.0.3
...
renovate/g
Author | SHA1 | Date | |
---|---|---|---|
96ef259ff7 | |||
eed3c0533c | |||
c72ba9828a | |||
4965a1b909 | |||
1bba550469 | |||
d678322b18 | |||
efd8897bdf | |||
7c7cec0993 | |||
3838ef0663 | |||
9e610af114 | |||
0177177238 | |||
a77e515c9b | |||
4af16ab009 | |||
da35423198 | |||
9612d61e60 | |||
92f396df10 | |||
9557834342 | |||
288ba2fcda | |||
f3920b02f7 | |||
2ec9dad3db | |||
e11227fe2d | |||
859931b78c | |||
b591524ac3 | |||
dc26b4fce5 | |||
f8cf02a2da | |||
a214e794f4 | |||
54d761b371 | |||
bea7a9b0e4 | |||
a46f4cff18 | |||
8eb2d600c7 | |||
ffb6c2a180 | |||
8e19a0fb07 | |||
79f4f96217 | |||
7f53390dce | |||
e83f8e197a | |||
d707f002eb | |||
c0f69f7fa7 | |||
adf914115f | |||
c166fe6127 | |||
9725e0fd76 | |||
5c4cd1b198 | |||
44f4658f37 | |||
b4997e7a7e | |||
f26892ac3c | |||
aae3851979 | |||
a17b3dc405 | |||
022614f155 | |||
874dc292ae | |||
9442013b37 | |||
862b1c3c53 | |||
52c93f2046 | |||
3d13d5213b | |||
103abc942e | |||
f0236522f3 | |||
6a3b8fab06 | |||
5c288dc763 | |||
6d0d3ac612 | |||
1ec97733e5 | |||
ded67b746b | |||
4590795cba | |||
060fd36883 | |||
76a1f99df1 | |||
38766a4cb7 | |||
bcc518cf96 | |||
3fdb2c79bf | |||
18f7a2ba0e | |||
e32cebb153 | |||
02031bd835 | |||
7726cb14a0 | |||
23cfe8090b | |||
d89d0a05b4 | |||
14d57ae2ec | |||
d5f4b687bb | |||
bdb880f9f2 | |||
22575a1c61 | |||
890297aa27 |
81
.github/ISSUE_TEMPLATE/00-bug_report_zh.yml
vendored
Normal file
81
.github/ISSUE_TEMPLATE/00-bug_report_zh.yml
vendored
Normal file
@ -0,0 +1,81 @@
|
||||
name: "错误报告"
|
||||
description: 错误报告 / 问题
|
||||
title: "[BUG] 请修改标题为您遇到的问题"
|
||||
labels: [bug]
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
感谢您花时间填写此错误报告。
|
||||
请**务必**确认您的问题无重复,且不是因为您的操作、网络或第三方软件问题。
|
||||
|
||||
- type: checkboxes
|
||||
attributes:
|
||||
label: 请确认以下事项
|
||||
description: |
|
||||
您必须勾选以下内容,否则您的问题可能会被直接关闭。
|
||||
或者您可以去[讨论区](https://github.com/OpenListTeam/OpenList/discussions)。
|
||||
options:
|
||||
- label: |
|
||||
我已确认阅读并同意 [AGPL-3.0 第15条](https://www.gnu.org/licenses/agpl-3.0.txt#:~:text=15.%20Disclaimer%20of%20Warranty.) 。
|
||||
本程序不提供任何明示或暗示的担保,使用风险由您自行承担。
|
||||
- label: |
|
||||
我已确认阅读并同意 [AGPL-3.0 第16条](https://www.gnu.org/licenses/agpl-3.0.txt#:~:text=16.%20Limitation%20of%20Liability.) 。
|
||||
无论何种情况,版权持有人或其他分发者均不对使用本程序所造成的任何损失承担责任。
|
||||
- label: |
|
||||
我确认我的描述清晰,语法礼貌,能帮助开发者快速定位问题,并符合社区规则。
|
||||
- label: |
|
||||
我已确认阅读了[OpenList文档](https://docs.oplist.org)。
|
||||
- label: |
|
||||
我已确认没有重复的问题或讨论。
|
||||
- label: |
|
||||
我已确认是`OpenList`的问题,而不是其他原因(例如 [网络](https://docs.oplist.org/zh/faq/howto.html#tls-handshake-timeout-read-connection-reset-by-peer-dns-lookup-failed-connect-connection-refused-client-timeout-exceeded-while-awaiting-headers-no-such-host) ,`依赖`或`操作`)。
|
||||
- label: |
|
||||
我认为此问题必须由`OpenList`处理,而非第三方。
|
||||
- label: |
|
||||
我已确认这个问题在最新版本中没有被修复。
|
||||
|
||||
- type: input
|
||||
id: version
|
||||
attributes:
|
||||
label: OpenList 版本(必填)
|
||||
description: |
|
||||
您使用的是哪个版本的软件?请不要使用`latest`或`master`作为答案。
|
||||
placeholder: v4.xx.xx
|
||||
validations:
|
||||
required: true
|
||||
- type: input
|
||||
id: driver
|
||||
attributes:
|
||||
label: 使用的存储驱动(必填)
|
||||
description: |
|
||||
您使用的是哪个存储驱动?
|
||||
placeholder: "例如: OneDrive"
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: bug-description
|
||||
attributes:
|
||||
label: 问题描述(必填)
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: config
|
||||
attributes:
|
||||
label: 配置文件内容(必填)
|
||||
description: |
|
||||
请提供您的`OpenList`应用的配置文件,并截图相关存储配置。(可隐藏隐私字段)
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: logs
|
||||
attributes:
|
||||
label: 日志(可选)
|
||||
description: |
|
||||
请复制粘贴错误日志,或者截图。(可隐藏隐私字段)
|
||||
- type: textarea
|
||||
id: reproduction
|
||||
attributes:
|
||||
label: 复现链接(可选)
|
||||
description: |
|
||||
请提供能复现此问题的链接。
|
81
.github/ISSUE_TEMPLATE/01-bug_report_en.yml
vendored
Normal file
81
.github/ISSUE_TEMPLATE/01-bug_report_en.yml
vendored
Normal file
@ -0,0 +1,81 @@
|
||||
name: "Bug Report"
|
||||
description: Bug Report / Issue
|
||||
title: "[BUG] Please modify the title to describe the issue you are facing"
|
||||
labels: [bug]
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
Thank you for taking the time to fill out this bug report.
|
||||
Please **make sure** your issue is not a duplicate and is not caused by your own operation, network, or third-party software.
|
||||
|
||||
- type: checkboxes
|
||||
attributes:
|
||||
label: Please confirm the following
|
||||
description: |
|
||||
You must check all the following, otherwise your issue may be closed directly.
|
||||
Or you can go to the [discussions](https://github.com/OpenListTeam/OpenList/discussions).
|
||||
options:
|
||||
- label: |
|
||||
I have read and agree to [AGPL-3.0 Section 15](https://www.gnu.org/licenses/agpl-3.0.txt#:~:text=15.%20Disclaimer%20of%20Warranty.) .
|
||||
The program is provided "as is" without any warranties; you bear all risks of using it.
|
||||
- label: |
|
||||
I have read and agree to [AGPL-3.0 Section 16](https://www.gnu.org/licenses/agpl-3.0.txt#:~:text=16.%20Limitation%20of%20Liability.) .
|
||||
The copyright holders and distributors are not liable for any damages resulting from the use or inability to use the program.
|
||||
- label: |
|
||||
I confirm my description is clear, polite, helps developers quickly locate the issue, and complies with community rules.
|
||||
- label: |
|
||||
I have read the [OpenList documentation](https://docs.oplist.org).
|
||||
- label: |
|
||||
I confirm there are no duplicate issues or discussions.
|
||||
- label: |
|
||||
I confirm this is an `OpenList` issue, not caused by other reasons (such as [network](https://docs.oplist.org/faq/howto.html#tls-handshake-timeout-read-connection-reset-by-peer-dns-lookup-failed-connect-connection-refused-client-timeout-exceeded-while-awaiting-headers-no-such-host), dependencies, or operation).
|
||||
- label: |
|
||||
I believe this issue must be handled by `OpenList` and not by a third party.
|
||||
- label: |
|
||||
I confirm this issue is not fixed in the latest version.
|
||||
|
||||
- type: input
|
||||
id: version
|
||||
attributes:
|
||||
label: OpenList Version (required)
|
||||
description: |
|
||||
What version of the software are you using? Please do not use `latest` or `master` as the answer.
|
||||
placeholder: v4.xx.xx
|
||||
validations:
|
||||
required: true
|
||||
- type: input
|
||||
id: driver
|
||||
attributes:
|
||||
label: Storage Driver Used (required)
|
||||
description: |
|
||||
Which storage driver are you using?
|
||||
placeholder: "e.g. OneDrive"
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: bug-description
|
||||
attributes:
|
||||
label: Bug Description (required)
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: config
|
||||
attributes:
|
||||
label: Configuration File Content (required)
|
||||
description: |
|
||||
Please provide your `OpenList` application's configuration file and a screenshot of the relevant storage configuration. (You may mask sensitive fields)
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: logs
|
||||
attributes:
|
||||
label: Logs (optional)
|
||||
description: |
|
||||
Please copy and paste any relevant log output or screenshots. (You may mask sensitive fields)
|
||||
- type: textarea
|
||||
id: reproduction
|
||||
attributes:
|
||||
label: Reproduction Link (optional)
|
||||
description: |
|
||||
Please provide a link to a repo or page that can reproduce this issue.
|
48
.github/ISSUE_TEMPLATE/02-feature_request_zh.yml
vendored
Normal file
48
.github/ISSUE_TEMPLATE/02-feature_request_zh.yml
vendored
Normal file
@ -0,0 +1,48 @@
|
||||
name: "功能请求"
|
||||
description: 功能请求 / 增强
|
||||
title: "[Feature] 请修改标题为您的功能名称"
|
||||
labels: [enhancement]
|
||||
body:
|
||||
- type: checkboxes
|
||||
attributes:
|
||||
label: 请确认以下事项
|
||||
description: |
|
||||
您必须勾选以下内容,否则您的问题可能会被直接关闭。
|
||||
或者您可以去[讨论区](https://github.com/OpenListTeam/OpenList/discussions)。
|
||||
options:
|
||||
- label: |
|
||||
我已确认阅读并同意 [AGPL-3.0 第15条](https://www.gnu.org/licenses/agpl-3.0.txt#:~:text=15.%20Disclaimer%20of%20Warranty.) 。
|
||||
本程序不提供任何明示或暗示的担保,使用风险由您自行承担。
|
||||
- label: |
|
||||
我已确认阅读并同意 [AGPL-3.0 第16条](https://www.gnu.org/licenses/agpl-3.0.txt#:~:text=16.%20Limitation%20of%20Liability.) 。
|
||||
无论何种情况,版权持有人或其他分发者均不对使用本程序所造成的任何损失承担责任。
|
||||
- label: |
|
||||
我确认我的描述清晰,语法礼貌,能帮助开发者快速定位问题,并符合社区规则。
|
||||
- label: |
|
||||
我已确认阅读了[OpenList文档](https://docs.oplist.org)。
|
||||
- label: |
|
||||
我已确认没有重复的问题或讨论。
|
||||
- label: |
|
||||
我认为此问题必须由`OpenList`处理,而非第三方。
|
||||
- label: |
|
||||
我已确认此功能尚未被实现。
|
||||
- label: |
|
||||
我已确认此功能是合理的,且有普遍需求,并非我个人需要。
|
||||
- type: textarea
|
||||
id: feature-description
|
||||
attributes:
|
||||
label: 需求描述
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: suggested-solution
|
||||
attributes:
|
||||
label: 实现思路
|
||||
description: |
|
||||
实现此需求的解决思路。
|
||||
- type: textarea
|
||||
id: additional-context
|
||||
attributes:
|
||||
label: 附加信息
|
||||
description: |
|
||||
相关的任何其他上下文或截图,或者你觉得有帮助的信息
|
48
.github/ISSUE_TEMPLATE/03-feature_request_en.yml
vendored
Normal file
48
.github/ISSUE_TEMPLATE/03-feature_request_en.yml
vendored
Normal file
@ -0,0 +1,48 @@
|
||||
name: "Feature Request"
|
||||
description: Feature Request / Enhancement
|
||||
title: "[Feature] Please change the title to your feature name"
|
||||
labels: [enhancement]
|
||||
body:
|
||||
- type: checkboxes
|
||||
attributes:
|
||||
label: Please confirm the following
|
||||
description: |
|
||||
You must check all the following, otherwise your request may be closed directly.
|
||||
Or you can go to the [discussions](https://github.com/OpenListTeam/OpenList/discussions).
|
||||
options:
|
||||
- label: |
|
||||
I have read and agree to [AGPL-3.0 Section 15](https://www.gnu.org/licenses/agpl-3.0.txt#:~:text=15.%20Disclaimer%20of%20Warranty.).
|
||||
The program is provided "as is" without any warranties; you bear all risks of using it.
|
||||
- label: |
|
||||
I have read and agree to [AGPL-3.0 Section 16](https://www.gnu.org/licenses/agpl-3.0.txt#:~:text=16.%20Limitation%20of%20Liability.).
|
||||
The copyright holders and distributors are not liable for any damages resulting from the use or inability to use the program.
|
||||
- label: |
|
||||
I confirm my description is clear, polite, helps developers quickly locate the issue, and complies with community rules.
|
||||
- label: |
|
||||
I have read the [OpenList documentation](https://docs.oplist.org).
|
||||
- label: |
|
||||
I confirm there are no duplicate issues or discussions.
|
||||
- label: |
|
||||
I believe this issue must be handled by `OpenList` and not by a third party.
|
||||
- label: |
|
||||
I confirm this feature has not been implemented yet.
|
||||
- label: |
|
||||
I confirm this feature is reasonable and has general demand, not just my personal need.
|
||||
- type: textarea
|
||||
id: feature-description
|
||||
attributes:
|
||||
label: Feature Description
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: suggested-solution
|
||||
attributes:
|
||||
label: Suggested Solution
|
||||
description: |
|
||||
Solution or approach to achieve this feature.
|
||||
- type: textarea
|
||||
id: additional-context
|
||||
attributes:
|
||||
label: Additional Information
|
||||
description: |
|
||||
Any other context or screenshots related to this feature request, or information you find helpful.
|
82
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
82
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
@ -1,82 +0,0 @@
|
||||
name: "Bug report"
|
||||
description: Bug / 错误报告 / 问题
|
||||
title: "[BUG] "
|
||||
labels: [bug]
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
Thanks for taking the time to fill out this bug report, please **confirm that your issue is not a duplicate issue and not because of your operation or version issues**
|
||||
感谢您花时间填写此错误报告,请**务必确认您的issue不是重复的且不是因为您的操作或版本问题**
|
||||
|
||||
- type: checkboxes
|
||||
attributes:
|
||||
label: Please make sure of the following things
|
||||
description: |
|
||||
You must check all the following, otherwise your issue may be closed directly. Or you can go to the [discussions](https://github.com/OpenListTeam/OpenList/discussions)
|
||||
您必须勾选以下所有内容,否则您的issue可能会被直接关闭。或者您可以去[讨论区](https://github.com/OpenListTeam/OpenList/discussions)
|
||||
options:
|
||||
- label: |
|
||||
I have read the [documentation](https://docs.oplist.org).
|
||||
我已经阅读了[文档](https://docs.oplist.org)。
|
||||
- label: |
|
||||
I'm sure there are no duplicate issues or discussions.
|
||||
我确定没有重复的issue或讨论。
|
||||
- label: |
|
||||
I'm sure it's due to `OpenList` and not something else(such as [Network](https://docs.oplist.org/faq/howto.html#tls-handshake-timeout-read-connection-reset-by-peer-dns-lookup-failed-connect-connection-refused-client-timeout-exceeded-while-awaiting-headers-no-such-host) ,`Dependencies` or `Operational`).
|
||||
我确定是`OpenList`的问题,而不是其他原因(例如[网络](https://docs.oplist.org/zh/faq/howto.html#tls-handshake-timeout-read-connection-reset-by-peer-dns-lookup-failed-connect-connection-refused-client-timeout-exceeded-while-awaiting-headers-no-such-host),`依赖`或`操作`)。
|
||||
- label: |
|
||||
I'm sure this issue is not fixed in the latest version.
|
||||
我确定这个问题在最新版本中没有被修复。
|
||||
|
||||
- type: input
|
||||
id: version
|
||||
attributes:
|
||||
label: OpenList Version / OpenList 版本
|
||||
description: |
|
||||
What version of our software are you running? Do not use `latest` or `master` as an answer.
|
||||
您使用的是哪个版本的软件?请不要使用`latest`或`master`作为答案。
|
||||
placeholder: v4.xx.xx
|
||||
validations:
|
||||
required: true
|
||||
- type: input
|
||||
id: driver
|
||||
attributes:
|
||||
label: Driver used / 使用的存储驱动
|
||||
description: |
|
||||
What storage driver are you using?
|
||||
您使用的是哪个存储驱动?
|
||||
placeholder: "for example: Onedrive"
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: bug-description
|
||||
attributes:
|
||||
label: Describe the bug / 问题描述
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: reproduction
|
||||
attributes:
|
||||
label: Reproduction / 复现链接
|
||||
description: |
|
||||
Please provide a link to a repo that can reproduce the problem you ran into. Please be aware that your issue may be closed directly if you don't provide it.
|
||||
请提供能复现此问题的链接,请知悉如果不提供它你的issue可能会被直接关闭
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: config
|
||||
attributes:
|
||||
label: Config / 配置
|
||||
description: |
|
||||
Please provide the configuration file of your `OpenList` application and take a screenshot of the relevant storage configuration. (you can mask sensitive fields)
|
||||
请提供您的`OpenList`应用的配置文件,并截图相关存储配置。(可隐藏隐私字段)
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: logs
|
||||
attributes:
|
||||
label: Logs / 日志
|
||||
description: |
|
||||
Please copy and paste any relevant log output.
|
||||
请复制粘贴错误日志,或者截图
|
10
.github/ISSUE_TEMPLATE/config.yml
vendored
10
.github/ISSUE_TEMPLATE/config.yml
vendored
@ -1,8 +1,14 @@
|
||||
blank_issues_enabled: true
|
||||
contact_links:
|
||||
- name: 问题和讨论
|
||||
url: https://github.com/OpenListTeam/OpenList/discussions
|
||||
about: 讨论、问题、想法等
|
||||
- name: Questions & Discussions
|
||||
url: https://github.com/OpenListTeam/OpenList/discussions
|
||||
about: Discuss / 讨论、问题、想法等
|
||||
about: Discuss issues, ideas, etc.
|
||||
- name: 即时聊天
|
||||
url: https://t.me/OpenListTeam
|
||||
about: 与我们聊天
|
||||
- name: Chat
|
||||
url: https://t.me/OpenListTeam
|
||||
about: Chat with us / 与我们聊天
|
||||
about: Chat with us
|
||||
|
34
.github/ISSUE_TEMPLATE/feature_request.yml
vendored
34
.github/ISSUE_TEMPLATE/feature_request.yml
vendored
@ -1,34 +0,0 @@
|
||||
name: "Feature request"
|
||||
description: Feature request / 功能请求 / 增强
|
||||
title: "[Feature] "
|
||||
labels: [enhancement]
|
||||
body:
|
||||
- type: checkboxes
|
||||
attributes:
|
||||
label: Please make sure of the following things
|
||||
description: You may select more than one, even select all.
|
||||
options:
|
||||
- label: I have read the [documentation](https://docs.openlist.org).
|
||||
- label: I'm sure there are no duplicate issues or discussions.
|
||||
- label: I'm sure this feature is not implemented.
|
||||
- label: I'm sure it's a reasonable and popular requirement.
|
||||
- type: textarea
|
||||
id: feature-description
|
||||
attributes:
|
||||
label: Description of the feature / 需求描述
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: suggested-solution
|
||||
attributes:
|
||||
label: Suggested solution / 实现思路
|
||||
description: |
|
||||
Solutions to achieve this requirement.
|
||||
实现此需求的解决思路。
|
||||
- type: textarea
|
||||
id: additional-context
|
||||
attributes:
|
||||
label: Additional context / 附件
|
||||
description: |
|
||||
Any other context or screenshots about the feature request here, or information you find helpful.
|
||||
相关的任何其他上下文或截图,或者你觉得有帮助的信息
|
21
.github/config.yml
vendored
21
.github/config.yml
vendored
@ -1,21 +0,0 @@
|
||||
# Configuration for welcome - https://github.com/behaviorbot/welcome
|
||||
|
||||
# Configuration for new-issue-welcome - https://github.com/behaviorbot/new-issue-welcome
|
||||
|
||||
# Comment to be posted to on first time issues
|
||||
newIssueWelcomeComment: >
|
||||
Thanks for opening your first issue here! Be sure to follow the issue template!
|
||||
|
||||
# Configuration for new-pr-welcome - https://github.com/behaviorbot/new-pr-welcome
|
||||
|
||||
# Comment to be posted to on PRs from first time contributors in your repository
|
||||
newPRWelcomeComment: >
|
||||
Thanks for opening this pull request! Please check out our contributing guidelines.
|
||||
|
||||
# Configuration for first-pr-merge - https://github.com/behaviorbot/first-pr-merge
|
||||
|
||||
# Comment to be posted to on pull requests merged by a first time user
|
||||
firstPRMergeComment: >
|
||||
Congrats on merging your first pull request! We here at behavior bot are proud of you!
|
||||
|
||||
# It is recommend to include as many gifs and emojis as possible
|
21
.github/stale.yml
vendored
21
.github/stale.yml
vendored
@ -1,21 +0,0 @@
|
||||
# Number of days of inactivity before an issue becomes stale
|
||||
daysUntilStale: 44
|
||||
# Number of days of inactivity before a stale issue is closed
|
||||
daysUntilClose: 20
|
||||
# Issues with these labels will never be considered stale
|
||||
exemptLabels:
|
||||
- accepted
|
||||
- security
|
||||
- working
|
||||
- pr-welcome
|
||||
# Label to use when marking an issue as stale
|
||||
staleLabel: stale
|
||||
# Comment to post when marking an issue as stale. Set to `false` to disable
|
||||
markComment: >
|
||||
This issue has been automatically marked as stale because it has not had
|
||||
recent activity. It will be closed if no further activity occurs. Thank you
|
||||
for your contributions.
|
||||
# Comment to post when closing a stale issue. Set to `false` to disable
|
||||
closeComment: >
|
||||
This issue was closed due to inactive more than 52 days. You can reopen or
|
||||
recreate it if you think it should continue. Thank you for your contributions again.
|
64
.github/workflows/beta_release.yml
vendored
64
.github/workflows/beta_release.yml
vendored
@ -1,8 +1,8 @@
|
||||
name: beta release
|
||||
name: Beta Release builds
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ 'main' ]
|
||||
branches: ["main"]
|
||||
workflow_dispatch:
|
||||
|
||||
concurrency:
|
||||
@ -16,8 +16,8 @@ jobs:
|
||||
changelog:
|
||||
strategy:
|
||||
matrix:
|
||||
platform: [ ubuntu-latest ]
|
||||
go-version: [ '1.21' ]
|
||||
platform: [ubuntu-latest]
|
||||
go-version: ["1.21"]
|
||||
name: Beta Release Changelog
|
||||
runs-on: ${{ matrix.platform }}
|
||||
steps:
|
||||
@ -65,17 +65,17 @@ jobs:
|
||||
strategy:
|
||||
matrix:
|
||||
include:
|
||||
- target: '!(*musl*|*windows-arm64*|*android*|*freebsd*)' # xgo
|
||||
- target: "!(*musl*|*windows-arm64*|*android*|*freebsd*)" # xgo
|
||||
hash: "md5"
|
||||
- target: 'linux-!(arm*)-musl*' #musl-not-arm
|
||||
- target: "linux-!(arm*)-musl*" #musl-not-arm
|
||||
hash: "md5-linux-musl"
|
||||
- target: 'linux-arm*-musl*' #musl-arm
|
||||
- target: "linux-arm*-musl*" #musl-arm
|
||||
hash: "md5-linux-musl-arm"
|
||||
- target: 'windows-arm64' #win-arm64
|
||||
- target: "windows-arm64" #win-arm64
|
||||
hash: "md5-windows-arm64"
|
||||
- target: 'android-*' #android
|
||||
- target: "android-*" #android
|
||||
hash: "md5-android"
|
||||
- target: 'freebsd-*' #freebsd
|
||||
- target: "freebsd-*" #freebsd
|
||||
hash: "md5-freebsd"
|
||||
|
||||
name: Beta Release
|
||||
@ -89,7 +89,7 @@ jobs:
|
||||
- name: Setup Go
|
||||
uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version: '1.22'
|
||||
go-version: "1.24"
|
||||
|
||||
- name: Setup web
|
||||
run: bash build.sh dev web
|
||||
@ -105,11 +105,11 @@ jobs:
|
||||
output: openlist-$target$ext
|
||||
musl-base-url: "https://github.com/OpenListTeam/musl-compilers/releases/latest/download/"
|
||||
x-flags: |
|
||||
github.com/OpenListTeam/OpenList/internal/conf.BuiltAt=$built_at
|
||||
github.com/OpenListTeam/OpenList/internal/conf.GitAuthor=OpenList
|
||||
github.com/OpenListTeam/OpenList/internal/conf.GitCommit=$git_commit
|
||||
github.com/OpenListTeam/OpenList/internal/conf.Version=$tag
|
||||
github.com/OpenListTeam/OpenList/internal/conf.WebVersion=dev
|
||||
github.com/OpenListTeam/OpenList/v4/internal/conf.BuiltAt=$built_at
|
||||
github.com/OpenListTeam/OpenList/v4/internal/conf.GitAuthor=OpenList
|
||||
github.com/OpenListTeam/OpenList/v4/internal/conf.GitCommit=$git_commit
|
||||
github.com/OpenListTeam/OpenList/v4/internal/conf.Version=$tag
|
||||
github.com/OpenListTeam/OpenList/v4/internal/conf.WebVersion=dev
|
||||
|
||||
- name: Compress
|
||||
run: |
|
||||
@ -117,7 +117,7 @@ jobs:
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
# See above
|
||||
# See above
|
||||
- name: Upload assets to beta release
|
||||
uses: softprops/action-gh-release@v2
|
||||
with:
|
||||
@ -141,33 +141,3 @@ jobs:
|
||||
path: ${{ github.workspace }}/build/compress/*
|
||||
compression-level: 0
|
||||
if-no-files-found: error # 'warn' or 'ignore' are also available, defaults to `warn`
|
||||
|
||||
|
||||
# TODO: We do not have desktop clients right now. We may need a better way to
|
||||
# trigger the build of desktop client when we actually have it.
|
||||
# desktop:
|
||||
# needs:
|
||||
# - release
|
||||
# name: Beta Release Desktop
|
||||
# runs-on: ubuntu-latest
|
||||
# steps:
|
||||
# - name: Checkout repo
|
||||
# uses: actions/checkout@v4
|
||||
# with:
|
||||
# repository: openlistteam/desktop-release
|
||||
# ref: main
|
||||
# persist-credentials: false
|
||||
# fetch-depth: 0
|
||||
|
||||
# - name: Commit
|
||||
# run: |
|
||||
# git config --local user.email "bot@nn.ci"
|
||||
# git config --local user.name "IlaBot"
|
||||
# git commit --allow-empty -m "Trigger build for ${{ github.sha }}"
|
||||
|
||||
# - name: Push commit
|
||||
# uses: ad-m/github-push-action@master
|
||||
# with:
|
||||
# github_token: ${{ secrets.MY_TOKEN }}
|
||||
# branch: main
|
||||
# repository: openlistteam/desktop-release
|
||||
|
23
.github/workflows/build.yml
vendored
23
.github/workflows/build.yml
vendored
@ -1,10 +1,10 @@
|
||||
name: build
|
||||
name: Test Build
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ 'main' ]
|
||||
branches: ["main"]
|
||||
pull_request:
|
||||
branches: [ 'main' ]
|
||||
branches: ["main"]
|
||||
workflow_dispatch:
|
||||
|
||||
concurrency:
|
||||
@ -16,7 +16,7 @@ jobs:
|
||||
strategy:
|
||||
matrix:
|
||||
platform: [ubuntu-latest]
|
||||
target:
|
||||
target:
|
||||
- darwin-amd64
|
||||
- darwin-arm64
|
||||
- windows-amd64
|
||||
@ -27,7 +27,6 @@ jobs:
|
||||
name: Build
|
||||
runs-on: ${{ matrix.platform }}
|
||||
steps:
|
||||
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
|
||||
@ -37,7 +36,7 @@ jobs:
|
||||
- name: Setup Go
|
||||
uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version: '1.22'
|
||||
go-version: "1.24"
|
||||
|
||||
- name: Setup web
|
||||
run: bash build.sh dev web
|
||||
@ -51,14 +50,14 @@ jobs:
|
||||
musl-target-format: $os-$musl-$arch
|
||||
out-dir: build
|
||||
x-flags: |
|
||||
github.com/OpenListTeam/OpenList/internal/conf.BuiltAt=$built_at
|
||||
github.com/OpenListTeam/OpenList/internal/conf.GitAuthor=OpenList
|
||||
github.com/OpenListTeam/OpenList/internal/conf.GitCommit=$git_commit
|
||||
github.com/OpenListTeam/OpenList/internal/conf.Version=$tag
|
||||
github.com/OpenListTeam/OpenList/internal/conf.WebVersion=dev
|
||||
github.com/OpenListTeam/OpenList/v4/internal/conf.BuiltAt=$built_at
|
||||
github.com/OpenListTeam/OpenList/v4/internal/conf.GitAuthor=OpenList
|
||||
github.com/OpenListTeam/OpenList/v4/internal/conf.GitCommit=$git_commit
|
||||
github.com/OpenListTeam/OpenList/v4/internal/conf.Version=$tag
|
||||
github.com/OpenListTeam/OpenList/v4/internal/conf.WebVersion=dev
|
||||
|
||||
- name: Upload artifact
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: openlist_${{ env.SHA }}_${{ matrix.target }}
|
||||
path: build/*
|
||||
path: build/*
|
||||
|
5
.github/workflows/changelog.yml
vendored
5
.github/workflows/changelog.yml
vendored
@ -1,10 +1,13 @@
|
||||
name: auto changelog
|
||||
name: Automatic changelog
|
||||
|
||||
on:
|
||||
push:
|
||||
tags:
|
||||
- 'v*'
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
|
||||
jobs:
|
||||
changelog:
|
||||
name: Create Release
|
||||
|
61
.github/workflows/issue_pr_comment.yml
vendored
Normal file
61
.github/workflows/issue_pr_comment.yml
vendored
Normal file
@ -0,0 +1,61 @@
|
||||
name: Issue or PR Auto Reply
|
||||
|
||||
on:
|
||||
issues:
|
||||
types: [opened]
|
||||
pull_request:
|
||||
types: [opened]
|
||||
|
||||
permissions:
|
||||
issues: write
|
||||
pull-requests: write
|
||||
|
||||
jobs:
|
||||
auto-reply:
|
||||
runs-on: ubuntu-latest
|
||||
if: github.event_name == 'issues'
|
||||
steps:
|
||||
- name: Check issue for unchecked tasks and reply
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
script: |
|
||||
const issueBody = context.payload.issue.body || "";
|
||||
const unchecked = /- \[ \] /.test(issueBody);
|
||||
let comment = "感谢您联系OpenList。我们会尽快回复您。\n";
|
||||
comment += "Thanks for contacting OpenList. We will reply to you as soon as possible.\n\n";
|
||||
if (unchecked) {
|
||||
comment += "由于您提出的 Issue 中包含部分未确认的项目,为了更好地管理项目,在人工审核后可能会直接关闭此问题。\n";
|
||||
comment += "如果您能确认并补充相关未确认项目的信息,欢迎随时重新提交。我们会及时关注并处理。感谢您的理解与支持!\n";
|
||||
comment += "Since your issue contains some unchecked tasks, it may be closed after manual review.\n";
|
||||
comment += "If you can confirm and provide information for the unchecked tasks, feel free to resubmit.\n";
|
||||
comment += "We will pay attention and handle it in a timely manner.\n\n";
|
||||
comment += "感谢您的理解与支持!\n";
|
||||
comment += "Thank you for your understanding and support!\n";
|
||||
}
|
||||
await github.rest.issues.createComment({
|
||||
...context.repo,
|
||||
issue_number: context.issue.number,
|
||||
body: comment
|
||||
});
|
||||
|
||||
pr-title-check:
|
||||
runs-on: ubuntu-latest
|
||||
if: github.event_name == 'pull_request'
|
||||
steps:
|
||||
- name: Check PR title for required prefix and comment
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
script: |
|
||||
const title = context.payload.pull_request.title || "";
|
||||
const ok = /^(feat|docs|fix|style|refactor|chore)\(.+?\): /i.test(title);
|
||||
if (!ok) {
|
||||
let comment = "⚠️ PR 标题需以 `feat(): `, `docs(): `, `fix(): `, `style(): `, `refactor(): `, `chore(): ` 其中之一开头,例如:`feat(component): 新增功能`。\n";
|
||||
comment += "⚠️ The PR title must start with `feat(): `, `docs(): `, `fix(): `, `style(): `, or `refactor(): `, `chore(): `. For example: `feat(component): add new feature`.\n\n";
|
||||
comment += "如果跨多个组件,请使用主要组件作为前缀,并在标题中枚举、描述中说明。\n";
|
||||
comment += "If it spans multiple components, use the main component as the prefix and enumerate in the title, describe in the body.\n\n";
|
||||
await github.rest.issues.createComment({
|
||||
...context.repo,
|
||||
issue_number: context.issue.number,
|
||||
body: comment
|
||||
});
|
||||
}
|
90
.github/workflows/release.yml
vendored
90
.github/workflows/release.yml
vendored
@ -1,9 +1,11 @@
|
||||
name: release
|
||||
name: Release builds
|
||||
|
||||
on:
|
||||
release:
|
||||
types: [ published ]
|
||||
permissions: write-all
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
|
||||
jobs:
|
||||
release:
|
||||
@ -67,32 +69,64 @@ jobs:
|
||||
files: build/compress/*
|
||||
prerelease: false
|
||||
|
||||
release-lite:
|
||||
strategy:
|
||||
matrix:
|
||||
platform: [ ubuntu-latest ]
|
||||
go-version: [ '1.21' ]
|
||||
name: Release Lite
|
||||
runs-on: ${{ matrix.platform }}
|
||||
steps:
|
||||
|
||||
# TODO: We do not have desktop clients right now. We may need a better way to
|
||||
# trigger the build of desktop client when we actually have it.
|
||||
# release_desktop:
|
||||
# needs: release
|
||||
# name: Release desktop
|
||||
# runs-on: ubuntu-latest
|
||||
# steps:
|
||||
# - name: Checkout repo
|
||||
# uses: actions/checkout@v4
|
||||
# with:
|
||||
# repository: openlistteam/desktop-release
|
||||
# ref: main
|
||||
# persist-credentials: false
|
||||
# fetch-depth: 0
|
||||
- name: Free Disk Space (Ubuntu)
|
||||
uses: jlumbroso/free-disk-space@main
|
||||
with:
|
||||
# this might remove tools that are actually needed,
|
||||
# if set to "true" but frees about 6 GB
|
||||
tool-cache: false
|
||||
|
||||
# all of these default to true, but feel free to set to
|
||||
# "false" if necessary for your workflow
|
||||
android: true
|
||||
dotnet: true
|
||||
haskell: true
|
||||
large-packages: true
|
||||
docker-images: true
|
||||
swap-storage: true
|
||||
|
||||
# - name: Add tag
|
||||
# run: |
|
||||
# git config --local user.email "bot@nn.ci"
|
||||
# git config --local user.name "IlaBot"
|
||||
# version=$(wget -qO- -t1 -T2 "https://api.github.com/repos/openlistteam/openlist/releases/latest" | grep "tag_name" | head -n 1 | awk -F ":" '{print $2}' | sed 's/\"//g;s/,//g;s/ //g')
|
||||
# git tag -a $version -m "release $version"
|
||||
- name: Prerelease
|
||||
uses: irongut/EditRelease@v1.2.0
|
||||
with:
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
id: ${{ github.event.release.id }}
|
||||
prerelease: true
|
||||
|
||||
- name: Setup Go
|
||||
uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version: ${{ matrix.go-version }}
|
||||
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
sudo snap install zig --classic --beta
|
||||
docker pull crazymax/xgo:latest
|
||||
go install github.com/crazy-max/xgo@latest
|
||||
sudo apt install upx
|
||||
|
||||
- name: Build
|
||||
run: |
|
||||
bash build.sh release lite
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Upload assets
|
||||
uses: softprops/action-gh-release@v2
|
||||
with:
|
||||
files: build/compress/*
|
||||
prerelease: false
|
||||
|
||||
# - name: Push tags
|
||||
# uses: ad-m/github-push-action@master
|
||||
# with:
|
||||
# github_token: ${{ secrets.MY_TOKEN }}
|
||||
# branch: main
|
||||
# repository: openlistteam/desktop-release
|
||||
|
35
.github/workflows/release_android.yml
vendored
35
.github/workflows/release_android.yml
vendored
@ -1,10 +1,11 @@
|
||||
name: release_android
|
||||
name: Release builds (Android)
|
||||
|
||||
on:
|
||||
release:
|
||||
types: [ published ]
|
||||
|
||||
permissions: write-all
|
||||
permissions:
|
||||
contents: write
|
||||
|
||||
jobs:
|
||||
release_android:
|
||||
@ -36,3 +37,33 @@ jobs:
|
||||
uses: softprops/action-gh-release@v2
|
||||
with:
|
||||
files: build/compress/*
|
||||
|
||||
release_android_lite:
|
||||
strategy:
|
||||
matrix:
|
||||
platform: [ ubuntu-latest ]
|
||||
go-version: [ '1.21' ]
|
||||
name: Release
|
||||
runs-on: ${{ matrix.platform }}
|
||||
steps:
|
||||
|
||||
- name: Setup Go
|
||||
uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version: ${{ matrix.go-version }}
|
||||
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Build
|
||||
run: |
|
||||
bash build.sh release lite android
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Upload assets
|
||||
uses: softprops/action-gh-release@v2
|
||||
with:
|
||||
files: build/compress/*
|
||||
|
141
.github/workflows/release_docker.yml
vendored
141
.github/workflows/release_docker.yml
vendored
@ -1,4 +1,4 @@
|
||||
name: release_docker
|
||||
name: Release builds (Docker)
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
@ -24,18 +24,21 @@ concurrency:
|
||||
cancel-in-progress: true
|
||||
|
||||
env:
|
||||
ORG_NAME: openlistteam
|
||||
DOCKERHUB_ORG_NAME: ${{ vars.DOCKERHUB_ORG_NAME || 'openlistteam' }}
|
||||
GHCR_ORG_NAME: ${{ vars.GHCR_ORG_NAME || 'openlistteam' }}
|
||||
IMAGE_NAME: openlist-git
|
||||
IMAGE_NAME_DOCKERHUB: openlist
|
||||
REGISTRY: ghcr.io
|
||||
ARTIFACT_NAME: 'binaries_docker_release'
|
||||
ARTIFACT_NAME_LITE: 'binaries_docker_release_lite'
|
||||
RELEASE_PLATFORMS: 'linux/amd64,linux/arm64,linux/arm/v7,linux/386,linux/arm/v6,linux/s390x,linux/ppc64le,linux/riscv64'
|
||||
IMAGE_PUSH: ${{ github.event_name == 'push' || github.event_name == 'workflow_dispatch' }}
|
||||
IMAGE_IS_PROD: ${{ github.ref_type == 'tag' || github.event.inputs.as_latest == 'true' }}
|
||||
IMAGE_TAGS_BETA: |
|
||||
type=raw,value=beta,enable={{is_default_branch}}
|
||||
|
||||
permissions: write-all
|
||||
permissions:
|
||||
packages: write
|
||||
|
||||
jobs:
|
||||
build_binary:
|
||||
@ -84,6 +87,52 @@ jobs:
|
||||
!build/*.tgz
|
||||
!build/musl-libs/**
|
||||
|
||||
build_binary_lite:
|
||||
name: Build Binaries for Docker Release
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version: 'stable'
|
||||
|
||||
- name: Cache Musl
|
||||
id: cache-musl
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: build/musl-libs
|
||||
key: docker-musl-libs-v2
|
||||
|
||||
- name: Download Musl Library
|
||||
if: steps.cache-musl.outputs.cache-hit != 'true'
|
||||
run: bash build.sh prepare lite docker-multiplatform
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Build go binary (beta)
|
||||
if: env.IMAGE_IS_PROD != 'true'
|
||||
run: bash build.sh beta lite docker-multiplatform
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Build go binary (release)
|
||||
if: env.IMAGE_IS_PROD == 'true'
|
||||
run: bash build.sh release lite docker-multiplatform
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Upload artifacts
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: ${{ env.ARTIFACT_NAME_LITE }}
|
||||
overwrite: true
|
||||
path: |
|
||||
build/
|
||||
!build/*.tgz
|
||||
!build/musl-libs/**
|
||||
|
||||
release_docker:
|
||||
needs: build_binary
|
||||
name: Release Docker image
|
||||
@ -132,7 +181,7 @@ jobs:
|
||||
if: env.IMAGE_PUSH == 'true'
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
username: ${{ env.ORG_NAME }}
|
||||
username: ${{ env.DOCKERHUB_ORG_NAME }}
|
||||
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||
|
||||
- name: Docker meta
|
||||
@ -140,8 +189,88 @@ jobs:
|
||||
uses: docker/metadata-action@v5
|
||||
with:
|
||||
images: |
|
||||
${{ env.REGISTRY }}/${{ env.ORG_NAME }}/${{ env.IMAGE_NAME }}
|
||||
${{ env.ORG_NAME }}/${{ env.IMAGE_NAME_DOCKERHUB }}
|
||||
${{ env.REGISTRY }}/${{ env.GHCR_ORG_NAME }}/${{ env.IMAGE_NAME }}
|
||||
${{ env.DOCKERHUB_ORG_NAME }}/${{ env.IMAGE_NAME_DOCKERHUB }}
|
||||
tags: >
|
||||
${{ env.IMAGE_IS_PROD == 'true' && (
|
||||
github.event_name == 'workflow_dispatch'
|
||||
&& format('type=raw,value={0}', github.event.inputs.manual_tag)
|
||||
|| format('type=raw,value={0}', github.ref_name)
|
||||
) || env.IMAGE_TAGS_BETA }}
|
||||
flavor: |
|
||||
latest=${{ env.IMAGE_IS_PROD }}
|
||||
${{ matrix.tag_favor }}
|
||||
|
||||
- name: Build and push
|
||||
id: docker_build
|
||||
uses: docker/build-push-action@v6
|
||||
with:
|
||||
context: .
|
||||
file: Dockerfile.ci
|
||||
push: ${{ env.IMAGE_PUSH == 'true' }}
|
||||
build-args: ${{ matrix.build_arg }}
|
||||
tags: ${{ steps.meta.outputs.tags }}
|
||||
labels: ${{ steps.meta.outputs.labels }}
|
||||
platforms: ${{ env.RELEASE_PLATFORMS }}
|
||||
|
||||
release_docker_lite:
|
||||
needs: build_binary_lite
|
||||
name: Release Docker image
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
matrix:
|
||||
image: ["latest", "ffmpeg", "aria2", "aio"]
|
||||
include:
|
||||
- image: "latest"
|
||||
build_arg: ""
|
||||
tag_favor: "suffix=-lite,onlatest=true"
|
||||
- image: "ffmpeg"
|
||||
build_arg: INSTALL_FFMPEG=true
|
||||
tag_favor: "suffix=-lite-ffmpeg,onlatest=true"
|
||||
- image: "aria2"
|
||||
build_arg: INSTALL_ARIA2=true
|
||||
tag_favor: "suffix=-lite-aria2,onlatest=true"
|
||||
- image: "aio"
|
||||
build_arg: |
|
||||
INSTALL_FFMPEG=true
|
||||
INSTALL_ARIA2=true
|
||||
tag_favor: "suffix=-lite-aio,onlatest=true"
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
- uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: ${{ env.ARTIFACT_NAME_LITE }}
|
||||
path: 'build/'
|
||||
|
||||
- name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@v3
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
|
||||
- name: Login to GitHub Container Registry
|
||||
if: env.IMAGE_PUSH == 'true'
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
registry: ${{ env.REGISTRY }}
|
||||
username: ${{ github.actor }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Login to DockerHub Container Registry
|
||||
if: env.IMAGE_PUSH == 'true'
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
username: ${{ env.DOCKERHUB_ORG_NAME }}
|
||||
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||
|
||||
- name: Docker meta
|
||||
id: meta
|
||||
uses: docker/metadata-action@v5
|
||||
with:
|
||||
images: |
|
||||
${{ env.REGISTRY }}/${{ env.GHCR_ORG_NAME }}/${{ env.IMAGE_NAME }}
|
||||
${{ env.DOCKERHUB_ORG_NAME }}/${{ env.IMAGE_NAME_DOCKERHUB }}
|
||||
tags: >
|
||||
${{ env.IMAGE_IS_PROD == 'true' && (
|
||||
github.event_name == 'workflow_dispatch'
|
||||
|
37
.github/workflows/release_freebsd.yml
vendored
37
.github/workflows/release_freebsd.yml
vendored
@ -1,12 +1,13 @@
|
||||
name: release_freebsd
|
||||
name: Release builds (Freebsd)
|
||||
|
||||
on:
|
||||
release:
|
||||
types: [ published ]
|
||||
|
||||
permissions: write-all
|
||||
jobs:
|
||||
permissions:
|
||||
contents: write
|
||||
|
||||
jobs:
|
||||
release_freebsd:
|
||||
strategy:
|
||||
matrix:
|
||||
@ -36,3 +37,33 @@ jobs:
|
||||
uses: softprops/action-gh-release@v2
|
||||
with:
|
||||
files: build/compress/*
|
||||
|
||||
release_freebsd_lite:
|
||||
strategy:
|
||||
matrix:
|
||||
platform: [ ubuntu-latest ]
|
||||
go-version: [ '1.21' ]
|
||||
name: Release
|
||||
runs-on: ${{ matrix.platform }}
|
||||
steps:
|
||||
|
||||
- name: Setup Go
|
||||
uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version: ${{ matrix.go-version }}
|
||||
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Build
|
||||
run: |
|
||||
bash build.sh release lite freebsd
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Upload assets
|
||||
uses: softprops/action-gh-release@v2
|
||||
with:
|
||||
files: build/compress/*
|
||||
|
37
.github/workflows/release_linux_musl.yml
vendored
37
.github/workflows/release_linux_musl.yml
vendored
@ -1,9 +1,12 @@
|
||||
name: release_linux_musl
|
||||
name: Release builds (linux_musl)
|
||||
|
||||
on:
|
||||
release:
|
||||
types: [ published ]
|
||||
permissions: write-all
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
|
||||
jobs:
|
||||
release_linux_musl:
|
||||
strategy:
|
||||
@ -34,3 +37,33 @@ jobs:
|
||||
uses: softprops/action-gh-release@v2
|
||||
with:
|
||||
files: build/compress/*
|
||||
|
||||
release_linux_musl_lite:
|
||||
strategy:
|
||||
matrix:
|
||||
platform: [ ubuntu-latest ]
|
||||
go-version: [ '1.21' ]
|
||||
name: Release
|
||||
runs-on: ${{ matrix.platform }}
|
||||
steps:
|
||||
|
||||
- name: Setup Go
|
||||
uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version: ${{ matrix.go-version }}
|
||||
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Build
|
||||
run: |
|
||||
bash build.sh release lite linux_musl
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Upload assets
|
||||
uses: softprops/action-gh-release@v2
|
||||
with:
|
||||
files: build/compress/*
|
||||
|
37
.github/workflows/release_linux_musl_arm.yml
vendored
37
.github/workflows/release_linux_musl_arm.yml
vendored
@ -1,10 +1,12 @@
|
||||
name: release_linux_musl_arm
|
||||
name: Release builds (linux_musl_arm)
|
||||
|
||||
on:
|
||||
release:
|
||||
types: [ published ]
|
||||
|
||||
permissions: write-all
|
||||
permissions:
|
||||
contents: write
|
||||
|
||||
jobs:
|
||||
release_linux_musl_arm:
|
||||
strategy:
|
||||
@ -35,3 +37,34 @@ jobs:
|
||||
uses: softprops/action-gh-release@v2
|
||||
with:
|
||||
files: build/compress/*
|
||||
|
||||
release_linux_musl_arm_lite:
|
||||
strategy:
|
||||
matrix:
|
||||
platform: [ ubuntu-latest ]
|
||||
go-version: [ '1.21' ]
|
||||
name: Release
|
||||
runs-on: ${{ matrix.platform }}
|
||||
steps:
|
||||
|
||||
- name: Setup Go
|
||||
uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version: ${{ matrix.go-version }}
|
||||
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Build
|
||||
run: |
|
||||
bash build.sh release lite linux_musl_arm
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Upload assets
|
||||
uses: softprops/action-gh-release@v2
|
||||
with:
|
||||
files: build/compress/*
|
||||
|
13
.github/workflows/test_docker.yml
vendored
13
.github/workflows/test_docker.yml
vendored
@ -1,4 +1,4 @@
|
||||
name: test_docker
|
||||
name: Docker Beta Release
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
@ -14,11 +14,13 @@ concurrency:
|
||||
cancel-in-progress: true
|
||||
|
||||
env:
|
||||
ORG_NAME: openlistteam
|
||||
DOCKERHUB_ORG_NAME: ${{ vars.DOCKERHUB_ORG_NAME || 'openlistteam' }}
|
||||
GHCR_ORG_NAME: ${{ vars.GHCR_ORG_NAME || 'openlistteam' }}
|
||||
IMAGE_NAME: openlist-git
|
||||
IMAGE_NAME_DOCKERHUB: openlist
|
||||
REGISTRY: ghcr.io
|
||||
ARTIFACT_NAME: 'binaries_docker_release'
|
||||
ARTIFACT_NAME_LITE: 'binaries_docker_release_lite'
|
||||
RELEASE_PLATFORMS: 'linux/amd64,linux/arm64,linux/arm/v7,linux/386,linux/arm/v6,linux/s390x,linux/ppc64le,linux/riscv64'
|
||||
IMAGE_PUSH: ${{ github.event_name == 'push' }}
|
||||
IMAGE_TAGS_BETA: |
|
||||
@ -70,7 +72,6 @@ jobs:
|
||||
name: Release Docker image
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: read
|
||||
packages: write
|
||||
strategy:
|
||||
matrix:
|
||||
@ -116,7 +117,7 @@ jobs:
|
||||
if: env.IMAGE_PUSH == 'true'
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
username: ${{ env.ORG_NAME }}
|
||||
username: ${{ env.DOCKERHUB_ORG_NAME }}
|
||||
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||
|
||||
- name: Docker meta
|
||||
@ -124,8 +125,8 @@ jobs:
|
||||
uses: docker/metadata-action@v5
|
||||
with:
|
||||
images: |
|
||||
${{ env.REGISTRY }}/${{ env.ORG_NAME }}/${{ env.IMAGE_NAME }}
|
||||
${{ env.ORG_NAME }}/${{ env.IMAGE_NAME_DOCKERHUB }}
|
||||
${{ env.REGISTRY }}/${{ env.GHCR_ORG_NAME }}/${{ env.IMAGE_NAME }}
|
||||
${{ env.DOCKERHUB_ORG_NAME }}/${{ env.IMAGE_NAME_DOCKERHUB }}
|
||||
tags: ${{ env.IMAGE_TAGS_BETA }}
|
||||
flavor: |
|
||||
${{ matrix.tag_favor }}
|
||||
|
40
.github/workflows/trigger-makefile-update.yml
vendored
Normal file
40
.github/workflows/trigger-makefile-update.yml
vendored
Normal file
@ -0,0 +1,40 @@
|
||||
name: Trigger OpenWRT Update
|
||||
|
||||
on:
|
||||
push:
|
||||
tags:
|
||||
- 'v*'
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
tag:
|
||||
description: 'Release tag to trigger update for'
|
||||
required: true
|
||||
type: string
|
||||
|
||||
jobs:
|
||||
trigger-makefile-update:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Trigger Makefile hash update
|
||||
uses: peter-evans/repository-dispatch@v3
|
||||
with:
|
||||
token: ${{ secrets.EXTERNAL_REPO_TOKEN_LUCI_APP_OPENLIST }}
|
||||
repository: ${{ vars.HOOK_REPO || 'OpenListTeam/luci-app-openlist' }}
|
||||
event-type: update-hashes
|
||||
client-payload: |
|
||||
{
|
||||
"source_repository": "${{ github.repository }}",
|
||||
"release_tag": "${{ inputs.tag || github.ref_name }}",
|
||||
"release_name": "${{ inputs.tag || github.ref_name }}",
|
||||
"release_url": "${{ github.server_url }}/${{ github.repository }}/releases/tag/${{ inputs.tag || github.ref_name }}",
|
||||
"triggered_by": "${{ github.actor }}",
|
||||
"trigger_reason": "${{ github.event_name }}"
|
||||
}
|
||||
|
||||
- name: Log trigger information
|
||||
run: |
|
||||
echo "🚀 Successfully triggered Makefile hash update"
|
||||
echo "📦 Target repository: OpenListTeam/luci-app-openlist"
|
||||
echo "🏷️ Tag: ${{ inputs.tag || github.ref_name }}"
|
||||
echo "👤 Triggered by: ${{ github.actor }}"
|
||||
echo "📅 Trigger time: $(date -u '+%Y-%m-%d %H:%M:%S UTC')"
|
163
README.md
163
README.md
@ -1,79 +1,62 @@
|
||||
<div align="center">
|
||||
<img width="100px" alt="logo" src="https://raw.githubusercontent.com/OpenListTeam/Logo/main/logo.svg"/></a>
|
||||
<p><em>🗂️A file list program that supports multiple storages, powered by Gin and SolidJS, fork of AList.</em></p>
|
||||
<div>
|
||||
<a href="https://goreportcard.com/report/github.com/OpenListTeam/OpenList/v3">
|
||||
<img src="https://goreportcard.com/badge/github.com/OpenListTeam/OpenList/v3" alt="latest version" />
|
||||
</a>
|
||||
<a href="https://github.com/OpenListTeam/OpenList/blob/main/LICENSE">
|
||||
<img src="https://img.shields.io/github/license/OpenListTeam/OpenList" alt="License" />
|
||||
</a>
|
||||
<a href="https://github.com/OpenListTeam/OpenList/actions?query=workflow%3ABuild">
|
||||
<img src="https://img.shields.io/github/actions/workflow/status/OpenListTeam/OpenList/build.yml?branch=main" alt="Build status" />
|
||||
</a>
|
||||
<a href="https://github.com/OpenListTeam/OpenList/releases">
|
||||
<img src="https://img.shields.io/github/release/OpenListTeam/OpenList" alt="latest version" />
|
||||
</a>
|
||||
</div>
|
||||
<div>
|
||||
<a href="https://github.com/OpenListTeam/OpenList/discussions">
|
||||
<img src="https://img.shields.io/github/discussions/OpenListTeam/OpenList?color=%23ED8936" alt="discussions" />
|
||||
</a>
|
||||
<a href="https://github.com/OpenListTeam/OpenList/releases">
|
||||
<img src="https://img.shields.io/github/downloads/OpenListTeam/OpenList/total?color=%239F7AEA&logo=github" alt="Downloads" />
|
||||
</a>
|
||||
</div>
|
||||
<img style="width: 128px; height: 128px;" src="https://raw.githubusercontent.com/OpenListTeam/Logo/main/logo.svg" alt="logo" />
|
||||
|
||||
<p><em>OpenList is a resilient, long-term governance, community-driven fork of AList — built to defend open source against trust-based attacks.</em></p>
|
||||
|
||||
<img src="https://goreportcard.com/badge/github.com/OpenListTeam/OpenList/v3" alt="latest version" />
|
||||
<a href="https://github.com/OpenListTeam/OpenList/blob/main/LICENSE"><img src="https://img.shields.io/github/license/OpenListTeam/OpenList" alt="License" /></a>
|
||||
<a href="https://github.com/OpenListTeam/OpenList/actions?query=workflow%3ABuild"><img src="https://img.shields.io/github/actions/workflow/status/OpenListTeam/OpenList/build.yml?branch=main" alt="Build status" /></a>
|
||||
<a href="https://github.com/OpenListTeam/OpenList/releases"><img src="https://img.shields.io/github/release/OpenListTeam/OpenList" alt="latest version" /></a>
|
||||
|
||||
<a href="https://github.com/OpenListTeam/OpenList/discussions"><img src="https://img.shields.io/github/discussions/OpenListTeam/OpenList?color=%23ED8936" alt="discussions" /></a>
|
||||
<a href="https://github.com/OpenListTeam/OpenList/releases"><img src="https://img.shields.io/github/downloads/OpenListTeam/OpenList/total?color=%239F7AEA&logo=github" alt="Downloads" /></a>
|
||||
</div>
|
||||
|
||||
---
|
||||
|
||||
> [!IMPORTANT]
|
||||
>
|
||||
> Drop-in replacement for AList with long-term governance, no hidden risks, and full transparency, built to defend open source against trust-based attacks.
|
||||
>
|
||||
> We sincerely thank the author [Xhofe](https://github.com/Xhofe) of the original project [AlistGo/alist](https://github.com/AlistGo/alist) and all other contributors.
|
||||
>
|
||||
> This fork is not yet stable, specific migration progress can be viewed in [OpenList Migration Work Summary](https://github.com/OpenListTeam/OpenList/issues/6).
|
||||
- English | [中文](./README_cn.md) | [日本語](./README_ja.md) | [Dutch](./README_nl.md)
|
||||
|
||||
English | [中文](./README_cn.md) | [日本語](./README_ja.md) | [Contributing](./CONTRIBUTING.md) | [CODE OF CONDUCT](./CODE_OF_CONDUCT.md)
|
||||
- [Contributing](./CONTRIBUTING.md)
|
||||
- [CODE OF CONDUCT](./CODE_OF_CONDUCT.md)
|
||||
- [LICENSE](./LICENSE)
|
||||
|
||||
## Features
|
||||
|
||||
- [x] Multiple storages
|
||||
- [x] Local storage
|
||||
- [x] [Aliyundrive](https://www.alipan.com/)
|
||||
- [x] OneDrive / Sharepoint ([global](https://www.office.com/), [cn](https://portal.partner.microsoftonline.cn),de,us)
|
||||
- [x] [189cloud](https://cloud.189.cn) (Personal, Family)
|
||||
- [x] [GoogleDrive](https://drive.google.com/)
|
||||
- [x] [123pan](https://www.123pan.com/)
|
||||
- [x] FTP / SFTP
|
||||
- [x] [PikPak](https://www.mypikpak.com/)
|
||||
- [x] [S3](https://aws.amazon.com/s3/)
|
||||
- [x] [Seafile](https://seafile.com/)
|
||||
- [x] [UPYUN Storage Service](https://www.upyun.com/products/file-storage)
|
||||
- [x] WebDav(Support OneDrive/SharePoint without API)
|
||||
- [x] Teambition([China](https://www.teambition.com/ ),[International](https://us.teambition.com/ ))
|
||||
- [x] [Mediatrack](https://www.mediatrack.cn/)
|
||||
- [x] [139yun](https://yun.139.com/) (Personal, Family, Group)
|
||||
- [x] [YandexDisk](https://disk.yandex.com/)
|
||||
- [x] [BaiduNetdisk](http://pan.baidu.com/)
|
||||
- [x] [Terabox](https://www.terabox.com/main)
|
||||
- [x] [UC](https://drive.uc.cn)
|
||||
- [x] [Quark](https://pan.quark.cn)
|
||||
- [x] [Thunder](https://pan.xunlei.com)
|
||||
- [x] [Lanzou](https://www.lanzou.com/)
|
||||
- [x] [ILanzou](https://www.ilanzou.com/)
|
||||
- [x] [Aliyundrive share](https://www.alipan.com/)
|
||||
- [x] [Google photo](https://photos.google.com/)
|
||||
- [x] [Mega.nz](https://mega.nz)
|
||||
- [x] [Baidu photo](https://photo.baidu.com/)
|
||||
- [x] SMB
|
||||
- [x] [115](https://115.com/)
|
||||
- [X] Cloudreve
|
||||
- [x] [Dropbox](https://www.dropbox.com/)
|
||||
- [x] [FeijiPan](https://www.feijipan.com/)
|
||||
- [x] [dogecloud](https://www.dogecloud.com/product/oss)
|
||||
- [x] [Azure Blob Storage](https://azure.microsoft.com/products/storage/blobs)
|
||||
- [x] Local storage
|
||||
- [x] [Aliyundrive](https://www.alipan.com)
|
||||
- [x] OneDrive / Sharepoint ([Global](https://www.microsoft.com/en-us/microsoft-365/onedrive/online-cloud-storage), [CN](https://portal.partner.microsoftonline.cn), DE, US)
|
||||
- [x] [189cloud](https://cloud.189.cn) (Personal, Family)
|
||||
- [x] [GoogleDrive](https://drive.google.com)
|
||||
- [x] [123pan](https://www.123pan.com)
|
||||
- [x] [FTP / SFTP](https://en.wikipedia.org/wiki/File_Transfer_Protocol)
|
||||
- [x] [PikPak](https://www.mypikpak.com)
|
||||
- [x] [S3](https://aws.amazon.com/s3)
|
||||
- [x] [Seafile](https://seafile.com)
|
||||
- [x] [UPYUN Storage Service](https://www.upyun.com/products/file-storage)
|
||||
- [x] [WebDAV](https://en.wikipedia.org/wiki/WebDAV)
|
||||
- [x] Teambition([China](https://www.teambition.com), [International](https://us.teambition.com))
|
||||
- [x] [Mediatrack](https://www.mediatrack.cn)
|
||||
- [x] [139yun](https://yun.139.com) (Personal, Family, Group)
|
||||
- [x] [YandexDisk](https://disk.yandex.com)
|
||||
- [x] [BaiduNetdisk](http://pan.baidu.com)
|
||||
- [x] [Terabox](https://www.terabox.com/main)
|
||||
- [x] [UC](https://drive.uc.cn)
|
||||
- [x] [Quark](https://pan.quark.cn)
|
||||
- [x] [Thunder](https://pan.xunlei.com)
|
||||
- [x] [Lanzou](https://www.lanzou.com)
|
||||
- [x] [ILanzou](https://www.ilanzou.com)
|
||||
- [x] [Aliyundrive share](https://www.alipan.com)
|
||||
- [x] [Google photo](https://photos.google.com)
|
||||
- [x] [Mega.nz](https://mega.nz)
|
||||
- [x] [Baidu photo](https://photo.baidu.com)
|
||||
- [x] [SMB](https://en.wikipedia.org/wiki/Server_Message_Block)
|
||||
- [x] [115](https://115.com)
|
||||
- [X] [Cloudreve](https://cloudreve.org)
|
||||
- [x] [Dropbox](https://www.dropbox.com)
|
||||
- [x] [FeijiPan](https://www.feijipan.com)
|
||||
- [x] [dogecloud](https://www.dogecloud.com/product/oss)
|
||||
- [x] [Azure Blob Storage](https://azure.microsoft.com/products/storage/blobs)
|
||||
- [x] Easy to deploy and out-of-the-box
|
||||
- [x] File preview (PDF, markdown, code, plain text, ...)
|
||||
- [x] Image preview in gallery mode
|
||||
@ -84,8 +67,8 @@ English | [中文](./README_cn.md) | [日本語](./README_ja.md) | [Contributing
|
||||
- [x] Dark mode
|
||||
- [x] I18n
|
||||
- [x] Protected routes (password protection and authentication)
|
||||
- [x] WebDav (waiting for detail documents)
|
||||
- [ ] Docker Deploy (rebuilding)
|
||||
- [x] WebDAV
|
||||
- [x] Docker Deploy
|
||||
- [x] Cloudflare Workers proxy
|
||||
- [x] File/Folder package download
|
||||
- [x] Web upload(Can allow visitors to upload), delete, mkdir, rename, move and copy
|
||||
@ -95,8 +78,8 @@ English | [中文](./README_cn.md) | [日本語](./README_ja.md) | [Contributing
|
||||
|
||||
## Document
|
||||
|
||||
- https://docs.oplist.org
|
||||
- https://docs.openlist.team
|
||||
- 📘 [Docs & Install Guide](https://docs.oplist.org)
|
||||
- 📚 [Backup Docs Site](https://docs.openlist.team)
|
||||
|
||||
## Demo
|
||||
|
||||
@ -106,24 +89,32 @@ N/A (to be rebuilt)
|
||||
|
||||
Please refer to [*Discussions*](https://github.com/OpenListTeam/OpenList/discussions) for raising general questions, ***Issues* is for bug reports and feature requests only.**
|
||||
|
||||
## License
|
||||
|
||||
The `OpenList` is open-source software licensed under the [AGPL-3.0](https://www.gnu.org/licenses/agpl-3.0.txt) license.
|
||||
|
||||
## Disclaimer
|
||||
|
||||
- This project is a free and open-source software designed to facilitate file sharing via net disks, primarily intended to support the downloading and learning of the Go programming language.
|
||||
- Please comply with all applicable laws and regulations when using this software. Any form of misuse is strictly prohibited.
|
||||
- The software is based on official SDKs or APIs without any modification, disruption, or interference with their behavior.
|
||||
- It only performs HTTP 302 redirects or traffic forwarding, and does not intercept, store, or tamper with any user data.
|
||||
- This project is not affiliated with any official platform or service provider.
|
||||
- The software is provided "as is", without any warranties of any kind, either express or implied, including but not limited to warranties of merchantability or fitness for a particular purpose.
|
||||
- The maintainers are not liable for any direct or indirect damages arising from the use of, or inability to use, this software.
|
||||
- You are solely responsible for any risks associated with using this software, including but not limited to account bans or download speed limitations.
|
||||
- This project is licensed under the [AGPL-3.0](https://www.gnu.org/licenses/agpl-3.0.txt) License. Please see the [LICENSE](./LICENSE) file for details.
|
||||
|
||||
## Contact Us
|
||||
|
||||
- [@GitHub](https://github.com/OpenListTeam)
|
||||
- [Telegram Group](https://t.me/OpenListTeam)
|
||||
- [Telegram Channel](https://t.me/OpenListOfficial)
|
||||
|
||||
## Contributors
|
||||
|
||||
We sincerely thank the author [Xhofe](https://github.com/Xhofe) of the original project [AlistGo/alist](https://github.com/AlistGo/alist) and all other contributors.
|
||||
|
||||
Thanks goes to these wonderful people:
|
||||
|
||||
[](https://github.com/OpenListTeam/OpenList/graphs/contributors)
|
||||
|
||||
## License
|
||||
|
||||
The `OpenList` is open-source software licensed under the AGPL-3.0 license.
|
||||
|
||||
## Disclaimer
|
||||
|
||||
- This program is a free and open source project. It is designed to share files on the network disk, which is convenient for downloading and learning Golang. Please abide by relevant laws and regulations when using it, and do not abuse it;
|
||||
- This program is implemented by calling the official sdk/interface, without destroying the official interface behavior;
|
||||
- This program only does 302 redirect/traffic forwarding, and does not intercept, store, or tamper with any user data;
|
||||
- Before using this program, you should understand and bear the corresponding risks, including but not limited to account ban, download speed limit, etc., which is none of this program's business;
|
||||
- If there is any infringement, please contact [OpenListTeam](https://github.com/OpenListTeam), and it will be dealt with in time.
|
||||
|
||||
---
|
||||
|
||||
> [@GitHub](https://github.com/OpenListTeam) · [Telegram Group](https://t.me/OpenListTeam) · [Telegram Channel](https://t.me/OpenListOfficial)
|
||||
|
179
README_cn.md
179
README_cn.md
@ -1,127 +1,120 @@
|
||||
<div align="center">
|
||||
<img width="100px" alt="logo" src="https://raw.githubusercontent.com/OpenListTeam/Logo/main/logo.svg"/></a>
|
||||
<p><em>🗂一个支持多存储的文件列表程序,使用 Gin 和 SolidJS,基于 AList 项目 fork 开发</em></p>
|
||||
<div>
|
||||
<a href="https://goreportcard.com/report/github.com/OpenListTeam/OpenList/v3">
|
||||
<img src="https://goreportcard.com/badge/github.com/OpenListTeam/OpenList/v3" alt="latest version" />
|
||||
</a>
|
||||
<a href="https://github.com/OpenListTeam/OpenList/blob/main/LICENSE">
|
||||
<img src="https://img.shields.io/github/license/OpenListTeam/OpenList" alt="License" />
|
||||
</a>
|
||||
<a href="https://github.com/OpenListTeam/OpenList/actions?query=workflow%3ABuild">
|
||||
<img src="https://img.shields.io/github/actions/workflow/status/OpenListTeam/OpenList/build.yml?branch=main" alt="Build status" />
|
||||
</a>
|
||||
<a href="https://github.com/OpenListTeam/OpenList/releases">
|
||||
<img src="https://img.shields.io/github/release/OpenListTeam/OpenList" alt="latest version" />
|
||||
</a>
|
||||
</div>
|
||||
<div>
|
||||
<a href="https://github.com/OpenListTeam/OpenList/discussions">
|
||||
<img src="https://img.shields.io/github/discussions/OpenListTeam/OpenList?color=%23ED8936" alt="discussions" />
|
||||
</a>
|
||||
<a href="https://github.com/OpenListTeam/OpenList/releases">
|
||||
<img src="https://img.shields.io/github/downloads/OpenListTeam/OpenList/total?color=%239F7AEA&logo=github" alt="Downloads" />
|
||||
</a>
|
||||
</div>
|
||||
<img style="width: 128px; height: 128px;" src="https://raw.githubusercontent.com/OpenListTeam/Logo/main/logo.svg" alt="logo" />
|
||||
|
||||
<p><em>OpenList 是一个有韧性、长期治理、社区驱动的 AList 分支,旨在防御基于信任的开源攻击。</em></p>
|
||||
|
||||
<img src="https://goreportcard.com/badge/github.com/OpenListTeam/OpenList/v3" alt="latest version" />
|
||||
<a href="https://github.com/OpenListTeam/OpenList/blob/main/LICENSE"><img src="https://img.shields.io/github/license/OpenListTeam/OpenList" alt="License" /></a>
|
||||
<a href="https://github.com/OpenListTeam/OpenList/actions?query=workflow%3ABuild"><img src="https://img.shields.io/github/actions/workflow/status/OpenListTeam/OpenList/build.yml?branch=main" alt="Build status" /></a>
|
||||
<a href="https://github.com/OpenListTeam/OpenList/releases"><img src="https://img.shields.io/github/release/OpenListTeam/OpenList" alt="latest version" /></a>
|
||||
|
||||
<a href="https://github.com/OpenListTeam/OpenList/discussions"><img src="https://img.shields.io/github/discussions/OpenListTeam/OpenList?color=%23ED8936" alt="discussions" /></a>
|
||||
<a href="https://github.com/OpenListTeam/OpenList/releases"><img src="https://img.shields.io/github/downloads/OpenListTeam/OpenList/total?color=%239F7AEA&logo=github" alt="Downloads" /></a>
|
||||
</div>
|
||||
|
||||
---
|
||||
|
||||
> [!IMPORTANT]
|
||||
>
|
||||
> 一个更可信、可持续的 AList 开源替代方案,防范未来可能的闭源、黑箱或不可信变更。
|
||||
>
|
||||
> 我们诚挚地感谢原项目 [AlistGo/alist](https://github.com/AlistGo/alist) 的作者 [Xhofe](https://github.com/Xhofe) 以及其他所有贡献者。
|
||||
>
|
||||
> 本 Fork 尚未稳定, 具体迁移进度可在 [OpenList 迁移工作总结](https://github.com/OpenListTeam/OpenList/issues/6) 中查看。
|
||||
- [English](./README.md) | 中文 | [日本語](./README_ja.md) | [Dutch](./README_nl.md)
|
||||
|
||||
[English](./README.md) | 中文 | [日本語](./README_ja.md) | [Contributing](./CONTRIBUTING.md) | [CODE OF CONDUCT](./CODE_OF_CONDUCT.md)
|
||||
- [贡献指南](./CONTRIBUTING.md)
|
||||
- [行为准则](./CODE_OF_CONDUCT.md)
|
||||
- [许可证](./LICENSE)
|
||||
|
||||
## 功能
|
||||
|
||||
- [x] 多种存储
|
||||
- [x] 本地存储
|
||||
- [x] [阿里云盘](https://www.alipan.com/)
|
||||
- [x] OneDrive / Sharepoint([国际版](https://www.office.com/), [世纪互联](https://portal.partner.microsoftonline.cn),de,us)
|
||||
- [x] [天翼云盘](https://cloud.189.cn) (个人云, 家庭云)
|
||||
- [x] [GoogleDrive](https://drive.google.com/)
|
||||
- [x] [123云盘](https://www.123pan.com/)
|
||||
- [x] FTP / SFTP
|
||||
- [x] [PikPak](https://www.mypikpak.com/)
|
||||
- [x] [S3](https://aws.amazon.com/cn/s3/)
|
||||
- [x] [Seafile](https://seafile.com/)
|
||||
- [x] [又拍云对象存储](https://www.upyun.com/products/file-storage)
|
||||
- [x] WebDav(支持无API的OneDrive/SharePoint)
|
||||
- [x] Teambition([中国](https://www.teambition.com/ ),[国际](https://us.teambition.com/ ))
|
||||
- [x] [分秒帧](https://www.mediatrack.cn/)
|
||||
- [x] [和彩云](https://yun.139.com/) (个人云, 家庭云,共享群组)
|
||||
- [x] [Yandex.Disk](https://disk.yandex.com/)
|
||||
- [x] [百度网盘](http://pan.baidu.com/)
|
||||
- [x] [UC网盘](https://drive.uc.cn)
|
||||
- [x] [夸克网盘](https://pan.quark.cn)
|
||||
- [x] [迅雷网盘](https://pan.xunlei.com)
|
||||
- [x] [蓝奏云](https://www.lanzou.com/)
|
||||
- [x] [蓝奏云优享版](https://www.ilanzou.com/)
|
||||
- [x] [阿里云盘分享](https://www.alipan.com/)
|
||||
- [x] [谷歌相册](https://photos.google.com/)
|
||||
- [x] [Mega.nz](https://mega.nz)
|
||||
- [x] [一刻相册](https://photo.baidu.com/)
|
||||
- [x] SMB
|
||||
- [x] [115](https://115.com/)
|
||||
- [X] Cloudreve
|
||||
- [x] [Dropbox](https://www.dropbox.com/)
|
||||
- [x] [飞机盘](https://www.feijipan.com/)
|
||||
- [x] [多吉云](https://www.dogecloud.com/product/oss)
|
||||
- [x] 本地存储
|
||||
- [x] [阿里云盘](https://www.alipan.com)
|
||||
- [x] OneDrive / Sharepoint ([国际版](https://www.microsoft.com/en-us/microsoft-365/onedrive/online-cloud-storage), [中国](https://portal.partner.microsoftonline.cn), DE, US)
|
||||
- [x] [天翼云盘](https://cloud.189.cn)(个人、家庭)
|
||||
- [x] [GoogleDrive](https://drive.google.com)
|
||||
- [x] [123云盘](https://www.123pan.com)
|
||||
- [x] [FTP / SFTP](https://en.wikipedia.org/wiki/File_Transfer_Protocol)
|
||||
- [x] [PikPak](https://www.mypikpak.com)
|
||||
- [x] [S3](https://aws.amazon.com/s3)
|
||||
- [x] [Seafile](https://seafile.com)
|
||||
- [x] [又拍云对象存储](https://www.upyun.com/products/file-storage)
|
||||
- [x] [WebDAV](https://en.wikipedia.org/wiki/WebDAV)
|
||||
- [x] Teambition([中国](https://www.teambition.com), [国际](https://us.teambition.com))
|
||||
- [x] [分秒帧](https://www.mediatrack.cn)
|
||||
- [x] [和彩云](https://yun.139.com)(个人、家庭、群组)
|
||||
- [x] [YandexDisk](https://disk.yandex.com)
|
||||
- [x] [百度网盘](http://pan.baidu.com)
|
||||
- [x] [Terabox](https://www.terabox.com/main)
|
||||
- [x] [UC网盘](https://drive.uc.cn)
|
||||
- [x] [夸克网盘](https://pan.quark.cn)
|
||||
- [x] [迅雷网盘](https://pan.xunlei.com)
|
||||
- [x] [蓝奏云](https://www.lanzou.com)
|
||||
- [x] [蓝奏云优享版](https://www.ilanzou.com)
|
||||
- [x] [阿里云盘分享](https://www.alipan.com)
|
||||
- [x] [Google 相册](https://photos.google.com)
|
||||
- [x] [Mega.nz](https://mega.nz)
|
||||
- [x] [百度相册](https://photo.baidu.com)
|
||||
- [x] [SMB](https://en.wikipedia.org/wiki/Server_Message_Block)
|
||||
- [x] [115](https://115.com)
|
||||
- [x] [Cloudreve](https://cloudreve.org)
|
||||
- [x] [Dropbox](https://www.dropbox.com)
|
||||
- [x] [飞机盘](https://www.feijipan.com)
|
||||
- [x] [多吉云](https://www.dogecloud.com/product/oss)
|
||||
- [x] [Azure Blob Storage](https://azure.microsoft.com/products/storage/blobs)
|
||||
- [x] 部署方便,开箱即用
|
||||
- [x] 文件预览(PDF、markdown、代码、纯文本……)
|
||||
- [x] 画廊模式下的图像预览
|
||||
- [x] 文件预览(PDF、markdown、代码、纯文本等)
|
||||
- [x] 画廊模式下的图片预览
|
||||
- [x] 视频和音频预览,支持歌词和字幕
|
||||
- [x] Office 文档预览(docx、pptx、xlsx、...)
|
||||
- [x] Office 文档预览(docx、pptx、xlsx 等)
|
||||
- [x] `README.md` 预览渲染
|
||||
- [x] 文件永久链接复制和直接文件下载
|
||||
- [x] 黑暗模式
|
||||
- [x] 国际化
|
||||
- [x] 受保护的路由(密码保护和身份验证)
|
||||
- [x] WebDav (详细文档待补充)
|
||||
- [ ] Docker 部署(重建中)
|
||||
- [x] Cloudflare workers 中转
|
||||
- [x] 受保护的路由(密码保护和认证)
|
||||
- [x] WebDAV
|
||||
- [x] Docker 部署
|
||||
- [x] Cloudflare Workers 代理
|
||||
- [x] 文件/文件夹打包下载
|
||||
- [x] 网页上传(可以允许访客上传),删除,新建文件夹,重命名,移动,复制
|
||||
- [x] 网页上传(可允许访客上传)、删除、新建文件夹、重命名、移动和复制
|
||||
- [x] 离线下载
|
||||
- [x] 跨存储复制文件
|
||||
- [x] 单线程下载/串流的多线程下载加速
|
||||
- [x] 单文件多线程下载/流式加速
|
||||
|
||||
## 文档
|
||||
|
||||
- https://docs.oplist.org
|
||||
- https://docs.openlist.team
|
||||
- 📘 [文档与安装指南](https://docs.oplist.org)
|
||||
- 📚 [备用文档站点](https://docs.openlist.team)
|
||||
|
||||
## Demo
|
||||
## 演示
|
||||
|
||||
N/A(重建中)
|
||||
N/A(待重建)
|
||||
|
||||
## 讨论
|
||||
|
||||
一般问题请到 [*Discussions*](https://github.com/OpenListTeam/OpenList/discussions) 讨论,***Issues* 仅针对错误报告和功能请求。**
|
||||
如有一般性问题请前往 [*Discussions*](https://github.com/OpenListTeam/OpenList/discussions) 讨论区,***Issues* 仅用于错误报告和功能请求。**
|
||||
|
||||
## 贡献者
|
||||
## 许可证
|
||||
|
||||
感谢这些开源作者们:
|
||||
|
||||
[](https://github.com/OpenListTeam/OpenList/graphs/contributors)
|
||||
|
||||
## 许可
|
||||
|
||||
`OpenList` 是按 AGPL-3.0 许可证许可的开源软件。
|
||||
`OpenList` 是基于 [AGPL-3.0](https://www.gnu.org/licenses/agpl-3.0.txt) 许可证的开源软件。
|
||||
|
||||
## 免责声明
|
||||
|
||||
- 本程序为免费开源项目,旨在分享网盘文件,方便下载以及学习golang,使用时请遵守相关法律法规,请勿滥用;
|
||||
- 本程序通过调用官方sdk/接口实现,无破坏官方接口行为;
|
||||
- 本程序仅做302重定向/流量转发,不拦截、存储、篡改任何用户数据;
|
||||
- 在使用本程序之前,你应了解并承担相应的风险,包括但不限于账号被ban,下载限速等,与本程序无关;
|
||||
- 如有侵权,请联系[OpenListTeam](https://github.com/OpenListTeam),团队会及时处理。
|
||||
- 本项目为免费开源软件,旨在通过网盘便捷分享文件,主要用于 Go 语言的下载与学习。
|
||||
- 使用本软件时请遵守相关法律法规,严禁任何形式的滥用。
|
||||
- 本软件基于官方 SDK 或 API 实现,未对其行为进行任何修改、破坏或干扰。
|
||||
- 仅进行 HTTP 302 跳转或流量转发,不拦截、存储或篡改任何用户数据。
|
||||
- 本项目与任何官方平台或服务提供商无关。
|
||||
- 本软件按“原样”提供,不附带任何明示或暗示的担保,包括但不限于适销性或特定用途的适用性。
|
||||
- 维护者不对因使用或无法使用本软件而导致的任何直接或间接损失负责。
|
||||
- 您需自行承担使用本软件的所有风险,包括但不限于账号被封、下载限速等。
|
||||
- 本项目遵循 [AGPL-3.0](https://www.gnu.org/licenses/agpl-3.0.txt) 许可证,详情请参见 [LICENSE](./LICENSE) 文件。
|
||||
|
||||
---
|
||||
## 联系我们
|
||||
|
||||
> [@GitHub](https://github.com/OpenListTeam) · [Telegram 交流群](https://t.me/OpenListTeam) · [Telegram 频道](https://t.me/OpenListOfficial)
|
||||
- [@GitHub](https://github.com/OpenListTeam)
|
||||
- [Telegram 交流群](https://t.me/OpenListTeam)
|
||||
- [Telegram 频道](https://t.me/OpenListOfficial)
|
||||
|
||||
## 贡献者
|
||||
|
||||
我们衷心感谢原项目 [AlistGo/alist](https://github.com/AlistGo/alist) 的作者 [Xhofe](https://github.com/Xhofe) 及所有其他贡献者。
|
||||
|
||||
感谢这些优秀的人:
|
||||
|
||||
[](https://github.com/OpenListTeam/OpenList/graphs/contributors)
|
||||
|
188
README_ja.md
188
README_ja.md
@ -1,128 +1,120 @@
|
||||
<div align="center">
|
||||
<img width="100px" alt="logo" src="https://raw.githubusercontent.com/OpenListTeam/Logo/main/logo.svg"/></a>
|
||||
<p><em>🗂複数のストレージをサポートするファイルリストプログラムで、Gin と SolidJS を使用し、AList プロジェクトをフォークして開発されました。</em></p>
|
||||
<div>
|
||||
<a href="https://goreportcard.com/report/github.com/OpenListTeam/OpenList/v3">
|
||||
<img src="https://goreportcard.com/badge/github.com/OpenListTeam/OpenList/v3" alt="latest version" />
|
||||
</a>
|
||||
<a href="https://github.com/OpenListTeam/OpenList/blob/main/LICENSE">
|
||||
<img src="https://img.shields.io/github/license/OpenListTeam/OpenList" alt="License" />
|
||||
</a>
|
||||
<a href="https://github.com/OpenListTeam/OpenList/actions?query=workflow%3ABuild">
|
||||
<img src="https://img.shields.io/github/actions/workflow/status/OpenListTeam/OpenList/build.yml?branch=main" alt="Build status" />
|
||||
</a>
|
||||
<a href="https://github.com/OpenListTeam/OpenList/releases">
|
||||
<img src="https://img.shields.io/github/release/OpenListTeam/OpenList" alt="latest version" />
|
||||
</a>
|
||||
</div>
|
||||
<div>
|
||||
<a href="https://github.com/OpenListTeam/OpenList/discussions">
|
||||
<img src="https://img.shields.io/github/discussions/OpenListTeam/OpenList?color=%23ED8936" alt="discussions" />
|
||||
</a>
|
||||
<a href="https://github.com/OpenListTeam/OpenList/releases">
|
||||
<img src="https://img.shields.io/github/downloads/OpenListTeam/OpenList/total?color=%239F7AEA&logo=github" alt="Downloads" />
|
||||
</a>
|
||||
</div>
|
||||
<img style="width: 128px; height: 128px;" src="https://raw.githubusercontent.com/OpenListTeam/Logo/main/logo.svg" alt="logo" />
|
||||
|
||||
<p><em>OpenList は、信頼ベースの攻撃からオープンソースを守るために構築された、レジリエントで長期ガバナンス、コミュニティ主導の AList フォークです。</em></p>
|
||||
|
||||
<img src="https://goreportcard.com/badge/github.com/OpenListTeam/OpenList/v3" alt="latest version" />
|
||||
<a href="https://github.com/OpenListTeam/OpenList/blob/main/LICENSE"><img src="https://img.shields.io/github/license/OpenListTeam/OpenList" alt="License" /></a>
|
||||
<a href="https://github.com/OpenListTeam/OpenList/actions?query=workflow%3ABuild"><img src="https://img.shields.io/github/actions/workflow/status/OpenListTeam/OpenList/build.yml?branch=main" alt="Build status" /></a>
|
||||
<a href="https://github.com/OpenListTeam/OpenList/releases"><img src="https://img.shields.io/github/release/OpenListTeam/OpenList" alt="latest version" /></a>
|
||||
|
||||
<a href="https://github.com/OpenListTeam/OpenList/discussions"><img src="https://img.shields.io/github/discussions/OpenListTeam/OpenList?color=%23ED8936" alt="discussions" /></a>
|
||||
<a href="https://github.com/OpenListTeam/OpenList/releases"><img src="https://img.shields.io/github/downloads/OpenListTeam/OpenList/total?color=%239F7AEA&logo=github" alt="Downloads" /></a>
|
||||
</div>
|
||||
|
||||
---
|
||||
|
||||
> [!IMPORTANT]
|
||||
>
|
||||
> より信頼性が高く、持続可能なAListのオープンソース代替案で、将来起こりうる非公開化、ブラックボックス化、または信頼できない変更から保護します。
|
||||
>
|
||||
> 元のプロジェクト [AlistGo/alist](https://github.com/AlistGo/alist) の作者 [Xhofe](https://github.com/Xhofe) および他のすべての貢献者に心から感謝いたします。
|
||||
>
|
||||
> このForkはまだ安定していません。具体的な移行の進捗状況は [OpenList 移行作業のまとめ](https://github.com/OpenListTeam/OpenList/issues/6) でご確認いただけます。
|
||||
- [English](./README.md) | [中文](./README_cn.md) | 日本語 | [Dutch](./README_nl.md)
|
||||
|
||||
[English](./README.md) | [中文](./README_cn.md) | 日本語 | [Contributing](./CONTRIBUTING.md) | [CODE OF CONDUCT](./CODE_OF_CONDUCT.md)
|
||||
- [コントリビュート](./CONTRIBUTING.md)
|
||||
- [行動規範](./CODE_OF_CONDUCT.md)
|
||||
- [ライセンス](./LICENSE)
|
||||
|
||||
## 特徴
|
||||
|
||||
- [x] マルチストレージ
|
||||
- [x] ローカルストレージ
|
||||
- [x] [Aliyundrive](https://www.alipan.com/)
|
||||
- [x] OneDrive / Sharepoint ([グローバル](https://www.office.com/), [cn](https://portal.partner.microsoftonline.cn),de,us)
|
||||
- [x] [189cloud](https://cloud.189.cn) (Personal, Family)
|
||||
- [x] [GoogleDrive](https://drive.google.com/)
|
||||
- [x] [123pan](https://www.123pan.com/)
|
||||
- [x] FTP / SFTP
|
||||
- [x] [PikPak](https://www.mypikpak.com/)
|
||||
- [x] [S3](https://aws.amazon.com/s3/)
|
||||
- [x] [Seafile](https://seafile.com/)
|
||||
- [x] [UPYUN Storage Service](https://www.upyun.com/products/file-storage)
|
||||
- [x] WebDav(Support OneDrive/SharePoint without API)
|
||||
- [x] Teambition([China](https://www.teambition.com/ ),[International](https://us.teambition.com/ ))
|
||||
- [x] [Mediatrack](https://www.mediatrack.cn/)
|
||||
- [x] [139yun](https://yun.139.com/) (Personal, Family, Group)
|
||||
- [x] [YandexDisk](https://disk.yandex.com/)
|
||||
- [x] [BaiduNetdisk](http://pan.baidu.com/)
|
||||
- [x] [Terabox](https://www.terabox.com/main)
|
||||
- [x] [UC](https://drive.uc.cn)
|
||||
- [x] [Quark](https://pan.quark.cn)
|
||||
- [x] [Thunder](https://pan.xunlei.com)
|
||||
- [x] [Lanzou](https://www.lanzou.com/)
|
||||
- [x] [ILanzou](https://www.ilanzou.com/)
|
||||
- [x] [Aliyundrive share](https://www.alipan.com/)
|
||||
- [x] [Google photo](https://photos.google.com/)
|
||||
- [x] [Mega.nz](https://mega.nz)
|
||||
- [x] [Baidu photo](https://photo.baidu.com/)
|
||||
- [x] SMB
|
||||
- [x] [115](https://115.com/)
|
||||
- [X] Cloudreve
|
||||
- [x] [Dropbox](https://www.dropbox.com/)
|
||||
- [x] [FeijiPan](https://www.feijipan.com/)
|
||||
- [x] [dogecloud](https://www.dogecloud.com/product/oss)
|
||||
- [x] デプロイが簡単で、すぐに使える
|
||||
- [x] ファイルプレビュー (PDF, マークダウン, コード, プレーンテキスト, ...)
|
||||
- [x] 複数ストレージ
|
||||
- [x] ローカルストレージ
|
||||
- [x] [Aliyundrive](https://www.alipan.com)
|
||||
- [x] OneDrive / Sharepoint ([グローバル](https://www.microsoft.com/en-us/microsoft-365/onedrive/online-cloud-storage), [中国](https://portal.partner.microsoftonline.cn), DE, US)
|
||||
- [x] [189cloud](https://cloud.189.cn)(個人、家族)
|
||||
- [x] [GoogleDrive](https://drive.google.com)
|
||||
- [x] [123pan](https://www.123pan.com)
|
||||
- [x] [FTP / SFTP](https://en.wikipedia.org/wiki/File_Transfer_Protocol)
|
||||
- [x] [PikPak](https://www.mypikpak.com)
|
||||
- [x] [S3](https://aws.amazon.com/s3)
|
||||
- [x] [Seafile](https://seafile.com)
|
||||
- [x] [UPYUN Storage Service](https://www.upyun.com/products/file-storage)
|
||||
- [x] [WebDAV](https://en.wikipedia.org/wiki/WebDAV)
|
||||
- [x] Teambition([中国](https://www.teambition.com), [国際](https://us.teambition.com))
|
||||
- [x] [Mediatrack](https://www.mediatrack.cn)
|
||||
- [x] [139yun](https://yun.139.com)(個人、家族、グループ)
|
||||
- [x] [YandexDisk](https://disk.yandex.com)
|
||||
- [x] [BaiduNetdisk](http://pan.baidu.com)
|
||||
- [x] [Terabox](https://www.terabox.com/main)
|
||||
- [x] [UC](https://drive.uc.cn)
|
||||
- [x] [Quark](https://pan.quark.cn)
|
||||
- [x] [Thunder](https://pan.xunlei.com)
|
||||
- [x] [Lanzou](https://www.lanzou.com)
|
||||
- [x] [ILanzou](https://www.ilanzou.com)
|
||||
- [x] [Aliyundrive share](https://www.alipan.com)
|
||||
- [x] [Google photo](https://photos.google.com)
|
||||
- [x] [Mega.nz](https://mega.nz)
|
||||
- [x] [Baidu photo](https://photo.baidu.com)
|
||||
- [x] [SMB](https://en.wikipedia.org/wiki/Server_Message_Block)
|
||||
- [x] [115](https://115.com)
|
||||
- [x] [Cloudreve](https://cloudreve.org)
|
||||
- [x] [Dropbox](https://www.dropbox.com)
|
||||
- [x] [FeijiPan](https://www.feijipan.com)
|
||||
- [x] [dogecloud](https://www.dogecloud.com/product/oss)
|
||||
- [x] [Azure Blob Storage](https://azure.microsoft.com/products/storage/blobs)
|
||||
- [x] 簡単にデプロイでき、すぐに使える
|
||||
- [x] ファイルプレビュー(PDF、markdown、コード、テキストなど)
|
||||
- [x] ギャラリーモードでの画像プレビュー
|
||||
- [x] ビデオとオーディオのプレビュー、歌詞と字幕のサポート
|
||||
- [x] Office ドキュメントのプレビュー (docx, pptx, xlsx, ...)
|
||||
- [x] `README.md` のプレビューレンダリング
|
||||
- [x] ビデオ・オーディオプレビュー、歌詞・字幕対応
|
||||
- [x] Officeドキュメントプレビュー(docx、pptx、xlsxなど)
|
||||
- [x] `README.md` プレビュー表示
|
||||
- [x] ファイルのパーマリンクコピーと直接ダウンロード
|
||||
- [x] ダークモード
|
||||
- [x] 国際化
|
||||
- [x] 保護されたルート (パスワード保護と認証)
|
||||
- [x] WebDav(詳細なドキュメントは今後追加予定)
|
||||
- [ ] Docker デプロイ(再構築中)
|
||||
- [x] Cloudflare ワーカープロキシ
|
||||
- [x] ファイル/フォルダパッケージのダウンロード
|
||||
- [x] ウェブアップロード(訪問者にアップロードを許可できる), 削除, mkdir, 名前変更, 移動, コピー
|
||||
- [x] 国際化対応
|
||||
- [x] 保護されたルート(パスワード保護と認証)
|
||||
- [x] WebDAV
|
||||
- [x] Dockerデプロイ
|
||||
- [x] Cloudflare Workersプロキシ
|
||||
- [x] ファイル/フォルダのパッケージダウンロード
|
||||
- [x] Webアップロード(訪問者のアップロード許可可)、削除、フォルダ作成、リネーム、移動、コピー
|
||||
- [x] オフラインダウンロード
|
||||
- [x] 二つのストレージ間でファイルをコピー
|
||||
- [x] シングルスレッドのダウンロード/ストリーム向けのマルチスレッド ダウンロード アクセラレーション
|
||||
- [x] ストレージ間のファイルコピー
|
||||
- [x] 単一ファイルのマルチスレッドダウンロード/ストリーム加速
|
||||
|
||||
## ドキュメント
|
||||
|
||||
- https://docs.oplist.org
|
||||
- https://docs.openlist.team
|
||||
- 📘 [ドキュメント・インストールガイド](https://docs.oplist.org)
|
||||
- 📚 [バックアップドキュメントサイト](https://docs.openlist.team)
|
||||
|
||||
## デモ
|
||||
|
||||
N/A (再構築中)
|
||||
N/A(再構築中)
|
||||
|
||||
## ディスカッション
|
||||
|
||||
一般的なご質問は [*Discussions*](https://github.com/OpenListTeam/OpenList/discussions) をご利用ください。***Issues* はバグ報告と機能リクエストに限定されています。**
|
||||
|
||||
## コントリビューター
|
||||
|
||||
これらの素晴らしい人々に感謝します:
|
||||
|
||||
[](https://github.com/OpenListTeam/OpenList/graphs/contributors)
|
||||
一般的な質問は [*Discussions*](https://github.com/OpenListTeam/OpenList/discussions) をご利用ください。***Issues* はバグ報告と機能リクエスト専用です。**
|
||||
|
||||
## ライセンス
|
||||
|
||||
「`OpenList`」は AGPL-3.0 ライセンスの下で公開されているオープンソースソフトウェアです。
|
||||
「OpenList」は [AGPL-3.0](https://www.gnu.org/licenses/agpl-3.0.txt) ライセンスの下で公開されているオープンソースソフトウェアです。
|
||||
|
||||
## 免責事項
|
||||
|
||||
- このプログラムはフリーでオープンソースのプロジェクトです。ネットワークディスク上でファイルを共有するように設計されており、golang のダウンロードや学習に便利です。利用にあたっては関連法規を遵守し、悪用しないようお願いします;
|
||||
- このプログラムは、公式インターフェースの動作を破壊することなく、公式 sdk/インターフェースを呼び出すことで実装されています;
|
||||
- このプログラムは、302リダイレクト/トラフィック転送のみを行い、いかなるユーザーデータも傍受、保存、改ざんしません;
|
||||
- このプログラムを使用する前に、アカウントの禁止、ダウンロード速度の制限など、対応するリスクを理解し、負担する必要があります;
|
||||
- 権利侵害がある場合は、[OpenListTeam](https://github.com/OpenListTeam) までご連絡ください。チームが迅速に対応いたします。
|
||||
- 本プロジェクトは無料のオープンソースソフトウェアであり、ネットワークディスクを通じたファイル共有を容易にすることを目的とし、主に Go 言語のダウンロードと学習をサポートします。
|
||||
- 本ソフトウェアの利用にあたっては、関連する法令を遵守し、不正利用を固く禁じます。
|
||||
- 本ソフトウェアは公式 SDK または API に基づいており、その動作を一切改変・破壊・妨害しません。
|
||||
- 302 リダイレクトまたはトラフィック転送のみを行い、ユーザーデータの傍受・保存・改ざんは一切行いません。
|
||||
- 本プロジェクトは、いかなる公式プラットフォームやサービスプロバイダーとも関係ありません。
|
||||
- 本ソフトウェアは「現状有姿」で提供されており、商品性や特定目的への適合性を含むいかなる保証もありません。
|
||||
- 本ソフトウェアの使用または使用不能によるいかなる直接的・間接的損害についても、メンテナは責任を負いません。
|
||||
- 本ソフトウェアの利用に伴うすべてのリスク(アカウントの凍結やダウンロード速度制限などを含む)は、利用者自身が負うものとします。
|
||||
- 本プロジェクトは [AGPL-3.0](https://www.gnu.org/licenses/agpl-3.0.txt) ライセンスに従います。詳細は [LICENSE](./LICENSE) ファイルをご覧ください。
|
||||
|
||||
---
|
||||
## お問い合わせ
|
||||
|
||||
> [@GitHub](https://github.com/OpenListTeam) · [Telegram Group](https://t.me/OpenListTeam) · [Telegram Channel](https://t.me/OpenListOfficial)
|
||||
- [@GitHub](https://github.com/OpenListTeam)
|
||||
- [Telegram グループ](https://t.me/OpenListTeam)
|
||||
- [Telegram チャンネル](https://t.me/OpenListOfficial)
|
||||
|
||||
## コントリビューター
|
||||
|
||||
オリジナルプロジェクト [AlistGo/alist](https://github.com/AlistGo/alist) の作者 [Xhofe](https://github.com/Xhofe) およびその他すべての貢献者に心より感謝いたします。
|
||||
|
||||
素晴らしい皆様に感謝します:
|
||||
|
||||
[](https://github.com/OpenListTeam/OpenList/graphs/contributors)
|
||||
|
120
README_nl.md
Normal file
120
README_nl.md
Normal file
@ -0,0 +1,120 @@
|
||||
<div align="center">
|
||||
<img style="width: 128px; height: 128px;" src="https://raw.githubusercontent.com/OpenListTeam/Logo/main/logo.svg" alt="logo" />
|
||||
|
||||
<p><em>OpenList is een veerkrachtige, langetermijn, door de gemeenschap geleide fork van AList — gebouwd om open source te beschermen tegen op vertrouwen gebaseerde aanvallen.</em></p>
|
||||
|
||||
<img src="https://goreportcard.com/badge/github.com/OpenListTeam/OpenList/v3" alt="latest version" />
|
||||
<a href="https://github.com/OpenListTeam/OpenList/blob/main/LICENSE"><img src="https://img.shields.io/github/license/OpenListTeam/OpenList" alt="License" /></a>
|
||||
<a href="https://github.com/OpenListTeam/OpenList/actions?query=workflow%3ABuild"><img src="https://img.shields.io/github/actions/workflow/status/OpenListTeam/OpenList/build.yml?branch=main" alt="Build status" /></a>
|
||||
<a href="https://github.com/OpenListTeam/OpenList/releases"><img src="https://img.shields.io/github/release/OpenListTeam/OpenList" alt="latest version" /></a>
|
||||
|
||||
<a href="https://github.com/OpenListTeam/OpenList/discussions"><img src="https://img.shields.io/github/discussions/OpenListTeam/OpenList?color=%23ED8936" alt="discussions" /></a>
|
||||
<a href="https://github.com/OpenListTeam/OpenList/releases"><img src="https://img.shields.io/github/downloads/OpenListTeam/OpenList/total?color=%239F7AEA&logo=github" alt="Downloads" /></a>
|
||||
</div>
|
||||
|
||||
---
|
||||
|
||||
- [English](./README.md) | [中文](./README_cn.md) | [日本語](./README_ja.md) | Dutch
|
||||
|
||||
- [Bijdragen](./CONTRIBUTING.md)
|
||||
- [Gedragscode](./CODE_OF_CONDUCT.md)
|
||||
- [Licentie](./LICENSE)
|
||||
|
||||
## Functies
|
||||
|
||||
- [x] Meerdere opslagmogelijkheden
|
||||
- [x] Lokale opslag
|
||||
- [x] [Aliyundrive](https://www.alipan.com)
|
||||
- [x] OneDrive / Sharepoint ([Global](https://www.microsoft.com/en-us/microsoft-365/onedrive/online-cloud-storage), [CN](https://portal.partner.microsoftonline.cn), DE, US)
|
||||
- [x] [189cloud](https://cloud.189.cn) (Persoonlijk, Familie)
|
||||
- [x] [GoogleDrive](https://drive.google.com)
|
||||
- [x] [123pan](https://www.123pan.com)
|
||||
- [x] [FTP / SFTP](https://en.wikipedia.org/wiki/File_Transfer_Protocol)
|
||||
- [x] [PikPak](https://www.mypikpak.com)
|
||||
- [x] [S3](https://aws.amazon.com/s3)
|
||||
- [x] [Seafile](https://seafile.com)
|
||||
- [x] [UPYUN Storage Service](https://www.upyun.com/products/file-storage)
|
||||
- [x] [WebDAV](https://en.wikipedia.org/wiki/WebDAV)
|
||||
- [x] Teambition([China](https://www.teambition.com), [Internationaal](https://us.teambition.com))
|
||||
- [x] [Mediatrack](https://www.mediatrack.cn)
|
||||
- [x] [139yun](https://yun.139.com) (Persoonlijk, Familie, Groep)
|
||||
- [x] [YandexDisk](https://disk.yandex.com)
|
||||
- [x] [BaiduNetdisk](http://pan.baidu.com)
|
||||
- [x] [Terabox](https://www.terabox.com/main)
|
||||
- [x] [UC](https://drive.uc.cn)
|
||||
- [x] [Quark](https://pan.quark.cn)
|
||||
- [x] [Thunder](https://pan.xunlei.com)
|
||||
- [x] [Lanzou](https://www.lanzou.com)
|
||||
- [x] [ILanzou](https://www.ilanzou.com)
|
||||
- [x] [Aliyundrive share](https://www.alipan.com)
|
||||
- [x] [Google photo](https://photos.google.com)
|
||||
- [x] [Mega.nz](https://mega.nz)
|
||||
- [x] [Baidu photo](https://photo.baidu.com)
|
||||
- [x] [SMB](https://en.wikipedia.org/wiki/Server_Message_Block)
|
||||
- [x] [115](https://115.com)
|
||||
- [x] [Cloudreve](https://cloudreve.org)
|
||||
- [x] [Dropbox](https://www.dropbox.com)
|
||||
- [x] [FeijiPan](https://www.feijipan.com)
|
||||
- [x] [dogecloud](https://www.dogecloud.com/product/oss)
|
||||
- [x] [Azure Blob Storage](https://azure.microsoft.com/products/storage/blobs)
|
||||
- [x] Eenvoudig te implementeren en direct te gebruiken
|
||||
- [x] Bestandsvoorbeeld (PDF, markdown, code, platte tekst, ...)
|
||||
- [x] Afbeeldingsvoorbeeld in galerijweergave
|
||||
- [x] Video- en audiovoorbeeld, ondersteuning voor songteksten en ondertitels
|
||||
- [x] Office-documenten voorbeeld (docx, pptx, xlsx, ...)
|
||||
- [x] `README.md` voorbeeldweergave
|
||||
- [x] Permalink kopiëren en direct downloaden van bestanden
|
||||
- [x] Donkere modus
|
||||
- [x] I18n
|
||||
- [x] Beschermde routes (wachtwoordbeveiliging en authenticatie)
|
||||
- [x] WebDAV
|
||||
- [x] Docker implementatie
|
||||
- [x] Cloudflare Workers proxy
|
||||
- [x] Bestands-/map-pakket download
|
||||
- [x] Webupload (bezoekers kunnen uploaden toestaan), verwijderen, map aanmaken, hernoemen, verplaatsen en kopiëren
|
||||
- [x] Offline download
|
||||
- [x] Bestanden kopiëren tussen twee opslaglocaties
|
||||
- [x] Multi-thread downloadversnelling voor enkelvoudige download/stream
|
||||
|
||||
## Documentatie
|
||||
|
||||
- 📘 [Documentatie & Installatiegids](https://docs.oplist.org)
|
||||
- 📚 [Back-up documentatiesite](https://docs.openlist.team)
|
||||
|
||||
## Demo
|
||||
|
||||
N.v.t. (wordt opnieuw opgebouwd)
|
||||
|
||||
## Discussie
|
||||
|
||||
Stel algemene vragen in [*Discussions*](https://github.com/OpenListTeam/OpenList/discussions), ***Issues* zijn alleen voor bugmeldingen en feature requests.**
|
||||
|
||||
## Licentie
|
||||
|
||||
`OpenList` is open-source software onder de [AGPL-3.0](https://www.gnu.org/licenses/agpl-3.0.txt) licentie.
|
||||
|
||||
## Disclaimer
|
||||
|
||||
- Dit project is gratis en open-source software, ontworpen om het delen van bestanden via netdisks te vergemakkelijken, voornamelijk bedoeld ter ondersteuning van het downloaden en leren van de programmeertaal Go.
|
||||
- Houd u bij het gebruik van deze software aan alle toepasselijke wetten en voorschriften. Elk misbruik is ten strengste verboden.
|
||||
- De software is gebaseerd op officiële SDK's of API's zonder enige wijziging, verstoring of beïnvloeding van hun gedrag.
|
||||
- Het voert alleen HTTP 302-omleidingen of verkeersdoorsturing uit en onderschept, slaat of wijzigt geen gebruikersgegevens.
|
||||
- Dit project is niet gelieerd aan enig officieel platform of dienstverlener.
|
||||
- De software wordt geleverd "zoals deze is", zonder enige vorm van garantie, expliciet of impliciet, inclusief maar niet beperkt tot garanties van verkoopbaarheid of geschiktheid voor een bepaald doel.
|
||||
- De beheerders zijn niet aansprakelijk voor enige directe of indirecte schade die voortvloeit uit het gebruik van of het onvermogen om deze software te gebruiken.
|
||||
- U bent zelf verantwoordelijk voor alle risico's die gepaard gaan met het gebruik van deze software, inclusief maar niet beperkt tot accountblokkades of downloadbeperkingen.
|
||||
- Dit project valt onder de [AGPL-3.0](https://www.gnu.org/licenses/agpl-3.0.txt) licentie. Zie het [LICENSE](./LICENSE) bestand voor details.
|
||||
|
||||
## Contact
|
||||
|
||||
- [@GitHub](https://github.com/OpenListTeam)
|
||||
- [Telegram Groep](https://t.me/OpenListTeam)
|
||||
- [Telegram Kanaal](https://t.me/OpenListOfficial)
|
||||
|
||||
## Bijdragers
|
||||
|
||||
Wij danken de auteur [Xhofe](https://github.com/Xhofe) van het originele project [AlistGo/alist](https://github.com/AlistGo/alist) en alle andere bijdragers.
|
||||
|
||||
Dank aan deze geweldige mensen:
|
||||
|
||||
[](https://github.com/OpenListTeam/OpenList/graphs/contributors)
|
202
build.sh
202
build.sh
@ -4,11 +4,15 @@ builtAt="$(date +'%F %T %z')"
|
||||
gitAuthor="The OpenList Projects Contributors <noreply@openlist.team>"
|
||||
gitCommit=$(git log --pretty=format:"%h" -1)
|
||||
|
||||
githubAuthHeader=""
|
||||
githubAuthValue=""
|
||||
githubAuthArgs=""
|
||||
if [ -n "$GITHUB_TOKEN" ]; then
|
||||
githubAuthHeader="--header"
|
||||
githubAuthValue="Authorization: Bearer $GITHUB_TOKEN"
|
||||
githubAuthArgs="--header \"Authorization: Bearer $GITHUB_TOKEN\""
|
||||
fi
|
||||
|
||||
# Check for lite parameter
|
||||
useLite=false
|
||||
if [[ "$*" == *"lite"* ]]; then
|
||||
useLite=true
|
||||
fi
|
||||
|
||||
if [ "$1" = "dev" ]; then
|
||||
@ -21,31 +25,42 @@ else
|
||||
git tag -d beta || true
|
||||
# Always true if there's no tag
|
||||
version=$(git describe --abbrev=0 --tags 2>/dev/null || echo "v0.0.0")
|
||||
webVersion=$(curl -fsSL --max-time 2 $githubAuthHeader $githubAuthValue "https://api.github.com/repos/OpenListTeam/OpenList-Frontend/releases/latest" | grep "tag_name" | head -n 1 | awk -F ":" '{print $2}' | sed 's/\"//g;s/,//g;s/ //g')
|
||||
webVersion=$(eval "curl -fsSL --max-time 2 $githubAuthArgs \"https://api.github.com/repos/OpenListTeam/OpenList-Frontend/releases/latest\"" | grep "tag_name" | head -n 1 | awk -F ":" '{print $2}' | sed 's/\"//g;s/,//g;s/ //g')
|
||||
fi
|
||||
|
||||
echo "backend version: $version"
|
||||
echo "frontend version: $webVersion"
|
||||
if [ "$useLite" = true ]; then
|
||||
echo "using lite frontend"
|
||||
else
|
||||
echo "using standard frontend"
|
||||
fi
|
||||
|
||||
ldflags="\
|
||||
-w -s \
|
||||
-X 'github.com/OpenListTeam/OpenList/internal/conf.BuiltAt=$builtAt' \
|
||||
-X 'github.com/OpenListTeam/OpenList/internal/conf.GitAuthor=$gitAuthor' \
|
||||
-X 'github.com/OpenListTeam/OpenList/internal/conf.GitCommit=$gitCommit' \
|
||||
-X 'github.com/OpenListTeam/OpenList/internal/conf.Version=$version' \
|
||||
-X 'github.com/OpenListTeam/OpenList/internal/conf.WebVersion=$webVersion' \
|
||||
-X 'github.com/OpenListTeam/OpenList/v4/internal/conf.BuiltAt=$builtAt' \
|
||||
-X 'github.com/OpenListTeam/OpenList/v4/internal/conf.GitAuthor=$gitAuthor' \
|
||||
-X 'github.com/OpenListTeam/OpenList/v4/internal/conf.GitCommit=$gitCommit' \
|
||||
-X 'github.com/OpenListTeam/OpenList/v4/internal/conf.Version=$version' \
|
||||
-X 'github.com/OpenListTeam/OpenList/v4/internal/conf.WebVersion=$webVersion' \
|
||||
"
|
||||
|
||||
FetchWebDev() {
|
||||
pre_release_tag=$(curl -fsSL --max-time 2 $githubAuthHeader $githubAuthValue https://api.github.com/repos/OpenListTeam/OpenList-Frontend/releases | jq -r 'map(select(.prerelease)) | first | .tag_name')
|
||||
pre_release_tag=$(eval "curl -fsSL --max-time 2 $githubAuthArgs https://api.github.com/repos/OpenListTeam/OpenList-Frontend/releases" | jq -r 'map(select(.prerelease)) | first | .tag_name')
|
||||
if [ -z "$pre_release_tag" ] || [ "$pre_release_tag" == "null" ]; then
|
||||
# fall back to latest release
|
||||
pre_release_json=$(curl -fsSL --max-time 2 $githubAuthHeader $githubAuthValue -H "Accept: application/vnd.github.v3+json" "https://api.github.com/repos/OpenListTeam/OpenList-Frontend/releases/latest")
|
||||
pre_release_json=$(eval "curl -fsSL --max-time 2 $githubAuthArgs -H \"Accept: application/vnd.github.v3+json\" \"https://api.github.com/repos/OpenListTeam/OpenList-Frontend/releases/latest\"")
|
||||
else
|
||||
pre_release_json=$(curl -fsSL --max-time 2 $githubAuthHeader $githubAuthValue -H "Accept: application/vnd.github.v3+json" "https://api.github.com/repos/OpenListTeam/OpenList-Frontend/releases/tags/$pre_release_tag")
|
||||
pre_release_json=$(eval "curl -fsSL --max-time 2 $githubAuthArgs -H \"Accept: application/vnd.github.v3+json\" \"https://api.github.com/repos/OpenListTeam/OpenList-Frontend/releases/tags/$pre_release_tag\"")
|
||||
fi
|
||||
pre_release_assets=$(echo "$pre_release_json" | jq -r '.assets[].browser_download_url')
|
||||
pre_release_tar_url=$(echo "$pre_release_assets" | grep "openlist-frontend-dist" | grep "\.tar\.gz$")
|
||||
|
||||
if [ "$useLite" = true ]; then
|
||||
pre_release_tar_url=$(echo "$pre_release_assets" | grep "openlist-frontend-dist-lite" | grep "\.tar\.gz$")
|
||||
else
|
||||
pre_release_tar_url=$(echo "$pre_release_assets" | grep "openlist-frontend-dist" | grep -v "lite" | grep "\.tar\.gz$")
|
||||
fi
|
||||
|
||||
curl -fsSL "$pre_release_tar_url" -o web-dist-dev.tar.gz
|
||||
rm -rf public/dist && mkdir -p public/dist
|
||||
tar -zxvf web-dist-dev.tar.gz -C public/dist
|
||||
@ -53,9 +68,15 @@ FetchWebDev() {
|
||||
}
|
||||
|
||||
FetchWebRelease() {
|
||||
release_json=$(curl -fsSL --max-time 2 $githubAuthHeader $githubAuthValue -H "Accept: application/vnd.github.v3+json" "https://api.github.com/repos/OpenListTeam/OpenList-Frontend/releases/latest")
|
||||
release_json=$(eval "curl -fsSL --max-time 2 $githubAuthArgs -H \"Accept: application/vnd.github.v3+json\" \"https://api.github.com/repos/OpenListTeam/OpenList-Frontend/releases/latest\"")
|
||||
release_assets=$(echo "$release_json" | jq -r '.assets[].browser_download_url')
|
||||
release_tar_url=$(echo "$release_assets" | grep "openlist-frontend-dist" | grep "\.tar\.gz$")
|
||||
|
||||
if [ "$useLite" = true ]; then
|
||||
release_tar_url=$(echo "$release_assets" | grep "openlist-frontend-dist-lite" | grep "\.tar\.gz$")
|
||||
else
|
||||
release_tar_url=$(echo "$release_assets" | grep "openlist-frontend-dist" | grep -v "lite" | grep "\.tar\.gz$")
|
||||
fi
|
||||
|
||||
curl -fsSL "$release_tar_url" -o dist.tar.gz
|
||||
rm -rf public/dist && mkdir -p public/dist
|
||||
tar -zxvf dist.tar.gz -C public/dist
|
||||
@ -254,7 +275,7 @@ BuildReleaseFreeBSD() {
|
||||
mkdir -p "build/freebsd"
|
||||
|
||||
# Get latest FreeBSD 14.x release version from GitHub
|
||||
freebsd_version=$(curl -fsSL --max-time 2 $githubAuthHeader $githubAuthValue "https://api.github.com/repos/freebsd/freebsd-src/tags" | \
|
||||
freebsd_version=$(eval "curl -fsSL --max-time 2 $githubAuthArgs \"https://api.github.com/repos/freebsd/freebsd-src/tags\"" | \
|
||||
jq -r '.[].name' | \
|
||||
grep '^release/14\.' | \
|
||||
sort -V | \
|
||||
@ -295,82 +316,171 @@ MakeRelease() {
|
||||
rm -rv compress
|
||||
fi
|
||||
mkdir compress
|
||||
|
||||
# Add -lite suffix if useLite is true
|
||||
liteSuffix=""
|
||||
if [ "$useLite" = true ]; then
|
||||
liteSuffix="-lite"
|
||||
fi
|
||||
|
||||
for i in $(find . -type f -name "$appName-linux-*"); do
|
||||
cp "$i" "$appName"
|
||||
tar -czvf compress/"$i".tar.gz "$appName"
|
||||
tar -czvf compress/"$i$liteSuffix".tar.gz "$appName"
|
||||
rm -f "$appName"
|
||||
done
|
||||
for i in $(find . -type f -name "$appName-android-*"); do
|
||||
cp "$i" "$appName"
|
||||
tar -czvf compress/"$i".tar.gz "$appName"
|
||||
tar -czvf compress/"$i$liteSuffix".tar.gz "$appName"
|
||||
rm -f "$appName"
|
||||
done
|
||||
for i in $(find . -type f -name "$appName-darwin-*"); do
|
||||
cp "$i" "$appName"
|
||||
tar -czvf compress/"$i".tar.gz "$appName"
|
||||
tar -czvf compress/"$i$liteSuffix".tar.gz "$appName"
|
||||
rm -f "$appName"
|
||||
done
|
||||
for i in $(find . -type f -name "$appName-freebsd-*"); do
|
||||
cp "$i" "$appName"
|
||||
tar -czvf compress/"$i".tar.gz "$appName"
|
||||
tar -czvf compress/"$i$liteSuffix".tar.gz "$appName"
|
||||
rm -f "$appName"
|
||||
done
|
||||
for i in $(find . -type f -name "$appName-windows-*"); do
|
||||
cp "$i" "$appName".exe
|
||||
zip compress/$(echo $i | sed 's/\.[^.]*$//').zip "$appName".exe
|
||||
zip compress/$(echo $i | sed 's/\.[^.]*$//')$liteSuffix.zip "$appName".exe
|
||||
rm -f "$appName".exe
|
||||
done
|
||||
cd compress
|
||||
find . -type f -print0 | xargs -0 md5sum >"$1"
|
||||
cat "$1"
|
||||
|
||||
# Handle MD5 filename - add -lite suffix only if not already present
|
||||
md5FileName="$1"
|
||||
if [ "$useLite" = true ] && [[ "$1" != *"-lite.txt" ]]; then
|
||||
md5FileName=$(echo "$1" | sed 's/\.txt$/-lite.txt/')
|
||||
fi
|
||||
|
||||
find . -type f -print0 | xargs -0 md5sum >"$md5FileName"
|
||||
cat "$md5FileName"
|
||||
cd ../..
|
||||
}
|
||||
|
||||
if [ "$1" = "dev" ]; then
|
||||
# Parse parameters to handle lite parameter position flexibility
|
||||
buildType=""
|
||||
dockerType=""
|
||||
otherParam=""
|
||||
|
||||
for arg in "$@"; do
|
||||
case $arg in
|
||||
dev|beta|release|zip|prepare)
|
||||
if [ -z "$buildType" ]; then
|
||||
buildType="$arg"
|
||||
fi
|
||||
;;
|
||||
docker|docker-multiplatform|linux_musl_arm|linux_musl|android|freebsd|web)
|
||||
if [ -z "$dockerType" ]; then
|
||||
dockerType="$arg"
|
||||
fi
|
||||
;;
|
||||
lite)
|
||||
# lite parameter is already handled above
|
||||
;;
|
||||
*)
|
||||
if [ -z "$otherParam" ]; then
|
||||
otherParam="$arg"
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
if [ "$buildType" = "dev" ]; then
|
||||
FetchWebDev
|
||||
if [ "$2" = "docker" ]; then
|
||||
if [ "$dockerType" = "docker" ]; then
|
||||
BuildDocker
|
||||
elif [ "$2" = "docker-multiplatform" ]; then
|
||||
elif [ "$dockerType" = "docker-multiplatform" ]; then
|
||||
BuildDockerMultiplatform
|
||||
elif [ "$2" = "web" ]; then
|
||||
elif [ "$dockerType" = "web" ]; then
|
||||
echo "web only"
|
||||
else
|
||||
BuildDev
|
||||
fi
|
||||
elif [ "$1" = "release" -o "$1" = "beta" ]; then
|
||||
if [ "$1" = "beta" ]; then
|
||||
elif [ "$buildType" = "release" -o "$buildType" = "beta" ]; then
|
||||
if [ "$buildType" = "beta" ]; then
|
||||
FetchWebDev
|
||||
else
|
||||
FetchWebRelease
|
||||
fi
|
||||
if [ "$2" = "docker" ]; then
|
||||
if [ "$dockerType" = "docker" ]; then
|
||||
BuildDocker
|
||||
elif [ "$2" = "docker-multiplatform" ]; then
|
||||
elif [ "$dockerType" = "docker-multiplatform" ]; then
|
||||
BuildDockerMultiplatform
|
||||
elif [ "$2" = "linux_musl_arm" ]; then
|
||||
elif [ "$dockerType" = "linux_musl_arm" ]; then
|
||||
BuildReleaseLinuxMuslArm
|
||||
MakeRelease "md5-linux-musl-arm.txt"
|
||||
elif [ "$2" = "linux_musl" ]; then
|
||||
if [ "$useLite" = true ]; then
|
||||
MakeRelease "md5-linux-musl-arm-lite.txt"
|
||||
else
|
||||
MakeRelease "md5-linux-musl-arm.txt"
|
||||
fi
|
||||
elif [ "$dockerType" = "linux_musl" ]; then
|
||||
BuildReleaseLinuxMusl
|
||||
MakeRelease "md5-linux-musl.txt"
|
||||
elif [ "$2" = "android" ]; then
|
||||
if [ "$useLite" = true ]; then
|
||||
MakeRelease "md5-linux-musl-lite.txt"
|
||||
else
|
||||
MakeRelease "md5-linux-musl.txt"
|
||||
fi
|
||||
elif [ "$dockerType" = "android" ]; then
|
||||
BuildReleaseAndroid
|
||||
MakeRelease "md5-android.txt"
|
||||
elif [ "$2" = "freebsd" ]; then
|
||||
if [ "$useLite" = true ]; then
|
||||
MakeRelease "md5-android-lite.txt"
|
||||
else
|
||||
MakeRelease "md5-android.txt"
|
||||
fi
|
||||
elif [ "$dockerType" = "freebsd" ]; then
|
||||
BuildReleaseFreeBSD
|
||||
MakeRelease "md5-freebsd.txt"
|
||||
elif [ "$2" = "web" ]; then
|
||||
if [ "$useLite" = true ]; then
|
||||
MakeRelease "md5-freebsd-lite.txt"
|
||||
else
|
||||
MakeRelease "md5-freebsd.txt"
|
||||
fi
|
||||
elif [ "$dockerType" = "web" ]; then
|
||||
echo "web only"
|
||||
else
|
||||
BuildRelease
|
||||
MakeRelease "md5.txt"
|
||||
if [ "$useLite" = true ]; then
|
||||
MakeRelease "md5-lite.txt"
|
||||
else
|
||||
MakeRelease "md5.txt"
|
||||
fi
|
||||
fi
|
||||
elif [ "$1" = "prepare" ]; then
|
||||
if [ "$2" = "docker-multiplatform" ]; then
|
||||
elif [ "$buildType" = "prepare" ]; then
|
||||
if [ "$dockerType" = "docker-multiplatform" ]; then
|
||||
PrepareBuildDockerMusl
|
||||
fi
|
||||
elif [ "$1" = "zip" ]; then
|
||||
MakeRelease "$2".txt
|
||||
elif [ "$buildType" = "zip" ]; then
|
||||
if [ -n "$otherParam" ]; then
|
||||
if [ "$useLite" = true ]; then
|
||||
MakeRelease "$otherParam-lite.txt"
|
||||
else
|
||||
MakeRelease "$otherParam.txt"
|
||||
fi
|
||||
elif [ -n "$dockerType" ]; then
|
||||
if [ "$useLite" = true ]; then
|
||||
MakeRelease "$dockerType-lite.txt"
|
||||
else
|
||||
MakeRelease "$dockerType.txt"
|
||||
fi
|
||||
else
|
||||
if [ "$useLite" = true ]; then
|
||||
MakeRelease "md5-lite.txt"
|
||||
else
|
||||
MakeRelease "md5.txt"
|
||||
fi
|
||||
fi
|
||||
else
|
||||
echo -e "Parameter error"
|
||||
echo -e "Usage: $0 {dev|beta|release|zip|prepare} [docker|docker-multiplatform|linux_musl_arm|linux_musl|android|freebsd|web] [lite] [other_params]"
|
||||
echo -e "Examples:"
|
||||
echo -e " $0 dev"
|
||||
echo -e " $0 dev lite"
|
||||
echo -e " $0 dev docker"
|
||||
echo -e " $0 dev docker lite"
|
||||
echo -e " $0 release"
|
||||
echo -e " $0 release lite"
|
||||
echo -e " $0 release docker lite"
|
||||
fi
|
||||
|
10
cmd/admin.go
10
cmd/admin.go
@ -4,11 +4,11 @@ Copyright © 2022 NAME HERE <EMAIL ADDRESS>
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"github.com/OpenListTeam/OpenList/internal/conf"
|
||||
"github.com/OpenListTeam/OpenList/internal/op"
|
||||
"github.com/OpenListTeam/OpenList/internal/setting"
|
||||
"github.com/OpenListTeam/OpenList/pkg/utils"
|
||||
"github.com/OpenListTeam/OpenList/pkg/utils/random"
|
||||
"github.com/OpenListTeam/OpenList/v4/internal/conf"
|
||||
"github.com/OpenListTeam/OpenList/v4/internal/op"
|
||||
"github.com/OpenListTeam/OpenList/v4/internal/setting"
|
||||
"github.com/OpenListTeam/OpenList/v4/pkg/utils"
|
||||
"github.com/OpenListTeam/OpenList/v4/pkg/utils/random"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
|
@ -4,8 +4,8 @@ Copyright © 2022 NAME HERE <EMAIL ADDRESS>
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"github.com/OpenListTeam/OpenList/internal/op"
|
||||
"github.com/OpenListTeam/OpenList/pkg/utils"
|
||||
"github.com/OpenListTeam/OpenList/v4/internal/op"
|
||||
"github.com/OpenListTeam/OpenList/v4/pkg/utils"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
|
@ -5,10 +5,10 @@ import (
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
|
||||
"github.com/OpenListTeam/OpenList/internal/bootstrap"
|
||||
"github.com/OpenListTeam/OpenList/internal/bootstrap/data"
|
||||
"github.com/OpenListTeam/OpenList/internal/db"
|
||||
"github.com/OpenListTeam/OpenList/pkg/utils"
|
||||
"github.com/OpenListTeam/OpenList/v4/internal/bootstrap"
|
||||
"github.com/OpenListTeam/OpenList/v4/internal/bootstrap/data"
|
||||
"github.com/OpenListTeam/OpenList/v4/internal/db"
|
||||
"github.com/OpenListTeam/OpenList/v4/pkg/utils"
|
||||
log "github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
|
98
cmd/crypt.go
98
cmd/crypt.go
@ -19,7 +19,7 @@ import (
|
||||
// encryption and decryption command format for Crypt driver
|
||||
|
||||
type options struct {
|
||||
Op string //decrypt or encrypt
|
||||
op string //decrypt or encrypt
|
||||
src string //source dir or file
|
||||
dst string //out destination
|
||||
|
||||
@ -57,7 +57,7 @@ func init() {
|
||||
// is called directly, e.g.:
|
||||
CryptCmd.Flags().StringVarP(&opt.src, "src", "s", "", "src file or dir to encrypt/decrypt")
|
||||
CryptCmd.Flags().StringVarP(&opt.dst, "dst", "d", "", "dst dir to output,if not set,output to src dir")
|
||||
CryptCmd.Flags().StringVar(&opt.Op, "op", "", "de or en which stands for decrypt or encrypt")
|
||||
CryptCmd.Flags().StringVar(&opt.op, "op", "", "de or en which stands for decrypt or encrypt")
|
||||
|
||||
CryptCmd.Flags().StringVar(&opt.pwd, "pwd", "", "password used to encrypt/decrypt,if not contain ___Obfuscated___ prefix,will be obfuscated before used")
|
||||
CryptCmd.Flags().StringVar(&opt.salt, "salt", "", "salt used to encrypt/decrypt,if not contain ___Obfuscated___ prefix,will be obfuscated before used")
|
||||
@ -71,7 +71,7 @@ func (o *options) validate() {
|
||||
if o.src == "" {
|
||||
log.Fatal("src can not be empty")
|
||||
}
|
||||
if o.Op != "encrypt" && o.Op != "decrypt" && o.Op != "en" && o.Op != "de" {
|
||||
if o.op != "encrypt" && o.op != "decrypt" && o.op != "en" && o.op != "de" {
|
||||
log.Fatal("op must be encrypt or decrypt")
|
||||
}
|
||||
if o.filenameEncryption != "off" && o.filenameEncryption != "standard" && o.filenameEncryption != "obfuscate" {
|
||||
@ -130,24 +130,89 @@ func (o *options) cryptFileDir() {
|
||||
// src is dir
|
||||
if dst == "" {
|
||||
//if src is dir and not set dst dir ,create ${src}_crypt dir as dst dir
|
||||
dst = path.Join("./", fileInfo.Name()+"_crypt")
|
||||
dst = path.Join(filepath.Dir(src), fileInfo.Name()+"_crypt")
|
||||
}
|
||||
log.Infof("dst : %v", dst)
|
||||
|
||||
dirnameMap := make(map[string]string)
|
||||
pathSeparator := string(os.PathSeparator)
|
||||
|
||||
filepath.Walk(src, func(p string, info os.FileInfo, err error) error {
|
||||
if err != nil {
|
||||
log.Errorf("get file %v info failed, err:%v", p, err)
|
||||
return err
|
||||
}
|
||||
if info.IsDir() {
|
||||
//create output dir
|
||||
d := strings.Replace(p, src, dst, 1)
|
||||
log.Infof("create output dir %v", d)
|
||||
checkCreateDir(d)
|
||||
|
||||
if p == src {
|
||||
return nil
|
||||
}
|
||||
d := strings.Replace(filepath.Dir(p), src, dst, 1)
|
||||
o.cryptFile(cipher, p, d)
|
||||
log.Infof("current path %v", p)
|
||||
|
||||
// relative path
|
||||
rp := strings.ReplaceAll(p, src, "")
|
||||
log.Infof("relative path %v", rp)
|
||||
|
||||
rpds := strings.Split(rp, pathSeparator)
|
||||
|
||||
if info.IsDir() {
|
||||
// absolute dst dir for current path
|
||||
dd := ""
|
||||
|
||||
if o.dirnameEncryption == "true" {
|
||||
if o.op == "encrypt" || o.op == "en" {
|
||||
for i := range rpds {
|
||||
oname := rpds[i]
|
||||
if _, ok := dirnameMap[rpds[i]]; ok {
|
||||
rpds[i] = dirnameMap[rpds[i]]
|
||||
} else {
|
||||
rpds[i] = cipher.EncryptDirName(rpds[i])
|
||||
dirnameMap[oname] = rpds[i]
|
||||
}
|
||||
}
|
||||
dd = path.Join(dst, strings.Join(rpds, pathSeparator))
|
||||
} else {
|
||||
for i := range rpds {
|
||||
oname := rpds[i]
|
||||
if _, ok := dirnameMap[rpds[i]]; ok {
|
||||
rpds[i] = dirnameMap[rpds[i]]
|
||||
} else {
|
||||
dnn, err := cipher.DecryptDirName(rpds[i])
|
||||
if err != nil {
|
||||
log.Fatalf("decrypt dir name %v failed,err:%v", rpds[i], err)
|
||||
}
|
||||
rpds[i] = dnn
|
||||
dirnameMap[oname] = dnn
|
||||
}
|
||||
|
||||
}
|
||||
dd = path.Join(dst, strings.Join(rpds, pathSeparator))
|
||||
}
|
||||
|
||||
} else {
|
||||
dd = path.Join(dst, rp)
|
||||
}
|
||||
|
||||
log.Infof("create output dir %v", dd)
|
||||
checkCreateDir(dd)
|
||||
return nil
|
||||
}
|
||||
|
||||
// file dst dir
|
||||
fdd := dst
|
||||
|
||||
if o.dirnameEncryption == "true" {
|
||||
for i := range rpds {
|
||||
if i == len(rpds)-1 {
|
||||
break
|
||||
}
|
||||
fdd = path.Join(fdd, dirnameMap[rpds[i]])
|
||||
}
|
||||
|
||||
} else {
|
||||
fdd = path.Join(fdd, strings.Join(rpds[:len(rpds)-1], pathSeparator))
|
||||
}
|
||||
|
||||
log.Infof("file output dir %v", fdd)
|
||||
o.cryptFile(cipher, p, fdd)
|
||||
return nil
|
||||
})
|
||||
|
||||
@ -168,11 +233,13 @@ func (o *options) cryptFile(cipher *rcCrypt.Cipher, src string, dst string) {
|
||||
|
||||
var cryptSrcReader io.Reader
|
||||
var outFile string
|
||||
if o.Op == "encrypt" || o.Op == "en" {
|
||||
if o.op == "encrypt" || o.op == "en" {
|
||||
filename := fileInfo.Name()
|
||||
if o.filenameEncryption != "off" {
|
||||
filename = cipher.EncryptFileName(fileInfo.Name())
|
||||
log.Infof("encrypt file name %v to %v", fileInfo.Name(), filename)
|
||||
} else {
|
||||
filename = fileInfo.Name() + o.suffix
|
||||
}
|
||||
cryptSrcReader, err = cipher.EncryptData(fd)
|
||||
if err != nil {
|
||||
@ -188,6 +255,8 @@ func (o *options) cryptFile(cipher *rcCrypt.Cipher, src string, dst string) {
|
||||
log.Fatalf("decrypt file name %v failed,err:%v", src, err)
|
||||
}
|
||||
log.Infof("decrypt file name %v to %v, ", fileInfo.Name(), filename)
|
||||
} else {
|
||||
filename = strings.TrimSuffix(filename, o.suffix)
|
||||
}
|
||||
|
||||
cryptSrcReader, err = cipher.DecryptData(fd)
|
||||
@ -222,9 +291,10 @@ func checkCreateDir(dir string) {
|
||||
log.Fatalf("create dir %v failed,err:%v", dir, err)
|
||||
}
|
||||
return
|
||||
} else if err != nil {
|
||||
log.Fatalf("read dir %v err: %v", dir, err)
|
||||
}
|
||||
|
||||
log.Fatalf("read dir %v err: %v", dir, err)
|
||||
}
|
||||
|
||||
func updateObfusParm(str string) string {
|
||||
|
12
cmd/lang.go
12
cmd/lang.go
@ -11,12 +11,12 @@ import (
|
||||
"reflect"
|
||||
"strings"
|
||||
|
||||
_ "github.com/OpenListTeam/OpenList/drivers"
|
||||
"github.com/OpenListTeam/OpenList/internal/bootstrap"
|
||||
"github.com/OpenListTeam/OpenList/internal/bootstrap/data"
|
||||
"github.com/OpenListTeam/OpenList/internal/conf"
|
||||
"github.com/OpenListTeam/OpenList/internal/op"
|
||||
"github.com/OpenListTeam/OpenList/pkg/utils"
|
||||
_ "github.com/OpenListTeam/OpenList/v4/drivers"
|
||||
"github.com/OpenListTeam/OpenList/v4/internal/bootstrap"
|
||||
"github.com/OpenListTeam/OpenList/v4/internal/bootstrap/data"
|
||||
"github.com/OpenListTeam/OpenList/v4/internal/conf"
|
||||
"github.com/OpenListTeam/OpenList/v4/internal/op"
|
||||
"github.com/OpenListTeam/OpenList/v4/pkg/utils"
|
||||
log "github.com/sirupsen/logrus"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
10
cmd/root.go
10
cmd/root.go
@ -4,10 +4,10 @@ import (
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"github.com/OpenListTeam/OpenList/cmd/flags"
|
||||
_ "github.com/OpenListTeam/OpenList/drivers"
|
||||
_ "github.com/OpenListTeam/OpenList/internal/archive"
|
||||
_ "github.com/OpenListTeam/OpenList/internal/offline_download"
|
||||
"github.com/OpenListTeam/OpenList/v4/cmd/flags"
|
||||
_ "github.com/OpenListTeam/OpenList/v4/drivers"
|
||||
_ "github.com/OpenListTeam/OpenList/v4/internal/archive"
|
||||
_ "github.com/OpenListTeam/OpenList/v4/internal/offline_download"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
@ -15,7 +15,7 @@ var RootCmd = &cobra.Command{
|
||||
Use: "openlist",
|
||||
Short: "A file list program that supports multiple storage.",
|
||||
Long: `A file list program that supports multiple storage,
|
||||
built with love by Xhofe and friends in Go/Solid.js.
|
||||
built with love by OpenListTeam.
|
||||
Complete documentation is available at https://docs.openlist.team/`,
|
||||
}
|
||||
|
||||
|
@ -13,12 +13,12 @@ import (
|
||||
"syscall"
|
||||
"time"
|
||||
|
||||
"github.com/OpenListTeam/OpenList/cmd/flags"
|
||||
"github.com/OpenListTeam/OpenList/internal/bootstrap"
|
||||
"github.com/OpenListTeam/OpenList/internal/conf"
|
||||
"github.com/OpenListTeam/OpenList/internal/fs"
|
||||
"github.com/OpenListTeam/OpenList/pkg/utils"
|
||||
"github.com/OpenListTeam/OpenList/server"
|
||||
"github.com/OpenListTeam/OpenList/v4/cmd/flags"
|
||||
"github.com/OpenListTeam/OpenList/v4/internal/bootstrap"
|
||||
"github.com/OpenListTeam/OpenList/v4/internal/conf"
|
||||
"github.com/OpenListTeam/OpenList/v4/internal/fs"
|
||||
"github.com/OpenListTeam/OpenList/v4/pkg/utils"
|
||||
"github.com/OpenListTeam/OpenList/v4/server"
|
||||
"github.com/OpenListTeam/sftpd-openlist"
|
||||
ftpserver "github.com/fclairamb/ftpserverlib"
|
||||
"github.com/gin-gonic/gin"
|
||||
|
@ -7,8 +7,8 @@ import (
|
||||
"os"
|
||||
"strconv"
|
||||
|
||||
"github.com/OpenListTeam/OpenList/internal/db"
|
||||
"github.com/OpenListTeam/OpenList/pkg/utils"
|
||||
"github.com/OpenListTeam/OpenList/v4/internal/db"
|
||||
"github.com/OpenListTeam/OpenList/v4/pkg/utils"
|
||||
"github.com/charmbracelet/bubbles/table"
|
||||
tea "github.com/charmbracelet/bubbletea"
|
||||
"github.com/charmbracelet/lipgloss"
|
||||
|
@ -5,10 +5,10 @@ import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/OpenListTeam/OpenList/internal/conf"
|
||||
"github.com/OpenListTeam/OpenList/internal/op"
|
||||
"github.com/OpenListTeam/OpenList/internal/setting"
|
||||
"github.com/OpenListTeam/OpenList/pkg/utils"
|
||||
"github.com/OpenListTeam/OpenList/v4/internal/conf"
|
||||
"github.com/OpenListTeam/OpenList/v4/internal/op"
|
||||
"github.com/OpenListTeam/OpenList/v4/internal/setting"
|
||||
"github.com/OpenListTeam/OpenList/v4/pkg/utils"
|
||||
"github.com/go-resty/resty/v2"
|
||||
)
|
||||
|
||||
|
@ -8,7 +8,7 @@ import (
|
||||
"os"
|
||||
"runtime"
|
||||
|
||||
"github.com/OpenListTeam/OpenList/internal/conf"
|
||||
"github.com/OpenListTeam/OpenList/v4/internal/conf"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
package _115
|
||||
|
||||
import (
|
||||
"github.com/OpenListTeam/OpenList/drivers/base"
|
||||
"github.com/OpenListTeam/OpenList/v4/drivers/base"
|
||||
driver115 "github.com/SheltonZhu/115driver/pkg/driver"
|
||||
log "github.com/sirupsen/logrus"
|
||||
)
|
||||
|
@ -5,10 +5,11 @@ import (
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"github.com/OpenListTeam/OpenList/internal/driver"
|
||||
"github.com/OpenListTeam/OpenList/internal/model"
|
||||
"github.com/OpenListTeam/OpenList/pkg/http_range"
|
||||
"github.com/OpenListTeam/OpenList/pkg/utils"
|
||||
"github.com/OpenListTeam/OpenList/v4/internal/driver"
|
||||
"github.com/OpenListTeam/OpenList/v4/internal/model"
|
||||
streamPkg "github.com/OpenListTeam/OpenList/v4/internal/stream"
|
||||
"github.com/OpenListTeam/OpenList/v4/pkg/http_range"
|
||||
"github.com/OpenListTeam/OpenList/v4/pkg/utils"
|
||||
driver115 "github.com/SheltonZhu/115driver/pkg/driver"
|
||||
"github.com/pkg/errors"
|
||||
"golang.org/x/time/rate"
|
||||
@ -184,12 +185,10 @@ func (d *Pan115) Put(ctx context.Context, dstDir model.Obj, stream model.FileStr
|
||||
}
|
||||
preHash = strings.ToUpper(preHash)
|
||||
fullHash := stream.GetHash().GetHash(utils.SHA1)
|
||||
if len(fullHash) <= 0 {
|
||||
tmpF, err := stream.CacheFullInTempFile()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
fullHash, err = utils.HashFile(utils.SHA1, tmpF)
|
||||
if len(fullHash) != utils.SHA1.Width {
|
||||
cacheFileProgress := model.UpdateProgressWithRange(up, 0, 50)
|
||||
up = model.UpdateProgressWithRange(up, 50, 100)
|
||||
_, fullHash, err = streamPkg.CacheFullInTempFileAndHash(stream, cacheFileProgress, utils.SHA1)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -1,8 +1,8 @@
|
||||
package _115
|
||||
|
||||
import (
|
||||
"github.com/OpenListTeam/OpenList/internal/driver"
|
||||
"github.com/OpenListTeam/OpenList/internal/op"
|
||||
"github.com/OpenListTeam/OpenList/v4/internal/driver"
|
||||
"github.com/OpenListTeam/OpenList/v4/internal/op"
|
||||
)
|
||||
|
||||
type Addition struct {
|
||||
|
@ -3,8 +3,8 @@ package _115
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/OpenListTeam/OpenList/internal/model"
|
||||
"github.com/OpenListTeam/OpenList/pkg/utils"
|
||||
"github.com/OpenListTeam/OpenList/v4/internal/model"
|
||||
"github.com/OpenListTeam/OpenList/v4/pkg/utils"
|
||||
"github.com/SheltonZhu/115driver/pkg/driver"
|
||||
)
|
||||
|
||||
|
@ -17,11 +17,11 @@ import (
|
||||
"sync/atomic"
|
||||
"time"
|
||||
|
||||
"github.com/OpenListTeam/OpenList/internal/conf"
|
||||
"github.com/OpenListTeam/OpenList/internal/driver"
|
||||
"github.com/OpenListTeam/OpenList/internal/model"
|
||||
"github.com/OpenListTeam/OpenList/pkg/http_range"
|
||||
"github.com/OpenListTeam/OpenList/pkg/utils"
|
||||
"github.com/OpenListTeam/OpenList/v4/internal/conf"
|
||||
"github.com/OpenListTeam/OpenList/v4/internal/driver"
|
||||
"github.com/OpenListTeam/OpenList/v4/internal/model"
|
||||
"github.com/OpenListTeam/OpenList/v4/pkg/http_range"
|
||||
"github.com/OpenListTeam/OpenList/v4/pkg/utils"
|
||||
"github.com/aliyun/aliyun-oss-go-sdk/oss"
|
||||
|
||||
cipher "github.com/SheltonZhu/115driver/pkg/crypto/ec115"
|
||||
|
@ -3,19 +3,20 @@ package _115_open
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/OpenListTeam/OpenList/cmd/flags"
|
||||
"github.com/OpenListTeam/OpenList/drivers/base"
|
||||
"github.com/OpenListTeam/OpenList/internal/driver"
|
||||
"github.com/OpenListTeam/OpenList/internal/model"
|
||||
"github.com/OpenListTeam/OpenList/internal/op"
|
||||
"github.com/OpenListTeam/OpenList/pkg/utils"
|
||||
sdk "github.com/xhofe/115-sdk-go"
|
||||
sdk "github.com/OpenListTeam/115-sdk-go"
|
||||
"github.com/OpenListTeam/OpenList/v4/cmd/flags"
|
||||
"github.com/OpenListTeam/OpenList/v4/drivers/base"
|
||||
"github.com/OpenListTeam/OpenList/v4/internal/driver"
|
||||
"github.com/OpenListTeam/OpenList/v4/internal/model"
|
||||
"github.com/OpenListTeam/OpenList/v4/internal/op"
|
||||
"github.com/OpenListTeam/OpenList/v4/internal/stream"
|
||||
"github.com/OpenListTeam/OpenList/v4/pkg/http_range"
|
||||
"github.com/OpenListTeam/OpenList/v4/pkg/utils"
|
||||
"golang.org/x/time/rate"
|
||||
)
|
||||
|
||||
@ -215,28 +216,29 @@ func (d *Open115) Remove(ctx context.Context, obj model.Obj) error {
|
||||
}
|
||||
|
||||
func (d *Open115) Put(ctx context.Context, dstDir model.Obj, file model.FileStreamer, up driver.UpdateProgress) error {
|
||||
if err := d.WaitLimit(ctx); err != nil {
|
||||
return err
|
||||
}
|
||||
tempF, err := file.CacheFullInTempFile()
|
||||
err := d.WaitLimit(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// cal full sha1
|
||||
sha1, err := utils.HashReader(utils.SHA1, tempF)
|
||||
sha1 := file.GetHash().GetHash(utils.SHA1)
|
||||
if len(sha1) != utils.SHA1.Width {
|
||||
cacheFileProgress := model.UpdateProgressWithRange(up, 0, 50)
|
||||
up = model.UpdateProgressWithRange(up, 50, 100)
|
||||
_, sha1, err = stream.CacheFullInTempFileAndHash(file, cacheFileProgress, utils.SHA1)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
const PreHashSize int64 = 128 * utils.KB
|
||||
hashSize := PreHashSize
|
||||
if file.GetSize() < PreHashSize {
|
||||
hashSize = file.GetSize()
|
||||
}
|
||||
reader, err := file.RangeRead(http_range.Range{Start: 0, Length: hashSize})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
_, err = tempF.Seek(0, io.SeekStart)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// pre 128k sha1
|
||||
sha1128k, err := utils.HashReader(utils.SHA1, io.LimitReader(tempF, 128*1024))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
_, err = tempF.Seek(0, io.SeekStart)
|
||||
sha1128k, err := utils.HashReader(utils.SHA1, reader)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -252,6 +254,7 @@ func (d *Open115) Put(ctx context.Context, dstDir model.Obj, file model.FileStre
|
||||
return err
|
||||
}
|
||||
if resp.Status == 2 {
|
||||
up(100)
|
||||
return nil
|
||||
}
|
||||
// 2. two way verify
|
||||
@ -265,15 +268,11 @@ func (d *Open115) Put(ctx context.Context, dstDir model.Obj, file model.FileStre
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
_, err = tempF.Seek(start, io.SeekStart)
|
||||
reader, err = file.RangeRead(http_range.Range{Start: start, Length: end - start + 1})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
signVal, err := utils.HashReader(utils.SHA1, io.LimitReader(tempF, end-start+1))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
_, err = tempF.Seek(0, io.SeekStart)
|
||||
signVal, err := utils.HashReader(utils.SHA1, reader)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -290,6 +289,7 @@ func (d *Open115) Put(ctx context.Context, dstDir model.Obj, file model.FileStre
|
||||
return err
|
||||
}
|
||||
if resp.Status == 2 {
|
||||
up(100)
|
||||
return nil
|
||||
}
|
||||
}
|
||||
@ -299,7 +299,7 @@ func (d *Open115) Put(ctx context.Context, dstDir model.Obj, file model.FileStre
|
||||
return err
|
||||
}
|
||||
// 4. upload
|
||||
err = d.multpartUpload(ctx, tempF, file, up, tokenResp, resp)
|
||||
err = d.multpartUpload(ctx, file, up, tokenResp, resp)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -1,8 +1,8 @@
|
||||
package _115_open
|
||||
|
||||
import (
|
||||
"github.com/OpenListTeam/OpenList/internal/driver"
|
||||
"github.com/OpenListTeam/OpenList/internal/op"
|
||||
"github.com/OpenListTeam/OpenList/v4/internal/driver"
|
||||
"github.com/OpenListTeam/OpenList/v4/internal/op"
|
||||
)
|
||||
|
||||
type Addition struct {
|
||||
@ -11,7 +11,7 @@ type Addition struct {
|
||||
// define other
|
||||
OrderBy string `json:"order_by" type:"select" options:"file_name,file_size,user_utime,file_type"`
|
||||
OrderDirection string `json:"order_direction" type:"select" options:"asc,desc"`
|
||||
LimitRate float64 `json:"limit_rate,string" type:"float" default:"1" help:"limit all api request rate ([limit]r/1s)"`
|
||||
LimitRate float64 `json:"limit_rate" type:"float" default:"1" help:"limit all api request rate ([limit]r/1s)"`
|
||||
AccessToken string `json:"access_token" required:"true"`
|
||||
RefreshToken string `json:"refresh_token" required:"true"`
|
||||
}
|
||||
|
@ -3,9 +3,9 @@ package _115_open
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/OpenListTeam/OpenList/internal/model"
|
||||
"github.com/OpenListTeam/OpenList/pkg/utils"
|
||||
sdk "github.com/xhofe/115-sdk-go"
|
||||
"github.com/OpenListTeam/OpenList/v4/internal/model"
|
||||
"github.com/OpenListTeam/OpenList/v4/pkg/utils"
|
||||
sdk "github.com/OpenListTeam/115-sdk-go"
|
||||
)
|
||||
|
||||
type Obj sdk.GetFilesResp_File
|
||||
|
@ -6,12 +6,12 @@ import (
|
||||
"io"
|
||||
"time"
|
||||
|
||||
"github.com/OpenListTeam/OpenList/internal/driver"
|
||||
"github.com/OpenListTeam/OpenList/internal/model"
|
||||
"github.com/OpenListTeam/OpenList/pkg/utils"
|
||||
sdk "github.com/OpenListTeam/115-sdk-go"
|
||||
"github.com/OpenListTeam/OpenList/v4/internal/driver"
|
||||
"github.com/OpenListTeam/OpenList/v4/internal/model"
|
||||
"github.com/OpenListTeam/OpenList/v4/pkg/utils"
|
||||
"github.com/aliyun/aliyun-oss-go-sdk/oss"
|
||||
"github.com/avast/retry-go"
|
||||
sdk "github.com/xhofe/115-sdk-go"
|
||||
)
|
||||
|
||||
func calPartSize(fileSize int64) int64 {
|
||||
@ -68,7 +68,7 @@ func (d *Open115) singleUpload(ctx context.Context, tempF model.File, tokenResp
|
||||
// } `json:"data"`
|
||||
// }
|
||||
|
||||
func (d *Open115) multpartUpload(ctx context.Context, tempF model.File, stream model.FileStreamer, up driver.UpdateProgress, tokenResp *sdk.UploadGetTokenResp, initResp *sdk.UploadInitResp) error {
|
||||
func (d *Open115) multpartUpload(ctx context.Context, stream model.FileStreamer, up driver.UpdateProgress, tokenResp *sdk.UploadGetTokenResp, initResp *sdk.UploadInitResp) error {
|
||||
fileSize := stream.GetSize()
|
||||
chunkSize := calPartSize(fileSize)
|
||||
|
||||
@ -121,7 +121,7 @@ func (d *Open115) multpartUpload(ctx context.Context, tempF model.File, stream m
|
||||
} else {
|
||||
offset += partSize
|
||||
}
|
||||
up(float64(offset) / float64(fileSize))
|
||||
up(float64(offset) * 100 / float64(fileSize))
|
||||
}
|
||||
|
||||
// callbackRespBytes := make([]byte, 1024)
|
||||
|
@ -3,10 +3,10 @@ package _115_share
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/OpenListTeam/OpenList/internal/driver"
|
||||
"github.com/OpenListTeam/OpenList/internal/errs"
|
||||
"github.com/OpenListTeam/OpenList/internal/model"
|
||||
"github.com/OpenListTeam/OpenList/pkg/utils"
|
||||
"github.com/OpenListTeam/OpenList/v4/internal/driver"
|
||||
"github.com/OpenListTeam/OpenList/v4/internal/errs"
|
||||
"github.com/OpenListTeam/OpenList/v4/internal/model"
|
||||
"github.com/OpenListTeam/OpenList/v4/pkg/utils"
|
||||
driver115 "github.com/SheltonZhu/115driver/pkg/driver"
|
||||
"golang.org/x/time/rate"
|
||||
)
|
||||
|
@ -1,8 +1,8 @@
|
||||
package _115_share
|
||||
|
||||
import (
|
||||
"github.com/OpenListTeam/OpenList/internal/driver"
|
||||
"github.com/OpenListTeam/OpenList/internal/op"
|
||||
"github.com/OpenListTeam/OpenList/v4/internal/driver"
|
||||
"github.com/OpenListTeam/OpenList/v4/internal/op"
|
||||
)
|
||||
|
||||
type Addition struct {
|
||||
|
@ -5,8 +5,8 @@ import (
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"github.com/OpenListTeam/OpenList/internal/model"
|
||||
"github.com/OpenListTeam/OpenList/pkg/utils"
|
||||
"github.com/OpenListTeam/OpenList/v4/internal/model"
|
||||
"github.com/OpenListTeam/OpenList/v4/pkg/utils"
|
||||
driver115 "github.com/SheltonZhu/115driver/pkg/driver"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
@ -12,12 +12,12 @@ import (
|
||||
|
||||
"golang.org/x/time/rate"
|
||||
|
||||
"github.com/OpenListTeam/OpenList/drivers/base"
|
||||
"github.com/OpenListTeam/OpenList/internal/driver"
|
||||
"github.com/OpenListTeam/OpenList/internal/errs"
|
||||
"github.com/OpenListTeam/OpenList/internal/model"
|
||||
"github.com/OpenListTeam/OpenList/internal/stream"
|
||||
"github.com/OpenListTeam/OpenList/pkg/utils"
|
||||
"github.com/OpenListTeam/OpenList/v4/drivers/base"
|
||||
"github.com/OpenListTeam/OpenList/v4/internal/driver"
|
||||
"github.com/OpenListTeam/OpenList/v4/internal/errs"
|
||||
"github.com/OpenListTeam/OpenList/v4/internal/model"
|
||||
"github.com/OpenListTeam/OpenList/v4/internal/stream"
|
||||
"github.com/OpenListTeam/OpenList/v4/pkg/utils"
|
||||
"github.com/aws/aws-sdk-go/aws"
|
||||
"github.com/aws/aws-sdk-go/aws/credentials"
|
||||
"github.com/aws/aws-sdk-go/aws/session"
|
||||
@ -188,7 +188,9 @@ func (d *Pan123) Put(ctx context.Context, dstDir model.Obj, file model.FileStrea
|
||||
etag := file.GetHash().GetHash(utils.MD5)
|
||||
var err error
|
||||
if len(etag) < utils.MD5.Width {
|
||||
_, etag, err = stream.CacheFullInTempFileAndHash(file, utils.MD5)
|
||||
cacheFileProgress := model.UpdateProgressWithRange(up, 0, 50)
|
||||
up = model.UpdateProgressWithRange(up, 50, 100)
|
||||
_, etag, err = stream.CacheFullInTempFileAndHash(file, cacheFileProgress, utils.MD5)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -1,8 +1,8 @@
|
||||
package _123
|
||||
|
||||
import (
|
||||
"github.com/OpenListTeam/OpenList/internal/driver"
|
||||
"github.com/OpenListTeam/OpenList/internal/op"
|
||||
"github.com/OpenListTeam/OpenList/v4/internal/driver"
|
||||
"github.com/OpenListTeam/OpenList/v4/internal/op"
|
||||
)
|
||||
|
||||
type Addition struct {
|
||||
|
@ -7,9 +7,9 @@ import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/OpenListTeam/OpenList/pkg/utils"
|
||||
"github.com/OpenListTeam/OpenList/v4/pkg/utils"
|
||||
|
||||
"github.com/OpenListTeam/OpenList/internal/model"
|
||||
"github.com/OpenListTeam/OpenList/v4/internal/model"
|
||||
)
|
||||
|
||||
type File struct {
|
||||
|
@ -7,10 +7,10 @@ import (
|
||||
"net/http"
|
||||
"strconv"
|
||||
|
||||
"github.com/OpenListTeam/OpenList/drivers/base"
|
||||
"github.com/OpenListTeam/OpenList/internal/driver"
|
||||
"github.com/OpenListTeam/OpenList/internal/model"
|
||||
"github.com/OpenListTeam/OpenList/pkg/utils"
|
||||
"github.com/OpenListTeam/OpenList/v4/drivers/base"
|
||||
"github.com/OpenListTeam/OpenList/v4/internal/driver"
|
||||
"github.com/OpenListTeam/OpenList/v4/internal/model"
|
||||
"github.com/OpenListTeam/OpenList/v4/pkg/utils"
|
||||
"github.com/go-resty/resty/v2"
|
||||
)
|
||||
|
||||
|
@ -13,8 +13,8 @@ import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/OpenListTeam/OpenList/drivers/base"
|
||||
"github.com/OpenListTeam/OpenList/pkg/utils"
|
||||
"github.com/OpenListTeam/OpenList/v4/drivers/base"
|
||||
"github.com/OpenListTeam/OpenList/v4/pkg/utils"
|
||||
"github.com/go-resty/resty/v2"
|
||||
jsoniter "github.com/json-iterator/go"
|
||||
log "github.com/sirupsen/logrus"
|
||||
|
@ -5,10 +5,10 @@ import (
|
||||
stdpath "path"
|
||||
"time"
|
||||
|
||||
"github.com/OpenListTeam/OpenList/internal/driver"
|
||||
"github.com/OpenListTeam/OpenList/internal/errs"
|
||||
"github.com/OpenListTeam/OpenList/internal/model"
|
||||
"github.com/OpenListTeam/OpenList/pkg/utils"
|
||||
"github.com/OpenListTeam/OpenList/v4/internal/driver"
|
||||
"github.com/OpenListTeam/OpenList/v4/internal/errs"
|
||||
"github.com/OpenListTeam/OpenList/v4/internal/model"
|
||||
"github.com/OpenListTeam/OpenList/v4/pkg/utils"
|
||||
)
|
||||
|
||||
type Pan123Link struct {
|
||||
|
@ -1,8 +1,8 @@
|
||||
package _123Link
|
||||
|
||||
import (
|
||||
"github.com/OpenListTeam/OpenList/internal/driver"
|
||||
"github.com/OpenListTeam/OpenList/internal/op"
|
||||
"github.com/OpenListTeam/OpenList/v4/internal/driver"
|
||||
"github.com/OpenListTeam/OpenList/v4/internal/op"
|
||||
)
|
||||
|
||||
type Addition struct {
|
||||
|
@ -3,8 +3,8 @@ package _123Link
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/OpenListTeam/OpenList/internal/errs"
|
||||
"github.com/OpenListTeam/OpenList/internal/model"
|
||||
"github.com/OpenListTeam/OpenList/v4/internal/errs"
|
||||
"github.com/OpenListTeam/OpenList/v4/internal/model"
|
||||
)
|
||||
|
||||
// Node is a node in the folder tree
|
||||
|
@ -4,12 +4,12 @@ import (
|
||||
"context"
|
||||
"strconv"
|
||||
|
||||
"github.com/OpenListTeam/OpenList/internal/driver"
|
||||
"github.com/OpenListTeam/OpenList/internal/errs"
|
||||
"github.com/OpenListTeam/OpenList/internal/model"
|
||||
"github.com/OpenListTeam/OpenList/internal/op"
|
||||
"github.com/OpenListTeam/OpenList/internal/stream"
|
||||
"github.com/OpenListTeam/OpenList/pkg/utils"
|
||||
"github.com/OpenListTeam/OpenList/v4/internal/driver"
|
||||
"github.com/OpenListTeam/OpenList/v4/internal/errs"
|
||||
"github.com/OpenListTeam/OpenList/v4/internal/model"
|
||||
"github.com/OpenListTeam/OpenList/v4/internal/op"
|
||||
"github.com/OpenListTeam/OpenList/v4/internal/stream"
|
||||
"github.com/OpenListTeam/OpenList/v4/pkg/utils"
|
||||
)
|
||||
|
||||
type Open123 struct {
|
||||
@ -109,7 +109,9 @@ func (d *Open123) Put(ctx context.Context, dstDir model.Obj, file model.FileStre
|
||||
etag := file.GetHash().GetHash(utils.MD5)
|
||||
|
||||
if len(etag) < utils.MD5.Width {
|
||||
_, etag, err = stream.CacheFullInTempFileAndHash(file, utils.MD5)
|
||||
cacheFileProgress := model.UpdateProgressWithRange(up, 0, 50)
|
||||
up = model.UpdateProgressWithRange(up, 50, 100)
|
||||
_, etag, err = stream.CacheFullInTempFileAndHash(file, cacheFileProgress, utils.MD5)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -121,7 +123,6 @@ func (d *Open123) Put(ctx context.Context, dstDir model.Obj, file model.FileStre
|
||||
if createResp.Data.Reuse {
|
||||
return nil
|
||||
}
|
||||
up(10)
|
||||
|
||||
return d.Upload(ctx, file, createResp, up)
|
||||
}
|
||||
|
@ -1,8 +1,8 @@
|
||||
package _123_open
|
||||
|
||||
import (
|
||||
"github.com/OpenListTeam/OpenList/internal/driver"
|
||||
"github.com/OpenListTeam/OpenList/internal/op"
|
||||
"github.com/OpenListTeam/OpenList/v4/internal/driver"
|
||||
"github.com/OpenListTeam/OpenList/v4/internal/op"
|
||||
)
|
||||
|
||||
type Addition struct {
|
||||
|
@ -4,8 +4,8 @@ import (
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"github.com/OpenListTeam/OpenList/internal/model"
|
||||
"github.com/OpenListTeam/OpenList/pkg/utils"
|
||||
"github.com/OpenListTeam/OpenList/v4/internal/model"
|
||||
"github.com/OpenListTeam/OpenList/v4/pkg/utils"
|
||||
)
|
||||
|
||||
type ApiInfo struct {
|
||||
|
@ -6,12 +6,12 @@ import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/OpenListTeam/OpenList/drivers/base"
|
||||
"github.com/OpenListTeam/OpenList/internal/driver"
|
||||
"github.com/OpenListTeam/OpenList/internal/model"
|
||||
"github.com/OpenListTeam/OpenList/pkg/errgroup"
|
||||
"github.com/OpenListTeam/OpenList/pkg/http_range"
|
||||
"github.com/OpenListTeam/OpenList/pkg/utils"
|
||||
"github.com/OpenListTeam/OpenList/v4/drivers/base"
|
||||
"github.com/OpenListTeam/OpenList/v4/internal/driver"
|
||||
"github.com/OpenListTeam/OpenList/v4/internal/model"
|
||||
"github.com/OpenListTeam/OpenList/v4/pkg/errgroup"
|
||||
"github.com/OpenListTeam/OpenList/v4/pkg/http_range"
|
||||
"github.com/OpenListTeam/OpenList/v4/pkg/utils"
|
||||
"github.com/avast/retry-go"
|
||||
"github.com/go-resty/resty/v2"
|
||||
)
|
||||
|
@ -7,8 +7,8 @@ import (
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"github.com/OpenListTeam/OpenList/drivers/base"
|
||||
"github.com/OpenListTeam/OpenList/internal/op"
|
||||
"github.com/OpenListTeam/OpenList/v4/drivers/base"
|
||||
"github.com/OpenListTeam/OpenList/v4/internal/op"
|
||||
"github.com/go-resty/resty/v2"
|
||||
log "github.com/sirupsen/logrus"
|
||||
)
|
||||
|
@ -11,12 +11,12 @@ import (
|
||||
|
||||
"golang.org/x/time/rate"
|
||||
|
||||
_123 "github.com/OpenListTeam/OpenList/drivers/123"
|
||||
"github.com/OpenListTeam/OpenList/drivers/base"
|
||||
"github.com/OpenListTeam/OpenList/internal/driver"
|
||||
"github.com/OpenListTeam/OpenList/internal/errs"
|
||||
"github.com/OpenListTeam/OpenList/internal/model"
|
||||
"github.com/OpenListTeam/OpenList/pkg/utils"
|
||||
_123 "github.com/OpenListTeam/OpenList/v4/drivers/123"
|
||||
"github.com/OpenListTeam/OpenList/v4/drivers/base"
|
||||
"github.com/OpenListTeam/OpenList/v4/internal/driver"
|
||||
"github.com/OpenListTeam/OpenList/v4/internal/errs"
|
||||
"github.com/OpenListTeam/OpenList/v4/internal/model"
|
||||
"github.com/OpenListTeam/OpenList/v4/pkg/utils"
|
||||
"github.com/go-resty/resty/v2"
|
||||
log "github.com/sirupsen/logrus"
|
||||
)
|
||||
|
@ -1,8 +1,8 @@
|
||||
package _123Share
|
||||
|
||||
import (
|
||||
"github.com/OpenListTeam/OpenList/internal/driver"
|
||||
"github.com/OpenListTeam/OpenList/internal/op"
|
||||
"github.com/OpenListTeam/OpenList/v4/internal/driver"
|
||||
"github.com/OpenListTeam/OpenList/v4/internal/op"
|
||||
)
|
||||
|
||||
type Addition struct {
|
||||
|
@ -7,9 +7,9 @@ import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/OpenListTeam/OpenList/pkg/utils"
|
||||
"github.com/OpenListTeam/OpenList/v4/pkg/utils"
|
||||
|
||||
"github.com/OpenListTeam/OpenList/internal/model"
|
||||
"github.com/OpenListTeam/OpenList/v4/internal/model"
|
||||
)
|
||||
|
||||
type File struct {
|
||||
|
@ -13,8 +13,8 @@ import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/OpenListTeam/OpenList/drivers/base"
|
||||
"github.com/OpenListTeam/OpenList/pkg/utils"
|
||||
"github.com/OpenListTeam/OpenList/v4/drivers/base"
|
||||
"github.com/OpenListTeam/OpenList/v4/pkg/utils"
|
||||
"github.com/go-resty/resty/v2"
|
||||
jsoniter "github.com/json-iterator/go"
|
||||
)
|
||||
@ -61,7 +61,7 @@ func (d *Pan123Share) request(url string, method string, callback base.ReqCallba
|
||||
"origin": "https://www.123pan.com",
|
||||
"referer": "https://www.123pan.com/",
|
||||
"authorization": "Bearer " + d.AccessToken,
|
||||
"user-agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) opnelist-client",
|
||||
"user-agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) openlist-client",
|
||||
"platform": "web",
|
||||
"app-version": "3",
|
||||
//"user-agent": base.UserAgent,
|
||||
|
@ -10,14 +10,14 @@ import (
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"github.com/OpenListTeam/OpenList/drivers/base"
|
||||
"github.com/OpenListTeam/OpenList/internal/driver"
|
||||
"github.com/OpenListTeam/OpenList/internal/errs"
|
||||
"github.com/OpenListTeam/OpenList/internal/model"
|
||||
streamPkg "github.com/OpenListTeam/OpenList/internal/stream"
|
||||
"github.com/OpenListTeam/OpenList/pkg/cron"
|
||||
"github.com/OpenListTeam/OpenList/pkg/utils"
|
||||
"github.com/OpenListTeam/OpenList/pkg/utils/random"
|
||||
"github.com/OpenListTeam/OpenList/v4/drivers/base"
|
||||
"github.com/OpenListTeam/OpenList/v4/internal/driver"
|
||||
"github.com/OpenListTeam/OpenList/v4/internal/errs"
|
||||
"github.com/OpenListTeam/OpenList/v4/internal/model"
|
||||
streamPkg "github.com/OpenListTeam/OpenList/v4/internal/stream"
|
||||
"github.com/OpenListTeam/OpenList/v4/pkg/cron"
|
||||
"github.com/OpenListTeam/OpenList/v4/pkg/utils"
|
||||
"github.com/OpenListTeam/OpenList/v4/pkg/utils/random"
|
||||
log "github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
@ -522,7 +522,9 @@ func (d *Yun139) Put(ctx context.Context, dstDir model.Obj, stream model.FileStr
|
||||
var err error
|
||||
fullHash := stream.GetHash().GetHash(utils.SHA256)
|
||||
if len(fullHash) != utils.SHA256.Width {
|
||||
_, fullHash, err = streamPkg.CacheFullInTempFileAndHash(stream, utils.SHA256)
|
||||
cacheFileProgress := model.UpdateProgressWithRange(up, 0, 50)
|
||||
up = model.UpdateProgressWithRange(up, 50, 100)
|
||||
_, fullHash, err = streamPkg.CacheFullInTempFileAndHash(stream, cacheFileProgress, utils.SHA256)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -1,8 +1,8 @@
|
||||
package _139
|
||||
|
||||
import (
|
||||
"github.com/OpenListTeam/OpenList/internal/driver"
|
||||
"github.com/OpenListTeam/OpenList/internal/op"
|
||||
"github.com/OpenListTeam/OpenList/v4/internal/driver"
|
||||
"github.com/OpenListTeam/OpenList/v4/internal/op"
|
||||
)
|
||||
|
||||
type Addition struct {
|
||||
|
@ -12,11 +12,11 @@ import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/OpenListTeam/OpenList/drivers/base"
|
||||
"github.com/OpenListTeam/OpenList/internal/model"
|
||||
"github.com/OpenListTeam/OpenList/internal/op"
|
||||
"github.com/OpenListTeam/OpenList/pkg/utils"
|
||||
"github.com/OpenListTeam/OpenList/pkg/utils/random"
|
||||
"github.com/OpenListTeam/OpenList/v4/drivers/base"
|
||||
"github.com/OpenListTeam/OpenList/v4/internal/model"
|
||||
"github.com/OpenListTeam/OpenList/v4/internal/op"
|
||||
"github.com/OpenListTeam/OpenList/v4/pkg/utils"
|
||||
"github.com/OpenListTeam/OpenList/v4/pkg/utils/random"
|
||||
"github.com/go-resty/resty/v2"
|
||||
jsoniter "github.com/json-iterator/go"
|
||||
log "github.com/sirupsen/logrus"
|
||||
|
@ -5,10 +5,10 @@ import (
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
"github.com/OpenListTeam/OpenList/drivers/base"
|
||||
"github.com/OpenListTeam/OpenList/internal/driver"
|
||||
"github.com/OpenListTeam/OpenList/internal/model"
|
||||
"github.com/OpenListTeam/OpenList/pkg/utils"
|
||||
"github.com/OpenListTeam/OpenList/v4/drivers/base"
|
||||
"github.com/OpenListTeam/OpenList/v4/internal/driver"
|
||||
"github.com/OpenListTeam/OpenList/v4/internal/model"
|
||||
"github.com/OpenListTeam/OpenList/v4/pkg/utils"
|
||||
"github.com/go-resty/resty/v2"
|
||||
log "github.com/sirupsen/logrus"
|
||||
)
|
||||
|
@ -18,7 +18,7 @@ import (
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
myrand "github.com/OpenListTeam/OpenList/pkg/utils/random"
|
||||
myrand "github.com/OpenListTeam/OpenList/v4/pkg/utils/random"
|
||||
log "github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
|
@ -4,7 +4,7 @@ import (
|
||||
"errors"
|
||||
"strconv"
|
||||
|
||||
"github.com/OpenListTeam/OpenList/pkg/utils"
|
||||
"github.com/OpenListTeam/OpenList/v4/pkg/utils"
|
||||
log "github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
|
@ -1,8 +1,8 @@
|
||||
package _189
|
||||
|
||||
import (
|
||||
"github.com/OpenListTeam/OpenList/internal/driver"
|
||||
"github.com/OpenListTeam/OpenList/internal/op"
|
||||
"github.com/OpenListTeam/OpenList/v4/internal/driver"
|
||||
"github.com/OpenListTeam/OpenList/v4/internal/op"
|
||||
)
|
||||
|
||||
type Addition struct {
|
||||
|
@ -15,11 +15,11 @@ import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/OpenListTeam/OpenList/drivers/base"
|
||||
"github.com/OpenListTeam/OpenList/internal/driver"
|
||||
"github.com/OpenListTeam/OpenList/internal/model"
|
||||
"github.com/OpenListTeam/OpenList/pkg/utils"
|
||||
myrand "github.com/OpenListTeam/OpenList/pkg/utils/random"
|
||||
"github.com/OpenListTeam/OpenList/v4/drivers/base"
|
||||
"github.com/OpenListTeam/OpenList/v4/internal/driver"
|
||||
"github.com/OpenListTeam/OpenList/v4/internal/model"
|
||||
"github.com/OpenListTeam/OpenList/v4/pkg/utils"
|
||||
myrand "github.com/OpenListTeam/OpenList/v4/pkg/utils/random"
|
||||
"github.com/go-resty/resty/v2"
|
||||
jsoniter "github.com/json-iterator/go"
|
||||
log "github.com/sirupsen/logrus"
|
||||
|
274
drivers/189_tv/driver.go
Normal file
274
drivers/189_tv/driver.go
Normal file
@ -0,0 +1,274 @@
|
||||
package _189_tv
|
||||
|
||||
import (
|
||||
"container/ring"
|
||||
"context"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/OpenListTeam/OpenList/v4/drivers/base"
|
||||
"github.com/OpenListTeam/OpenList/v4/internal/driver"
|
||||
"github.com/OpenListTeam/OpenList/v4/internal/errs"
|
||||
"github.com/OpenListTeam/OpenList/v4/internal/model"
|
||||
"github.com/go-resty/resty/v2"
|
||||
)
|
||||
|
||||
type Cloud189TV struct {
|
||||
model.Storage
|
||||
Addition
|
||||
client *resty.Client
|
||||
tokenInfo *AppSessionResp
|
||||
uploadThread int
|
||||
familyTransferFolder *ring.Ring
|
||||
cleanFamilyTransferFile func()
|
||||
storageConfig driver.Config
|
||||
}
|
||||
|
||||
func (y *Cloud189TV) Config() driver.Config {
|
||||
if y.storageConfig.Name == "" {
|
||||
y.storageConfig = config
|
||||
}
|
||||
return y.storageConfig
|
||||
}
|
||||
|
||||
func (y *Cloud189TV) GetAddition() driver.Additional {
|
||||
return &y.Addition
|
||||
}
|
||||
|
||||
func (y *Cloud189TV) Init(ctx context.Context) (err error) {
|
||||
// 兼容旧上传接口
|
||||
y.storageConfig.NoOverwriteUpload = y.isFamily() && y.Addition.RapidUpload
|
||||
|
||||
// 处理个人云和家庭云参数
|
||||
if y.isFamily() && y.RootFolderID == "-11" {
|
||||
y.RootFolderID = ""
|
||||
}
|
||||
if !y.isFamily() && y.RootFolderID == "" {
|
||||
y.RootFolderID = "-11"
|
||||
}
|
||||
|
||||
// 限制上传线程数
|
||||
y.uploadThread, _ = strconv.Atoi(y.UploadThread)
|
||||
if y.uploadThread < 1 || y.uploadThread > 32 {
|
||||
y.uploadThread, y.UploadThread = 3, "3"
|
||||
}
|
||||
|
||||
// 初始化请求客户端
|
||||
if y.client == nil {
|
||||
y.client = base.NewRestyClient().SetHeaders(
|
||||
map[string]string{
|
||||
"Accept": "application/json;charset=UTF-8",
|
||||
"User-Agent": "EcloudTV/6.5.5 (PJX110; unknown; home02) Android/35",
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
// 避免重复登陆
|
||||
if !y.isLogin() || y.Addition.AccessToken == "" {
|
||||
if err = y.login(); err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// 处理家庭云ID
|
||||
if y.FamilyID == "" {
|
||||
if y.FamilyID, err = y.getFamilyID(); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func (y *Cloud189TV) Drop(ctx context.Context) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (y *Cloud189TV) List(ctx context.Context, dir model.Obj, args model.ListArgs) ([]model.Obj, error) {
|
||||
return y.getFiles(ctx, dir.GetID(), y.isFamily())
|
||||
}
|
||||
|
||||
func (y *Cloud189TV) Link(ctx context.Context, file model.Obj, args model.LinkArgs) (*model.Link, error) {
|
||||
var downloadUrl struct {
|
||||
URL string `json:"fileDownloadUrl"`
|
||||
}
|
||||
|
||||
isFamily := y.isFamily()
|
||||
fullUrl := ApiUrl
|
||||
if isFamily {
|
||||
fullUrl += "/family/file"
|
||||
}
|
||||
fullUrl += "/getFileDownloadUrl.action"
|
||||
|
||||
_, err := y.get(fullUrl, func(r *resty.Request) {
|
||||
r.SetContext(ctx)
|
||||
r.SetQueryParam("fileId", file.GetID())
|
||||
if isFamily {
|
||||
r.SetQueryParams(map[string]string{
|
||||
"familyId": y.FamilyID,
|
||||
})
|
||||
} else {
|
||||
r.SetQueryParams(map[string]string{
|
||||
"dt": "3",
|
||||
"flag": "1",
|
||||
})
|
||||
}
|
||||
}, &downloadUrl, isFamily)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// 重定向获取真实链接
|
||||
downloadUrl.URL = strings.Replace(strings.ReplaceAll(downloadUrl.URL, "&", "&"), "http://", "https://", 1)
|
||||
res, err := base.NoRedirectClient.R().SetContext(ctx).SetDoNotParseResponse(true).Get(downloadUrl.URL)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer res.RawBody().Close()
|
||||
if res.StatusCode() == 302 {
|
||||
downloadUrl.URL = res.Header().Get("location")
|
||||
}
|
||||
|
||||
like := &model.Link{
|
||||
URL: downloadUrl.URL,
|
||||
Header: http.Header{
|
||||
"User-Agent": []string{base.UserAgent},
|
||||
},
|
||||
}
|
||||
|
||||
return like, nil
|
||||
}
|
||||
|
||||
func (y *Cloud189TV) MakeDir(ctx context.Context, parentDir model.Obj, dirName string) (model.Obj, error) {
|
||||
isFamily := y.isFamily()
|
||||
fullUrl := ApiUrl
|
||||
if isFamily {
|
||||
fullUrl += "/family/file"
|
||||
}
|
||||
fullUrl += "/createFolder.action"
|
||||
|
||||
var newFolder Cloud189Folder
|
||||
_, err := y.post(fullUrl, func(req *resty.Request) {
|
||||
req.SetContext(ctx)
|
||||
req.SetQueryParams(map[string]string{
|
||||
"folderName": dirName,
|
||||
"relativePath": "",
|
||||
})
|
||||
if isFamily {
|
||||
req.SetQueryParams(map[string]string{
|
||||
"familyId": y.FamilyID,
|
||||
"parentId": parentDir.GetID(),
|
||||
})
|
||||
} else {
|
||||
req.SetQueryParams(map[string]string{
|
||||
"parentFolderId": parentDir.GetID(),
|
||||
})
|
||||
}
|
||||
}, &newFolder, isFamily)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &newFolder, nil
|
||||
}
|
||||
|
||||
func (y *Cloud189TV) Move(ctx context.Context, srcObj, dstDir model.Obj) (model.Obj, error) {
|
||||
isFamily := y.isFamily()
|
||||
other := map[string]string{"targetFileName": dstDir.GetName()}
|
||||
|
||||
resp, err := y.CreateBatchTask("MOVE", IF(isFamily, y.FamilyID, ""), dstDir.GetID(), other, BatchTaskInfo{
|
||||
FileId: srcObj.GetID(),
|
||||
FileName: srcObj.GetName(),
|
||||
IsFolder: BoolToNumber(srcObj.IsDir()),
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err = y.WaitBatchTask("MOVE", resp.TaskID, time.Millisecond*400); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return srcObj, nil
|
||||
}
|
||||
|
||||
func (y *Cloud189TV) Rename(ctx context.Context, srcObj model.Obj, newName string) (model.Obj, error) {
|
||||
isFamily := y.isFamily()
|
||||
queryParam := make(map[string]string)
|
||||
fullUrl := ApiUrl
|
||||
method := http.MethodPost
|
||||
if isFamily {
|
||||
fullUrl += "/family/file"
|
||||
method = http.MethodGet
|
||||
queryParam["familyId"] = y.FamilyID
|
||||
}
|
||||
|
||||
var newObj model.Obj
|
||||
switch f := srcObj.(type) {
|
||||
case *Cloud189File:
|
||||
fullUrl += "/renameFile.action"
|
||||
queryParam["fileId"] = srcObj.GetID()
|
||||
queryParam["destFileName"] = newName
|
||||
newObj = &Cloud189File{Icon: f.Icon} // 复用预览
|
||||
case *Cloud189Folder:
|
||||
fullUrl += "/renameFolder.action"
|
||||
queryParam["folderId"] = srcObj.GetID()
|
||||
queryParam["destFolderName"] = newName
|
||||
newObj = &Cloud189Folder{}
|
||||
default:
|
||||
return nil, errs.NotSupport
|
||||
}
|
||||
|
||||
_, err := y.request(fullUrl, method, func(req *resty.Request) {
|
||||
req.SetContext(ctx).SetQueryParams(queryParam)
|
||||
}, nil, newObj, isFamily)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return newObj, nil
|
||||
}
|
||||
|
||||
func (y *Cloud189TV) Copy(ctx context.Context, srcObj, dstDir model.Obj) error {
|
||||
isFamily := y.isFamily()
|
||||
other := map[string]string{"targetFileName": dstDir.GetName()}
|
||||
|
||||
resp, err := y.CreateBatchTask("COPY", IF(isFamily, y.FamilyID, ""), dstDir.GetID(), other, BatchTaskInfo{
|
||||
FileId: srcObj.GetID(),
|
||||
FileName: srcObj.GetName(),
|
||||
IsFolder: BoolToNumber(srcObj.IsDir()),
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return y.WaitBatchTask("COPY", resp.TaskID, time.Second)
|
||||
}
|
||||
|
||||
func (y *Cloud189TV) Remove(ctx context.Context, obj model.Obj) error {
|
||||
isFamily := y.isFamily()
|
||||
|
||||
resp, err := y.CreateBatchTask("DELETE", IF(isFamily, y.FamilyID, ""), "", nil, BatchTaskInfo{
|
||||
FileId: obj.GetID(),
|
||||
FileName: obj.GetName(),
|
||||
IsFolder: BoolToNumber(obj.IsDir()),
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// 批量任务数量限制,过快会导致无法删除
|
||||
return y.WaitBatchTask("DELETE", resp.TaskID, time.Millisecond*200)
|
||||
}
|
||||
|
||||
func (y *Cloud189TV) Put(ctx context.Context, dstDir model.Obj, stream model.FileStreamer, up driver.UpdateProgress) (newObj model.Obj, err error) {
|
||||
overwrite := true
|
||||
isFamily := y.isFamily()
|
||||
|
||||
// 响应时间长,按需启用
|
||||
if y.Addition.RapidUpload && !stream.IsForceStreamUpload() {
|
||||
if newObj, err := y.RapidUpload(ctx, dstDir, stream, isFamily, overwrite); err == nil {
|
||||
return newObj, nil
|
||||
}
|
||||
}
|
||||
|
||||
return y.OldUpload(ctx, dstDir, stream, up, isFamily, overwrite)
|
||||
|
||||
}
|
166
drivers/189_tv/help.go
Normal file
166
drivers/189_tv/help.go
Normal file
@ -0,0 +1,166 @@
|
||||
package _189_tv
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/hmac"
|
||||
"crypto/sha1"
|
||||
"encoding/hex"
|
||||
"encoding/xml"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"regexp"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
func clientSuffix() map[string]string {
|
||||
return map[string]string{
|
||||
"clientType": AndroidTV,
|
||||
"version": TvVersion,
|
||||
"channelId": TvChannelId,
|
||||
"clientSn": "unknown",
|
||||
"model": "PJX110",
|
||||
"osFamily": "Android",
|
||||
"osVersion": "35",
|
||||
"networkAccessMode": "WIFI",
|
||||
"telecomsOperator": "46011",
|
||||
}
|
||||
}
|
||||
|
||||
// SessionKeySignatureOfHmac HMAC签名
|
||||
func SessionKeySignatureOfHmac(sessionSecret, sessionKey, operate, fullUrl, dateOfGmt string) string {
|
||||
urlpath := regexp.MustCompile(`://[^/]+((/[^/\s?#]+)*)`).FindStringSubmatch(fullUrl)[1]
|
||||
mac := hmac.New(sha1.New, []byte(sessionSecret))
|
||||
data := fmt.Sprintf("SessionKey=%s&Operate=%s&RequestURI=%s&Date=%s", sessionKey, operate, urlpath, dateOfGmt)
|
||||
mac.Write([]byte(data))
|
||||
return strings.ToUpper(hex.EncodeToString(mac.Sum(nil)))
|
||||
}
|
||||
|
||||
// AppKeySignatureOfHmac HMAC签名
|
||||
func AppKeySignatureOfHmac(sessionSecret, appKey, operate, fullUrl string, timestamp int64) string {
|
||||
urlpath := regexp.MustCompile(`://[^/]+((/[^/\s?#]+)*)`).FindStringSubmatch(fullUrl)[1]
|
||||
mac := hmac.New(sha1.New, []byte(sessionSecret))
|
||||
data := fmt.Sprintf("AppKey=%s&Operate=%s&RequestURI=%s&Timestamp=%d", appKey, operate, urlpath, timestamp)
|
||||
mac.Write([]byte(data))
|
||||
return strings.ToUpper(hex.EncodeToString(mac.Sum(nil)))
|
||||
}
|
||||
|
||||
// 获取http规范的时间
|
||||
func getHttpDateStr() string {
|
||||
return time.Now().UTC().Format(http.TimeFormat)
|
||||
}
|
||||
|
||||
// 时间戳
|
||||
func timestamp() int64 {
|
||||
return time.Now().UTC().UnixNano() / 1e6
|
||||
}
|
||||
|
||||
type Time time.Time
|
||||
|
||||
func (t *Time) UnmarshalJSON(b []byte) error { return t.Unmarshal(b) }
|
||||
func (t *Time) UnmarshalXML(e *xml.Decoder, ee xml.StartElement) error {
|
||||
b, err := e.Token()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if b, ok := b.(xml.CharData); ok {
|
||||
if err = t.Unmarshal(b); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return e.Skip()
|
||||
}
|
||||
func (t *Time) Unmarshal(b []byte) error {
|
||||
bs := strings.Trim(string(b), "\"")
|
||||
var v time.Time
|
||||
var err error
|
||||
for _, f := range []string{"2006-01-02 15:04:05 -07", "Jan 2, 2006 15:04:05 PM -07"} {
|
||||
v, err = time.ParseInLocation(f, bs+" +08", time.Local)
|
||||
if err == nil {
|
||||
break
|
||||
}
|
||||
}
|
||||
*t = Time(v)
|
||||
return err
|
||||
}
|
||||
|
||||
type String string
|
||||
|
||||
func (t *String) UnmarshalJSON(b []byte) error { return t.Unmarshal(b) }
|
||||
func (t *String) UnmarshalXML(e *xml.Decoder, ee xml.StartElement) error {
|
||||
b, err := e.Token()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if b, ok := b.(xml.CharData); ok {
|
||||
if err = t.Unmarshal(b); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return e.Skip()
|
||||
}
|
||||
func (s *String) Unmarshal(b []byte) error {
|
||||
*s = String(bytes.Trim(b, "\""))
|
||||
return nil
|
||||
}
|
||||
|
||||
func toFamilyOrderBy(o string) string {
|
||||
switch o {
|
||||
case "filename":
|
||||
return "1"
|
||||
case "filesize":
|
||||
return "2"
|
||||
case "lastOpTime":
|
||||
return "3"
|
||||
default:
|
||||
return "1"
|
||||
}
|
||||
}
|
||||
|
||||
func toDesc(o string) string {
|
||||
switch o {
|
||||
case "desc":
|
||||
return "true"
|
||||
case "asc":
|
||||
fallthrough
|
||||
default:
|
||||
return "false"
|
||||
}
|
||||
}
|
||||
|
||||
func ParseHttpHeader(str string) map[string]string {
|
||||
header := make(map[string]string)
|
||||
for _, value := range strings.Split(str, "&") {
|
||||
if k, v, found := strings.Cut(value, "="); found {
|
||||
header[k] = v
|
||||
}
|
||||
}
|
||||
return header
|
||||
}
|
||||
|
||||
func MustString(str string, err error) string {
|
||||
return str
|
||||
}
|
||||
|
||||
func BoolToNumber(b bool) int {
|
||||
if b {
|
||||
return 1
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func isBool(bs ...bool) bool {
|
||||
for _, b := range bs {
|
||||
if b {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func IF[V any](o bool, t V, f V) V {
|
||||
if o {
|
||||
return t
|
||||
}
|
||||
return f
|
||||
}
|
30
drivers/189_tv/meta.go
Normal file
30
drivers/189_tv/meta.go
Normal file
@ -0,0 +1,30 @@
|
||||
package _189_tv
|
||||
|
||||
import (
|
||||
"github.com/OpenListTeam/OpenList/v4/internal/driver"
|
||||
"github.com/OpenListTeam/OpenList/v4/internal/op"
|
||||
)
|
||||
|
||||
type Addition struct {
|
||||
driver.RootID
|
||||
AccessToken string `json:"access_token"`
|
||||
TempUuid string
|
||||
OrderBy string `json:"order_by" type:"select" options:"filename,filesize,lastOpTime" default:"filename"`
|
||||
OrderDirection string `json:"order_direction" type:"select" options:"asc,desc" default:"asc"`
|
||||
Type string `json:"type" type:"select" options:"personal,family" default:"personal"`
|
||||
FamilyID string `json:"family_id"`
|
||||
UploadThread string `json:"upload_thread" default:"3" help:"1<=thread<=32"`
|
||||
RapidUpload bool `json:"rapid_upload"`
|
||||
}
|
||||
|
||||
var config = driver.Config{
|
||||
Name: "189CloudTV",
|
||||
DefaultRoot: "-11",
|
||||
CheckStatus: true,
|
||||
}
|
||||
|
||||
func init() {
|
||||
op.RegisterDriver(func() driver.Driver {
|
||||
return &Cloud189TV{}
|
||||
})
|
||||
}
|
318
drivers/189_tv/types.go
Normal file
318
drivers/189_tv/types.go
Normal file
@ -0,0 +1,318 @@
|
||||
package _189_tv
|
||||
|
||||
import (
|
||||
"encoding/xml"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/OpenListTeam/OpenList/v4/pkg/utils"
|
||||
)
|
||||
|
||||
// 居然有四种返回方式
|
||||
type RespErr struct {
|
||||
ResCode any `json:"res_code"` // int or string
|
||||
ResMessage string `json:"res_message"`
|
||||
|
||||
Error_ string `json:"error"`
|
||||
|
||||
XMLName xml.Name `xml:"error"`
|
||||
Code string `json:"code" xml:"code"`
|
||||
Message string `json:"message" xml:"message"`
|
||||
Msg string `json:"msg"`
|
||||
|
||||
ErrorCode string `json:"errorCode"`
|
||||
ErrorMsg string `json:"errorMsg"`
|
||||
}
|
||||
|
||||
func (e *RespErr) HasError() bool {
|
||||
switch v := e.ResCode.(type) {
|
||||
case int, int64, int32:
|
||||
return v != 0
|
||||
case string:
|
||||
return e.ResCode != ""
|
||||
}
|
||||
return (e.Code != "" && e.Code != "SUCCESS") || e.ErrorCode != "" || e.Error_ != ""
|
||||
}
|
||||
|
||||
func (e *RespErr) Error() string {
|
||||
switch v := e.ResCode.(type) {
|
||||
case int, int64, int32:
|
||||
if v != 0 {
|
||||
return fmt.Sprintf("res_code: %d ,res_msg: %s", v, e.ResMessage)
|
||||
}
|
||||
case string:
|
||||
if e.ResCode != "" {
|
||||
return fmt.Sprintf("res_code: %s ,res_msg: %s", e.ResCode, e.ResMessage)
|
||||
}
|
||||
}
|
||||
|
||||
if e.Code != "" && e.Code != "SUCCESS" {
|
||||
if e.Msg != "" {
|
||||
return fmt.Sprintf("code: %s ,msg: %s", e.Code, e.Msg)
|
||||
}
|
||||
if e.Message != "" {
|
||||
return fmt.Sprintf("code: %s ,msg: %s", e.Code, e.Message)
|
||||
}
|
||||
return "code: " + e.Code
|
||||
}
|
||||
|
||||
if e.ErrorCode != "" {
|
||||
return fmt.Sprintf("err_code: %s ,err_msg: %s", e.ErrorCode, e.ErrorMsg)
|
||||
}
|
||||
|
||||
if e.Error_ != "" {
|
||||
return fmt.Sprintf("error: %s ,message: %s", e.ErrorCode, e.Message)
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
// 刷新session返回
|
||||
type UserSessionResp struct {
|
||||
ResCode int `json:"res_code"`
|
||||
ResMessage string `json:"res_message"`
|
||||
|
||||
LoginName string `json:"loginName"`
|
||||
|
||||
KeepAlive int `json:"keepAlive"`
|
||||
GetFileDiffSpan int `json:"getFileDiffSpan"`
|
||||
GetUserInfoSpan int `json:"getUserInfoSpan"`
|
||||
|
||||
// 个人云
|
||||
SessionKey string `json:"sessionKey"`
|
||||
SessionSecret string `json:"sessionSecret"`
|
||||
// 家庭云
|
||||
FamilySessionKey string `json:"familySessionKey"`
|
||||
FamilySessionSecret string `json:"familySessionSecret"`
|
||||
}
|
||||
|
||||
type UuidInfoResp struct {
|
||||
Uuid string `json:"uuid"`
|
||||
}
|
||||
|
||||
type E189AccessTokenResp struct {
|
||||
E189AccessToken string `json:"accessToken"`
|
||||
ExpiresIn int64 `json:"expiresIn"`
|
||||
}
|
||||
|
||||
// 登录返回
|
||||
type AppSessionResp struct {
|
||||
UserSessionResp
|
||||
|
||||
IsSaveName string `json:"isSaveName"`
|
||||
|
||||
// 会话刷新Token
|
||||
AccessToken string `json:"accessToken"`
|
||||
//Token刷新
|
||||
RefreshToken string `json:"refreshToken"`
|
||||
}
|
||||
|
||||
// 家庭云账户
|
||||
type FamilyInfoListResp struct {
|
||||
FamilyInfoResp []FamilyInfoResp `json:"familyInfoResp"`
|
||||
}
|
||||
type FamilyInfoResp struct {
|
||||
Count int `json:"count"`
|
||||
CreateTime string `json:"createTime"`
|
||||
FamilyID int64 `json:"familyId"`
|
||||
RemarkName string `json:"remarkName"`
|
||||
Type int `json:"type"`
|
||||
UseFlag int `json:"useFlag"`
|
||||
UserRole int `json:"userRole"`
|
||||
}
|
||||
|
||||
/*文件部分*/
|
||||
// 文件
|
||||
type Cloud189File struct {
|
||||
ID String `json:"id"`
|
||||
Name string `json:"name"`
|
||||
Size int64 `json:"size"`
|
||||
Md5 string `json:"md5"`
|
||||
|
||||
LastOpTime Time `json:"lastOpTime"`
|
||||
CreateDate Time `json:"createDate"`
|
||||
Icon struct {
|
||||
//iconOption 5
|
||||
SmallUrl string `json:"smallUrl"`
|
||||
LargeUrl string `json:"largeUrl"`
|
||||
|
||||
// iconOption 10
|
||||
Max600 string `json:"max600"`
|
||||
MediumURL string `json:"mediumUrl"`
|
||||
} `json:"icon"`
|
||||
|
||||
// Orientation int64 `json:"orientation"`
|
||||
// FileCata int64 `json:"fileCata"`
|
||||
// MediaType int `json:"mediaType"`
|
||||
// Rev string `json:"rev"`
|
||||
// StarLabel int64 `json:"starLabel"`
|
||||
}
|
||||
|
||||
func (c *Cloud189File) CreateTime() time.Time {
|
||||
return time.Time(c.CreateDate)
|
||||
}
|
||||
|
||||
func (c *Cloud189File) GetHash() utils.HashInfo {
|
||||
return utils.NewHashInfo(utils.MD5, c.Md5)
|
||||
}
|
||||
|
||||
func (c *Cloud189File) GetSize() int64 { return c.Size }
|
||||
func (c *Cloud189File) GetName() string { return c.Name }
|
||||
func (c *Cloud189File) ModTime() time.Time { return time.Time(c.LastOpTime) }
|
||||
func (c *Cloud189File) IsDir() bool { return false }
|
||||
func (c *Cloud189File) GetID() string { return string(c.ID) }
|
||||
func (c *Cloud189File) GetPath() string { return "" }
|
||||
func (c *Cloud189File) Thumb() string { return c.Icon.SmallUrl }
|
||||
|
||||
// 文件夹
|
||||
type Cloud189Folder struct {
|
||||
ID String `json:"id"`
|
||||
ParentID int64 `json:"parentId"`
|
||||
Name string `json:"name"`
|
||||
|
||||
LastOpTime Time `json:"lastOpTime"`
|
||||
CreateDate Time `json:"createDate"`
|
||||
|
||||
// FileListSize int64 `json:"fileListSize"`
|
||||
// FileCount int64 `json:"fileCount"`
|
||||
// FileCata int64 `json:"fileCata"`
|
||||
// Rev string `json:"rev"`
|
||||
// StarLabel int64 `json:"starLabel"`
|
||||
}
|
||||
|
||||
func (c *Cloud189Folder) CreateTime() time.Time {
|
||||
return time.Time(c.CreateDate)
|
||||
}
|
||||
|
||||
func (c *Cloud189Folder) GetHash() utils.HashInfo {
|
||||
return utils.HashInfo{}
|
||||
}
|
||||
|
||||
func (c *Cloud189Folder) GetSize() int64 { return 0 }
|
||||
func (c *Cloud189Folder) GetName() string { return c.Name }
|
||||
func (c *Cloud189Folder) ModTime() time.Time { return time.Time(c.LastOpTime) }
|
||||
func (c *Cloud189Folder) IsDir() bool { return true }
|
||||
func (c *Cloud189Folder) GetID() string { return string(c.ID) }
|
||||
func (c *Cloud189Folder) GetPath() string { return "" }
|
||||
|
||||
type Cloud189FilesResp struct {
|
||||
//ResCode int `json:"res_code"`
|
||||
//ResMessage string `json:"res_message"`
|
||||
FileListAO struct {
|
||||
Count int `json:"count"`
|
||||
FileList []Cloud189File `json:"fileList"`
|
||||
FolderList []Cloud189Folder `json:"folderList"`
|
||||
} `json:"fileListAO"`
|
||||
}
|
||||
|
||||
// TaskInfo 任务信息
|
||||
type BatchTaskInfo struct {
|
||||
// FileId 文件ID
|
||||
FileId string `json:"fileId"`
|
||||
// FileName 文件名
|
||||
FileName string `json:"fileName"`
|
||||
// IsFolder 是否是文件夹,0-否,1-是
|
||||
IsFolder int `json:"isFolder"`
|
||||
// SrcParentId 文件所在父目录ID
|
||||
SrcParentId string `json:"srcParentId,omitempty"`
|
||||
|
||||
/* 冲突管理 */
|
||||
// 1 -> 跳过 2 -> 保留 3 -> 覆盖
|
||||
DealWay int `json:"dealWay,omitempty"`
|
||||
IsConflict int `json:"isConflict,omitempty"`
|
||||
}
|
||||
|
||||
/* 上传部分 */
|
||||
type InitMultiUploadResp struct {
|
||||
//Code string `json:"code"`
|
||||
Data struct {
|
||||
UploadType int `json:"uploadType"`
|
||||
UploadHost string `json:"uploadHost"`
|
||||
UploadFileID string `json:"uploadFileId"`
|
||||
FileDataExists int `json:"fileDataExists"`
|
||||
} `json:"data"`
|
||||
}
|
||||
type UploadUrlsResp struct {
|
||||
Code string `json:"code"`
|
||||
Data map[string]UploadUrlsData `json:"uploadUrls"`
|
||||
}
|
||||
type UploadUrlsData struct {
|
||||
RequestURL string `json:"requestURL"`
|
||||
RequestHeader string `json:"requestHeader"`
|
||||
}
|
||||
|
||||
/* 第二种上传方式 */
|
||||
type CreateUploadFileResp struct {
|
||||
// 上传文件请求ID
|
||||
UploadFileId int64 `json:"uploadFileId"`
|
||||
// 上传文件数据的URL路径
|
||||
FileUploadUrl string `json:"fileUploadUrl"`
|
||||
// 上传文件完成后确认路径
|
||||
FileCommitUrl string `json:"fileCommitUrl"`
|
||||
// 文件是否已存在云盘中,0-未存在,1-已存在
|
||||
FileDataExists int `json:"fileDataExists"`
|
||||
}
|
||||
|
||||
type GetUploadFileStatusResp struct {
|
||||
CreateUploadFileResp
|
||||
|
||||
// 已上传的大小
|
||||
DataSize int64 `json:"dataSize"`
|
||||
Size int64 `json:"size"`
|
||||
}
|
||||
|
||||
func (r *GetUploadFileStatusResp) GetSize() int64 {
|
||||
return r.DataSize + r.Size
|
||||
}
|
||||
|
||||
type CommitMultiUploadFileResp struct {
|
||||
File struct {
|
||||
UserFileID String `json:"userFileId"`
|
||||
FileName string `json:"fileName"`
|
||||
FileSize int64 `json:"fileSize"`
|
||||
FileMd5 string `json:"fileMd5"`
|
||||
CreateDate Time `json:"createDate"`
|
||||
} `json:"file"`
|
||||
}
|
||||
|
||||
type OldCommitUploadFileResp struct {
|
||||
XMLName xml.Name `xml:"file"`
|
||||
ID String `xml:"id"`
|
||||
Name string `xml:"name"`
|
||||
Size int64 `xml:"size"`
|
||||
Md5 string `xml:"md5"`
|
||||
CreateDate Time `xml:"createDate"`
|
||||
}
|
||||
|
||||
func (f *OldCommitUploadFileResp) toFile() *Cloud189File {
|
||||
return &Cloud189File{
|
||||
ID: f.ID,
|
||||
Name: f.Name,
|
||||
Size: f.Size,
|
||||
Md5: f.Md5,
|
||||
CreateDate: f.CreateDate,
|
||||
LastOpTime: f.CreateDate,
|
||||
}
|
||||
}
|
||||
|
||||
type CreateBatchTaskResp struct {
|
||||
TaskID string `json:"taskId"`
|
||||
}
|
||||
|
||||
type BatchTaskStateResp struct {
|
||||
FailedCount int `json:"failedCount"`
|
||||
Process int `json:"process"`
|
||||
SkipCount int `json:"skipCount"`
|
||||
SubTaskCount int `json:"subTaskCount"`
|
||||
SuccessedCount int `json:"successedCount"`
|
||||
SuccessedFileIDList []int64 `json:"successedFileIdList"`
|
||||
TaskID string `json:"taskId"`
|
||||
TaskStatus int `json:"taskStatus"` //1 初始化 2 存在冲突 3 执行中,4 完成
|
||||
}
|
||||
|
||||
type BatchTaskConflictTaskInfoResp struct {
|
||||
SessionKey string `json:"sessionKey"`
|
||||
TargetFolderID int `json:"targetFolderId"`
|
||||
TaskID string `json:"taskId"`
|
||||
TaskInfos []BatchTaskInfo
|
||||
TaskType int `json:"taskType"`
|
||||
}
|
564
drivers/189_tv/utils.go
Normal file
564
drivers/189_tv/utils.go
Normal file
@ -0,0 +1,564 @@
|
||||
package _189_tv
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/base64"
|
||||
"encoding/xml"
|
||||
"fmt"
|
||||
"github.com/skip2/go-qrcode"
|
||||
"io"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/OpenListTeam/OpenList/v4/drivers/base"
|
||||
"github.com/OpenListTeam/OpenList/v4/internal/driver"
|
||||
"github.com/OpenListTeam/OpenList/v4/internal/model"
|
||||
"github.com/OpenListTeam/OpenList/v4/internal/op"
|
||||
"github.com/OpenListTeam/OpenList/v4/pkg/utils"
|
||||
|
||||
"github.com/go-resty/resty/v2"
|
||||
"github.com/google/uuid"
|
||||
jsoniter "github.com/json-iterator/go"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
const (
|
||||
TVAppKey = "600100885"
|
||||
TVAppSignatureSecre = "fe5734c74c2f96a38157f420b32dc995"
|
||||
TvVersion = "6.5.5"
|
||||
AndroidTV = "FAMILY_TV"
|
||||
TvChannelId = "home02"
|
||||
|
||||
ApiUrl = "https://api.cloud.189.cn"
|
||||
)
|
||||
|
||||
func (y *Cloud189TV) SignatureHeader(url, method string, isFamily bool) map[string]string {
|
||||
dateOfGmt := getHttpDateStr()
|
||||
sessionKey := y.tokenInfo.SessionKey
|
||||
sessionSecret := y.tokenInfo.SessionSecret
|
||||
if isFamily {
|
||||
sessionKey = y.tokenInfo.FamilySessionKey
|
||||
sessionSecret = y.tokenInfo.FamilySessionSecret
|
||||
}
|
||||
|
||||
header := map[string]string{
|
||||
"Date": dateOfGmt,
|
||||
"SessionKey": sessionKey,
|
||||
"X-Request-ID": uuid.NewString(),
|
||||
"Signature": SessionKeySignatureOfHmac(sessionSecret, sessionKey, method, url, dateOfGmt),
|
||||
}
|
||||
return header
|
||||
}
|
||||
|
||||
func (y *Cloud189TV) AppKeySignatureHeader(url, method string) map[string]string {
|
||||
tempTime := timestamp()
|
||||
header := map[string]string{
|
||||
"Timestamp": strconv.FormatInt(tempTime, 10),
|
||||
"X-Request-ID": uuid.NewString(),
|
||||
"AppKey": TVAppKey,
|
||||
"AppSignature": AppKeySignatureOfHmac(TVAppSignatureSecre, TVAppKey, method, url, tempTime),
|
||||
}
|
||||
return header
|
||||
}
|
||||
|
||||
func (y *Cloud189TV) request(url, method string, callback base.ReqCallback, params map[string]string, resp interface{}, isFamily ...bool) ([]byte, error) {
|
||||
req := y.client.R().SetQueryParams(clientSuffix())
|
||||
|
||||
if params != nil {
|
||||
req.SetQueryParams(params)
|
||||
}
|
||||
|
||||
// Signature
|
||||
req.SetHeaders(y.SignatureHeader(url, method, isBool(isFamily...)))
|
||||
|
||||
var erron RespErr
|
||||
req.SetError(&erron)
|
||||
|
||||
if callback != nil {
|
||||
callback(req)
|
||||
}
|
||||
if resp != nil {
|
||||
req.SetResult(resp)
|
||||
}
|
||||
res, err := req.Execute(method, url)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if strings.Contains(res.String(), "userSessionBO is null") ||
|
||||
strings.Contains(res.String(), "InvalidSessionKey") {
|
||||
return nil, errors.New("session expired")
|
||||
}
|
||||
|
||||
// 处理错误
|
||||
if erron.HasError() {
|
||||
return nil, &erron
|
||||
}
|
||||
return res.Body(), nil
|
||||
}
|
||||
|
||||
func (y *Cloud189TV) get(url string, callback base.ReqCallback, resp interface{}, isFamily ...bool) ([]byte, error) {
|
||||
return y.request(url, http.MethodGet, callback, nil, resp, isFamily...)
|
||||
}
|
||||
|
||||
func (y *Cloud189TV) post(url string, callback base.ReqCallback, resp interface{}, isFamily ...bool) ([]byte, error) {
|
||||
return y.request(url, http.MethodPost, callback, nil, resp, isFamily...)
|
||||
}
|
||||
|
||||
func (y *Cloud189TV) put(ctx context.Context, url string, headers map[string]string, sign bool, file io.Reader, isFamily bool) ([]byte, error) {
|
||||
req, err := http.NewRequestWithContext(ctx, http.MethodPut, url, file)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
query := req.URL.Query()
|
||||
for key, value := range clientSuffix() {
|
||||
query.Add(key, value)
|
||||
}
|
||||
req.URL.RawQuery = query.Encode()
|
||||
|
||||
for key, value := range headers {
|
||||
req.Header.Add(key, value)
|
||||
}
|
||||
|
||||
if sign {
|
||||
for key, value := range y.SignatureHeader(url, http.MethodPut, isFamily) {
|
||||
req.Header.Add(key, value)
|
||||
}
|
||||
}
|
||||
|
||||
resp, err := base.HttpClient.Do(req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
body, err := io.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var erron RespErr
|
||||
jsoniter.Unmarshal(body, &erron)
|
||||
xml.Unmarshal(body, &erron)
|
||||
if erron.HasError() {
|
||||
return nil, &erron
|
||||
}
|
||||
if resp.StatusCode != http.StatusOK {
|
||||
return nil, errors.Errorf("put fail,err:%s", string(body))
|
||||
}
|
||||
return body, nil
|
||||
}
|
||||
func (y *Cloud189TV) getFiles(ctx context.Context, fileId string, isFamily bool) ([]model.Obj, error) {
|
||||
fullUrl := ApiUrl
|
||||
if isFamily {
|
||||
fullUrl += "/family/file"
|
||||
}
|
||||
fullUrl += "/listFiles.action"
|
||||
|
||||
res := make([]model.Obj, 0, 130)
|
||||
for pageNum := 1; ; pageNum++ {
|
||||
var resp Cloud189FilesResp
|
||||
_, err := y.get(fullUrl, func(r *resty.Request) {
|
||||
r.SetContext(ctx)
|
||||
r.SetQueryParams(map[string]string{
|
||||
"folderId": fileId,
|
||||
"fileType": "0",
|
||||
"mediaAttr": "0",
|
||||
"iconOption": "5",
|
||||
"pageNum": fmt.Sprint(pageNum),
|
||||
"pageSize": "130",
|
||||
})
|
||||
if isFamily {
|
||||
r.SetQueryParams(map[string]string{
|
||||
"familyId": y.FamilyID,
|
||||
"orderBy": toFamilyOrderBy(y.OrderBy),
|
||||
"descending": toDesc(y.OrderDirection),
|
||||
})
|
||||
} else {
|
||||
r.SetQueryParams(map[string]string{
|
||||
"recursive": "0",
|
||||
"orderBy": y.OrderBy,
|
||||
"descending": toDesc(y.OrderDirection),
|
||||
})
|
||||
}
|
||||
}, &resp, isFamily)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// 获取完毕跳出
|
||||
if resp.FileListAO.Count == 0 {
|
||||
break
|
||||
}
|
||||
|
||||
for i := 0; i < len(resp.FileListAO.FolderList); i++ {
|
||||
res = append(res, &resp.FileListAO.FolderList[i])
|
||||
}
|
||||
for i := 0; i < len(resp.FileListAO.FileList); i++ {
|
||||
res = append(res, &resp.FileListAO.FileList[i])
|
||||
}
|
||||
}
|
||||
return res, nil
|
||||
}
|
||||
|
||||
func (y *Cloud189TV) login() (err error) {
|
||||
req := y.client.R().SetQueryParams(clientSuffix())
|
||||
var erron RespErr
|
||||
var tokenInfo AppSessionResp
|
||||
if y.Addition.AccessToken == "" {
|
||||
if y.Addition.TempUuid == "" {
|
||||
// 获取登录参数
|
||||
var uuidInfo UuidInfoResp
|
||||
req.SetResult(&uuidInfo).SetError(&erron)
|
||||
// Signature
|
||||
req.SetHeaders(y.AppKeySignatureHeader(ApiUrl+"/family/manage/getQrCodeUUID.action",
|
||||
http.MethodGet))
|
||||
_, err = req.Execute(http.MethodGet, ApiUrl+"/family/manage/getQrCodeUUID.action")
|
||||
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if erron.HasError() {
|
||||
return &erron
|
||||
}
|
||||
|
||||
if uuidInfo.Uuid == "" {
|
||||
return errors.New("uuidInfo is empty")
|
||||
}
|
||||
y.Addition.TempUuid = uuidInfo.Uuid
|
||||
op.MustSaveDriverStorage(y)
|
||||
|
||||
// 展示二维码
|
||||
qrTemplate := `<body>
|
||||
<img src="data:image/jpeg;base64,%s"/>
|
||||
<br>Or Click here: <a href="%s">%s</a>
|
||||
</body>`
|
||||
|
||||
// Generate QR code
|
||||
qrCode, err := qrcode.Encode(uuidInfo.Uuid, qrcode.Medium, 256)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to generate QR code: %v", err)
|
||||
}
|
||||
|
||||
// Encode QR code to base64
|
||||
qrCodeBase64 := base64.StdEncoding.EncodeToString(qrCode)
|
||||
|
||||
// Create the HTML page
|
||||
qrPage := fmt.Sprintf(qrTemplate, qrCodeBase64, uuidInfo.Uuid, uuidInfo.Uuid)
|
||||
return fmt.Errorf("need verify: \n%s", qrPage)
|
||||
|
||||
} else {
|
||||
var accessTokenResp E189AccessTokenResp
|
||||
req.SetResult(&accessTokenResp).SetError(&erron)
|
||||
// Signature
|
||||
req.SetHeaders(y.AppKeySignatureHeader(ApiUrl+"/family/manage/qrcodeLoginResult.action",
|
||||
http.MethodGet))
|
||||
req.SetQueryParam("uuid", y.Addition.TempUuid)
|
||||
_, err = req.Execute(http.MethodGet, ApiUrl+"/family/manage/qrcodeLoginResult.action")
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if erron.HasError() {
|
||||
return &erron
|
||||
}
|
||||
if accessTokenResp.E189AccessToken == "" {
|
||||
return errors.New("E189AccessToken is empty")
|
||||
}
|
||||
y.Addition.AccessToken = accessTokenResp.E189AccessToken
|
||||
y.Addition.TempUuid = ""
|
||||
}
|
||||
}
|
||||
// 获取SessionKey 和 SessionSecret
|
||||
reqb := y.client.R().SetQueryParams(clientSuffix())
|
||||
reqb.SetResult(&tokenInfo).SetError(&erron)
|
||||
// Signature
|
||||
reqb.SetHeaders(y.AppKeySignatureHeader(ApiUrl+"/family/manage/loginFamilyMerge.action",
|
||||
http.MethodGet))
|
||||
reqb.SetQueryParam("e189AccessToken", y.Addition.AccessToken)
|
||||
_, err = reqb.Execute(http.MethodGet, ApiUrl+"/family/manage/loginFamilyMerge.action")
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if erron.HasError() {
|
||||
return &erron
|
||||
}
|
||||
|
||||
y.tokenInfo = &tokenInfo
|
||||
op.MustSaveDriverStorage(y)
|
||||
return
|
||||
}
|
||||
|
||||
func (y *Cloud189TV) RapidUpload(ctx context.Context, dstDir model.Obj, stream model.FileStreamer, isFamily bool, overwrite bool) (model.Obj, error) {
|
||||
fileMd5 := stream.GetHash().GetHash(utils.MD5)
|
||||
if len(fileMd5) < utils.MD5.Width {
|
||||
return nil, errors.New("invalid hash")
|
||||
}
|
||||
|
||||
uploadInfo, err := y.OldUploadCreate(ctx, dstDir.GetID(), fileMd5, stream.GetName(), fmt.Sprint(stream.GetSize()), isFamily)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if uploadInfo.FileDataExists != 1 {
|
||||
return nil, errors.New("rapid upload fail")
|
||||
}
|
||||
|
||||
return y.OldUploadCommit(ctx, uploadInfo.FileCommitUrl, uploadInfo.UploadFileId, isFamily, overwrite)
|
||||
}
|
||||
|
||||
// 旧版本上传,家庭云不支持覆盖
|
||||
func (y *Cloud189TV) OldUpload(ctx context.Context, dstDir model.Obj, file model.FileStreamer, up driver.UpdateProgress, isFamily bool, overwrite bool) (model.Obj, error) {
|
||||
tempFile, err := file.CacheFullInTempFile()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
fileMd5, err := utils.HashFile(utils.MD5, tempFile)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// 创建上传会话
|
||||
uploadInfo, err := y.OldUploadCreate(ctx, dstDir.GetID(), fileMd5, file.GetName(), fmt.Sprint(file.GetSize()), isFamily)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// 网盘中不存在该文件,开始上传
|
||||
status := GetUploadFileStatusResp{CreateUploadFileResp: *uploadInfo}
|
||||
for status.GetSize() < file.GetSize() && status.FileDataExists != 1 {
|
||||
if utils.IsCanceled(ctx) {
|
||||
return nil, ctx.Err()
|
||||
}
|
||||
|
||||
header := map[string]string{
|
||||
"ResumePolicy": "1",
|
||||
"Expect": "100-continue",
|
||||
}
|
||||
|
||||
if isFamily {
|
||||
header["FamilyId"] = fmt.Sprint(y.FamilyID)
|
||||
header["UploadFileId"] = fmt.Sprint(status.UploadFileId)
|
||||
} else {
|
||||
header["Edrive-UploadFileId"] = fmt.Sprint(status.UploadFileId)
|
||||
}
|
||||
|
||||
_, err := y.put(ctx, status.FileUploadUrl, header, true, io.NopCloser(tempFile), isFamily)
|
||||
if err, ok := err.(*RespErr); ok && err.Code != "InputStreamReadError" {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// 获取断点状态
|
||||
fullUrl := ApiUrl + "/getUploadFileStatus.action"
|
||||
if y.isFamily() {
|
||||
fullUrl = ApiUrl + "/family/file/getFamilyFileStatus.action"
|
||||
}
|
||||
_, err = y.get(fullUrl, func(req *resty.Request) {
|
||||
req.SetContext(ctx).SetQueryParams(map[string]string{
|
||||
"uploadFileId": fmt.Sprint(status.UploadFileId),
|
||||
"resumePolicy": "1",
|
||||
})
|
||||
if isFamily {
|
||||
req.SetQueryParam("familyId", fmt.Sprint(y.FamilyID))
|
||||
}
|
||||
}, &status, isFamily)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if _, err := tempFile.Seek(status.GetSize(), io.SeekStart); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
up(float64(status.GetSize()) / float64(file.GetSize()) * 100)
|
||||
}
|
||||
|
||||
return y.OldUploadCommit(ctx, status.FileCommitUrl, status.UploadFileId, isFamily, overwrite)
|
||||
}
|
||||
|
||||
// 创建上传会话
|
||||
func (y *Cloud189TV) OldUploadCreate(ctx context.Context, parentID string, fileMd5, fileName, fileSize string, isFamily bool) (*CreateUploadFileResp, error) {
|
||||
var uploadInfo CreateUploadFileResp
|
||||
|
||||
fullUrl := ApiUrl + "/createUploadFile.action"
|
||||
if isFamily {
|
||||
fullUrl = ApiUrl + "/family/file/createFamilyFile.action"
|
||||
}
|
||||
_, err := y.post(fullUrl, func(req *resty.Request) {
|
||||
req.SetContext(ctx)
|
||||
if isFamily {
|
||||
req.SetQueryParams(map[string]string{
|
||||
"familyId": y.FamilyID,
|
||||
"parentId": parentID,
|
||||
"fileMd5": fileMd5,
|
||||
"fileName": fileName,
|
||||
"fileSize": fileSize,
|
||||
"resumePolicy": "1",
|
||||
})
|
||||
} else {
|
||||
req.SetFormData(map[string]string{
|
||||
"parentFolderId": parentID,
|
||||
"fileName": fileName,
|
||||
"size": fileSize,
|
||||
"md5": fileMd5,
|
||||
"opertype": "3",
|
||||
"flag": "1",
|
||||
"resumePolicy": "1",
|
||||
"isLog": "0",
|
||||
})
|
||||
}
|
||||
}, &uploadInfo, isFamily)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &uploadInfo, nil
|
||||
}
|
||||
|
||||
// 提交上传文件
|
||||
func (y *Cloud189TV) OldUploadCommit(ctx context.Context, fileCommitUrl string, uploadFileID int64, isFamily bool, overwrite bool) (model.Obj, error) {
|
||||
var resp OldCommitUploadFileResp
|
||||
_, err := y.post(fileCommitUrl, func(req *resty.Request) {
|
||||
req.SetContext(ctx)
|
||||
if isFamily {
|
||||
req.SetHeaders(map[string]string{
|
||||
"ResumePolicy": "1",
|
||||
"UploadFileId": fmt.Sprint(uploadFileID),
|
||||
"FamilyId": fmt.Sprint(y.FamilyID),
|
||||
})
|
||||
} else {
|
||||
req.SetFormData(map[string]string{
|
||||
"opertype": IF(overwrite, "3", "1"),
|
||||
"resumePolicy": "1",
|
||||
"uploadFileId": fmt.Sprint(uploadFileID),
|
||||
"isLog": "0",
|
||||
})
|
||||
}
|
||||
}, &resp, isFamily)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return resp.toFile(), nil
|
||||
}
|
||||
|
||||
func (y *Cloud189TV) isFamily() bool {
|
||||
return y.Type == "family"
|
||||
}
|
||||
|
||||
func (y *Cloud189TV) isLogin() bool {
|
||||
if y.tokenInfo == nil {
|
||||
return false
|
||||
}
|
||||
_, err := y.get(ApiUrl+"/getUserInfo.action", nil, nil)
|
||||
return err == nil
|
||||
}
|
||||
|
||||
// 获取家庭云所有用户信息
|
||||
func (y *Cloud189TV) getFamilyInfoList() ([]FamilyInfoResp, error) {
|
||||
var resp FamilyInfoListResp
|
||||
_, err := y.get(ApiUrl+"/family/manage/getFamilyList.action", nil, &resp, true)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return resp.FamilyInfoResp, nil
|
||||
}
|
||||
|
||||
// 抽取家庭云ID
|
||||
func (y *Cloud189TV) getFamilyID() (string, error) {
|
||||
infos, err := y.getFamilyInfoList()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
if len(infos) == 0 {
|
||||
return "", fmt.Errorf("cannot get automatically,please input family_id")
|
||||
}
|
||||
for _, info := range infos {
|
||||
if strings.Contains(y.tokenInfo.LoginName, info.RemarkName) {
|
||||
return fmt.Sprint(info.FamilyID), nil
|
||||
}
|
||||
}
|
||||
return fmt.Sprint(infos[0].FamilyID), nil
|
||||
}
|
||||
|
||||
func (y *Cloud189TV) CreateBatchTask(aType string, familyID string, targetFolderId string, other map[string]string, taskInfos ...BatchTaskInfo) (*CreateBatchTaskResp, error) {
|
||||
var resp CreateBatchTaskResp
|
||||
_, err := y.post(ApiUrl+"/batch/createBatchTask.action", func(req *resty.Request) {
|
||||
req.SetFormData(map[string]string{
|
||||
"type": aType,
|
||||
"taskInfos": MustString(utils.Json.MarshalToString(taskInfos)),
|
||||
})
|
||||
if targetFolderId != "" {
|
||||
req.SetFormData(map[string]string{"targetFolderId": targetFolderId})
|
||||
}
|
||||
if familyID != "" {
|
||||
req.SetFormData(map[string]string{"familyId": familyID})
|
||||
}
|
||||
req.SetFormData(other)
|
||||
}, &resp, familyID != "")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &resp, nil
|
||||
}
|
||||
|
||||
// 检测任务状态
|
||||
func (y *Cloud189TV) CheckBatchTask(aType string, taskID string) (*BatchTaskStateResp, error) {
|
||||
var resp BatchTaskStateResp
|
||||
_, err := y.post(ApiUrl+"/batch/checkBatchTask.action", func(req *resty.Request) {
|
||||
req.SetFormData(map[string]string{
|
||||
"type": aType,
|
||||
"taskId": taskID,
|
||||
})
|
||||
}, &resp)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &resp, nil
|
||||
}
|
||||
|
||||
// 获取冲突的任务信息
|
||||
func (y *Cloud189TV) GetConflictTaskInfo(aType string, taskID string) (*BatchTaskConflictTaskInfoResp, error) {
|
||||
var resp BatchTaskConflictTaskInfoResp
|
||||
_, err := y.post(ApiUrl+"/batch/getConflictTaskInfo.action", func(req *resty.Request) {
|
||||
req.SetFormData(map[string]string{
|
||||
"type": aType,
|
||||
"taskId": taskID,
|
||||
})
|
||||
}, &resp)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &resp, nil
|
||||
}
|
||||
|
||||
// 处理冲突
|
||||
func (y *Cloud189TV) ManageBatchTask(aType string, taskID string, targetFolderId string, taskInfos ...BatchTaskInfo) error {
|
||||
_, err := y.post(ApiUrl+"/batch/manageBatchTask.action", func(req *resty.Request) {
|
||||
req.SetFormData(map[string]string{
|
||||
"targetFolderId": targetFolderId,
|
||||
"type": aType,
|
||||
"taskId": taskID,
|
||||
"taskInfos": MustString(utils.Json.MarshalToString(taskInfos)),
|
||||
})
|
||||
}, nil)
|
||||
return err
|
||||
}
|
||||
|
||||
var ErrIsConflict = errors.New("there is a conflict with the target object")
|
||||
|
||||
// 等待任务完成
|
||||
func (y *Cloud189TV) WaitBatchTask(aType string, taskID string, t time.Duration) error {
|
||||
for {
|
||||
state, err := y.CheckBatchTask(aType, taskID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
switch state.TaskStatus {
|
||||
case 2:
|
||||
return ErrIsConflict
|
||||
case 4:
|
||||
return nil
|
||||
}
|
||||
time.Sleep(t)
|
||||
}
|
||||
}
|
@ -8,11 +8,11 @@ import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/OpenListTeam/OpenList/drivers/base"
|
||||
"github.com/OpenListTeam/OpenList/internal/driver"
|
||||
"github.com/OpenListTeam/OpenList/internal/errs"
|
||||
"github.com/OpenListTeam/OpenList/internal/model"
|
||||
"github.com/OpenListTeam/OpenList/pkg/utils"
|
||||
"github.com/OpenListTeam/OpenList/v4/drivers/base"
|
||||
"github.com/OpenListTeam/OpenList/v4/internal/driver"
|
||||
"github.com/OpenListTeam/OpenList/v4/internal/errs"
|
||||
"github.com/OpenListTeam/OpenList/v4/internal/model"
|
||||
"github.com/OpenListTeam/OpenList/v4/pkg/utils"
|
||||
"github.com/go-resty/resty/v2"
|
||||
"github.com/google/uuid"
|
||||
)
|
||||
|
@ -18,8 +18,8 @@ import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/OpenListTeam/OpenList/internal/model"
|
||||
"github.com/OpenListTeam/OpenList/pkg/utils/random"
|
||||
"github.com/OpenListTeam/OpenList/v4/internal/model"
|
||||
"github.com/OpenListTeam/OpenList/v4/pkg/utils/random"
|
||||
)
|
||||
|
||||
func clientSuffix() map[string]string {
|
||||
|
@ -1,8 +1,8 @@
|
||||
package _189pc
|
||||
|
||||
import (
|
||||
"github.com/OpenListTeam/OpenList/internal/driver"
|
||||
"github.com/OpenListTeam/OpenList/internal/op"
|
||||
"github.com/OpenListTeam/OpenList/v4/internal/driver"
|
||||
"github.com/OpenListTeam/OpenList/v4/internal/op"
|
||||
)
|
||||
|
||||
type Addition struct {
|
||||
|
@ -7,7 +7,7 @@ import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/OpenListTeam/OpenList/pkg/utils"
|
||||
"github.com/OpenListTeam/OpenList/v4/pkg/utils"
|
||||
)
|
||||
|
||||
// 居然有四种返回方式
|
||||
|
@ -18,16 +18,16 @@ import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/OpenListTeam/OpenList/drivers/base"
|
||||
"github.com/OpenListTeam/OpenList/internal/conf"
|
||||
"github.com/OpenListTeam/OpenList/internal/driver"
|
||||
"github.com/OpenListTeam/OpenList/internal/errs"
|
||||
"github.com/OpenListTeam/OpenList/internal/model"
|
||||
"github.com/OpenListTeam/OpenList/internal/op"
|
||||
"github.com/OpenListTeam/OpenList/internal/setting"
|
||||
"github.com/OpenListTeam/OpenList/internal/stream"
|
||||
"github.com/OpenListTeam/OpenList/pkg/errgroup"
|
||||
"github.com/OpenListTeam/OpenList/pkg/utils"
|
||||
"github.com/OpenListTeam/OpenList/v4/drivers/base"
|
||||
"github.com/OpenListTeam/OpenList/v4/internal/conf"
|
||||
"github.com/OpenListTeam/OpenList/v4/internal/driver"
|
||||
"github.com/OpenListTeam/OpenList/v4/internal/errs"
|
||||
"github.com/OpenListTeam/OpenList/v4/internal/model"
|
||||
"github.com/OpenListTeam/OpenList/v4/internal/op"
|
||||
"github.com/OpenListTeam/OpenList/v4/internal/setting"
|
||||
"github.com/OpenListTeam/OpenList/v4/internal/stream"
|
||||
"github.com/OpenListTeam/OpenList/v4/pkg/errgroup"
|
||||
"github.com/OpenListTeam/OpenList/v4/pkg/utils"
|
||||
|
||||
"github.com/avast/retry-go"
|
||||
"github.com/go-resty/resty/v2"
|
||||
@ -322,7 +322,7 @@ func (y *Cloud189PC) login() (err error) {
|
||||
_, err = y.client.R().
|
||||
SetResult(&tokenInfo).SetError(&erron).
|
||||
SetQueryParams(clientSuffix()).
|
||||
SetQueryParam("redirectURL", url.QueryEscape(loginresp.ToUrl)).
|
||||
SetQueryParam("redirectURL", loginresp.ToUrl).
|
||||
Post(API_URL + "/getSessionForPC.action")
|
||||
if err != nil {
|
||||
return
|
||||
@ -820,7 +820,9 @@ func (y *Cloud189PC) GetMultiUploadUrls(ctx context.Context, isFamily bool, uplo
|
||||
|
||||
// 旧版本上传,家庭云不支持覆盖
|
||||
func (y *Cloud189PC) OldUpload(ctx context.Context, dstDir model.Obj, file model.FileStreamer, up driver.UpdateProgress, isFamily bool, overwrite bool) (model.Obj, error) {
|
||||
tempFile, fileMd5, err := stream.CacheFullInTempFileAndHash(file, utils.MD5)
|
||||
cacheFileProgress := model.UpdateProgressWithRange(up, 0, 50)
|
||||
up = model.UpdateProgressWithRange(up, 50, 100)
|
||||
tempFile, fileMd5, err := stream.CacheFullInTempFileAndHash(file, cacheFileProgress, utils.MD5)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -7,12 +7,12 @@ import (
|
||||
stdpath "path"
|
||||
"strings"
|
||||
|
||||
"github.com/OpenListTeam/OpenList/internal/driver"
|
||||
"github.com/OpenListTeam/OpenList/internal/errs"
|
||||
"github.com/OpenListTeam/OpenList/internal/fs"
|
||||
"github.com/OpenListTeam/OpenList/internal/model"
|
||||
"github.com/OpenListTeam/OpenList/internal/stream"
|
||||
"github.com/OpenListTeam/OpenList/pkg/utils"
|
||||
"github.com/OpenListTeam/OpenList/v4/internal/driver"
|
||||
"github.com/OpenListTeam/OpenList/v4/internal/errs"
|
||||
"github.com/OpenListTeam/OpenList/v4/internal/fs"
|
||||
"github.com/OpenListTeam/OpenList/v4/internal/model"
|
||||
"github.com/OpenListTeam/OpenList/v4/internal/stream"
|
||||
"github.com/OpenListTeam/OpenList/v4/pkg/utils"
|
||||
)
|
||||
|
||||
type Alias struct {
|
||||
@ -113,6 +113,7 @@ func (d *Alias) Link(ctx context.Context, file model.Obj, args model.LinkArgs) (
|
||||
for _, dst := range dsts {
|
||||
link, err := d.link(ctx, dst, sub, args)
|
||||
if err == nil {
|
||||
link.Expiration = nil // 去除非必要缓存,d.link里op.Lin有缓存
|
||||
if !args.Redirect && len(link.URL) > 0 {
|
||||
// 正常情况下 多并发 仅支持返回URL的驱动
|
||||
// alias套娃alias 可以让crypt、mega等驱动(不返回URL的) 支持并发
|
||||
|
@ -1,8 +1,8 @@
|
||||
package alias
|
||||
|
||||
import (
|
||||
"github.com/OpenListTeam/OpenList/internal/driver"
|
||||
"github.com/OpenListTeam/OpenList/internal/op"
|
||||
"github.com/OpenListTeam/OpenList/v4/internal/driver"
|
||||
"github.com/OpenListTeam/OpenList/v4/internal/op"
|
||||
)
|
||||
|
||||
type Addition struct {
|
||||
|
@ -7,14 +7,14 @@ import (
|
||||
stdpath "path"
|
||||
"strings"
|
||||
|
||||
"github.com/OpenListTeam/OpenList/internal/driver"
|
||||
"github.com/OpenListTeam/OpenList/internal/errs"
|
||||
"github.com/OpenListTeam/OpenList/internal/fs"
|
||||
"github.com/OpenListTeam/OpenList/internal/model"
|
||||
"github.com/OpenListTeam/OpenList/internal/op"
|
||||
"github.com/OpenListTeam/OpenList/internal/sign"
|
||||
"github.com/OpenListTeam/OpenList/pkg/utils"
|
||||
"github.com/OpenListTeam/OpenList/server/common"
|
||||
"github.com/OpenListTeam/OpenList/v4/internal/driver"
|
||||
"github.com/OpenListTeam/OpenList/v4/internal/errs"
|
||||
"github.com/OpenListTeam/OpenList/v4/internal/fs"
|
||||
"github.com/OpenListTeam/OpenList/v4/internal/model"
|
||||
"github.com/OpenListTeam/OpenList/v4/internal/op"
|
||||
"github.com/OpenListTeam/OpenList/v4/internal/sign"
|
||||
"github.com/OpenListTeam/OpenList/v4/pkg/utils"
|
||||
"github.com/OpenListTeam/OpenList/v4/server/common"
|
||||
)
|
||||
|
||||
func (d *Alias) listRoot() []model.Obj {
|
||||
@ -103,7 +103,12 @@ func (d *Alias) link(ctx context.Context, dst, sub string, args model.LinkArgs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if _, ok := storage.(*Alias); !ok && !args.Redirect {
|
||||
useRawLink := len(common.GetApiUrl(ctx)) == 0 // ftp、s3
|
||||
if !useRawLink {
|
||||
_, ok := storage.(*Alias)
|
||||
useRawLink = !ok && !args.Redirect
|
||||
}
|
||||
if useRawLink {
|
||||
link, _, err := op.Link(ctx, storage, reqActualPath, args)
|
||||
return link, err
|
||||
}
|
||||
@ -114,13 +119,10 @@ func (d *Alias) link(ctx context.Context, dst, sub string, args model.LinkArgs)
|
||||
if common.ShouldProxy(storage, stdpath.Base(sub)) {
|
||||
link := &model.Link{
|
||||
URL: fmt.Sprintf("%s/p%s?sign=%s",
|
||||
common.GetApiUrl(args.HttpReq),
|
||||
common.GetApiUrl(ctx),
|
||||
utils.EncodePath(reqPath, true),
|
||||
sign.Sign(reqPath)),
|
||||
}
|
||||
if args.HttpReq != nil && d.ProxyRange {
|
||||
link.RangeReadCloser = common.NoProxyRange
|
||||
}
|
||||
return link, nil
|
||||
}
|
||||
link, _, err := op.Link(ctx, storage, reqActualPath, args)
|
||||
@ -201,31 +203,24 @@ func (d *Alias) extract(ctx context.Context, dst, sub string, args model.Archive
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if _, ok := storage.(driver.ArchiveReader); ok {
|
||||
if _, ok := storage.(*Alias); !ok && !args.Redirect {
|
||||
link, _, err := op.DriverExtract(ctx, storage, reqActualPath, args)
|
||||
return link, err
|
||||
}
|
||||
if _, ok := storage.(driver.ArchiveReader); !ok {
|
||||
return nil, errs.NotImplement
|
||||
}
|
||||
if args.Redirect && common.ShouldProxy(storage, stdpath.Base(sub)) {
|
||||
_, err = fs.Get(ctx, reqPath, &fs.GetArgs{NoLog: true})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if common.ShouldProxy(storage, stdpath.Base(sub)) {
|
||||
link := &model.Link{
|
||||
URL: fmt.Sprintf("%s/ap%s?inner=%s&pass=%s&sign=%s",
|
||||
common.GetApiUrl(args.HttpReq),
|
||||
utils.EncodePath(reqPath, true),
|
||||
utils.EncodePath(args.InnerPath, true),
|
||||
url.QueryEscape(args.Password),
|
||||
sign.SignArchive(reqPath)),
|
||||
}
|
||||
if args.HttpReq != nil && d.ProxyRange {
|
||||
link.RangeReadCloser = common.NoProxyRange
|
||||
}
|
||||
return link, nil
|
||||
link := &model.Link{
|
||||
URL: fmt.Sprintf("%s/ap%s?inner=%s&pass=%s&sign=%s",
|
||||
common.GetApiUrl(ctx),
|
||||
utils.EncodePath(reqPath, true),
|
||||
utils.EncodePath(args.InnerPath, true),
|
||||
url.QueryEscape(args.Password),
|
||||
sign.SignArchive(reqPath)),
|
||||
}
|
||||
link, _, err := op.DriverExtract(ctx, storage, reqActualPath, args)
|
||||
return link, err
|
||||
return link, nil
|
||||
}
|
||||
return nil, errs.NotImplement
|
||||
link, _, err := op.DriverExtract(ctx, storage, reqActualPath, args)
|
||||
return link, err
|
||||
}
|
||||
|
@ -14,14 +14,14 @@ import (
|
||||
"os"
|
||||
"time"
|
||||
|
||||
"github.com/OpenListTeam/OpenList/drivers/base"
|
||||
"github.com/OpenListTeam/OpenList/internal/conf"
|
||||
"github.com/OpenListTeam/OpenList/internal/driver"
|
||||
"github.com/OpenListTeam/OpenList/internal/errs"
|
||||
"github.com/OpenListTeam/OpenList/internal/model"
|
||||
"github.com/OpenListTeam/OpenList/internal/stream"
|
||||
"github.com/OpenListTeam/OpenList/pkg/cron"
|
||||
"github.com/OpenListTeam/OpenList/pkg/utils"
|
||||
"github.com/OpenListTeam/OpenList/v4/drivers/base"
|
||||
"github.com/OpenListTeam/OpenList/v4/internal/conf"
|
||||
"github.com/OpenListTeam/OpenList/v4/internal/driver"
|
||||
"github.com/OpenListTeam/OpenList/v4/internal/errs"
|
||||
"github.com/OpenListTeam/OpenList/v4/internal/model"
|
||||
"github.com/OpenListTeam/OpenList/v4/internal/stream"
|
||||
"github.com/OpenListTeam/OpenList/v4/pkg/cron"
|
||||
"github.com/OpenListTeam/OpenList/v4/pkg/utils"
|
||||
"github.com/go-resty/resty/v2"
|
||||
log "github.com/sirupsen/logrus"
|
||||
)
|
||||
|
@ -3,7 +3,7 @@ package aliyundrive
|
||||
import (
|
||||
"crypto/ecdsa"
|
||||
|
||||
"github.com/OpenListTeam/OpenList/pkg/generic_sync"
|
||||
"github.com/OpenListTeam/OpenList/v4/pkg/generic_sync"
|
||||
)
|
||||
|
||||
type State struct {
|
||||
|
@ -1,8 +1,8 @@
|
||||
package aliyundrive
|
||||
|
||||
import (
|
||||
"github.com/OpenListTeam/OpenList/internal/driver"
|
||||
"github.com/OpenListTeam/OpenList/internal/op"
|
||||
"github.com/OpenListTeam/OpenList/v4/internal/driver"
|
||||
"github.com/OpenListTeam/OpenList/v4/internal/op"
|
||||
)
|
||||
|
||||
type Addition struct {
|
||||
|
@ -3,7 +3,7 @@ package aliyundrive
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/OpenListTeam/OpenList/internal/model"
|
||||
"github.com/OpenListTeam/OpenList/v4/internal/model"
|
||||
)
|
||||
|
||||
type RespErr struct {
|
||||
|
@ -7,9 +7,9 @@ import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
|
||||
"github.com/OpenListTeam/OpenList/drivers/base"
|
||||
"github.com/OpenListTeam/OpenList/internal/op"
|
||||
"github.com/OpenListTeam/OpenList/pkg/utils"
|
||||
"github.com/OpenListTeam/OpenList/v4/drivers/base"
|
||||
"github.com/OpenListTeam/OpenList/v4/internal/op"
|
||||
"github.com/OpenListTeam/OpenList/v4/pkg/utils"
|
||||
"github.com/dustinxie/ecc"
|
||||
"github.com/go-resty/resty/v2"
|
||||
"github.com/google/uuid"
|
||||
|
@ -8,12 +8,12 @@ import (
|
||||
"path/filepath"
|
||||
"time"
|
||||
|
||||
"github.com/OpenListTeam/OpenList/drivers/base"
|
||||
"github.com/OpenListTeam/OpenList/internal/driver"
|
||||
"github.com/OpenListTeam/OpenList/internal/errs"
|
||||
"github.com/OpenListTeam/OpenList/internal/model"
|
||||
"github.com/OpenListTeam/OpenList/pkg/utils"
|
||||
"github.com/Xhofe/rateg"
|
||||
"github.com/OpenListTeam/OpenList/v4/drivers/base"
|
||||
"github.com/OpenListTeam/OpenList/v4/internal/driver"
|
||||
"github.com/OpenListTeam/OpenList/v4/internal/errs"
|
||||
"github.com/OpenListTeam/OpenList/v4/internal/model"
|
||||
"github.com/OpenListTeam/OpenList/v4/pkg/utils"
|
||||
"github.com/OpenListTeam/rateg"
|
||||
"github.com/go-resty/resty/v2"
|
||||
log "github.com/sirupsen/logrus"
|
||||
)
|
||||
|
@ -1,8 +1,8 @@
|
||||
package aliyundrive_open
|
||||
|
||||
import (
|
||||
"github.com/OpenListTeam/OpenList/internal/driver"
|
||||
"github.com/OpenListTeam/OpenList/internal/op"
|
||||
"github.com/OpenListTeam/OpenList/v4/internal/driver"
|
||||
"github.com/OpenListTeam/OpenList/v4/internal/op"
|
||||
)
|
||||
|
||||
type Addition struct {
|
||||
|
@ -3,9 +3,9 @@ package aliyundrive_open
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/OpenListTeam/OpenList/pkg/utils"
|
||||
"github.com/OpenListTeam/OpenList/v4/pkg/utils"
|
||||
|
||||
"github.com/OpenListTeam/OpenList/internal/model"
|
||||
"github.com/OpenListTeam/OpenList/v4/internal/model"
|
||||
)
|
||||
|
||||
type ErrResp struct {
|
||||
|
@ -11,12 +11,12 @@ import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/OpenListTeam/OpenList/drivers/base"
|
||||
"github.com/OpenListTeam/OpenList/internal/driver"
|
||||
"github.com/OpenListTeam/OpenList/internal/model"
|
||||
streamPkg "github.com/OpenListTeam/OpenList/internal/stream"
|
||||
"github.com/OpenListTeam/OpenList/pkg/http_range"
|
||||
"github.com/OpenListTeam/OpenList/pkg/utils"
|
||||
"github.com/OpenListTeam/OpenList/v4/drivers/base"
|
||||
"github.com/OpenListTeam/OpenList/v4/internal/driver"
|
||||
"github.com/OpenListTeam/OpenList/v4/internal/model"
|
||||
streamPkg "github.com/OpenListTeam/OpenList/v4/internal/stream"
|
||||
"github.com/OpenListTeam/OpenList/v4/pkg/http_range"
|
||||
"github.com/OpenListTeam/OpenList/v4/pkg/utils"
|
||||
"github.com/avast/retry-go"
|
||||
"github.com/go-resty/resty/v2"
|
||||
log "github.com/sirupsen/logrus"
|
||||
@ -194,7 +194,9 @@ func (d *AliyundriveOpen) upload(ctx context.Context, dstDir model.Obj, stream m
|
||||
|
||||
hash := stream.GetHash().GetHash(utils.SHA1)
|
||||
if len(hash) != utils.SHA1.Width {
|
||||
_, hash, err = streamPkg.CacheFullInTempFileAndHash(stream, utils.SHA1)
|
||||
cacheFileProgress := model.UpdateProgressWithRange(up, 0, 50)
|
||||
up = model.UpdateProgressWithRange(up, 50, 100)
|
||||
_, hash, err = streamPkg.CacheFullInTempFileAndHash(stream, cacheFileProgress, utils.SHA1)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -9,10 +9,10 @@ import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/OpenListTeam/OpenList/drivers/base"
|
||||
"github.com/OpenListTeam/OpenList/internal/model"
|
||||
"github.com/OpenListTeam/OpenList/internal/op"
|
||||
"github.com/OpenListTeam/OpenList/pkg/utils"
|
||||
"github.com/OpenListTeam/OpenList/v4/drivers/base"
|
||||
"github.com/OpenListTeam/OpenList/v4/internal/model"
|
||||
"github.com/OpenListTeam/OpenList/v4/internal/op"
|
||||
"github.com/OpenListTeam/OpenList/v4/pkg/utils"
|
||||
"github.com/go-resty/resty/v2"
|
||||
log "github.com/sirupsen/logrus"
|
||||
)
|
||||
@ -28,6 +28,7 @@ func (d *AliyundriveOpen) _refreshToken() (string, string, error) {
|
||||
ErrorMessage string `json:"text"`
|
||||
}
|
||||
_, err := base.RestyClient.R().
|
||||
SetHeader("User-Agent", "Mozilla/5.0 (Macintosh; Apple macOS 15_5) AppleWebKit/537.36 (KHTML, like Gecko) Safari/537.36 Chrome/138.0.0.0 Openlist/425.6.30").
|
||||
SetResult(&resp).
|
||||
SetQueryParams(map[string]string{
|
||||
"refresh_ui": d.RefreshToken,
|
||||
@ -42,7 +43,7 @@ func (d *AliyundriveOpen) _refreshToken() (string, string, error) {
|
||||
if resp.ErrorMessage != "" {
|
||||
return "", "", fmt.Errorf("failed to refresh token: %s", resp.ErrorMessage)
|
||||
}
|
||||
return "", "", fmt.Errorf("empty token returned from official API")
|
||||
return "", "", fmt.Errorf("empty token returned from official API, a wrong refresh token may have been used")
|
||||
}
|
||||
return resp.RefreshToken, resp.AccessToken, nil
|
||||
}
|
||||
|
@ -6,13 +6,13 @@ import (
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"github.com/OpenListTeam/OpenList/drivers/base"
|
||||
"github.com/OpenListTeam/OpenList/internal/driver"
|
||||
"github.com/OpenListTeam/OpenList/internal/errs"
|
||||
"github.com/OpenListTeam/OpenList/internal/model"
|
||||
"github.com/OpenListTeam/OpenList/pkg/cron"
|
||||
"github.com/OpenListTeam/OpenList/pkg/utils"
|
||||
"github.com/Xhofe/rateg"
|
||||
"github.com/OpenListTeam/OpenList/v4/drivers/base"
|
||||
"github.com/OpenListTeam/OpenList/v4/internal/driver"
|
||||
"github.com/OpenListTeam/OpenList/v4/internal/errs"
|
||||
"github.com/OpenListTeam/OpenList/v4/internal/model"
|
||||
"github.com/OpenListTeam/OpenList/v4/pkg/cron"
|
||||
"github.com/OpenListTeam/OpenList/v4/pkg/utils"
|
||||
"github.com/OpenListTeam/rateg"
|
||||
"github.com/go-resty/resty/v2"
|
||||
log "github.com/sirupsen/logrus"
|
||||
)
|
||||
|
@ -1,8 +1,8 @@
|
||||
package aliyundrive_share
|
||||
|
||||
import (
|
||||
"github.com/OpenListTeam/OpenList/internal/driver"
|
||||
"github.com/OpenListTeam/OpenList/internal/op"
|
||||
"github.com/OpenListTeam/OpenList/v4/internal/driver"
|
||||
"github.com/OpenListTeam/OpenList/v4/internal/op"
|
||||
)
|
||||
|
||||
type Addition struct {
|
||||
|
@ -3,7 +3,7 @@ package aliyundrive_share
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/OpenListTeam/OpenList/internal/model"
|
||||
"github.com/OpenListTeam/OpenList/v4/internal/model"
|
||||
)
|
||||
|
||||
type ErrorResp struct {
|
||||
|
@ -4,8 +4,8 @@ import (
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"github.com/OpenListTeam/OpenList/drivers/base"
|
||||
"github.com/OpenListTeam/OpenList/internal/op"
|
||||
"github.com/OpenListTeam/OpenList/v4/drivers/base"
|
||||
"github.com/OpenListTeam/OpenList/v4/internal/op"
|
||||
log "github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user