Compare commits

...

107 Commits

Author SHA1 Message Date
16e07ae016 fix(s3): set default root path (close #2834) 2022-12-30 14:53:01 +08:00
d1b9db38c7 feat(docker): add docker-compose file (close #2067) 2022-12-30 14:25:22 +08:00
395f0fc5f3 fix(docker): use root user as default 2022-12-30 14:21:39 +08:00
143e4cd077 fix: mysql FULLTEXT search (#2840) 2022-12-30 14:20:04 +08:00
f777a2fab4 fix: version doesn't update 2022-12-30 01:24:37 +08:00
dad3012ec3 fix(deps): update module github.com/aws/aws-sdk-go to v1.44.169 (#2816)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2022-12-29 21:22:50 +08:00
d45209edb2 fix: /entrypoint.sh permission denied 2022-12-29 17:16:30 +08:00
e89489453d fix: cache nil value for meta 2022-12-28 17:44:34 +08:00
ed6c8194a7 feat: add PUID, PGID, Umask settings to docker image (close #2525 pr #2818)
Co-authored-by: DDSRem <1448139087@qq.com>
2022-12-28 17:18:27 +08:00
83fe17c6ec feat: support github login (#2639)
* Support Github Login

* improve according to codefactor

* fix due to last updates

* optimization

Co-authored-by: Noah Hsu <i@nn.ci>
2022-12-27 22:11:22 +08:00
c00dcc8f39 fix(deps): update module github.com/gin-gonic/gin to v1.8.2 (#2785)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2022-12-25 18:20:24 +08:00
e118f4a3b9 feat: update index by req.Paths 2022-12-24 20:23:04 +08:00
5e28d0f96a fix(deps): update module github.com/aws/aws-sdk-go to v1.44.167 (#2781)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2022-12-24 16:14:20 +08:00
3af23f6792 feat: batch reload all storages (close #2762 pr #2775) 2022-12-21 19:21:18 +08:00
3a41b929c9 fix: pgsql search [skip ci] (close #2761 pr #2774) 2022-12-21 19:19:37 +08:00
105f22969c feat: support cancel for some drivers (close #2717) 2022-12-21 15:03:09 +08:00
e4a88a7c13 fix(deps): update module github.com/aws/aws-sdk-go to v1.44.164 (#2773)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2022-12-21 12:04:32 +08:00
b0255040c6 chore: fix typo 2022-12-20 20:07:19 +08:00
f1e842e12a feat: customize settings layout (close #2765) 2022-12-20 20:04:37 +08:00
d756cf3e9f fix(local): disable copying or moving to subfolders (close #2760) 2022-12-20 16:27:04 +08:00
146619134d feat: customize proxy ignore headers (close #2763 pr #2766)
* clean referer when use proxy

* feat: customize proxy ignore headers

Co-authored-by: Noah Hsu <i@nn.ci>
2022-12-20 16:08:32 +08:00
372030071e fix(deps): update module github.com/aws/aws-sdk-go to v1.44.163 [skip ci] (#2738)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2022-12-20 15:13:14 +08:00
62a06fa0f9 feat: optimize file operation interface (#2757)
* feat: optimize file operation interface

* chore: fix typo

Co-authored-by: Noah Hsu <i@nn.ci>
2022-12-20 15:02:40 +08:00
e2bcca2fbd feat: static files for embed viewers (#2739) 2022-12-19 13:34:06 +08:00
4568af9542 feat: better static file Cache-Control (#2751) 2022-12-19 13:32:00 +08:00
b50d486a63 fix: sub path check if subPath = / 2022-12-18 21:28:38 +08:00
0ae3fc608b feat: export all cmd (#2746) 2022-12-18 19:53:39 +08:00
6024e8d832 refactor: split the db package hook and cache to the op package (#2747)
* refactor:separate the setting method from the db package to the op package and add the cache

* refactor:separate the meta method from the db package to the op package

* fix:setting not load database data

* refactor:separate the user method from the db package to the op package

* refactor:remove user JoinPath error

* fix:op package user cache

* refactor:fs package list method

* fix:tile virtual paths (close #2743)

* Revert "refactor:remove user JoinPath error"

This reverts commit 4e20daaf9e700da047000d4fd4900abbe05c3848.

* clean path directly may lead to unknown behavior

* fix: The path of the meta passed in must be prefix of reqPath

* chore: rename all virtualPath to mountPath

* fix: `getStoragesByPath` and `GetStorageVirtualFilesByPath`

is_sub_path:

/a/b isn't subpath of /a/bc

* fix: don't save setting if hook error

Co-authored-by: Noah Hsu <i@nn.ci>
2022-12-18 19:51:20 +08:00
f38f4f401b fix(139): modify chunk size to avoid large file upload failure (close #2744 close #2682 pr #2745) 2022-12-18 17:48:09 +08:00
3b2ae85009 chore: only ignore root dirs (#2741) 2022-12-18 16:48:32 +08:00
faf4150d1e docs: fix badges on README.md and README_cn.md [skip ci] (#2749) 2022-12-18 16:48:03 +08:00
fb64f00640 refactor: obj name mapping and internal path processing (#2733)
* refactor:Prepare to remove the get interface

* feat:add obj Unwarp interface

* refactor:obj name mapping and program internal path processing

* chore: fix typo

* feat: unwrap get

* fix: no use op.Get to get parent id

* fix: set the path uniformly

Co-authored-by: Noah Hsu <i@nn.ci>
2022-12-17 19:49:05 +08:00
3d336b328a feat: add pikpak share driver (close #2728 pr #2731) 2022-12-16 19:10:19 +08:00
f9cf29e0b6 fix(deps): update module golang.org/x/crypto to v0.4.0 (#2638) [skip ci]
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2022-12-16 19:08:52 +08:00
cbd038f30f fix(deps): update module golang.org/x/net to v0.4.0 (#2608) [skip ci]
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2022-12-16 19:05:20 +08:00
2aeb75a779 fix(deps): update module github.com/blevesearch/bleve/v2 to v2.3.6 (#2727) [skip ci]
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2022-12-16 19:05:06 +08:00
2f8eaf6bea fix(deps): update module github.com/pquerna/otp to v1.4.0 (#2708) [skip ci]
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2022-12-16 18:15:59 +08:00
fb7a5dec1b fix(deps): update module golang.org/x/image to v0.2.0 (#2601) [skip ci]
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2022-12-16 18:15:19 +08:00
e61bac039a fix(deps): update module github.com/aws/aws-sdk-go to v1.44.161 (#2595) [skip ci]
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2022-12-16 18:14:56 +08:00
b3be9ef428 feat(search): use FULLTEXT index (close #2716 pr #2726) 2022-12-16 16:51:36 +08:00
5a6b600ace feat: show gorm log on debug/dev mode (#2720) 2022-12-15 17:48:52 +08:00
e58ca686e3 feat: cache static files (#2715) 2022-12-15 17:48:29 +08:00
6f4b1ba4b3 feat: log to stdout & file (#2709) 2022-12-14 13:19:08 +08:00
cdc45630ae fix: whereInParent when parent = "/" (#2706) 2022-12-14 10:37:09 +08:00
7947ff1ae4 feat: limit max connection count (#2701) 2022-12-14 10:33:58 +08:00
33bae52fa1 refactor: optimize driver initialization need to manually deserialize and assign values, and remove redundant driver registration parameters (#2691)
* refactor: optimize driver initialization need to manually deserialize and assign values, and remove redundant driver registration parameters

* fix typo

Co-authored-by: Noah Hsu <i@nn.ci>
2022-12-13 18:03:30 +08:00
3ee45c69a7 fix(baidu_netdisk): encode path for create (close #2690) 2022-12-13 17:57:41 +08:00
179d285564 feat: optimize database search (#2687)
* feat: remove index on `SearchNode.Name`

As we do not use s% on name column, index there does not work

* fix: init index after init data

Or on the first run, it will log 'init index error: readObjectStart: expect { or n, but found , error found in #0 byte of ...||..., bigger context ...||...'

* fix: match parent more precisely

It will match `/a/bc` if we search in `/a/b` originally.
But it is not backward compatible by adding a suffix `/`
to all the data in parent field
2022-12-12 20:20:01 +08:00
a2e8e96c71 feat: respond static file on loading storages (#2686) 2022-12-12 20:17:58 +08:00
5043815d48 fix(search): don't delete virtual folder while update indexes (close #2677) 2022-12-11 14:59:58 +08:00
1640f06e13 feat(search): multiple keywords split by space (#2669) 2022-12-10 19:28:34 +08:00
62ea93837c feat: alist v3 index permission (#2653)
* feat: alist v3 index permission

* fix allowIndexed check

Co-authored-by: Noah Hsu <i@nn.ci>
2022-12-10 19:03:09 +08:00
446f82888c fix(local): add sign to thumbnail (close #2536 close #2650) 2022-12-09 10:08:31 +08:00
6f1aeb47fd feat: index enhancement (close #2632 pr #2636)
* feat: index paths as setting

* feat: clear index (#2632)

* feat: check indexMQ more frequently
2022-12-09 10:02:13 +08:00
1f7c1b4f43 fix(cors): allow all methods (close #2640) 2022-12-08 11:35:21 +08:00
3fa0217c4b feat(alist-v3): support write (close #2626 pr #2635) 2022-12-07 19:02:28 +08:00
2dd30f2b77 feat(search): support with password 2022-12-07 10:45:02 +08:00
6e23c8b4c0 feat: partial update index (close #2593 close #2621 pr #2624) 2022-12-07 10:41:52 +08:00
72aa63adce fix: skip virtual driver on building index (close #2604 pr #2617) 2022-12-06 20:43:32 +08:00
e65e8be59e fix(search): missed base_path of user for parent (close #2611) 2022-12-06 17:28:39 +08:00
7aa4dfb240 feat: use natural sort in SortFiles (#2612) 2022-12-06 17:28:18 +08:00
bd324233a0 fix: can't paste image while report bug (#2597) [skip ci] 2022-12-06 09:19:49 +08:00
f1a9b68022 fix(index): update indexes in database 2022-12-05 20:23:37 +08:00
dda1da4576 fix(index): nil pointer call 2022-12-05 20:22:35 +08:00
5b7aa9c1cf feat: allow all cors headers (close #2571) 2022-12-05 20:05:20 +08:00
a28aaceaad chore(ci): only build on main branch 2022-12-05 19:52:02 +08:00
2bb200af87 fix(deps): update modules by renovate[bot]
fix(deps): update module github.com/sheltonzhu/115driver to v1.0.13 (#2413) [skip ci]

fix(deps): update module github.com/golang-jwt/jwt/v4 to v4.4.3 (#2526) [skip ci]

fix(deps): update module golang.org/x/image to v0.1.0 (#2587) [skip ci]

chore: go mod tidy
Co-Authored-By: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2022-12-05 19:50:49 +08:00
97f1efbb72 feat!: disable --force-bin-dir if --data is abs
related issues: #2580 #2542

after this commit, the `--force-bin-dir` would take no effect if `--data` is absolute path
2022-12-05 18:32:48 +08:00
bf8b6f4c2c feat: customize ignore paths of indexes 2022-12-05 16:45:11 +08:00
bd33c200dc feat: optimize index build 2022-12-05 16:07:36 +08:00
bc6baf1be0 fix(ci): sort lang json file 2022-12-05 14:40:46 +08:00
dc8d5106f9 feat: auto fix address in alist & smb storages (#2582) 2022-12-05 13:31:34 +08:00
8c0dfe2f3d feat: Search enhancement (#2562)
* feat: ignore AList storage on indexing

* fix: remove unused err in `walkFn`

* chore(ci): fix auto_lang trigger and run it

* feat: batch index

* feat: quit index & init index

* feat: set DocType for bleve data

* fix: build index cleanup check origin err
2022-12-05 13:28:39 +08:00
4e1be9bee6 fix: async init aria2 to optimize start duration 2022-12-04 00:00:40 +08:00
4c5285e094 chore(ci): format lang file (#2558) 2022-12-03 12:19:10 +08:00
0838feeb82 fix:introduce buffered response writer for webdav, fix status/error return failed. (#2544)
* fix: introduce buffered response writer for webdav, fix webdav status/error return failed.

* fix: bypass buffered writer for GET/HEAD/POST requests
2022-12-02 17:59:59 +08:00
ae791c8634 fix: hide check in canAccess (#2556)
修复 meta.Password 和 meta.Hide 都为空的情况下,会导致无权限访问
2022-12-02 17:44:29 +08:00
09f480318c fix: unify settings string (#2555) 2022-12-02 17:42:42 +08:00
4c5be5f07f feat: only show CanAccess search results (#2548)
* feat: only show `CanAccess` search results

* have done in frontend

Co-authored-by: Noah Hsu <i@nn.ci>
2022-12-02 10:09:39 +08:00
9c1ffdbb82 fix(aliyundrive): return error if got wrong http code (#2543) 2022-12-01 21:48:19 +08:00
18a63e34dd fix(task): memory alignment for curID (close #2541) 2022-12-01 13:16:31 +08:00
ff0bcfef8a feat: optional sign all files 2022-11-30 22:10:07 +08:00
4980b71ba3 fix: add hide check to canAccess (close #2532) 2022-11-30 22:01:33 +08:00
b5bf5f4325 fix: check if the req path is relative path (close #2531) 2022-11-30 21:38:00 +08:00
f9788ea7cf feat(webdav): delete privacy header and optimize 302 (#2534)
* fix: delete set-cookie from sharepoint webdav response header

* fix: avoid two redirects when using webdav

* fix: return the correct Content-Type instead of just `application/octet-stream`

* feat: webdav backend localOnly -> proxyOnly
2022-11-30 20:52:33 +08:00
83644dab85 fix: mapping filename in GetName
some missed filename mapping
2022-11-30 20:46:54 +08:00
d94cf72da2 fix(local): webp image decode while generate thumbnail (close #2484 pr #2520)
* Fix that webp thumb  in local storage won't load

* Simplify code

Co-authored-by: Noah Hsu <i@nn.ci>
2022-11-29 09:47:40 +08:00
e98561ceb1 fix: filename char mapping while build index 2022-11-28 21:08:11 +08:00
76f37373e0 fix: settings map read and write concurrently 2022-11-28 16:54:03 +08:00
61a06992c3 fix(aria2): directory missing (close #1856 pr #2504) 2022-11-28 14:05:28 +08:00
ddcba93eea feat: multiple search indexes (#2514)
* refactor: abstract search interface

* wip: ~

* fix cycle import

* objs update hook

* wip: ~

* Delete search/none

* auto update index while cache changed

* db searcher

TODO: bleve init issue

cannot open index, metadata missing

* fix size type

why float64??

* fix typo

* fix nil pointer using

* api adapt ui

* bleve: fix clear & change struct
2022-11-28 13:45:25 +08:00
bb969d8dc6 fix(aliyundrive_share): get share link download url directly (close #2472) 2022-11-24 18:50:04 +08:00
2383e851e2 fix: reset index before build new one (#2471) 2022-11-24 14:47:49 +08:00
330a767fd7 feat: build index & search with bleve (close #1740 pr #2386)
* feat: build index & search with bleve (#1740)

* delete unused struct

Co-authored-by: Noah Hsu <i@nn.ci>
2022-11-24 11:46:47 +08:00
2b902de6fd fix(build): switch to crazymax/xgo 2022-11-22 21:08:27 +08:00
85e1350af8 fix: check password while upload (close #2444) 2022-11-22 16:14:01 +08:00
c09800790b feat: custom filename char mapping
fixes #2447 #2446 #2440 #2409 #2006 #1979 #1507 #324 #691 #518 #430
2022-11-22 15:54:18 +08:00
25fd343069 chore(deps): update module gorm and aws-sdk
fix(deps): update module gorm.io/gorm to v1.24.2 (#2436)

fix(deps): update module github.com/aws/aws-sdk-go to v1.44.142 (#2407)

Co-Authored-By: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2022-11-21 17:37:03 +08:00
518487e3df fix(123): optimize error messages (#2415) 2022-11-19 21:48:03 +08:00
a02d9c8463 fix: check error type on file not found (#2383) 2022-11-18 01:30:37 +08:00
8beeba7c0c fix(google_drive): check token before return link (close #2392) 2022-11-17 09:08:31 +08:00
50fb49f0c3 fix(deps): update dependencies by renovate[bot] (#2344)
chore(deps): add renovate.json (#2344)

fix(deps): update module github.com/aws/aws-sdk-go to v1.44.137 (#2345)

chore(deps): update actions-cool/issues-helper action to v2.5.0 (#2346)

fix(deps): update module github.com/caarlos0/env/v6 to v6.10.1 (#2348)

fix(deps): update module github.com/gin-contrib/cors to v1.4.0 (#2349)

fix(deps): update module github.com/sirupsen/logrus to v1.9.0 (#2354) [skip ci]

fix(deps): update module gorm.io/driver/postgres to v1.4.5 (#2361)  [skip ci]

fix(deps): update module golang.org/x/crypto to v0.2.0 (#2357) [skip ci]

fix(deps): update module github.com/aws/aws-sdk-go to v1.44.138 (#2358) [skip ci]

fix(deps): update module gorm.io/gorm to v1.24.1 (#2366) [skip ci]

fix(deps): update module gorm.io/driver/mysql to v1.4.4 (#2360) [skip ci]

fix(deps): update module github.com/spf13/cobra to v1.6.1 (#2356) [skip ci]

chore(deps): update actions-cool/issues-helper action to v3 (#2367) [skip ci]

fix(deps): update module gorm.io/driver/sqlite to v1.4.3 (#2365) [skip ci]

chore(deps): update actions/checkout action to v3 (#2368) [skip ci]

chore(deps): update actions/setup-go action to v3 (#2374) [skip ci]

chore(deps): update actions/upload-artifact action to v3 (#2375) [skip ci]

chore(deps): update docker/build-push-action action to v3 (#2377) [skip ci]

chore(deps): update docker/login-action action to v2 (#2378) [skip ci]

chore(deps): update docker/metadata-action action to v4 (#2381) [skip ci]

chore(deps): update docker/setup-buildx-action action to v2 (#2382) [skip ci]

chore(deps): update docker/setup-qemu-action action to v2 (#2387) [skip ci]

fix(deps): update module github.com/aws/aws-sdk-go to v1.44.139 (#2394) [skip ci]

fix(deps): update module golang.org/x/crypto to v0.3.0 (#2395) [skip ci]

Co-Authored-By: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2022-11-17 08:49:15 +08:00
4dcaa24758 fix: cache is modified while sorting (close #2340) 2022-11-15 14:38:23 +08:00
3fbdf6f022 fix: resolve import cycle in alist v3 driver (close #2337 pr #2338) 2022-11-15 10:51:32 +08:00
aa9ba289bb fix(123): overwrite upload if file has no change (close #2324) 2022-11-14 17:58:49 +08:00
3b6d8987db chore: add id to resp of create storage 2022-11-13 20:17:10 +08:00
6e3df9f847 fix(google_drive): type of chunk_size (close #2303) 2022-11-12 18:46:38 +08:00
213 changed files with 4602 additions and 1943 deletions

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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 }}

View File

@ -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 }}

View File

@ -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 }}

View File

@ -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 }}

View File

@ -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

View File

@ -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
View File

@ -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

View File

@ -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" ]

View File

@ -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" />

View File

@ -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" />

View File

@ -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.

View File

@ -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.

View File

@ -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

View File

@ -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.

View File

@ -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.

View File

@ -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")
} }

View File

@ -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)
} }

View File

@ -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.

View File

@ -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.

View File

@ -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
View 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'

View File

@ -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()
} }

View File

@ -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{}
})
} }

View File

@ -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
} }

View File

@ -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{}
})
} }

View File

@ -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"`
} }

View File

@ -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()

View File

@ -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()),

View File

@ -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{}
}) })
} }

View File

@ -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)

View File

@ -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{}
}) })
} }

View File

@ -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()

View File

@ -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)
} }

View File

@ -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{}
}) })
} }

View File

@ -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

View File

@ -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]

View File

@ -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{}
}) })
} }

View File

@ -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) {

View File

@ -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{}
}) })
} }

View File

@ -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"`
}

View File

@ -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)
}

View File

@ -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

View File

@ -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{}
})
} }

View File

@ -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
} }

View File

@ -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)

View File

@ -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{}
}) })
} }

View File

@ -21,6 +21,7 @@ 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"

View File

@ -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)
@ -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
} }

View File

@ -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{}
})
} }

View File

@ -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)
} }

View File

@ -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)

View File

@ -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{}
}) })
} }

View File

@ -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)

View File

@ -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)
} }

View File

@ -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{}
})
} }

View File

@ -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 {

View File

@ -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{}
})
} }

View File

@ -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

View File

@ -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 {

View File

@ -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{}
})
} }

View File

@ -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
} }

View File

@ -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{}
}) })
} }

View File

@ -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)

View File

@ -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{}
})
} }

View File

@ -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
} }

View File

@ -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{}
}) })
} }

View File

@ -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
}

View File

@ -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

View File

@ -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{}
}) })
} }

View File

@ -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)
} }

View File

@ -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{}
})
} }

View File

@ -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},
} }
} }

View File

@ -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

View File

@ -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
} }

View File

@ -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{}
})
} }

View 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)

View 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{}
})
}

View 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"`
}

View 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
}

View File

@ -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

View File

@ -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{}
})
} }

View File

@ -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,

View File

@ -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
} }

View File

@ -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{}
})
} }

View File

@ -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 {

View File

@ -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{}
})
} }

View File

@ -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

View File

@ -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{}
}) })
} }

View File

@ -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

View File

@ -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{}
})
} }

View File

@ -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
} }

View File

@ -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

View File

@ -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{}
}) })
} }

View File

@ -32,15 +32,10 @@ func (x *Thunder) Config() driver.Config {
} }
func (x *Thunder) GetAddition() driver.Additional { func (x *Thunder) GetAddition() driver.Additional {
return x.Addition return &x.Addition
} }
func (x *Thunder) Init(ctx context.Context, storage model.Storage) (err error) { func (x *Thunder) Init(ctx context.Context) (err error) {
x.Storage = storage
if err = utils.Json.UnmarshalFromString(x.Storage.Addition, &x.Addition); err != nil {
return err
}
// 初始化所需参数 // 初始化所需参数
if x.XunLeiCommon == nil { if x.XunLeiCommon == nil {
x.XunLeiCommon = &XunLeiCommon{ x.XunLeiCommon = &XunLeiCommon{
@ -126,15 +121,10 @@ func (x *ThunderExpert) Config() driver.Config {
} }
func (x *ThunderExpert) GetAddition() driver.Additional { func (x *ThunderExpert) GetAddition() driver.Additional {
return x.ExpertAddition return &x.ExpertAddition
} }
func (x *ThunderExpert) Init(ctx context.Context, storage model.Storage) (err error) { func (x *ThunderExpert) Init(ctx context.Context) (err error) {
x.Storage = storage
if err = utils.Json.UnmarshalFromString(x.Storage.Addition, &x.ExpertAddition); err != nil {
return err
}
// 防止重复登录 // 防止重复登录
identity := x.GetIdentity() identity := x.GetIdentity()
if identity != x.identity || !x.IsLogin() { if identity != x.identity || !x.IsLogin() {

View File

@ -93,10 +93,10 @@ var configExpert = driver.Config{
} }
func init() { func init() {
op.RegisterDriver(config, func() driver.Driver { op.RegisterDriver(func() driver.Driver {
return &Thunder{} return &Thunder{}
}) })
op.RegisterDriver(configExpert, func() driver.Driver { op.RegisterDriver(func() driver.Driver {
return &ThunderExpert{} return &ThunderExpert{}
}) })
} }

View File

@ -25,15 +25,10 @@ func (d *USS) Config() driver.Config {
} }
func (d *USS) GetAddition() driver.Additional { func (d *USS) GetAddition() driver.Additional {
return d.Addition return &d.Addition
} }
func (d *USS) Init(ctx context.Context, storage model.Storage) error { func (d *USS) Init(ctx context.Context) error {
d.Storage = storage
err := utils.Json.UnmarshalFromString(d.Storage.Addition, &d.Addition)
if err != nil {
return err
}
d.client = upyun.NewUpYun(&upyun.UpYunConfig{ d.client = upyun.NewUpYun(&upyun.UpYunConfig{
Bucket: d.Bucket, Bucket: d.Bucket,
Operator: d.OperatorName, Operator: d.OperatorName,
@ -76,11 +71,6 @@ func (d *USS) List(ctx context.Context, dir model.Obj, args model.ListArgs) ([]m
return res, err return res, err
} }
//func (d *USS) Get(ctx context.Context, path string) (model.Obj, error) {
// // this is optional
// return nil, errs.NotImplement
//}
func (d *USS) Link(ctx context.Context, file model.Obj, args model.LinkArgs) (*model.Link, error) { func (d *USS) Link(ctx context.Context, file model.Obj, args model.LinkArgs) (*model.Link, error) {
key := getKey(file.GetPath(), false) key := getKey(file.GetPath(), false)
host := d.CustomHost host := d.CustomHost
@ -133,6 +123,7 @@ func (d *USS) Remove(ctx context.Context, obj model.Obj) error {
} }
func (d *USS) Put(ctx context.Context, dstDir model.Obj, stream model.FileStreamer, up driver.UpdateProgress) error { func (d *USS) Put(ctx context.Context, dstDir model.Obj, stream model.FileStreamer, up driver.UpdateProgress) error {
// TODO not support cancel??
return d.client.Put(&upyun.PutObjectConfig{ return d.client.Put(&upyun.PutObjectConfig{
Path: getKey(path.Join(dstDir.GetPath(), stream.GetName()), false), Path: getKey(path.Join(dstDir.GetPath(), stream.GetName()), false),
Reader: stream, Reader: stream,

Some files were not shown because too many files have changed in this diff Show More