Compare commits
120 Commits
Author | SHA1 | Date | |
---|---|---|---|
4a0e47dbac | |||
510d266da8 | |||
35dfb36884 | |||
b88f4d2ba6 | |||
50318da879 | |||
575487a0e2 | |||
69d3ccaed2 | |||
170859a112 | |||
7fdcb106a5 | |||
14d4ddb752 | |||
428e59a844 | |||
1c8d895fc0 | |||
fbf3fb825b | |||
16e07ae016 | |||
d1b9db38c7 | |||
395f0fc5f3 | |||
143e4cd077 | |||
f777a2fab4 | |||
dad3012ec3 | |||
d45209edb2 | |||
e89489453d | |||
ed6c8194a7 | |||
83fe17c6ec | |||
c00dcc8f39 | |||
e118f4a3b9 | |||
5e28d0f96a | |||
3af23f6792 | |||
3a41b929c9 | |||
105f22969c | |||
e4a88a7c13 | |||
b0255040c6 | |||
f1e842e12a | |||
d756cf3e9f | |||
146619134d | |||
372030071e | |||
62a06fa0f9 | |||
e2bcca2fbd | |||
4568af9542 | |||
b50d486a63 | |||
0ae3fc608b | |||
6024e8d832 | |||
f38f4f401b | |||
3b2ae85009 | |||
faf4150d1e | |||
fb64f00640 | |||
3d336b328a | |||
f9cf29e0b6 | |||
cbd038f30f | |||
2aeb75a779 | |||
2f8eaf6bea | |||
fb7a5dec1b | |||
e61bac039a | |||
b3be9ef428 | |||
5a6b600ace | |||
e58ca686e3 | |||
6f4b1ba4b3 | |||
cdc45630ae | |||
7947ff1ae4 | |||
33bae52fa1 | |||
3ee45c69a7 | |||
179d285564 | |||
a2e8e96c71 | |||
5043815d48 | |||
1640f06e13 | |||
62ea93837c | |||
446f82888c | |||
6f1aeb47fd | |||
1f7c1b4f43 | |||
3fa0217c4b | |||
2dd30f2b77 | |||
6e23c8b4c0 | |||
72aa63adce | |||
e65e8be59e | |||
7aa4dfb240 | |||
bd324233a0 | |||
f1a9b68022 | |||
dda1da4576 | |||
5b7aa9c1cf | |||
a28aaceaad | |||
2bb200af87 | |||
97f1efbb72 | |||
bf8b6f4c2c | |||
bd33c200dc | |||
bc6baf1be0 | |||
dc8d5106f9 | |||
8c0dfe2f3d | |||
4e1be9bee6 | |||
4c5285e094 | |||
0838feeb82 | |||
ae791c8634 | |||
09f480318c | |||
4c5be5f07f | |||
9c1ffdbb82 | |||
18a63e34dd | |||
ff0bcfef8a | |||
4980b71ba3 | |||
b5bf5f4325 | |||
f9788ea7cf | |||
83644dab85 | |||
d94cf72da2 | |||
e98561ceb1 | |||
76f37373e0 | |||
61a06992c3 | |||
ddcba93eea | |||
bb969d8dc6 | |||
2383e851e2 | |||
330a767fd7 | |||
2b902de6fd | |||
85e1350af8 | |||
c09800790b | |||
25fd343069 | |||
518487e3df | |||
a02d9c8463 | |||
8beeba7c0c | |||
50fb49f0c3 | |||
4dcaa24758 | |||
3fbdf6f022 | |||
aa9ba289bb | |||
3b6d8987db | |||
6e3df9f847 |
1
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
1
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
@ -54,4 +54,3 @@ body:
|
|||||||
description: |
|
description: |
|
||||||
Please copy and paste any relevant log output.
|
Please copy and paste any relevant log output.
|
||||||
请复制粘贴错误日志,或者截图
|
请复制粘贴错误日志,或者截图
|
||||||
render: shell
|
|
9
.github/workflows/auto_lang.yml
vendored
9
.github/workflows/auto_lang.yml
vendored
@ -7,6 +7,8 @@ on:
|
|||||||
paths:
|
paths:
|
||||||
- 'drivers/**'
|
- 'drivers/**'
|
||||||
- 'internal/bootstrap/data/setting.go'
|
- 'internal/bootstrap/data/setting.go'
|
||||||
|
- 'internal/conf/const.go'
|
||||||
|
- 'cmd/lang.go'
|
||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
@ -19,12 +21,12 @@ jobs:
|
|||||||
runs-on: ${{ matrix.platform }}
|
runs-on: ${{ matrix.platform }}
|
||||||
steps:
|
steps:
|
||||||
- name: Setup go
|
- name: Setup go
|
||||||
uses: actions/setup-go@v2
|
uses: actions/setup-go@v3
|
||||||
with:
|
with:
|
||||||
go-version: ${{ matrix.go-version }}
|
go-version: ${{ matrix.go-version }}
|
||||||
|
|
||||||
- name: Checkout alist
|
- name: Checkout alist
|
||||||
uses: actions/checkout@v2
|
uses: actions/checkout@v3
|
||||||
with:
|
with:
|
||||||
path: alist
|
path: alist
|
||||||
|
|
||||||
@ -42,6 +44,7 @@ jobs:
|
|||||||
cd alist
|
cd alist
|
||||||
go run ./main.go lang
|
go run ./main.go lang
|
||||||
cd ..
|
cd ..
|
||||||
|
|
||||||
- name: Copy lang file
|
- name: Copy lang file
|
||||||
run: |
|
run: |
|
||||||
cp -f ./alist/lang/*.json ./alist-web/src/lang/en/ 2>/dev/null || :
|
cp -f ./alist/lang/*.json ./alist-web/src/lang/en/ 2>/dev/null || :
|
||||||
@ -61,4 +64,4 @@ jobs:
|
|||||||
github_token: ${{ secrets.MY_TOKEN }}
|
github_token: ${{ secrets.MY_TOKEN }}
|
||||||
branch: main
|
branch: main
|
||||||
directory: alist-web
|
directory: alist-web
|
||||||
repository: alist-org/alist-web
|
repository: alist-org/alist-web
|
||||||
|
12
.github/workflows/build.yml
vendored
12
.github/workflows/build.yml
vendored
@ -2,9 +2,9 @@ name: build
|
|||||||
|
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
branches: [ '**' ]
|
branches: [ 'main' ]
|
||||||
pull_request:
|
pull_request:
|
||||||
branches: [ '**' ]
|
branches: [ 'main' ]
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
build:
|
build:
|
||||||
@ -16,7 +16,7 @@ jobs:
|
|||||||
runs-on: ${{ matrix.platform }}
|
runs-on: ${{ matrix.platform }}
|
||||||
steps:
|
steps:
|
||||||
- name: Setup Go
|
- name: Setup Go
|
||||||
uses: actions/setup-go@v2
|
uses: actions/setup-go@v3
|
||||||
with:
|
with:
|
||||||
go-version: ${{ matrix.go-version }}
|
go-version: ${{ matrix.go-version }}
|
||||||
|
|
||||||
@ -25,8 +25,8 @@ jobs:
|
|||||||
|
|
||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
run: |
|
run: |
|
||||||
docker pull techknowlogick/xgo:latest
|
docker pull crazymax/xgo:latest
|
||||||
go install src.techknowlogick.com/xgo@latest
|
go install github.com/crazy-max/xgo@latest
|
||||||
sudo apt install upx
|
sudo apt install upx
|
||||||
|
|
||||||
- name: Build
|
- name: Build
|
||||||
@ -34,7 +34,7 @@ jobs:
|
|||||||
bash build.sh dev
|
bash build.sh dev
|
||||||
|
|
||||||
- name: Upload artifact
|
- name: Upload artifact
|
||||||
uses: actions/upload-artifact@v2
|
uses: actions/upload-artifact@v3
|
||||||
with:
|
with:
|
||||||
name: alist
|
name: alist
|
||||||
path: dist
|
path: dist
|
12
.github/workflows/build_docker.yml
vendored
12
.github/workflows/build_docker.yml
vendored
@ -10,27 +10,27 @@ jobs:
|
|||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v2
|
uses: actions/checkout@v3
|
||||||
- name: Docker meta
|
- name: Docker meta
|
||||||
id: meta
|
id: meta
|
||||||
uses: docker/metadata-action@v3
|
uses: docker/metadata-action@v4
|
||||||
with:
|
with:
|
||||||
images: xhofe/alist
|
images: xhofe/alist
|
||||||
- name: Replace release with dev
|
- name: Replace release with dev
|
||||||
run: |
|
run: |
|
||||||
sed -i 's/release/dev/g' Dockerfile
|
sed -i 's/release/dev/g' Dockerfile
|
||||||
- name: Set up QEMU
|
- name: Set up QEMU
|
||||||
uses: docker/setup-qemu-action@v1
|
uses: docker/setup-qemu-action@v2
|
||||||
- name: Set up Docker Buildx
|
- name: Set up Docker Buildx
|
||||||
uses: docker/setup-buildx-action@v1
|
uses: docker/setup-buildx-action@v2
|
||||||
- name: Login to DockerHub
|
- name: Login to DockerHub
|
||||||
uses: docker/login-action@v1
|
uses: docker/login-action@v2
|
||||||
with:
|
with:
|
||||||
username: xhofe
|
username: xhofe
|
||||||
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||||
- name: Build and push
|
- name: Build and push
|
||||||
id: docker_build
|
id: docker_build
|
||||||
uses: docker/build-push-action@v2
|
uses: docker/build-push-action@v3
|
||||||
with:
|
with:
|
||||||
context: .
|
context: .
|
||||||
push: true
|
push: true
|
||||||
|
2
.github/workflows/issue_duplicate.yml
vendored
2
.github/workflows/issue_duplicate.yml
vendored
@ -10,7 +10,7 @@ jobs:
|
|||||||
if: github.event.label.name == 'duplicate'
|
if: github.event.label.name == 'duplicate'
|
||||||
steps:
|
steps:
|
||||||
- name: Create comment
|
- name: Create comment
|
||||||
uses: actions-cool/issues-helper@v2
|
uses: actions-cool/issues-helper@v3
|
||||||
with:
|
with:
|
||||||
actions: 'create-comment'
|
actions: 'create-comment'
|
||||||
token: ${{ secrets.GITHUB_TOKEN }}
|
token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
2
.github/workflows/issue_invalid.yml
vendored
2
.github/workflows/issue_invalid.yml
vendored
@ -10,7 +10,7 @@ jobs:
|
|||||||
if: github.event.label.name == 'invalid'
|
if: github.event.label.name == 'invalid'
|
||||||
steps:
|
steps:
|
||||||
- name: Create comment
|
- name: Create comment
|
||||||
uses: actions-cool/issues-helper@v2
|
uses: actions-cool/issues-helper@v3
|
||||||
with:
|
with:
|
||||||
actions: 'create-comment'
|
actions: 'create-comment'
|
||||||
token: ${{ secrets.GITHUB_TOKEN }}
|
token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
2
.github/workflows/issue_question.yml
vendored
2
.github/workflows/issue_question.yml
vendored
@ -10,7 +10,7 @@ jobs:
|
|||||||
if: github.event.label.name == 'question'
|
if: github.event.label.name == 'question'
|
||||||
steps:
|
steps:
|
||||||
- name: Create comment
|
- name: Create comment
|
||||||
uses: actions-cool/issues-helper@v2.0.0
|
uses: actions-cool/issues-helper@v3.3.3
|
||||||
with:
|
with:
|
||||||
actions: 'create-comment'
|
actions: 'create-comment'
|
||||||
token: ${{ secrets.GITHUB_TOKEN }}
|
token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
2
.github/workflows/issue_wontfix.yml
vendored
2
.github/workflows/issue_wontfix.yml
vendored
@ -10,7 +10,7 @@ jobs:
|
|||||||
if: github.event.label.name == 'wontfix'
|
if: github.event.label.name == 'wontfix'
|
||||||
steps:
|
steps:
|
||||||
- name: Create comment
|
- name: Create comment
|
||||||
uses: actions-cool/issues-helper@v2
|
uses: actions-cool/issues-helper@v3
|
||||||
with:
|
with:
|
||||||
actions: 'create-comment'
|
actions: 'create-comment'
|
||||||
token: ${{ secrets.GITHUB_TOKEN }}
|
token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
10
.github/workflows/release.yml
vendored
10
.github/workflows/release.yml
vendored
@ -11,7 +11,7 @@ jobs:
|
|||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout code
|
- name: Checkout code
|
||||||
uses: actions/checkout@v2
|
uses: actions/checkout@v3
|
||||||
with:
|
with:
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
- run: npx changelogithub # or changelogithub@0.12 if ensure the stable result
|
- run: npx changelogithub # or changelogithub@0.12 if ensure the stable result
|
||||||
@ -27,19 +27,19 @@ jobs:
|
|||||||
runs-on: ${{ matrix.platform }}
|
runs-on: ${{ matrix.platform }}
|
||||||
steps:
|
steps:
|
||||||
- name: Setup Go
|
- name: Setup Go
|
||||||
uses: actions/setup-go@v2
|
uses: actions/setup-go@v3
|
||||||
with:
|
with:
|
||||||
go-version: ${{ matrix.go-version }}
|
go-version: ${{ matrix.go-version }}
|
||||||
|
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v2
|
uses: actions/checkout@v3
|
||||||
with:
|
with:
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
|
|
||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
run: |
|
run: |
|
||||||
docker pull techknowlogick/xgo:latest
|
docker pull crazymax/xgo:latest
|
||||||
go install src.techknowlogick.com/xgo@latest
|
go install github.com/crazy-max/xgo@latest
|
||||||
sudo apt install upx
|
sudo apt install upx
|
||||||
|
|
||||||
- name: Build
|
- name: Build
|
||||||
|
12
.github/workflows/release_docker.yml
vendored
12
.github/workflows/release_docker.yml
vendored
@ -11,29 +11,29 @@ jobs:
|
|||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v2
|
uses: actions/checkout@v3
|
||||||
|
|
||||||
- name: Docker meta
|
- name: Docker meta
|
||||||
id: meta
|
id: meta
|
||||||
uses: docker/metadata-action@v3
|
uses: docker/metadata-action@v4
|
||||||
with:
|
with:
|
||||||
images: xhofe/alist
|
images: xhofe/alist
|
||||||
|
|
||||||
- name: Set up QEMU
|
- name: Set up QEMU
|
||||||
uses: docker/setup-qemu-action@v1
|
uses: docker/setup-qemu-action@v2
|
||||||
|
|
||||||
- name: Set up Docker Buildx
|
- name: Set up Docker Buildx
|
||||||
uses: docker/setup-buildx-action@v1
|
uses: docker/setup-buildx-action@v2
|
||||||
|
|
||||||
- name: Login to DockerHub
|
- name: Login to DockerHub
|
||||||
uses: docker/login-action@v1
|
uses: docker/login-action@v2
|
||||||
with:
|
with:
|
||||||
username: xhofe
|
username: xhofe
|
||||||
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||||
|
|
||||||
- name: Build and push
|
- name: Build and push
|
||||||
id: docker_build
|
id: docker_build
|
||||||
uses: docker/build-push-action@v2
|
uses: docker/build-push-action@v3
|
||||||
with:
|
with:
|
||||||
context: .
|
context: .
|
||||||
push: true
|
push: true
|
||||||
|
15
.gitignore
vendored
15
.gitignore
vendored
@ -20,11 +20,12 @@ output/
|
|||||||
|
|
||||||
# Dependency directories (remove the comment below to include it)
|
# Dependency directories (remove the comment below to include it)
|
||||||
# vendor/
|
# vendor/
|
||||||
bin/*
|
/bin/*
|
||||||
*.json
|
*.json
|
||||||
data/
|
/build
|
||||||
log/
|
/data/
|
||||||
lang/
|
/log/
|
||||||
daemon/
|
/lang/
|
||||||
public/dist/*
|
/daemon/
|
||||||
!public/dist/README.md
|
/public/dist/*
|
||||||
|
/!public/dist/README.md
|
||||||
|
@ -10,6 +10,9 @@ LABEL MAINTAINER="i@nn.ci"
|
|||||||
VOLUME /opt/alist/data/
|
VOLUME /opt/alist/data/
|
||||||
WORKDIR /opt/alist/
|
WORKDIR /opt/alist/
|
||||||
COPY --from=builder /app/bin/alist ./
|
COPY --from=builder /app/bin/alist ./
|
||||||
RUN apk add ca-certificates
|
COPY entrypoint.sh /entrypoint.sh
|
||||||
|
RUN apk add ca-certificates bash su-exec; \
|
||||||
|
chmod +x /entrypoint.sh
|
||||||
|
ENV PUID=0 PGID=0 UMASK=022
|
||||||
EXPOSE 5244
|
EXPOSE 5244
|
||||||
CMD [ "./alist", "server", "--no-prefix" ]
|
ENTRYPOINT [ "/entrypoint.sh" ]
|
||||||
|
@ -9,7 +9,7 @@
|
|||||||
<img src="https://img.shields.io/github/license/Xhofe/alist" alt="License" />
|
<img src="https://img.shields.io/github/license/Xhofe/alist" alt="License" />
|
||||||
</a>
|
</a>
|
||||||
<a href="https://github.com/Xhofe/alist/actions?query=workflow%3ABuild">
|
<a href="https://github.com/Xhofe/alist/actions?query=workflow%3ABuild">
|
||||||
<img src="https://img.shields.io/github/workflow/status/Xhofe/alist/build" alt="Build status" />
|
<img src="https://img.shields.io/github/actions/workflow/status/Xhofe/alist/build.yml?branch=main" alt="Build status" />
|
||||||
</a>
|
</a>
|
||||||
<a href="https://github.com/Xhofe/alist/releases">
|
<a href="https://github.com/Xhofe/alist/releases">
|
||||||
<img src="https://img.shields.io/github/release/Xhofe/alist" alt="latest version" />
|
<img src="https://img.shields.io/github/release/Xhofe/alist" alt="latest version" />
|
||||||
|
@ -9,7 +9,7 @@
|
|||||||
<img src="https://img.shields.io/github/license/Xhofe/alist" alt="License" />
|
<img src="https://img.shields.io/github/license/Xhofe/alist" alt="License" />
|
||||||
</a>
|
</a>
|
||||||
<a href="https://github.com/Xhofe/alist/actions?query=workflow%3ABuild">
|
<a href="https://github.com/Xhofe/alist/actions?query=workflow%3ABuild">
|
||||||
<img src="https://img.shields.io/github/workflow/status/Xhofe/alist/build" alt="Build status" />
|
<img src="https://img.shields.io/github/actions/workflow/status/Xhofe/alist/build.yml?branch=main" alt="Build status" />
|
||||||
</a>
|
</a>
|
||||||
<a href="https://github.com/Xhofe/alist/releases">
|
<a href="https://github.com/Xhofe/alist/releases">
|
||||||
<img src="https://img.shields.io/github/release/Xhofe/alist" alt="latest version" />
|
<img src="https://img.shields.io/github/release/Xhofe/alist" alt="latest version" />
|
||||||
|
10
cmd/admin.go
10
cmd/admin.go
@ -4,19 +4,19 @@ Copyright © 2022 NAME HERE <EMAIL ADDRESS>
|
|||||||
package cmd
|
package cmd
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/alist-org/alist/v3/internal/db"
|
"github.com/alist-org/alist/v3/internal/op"
|
||||||
"github.com/alist-org/alist/v3/pkg/utils"
|
"github.com/alist-org/alist/v3/pkg/utils"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
)
|
)
|
||||||
|
|
||||||
// passwordCmd represents the password command
|
// PasswordCmd represents the password command
|
||||||
var passwordCmd = &cobra.Command{
|
var PasswordCmd = &cobra.Command{
|
||||||
Use: "admin",
|
Use: "admin",
|
||||||
Aliases: []string{"password"},
|
Aliases: []string{"password"},
|
||||||
Short: "Show admin user's info",
|
Short: "Show admin user's info",
|
||||||
Run: func(cmd *cobra.Command, args []string) {
|
Run: func(cmd *cobra.Command, args []string) {
|
||||||
Init()
|
Init()
|
||||||
admin, err := db.GetAdmin()
|
admin, err := op.GetAdmin()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
utils.Log.Errorf("failed get admin user: %+v", err)
|
utils.Log.Errorf("failed get admin user: %+v", err)
|
||||||
} else {
|
} else {
|
||||||
@ -26,7 +26,7 @@ var passwordCmd = &cobra.Command{
|
|||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
rootCmd.AddCommand(passwordCmd)
|
RootCmd.AddCommand(PasswordCmd)
|
||||||
|
|
||||||
// Here you will define your flags and configuration settings.
|
// Here you will define your flags and configuration settings.
|
||||||
|
|
||||||
|
@ -4,22 +4,22 @@ Copyright © 2022 NAME HERE <EMAIL ADDRESS>
|
|||||||
package cmd
|
package cmd
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/alist-org/alist/v3/internal/db"
|
"github.com/alist-org/alist/v3/internal/op"
|
||||||
"github.com/alist-org/alist/v3/pkg/utils"
|
"github.com/alist-org/alist/v3/pkg/utils"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
)
|
)
|
||||||
|
|
||||||
// cancel2FACmd represents the delete2fa command
|
// Cancel2FACmd represents the delete2fa command
|
||||||
var cancel2FACmd = &cobra.Command{
|
var Cancel2FACmd = &cobra.Command{
|
||||||
Use: "cancel2fa",
|
Use: "cancel2fa",
|
||||||
Short: "Delete 2FA of admin user",
|
Short: "Delete 2FA of admin user",
|
||||||
Run: func(cmd *cobra.Command, args []string) {
|
Run: func(cmd *cobra.Command, args []string) {
|
||||||
Init()
|
Init()
|
||||||
admin, err := db.GetAdmin()
|
admin, err := op.GetAdmin()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
utils.Log.Errorf("failed to get admin user: %+v", err)
|
utils.Log.Errorf("failed to get admin user: %+v", err)
|
||||||
} else {
|
} else {
|
||||||
err := db.Cancel2FAByUser(admin)
|
err := op.Cancel2FAByUser(admin)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
utils.Log.Errorf("failed to cancel 2FA: %+v", err)
|
utils.Log.Errorf("failed to cancel 2FA: %+v", err)
|
||||||
}
|
}
|
||||||
@ -28,7 +28,7 @@ var cancel2FACmd = &cobra.Command{
|
|||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
rootCmd.AddCommand(cancel2FACmd)
|
RootCmd.AddCommand(Cancel2FACmd)
|
||||||
|
|
||||||
// Here you will define your flags and configuration settings.
|
// Here you will define your flags and configuration settings.
|
||||||
|
|
||||||
|
@ -16,6 +16,7 @@ func Init() {
|
|||||||
bootstrap.Log()
|
bootstrap.Log()
|
||||||
bootstrap.InitDB()
|
bootstrap.InitDB()
|
||||||
data.InitData()
|
data.InitData()
|
||||||
|
bootstrap.InitIndex()
|
||||||
}
|
}
|
||||||
|
|
||||||
var pid = -1
|
var pid = -1
|
||||||
|
@ -71,7 +71,7 @@ func writeFile(name string, data interface{}) {
|
|||||||
} else {
|
} else {
|
||||||
log.Infof("%s.json changed, update file", name)
|
log.Infof("%s.json changed, update file", name)
|
||||||
//log.Infof("old: %+v\nnew:%+v", oldData, data)
|
//log.Infof("old: %+v\nnew:%+v", oldData, data)
|
||||||
utils.WriteJsonToFile(fmt.Sprintf("lang/%s.json", name), data)
|
utils.WriteJsonToFile(fmt.Sprintf("lang/%s.json", name), newData, true)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -123,8 +123,8 @@ func generateSettingsJson() {
|
|||||||
//utils.WriteJsonToFile("lang/settings.json", settingsLang)
|
//utils.WriteJsonToFile("lang/settings.json", settingsLang)
|
||||||
}
|
}
|
||||||
|
|
||||||
// langCmd represents the lang command
|
// LangCmd represents the lang command
|
||||||
var langCmd = &cobra.Command{
|
var LangCmd = &cobra.Command{
|
||||||
Use: "lang",
|
Use: "lang",
|
||||||
Short: "Generate language json file",
|
Short: "Generate language json file",
|
||||||
Run: func(cmd *cobra.Command, args []string) {
|
Run: func(cmd *cobra.Command, args []string) {
|
||||||
@ -138,7 +138,7 @@ var langCmd = &cobra.Command{
|
|||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
rootCmd.AddCommand(langCmd)
|
RootCmd.AddCommand(LangCmd)
|
||||||
|
|
||||||
// Here you will define your flags and configuration settings.
|
// Here you will define your flags and configuration settings.
|
||||||
|
|
||||||
|
@ -7,8 +7,8 @@ import (
|
|||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
)
|
)
|
||||||
|
|
||||||
// restartCmd represents the restart command
|
// RestartCmd represents the restart command
|
||||||
var restartCmd = &cobra.Command{
|
var RestartCmd = &cobra.Command{
|
||||||
Use: "restart",
|
Use: "restart",
|
||||||
Short: "Restart alist server by daemon/pid file",
|
Short: "Restart alist server by daemon/pid file",
|
||||||
Run: func(cmd *cobra.Command, args []string) {
|
Run: func(cmd *cobra.Command, args []string) {
|
||||||
@ -18,7 +18,7 @@ var restartCmd = &cobra.Command{
|
|||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
rootCmd.AddCommand(restartCmd)
|
RootCmd.AddCommand(RestartCmd)
|
||||||
|
|
||||||
// Here you will define your flags and configuration settings.
|
// Here you will define your flags and configuration settings.
|
||||||
|
|
||||||
|
14
cmd/root.go
14
cmd/root.go
@ -8,7 +8,7 @@ import (
|
|||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
)
|
)
|
||||||
|
|
||||||
var rootCmd = &cobra.Command{
|
var RootCmd = &cobra.Command{
|
||||||
Use: "alist",
|
Use: "alist",
|
||||||
Short: "A file list program that supports multiple storage.",
|
Short: "A file list program that supports multiple storage.",
|
||||||
Long: `A file list program that supports multiple storage,
|
Long: `A file list program that supports multiple storage,
|
||||||
@ -17,16 +17,16 @@ Complete documentation is available at https://alist.nn.ci/`,
|
|||||||
}
|
}
|
||||||
|
|
||||||
func Execute() {
|
func Execute() {
|
||||||
if err := rootCmd.Execute(); err != nil {
|
if err := RootCmd.Execute(); err != nil {
|
||||||
fmt.Fprintln(os.Stderr, err)
|
fmt.Fprintln(os.Stderr, err)
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
rootCmd.PersistentFlags().StringVar(&flags.DataDir, "data", "data", "config file")
|
RootCmd.PersistentFlags().StringVar(&flags.DataDir, "data", "data", "config file")
|
||||||
rootCmd.PersistentFlags().BoolVar(&flags.Debug, "debug", false, "start with debug mode")
|
RootCmd.PersistentFlags().BoolVar(&flags.Debug, "debug", false, "start with debug mode")
|
||||||
rootCmd.PersistentFlags().BoolVar(&flags.NoPrefix, "no-prefix", false, "disable env prefix")
|
RootCmd.PersistentFlags().BoolVar(&flags.NoPrefix, "no-prefix", false, "disable env prefix")
|
||||||
rootCmd.PersistentFlags().BoolVar(&flags.Dev, "dev", false, "start with dev mode")
|
RootCmd.PersistentFlags().BoolVar(&flags.Dev, "dev", false, "start with dev mode")
|
||||||
rootCmd.PersistentFlags().BoolVar(&flags.ForceBinDir, "force-bin-dir", false, "Force to use the directory where the binary file is located as data directory")
|
RootCmd.PersistentFlags().BoolVar(&flags.ForceBinDir, "force-bin-dir", false, "Force to use the directory where the binary file is located as data directory")
|
||||||
}
|
}
|
||||||
|
@ -20,8 +20,8 @@ import (
|
|||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
)
|
)
|
||||||
|
|
||||||
// serverCmd represents the server command
|
// ServerCmd represents the server command
|
||||||
var serverCmd = &cobra.Command{
|
var ServerCmd = &cobra.Command{
|
||||||
Use: "server",
|
Use: "server",
|
||||||
Short: "Start the server at the specified address",
|
Short: "Start the server at the specified address",
|
||||||
Long: `Start the server at the specified address
|
Long: `Start the server at the specified address
|
||||||
@ -76,7 +76,7 @@ the address is defined in config file`,
|
|||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
rootCmd.AddCommand(serverCmd)
|
RootCmd.AddCommand(ServerCmd)
|
||||||
|
|
||||||
// Here you will define your flags and configuration settings.
|
// Here you will define your flags and configuration settings.
|
||||||
|
|
||||||
@ -95,5 +95,5 @@ func OutAlistInit() {
|
|||||||
cmd *cobra.Command
|
cmd *cobra.Command
|
||||||
args []string
|
args []string
|
||||||
)
|
)
|
||||||
serverCmd.Run(cmd, args)
|
ServerCmd.Run(cmd, args)
|
||||||
}
|
}
|
||||||
|
@ -13,8 +13,8 @@ import (
|
|||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
)
|
)
|
||||||
|
|
||||||
// startCmd represents the start command
|
// StartCmd represents the start command
|
||||||
var startCmd = &cobra.Command{
|
var StartCmd = &cobra.Command{
|
||||||
Use: "start",
|
Use: "start",
|
||||||
Short: "Silent start alist server with `--force-bin-dir`",
|
Short: "Silent start alist server with `--force-bin-dir`",
|
||||||
Run: func(cmd *cobra.Command, args []string) {
|
Run: func(cmd *cobra.Command, args []string) {
|
||||||
@ -57,7 +57,7 @@ func start() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
rootCmd.AddCommand(startCmd)
|
RootCmd.AddCommand(StartCmd)
|
||||||
|
|
||||||
// Here you will define your flags and configuration settings.
|
// Here you will define your flags and configuration settings.
|
||||||
|
|
||||||
|
@ -10,8 +10,8 @@ import (
|
|||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
)
|
)
|
||||||
|
|
||||||
// stopCmd represents the stop command
|
// StopCmd represents the stop command
|
||||||
var stopCmd = &cobra.Command{
|
var StopCmd = &cobra.Command{
|
||||||
Use: "stop",
|
Use: "stop",
|
||||||
Short: "Stop alist server by daemon/pid file",
|
Short: "Stop alist server by daemon/pid file",
|
||||||
Run: func(cmd *cobra.Command, args []string) {
|
Run: func(cmd *cobra.Command, args []string) {
|
||||||
@ -44,7 +44,7 @@ func stop() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
rootCmd.AddCommand(stopCmd)
|
RootCmd.AddCommand(StopCmd)
|
||||||
|
|
||||||
// Here you will define your flags and configuration settings.
|
// Here you will define your flags and configuration settings.
|
||||||
|
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
Copyright © 2022 NAME HERE <EMAIL ADDRESS>
|
Copyright © 2022 NAME HERE <EMAIL ADDRESS>
|
||||||
|
|
||||||
*/
|
*/
|
||||||
package cmd
|
package cmd
|
||||||
|
|
||||||
@ -12,8 +11,8 @@ import (
|
|||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
)
|
)
|
||||||
|
|
||||||
// versionCmd represents the version command
|
// VersionCmd represents the version command
|
||||||
var versionCmd = &cobra.Command{
|
var VersionCmd = &cobra.Command{
|
||||||
Use: "version",
|
Use: "version",
|
||||||
Short: "Show current version of AList",
|
Short: "Show current version of AList",
|
||||||
Run: func(cmd *cobra.Command, args []string) {
|
Run: func(cmd *cobra.Command, args []string) {
|
||||||
@ -30,7 +29,7 @@ WebVersion: %s
|
|||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
rootCmd.AddCommand(versionCmd)
|
RootCmd.AddCommand(VersionCmd)
|
||||||
|
|
||||||
// Here you will define your flags and configuration settings.
|
// Here you will define your flags and configuration settings.
|
||||||
|
|
||||||
|
14
docker-compose.yml
Normal file
14
docker-compose.yml
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
version: '3.3'
|
||||||
|
services:
|
||||||
|
alist:
|
||||||
|
restart: always
|
||||||
|
volumes:
|
||||||
|
- '/etc/alist:/opt/alist/data'
|
||||||
|
ports:
|
||||||
|
- '5244:5244'
|
||||||
|
environment:
|
||||||
|
- PUID=0
|
||||||
|
- PGID=0
|
||||||
|
- UMASK=022
|
||||||
|
container_name: alist
|
||||||
|
image: 'xhofe/alist:latest'
|
@ -22,15 +22,10 @@ func (d *Pan115) Config() driver.Config {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (d *Pan115) GetAddition() driver.Additional {
|
func (d *Pan115) GetAddition() driver.Additional {
|
||||||
return d.Addition
|
return &d.Addition
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *Pan115) Init(ctx context.Context, storage model.Storage) error {
|
func (d *Pan115) Init(ctx context.Context) error {
|
||||||
d.Storage = storage
|
|
||||||
err := utils.Json.UnmarshalFromString(d.Storage.Addition, &d.Addition)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return d.login()
|
return d.login()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6,7 +6,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type Addition struct {
|
type Addition struct {
|
||||||
Cookie string `json:"cookie"`
|
Cookie string `json:"cookie"`
|
||||||
QRCodeToken string `json:"qrcode_token"`
|
QRCodeToken string `json:"qrcode_token"`
|
||||||
driver.RootID
|
driver.RootID
|
||||||
}
|
}
|
||||||
@ -18,10 +18,8 @@ var config = driver.Config{
|
|||||||
OnlyLocal: true,
|
OnlyLocal: true,
|
||||||
}
|
}
|
||||||
|
|
||||||
func New() driver.Driver {
|
|
||||||
return &Pan115{}
|
|
||||||
}
|
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
op.RegisterDriver(config, New)
|
op.RegisterDriver(func() driver.Driver {
|
||||||
|
return &Pan115{}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
@ -4,9 +4,9 @@ import (
|
|||||||
"bytes"
|
"bytes"
|
||||||
"context"
|
"context"
|
||||||
"crypto/md5"
|
"crypto/md5"
|
||||||
|
"encoding/base64"
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
"encoding/base64"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"net/http"
|
"net/http"
|
||||||
@ -37,15 +37,10 @@ func (d *Pan123) Config() driver.Config {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (d *Pan123) GetAddition() driver.Additional {
|
func (d *Pan123) GetAddition() driver.Additional {
|
||||||
return d.Addition
|
return &d.Addition
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *Pan123) Init(ctx context.Context, storage model.Storage) error {
|
func (d *Pan123) Init(ctx context.Context) error {
|
||||||
d.Storage = storage
|
|
||||||
err := utils.Json.UnmarshalFromString(d.Storage.Addition, &d.Addition)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return d.login()
|
return d.login()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -63,14 +58,9 @@ func (d *Pan123) List(ctx context.Context, dir model.Obj, args model.ListArgs) (
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
//func (d *Pan123) Get(ctx context.Context, path string) (model.Obj, error) {
|
|
||||||
// // this is optional
|
|
||||||
// return nil, errs.NotImplement
|
|
||||||
//}
|
|
||||||
|
|
||||||
func (d *Pan123) Link(ctx context.Context, file model.Obj, args model.LinkArgs) (*model.Link, error) {
|
func (d *Pan123) Link(ctx context.Context, file model.Obj, args model.LinkArgs) (*model.Link, error) {
|
||||||
if f, ok := file.(File); ok {
|
if f, ok := file.(File); ok {
|
||||||
var resp DownResp
|
//var resp DownResp
|
||||||
var headers map[string]string
|
var headers map[string]string
|
||||||
if !utils.IsLocalIPAddr(args.IP) {
|
if !utils.IsLocalIPAddr(args.IP) {
|
||||||
headers = map[string]string{
|
headers = map[string]string{
|
||||||
@ -87,13 +77,14 @@ func (d *Pan123) Link(ctx context.Context, file model.Obj, args model.LinkArgs)
|
|||||||
"size": f.Size,
|
"size": f.Size,
|
||||||
"type": f.Type,
|
"type": f.Type,
|
||||||
}
|
}
|
||||||
_, err := d.request("https://www.123pan.com/api/file/download_info", http.MethodPost, func(req *resty.Request) {
|
resp, err := d.request("https://www.123pan.com/api/file/download_info", http.MethodPost, func(req *resty.Request) {
|
||||||
req.SetBody(data).SetHeaders(headers)
|
req.SetBody(data).SetHeaders(headers)
|
||||||
}, &resp)
|
}, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
u, err := url.Parse(resp.Data.DownloadUrl)
|
downloadUrl := utils.Json.Get(resp, "data", "DownloadUrl").ToString()
|
||||||
|
u, err := url.Parse(downloadUrl)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -112,7 +103,7 @@ func (d *Pan123) Link(ctx context.Context, file model.Obj, args model.LinkArgs)
|
|||||||
}
|
}
|
||||||
log.Debug(res.String())
|
log.Debug(res.String())
|
||||||
link := model.Link{
|
link := model.Link{
|
||||||
URL: resp.Data.DownloadUrl,
|
URL: downloadUrl,
|
||||||
}
|
}
|
||||||
log.Debugln("res code: ", res.StatusCode())
|
log.Debugln("res code: ", res.StatusCode())
|
||||||
if res.StatusCode() == 302 {
|
if res.StatusCode() == 302 {
|
||||||
@ -229,13 +220,13 @@ func (d *Pan123) Put(ctx context.Context, dstDir model.Obj, stream model.FileStr
|
|||||||
"type": 0,
|
"type": 0,
|
||||||
}
|
}
|
||||||
var resp UploadResp
|
var resp UploadResp
|
||||||
_, err := d.request("https://www.123pan.com/api/file/upload_request", http.MethodPost, func(req *resty.Request) {
|
_, err := d.request("https://www.123pan.com/a/api/file/upload_request", http.MethodPost, func(req *resty.Request) {
|
||||||
req.SetBody(data)
|
req.SetBody(data).SetContext(ctx)
|
||||||
}, &resp)
|
}, &resp)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if resp.Data.Key == "" {
|
if resp.Data.Reuse || resp.Data.Key == "" {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
cfg := &aws.Config{
|
cfg := &aws.Config{
|
||||||
@ -254,14 +245,14 @@ func (d *Pan123) Put(ctx context.Context, dstDir model.Obj, stream model.FileStr
|
|||||||
Key: &resp.Data.Key,
|
Key: &resp.Data.Key,
|
||||||
Body: uploadFile,
|
Body: uploadFile,
|
||||||
}
|
}
|
||||||
_, err = uploader.Upload(input)
|
_, err = uploader.UploadWithContext(ctx, input)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
_, err = d.request("https://www.123pan.com/api/file/upload_complete", http.MethodPost, func(req *resty.Request) {
|
_, err = d.request("https://www.123pan.com/api/file/upload_complete", http.MethodPost, func(req *resty.Request) {
|
||||||
req.SetBody(base.Json{
|
req.SetBody(base.Json{
|
||||||
"fileId": resp.Data.FileId,
|
"fileId": resp.Data.FileId,
|
||||||
})
|
}).SetContext(ctx)
|
||||||
}, nil)
|
}, nil)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -21,10 +21,8 @@ var config = driver.Config{
|
|||||||
DefaultRoot: "0",
|
DefaultRoot: "0",
|
||||||
}
|
}
|
||||||
|
|
||||||
func New() driver.Driver {
|
|
||||||
return &Pan123{}
|
|
||||||
}
|
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
op.RegisterDriver(config, New)
|
op.RegisterDriver(func() driver.Driver {
|
||||||
|
return &Pan123{}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
@ -7,13 +7,13 @@ import (
|
|||||||
"github.com/alist-org/alist/v3/internal/model"
|
"github.com/alist-org/alist/v3/internal/model"
|
||||||
)
|
)
|
||||||
|
|
||||||
type BaseResp struct {
|
//type BaseResp struct {
|
||||||
Code int `json:"code"`
|
// Code interface{} `json:"code"`
|
||||||
Message string `json:"message"`
|
// Message string `json:"message"`
|
||||||
}
|
//}
|
||||||
|
|
||||||
type TokenResp struct {
|
type TokenResp struct {
|
||||||
BaseResp
|
//BaseResp
|
||||||
Data struct {
|
Data struct {
|
||||||
Token string `json:"token"`
|
Token string `json:"token"`
|
||||||
} `json:"data"`
|
} `json:"data"`
|
||||||
@ -62,22 +62,22 @@ var _ model.Obj = (*File)(nil)
|
|||||||
//var _ model.Thumb = (*File)(nil)
|
//var _ model.Thumb = (*File)(nil)
|
||||||
|
|
||||||
type Files struct {
|
type Files struct {
|
||||||
BaseResp
|
//BaseResp
|
||||||
Data struct {
|
Data struct {
|
||||||
InfoList []File `json:"InfoList"`
|
InfoList []File `json:"InfoList"`
|
||||||
Next string `json:"Next"`
|
Next string `json:"Next"`
|
||||||
} `json:"data"`
|
} `json:"data"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type DownResp struct {
|
//type DownResp struct {
|
||||||
BaseResp
|
// //BaseResp
|
||||||
Data struct {
|
// Data struct {
|
||||||
DownloadUrl string `json:"DownloadUrl"`
|
// DownloadUrl string `json:"DownloadUrl"`
|
||||||
} `json:"data"`
|
// } `json:"data"`
|
||||||
}
|
//}
|
||||||
|
|
||||||
type UploadResp struct {
|
type UploadResp struct {
|
||||||
BaseResp
|
//BaseResp
|
||||||
Data struct {
|
Data struct {
|
||||||
AccessKeyId string `json:"AccessKeyId"`
|
AccessKeyId string `json:"AccessKeyId"`
|
||||||
Bucket string `json:"Bucket"`
|
Bucket string `json:"Bucket"`
|
||||||
@ -85,5 +85,6 @@ type UploadResp struct {
|
|||||||
SecretAccessKey string `json:"SecretAccessKey"`
|
SecretAccessKey string `json:"SecretAccessKey"`
|
||||||
SessionToken string `json:"SessionToken"`
|
SessionToken string `json:"SessionToken"`
|
||||||
FileId int64 `json:"FileId"`
|
FileId int64 `json:"FileId"`
|
||||||
|
Reuse bool `json:"Reuse"`
|
||||||
} `json:"data"`
|
} `json:"data"`
|
||||||
}
|
}
|
||||||
|
@ -15,7 +15,7 @@ import (
|
|||||||
|
|
||||||
func (d *Pan123) login() error {
|
func (d *Pan123) login() error {
|
||||||
var body base.Json
|
var body base.Json
|
||||||
url := "https://www.123pan.com/api/user/sign_in"
|
url := "https://www.123pan.com/a/api/user/sign_in"
|
||||||
if utils.IsEmailFormat(d.Username) {
|
if utils.IsEmailFormat(d.Username) {
|
||||||
body = base.Json{
|
body = base.Json{
|
||||||
"mail": d.Username,
|
"mail": d.Username,
|
||||||
@ -29,14 +29,14 @@ func (d *Pan123) login() error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
var resp TokenResp
|
var resp TokenResp
|
||||||
_, err := base.RestyClient.R().
|
res, err := base.RestyClient.R().
|
||||||
SetResult(&resp).
|
SetResult(&resp).
|
||||||
SetBody(body).Post(url)
|
SetBody(body).Post(url)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if resp.Code != 200 {
|
if utils.Json.Get(res.Body(), "code").ToInt() != 200 {
|
||||||
err = fmt.Errorf(resp.Message)
|
err = fmt.Errorf(utils.Json.Get(res.Body(), "message").ToString())
|
||||||
} else {
|
} else {
|
||||||
d.AccessToken = resp.Data.Token
|
d.AccessToken = resp.Data.Token
|
||||||
}
|
}
|
||||||
@ -45,7 +45,12 @@ func (d *Pan123) login() error {
|
|||||||
|
|
||||||
func (d *Pan123) request(url string, method string, callback base.ReqCallback, resp interface{}) ([]byte, error) {
|
func (d *Pan123) request(url string, method string, callback base.ReqCallback, resp interface{}) ([]byte, error) {
|
||||||
req := base.RestyClient.R()
|
req := base.RestyClient.R()
|
||||||
req.SetHeader("Authorization", "Bearer "+d.AccessToken)
|
req.SetHeaders(map[string]string{
|
||||||
|
"origin": "https://www.123pan.com",
|
||||||
|
"authorization": "Bearer " + d.AccessToken,
|
||||||
|
"platform": "web",
|
||||||
|
"app-version": "1.2",
|
||||||
|
})
|
||||||
if callback != nil {
|
if callback != nil {
|
||||||
callback(req)
|
callback(req)
|
||||||
}
|
}
|
||||||
@ -57,7 +62,7 @@ func (d *Pan123) request(url string, method string, callback base.ReqCallback, r
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
body := res.Body()
|
body := res.Body()
|
||||||
code := jsoniter.Get(body, "code").ToInt()
|
code := utils.Json.Get(body, "code").ToInt()
|
||||||
if code != 0 {
|
if code != 0 {
|
||||||
if code == 401 {
|
if code == 401 {
|
||||||
err := d.login()
|
err := d.login()
|
||||||
|
@ -27,16 +27,11 @@ func (d *Yun139) Config() driver.Config {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (d *Yun139) GetAddition() driver.Additional {
|
func (d *Yun139) GetAddition() driver.Additional {
|
||||||
return d.Addition
|
return &d.Addition
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *Yun139) Init(ctx context.Context, storage model.Storage) error {
|
func (d *Yun139) Init(ctx context.Context) error {
|
||||||
d.Storage = storage
|
_, err := d.post("/orchestration/personalCloud/user/v1.0/qryUserExternInfo", base.Json{
|
||||||
err := utils.Json.UnmarshalFromString(d.Storage.Addition, &d.Addition)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
_, err = d.post("/orchestration/personalCloud/user/v1.0/qryUserExternInfo", base.Json{
|
|
||||||
"qryUserExternInfoReq": base.Json{
|
"qryUserExternInfoReq": base.Json{
|
||||||
"commonAccountInfo": base.Json{
|
"commonAccountInfo": base.Json{
|
||||||
"account": d.Account,
|
"account": d.Account,
|
||||||
@ -59,11 +54,6 @@ func (d *Yun139) List(ctx context.Context, dir model.Obj, args model.ListArgs) (
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//func (d *Yun139) Get(ctx context.Context, path string) (model.Obj, error) {
|
|
||||||
// // this is optional
|
|
||||||
// return nil, errs.NotImplement
|
|
||||||
//}
|
|
||||||
|
|
||||||
func (d *Yun139) Link(ctx context.Context, file model.Obj, args model.LinkArgs) (*model.Link, error) {
|
func (d *Yun139) Link(ctx context.Context, file model.Obj, args model.LinkArgs) (*model.Link, error) {
|
||||||
u, err := d.getLink(file.GetID())
|
u, err := d.getLink(file.GetID())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -275,10 +265,13 @@ func (d *Yun139) Put(ctx context.Context, dstDir model.Obj, stream model.FileStr
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
var Default int64 = 10485760
|
var Default int64 = 104857600
|
||||||
part := int(math.Ceil(float64(stream.GetSize()) / float64(Default)))
|
part := int(math.Ceil(float64(stream.GetSize()) / float64(Default)))
|
||||||
var start int64 = 0
|
var start int64 = 0
|
||||||
for i := 0; i < part; i++ {
|
for i := 0; i < part; i++ {
|
||||||
|
if utils.IsCanceled(ctx) {
|
||||||
|
return ctx.Err()
|
||||||
|
}
|
||||||
byteSize := stream.GetSize() - start
|
byteSize := stream.GetSize() - start
|
||||||
if byteSize > Default {
|
if byteSize > Default {
|
||||||
byteSize = Default
|
byteSize = Default
|
||||||
@ -292,6 +285,7 @@ func (d *Yun139) Put(ctx context.Context, dstDir model.Obj, stream model.FileStr
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
req = req.WithContext(ctx)
|
||||||
headers := map[string]string{
|
headers := map[string]string{
|
||||||
"Accept": "*/*",
|
"Accept": "*/*",
|
||||||
"Content-Type": "text/plain;name=" + unicode(stream.GetName()),
|
"Content-Type": "text/plain;name=" + unicode(stream.GetName()),
|
||||||
|
@ -19,7 +19,7 @@ var config = driver.Config{
|
|||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
op.RegisterDriver(config, func() driver.Driver {
|
op.RegisterDriver(func() driver.Driver {
|
||||||
return &Yun139{}
|
return &Yun139{}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -26,15 +26,10 @@ func (d *Cloud189) Config() driver.Config {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (d *Cloud189) GetAddition() driver.Additional {
|
func (d *Cloud189) GetAddition() driver.Additional {
|
||||||
return d.Addition
|
return &d.Addition
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *Cloud189) Init(ctx context.Context, storage model.Storage) error {
|
func (d *Cloud189) Init(ctx context.Context) error {
|
||||||
d.Storage = storage
|
|
||||||
err := utils.Json.UnmarshalFromString(d.Storage.Addition, &d.Addition)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
d.client = resty.New().
|
d.client = resty.New().
|
||||||
SetTimeout(base.DefaultTimeout).
|
SetTimeout(base.DefaultTimeout).
|
||||||
SetRetryCount(3).
|
SetRetryCount(3).
|
||||||
@ -51,11 +46,6 @@ func (d *Cloud189) List(ctx context.Context, dir model.Obj, args model.ListArgs)
|
|||||||
return d.getFiles(dir.GetID())
|
return d.getFiles(dir.GetID())
|
||||||
}
|
}
|
||||||
|
|
||||||
//func (d *Cloud189) Get(ctx context.Context, path string) (model.Obj, error) {
|
|
||||||
// // this is optional
|
|
||||||
// return nil, errs.NotImplement
|
|
||||||
//}
|
|
||||||
|
|
||||||
func (d *Cloud189) Link(ctx context.Context, file model.Obj, args model.LinkArgs) (*model.Link, error) {
|
func (d *Cloud189) Link(ctx context.Context, file model.Obj, args model.LinkArgs) (*model.Link, error) {
|
||||||
var resp DownResp
|
var resp DownResp
|
||||||
u := "https://cloud.189.cn/api/portal/getFileInfo.action"
|
u := "https://cloud.189.cn/api/portal/getFileInfo.action"
|
||||||
@ -204,7 +194,7 @@ func (d *Cloud189) Remove(ctx context.Context, obj model.Obj) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (d *Cloud189) Put(ctx context.Context, dstDir model.Obj, stream model.FileStreamer, up driver.UpdateProgress) error {
|
func (d *Cloud189) Put(ctx context.Context, dstDir model.Obj, stream model.FileStreamer, up driver.UpdateProgress) error {
|
||||||
return d.newUpload(dstDir, stream, up)
|
return d.newUpload(ctx, dstDir, stream, up)
|
||||||
}
|
}
|
||||||
|
|
||||||
var _ driver.Driver = (*Cloud189)(nil)
|
var _ driver.Driver = (*Cloud189)(nil)
|
||||||
|
@ -18,7 +18,7 @@ var config = driver.Config{
|
|||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
op.RegisterDriver(config, func() driver.Driver {
|
op.RegisterDriver(func() driver.Driver {
|
||||||
return &Cloud189{}
|
return &Cloud189{}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,7 @@ package _189
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
"context"
|
||||||
"crypto/md5"
|
"crypto/md5"
|
||||||
"encoding/base64"
|
"encoding/base64"
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
@ -306,7 +307,7 @@ func (d *Cloud189) uploadRequest(uri string, form map[string]string, resp interf
|
|||||||
return data, nil
|
return data, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *Cloud189) newUpload(dstDir model.Obj, file model.FileStreamer, up driver.UpdateProgress) error {
|
func (d *Cloud189) newUpload(ctx context.Context, dstDir model.Obj, file model.FileStreamer, up driver.UpdateProgress) error {
|
||||||
sessionKey, err := d.getSessionKey()
|
sessionKey, err := d.getSessionKey()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@ -335,6 +336,9 @@ func (d *Cloud189) newUpload(dstDir model.Obj, file model.FileStreamer, up drive
|
|||||||
md5s := make([]string, 0)
|
md5s := make([]string, 0)
|
||||||
md5Sum := md5.New()
|
md5Sum := md5.New()
|
||||||
for i = 1; i <= count; i++ {
|
for i = 1; i <= count; i++ {
|
||||||
|
if utils.IsCanceled(ctx) {
|
||||||
|
return ctx.Err()
|
||||||
|
}
|
||||||
byteSize = file.GetSize() - finish
|
byteSize = file.GetSize() - finish
|
||||||
if DEFAULT < byteSize {
|
if DEFAULT < byteSize {
|
||||||
byteSize = DEFAULT
|
byteSize = DEFAULT
|
||||||
@ -364,12 +368,15 @@ func (d *Cloud189) newUpload(dstDir model.Obj, file model.FileStreamer, up drive
|
|||||||
log.Debugf("uploadData: %+v", uploadData)
|
log.Debugf("uploadData: %+v", uploadData)
|
||||||
requestURL := uploadData.RequestURL
|
requestURL := uploadData.RequestURL
|
||||||
uploadHeaders := strings.Split(decodeURIComponent(uploadData.RequestHeader), "&")
|
uploadHeaders := strings.Split(decodeURIComponent(uploadData.RequestHeader), "&")
|
||||||
req, _ := http.NewRequest(http.MethodPut, requestURL, bytes.NewReader(byteData))
|
req, err := http.NewRequest(http.MethodPut, requestURL, bytes.NewReader(byteData))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
req = req.WithContext(ctx)
|
||||||
for _, v := range uploadHeaders {
|
for _, v := range uploadHeaders {
|
||||||
i := strings.Index(v, "=")
|
i := strings.Index(v, "=")
|
||||||
req.Header.Set(v[0:i], v[i+1:])
|
req.Header.Set(v[0:i], v[i+1:])
|
||||||
}
|
}
|
||||||
|
|
||||||
r, err := base.HttpClient.Do(req)
|
r, err := base.HttpClient.Do(req)
|
||||||
log.Debugf("%+v %+v", r, r.Request.Header)
|
log.Debugf("%+v %+v", r, r.Request.Header)
|
||||||
r.Body.Close()
|
r.Body.Close()
|
||||||
|
@ -13,7 +13,7 @@ import (
|
|||||||
"github.com/go-resty/resty/v2"
|
"github.com/go-resty/resty/v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Yun189PC struct {
|
type Cloud189PC struct {
|
||||||
model.Storage
|
model.Storage
|
||||||
Addition
|
Addition
|
||||||
|
|
||||||
@ -26,20 +26,15 @@ type Yun189PC struct {
|
|||||||
tokenInfo *AppSessionResp
|
tokenInfo *AppSessionResp
|
||||||
}
|
}
|
||||||
|
|
||||||
func (y *Yun189PC) Config() driver.Config {
|
func (y *Cloud189PC) Config() driver.Config {
|
||||||
return config
|
return config
|
||||||
}
|
}
|
||||||
|
|
||||||
func (y *Yun189PC) GetAddition() driver.Additional {
|
func (y *Cloud189PC) GetAddition() driver.Additional {
|
||||||
return y.Addition
|
return &y.Addition
|
||||||
}
|
}
|
||||||
|
|
||||||
func (y *Yun189PC) Init(ctx context.Context, storage model.Storage) (err error) {
|
func (y *Cloud189PC) Init(ctx context.Context) (err error) {
|
||||||
y.Storage = storage
|
|
||||||
if err = utils.Json.UnmarshalFromString(y.Storage.Addition, &y.Addition); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// 处理个人云和家庭云参数
|
// 处理个人云和家庭云参数
|
||||||
if y.isFamily() && y.RootFolderID == "-11" {
|
if y.isFamily() && y.RootFolderID == "-11" {
|
||||||
y.RootFolderID = ""
|
y.RootFolderID = ""
|
||||||
@ -78,15 +73,15 @@ func (y *Yun189PC) Init(ctx context.Context, storage model.Storage) (err error)
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (y *Yun189PC) Drop(ctx context.Context) error {
|
func (y *Cloud189PC) Drop(ctx context.Context) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (y *Yun189PC) List(ctx context.Context, dir model.Obj, args model.ListArgs) ([]model.Obj, error) {
|
func (y *Cloud189PC) List(ctx context.Context, dir model.Obj, args model.ListArgs) ([]model.Obj, error) {
|
||||||
return y.getFiles(ctx, dir.GetID())
|
return y.getFiles(ctx, dir.GetID())
|
||||||
}
|
}
|
||||||
|
|
||||||
func (y *Yun189PC) Link(ctx context.Context, file model.Obj, args model.LinkArgs) (*model.Link, error) {
|
func (y *Cloud189PC) Link(ctx context.Context, file model.Obj, args model.LinkArgs) (*model.Link, error) {
|
||||||
var downloadUrl struct {
|
var downloadUrl struct {
|
||||||
URL string `json:"fileDownloadUrl"`
|
URL string `json:"fileDownloadUrl"`
|
||||||
}
|
}
|
||||||
@ -145,7 +140,7 @@ func (y *Yun189PC) Link(ctx context.Context, file model.Obj, args model.LinkArgs
|
|||||||
return like, nil
|
return like, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (y *Yun189PC) MakeDir(ctx context.Context, parentDir model.Obj, dirName string) error {
|
func (y *Cloud189PC) MakeDir(ctx context.Context, parentDir model.Obj, dirName string) error {
|
||||||
fullUrl := API_URL
|
fullUrl := API_URL
|
||||||
if y.isFamily() {
|
if y.isFamily() {
|
||||||
fullUrl += "/family/file"
|
fullUrl += "/family/file"
|
||||||
@ -172,7 +167,7 @@ func (y *Yun189PC) MakeDir(ctx context.Context, parentDir model.Obj, dirName str
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (y *Yun189PC) Move(ctx context.Context, srcObj, dstDir model.Obj) error {
|
func (y *Cloud189PC) Move(ctx context.Context, srcObj, dstDir model.Obj) error {
|
||||||
_, err := y.post(API_URL+"/batch/createBatchTask.action", func(req *resty.Request) {
|
_, err := y.post(API_URL+"/batch/createBatchTask.action", func(req *resty.Request) {
|
||||||
req.SetContext(ctx)
|
req.SetContext(ctx)
|
||||||
req.SetFormData(map[string]string{
|
req.SetFormData(map[string]string{
|
||||||
@ -196,7 +191,7 @@ func (y *Yun189PC) Move(ctx context.Context, srcObj, dstDir model.Obj) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (y *Yun189PC) Rename(ctx context.Context, srcObj model.Obj, newName string) error {
|
func (y *Cloud189PC) Rename(ctx context.Context, srcObj model.Obj, newName string) error {
|
||||||
queryParam := make(map[string]string)
|
queryParam := make(map[string]string)
|
||||||
fullUrl := API_URL
|
fullUrl := API_URL
|
||||||
method := http.MethodPost
|
method := http.MethodPost
|
||||||
@ -221,7 +216,7 @@ func (y *Yun189PC) Rename(ctx context.Context, srcObj model.Obj, newName string)
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (y *Yun189PC) Copy(ctx context.Context, srcObj, dstDir model.Obj) error {
|
func (y *Cloud189PC) Copy(ctx context.Context, srcObj, dstDir model.Obj) error {
|
||||||
_, err := y.post(API_URL+"/batch/createBatchTask.action", func(req *resty.Request) {
|
_, err := y.post(API_URL+"/batch/createBatchTask.action", func(req *resty.Request) {
|
||||||
req.SetContext(ctx)
|
req.SetContext(ctx)
|
||||||
req.SetFormData(map[string]string{
|
req.SetFormData(map[string]string{
|
||||||
@ -246,7 +241,7 @@ func (y *Yun189PC) Copy(ctx context.Context, srcObj, dstDir model.Obj) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (y *Yun189PC) Remove(ctx context.Context, obj model.Obj) error {
|
func (y *Cloud189PC) Remove(ctx context.Context, obj model.Obj) error {
|
||||||
_, err := y.post(API_URL+"/batch/createBatchTask.action", func(req *resty.Request) {
|
_, err := y.post(API_URL+"/batch/createBatchTask.action", func(req *resty.Request) {
|
||||||
req.SetContext(ctx)
|
req.SetContext(ctx)
|
||||||
req.SetFormData(map[string]string{
|
req.SetFormData(map[string]string{
|
||||||
@ -270,7 +265,7 @@ func (y *Yun189PC) Remove(ctx context.Context, obj model.Obj) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (y *Yun189PC) Put(ctx context.Context, dstDir model.Obj, stream model.FileStreamer, up driver.UpdateProgress) error {
|
func (y *Cloud189PC) Put(ctx context.Context, dstDir model.Obj, stream model.FileStreamer, up driver.UpdateProgress) error {
|
||||||
if y.RapidUpload {
|
if y.RapidUpload {
|
||||||
return y.FastUpload(ctx, dstDir, stream, up)
|
return y.FastUpload(ctx, dstDir, stream, up)
|
||||||
}
|
}
|
||||||
|
@ -24,7 +24,7 @@ var config = driver.Config{
|
|||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
op.RegisterDriver(config, func() driver.Driver {
|
op.RegisterDriver(func() driver.Driver {
|
||||||
return &Yun189PC{}
|
return &Cloud189PC{}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -47,7 +47,7 @@ const (
|
|||||||
CHANNEL_ID = "web_cloud.189.cn"
|
CHANNEL_ID = "web_cloud.189.cn"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (y *Yun189PC) request(url, method string, callback base.ReqCallback, params Params, resp interface{}) ([]byte, error) {
|
func (y *Cloud189PC) request(url, method string, callback base.ReqCallback, params Params, resp interface{}) ([]byte, error) {
|
||||||
dateOfGmt := getHttpDateStr()
|
dateOfGmt := getHttpDateStr()
|
||||||
sessionKey := y.tokenInfo.SessionKey
|
sessionKey := y.tokenInfo.SessionKey
|
||||||
sessionSecret := y.tokenInfo.SessionSecret
|
sessionSecret := y.tokenInfo.SessionSecret
|
||||||
@ -124,15 +124,15 @@ func (y *Yun189PC) request(url, method string, callback base.ReqCallback, params
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (y *Yun189PC) get(url string, callback base.ReqCallback, resp interface{}) ([]byte, error) {
|
func (y *Cloud189PC) get(url string, callback base.ReqCallback, resp interface{}) ([]byte, error) {
|
||||||
return y.request(url, http.MethodGet, callback, nil, resp)
|
return y.request(url, http.MethodGet, callback, nil, resp)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (y *Yun189PC) post(url string, callback base.ReqCallback, resp interface{}) ([]byte, error) {
|
func (y *Cloud189PC) post(url string, callback base.ReqCallback, resp interface{}) ([]byte, error) {
|
||||||
return y.request(url, http.MethodPost, callback, nil, resp)
|
return y.request(url, http.MethodPost, callback, nil, resp)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (y *Yun189PC) getFiles(ctx context.Context, fileId string) ([]model.Obj, error) {
|
func (y *Cloud189PC) getFiles(ctx context.Context, fileId string) ([]model.Obj, error) {
|
||||||
fullUrl := API_URL
|
fullUrl := API_URL
|
||||||
if y.isFamily() {
|
if y.isFamily() {
|
||||||
fullUrl += "/family/file"
|
fullUrl += "/family/file"
|
||||||
@ -184,7 +184,7 @@ func (y *Yun189PC) getFiles(ctx context.Context, fileId string) ([]model.Obj, er
|
|||||||
return res, nil
|
return res, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (y *Yun189PC) login() (err error) {
|
func (y *Cloud189PC) login() (err error) {
|
||||||
// 初始化登陆所需参数
|
// 初始化登陆所需参数
|
||||||
if y.loginParam == nil || !y.NoUseOcr {
|
if y.loginParam == nil || !y.NoUseOcr {
|
||||||
if err = y.initLoginParam(); err != nil {
|
if err = y.initLoginParam(); err != nil {
|
||||||
@ -264,7 +264,7 @@ func (y *Yun189PC) login() (err error) {
|
|||||||
/* 初始化登陆需要的参数
|
/* 初始化登陆需要的参数
|
||||||
* 如果遇到验证码返回错误
|
* 如果遇到验证码返回错误
|
||||||
*/
|
*/
|
||||||
func (y *Yun189PC) initLoginParam() error {
|
func (y *Cloud189PC) initLoginParam() error {
|
||||||
// 清除cookie
|
// 清除cookie
|
||||||
jar, _ := cookiejar.New(nil)
|
jar, _ := cookiejar.New(nil)
|
||||||
y.client.SetCookieJar(jar)
|
y.client.SetCookieJar(jar)
|
||||||
@ -335,7 +335,7 @@ func (y *Yun189PC) initLoginParam() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 刷新会话
|
// 刷新会话
|
||||||
func (y *Yun189PC) refreshSession() (err error) {
|
func (y *Cloud189PC) refreshSession() (err error) {
|
||||||
var erron RespErr
|
var erron RespErr
|
||||||
var userSessionResp UserSessionResp
|
var userSessionResp UserSessionResp
|
||||||
_, err = y.client.R().
|
_, err = y.client.R().
|
||||||
@ -381,7 +381,7 @@ func (y *Yun189PC) refreshSession() (err error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 普通上传
|
// 普通上传
|
||||||
func (y *Yun189PC) CommonUpload(ctx context.Context, dstDir model.Obj, file model.FileStreamer, up driver.UpdateProgress) (err error) {
|
func (y *Cloud189PC) CommonUpload(ctx context.Context, dstDir model.Obj, file model.FileStreamer, up driver.UpdateProgress) (err error) {
|
||||||
const DEFAULT int64 = 10485760
|
const DEFAULT int64 = 10485760
|
||||||
var count = int64(math.Ceil(float64(file.GetSize()) / float64(DEFAULT)))
|
var count = int64(math.Ceil(float64(file.GetSize()) / float64(DEFAULT)))
|
||||||
|
|
||||||
@ -418,10 +418,8 @@ func (y *Yun189PC) CommonUpload(ctx context.Context, dstDir model.Obj, file mode
|
|||||||
silceMd5Hexs := make([]string, 0, count)
|
silceMd5Hexs := make([]string, 0, count)
|
||||||
byteData := bytes.NewBuffer(make([]byte, DEFAULT))
|
byteData := bytes.NewBuffer(make([]byte, DEFAULT))
|
||||||
for i := int64(1); i <= count; i++ {
|
for i := int64(1); i <= count; i++ {
|
||||||
select {
|
if utils.IsCanceled(ctx) {
|
||||||
case <-ctx.Done():
|
|
||||||
return ctx.Err()
|
return ctx.Err()
|
||||||
default:
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 读取块
|
// 读取块
|
||||||
@ -491,7 +489,7 @@ func (y *Yun189PC) CommonUpload(ctx context.Context, dstDir model.Obj, file mode
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 快传
|
// 快传
|
||||||
func (y *Yun189PC) FastUpload(ctx context.Context, dstDir model.Obj, file model.FileStreamer, up driver.UpdateProgress) (err error) {
|
func (y *Cloud189PC) FastUpload(ctx context.Context, dstDir model.Obj, file model.FileStreamer, up driver.UpdateProgress) (err error) {
|
||||||
// 需要获取完整文件md5,必须支持 io.Seek
|
// 需要获取完整文件md5,必须支持 io.Seek
|
||||||
tempFile, err := utils.CreateTempFile(file.GetReadCloser())
|
tempFile, err := utils.CreateTempFile(file.GetReadCloser())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -511,10 +509,8 @@ func (y *Yun189PC) FastUpload(ctx context.Context, dstDir model.Obj, file model.
|
|||||||
silceMd5Hexs := make([]string, 0, count)
|
silceMd5Hexs := make([]string, 0, count)
|
||||||
silceMd5Base64s := make([]string, 0, count)
|
silceMd5Base64s := make([]string, 0, count)
|
||||||
for i := 1; i <= count; i++ {
|
for i := 1; i <= count; i++ {
|
||||||
select {
|
if utils.IsCanceled(ctx) {
|
||||||
case <-ctx.Done():
|
|
||||||
return ctx.Err()
|
return ctx.Err()
|
||||||
default:
|
|
||||||
}
|
}
|
||||||
|
|
||||||
silceMd5.Reset()
|
silceMd5.Reset()
|
||||||
@ -616,11 +612,11 @@ func (y *Yun189PC) FastUpload(ctx context.Context, dstDir model.Obj, file model.
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (y *Yun189PC) isFamily() bool {
|
func (y *Cloud189PC) isFamily() bool {
|
||||||
return y.Type == "family"
|
return y.Type == "family"
|
||||||
}
|
}
|
||||||
|
|
||||||
func (y *Yun189PC) isLogin() bool {
|
func (y *Cloud189PC) isLogin() bool {
|
||||||
if y.tokenInfo == nil {
|
if y.tokenInfo == nil {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
@ -629,7 +625,7 @@ func (y *Yun189PC) isLogin() bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 获取家庭云所有用户信息
|
// 获取家庭云所有用户信息
|
||||||
func (y *Yun189PC) getFamilyInfoList() ([]FamilyInfoResp, error) {
|
func (y *Cloud189PC) getFamilyInfoList() ([]FamilyInfoResp, error) {
|
||||||
var resp FamilyInfoListResp
|
var resp FamilyInfoListResp
|
||||||
_, err := y.get(API_URL+"/family/manage/getFamilyList.action", nil, &resp)
|
_, err := y.get(API_URL+"/family/manage/getFamilyList.action", nil, &resp)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -639,7 +635,7 @@ func (y *Yun189PC) getFamilyInfoList() ([]FamilyInfoResp, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 抽取家庭云ID
|
// 抽取家庭云ID
|
||||||
func (y *Yun189PC) getFamilyID() (string, error) {
|
func (y *Cloud189PC) getFamilyID() (string, error) {
|
||||||
infos, err := y.getFamilyInfoList()
|
infos, err := y.getFamilyInfoList()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
|
@ -7,7 +7,6 @@ import (
|
|||||||
"github.com/alist-org/alist/v3/internal/driver"
|
"github.com/alist-org/alist/v3/internal/driver"
|
||||||
"github.com/alist-org/alist/v3/internal/errs"
|
"github.com/alist-org/alist/v3/internal/errs"
|
||||||
"github.com/alist-org/alist/v3/internal/model"
|
"github.com/alist-org/alist/v3/internal/model"
|
||||||
"github.com/alist-org/alist/v3/pkg/utils"
|
|
||||||
"github.com/alist-org/alist/v3/server/common"
|
"github.com/alist-org/alist/v3/server/common"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -21,18 +20,16 @@ func (d *AListV2) Config() driver.Config {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (d *AListV2) GetAddition() driver.Additional {
|
func (d *AListV2) GetAddition() driver.Additional {
|
||||||
return d.Addition
|
return &d.Addition
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *AListV2) Init(ctx context.Context, storage model.Storage) error {
|
func (d *AListV2) Init(ctx context.Context) error {
|
||||||
d.Storage = storage
|
if len(d.Addition.Address) > 0 && string(d.Addition.Address[len(d.Addition.Address)-1]) == "/" {
|
||||||
err := utils.Json.UnmarshalFromString(d.Storage.Addition, &d.Addition)
|
d.Addition.Address = d.Addition.Address[0 : len(d.Addition.Address)-1]
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
}
|
||||||
// TODO login / refresh token
|
// TODO login / refresh token
|
||||||
//op.MustSaveDriverStorage(d)
|
//op.MustSaveDriverStorage(d)
|
||||||
return err
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *AListV2) Drop(ctx context.Context) error {
|
func (d *AListV2) Drop(ctx context.Context) error {
|
||||||
@ -70,11 +67,6 @@ func (d *AListV2) List(ctx context.Context, dir model.Obj, args model.ListArgs)
|
|||||||
return files, nil
|
return files, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
//func (d *AList) Get(ctx context.Context, path string) (model.Obj, error) {
|
|
||||||
// // this is optional
|
|
||||||
// return nil, errs.NotImplement
|
|
||||||
//}
|
|
||||||
|
|
||||||
func (d *AListV2) Link(ctx context.Context, file model.Obj, args model.LinkArgs) (*model.Link, error) {
|
func (d *AListV2) Link(ctx context.Context, file model.Obj, args model.LinkArgs) (*model.Link, error) {
|
||||||
url := d.Address + "/api/public/path"
|
url := d.Address + "/api/public/path"
|
||||||
var resp common.Resp[PathResp]
|
var resp common.Resp[PathResp]
|
||||||
|
@ -20,7 +20,7 @@ var config = driver.Config{
|
|||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
op.RegisterDriver(config, func() driver.Driver {
|
op.RegisterDriver(func() driver.Driver {
|
||||||
return &AListV2{}
|
return &AListV2{}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -2,14 +2,15 @@ package alist_v3
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"io"
|
||||||
|
"path"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"github.com/alist-org/alist/v3/drivers/base"
|
"github.com/alist-org/alist/v3/drivers/base"
|
||||||
"github.com/alist-org/alist/v3/internal/driver"
|
"github.com/alist-org/alist/v3/internal/driver"
|
||||||
"github.com/alist-org/alist/v3/internal/errs"
|
|
||||||
"github.com/alist-org/alist/v3/internal/model"
|
"github.com/alist-org/alist/v3/internal/model"
|
||||||
"github.com/alist-org/alist/v3/pkg/utils"
|
|
||||||
"github.com/alist-org/alist/v3/server/common"
|
"github.com/alist-org/alist/v3/server/common"
|
||||||
"github.com/alist-org/alist/v3/server/handles"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type AListV3 struct {
|
type AListV3 struct {
|
||||||
@ -22,18 +23,14 @@ func (d *AListV3) Config() driver.Config {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (d *AListV3) GetAddition() driver.Additional {
|
func (d *AListV3) GetAddition() driver.Additional {
|
||||||
return d.Addition
|
return &d.Addition
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *AListV3) Init(ctx context.Context, storage model.Storage) error {
|
func (d *AListV3) Init(ctx context.Context) error {
|
||||||
d.Storage = storage
|
d.Addition.Address = strings.TrimSuffix(d.Addition.Address, "/")
|
||||||
err := utils.Json.UnmarshalFromString(d.Storage.Addition, &d.Addition)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
// TODO login / refresh token
|
// TODO login / refresh token
|
||||||
//op.MustSaveDriverStorage(d)
|
//op.MustSaveDriverStorage(d)
|
||||||
return err
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *AListV3) Drop(ctx context.Context) error {
|
func (d *AListV3) Drop(ctx context.Context) error {
|
||||||
@ -42,12 +39,12 @@ func (d *AListV3) Drop(ctx context.Context) error {
|
|||||||
|
|
||||||
func (d *AListV3) List(ctx context.Context, dir model.Obj, args model.ListArgs) ([]model.Obj, error) {
|
func (d *AListV3) List(ctx context.Context, dir model.Obj, args model.ListArgs) ([]model.Obj, error) {
|
||||||
url := d.Address + "/api/fs/list"
|
url := d.Address + "/api/fs/list"
|
||||||
var resp common.Resp[handles.FsListResp]
|
var resp common.Resp[FsListResp]
|
||||||
_, err := base.RestyClient.R().
|
_, err := base.RestyClient.R().
|
||||||
SetResult(&resp).
|
SetResult(&resp).
|
||||||
SetHeader("Authorization", d.AccessToken).
|
SetHeader("Authorization", d.AccessToken).
|
||||||
SetBody(handles.ListReq{
|
SetBody(ListReq{
|
||||||
PageReq: common.PageReq{
|
PageReq: model.PageReq{
|
||||||
Page: 1,
|
Page: 1,
|
||||||
PerPage: 0,
|
PerPage: 0,
|
||||||
},
|
},
|
||||||
@ -74,18 +71,13 @@ func (d *AListV3) List(ctx context.Context, dir model.Obj, args model.ListArgs)
|
|||||||
return files, nil
|
return files, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
//func (d *AList) Get(ctx context.Context, path string) (model.Obj, error) {
|
|
||||||
// // this is optional
|
|
||||||
// return nil, errs.NotImplement
|
|
||||||
//}
|
|
||||||
|
|
||||||
func (d *AListV3) Link(ctx context.Context, file model.Obj, args model.LinkArgs) (*model.Link, error) {
|
func (d *AListV3) Link(ctx context.Context, file model.Obj, args model.LinkArgs) (*model.Link, error) {
|
||||||
url := d.Address + "/api/fs/get"
|
url := d.Address + "/api/fs/get"
|
||||||
var resp common.Resp[handles.FsGetResp]
|
var resp common.Resp[FsGetResp]
|
||||||
_, err := base.RestyClient.R().
|
_, err := base.RestyClient.R().
|
||||||
SetResult(&resp).
|
SetResult(&resp).
|
||||||
SetHeader("Authorization", d.AccessToken).
|
SetHeader("Authorization", d.AccessToken).
|
||||||
SetBody(handles.FsGetReq{
|
SetBody(FsGetReq{
|
||||||
Path: file.GetPath(),
|
Path: file.GetPath(),
|
||||||
Password: d.Password,
|
Password: d.Password,
|
||||||
}).Post(url)
|
}).Post(url)
|
||||||
@ -98,27 +90,86 @@ func (d *AListV3) Link(ctx context.Context, file model.Obj, args model.LinkArgs)
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (d *AListV3) MakeDir(ctx context.Context, parentDir model.Obj, dirName string) error {
|
func (d *AListV3) MakeDir(ctx context.Context, parentDir model.Obj, dirName string) error {
|
||||||
return errs.NotImplement
|
url := d.Address + "/api/fs/mkdir"
|
||||||
|
var resp common.Resp[interface{}]
|
||||||
|
_, err := base.RestyClient.R().
|
||||||
|
SetResult(&resp).
|
||||||
|
SetHeader("Authorization", d.AccessToken).
|
||||||
|
SetBody(MkdirOrLinkReq{
|
||||||
|
Path: path.Join(parentDir.GetPath(), dirName),
|
||||||
|
}).Post(url)
|
||||||
|
return checkResp(resp, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *AListV3) Move(ctx context.Context, srcObj, dstDir model.Obj) error {
|
func (d *AListV3) Move(ctx context.Context, srcObj, dstDir model.Obj) error {
|
||||||
return errs.NotImplement
|
url := d.Address + "/api/fs/move"
|
||||||
|
var resp common.Resp[interface{}]
|
||||||
|
_, err := base.RestyClient.R().
|
||||||
|
SetResult(&resp).
|
||||||
|
SetHeader("Authorization", d.AccessToken).
|
||||||
|
SetBody(MoveCopyReq{
|
||||||
|
SrcDir: srcObj.GetPath(),
|
||||||
|
DstDir: dstDir.GetPath(),
|
||||||
|
Names: []string{srcObj.GetName()},
|
||||||
|
}).Post(url)
|
||||||
|
return checkResp(resp, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *AListV3) Rename(ctx context.Context, srcObj model.Obj, newName string) error {
|
func (d *AListV3) Rename(ctx context.Context, srcObj model.Obj, newName string) error {
|
||||||
return errs.NotImplement
|
url := d.Address + "/api/fs/rename"
|
||||||
|
var resp common.Resp[interface{}]
|
||||||
|
_, err := base.RestyClient.R().
|
||||||
|
SetResult(&resp).
|
||||||
|
SetHeader("Authorization", d.AccessToken).
|
||||||
|
SetBody(RenameReq{
|
||||||
|
Path: srcObj.GetPath(),
|
||||||
|
Name: newName,
|
||||||
|
}).Post(url)
|
||||||
|
return checkResp(resp, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *AListV3) Copy(ctx context.Context, srcObj, dstDir model.Obj) error {
|
func (d *AListV3) Copy(ctx context.Context, srcObj, dstDir model.Obj) error {
|
||||||
return errs.NotImplement
|
url := d.Address + "/api/fs/copy"
|
||||||
|
var resp common.Resp[interface{}]
|
||||||
|
_, err := base.RestyClient.R().
|
||||||
|
SetResult(&resp).
|
||||||
|
SetHeader("Authorization", d.AccessToken).
|
||||||
|
SetBody(MoveCopyReq{
|
||||||
|
SrcDir: srcObj.GetPath(),
|
||||||
|
DstDir: dstDir.GetPath(),
|
||||||
|
Names: []string{srcObj.GetName()},
|
||||||
|
}).Post(url)
|
||||||
|
return checkResp(resp, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *AListV3) Remove(ctx context.Context, obj model.Obj) error {
|
func (d *AListV3) Remove(ctx context.Context, obj model.Obj) error {
|
||||||
return errs.NotImplement
|
url := d.Address + "/api/fs/remove"
|
||||||
|
var resp common.Resp[interface{}]
|
||||||
|
_, err := base.RestyClient.R().
|
||||||
|
SetResult(&resp).
|
||||||
|
SetHeader("Authorization", d.AccessToken).
|
||||||
|
SetBody(RemoveReq{
|
||||||
|
Dir: obj.GetPath(),
|
||||||
|
Names: []string{obj.GetName()},
|
||||||
|
}).Post(url)
|
||||||
|
return checkResp(resp, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *AListV3) Put(ctx context.Context, dstDir model.Obj, stream model.FileStreamer, up driver.UpdateProgress) error {
|
func (d *AListV3) Put(ctx context.Context, dstDir model.Obj, stream model.FileStreamer, up driver.UpdateProgress) error {
|
||||||
return errs.NotImplement
|
url := d.Address + "/api/fs/put"
|
||||||
|
var resp common.Resp[interface{}]
|
||||||
|
fileBytes, err := io.ReadAll(stream.GetReadCloser())
|
||||||
|
if err != nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
_, err = base.RestyClient.R().SetContext(ctx).
|
||||||
|
SetResult(&resp).
|
||||||
|
SetHeader("Authorization", d.AccessToken).
|
||||||
|
SetHeader("File-Path", path.Join(dstDir.GetPath(), stream.GetName())).
|
||||||
|
SetHeader("Password", d.Password).
|
||||||
|
SetHeader("Content-Length", strconv.FormatInt(stream.GetSize(), 10)).
|
||||||
|
SetBody(fileBytes).Put(url)
|
||||||
|
return checkResp(resp, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
//func (d *AList) Other(ctx context.Context, args model.OtherArgs) (interface{}, error) {
|
//func (d *AList) Other(ctx context.Context, args model.OtherArgs) (interface{}, error) {
|
||||||
|
@ -15,12 +15,11 @@ type Addition struct {
|
|||||||
var config = driver.Config{
|
var config = driver.Config{
|
||||||
Name: "AList V3",
|
Name: "AList V3",
|
||||||
LocalSort: true,
|
LocalSort: true,
|
||||||
NoUpload: true,
|
|
||||||
DefaultRoot: "/",
|
DefaultRoot: "/",
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
op.RegisterDriver(config, func() driver.Driver {
|
op.RegisterDriver(func() driver.Driver {
|
||||||
return &AListV3{}
|
return &AListV3{}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -1 +1,65 @@
|
|||||||
package alist_v3
|
package alist_v3
|
||||||
|
|
||||||
|
import (
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/alist-org/alist/v3/internal/model"
|
||||||
|
)
|
||||||
|
|
||||||
|
type ListReq struct {
|
||||||
|
model.PageReq
|
||||||
|
Path string `json:"path" form:"path"`
|
||||||
|
Password string `json:"password" form:"password"`
|
||||||
|
Refresh bool `json:"refresh"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type ObjResp struct {
|
||||||
|
Name string `json:"name"`
|
||||||
|
Size int64 `json:"size"`
|
||||||
|
IsDir bool `json:"is_dir"`
|
||||||
|
Modified time.Time `json:"modified"`
|
||||||
|
Sign string `json:"sign"`
|
||||||
|
Thumb string `json:"thumb"`
|
||||||
|
Type int `json:"type"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type FsListResp struct {
|
||||||
|
Content []ObjResp `json:"content"`
|
||||||
|
Total int64 `json:"total"`
|
||||||
|
Readme string `json:"readme"`
|
||||||
|
Write bool `json:"write"`
|
||||||
|
Provider string `json:"provider"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type FsGetReq struct {
|
||||||
|
Path string `json:"path" form:"path"`
|
||||||
|
Password string `json:"password" form:"password"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type FsGetResp struct {
|
||||||
|
ObjResp
|
||||||
|
RawURL string `json:"raw_url"`
|
||||||
|
Readme string `json:"readme"`
|
||||||
|
Provider string `json:"provider"`
|
||||||
|
Related []ObjResp `json:"related"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type MkdirOrLinkReq struct {
|
||||||
|
Path string `json:"path" form:"path"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type MoveCopyReq struct {
|
||||||
|
SrcDir string `json:"src_dir"`
|
||||||
|
DstDir string `json:"dst_dir"`
|
||||||
|
Names []string `json:"names"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type RenameReq struct {
|
||||||
|
Path string `json:"path"`
|
||||||
|
Name string `json:"name"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type RemoveReq struct {
|
||||||
|
Dir string `json:"dir"`
|
||||||
|
Names []string `json:"names"`
|
||||||
|
}
|
||||||
|
@ -1 +1,17 @@
|
|||||||
package alist_v3
|
package alist_v3
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
|
||||||
|
"github.com/alist-org/alist/v3/server/common"
|
||||||
|
)
|
||||||
|
|
||||||
|
func checkResp(resp common.Resp[interface{}], err error) error {
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if resp.Message == "success" {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return errors.New(resp.Message)
|
||||||
|
}
|
||||||
|
@ -38,18 +38,13 @@ func (d *AliDrive) Config() driver.Config {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (d *AliDrive) GetAddition() driver.Additional {
|
func (d *AliDrive) GetAddition() driver.Additional {
|
||||||
return d.Addition
|
return &d.Addition
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *AliDrive) Init(ctx context.Context, storage model.Storage) error {
|
func (d *AliDrive) Init(ctx context.Context) error {
|
||||||
d.Storage = storage
|
|
||||||
err := utils.Json.UnmarshalFromString(d.Storage.Addition, &d.Addition)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
// TODO login / refresh token
|
// TODO login / refresh token
|
||||||
//op.MustSaveDriverStorage(d)
|
//op.MustSaveDriverStorage(d)
|
||||||
err = d.refreshToken()
|
err := d.refreshToken()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -86,11 +81,6 @@ func (d *AliDrive) List(ctx context.Context, dir model.Obj, args model.ListArgs)
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
//func (d *AliDrive) Get(ctx context.Context, path string) (model.Obj, error) {
|
|
||||||
// // TODO this is optional
|
|
||||||
// return nil, errs.NotImplement
|
|
||||||
//}
|
|
||||||
|
|
||||||
func (d *AliDrive) Link(ctx context.Context, file model.Obj, args model.LinkArgs) (*model.Link, error) {
|
func (d *AliDrive) Link(ctx context.Context, file model.Obj, args model.LinkArgs) (*model.Link, error) {
|
||||||
data := base.Json{
|
data := base.Json{
|
||||||
"drive_id": d.DriveId,
|
"drive_id": d.DriveId,
|
||||||
@ -258,10 +248,14 @@ func (d *AliDrive) Put(ctx context.Context, dstDir model.Obj, stream model.FileS
|
|||||||
}
|
}
|
||||||
|
|
||||||
for i, partInfo := range resp.PartInfoList {
|
for i, partInfo := range resp.PartInfoList {
|
||||||
|
if utils.IsCanceled(ctx) {
|
||||||
|
return ctx.Err()
|
||||||
|
}
|
||||||
req, err := http.NewRequest("PUT", partInfo.UploadUrl, io.LimitReader(file, DEFAULT))
|
req, err := http.NewRequest("PUT", partInfo.UploadUrl, io.LimitReader(file, DEFAULT))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
req = req.WithContext(ctx)
|
||||||
res, err := base.HttpClient.Do(req)
|
res, err := base.HttpClient.Do(req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -18,10 +18,8 @@ var config = driver.Config{
|
|||||||
DefaultRoot: "root",
|
DefaultRoot: "root",
|
||||||
}
|
}
|
||||||
|
|
||||||
func New() driver.Driver {
|
|
||||||
return &AliDrive{}
|
|
||||||
}
|
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
op.RegisterDriver(config, New)
|
op.RegisterDriver(func() driver.Driver {
|
||||||
|
return &AliDrive{}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
@ -62,6 +62,8 @@ func (d *AliDrive) request(url, method string, callback base.ReqCallback, resp i
|
|||||||
return d.request(url, method, callback, resp)
|
return d.request(url, method, callback, resp)
|
||||||
}
|
}
|
||||||
return nil, errors.New(e.Message), e
|
return nil, errors.New(e.Message), e
|
||||||
|
} else if res.IsError() {
|
||||||
|
return nil, errors.New("bad status code " + res.Status()), e
|
||||||
}
|
}
|
||||||
return res.Body(), nil, e
|
return res.Body(), nil, e
|
||||||
}
|
}
|
||||||
|
@ -8,7 +8,6 @@ import (
|
|||||||
|
|
||||||
"github.com/alist-org/alist/v3/drivers/base"
|
"github.com/alist-org/alist/v3/drivers/base"
|
||||||
"github.com/alist-org/alist/v3/internal/driver"
|
"github.com/alist-org/alist/v3/internal/driver"
|
||||||
"github.com/alist-org/alist/v3/internal/errs"
|
|
||||||
"github.com/alist-org/alist/v3/internal/model"
|
"github.com/alist-org/alist/v3/internal/model"
|
||||||
"github.com/alist-org/alist/v3/pkg/cron"
|
"github.com/alist-org/alist/v3/pkg/cron"
|
||||||
"github.com/alist-org/alist/v3/pkg/utils"
|
"github.com/alist-org/alist/v3/pkg/utils"
|
||||||
@ -29,16 +28,11 @@ func (d *AliyundriveShare) Config() driver.Config {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (d *AliyundriveShare) GetAddition() driver.Additional {
|
func (d *AliyundriveShare) GetAddition() driver.Additional {
|
||||||
return d.Addition
|
return &d.Addition
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *AliyundriveShare) Init(ctx context.Context, storage model.Storage) error {
|
func (d *AliyundriveShare) Init(ctx context.Context) error {
|
||||||
d.Storage = storage
|
err := d.refreshToken()
|
||||||
err := utils.Json.UnmarshalFromString(d.Storage.Addition, &d.Addition)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
err = d.refreshToken()
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -73,69 +67,42 @@ func (d *AliyundriveShare) List(ctx context.Context, dir model.Obj, args model.L
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
//func (d *AliyundriveShare) Get(ctx context.Context, path string) (model.Obj, error) {
|
|
||||||
// // this is optional
|
|
||||||
// return nil, errs.NotImplement
|
|
||||||
//}
|
|
||||||
|
|
||||||
func (d *AliyundriveShare) Link(ctx context.Context, file model.Obj, args model.LinkArgs) (*model.Link, error) {
|
func (d *AliyundriveShare) Link(ctx context.Context, file model.Obj, args model.LinkArgs) (*model.Link, error) {
|
||||||
data := base.Json{
|
data := base.Json{
|
||||||
"drive_id": d.DriveId,
|
"drive_id": d.DriveId,
|
||||||
"file_id": file.GetID(),
|
"file_id": file.GetID(),
|
||||||
"expire_sec": 14400,
|
// // Only ten minutes lifetime
|
||||||
|
"expire_sec": 600,
|
||||||
|
"share_id": d.ShareId,
|
||||||
}
|
}
|
||||||
|
var resp ShareLinkResp
|
||||||
var e ErrorResp
|
var e ErrorResp
|
||||||
res, err := base.RestyClient.R().
|
_, err := base.RestyClient.R().
|
||||||
SetError(&e).SetBody(data).
|
SetError(&e).SetBody(data).SetResult(&resp).
|
||||||
SetHeader("content-type", "application/json").
|
SetHeader("content-type", "application/json").
|
||||||
SetHeader("Authorization", "Bearer\t"+d.AccessToken).
|
SetHeader("Authorization", "Bearer\t"+d.AccessToken).
|
||||||
Post("https://api.aliyundrive.com/v2/file/get_download_url")
|
SetHeader("x-share-token", d.ShareToken).
|
||||||
|
Post("https://api.aliyundrive.com/v2/file/get_share_link_download_url")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
var u string
|
var u string
|
||||||
if e.Code != "" {
|
if e.Code != "" {
|
||||||
if e.Code == "AccessTokenInvalid" {
|
if e.Code == "AccessTokenInvalid" || e.Code == "ShareLinkTokenInvalid" {
|
||||||
err = d.refreshToken()
|
if e.Code == "AccessTokenInvalid" {
|
||||||
|
err = d.refreshToken()
|
||||||
|
} else {
|
||||||
|
err = d.getShareToken()
|
||||||
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return d.Link(ctx, file, args)
|
return d.Link(ctx, file, args)
|
||||||
} else if e.Code == "ForbiddenNoPermission.File" {
|
|
||||||
data = utils.MergeMap(data, base.Json{
|
|
||||||
// Only ten minutes valid
|
|
||||||
"expire_sec": 600,
|
|
||||||
"share_id": d.ShareId,
|
|
||||||
})
|
|
||||||
var resp ShareLinkResp
|
|
||||||
var e2 ErrorResp
|
|
||||||
_, err = base.RestyClient.R().
|
|
||||||
SetError(&e2).SetBody(data).SetResult(&resp).
|
|
||||||
SetHeader("content-type", "application/json").
|
|
||||||
SetHeader("Authorization", "Bearer\t"+d.AccessToken).
|
|
||||||
SetHeader("x-share-token", d.ShareToken).
|
|
||||||
Post("https://api.aliyundrive.com/v2/file/get_share_link_download_url")
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
if e2.Code != "" {
|
|
||||||
if e2.Code == "AccessTokenInvalid" || e2.Code == "ShareLinkTokenInvalid" {
|
|
||||||
err = d.getShareToken()
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return d.Link(ctx, file, args)
|
|
||||||
} else {
|
|
||||||
return nil, errors.New(e2.Code + ":" + e2.Message)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
u = resp.DownloadUrl
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
return nil, errors.New(e.Code + ":" + e.Message)
|
return nil, errors.New(e.Code + ": " + e.Message)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
u = utils.Json.Get(res.Body(), "url").ToString()
|
u = resp.DownloadUrl
|
||||||
}
|
}
|
||||||
return &model.Link{
|
return &model.Link{
|
||||||
Header: http.Header{
|
Header: http.Header{
|
||||||
@ -145,34 +112,4 @@ func (d *AliyundriveShare) Link(ctx context.Context, file model.Obj, args model.
|
|||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *AliyundriveShare) MakeDir(ctx context.Context, parentDir model.Obj, dirName string) error {
|
|
||||||
// TODO create folder
|
|
||||||
return errs.NotSupport
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *AliyundriveShare) Move(ctx context.Context, srcObj, dstDir model.Obj) error {
|
|
||||||
// TODO move obj
|
|
||||||
return errs.NotSupport
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *AliyundriveShare) Rename(ctx context.Context, srcObj model.Obj, newName string) error {
|
|
||||||
// TODO rename obj
|
|
||||||
return errs.NotSupport
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *AliyundriveShare) Copy(ctx context.Context, srcObj, dstDir model.Obj) error {
|
|
||||||
// TODO copy obj
|
|
||||||
return errs.NotSupport
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *AliyundriveShare) Remove(ctx context.Context, obj model.Obj) error {
|
|
||||||
// TODO remove obj
|
|
||||||
return errs.NotSupport
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *AliyundriveShare) Put(ctx context.Context, dstDir model.Obj, stream model.FileStreamer, up driver.UpdateProgress) error {
|
|
||||||
// TODO upload file
|
|
||||||
return errs.NotSupport
|
|
||||||
}
|
|
||||||
|
|
||||||
var _ driver.Driver = (*AliyundriveShare)(nil)
|
var _ driver.Driver = (*AliyundriveShare)(nil)
|
||||||
|
@ -23,7 +23,7 @@ var config = driver.Config{
|
|||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
op.RegisterDriver(config, func() driver.Driver {
|
op.RegisterDriver(func() driver.Driver {
|
||||||
return &AliyundriveShare{}
|
return &AliyundriveShare{}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -21,11 +21,13 @@ import (
|
|||||||
_ "github.com/alist-org/alist/v3/drivers/mega"
|
_ "github.com/alist-org/alist/v3/drivers/mega"
|
||||||
_ "github.com/alist-org/alist/v3/drivers/onedrive"
|
_ "github.com/alist-org/alist/v3/drivers/onedrive"
|
||||||
_ "github.com/alist-org/alist/v3/drivers/pikpak"
|
_ "github.com/alist-org/alist/v3/drivers/pikpak"
|
||||||
|
_ "github.com/alist-org/alist/v3/drivers/pikpak_share"
|
||||||
_ "github.com/alist-org/alist/v3/drivers/quark"
|
_ "github.com/alist-org/alist/v3/drivers/quark"
|
||||||
_ "github.com/alist-org/alist/v3/drivers/s3"
|
_ "github.com/alist-org/alist/v3/drivers/s3"
|
||||||
_ "github.com/alist-org/alist/v3/drivers/sftp"
|
_ "github.com/alist-org/alist/v3/drivers/sftp"
|
||||||
_ "github.com/alist-org/alist/v3/drivers/smb"
|
_ "github.com/alist-org/alist/v3/drivers/smb"
|
||||||
_ "github.com/alist-org/alist/v3/drivers/teambition"
|
_ "github.com/alist-org/alist/v3/drivers/teambition"
|
||||||
|
_ "github.com/alist-org/alist/v3/drivers/terabox"
|
||||||
_ "github.com/alist-org/alist/v3/drivers/thunder"
|
_ "github.com/alist-org/alist/v3/drivers/thunder"
|
||||||
_ "github.com/alist-org/alist/v3/drivers/uss"
|
_ "github.com/alist-org/alist/v3/drivers/uss"
|
||||||
_ "github.com/alist-org/alist/v3/drivers/virtual"
|
_ "github.com/alist-org/alist/v3/drivers/virtual"
|
||||||
|
@ -31,15 +31,10 @@ func (d *BaiduNetdisk) Config() driver.Config {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (d *BaiduNetdisk) GetAddition() driver.Additional {
|
func (d *BaiduNetdisk) GetAddition() driver.Additional {
|
||||||
return d.Addition
|
return &d.Addition
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *BaiduNetdisk) Init(ctx context.Context, storage model.Storage) error {
|
func (d *BaiduNetdisk) Init(ctx context.Context) error {
|
||||||
d.Storage = storage
|
|
||||||
err := utils.Json.UnmarshalFromString(d.Storage.Addition, &d.Addition)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return d.refreshToken()
|
return d.refreshToken()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -57,11 +52,6 @@ func (d *BaiduNetdisk) List(ctx context.Context, dir model.Obj, args model.ListA
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
//func (d *BaiduNetdisk) Get(ctx context.Context, path string) (model.Obj, error) {
|
|
||||||
// // this is optional
|
|
||||||
// return nil, errs.NotImplement
|
|
||||||
//}
|
|
||||||
|
|
||||||
func (d *BaiduNetdisk) Link(ctx context.Context, file model.Obj, args model.LinkArgs) (*model.Link, error) {
|
func (d *BaiduNetdisk) Link(ctx context.Context, file model.Obj, args model.LinkArgs) (*model.Link, error) {
|
||||||
if d.DownloadAPI == "crack" {
|
if d.DownloadAPI == "crack" {
|
||||||
return d.linkCrack(file, args)
|
return d.linkCrack(file, args)
|
||||||
@ -98,12 +88,11 @@ func (d *BaiduNetdisk) Rename(ctx context.Context, srcObj model.Obj, newName str
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (d *BaiduNetdisk) Copy(ctx context.Context, srcObj, dstDir model.Obj) error {
|
func (d *BaiduNetdisk) Copy(ctx context.Context, srcObj, dstDir model.Obj) error {
|
||||||
dest, newname := stdpath.Split(dstDir.GetPath())
|
|
||||||
data := []base.Json{
|
data := []base.Json{
|
||||||
{
|
{
|
||||||
"path": srcObj.GetPath(),
|
"path": srcObj.GetPath(),
|
||||||
"dest": dest,
|
"dest": dstDir.GetPath(),
|
||||||
"newname": newname,
|
"newname": srcObj.GetName(),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
_, err := d.manage("copy", data)
|
_, err := d.manage("copy", data)
|
||||||
@ -175,7 +164,8 @@ func (d *BaiduNetdisk) Put(ctx context.Context, dstDir model.Obj, stream model.F
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
path := encodeURIComponent(stdpath.Join(dstDir.GetPath(), stream.GetName()))
|
rawPath := stdpath.Join(dstDir.GetPath(), stream.GetName())
|
||||||
|
path := encodeURIComponent(rawPath)
|
||||||
block_list_str := fmt.Sprintf("[%s]", strings.Join(block_list, ","))
|
block_list_str := fmt.Sprintf("[%s]", strings.Join(block_list, ","))
|
||||||
data := fmt.Sprintf("path=%s&size=%d&isdir=0&autoinit=1&block_list=%s&content-md5=%s&slice-md5=%s",
|
data := fmt.Sprintf("path=%s&size=%d&isdir=0&autoinit=1&block_list=%s&content-md5=%s&slice-md5=%s",
|
||||||
path, stream.GetSize(),
|
path, stream.GetSize(),
|
||||||
@ -202,6 +192,9 @@ func (d *BaiduNetdisk) Put(ctx context.Context, dstDir model.Obj, stream model.F
|
|||||||
}
|
}
|
||||||
left = stream.GetSize()
|
left = stream.GetSize()
|
||||||
for i, partseq := range precreateResp.BlockList {
|
for i, partseq := range precreateResp.BlockList {
|
||||||
|
if utils.IsCanceled(ctx) {
|
||||||
|
return ctx.Err()
|
||||||
|
}
|
||||||
byteSize := Default
|
byteSize := Default
|
||||||
var byteData []byte
|
var byteData []byte
|
||||||
if left < Default {
|
if left < Default {
|
||||||
@ -217,7 +210,11 @@ func (d *BaiduNetdisk) Put(ctx context.Context, dstDir model.Obj, stream model.F
|
|||||||
}
|
}
|
||||||
u := "https://d.pcs.baidu.com/rest/2.0/pcs/superfile2"
|
u := "https://d.pcs.baidu.com/rest/2.0/pcs/superfile2"
|
||||||
params["partseq"] = strconv.Itoa(partseq)
|
params["partseq"] = strconv.Itoa(partseq)
|
||||||
res, err := base.RestyClient.R().SetQueryParams(params).SetFileReader("file", stream.GetName(), bytes.NewReader(byteData)).Post(u)
|
res, err := base.RestyClient.R().
|
||||||
|
SetContext(ctx).
|
||||||
|
SetQueryParams(params).
|
||||||
|
SetFileReader("file", stream.GetName(), bytes.NewReader(byteData)).
|
||||||
|
Post(u)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -226,7 +223,7 @@ func (d *BaiduNetdisk) Put(ctx context.Context, dstDir model.Obj, stream model.F
|
|||||||
up(i * 100 / len(precreateResp.BlockList))
|
up(i * 100 / len(precreateResp.BlockList))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_, err = d.create(path, stream.GetSize(), 0, precreateResp.Uploadid, block_list_str)
|
_, err = d.create(rawPath, stream.GetSize(), 0, precreateResp.Uploadid, block_list_str)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -20,10 +20,8 @@ var config = driver.Config{
|
|||||||
DefaultRoot: "/",
|
DefaultRoot: "/",
|
||||||
}
|
}
|
||||||
|
|
||||||
func New() driver.Driver {
|
|
||||||
return &BaiduNetdisk{}
|
|
||||||
}
|
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
op.RegisterDriver(config, New)
|
op.RegisterDriver(func() driver.Driver {
|
||||||
|
return &BaiduNetdisk{}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
@ -187,7 +187,7 @@ func (d *BaiduNetdisk) create(path string, size int64, isdir int, uploadid, bloc
|
|||||||
params := map[string]string{
|
params := map[string]string{
|
||||||
"method": "create",
|
"method": "create",
|
||||||
}
|
}
|
||||||
data := fmt.Sprintf("path=%s&size=%d&isdir=%d", path, size, isdir)
|
data := fmt.Sprintf("path=%s&size=%d&isdir=%d", encodeURIComponent(path), size, isdir)
|
||||||
if uploadid != "" {
|
if uploadid != "" {
|
||||||
data += fmt.Sprintf("&uploadid=%s&block_list=%s", uploadid, block_list)
|
data += fmt.Sprintf("&uploadid=%s&block_list=%s", uploadid, block_list)
|
||||||
}
|
}
|
||||||
|
@ -29,15 +29,10 @@ func (d *BaiduPhoto) Config() driver.Config {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (d *BaiduPhoto) GetAddition() driver.Additional {
|
func (d *BaiduPhoto) GetAddition() driver.Additional {
|
||||||
return d.Addition
|
return &d.Addition
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *BaiduPhoto) Init(ctx context.Context, storage model.Storage) error {
|
func (d *BaiduPhoto) Init(ctx context.Context) error {
|
||||||
d.Storage = storage
|
|
||||||
err := utils.Json.UnmarshalFromString(d.Storage.Addition, &d.Addition)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return d.refreshToken()
|
return d.refreshToken()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -245,6 +240,9 @@ func (d *BaiduPhoto) Put(ctx context.Context, dstDir model.Obj, stream model.Fil
|
|||||||
}
|
}
|
||||||
|
|
||||||
for i := 0; i < count; i++ {
|
for i := 0; i < count; i++ {
|
||||||
|
if utils.IsCanceled(ctx) {
|
||||||
|
return ctx.Err()
|
||||||
|
}
|
||||||
uploadParams["partseq"] = fmt.Sprint(i)
|
uploadParams["partseq"] = fmt.Sprint(i)
|
||||||
_, err = d.Post("https://c3.pcs.baidu.com/rest/2.0/pcs/superfile2", func(r *resty.Request) {
|
_, err = d.Post("https://c3.pcs.baidu.com/rest/2.0/pcs/superfile2", func(r *resty.Request) {
|
||||||
r.SetContext(ctx)
|
r.SetContext(ctx)
|
||||||
|
@ -24,7 +24,7 @@ var config = driver.Config{
|
|||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
op.RegisterDriver(config, func() driver.Driver {
|
op.RegisterDriver(func() driver.Driver {
|
||||||
return &BaiduPhoto{}
|
return &BaiduPhoto{}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -100,7 +100,7 @@ type (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func (a *Album) GetSize() int64 { return 0 }
|
func (a *Album) GetSize() int64 { return 0 }
|
||||||
func (a *Album) GetName() string { return fmt.Sprint(a.Title) }
|
func (a *Album) GetName() string { return a.Title }
|
||||||
func (a *Album) ModTime() time.Time {
|
func (a *Album) ModTime() time.Time {
|
||||||
if a.parseTime == nil {
|
if a.parseTime == nil {
|
||||||
a.parseTime = toTime(a.Mtime)
|
a.parseTime = toTime(a.Mtime)
|
||||||
|
@ -7,7 +7,6 @@ import (
|
|||||||
"github.com/alist-org/alist/v3/internal/driver"
|
"github.com/alist-org/alist/v3/internal/driver"
|
||||||
"github.com/alist-org/alist/v3/internal/errs"
|
"github.com/alist-org/alist/v3/internal/errs"
|
||||||
"github.com/alist-org/alist/v3/internal/model"
|
"github.com/alist-org/alist/v3/internal/model"
|
||||||
"github.com/alist-org/alist/v3/pkg/utils"
|
|
||||||
"github.com/jlaffaye/ftp"
|
"github.com/jlaffaye/ftp"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -22,15 +21,10 @@ func (d *FTP) Config() driver.Config {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (d *FTP) GetAddition() driver.Additional {
|
func (d *FTP) GetAddition() driver.Additional {
|
||||||
return d.Addition
|
return &d.Addition
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *FTP) Init(ctx context.Context, storage model.Storage) error {
|
func (d *FTP) Init(ctx context.Context) error {
|
||||||
d.Storage = storage
|
|
||||||
err := utils.Json.UnmarshalFromString(d.Storage.Addition, &d.Addition)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return d.login()
|
return d.login()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -66,11 +60,6 @@ func (d *FTP) List(ctx context.Context, dir model.Obj, args model.ListArgs) ([]m
|
|||||||
return res, nil
|
return res, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
//func (d *FTP) Get(ctx context.Context, path string) (model.Obj, error) {
|
|
||||||
// // this is optional
|
|
||||||
// return nil, errs.NotImplement
|
|
||||||
//}
|
|
||||||
|
|
||||||
func (d *FTP) Link(ctx context.Context, file model.Obj, args model.LinkArgs) (*model.Link, error) {
|
func (d *FTP) Link(ctx context.Context, file model.Obj, args model.LinkArgs) (*model.Link, error) {
|
||||||
if err := d.login(); err != nil {
|
if err := d.login(); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@ -124,6 +113,7 @@ func (d *FTP) Put(ctx context.Context, dstDir model.Obj, stream model.FileStream
|
|||||||
if err := d.login(); err != nil {
|
if err := d.login(); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
// TODO: support cancel
|
||||||
return d.conn.Stor(stdpath.Join(dstDir.GetPath(), stream.GetName()), stream)
|
return d.conn.Stor(stdpath.Join(dstDir.GetPath(), stream.GetName()), stream)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -19,10 +19,8 @@ var config = driver.Config{
|
|||||||
DefaultRoot: "/",
|
DefaultRoot: "/",
|
||||||
}
|
}
|
||||||
|
|
||||||
func New() driver.Driver {
|
|
||||||
return &FTP{}
|
|
||||||
}
|
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
op.RegisterDriver(config, New)
|
op.RegisterDriver(func() driver.Driver {
|
||||||
|
return &FTP{}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
@ -4,14 +4,12 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
stdpath "path"
|
|
||||||
"strconv"
|
"strconv"
|
||||||
|
|
||||||
"github.com/alist-org/alist/v3/drivers/base"
|
"github.com/alist-org/alist/v3/drivers/base"
|
||||||
"github.com/alist-org/alist/v3/internal/driver"
|
"github.com/alist-org/alist/v3/internal/driver"
|
||||||
"github.com/alist-org/alist/v3/internal/errs"
|
"github.com/alist-org/alist/v3/internal/errs"
|
||||||
"github.com/alist-org/alist/v3/internal/model"
|
"github.com/alist-org/alist/v3/internal/model"
|
||||||
"github.com/alist-org/alist/v3/internal/op"
|
|
||||||
"github.com/alist-org/alist/v3/pkg/utils"
|
"github.com/alist-org/alist/v3/pkg/utils"
|
||||||
"github.com/go-resty/resty/v2"
|
"github.com/go-resty/resty/v2"
|
||||||
)
|
)
|
||||||
@ -27,15 +25,10 @@ func (d *GoogleDrive) Config() driver.Config {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (d *GoogleDrive) GetAddition() driver.Additional {
|
func (d *GoogleDrive) GetAddition() driver.Additional {
|
||||||
return d.Addition
|
return &d.Addition
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *GoogleDrive) Init(ctx context.Context, storage model.Storage) error {
|
func (d *GoogleDrive) Init(ctx context.Context) error {
|
||||||
d.Storage = storage
|
|
||||||
err := utils.Json.UnmarshalFromString(d.Storage.Addition, &d.Addition)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if d.ChunkSize == 0 {
|
if d.ChunkSize == 0 {
|
||||||
d.ChunkSize = 5
|
d.ChunkSize = 5
|
||||||
}
|
}
|
||||||
@ -56,13 +49,12 @@ func (d *GoogleDrive) List(ctx context.Context, dir model.Obj, args model.ListAr
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
//func (d *GoogleDrive) Get(ctx context.Context, path string) (model.Obj, error) {
|
|
||||||
// // this is optional
|
|
||||||
// return nil, errs.NotImplement
|
|
||||||
//}
|
|
||||||
|
|
||||||
func (d *GoogleDrive) Link(ctx context.Context, file model.Obj, args model.LinkArgs) (*model.Link, error) {
|
func (d *GoogleDrive) Link(ctx context.Context, file model.Obj, args model.LinkArgs) (*model.Link, error) {
|
||||||
url := fmt.Sprintf("https://www.googleapis.com/drive/v3/files/%s?includeItemsFromAllDrives=true&supportsAllDrives=true", file.GetID())
|
url := fmt.Sprintf("https://www.googleapis.com/drive/v3/files/%s?includeItemsFromAllDrives=true&supportsAllDrives=true", file.GetID())
|
||||||
|
_, err := d.request(url, http.MethodGet, nil, nil)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
link := model.Link{
|
link := model.Link{
|
||||||
URL: url + "&alt=media",
|
URL: url + "&alt=media",
|
||||||
Header: http.Header{
|
Header: http.Header{
|
||||||
@ -118,8 +110,7 @@ func (d *GoogleDrive) Remove(ctx context.Context, obj model.Obj) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (d *GoogleDrive) Put(ctx context.Context, dstDir model.Obj, stream model.FileStreamer, up driver.UpdateProgress) error {
|
func (d *GoogleDrive) Put(ctx context.Context, dstDir model.Obj, stream model.FileStreamer, up driver.UpdateProgress) error {
|
||||||
obj, _ := op.Get(ctx, d, stdpath.Join(dstDir.GetPath(), stream.GetName()))
|
obj := stream.GetOld()
|
||||||
|
|
||||||
var (
|
var (
|
||||||
e Error
|
e Error
|
||||||
url string
|
url string
|
||||||
@ -143,7 +134,7 @@ func (d *GoogleDrive) Put(ctx context.Context, dstDir model.Obj, stream model.Fi
|
|||||||
"X-Upload-Content-Type": stream.GetMimetype(),
|
"X-Upload-Content-Type": stream.GetMimetype(),
|
||||||
"X-Upload-Content-Length": strconv.FormatInt(stream.GetSize(), 10),
|
"X-Upload-Content-Length": strconv.FormatInt(stream.GetSize(), 10),
|
||||||
}).
|
}).
|
||||||
SetError(&e).SetBody(data)
|
SetError(&e).SetBody(data).SetContext(ctx)
|
||||||
if obj != nil {
|
if obj != nil {
|
||||||
res, err = req.Patch(url)
|
res, err = req.Patch(url)
|
||||||
} else {
|
} else {
|
||||||
|
@ -12,7 +12,7 @@ type Addition struct {
|
|||||||
OrderDirection string `json:"order_direction" type:"select" options:"asc,desc"`
|
OrderDirection string `json:"order_direction" type:"select" options:"asc,desc"`
|
||||||
ClientID string `json:"client_id" required:"true" default:"202264815644.apps.googleusercontent.com"`
|
ClientID string `json:"client_id" required:"true" default:"202264815644.apps.googleusercontent.com"`
|
||||||
ClientSecret string `json:"client_secret" required:"true" default:"X4Z3ca8xfWDb1Voo-F9a7ZxJ"`
|
ClientSecret string `json:"client_secret" required:"true" default:"X4Z3ca8xfWDb1Voo-F9a7ZxJ"`
|
||||||
ChunkSize int64 `json:"chunk_size" default:"5" help:"chunk size while uploading (unit: MB)"`
|
ChunkSize int64 `json:"chunk_size" type:"number" default:"5" help:"chunk size while uploading (unit: MB)"`
|
||||||
}
|
}
|
||||||
|
|
||||||
var config = driver.Config{
|
var config = driver.Config{
|
||||||
@ -21,10 +21,8 @@ var config = driver.Config{
|
|||||||
DefaultRoot: "root",
|
DefaultRoot: "root",
|
||||||
}
|
}
|
||||||
|
|
||||||
func New() driver.Driver {
|
|
||||||
return &GoogleDrive{}
|
|
||||||
}
|
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
op.RegisterDriver(config, New)
|
op.RegisterDriver(func() driver.Driver {
|
||||||
|
return &GoogleDrive{}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
@ -9,6 +9,7 @@ import (
|
|||||||
|
|
||||||
"github.com/alist-org/alist/v3/drivers/base"
|
"github.com/alist-org/alist/v3/drivers/base"
|
||||||
"github.com/alist-org/alist/v3/internal/model"
|
"github.com/alist-org/alist/v3/internal/model"
|
||||||
|
"github.com/alist-org/alist/v3/pkg/utils"
|
||||||
"github.com/go-resty/resty/v2"
|
"github.com/go-resty/resty/v2"
|
||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
)
|
)
|
||||||
@ -104,6 +105,9 @@ func (d *GoogleDrive) chunkUpload(ctx context.Context, stream model.FileStreamer
|
|||||||
var defaultChunkSize = d.ChunkSize * 1024 * 1024
|
var defaultChunkSize = d.ChunkSize * 1024 * 1024
|
||||||
var finish int64 = 0
|
var finish int64 = 0
|
||||||
for finish < stream.GetSize() {
|
for finish < stream.GetSize() {
|
||||||
|
if utils.IsCanceled(ctx) {
|
||||||
|
return ctx.Err()
|
||||||
|
}
|
||||||
chunkSize := stream.GetSize() - finish
|
chunkSize := stream.GetSize() - finish
|
||||||
if chunkSize > defaultChunkSize {
|
if chunkSize > defaultChunkSize {
|
||||||
chunkSize = defaultChunkSize
|
chunkSize = defaultChunkSize
|
||||||
@ -112,7 +116,7 @@ func (d *GoogleDrive) chunkUpload(ctx context.Context, stream model.FileStreamer
|
|||||||
req.SetHeaders(map[string]string{
|
req.SetHeaders(map[string]string{
|
||||||
"Content-Length": strconv.FormatInt(chunkSize, 10),
|
"Content-Length": strconv.FormatInt(chunkSize, 10),
|
||||||
"Content-Range": fmt.Sprintf("bytes %d-%d/%d", finish, finish+chunkSize-1, stream.GetSize()),
|
"Content-Range": fmt.Sprintf("bytes %d-%d/%d", finish, finish+chunkSize-1, stream.GetSize()),
|
||||||
}).SetBody(io.LimitReader(stream.GetReadCloser(), chunkSize))
|
}).SetBody(io.LimitReader(stream.GetReadCloser(), chunkSize)).SetContext(ctx)
|
||||||
}, nil)
|
}, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -26,15 +26,10 @@ func (d *GooglePhoto) Config() driver.Config {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (d *GooglePhoto) GetAddition() driver.Additional {
|
func (d *GooglePhoto) GetAddition() driver.Additional {
|
||||||
return d.Addition
|
return &d.Addition
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *GooglePhoto) Init(ctx context.Context, storage model.Storage) error {
|
func (d *GooglePhoto) Init(ctx context.Context) error {
|
||||||
d.Storage = storage
|
|
||||||
err := utils.Json.UnmarshalFromString(d.Storage.Addition, &d.Addition)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return d.refreshToken()
|
return d.refreshToken()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -52,11 +47,6 @@ func (d *GooglePhoto) List(ctx context.Context, dir model.Obj, args model.ListAr
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
//func (d *GooglePhoto) Get(ctx context.Context, path string) (model.Obj, error) {
|
|
||||||
// // this is optional
|
|
||||||
// return nil, errs.NotImplement
|
|
||||||
//}
|
|
||||||
|
|
||||||
func (d *GooglePhoto) Link(ctx context.Context, file model.Obj, args model.LinkArgs) (*model.Link, error) {
|
func (d *GooglePhoto) Link(ctx context.Context, file model.Obj, args model.LinkArgs) (*model.Link, error) {
|
||||||
f, err := d.getMedia(file.GetID())
|
f, err := d.getMedia(file.GetID())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -134,7 +124,7 @@ func (d *GooglePhoto) Put(ctx context.Context, dstDir model.Obj, stream model.Fi
|
|||||||
}
|
}
|
||||||
|
|
||||||
resp, err := d.request(postUrl, http.MethodPost, func(req *resty.Request) {
|
resp, err := d.request(postUrl, http.MethodPost, func(req *resty.Request) {
|
||||||
req.SetBody(stream.GetReadCloser())
|
req.SetBody(stream.GetReadCloser()).SetContext(ctx)
|
||||||
}, nil, postHeaders)
|
}, nil, postHeaders)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -21,10 +21,8 @@ var config = driver.Config{
|
|||||||
LocalSort: true,
|
LocalSort: true,
|
||||||
}
|
}
|
||||||
|
|
||||||
func New() driver.Driver {
|
|
||||||
return &GooglePhoto{}
|
|
||||||
}
|
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
op.RegisterDriver(config, New)
|
op.RegisterDriver(func() driver.Driver {
|
||||||
|
return &GooglePhoto{}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
@ -9,7 +9,6 @@ import (
|
|||||||
"github.com/alist-org/alist/v3/internal/driver"
|
"github.com/alist-org/alist/v3/internal/driver"
|
||||||
"github.com/alist-org/alist/v3/internal/errs"
|
"github.com/alist-org/alist/v3/internal/errs"
|
||||||
"github.com/alist-org/alist/v3/internal/model"
|
"github.com/alist-org/alist/v3/internal/model"
|
||||||
"github.com/alist-org/alist/v3/pkg/utils"
|
|
||||||
"github.com/go-resty/resty/v2"
|
"github.com/go-resty/resty/v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -25,15 +24,10 @@ func (d *LanZou) Config() driver.Config {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (d *LanZou) GetAddition() driver.Additional {
|
func (d *LanZou) GetAddition() driver.Additional {
|
||||||
return d.Addition
|
return &d.Addition
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *LanZou) Init(ctx context.Context, storage model.Storage) error {
|
func (d *LanZou) Init(ctx context.Context) error {
|
||||||
d.Storage = storage
|
|
||||||
err := utils.Json.UnmarshalFromString(d.Storage.Addition, &d.Addition)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if d.IsCookie() {
|
if d.IsCookie() {
|
||||||
if d.RootFolderID == "" {
|
if d.RootFolderID == "" {
|
||||||
d.RootFolderID = "-1"
|
d.RootFolderID = "-1"
|
||||||
@ -163,7 +157,7 @@ func (d *LanZou) Put(ctx context.Context, dstDir model.Obj, stream model.FileStr
|
|||||||
"id": "WU_FILE_0",
|
"id": "WU_FILE_0",
|
||||||
"name": stream.GetName(),
|
"name": stream.GetName(),
|
||||||
"folder_id": dstDir.GetID(),
|
"folder_id": dstDir.GetID(),
|
||||||
}).SetFileReader("upload_file", stream.GetName(), stream)
|
}).SetFileReader("upload_file", stream.GetName(), stream).SetContext(ctx)
|
||||||
}, nil, true)
|
}, nil, true)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -25,7 +25,7 @@ var config = driver.Config{
|
|||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
op.RegisterDriver(config, func() driver.Driver {
|
op.RegisterDriver(func() driver.Driver {
|
||||||
return &LanZou{}
|
return &LanZou{}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -16,11 +16,12 @@ import (
|
|||||||
|
|
||||||
"github.com/alist-org/alist/v3/internal/conf"
|
"github.com/alist-org/alist/v3/internal/conf"
|
||||||
"github.com/alist-org/alist/v3/internal/driver"
|
"github.com/alist-org/alist/v3/internal/driver"
|
||||||
"github.com/alist-org/alist/v3/internal/errs"
|
|
||||||
"github.com/alist-org/alist/v3/internal/model"
|
"github.com/alist-org/alist/v3/internal/model"
|
||||||
|
"github.com/alist-org/alist/v3/internal/sign"
|
||||||
"github.com/alist-org/alist/v3/pkg/utils"
|
"github.com/alist-org/alist/v3/pkg/utils"
|
||||||
"github.com/alist-org/alist/v3/server/common"
|
"github.com/alist-org/alist/v3/server/common"
|
||||||
"github.com/disintegration/imaging"
|
"github.com/disintegration/imaging"
|
||||||
|
_ "golang.org/x/image/webp"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Local struct {
|
type Local struct {
|
||||||
@ -32,24 +33,18 @@ func (d *Local) Config() driver.Config {
|
|||||||
return config
|
return config
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *Local) Init(ctx context.Context, storage model.Storage) error {
|
func (d *Local) Init(ctx context.Context) error {
|
||||||
d.Storage = storage
|
|
||||||
err := utils.Json.UnmarshalFromString(d.Storage.Addition, &d.Addition)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if !utils.Exists(d.GetRootPath()) {
|
if !utils.Exists(d.GetRootPath()) {
|
||||||
err = fmt.Errorf("root folder %s not exists", d.GetRootPath())
|
return fmt.Errorf("root folder %s not exists", d.GetRootPath())
|
||||||
} else {
|
|
||||||
if !filepath.IsAbs(d.GetRootPath()) {
|
|
||||||
abs, err := filepath.Abs(d.GetRootPath())
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
d.SetRootPath(abs)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return err
|
if !filepath.IsAbs(d.GetRootPath()) {
|
||||||
|
abs, err := filepath.Abs(d.GetRootPath())
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
d.Addition.RootFolderPath = abs
|
||||||
|
}
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *Local) Drop(ctx context.Context) error {
|
func (d *Local) Drop(ctx context.Context) error {
|
||||||
@ -57,7 +52,7 @@ func (d *Local) Drop(ctx context.Context) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (d *Local) GetAddition() driver.Additional {
|
func (d *Local) GetAddition() driver.Additional {
|
||||||
return d.Addition
|
return &d.Addition
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *Local) List(ctx context.Context, dir model.Obj, args model.ListArgs) ([]model.Obj, error) {
|
func (d *Local) List(ctx context.Context, dir model.Obj, args model.ListArgs) ([]model.Obj, error) {
|
||||||
@ -75,15 +70,16 @@ func (d *Local) List(ctx context.Context, dir model.Obj, args model.ListArgs) ([
|
|||||||
if d.Thumbnail && utils.GetFileType(f.Name()) == conf.IMAGE {
|
if d.Thumbnail && utils.GetFileType(f.Name()) == conf.IMAGE {
|
||||||
thumb = common.GetApiUrl(nil) + stdpath.Join("/d", args.ReqPath, f.Name())
|
thumb = common.GetApiUrl(nil) + stdpath.Join("/d", args.ReqPath, f.Name())
|
||||||
thumb = utils.EncodePath(thumb, true)
|
thumb = utils.EncodePath(thumb, true)
|
||||||
thumb += "?type=thumb"
|
thumb += "?type=thumb&sign=" + sign.Sign(stdpath.Join(args.ReqPath, f.Name()))
|
||||||
}
|
}
|
||||||
isFolder := f.IsDir() || isSymlinkDir(f, fullPath)
|
isFolder := f.IsDir() || isSymlinkDir(f, fullPath)
|
||||||
size := f.Size()
|
var size int64
|
||||||
if isFolder {
|
if !isFolder {
|
||||||
size = 0
|
size = f.Size()
|
||||||
}
|
}
|
||||||
file := model.ObjThumb{
|
file := model.ObjThumb{
|
||||||
Object: model.Object{
|
Object: model.Object{
|
||||||
|
Path: filepath.Join(dir.GetPath(), f.Name()),
|
||||||
Name: f.Name(),
|
Name: f.Name(),
|
||||||
Modified: f.ModTime(),
|
Modified: f.ModTime(),
|
||||||
Size: size,
|
Size: size,
|
||||||
@ -98,29 +94,6 @@ func (d *Local) List(ctx context.Context, dir model.Obj, args model.ListArgs) ([
|
|||||||
return files, nil
|
return files, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *Local) Get(ctx context.Context, path string) (model.Obj, error) {
|
|
||||||
f, err := os.Stat(path)
|
|
||||||
if err != nil {
|
|
||||||
if strings.Contains(err.Error(), "cannot find the file") {
|
|
||||||
return nil, errs.ObjectNotFound
|
|
||||||
}
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
isFolder := f.IsDir() || isSymlinkDir(f, path)
|
|
||||||
size := f.Size()
|
|
||||||
if isFolder {
|
|
||||||
size = 0
|
|
||||||
}
|
|
||||||
file := model.Object{
|
|
||||||
Path: path,
|
|
||||||
Name: f.Name(),
|
|
||||||
Modified: f.ModTime(),
|
|
||||||
Size: size,
|
|
||||||
IsFolder: isFolder,
|
|
||||||
}
|
|
||||||
return &file, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *Local) Link(ctx context.Context, file model.Obj, args model.LinkArgs) (*model.Link, error) {
|
func (d *Local) Link(ctx context.Context, file model.Obj, args model.LinkArgs) (*model.Link, error) {
|
||||||
fullPath := file.GetPath()
|
fullPath := file.GetPath()
|
||||||
var link model.Link
|
var link model.Link
|
||||||
@ -163,6 +136,9 @@ func (d *Local) MakeDir(ctx context.Context, parentDir model.Obj, dirName string
|
|||||||
func (d *Local) Move(ctx context.Context, srcObj, dstDir model.Obj) error {
|
func (d *Local) Move(ctx context.Context, srcObj, dstDir model.Obj) error {
|
||||||
srcPath := srcObj.GetPath()
|
srcPath := srcObj.GetPath()
|
||||||
dstPath := filepath.Join(dstDir.GetPath(), srcObj.GetName())
|
dstPath := filepath.Join(dstDir.GetPath(), srcObj.GetName())
|
||||||
|
if utils.IsSubPath(srcPath, dstPath) {
|
||||||
|
return fmt.Errorf("the destination folder is a subfolder of the source folder")
|
||||||
|
}
|
||||||
err := os.Rename(srcPath, dstPath)
|
err := os.Rename(srcPath, dstPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@ -183,6 +159,9 @@ func (d *Local) Rename(ctx context.Context, srcObj model.Obj, newName string) er
|
|||||||
func (d *Local) Copy(ctx context.Context, srcObj, dstDir model.Obj) error {
|
func (d *Local) Copy(ctx context.Context, srcObj, dstDir model.Obj) error {
|
||||||
srcPath := srcObj.GetPath()
|
srcPath := srcObj.GetPath()
|
||||||
dstPath := filepath.Join(dstDir.GetPath(), srcObj.GetName())
|
dstPath := filepath.Join(dstDir.GetPath(), srcObj.GetName())
|
||||||
|
if utils.IsSubPath(srcPath, dstPath) {
|
||||||
|
return fmt.Errorf("the destination folder is a subfolder of the source folder")
|
||||||
|
}
|
||||||
var err error
|
var err error
|
||||||
if srcObj.IsDir() {
|
if srcObj.IsDir() {
|
||||||
err = utils.CopyDir(srcPath, dstPath)
|
err = utils.CopyDir(srcPath, dstPath)
|
||||||
|
@ -19,10 +19,8 @@ var config = driver.Config{
|
|||||||
DefaultRoot: "/",
|
DefaultRoot: "/",
|
||||||
}
|
}
|
||||||
|
|
||||||
func New() driver.Driver {
|
|
||||||
return &Local{}
|
|
||||||
}
|
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
op.RegisterDriver(config, New)
|
op.RegisterDriver(func() driver.Driver {
|
||||||
|
return &Local{}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
@ -8,14 +8,12 @@ import (
|
|||||||
"io"
|
"io"
|
||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
"path"
|
|
||||||
"strconv"
|
"strconv"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/alist-org/alist/v3/drivers/base"
|
"github.com/alist-org/alist/v3/drivers/base"
|
||||||
"github.com/alist-org/alist/v3/internal/driver"
|
"github.com/alist-org/alist/v3/internal/driver"
|
||||||
"github.com/alist-org/alist/v3/internal/model"
|
"github.com/alist-org/alist/v3/internal/model"
|
||||||
"github.com/alist-org/alist/v3/internal/op"
|
|
||||||
"github.com/alist-org/alist/v3/pkg/utils"
|
"github.com/alist-org/alist/v3/pkg/utils"
|
||||||
"github.com/aws/aws-sdk-go/aws"
|
"github.com/aws/aws-sdk-go/aws"
|
||||||
"github.com/aws/aws-sdk-go/aws/credentials"
|
"github.com/aws/aws-sdk-go/aws/credentials"
|
||||||
@ -36,16 +34,11 @@ func (d *MediaTrack) Config() driver.Config {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (d *MediaTrack) GetAddition() driver.Additional {
|
func (d *MediaTrack) GetAddition() driver.Additional {
|
||||||
return d.Addition
|
return &d.Addition
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *MediaTrack) Init(ctx context.Context, storage model.Storage) error {
|
func (d *MediaTrack) Init(ctx context.Context) error {
|
||||||
d.Storage = storage
|
_, err := d.request("https://kayle.api.mediatrack.cn/users", http.MethodGet, nil, nil)
|
||||||
err := utils.Json.UnmarshalFromString(d.Storage.Addition, &d.Addition)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
_, err = d.request("https://kayle.api.mediatrack.cn/users", http.MethodGet, nil, nil)
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -64,7 +57,7 @@ func (d *MediaTrack) List(ctx context.Context, dir model.Obj, args model.ListArg
|
|||||||
if f.File != nil && f.File.Cover != "" {
|
if f.File != nil && f.File.Cover != "" {
|
||||||
thumb = "https://nano.mtres.cn/" + f.File.Cover
|
thumb = "https://nano.mtres.cn/" + f.File.Cover
|
||||||
}
|
}
|
||||||
return &model.ObjThumb{
|
return &Object{
|
||||||
Object: model.Object{
|
Object: model.Object{
|
||||||
ID: f.ID,
|
ID: f.ID,
|
||||||
Name: f.Title,
|
Name: f.Title,
|
||||||
@ -73,15 +66,11 @@ func (d *MediaTrack) List(ctx context.Context, dir model.Obj, args model.ListArg
|
|||||||
Size: size,
|
Size: size,
|
||||||
},
|
},
|
||||||
Thumbnail: model.Thumbnail{Thumbnail: thumb},
|
Thumbnail: model.Thumbnail{Thumbnail: thumb},
|
||||||
|
ParentID: dir.GetID(),
|
||||||
}, nil
|
}, nil
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
//func (d *MediaTrack) Get(ctx context.Context, path string) (model.Obj, error) {
|
|
||||||
// // this is optional
|
|
||||||
// return nil, errs.NotImplement
|
|
||||||
//}
|
|
||||||
|
|
||||||
func (d *MediaTrack) Link(ctx context.Context, file model.Obj, args model.LinkArgs) (*model.Link, error) {
|
func (d *MediaTrack) Link(ctx context.Context, file model.Obj, args model.LinkArgs) (*model.Link, error) {
|
||||||
url := fmt.Sprintf("https://kayn.api.mediatrack.cn/v1/download_token/asset?asset_id=%s&source_type=project&password=&source_id=%s",
|
url := fmt.Sprintf("https://kayn.api.mediatrack.cn/v1/download_token/asset?asset_id=%s&source_type=project&password=&source_id=%s",
|
||||||
file.GetID(), d.ProjectID)
|
file.GetID(), d.ProjectID)
|
||||||
@ -156,16 +145,18 @@ func (d *MediaTrack) Copy(ctx context.Context, srcObj, dstDir model.Obj) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (d *MediaTrack) Remove(ctx context.Context, obj model.Obj) error {
|
func (d *MediaTrack) Remove(ctx context.Context, obj model.Obj) error {
|
||||||
dir, err := op.Get(ctx, d, path.Dir(obj.GetPath()))
|
var parentID string
|
||||||
if err != nil {
|
if o, ok := obj.(*Object); ok {
|
||||||
return err
|
parentID = o.ParentID
|
||||||
|
} else {
|
||||||
|
return fmt.Errorf("obj is not local Object")
|
||||||
}
|
}
|
||||||
data := base.Json{
|
data := base.Json{
|
||||||
"origin_id": dir.GetID(),
|
"origin_id": parentID,
|
||||||
"ids": []string{obj.GetID()},
|
"ids": []string{obj.GetID()},
|
||||||
}
|
}
|
||||||
url := "https://jayce.api.mediatrack.cn/v4/assets/batch/delete"
|
url := "https://jayce.api.mediatrack.cn/v4/assets/batch/delete"
|
||||||
_, err = d.request(url, http.MethodDelete, func(req *resty.Request) {
|
_, err := d.request(url, http.MethodDelete, func(req *resty.Request) {
|
||||||
req.SetBody(data)
|
req.SetBody(data)
|
||||||
}, nil)
|
}, nil)
|
||||||
return err
|
return err
|
||||||
@ -204,7 +195,7 @@ func (d *MediaTrack) Put(ctx context.Context, dstDir model.Obj, stream model.Fil
|
|||||||
Key: &resp.Data.Object,
|
Key: &resp.Data.Object,
|
||||||
Body: tempFile,
|
Body: tempFile,
|
||||||
}
|
}
|
||||||
_, err = uploader.Upload(input)
|
_, err = uploader.UploadWithContext(ctx, input)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -18,7 +18,7 @@ var config = driver.Config{
|
|||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
op.RegisterDriver(config, func() driver.Driver {
|
op.RegisterDriver(func() driver.Driver {
|
||||||
return &MediaTrack{}
|
return &MediaTrack{}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,10 @@
|
|||||||
package mediatrack
|
package mediatrack
|
||||||
|
|
||||||
import "time"
|
import (
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/alist-org/alist/v3/internal/model"
|
||||||
|
)
|
||||||
|
|
||||||
type BaseResp struct {
|
type BaseResp struct {
|
||||||
Status string `json:"status"`
|
Status string `json:"status"`
|
||||||
@ -60,3 +64,9 @@ type UploadResp struct {
|
|||||||
TraceID string `json:"trace_id"`
|
TraceID string `json:"trace_id"`
|
||||||
RequestID string `json:"requestId"`
|
RequestID string `json:"requestId"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type Object struct {
|
||||||
|
model.Object
|
||||||
|
model.Thumbnail
|
||||||
|
ParentID string
|
||||||
|
}
|
||||||
|
@ -9,7 +9,6 @@ import (
|
|||||||
"github.com/alist-org/alist/v3/internal/driver"
|
"github.com/alist-org/alist/v3/internal/driver"
|
||||||
"github.com/alist-org/alist/v3/internal/errs"
|
"github.com/alist-org/alist/v3/internal/errs"
|
||||||
"github.com/alist-org/alist/v3/internal/model"
|
"github.com/alist-org/alist/v3/internal/model"
|
||||||
"github.com/alist-org/alist/v3/pkg/chanio"
|
|
||||||
"github.com/alist-org/alist/v3/pkg/utils"
|
"github.com/alist-org/alist/v3/pkg/utils"
|
||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
"github.com/t3rm1n4l/go-mega"
|
"github.com/t3rm1n4l/go-mega"
|
||||||
@ -26,15 +25,10 @@ func (d *Mega) Config() driver.Config {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (d *Mega) GetAddition() driver.Additional {
|
func (d *Mega) GetAddition() driver.Additional {
|
||||||
return d.Addition
|
return &d.Addition
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *Mega) Init(ctx context.Context, storage model.Storage) error {
|
func (d *Mega) Init(ctx context.Context) error {
|
||||||
d.Storage = storage
|
|
||||||
err := utils.Json.UnmarshalFromString(d.Storage.Addition, &d.Addition)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
d.c = mega.New()
|
d.c = mega.New()
|
||||||
return d.c.Login(d.Email, d.Password)
|
return d.c.Login(d.Email, d.Password)
|
||||||
}
|
}
|
||||||
@ -62,13 +56,10 @@ func (d *Mega) List(ctx context.Context, dir model.Obj, args model.ListArgs) ([]
|
|||||||
return nil, fmt.Errorf("unable to convert dir to mega node")
|
return nil, fmt.Errorf("unable to convert dir to mega node")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *Mega) Get(ctx context.Context, path string) (model.Obj, error) {
|
func (d *Mega) GetRoot(ctx context.Context) (model.Obj, error) {
|
||||||
if path == "/" {
|
n := d.c.FS.GetRoot()
|
||||||
n := d.c.FS.GetRoot()
|
log.Debugf("mega root: %+v", *n)
|
||||||
log.Debugf("mega root: %+v", *n)
|
return &MegaNode{n}, nil
|
||||||
return &MegaNode{n}, nil
|
|
||||||
}
|
|
||||||
return nil, errs.NotSupport
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *Mega) Link(ctx context.Context, file model.Obj, args model.LinkArgs) (*model.Link, error) {
|
func (d *Mega) Link(ctx context.Context, file model.Obj, args model.LinkArgs) (*model.Link, error) {
|
||||||
@ -85,17 +76,21 @@ func (d *Mega) Link(ctx context.Context, file model.Obj, args model.LinkArgs) (*
|
|||||||
//u := down.GetResourceUrl()
|
//u := down.GetResourceUrl()
|
||||||
//u = strings.Replace(u, "http", "https", 1)
|
//u = strings.Replace(u, "http", "https", 1)
|
||||||
//return &model.Link{URL: u}, nil
|
//return &model.Link{URL: u}, nil
|
||||||
c := chanio.New()
|
r, w := io.Pipe()
|
||||||
go func() {
|
go func() {
|
||||||
defer func() {
|
defer func() {
|
||||||
_ = recover()
|
_ = recover()
|
||||||
}()
|
}()
|
||||||
log.Debugf("chunk size: %d", down.Chunks())
|
log.Debugf("chunk size: %d", down.Chunks())
|
||||||
|
var (
|
||||||
|
chunk []byte
|
||||||
|
err error
|
||||||
|
)
|
||||||
for id := 0; id < down.Chunks(); id++ {
|
for id := 0; id < down.Chunks(); id++ {
|
||||||
chunk, err := down.DownloadChunk(id)
|
chunk, err = down.DownloadChunk(id)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Errorf("mega down: %+v", err)
|
log.Errorf("mega down: %+v", err)
|
||||||
return
|
break
|
||||||
}
|
}
|
||||||
log.Debugf("id: %d,len: %d", id, len(chunk))
|
log.Debugf("id: %d,len: %d", id, len(chunk))
|
||||||
//_, _, err = down.ChunkLocation(id)
|
//_, _, err = down.ChunkLocation(id)
|
||||||
@ -104,14 +99,16 @@ func (d *Mega) Link(ctx context.Context, file model.Obj, args model.LinkArgs) (*
|
|||||||
// return
|
// return
|
||||||
//}
|
//}
|
||||||
//_, err = c.Write(chunk)
|
//_, err = c.Write(chunk)
|
||||||
_, err = c.Write(chunk)
|
if _, err = w.Write(chunk); err != nil {
|
||||||
|
break
|
||||||
|
}
|
||||||
}
|
}
|
||||||
err := c.Close()
|
err = w.CloseWithError(err)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Errorf("mega down: %+v", err)
|
log.Errorf("mega down: %+v", err)
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
return &model.Link{Data: c}, nil
|
return &model.Link{Data: r}, nil
|
||||||
}
|
}
|
||||||
return nil, fmt.Errorf("unable to convert dir to mega node")
|
return nil, fmt.Errorf("unable to convert dir to mega node")
|
||||||
}
|
}
|
||||||
@ -159,6 +156,9 @@ func (d *Mega) Put(ctx context.Context, dstDir model.Obj, stream model.FileStrea
|
|||||||
}
|
}
|
||||||
|
|
||||||
for id := 0; id < u.Chunks(); id++ {
|
for id := 0; id < u.Chunks(); id++ {
|
||||||
|
if utils.IsCanceled(ctx) {
|
||||||
|
return ctx.Err()
|
||||||
|
}
|
||||||
_, chkSize, err := u.ChunkLocation(id)
|
_, chkSize, err := u.ChunkLocation(id)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -20,7 +20,7 @@ var config = driver.Config{
|
|||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
op.RegisterDriver(config, func() driver.Driver {
|
op.RegisterDriver(func() driver.Driver {
|
||||||
return &Mega{}
|
return &Mega{}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -2,14 +2,13 @@ package onedrive
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
stdpath "path"
|
|
||||||
|
|
||||||
"github.com/alist-org/alist/v3/drivers/base"
|
"github.com/alist-org/alist/v3/drivers/base"
|
||||||
"github.com/alist-org/alist/v3/internal/driver"
|
"github.com/alist-org/alist/v3/internal/driver"
|
||||||
"github.com/alist-org/alist/v3/internal/errs"
|
"github.com/alist-org/alist/v3/internal/errs"
|
||||||
"github.com/alist-org/alist/v3/internal/model"
|
"github.com/alist-org/alist/v3/internal/model"
|
||||||
"github.com/alist-org/alist/v3/internal/op"
|
|
||||||
"github.com/alist-org/alist/v3/pkg/utils"
|
"github.com/alist-org/alist/v3/pkg/utils"
|
||||||
"github.com/go-resty/resty/v2"
|
"github.com/go-resty/resty/v2"
|
||||||
)
|
)
|
||||||
@ -25,15 +24,10 @@ func (d *Onedrive) Config() driver.Config {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (d *Onedrive) GetAddition() driver.Additional {
|
func (d *Onedrive) GetAddition() driver.Additional {
|
||||||
return d.Addition
|
return &d.Addition
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *Onedrive) Init(ctx context.Context, storage model.Storage) error {
|
func (d *Onedrive) Init(ctx context.Context) error {
|
||||||
d.Storage = storage
|
|
||||||
err := utils.Json.UnmarshalFromString(d.Storage.Addition, &d.Addition)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if d.ChunkSize < 1 {
|
if d.ChunkSize < 1 {
|
||||||
d.ChunkSize = 5
|
d.ChunkSize = 5
|
||||||
}
|
}
|
||||||
@ -50,7 +44,7 @@ func (d *Onedrive) List(ctx context.Context, dir model.Obj, args model.ListArgs)
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return utils.SliceConvert(files, func(src File) (model.Obj, error) {
|
return utils.SliceConvert(files, func(src File) (model.Obj, error) {
|
||||||
return fileToObj(src), nil
|
return fileToObj(src, dir.GetID()), nil
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -95,18 +89,21 @@ func (d *Onedrive) Move(ctx context.Context, srcObj, dstDir model.Obj) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (d *Onedrive) Rename(ctx context.Context, srcObj model.Obj, newName string) error {
|
func (d *Onedrive) Rename(ctx context.Context, srcObj model.Obj, newName string) error {
|
||||||
dstDir, err := op.Get(ctx, d, stdpath.Dir(srcObj.GetPath()))
|
//dstDir, err := op.GetUnwrap(ctx, d, stdpath.Dir(srcObj.GetPath()))
|
||||||
if err != nil {
|
var parentID string
|
||||||
return err
|
if o, ok := srcObj.(*Object); ok {
|
||||||
|
parentID = o.ParentID
|
||||||
|
} else {
|
||||||
|
return fmt.Errorf("srcObj is not Object")
|
||||||
}
|
}
|
||||||
data := base.Json{
|
data := base.Json{
|
||||||
"parentReference": base.Json{
|
"parentReference": base.Json{
|
||||||
"id": dstDir.GetID(),
|
"id": parentID,
|
||||||
},
|
},
|
||||||
"name": newName,
|
"name": newName,
|
||||||
}
|
}
|
||||||
url := d.GetMetaUrl(false, srcObj.GetPath())
|
url := d.GetMetaUrl(false, srcObj.GetPath())
|
||||||
_, err = d.Request(url, http.MethodPatch, func(req *resty.Request) {
|
_, err := d.Request(url, http.MethodPatch, func(req *resty.Request) {
|
||||||
req.SetBody(data)
|
req.SetBody(data)
|
||||||
}, nil)
|
}, nil)
|
||||||
return err
|
return err
|
||||||
@ -140,7 +137,7 @@ func (d *Onedrive) Remove(ctx context.Context, obj model.Obj) error {
|
|||||||
func (d *Onedrive) Put(ctx context.Context, dstDir model.Obj, stream model.FileStreamer, up driver.UpdateProgress) error {
|
func (d *Onedrive) Put(ctx context.Context, dstDir model.Obj, stream model.FileStreamer, up driver.UpdateProgress) error {
|
||||||
var err error
|
var err error
|
||||||
if stream.GetSize() <= 4*1024*1024 {
|
if stream.GetSize() <= 4*1024*1024 {
|
||||||
err = d.upSmall(dstDir, stream)
|
err = d.upSmall(ctx, dstDir, stream)
|
||||||
} else {
|
} else {
|
||||||
err = d.upBig(ctx, dstDir, stream, up)
|
err = d.upBig(ctx, dstDir, stream, up)
|
||||||
}
|
}
|
||||||
|
@ -23,10 +23,8 @@ var config = driver.Config{
|
|||||||
DefaultRoot: "/",
|
DefaultRoot: "/",
|
||||||
}
|
}
|
||||||
|
|
||||||
func New() driver.Driver {
|
|
||||||
return &Onedrive{}
|
|
||||||
}
|
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
op.RegisterDriver(config, New)
|
op.RegisterDriver(func() driver.Driver {
|
||||||
|
return &Onedrive{}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
@ -42,21 +42,29 @@ type File struct {
|
|||||||
} `json:"parentReference"`
|
} `json:"parentReference"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func fileToObj(f File) *model.ObjThumbURL {
|
type Object struct {
|
||||||
|
model.ObjThumbURL
|
||||||
|
ParentID string
|
||||||
|
}
|
||||||
|
|
||||||
|
func fileToObj(f File, parentID string) *Object {
|
||||||
thumb := ""
|
thumb := ""
|
||||||
if len(f.Thumbnails) > 0 {
|
if len(f.Thumbnails) > 0 {
|
||||||
thumb = f.Thumbnails[0].Medium.Url
|
thumb = f.Thumbnails[0].Medium.Url
|
||||||
}
|
}
|
||||||
return &model.ObjThumbURL{
|
return &Object{
|
||||||
Object: model.Object{
|
ObjThumbURL: model.ObjThumbURL{
|
||||||
ID: f.Id,
|
Object: model.Object{
|
||||||
Name: f.Name,
|
ID: f.Id,
|
||||||
Size: f.Size,
|
Name: f.Name,
|
||||||
Modified: f.LastModifiedDateTime,
|
Size: f.Size,
|
||||||
IsFolder: f.File == nil,
|
Modified: f.LastModifiedDateTime,
|
||||||
|
IsFolder: f.File == nil,
|
||||||
|
},
|
||||||
|
Thumbnail: model.Thumbnail{Thumbnail: thumb},
|
||||||
|
Url: model.Url{Url: f.Url},
|
||||||
},
|
},
|
||||||
Thumbnail: model.Thumbnail{Thumbnail: thumb},
|
ParentID: parentID,
|
||||||
Url: model.Url{Url: f.Url},
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -147,14 +147,14 @@ func (d *Onedrive) GetFile(path string) (*File, error) {
|
|||||||
return &file, err
|
return &file, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *Onedrive) upSmall(dstDir model.Obj, stream model.FileStreamer) error {
|
func (d *Onedrive) upSmall(ctx context.Context, dstDir model.Obj, stream model.FileStreamer) error {
|
||||||
url := d.GetMetaUrl(false, stdpath.Join(dstDir.GetPath(), stream.GetName())) + "/content"
|
url := d.GetMetaUrl(false, stdpath.Join(dstDir.GetPath(), stream.GetName())) + "/content"
|
||||||
data, err := io.ReadAll(stream)
|
data, err := io.ReadAll(stream)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
_, err = d.Request(url, http.MethodPut, func(req *resty.Request) {
|
_, err = d.Request(url, http.MethodPut, func(req *resty.Request) {
|
||||||
req.SetBody(data)
|
req.SetBody(data).SetContext(ctx)
|
||||||
}, nil)
|
}, nil)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -185,6 +185,10 @@ func (d *Onedrive) upBig(ctx context.Context, dstDir model.Obj, stream model.Fil
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
req, err := http.NewRequest("PUT", uploadUrl, bytes.NewBuffer(byteData))
|
req, err := http.NewRequest("PUT", uploadUrl, bytes.NewBuffer(byteData))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
req = req.WithContext(ctx)
|
||||||
req.Header.Set("Content-Length", strconv.Itoa(int(byteSize)))
|
req.Header.Set("Content-Length", strconv.Itoa(int(byteSize)))
|
||||||
req.Header.Set("Content-Range", fmt.Sprintf("bytes %d-%d/%d", finish, finish+byteSize-1, stream.GetSize()))
|
req.Header.Set("Content-Range", fmt.Sprintf("bytes %d-%d/%d", finish, finish+byteSize-1, stream.GetSize()))
|
||||||
finish += byteSize
|
finish += byteSize
|
||||||
|
@ -35,15 +35,10 @@ func (d *PikPak) Config() driver.Config {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (d *PikPak) GetAddition() driver.Additional {
|
func (d *PikPak) GetAddition() driver.Additional {
|
||||||
return d.Addition
|
return &d.Addition
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *PikPak) Init(ctx context.Context, storage model.Storage) error {
|
func (d *PikPak) Init(ctx context.Context) error {
|
||||||
d.Storage = storage
|
|
||||||
err := utils.Json.UnmarshalFromString(d.Storage.Addition, &d.Addition)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return d.login()
|
return d.login()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -194,7 +189,7 @@ func (d *PikPak) Put(ctx context.Context, dstDir model.Obj, stream model.FileStr
|
|||||||
Key: &key,
|
Key: &key,
|
||||||
Body: tempFile,
|
Body: tempFile,
|
||||||
}
|
}
|
||||||
_, err = uploader.Upload(input)
|
_, err = uploader.UploadWithContext(ctx, input)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -17,10 +17,8 @@ var config = driver.Config{
|
|||||||
DefaultRoot: "",
|
DefaultRoot: "",
|
||||||
}
|
}
|
||||||
|
|
||||||
func New() driver.Driver {
|
|
||||||
return &PikPak{}
|
|
||||||
}
|
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
op.RegisterDriver(config, New)
|
op.RegisterDriver(func() driver.Driver {
|
||||||
|
return &PikPak{}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
81
drivers/pikpak_share/driver.go
Normal file
81
drivers/pikpak_share/driver.go
Normal file
@ -0,0 +1,81 @@
|
|||||||
|
package pikpak_share
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"github.com/alist-org/alist/v3/internal/driver"
|
||||||
|
"github.com/alist-org/alist/v3/internal/model"
|
||||||
|
"github.com/alist-org/alist/v3/pkg/utils"
|
||||||
|
"github.com/go-resty/resty/v2"
|
||||||
|
log "github.com/sirupsen/logrus"
|
||||||
|
)
|
||||||
|
|
||||||
|
type PikPakShare struct {
|
||||||
|
model.Storage
|
||||||
|
Addition
|
||||||
|
RefreshToken string
|
||||||
|
AccessToken string
|
||||||
|
PassCodeToken string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *PikPakShare) Config() driver.Config {
|
||||||
|
return config
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *PikPakShare) GetAddition() driver.Additional {
|
||||||
|
return &d.Addition
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *PikPakShare) Init(ctx context.Context) error {
|
||||||
|
err := d.login()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if d.SharePwd != "" {
|
||||||
|
err = d.getSharePassToken()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *PikPakShare) Drop(ctx context.Context) error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *PikPakShare) List(ctx context.Context, dir model.Obj, args model.ListArgs) ([]model.Obj, error) {
|
||||||
|
files, err := d.getFiles(dir.GetID())
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return utils.SliceConvert(files, func(src File) (model.Obj, error) {
|
||||||
|
return fileToObj(src), nil
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *PikPakShare) Link(ctx context.Context, file model.Obj, args model.LinkArgs) (*model.Link, error) {
|
||||||
|
var resp ShareResp
|
||||||
|
query := map[string]string{
|
||||||
|
"share_id": d.ShareId,
|
||||||
|
"file_id": file.GetID(),
|
||||||
|
"pass_code_token": d.PassCodeToken,
|
||||||
|
}
|
||||||
|
_, err := d.request("https://api-drive.mypikpak.com/drive/v1/share/file_info", http.MethodGet, func(req *resty.Request) {
|
||||||
|
req.SetQueryParams(query)
|
||||||
|
}, &resp)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
link := model.Link{
|
||||||
|
URL: resp.FileInfo.WebContentLink,
|
||||||
|
}
|
||||||
|
if len(resp.FileInfo.Medias) > 0 && resp.FileInfo.Medias[0].Link.Url != "" {
|
||||||
|
log.Debugln("use media link")
|
||||||
|
link.URL = resp.FileInfo.Medias[0].Link.Url
|
||||||
|
}
|
||||||
|
return &link, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
var _ driver.Driver = (*PikPakShare)(nil)
|
27
drivers/pikpak_share/meta.go
Normal file
27
drivers/pikpak_share/meta.go
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
package pikpak_share
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/alist-org/alist/v3/internal/driver"
|
||||||
|
"github.com/alist-org/alist/v3/internal/op"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Addition struct {
|
||||||
|
driver.RootID
|
||||||
|
Username string `json:"username" required:"true"`
|
||||||
|
Password string `json:"password" required:"true"`
|
||||||
|
ShareId string `json:"share_id" required:"true"`
|
||||||
|
SharePwd string `json:"share_pwd"`
|
||||||
|
}
|
||||||
|
|
||||||
|
var config = driver.Config{
|
||||||
|
Name: "PikPakShare",
|
||||||
|
LocalSort: true,
|
||||||
|
NoUpload: true,
|
||||||
|
DefaultRoot: "",
|
||||||
|
}
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
op.RegisterDriver(func() driver.Driver {
|
||||||
|
return &PikPakShare{}
|
||||||
|
})
|
||||||
|
}
|
80
drivers/pikpak_share/types.go
Normal file
80
drivers/pikpak_share/types.go
Normal file
@ -0,0 +1,80 @@
|
|||||||
|
package pikpak_share
|
||||||
|
|
||||||
|
import (
|
||||||
|
"strconv"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/alist-org/alist/v3/internal/model"
|
||||||
|
)
|
||||||
|
|
||||||
|
type RespErr struct {
|
||||||
|
ErrorCode int `json:"error_code"`
|
||||||
|
Error string `json:"error"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type ShareResp struct {
|
||||||
|
ShareStatus string `json:"share_status"`
|
||||||
|
ShareStatusText string `json:"share_status_text"`
|
||||||
|
FileInfo File `json:"file_info"`
|
||||||
|
Files []File `json:"files"`
|
||||||
|
NextPageToken string `json:"next_page_token"`
|
||||||
|
PassCodeToken string `json:"pass_code_token"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type File struct {
|
||||||
|
Id string `json:"id"`
|
||||||
|
ShareId string `json:"share_id"`
|
||||||
|
Kind string `json:"kind"`
|
||||||
|
Name string `json:"name"`
|
||||||
|
ModifiedTime time.Time `json:"modified_time"`
|
||||||
|
Size string `json:"size"`
|
||||||
|
ThumbnailLink string `json:"thumbnail_link"`
|
||||||
|
WebContentLink string `json:"web_content_link"`
|
||||||
|
Medias []Media `json:"medias"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func fileToObj(f File) *model.ObjThumb {
|
||||||
|
size, _ := strconv.ParseInt(f.Size, 10, 64)
|
||||||
|
return &model.ObjThumb{
|
||||||
|
Object: model.Object{
|
||||||
|
ID: f.Id,
|
||||||
|
Name: f.Name,
|
||||||
|
Size: size,
|
||||||
|
Modified: f.ModifiedTime,
|
||||||
|
IsFolder: f.Kind == "drive#folder",
|
||||||
|
},
|
||||||
|
Thumbnail: model.Thumbnail{
|
||||||
|
Thumbnail: f.ThumbnailLink,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type Media struct {
|
||||||
|
MediaId string `json:"media_id"`
|
||||||
|
MediaName string `json:"media_name"`
|
||||||
|
Video struct {
|
||||||
|
Height int `json:"height"`
|
||||||
|
Width int `json:"width"`
|
||||||
|
Duration int `json:"duration"`
|
||||||
|
BitRate int `json:"bit_rate"`
|
||||||
|
FrameRate int `json:"frame_rate"`
|
||||||
|
VideoCodec string `json:"video_codec"`
|
||||||
|
AudioCodec string `json:"audio_codec"`
|
||||||
|
VideoType string `json:"video_type"`
|
||||||
|
} `json:"video"`
|
||||||
|
Link struct {
|
||||||
|
Url string `json:"url"`
|
||||||
|
Token string `json:"token"`
|
||||||
|
Expire time.Time `json:"expire"`
|
||||||
|
} `json:"link"`
|
||||||
|
NeedMoreQuota bool `json:"need_more_quota"`
|
||||||
|
VipTypes []interface{} `json:"vip_types"`
|
||||||
|
RedirectLink string `json:"redirect_link"`
|
||||||
|
IconLink string `json:"icon_link"`
|
||||||
|
IsDefault bool `json:"is_default"`
|
||||||
|
Priority int `json:"priority"`
|
||||||
|
IsOrigin bool `json:"is_origin"`
|
||||||
|
ResolutionName string `json:"resolution_name"`
|
||||||
|
IsVisible bool `json:"is_visible"`
|
||||||
|
Category string `json:"category"`
|
||||||
|
}
|
154
drivers/pikpak_share/util.go
Normal file
154
drivers/pikpak_share/util.go
Normal file
@ -0,0 +1,154 @@
|
|||||||
|
package pikpak_share
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"github.com/alist-org/alist/v3/drivers/base"
|
||||||
|
"github.com/alist-org/alist/v3/internal/op"
|
||||||
|
"github.com/go-resty/resty/v2"
|
||||||
|
jsoniter "github.com/json-iterator/go"
|
||||||
|
)
|
||||||
|
|
||||||
|
// do others that not defined in Driver interface
|
||||||
|
|
||||||
|
func (d *PikPakShare) login() error {
|
||||||
|
url := "https://user.mypikpak.com/v1/auth/signin"
|
||||||
|
var e RespErr
|
||||||
|
res, err := base.RestyClient.R().SetError(&e).SetBody(base.Json{
|
||||||
|
"captcha_token": "",
|
||||||
|
"client_id": "YNxT9w7GMdWvEOKa",
|
||||||
|
"client_secret": "dbw2OtmVEeuUvIptb1Coyg",
|
||||||
|
"username": d.Username,
|
||||||
|
"password": d.Password,
|
||||||
|
}).Post(url)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if e.ErrorCode != 0 {
|
||||||
|
return errors.New(e.Error)
|
||||||
|
}
|
||||||
|
data := res.Body()
|
||||||
|
d.RefreshToken = jsoniter.Get(data, "refresh_token").ToString()
|
||||||
|
d.AccessToken = jsoniter.Get(data, "access_token").ToString()
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *PikPakShare) refreshToken() error {
|
||||||
|
url := "https://user.mypikpak.com/v1/auth/token"
|
||||||
|
var e RespErr
|
||||||
|
res, err := base.RestyClient.R().SetError(&e).
|
||||||
|
SetHeader("user-agent", "").SetBody(base.Json{
|
||||||
|
"client_id": "YNxT9w7GMdWvEOKa",
|
||||||
|
"client_secret": "dbw2OtmVEeuUvIptb1Coyg",
|
||||||
|
"grant_type": "refresh_token",
|
||||||
|
"refresh_token": d.RefreshToken,
|
||||||
|
}).Post(url)
|
||||||
|
if err != nil {
|
||||||
|
d.Status = err.Error()
|
||||||
|
op.MustSaveDriverStorage(d)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if e.ErrorCode != 0 {
|
||||||
|
if e.ErrorCode == 4126 {
|
||||||
|
// refresh_token invalid, re-login
|
||||||
|
return d.login()
|
||||||
|
}
|
||||||
|
d.Status = e.Error
|
||||||
|
op.MustSaveDriverStorage(d)
|
||||||
|
return errors.New(e.Error)
|
||||||
|
}
|
||||||
|
data := res.Body()
|
||||||
|
d.Status = "work"
|
||||||
|
d.RefreshToken = jsoniter.Get(data, "refresh_token").ToString()
|
||||||
|
d.AccessToken = jsoniter.Get(data, "access_token").ToString()
|
||||||
|
op.MustSaveDriverStorage(d)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *PikPakShare) request(url string, method string, callback base.ReqCallback, resp interface{}) ([]byte, error) {
|
||||||
|
req := base.RestyClient.R()
|
||||||
|
req.SetHeader("Authorization", "Bearer "+d.AccessToken)
|
||||||
|
if callback != nil {
|
||||||
|
callback(req)
|
||||||
|
}
|
||||||
|
if resp != nil {
|
||||||
|
req.SetResult(resp)
|
||||||
|
}
|
||||||
|
var e RespErr
|
||||||
|
req.SetError(&e)
|
||||||
|
res, err := req.Execute(method, url)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if e.ErrorCode != 0 {
|
||||||
|
if e.ErrorCode == 16 {
|
||||||
|
// login / refresh token
|
||||||
|
err = d.refreshToken()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return d.request(url, method, callback, resp)
|
||||||
|
}
|
||||||
|
return nil, errors.New(e.Error)
|
||||||
|
}
|
||||||
|
return res.Body(), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *PikPakShare) getSharePassToken() error {
|
||||||
|
query := map[string]string{
|
||||||
|
"share_id": d.ShareId,
|
||||||
|
"pass_code": d.SharePwd,
|
||||||
|
"thumbnail_size": "SIZE_LARGE",
|
||||||
|
"limit": "100",
|
||||||
|
}
|
||||||
|
var resp ShareResp
|
||||||
|
_, err := d.request("https://api-drive.mypikpak.com/drive/v1/share", http.MethodGet, func(req *resty.Request) {
|
||||||
|
req.SetQueryParams(query)
|
||||||
|
}, &resp)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
d.PassCodeToken = resp.PassCodeToken
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *PikPakShare) getFiles(id string) ([]File, error) {
|
||||||
|
res := make([]File, 0)
|
||||||
|
pageToken := "first"
|
||||||
|
for pageToken != "" {
|
||||||
|
if pageToken == "first" {
|
||||||
|
pageToken = ""
|
||||||
|
}
|
||||||
|
query := map[string]string{
|
||||||
|
"parent_id": id,
|
||||||
|
"share_id": d.ShareId,
|
||||||
|
"thumbnail_size": "SIZE_LARGE",
|
||||||
|
"with_audit": "true",
|
||||||
|
"limit": "100",
|
||||||
|
"filters": `{"phase":{"eq":"PHASE_TYPE_COMPLETE"},"trashed":{"eq":false}}`,
|
||||||
|
"page_token": pageToken,
|
||||||
|
"pass_code_token": d.PassCodeToken,
|
||||||
|
}
|
||||||
|
var resp ShareResp
|
||||||
|
_, err := d.request("https://api-drive.mypikpak.com/drive/v1/share/detail", http.MethodGet, func(req *resty.Request) {
|
||||||
|
req.SetQueryParams(query)
|
||||||
|
}, &resp)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if resp.ShareStatus != "OK" {
|
||||||
|
if resp.ShareStatus == "PASS_CODE_EMPTY" || resp.ShareStatus == "PASS_CODE_ERROR" {
|
||||||
|
err = d.getSharePassToken()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return d.getFiles(id)
|
||||||
|
}
|
||||||
|
return nil, errors.New(resp.ShareStatusText)
|
||||||
|
}
|
||||||
|
pageToken = resp.NextPageToken
|
||||||
|
res = append(res, resp.Files...)
|
||||||
|
}
|
||||||
|
return res, nil
|
||||||
|
}
|
@ -29,16 +29,11 @@ func (d *Quark) Config() driver.Config {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (d *Quark) GetAddition() driver.Additional {
|
func (d *Quark) GetAddition() driver.Additional {
|
||||||
return d.Addition
|
return &d.Addition
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *Quark) Init(ctx context.Context, storage model.Storage) error {
|
func (d *Quark) Init(ctx context.Context) error {
|
||||||
d.Storage = storage
|
_, err := d.request("/config", http.MethodGet, nil, nil)
|
||||||
err := utils.Json.UnmarshalFromString(d.Storage.Addition, &d.Addition)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
_, err = d.request("/config", http.MethodGet, nil, nil)
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -56,11 +51,6 @@ func (d *Quark) List(ctx context.Context, dir model.Obj, args model.ListArgs) ([
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
//func (d *Quark) Get(ctx context.Context, path string) (model.Obj, error) {
|
|
||||||
// // TODO this is optional
|
|
||||||
// return nil, errs.NotImplement
|
|
||||||
//}
|
|
||||||
|
|
||||||
func (d *Quark) Link(ctx context.Context, file model.Obj, args model.LinkArgs) (*model.Link, error) {
|
func (d *Quark) Link(ctx context.Context, file model.Obj, args model.LinkArgs) (*model.Link, error) {
|
||||||
data := base.Json{
|
data := base.Json{
|
||||||
"fids": []string{file.GetID()},
|
"fids": []string{file.GetID()},
|
||||||
@ -189,6 +179,9 @@ func (d *Quark) Put(ctx context.Context, dstDir model.Obj, stream model.FileStre
|
|||||||
partNumber := 1
|
partNumber := 1
|
||||||
sizeDivide100 := stream.GetSize() / 100
|
sizeDivide100 := stream.GetSize() / 100
|
||||||
for left > 0 {
|
for left > 0 {
|
||||||
|
if utils.IsCanceled(ctx) {
|
||||||
|
return ctx.Err()
|
||||||
|
}
|
||||||
if left > int64(partSize) {
|
if left > int64(partSize) {
|
||||||
bytes = defaultBytes
|
bytes = defaultBytes
|
||||||
} else {
|
} else {
|
||||||
@ -200,7 +193,7 @@ func (d *Quark) Put(ctx context.Context, dstDir model.Obj, stream model.FileStre
|
|||||||
}
|
}
|
||||||
left -= int64(partSize)
|
left -= int64(partSize)
|
||||||
log.Debugf("left: %d", left)
|
log.Debugf("left: %d", left)
|
||||||
m, err := d.upPart(pre, stream.GetMimetype(), partNumber, bytes)
|
m, err := d.upPart(ctx, pre, stream.GetMimetype(), partNumber, bytes)
|
||||||
//m, err := driver.UpPart(pre, file.GetMIMEType(), partNumber, bytes, account, md5Str, sha1Str)
|
//m, err := driver.UpPart(pre, file.GetMIMEType(), partNumber, bytes, account, md5Str, sha1Str)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -18,10 +18,8 @@ var config = driver.Config{
|
|||||||
DefaultRoot: "0",
|
DefaultRoot: "0",
|
||||||
}
|
}
|
||||||
|
|
||||||
func New() driver.Driver {
|
|
||||||
return &Quark{}
|
|
||||||
}
|
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
op.RegisterDriver(config, New)
|
op.RegisterDriver(func() driver.Driver {
|
||||||
|
return &Quark{}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package quark
|
package quark
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"crypto/md5"
|
"crypto/md5"
|
||||||
"encoding/base64"
|
"encoding/base64"
|
||||||
"errors"
|
"errors"
|
||||||
@ -118,7 +119,7 @@ func (d *Quark) upHash(md5, sha1, taskId string) (bool, error) {
|
|||||||
return resp.Data.Finish, err
|
return resp.Data.Finish, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *Quark) upPart(pre UpPreResp, mineType string, partNumber int, bytes []byte) (string, error) {
|
func (d *Quark) upPart(ctx context.Context, pre UpPreResp, mineType string, partNumber int, bytes []byte) (string, error) {
|
||||||
//func (driver Quark) UpPart(pre UpPreResp, mineType string, partNumber int, bytes []byte, account *model.Account, md5Str, sha1Str string) (string, error) {
|
//func (driver Quark) UpPart(pre UpPreResp, mineType string, partNumber int, bytes []byte, account *model.Account, md5Str, sha1Str string) (string, error) {
|
||||||
timeStr := time.Now().UTC().Format(http.TimeFormat)
|
timeStr := time.Now().UTC().Format(http.TimeFormat)
|
||||||
data := base.Json{
|
data := base.Json{
|
||||||
@ -135,7 +136,7 @@ x-oss-user-agent:aliyun-sdk-js/6.6.1 Chrome 98.0.4758.80 on Windows 10 64-bit
|
|||||||
}
|
}
|
||||||
var resp UpAuthResp
|
var resp UpAuthResp
|
||||||
_, err := d.request("/file/upload/auth", http.MethodPost, func(req *resty.Request) {
|
_, err := d.request("/file/upload/auth", http.MethodPost, func(req *resty.Request) {
|
||||||
req.SetBody(data)
|
req.SetBody(data).SetContext(ctx)
|
||||||
}, &resp)
|
}, &resp)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
@ -150,7 +151,7 @@ x-oss-user-agent:aliyun-sdk-js/6.6.1 Chrome 98.0.4758.80 on Windows 10 64-bit
|
|||||||
// }
|
// }
|
||||||
//}
|
//}
|
||||||
u := fmt.Sprintf("https://%s.%s/%s", pre.Data.Bucket, pre.Data.UploadUrl[7:], pre.Data.ObjKey)
|
u := fmt.Sprintf("https://%s.%s/%s", pre.Data.Bucket, pre.Data.UploadUrl[7:], pre.Data.ObjKey)
|
||||||
res, err := base.RestyClient.R().
|
res, err := base.RestyClient.R().SetContext(ctx).
|
||||||
SetHeaders(map[string]string{
|
SetHeaders(map[string]string{
|
||||||
"Authorization": resp.Data.AuthKey,
|
"Authorization": resp.Data.AuthKey,
|
||||||
"Content-Type": mineType,
|
"Content-Type": mineType,
|
||||||
|
@ -11,7 +11,6 @@ import (
|
|||||||
|
|
||||||
"github.com/alist-org/alist/v3/internal/driver"
|
"github.com/alist-org/alist/v3/internal/driver"
|
||||||
"github.com/alist-org/alist/v3/internal/model"
|
"github.com/alist-org/alist/v3/internal/model"
|
||||||
"github.com/alist-org/alist/v3/pkg/utils"
|
|
||||||
"github.com/aws/aws-sdk-go/aws/session"
|
"github.com/aws/aws-sdk-go/aws/session"
|
||||||
"github.com/aws/aws-sdk-go/service/s3"
|
"github.com/aws/aws-sdk-go/service/s3"
|
||||||
"github.com/aws/aws-sdk-go/service/s3/s3manager"
|
"github.com/aws/aws-sdk-go/service/s3/s3manager"
|
||||||
@ -31,19 +30,14 @@ func (d *S3) Config() driver.Config {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (d *S3) GetAddition() driver.Additional {
|
func (d *S3) GetAddition() driver.Additional {
|
||||||
return d.Addition
|
return &d.Addition
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *S3) Init(ctx context.Context, storage model.Storage) error {
|
func (d *S3) Init(ctx context.Context) error {
|
||||||
d.Storage = storage
|
|
||||||
err := utils.Json.UnmarshalFromString(d.Storage.Addition, &d.Addition)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if d.Region == "" {
|
if d.Region == "" {
|
||||||
d.Region = "alist"
|
d.Region = "alist"
|
||||||
}
|
}
|
||||||
err = d.initSession()
|
err := d.initSession()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -63,11 +57,6 @@ func (d *S3) List(ctx context.Context, dir model.Obj, args model.ListArgs) ([]mo
|
|||||||
return d.listV1(dir.GetPath())
|
return d.listV1(dir.GetPath())
|
||||||
}
|
}
|
||||||
|
|
||||||
//func (d *S3) Get(ctx context.Context, path string) (model.Obj, error) {
|
|
||||||
// // this is optional
|
|
||||||
// return nil, errs.NotImplement
|
|
||||||
//}
|
|
||||||
|
|
||||||
func (d *S3) Link(ctx context.Context, file model.Obj, args model.LinkArgs) (*model.Link, error) {
|
func (d *S3) Link(ctx context.Context, file model.Obj, args model.LinkArgs) (*model.Link, error) {
|
||||||
path := getKey(file.GetPath(), false)
|
path := getKey(file.GetPath(), false)
|
||||||
disposition := fmt.Sprintf(`attachment;filename="%s"`, url.QueryEscape(stdpath.Base(path)))
|
disposition := fmt.Sprintf(`attachment;filename="%s"`, url.QueryEscape(stdpath.Base(path)))
|
||||||
@ -145,7 +134,7 @@ func (d *S3) Put(ctx context.Context, dstDir model.Obj, stream model.FileStreame
|
|||||||
Key: &key,
|
Key: &key,
|
||||||
Body: stream,
|
Body: stream,
|
||||||
}
|
}
|
||||||
_, err := uploader.Upload(input)
|
_, err := uploader.UploadWithContext(ctx, input)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -21,14 +21,13 @@ type Addition struct {
|
|||||||
|
|
||||||
var config = driver.Config{
|
var config = driver.Config{
|
||||||
Name: "S3",
|
Name: "S3",
|
||||||
|
DefaultRoot: "/",
|
||||||
LocalSort: true,
|
LocalSort: true,
|
||||||
CheckStatus: true,
|
CheckStatus: true,
|
||||||
}
|
}
|
||||||
|
|
||||||
func New() driver.Driver {
|
|
||||||
return &S3{}
|
|
||||||
}
|
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
op.RegisterDriver(config, New)
|
op.RegisterDriver(func() driver.Driver {
|
||||||
|
return &S3{}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
@ -23,15 +23,10 @@ func (d *SFTP) Config() driver.Config {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (d *SFTP) GetAddition() driver.Additional {
|
func (d *SFTP) GetAddition() driver.Additional {
|
||||||
return d.Addition
|
return &d.Addition
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *SFTP) Init(ctx context.Context, storage model.Storage) error {
|
func (d *SFTP) Init(ctx context.Context) error {
|
||||||
d.Storage = storage
|
|
||||||
err := utils.Json.UnmarshalFromString(d.Storage.Addition, &d.Addition)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return d.initClient()
|
return d.initClient()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -52,11 +47,6 @@ func (d *SFTP) List(ctx context.Context, dir model.Obj, args model.ListArgs) ([]
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
//func (d *SFTP) Get(ctx context.Context, path string) (model.Obj, error) {
|
|
||||||
// // this is optional
|
|
||||||
// return nil, errs.NotImplement
|
|
||||||
//}
|
|
||||||
|
|
||||||
func (d *SFTP) Link(ctx context.Context, file model.Obj, args model.LinkArgs) (*model.Link, error) {
|
func (d *SFTP) Link(ctx context.Context, file model.Obj, args model.LinkArgs) (*model.Link, error) {
|
||||||
remoteFile, err := d.client.Open(file.GetPath())
|
remoteFile, err := d.client.Open(file.GetPath())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -21,10 +21,8 @@ var config = driver.Config{
|
|||||||
CheckStatus: true,
|
CheckStatus: true,
|
||||||
}
|
}
|
||||||
|
|
||||||
func New() driver.Driver {
|
|
||||||
return &SFTP{}
|
|
||||||
}
|
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
op.RegisterDriver(config, New)
|
op.RegisterDriver(func() driver.Driver {
|
||||||
|
return &SFTP{}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
@ -4,6 +4,7 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"errors"
|
"errors"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/alist-org/alist/v3/internal/driver"
|
"github.com/alist-org/alist/v3/internal/driver"
|
||||||
@ -25,14 +26,12 @@ func (d *SMB) Config() driver.Config {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (d *SMB) GetAddition() driver.Additional {
|
func (d *SMB) GetAddition() driver.Additional {
|
||||||
return d.Addition
|
return &d.Addition
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *SMB) Init(ctx context.Context, storage model.Storage) error {
|
func (d *SMB) Init(ctx context.Context) error {
|
||||||
d.Storage = storage
|
if strings.Index(d.Addition.Address, ":") < 0 {
|
||||||
err := utils.Json.UnmarshalFromString(d.Storage.Addition, &d.Addition)
|
d.Addition.Address = d.Addition.Address + ":445"
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
}
|
||||||
return d.initFS()
|
return d.initFS()
|
||||||
}
|
}
|
||||||
@ -70,11 +69,6 @@ func (d *SMB) List(ctx context.Context, dir model.Obj, args model.ListArgs) ([]m
|
|||||||
return files, nil
|
return files, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
//func (d *SMB) Get(ctx context.Context, path string) (model.Obj, error) {
|
|
||||||
// // this is optional
|
|
||||||
// return nil, errs.NotImplement
|
|
||||||
//}
|
|
||||||
|
|
||||||
func (d *SMB) Link(ctx context.Context, file model.Obj, args model.LinkArgs) (*model.Link, error) {
|
func (d *SMB) Link(ctx context.Context, file model.Obj, args model.LinkArgs) (*model.Link, error) {
|
||||||
if err := d.checkConn(); err != nil {
|
if err := d.checkConn(); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -22,7 +22,7 @@ var config = driver.Config{
|
|||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
op.RegisterDriver(config, func() driver.Driver {
|
op.RegisterDriver(func() driver.Driver {
|
||||||
return &SMB{}
|
return &SMB{}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -8,7 +8,6 @@ import (
|
|||||||
"github.com/alist-org/alist/v3/drivers/base"
|
"github.com/alist-org/alist/v3/drivers/base"
|
||||||
"github.com/alist-org/alist/v3/internal/driver"
|
"github.com/alist-org/alist/v3/internal/driver"
|
||||||
"github.com/alist-org/alist/v3/internal/model"
|
"github.com/alist-org/alist/v3/internal/model"
|
||||||
"github.com/alist-org/alist/v3/pkg/utils"
|
|
||||||
"github.com/go-resty/resty/v2"
|
"github.com/go-resty/resty/v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -22,16 +21,11 @@ func (d *Teambition) Config() driver.Config {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (d *Teambition) GetAddition() driver.Additional {
|
func (d *Teambition) GetAddition() driver.Additional {
|
||||||
return d.Addition
|
return &d.Addition
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *Teambition) Init(ctx context.Context, storage model.Storage) error {
|
func (d *Teambition) Init(ctx context.Context) error {
|
||||||
d.Storage = storage
|
_, err := d.request("/api/v2/roles", http.MethodGet, nil, nil)
|
||||||
err := utils.Json.UnmarshalFromString(d.Storage.Addition, &d.Addition)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
_, err = d.request("/api/v2/roles", http.MethodGet, nil, nil)
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -43,11 +37,6 @@ func (d *Teambition) List(ctx context.Context, dir model.Obj, args model.ListArg
|
|||||||
return d.getFiles(dir.GetID())
|
return d.getFiles(dir.GetID())
|
||||||
}
|
}
|
||||||
|
|
||||||
//func (d *Teambition) Get(ctx context.Context, path string) (model.Obj, error) {
|
|
||||||
// // this is optional
|
|
||||||
// return nil, errs.NotImplement
|
|
||||||
//}
|
|
||||||
|
|
||||||
func (d *Teambition) Link(ctx context.Context, file model.Obj, args model.LinkArgs) (*model.Link, error) {
|
func (d *Teambition) Link(ctx context.Context, file model.Obj, args model.LinkArgs) (*model.Link, error) {
|
||||||
if u, ok := file.(model.URL); ok {
|
if u, ok := file.(model.URL); ok {
|
||||||
url := u.URL()
|
url := u.URL()
|
||||||
@ -143,11 +132,11 @@ func (d *Teambition) Put(ctx context.Context, dstDir model.Obj, stream model.Fil
|
|||||||
var newFile *FileUpload
|
var newFile *FileUpload
|
||||||
if stream.GetSize() <= 20971520 {
|
if stream.GetSize() <= 20971520 {
|
||||||
// post upload
|
// post upload
|
||||||
newFile, err = d.upload(stream, token)
|
newFile, err = d.upload(ctx, stream, token)
|
||||||
} else {
|
} else {
|
||||||
// chunk upload
|
// chunk upload
|
||||||
//err = base.ErrNotImplement
|
//err = base.ErrNotImplement
|
||||||
newFile, err = d.chunkUpload(stream, token, up)
|
newFile, err = d.chunkUpload(ctx, stream, token, up)
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -18,10 +18,8 @@ var config = driver.Config{
|
|||||||
Name: "Teambition",
|
Name: "Teambition",
|
||||||
}
|
}
|
||||||
|
|
||||||
func New() driver.Driver {
|
|
||||||
return &Teambition{}
|
|
||||||
}
|
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
op.RegisterDriver(config, New)
|
op.RegisterDriver(func() driver.Driver {
|
||||||
|
return &Teambition{}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package teambition
|
package teambition
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
@ -12,6 +13,7 @@ import (
|
|||||||
"github.com/alist-org/alist/v3/drivers/base"
|
"github.com/alist-org/alist/v3/drivers/base"
|
||||||
"github.com/alist-org/alist/v3/internal/driver"
|
"github.com/alist-org/alist/v3/internal/driver"
|
||||||
"github.com/alist-org/alist/v3/internal/model"
|
"github.com/alist-org/alist/v3/internal/model"
|
||||||
|
"github.com/alist-org/alist/v3/pkg/utils"
|
||||||
"github.com/go-resty/resty/v2"
|
"github.com/go-resty/resty/v2"
|
||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
)
|
)
|
||||||
@ -115,13 +117,15 @@ func (d *Teambition) getFiles(parentId string) ([]model.Obj, error) {
|
|||||||
return files, nil
|
return files, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *Teambition) upload(file model.FileStreamer, token string) (*FileUpload, error) {
|
func (d *Teambition) upload(ctx context.Context, file model.FileStreamer, token string) (*FileUpload, error) {
|
||||||
prefix := "tcs"
|
prefix := "tcs"
|
||||||
if d.isInternational() {
|
if d.isInternational() {
|
||||||
prefix = "us-tcs"
|
prefix = "us-tcs"
|
||||||
}
|
}
|
||||||
var newFile FileUpload
|
var newFile FileUpload
|
||||||
_, err := base.RestyClient.R().SetResult(&newFile).SetHeader("Authorization", token).
|
_, err := base.RestyClient.R().
|
||||||
|
SetContext(ctx).
|
||||||
|
SetResult(&newFile).SetHeader("Authorization", token).
|
||||||
SetMultipartFormData(map[string]string{
|
SetMultipartFormData(map[string]string{
|
||||||
"name": file.GetName(),
|
"name": file.GetName(),
|
||||||
"type": file.GetMimetype(),
|
"type": file.GetMimetype(),
|
||||||
@ -135,7 +139,7 @@ func (d *Teambition) upload(file model.FileStreamer, token string) (*FileUpload,
|
|||||||
return &newFile, nil
|
return &newFile, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *Teambition) chunkUpload(file model.FileStreamer, token string, up driver.UpdateProgress) (*FileUpload, error) {
|
func (d *Teambition) chunkUpload(ctx context.Context, file model.FileStreamer, token string, up driver.UpdateProgress) (*FileUpload, error) {
|
||||||
prefix := "tcs"
|
prefix := "tcs"
|
||||||
referer := "https://www.teambition.com/"
|
referer := "https://www.teambition.com/"
|
||||||
if d.isInternational() {
|
if d.isInternational() {
|
||||||
@ -153,6 +157,9 @@ func (d *Teambition) chunkUpload(file model.FileStreamer, token string, up drive
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
for i := 0; i < newChunk.Chunks; i++ {
|
for i := 0; i < newChunk.Chunks; i++ {
|
||||||
|
if utils.IsCanceled(ctx) {
|
||||||
|
return nil, ctx.Err()
|
||||||
|
}
|
||||||
chunkSize := newChunk.ChunkSize
|
chunkSize := newChunk.ChunkSize
|
||||||
if i == newChunk.Chunks-1 {
|
if i == newChunk.Chunks-1 {
|
||||||
chunkSize = int(file.GetSize()) - i*chunkSize
|
chunkSize = int(file.GetSize()) - i*chunkSize
|
||||||
@ -166,11 +173,13 @@ func (d *Teambition) chunkUpload(file model.FileStreamer, token string, up drive
|
|||||||
u := fmt.Sprintf("https://%s.teambition.net/upload/chunk/%s?chunk=%d&chunks=%d",
|
u := fmt.Sprintf("https://%s.teambition.net/upload/chunk/%s?chunk=%d&chunks=%d",
|
||||||
prefix, newChunk.FileKey, i+1, newChunk.Chunks)
|
prefix, newChunk.FileKey, i+1, newChunk.Chunks)
|
||||||
log.Debugf("url: %s", u)
|
log.Debugf("url: %s", u)
|
||||||
_, err := base.RestyClient.R().SetHeaders(map[string]string{
|
_, err := base.RestyClient.R().
|
||||||
"Authorization": token,
|
SetContext(ctx).
|
||||||
"Content-Type": "application/octet-stream",
|
SetHeaders(map[string]string{
|
||||||
"Referer": referer,
|
"Authorization": token,
|
||||||
}).SetBody(chunkData).Post(u)
|
"Content-Type": "application/octet-stream",
|
||||||
|
"Referer": referer,
|
||||||
|
}).SetBody(chunkData).Post(u)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -6,7 +6,6 @@ import (
|
|||||||
"github.com/alist-org/alist/v3/internal/driver"
|
"github.com/alist-org/alist/v3/internal/driver"
|
||||||
"github.com/alist-org/alist/v3/internal/errs"
|
"github.com/alist-org/alist/v3/internal/errs"
|
||||||
"github.com/alist-org/alist/v3/internal/model"
|
"github.com/alist-org/alist/v3/internal/model"
|
||||||
"github.com/alist-org/alist/v3/pkg/utils"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type Template struct {
|
type Template struct {
|
||||||
@ -19,18 +18,13 @@ func (d *Template) Config() driver.Config {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (d *Template) GetAddition() driver.Additional {
|
func (d *Template) GetAddition() driver.Additional {
|
||||||
return d.Addition
|
return &d.Addition
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *Template) Init(ctx context.Context, storage model.Storage) error {
|
func (d *Template) Init(ctx context.Context) error {
|
||||||
d.Storage = storage
|
|
||||||
err := utils.Json.UnmarshalFromString(d.Storage.Addition, &d.Addition)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
// TODO login / refresh token
|
// TODO login / refresh token
|
||||||
//op.MustSaveDriverStorage(d)
|
//op.MustSaveDriverStorage(d)
|
||||||
return err
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *Template) Drop(ctx context.Context) error {
|
func (d *Template) Drop(ctx context.Context) error {
|
||||||
@ -42,11 +36,6 @@ func (d *Template) List(ctx context.Context, dir model.Obj, args model.ListArgs)
|
|||||||
return nil, errs.NotImplement
|
return nil, errs.NotImplement
|
||||||
}
|
}
|
||||||
|
|
||||||
//func (d *Template) Get(ctx context.Context, path string) (model.Obj, error) {
|
|
||||||
// // this is optional
|
|
||||||
// return nil, errs.NotImplement
|
|
||||||
//}
|
|
||||||
|
|
||||||
func (d *Template) Link(ctx context.Context, file model.Obj, args model.LinkArgs) (*model.Link, error) {
|
func (d *Template) Link(ctx context.Context, file model.Obj, args model.LinkArgs) (*model.Link, error) {
|
||||||
// TODO return link of file
|
// TODO return link of file
|
||||||
return nil, errs.NotImplement
|
return nil, errs.NotImplement
|
||||||
|
@ -25,7 +25,7 @@ var config = driver.Config{
|
|||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
op.RegisterDriver(config, func() driver.Driver {
|
op.RegisterDriver(func() driver.Driver {
|
||||||
return &Template{}
|
return &Template{}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
214
drivers/terabox/driver.go
Normal file
214
drivers/terabox/driver.go
Normal file
@ -0,0 +1,214 @@
|
|||||||
|
package terbox
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"context"
|
||||||
|
"crypto/md5"
|
||||||
|
"encoding/hex"
|
||||||
|
"fmt"
|
||||||
|
"github.com/alist-org/alist/v3/drivers/base"
|
||||||
|
"github.com/alist-org/alist/v3/pkg/utils"
|
||||||
|
log "github.com/sirupsen/logrus"
|
||||||
|
"io"
|
||||||
|
"math"
|
||||||
|
"net/http"
|
||||||
|
"os"
|
||||||
|
stdpath "path"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/alist-org/alist/v3/internal/driver"
|
||||||
|
"github.com/alist-org/alist/v3/internal/model"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Terabox struct {
|
||||||
|
model.Storage
|
||||||
|
Addition
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *Terabox) Config() driver.Config {
|
||||||
|
return config
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *Terabox) GetAddition() driver.Additional {
|
||||||
|
return &d.Addition
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *Terabox) Init(ctx context.Context) error {
|
||||||
|
_, err := d.request("https://www.terabox.com/api/check/login", http.MethodGet, nil, nil)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *Terabox) Drop(ctx context.Context) error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *Terabox) List(ctx context.Context, dir model.Obj, args model.ListArgs) ([]model.Obj, error) {
|
||||||
|
files, err := d.getFiles(dir.GetPath())
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return utils.SliceConvert(files, func(src File) (model.Obj, error) {
|
||||||
|
return fileToObj(src), nil
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *Terabox) Link(ctx context.Context, file model.Obj, args model.LinkArgs) (*model.Link, error) {
|
||||||
|
if d.DownloadAPI == "crack" {
|
||||||
|
return d.linkCrack(file, args)
|
||||||
|
}
|
||||||
|
return d.linkOfficial(file, args)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *Terabox) MakeDir(ctx context.Context, parentDir model.Obj, dirName string) error {
|
||||||
|
_, err := d.create(stdpath.Join(parentDir.GetPath(), dirName), 0, 1, "", "")
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *Terabox) Move(ctx context.Context, srcObj, dstDir model.Obj) error {
|
||||||
|
data := []base.Json{
|
||||||
|
{
|
||||||
|
"path": srcObj.GetPath(),
|
||||||
|
"dest": dstDir.GetPath(),
|
||||||
|
"newname": srcObj.GetName(),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
_, err := d.manage("move", data)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *Terabox) Rename(ctx context.Context, srcObj model.Obj, newName string) error {
|
||||||
|
data := []base.Json{
|
||||||
|
{
|
||||||
|
"path": srcObj.GetPath(),
|
||||||
|
"newname": newName,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
_, err := d.manage("rename", data)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *Terabox) Copy(ctx context.Context, srcObj, dstDir model.Obj) error {
|
||||||
|
data := []base.Json{
|
||||||
|
{
|
||||||
|
"path": srcObj.GetPath(),
|
||||||
|
"dest": dstDir.GetPath(),
|
||||||
|
"newname": srcObj.GetName(),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
_, err := d.manage("copy", data)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *Terabox) Remove(ctx context.Context, obj model.Obj) error {
|
||||||
|
data := []string{obj.GetPath()}
|
||||||
|
_, err := d.manage("delete", data)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *Terabox) Put(ctx context.Context, dstDir model.Obj, stream model.FileStreamer, up driver.UpdateProgress) error {
|
||||||
|
tempFile, err := utils.CreateTempFile(stream.GetReadCloser())
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer func() {
|
||||||
|
_ = tempFile.Close()
|
||||||
|
_ = os.Remove(tempFile.Name())
|
||||||
|
}()
|
||||||
|
var Default int64 = 4 * 1024 * 1024
|
||||||
|
defaultByteData := make([]byte, Default)
|
||||||
|
count := int(math.Ceil(float64(stream.GetSize()) / float64(Default)))
|
||||||
|
// cal md5
|
||||||
|
h1 := md5.New()
|
||||||
|
h2 := md5.New()
|
||||||
|
block_list := make([]string, 0)
|
||||||
|
left := stream.GetSize()
|
||||||
|
for i := 0; i < count; i++ {
|
||||||
|
byteSize := Default
|
||||||
|
var byteData []byte
|
||||||
|
if left < Default {
|
||||||
|
byteSize = left
|
||||||
|
byteData = make([]byte, byteSize)
|
||||||
|
} else {
|
||||||
|
byteData = defaultByteData
|
||||||
|
}
|
||||||
|
left -= byteSize
|
||||||
|
_, err = io.ReadFull(tempFile, byteData)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
h1.Write(byteData)
|
||||||
|
h2.Write(byteData)
|
||||||
|
block_list = append(block_list, fmt.Sprintf("\"%s\"", hex.EncodeToString(h2.Sum(nil))))
|
||||||
|
h2.Reset()
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = tempFile.Seek(0, io.SeekStart)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
rawPath := stdpath.Join(dstDir.GetPath(), stream.GetName())
|
||||||
|
path := encodeURIComponent(rawPath)
|
||||||
|
block_list_str := fmt.Sprintf("[%s]", strings.Join(block_list, ","))
|
||||||
|
data := fmt.Sprintf("path=%s&size=%d&isdir=0&autoinit=1&block_list=%s",
|
||||||
|
path, stream.GetSize(),
|
||||||
|
block_list_str)
|
||||||
|
params := map[string]string{}
|
||||||
|
var precreateResp PrecreateResp
|
||||||
|
_, err = d.post("/api/precreate", params, data, &precreateResp)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
log.Debugf("%+v", precreateResp)
|
||||||
|
if precreateResp.ReturnType == 2 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
params = map[string]string{
|
||||||
|
"method": "upload",
|
||||||
|
"path": path,
|
||||||
|
"uploadid": precreateResp.Uploadid,
|
||||||
|
"app_id": "250528",
|
||||||
|
"web": "1",
|
||||||
|
"channel": "dubox",
|
||||||
|
"clienttype": "0",
|
||||||
|
}
|
||||||
|
left = stream.GetSize()
|
||||||
|
for i, partseq := range precreateResp.BlockList {
|
||||||
|
if utils.IsCanceled(ctx) {
|
||||||
|
return ctx.Err()
|
||||||
|
}
|
||||||
|
byteSize := Default
|
||||||
|
var byteData []byte
|
||||||
|
if left < Default {
|
||||||
|
byteSize = left
|
||||||
|
byteData = make([]byte, byteSize)
|
||||||
|
} else {
|
||||||
|
byteData = defaultByteData
|
||||||
|
}
|
||||||
|
left -= byteSize
|
||||||
|
_, err = io.ReadFull(tempFile, byteData)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
u := "https://c-jp.terabox.com/rest/2.0/pcs/superfile2"
|
||||||
|
params["partseq"] = strconv.Itoa(partseq)
|
||||||
|
res, err := base.RestyClient.R().
|
||||||
|
SetContext(ctx).
|
||||||
|
SetQueryParams(params).
|
||||||
|
SetFileReader("file", stream.GetName(), bytes.NewReader(byteData)).
|
||||||
|
SetHeader("Cookie", d.Cookie).
|
||||||
|
Post(u)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
log.Debugln(res.String())
|
||||||
|
if len(precreateResp.BlockList) > 0 {
|
||||||
|
up(i * 100 / len(precreateResp.BlockList))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_, err = d.create(rawPath, stream.GetSize(), 0, precreateResp.Uploadid, block_list_str)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
var _ driver.Driver = (*Terabox)(nil)
|
25
drivers/terabox/meta.go
Normal file
25
drivers/terabox/meta.go
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
package terbox
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/alist-org/alist/v3/internal/driver"
|
||||||
|
"github.com/alist-org/alist/v3/internal/op"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Addition struct {
|
||||||
|
driver.RootPath
|
||||||
|
Cookie string `json:"cookie" required:"true"`
|
||||||
|
DownloadAPI string `json:"download_api" type:"select" options:"official,crack" default:"official"`
|
||||||
|
OrderBy string `json:"order_by" type:"select" options:"name,time,size" default:"name"`
|
||||||
|
OrderDirection string `json:"order_direction" type:"select" options:"asc,desc" default:"asc"`
|
||||||
|
}
|
||||||
|
|
||||||
|
var config = driver.Config{
|
||||||
|
Name: "Terabox",
|
||||||
|
DefaultRoot: "/",
|
||||||
|
}
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
op.RegisterDriver(func() driver.Driver {
|
||||||
|
return &Terabox{}
|
||||||
|
})
|
||||||
|
}
|
92
drivers/terabox/types.go
Normal file
92
drivers/terabox/types.go
Normal file
@ -0,0 +1,92 @@
|
|||||||
|
package terbox
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/alist-org/alist/v3/internal/model"
|
||||||
|
"strconv"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
type File struct {
|
||||||
|
//TkbindId int `json:"tkbind_id"`
|
||||||
|
//OwnerType int `json:"owner_type"`
|
||||||
|
//Category int `json:"category"`
|
||||||
|
//RealCategory string `json:"real_category"`
|
||||||
|
FsId int64 `json:"fs_id"`
|
||||||
|
ServerMtime int64 `json:"server_mtime"`
|
||||||
|
//OperId int `json:"oper_id"`
|
||||||
|
//ServerCtime int `json:"server_ctime"`
|
||||||
|
Thumbs struct {
|
||||||
|
//Icon string `json:"icon"`
|
||||||
|
Url3 string `json:"url3"`
|
||||||
|
//Url2 string `json:"url2"`
|
||||||
|
//Url1 string `json:"url1"`
|
||||||
|
} `json:"thumbs"`
|
||||||
|
//Wpfile int `json:"wpfile"`
|
||||||
|
//LocalMtime int `json:"local_mtime"`
|
||||||
|
Size int64 `json:"size"`
|
||||||
|
//ExtentTinyint7 int `json:"extent_tinyint7"`
|
||||||
|
Path string `json:"path"`
|
||||||
|
//Share int `json:"share"`
|
||||||
|
//ServerAtime int `json:"server_atime"`
|
||||||
|
//Pl int `json:"pl"`
|
||||||
|
//LocalCtime int `json:"local_ctime"`
|
||||||
|
ServerFilename string `json:"server_filename"`
|
||||||
|
//Md5 string `json:"md5"`
|
||||||
|
//OwnerId int `json:"owner_id"`
|
||||||
|
//Unlist int `json:"unlist"`
|
||||||
|
Isdir int `json:"isdir"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type ListResp struct {
|
||||||
|
Errno int `json:"errno"`
|
||||||
|
GuidInfo string `json:"guid_info"`
|
||||||
|
List []File `json:"list"`
|
||||||
|
RequestId int64 `json:"request_id"`
|
||||||
|
Guid int `json:"guid"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func fileToObj(f File) *model.ObjThumb {
|
||||||
|
return &model.ObjThumb{
|
||||||
|
Object: model.Object{
|
||||||
|
ID: strconv.FormatInt(f.FsId, 10),
|
||||||
|
Name: f.ServerFilename,
|
||||||
|
Size: f.Size,
|
||||||
|
Modified: time.Unix(f.ServerMtime, 0),
|
||||||
|
IsFolder: f.Isdir == 1,
|
||||||
|
},
|
||||||
|
Thumbnail: model.Thumbnail{Thumbnail: f.Thumbs.Url3},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type DownloadResp struct {
|
||||||
|
Errno int `json:"errno"`
|
||||||
|
Dlink []struct {
|
||||||
|
Dlink string `json:"dlink"`
|
||||||
|
} `json:"dlink"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type DownloadResp2 struct {
|
||||||
|
Errno int `json:"errno"`
|
||||||
|
Info []struct {
|
||||||
|
Dlink string `json:"dlink"`
|
||||||
|
} `json:"info"`
|
||||||
|
RequestID int64 `json:"request_id"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type HomeInfoResp struct {
|
||||||
|
Errno int `json:"errno"`
|
||||||
|
Data struct {
|
||||||
|
Sign1 string `json:"sign1"`
|
||||||
|
Sign3 string `json:"sign3"`
|
||||||
|
Timestamp int `json:"timestamp"`
|
||||||
|
} `json:"data"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type PrecreateResp struct {
|
||||||
|
Path string `json:"path"`
|
||||||
|
Uploadid string `json:"uploadid"`
|
||||||
|
ReturnType int `json:"return_type"`
|
||||||
|
BlockList []int `json:"block_list"`
|
||||||
|
Errno int `json:"errno"`
|
||||||
|
RequestId int64 `json:"request_id"`
|
||||||
|
}
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user