diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
deleted file mode 100644
index 9fecea17..00000000
--- a/.github/workflows/build.yml
+++ /dev/null
@@ -1,50 +0,0 @@
-name: build
-
-on:
- push:
- branches: [ '**' ]
- pull_request:
- branches: [ '**' ]
-
-jobs:
- build:
- strategy:
- matrix:
- platform: [ubuntu-latest]
- go-version: [1.18]
- name: Build
- runs-on: ${{ matrix.platform }}
- steps:
- - name: Setup Go
- uses: actions/setup-go@v2
- with:
- go-version: ${{ matrix.go-version }}
-
- - name: Set up Node
- uses: actions/setup-node@v2
- with:
- node-version: '16'
-
- - name: Checkout
- uses: actions/checkout@v2
- with:
- path: alist
-
- - name: Install dependencies
- run: |
- docker pull techknowlogick/xgo:latest
- go install src.techknowlogick.com/xgo@latest
- sudo apt install upx
-
- - name: Build
- run: |
- mv alist/build.sh .
- bash build.sh web
- mv dist/* alist/public
- bash build.sh build
-
- - name: Upload artifact
- uses: actions/upload-artifact@v2
- with:
- name: artifact
- path: alist/build
\ No newline at end of file
diff --git a/.github/workflows/build_docker.yml b/.github/workflows/build_docker.yml
deleted file mode 100644
index 5b3db5cb..00000000
--- a/.github/workflows/build_docker.yml
+++ /dev/null
@@ -1,44 +0,0 @@
-name: build_docker
-
-on:
- push:
- branches: [ v2 ]
-
-jobs:
- build_docker:
- name: Docker
- runs-on: ubuntu-latest
- steps:
- - name: Checkout
- uses: actions/checkout@v2
- - name: Docker meta
- id: meta
- uses: docker/metadata-action@v3
- with:
- images: xhofe/alist
- - name: Set up Node
- uses: actions/setup-node@v2
- with:
- node-version: '16'
- - name: Build web
- run: |
- bash build.sh web
- mv dist/* public
- - name: Set up QEMU
- uses: docker/setup-qemu-action@v1
- - name: Set up Docker Buildx
- uses: docker/setup-buildx-action@v1
- - name: Login to DockerHub
- uses: docker/login-action@v1
- with:
- username: xhofe
- password: ${{ secrets.DOCKERHUB_TOKEN }}
- - name: Build and push
- id: docker_build
- uses: docker/build-push-action@v2
- with:
- context: .
- push: true
- tags: ${{ steps.meta.outputs.tags }}
- labels: ${{ steps.meta.outputs.labels }}
- platforms: linux/amd64,linux/arm64,linux/arm/v7,linux/386,linux/arm/v6,linux/s390x
\ No newline at end of file
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
deleted file mode 100644
index 4edfa8c1..00000000
--- a/.github/workflows/release.yml
+++ /dev/null
@@ -1,72 +0,0 @@
-name: release
-
-on:
- push:
- tags:
- - '*'
-
-jobs:
- changelog:
- name: Create Release
- runs-on: ubuntu-latest
- steps:
- - name: Checkout code
- uses: actions/checkout@v2
- with:
- fetch-depth: 0
- - name: Changelog
- uses: Bullrich/generate-release-changelog@master
- id: Changelog
- env:
- REPO: ${{ github.repository }}
- - name: Create Release
- id: create_release
- uses: actions/create-release@latest
- env:
- GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # This token is provided by Actions, you do not need to create your own token
- with:
- tag_name: ${{ github.ref }}
- release_name: Release ${{ github.ref }}
- body: |
- ${{ steps.Changelog.outputs.changelog }}
- draft: false
- prerelease: false
- release:
- needs: changelog
- strategy:
- matrix:
- platform: [ubuntu-latest]
- go-version: [1.18]
- name: Release
- runs-on: ${{ matrix.platform }}
- steps:
- - name: Setup Go
- uses: actions/setup-go@v2
- with:
- go-version: ${{ matrix.go-version }}
-
- - name: Checkout
- uses: actions/checkout@v2
- with:
- ref: v2
- path: alist
- persist-credentials: false
- fetch-depth: 0
-
- - name: Install upx
- run: |
- docker pull techknowlogick/xgo:latest
- go install src.techknowlogick.com/xgo@latest
- sudo apt install upx
-
- - name: Build
- run: |
- mv alist/build.sh .
- bash build.sh cdn
- mv dist/* alist/public
- bash build.sh release
-
- - name: Release
- uses: softprops/action-gh-release@v1
- with:
- files: alist/build/compress/*
\ No newline at end of file
diff --git a/.github/workflows/release_docker.yml b/.github/workflows/release_docker.yml
deleted file mode 100644
index 66f8b7e1..00000000
--- a/.github/workflows/release_docker.yml
+++ /dev/null
@@ -1,45 +0,0 @@
-name: release_docker
-
-on:
- push:
- tags:
- - '*'
-
-jobs:
- docker_release:
- name: Docker
- runs-on: ubuntu-latest
- steps:
- - name: Checkout
- uses: actions/checkout@v2
- - name: Docker meta
- id: meta
- uses: docker/metadata-action@v3
- with:
- images: xhofe/alist
- - name: Set up Node
- uses: actions/setup-node@v2
- with:
- node-version: '16'
- - name: Build web
- run: |
- bash build.sh cdn
- mv dist/* public
- - name: Set up QEMU
- uses: docker/setup-qemu-action@v1
- - name: Set up Docker Buildx
- uses: docker/setup-buildx-action@v1
- - name: Login to DockerHub
- uses: docker/login-action@v1
- with:
- username: xhofe
- password: ${{ secrets.DOCKERHUB_TOKEN }}
- - name: Build and push
- id: docker_build
- uses: docker/build-push-action@v2
- with:
- context: .
- push: true
- tags: ${{ steps.meta.outputs.tags }}
- labels: ${{ steps.meta.outputs.labels }}
- platforms: linux/amd64,linux/arm64,linux/arm/v7,linux/386,linux/arm/v6,linux/s390x
\ No newline at end of file
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 55ad7910..fdcc4b13 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -17,12 +17,12 @@ Clone `alist` and `alist-web` anywhere:
$ git clone https://github.com/Xhofe/alist.git
$ git clone https://github.com/Xhofe/alist-web.git
```
-You should switch to the dev branch for development.
+You should switch to the `main` branch for development.
## Preview your change
### backend
```shell
-$ go run alist.go
+$ go run cmd/alist.go
```
### frontend
```shell
@@ -102,4 +102,4 @@ The rest of the commit message is then used for this.
## Submit a pull request
Push your branch to your `alist` fork and open a pull request against the
-`dev` branch.
+`main` branch.
diff --git a/Dockerfile b/Dockerfile
deleted file mode 100644
index 2219a7ab..00000000
--- a/Dockerfile
+++ /dev/null
@@ -1,14 +0,0 @@
-FROM alpine:edge as builder
-LABEL stage=go-builder
-WORKDIR /app/
-COPY ./ ./
-RUN apk add --no-cache bash git go gcc musl-dev; \
- bash build.sh docker
-
-FROM alpine:edge
-LABEL MAINTAINER="i@nn.ci"
-VOLUME /opt/alist/data/
-WORKDIR /opt/alist/
-COPY --from=builder /app/bin/alist ./
-EXPOSE 5244
-CMD [ "./alist", "-docker" ]
\ No newline at end of file
diff --git a/README.md b/README.md
index f7d51acc..da4ce43f 100755
--- a/README.md
+++ b/README.md
@@ -1,6 +1,6 @@
-

-
🗂️Another file list program that supports multiple storage, powered by Gin and React.
+

+
🗂️A file list program that supports multiple storage, powered by Gin and React.

@@ -13,64 +13,12 @@
---
-English | [中文](./README_cn.md) | [Contributors](./CONTRIBUTORS.md) | [Contributing](./CONTRIBUTING.md)
-
-## Features
-
-- [x] Multiple storage
- - [x] Local storage
- - [x] [Aliyundrive](https://www.aliyundrive.com/)
- - [x] OneDrive / Sharepoint ([global](https://www.office.com/), [cn](https://portal.partner.microsoftonline.cn),de,us)
- - [x] [189cloud](https://cloud.189.cn) (Personal, Family)
- - [x] [GoogleDrive](https://drive.google.com/)
- - [x] [123pan](https://www.123pan.com/)
- - [x] [Lanzou](https://pc.woozooo.com/)
- - [x] [Alist](https://github.com/Xhofe/alist)
- - [x] FTP
- - [x] [PikPak](https://www.mypikpak.com/)
- - [x] [ShandianPan](https://shandianpan.com/)
- - [x] [S3](https://aws.amazon.com/s3/)
- - [x] WebDav(Support OneDrive/SharePoint without API)
- - [x] Teambition([China](https://www.teambition.com/ ),[International](https://us.teambition.com/ ))
- - [x] [Mediatrack](https://www.mediatrack.cn/)
- - [x] [139yun](https://yun.139.com/) (Personal, Family)
- - [x] [Yandex.Disk](https://disk.yandex.com/)
- - [x] [Baidu Disk](http://pan.baidu.com/)
- - [x] [Quark](https://pan.quark.cn)
- - [x] [XunleiCloud](https://pan.xunlei.com/)
- - [x] SFTP
- - [x] [Baidu.Photo](https://photo.baidu.com/)
-- [x] Easy to deploy and out-of-the-box
-- [x] File preview (PDF, markdown, code, plain text, ...)
-- [x] Image preview in gallery mode
-- [x] Video and audio preview (mp4, mp3, ...)
-- [x] Office documents preview (docx, pptx, xlsx, ...)
-- [x] `README.md` preview rendering
-- [x] File permalink copy and direct file download
-- [x] Dark mode
-- [x] I18n
-- [x] Protected routes (password protection and authentication)
-- [x] WebDav (see https://alist-doc.nn.ci/en/docs/webdav for details)
-- [x] [Docker Deploy](https://hub.docker.com/r/xhofe/alist)
-- [x] Cloudflare workers proxy
-- [x] File/Folder package download
-- [x] Support video list playback and subtitles(ass,srt,vtt)
-- [x] Web upload(Can allow visitors to upload), delete, mkdir, rename, move and copy
+[Contributors](./CONTRIBUTORS.md) | [Contributing](./CONTRIBUTING.md)
## Discussion
Please go to our [discussion forum](https://github.com/Xhofe/alist/discussions) for general questions, **issues are for bug reports and feature request only.**
-## Demo
-
-Available at:
.
-
-
-
-## Document
-
-
-
## Special sponsors
- [Find Resources - Aliyundrive Resource Search Engine](https://zhaoziyuan.la/)
- [JetBrains: Essential tools for software developers and teams](https://www.jetbrains.com/)
diff --git a/README_cn.md b/README_cn.md
deleted file mode 100644
index 1d387624..00000000
--- a/README_cn.md
+++ /dev/null
@@ -1,91 +0,0 @@
-
-

-
🗂️一个支持多存储的文件列表程序,使用 Gin 和 React 。
-

-

-

-

-

-
-
-
-
-
----
-
-[English](./README.md) | 中文 | [Contributors](./CONTRIBUTORS.md) | [Contributing](./CONTRIBUTING.md)
-
-## 支持
-
-- [x] 多种存储
- - [x] 本地存储
- - [x] [阿里云盘](https://www.aliyundrive.com/)
- - [x] OneDrive / Sharepoint([国际版](https://www.office.com/), [世纪互联](https://portal.partner.microsoftonline.cn),de,us)
- - [x] [天翼云盘](https://cloud.189.cn) (个人云, 家庭云)
- - [x] [GoogleDrive](https://drive.google.com/)
- - [x] [123云盘](https://www.123pan.com/)
- - [x] [蓝奏云](https://pc.woozooo.com/)
- - [x] [Alist](https://github.com/Xhofe/alist)
- - [x] FTP
- - [x] [PikPak](https://www.mypikpak.com/)
- - [x] [闪电盘](https://shandianpan.com/)
- - [x] [S3](https://aws.amazon.com/cn/s3/)
- - [x] WebDav(支持无API的OneDrive/SharePoint)
- - [x] Teambition([中国](https://www.teambition.com/ ),[国际](https://us.teambition.com/ ))
- - [x] [分秒帧](https://www.mediatrack.cn/)
- - [x] [和彩云](https://yun.139.com/) (个人云, 家庭云)
- - [x] [Yandex.Disk](https://disk.yandex.com/)
- - [x] [百度网盘](http://pan.baidu.com/)
- - [x] [夸克网盘](https://pan.quark.cn)
- - [x] [迅雷云盘](https://pan.xunlei.com/)
- - [x] SFTP
- - [x] [一刻相册](https://photo.baidu.com/)
-- [x] 部署方便,开箱即用
-- [x] 文件预览(PDF、markdown、代码、纯文本……)
-- [x] 画廊模式下的图像预览
-- [x] 视频和音频预览(mp4、mp3 等)
-- [x] Office 文档预览(docx、pptx、xlsx、...)
-- [x] `README.md` 预览渲染
-- [x] 文件永久链接复制和直接文件下载
-- [x] 黑暗模式
-- [x] 国际化
-- [x] 受保护的路由(密码保护和身份验证)
-- [x] WebDav(具体见https://alist-doc.nn.ci/docs/webdav )
-- [x] [Docker 部署](https://hub.docker.com/r/xhofe/alist)
-- [x] Cloudflare workers 中转
-- [x] 文件/文件夹打包下载
-- [x] 支持视频列表播放和字幕(ass,srt,vtt)
-- [x] 网页上传(可以允许访客上传),删除,新建文件夹,重命名,移动,复制
-
-## 讨论
-
-一般问题请到[讨论论坛](https://github.com/Xhofe/alist/discussions) ,**issue仅针对错误报告和功能请求。**
-
-## 演示
-
-。
-
-
-
-## 文档
-
-
-
-## 特别赞助
-- [找资源 - 阿里云盘资源搜索引擎](https://zhaoziyuan.la/)
-- [JetBrains: Essential tools for software developers and teams](https://www.jetbrains.com/)
-
-## 许可
-
-`AList` 是在 AGPL-3.0 许可下许可的开源软件。
-
-## 免责声明
-- 本程序为免费开源项目,旨在分享网盘文件,方便下载以及学习golang,使用时请遵守相关法律法规,请勿滥用;
-- 本程序通过调用官方sdk/接口实现,无破坏官方接口行为;
-- 本程序仅做302重定向/流量转发,不拦截、存储、篡改任何用户数据;
-- 在使用本程序之前,你应了解并承担相应的风险,包括但不限于账号被ban,下载限速等,与本程序无关;
-- 如有侵权,请通过[邮件](mailto:i@nn.ci)与我联系,会及时处理。
-
----
-
-> [@博客](https://nn.ci/) · [@GitHub](https://github.com/Xhofe) · [@Telegram群](https://t.me/alist_chat) · [@QQ群](https://jq.qq.com/?_wv=1027&k=YJJj2Gwb)
\ No newline at end of file
diff --git a/alist.go b/alist.go
deleted file mode 100644
index 84514efa..00000000
--- a/alist.go
+++ /dev/null
@@ -1,59 +0,0 @@
-package main
-
-import (
- "fmt"
- "github.com/Xhofe/alist/bootstrap"
- "github.com/Xhofe/alist/conf"
- _ "github.com/Xhofe/alist/drivers"
- "github.com/Xhofe/alist/model"
- "github.com/Xhofe/alist/server"
- "github.com/gin-gonic/gin"
- log "github.com/sirupsen/logrus"
-)
-
-func Init() bool {
- bootstrap.InitConf()
- bootstrap.InitCron()
- bootstrap.InitModel()
- if conf.Password {
- pass, err := model.GetSettingByKey("password")
- if err != nil {
- log.Errorf(err.Error())
- return false
- }
- fmt.Printf("your password: %s\n", pass.Value)
- return false
- }
- server.InitIndex()
- bootstrap.InitSettings()
- bootstrap.InitAccounts()
- bootstrap.InitCache()
- return true
-}
-
-func main() {
- if conf.Version {
- fmt.Printf("Built At: %s\nGo Version: %s\nAuthor: %s\nCommit ID: %s\nVersion: %s\nWebVersion: %s\n",
- conf.BuiltAt, conf.GoVersion, conf.GitAuthor, conf.GitCommit, conf.GitTag, conf.WebTag)
- return
- }
- if !Init() {
- return
- }
- if !conf.Debug {
- gin.SetMode(gin.ReleaseMode)
- }
- r := gin.Default()
- server.InitApiRouter(r)
- base := fmt.Sprintf("%s:%d", conf.Conf.Address, conf.Conf.Port)
- log.Infof("start server @ %s", base)
- var err error
- if conf.Conf.Scheme.Https {
- err = r.RunTLS(base, conf.Conf.Scheme.CertFile, conf.Conf.Scheme.KeyFile)
- } else {
- err = r.Run(base)
- }
- if err != nil {
- log.Errorf("failed to start: %s", err.Error())
- }
-}
diff --git a/bootstrap/account.go b/bootstrap/account.go
deleted file mode 100644
index 8766e43a..00000000
--- a/bootstrap/account.go
+++ /dev/null
@@ -1,33 +0,0 @@
-package bootstrap
-
-import (
- "github.com/Xhofe/alist/conf"
- "github.com/Xhofe/alist/drivers/base"
- "github.com/Xhofe/alist/drivers/operate"
- "github.com/Xhofe/alist/model"
- log "github.com/sirupsen/logrus"
-)
-
-func InitAccounts() {
- log.Infof("init accounts...")
- var accounts []model.Account
- if err := conf.DB.Find(&accounts).Error; err != nil {
- log.Fatalf("failed sync init accounts")
- }
- for i, account := range accounts {
- model.RegisterAccount(account)
- driver, ok := base.GetDriver(account.Type)
- if !ok {
- log.Errorf("no [%s] driver", account.Type)
- } else {
- log.Infof("start init account: [%s], type: [%s]", account.Name, account.Type)
- //err := driver.Save(&accounts[i], nil)
- err := operate.Save(driver, &accounts[i], nil)
- if err != nil {
- log.Errorf("init account [%s] error:[%s]", account.Name, err.Error())
- } else {
- log.Infof("success init account: %s, type: %s", account.Name, account.Type)
- }
- }
- }
-}
diff --git a/bootstrap/cache.go b/bootstrap/cache.go
deleted file mode 100644
index 7d9dfba1..00000000
--- a/bootstrap/cache.go
+++ /dev/null
@@ -1,22 +0,0 @@
-package bootstrap
-
-import (
- "github.com/Xhofe/alist/conf"
- "github.com/eko/gocache/v2/cache"
- "github.com/eko/gocache/v2/store"
- goCache "github.com/patrickmn/go-cache"
- log "github.com/sirupsen/logrus"
- "time"
-)
-
-// InitCache init cache
-func InitCache() {
- log.Infof("init cache...")
- c := conf.Conf.Cache
- if c.Expiration == 0 {
- c.Expiration, c.CleanupInterval = 60, 120
- }
- goCacheClient := goCache.New(time.Duration(c.Expiration)*time.Minute, time.Duration(c.CleanupInterval)*time.Minute)
- goCacheStore := store.NewGoCache(goCacheClient, nil)
- conf.Cache = cache.New(goCacheStore)
-}
diff --git a/bootstrap/conf.go b/bootstrap/conf.go
deleted file mode 100644
index 5c9a1b37..00000000
--- a/bootstrap/conf.go
+++ /dev/null
@@ -1,71 +0,0 @@
-package bootstrap
-
-import (
- "github.com/Xhofe/alist/conf"
- "github.com/Xhofe/alist/utils"
- "github.com/caarlos0/env/v6"
- log "github.com/sirupsen/logrus"
- "io/ioutil"
- "os"
- "path/filepath"
-)
-
-// InitConf init config
-func InitConf() {
- log.Infof("reading config file: %s", conf.ConfigFile)
- if !utils.Exists(conf.ConfigFile) {
- log.Infof("config file not exists, creating default config file")
- _, err := utils.CreatNestedFile(conf.ConfigFile)
- if err != nil {
- log.Fatalf("failed to create config file")
- }
- conf.Conf = conf.DefaultConfig()
- if !utils.WriteToJson(conf.ConfigFile, conf.Conf) {
- log.Fatalf("failed to create default config file")
- }
- } else {
- config, err := ioutil.ReadFile(conf.ConfigFile)
- if err != nil {
- log.Fatalf("reading config file error:%s", err.Error())
- }
- conf.Conf = conf.DefaultConfig()
- err = utils.Json.Unmarshal(config, conf.Conf)
- if err != nil {
- log.Fatalf("load config error: %s", err.Error())
- }
- log.Debugf("config:%+v", conf.Conf)
- // update config.json struct
- confBody, err := utils.Json.MarshalIndent(conf.Conf, "", " ")
- if err != nil {
- log.Fatalf("marshal config error:%s", err.Error())
- }
- err = ioutil.WriteFile(conf.ConfigFile, confBody, 0777)
- if err != nil {
- log.Fatalf("update config struct error: %s", err.Error())
- }
- }
- if !conf.Conf.Force {
- confFromEnv()
- }
- err := os.RemoveAll(filepath.Join(conf.Conf.TempDir))
- if err != nil {
- log.Errorln("failed delete temp file:", err)
- }
- err = os.MkdirAll(conf.Conf.TempDir, 0700)
- if err != nil {
- log.Fatalf("create temp dir error: %s", err.Error())
- }
- log.Debugf("config: %+v", conf.Conf)
-}
-
-func confFromEnv() {
- prefix := "ALIST_"
- if conf.Docker {
- prefix = ""
- }
- if err := env.Parse(conf.Conf, env.Options{
- Prefix: prefix,
- }); err != nil {
- log.Fatalf("load config from env error: %s", err.Error())
- }
-}
diff --git a/bootstrap/cron.go b/bootstrap/cron.go
deleted file mode 100644
index 6effc3d5..00000000
--- a/bootstrap/cron.go
+++ /dev/null
@@ -1,14 +0,0 @@
-package bootstrap
-
-import (
- "github.com/Xhofe/alist/conf"
- "github.com/robfig/cron/v3"
- log "github.com/sirupsen/logrus"
-)
-
-// InitCron init cron
-func InitCron() {
- log.Infof("init cron...")
- conf.Cron = cron.New()
- conf.Cron.Start()
-}
diff --git a/bootstrap/log.go b/bootstrap/log.go
deleted file mode 100644
index 45bb418b..00000000
--- a/bootstrap/log.go
+++ /dev/null
@@ -1,36 +0,0 @@
-package bootstrap
-
-import (
- "flag"
- "github.com/Xhofe/alist/conf"
- log "github.com/sirupsen/logrus"
-)
-
-// InitLog init log
-func InitLog() {
- if conf.Debug {
- log.SetLevel(log.DebugLevel)
- log.SetReportCaller(true)
- }
- if conf.Password || conf.Version {
- log.SetLevel(log.WarnLevel)
- }
- log.SetFormatter(&log.TextFormatter{
- //DisableColors: true,
- ForceColors: true,
- EnvironmentOverrideColors: true,
- TimestampFormat: "2006-01-02 15:04:05",
- FullTimestamp: true,
- })
- log.Infof("init log...")
-}
-
-func init() {
- flag.StringVar(&conf.ConfigFile, "conf", "data/config.json", "config file")
- flag.BoolVar(&conf.Debug, "debug", false, "start with debug mode")
- flag.BoolVar(&conf.Version, "version", false, "print version info")
- flag.BoolVar(&conf.Password, "password", false, "print current password")
- flag.BoolVar(&conf.Docker, "docker", false, "is using docker")
- flag.Parse()
- InitLog()
-}
diff --git a/bootstrap/model.go b/bootstrap/model.go
deleted file mode 100644
index e199f116..00000000
--- a/bootstrap/model.go
+++ /dev/null
@@ -1,84 +0,0 @@
-package bootstrap
-
-import (
- "fmt"
- "github.com/Xhofe/alist/conf"
- "github.com/Xhofe/alist/model"
- log "github.com/sirupsen/logrus"
- "gorm.io/driver/mysql"
- "gorm.io/driver/postgres"
- "gorm.io/driver/sqlite"
- "gorm.io/gorm"
- "gorm.io/gorm/logger"
- "gorm.io/gorm/schema"
- log2 "log"
- "os"
- "strings"
- "time"
-)
-
-func InitModel() {
- log.Infof("init model...")
- var err error
- databaseConfig := conf.Conf.Database
- newLogger := logger.New(
- log2.New(os.Stdout, "\r\n", log2.LstdFlags),
- logger.Config{
- SlowThreshold: time.Second,
- LogLevel: logger.Silent,
- IgnoreRecordNotFoundError: true,
- Colorful: true,
- },
- )
- gormConfig := &gorm.Config{
- NamingStrategy: schema.NamingStrategy{
- TablePrefix: databaseConfig.TablePrefix,
- },
- Logger: newLogger,
- }
- switch databaseConfig.Type {
- case "sqlite3":
- {
- if !(strings.HasSuffix(databaseConfig.DBFile, ".db") && len(databaseConfig.DBFile) > 3) {
- log.Fatalf("db name error.")
- }
- db, err := gorm.Open(sqlite.Open(databaseConfig.DBFile), gormConfig)
- if err != nil {
- log.Fatalf("failed to connect database:%s", err.Error())
- }
- conf.DB = db
- }
- case "mysql":
- {
- dsn := fmt.Sprintf("%s:%s@tcp(%s:%d)/%s?charset=utf8mb4&parseTime=True&loc=Local&tls=%s",
- databaseConfig.User, databaseConfig.Password, databaseConfig.Host, databaseConfig.Port, databaseConfig.Name, databaseConfig.SslMode)
- db, err := gorm.Open(mysql.Open(dsn), gormConfig)
- if err != nil {
- log.Fatalf("failed to connect database:%s", err.Error())
- }
- conf.DB = db
- }
- case "postgres":
- {
- dsn := fmt.Sprintf("host=%s user=%s password=%s dbname=%s port=%d sslmode=%s TimeZone=Asia/Shanghai",
- databaseConfig.Host, databaseConfig.User, databaseConfig.Password, databaseConfig.Name, databaseConfig.Port, databaseConfig.SslMode)
- db, err := gorm.Open(postgres.Open(dsn), gormConfig)
- if err != nil {
- log.Errorf("failed to connect database:%s", err.Error())
- }
- conf.DB = db
- }
- default:
- log.Fatalf("not supported database type: %s", databaseConfig.Type)
- }
- log.Infof("auto migrate model...")
- if databaseConfig.Type == "mysql" {
- err = conf.DB.Set("gorm:table_options", "ENGINE=InnoDB CHARSET=utf8mb4").
- AutoMigrate(&model.SettingItem{}, &model.Account{}, &model.Meta{}, &model.SearchFile{})
- } else {
- err = conf.DB.AutoMigrate(&model.SettingItem{}, &model.Account{}, &model.Meta{}, &model.SearchFile{})
- }
- if err != nil {
- log.Fatalf("failed to auto migrate: %s", err.Error())
- }
-}
diff --git a/bootstrap/setting.go b/bootstrap/setting.go
deleted file mode 100644
index 0927682f..00000000
--- a/bootstrap/setting.go
+++ /dev/null
@@ -1,323 +0,0 @@
-package bootstrap
-
-import (
- "github.com/Xhofe/alist/conf"
- "github.com/Xhofe/alist/model"
- "github.com/Xhofe/alist/utils"
- log "github.com/sirupsen/logrus"
- "gorm.io/gorm"
- "strings"
-)
-
-func InitSettings() {
- log.Infof("init settings...")
-
- err := model.SaveSetting(model.Version)
- if err != nil {
- log.Fatalf("failed write setting: %s", err.Error())
- }
-
- settings := []model.SettingItem{
- {
- Key: "title",
- Value: "Alist",
- Description: "title",
- Type: "string",
- Access: model.PUBLIC,
- Group: model.FRONT,
- },
- {
- Key: "password",
- Value: utils.RandomStr(8),
- Description: "password",
- Type: "string",
- Access: model.PRIVATE,
- Group: model.BACK,
- },
- {
- Key: "logo",
- Value: "https://cdn.jsdelivr.net/gh/alist-org/logo@main/can_circle.svg",
- Description: "logo",
- Type: "string",
- Access: model.PUBLIC,
- Group: model.FRONT,
- },
- {
- Key: "favicon",
- Value: "https://cdn.jsdelivr.net/gh/alist-org/logo@main/logo.svg",
- Description: "favicon",
- Type: "string",
- Access: model.PUBLIC,
- Group: model.FRONT,
- },
- {
- Key: "icon color",
- Value: "#1890ff",
- Description: "icon's color",
- Type: "string",
- Access: model.PUBLIC,
- Group: model.FRONT,
- },
- {
- Key: "announcement",
- Value: "This is a test announcement.",
- Description: "announcement message (support markdown)",
- Type: "text",
- Access: model.PUBLIC,
- Group: model.FRONT,
- },
- {
- Key: "text types",
- Value: strings.Join(conf.TextTypes, ","),
- Type: "string",
- Description: "text type extensions",
- Group: model.FRONT,
- },
- {
- Key: "audio types",
- Value: strings.Join(conf.AudioTypes, ","),
- Type: "string",
- Description: "audio type extensions",
- Group: model.FRONT,
- },
- {
- Key: "video types",
- Value: strings.Join(conf.VideoTypes, ","),
- Type: "string",
- Description: "video type extensions",
- Group: model.FRONT,
- },
- {
- Key: "d_proxy types",
- Value: strings.Join(conf.DProxyTypes, ","),
- Type: "string",
- Description: "/d but proxy",
- Access: model.PRIVATE,
- Group: model.BACK,
- },
- {
- Key: "hide files",
- Value: "/\\/README.md/i",
- Type: "text",
- Description: "hide files, support RegExp, one per line",
- Group: model.FRONT,
- },
- {
- Key: "music cover",
- Value: "https://cdn.jsdelivr.net/gh/alist-org/logo@main/circle_center.svg",
- Description: "music cover image",
- Type: "string",
- Access: model.PUBLIC,
- Group: model.FRONT,
- },
- {
- Key: "site beian",
- Description: "chinese beian info",
- Type: "string",
- Access: model.PUBLIC,
- Group: model.FRONT,
- },
- {
- Key: "global readme url",
- Description: "Default display when directory has no readme",
- Type: "string",
- Access: model.PUBLIC,
- Group: model.FRONT,
- },
- {
- Key: "pdf viewer url",
- Type: "string",
- Value: "https://alist-org.github.io/pdf.js/web/viewer.html?file=$url",
- Access: model.PUBLIC,
- Group: model.FRONT,
- },
- {
- Key: "autoplay video",
- Value: "false",
- Type: "bool",
- Access: model.PUBLIC,
- Group: model.FRONT,
- },
- {
- Key: "autoplay audio",
- Value: "false",
- Type: "bool",
- Access: model.PUBLIC,
- Group: model.FRONT,
- },
- {
- Key: "check parent folder",
- Value: "false",
- Type: "bool",
- Description: "check parent folder password",
- Access: model.PRIVATE,
- Group: model.BACK,
- },
- {
- Key: "customize head",
- Value: "",
- Type: "text",
- Description: "Customize head, placed at the beginning of the head",
- Access: model.PRIVATE,
- Group: model.FRONT,
- },
- {
- Key: "customize body",
- Value: "",
- Type: "text",
- Description: "Customize script, placed at the end of the body",
- Access: model.PRIVATE,
- Group: model.FRONT,
- },
- {
- Key: "home emoji",
- Value: "🏠",
- Type: "string",
- Description: "emoji in front of home in nav",
- Access: model.PUBLIC,
- Group: model.FRONT,
- },
- {
- Key: "animation",
- Value: "true",
- Type: "bool",
- Description: "when there are a lot of files, the animation will freeze when opening",
- Access: model.PUBLIC,
- Group: model.FRONT,
- },
- {
- Key: "check down link",
- Value: "false",
- Type: "bool",
- Description: "check down link password, your link will be 'https://alist.com/d/filename?pw=xxx'",
- Access: model.PUBLIC,
- Group: model.BACK,
- },
- {
- Key: "WebDAV username",
- Value: "admin",
- Description: "WebDAV username",
- Type: "string",
- Access: model.PRIVATE,
- Group: model.BACK,
- },
- {
- Key: "WebDAV password",
- Value: utils.RandomStr(8),
- Description: "WebDAV password",
- Type: "string",
- Access: model.PRIVATE,
- Group: model.BACK,
- },
- {
- Key: "artplayer whitelist",
- Value: "*",
- Description: "refer to https://artplayer.org/document/options#whitelist",
- Type: "string",
- Access: model.PUBLIC,
- Group: model.FRONT,
- },
- {
- Key: "artplayer autoSize",
- Value: "true",
- Description: "refer to https://artplayer.org/document/options#autosize",
- Type: "bool",
- Access: model.PUBLIC,
- Group: model.FRONT,
- },
- {
- Key: "Visitor WebDAV username",
- Value: "guest",
- Description: "Visitor WebDAV username",
- Type: "string",
- Access: model.PRIVATE,
- Group: model.BACK,
- },
- {
- Key: "Visitor WebDAV password",
- Value: "guest",
- Description: "Visitor WebDAV password",
- Type: "string",
- Access: model.PRIVATE,
- Group: model.BACK,
- },
- {
- Key: "load type",
- Value: "all",
- Type: "select",
- Values: "all,load more,auto load more,pagination",
- Description: "Not recommended to choose to auto load more, it has bugs now",
- Access: model.PUBLIC,
- Group: model.FRONT,
- },
- {
- Key: "default page size",
- Value: "30",
- Type: "number",
- Access: model.PUBLIC,
- Group: model.FRONT,
- },
- {
- Key: "ocr api",
- Value: "https://api.nn.ci/ocr/file/json",
- Description: "Used to identify verification codes",
- Type: "string",
- Access: model.PRIVATE,
- Group: model.BACK,
- },
- {
- Key: "enable search",
- Value: "false",
- Type: "bool",
- Access: model.PUBLIC,
- Group: model.BACK,
- Description: "Experimental function, not recommended as it's still under development",
- },
- {
- Key: "Aria2 RPC url",
- Value: "http://localhost:6800/jsonrpc",
- Description: "Aria2 RPC url, e.g. 'http://aria2.example.com:6800/jsonrpc'",
- Type: "string",
- Access: model.PRIVATE,
- Group: model.BACK,
- },
- {
- Key: "Aria2 RPC secret",
- Value: "",
- Description: "Aria2 RPC secret, e.g. '123456'",
- Type: "string",
- Access: model.PRIVATE,
- Group: model.BACK,
- },
- }
- for i, _ := range settings {
- v := settings[i]
- v.Version = conf.GitTag
- o, err := model.GetSettingByKey(v.Key)
- if err != nil {
- if err == gorm.ErrRecordNotFound {
- err = model.SaveSetting(v)
- if v.Key == "password" {
- log.Infof("Initial password: %s", conf.C.Sprintf(v.Value))
- }
- if err != nil {
- log.Fatalf("failed write setting: %s", err.Error())
- }
- } else {
- log.Fatalf("can't get setting: %s", err.Error())
- }
- } else {
- //o.Version = conf.GitTag
- //err = model.SaveSetting(*o)
- v.Value = o.Value
- err = model.SaveSetting(v)
- if err != nil {
- log.Fatalf("failed write setting: %s", err.Error())
- }
- if v.Key == "password" {
- log.Infof("Your password: %s", conf.C.Sprintf(v.Value))
- }
- }
- }
- model.LoadSettings()
-}
diff --git a/build.sh b/build.sh
deleted file mode 100644
index 980a5282..00000000
--- a/build.sh
+++ /dev/null
@@ -1,157 +0,0 @@
-#!/bin/bash
-
-# 构建前端,在当前目录产生一个dist文件夹
-BUILD_WEB() {
- git clone https://github.com/alist-org/alist-web.git
- cd alist-web
- yarn
- yarn build
- sed -i -e "s/\/CDN_URL\//\//g" dist/index.html
- sed -i -e "s/assets/\/assets/g" dist/index.html
- rm -f dist/index.html-e
- mv dist ..
- cd .. || exit
- rm -rf alist-web
-}
-
-CDN_WEB() {
- curl -L https://github.com/alist-org/alist-web/releases/latest/download/dist.tar.gz -o dist.tar.gz
- tar -zxvf dist.tar.gz
- rm -f dist.tar.gz
-}
-
-# 在DOCKER中构建
-BUILD_DOCKER() {
- appName="alist"
- builtAt="$(date +'%F %T %z')"
- goVersion=$(go version | sed 's/go version //')
- gitAuthor=$(git show -s --format='format:%aN <%ae>' HEAD)
- gitCommit=$(git log --pretty=format:"%h" -1)
- gitTag=$(git describe --long --tags --dirty --always)
- webTag=$(wget -qO- -t1 -T2 "https://api.github.com/repos/alist-org/alist-web/releases/latest" | grep "tag_name" | head -n 1 | awk -F ":" '{print $2}' | sed 's/\"//g;s/,//g;s/ //g')
- ldflags="\
--w -s \
--X 'github.com/Xhofe/alist/conf.BuiltAt=$builtAt' \
--X 'github.com/Xhofe/alist/conf.GoVersion=$goVersion' \
--X 'github.com/Xhofe/alist/conf.GitAuthor=$gitAuthor' \
--X 'github.com/Xhofe/alist/conf.GitCommit=$gitCommit' \
--X 'github.com/Xhofe/alist/conf.GitTag=$gitTag' \
--X 'github.com/Xhofe/alist/conf.WebTag=$webTag' \
- "
- go build -o ./bin/alist -ldflags="$ldflags" -tags=jsoniter alist.go
-}
-
-BUILD() {
- cd alist
- appName="alist"
- builtAt="$(date +'%F %T %z')"
- goVersion=$(go version | sed 's/go version //')
- gitAuthor=$(git show -s --format='format:%aN <%ae>' HEAD)
- gitCommit=$(git log --pretty=format:"%h" -1)
- gitTag=$(git describe --long --tags --dirty --always)
- webTag=$(wget -qO- -t1 -T2 "https://api.github.com/repos/alist-org/alist-web/releases/latest" | grep "tag_name" | head -n 1 | awk -F ":" '{print $2}' | sed 's/\"//g;s/,//g;s/ //g')
- echo "build version: $gitTag"
-
- ldflags="\
--w -s \
--X 'github.com/Xhofe/alist/conf.BuiltAt=$builtAt' \
--X 'github.com/Xhofe/alist/conf.GoVersion=$goVersion' \
--X 'github.com/Xhofe/alist/conf.GitAuthor=$gitAuthor' \
--X 'github.com/Xhofe/alist/conf.GitCommit=$gitCommit' \
--X 'github.com/Xhofe/alist/conf.GitTag=$gitTag' \
--X 'github.com/Xhofe/alist/conf.WebTag=$webTag' \
-"
- rm -rf .git/
- if [ "$1" == "release" ]; then
- xgo -out "$appName" -ldflags="$ldflags" -tags=jsoniter .
- else
- xgo -targets=linux/amd64,windows/amd64,darwin/amd64 -out "$appName" -ldflags="$ldflags" -tags=jsoniter .
- fi
- mkdir -p "build"
- mv alist-* build
- if [ "$1" != "release" ]; then
- cd build
- upx -9 ./alist-linux*
- upx -9 ./alist-windows*
- find . -type f -print0 | xargs -0 md5sum >md5.txt
- cat md5.txt
- cd .. || exit
- fi
- cd .. || exit
-}
-
-BUILD_MUSL() {
- BASE="https://musl.cc/"
- FILES=(x86_64-linux-musl-cross aarch64-linux-musl-cross arm-linux-musleabihf-cross mips-linux-musl-cross mips64-linux-musl-cross mips64el-linux-musl-cross mipsel-linux-musl-cross powerpc64le-linux-musl-cross s390x-linux-musl-cross)
- for i in "${FILES[@]}"; do
- url="${BASE}${i}.tgz"
- curl -L -o "${i}.tgz" "${url}"
- sudo tar xf "${i}.tgz" --strip-components 1 -C /usr/local
- done
- cd alist
- appName="alist"
- builtAt="$(date +'%F %T %z')"
- goVersion=$(go version | sed 's/go version //')
- gitAuthor=$(git show -s --format='format:%aN <%ae>' HEAD)
- gitCommit=$(git log --pretty=format:"%h" -1)
- gitTag=$(git describe --long --tags --dirty --always)
- webTag=$(wget -qO- -t1 -T2 "https://api.github.com/repos/alist-org/alist-web/releases/latest" | grep "tag_name" | head -n 1 | awk -F ":" '{print $2}' | sed 's/\"//g;s/,//g;s/ //g')
- ldflags="\
--w -s --extldflags '-static -fpic' \
--X 'github.com/Xhofe/alist/conf.BuiltAt=$builtAt' \
--X 'github.com/Xhofe/alist/conf.GoVersion=$goVersion' \
--X 'github.com/Xhofe/alist/conf.GitAuthor=$gitAuthor' \
--X 'github.com/Xhofe/alist/conf.GitCommit=$gitCommit' \
--X 'github.com/Xhofe/alist/conf.GitTag=$gitTag' \
--X 'github.com/Xhofe/alist/conf.WebTag=$webTag' \
- "
- OS_ARCHES=(linux-musl-amd64 linux-musl-arm64 linux-musl-arm linux-musl-mips linux-musl-mips64 linux-musl-mips64le linux-musl-mipsle linux-musl-ppc64le linux-musl-s390x)
- CGO_ARGS=(x86_64-linux-musl-gcc aarch64-linux-musl-gcc arm-linux-musleabihf-gcc mips-linux-musl-gcc mips64-linux-musl-gcc mips64el-linux-musl-gcc mipsel-linux-musl-gcc powerpc64le-linux-musl-gcc s390x-linux-musl-gcc)
- for i in "${!OS_ARCHES[@]}"; do
- os_arch=${OS_ARCHES[$i]}
- cgo_cc=${CGO_ARGS[$i]}
- echo building for ${os_arch}
- export GOOS=${os_arch%%-*}
- export GOARCH=${os_arch##*-}
- export CC=${cgo_cc}
- export CGO_ENABLED=1
- go build -o ./build/$appName-$os_arch -ldflags="$ldflags" -tags=jsoniter alist.go
- done
- cd .. || exit
-}
-
-RELEASE() {
- cd alist/build
- upx -9 ./alist-linux-amd64
- upx -9 ./alist-windows*
- find . -type f -print0 | xargs -0 md5sum >md5.txt
- cat md5.txt
- mkdir compress
- mv md5.txt compress
- for i in $(find . -type f -name "$appName-linux-*"); do
- tar -czvf compress/"$i".tar.gz "$i"
- done
- for i in $(find . -type f -name "$appName-darwin-*"); do
- tar -czvf compress/"$i".tar.gz "$i"
- done
- for i in $(find . -type f -name "$appName-windows-*"); do
- zip compress/$(echo $i | sed 's/\.[^.]*$//').zip "$i"
- done
- cd ../.. || exit
-}
-
-if [ "$1" = "web" ]; then
- BUILD_WEB
-elif [ "$1" = "cdn" ]; then
- CDN_WEB
-elif [ "$1" = "docker" ]; then
- BUILD_DOCKER
-elif [ "$1" = "build" ]; then
- BUILD build
-elif [ "$1" = "release" ]; then
- BUILD_MUSL
- BUILD release
- RELEASE
-else
- echo -e "${RED_COLOR} Parameter error ${RES}"
-fi
\ No newline at end of file
diff --git a/cmd/alist.go b/cmd/alist.go
new file mode 100644
index 00000000..91cca4fb
--- /dev/null
+++ b/cmd/alist.go
@@ -0,0 +1,7 @@
+package main
+
+import "fmt"
+
+func main() {
+ fmt.Println("Hello, world.")
+}
diff --git a/conf/config.go b/conf/config.go
deleted file mode 100644
index 7d4c0fe0..00000000
--- a/conf/config.go
+++ /dev/null
@@ -1,54 +0,0 @@
-package conf
-
-type Database struct {
- Type string `json:"type" env:"DB_TYPE"`
- Host string `json:"host" env:"DB_HOST"`
- Port int `json:"port" env:"DB_PORT"`
- User string `json:"user" env:"DB_USER"`
- Password string `json:"password" env:"DB_PASS"`
- Name string `json:"name" env:"DB_NAME"`
- DBFile string `json:"db_file" env:"DB_FILE"`
- TablePrefix string `json:"table_prefix" env:"DB_TABLE_PREFIX"`
- SslMode string `json:"ssl_mode" env:"DB_SLL_MODE"`
-}
-
-type Scheme struct {
- Https bool `json:"https" env:"HTTPS"`
- CertFile string `json:"cert_file" env:"CERT_FILE"`
- KeyFile string `json:"key_file" env:"KEY_FILE"`
-}
-
-type CacheConfig struct {
- Expiration int64 `json:"expiration" env:"CACHE_EXPIRATION"`
- CleanupInterval int64 `json:"cleanup_interval" env:"CLEANUP_INTERVAL"`
-}
-
-type Config struct {
- Force bool `json:"force"`
- Address string `json:"address" env:"ADDR"`
- Port int `json:"port" env:"PORT"`
- Assets string `json:"assets" env:"ASSETS"`
- Database Database `json:"database"`
- Scheme Scheme `json:"scheme"`
- Cache CacheConfig `json:"cache"`
- TempDir string `json:"temp_dir" env:"TEMP_DIR"`
-}
-
-func DefaultConfig() *Config {
- return &Config{
- Address: "0.0.0.0",
- Port: 5244,
- Assets: "https://npm.elemecdn.com/alist-web@$version/dist",
- TempDir: "data/temp",
- Database: Database{
- Type: "sqlite3",
- Port: 0,
- TablePrefix: "x_",
- DBFile: "data/data.db",
- },
- Cache: CacheConfig{
- Expiration: 60,
- CleanupInterval: 120,
- },
- }
-}
diff --git a/conf/const.go b/conf/const.go
deleted file mode 100644
index 32336dc6..00000000
--- a/conf/const.go
+++ /dev/null
@@ -1,11 +0,0 @@
-package conf
-
-const (
- UNKNOWN = iota
- FOLDER
- OFFICE
- VIDEO
- AUDIO
- TEXT
- IMAGE
-)
\ No newline at end of file
diff --git a/conf/var.go b/conf/var.go
deleted file mode 100644
index 4efc92ea..00000000
--- a/conf/var.go
+++ /dev/null
@@ -1,104 +0,0 @@
-package conf
-
-import (
- "context"
- "github.com/eko/gocache/v2/cache"
- "github.com/fatih/color"
- "github.com/robfig/cron/v3"
- "gorm.io/gorm"
- "strconv"
-)
-
-var (
- BuiltAt string
- GoVersion string
- GitAuthor string
- GitCommit string
- GitTag string = "dev"
- WebTag string
-)
-
-var (
- ConfigFile string // config file
- Conf *Config
- Debug bool
- Version bool
- Password bool
- Docker bool
-
- DB *gorm.DB
- Cache *cache.Cache
- Ctx = context.TODO()
- Cron *cron.Cron
-
- C = color.New(color.FgHiBlue, color.Bold, color.BgHiWhite, color.Underline)
-)
-
-var (
- TextTypes = []string{"txt", "htm", "html", "xml", "java", "properties", "sql",
- "js", "md", "json", "conf", "ini", "vue", "php", "py", "bat", "gitignore", "yml",
- "go", "sh", "c", "cpp", "h", "hpp", "tsx", "vtt", "srt", "ass"}
- DProxyTypes = []string{"m3u8"}
- OfficeTypes = []string{"doc", "docx", "xls", "xlsx", "ppt", "pptx", "pdf"}
- VideoTypes = []string{"mp4", "mkv", "avi", "mov", "rmvb", "webm", "flv", "m4v"}
- AudioTypes = []string{"mp3", "flac", "ogg", "m4a", "wav", "opus"}
- ImageTypes = []string{"jpg", "tiff", "jpeg", "png", "gif", "bmp", "svg", "ico", "swf", "webp"}
-)
-
-var settingsMap = make(map[string]string)
-
-func Set(key string, value string) {
- settingsMap[key] = value
-}
-
-func GetStr(key string) string {
- value, ok := settingsMap[key]
- if !ok {
- return ""
- }
- return value
-}
-
-func GetBool(key string) bool {
- value, ok := settingsMap[key]
- if !ok {
- return false
- }
- return value == "true"
-}
-
-func GetInt(key string, defaultV int) int {
- value, ok := settingsMap[key]
- if !ok {
- return defaultV
- }
- v, err := strconv.Atoi(value)
- if err != nil {
- return defaultV
- }
- return v
-}
-
-var (
- LoadSettings = []string{
- "check parent folder", "check down link", "WebDAV username", "WebDAV password",
- "Visitor WebDAV username", "Visitor WebDAV password",
- "default page size", "load type",
- "ocr api", "favicon",
- "enable search",
- }
-)
-
-var (
- RawIndexHtml string
- ManageHtml string
- IndexHtml string
- Token string
-
- //CheckParent bool
- //CheckDown bool
- //DavUsername string
- //DavPassword string
- //VisitorDavUsername string
- //VisitorDavPassword string
-)
diff --git a/drivers/123/123.go b/drivers/123/123.go
deleted file mode 100644
index 87f8cafe..00000000
--- a/drivers/123/123.go
+++ /dev/null
@@ -1,178 +0,0 @@
-package _23
-
-import (
- "errors"
- "fmt"
- "path/filepath"
- "strconv"
-
- "github.com/Xhofe/alist/drivers/base"
- "github.com/Xhofe/alist/model"
- "github.com/Xhofe/alist/utils"
- "github.com/go-resty/resty/v2"
- jsoniter "github.com/json-iterator/go"
- log "github.com/sirupsen/logrus"
-)
-
-func (driver Pan123) Login(account *model.Account) error {
- url := "https://www.123pan.com/api/user/sign_in"
- if account.APIProxyUrl != "" {
- url = fmt.Sprintf("%s/%s", account.APIProxyUrl, url)
- }
- var resp Pan123TokenResp
- _, err := base.RestyClient.R().
- SetResult(&resp).
- SetBody(base.Json{
- "passport": account.Username,
- "password": account.Password,
- }).Post(url)
- if err != nil {
- return err
- }
- if resp.Code != 200 {
- err = fmt.Errorf(resp.Message)
- account.Status = resp.Message
- } else {
- account.Status = "work"
- account.AccessToken = resp.Data.Token
- }
- _ = model.SaveAccount(account)
- return err
-}
-
-func (driver Pan123) FormatFile(file *File) *model.File {
- f := &model.File{
- Id: strconv.FormatInt(file.FileId, 10),
- Name: file.FileName,
- Size: file.Size,
- Driver: driver.Config().Name,
- UpdatedAt: file.UpdateAt,
- Thumbnail: file.DownloadUrl,
- }
- f.Type = file.GetType()
- return f
-}
-
-func (driver Pan123) GetFiles(parentId string, account *model.Account) ([]File, error) {
- next := "0"
- res := make([]File, 0)
- for next != "-1" {
- var resp Pan123Files
- query := map[string]string{
- "driveId": "0",
- "limit": "100",
- "next": next,
- "orderBy": account.OrderBy,
- "orderDirection": account.OrderDirection,
- "parentFileId": parentId,
- "trashed": "false",
- }
- _, err := driver.Request("https://www.123pan.com/api/file/list/new",
- base.Get, nil, query, nil, &resp, false, account)
- if err != nil {
- return nil, err
- }
- next = resp.Data.Next
- res = append(res, resp.Data.InfoList...)
- }
- return res, nil
-}
-
-func (driver Pan123) Request(url string, method int, headers, query map[string]string, data *base.Json, resp interface{}, proxy bool, account *model.Account) ([]byte, error) {
- rawUrl := url
- if account.APIProxyUrl != "" && proxy {
- url = fmt.Sprintf("%s/%s", account.APIProxyUrl, url)
- }
- req := base.RestyClient.R()
- req.SetHeader("Authorization", "Bearer "+account.AccessToken)
- if headers != nil {
- req.SetHeaders(headers)
- }
- if query != nil {
- req.SetQueryParams(query)
- }
- if data != nil {
- req.SetBody(data)
- }
- if resp != nil {
- req.SetResult(resp)
- }
- var res *resty.Response
- var err error
- switch method {
- case base.Get:
- res, err = req.Get(url)
- case base.Post:
- res, err = req.Post(url)
- default:
- return nil, base.ErrNotSupport
- }
- if err != nil {
- return nil, err
- }
- log.Debug(res.String())
- body := res.Body()
- code := jsoniter.Get(body, "code").ToInt()
- if code != 0 {
- if code == 401 {
- err := driver.Login(account)
- if err != nil {
- return nil, err
- }
- return driver.Request(rawUrl, method, headers, query, data, resp, proxy, account)
- }
- return nil, errors.New(jsoniter.Get(body, "message").ToString())
- }
- return body, nil
-}
-
-//func (driver Pan123) Post(url string, data base.Json, account *model.Account) ([]byte, error) {
-// res, err := pan123Client.R().
-// SetHeader("authorization", "Bearer "+account.AccessToken).
-// SetBody(data).Post(url)
-// if err != nil {
-// return nil, err
-// }
-// body := res.Body()
-// if jsoniter.Get(body, "code").ToInt() != 0 {
-// return nil, errors.New(jsoniter.Get(body, "message").ToString())
-// }
-// return body, nil
-//}
-
-func (driver Pan123) GetFile(path string, account *model.Account) (*File, error) {
- dir, name := filepath.Split(path)
- dir = utils.ParsePath(dir)
- _, err := driver.Files(dir, account)
- if err != nil {
- return nil, err
- }
- parentFiles_, _ := base.GetCache(dir, account)
- parentFiles, _ := parentFiles_.([]File)
- for _, file := range parentFiles {
- if file.FileName == name {
- //if file.Type != conf.FOLDER {
- // return &file, err
- //} else {
- // return nil, base.ErrNotFile
- //}
- return &file, nil
- }
- }
- return nil, base.ErrPathNotFound
-}
-
-//func HMAC(message string, secret string) string {
-// key := []byte(secret)
-// h := hmac.New(sha256.New, key)
-// h.Write([]byte(message))
-// // fmt.Println(h.Sum(nil))
-// //sha := hex.EncodeToString(h.Sum(nil))
-// // fmt.Println(sha)
-// //return sha
-// return string(h.Sum(nil))
-//}
-
-func init() {
- base.RegisterDriver(&Pan123{})
-}
diff --git a/drivers/123/driver.go b/drivers/123/driver.go
deleted file mode 100644
index 47c8b21b..00000000
--- a/drivers/123/driver.go
+++ /dev/null
@@ -1,460 +0,0 @@
-package _23
-
-import (
- "bytes"
- "crypto/md5"
- "encoding/binary"
- "encoding/hex"
- "fmt"
- "io"
- "io/ioutil"
- "net/url"
- "os"
- "path/filepath"
- "strconv"
-
- "github.com/Xhofe/alist/conf"
- "github.com/Xhofe/alist/drivers/base"
- "github.com/Xhofe/alist/model"
- "github.com/Xhofe/alist/utils"
- "github.com/aws/aws-sdk-go/aws"
- "github.com/aws/aws-sdk-go/aws/credentials"
- "github.com/aws/aws-sdk-go/aws/session"
- "github.com/aws/aws-sdk-go/service/s3/s3manager"
- log "github.com/sirupsen/logrus"
-)
-
-type Pan123 struct{}
-
-func (driver Pan123) Config() base.DriverConfig {
- return base.DriverConfig{
- Name: "123Pan",
- }
-}
-
-func (driver Pan123) Items() []base.Item {
- return []base.Item{
- {
- Name: "username",
- Label: "username",
- Type: base.TypeString,
- Required: true,
- Description: "account username/phone number",
- },
- {
- Name: "password",
- Label: "password",
- Type: base.TypeString,
- Required: true,
- Description: "account password",
- },
- {
- Name: "root_folder",
- Label: "root folder file_id",
- Type: base.TypeString,
- Required: false,
- },
- {
- Name: "order_by",
- Label: "order_by",
- Type: base.TypeSelect,
- Values: "name,fileId,updateAt,createAt",
- Required: true,
- Default: "name",
- },
- {
- Name: "order_direction",
- Label: "order_direction",
- Type: base.TypeSelect,
- Values: "asc,desc",
- Required: true,
- Default: "asc",
- },
- {
- Name: "bool_1",
- Label: "stream upload",
- Type: base.TypeBool,
- Description: "io stream upload (test)",
- },
- }
-}
-
-func (driver Pan123) Save(account *model.Account, old *model.Account) error {
- if account == nil {
- return nil
- }
- if account.RootFolder == "" {
- account.RootFolder = "0"
- }
- err := driver.Login(account)
- return err
-}
-
-func (driver Pan123) File(path string, account *model.Account) (*model.File, error) {
- path = utils.ParsePath(path)
- if path == "/" {
- return &model.File{
- Id: account.RootFolder,
- Name: account.Name,
- Size: 0,
- Type: conf.FOLDER,
- Driver: driver.Config().Name,
- UpdatedAt: account.UpdatedAt,
- }, nil
- }
- dir, name := filepath.Split(path)
- files, err := driver.Files(dir, account)
- if err != nil {
- return nil, err
- }
- for _, file := range files {
- if file.Name == name {
- return &file, nil
- }
- }
- return nil, base.ErrPathNotFound
-}
-
-func (driver Pan123) Files(path string, account *model.Account) ([]model.File, error) {
- path = utils.ParsePath(path)
- var rawFiles []File
- cache, err := base.GetCache(path, account)
- if err == nil {
- rawFiles, _ = cache.([]File)
- } else {
- file, err := driver.File(path, account)
- if err != nil {
- return nil, err
- }
- rawFiles, err = driver.GetFiles(file.Id, account)
- if err != nil {
- return nil, err
- }
- if len(rawFiles) > 0 {
- _ = base.SetCache(path, rawFiles, account)
- }
- }
- files := make([]model.File, 0, len(rawFiles))
- for _, file := range rawFiles {
- files = append(files, *driver.FormatFile(&file))
- }
- return files, nil
-}
-
-func (driver Pan123) Link(args base.Args, account *model.Account) (*base.Link, error) {
- log.Debugf("%+v", args)
- file, err := driver.GetFile(utils.ParsePath(args.Path), account)
- if err != nil {
- return nil, err
- }
- var resp Pan123DownResp
- var headers map[string]string
- if !utils.IsLocalIPAddr(args.IP) {
- headers = map[string]string{
- //"X-Real-IP": "1.1.1.1",
- "X-Forwarded-For": args.IP,
- }
- }
- data := base.Json{
- "driveId": 0,
- "etag": file.Etag,
- "fileId": file.FileId,
- "fileName": file.FileName,
- "s3keyFlag": file.S3KeyFlag,
- "size": file.Size,
- "type": file.Type,
- }
- _, err = driver.Request("https://www.123pan.com/api/file/download_info",
- base.Post, headers, nil, &data, &resp, false, account)
- //_, err = pan123Client.R().SetResult(&resp).SetHeader("authorization", "Bearer "+account.AccessToken).
- // SetBody().Post("https://www.123pan.com/api/file/download_info")
- if err != nil {
- return nil, err
- }
- u, err := url.Parse(resp.Data.DownloadUrl)
- if err != nil {
- return nil, err
- }
- u_ := fmt.Sprintf("https://%s%s", u.Host, u.Path)
- res, err := base.NoRedirectClient.R().SetQueryParamsFromValues(u.Query()).Get(u_)
- if err != nil {
- return nil, err
- }
- log.Debug(res.String())
- link := base.Link{
- Url: resp.Data.DownloadUrl,
- }
- if res.StatusCode() == 302 {
- link.Url = res.Header().Get("location")
- }
- return &link, nil
-}
-
-func (driver Pan123) Path(path string, account *model.Account) (*model.File, []model.File, error) {
- path = utils.ParsePath(path)
- log.Debugf("pan123 path: %s", path)
- file, err := driver.File(path, account)
- if err != nil {
- return nil, nil, err
- }
- if !file.IsDir() {
- return file, nil, nil
- }
- files, err := driver.Files(path, account)
- if err != nil {
- return nil, nil, err
- }
- return nil, files, nil
-}
-
-//func (driver Pan123) Proxy(r *http.Request, account *model.Account) {
-// r.Header.Del("origin")
-//}
-
-func (driver Pan123) Preview(path string, account *model.Account) (interface{}, error) {
- return nil, base.ErrNotSupport
-}
-
-func (driver Pan123) MakeDir(path string, account *model.Account) error {
- dir, name := filepath.Split(path)
- parentFile, err := driver.File(dir, account)
- if err != nil {
- return err
- }
- if !parentFile.IsDir() {
- return base.ErrNotFolder
- }
- parentFileId, _ := strconv.Atoi(parentFile.Id)
- data := base.Json{
- "driveId": 0,
- "etag": "",
- "fileName": name,
- "parentFileId": parentFileId,
- "size": 0,
- "type": 1,
- }
- _, err = driver.Request("https://www.123pan.com/api/file/upload_request",
- base.Post, nil, nil, &data, nil, false, account)
- return err
-}
-
-func (driver Pan123) Move(src string, dst string, account *model.Account) error {
- dstDir, _ := filepath.Split(dst)
- srcFile, err := driver.File(src, account)
- if err != nil {
- return err
- }
- fileId, _ := strconv.Atoi(srcFile.Id)
-
- dstDirFile, err := driver.File(dstDir, account)
- if err != nil {
- return err
- }
- parentFileId, _ := strconv.Atoi(dstDirFile.Id)
- data := base.Json{
- "fileIdList": []base.Json{{"FileId": fileId}},
- "parentFileId": parentFileId,
- }
- _, err = driver.Request("https://www.123pan.com/api/file/mod_pid",
- base.Post, nil, nil, &data, nil, false, account)
- return err
-}
-
-func (driver Pan123) Rename(src string, dst string, account *model.Account) error {
- _, dstName := filepath.Split(dst)
- srcFile, err := driver.File(src, account)
- if err != nil {
- return err
- }
- fileId, _ := strconv.Atoi(srcFile.Id)
-
- data := base.Json{
- "driveId": 0,
- "fileId": fileId,
- "fileName": dstName,
- }
- _, err = driver.Request("https://www.123pan.com/api/file/rename",
- base.Post, nil, nil, &data, nil, false, account)
- return err
-}
-
-func (driver Pan123) Copy(src string, dst string, account *model.Account) error {
- return base.ErrNotSupport
-}
-
-func (driver Pan123) Delete(path string, account *model.Account) error {
- file, err := driver.GetFile(path, account)
- if err != nil {
- return err
- }
- log.Debugln("delete 123 file: ", file)
- data := base.Json{
- "driveId": 0,
- "operation": true,
- "fileTrashInfoList": []File{*file},
- }
- _, err = driver.Request("https://www.123pan.com/b/api/file/trash",
- base.Post, nil, nil, &data, nil, false, account)
- return err
-}
-
-func (driver Pan123) Upload(file *model.FileStream, account *model.Account) error {
- if file == nil {
- return base.ErrEmptyFile
- }
- parentFile, err := driver.File(file.ParentPath, account)
- if err != nil {
- return err
- }
- if !parentFile.IsDir() {
- return base.ErrNotFolder
- }
-
- const DEFAULT int64 = 10485760
- var uploadFile io.Reader
- h := md5.New()
- if account.Bool1 && file.GetSize() > uint64(DEFAULT) {
- // 只计算前10MIB
- buf := bytes.NewBuffer(make([]byte, 0, DEFAULT))
- if n, err := io.CopyN(io.MultiWriter(buf, h), file, DEFAULT); err != io.EOF && n == 0 {
- return err
- }
- // 增加额外参数防止MD5碰撞
- h.Write([]byte(file.Name))
- num := make([]byte, 8)
- binary.BigEndian.PutUint64(num, file.Size)
- h.Write(num)
- // 拼装
- uploadFile = io.MultiReader(buf, file)
- } else {
- // 计算完整文件MD5
- tempFile, err := ioutil.TempFile(conf.Conf.TempDir, "file-*")
- if err != nil {
- return err
- }
- defer func() {
- _ = tempFile.Close()
- _ = os.Remove(tempFile.Name())
- }()
-
- if _, err = io.Copy(io.MultiWriter(tempFile, h), file); err != nil {
- return err
- }
-
- _, err = tempFile.Seek(0, io.SeekStart)
- if err != nil {
- return err
- }
- uploadFile = tempFile
- }
- etag := hex.EncodeToString(h.Sum(nil))
- data := base.Json{
- "driveId": 0,
- "duplicate": 2, // 2->覆盖 1->重命名 0->默认
- "etag": etag,
- "fileName": file.GetFileName(),
- "parentFileId": parentFile.Id,
- "size": file.GetSize(),
- "type": 0,
- }
- var resp UploadResp
- _, err = driver.Request("https://www.123pan.com/api/file/upload_request",
- base.Post, map[string]string{"app-version": "1.1"}, nil, &data, &resp, false, account)
- //res, err := driver.Post("https://www.123pan.com/api/file/upload_request", data, account)
- if err != nil {
- return err
- }
- if resp.Data.Key == "" {
- return nil
- }
- cfg := &aws.Config{
- Credentials: credentials.NewStaticCredentials(resp.Data.AccessKeyId, resp.Data.SecretAccessKey, resp.Data.SessionToken),
- Region: aws.String("123pan"),
- Endpoint: aws.String("file.123pan.com"),
- S3ForcePathStyle: aws.Bool(true),
- }
- s, err := session.NewSession(cfg)
- if err != nil {
- return err
- }
- uploader := s3manager.NewUploader(s)
- input := &s3manager.UploadInput{
- Bucket: &resp.Data.Bucket,
- Key: &resp.Data.Key,
- Body: uploadFile,
- }
- _, err = uploader.Upload(input)
- if err != nil {
- return err
- }
- _, err = driver.Request("https://www.123pan.com/api/file/upload_complete", base.Post, nil, nil, &base.Json{
- "fileId": resp.Data.FileId,
- }, nil, false, account)
- return err
-}
-
-//type UploadResp struct {
-// XMLName xml.Name `xml:"InitiateMultipartUploadResult"`
-// Bucket string `xml:"Bucket"`
-// Key string `xml:"Key"`
-// UploadId string `xml:"UploadId"`
-//}
-
-// TODO unfinished
-//func (driver Pan123) Upload(file *model.FileStream, account *model.Account) error {
-// return base.ErrNotImplement
-// parentFile, err := driver.File(file.ParentPath, account)
-// if err != nil {
-// return err
-// }
-// if !parentFile.IsDir() {
-// return base.ErrNotFolder
-// }
-// parentFileId, _ := strconv.Atoi(parentFile.Id)
-// data := base.Json{
-// "driveId": 0,
-// "duplicate": true,
-// "etag": RandStr(32), //maybe file's md5
-// "fileName": file.GetFileName(),
-// "parentFileId": parentFileId,
-// "size": file.GetSize(),
-// "type": 0,
-// }
-// res, err := driver.Request("https://www.123pan.com/api/file/upload_request",
-// base.Post, nil, nil, &data, nil, false, account)
-// //res, err := driver.Post("https://www.123pan.com/api/file/upload_request", data, account)
-// if err != nil {
-// return err
-// }
-// baseUrl := fmt.Sprintf("https://file.123pan.com/%s/%s", jsoniter.Get(res, "data.Bucket").ToString(), jsoniter.Get(res, "data.Key").ToString())
-// var resp UploadResp
-// kSecret := jsoniter.Get(res, "data.SecretAccessKey").ToString()
-// nowTimeStr := time.Now().String()
-// Date := strings.ReplaceAll(strings.Split(nowTimeStr, "T")[0], "-", "")
-//
-// StringToSign := fmt.Sprintf("%s\n%s\n%s\n%s",
-// "AWS4-HMAC-SHA256",
-// nowTimeStr,
-// fmt.Sprintf("%s/us-east-1/s3/aws4_request", Date),
-// )
-//
-// kDate := HMAC("AWS4"+kSecret, Date)
-// kRegion := HMAC(kDate, "us-east-1")
-// kService := HMAC(kRegion, "s3")
-// kSigning := HMAC(kService, "aws4_request")
-// _, err = base.RestyClient.R().SetResult(&resp).SetHeaders(map[string]string{
-// "Authorization": fmt.Sprintf("AWS4-HMAC-SHA256 Credential=%s/%s/us-east-1/s3/aws4_request, SignedHeaders=host;x-amz-content-sha256;x-amz-date;x-amz-security-token;x-amz-user-agent, Signature=%s",
-// jsoniter.Get(res, "data.AccessKeyId"),
-// Date,
-// hex.EncodeToString([]byte(HMAC(StringToSign, kSigning)))),
-// "X-Amz-Content-Sha256": "UNSIGNED-PAYLOAD",
-// "X-Amz-Date": nowTimeStr,
-// "x-amz-security-token": jsoniter.Get(res, "data.SessionToken").ToString(),
-// }).Post(fmt.Sprintf("%s?uploads", baseUrl))
-// if err != nil {
-// return err
-// }
-// return base.ErrNotImplement
-//}
-
-var _ base.Driver = (*Pan123)(nil)
diff --git a/drivers/123/types.go b/drivers/123/types.go
deleted file mode 100644
index c464628c..00000000
--- a/drivers/123/types.go
+++ /dev/null
@@ -1,74 +0,0 @@
-package _23
-
-import (
- "path"
- "time"
-
- "github.com/Xhofe/alist/conf"
- "github.com/Xhofe/alist/utils"
-)
-
-type File struct {
- FileName string `json:"FileName"`
- Size int64 `json:"Size"`
- UpdateAt *time.Time `json:"UpdateAt"`
- FileId int64 `json:"FileId"`
- Type int `json:"Type"`
- Etag string `json:"Etag"`
- S3KeyFlag string `json:"S3KeyFlag"`
- DownloadUrl string `json:"DownloadUrl"`
-}
-
-func (f File) GetSize() uint64 {
- return uint64(f.Size)
-}
-
-func (f File) GetName() string {
- return f.FileName
-}
-
-func (f File) GetType() int {
- if f.Type == 1 {
- return conf.FOLDER
- }
- return utils.GetFileType(path.Ext(f.FileName))
-}
-
-type BaseResp struct {
- Code int `json:"code"`
- Message string `json:"message"`
-}
-
-type Pan123TokenResp struct {
- BaseResp
- Data struct {
- Token string `json:"token"`
- } `json:"data"`
-}
-
-type Pan123Files struct {
- BaseResp
- Data struct {
- InfoList []File `json:"InfoList"`
- Next string `json:"Next"`
- } `json:"data"`
-}
-
-type Pan123DownResp struct {
- BaseResp
- Data struct {
- DownloadUrl string `json:"DownloadUrl"`
- } `json:"data"`
-}
-
-type UploadResp struct {
- BaseResp
- Data struct {
- AccessKeyId string `json:"AccessKeyId"`
- Bucket string `json:"Bucket"`
- Key string `json:"Key"`
- SecretAccessKey string `json:"SecretAccessKey"`
- SessionToken string `json:"SessionToken"`
- FileId int64 `json:"FileId"`
- } `json:"data"`
-}
diff --git a/drivers/139/139.go b/drivers/139/139.go
deleted file mode 100644
index fb6a412b..00000000
--- a/drivers/139/139.go
+++ /dev/null
@@ -1,175 +0,0 @@
-package _39
-
-import (
- "errors"
- "fmt"
- "github.com/Xhofe/alist/conf"
- "github.com/Xhofe/alist/drivers/base"
- "github.com/Xhofe/alist/model"
- "github.com/Xhofe/alist/utils"
- "github.com/go-resty/resty/v2"
- jsoniter "github.com/json-iterator/go"
- log "github.com/sirupsen/logrus"
- "path"
- "time"
-)
-
-func (driver Cloud139) Request(pathname string, method int, headers, query, form map[string]string, data interface{}, resp interface{}, account *model.Account) ([]byte, error) {
- url := "https://yun.139.com" + pathname
- req := base.RestyClient.R()
- randStr := utils.RandomStr(16)
- ts := time.Now().Format("2006-01-02 15:04:05")
- log.Debugf("%+v", data)
- body, err := utils.Json.Marshal(data)
- if err != nil {
- return nil, err
- }
- sign := calSign(string(body), ts, randStr)
- svcType := "1"
- if isFamily(account) {
- svcType = "2"
- }
- req.SetHeaders(map[string]string{
- "Accept": "application/json, text/plain, */*",
- "CMS-DEVICE": "default",
- "Cookie": account.AccessToken,
- "mcloud-channel": "1000101",
- "mcloud-client": "10701",
- //"mcloud-route": "001",
- "mcloud-sign": fmt.Sprintf("%s,%s,%s", ts, randStr, sign),
- //"mcloud-skey":"",
- "mcloud-version": "6.6.0",
- "Origin": "https://yun.139.com",
- "Referer": "https://yun.139.com/w/",
- "x-DeviceInfo": "||9|6.6.0|chrome|95.0.4638.69|uwIy75obnsRPIwlJSd7D9GhUvFwG96ce||macos 10.15.2||zh-CN|||",
- "x-huawei-channelSrc": "10000034",
- "x-inner-ntwk": "2",
- "x-m4c-caller": "PC",
- "x-m4c-src": "10002",
- "x-SvcType": svcType,
- })
- if headers != nil {
- req.SetHeaders(headers)
- }
- if query != nil {
- req.SetQueryParams(query)
- }
- if form != nil {
- req.SetFormData(form)
- }
- if data != nil {
- req.SetBody(data)
- }
- var e BaseResp
- //var err error
- var res *resty.Response
- req.SetResult(&e)
- switch method {
- case base.Get:
- res, err = req.Get(url)
- case base.Post:
- res, err = req.Post(url)
- case base.Delete:
- res, err = req.Delete(url)
- case base.Patch:
- res, err = req.Patch(url)
- case base.Put:
- res, err = req.Put(url)
- default:
- return nil, base.ErrNotSupport
- }
- if err != nil {
- return nil, err
- }
- log.Debugln(res.String())
- if !e.Success {
- return nil, errors.New(e.Message)
- }
- if resp != nil {
- err = utils.Json.Unmarshal(res.Body(), resp)
- if err != nil {
- return nil, err
- }
- }
- return res.Body(), nil
-}
-
-func (driver Cloud139) Post(pathname string, data interface{}, resp interface{}, account *model.Account) ([]byte, error) {
- return driver.Request(pathname, base.Post, nil, nil, nil, data, resp, account)
-}
-
-func (driver Cloud139) GetFiles(catalogID string, account *model.Account) ([]model.File, error) {
- start := 0
- limit := 100
- files := make([]model.File, 0)
- for {
- data := base.Json{
- "catalogID": catalogID,
- "sortDirection": 1,
- "startNumber": start + 1,
- "endNumber": start + limit,
- "filterType": 0,
- "catalogSortType": 0,
- "contentSortType": 0,
- "commonAccountInfo": base.Json{
- "account": account.Username,
- "accountType": 1,
- },
- }
- var resp GetDiskResp
- _, err := driver.Post("/orchestration/personalCloud/catalog/v1.0/getDisk", data, &resp, account)
- if err != nil {
- return nil, err
- }
- for _, catalog := range resp.Data.GetDiskResult.CatalogList {
- f := model.File{
- Id: catalog.CatalogID,
- Name: catalog.CatalogName,
- Size: 0,
- Type: conf.FOLDER,
- Driver: driver.Config().Name,
- UpdatedAt: getTime(catalog.UpdateTime),
- }
- files = append(files, f)
- }
- for _, content := range resp.Data.GetDiskResult.ContentList {
- f := model.File{
- Id: content.ContentID,
- Name: content.ContentName,
- Size: content.ContentSize,
- Type: utils.GetFileType(path.Ext(content.ContentName)),
- Driver: driver.Config().Name,
- UpdatedAt: getTime(content.UpdateTime),
- Thumbnail: content.ThumbnailURL,
- //Thumbnail: content.BigthumbnailURL,
- }
- files = append(files, f)
- }
- if start+limit >= resp.Data.GetDiskResult.NodeCount {
- break
- }
- start += limit
- }
- return files, nil
-}
-
-func (driver Cloud139) GetLink(contentId string, account *model.Account) (string, error) {
- data := base.Json{
- "appName": "",
- "contentID": contentId,
- "commonAccountInfo": base.Json{
- "account": account.Username,
- "accountType": 1,
- },
- }
- res, err := driver.Post("/orchestration/personalCloud/uploadAndDownload/v1.0/downloadRequest",
- data, nil, account)
- if err != nil {
- return "", err
- }
- return jsoniter.Get(res, "data", "downloadURL").ToString(), nil
-}
-
-func init() {
- base.RegisterDriver(&Cloud139{})
-}
diff --git a/drivers/139/driver.go b/drivers/139/driver.go
deleted file mode 100644
index 8864787c..00000000
--- a/drivers/139/driver.go
+++ /dev/null
@@ -1,457 +0,0 @@
-package _39
-
-import (
- "bytes"
- "fmt"
- "github.com/Xhofe/alist/conf"
- "github.com/Xhofe/alist/drivers/base"
- "github.com/Xhofe/alist/model"
- "github.com/Xhofe/alist/utils"
- log "github.com/sirupsen/logrus"
- "io"
- "math"
- "net/http"
- "path/filepath"
- "strconv"
-)
-
-type Cloud139 struct{}
-
-func (driver Cloud139) Config() base.DriverConfig {
- return base.DriverConfig{
- Name: "139Yun",
- LocalSort: true,
- }
-}
-
-func (driver Cloud139) Items() []base.Item {
- return []base.Item{
- {
- Name: "username",
- Label: "phone",
- Type: base.TypeString,
- Required: true,
- Description: "phone number",
- },
- {
- Name: "access_token",
- Label: "Cookie",
- Type: base.TypeString,
- Required: true,
- Description: "Unknown expiration time",
- },
- {
- Name: "internal_type",
- Label: "139yun type",
- Type: base.TypeSelect,
- Required: true,
- Values: "Personal,Family",
- },
- {
- Name: "root_folder",
- Label: "root folder file_id",
- Type: base.TypeString,
- Required: true,
- },
- {
- Name: "site_id",
- Label: "cloud_id",
- Type: base.TypeString,
- Required: false,
- },
- }
-}
-
-func (driver Cloud139) Save(account *model.Account, old *model.Account) error {
- if account == nil {
- return nil
- }
- _, err := driver.Request("/orchestration/personalCloud/user/v1.0/qryUserExternInfo", base.Post, nil, nil, nil, base.Json{
- "qryUserExternInfoReq": base.Json{
- "commonAccountInfo": base.Json{
- "account": account.Username,
- "accountType": 1,
- },
- },
- }, nil, account)
- return err
-}
-
-func (driver Cloud139) File(path string, account *model.Account) (*model.File, error) {
- path = utils.ParsePath(path)
- if path == "/" {
- return &model.File{
- Id: account.RootFolder,
- Name: account.Name,
- Size: 0,
- Type: conf.FOLDER,
- Driver: driver.Config().Name,
- UpdatedAt: account.UpdatedAt,
- }, nil
- }
- dir, name := filepath.Split(path)
- files, err := driver.Files(dir, account)
- if err != nil {
- return nil, err
- }
- for _, file := range files {
- if file.Name == name {
- return &file, nil
- }
- }
- return nil, base.ErrPathNotFound
-}
-
-func (driver Cloud139) Files(path string, account *model.Account) ([]model.File, error) {
- path = utils.ParsePath(path)
- var files []model.File
- cache, err := base.GetCache(path, account)
- if err == nil {
- files, _ = cache.([]model.File)
- } else {
- file, err := driver.File(path, account)
- if err != nil {
- return nil, err
- }
- if isFamily(account) {
- files, err = driver.familyGetFiles(file.Id, account)
- } else {
- files, err = driver.GetFiles(file.Id, account)
- }
- if err != nil {
- return nil, err
- }
- if len(files) > 0 {
- _ = base.SetCache(path, files, account)
- }
- }
- return files, nil
-}
-
-func (driver Cloud139) Link(args base.Args, account *model.Account) (*base.Link, error) {
- file, err := driver.File(args.Path, account)
- if err != nil {
- return nil, err
- }
- var u string
- //if isFamily(account) {
- // u, err = driver.familyLink(file.Id, account)
- //} else {
- u, err = driver.GetLink(file.Id, account)
- //}
- if err != nil {
- return nil, err
- }
- return &base.Link{Url: u}, nil
-}
-
-func (driver Cloud139) Path(path string, account *model.Account) (*model.File, []model.File, error) {
- path = utils.ParsePath(path)
- log.Debugf("139 path: %s", path)
- file, err := driver.File(path, account)
- if err != nil {
- return nil, nil, err
- }
- if !file.IsDir() {
- return file, nil, nil
- }
- files, err := driver.Files(path, account)
- if err != nil {
- return nil, nil, err
- }
- return nil, files, nil
-}
-
-//func (driver Cloud139) Proxy(r *http.Request, account *model.Account) {
-//
-//}
-
-func (driver Cloud139) Preview(path string, account *model.Account) (interface{}, error) {
- return nil, base.ErrNotSupport
-}
-
-func (driver Cloud139) MakeDir(path string, account *model.Account) error {
- parentFile, err := driver.File(utils.Dir(path), account)
- if err != nil {
- return err
- }
- data := base.Json{
- "createCatalogExtReq": base.Json{
- "parentCatalogID": parentFile.Id,
- "newCatalogName": utils.Base(path),
- "commonAccountInfo": base.Json{
- "account": account.Username,
- "accountType": 1,
- },
- },
- }
- pathname := "/orchestration/personalCloud/catalog/v1.0/createCatalogExt"
- if isFamily(account) {
- data = base.Json{
- "cloudID": account.SiteId,
- "commonAccountInfo": base.Json{
- "account": account.Username,
- "accountType": 1,
- },
- "docLibName": utils.Base(path),
- }
- pathname = "/orchestration/familyCloud/cloudCatalog/v1.0/createCloudDoc"
- }
- _, err = driver.Post(pathname,
- data, nil, account)
- return err
-}
-
-func (driver Cloud139) Move(src string, dst string, account *model.Account) error {
- if isFamily(account) {
- return base.ErrNotSupport
- }
- srcFile, err := driver.File(src, account)
- if err != nil {
- return err
- }
- dstParentFile, err := driver.File(utils.Dir(dst), account)
- if err != nil {
- return err
- }
- var contentInfoList []string
- var catalogInfoList []string
- if srcFile.IsDir() {
- catalogInfoList = append(catalogInfoList, srcFile.Id)
- } else {
- contentInfoList = append(contentInfoList, srcFile.Id)
- }
- data := base.Json{
- "createBatchOprTaskReq": base.Json{
- "taskType": 3,
- "actionType": "304",
- "taskInfo": base.Json{
- "contentInfoList": contentInfoList,
- "catalogInfoList": catalogInfoList,
- "newCatalogID": dstParentFile.Id,
- },
- "commonAccountInfo": base.Json{
- "account": account.Username,
- "accountType": 1,
- },
- },
- }
- pathname := "/orchestration/personalCloud/batchOprTask/v1.0/createBatchOprTask"
- _, err = driver.Post(pathname, data, nil, account)
- return err
-}
-
-func (driver Cloud139) Rename(src string, dst string, account *model.Account) error {
- if isFamily(account) {
- return base.ErrNotSupport
- }
- srcFile, err := driver.File(src, account)
- if err != nil {
- return err
- }
- var data base.Json
- var pathname string
- if srcFile.IsDir() {
- data = base.Json{
- "catalogID": srcFile.Id,
- "catalogName": utils.Base(dst),
- "commonAccountInfo": base.Json{
- "account": account.Username,
- "accountType": 1,
- },
- }
- pathname = "/orchestration/personalCloud/catalog/v1.0/updateCatalogInfo"
- } else {
- data = base.Json{
- "contentID": srcFile.Id,
- "contentName": utils.Base(dst),
- "commonAccountInfo": base.Json{
- "account": account.Username,
- "accountType": 1,
- },
- }
- pathname = "/orchestration/personalCloud/catalog/v1.0/updateContentInfo"
- }
- _, err = driver.Post(pathname, data, nil, account)
- return err
-}
-
-func (driver Cloud139) Copy(src string, dst string, account *model.Account) error {
- if isFamily(account) {
- return base.ErrNotSupport
- }
- srcFile, err := driver.File(src, account)
- if err != nil {
- return err
- }
- dstParentFile, err := driver.File(utils.Dir(dst), account)
- if err != nil {
- return err
- }
- var contentInfoList []string
- var catalogInfoList []string
- if srcFile.IsDir() {
- catalogInfoList = append(catalogInfoList, srcFile.Id)
- } else {
- contentInfoList = append(contentInfoList, srcFile.Id)
- }
- data := base.Json{
- "createBatchOprTaskReq": base.Json{
- "taskType": 3,
- "actionType": 309,
- "taskInfo": base.Json{
- "contentInfoList": contentInfoList,
- "catalogInfoList": catalogInfoList,
- "newCatalogID": dstParentFile.Id,
- },
- "commonAccountInfo": base.Json{
- "account": account.Username,
- "accountType": 1,
- },
- },
- }
- pathname := "/orchestration/personalCloud/batchOprTask/v1.0/createBatchOprTask"
- _, err = driver.Post(pathname, data, nil, account)
- return err
-}
-
-func (driver Cloud139) Delete(path string, account *model.Account) error {
- file, err := driver.File(path, account)
- if err != nil {
- return err
- }
- var contentInfoList []string
- var catalogInfoList []string
- if file.IsDir() {
- catalogInfoList = append(catalogInfoList, file.Id)
- } else {
- contentInfoList = append(contentInfoList, file.Id)
- }
- data := base.Json{
- "createBatchOprTaskReq": base.Json{
- "taskType": 2,
- "actionType": 201,
- "taskInfo": base.Json{
- "newCatalogID": "",
- "contentInfoList": contentInfoList,
- "catalogInfoList": catalogInfoList,
- },
- "commonAccountInfo": base.Json{
- "account": account.Username,
- "accountType": 1,
- },
- },
- }
- pathname := "/orchestration/personalCloud/batchOprTask/v1.0/createBatchOprTask"
- if isFamily(account) {
- data = base.Json{
- "catalogList": catalogInfoList,
- "contentList": contentInfoList,
- "commonAccountInfo": base.Json{
- "account": account.Username,
- "accountType": 1,
- },
- "sourceCatalogType": 1002,
- "taskType": 2,
- }
- pathname = "/orchestration/familyCloud/batchOprTask/v1.0/createBatchOprTask"
- }
- _, err = driver.Post(pathname, data, nil, account)
- return err
-}
-
-func (driver Cloud139) Upload(file *model.FileStream, account *model.Account) error {
- if file == nil {
- return base.ErrEmptyFile
- }
- parentFile, err := driver.File(file.ParentPath, account)
- if err != nil {
- return err
- }
- if !parentFile.IsDir() {
- return base.ErrNotFolder
- }
- data := base.Json{
- "manualRename": 2,
- "operation": 0,
- "fileCount": 1,
- "totalSize": file.Size,
- "uploadContentList": []base.Json{{
- "contentName": file.Name,
- "contentSize": file.Size,
- // "digest": "5a3231986ce7a6b46e408612d385bafa"
- }},
- "parentCatalogID": parentFile.Id,
- "newCatalogName": "",
- "commonAccountInfo": base.Json{
- "account": account.Username,
- "accountType": 1,
- },
- }
- pathname := "/orchestration/personalCloud/uploadAndDownload/v1.0/pcUploadFileRequest"
- if isFamily(account) {
- data = newJson(base.Json{
- "fileCount": 1,
- "manualRename": 2,
- "operation": 0,
- "path": "",
- "seqNo": "",
- "totalSize": file.Size,
- "uploadContentList": []base.Json{{
- "contentName": file.Name,
- "contentSize": file.Size,
- // "digest": "5a3231986ce7a6b46e408612d385bafa"
- }},
- }, account)
- pathname = "/orchestration/familyCloud/content/v1.0/getFileUploadURL"
- return base.ErrNotSupport
- }
- var resp UploadResp
- _, err = driver.Post(pathname, data, &resp, account)
- if err != nil {
- return err
- }
- var Default uint64 = 10485760
- part := int(math.Ceil(float64(file.Size) / float64(Default)))
- var start uint64 = 0
- for i := 0; i < part; i++ {
- byteSize := file.Size - start
- if byteSize > Default {
- byteSize = Default
- }
- byteData := make([]byte, byteSize)
- _, err = io.ReadFull(file, byteData)
- if err != nil {
- return err
- }
- req, err := http.NewRequest("POST", resp.Data.UploadResult.RedirectionURL, bytes.NewBuffer(byteData))
- if err != nil {
- return err
- }
- headers := map[string]string{
- "Accept": "*/*",
- "Content-Type": "text/plain;name=" + unicode(file.Name),
- "contentSize": strconv.FormatUint(file.Size, 10),
- "range": fmt.Sprintf("bytes=%d-%d", start, start+byteSize-1),
- "content-length": strconv.FormatUint(byteSize, 10),
- "uploadtaskID": resp.Data.UploadResult.UploadTaskID,
- "rangeType": "0",
- "Referer": "https://yun.139.com/",
- "User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.69 Safari/537.36 Edg/95.0.1020.44",
- "x-SvcType": "1",
- }
- for k, v := range headers {
- req.Header.Set(k, v)
- }
- res, err := base.HttpClient.Do(req)
- if err != nil {
- return err
- }
- log.Debugf("%+v", res)
- res.Body.Close()
- start += byteSize
- }
- return nil
-}
-
-var _ base.Driver = (*Cloud139)(nil)
diff --git a/drivers/139/family.go b/drivers/139/family.go
deleted file mode 100644
index 05f80853..00000000
--- a/drivers/139/family.go
+++ /dev/null
@@ -1,74 +0,0 @@
-package _39
-
-import (
- "github.com/Xhofe/alist/conf"
- "github.com/Xhofe/alist/drivers/base"
- "github.com/Xhofe/alist/model"
- "github.com/Xhofe/alist/utils"
- jsoniter "github.com/json-iterator/go"
- "path"
-)
-
-func (driver Cloud139) familyGetFiles(catalogID string, account *model.Account) ([]model.File, error) {
- pageNum := 1
- files := make([]model.File, 0)
- for {
- data := newJson(base.Json{
- "catalogID": catalogID,
- "contentSortType": 0,
- "pageInfo": base.Json{
- "pageNum": pageNum,
- "pageSize": 100,
- },
- "sortDirection": 1,
- }, account)
-
- var resp QueryContentListResp
- _, err := driver.Post("/orchestration/familyCloud/content/v1.0/queryContentList", data, &resp, account)
- if err != nil {
- return nil, err
- }
- for _, catalog := range resp.Data.CloudCatalogList {
- f := model.File{
- Id: catalog.CatalogID,
- Name: catalog.CatalogName,
- Size: 0,
- Type: conf.FOLDER,
- Driver: driver.Config().Name,
- UpdatedAt: getTime(catalog.LastUpdateTime),
- }
- files = append(files, f)
- }
- for _, content := range resp.Data.CloudContentList {
- f := model.File{
- Id: content.ContentID,
- Name: content.ContentName,
- Size: content.ContentSize,
- Type: utils.GetFileType(path.Ext(content.ContentName)),
- Driver: driver.Config().Name,
- UpdatedAt: getTime(content.LastUpdateTime),
- Thumbnail: content.ThumbnailURL,
- //Thumbnail: content.BigthumbnailURL,
- }
- files = append(files, f)
- }
- if 100*pageNum > resp.Data.TotalCount {
- break
- }
- pageNum++
- }
- return files, nil
-}
-
-func (driver Cloud139) familyLink(contentId string, account *model.Account) (string, error) {
- data := newJson(base.Json{
- "contentID": contentId,
- //"path":"",
- }, account)
- res, err := driver.Post("/orchestration/familyCloud/content/v1.0/getFileDownLoadURL",
- data, nil, account)
- if err != nil {
- return "", err
- }
- return jsoniter.Get(res, "data", "downloadURL").ToString(), nil
-}
diff --git a/drivers/139/types.go b/drivers/139/types.go
deleted file mode 100644
index 4973af26..00000000
--- a/drivers/139/types.go
+++ /dev/null
@@ -1,187 +0,0 @@
-package _39
-
-type BaseResp struct {
- Success bool `json:"success"`
- Code string `json:"code"`
- Message string `json:"message"`
-}
-
-type Catalog struct {
- CatalogID string `json:"catalogID"`
- CatalogName string `json:"catalogName"`
- //CatalogType int `json:"catalogType"`
- //CreateTime string `json:"createTime"`
- UpdateTime string `json:"updateTime"`
- //IsShared bool `json:"isShared"`
- //CatalogLevel int `json:"catalogLevel"`
- //ShareDoneeCount int `json:"shareDoneeCount"`
- //OpenType int `json:"openType"`
- //ParentCatalogID string `json:"parentCatalogId"`
- //DirEtag int `json:"dirEtag"`
- //Tombstoned int `json:"tombstoned"`
- //ProxyID interface{} `json:"proxyID"`
- //Moved int `json:"moved"`
- //IsFixedDir int `json:"isFixedDir"`
- //IsSynced interface{} `json:"isSynced"`
- //Owner string `json:"owner"`
- //Modifier interface{} `json:"modifier"`
- //Path string `json:"path"`
- //ShareType int `json:"shareType"`
- //SoftLink interface{} `json:"softLink"`
- //ExtProp1 interface{} `json:"extProp1"`
- //ExtProp2 interface{} `json:"extProp2"`
- //ExtProp3 interface{} `json:"extProp3"`
- //ExtProp4 interface{} `json:"extProp4"`
- //ExtProp5 interface{} `json:"extProp5"`
- //ETagOprType int `json:"ETagOprType"`
-}
-
-type Content struct {
- ContentID string `json:"contentID"`
- ContentName string `json:"contentName"`
- //ContentSuffix string `json:"contentSuffix"`
- ContentSize int64 `json:"contentSize"`
- //ContentDesc string `json:"contentDesc"`
- //ContentType int `json:"contentType"`
- //ContentOrigin int `json:"contentOrigin"`
- UpdateTime string `json:"updateTime"`
- //CommentCount int `json:"commentCount"`
- ThumbnailURL string `json:"thumbnailURL"`
- //BigthumbnailURL string `json:"bigthumbnailURL"`
- //PresentURL string `json:"presentURL"`
- //PresentLURL string `json:"presentLURL"`
- //PresentHURL string `json:"presentHURL"`
- //ContentTAGList interface{} `json:"contentTAGList"`
- //ShareDoneeCount int `json:"shareDoneeCount"`
- //Safestate int `json:"safestate"`
- //Transferstate int `json:"transferstate"`
- //IsFocusContent int `json:"isFocusContent"`
- //UpdateShareTime interface{} `json:"updateShareTime"`
- //UploadTime string `json:"uploadTime"`
- //OpenType int `json:"openType"`
- //AuditResult int `json:"auditResult"`
- //ParentCatalogID string `json:"parentCatalogId"`
- //Channel string `json:"channel"`
- //GeoLocFlag string `json:"geoLocFlag"`
- //Digest string `json:"digest"`
- //Version string `json:"version"`
- //FileEtag string `json:"fileEtag"`
- //FileVersion string `json:"fileVersion"`
- //Tombstoned int `json:"tombstoned"`
- //ProxyID string `json:"proxyID"`
- //Moved int `json:"moved"`
- //MidthumbnailURL string `json:"midthumbnailURL"`
- //Owner string `json:"owner"`
- //Modifier string `json:"modifier"`
- //ShareType int `json:"shareType"`
- //ExtInfo struct {
- // Uploader string `json:"uploader"`
- // Address string `json:"address"`
- //} `json:"extInfo"`
- //Exif struct {
- // CreateTime string `json:"createTime"`
- // Longitude interface{} `json:"longitude"`
- // Latitude interface{} `json:"latitude"`
- // LocalSaveTime interface{} `json:"localSaveTime"`
- //} `json:"exif"`
- //CollectionFlag interface{} `json:"collectionFlag"`
- //TreeInfo interface{} `json:"treeInfo"`
- //IsShared bool `json:"isShared"`
- //ETagOprType int `json:"ETagOprType"`
-}
-
-type GetDiskResp struct {
- BaseResp
- Data struct {
- Result struct {
- ResultCode string `json:"resultCode"`
- ResultDesc interface{} `json:"resultDesc"`
- } `json:"result"`
- GetDiskResult struct {
- ParentCatalogID string `json:"parentCatalogID"`
- NodeCount int `json:"nodeCount"`
- CatalogList []Catalog `json:"catalogList"`
- ContentList []Content `json:"contentList"`
- IsCompleted int `json:"isCompleted"`
- } `json:"getDiskResult"`
- } `json:"data"`
-}
-
-type UploadResp struct {
- BaseResp
- Data struct {
- Result struct {
- ResultCode string `json:"resultCode"`
- ResultDesc interface{} `json:"resultDesc"`
- } `json:"result"`
- UploadResult struct {
- UploadTaskID string `json:"uploadTaskID"`
- RedirectionURL string `json:"redirectionUrl"`
- NewContentIDList []struct {
- ContentID string `json:"contentID"`
- ContentName string `json:"contentName"`
- IsNeedUpload string `json:"isNeedUpload"`
- FileEtag int64 `json:"fileEtag"`
- FileVersion int64 `json:"fileVersion"`
- OverridenFlag int `json:"overridenFlag"`
- } `json:"newContentIDList"`
- CatalogIDList interface{} `json:"catalogIDList"`
- IsSlice interface{} `json:"isSlice"`
- } `json:"uploadResult"`
- } `json:"data"`
-}
-
-type CloudContent struct {
- ContentID string `json:"contentID"`
- //Modifier string `json:"modifier"`
- //Nickname string `json:"nickname"`
- //CloudNickName string `json:"cloudNickName"`
- ContentName string `json:"contentName"`
- //ContentType int `json:"contentType"`
- //ContentSuffix string `json:"contentSuffix"`
- ContentSize int64 `json:"contentSize"`
- //ContentDesc string `json:"contentDesc"`
- //CreateTime string `json:"createTime"`
- //Shottime interface{} `json:"shottime"`
- LastUpdateTime string `json:"lastUpdateTime"`
- ThumbnailURL string `json:"thumbnailURL"`
- //MidthumbnailURL string `json:"midthumbnailURL"`
- //BigthumbnailURL string `json:"bigthumbnailURL"`
- //PresentURL string `json:"presentURL"`
- //PresentLURL string `json:"presentLURL"`
- //PresentHURL string `json:"presentHURL"`
- //ParentCatalogID string `json:"parentCatalogID"`
- //Uploader string `json:"uploader"`
- //UploaderNickName string `json:"uploaderNickName"`
- //TreeInfo interface{} `json:"treeInfo"`
- //UpdateTime interface{} `json:"updateTime"`
- //ExtInfo struct {
- // Uploader string `json:"uploader"`
- //} `json:"extInfo"`
- //EtagOprType interface{} `json:"etagOprType"`
-}
-
-type CloudCatalog struct {
- CatalogID string `json:"catalogID"`
- CatalogName string `json:"catalogName"`
- //CloudID string `json:"cloudID"`
- //CreateTime string `json:"createTime"`
- LastUpdateTime string `json:"lastUpdateTime"`
- //Creator string `json:"creator"`
- //CreatorNickname string `json:"creatorNickname"`
-}
-
-type QueryContentListResp struct {
- BaseResp
- Data struct {
- Result struct {
- ResultCode string `json:"resultCode"`
- ResultDesc string `json:"resultDesc"`
- } `json:"result"`
- Path string `json:"path"`
- CloudContentList []CloudContent `json:"cloudContentList"`
- CloudCatalogList []CloudCatalog `json:"cloudCatalogList"`
- TotalCount int `json:"totalCount"`
- RecallContent interface{} `json:"recallContent"`
- } `json:"data"`
-}
diff --git a/drivers/139/util.go b/drivers/139/util.go
deleted file mode 100644
index 8d513ab3..00000000
--- a/drivers/139/util.go
+++ /dev/null
@@ -1,70 +0,0 @@
-package _39
-
-import (
- "encoding/base64"
- "github.com/Xhofe/alist/drivers/base"
- "github.com/Xhofe/alist/model"
- "github.com/Xhofe/alist/utils"
- "net/url"
- "sort"
- "strconv"
- "strings"
- "time"
-)
-
-func encodeURIComponent(str string) string {
- r := url.QueryEscape(str)
- r = strings.Replace(r, "+", "%20", -1)
- return r
-}
-
-func calSign(body, ts, randStr string) string {
- body = strings.ReplaceAll(body, "\n", "")
- body = strings.ReplaceAll(body, " ", "")
- body = encodeURIComponent(body)
- strs := strings.Split(body, "")
- sort.Strings(strs)
- body = strings.Join(strs, "")
- body = base64.StdEncoding.EncodeToString([]byte(body))
- res := utils.GetMD5Encode(body) + utils.GetMD5Encode(ts+":"+randStr)
- res = strings.ToUpper(utils.GetMD5Encode(res))
- return res
-}
-
-func getTime(t string) *time.Time {
- stamp, _ := time.ParseInLocation("20060102150405", t, time.Local)
- return &stamp
-}
-
-func isFamily(account *model.Account) bool {
- return account.InternalType == "Family"
-}
-
-func unicode(str string) string {
- textQuoted := strconv.QuoteToASCII(str)
- textUnquoted := textQuoted[1 : len(textQuoted)-1]
- return textUnquoted
-}
-
-func MergeMap(mObj ...map[string]interface{}) map[string]interface{} {
- newObj := map[string]interface{}{}
- for _, m := range mObj {
- for k, v := range m {
- newObj[k] = v
- }
- }
- return newObj
-}
-
-func newJson(data map[string]interface{}, account *model.Account) map[string]interface{} {
- common := map[string]interface{}{
- "catalogType": 3,
- "cloudID": account.SiteId,
- "cloudType": 1,
- "commonAccountInfo": base.Json{
- "account": account.Username,
- "accountType": 1,
- },
- }
- return MergeMap(data, common)
-}
diff --git a/drivers/189/189.go b/drivers/189/189.go
deleted file mode 100644
index fe611adf..00000000
--- a/drivers/189/189.go
+++ /dev/null
@@ -1,620 +0,0 @@
-package _89
-
-import (
- "bytes"
- "crypto/md5"
- "encoding/base64"
- "encoding/hex"
- "errors"
- "fmt"
- "io"
- "math"
- "net/http"
- "regexp"
- "strconv"
- "strings"
- "time"
-
- "github.com/Xhofe/alist/conf"
- "github.com/Xhofe/alist/drivers/base"
- "github.com/Xhofe/alist/model"
- "github.com/Xhofe/alist/utils"
- "github.com/go-resty/resty/v2"
- jsoniter "github.com/json-iterator/go"
- log "github.com/sirupsen/logrus"
-)
-
-var client189Map map[string]*resty.Client
-var infoMap = make(map[string]Rsa)
-
-func (driver Cloud189) getClient(account *model.Account) (*resty.Client, error) {
- client, ok := client189Map[account.Name]
- if ok {
- return client, nil
- }
- err := driver.Login(account)
- if err != nil {
- return nil, err
- }
- client, ok = client189Map[account.Name]
- if !ok {
- return nil, fmt.Errorf("can't find [%s] client", account.Name)
- }
- return client, nil
-}
-
-func (driver Cloud189) FormatFile(file *Cloud189File) *model.File {
- f := &model.File{
- Id: strconv.FormatInt(file.Id, 10),
- Name: file.Name,
- Size: file.Size,
- Driver: driver.Config().Name,
- UpdatedAt: nil,
- Thumbnail: file.Icon.SmallUrl,
- Url: file.Url,
- }
- loc, _ := time.LoadLocation("Local")
- lastOpTime, err := time.ParseInLocation("2006-01-02 15:04:05", file.LastOpTime, loc)
- if err == nil {
- f.UpdatedAt = &lastOpTime
- }
- if file.Size == -1 {
- f.Size = 0
- }
- f.Type = file.GetType()
- return f
-}
-
-//func (c Cloud189) GetFile(path string, account *model.Account) (*Cloud189File, error) {
-// dir, name := filepath.Split(path)
-// dir = utils.ParsePath(dir)
-// _, _, err := c.ParentPath(dir, account)
-// if err != nil {
-// return nil, err
-// }
-// parentFiles_, _ := conf.Cache.Get(conf.Ctx, fmt.Sprintf("%s%s", account.Name, dir))
-// parentFiles, _ := parentFiles_.([]Cloud189File)
-// for _, file := range parentFiles {
-// if file.Name == name {
-// if file.Size != -1 {
-// return &file, err
-// } else {
-// return nil, ErrNotFile
-// }
-// }
-// }
-// return nil, ErrPathNotFound
-//}
-
-type LoginResp struct {
- Msg string `json:"msg"`
- Result int `json:"result"`
- ToUrl string `json:"toUrl"`
-}
-
-// Login refer to PanIndex
-func (driver Cloud189) Login(account *model.Account) error {
- client := resty.New()
- //client.SetCookieJar(cookieJar)
- client.SetTimeout(base.DefaultTimeout)
- client.SetRetryCount(3)
- client.SetHeader("Referer", "https://cloud.189.cn/")
- client.SetHeader("User-Agent", base.UserAgent)
- url := "https://cloud.189.cn/api/portal/loginUrl.action?redirectURL=https%3A%2F%2Fcloud.189.cn%2Fmain.action"
- b := ""
- lt := ""
- ltText := regexp.MustCompile(`lt = "(.+?)"`)
- var res *resty.Response
- var err error
- for i := 0; i < 3; i++ {
- res, err = client.R().Get(url)
- if err != nil {
- return err
- }
- // 已经登陆
- if res.RawResponse.Request.URL.String() == "https://cloud.189.cn/web/main" {
- return nil
- }
- b = res.String()
- ltTextArr := ltText.FindStringSubmatch(b)
- if len(ltTextArr) > 0 {
- lt = ltTextArr[1]
- break
- } else {
- <-time.After(time.Second)
- }
- }
- if lt == "" {
- return fmt.Errorf("get page: %s \nstatus: %d \nrequest url: %s\nredirect url: %s",
- b, res.StatusCode(), res.RawResponse.Request.URL.String(), res.Header().Get("location"))
- }
- captchaToken := regexp.MustCompile(`captchaToken' value='(.+?)'`).FindStringSubmatch(b)[1]
- returnUrl := regexp.MustCompile(`returnUrl = '(.+?)'`).FindStringSubmatch(b)[1]
- paramId := regexp.MustCompile(`paramId = "(.+?)"`).FindStringSubmatch(b)[1]
- //reqId := regexp.MustCompile(`reqId = "(.+?)"`).FindStringSubmatch(b)[1]
- jRsakey := regexp.MustCompile(`j_rsaKey" value="(\S+)"`).FindStringSubmatch(b)[1]
- vCodeID := regexp.MustCompile(`picCaptcha\.do\?token\=([A-Za-z0-9\&\=]+)`).FindStringSubmatch(b)[1]
- vCodeRS := ""
- if vCodeID != "" {
- // need ValidateCode
- log.Debugf("try to identify verification codes")
- timeStamp := strconv.FormatInt(time.Now().UnixNano()/1e6, 10)
- u := "https://open.e.189.cn/api/logbox/oauth2/picCaptcha.do?token=" + vCodeID + timeStamp
- imgRes, err := client.R().SetHeaders(map[string]string{
- "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:74.0) Gecko/20100101 Firefox/76.0",
- "Referer": "https://open.e.189.cn/api/logbox/oauth2/unifyAccountLogin.do",
- "Sec-Fetch-Dest": "image",
- "Sec-Fetch-Mode": "no-cors",
- "Sec-Fetch-Site": "same-origin",
- }).Get(u)
- if err != nil {
- return err
- }
- vRes, err := client.R().SetMultipartField(
- "image", "validateCode.png", "image/png", bytes.NewReader(imgRes.Body())).
- Post(conf.GetStr("ocr api"))
- if err != nil {
- return err
- }
- if jsoniter.Get(vRes.Body(), "status").ToInt() != 200 {
- return errors.New("ocr error:" + jsoniter.Get(vRes.Body(), "msg").ToString())
- }
- vCodeRS = jsoniter.Get(vRes.Body(), "result").ToString()
- log.Debugln("code: ", vCodeRS)
- }
- userRsa := RsaEncode([]byte(account.Username), jRsakey, true)
- passwordRsa := RsaEncode([]byte(account.Password), jRsakey, true)
- url = "https://open.e.189.cn/api/logbox/oauth2/loginSubmit.do"
- var loginResp LoginResp
- res, err = client.R().
- SetHeaders(map[string]string{
- "lt": lt,
- "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Safari/537.36",
- "Referer": "https://open.e.189.cn/",
- "accept": "application/json;charset=UTF-8",
- }).SetFormData(map[string]string{
- "appKey": "cloud",
- "accountType": "01",
- "userName": "{RSA}" + userRsa,
- "password": "{RSA}" + passwordRsa,
- "validateCode": vCodeRS,
- "captchaToken": captchaToken,
- "returnUrl": returnUrl,
- "mailSuffix": "@pan.cn",
- "paramId": paramId,
- "clientType": "10010",
- "dynamicCheck": "FALSE",
- "cb_SaveName": "1",
- "isOauth2": "false",
- }).Post(url)
- if err != nil {
- return err
- }
- err = utils.Json.Unmarshal(res.Body(), &loginResp)
- if err != nil {
- log.Error(err.Error())
- return err
- }
- if loginResp.Result != 0 {
- return fmt.Errorf(loginResp.Msg)
- }
- _, err = client.R().Get(loginResp.ToUrl)
- if err != nil {
- log.Errorf(err.Error())
- return err
- }
- client189Map[account.Name] = client
- return nil
-}
-
-func (driver Cloud189) isFamily(account *model.Account) bool {
- return account.InternalType == "Family"
-}
-
-func (driver Cloud189) GetFiles(fileId string, account *model.Account) ([]Cloud189File, error) {
- res := make([]Cloud189File, 0)
- pageNum := 1
-
- for {
- var resp Cloud189Files
- body, err := driver.Request("https://cloud.189.cn/api/open/file/listFiles.action", base.Get, map[string]string{
- //"noCache": random(),
- "pageSize": "60",
- "pageNum": strconv.Itoa(pageNum),
- "mediaType": "0",
- "folderId": fileId,
- "iconOption": "5",
- "orderBy": "lastOpTime", //account.OrderBy
- "descending": "true", //account.OrderDirection
- }, nil, nil, account)
- if err != nil {
- return nil, err
- }
- err = utils.Json.Unmarshal(body, &resp)
- if err != nil {
- return nil, err
- }
- if resp.ResCode != 0 {
- return nil, fmt.Errorf(resp.ResMessage)
- }
- if resp.FileListAO.Count == 0 {
- break
- }
- for _, folder := range resp.FileListAO.FolderList {
- res = append(res, Cloud189File{
- Id: folder.Id,
- LastOpTime: folder.LastOpTime,
- Name: folder.Name,
- Size: -1,
- })
- }
- res = append(res, resp.FileListAO.FileList...)
- pageNum++
- }
- return res, nil
-}
-
-func (driver Cloud189) Request(url string, method int, query, form map[string]string, headers map[string]string, account *model.Account) ([]byte, error) {
- client, err := driver.getClient(account)
- if err != nil {
- return nil, err
- }
- //var resp base.Json
- if driver.isFamily(account) {
- url = strings.Replace(url, "/api/open", "/api/open/family", 1)
- if query != nil {
- query["familyId"] = account.SiteId
- }
- if form != nil {
- form["familyId"] = account.SiteId
- }
- }
- var e Cloud189Error
- req := client.R().SetError(&e).
- SetHeader("Accept", "application/json;charset=UTF-8").
- SetQueryParams(map[string]string{
- "noCache": random(),
- })
- if query != nil {
- req = req.SetQueryParams(query)
- }
- if form != nil {
- req = req.SetFormData(form)
- }
- if headers != nil {
- req = req.SetHeaders(headers)
- }
- var res *resty.Response
- switch method {
- case base.Get:
- res, err = req.Get(url)
- case base.Post:
- res, err = req.Post(url)
- default:
- return nil, base.ErrNotSupport
- }
- if err != nil {
- return nil, err
- }
- //log.Debug(res.String())
- if e.ErrorCode != "" {
- if e.ErrorCode == "InvalidSessionKey" {
- err = driver.Login(account)
- if err != nil {
- return nil, err
- }
- return driver.Request(url, method, query, form, nil, account)
- }
- }
- if jsoniter.Get(res.Body(), "res_code").ToInt() != 0 {
- err = errors.New(jsoniter.Get(res.Body(), "res_message").ToString())
- }
- return res.Body(), err
-}
-
-func (driver Cloud189) GetSessionKey(account *model.Account) (string, error) {
- //info, ok := infoMap[account.Name]
- //if !ok {
- // info = Info{}
- // infoMap[account.Name] = info
- //} else {
- // log.Debugf("hit")
- //}
- //if info.SessionKey != "" {
- // return info.SessionKey, nil
- //}
- resp, err := driver.Request("https://cloud.189.cn/v2/getUserBriefInfo.action", base.Get, nil, nil, nil, account)
- if err != nil {
- return "", err
- }
- sessionKey := jsoniter.Get(resp, "sessionKey").ToString()
- //info.SessionKey = sessionKey
- return sessionKey, nil
-}
-
-func (driver Cloud189) GetResKey(account *model.Account) (string, string, error) {
- rsa, ok := infoMap[account.Name]
- if !ok {
- rsa = Rsa{}
- infoMap[account.Name] = rsa
- }
- now := time.Now().UnixMilli()
- if rsa.Expire > now {
- return rsa.PubKey, rsa.PkId, nil
- }
- resp, err := driver.Request("https://cloud.189.cn/api/security/generateRsaKey.action", base.Get, nil, nil, nil, account)
- if err != nil {
- return "", "", err
- }
- pubKey, pkId := jsoniter.Get(resp, "pubKey").ToString(), jsoniter.Get(resp, "pkId").ToString()
- rsa.PubKey, rsa.PkId = pubKey, pkId
- rsa.Expire = jsoniter.Get(resp, "expire").ToInt64()
- return pubKey, pkId, nil
-}
-
-//func (driver Cloud189) UploadRequest1(uri string, form map[string]string, account *model.Account, resp interface{}) ([]byte, error) {
-// //sessionKey, err := driver.GetSessionKey(account)
-// //if err != nil {
-// // return nil, err
-// //}
-// sessionKey := account.DriveId
-// pubKey, pkId, err := driver.GetResKey(account)
-// log.Debugln(sessionKey, pubKey, pkId)
-// if err != nil {
-// return nil, err
-// }
-// xRId := Random("xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx")
-// pkey := Random("xxxxxxxxxxxx4xxxyxxxxxxxxxxxxxxx")[0 : 16+int(16*mathRand.Float32())]
-// params := hex.EncodeToString(AesEncrypt([]byte(qs(form)), []byte(pkey[0:16])))
-// date := strconv.FormatInt(time.Now().Unix(), 10)
-// a := make(url.Values)
-// a.Set("SessionKey", sessionKey)
-// a.Set("Operate", http.MethodGet)
-// a.Set("RequestURI", uri)
-// a.Set("Date", date)
-// a.Set("params", params)
-// signature := hex.EncodeToString(SHA1(EncodeParam(a), pkey))
-// encryptionText := RsaEncode([]byte(pkey), pubKey, false)
-// headers := map[string]string{
-// "signature": signature,
-// "sessionKey": sessionKey,
-// "encryptionText": encryptionText,
-// "pkId": pkId,
-// "x-request-id": xRId,
-// "x-request-date": date,
-// }
-// req := base.RestyClient.R().SetHeaders(headers).SetQueryParam("params", params)
-// if resp != nil {
-// req.SetResult(resp)
-// }
-// res, err := req.Get("https://upload.cloud.189.cn" + uri)
-// if err != nil {
-// return nil, err
-// }
-// //log.Debug(res.String())
-// data := res.Body()
-// if jsoniter.Get(data, "code").ToString() != "SUCCESS" {
-// return nil, errors.New(uri + "---" + jsoniter.Get(data, "msg").ToString())
-// }
-// return data, nil
-//}
-//
-//func (driver Cloud189) UploadRequest2(uri string, form map[string]string, account *model.Account, resp interface{}) ([]byte, error) {
-// c := strconv.FormatInt(time.Now().UnixMilli(), 10)
-// r := Random("xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx")
-// l := Random("xxxxxxxxxxxx4xxxyxxxxxxxxxxxxxxx")
-// l = l[0 : 16+int(16*mathRand.Float32())]
-//
-// e := qs(form)
-// data := AesEncrypt([]byte(e), []byte(l[0:16]))
-// h := hex.EncodeToString(data)
-//
-// sessionKey := account.DriveId
-// a := make(url.Values)
-// a.Set("SessionKey", sessionKey)
-// a.Set("Operate", http.MethodGet)
-// a.Set("RequestURI", uri)
-// a.Set("Date", c)
-// a.Set("params", h)
-// g := SHA1(EncodeParam(a), l)
-//
-// pubKey, pkId, err := driver.GetResKey(account)
-// if err != nil {
-// return nil, err
-// }
-// b := RsaEncode([]byte(l), pubKey, false)
-// client, err := driver.getClient(account)
-// if err != nil {
-// return nil, err
-// }
-// req := client.R()
-// req.Header.Set("accept", "application/json;charset=UTF-8")
-// req.Header.Set("SessionKey", sessionKey)
-// req.Header.Set("Signature", hex.EncodeToString(g))
-// req.Header.Set("X-Request-Date", c)
-// req.Header.Set("X-Request-ID", r)
-// req.Header.Set("EncryptionText", b)
-// req.Header.Set("PkId", pkId)
-// if resp != nil {
-// req.SetResult(resp)
-// }
-// res, err := req.Get("https://upload.cloud.189.cn" + uri + "?params=" + h)
-// if err != nil {
-// return nil, err
-// }
-// //log.Debug(res.String())
-// data = res.Body()
-// if jsoniter.Get(data, "code").ToString() != "SUCCESS" {
-// return nil, errors.New(uri + "---" + jsoniter.Get(data, "msg").ToString())
-// }
-// return data, nil
-//}
-
-func (driver Cloud189) UploadRequest(uri string, form map[string]string, account *model.Account, resp interface{}) ([]byte, error) {
- c := strconv.FormatInt(time.Now().UnixMilli(), 10)
- r := Random("xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx")
- l := Random("xxxxxxxxxxxx4xxxyxxxxxxxxxxxxxxx")
- l = l[0 : 16+int(16*utils.Rand.Float32())]
-
- e := qs(form)
- data := AesEncrypt([]byte(e), []byte(l[0:16]))
- h := hex.EncodeToString(data)
-
- sessionKey := account.DriveId
- signature := hmacSha1(fmt.Sprintf("SessionKey=%s&Operate=GET&RequestURI=%s&Date=%s¶ms=%s", sessionKey, uri, c, h), l)
-
- pubKey, pkId, err := driver.GetResKey(account)
- if err != nil {
- return nil, err
- }
- b := RsaEncode([]byte(l), pubKey, false)
- client, err := driver.getClient(account)
- if err != nil {
- return nil, err
- }
- req := client.R()
- req.Header.Set("accept", "application/json;charset=UTF-8")
- req.Header.Set("SessionKey", sessionKey)
- req.Header.Set("Signature", signature)
- req.Header.Set("X-Request-Date", c)
- req.Header.Set("X-Request-ID", r)
- req.Header.Set("EncryptionText", b)
- req.Header.Set("PkId", pkId)
- if resp != nil {
- req.SetResult(resp)
- }
- res, err := req.Get("https://upload.cloud.189.cn" + uri + "?params=" + h)
- if err != nil {
- return nil, err
- }
- //log.Debug(res.String())
- data = res.Body()
- if jsoniter.Get(data, "code").ToString() != "SUCCESS" {
- return nil, errors.New(uri + "---" + jsoniter.Get(data, "msg").ToString())
- }
- return data, nil
-}
-
-// NewUpload Error: signature check false
-func (driver Cloud189) NewUpload(file *model.FileStream, account *model.Account) error {
- sessionKey, err := driver.GetSessionKey(account)
- if err != nil {
- account.Status = err.Error()
- } else {
- account.Status = "work"
- account.DriveId = sessionKey
- }
- _ = model.SaveAccount(account)
- const DEFAULT uint64 = 10485760
- var count = int64(math.Ceil(float64(file.GetSize()) / float64(DEFAULT)))
- var finish uint64 = 0
- parentFile, err := driver.File(file.ParentPath, account)
- if err != nil {
- return err
- }
- if !parentFile.IsDir() {
- return base.ErrNotFolder
- }
- res, err := driver.UploadRequest("/person/initMultiUpload", map[string]string{
- "parentFolderId": parentFile.Id,
- "fileName": encode(file.Name),
- "fileSize": strconv.FormatInt(int64(file.Size), 10),
- "sliceSize": strconv.FormatInt(int64(DEFAULT), 10),
- "lazyCheck": "1",
- }, account, nil)
- if err != nil {
- return err
- }
- uploadFileId := jsoniter.Get(res, "data", "uploadFileId").ToString()
- //_, err = driver.UploadRequest("/person/getUploadedPartsInfo", map[string]string{
- // "uploadFileId": uploadFileId,
- //}, account, nil)
- var i int64
- var byteSize uint64
- md5s := make([]string, 0)
- md5Sum := md5.New()
- for i = 1; i <= count; i++ {
- byteSize = file.GetSize() - finish
- if DEFAULT < byteSize {
- byteSize = DEFAULT
- }
- //log.Debugf("%d,%d", byteSize, finish)
- byteData := make([]byte, byteSize)
- n, err := io.ReadFull(file, byteData)
- //log.Debug(err, n)
- if err != nil {
- return err
- }
- finish += uint64(n)
- md5Bytes := getMd5(byteData)
- md5Hex := hex.EncodeToString(md5Bytes)
- md5Base64 := base64.StdEncoding.EncodeToString(md5Bytes)
- md5s = append(md5s, strings.ToUpper(md5Hex))
- md5Sum.Write(byteData)
- //log.Debugf("md5Bytes: %+v,md5Str:%s,md5Base64:%s", md5Bytes, md5Hex, md5Base64)
- var resp UploadUrlsResp
- res, err = driver.UploadRequest("/person/getMultiUploadUrls", map[string]string{
- "partInfo": fmt.Sprintf("%s-%s", strconv.FormatInt(i, 10), md5Base64),
- "uploadFileId": uploadFileId,
- }, account, &resp)
- if err != nil {
- return err
- }
- uploadData := resp.UploadUrls["partNumber_"+strconv.FormatInt(i, 10)]
- log.Debugf("uploadData: %+v", uploadData)
- requestURL := uploadData.RequestURL
- uploadHeaders := strings.Split(decodeURIComponent(uploadData.RequestHeader), "&")
- req, _ := http.NewRequest(http.MethodPut, requestURL, bytes.NewReader(byteData))
- for _, v := range uploadHeaders {
- i := strings.Index(v, "=")
- req.Header.Set(v[0:i], v[i+1:])
- }
-
- r, err := base.HttpClient.Do(req)
- log.Debugf("%+v %+v", r, r.Request.Header)
- r.Body.Close()
- if err != nil {
- return err
- }
- }
- fileMd5 := hex.EncodeToString(md5Sum.Sum(nil))
- sliceMd5 := fileMd5
- if file.GetSize() > DEFAULT {
- sliceMd5 = utils.GetMD5Encode(strings.Join(md5s, "\n"))
- }
- res, err = driver.UploadRequest("/person/commitMultiUploadFile", map[string]string{
- "uploadFileId": uploadFileId,
- "fileMd5": fileMd5,
- "sliceMd5": sliceMd5,
- "lazyCheck": "1",
- }, account, nil)
- account.DriveId, _ = driver.GetSessionKey(account)
- return err
-}
-
-func (driver Cloud189) OldUpload(file *model.FileStream, account *model.Account) error {
- //return base.ErrNotImplement
- client, err := driver.getClient(account)
- if err != nil {
- return err
- }
- parentFile, err := driver.File(file.ParentPath, account)
- if err != nil {
- return err
- }
- // api refer to PanIndex
- res, err := client.R().SetMultipartFormData(map[string]string{
- "parentId": parentFile.Id,
- "sessionKey": account.DriveId,
- "opertype": "1",
- "fname": file.GetFileName(),
- }).SetMultipartField("Filedata", file.GetFileName(), file.GetMIMEType(), file).Post("https://hb02.upload.cloud.189.cn/v1/DCIWebUploadAction")
- if err != nil {
- return err
- }
- if jsoniter.Get(res.Body(), "MD5").ToString() != "" {
- return nil
- }
- log.Debugf(res.String())
- return errors.New(res.String())
-}
diff --git a/drivers/189/driver.go b/drivers/189/driver.go
deleted file mode 100644
index 1b9ab510..00000000
--- a/drivers/189/driver.go
+++ /dev/null
@@ -1,382 +0,0 @@
-package _89
-
-import (
- "fmt"
- "net/http"
- "path/filepath"
- "strings"
-
- "github.com/Xhofe/alist/conf"
- "github.com/Xhofe/alist/drivers/base"
- "github.com/Xhofe/alist/model"
- "github.com/Xhofe/alist/utils"
- "github.com/go-resty/resty/v2"
- log "github.com/sirupsen/logrus"
-)
-
-type Cloud189 struct{}
-
-func (driver Cloud189) Config() base.DriverConfig {
- return base.DriverConfig{
- Name: "189Cloud",
- LocalSort: true,
- }
-}
-
-func (driver Cloud189) Items() []base.Item {
- return []base.Item{
- {
- Name: "username",
- Label: "username",
- Type: base.TypeString,
- Required: true,
- Description: "account username/phone number",
- },
- {
- Name: "password",
- Label: "password",
- Type: base.TypeString,
- Required: true,
- Description: "account password",
- },
- {
- Name: "root_folder",
- Label: "root folder file_id",
- Type: base.TypeString,
- Required: true,
- },
- //{
- // Name: "internal_type",
- // Label: "189cloud type",
- // Type: base.TypeSelect,
- // Required: true,
- // Values: "Personal,Family",
- //},
- //{
- // Name: "site_id",
- // Label: "family id",
- // Type: base.TypeString,
- //},
- //{
- // Name: "order_by",
- // Label: "order_by",
- // Type: base.TypeSelect,
- // Values: "name,size,lastOpTime,createdDate",
- // Required: true,
- //},
- //{
- // Name: "order_direction",
- // Label: "desc",
- // Type: base.TypeSelect,
- // Values: "true,false",
- // Required: true,
- //},
- }
-}
-
-func (driver Cloud189) Save(account *model.Account, old *model.Account) error {
- if old != nil {
- delete(client189Map, old.Name)
- }
- if account == nil {
- return nil
- }
- if err := driver.Login(account); err != nil {
- account.Status = err.Error()
- _ = model.SaveAccount(account)
- return err
- }
- sessionKey, err := driver.GetSessionKey(account)
- if err != nil {
- account.Status = err.Error()
- } else {
- account.Status = "work"
- account.DriveId = sessionKey
- }
- _ = model.SaveAccount(account)
- return err
-}
-
-func (driver Cloud189) File(path string, account *model.Account) (*model.File, error) {
- path = utils.ParsePath(path)
- if path == "/" {
- return &model.File{
- Id: account.RootFolder,
- Name: account.Name,
- Size: 0,
- Type: conf.FOLDER,
- Driver: driver.Config().Name,
- UpdatedAt: account.UpdatedAt,
- }, nil
- }
- dir, name := filepath.Split(path)
- files, err := driver.Files(dir, account)
- if err != nil {
- return nil, err
- }
- for _, file := range files {
- if file.Name == name {
- return &file, nil
- }
- }
- return nil, base.ErrPathNotFound
-}
-
-func (driver Cloud189) Files(path string, account *model.Account) ([]model.File, error) {
- path = utils.ParsePath(path)
- var rawFiles []Cloud189File
- cache, err := base.GetCache(path, account)
- if err == nil {
- rawFiles, _ = cache.([]Cloud189File)
- } else {
- file, err := driver.File(path, account)
- if err != nil {
- return nil, err
- }
- rawFiles, err = driver.GetFiles(file.Id, account)
- if err != nil {
- return nil, err
- }
- if len(rawFiles) > 0 {
- _ = base.SetCache(path, rawFiles, account)
- }
- }
- files := make([]model.File, 0)
- for _, file := range rawFiles {
- files = append(files, *driver.FormatFile(&file))
- }
- return files, nil
-}
-
-func (driver Cloud189) Link(args base.Args, account *model.Account) (*base.Link, error) {
- file, err := driver.File(utils.ParsePath(args.Path), account)
- if err != nil {
- return nil, err
- }
- if file.Type == conf.FOLDER {
- return nil, base.ErrNotFile
- }
- var resp DownResp
- u := "https://cloud.189.cn/api/portal/getFileInfo.action"
- body, err := driver.Request(u, base.Get, map[string]string{
- "fileId": file.Id,
- }, nil, nil, account)
- if err != nil {
- return nil, err
- }
- log.Debugln(string(body))
- err = utils.Json.Unmarshal(body, &resp)
- if err != nil {
- return nil, err
- }
- if resp.ResCode != 0 {
- return nil, fmt.Errorf(resp.ResMessage)
- }
- client, err := driver.getClient(account)
- if err != nil {
- return nil, err
- }
- client = resty.NewWithClient(client.GetClient()).SetRedirectPolicy(
- resty.RedirectPolicyFunc(func(req *http.Request, via []*http.Request) error {
- return http.ErrUseLastResponse
- }))
- res, err := client.R().SetHeader("User-Agent", base.UserAgent).Get("https:" + resp.FileDownloadUrl)
- if err != nil {
- return nil, err
- }
- log.Debugln(res.Status())
- log.Debugln(res.String())
- link := base.Link{
- Headers: []base.Header{
- {Name: "User-Agent", Value: base.UserAgent},
- //{Name: "Authorization", Value: ""},
- },
- }
- log.Debugln("first url:", resp.FileDownloadUrl)
- if res.StatusCode() == 302 {
- link.Url = res.Header().Get("location")
- log.Debugln("second url:", link.Url)
- _, _ = client.R().Get(link.Url)
- if res.StatusCode() == 302 {
- link.Url = res.Header().Get("location")
- }
- log.Debugln("third url:", link.Url)
- } else {
- link.Url = resp.FileDownloadUrl
- }
- link.Url = strings.Replace(link.Url, "http://", "https://", 1)
- return &link, nil
-}
-
-func (driver Cloud189) Path(path string, account *model.Account) (*model.File, []model.File, error) {
- path = utils.ParsePath(path)
- log.Debugf("189 path: %s", path)
- file, err := driver.File(path, account)
- if err != nil {
- return nil, nil, err
- }
- if !file.IsDir() {
- return file, nil, nil
- }
- files, err := driver.Files(path, account)
- if err != nil {
- return nil, nil, err
- }
- return nil, files, nil
-}
-
-//func (driver Cloud189) Proxy(r *http.Request, account *model.Account) {
-// r.Header.Del("Origin")
-//}
-
-func (driver Cloud189) Preview(path string, account *model.Account) (interface{}, error) {
- return nil, base.ErrNotSupport
-}
-
-func (driver Cloud189) MakeDir(path string, account *model.Account) error {
- dir, name := filepath.Split(path)
- parent, err := driver.File(dir, account)
- if err != nil {
- return err
- }
- if !parent.IsDir() {
- return base.ErrNotFolder
- }
- form := map[string]string{
- "parentFolderId": parent.Id,
- "folderName": name,
- }
- _, err = driver.Request("https://cloud.189.cn/api/open/file/createFolder.action", base.Post, nil, form, nil, account)
- return err
-}
-
-func (driver Cloud189) Move(src string, dst string, account *model.Account) error {
- dstDir, dstName := filepath.Split(dst)
- srcFile, err := driver.File(src, account)
- if err != nil {
- return err
- }
- dstDirFile, err := driver.File(dstDir, account)
- if err != nil {
- return err
- }
- isFolder := 0
- if srcFile.IsDir() {
- isFolder = 1
- }
- taskInfos := []base.Json{
- {
- "fileId": srcFile.Id,
- "fileName": dstName,
- "isFolder": isFolder,
- },
- }
- taskInfosBytes, err := utils.Json.Marshal(taskInfos)
- if err != nil {
- return err
- }
- form := map[string]string{
- "type": "MOVE",
- "targetFolderId": dstDirFile.Id,
- "taskInfos": string(taskInfosBytes),
- }
- _, err = driver.Request("https://cloud.189.cn/api/open/batch/createBatchTask.action", base.Post, nil, form, nil, account)
- return err
-}
-
-func (driver Cloud189) Rename(src string, dst string, account *model.Account) error {
- _, dstName := filepath.Split(dst)
- srcFile, err := driver.File(src, account)
- if err != nil {
- return err
- }
- url := "https://cloud.189.cn/api/open/file/renameFile.action"
- idKey := "fileId"
- nameKey := "destFileName"
- if srcFile.IsDir() {
- url = "https://cloud.189.cn/api/open/file/renameFolder.action"
- idKey = "folderId"
- nameKey = "destFolderName"
- }
- form := map[string]string{
- idKey: srcFile.Id,
- nameKey: dstName,
- }
- _, err = driver.Request(url, base.Post, nil, form, nil, account)
- return err
-}
-
-func (driver Cloud189) Copy(src string, dst string, account *model.Account) error {
- dstDir, dstName := filepath.Split(dst)
- srcFile, err := driver.File(src, account)
- if err != nil {
- return err
- }
- dstDirFile, err := driver.File(dstDir, account)
- if err != nil {
- return err
- }
- isFolder := 0
- if srcFile.IsDir() {
- isFolder = 1
- }
- taskInfos := []base.Json{
- {
- "fileId": srcFile.Id,
- "fileName": dstName,
- "isFolder": isFolder,
- },
- }
- taskInfosBytes, err := utils.Json.Marshal(taskInfos)
- if err != nil {
- return err
- }
- form := map[string]string{
- "type": "COPY",
- "targetFolderId": dstDirFile.Id,
- "taskInfos": string(taskInfosBytes),
- }
- _, err = driver.Request("https://cloud.189.cn/api/open/batch/createBatchTask.action", base.Post, nil, form, nil, account)
- return err
-}
-
-func (driver Cloud189) Delete(path string, account *model.Account) error {
- path = utils.ParsePath(path)
- file, err := driver.File(path, account)
- if err != nil {
- return err
- }
- isFolder := 0
- if file.IsDir() {
- isFolder = 1
- }
- taskInfos := []base.Json{
- {
- "fileId": file.Id,
- "fileName": file.Name,
- "isFolder": isFolder,
- },
- }
- taskInfosBytes, err := utils.Json.Marshal(taskInfos)
- if err != nil {
- return err
- }
- form := map[string]string{
- "type": "DELETE",
- "targetFolderId": "",
- "taskInfos": string(taskInfosBytes),
- }
- _, err = driver.Request("https://cloud.189.cn/api/open/batch/createBatchTask.action", base.Post, nil, form, nil, account)
- return err
-}
-
-func (driver Cloud189) Upload(file *model.FileStream, account *model.Account) error {
- //return base.ErrNotImplement
- if file == nil {
- return base.ErrEmptyFile
- }
- return driver.NewUpload(file, account)
- //return driver.OldUpload(file, account)
-}
-
-var _ base.Driver = (*Cloud189)(nil)
diff --git a/drivers/189/types.go b/drivers/189/types.go
deleted file mode 100644
index 267fdef4..00000000
--- a/drivers/189/types.go
+++ /dev/null
@@ -1,91 +0,0 @@
-package _89
-
-import (
- "github.com/Xhofe/alist/conf"
- "github.com/Xhofe/alist/utils"
- "path"
-)
-
-type Cloud189Error struct {
- ErrorCode string `json:"errorCode"`
- ErrorMsg string `json:"errorMsg"`
-}
-
-type Cloud189File struct {
- Id int64 `json:"id"`
- LastOpTime string `json:"lastOpTime"`
- Name string `json:"name"`
- Size int64 `json:"size"`
- Icon struct {
- SmallUrl string `json:"smallUrl"`
- //LargeUrl string `json:"largeUrl"`
- } `json:"icon"`
- Url string `json:"url"`
-}
-
-func (f Cloud189File) GetSize() uint64 {
- if f.Size == -1 {
- return 0
- }
- return uint64(f.Size)
-}
-
-func (f Cloud189File) GetName() string {
- return f.Name
-}
-
-func (f Cloud189File) GetType() int {
- if f.Size == -1 {
- return conf.FOLDER
- }
- return utils.GetFileType(path.Ext(f.Name))
-}
-
-type Cloud189Folder struct {
- Id int64 `json:"id"`
- LastOpTime string `json:"lastOpTime"`
- Name string `json:"name"`
-}
-
-type Cloud189Files struct {
- ResCode int `json:"res_code"`
- ResMessage string `json:"res_message"`
- FileListAO struct {
- Count int `json:"count"`
- FileList []Cloud189File `json:"fileList"`
- FolderList []Cloud189Folder `json:"folderList"`
- } `json:"fileListAO"`
-}
-
-type UploadUrlsResp struct {
- Code string `json:"code"`
- UploadUrls map[string]Part `json:"uploadUrls"`
-}
-
-type Part struct {
- RequestURL string `json:"requestURL"`
- RequestHeader string `json:"requestHeader"`
-}
-
-//type Info struct {
-// SessionKey string
-// Rsa Rsa
-//}
-
-type Rsa struct {
- Expire int64 `json:"expire"`
- PkId string `json:"pkId"`
- PubKey string `json:"pubKey"`
-}
-
-type Cloud189Down struct {
- ResCode int `json:"res_code"`
- ResMessage string `json:"res_message"`
- FileDownloadUrl string `json:"fileDownloadUrl"`
-}
-
-type DownResp struct {
- ResCode int `json:"res_code"`
- ResMessage string `json:"res_message"`
- FileDownloadUrl string `json:"downloadUrl"`
-}
diff --git a/drivers/189/util.go b/drivers/189/util.go
deleted file mode 100644
index c079af87..00000000
--- a/drivers/189/util.go
+++ /dev/null
@@ -1,199 +0,0 @@
-package _89
-
-import (
- "bytes"
- "crypto/aes"
- "crypto/hmac"
- "crypto/md5"
- "crypto/rand"
- "crypto/rsa"
- "crypto/sha1"
- "crypto/x509"
- "encoding/base64"
- "encoding/hex"
- "encoding/pem"
- "fmt"
- "github.com/Xhofe/alist/drivers/base"
- "github.com/Xhofe/alist/utils"
- "github.com/go-resty/resty/v2"
- log "github.com/sirupsen/logrus"
- "net/url"
- "regexp"
- "strconv"
- "strings"
-)
-
-func random() string {
- return fmt.Sprintf("0.%17v", utils.Rand.Int63n(100000000000000000))
-}
-
-func RsaEncode(origData []byte, j_rsakey string, hex bool) string {
- publicKey := []byte("-----BEGIN PUBLIC KEY-----\n" + j_rsakey + "\n-----END PUBLIC KEY-----")
- block, _ := pem.Decode(publicKey)
- pubInterface, _ := x509.ParsePKIXPublicKey(block.Bytes)
- pub := pubInterface.(*rsa.PublicKey)
- b, err := rsa.EncryptPKCS1v15(rand.Reader, pub, origData)
- if err != nil {
- log.Errorf("err: %s", err.Error())
- }
- res := base64.StdEncoding.EncodeToString(b)
- if hex {
- return b64tohex(res)
- }
- return res
-}
-
-var b64map = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
-
-var BI_RM = "0123456789abcdefghijklmnopqrstuvwxyz"
-
-func int2char(a int) string {
- return strings.Split(BI_RM, "")[a]
-}
-
-func b64tohex(a string) string {
- d := ""
- e := 0
- c := 0
- for i := 0; i < len(a); i++ {
- m := strings.Split(a, "")[i]
- if m != "=" {
- v := strings.Index(b64map, m)
- if 0 == e {
- e = 1
- d += int2char(v >> 2)
- c = 3 & v
- } else if 1 == e {
- e = 2
- d += int2char(c<<2 | v>>4)
- c = 15 & v
- } else if 2 == e {
- e = 3
- d += int2char(c)
- d += int2char(v >> 2)
- c = 3 & v
- } else {
- e = 0
- d += int2char(c<<2 | v>>4)
- d += int2char(15 & v)
- }
- }
- }
- if e == 1 {
- d += int2char(c << 2)
- }
- return d
-}
-
-func qs(form map[string]string) string {
- f := make(url.Values)
- for k, v := range form {
- f.Set(k, v)
- }
- return EncodeParam(f)
- //strList := make([]string, 0)
- //for k, v := range form {
- // strList = append(strList, fmt.Sprintf("%s=%s", k, url.QueryEscape(v)))
- //}
- //return strings.Join(strList, "&")
-}
-
-func EncodeParam(v url.Values) string {
- if v == nil {
- return ""
- }
- var buf strings.Builder
- keys := make([]string, 0, len(v))
- for k := range v {
- keys = append(keys, k)
- }
- for _, k := range keys {
- vs := v[k]
- for _, v := range vs {
- if buf.Len() > 0 {
- buf.WriteByte('&')
- }
- buf.WriteString(k)
- buf.WriteByte('=')
- //if k == "fileName" {
- // buf.WriteString(encode(v))
- //} else {
- buf.WriteString(v)
- //}
- }
- }
- return buf.String()
-}
-
-func encode(str string) string {
- //str = strings.ReplaceAll(str, "%", "%25")
- //str = strings.ReplaceAll(str, "&", "%26")
- //str = strings.ReplaceAll(str, "+", "%2B")
- //return str
- return url.QueryEscape(str)
-}
-
-func AesEncrypt(data, key []byte) []byte {
- block, _ := aes.NewCipher(key)
- if block == nil {
- return []byte{}
- }
- data = PKCS7Padding(data, block.BlockSize())
- decrypted := make([]byte, len(data))
- size := block.BlockSize()
- for bs, be := 0, size; bs < len(data); bs, be = bs+size, be+size {
- block.Encrypt(decrypted[bs:be], data[bs:be])
- }
- return decrypted
-}
-
-func PKCS7Padding(ciphertext []byte, blockSize int) []byte {
- padding := blockSize - len(ciphertext)%blockSize
- padtext := bytes.Repeat([]byte{byte(padding)}, padding)
- return append(ciphertext, padtext...)
-}
-
-func hmacSha1(data string, secret string) string {
- h := hmac.New(sha1.New, []byte(secret))
- h.Write([]byte(data))
- return hex.EncodeToString(h.Sum(nil))
-}
-
-func getMd5(data []byte) []byte {
- h := md5.New()
- h.Write(data)
- return h.Sum(nil)
-}
-
-func init() {
- base.RegisterDriver(&Cloud189{})
- client189Map = make(map[string]*resty.Client)
-}
-
-func decodeURIComponent(str string) string {
- r, _ := url.PathUnescape(str)
- //r = strings.ReplaceAll(r, " ", "+")
- return r
-}
-
-func Random(v string) string {
- reg := regexp.MustCompilePOSIX("[xy]")
- data := reg.ReplaceAllFunc([]byte(v), func(msg []byte) []byte {
- var i int64
- t := int64(16 * utils.Rand.Float32())
- if msg[0] == 120 {
- i = t
- } else {
- i = 3&t | 8
- }
- return []byte(strconv.FormatInt(i, 16))
- })
- return string(data)
-}
-
-//func SHA1(v, l string) []byte {
-// key := []byte(l)
-// mac := hmac.New(sha1.New, key)
-// mac.Write([]byte(v))
-// return mac.Sum(nil)
-//}
diff --git a/drivers/189pc/189.go b/drivers/189pc/189.go
deleted file mode 100644
index b6f72f6b..00000000
--- a/drivers/189pc/189.go
+++ /dev/null
@@ -1,318 +0,0 @@
-package _189
-
-import (
- "bytes"
- "errors"
- "fmt"
- "net/http"
- "net/http/cookiejar"
- "net/url"
- "regexp"
- "sync"
-
- "github.com/Xhofe/alist/conf"
- "github.com/Xhofe/alist/drivers/base"
- "github.com/Xhofe/alist/model"
- "github.com/Xhofe/alist/utils"
- "github.com/go-resty/resty/v2"
- "github.com/google/uuid"
- log "github.com/sirupsen/logrus"
-)
-
-var userStateCache = struct {
- sync.Mutex
- States map[string]*State
-}{States: make(map[string]*State)}
-
-func GetState(account *model.Account) *State {
- userStateCache.Lock()
- defer userStateCache.Unlock()
- if v, ok := userStateCache.States[account.Username]; ok && v != nil {
- return v
- }
- state := &State{client: resty.New().
- SetHeaders(map[string]string{
- "Accept": "application/json;charset=UTF-8",
- "User-Agent": base.UserAgent,
- }).SetTimeout(base.DefaultTimeout),
- }
- userStateCache.States[account.Username] = state
- return state
-}
-
-type State struct {
- sync.Mutex
- client *resty.Client
-
- RsaPublicKey string
-
- SessionKey string
- SessionSecret string
- FamilySessionKey string
- FamilySessionSecret string
-
- AccessToken string
-
- //怎么刷新的???
- RefreshToken string
-}
-
-func (s *State) login(account *model.Account) error {
- // 清除cookie
- jar, _ := cookiejar.New(nil)
- s.client.SetCookieJar(jar)
-
- var err error
- var res *resty.Response
- defer func() {
- account.Status = "work"
- if err != nil {
- account.Status = err.Error()
- }
- model.SaveAccount(account)
- if res != nil {
- log.Debug(res.String())
- }
- }()
-
- var param *LoginParam
- param, err = s.getLoginParam()
- if err != nil {
- return err
- }
-
- // 提交登录
- s.RsaPublicKey = fmt.Sprintf("-----BEGIN PUBLIC KEY-----\n%s\n-----END PUBLIC KEY-----", param.jRsaKey)
- res, err = s.client.R().
- SetHeaders(map[string]string{
- "Referer": AUTH_URL,
- "REQID": param.ReqId,
- "lt": param.Lt,
- }).
- SetFormData(map[string]string{
- "appKey": APP_ID,
- "accountType": "02",
- "userName": "{RSA}" + rsaEncrypt(s.RsaPublicKey, account.Username),
- "password": "{RSA}" + rsaEncrypt(s.RsaPublicKey, account.Password),
- "validateCode": param.vCodeRS,
- "captchaToken": param.CaptchaToken,
- "returnUrl": RETURN_URL,
- "mailSuffix": "@189.cn",
- "dynamicCheck": "FALSE",
- "clientType": CLIENT_TYPE,
- "cb_SaveName": "1",
- "isOauth2": "false",
- "state": "",
- "paramId": param.ParamId,
- }).
- Post(AUTH_URL + "/api/logbox/oauth2/loginSubmit.do")
- if err != nil {
- return err
- }
- toUrl := utils.Json.Get(res.Body(), "toUrl").ToString()
- if toUrl == "" {
- log.Error(res.String())
- return fmt.Errorf(res.String())
- }
-
- // 获取Session
- var erron Erron
- var sessionResp appSessionResp
- res, err = s.client.R().
- SetResult(&sessionResp).SetError(&erron).
- SetQueryParams(clientSuffix()).
- SetQueryParam("redirectURL", url.QueryEscape(toUrl)).
- Post(API_URL + "/getSessionForPC.action")
- if err != nil {
- return err
- }
-
- if erron.ResCode != "" {
- err = fmt.Errorf(erron.ResMessage)
- return err
- }
- if sessionResp.ResCode != 0 {
- err = fmt.Errorf(sessionResp.ResMessage)
- return err
- }
- s.SessionKey = sessionResp.SessionKey
- s.SessionSecret = sessionResp.SessionSecret
- s.FamilySessionKey = sessionResp.FamilySessionKey
- s.FamilySessionSecret = sessionResp.FamilySessionSecret
- s.AccessToken = sessionResp.AccessToken
- s.RefreshToken = sessionResp.RefreshToken
- return err
-}
-
-func (s *State) getLoginParam() (*LoginParam, error) {
- res, err := s.client.R().
- SetQueryParams(map[string]string{
- "appId": APP_ID,
- "clientType": CLIENT_TYPE,
- "returnURL": RETURN_URL,
- "timeStamp": fmt.Sprint(timestamp()),
- }).
- Get(WEB_URL + "/api/portal/unifyLoginForPC.action")
- if err != nil {
- return nil, err
- }
- log.Debug(res.String())
- param := &LoginParam{
- CaptchaToken: regexp.MustCompile(`'captchaToken' value='(.+?)'`).FindStringSubmatch(res.String())[1],
- Lt: regexp.MustCompile(`lt = "(.+?)"`).FindStringSubmatch(res.String())[1],
- ParamId: regexp.MustCompile(`paramId = "(.+?)"`).FindStringSubmatch(res.String())[1],
- ReqId: regexp.MustCompile(`reqId = "(.+?)"`).FindStringSubmatch(res.String())[1],
- jRsaKey: regexp.MustCompile(`"j_rsaKey" value="(.+?)"`).FindStringSubmatch(res.String())[1],
-
- vCodeID: regexp.MustCompile(`token=([A-Za-z0-9&=]+)`).FindStringSubmatch(res.String())[1],
- }
-
- imgRes, err := s.client.R().Get(fmt.Sprint(AUTH_URL, "/api/logbox/oauth2/picCaptcha.do?token=", param.vCodeID, timestamp()))
- if err != nil {
- return nil, err
- }
- if len(imgRes.Body()) > 0 {
- vRes, err := resty.New().R().
- SetMultipartField("image", "validateCode.png", "image/png", bytes.NewReader(imgRes.Body())).
- Post(conf.GetStr("ocr api"))
- if err != nil {
- return nil, err
- }
- if utils.Json.Get(vRes.Body(), "status").ToInt() != 200 {
- return nil, errors.New("ocr error:" + utils.Json.Get(vRes.Body(), "msg").ToString())
- }
- param.vCodeRS = utils.Json.Get(vRes.Body(), "result").ToString()
- log.Debugln("code: ", param.vCodeRS)
- }
- return param, nil
-}
-
-func (s *State) refreshSession(account *model.Account) error {
- var erron Erron
- var userSessionResp UserSessionResp
- res, err := s.client.R().
- SetResult(&userSessionResp).SetError(&erron).
- SetQueryParams(clientSuffix()).
- SetQueryParams(map[string]string{
- "appId": APP_ID,
- "accessToken": s.AccessToken,
- }).
- SetHeader("X-Request-ID", uuid.NewString()).
- Get(API_URL + "/getSessionForPC.action")
- if err != nil {
- return err
- }
- log.Debug(res.String())
- if erron.ResCode != "" {
- return fmt.Errorf(erron.ResMessage)
- }
-
- switch userSessionResp.ResCode {
- case 0:
- s.SessionKey = userSessionResp.SessionKey
- s.SessionSecret = userSessionResp.SessionSecret
- s.FamilySessionKey = userSessionResp.FamilySessionKey
- s.FamilySessionSecret = userSessionResp.FamilySessionSecret
- case 11, 18:
- return s.login(account)
- default:
- account.Status = userSessionResp.ResMessage
- _ = model.SaveAccount(account)
- return fmt.Errorf(userSessionResp.ResMessage)
- }
- return nil
-}
-
-func (s *State) IsLogin(account *model.Account) bool {
- _, err := s.Request(http.MethodGet, API_URL+"/getUserInfo.action", nil, func(r *resty.Request) { r.SetQueryParams(clientSuffix()) }, account)
- return err == nil
-}
-
-func (s *State) Login(account *model.Account) error {
- s.Lock()
- defer s.Unlock()
- return s.login(account)
-}
-
-func (s *State) RefreshSession(account *model.Account) error {
- s.Lock()
- defer s.Unlock()
- return s.refreshSession(account)
-}
-
-func (s *State) Request(method string, fullUrl string, params Params, callback func(*resty.Request), account *model.Account) (*resty.Response, error) {
- s.Lock()
- dateOfGmt := getHttpDateStr()
- sessionKey := s.SessionKey
- sessionSecret := s.SessionSecret
- if isFamily(account) {
- sessionKey = s.FamilySessionKey
- sessionSecret = s.FamilySessionSecret
- }
-
- req := s.client.R()
- req.SetHeaders(map[string]string{
- "Date": dateOfGmt,
- "SessionKey": sessionKey,
- "X-Request-ID": uuid.NewString(),
- })
-
- // 设置params
- var paramsData string
- if params != nil {
- paramsData = AesECBEncrypt(params.Encode(), s.SessionSecret[:16])
- req.SetQueryParam("params", paramsData)
- }
- req.SetHeader("Signature", signatureOfHmac(sessionSecret, sessionKey, method, fullUrl, dateOfGmt, paramsData))
-
- if callback != nil {
- callback(req)
- }
- s.Unlock()
-
- res, err := req.Execute(method, fullUrl)
- if err != nil {
- return nil, err
- }
- log.Debug(res.String())
-
- var erron Erron
- utils.Json.Unmarshal(res.Body(), &erron)
- if erron.ResCode != "" {
- return nil, fmt.Errorf(erron.ResMessage)
- }
- if erron.Code != "" && erron.Code != "SUCCESS" {
- if erron.Msg == "" {
- if erron.Message == "" {
- return nil, fmt.Errorf(res.String())
- }
- return nil, fmt.Errorf(erron.Message)
- }
- return nil, fmt.Errorf(erron.Msg)
- }
- if erron.ErrorCode != "" {
- switch erron.ErrorCode {
- case "InvalidSessionKey":
- if err := s.RefreshSession(account); err != nil {
- return nil, err
- }
- return s.Request(method, fullUrl, params, callback, account)
- }
- return nil, fmt.Errorf(erron.ErrorMsg)
- }
-
- switch utils.Json.Get(res.Body(), "res_code").ToInt64() {
- case 11, 18:
- if err := s.RefreshSession(account); err != nil {
- return nil, err
- }
- return s.Request(method, fullUrl, params, callback, account)
- case 0:
- if res.StatusCode() == http.StatusOK {
- return res, nil
- }
- return nil, fmt.Errorf(res.String())
- default:
- return nil, fmt.Errorf(utils.Json.Get(res.Body(), "res_message").ToString())
- }
-}
diff --git a/drivers/189pc/driver.go b/drivers/189pc/driver.go
deleted file mode 100644
index 5337f79d..00000000
--- a/drivers/189pc/driver.go
+++ /dev/null
@@ -1,923 +0,0 @@
-package _189
-
-import (
- "bytes"
- "crypto/md5"
- "encoding/base64"
- "encoding/hex"
- "fmt"
- "io"
- "io/ioutil"
- "math"
- "net/http"
- "net/url"
- "os"
- "path/filepath"
- "strings"
-
- "github.com/Xhofe/alist/conf"
- "github.com/Xhofe/alist/drivers/base"
- "github.com/Xhofe/alist/model"
- "github.com/Xhofe/alist/utils"
- "github.com/go-resty/resty/v2"
- log "github.com/sirupsen/logrus"
-)
-
-func init() {
- base.RegisterDriver(new(Cloud189))
-}
-
-type Cloud189 struct {
-}
-
-func (driver Cloud189) Config() base.DriverConfig {
- return base.DriverConfig{
- Name: "189CloudPC",
- }
-}
-
-func (driver Cloud189) Items() []base.Item {
- return []base.Item{
- {
- Name: "username",
- Label: "username",
- Type: base.TypeString,
- Required: true,
- Description: "account username/phone number",
- },
- {
- Name: "password",
- Label: "password",
- Type: base.TypeString,
- Required: true,
- Description: "account password",
- },
- {
- Name: "root_folder",
- Label: "root folder file_id",
- Type: base.TypeString,
- },
- {
- Name: "internal_type",
- Label: "189cloud type",
- Type: base.TypeSelect,
- Required: true,
- Values: "Personal,Family",
- },
- {
- Name: "site_id",
- Label: "family id",
- Type: base.TypeString,
- },
- {
- Name: "order_by",
- Label: "order_by",
- Type: base.TypeSelect,
- Values: "filename,filesize,lastOpTime",
- Required: true,
- },
- {
- Name: "order_direction",
- Label: "desc",
- Type: base.TypeSelect,
- Values: "true,false",
- Required: true,
- },
- {
- Name: "bool_1",
- Label: "fast upload",
- Type: base.TypeBool,
- },
- }
-}
-
-func (driver Cloud189) Save(account *model.Account, old *model.Account) error {
- if account == nil {
- return nil
- }
-
- if !isFamily(account) && account.RootFolder == "" {
- account.RootFolder = "-11"
- account.SiteId = ""
- }
- if isFamily(account) && account.RootFolder == "-11" {
- account.RootFolder = ""
- }
-
- state := GetState(account)
- if !state.IsLogin(account) {
- if err := state.Login(account); err != nil {
- return err
- }
- }
-
- if isFamily(account) {
- list, err := driver.getFamilyInfoList(account)
- if err != nil {
- return err
- }
- for _, l := range list {
- if account.SiteId == "" {
- account.SiteId = fmt.Sprint(l.FamilyID)
- }
- log.Infof("天翼家庭云 用户名:%s FamilyID %d\n", l.RemarkName, l.FamilyID)
- }
- }
-
- account.Status = "work"
- model.SaveAccount(account)
- return nil
-}
-
-func (driver Cloud189) getFamilyInfoList(account *model.Account) ([]FamilyInfoResp, error) {
- var resp FamilyInfoListResp
- _, err := GetState(account).Request(http.MethodGet, API_URL+"/family/manage/getFamilyList.action", nil, func(r *resty.Request) {
- r.SetQueryParams(clientSuffix())
- r.SetResult(&resp)
- }, account)
- if err != nil {
- return nil, err
- }
- return resp.FamilyInfoResp, nil
-}
-
-func (driver Cloud189) File(path string, account *model.Account) (*model.File, error) {
- path = utils.ParsePath(path)
- if path == "/" {
- return &model.File{
- Id: account.RootFolder,
- Name: account.Name,
- Size: 0,
- Type: conf.FOLDER,
- Driver: driver.Config().Name,
- UpdatedAt: account.UpdatedAt,
- }, nil
- }
- dir, name := filepath.Split(path)
- files, err := driver.Files(dir, account)
- if err != nil {
- return nil, err
- }
- for _, file := range files {
- if file.Name == name {
- return &file, nil
- }
- }
- return nil, base.ErrPathNotFound
-}
-
-func (driver Cloud189) Files(path string, account *model.Account) ([]model.File, error) {
- path = utils.ParsePath(path)
- cache, err := base.GetCache(path, account)
- if err == nil {
- files, _ := cache.([]model.File)
- return files, nil
- }
-
- file, err := driver.File(path, account)
- if err != nil {
- return nil, err
- }
-
- fullUrl := API_URL
- if isFamily(account) {
- fullUrl += "/family/file"
- }
- fullUrl += "/listFiles.action"
-
- files := make([]model.File, 0)
- client := GetState(account)
- for pageNum := 1; ; pageNum++ {
- var resp Cloud189FilesResp
- _, err = client.Request(http.MethodGet, fullUrl, nil, func(r *resty.Request) {
- r.SetQueryParams(clientSuffix()).
- SetQueryParams(map[string]string{
- "folderId": file.Id,
- "fileType": "0",
- "mediaAttr": "0",
- "iconOption": "5",
- "pageNum": fmt.Sprint(pageNum),
- "pageSize": "130",
- })
- if isFamily(account) {
- r.SetQueryParams(map[string]string{
- "familyId": account.SiteId,
- "orderBy": toFamilyOrderBy(account.OrderBy),
- "descending": account.OrderDirection,
- })
- } else {
- r.SetQueryParams(map[string]string{
- "recursive": "0",
- "orderBy": account.OrderBy,
- "descending": account.OrderDirection,
- })
- }
- r.SetResult(&resp)
- }, account)
- if err != nil {
- return nil, err
- }
- // 获取完毕跳出
- if resp.FileListAO.Count == 0 {
- break
- }
-
- for _, folder := range resp.FileListAO.FolderList {
- files = append(files, model.File{
- Id: fmt.Sprint(folder.ID),
- Name: folder.Name,
- Size: 0,
- Type: conf.FOLDER,
- Driver: driver.Config().Name,
- UpdatedAt: MustParseTime(folder.LastOpTime),
- })
- }
- for _, file := range resp.FileListAO.FileList {
- files = append(files, model.File{
- Id: fmt.Sprint(file.ID),
- Name: file.Name,
- Size: file.Size,
- Type: utils.GetFileType(filepath.Ext(file.Name)),
- Driver: driver.Config().Name,
- UpdatedAt: MustParseTime(file.LastOpTime),
- Thumbnail: file.Icon.SmallUrl,
- })
- }
- }
- if len(files) > 0 {
- _ = base.SetCache(path, files, account)
- }
- return files, nil
-}
-
-func (driver Cloud189) Path(path string, account *model.Account) (*model.File, []model.File, error) {
- path = utils.ParsePath(path)
- log.Debugf("189PC path: %s", path)
- file, err := driver.File(path, account)
- if err != nil {
- return nil, nil, err
- }
- if !file.IsDir() {
- return file, nil, nil
- }
- files, err := driver.Files(path, account)
- if err != nil {
- return nil, nil, err
- }
- return nil, files, nil
-}
-
-func (driver Cloud189) Link(args base.Args, account *model.Account) (*base.Link, error) {
- file, err := driver.File(utils.ParsePath(args.Path), account)
- if err != nil {
- return nil, err
- }
- if file.Type == conf.FOLDER {
- return nil, base.ErrNotFile
- }
-
- fullUrl := API_URL
- if isFamily(account) {
- fullUrl += "/family/file"
- }
- fullUrl += "/getFileDownloadUrl.action"
-
- var downloadUrl struct {
- URL string `json:"fileDownloadUrl"`
- }
- _, err = GetState(account).Request(http.MethodGet, fullUrl, nil, func(r *resty.Request) {
- r.SetQueryParams(clientSuffix()).SetQueryParam("fileId", file.Id)
- if isFamily(account) {
- r.SetQueryParams(map[string]string{
- "familyId": account.SiteId,
- })
- } else {
- r.SetQueryParams(map[string]string{
- "dt": "3",
- "flag": "1",
- })
- }
- r.SetResult(&downloadUrl)
- }, account)
- if err != nil {
- return nil, err
- }
- return &base.Link{
- Headers: []base.Header{
- {Name: "User-Agent", Value: base.UserAgent},
- },
- Url: strings.ReplaceAll(downloadUrl.URL, "&", "&"),
- }, nil
-}
-
-func (driver Cloud189) Preview(path string, account *model.Account) (interface{}, error) {
- return nil, base.ErrNotSupport
-}
-
-func (driver Cloud189) MakeDir(path string, account *model.Account) error {
- dir, name := filepath.Split(path)
- parentFile, err := driver.File(dir, account)
- if err != nil {
- return err
- }
- if !parentFile.IsDir() {
- return base.ErrNotFolder
- }
-
- fullUrl := API_URL
- if isFamily(account) {
- fullUrl += "/family/file"
- }
- fullUrl += "/createFolder.action"
-
- _, err = GetState(account).Request(http.MethodPost, fullUrl, nil, func(r *resty.Request) {
- r.SetQueryParams(clientSuffix()).SetQueryParams(map[string]string{
- "folderName": name,
- "relativePath": "",
- })
- if isFamily(account) {
- r.SetQueryParams(map[string]string{
- "familyId": account.SiteId,
- "parentId": parentFile.Id,
- })
- } else {
- r.SetQueryParams(map[string]string{
- "parentFolderId": parentFile.Id,
- })
- }
- }, account)
- return err
-}
-
-func (driver Cloud189) Move(src string, dst string, account *model.Account) error {
- srcFile, err := driver.File(src, account)
- if err != nil {
- return err
- }
-
- dstDirFile, err := driver.File(filepath.Dir(dst), account)
- if err != nil {
- return err
- }
-
- _, err = GetState(account).Request(http.MethodPost, API_URL+"/batch/createBatchTask.action", nil, func(r *resty.Request) {
- r.SetFormData(clientSuffix()).SetFormData(map[string]string{
- "type": "MOVE",
- "taskInfos": string(MustToBytes(utils.Json.Marshal(
- []*BatchTaskInfo{
- {
- FileId: srcFile.Id,
- FileName: srcFile.Name,
- IsFolder: BoolToNumber(srcFile.IsDir()),
- },
- }))),
- "targetFolderId": dstDirFile.Id,
- })
- if isFamily(account) {
- r.SetFormData(map[string]string{
- "familyId": account.SiteId,
- })
- }
- }, account)
- return err
-}
-
-/*
-func (driver Cloud189) Move(src string, dst string, account *model.Account) error {
- srcFile, err := driver.File(src, account)
- if err != nil {
- return err
- }
-
- dstDirFile, err := driver.File(filepath.Dir(dst), account)
- if err != nil {
- return err
- }
-
- var queryParam map[string]string
- fullUrl := API_URL
- method := http.MethodPost
- if isFamily(account) {
- fullUrl += "/family/file"
- method = http.MethodGet
- }
- if srcFile.IsDir() {
- fullUrl += "/moveFolder.action"
- queryParam = map[string]string{
- "folderId": srcFile.Id,
- "destFolderName": srcFile.Name,
- }
- } else {
- fullUrl += "/moveFile.action"
- queryParam = map[string]string{
- "fileId": srcFile.Id,
- "destFileName": srcFile.Name,
- }
- }
-
- _, err = GetState(account).Request(method, fullUrl, nil, func(r *resty.Request) {
- r.SetQueryParams(queryParam).SetQueryParams(clientSuffix())
- if isFamily(account) {
- r.SetQueryParams(map[string]string{
- "familyId": account.SiteId,
- "destParentId": dstDirFile.Id,
- })
- } else {
- r.SetQueryParam("destParentFolderId", dstDirFile.Id)
- }
- }, account)
- return err
-}*/
-
-func (driver Cloud189) Rename(src string, dst string, account *model.Account) error {
- srcFile, err := driver.File(src, account)
- if err != nil {
- return err
- }
-
- var queryParam map[string]string
- fullUrl := API_URL
- method := http.MethodPost
- if isFamily(account) {
- fullUrl += "/family/file"
- method = http.MethodGet
- }
- if srcFile.IsDir() {
- fullUrl += "/renameFolder.action"
- queryParam = map[string]string{
- "folderId": srcFile.Id,
- "destFolderName": filepath.Base(dst),
- }
- } else {
- fullUrl += "/renameFile.action"
- queryParam = map[string]string{
- "fileId": srcFile.Id,
- "destFileName": filepath.Base(dst),
- }
- }
-
- _, err = GetState(account).Request(method, fullUrl, nil, func(r *resty.Request) {
- r.SetQueryParams(queryParam).SetQueryParams(clientSuffix())
- if isFamily(account) {
- r.SetQueryParam("familyId", account.SiteId)
- }
- }, account)
- return err
-}
-
-func (driver Cloud189) Copy(src string, dst string, account *model.Account) error {
- srcFile, err := driver.File(src, account)
- if err != nil {
- return err
- }
-
- dstDirFile, err := driver.File(filepath.Dir(dst), account)
- if err != nil {
- return err
- }
-
- _, err = GetState(account).Request(http.MethodPost, API_URL+"/batch/createBatchTask.action", nil, func(r *resty.Request) {
- r.SetFormData(clientSuffix()).SetFormData(map[string]string{
- "type": "COPY",
- "taskInfos": string(MustToBytes(utils.Json.Marshal(
- []*BatchTaskInfo{
- {
- FileId: srcFile.Id,
- FileName: srcFile.Name,
- IsFolder: BoolToNumber(srcFile.IsDir()),
- },
- }))),
- "targetFolderId": dstDirFile.Id,
- "targetFileName": filepath.Base(dst),
- })
- if isFamily(account) {
- r.SetFormData(map[string]string{
- "familyId": account.SiteId,
- })
- }
- }, account)
- return err
-}
-
-func (driver Cloud189) Delete(path string, account *model.Account) error {
- path = utils.ParsePath(path)
- srcFile, err := driver.File(path, account)
- if err != nil {
- return err
- }
-
- _, err = GetState(account).Request(http.MethodPost, API_URL+"/batch/createBatchTask.action", nil, func(r *resty.Request) {
- r.SetFormData(clientSuffix()).SetFormData(map[string]string{
- "type": "DELETE",
- "taskInfos": string(MustToBytes(utils.Json.Marshal(
- []*BatchTaskInfo{
- {
- FileId: srcFile.Id,
- FileName: srcFile.Name,
- IsFolder: BoolToNumber(srcFile.IsDir()),
- },
- }))),
- })
-
- if isFamily(account) {
- r.SetFormData(map[string]string{
- "familyId": account.SiteId,
- })
- }
- }, account)
- return err
-}
-
-func (driver Cloud189) Upload(file *model.FileStream, account *model.Account) error {
- if file == nil {
- return base.ErrEmptyFile
- }
-
- parentFile, err := driver.File(file.ParentPath, account)
- if err != nil {
- return err
- }
- if !parentFile.IsDir() {
- return base.ErrNotFolder
- }
-
- if account.Bool1 {
- return driver.FastUpload(file, parentFile, account)
- }
- return driver.CommonUpload(file, parentFile, account)
- /*
- if isFamily(account) {
- return driver.uploadFamily(file, parentFile, account)
- }
- return driver.uploadPerson(file, parentFile, account)
- */
-}
-
-func (driver Cloud189) CommonUpload(file *model.FileStream, parentFile *model.File, account *model.Account) error {
- // 初始化上传
- state := GetState(account)
- const DEFAULT int64 = 10485760
- count := int(math.Ceil(float64(file.Size) / float64(DEFAULT)))
-
- params := Params{
- "parentFolderId": parentFile.Id,
- "fileName": url.PathEscape(file.Name),
- "fileSize": fmt.Sprint(file.Size),
- "sliceSize": fmt.Sprint(DEFAULT),
- "lazyCheck": "1",
- }
-
- fullUrl := UPLOAD_URL
- if isFamily(account) {
- params.Set("familyId", account.SiteId)
- fullUrl += "/family"
- } else {
- //params.Set("extend", `{"opScene":"1","relativepath":"","rootfolderid":""}`)
- fullUrl += "/person"
- }
-
- var initMultiUpload InitMultiUploadResp
- _, err := state.Request(http.MethodGet, fullUrl+"/initMultiUpload", params, func(r *resty.Request) { r.SetQueryParams(clientSuffix()).SetResult(&initMultiUpload) }, account)
- if err != nil {
- return err
- }
-
- fileMd5 := md5.New()
- silceMd5 := md5.New()
- silceMd5Hexs := make([]string, 0, count)
- byteData := bytes.NewBuffer(make([]byte, DEFAULT))
- for i := 1; i <= count; i++ {
- byteData.Reset()
- silceMd5.Reset()
- if n, err := io.CopyN(io.MultiWriter(fileMd5, silceMd5, byteData), file, DEFAULT); err != io.EOF && n == 0 {
- return err
- }
- md5Bytes := silceMd5.Sum(nil)
- silceMd5Hexs = append(silceMd5Hexs, strings.ToUpper(hex.EncodeToString(md5Bytes)))
- silceMd5Base64 := base64.StdEncoding.EncodeToString(md5Bytes)
-
- var uploadUrl UploadUrlsResp
- _, err = state.Request(http.MethodGet, fullUrl+"/getMultiUploadUrls",
- Params{"partInfo": fmt.Sprintf("%d-%s", i, silceMd5Base64), "uploadFileId": initMultiUpload.Data.UploadFileID},
- func(r *resty.Request) { r.SetQueryParams(clientSuffix()).SetResult(&uploadUrl) },
- account)
- if err != nil {
- return err
- }
-
- uploadData := uploadUrl.UploadUrls[fmt.Sprint("partNumber_", i)]
- req, _ := http.NewRequest(http.MethodPut, uploadData.RequestURL, byteData)
- req.Header.Set("User-Agent", "")
- for k, v := range ParseHttpHeader(uploadData.RequestHeader) {
- req.Header.Set(k, v)
- }
- for k, v := range clientSuffix() {
- req.URL.RawQuery += fmt.Sprintf("&%s=%s", k, v)
- }
- r, err := base.HttpClient.Do(req)
- if err != nil {
- return err
- }
- if r.StatusCode != http.StatusOK {
- data, _ := io.ReadAll(r.Body)
- r.Body.Close()
- return fmt.Errorf(string(data))
- }
- r.Body.Close()
- }
-
- fileMd5Hex := strings.ToUpper(hex.EncodeToString(fileMd5.Sum(nil)))
- sliceMd5Hex := fileMd5Hex
- if int64(file.Size) > DEFAULT {
- sliceMd5Hex = strings.ToUpper(utils.GetMD5Encode(strings.Join(silceMd5Hexs, "\n")))
- }
-
- _, err = state.Request(http.MethodGet, fullUrl+"/commitMultiUploadFile",
- Params{
- "uploadFileId": initMultiUpload.Data.UploadFileID,
- "fileMd5": fileMd5Hex,
- "sliceMd5": sliceMd5Hex,
- "lazyCheck": "1",
- "isLog": "0",
- "opertype": "3",
- },
- func(r *resty.Request) { r.SetQueryParams(clientSuffix()) }, account)
- return err
-}
-
-func (driver Cloud189) FastUpload(file *model.FileStream, parentFile *model.File, account *model.Account) error {
- tempFile, err := ioutil.TempFile(conf.Conf.TempDir, "file-*")
- if err != nil {
- return err
- }
- defer func() {
- _ = tempFile.Close()
- _ = os.Remove(tempFile.Name())
- }()
- // 初始化上传
- state := GetState(account)
-
- const DEFAULT int64 = 10485760
- count := int(math.Ceil(float64(file.Size) / float64(DEFAULT)))
-
- // 优先计算所需信息
- fileMd5 := md5.New()
- silceMd5 := md5.New()
- silceMd5Hexs := make([]string, 0, count)
- silceMd5Base64s := make([]string, 0, count)
- for i := 1; i <= count; i++ {
- silceMd5.Reset()
- if n, err := io.CopyN(io.MultiWriter(fileMd5, silceMd5, tempFile), file, DEFAULT); err != nil && n == 0 {
- return err
- }
- md5Byte := silceMd5.Sum(nil)
- silceMd5Hexs = append(silceMd5Hexs, strings.ToUpper(hex.EncodeToString(md5Byte)))
- silceMd5Base64s = append(silceMd5Base64s, fmt.Sprint(i, "-", base64.StdEncoding.EncodeToString(md5Byte)))
- }
- fileMd5Hex := strings.ToUpper(hex.EncodeToString(fileMd5.Sum(nil)))
- sliceMd5Hex := fileMd5Hex
- if int64(file.Size) > DEFAULT {
- sliceMd5Hex = strings.ToUpper(utils.GetMD5Encode(strings.Join(silceMd5Hexs, "\n")))
- }
-
- params := Params{
- "parentFolderId": parentFile.Id,
- "fileName": url.PathEscape(file.Name),
- "fileSize": fmt.Sprint(file.Size),
- "fileMd5": fileMd5Hex,
- "sliceSize": fmt.Sprint(DEFAULT),
- "sliceMd5": sliceMd5Hex,
- }
-
- fullUrl := UPLOAD_URL
- if isFamily(account) {
- params.Set("familyId", account.SiteId)
- fullUrl += "/family"
- } else {
- //params.Set("extend", `{"opScene":"1","relativepath":"","rootfolderid":""}`)
- fullUrl += "/person"
- }
-
- var uploadInfo InitMultiUploadResp
- _, err = state.Request(http.MethodGet, fullUrl+"/initMultiUpload", params, func(r *resty.Request) { r.SetQueryParams(clientSuffix()).SetResult(&uploadInfo) }, account)
- if err != nil {
- return err
- }
-
- if uploadInfo.Data.FileDataExists != 1 {
- var uploadUrls UploadUrlsResp
- _, err := state.Request(http.MethodGet, fullUrl+"/getMultiUploadUrls",
- Params{
- "uploadFileId": uploadInfo.Data.UploadFileID,
- "partInfo": strings.Join(silceMd5Base64s, ","),
- },
- func(r *resty.Request) { r.SetQueryParams(clientSuffix()).SetResult(&uploadUrls) },
- account)
- if err != nil {
- return err
- }
- for i := 1; i <= count; i++ {
- uploadData := uploadUrls.UploadUrls[fmt.Sprint("partNumber_", i)]
- req, _ := http.NewRequest(http.MethodPut, uploadData.RequestURL, io.NewSectionReader(tempFile, int64(i-1)*DEFAULT, DEFAULT))
- req.Header.Set("User-Agent", "")
- for k, v := range ParseHttpHeader(uploadData.RequestHeader) {
- req.Header.Set(k, v)
- }
- for k, v := range clientSuffix() {
- req.URL.RawQuery += fmt.Sprintf("&%s=%s", k, v)
- }
- r, err := base.HttpClient.Do(req)
- if err != nil {
- return err
- }
- if r.StatusCode != http.StatusOK {
- data, _ := io.ReadAll(r.Body)
- r.Body.Close()
- return fmt.Errorf(string(data))
- }
- r.Body.Close()
- }
- }
-
- _, err = state.Request(http.MethodGet, fullUrl+"/commitMultiUploadFile",
- Params{
- "uploadFileId": uploadInfo.Data.UploadFileID,
- "isLog": "0",
- "opertype": "3",
- },
- func(r *resty.Request) { r.SetQueryParams(clientSuffix()) },
- account)
- return err
-}
-
-/*
-func (driver Cloud189) uploadFamily(file *model.FileStream, parentFile *model.File, account *model.Account) error {
- tempFile, err := ioutil.TempFile(conf.Conf.TempDir, "file-*")
- if err != nil {
- return err
- }
-
- defer func() {
- _ = tempFile.Close()
- _ = os.Remove(tempFile.Name())
- }()
-
- fileMd5 := md5.New()
- if _, err = io.Copy(io.MultiWriter(fileMd5, tempFile), file); err != nil {
- return err
- }
-
- client := GetState(account)
- var createUpload CreateUploadFileResult
- _, err = client.Request(http.MethodGet, API_URL+"/family/file/createFamilyFile.action", nil, func(r *resty.Request) {
- r.SetQueryParams(map[string]string{
- "fileMd5": hex.EncodeToString(fileMd5.Sum(nil)),
- "fileName": file.Name,
- "familyId": account.SiteId,
- "parentId": parentFile.Id,
- "resumePolicy": "1",
- "fileSize": fmt.Sprint(file.Size),
- })
- r.SetQueryParams(clientSuffix())
- r.SetResult(&createUpload)
- }, account)
- if err != nil {
- return err
- }
-
- if createUpload.FileDataExists != 1 {
- if createUpload.UploadFileId, err = driver.uploadFileData(file, tempFile, createUpload, account); err != nil {
- return err
- }
- }
-
- _, err = client.Request(http.MethodGet, createUpload.FileCommitUrl, nil, func(r *resty.Request) {
- r.SetQueryParams(clientSuffix())
- r.SetHeaders(map[string]string{
- "FamilyId": account.SiteId,
- "uploadFileId": fmt.Sprint(createUpload.UploadFileId),
- "ResumePolicy": "1",
- })
- }, account)
- return err
-}
-
-func (driver Cloud189) uploadPerson(file *model.FileStream, parentFile *model.File, account *model.Account) error {
- tempFile, err := ioutil.TempFile(conf.Conf.TempDir, "file-*")
- if err != nil {
- return err
- }
-
- defer func() {
- _ = tempFile.Close()
- _ = os.Remove(tempFile.Name())
- }()
-
- fileMd5 := md5.New()
- if _, err = io.Copy(io.MultiWriter(fileMd5, tempFile), file); err != nil {
- return err
- }
-
- client := GetState(account)
- var createUpload CreateUploadFileResult
- _, err = client.Request(http.MethodPost, API_URL+"/createUploadFile.action", nil, func(r *resty.Request) {
- r.SetQueryParams(clientSuffix())
- r.SetFormData(clientSuffix()).SetFormData(map[string]string{
- "parentFolderId": parentFile.Id,
- "baseFileId": "",
- "fileName": file.Name,
- "size": fmt.Sprint(file.Size),
- "md5": hex.EncodeToString(fileMd5.Sum(nil)),
- // "lastWrite": param.LastWrite,
- // "localPath": strings.ReplaceAll(file.ParentPath, "\\", "/"),
- "opertype": "1",
- "flag": "1",
- "resumePolicy": "1",
- "isLog": "0",
- "fileExt": "",
- })
- r.SetResult(&createUpload)
- }, account)
- if err != nil {
- return err
- }
-
- if createUpload.FileDataExists != 1 {
- if createUpload.UploadFileId, err = driver.uploadFileData(file, tempFile, createUpload, account); err != nil {
- return err
- }
- }
-
- _, err = client.Request(http.MethodPost, createUpload.FileCommitUrl, nil, func(r *resty.Request) {
- r.SetQueryParams(clientSuffix())
- r.SetFormData(map[string]string{
- "uploadFileId": fmt.Sprint(createUpload.UploadFileId),
- "opertype": "5", //5 覆盖 1 重命名
- "ResumePolicy": "1",
- "isLog": "0",
- })
- }, account)
- return err
-}
-
-func (driver Cloud189) uploadFileData(file *model.FileStream, tempFile *os.File, createUpload CreateUploadFileResult, account *model.Account) (int64, error) {
- uploadFileState, err := driver.getUploadFileState(createUpload.UploadFileId, account)
- if err != nil {
- return 0, err
- }
-
- if uploadFileState.FileDataExists == 1 || uploadFileState.DataSize == int64(file.Size) {
- return uploadFileState.UploadFileId, nil
- }
-
- if _, err = tempFile.Seek(uploadFileState.DataSize, io.SeekStart); err != nil {
- return 0, err
- }
-
- _, err = GetState(account).Request("PUT", uploadFileState.FileUploadUrl, nil, func(r *resty.Request) {
- r.SetQueryParams(clientSuffix())
- r.SetHeaders(map[string]string{
- "Content-Type": "application/octet-stream",
- "ResumePolicy": "1",
- "Edrive-UploadFileRange": fmt.Sprintf("bytes=%d-%d", uploadFileState.DataSize, file.Size),
- "Expect": "100-continue",
- })
- if isFamily(account) {
- r.SetHeaders(map[string]string{
- "familyId": account.SiteId,
- "UploadFileId": fmt.Sprint(uploadFileState.UploadFileId),
- })
- } else {
- r.SetHeader("Edrive-UploadFileId", fmt.Sprint(uploadFileState.UploadFileId))
- }
- r.SetBody(tempFile)
- }, account)
- return uploadFileState.UploadFileId, err
-}
-
-func (driver Cloud189) getUploadFileState(uploadFileId int64, account *model.Account) (*UploadFileStatusResult, error) {
- fullUrl := API_URL
- if isFamily(account) {
- fullUrl += "/family/file/getFamilyFileStatus.action"
- } else {
- fullUrl += "/getUploadFileStatus.action"
- }
- var uploadFileState UploadFileStatusResult
- _, err := GetState(account).Request(http.MethodGet, fullUrl, nil, func(r *resty.Request) {
- r.SetQueryParams(clientSuffix())
- r.SetQueryParams(map[string]string{
- "uploadFileId": fmt.Sprint(uploadFileId),
- "resumePolicy": "1",
- })
- if isFamily(account) {
- r.SetQueryParam("familyId", account.SiteId)
- }
- r.SetResult(&uploadFileState)
- }, account)
- if err != nil {
- return nil, err
- }
- return &uploadFileState, nil
-}*/
-
-var _ base.Driver = (*Cloud189)(nil)
diff --git a/drivers/189pc/type.go b/drivers/189pc/type.go
deleted file mode 100644
index b8d2c0af..00000000
--- a/drivers/189pc/type.go
+++ /dev/null
@@ -1,180 +0,0 @@
-package _189
-
-import "encoding/xml"
-
-type LoginParam struct {
- CaptchaToken string
- Lt string
- ParamId string
- ReqId string
- jRsaKey string
-
- vCodeID string
- vCodeRS string
-}
-
-// 居然有四种返回方式
-type Erron struct {
- ResCode string `json:"res_code"`
- ResMessage string `json:"res_message"`
-
- XMLName xml.Name `xml:"error"`
- Code string `json:"code" xml:"code"`
- Message string `json:"message" xml:"message"`
-
- // Code string `json:"code"`
- Msg string `json:"msg"`
-
- ErrorCode string `json:"errorCode"`
- ErrorMsg string `json:"errorMsg"`
-}
-
-// 刷新session返回
-type UserSessionResp struct {
- ResCode int `json:"res_code"`
- ResMessage string `json:"res_message"`
-
- LoginName string `json:"loginName"`
-
- KeepAlive int `json:"keepAlive"`
- GetFileDiffSpan int `json:"getFileDiffSpan"`
- GetUserInfoSpan int `json:"getUserInfoSpan"`
-
- // 个人云
- SessionKey string `json:"sessionKey"`
- SessionSecret string `json:"sessionSecret"`
- // 家庭云
- FamilySessionKey string `json:"familySessionKey"`
- FamilySessionSecret string `json:"familySessionSecret"`
-}
-
-//登录返回
-type appSessionResp struct {
- UserSessionResp
-
- IsSaveName string `json:"isSaveName"`
-
- // 会话刷新Token
- AccessToken string `json:"accessToken"`
- //Token刷新
- RefreshToken string `json:"refreshToken"`
-}
-
-type FamilyInfoListResp struct {
- FamilyInfoResp []FamilyInfoResp `json:"familyInfoResp"`
-}
-type FamilyInfoResp struct {
- Count int `json:"count"`
- CreateTime string `json:"createTime"`
- FamilyID int `json:"familyId"`
- RemarkName string `json:"remarkName"`
- Type int `json:"type"`
- UseFlag int `json:"useFlag"`
- UserRole int `json:"userRole"`
-}
-
-/*文件部分*/
-// 文件
-type Cloud189File struct {
- CreateDate string `json:"createDate"`
- FileCata int64 `json:"fileCata"`
- Icon struct {
- //iconOption 5
- SmallUrl string `json:"smallUrl"`
- LargeUrl string `json:"largeUrl"`
-
- // iconOption 10
- Max600 string `json:"max600"`
- MediumURL string `json:"mediumUrl"`
- } `json:"icon"`
- ID int64 `json:"id"`
- LastOpTime string `json:"lastOpTime"`
- Md5 string `json:"md5"`
- MediaType int `json:"mediaType"`
- Name string `json:"name"`
- Orientation int64 `json:"orientation"`
- Rev string `json:"rev"`
- Size int64 `json:"size"`
- StarLabel int64 `json:"starLabel"`
-}
-
-// 文件夹
-type Cloud189Folder struct {
- ID int64 `json:"id"`
- ParentID int64 `json:"parentId"`
- Name string `json:"name"`
-
- FileCata int64 `json:"fileCata"`
- FileCount int64 `json:"fileCount"`
-
- LastOpTime string `json:"lastOpTime"`
- CreateDate string `json:"createDate"`
-
- FileListSize int64 `json:"fileListSize"`
- Rev string `json:"rev"`
- StarLabel int64 `json:"starLabel"`
-}
-
-type Cloud189FilesResp struct {
- //ResCode int `json:"res_code"`
- //ResMessage string `json:"res_message"`
- FileListAO struct {
- Count int `json:"count"`
- FileList []Cloud189File `json:"fileList"`
- FolderList []Cloud189Folder `json:"folderList"`
- } `json:"fileListAO"`
-}
-
-// TaskInfo 任务信息
-type BatchTaskInfo struct {
- // FileId 文件ID
- FileId string `json:"fileId"`
- // FileName 文件名
- FileName string `json:"fileName"`
- // IsFolder 是否是文件夹,0-否,1-是
- IsFolder int `json:"isFolder"`
- // SrcParentId 文件所在父目录ID
- //SrcParentId string `json:"srcParentId"`
-}
-
-/*
-type CreateUploadFileResult struct {
- // UploadFileId 上传文件请求ID
- UploadFileId int64 `json:"uploadFileId"`
- // FileUploadUrl 上传文件数据的URL路径
- FileUploadUrl string `json:"fileUploadUrl"`
- // FileCommitUrl 上传文件完成后确认路径
- FileCommitUrl string `json:"fileCommitUrl"`
- // FileDataExists 文件是否已存在云盘中,0-未存在,1-已存在
- FileDataExists int `json:"fileDataExists"`
-}
-
-type UploadFileStatusResult struct {
- // 上传文件的ID
- UploadFileId int64 `json:"uploadFileId"`
- // 已上传的大小
- DataSize int64 `json:"dataSize"`
- FileUploadUrl string `json:"fileUploadUrl"`
- FileCommitUrl string `json:"fileCommitUrl"`
- FileDataExists int `json:"fileDataExists"`
-}
-*/
-
-type InitMultiUploadResp struct {
- //Code string `json:"code"`
- Data struct {
- UploadType int `json:"uploadType"`
- UploadHost string `json:"uploadHost"`
- UploadFileID string `json:"uploadFileId"`
- FileDataExists int `json:"fileDataExists"`
- } `json:"data"`
-}
-type UploadUrlsResp struct {
- Code string `json:"code"`
- UploadUrls map[string]Part `json:"uploadUrls"`
-}
-
-type Part struct {
- RequestURL string `json:"requestURL"`
- RequestHeader string `json:"requestHeader"`
-}
diff --git a/drivers/189pc/util.go b/drivers/189pc/util.go
deleted file mode 100644
index c31e98e8..00000000
--- a/drivers/189pc/util.go
+++ /dev/null
@@ -1,177 +0,0 @@
-package _189
-
-import (
- "bytes"
- "crypto/aes"
- "crypto/hmac"
- "crypto/rand"
- "crypto/rsa"
- "crypto/sha1"
- "crypto/x509"
- "encoding/base64"
- "encoding/hex"
- "encoding/pem"
- "fmt"
- rand2 "math/rand"
- "net/http"
- "net/url"
- "sort"
- "strings"
- "time"
-
- "github.com/Xhofe/alist/model"
-)
-
-const (
- APP_ID = "8025431004"
- CLIENT_TYPE = "10020"
- VERSION = "6.2"
-
- WEB_URL = "https://cloud.189.cn"
- AUTH_URL = "https://open.e.189.cn"
- API_URL = "https://api.cloud.189.cn"
- UPLOAD_URL = "https://upload.cloud.189.cn"
-
- RETURN_URL = "https://m.cloud.189.cn/zhuanti/2020/loginErrorPc/index.html"
-
- PC = "TELEPC"
- MAC = "TELEMAC"
-
- CHANNEL_ID = "web_cloud.189.cn"
-)
-
-func clientSuffix() map[string]string {
- return map[string]string{
- "clientType": PC,
- "version": VERSION,
- "channelId": CHANNEL_ID,
- "rand": fmt.Sprintf("%d_%d", rand2.Int63n(1e5), rand2.Int63n(1e10)),
- }
-}
-
-// 带params的SignatureOfHmac HMAC签名
-func signatureOfHmac(sessionSecret, sessionKey, operate, fullUrl, dateOfGmt, param string) string {
- u, _ := url.Parse(fullUrl)
- mac := hmac.New(sha1.New, []byte(sessionSecret))
- data := fmt.Sprintf("SessionKey=%s&Operate=%s&RequestURI=%s&Date=%s", sessionKey, operate, u.Path, dateOfGmt)
- if param != "" {
- data += fmt.Sprintf("¶ms=%s", param)
- }
- mac.Write([]byte(data))
- return strings.ToUpper(hex.EncodeToString(mac.Sum(nil)))
-}
-
-// 获取http规范的时间
-func getHttpDateStr() string {
- return time.Now().UTC().Format(http.TimeFormat)
-}
-
-// RAS 加密用户名密码
-func rsaEncrypt(publicKey, origData string) string {
- block, _ := pem.Decode([]byte(publicKey))
- pubInterface, _ := x509.ParsePKIXPublicKey(block.Bytes)
- data, _ := rsa.EncryptPKCS1v15(rand.Reader, pubInterface.(*rsa.PublicKey), []byte(origData))
- return base64ToHex(base64.StdEncoding.EncodeToString(data))
-}
-
-// aes 加密params
-func AesECBEncrypt(data, key string) string {
- block, _ := aes.NewCipher([]byte(key))
- paddingData := PKCS7Padding([]byte(data), block.BlockSize())
- decrypted := make([]byte, len(paddingData))
- size := block.BlockSize()
- for src, dst := paddingData, decrypted; len(src) > 0; src, dst = src[size:], dst[size:] {
- block.Encrypt(dst[:size], src[:size])
- }
- return strings.ToUpper(hex.EncodeToString(decrypted))
-}
-
-func PKCS7Padding(ciphertext []byte, blockSize int) []byte {
- padding := blockSize - len(ciphertext)%blockSize
- padtext := bytes.Repeat([]byte{byte(padding)}, padding)
- return append(ciphertext, padtext...)
-}
-
-// 时间戳
-func timestamp() int64 {
- return time.Now().UTC().UnixNano() / 1e6
-}
-
-func base64ToHex(a string) string {
- v, _ := base64.StdEncoding.DecodeString(a)
- return strings.ToUpper(hex.EncodeToString(v))
-}
-
-func isFamily(account *model.Account) bool {
- return account.InternalType == "Family"
-}
-
-func toFamilyOrderBy(o string) string {
- switch o {
- case "filename":
- return "1"
- case "filesize":
- return "2"
- case "lastOpTime":
- return "3"
- default:
- return "1"
- }
-}
-
-func ParseHttpHeader(str string) map[string]string {
- header := make(map[string]string)
- for _, value := range strings.Split(str, "&") {
- i := strings.Index(value, "=")
- header[strings.TrimSpace(value[0:i])] = strings.TrimSpace(value[i+1:])
- }
- return header
-}
-
-func MustString(str string, err error) string {
- return str
-}
-
-func MustToBytes(b []byte, err error) []byte {
- return b
-}
-
-func BoolToNumber(b bool) int {
- if b {
- return 1
- }
- return 0
-}
-
-func MustParseTime(str string) *time.Time {
- loc, _ := time.LoadLocation("Local")
- lastOpTime, _ := time.ParseInLocation("2006-01-02 15:04:05", str, loc)
- return &lastOpTime
-}
-
-type Params map[string]string
-
-func (p Params) Set(k, v string) {
- p[k] = v
-}
-
-func (p Params) Encode() string {
- if p == nil {
- return ""
- }
- var buf strings.Builder
- keys := make([]string, 0, len(p))
- for k := range p {
- keys = append(keys, k)
- }
- sort.Strings(keys)
- for _, k := range keys {
- if buf.Len() > 0 {
- buf.WriteByte('&')
- }
- buf.WriteString(k)
- buf.WriteByte('=')
- buf.WriteString(p[k])
- }
- return buf.String()
-}
diff --git a/drivers/alidrive/alidrive.go b/drivers/alidrive/alidrive.go
deleted file mode 100644
index 4bb2a0e7..00000000
--- a/drivers/alidrive/alidrive.go
+++ /dev/null
@@ -1,209 +0,0 @@
-package alidrive
-
-import (
- "errors"
- "fmt"
- "github.com/Xhofe/alist/drivers/base"
- "github.com/Xhofe/alist/model"
- "github.com/Xhofe/alist/utils"
- "github.com/go-resty/resty/v2"
- jsoniter "github.com/json-iterator/go"
- log "github.com/sirupsen/logrus"
- "path/filepath"
-)
-
-var aliClient = resty.New()
-
-func (driver AliDrive) FormatFile(file *AliFile) *model.File {
- f := &model.File{
- Id: file.FileId,
- Name: file.Name,
- Size: file.Size,
- UpdatedAt: file.UpdatedAt,
- Thumbnail: file.Thumbnail,
- Driver: driver.Config().Name,
- Url: file.Url,
- }
- f.Type = file.GetType()
- return f
-}
-
-func (driver AliDrive) GetFiles(fileId string, account *model.Account) ([]AliFile, error) {
- marker := "first"
- res := make([]AliFile, 0)
- for marker != "" {
- if marker == "first" {
- marker = ""
- }
- var resp AliFiles
- var e AliRespError
- _, err := aliClient.R().
- SetResult(&resp).
- SetError(&e).
- SetHeader("authorization", "Bearer\t"+account.AccessToken).
- SetBody(base.Json{
- "drive_id": account.DriveId,
- "fields": "*",
- "image_thumbnail_process": "image/resize,w_400/format,jpeg",
- "image_url_process": "image/resize,w_1920/format,jpeg",
- "limit": account.Limit,
- "marker": marker,
- "order_by": account.OrderBy,
- "order_direction": account.OrderDirection,
- "parent_file_id": fileId,
- "video_thumbnail_process": "video/snapshot,t_0,f_jpg,ar_auto,w_300",
- "url_expire_sec": 14400,
- }).Post("https://api.aliyundrive.com/v2/file/list")
- if err != nil {
- return nil, err
- }
- if e.Code != "" {
- if e.Code == "AccessTokenInvalid" {
- err = driver.RefreshToken(account)
- if err != nil {
- return nil, err
- } else {
- _ = model.SaveAccount(account)
- return driver.GetFiles(fileId, account)
- }
- }
- return nil, fmt.Errorf("%s", e.Message)
- }
- marker = resp.NextMarker
- res = append(res, resp.Items...)
- }
- return res, nil
-}
-
-func (driver AliDrive) GetFile(path string, account *model.Account) (*AliFile, error) {
- dir, name := filepath.Split(path)
- dir = utils.ParsePath(dir)
- _, err := driver.Files(dir, account)
- if err != nil {
- return nil, err
- }
- parentFiles_, _ := base.GetCache(dir, account)
- parentFiles, _ := parentFiles_.([]AliFile)
- for _, file := range parentFiles {
- if file.Name == name {
- if file.Type == "file" {
- return &file, err
- } else {
- return nil, fmt.Errorf("not file")
- }
- }
- }
- return nil, base.ErrPathNotFound
-}
-
-func (driver AliDrive) RefreshToken(account *model.Account) error {
- url := "https://auth.aliyundrive.com/v2/account/token"
- var resp base.TokenResp
- var e AliRespError
- _, err := aliClient.R().
- //ForceContentType("application/json").
- SetBody(base.Json{"refresh_token": account.RefreshToken, "grant_type": "refresh_token"}).
- SetResult(&resp).
- SetError(&e).
- Post(url)
- if err != nil {
- account.Status = err.Error()
- return err
- }
- log.Debugf("%+v,%+v", resp, e)
- if e.Code != "" {
- account.Status = e.Message
- return fmt.Errorf("failed to refresh token: %s", e.Message)
- } else {
- account.Status = "work"
- }
- account.RefreshToken, account.AccessToken = resp.RefreshToken, resp.AccessToken
- return nil
-}
-
-func (driver AliDrive) rename(fileId, name string, account *model.Account) error {
- var resp base.Json
- var e AliRespError
- _, err := aliClient.R().SetResult(&resp).SetError(&e).
- SetHeader("authorization", "Bearer\t"+account.AccessToken).
- SetBody(base.Json{
- "check_name_mode": "refuse",
- "drive_id": account.DriveId,
- "file_id": fileId,
- "name": name,
- }).Post("https://api.aliyundrive.com/v3/file/update")
- if err != nil {
- return err
- }
- if e.Code != "" {
- if e.Code == "AccessTokenInvalid" {
- err = driver.RefreshToken(account)
- if err != nil {
- return err
- } else {
- _ = model.SaveAccount(account)
- return driver.rename(fileId, name, account)
- }
- }
- return fmt.Errorf("%s", e.Message)
- }
- if resp["name"] == name {
- return nil
- }
- return fmt.Errorf("%+v", resp)
-}
-
-func (driver AliDrive) batch(srcId, dstId string, url string, account *model.Account) error {
- var e AliRespError
- res, err := aliClient.R().SetError(&e).
- SetHeader("authorization", "Bearer\t"+account.AccessToken).
- SetBody(base.Json{
- "requests": []base.Json{
- {
- "headers": base.Json{
- "Content-Type": "application/json",
- },
- "method": "POST",
- "id": srcId,
- "body": base.Json{
- "drive_id": account.DriveId,
- "file_id": srcId,
- "to_drive_id": account.DriveId,
- "to_parent_file_id": dstId,
- },
- "url": url,
- },
- },
- "resource": "file",
- }).Post("https://api.aliyundrive.com/v3/batch")
- if err != nil {
- return err
- }
- if e.Code != "" {
- if e.Code == "AccessTokenInvalid" {
- err = driver.RefreshToken(account)
- if err != nil {
- return err
- } else {
- _ = model.SaveAccount(account)
- return driver.batch(srcId, dstId, url, account)
- }
- }
- return fmt.Errorf("%s", e.Message)
- }
- status := jsoniter.Get(res.Body(), "responses", 0, "status").ToInt()
- if status < 400 && status >= 100 {
- return nil
- }
- return errors.New(res.String())
-}
-
-func init() {
- base.RegisterDriver(&AliDrive{})
- aliClient.
- SetTimeout(base.DefaultTimeout).
- SetRetryCount(3).
- SetHeader("user-agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Safari/537.36").
- SetHeader("content-type", "application/json").
- SetHeader("origin", "https://www.aliyundrive.com")
-}
diff --git a/drivers/alidrive/driver.go b/drivers/alidrive/driver.go
deleted file mode 100644
index be964c90..00000000
--- a/drivers/alidrive/driver.go
+++ /dev/null
@@ -1,566 +0,0 @@
-package alidrive
-
-import (
- "bytes"
- "crypto/sha1"
- "encoding/base64"
- "encoding/hex"
- "errors"
- "fmt"
- "io"
- "io/ioutil"
- "math"
- "math/big"
- "net/http"
- "os"
- "path/filepath"
-
- "github.com/Xhofe/alist/conf"
- "github.com/Xhofe/alist/drivers/base"
- "github.com/Xhofe/alist/model"
- "github.com/Xhofe/alist/utils"
- "github.com/robfig/cron/v3"
- log "github.com/sirupsen/logrus"
-)
-
-type AliDrive struct{}
-
-func (driver AliDrive) Config() base.DriverConfig {
- return base.DriverConfig{
- Name: "AliDrive",
- }
-}
-
-func (driver AliDrive) Items() []base.Item {
- return []base.Item{
- {
- Name: "refresh_token",
- Label: "refresh token",
- Type: base.TypeString,
- Required: true,
- },
- {
- Name: "root_folder",
- Label: "root folder file_id",
- Type: base.TypeString,
- Required: false,
- },
- {
- Name: "order_by",
- Label: "order_by",
- Type: base.TypeSelect,
- Values: "name,size,updated_at,created_at",
- Required: false,
- },
- {
- Name: "order_direction",
- Label: "order_direction",
- Type: base.TypeSelect,
- Values: "ASC,DESC",
- Required: false,
- },
- {
- Name: "limit",
- Label: "limit",
- Type: base.TypeNumber,
- Required: false,
- Description: ">0 and <=200",
- },
- {
- Name: "bool_1",
- Label: "fast upload",
- Type: base.TypeBool,
- },
- }
-}
-
-func (driver AliDrive) Save(account *model.Account, old *model.Account) error {
- if old != nil {
- conf.Cron.Remove(cron.EntryID(old.CronId))
- }
- if account == nil {
- return nil
- }
- if account.RootFolder == "" {
- account.RootFolder = "root"
- }
- if account.Limit == 0 {
- account.Limit = 200
- }
- err := driver.RefreshToken(account)
- if err != nil {
- return err
- }
- var resp base.Json
- _, _ = aliClient.R().SetResult(&resp).
- SetBody("{}").
- SetHeader("authorization", "Bearer\t"+account.AccessToken).
- Post("https://api.aliyundrive.com/v2/user/get")
- log.Debugf("user info: %+v", resp)
- account.DriveId = resp["default_drive_id"].(string)
- cronId, err := conf.Cron.AddFunc("@every 2h", func() {
- id := account.ID
- log.Debugf("ali account id: %d", id)
- newAccount, err := model.GetAccountById(id)
- log.Debugf("ali account: %+v", newAccount)
- if err != nil {
- return
- }
- err = driver.RefreshToken(newAccount)
- _ = model.SaveAccount(newAccount)
- })
- if err != nil {
- return err
- }
- account.CronId = int(cronId)
- err = model.SaveAccount(account)
- if err != nil {
- return err
- }
- return nil
-}
-
-func (driver AliDrive) File(path string, account *model.Account) (*model.File, error) {
- path = utils.ParsePath(path)
- if path == "/" {
- return &model.File{
- Id: account.RootFolder,
- Name: account.Name,
- Size: 0,
- Type: conf.FOLDER,
- Driver: driver.Config().Name,
- UpdatedAt: account.UpdatedAt,
- }, nil
- }
- dir, name := filepath.Split(path)
- files, err := driver.Files(dir, account)
- if err != nil {
- return nil, err
- }
- for _, file := range files {
- if file.Name == name {
- return &file, nil
- }
- }
- return nil, base.ErrPathNotFound
-}
-
-func (driver AliDrive) Files(path string, account *model.Account) ([]model.File, error) {
- path = utils.ParsePath(path)
- var rawFiles []AliFile
- cache, err := base.GetCache(path, account)
- if err == nil {
- rawFiles, _ = cache.([]AliFile)
- } else {
- file, err := driver.File(path, account)
- if err != nil {
- return nil, err
- }
- rawFiles, err = driver.GetFiles(file.Id, account)
- if err != nil {
- return nil, err
- }
- if len(rawFiles) > 0 {
- _ = base.SetCache(path, rawFiles, account)
- }
- }
- files := make([]model.File, 0)
- for _, file := range rawFiles {
- files = append(files, *driver.FormatFile(&file))
- }
- return files, nil
-}
-
-func (driver AliDrive) Link(args base.Args, account *model.Account) (*base.Link, error) {
- file, err := driver.File(args.Path, account)
- if err != nil {
- return nil, err
- }
- var resp base.Json
- var e AliRespError
- _, err = aliClient.R().SetResult(&resp).
- SetError(&e).
- SetHeader("authorization", "Bearer\t"+account.AccessToken).
- SetBody(base.Json{
- "drive_id": account.DriveId,
- "file_id": file.Id,
- "expire_sec": 14400,
- }).Post("https://api.aliyundrive.com/v2/file/get_download_url")
- if err != nil {
- return nil, err
- }
- if e.Code != "" {
- if e.Code == "AccessTokenInvalid" {
- err = driver.RefreshToken(account)
- if err != nil {
- return nil, err
- } else {
- _ = model.SaveAccount(account)
- return driver.Link(args, account)
- }
- }
- return nil, fmt.Errorf("%s", e.Message)
- }
- return &base.Link{
- Headers: []base.Header{
- {
- Name: "Referer",
- Value: "https://www.aliyundrive.com/",
- },
- },
- Url: resp["url"].(string),
- }, nil
-}
-
-func (driver AliDrive) Path(path string, account *model.Account) (*model.File, []model.File, error) {
- path = utils.ParsePath(path)
- log.Debugf("ali path: %s", path)
- file, err := driver.File(path, account)
- if err != nil {
- return nil, nil, err
- }
- if !file.IsDir() {
- return file, nil, nil
- }
- files, err := driver.Files(path, account)
- if err != nil {
- return nil, nil, err
- }
- return nil, files, nil
-}
-
-//func (driver AliDrive) Proxy(r *http.Request, account *model.Account) {
-// r.Header.Del("Origin")
-// r.Header.Set("Referer", "https://www.aliyundrive.com/")
-//}
-
-func (driver AliDrive) Preview(path string, account *model.Account) (interface{}, error) {
- file, err := driver.GetFile(path, account)
- if err != nil {
- return nil, err
- }
- // office
- var resp base.Json
- var e AliRespError
- var url string
- req := base.Json{
- "drive_id": account.DriveId,
- "file_id": file.FileId,
- }
- switch file.Category {
- case "doc":
- {
- url = "https://api.aliyundrive.com/v2/file/get_office_preview_url"
- req["access_token"] = account.AccessToken
- }
- case "video":
- {
- url = "https://api.aliyundrive.com/v2/file/get_video_preview_play_info"
- req["category"] = "live_transcoding"
- }
- default:
- return nil, base.ErrNotSupport
- }
- _, err = aliClient.R().SetResult(&resp).SetError(&e).
- SetHeader("authorization", "Bearer\t"+account.AccessToken).
- SetBody(req).Post(url)
- if err != nil {
- return nil, err
- }
- if e.Code != "" {
- return nil, fmt.Errorf("%s", e.Message)
- }
- return resp, nil
-}
-
-func (driver AliDrive) MakeDir(path string, account *model.Account) error {
- dir, name := filepath.Split(path)
- parentFile, err := driver.File(dir, account)
- if err != nil {
- return err
- }
- if !parentFile.IsDir() {
- return base.ErrNotFolder
- }
- var resp base.Json
- var e AliRespError
- _, err = aliClient.R().SetResult(&resp).SetError(&e).
- SetHeader("authorization", "Bearer\t"+account.AccessToken).
- SetBody(base.Json{
- "check_name_mode": "refuse",
- "drive_id": account.DriveId,
- "name": name,
- "parent_file_id": parentFile.Id,
- "type": "folder",
- }).Post("https://api.aliyundrive.com/adrive/v2/file/createWithFolders")
- if e.Code != "" {
- if e.Code == "AccessTokenInvalid" {
- err = driver.RefreshToken(account)
- if err != nil {
- return err
- } else {
- _ = model.SaveAccount(account)
- return driver.MakeDir(path, account)
- }
- }
- return fmt.Errorf("%s", e.Message)
- }
- if resp["file_name"] == name {
- return nil
- }
- return fmt.Errorf("%+v", resp)
-}
-
-func (driver AliDrive) Move(src string, dst string, account *model.Account) error {
- dstDir, _ := filepath.Split(dst)
- srcFile, err := driver.File(src, account)
- if err != nil {
- return err
- }
- dstDirFile, err := driver.File(dstDir, account)
- if err != nil {
- return err
- }
- err = driver.batch(srcFile.Id, dstDirFile.Id, "/file/move", account)
- return err
-}
-
-func (driver AliDrive) Rename(src string, dst string, account *model.Account) error {
- _, dstName := filepath.Split(dst)
- srcFile, err := driver.File(src, account)
- if err != nil {
- return err
- }
- err = driver.rename(srcFile.Id, dstName, account)
- return err
-}
-
-func (driver AliDrive) Copy(src string, dst string, account *model.Account) error {
- dstDir, _ := filepath.Split(dst)
- srcFile, err := driver.File(src, account)
- if err != nil {
- return err
- }
- dstDirFile, err := driver.File(dstDir, account)
- if err != nil {
- return err
- }
- err = driver.batch(srcFile.Id, dstDirFile.Id, "/file/copy", account)
- return err
-}
-
-func (driver AliDrive) Delete(path string, account *model.Account) error {
- file, err := driver.File(path, account)
- if err != nil {
- return err
- }
- var e AliRespError
- res, err := aliClient.R().SetError(&e).
- SetHeader("authorization", "Bearer\t"+account.AccessToken).
- SetBody(base.Json{
- "drive_id": account.DriveId,
- "file_id": file.Id,
- }).Post("https://api.aliyundrive.com/v2/recyclebin/trash")
- if err != nil {
- return err
- }
- if e.Code != "" {
- if e.Code == "AccessTokenInvalid" {
- err = driver.RefreshToken(account)
- if err != nil {
- return err
- } else {
- _ = model.SaveAccount(account)
- return driver.Delete(path, account)
- }
- }
- return fmt.Errorf("%s", e.Message)
- }
- if res.StatusCode() < 400 {
- return nil
- }
- return errors.New(res.String())
-}
-
-type UploadResp struct {
- FileId string `json:"file_id"`
- UploadId string `json:"upload_id"`
- PartInfoList []struct {
- UploadUrl string `json:"upload_url"`
- } `json:"part_info_list"`
-
- RapidUpload bool `json:"rapid_upload"`
-}
-
-func (driver AliDrive) Upload(file *model.FileStream, account *model.Account) error {
- if file == nil {
- return base.ErrEmptyFile
- }
-
- parentFile, err := driver.File(file.ParentPath, account)
- if err != nil {
- return err
- }
- if !parentFile.IsDir() {
- return base.ErrNotFolder
- }
-
- const DEFAULT int64 = 10485760
- var count = int(math.Ceil(float64(file.GetSize()) / float64(DEFAULT)))
-
- partInfoList := make([]base.Json, 0, count)
- for i := 1; i <= count; i++ {
- partInfoList = append(partInfoList, base.Json{"part_number": i})
- }
-
- reqBody := base.Json{
- "check_name_mode": "overwrite",
- "drive_id": account.DriveId,
- "name": file.GetFileName(),
- "parent_file_id": parentFile.Id,
- "part_info_list": partInfoList,
- "size": file.GetSize(),
- "type": "file",
- }
-
- if account.Bool1 {
- buf := bytes.NewBuffer(make([]byte, 0, 1024))
- io.CopyN(buf, file, 1024)
- reqBody["pre_hash"] = utils.GetSHA1Encode(buf.String())
- // 把头部拼接回去
- file.File = struct {
- io.Reader
- io.Closer
- }{
- Reader: io.MultiReader(buf, file.File),
- Closer: file.File,
- }
- } else {
- reqBody["content_hash_name"] = "none"
- reqBody["proof_version"] = "v1"
- }
-
- var resp UploadResp
- var e AliRespError
- client := aliClient.R().SetResult(&resp).SetError(&e).SetHeader("authorization", "Bearer\t"+account.AccessToken).SetBody(reqBody)
-
- _, err = client.Post("https://api.aliyundrive.com/adrive/v2/file/createWithFolders")
- if err != nil {
- return err
- }
- if e.Code != "" && e.Code != "PreHashMatched" {
- if e.Code == "AccessTokenInvalid" {
- err = driver.RefreshToken(account)
- if err != nil {
- return err
- } else {
- _ = model.SaveAccount(account)
- return driver.Upload(file, account)
- }
- }
- return fmt.Errorf("%s", e.Message)
- }
-
- if account.Bool1 && e.Code == "PreHashMatched" {
- tempFile, err := ioutil.TempFile(conf.Conf.TempDir, "file-*")
- if err != nil {
- return err
- }
-
- defer func() {
- _ = tempFile.Close()
- _ = os.Remove(tempFile.Name())
- }()
-
- delete(reqBody, "pre_hash")
- h := sha1.New()
- if _, err = io.Copy(io.MultiWriter(tempFile, h), file.File); err != nil {
- return err
- }
- reqBody["content_hash"] = hex.EncodeToString(h.Sum(nil))
- reqBody["content_hash_name"] = "sha1"
- reqBody["proof_version"] = "v1"
-
- /*
- js 隐性转换太坑不知道有没有bug
- var n = e.access_token,
- r = new BigNumber('0x'.concat(md5(n).slice(0, 16))),
- i = new BigNumber(t.file.size),
- o = i ? r.mod(i) : new gt.BigNumber(0);
- (t.file.slice(o.toNumber(), Math.min(o.plus(8).toNumber(), t.file.size)))
- */
- buf := make([]byte, 8)
- r, _ := new(big.Int).SetString(utils.GetMD5Encode(account.AccessToken)[:16], 16)
- i := new(big.Int).SetUint64(file.Size)
- o := r.Mod(r, i)
- n, _ := io.NewSectionReader(tempFile, o.Int64(), 8).Read(buf[:8])
- reqBody["proof_code"] = base64.StdEncoding.EncodeToString(buf[:n])
-
- _, err = client.Post("https://api.aliyundrive.com/adrive/v2/file/createWithFolders")
- if err != nil {
- return err
- }
- if e.Code != "" && e.Code != "PreHashMatched" {
- return fmt.Errorf("%s", e.Message)
- }
-
- if resp.RapidUpload {
- return nil
- }
-
- // 秒传失败
- if _, err = tempFile.Seek(0, io.SeekStart); err != nil {
- return err
- }
- file.File = tempFile
- }
-
- for _, partInfo := range resp.PartInfoList {
- req, err := http.NewRequest("PUT", partInfo.UploadUrl, io.LimitReader(file.File, DEFAULT))
- if err != nil {
- return err
- }
- res, err := base.HttpClient.Do(req)
- if err != nil {
- return err
- }
- log.Debugf("%+v", res)
- res.Body.Close()
- //res, err := base.BaseClient.R().
- // SetHeader("Content-Type","").
- // SetBody(byteData).Put(resp.PartInfoList[i].UploadUrl)
- //if err != nil {
- // return err
- //}
- //log.Debugf("put to %s : %d,%s", resp.PartInfoList[i].UploadUrl, res.StatusCode(),res.String())
- }
- var resp2 base.Json
- _, err = aliClient.R().SetResult(&resp2).SetError(&e).
- SetHeader("authorization", "Bearer\t"+account.AccessToken).
- SetBody(base.Json{
- "drive_id": account.DriveId,
- "file_id": resp.FileId,
- "upload_id": resp.UploadId,
- }).Post("https://api.aliyundrive.com/v2/file/complete")
- if err != nil {
- return err
- }
- if e.Code != "" && e.Code != "PreHashMatched" {
- //if e.Code == "AccessTokenInvalid" {
- // err = driver.RefreshToken(account)
- // if err != nil {
- // return err
- // } else {
- // _ = model.SaveAccount(account)
- // return driver.Upload(file, account)
- // }
- //}
- return fmt.Errorf("%s", e.Message)
- }
- if resp2["file_id"] == resp.FileId {
- return nil
- }
- return fmt.Errorf("%+v", resp2)
-}
-
-var _ base.Driver = (*AliDrive)(nil)
diff --git a/drivers/alidrive/types.go b/drivers/alidrive/types.go
deleted file mode 100644
index 93e3f286..00000000
--- a/drivers/alidrive/types.go
+++ /dev/null
@@ -1,53 +0,0 @@
-package alidrive
-
-import (
- "github.com/Xhofe/alist/conf"
- "github.com/Xhofe/alist/utils"
- "time"
-)
-
-type AliRespError struct {
- Code string `json:"code"`
- Message string `json:"message"`
-}
-
-type AliFiles struct {
- Items []AliFile `json:"items"`
- NextMarker string `json:"next_marker"`
-}
-
-type AliFile struct {
- DriveId string `json:"drive_id"`
- CreatedAt *time.Time `json:"created_at"`
- FileExtension string `json:"file_extension"`
- FileId string `json:"file_id"`
- Type string `json:"type"`
- Name string `json:"name"`
- Category string `json:"category"`
- ParentFileId string `json:"parent_file_id"`
- UpdatedAt *time.Time `json:"updated_at"`
- Size int64 `json:"size"`
- Thumbnail string `json:"thumbnail"`
- Url string `json:"url"`
-}
-
-func (f AliFile) GetSize() uint64 {
- return uint64(f.Size)
-}
-
-func (f AliFile) GetName() string {
- return f.Name
-}
-
-func (f AliFile) GetType() int {
- if f.Type == "folder" {
- return conf.FOLDER
- }
- if f.Category == "video" {
- return conf.VIDEO
- }
- if f.Category == "image" {
- return conf.IMAGE
- }
- return utils.GetFileType(f.FileExtension)
-}
diff --git a/drivers/alist/alist.go b/drivers/alist/alist.go
deleted file mode 100644
index 4e287cd1..00000000
--- a/drivers/alist/alist.go
+++ /dev/null
@@ -1,44 +0,0 @@
-package alist
-
-import (
- "errors"
- "github.com/Xhofe/alist/drivers/base"
- "github.com/Xhofe/alist/model"
-)
-
-type BaseResp struct {
- Code int `json:"code"`
- Message string `json:"message"`
-}
-
-type PathResp struct {
- BaseResp
- Data struct {
- Type string `json:"type"`
- //Meta Meta `json:"meta"`
- Files []model.File `json:"files"`
- } `json:"data"`
-}
-
-type PreviewResp struct {
- BaseResp
- Data interface{} `json:"data"`
-}
-
-func (driver *Alist) Login(account *model.Account) error {
- var resp BaseResp
- _, err := base.RestyClient.R().SetResult(&resp).
- SetHeader("Authorization", account.AccessToken).
- Get(account.SiteUrl + "/api/admin/login")
- if err != nil {
- return err
- }
- if resp.Code != 200 {
- return errors.New(resp.Message)
- }
- return nil
-}
-
-func init() {
- base.RegisterDriver(&Alist{})
-}
diff --git a/drivers/alist/driver.go b/drivers/alist/driver.go
deleted file mode 100644
index 3919ff5a..00000000
--- a/drivers/alist/driver.go
+++ /dev/null
@@ -1,192 +0,0 @@
-package alist
-
-import (
- "errors"
- "fmt"
- "github.com/Xhofe/alist/conf"
- "github.com/Xhofe/alist/drivers/base"
- "github.com/Xhofe/alist/model"
- "github.com/Xhofe/alist/utils"
- "path/filepath"
- "strings"
- "time"
-)
-
-type Alist struct{}
-
-func (driver Alist) Config() base.DriverConfig {
- return base.DriverConfig{
- Name: "Alist",
- NoNeedSetLink: true,
- NoCors: true,
- }
-}
-
-func (driver Alist) Items() []base.Item {
- return []base.Item{
- {
- Name: "site_url",
- Label: "alist site url",
- Type: base.TypeString,
- Required: true,
- },
- {
- Name: "access_token",
- Label: "token",
- Type: base.TypeString,
- Description: "admin token",
- Required: true,
- },
- {
- Name: "root_folder",
- Label: "root folder path",
- Type: base.TypeString,
- Required: false,
- },
- }
-}
-
-func (driver Alist) Save(account *model.Account, old *model.Account) error {
- if account == nil {
- return nil
- }
- account.SiteUrl = strings.TrimRight(account.SiteUrl, "/")
- if account.RootFolder == "" {
- account.RootFolder = "/"
- }
- err := driver.Login(account)
- if err == nil {
- account.Status = "work"
- } else {
- account.Status = err.Error()
- }
- _ = model.SaveAccount(account)
- return err
-}
-
-func (driver Alist) File(path string, account *model.Account) (*model.File, error) {
- now := time.Now()
- if path == "/" {
- return &model.File{
- Id: "root",
- Name: "root",
- Size: 0,
- Type: conf.FOLDER,
- Driver: driver.Config().Name,
- UpdatedAt: &now,
- }, nil
- }
- _, files, err := driver.Path(utils.Dir(path), account)
- if err != nil {
- return nil, err
- }
- if files == nil {
- return nil, base.ErrPathNotFound
- }
- name := utils.Base(path)
- for _, file := range files {
- if file.Name == name {
- return &file, nil
- }
- }
- return nil, base.ErrPathNotFound
-}
-
-func (driver Alist) Files(path string, account *model.Account) ([]model.File, error) {
- //return nil, base.ErrNotImplement
- _, files, err := driver.Path(path, account)
- if err != nil {
- return nil, err
- }
- if files == nil {
- return nil, base.ErrNotFolder
- }
- return files, nil
-}
-
-func (driver Alist) Link(args base.Args, account *model.Account) (*base.Link, error) {
- path := args.Path
- path = utils.ParsePath(path)
- name := utils.Base(path)
- flag := "d"
- if utils.GetFileType(filepath.Ext(path)) == conf.TEXT {
- flag = "p"
- }
- link := base.Link{}
- link.Url = fmt.Sprintf("%s/%s%s?sign=%s", account.SiteUrl, flag, path, utils.SignWithToken(name, conf.Token))
- return &link, nil
-}
-
-func (driver Alist) Path(path string, account *model.Account) (*model.File, []model.File, error) {
- path = utils.ParsePath(path)
- path = filepath.Join(account.RootFolder, path)
- path = strings.ReplaceAll(path, "\\", "/")
- cache, err := base.GetCache(path, account)
- if err == nil {
- files := cache.([]model.File)
- return nil, files, nil
- }
- var resp PathResp
- _, err = base.RestyClient.R().SetResult(&resp).
- SetHeader("Authorization", account.AccessToken).
- SetBody(base.Json{
- "path": path,
- }).Post(account.SiteUrl + "/api/public/path")
- if err != nil {
- return nil, nil, err
- }
- if resp.Code != 200 {
- return nil, nil, errors.New(resp.Message)
- }
- if resp.Data.Type == "file" {
- return &resp.Data.Files[0], nil, nil
- }
- if len(resp.Data.Files) > 0 {
- _ = base.SetCache(path, resp.Data.Files, account)
- }
- return nil, resp.Data.Files, nil
-}
-
-//func (driver Alist) Proxy(r *http.Request, account *model.Account) {}
-
-func (driver Alist) Preview(path string, account *model.Account) (interface{}, error) {
- var resp PathResp
- _, err := base.RestyClient.R().SetResult(&resp).
- SetHeader("Authorization", account.AccessToken).
- SetBody(base.Json{
- "path": path,
- }).Post(account.SiteUrl + "/api/public/preview")
- if err != nil {
- return nil, err
- }
- if resp.Code != 200 {
- return nil, errors.New(resp.Message)
- }
- return resp.Data, nil
-}
-
-func (driver Alist) MakeDir(path string, account *model.Account) error {
- return base.ErrNotImplement
-}
-
-func (driver Alist) Move(src string, dst string, account *model.Account) error {
- return base.ErrNotImplement
-}
-
-func (driver Alist) Rename(src string, dst string, account *model.Account) error {
- return base.ErrNotImplement
-}
-
-func (driver Alist) Copy(src string, dst string, account *model.Account) error {
- return base.ErrNotImplement
-}
-
-func (driver Alist) Delete(path string, account *model.Account) error {
- return base.ErrNotImplement
-}
-
-func (driver Alist) Upload(file *model.FileStream, account *model.Account) error {
- return base.ErrNotImplement
-}
-
-var _ base.Driver = (*Alist)(nil)
diff --git a/drivers/all.go b/drivers/all.go
deleted file mode 100644
index cf0fb8e5..00000000
--- a/drivers/all.go
+++ /dev/null
@@ -1,52 +0,0 @@
-package drivers
-
-import (
- _ "github.com/Xhofe/alist/drivers/123"
- _ "github.com/Xhofe/alist/drivers/139"
- _ "github.com/Xhofe/alist/drivers/189"
- _ "github.com/Xhofe/alist/drivers/189pc"
- _ "github.com/Xhofe/alist/drivers/alidrive"
- _ "github.com/Xhofe/alist/drivers/alist"
- _ "github.com/Xhofe/alist/drivers/baidu"
- "github.com/Xhofe/alist/drivers/base"
- _ "github.com/Xhofe/alist/drivers/ftp"
- _ "github.com/Xhofe/alist/drivers/google"
- _ "github.com/Xhofe/alist/drivers/lanzou"
- _ "github.com/Xhofe/alist/drivers/mediatrack"
- _ "github.com/Xhofe/alist/drivers/native"
- _ "github.com/Xhofe/alist/drivers/onedrive"
- _ "github.com/Xhofe/alist/drivers/pikpak"
- _ "github.com/Xhofe/alist/drivers/quark"
- _ "github.com/Xhofe/alist/drivers/s3"
- _ "github.com/Xhofe/alist/drivers/sftp"
- _ "github.com/Xhofe/alist/drivers/shandian"
- _ "github.com/Xhofe/alist/drivers/teambition"
- _ "github.com/Xhofe/alist/drivers/uss"
- _ "github.com/Xhofe/alist/drivers/webdav"
- _ "github.com/Xhofe/alist/drivers/xunlei"
- _ "github.com/Xhofe/alist/drivers/yandex"
- _ "github.com/Xhofe/alist/drivers/baiduphoto"
- log "github.com/sirupsen/logrus"
- "strings"
-)
-
-var NoCors string
-var NoUpload string
-
-func GetConfig() {
- for k, v := range base.GetDriversMap() {
- if v.Config().NoCors {
- NoCors += k + ","
- }
- if v.Upload(nil, nil) != base.ErrEmptyFile {
- NoUpload += k + ","
- }
- }
- NoCors = strings.Trim(NoCors, ",")
- NoUpload += "root"
-}
-
-func init() {
- log.Debug("all init")
- GetConfig()
-}
diff --git a/drivers/baidu/baidu.go b/drivers/baidu/baidu.go
deleted file mode 100644
index fe0b7ca1..00000000
--- a/drivers/baidu/baidu.go
+++ /dev/null
@@ -1,185 +0,0 @@
-package baidu
-
-import (
- "fmt"
- "github.com/Xhofe/alist/conf"
- "github.com/Xhofe/alist/drivers/base"
- "github.com/Xhofe/alist/model"
- "github.com/Xhofe/alist/utils"
- "github.com/go-resty/resty/v2"
- jsoniter "github.com/json-iterator/go"
- "path"
- "strconv"
-)
-
-func (driver Baidu) RefreshToken(account *model.Account) error {
- err := driver.refreshToken(account)
- if err != nil && err == base.ErrEmptyToken {
- err = driver.refreshToken(account)
- }
- if err != nil {
- account.Status = err.Error()
- }
- _ = model.SaveAccount(account)
- return err
-}
-
-func (driver Baidu) refreshToken(account *model.Account) error {
- u := "https://openapi.baidu.com/oauth/2.0/token"
- var resp base.TokenResp
- var e TokenErrResp
- _, err := base.RestyClient.R().SetResult(&resp).SetError(&e).SetQueryParams(map[string]string{
- "grant_type": "refresh_token",
- "refresh_token": account.RefreshToken,
- "client_id": account.ClientId,
- "client_secret": account.ClientSecret,
- }).Get(u)
- if err != nil {
- return err
- }
- if e.Error != "" {
- return fmt.Errorf("%s : %s", e.Error, e.ErrorDescription)
- }
- if resp.RefreshToken == "" {
- return base.ErrEmptyToken
- }
- account.Status = "work"
- account.AccessToken, account.RefreshToken = resp.AccessToken, resp.RefreshToken
- return nil
-}
-
-func (driver Baidu) Request(fullurl string, method int, headers, query, form map[string]string, data interface{}, resp interface{}, account *model.Account) ([]byte, error) {
- req := base.RestyClient.R()
- req.SetQueryParam("access_token", account.AccessToken)
- if headers != nil {
- req.SetHeaders(headers)
- }
- if query != nil {
- req.SetQueryParams(query)
- }
- if form != nil {
- req.SetFormData(form)
- }
- if data != nil {
- req.SetBody(data)
- }
- if resp != nil {
- req.SetResult(resp)
- }
- var res *resty.Response
- var err error
- switch method {
- case base.Get:
- res, err = req.Get(fullurl)
- case base.Post:
- res, err = req.Post(fullurl)
- case base.Patch:
- res, err = req.Patch(fullurl)
- case base.Delete:
- res, err = req.Delete(fullurl)
- case base.Put:
- res, err = req.Put(fullurl)
- default:
- return nil, base.ErrNotSupport
- }
- if err != nil {
- return nil, err
- }
- //log.Debug(res.String())
- errno := jsoniter.Get(res.Body(), "errno").ToInt()
- if errno != 0 {
- if errno == -6 {
- err = driver.RefreshToken(account)
- if err != nil {
- return nil, err
- }
- return driver.Request(fullurl, method, headers, query, form, data, resp, account)
- }
- return nil, fmt.Errorf("errno: %d, refer to https://pan.baidu.com/union/doc/", errno)
- }
- return res.Body(), nil
-}
-
-func (driver Baidu) Get(pathname string, params map[string]string, resp interface{}, account *model.Account) ([]byte, error) {
- return driver.Request("https://pan.baidu.com/rest/2.0"+pathname, base.Get, nil, params, nil, nil, resp, account)
-}
-
-func (driver Baidu) Post(pathname string, params map[string]string, data interface{}, resp interface{}, account *model.Account) ([]byte, error) {
- return driver.Request("https://pan.baidu.com/rest/2.0"+pathname, base.Post, nil, params, nil, data, resp, account)
-}
-
-func (driver Baidu) manage(opera string, filelist interface{}, account *model.Account) ([]byte, error) {
- params := map[string]string{
- "method": "filemanager",
- "opera": opera,
- }
- marshal, err := utils.Json.Marshal(filelist)
- if err != nil {
- return nil, err
- }
- data := fmt.Sprintf("async=0&filelist=%s&ondup=newcopy", string(marshal))
- return driver.Post("/xpan/file", params, data, nil, account)
-}
-
-func (driver Baidu) GetFiles(dir string, account *model.Account) ([]model.File, error) {
- dir = utils.Join(account.RootFolder, dir)
- start := 0
- limit := 200
- params := map[string]string{
- "method": "list",
- "dir": dir,
- "web": "web",
- }
- if account.OrderBy != "" {
- params["order"] = account.OrderBy
- if account.OrderDirection == "desc" {
- params["desc"] = "1"
- }
- }
- res := make([]model.File, 0)
- for {
- params["start"] = strconv.Itoa(start)
- params["limit"] = strconv.Itoa(limit)
- start += limit
- var resp ListResp
- _, err := driver.Get("/xpan/file", params, &resp, account)
- if err != nil {
- return nil, err
- }
- if len(resp.List) == 0 {
- break
- }
- for _, f := range resp.List {
- file := model.File{
- Id: strconv.FormatInt(f.FsId, 10),
- Name: f.ServerFilename,
- Size: f.Size,
- Driver: driver.Config().Name,
- UpdatedAt: getTime(f.ServerMtime),
- Thumbnail: f.Thumbs.Url3,
- }
- if f.Isdir == 1 {
- file.Type = conf.FOLDER
- } else {
- file.Type = utils.GetFileType(path.Ext(f.ServerFilename))
- }
- res = append(res, file)
- }
- }
- return res, nil
-}
-
-func (driver Baidu) create(path string, size uint64, isdir int, uploadid, block_list string, account *model.Account) ([]byte, error) {
- params := map[string]string{
- "method": "create",
- }
- data := fmt.Sprintf("path=%s&size=%d&isdir=%d", path, size, isdir)
- if uploadid != "" {
- data += fmt.Sprintf("&uploadid=%s&block_list=%s", uploadid, block_list)
- }
- return driver.Post("/xpan/file", params, data, nil, account)
-}
-
-func init() {
- base.RegisterDriver(&Baidu{})
-}
diff --git a/drivers/baidu/driver.go b/drivers/baidu/driver.go
deleted file mode 100644
index 1f17d21b..00000000
--- a/drivers/baidu/driver.go
+++ /dev/null
@@ -1,399 +0,0 @@
-package baidu
-
-import (
- "bytes"
- "crypto/md5"
- "encoding/hex"
- "fmt"
- "github.com/Xhofe/alist/conf"
- "github.com/Xhofe/alist/drivers/base"
- "github.com/Xhofe/alist/model"
- "github.com/Xhofe/alist/utils"
- log "github.com/sirupsen/logrus"
- "io"
- "io/ioutil"
- "math"
- "os"
- "path/filepath"
- "strconv"
- "strings"
-)
-
-type Baidu struct{}
-
-func (driver Baidu) Config() base.DriverConfig {
- return base.DriverConfig{
- Name: "Baidu.Disk",
- }
-}
-
-func (driver Baidu) Items() []base.Item {
- return []base.Item{
- {
- Name: "refresh_token",
- Label: "refresh token",
- Type: base.TypeString,
- Required: true,
- },
- {
- Name: "root_folder",
- Label: "root folder path",
- Type: base.TypeString,
- Default: "/",
- Required: true,
- },
- {
- Name: "order_by",
- Label: "order_by",
- Type: base.TypeSelect,
- Default: "name",
- Values: "name,time,size",
- Required: false,
- },
- {
- Name: "order_direction",
- Label: "order_direction",
- Type: base.TypeSelect,
- Values: "asc,desc",
- Default: "asc",
- Required: false,
- },
- {
- Name: "internal_type",
- Label: "download api",
- Type: base.TypeSelect,
- Required: true,
- Values: "official,crack",
- Default: "official",
- },
- {
- Name: "client_id",
- Label: "client id",
- Default: "iYCeC9g08h5vuP9UqvPHKKSVrKFXGa1v",
- Type: base.TypeString,
- Required: true,
- },
- {
- Name: "client_secret",
- Label: "client secret",
- Default: "jXiFMOPVPCWlO2M5CwWQzffpNPaGTRBG",
- Type: base.TypeString,
- Required: true,
- },
- }
-}
-
-func (driver Baidu) Save(account *model.Account, old *model.Account) error {
- if account == nil {
- return nil
- }
- return driver.RefreshToken(account)
-}
-
-func (driver Baidu) File(path string, account *model.Account) (*model.File, error) {
- path = utils.ParsePath(path)
- if path == "/" {
- return &model.File{
- Id: account.RootFolder,
- Name: account.Name,
- Size: 0,
- Type: conf.FOLDER,
- Driver: driver.Config().Name,
- UpdatedAt: account.UpdatedAt,
- }, nil
- }
- dir, name := filepath.Split(path)
- files, err := driver.Files(dir, account)
- if err != nil {
- return nil, err
- }
- for _, file := range files {
- if file.Name == name {
- return &file, nil
- }
- }
- return nil, base.ErrPathNotFound
-}
-
-func (driver Baidu) Files(path string, account *model.Account) ([]model.File, error) {
- path = utils.ParsePath(path)
- cache, err := base.GetCache(path, account)
- if err == nil {
- files, _ := cache.([]model.File)
- return files, nil
- }
- files, err := driver.GetFiles(path, account)
- if err != nil {
- return nil, err
- }
- if len(files) > 0 {
- _ = base.SetCache(path, files, account)
- }
- return files, nil
-}
-
-func (driver Baidu) Link(args base.Args, account *model.Account) (*base.Link, error) {
- if account.InternalType == "crack" {
- return driver.LinkCrack(args, account)
- }
- return driver.LinkOfficial(args, account)
-}
-
-func (driver Baidu) LinkOfficial(args base.Args, account *model.Account) (*base.Link, error) {
- file, err := driver.File(args.Path, account)
- if err != nil {
- return nil, err
- }
- if file.IsDir() {
- return nil, base.ErrNotFile
- }
- var resp DownloadResp
- params := map[string]string{
- "method": "filemetas",
- "fsids": fmt.Sprintf("[%s]", file.Id),
- "dlink": "1",
- }
- _, err = driver.Get("/xpan/multimedia", params, &resp, account)
- if err != nil {
- return nil, err
- }
- u := fmt.Sprintf("%s&access_token=%s", resp.List[0].Dlink, account.AccessToken)
- res, err := base.NoRedirectClient.R().SetHeader("User-Agent", "pan.baidu.com").Head(u)
- if err != nil {
- return nil, err
- }
- //if res.StatusCode() == 302 {
- u = res.Header().Get("location")
- //}
- return &base.Link{
- Url: u,
- Headers: []base.Header{
- {Name: "User-Agent", Value: "pan.baidu.com"},
- }}, nil
-}
-
-func (driver Baidu) LinkCrack(args base.Args, account *model.Account) (*base.Link, error) {
- file, err := driver.File(args.Path, account)
- if err != nil {
- return nil, err
- }
- if file.IsDir() {
- return nil, base.ErrNotFile
- }
- var resp DownloadResp2
- param := map[string]string{
- "target": fmt.Sprintf("[\"%s\"]", utils.Join(account.RootFolder, args.Path)),
- "dlink": "1",
- "web": "5",
- "origin": "dlna",
- }
- _, err = driver.Request("https://pan.baidu.com/api/filemetas", base.Get, nil, param, nil, nil, &resp, account)
- if err != nil {
- return nil, err
- }
- return &base.Link{
- Url: resp.Info[0].Dlink,
- Headers: []base.Header{
- {Name: "User-Agent", Value: "pan.baidu.com"},
- }}, nil
-}
-
-func (driver Baidu) Path(path string, account *model.Account) (*model.File, []model.File, error) {
- file, err := driver.File(path, account)
- if err != nil {
- return nil, nil, err
- }
- if !file.IsDir() {
- return file, nil, nil
- }
- files, err := driver.Files(path, account)
- if err != nil {
- return nil, nil, err
- }
- return nil, files, nil
-}
-
-//func (driver Baidu) Proxy(r *http.Request, account *model.Account) {
-// r.Header.Set("User-Agent", "pan.baidu.com")
-//}
-
-func (driver Baidu) Preview(path string, account *model.Account) (interface{}, error) {
- return nil, base.ErrNotSupport
-}
-
-func (driver Baidu) MakeDir(path string, account *model.Account) error {
- _, err := driver.create(utils.Join(account.RootFolder, path), 0, 1, "", "", account)
- return err
-}
-
-func (driver Baidu) Move(src string, dst string, account *model.Account) error {
- path := utils.Join(account.RootFolder, src)
- dest, newname := utils.Split(utils.Join(account.RootFolder, dst))
- data := []base.Json{
- {
- "path": path,
- "dest": dest,
- "newname": newname,
- },
- }
- _, err := driver.manage("move", data, account)
- return err
-}
-
-func (driver Baidu) Rename(src string, dst string, account *model.Account) error {
- path := utils.Join(account.RootFolder, src)
- newname := utils.Base(dst)
- data := []base.Json{
- {
- "path": path,
- "newname": newname,
- },
- }
- _, err := driver.manage("rename", data, account)
- return err
-}
-
-func (driver Baidu) Copy(src string, dst string, account *model.Account) error {
- path := utils.Join(account.RootFolder, src)
- dest, newname := utils.Split(utils.Join(account.RootFolder, dst))
- data := []base.Json{
- {
- "path": path,
- "dest": dest,
- "newname": newname,
- },
- }
- _, err := driver.manage("copy", data, account)
- return err
-}
-
-func (driver Baidu) Delete(path string, account *model.Account) error {
- path = utils.Join(account.RootFolder, path)
- data := []string{path}
- _, err := driver.manage("delete", data, account)
- return err
-}
-
-func (driver Baidu) Upload(file *model.FileStream, account *model.Account) error {
- if file == nil {
- return base.ErrEmptyFile
- }
- tempFile, err := ioutil.TempFile(conf.Conf.TempDir, "file-*")
- if err != nil {
- return err
- }
- defer func() {
- _ = tempFile.Close()
- _ = os.Remove(tempFile.Name())
- }()
- _, err = io.Copy(tempFile, file)
- if err != nil {
- return err
- }
- _, err = tempFile.Seek(0, io.SeekStart)
- if err != nil {
- return err
- }
- var Default uint64 = 4 * 1024 * 1024
- defaultByteData := make([]byte, Default)
- count := int(math.Ceil(float64(file.GetSize()) / float64(Default)))
- var SliceSize uint64 = 256 * 1024
- // cal md5
- h1 := md5.New()
- h2 := md5.New()
- block_list := make([]string, 0)
- content_md5 := ""
- slice_md5 := ""
- left := file.GetSize()
- for i := 0; i < count; i++ {
- byteSize := Default
- var byteData []byte
- if left < Default {
- byteSize = left
- byteData = make([]byte, byteSize)
- } else {
- byteData = defaultByteData
- }
- left -= byteSize
- _, err = io.ReadFull(tempFile, byteData)
- if err != nil {
- return err
- }
- h1.Write(byteData)
- h2.Write(byteData)
- block_list = append(block_list, fmt.Sprintf("\"%s\"", hex.EncodeToString(h2.Sum(nil))))
- h2.Reset()
- }
- content_md5 = hex.EncodeToString(h1.Sum(nil))
- _, err = tempFile.Seek(0, io.SeekStart)
- if err != nil {
- return err
- }
- if file.GetSize() <= SliceSize {
- slice_md5 = content_md5
- } else {
- sliceData := make([]byte, SliceSize)
- _, err = io.ReadFull(tempFile, sliceData)
- if err != nil {
- return err
- }
- h2.Write(sliceData)
- slice_md5 = hex.EncodeToString(h2.Sum(nil))
- _, err = tempFile.Seek(0, io.SeekStart)
- if err != nil {
- return err
- }
- }
- path := encodeURIComponent(utils.Join(account.RootFolder, file.ParentPath, file.Name))
- block_list_str := fmt.Sprintf("[%s]", strings.Join(block_list, ","))
- data := fmt.Sprintf("path=%s&size=%d&isdir=0&autoinit=1&block_list=%s&content-md5=%s&slice-md5=%s",
- path, file.GetSize(),
- block_list_str,
- content_md5, slice_md5)
- params := map[string]string{
- "method": "precreate",
- }
- var precreateResp PrecreateResp
- _, err = driver.Post("/xpan/file", params, data, &precreateResp, account)
- if err != nil {
- return err
- }
- log.Debugf("%+v", precreateResp)
- if precreateResp.ReturnType == 2 {
- return nil
- }
- params = map[string]string{
- "method": "upload",
- "access_token": account.AccessToken,
- "type": "tmpfile",
- "path": path,
- "uploadid": precreateResp.Uploadid,
- }
- left = file.GetSize()
- for _, partseq := range precreateResp.BlockList {
- byteSize := Default
- var byteData []byte
- if left < Default {
- byteSize = left
- byteData = make([]byte, byteSize)
- } else {
- byteData = defaultByteData
- }
- left -= byteSize
- _, err = io.ReadFull(tempFile, byteData)
- if err != nil {
- return err
- }
- u := "https://d.pcs.baidu.com/rest/2.0/pcs/superfile2"
- params["partseq"] = strconv.Itoa(partseq)
- res, err := base.RestyClient.R().SetQueryParams(params).SetFileReader("file", file.Name, bytes.NewReader(byteData)).Post(u)
- if err != nil {
- return err
- }
- log.Debugln(res.String())
- }
- _, err = driver.create(path, file.GetSize(), 0, precreateResp.Uploadid, block_list_str, account)
- return err
-}
-
-var _ base.Driver = (*Baidu)(nil)
diff --git a/drivers/baidu/types.go b/drivers/baidu/types.go
deleted file mode 100644
index 5b4d2a71..00000000
--- a/drivers/baidu/types.go
+++ /dev/null
@@ -1,143 +0,0 @@
-package baidu
-
-type TokenErrResp struct {
- ErrorDescription string `json:"error_description"`
- Error string `json:"error"`
-}
-
-type File struct {
- //TkbindId int `json:"tkbind_id"`
- //OwnerType int `json:"owner_type"`
- //Category int `json:"category"`
- //RealCategory string `json:"real_category"`
- FsId int64 `json:"fs_id"`
- ServerMtime int64 `json:"server_mtime"`
- //OperId int `json:"oper_id"`
- //ServerCtime int `json:"server_ctime"`
- Thumbs struct {
- //Icon string `json:"icon"`
- Url3 string `json:"url3"`
- //Url2 string `json:"url2"`
- //Url1 string `json:"url1"`
- } `json:"thumbs"`
- //Wpfile int `json:"wpfile"`
- //LocalMtime int `json:"local_mtime"`
- Size int64 `json:"size"`
- //ExtentTinyint7 int `json:"extent_tinyint7"`
- Path string `json:"path"`
- //Share int `json:"share"`
- //ServerAtime int `json:"server_atime"`
- //Pl int `json:"pl"`
- //LocalCtime int `json:"local_ctime"`
- ServerFilename string `json:"server_filename"`
- //Md5 string `json:"md5"`
- //OwnerId int `json:"owner_id"`
- //Unlist int `json:"unlist"`
- Isdir int `json:"isdir"`
-}
-
-type ListResp struct {
- Errno int `json:"errno"`
- GuidInfo string `json:"guid_info"`
- List []File `json:"list"`
- RequestId int64 `json:"request_id"`
- Guid int `json:"guid"`
-}
-
-type DownloadResp struct {
- Errmsg string `json:"errmsg"`
- Errno int `json:"errno"`
- List []struct {
- //Category int `json:"category"`
- //DateTaken int `json:"date_taken,omitempty"`
- Dlink string `json:"dlink"`
- //Filename string `json:"filename"`
- //FsId int64 `json:"fs_id"`
- //Height int `json:"height,omitempty"`
- //Isdir int `json:"isdir"`
- //Md5 string `json:"md5"`
- //OperId int `json:"oper_id"`
- //Path string `json:"path"`
- //ServerCtime int `json:"server_ctime"`
- //ServerMtime int `json:"server_mtime"`
- //Size int `json:"size"`
- //Thumbs struct {
- // Icon string `json:"icon,omitempty"`
- // Url1 string `json:"url1,omitempty"`
- // Url2 string `json:"url2,omitempty"`
- // Url3 string `json:"url3,omitempty"`
- //} `json:"thumbs"`
- //Width int `json:"width,omitempty"`
- } `json:"list"`
- //Names struct {
- //} `json:"names"`
- RequestId string `json:"request_id"`
-}
-
-type DownloadResp2 struct {
- Errno int `json:"errno"`
- Info []struct {
- //ExtentTinyint4 int `json:"extent_tinyint4"`
- //ExtentTinyint1 int `json:"extent_tinyint1"`
- //Bitmap string `json:"bitmap"`
- //Category int `json:"category"`
- //Isdir int `json:"isdir"`
- //Videotag int `json:"videotag"`
- Dlink string `json:"dlink"`
- //OperID int64 `json:"oper_id"`
- //PathMd5 int `json:"path_md5"`
- //Wpfile int `json:"wpfile"`
- //LocalMtime int `json:"local_mtime"`
- /*Thumbs struct {
- Icon string `json:"icon"`
- URL3 string `json:"url3"`
- URL2 string `json:"url2"`
- URL1 string `json:"url1"`
- } `json:"thumbs"`*/
- //PlaySource int `json:"play_source"`
- //Share int `json:"share"`
- //FileKey string `json:"file_key"`
- //Errno int `json:"errno"`
- //LocalCtime int `json:"local_ctime"`
- //Rotate int `json:"rotate"`
- //Metadata time.Time `json:"metadata"`
- //Height int `json:"height"`
- //SampleRate int `json:"sample_rate"`
- //Width int `json:"width"`
- //OwnerType int `json:"owner_type"`
- //Privacy int `json:"privacy"`
- //ExtentInt3 int64 `json:"extent_int3"`
- //RealCategory string `json:"real_category"`
- //SrcLocation string `json:"src_location"`
- //MetaInfo string `json:"meta_info"`
- //ID string `json:"id"`
- //Duration int `json:"duration"`
- //FileSize string `json:"file_size"`
- //Channels int `json:"channels"`
- //UseSegment int `json:"use_segment"`
- //ServerCtime int `json:"server_ctime"`
- //Resolution string `json:"resolution"`
- //OwnerID int `json:"owner_id"`
- //ExtraInfo string `json:"extra_info"`
- //Size int `json:"size"`
- //FsID int64 `json:"fs_id"`
- //ExtentTinyint3 int `json:"extent_tinyint3"`
- //Md5 string `json:"md5"`
- //Path string `json:"path"`
- //FrameRate int `json:"frame_rate"`
- //ExtentTinyint2 int `json:"extent_tinyint2"`
- //ServerFilename string `json:"server_filename"`
- //ServerMtime int `json:"server_mtime"`
- //TkbindID int `json:"tkbind_id"`
- } `json:"info"`
- RequestID int64 `json:"request_id"`
-}
-
-type PrecreateResp struct {
- Path string `json:"path"`
- Uploadid string `json:"uploadid"`
- ReturnType int `json:"return_type"`
- BlockList []int `json:"block_list"`
- Errno int `json:"errno"`
- RequestId int64 `json:"request_id"`
-}
diff --git a/drivers/baidu/util.go b/drivers/baidu/util.go
deleted file mode 100644
index bf41c7f1..00000000
--- a/drivers/baidu/util.go
+++ /dev/null
@@ -1,18 +0,0 @@
-package baidu
-
-import (
- "net/url"
- "strings"
- "time"
-)
-
-func getTime(t int64) *time.Time {
- tm := time.Unix(t, 0)
- return &tm
-}
-
-func encodeURIComponent(str string) string {
- r := url.QueryEscape(str)
- r = strings.ReplaceAll(r, "+", "%20")
- return r
-}
diff --git a/drivers/baiduphoto/baidu.go b/drivers/baiduphoto/baidu.go
deleted file mode 100644
index c192939b..00000000
--- a/drivers/baiduphoto/baidu.go
+++ /dev/null
@@ -1,259 +0,0 @@
-package baiduphoto
-
-import (
- "fmt"
- "net/http"
-
- "github.com/Xhofe/alist/drivers/base"
- "github.com/Xhofe/alist/model"
- "github.com/Xhofe/alist/utils"
- "github.com/go-resty/resty/v2"
- log "github.com/sirupsen/logrus"
-)
-
-func (driver Baidu) RefreshToken(account *model.Account) error {
- err := driver.refreshToken(account)
- if err != nil && err == base.ErrEmptyToken {
- err = driver.refreshToken(account)
- }
- if err != nil {
- account.Status = err.Error()
- }
- _ = model.SaveAccount(account)
- return err
-}
-
-func (driver Baidu) refreshToken(account *model.Account) error {
- u := "https://openapi.baidu.com/oauth/2.0/token"
- var resp base.TokenResp
- var e TokenErrResp
- _, err := base.RestyClient.R().
- SetResult(&resp).
- SetError(&e).
- SetQueryParams(map[string]string{
- "grant_type": "refresh_token",
- "refresh_token": account.RefreshToken,
- "client_id": account.ClientId,
- "client_secret": account.ClientSecret,
- }).Get(u)
- if err != nil {
- return err
- }
- if e.ErrorMsg != "" {
- return &e
- }
- if resp.RefreshToken == "" {
- return base.ErrEmptyToken
- }
- account.Status = "work"
- account.AccessToken, account.RefreshToken = resp.AccessToken, resp.RefreshToken
- return nil
-}
-
-func (driver Baidu) Request(method string, url string, callback func(*resty.Request), account *model.Account) (*resty.Response, error) {
- req := base.RestyClient.R()
- req.SetQueryParam("access_token", account.AccessToken)
- if callback != nil {
- callback(req)
- }
-
- res, err := req.Execute(method, url)
- if err != nil {
- return nil, err
- }
- log.Debug(res.String())
-
- var erron Erron
- if err = utils.Json.Unmarshal(res.Body(), &erron); err != nil {
- return nil, err
- }
-
- switch erron.Errno {
- case 0:
- return res, nil
- case -6:
- if err = driver.RefreshToken(account); err != nil {
- return nil, err
- }
- default:
- return nil, fmt.Errorf("errno: %d, refer to https://photo.baidu.com/union/doc", erron.Errno)
- }
- return driver.Request(method, url, callback, account)
-}
-
-// 获取所有根文件
-func (driver Baidu) GetAllFile(account *model.Account) (files []File, err error) {
- var cursor string
-
- for {
- var resp FileListResp
- _, err = driver.Request(http.MethodGet, FILE_API_URL_V1+"/list", func(r *resty.Request) {
- r.SetQueryParams(map[string]string{
- "need_thumbnail": "1",
- "need_filter_hidden": "0",
- "cursor": cursor,
- })
- r.SetResult(&resp)
- }, account)
- if err != nil {
- return
- }
-
- cursor = resp.Cursor
- files = append(files, resp.List...)
-
- if !resp.HasNextPage() {
- return
- }
- }
-}
-
-// 获取所有相册
-func (driver Baidu) GetAllAlbum(account *model.Account) (albums []Album, err error) {
- var cursor string
- for {
- var resp AlbumListResp
- _, err = driver.Request(http.MethodGet, ALBUM_API_URL+"/list", func(r *resty.Request) {
- r.SetQueryParams(map[string]string{
- "need_amount": "1",
- "limit": "100",
- "cursor": cursor,
- })
- r.SetResult(&resp)
- }, account)
- if err != nil {
- return
- }
- if albums == nil {
- albums = make([]Album, 0, resp.TotalCount)
- }
-
- cursor = resp.Cursor
- albums = append(albums, resp.List...)
-
- if !resp.HasNextPage() {
- return
- }
- }
-}
-
-// 获取相册中所有文件
-func (driver Baidu) GetAllAlbumFile(albumID string, account *model.Account) (files []AlbumFile, err error) {
- var cursor string
- for {
- var resp AlbumFileListResp
- _, err = driver.Request(http.MethodGet, ALBUM_API_URL+"/listfile", func(r *resty.Request) {
- r.SetQueryParams(map[string]string{
- "album_id": splitID(albumID)[0],
- "need_amount": "1",
- "limit": "1000",
- "cursor": cursor,
- })
- r.SetResult(&resp)
- }, account)
- if err != nil {
- return
- }
- if files == nil {
- files = make([]AlbumFile, 0, resp.TotalCount)
- }
-
- cursor = resp.Cursor
- files = append(files, resp.List...)
-
- if !resp.HasNextPage() {
- return
- }
- }
-}
-
-// 创建相册
-func (driver Baidu) CreateAlbum(name string, account *model.Account) error {
- if !checkName(name) {
- return ErrNotSupportName
- }
- _, err := driver.Request(http.MethodPost, ALBUM_API_URL+"/create", func(r *resty.Request) {
- r.SetQueryParams(map[string]string{
- "title": name,
- "tid": getTid(),
- "source": "0",
- })
- }, account)
- return err
-}
-
-// 相册改名
-func (driver Baidu) SetAlbumName(albumID string, name string, account *model.Account) error {
- if !checkName(name) {
- return ErrNotSupportName
- }
-
- e := splitID(albumID)
- _, err := driver.Request(http.MethodPost, ALBUM_API_URL+"/settitle", func(r *resty.Request) {
- r.SetFormData(map[string]string{
- "title": name,
- "album_id": e[0],
- "tid": e[1],
- })
- }, account)
- return err
-}
-
-// 删除相册
-func (driver Baidu) DeleteAlbum(albumID string, account *model.Account) error {
- e := splitID(albumID)
- _, err := driver.Request(http.MethodPost, ALBUM_API_URL+"/delete", func(r *resty.Request) {
- r.SetFormData(map[string]string{
- "album_id": e[0],
- "tid": e[1],
- "delete_origin_image": "0", // 是否删除原图 0 不删除
- })
- }, account)
- return err
-}
-
-// 删除相册文件
-func (driver Baidu) DeleteAlbumFile(albumID string, account *model.Account, fileIDs ...string) error {
- e := splitID(albumID)
- _, err := driver.Request(http.MethodPost, ALBUM_API_URL+"/delfile", func(r *resty.Request) {
- r.SetFormData(map[string]string{
- "album_id": e[0],
- "tid": e[1],
- "list": fsidsFormat(fileIDs...),
- "del_origin": "0", // 是否删除原图 0 不删除 1 删除
- })
- }, account)
- return err
-}
-
-// 增加相册文件
-func (driver Baidu) AddAlbumFile(albumID string, account *model.Account, fileIDs ...string) error {
- e := splitID(albumID)
- _, err := driver.Request(http.MethodGet, ALBUM_API_URL+"/addfile", func(r *resty.Request) {
- r.SetQueryParams(map[string]string{
- "album_id": e[0],
- "tid": e[1],
- "list": fsidsFormatNotUk(fileIDs...),
- })
- }, account)
- return err
-}
-
-// 保存相册文件为根文件
-func (driver Baidu) CopyAlbumFile(albumID string, account *model.Account, fileID string) (*CopyFile, error) {
- var resp CopyFileResp
- e := splitID(fileID)
- _, err := driver.Request(http.MethodPost, ALBUM_API_URL+"/copyfile", func(r *resty.Request) {
- r.SetFormData(map[string]string{
- "album_id": splitID(albumID)[0],
- "tid": e[2],
- "uk": e[1],
- "list": fsidsFormatNotUk(fileID),
- })
- r.SetResult(&resp)
- }, account)
- if err != nil {
- return nil, err
- }
- return &resp.List[0], err
-}
diff --git a/drivers/baiduphoto/driver.go b/drivers/baiduphoto/driver.go
deleted file mode 100644
index 833ef89f..00000000
--- a/drivers/baiduphoto/driver.go
+++ /dev/null
@@ -1,502 +0,0 @@
-package baiduphoto
-
-import (
- "crypto/md5"
- "encoding/hex"
- "fmt"
- "io"
- "io/ioutil"
- "math"
- "net/http"
- "os"
-
- "github.com/Xhofe/alist/conf"
- "github.com/Xhofe/alist/drivers/base"
- "github.com/Xhofe/alist/model"
- "github.com/Xhofe/alist/utils"
- "github.com/go-resty/resty/v2"
-)
-
-type Baidu struct{}
-
-func init() {
- base.RegisterDriver(new(Baidu))
-}
-
-func (driver Baidu) Config() base.DriverConfig {
- return base.DriverConfig{
- Name: "Baidu.Photo",
- LocalSort: true,
- }
-}
-
-func (driver Baidu) Items() []base.Item {
- return []base.Item{
- {
- Name: "refresh_token",
- Label: "refresh token",
- Type: base.TypeString,
- Required: true,
- },
- {
- Name: "root_folder",
- Label: "album_id",
- Type: base.TypeString,
- },
- {
- Name: "internal_type",
- Label: "download api",
- Type: base.TypeSelect,
- Required: true,
- Values: "file,album",
- Default: "album",
- },
- {
- Name: "client_id",
- Label: "client id",
- Default: "iYCeC9g08h5vuP9UqvPHKKSVrKFXGa1v",
- Type: base.TypeString,
- Required: true,
- },
- {
- Name: "client_secret",
- Label: "client secret",
- Default: "jXiFMOPVPCWlO2M5CwWQzffpNPaGTRBG",
- Type: base.TypeString,
- Required: true,
- },
- }
-}
-
-func (driver Baidu) Save(account *model.Account, old *model.Account) error {
- if account == nil {
- return nil
- }
- return driver.RefreshToken(account)
-}
-
-func (driver Baidu) File(path string, account *model.Account) (*model.File, error) {
- path = utils.ParsePath(path)
- if path == "/" {
- return &model.File{
- Id: account.RootFolder,
- Name: account.Name,
- Size: 0,
- Type: conf.FOLDER,
- Driver: driver.Config().Name,
- UpdatedAt: account.UpdatedAt,
- }, nil
- }
-
- dir, name := utils.Split(path)
- files, err := driver.Files(dir, account)
- if err != nil {
- return nil, err
- }
- for _, file := range files {
- if file.Name == name {
- return &file, nil
- }
- }
- return nil, base.ErrPathNotFound
-}
-
-func (driver Baidu) Files(path string, account *model.Account) ([]model.File, error) {
- path = utils.ParsePath(path)
- var files []model.File
- cache, err := base.GetCache(path, account)
- if err == nil {
- files, _ = cache.([]model.File)
- return files, nil
- }
-
- file, err := driver.File(path, account)
- if err != nil {
- return nil, err
- }
-
- if IsAlbum(file) {
- albumFiles, err := driver.GetAllAlbumFile(file.Id, account)
- if err != nil {
- return nil, err
- }
- files = make([]model.File, 0, len(albumFiles))
- for _, file := range albumFiles {
- var thumbnail string
- if len(file.Thumburl) > 0 {
- thumbnail = file.Thumburl[0]
- }
- files = append(files, model.File{
- Id: joinID(file.Fsid, file.Uk, file.Tid),
- Name: file.Name(),
- Size: file.Size,
- Type: utils.GetFileType(utils.Ext(file.Path)),
- Driver: driver.Config().Name,
- UpdatedAt: getTime(file.Mtime),
- Thumbnail: thumbnail,
- })
- }
- } else if IsRoot(file) {
- albums, err := driver.GetAllAlbum(account)
- if err != nil {
- return nil, err
- }
-
- files = make([]model.File, 0, len(albums))
- for _, album := range albums {
- files = append(files, model.File{
- Id: joinID(album.AlbumID, album.Tid),
- Name: album.Title,
- Size: 0,
- Type: conf.FOLDER,
- Driver: driver.Config().Name,
- UpdatedAt: getTime(album.Mtime),
- })
- }
- } else {
- return nil, base.ErrNotSupport
- }
-
- if len(files) > 0 {
- _ = base.SetCache(path, files, account)
- }
- return files, nil
-}
-
-func (driver Baidu) Link(args base.Args, account *model.Account) (*base.Link, error) {
- if account.InternalType == "file" {
- return driver.LinkFile(args, account)
- }
- return driver.LinkAlbum(args, account)
-}
-
-func (driver Baidu) LinkAlbum(args base.Args, account *model.Account) (*base.Link, error) {
- file, err := driver.File(args.Path, account)
- if err != nil {
- return nil, err
- }
- if !IsAlbumFile(file) {
- return nil, base.ErrNotSupport
- }
-
- album, err := driver.File(utils.Dir(utils.ParsePath(args.Path)), account)
- if err != nil {
- return nil, err
- }
-
- e := splitID(file.Id)
- res, err := base.NoRedirectClient.R().
- SetQueryParams(map[string]string{
- "access_token": account.AccessToken,
- "album_id": splitID(album.Id)[0],
- "tid": e[2],
- "fsid": e[0],
- "uk": e[1],
- }).
- Head(ALBUM_API_URL + "/download")
- if err != nil {
- return nil, err
- }
- return &base.Link{
- Headers: []base.Header{
- {Name: "User-Agent", Value: base.UserAgent},
- },
- Url: res.Header().Get("location"),
- }, nil
-}
-
-func (driver Baidu) LinkFile(args base.Args, account *model.Account) (*base.Link, error) {
- file, err := driver.File(args.Path, account)
- if err != nil {
- return nil, err
- }
-
- if !IsAlbumFile(file) {
- return nil, base.ErrNotSupport
- }
-
- album, err := driver.File(utils.Dir(utils.ParsePath(args.Path)), account)
- if err != nil {
- return nil, err
- }
- // 拷贝到根目录
- cfile, err := driver.CopyAlbumFile(album.Id, account, file.Id)
- if err != nil {
- return nil, err
- }
-
- res, err := driver.Request(http.MethodGet, FILE_API_URL_V2+"/download", func(r *resty.Request) {
- r.SetQueryParams(map[string]string{
- "fsid": fmt.Sprint(cfile.Fsid),
- })
- }, account)
- if err != nil {
- return nil, err
- }
- return &base.Link{
- Headers: []base.Header{
- {Name: "User-Agent", Value: base.UserAgent},
- },
- Url: utils.Json.Get(res.Body(), "dlink").ToString(),
- }, nil
-}
-
-func (driver Baidu) Path(path string, account *model.Account) (*model.File, []model.File, error) {
- path = utils.ParsePath(path)
- file, err := driver.File(path, account)
- if err != nil {
- return nil, nil, err
- }
- if !file.IsDir() {
- return file, nil, nil
- }
- files, err := driver.Files(path, account)
- if err != nil {
- return nil, nil, err
- }
- return nil, files, nil
-}
-
-func (driver Baidu) Preview(path string, account *model.Account) (interface{}, error) {
- return nil, base.ErrNotSupport
-}
-
-func (driver Baidu) Rename(src string, dst string, account *model.Account) error {
- srcFile, err := driver.File(src, account)
- if err != nil {
- return err
- }
-
- if IsAlbum(srcFile) {
- return driver.SetAlbumName(srcFile.Id, utils.Base(dst), account)
- }
- return base.ErrNotSupport
-}
-
-func (driver Baidu) MakeDir(path string, account *model.Account) error {
- dir, name := utils.Split(path)
- parentFile, err := driver.File(dir, account)
- if err != nil {
- return err
- }
-
- if !IsRoot(parentFile) {
- return base.ErrNotSupport
- }
- return driver.CreateAlbum(name, account)
-}
-
-func (driver Baidu) Move(src string, dst string, account *model.Account) error {
- srcFile, err := driver.File(src, account)
- if err != nil {
- return err
- }
-
- if IsAlbumFile(srcFile) {
- // 移动相册文件
- dstAlbum, err := driver.File(utils.Dir(dst), account)
- if err != nil {
- return err
- }
- if !IsAlbum(dstAlbum) {
- return base.ErrNotSupport
- }
-
- srcAlbum, err := driver.File(utils.Dir(src), account)
- if err != nil {
- return err
- }
-
- newFile, err := driver.CopyAlbumFile(srcAlbum.Id, account, srcFile.Id)
- if err != nil {
- return err
- }
- err = driver.DeleteAlbumFile(srcAlbum.Id, account, srcFile.Id)
- if err != nil {
- return err
- }
- err = driver.AddAlbumFile(dstAlbum.Id, account, joinID(newFile.Fsid))
- if err != nil {
- return err
- }
- return nil
- }
- return base.ErrNotSupport
-}
-
-func (driver Baidu) Copy(src string, dst string, account *model.Account) error {
- srcFile, err := driver.File(src, account)
- if err != nil {
- return err
- }
-
- if IsAlbumFile(srcFile) {
- // 复制相册文件
- dstAlbum, err := driver.File(utils.Dir(dst), account)
- if err != nil {
- return err
- }
- if !IsAlbum(dstAlbum) {
- return base.ErrNotSupport
- }
-
- srcAlbum, err := driver.File(utils.Dir(src), account)
- if err != nil {
- return err
- }
-
- newFile, err := driver.CopyAlbumFile(srcAlbum.Id, account, srcFile.Id)
- if err != nil {
- return err
- }
- err = driver.AddAlbumFile(dstAlbum.Id, account, joinID(newFile.Fsid))
- if err != nil {
- return err
- }
- return nil
- }
- return base.ErrNotSupport
-}
-
-func (driver Baidu) Delete(path string, account *model.Account) error {
- file, err := driver.File(path, account)
- if err != nil {
- return err
- }
-
- // 删除相册
- if IsAlbum(file) {
- return driver.DeleteAlbum(file.Id, account)
- }
-
- // 生成相册文件
- if IsAlbumFile(file) {
- // 删除相册文件
- album, err := driver.File(utils.Dir(path), account)
- if err != nil {
- return err
- }
- return driver.DeleteAlbumFile(album.Id, account, file.Id)
- }
- return base.ErrNotSupport
-}
-
-func (driver Baidu) Upload(file *model.FileStream, account *model.Account) error {
- if file == nil {
- return base.ErrEmptyFile
- }
-
- parentFile, err := driver.File(file.ParentPath, account)
- if err != nil {
- return err
- }
-
- if !IsAlbum(parentFile) {
- return base.ErrNotSupport
- }
-
- tempFile, err := ioutil.TempFile(conf.Conf.TempDir, "file-*")
- if err != nil {
- return err
- }
- defer func() {
- tempFile.Close()
- os.Remove(tempFile.Name())
- }()
-
- // 计算需要的数据
- const DEFAULT = 1 << 22
- const SliceSize = 1 << 18
- count := int(math.Ceil(float64(file.Size) / float64(DEFAULT)))
-
- sliceMD5List := make([]string, 0, count)
- fileMd5 := md5.New()
- sliceMd5 := md5.New()
- for i := 1; i <= count; i++ {
- if n, err := io.CopyN(io.MultiWriter(fileMd5, sliceMd5, tempFile), file, DEFAULT); err != io.EOF && n == 0 {
- return err
- }
- sliceMD5List = append(sliceMD5List, hex.EncodeToString(sliceMd5.Sum(nil)))
- sliceMd5.Reset()
- }
-
- if _, err = tempFile.Seek(0, io.SeekStart); err != nil {
- return err
- }
-
- content_md5 := hex.EncodeToString(fileMd5.Sum(nil))
- slice_md5 := content_md5
- if file.GetSize() > SliceSize {
- sliceData := make([]byte, SliceSize)
- if _, err = io.ReadFull(tempFile, sliceData); err != nil {
- return err
- }
- sliceMd5.Write(sliceData)
- slice_md5 = hex.EncodeToString(sliceMd5.Sum(nil))
- if _, err = tempFile.Seek(0, io.SeekStart); err != nil {
- return err
- }
- }
-
- // 开始执行上传
- params := map[string]string{
- "autoinit": "1",
- "isdir": "0",
- "rtype": "1",
- "ctype": "11",
- "path": utils.ParsePath(file.Name),
- "size": fmt.Sprint(file.Size),
- "slice-md5": slice_md5,
- "content-md5": content_md5,
- "block_list": MustString(utils.Json.MarshalToString(sliceMD5List)),
- }
-
- // 预上传
- var precreateResp PrecreateResp
- _, err = driver.Request(http.MethodPost, FILE_API_URL_V1+"/precreate", func(r *resty.Request) {
- r.SetFormData(params)
- r.SetResult(&precreateResp)
- }, account)
- if err != nil {
- return err
- }
-
- switch precreateResp.ReturnType {
- case 1: // 上传文件
- uploadParams := map[string]string{
- "method": "upload",
- "path": params["path"],
- "uploadid": precreateResp.UploadID,
- }
-
- for i := 0; i < count; i++ {
- uploadParams["partseq"] = fmt.Sprint(i)
- _, err = driver.Request(http.MethodPost, "https://c3.pcs.baidu.com/rest/2.0/pcs/superfile2", func(r *resty.Request) {
- r.SetQueryParams(uploadParams)
- r.SetFileReader("file", file.Name, io.LimitReader(tempFile, DEFAULT))
- }, account)
- if err != nil {
- return err
- }
- }
- fallthrough
- case 2: // 创建文件
- params["uploadid"] = precreateResp.UploadID
- _, err = driver.Request(http.MethodPost, FILE_API_URL_V1+"/create", func(r *resty.Request) {
- r.SetFormData(params)
- r.SetResult(&precreateResp)
- }, account)
- if err != nil {
- return err
- }
- fallthrough
- case 3: // 增加到相册
- err = driver.AddAlbumFile(parentFile.Id, account, joinID(precreateResp.Data.FsID))
- if err != nil {
- return err
- }
- }
- return nil
-}
-
-var _ base.Driver = (*Baidu)(nil)
diff --git a/drivers/baiduphoto/types.go b/drivers/baiduphoto/types.go
deleted file mode 100644
index 926329d6..00000000
--- a/drivers/baiduphoto/types.go
+++ /dev/null
@@ -1,126 +0,0 @@
-package baiduphoto
-
-import (
- "fmt"
-
- "github.com/Xhofe/alist/utils"
-)
-
-type TokenErrResp struct {
- ErrorDescription string `json:"error_description"`
- ErrorMsg string `json:"error"`
-}
-
-func (e *TokenErrResp) Error() string {
- return fmt.Sprint(e.ErrorMsg, " : ", e.ErrorDescription)
-}
-
-type Erron struct {
- Errno int `json:"errno"`
- RequestID int `json:"request_id"`
-}
-
-type Page struct {
- HasMore int `json:"has_more"`
- Cursor string `json:"cursor"`
-}
-
-func (p Page) HasNextPage() bool {
- return p.HasMore == 1
-}
-
-type (
- FileListResp struct {
- Page
- List []File `json:"list"`
- }
-
- File struct {
- Fsid int64 `json:"fsid"` // 文件ID
- Path string `json:"path"` // 文件路径
- Size int64 `json:"size"`
- Ctime int64 `json:"ctime"` // 创建时间 s
- Mtime int64 `json:"mtime"` // 修改时间 s
- Thumburl []string `json:"thumburl"`
- }
-)
-
-func (f File) Name() string {
- return utils.Base(f.Path)
-}
-
-/*相册部分*/
-type (
- AlbumListResp struct {
- Page
- List []Album `json:"list"`
- Reset int64 `json:"reset"`
- TotalCount int64 `json:"total_count"`
- }
-
- Album struct {
- AlbumID string `json:"album_id"`
- Tid int64 `json:"tid"`
- Title string `json:"title"`
- JoinTime int64 `json:"join_time"`
- CreateTime int64 `json:"create_time"`
- Mtime int64 `json:"mtime"`
- }
-
- AlbumFileListResp struct {
- Page
- List []AlbumFile `json:"list"`
- Reset int64 `json:"reset"`
- TotalCount int64 `json:"total_count"`
- }
-
- AlbumFile struct {
- File
- Tid int64 `json:"tid"`
- Uk int64 `json:"uk"`
- }
-)
-
-type (
- CopyFileResp struct {
- List []CopyFile `json:"list"`
- }
- CopyFile struct {
- FromFsid int64 `json:"from_fsid"` // 源ID
- Fsid int64 `json:"fsid"` // 目标ID
- Path string `json:"path"`
- ShootTime int `json:"shoot_time"`
- }
-)
-
-/*上传部分*/
-type (
- UploadFile struct {
- FsID int64 `json:"fs_id"`
- Size int64 `json:"size"`
- Md5 string `json:"md5"`
- ServerFilename string `json:"server_filename"`
- Path string `json:"path"`
- Ctime int `json:"ctime"`
- Mtime int `json:"mtime"`
- Isdir int `json:"isdir"`
- Category int `json:"category"`
- ServerMd5 string `json:"server_md5"`
- ShootTime int `json:"shoot_time"`
- }
-
- CreateFileResp struct {
- Data UploadFile `json:"data"`
- }
-
- PrecreateResp struct {
- ReturnType int `json:"return_type"` //存在返回2 不存在返回1 已经保存3
- //存在返回
- CreateFileResp
-
- //不存在返回
- Path string `json:"path"`
- UploadID string `json:"uploadid"`
- Blocklist []int64 `json:"block_list"`
- }
-)
diff --git a/drivers/baiduphoto/util.go b/drivers/baiduphoto/util.go
deleted file mode 100644
index 2c0542c7..00000000
--- a/drivers/baiduphoto/util.go
+++ /dev/null
@@ -1,84 +0,0 @@
-package baiduphoto
-
-import (
- "errors"
- "fmt"
- "math"
- "math/rand"
- "regexp"
- "strings"
- "time"
-
- "github.com/Xhofe/alist/model"
-)
-
-const (
- API_URL = "https://photo.baidu.com/youai"
- ALBUM_API_URL = API_URL + "/album/v1"
- FILE_API_URL_V1 = API_URL + "/file/v1"
- FILE_API_URL_V2 = API_URL + "/file/v2"
-)
-
-var (
- ErrNotSupportName = errors.New("only chinese and english, numbers and underscores are supported, and the length is no more than 20")
-)
-
-//Tid生成
-func getTid() string {
- return fmt.Sprintf("3%d%.0f", time.Now().Unix(), math.Floor(9000000*rand.Float64()+1000000))
-}
-
-// 检查名称
-func checkName(name string) bool {
- return len(name) <= 20 && regexp.MustCompile("[\u4e00-\u9fa5A-Za-z0-9_]").MatchString(name)
-}
-
-func getTime(t int64) *time.Time {
- tm := time.Unix(t, 0)
- return &tm
-}
-
-func fsidsFormat(ids ...string) string {
- var buf []string
- for _, id := range ids {
- e := strings.Split(id, "|")
- buf = append(buf, fmt.Sprintf("{\"fsid\":%s,\"uk\":%s}", e[0], e[1]))
- }
- return fmt.Sprintf("[%s]", strings.Join(buf, ","))
-}
-
-func fsidsFormatNotUk(ids ...string) string {
- var buf []string
- for _, id := range ids {
- buf = append(buf, fmt.Sprintf("{\"fsid\":%s}", strings.Split(id, "|")[0]))
- }
- return fmt.Sprintf("[%s]", strings.Join(buf, ","))
-}
-
-func splitID(id string) []string {
- return strings.SplitN(id, "|", 3)[:3]
-}
-
-func joinID(ids ...interface{}) string {
- idsStr := make([]string, 0, len(ids))
- for _, id := range ids {
- idsStr = append(idsStr, fmt.Sprint(id))
- }
- return strings.Join(idsStr, "|")
-}
-
-func IsAlbum(file *model.File) bool {
- return file.Id != "" && file.IsDir()
-}
-
-func IsAlbumFile(file *model.File) bool {
- return file.Id != "" && !file.IsDir()
-}
-
-func IsRoot(file *model.File) bool {
- return file.Id == "" && file.IsDir()
-}
-
-func MustString(str string, err error) string {
- return str
-}
diff --git a/drivers/base/base.go b/drivers/base/base.go
deleted file mode 100644
index 68027f41..00000000
--- a/drivers/base/base.go
+++ /dev/null
@@ -1,61 +0,0 @@
-package base
-
-import "github.com/Xhofe/alist/model"
-
-type Base struct{}
-
-func (b Base) Config() DriverConfig {
- return DriverConfig{}
-}
-
-func (b Base) Items() []Item {
- return nil
-}
-
-func (b Base) Save(account *model.Account, old *model.Account) error {
- return ErrNotImplement
-}
-
-func (b Base) File(path string, account *model.Account) (*model.File, error) {
- return nil, ErrNotImplement
-}
-
-func (b Base) Files(path string, account *model.Account) ([]model.File, error) {
- return nil, ErrNotImplement
-}
-
-func (b Base) Link(args Args, account *model.Account) (*Link, error) {
- return nil, ErrNotImplement
-}
-
-func (b Base) Path(path string, account *model.Account) (*model.File, []model.File, error) {
- return nil, nil, ErrNotImplement
-}
-
-func (b Base) Preview(path string, account *model.Account) (interface{}, error) {
- return nil, ErrNotImplement
-}
-
-func (b Base) MakeDir(path string, account *model.Account) error {
- return ErrNotImplement
-}
-
-func (b Base) Move(src string, dst string, account *model.Account) error {
- return ErrNotImplement
-}
-
-func (b Base) Rename(src string, dst string, account *model.Account) error {
- return ErrNotImplement
-}
-
-func (b Base) Copy(src string, dst string, account *model.Account) error {
- return ErrNotImplement
-}
-
-func (b Base) Delete(path string, account *model.Account) error {
- return ErrNotImplement
-}
-
-func (b Base) Upload(file *model.FileStream, account *model.Account) error {
- return ErrNotImplement
-}
diff --git a/drivers/base/cache.go b/drivers/base/cache.go
deleted file mode 100644
index b0d34189..00000000
--- a/drivers/base/cache.go
+++ /dev/null
@@ -1,58 +0,0 @@
-package base
-
-import (
- "github.com/Xhofe/alist/conf"
- "github.com/Xhofe/alist/model"
- "github.com/Xhofe/alist/utils"
- log "github.com/sirupsen/logrus"
- "strings"
-)
-
-func KeyCache(path string, account *model.Account) string {
- //path = utils.ParsePath(path)
- key := utils.ParsePath(utils.Join(account.Name, path))
- log.Debugln("cache key: ", key)
- return key
-}
-
-func SaveSearchFiles[T model.ISearchFile](key string, obj []T) {
- if strings.Contains(key, ".balance") {
- return
- }
- err := model.DeleteSearchFilesByPath(key)
- if err != nil {
- log.Errorln("failed create search files", err)
- return
- }
- files := make([]model.SearchFile, len(obj))
- for i := 0; i < len(obj); i++ {
- files[i] = model.SearchFile{
- Path: key,
- Name: obj[i].GetName(),
- Size: obj[i].GetSize(),
- Type: obj[i].GetType(),
- }
- }
- err = model.CreateSearchFiles(files)
- if err != nil {
- log.Errorln("failed create search files", err)
- }
-}
-
-func SetCache[T model.ISearchFile](path string, obj []T, account *model.Account) error {
- key := KeyCache(path, account)
- if conf.GetBool("enable search") {
- go SaveSearchFiles(key, obj)
- }
- return conf.Cache.Set(conf.Ctx, key, obj, nil)
-}
-
-func GetCache(path string, account *model.Account) (interface{}, error) {
- return conf.Cache.Get(conf.Ctx, KeyCache(path, account))
-}
-
-func DeleteCache(path string, account *model.Account) error {
- err := conf.Cache.Delete(conf.Ctx, KeyCache(path, account))
- log.Debugf("delete cache %s: %+v", path, err)
- return err
-}
diff --git a/drivers/base/driver.go b/drivers/base/driver.go
deleted file mode 100644
index a4d6fb05..00000000
--- a/drivers/base/driver.go
+++ /dev/null
@@ -1,181 +0,0 @@
-package base
-
-import (
- "github.com/Xhofe/alist/model"
- "github.com/go-resty/resty/v2"
- log "github.com/sirupsen/logrus"
- "net/http"
- "time"
-)
-
-type DriverConfig struct {
- Name string
- OnlyProxy bool // 必须使用代理(本机或者其他机器)
- OnlyLocal bool // 必须本机返回的
- ApiProxy bool // 使用API中转的
- NoNeedSetLink bool // 不需要设置链接的
- NoCors bool // 不可以跨域
- LocalSort bool // 本地排序
-}
-
-type Args struct {
- Path string
- IP string
- Header http.Header
-}
-
-type Driver interface {
- // Config 配置
- Config() DriverConfig
- // Items 账号所需参数
- Items() []Item
- // Save 保存时处理
- Save(account *model.Account, old *model.Account) error
- // File 取文件
- File(path string, account *model.Account) (*model.File, error)
- // Files 取文件夹
- Files(path string, account *model.Account) ([]model.File, error)
- // Link 取链接
- Link(args Args, account *model.Account) (*Link, error)
- // Path 取路径(文件或文件夹)
- Path(path string, account *model.Account) (*model.File, []model.File, error)
- // Deprecated Proxy 代理处理
- //Proxy(r *http.Request, account *model.Account)
- // Preview 预览
- Preview(path string, account *model.Account) (interface{}, error)
- // MakeDir 创建文件夹
- MakeDir(path string, account *model.Account) error
- // Move 移动/改名
- Move(src string, dst string, account *model.Account) error
- // Rename 改名
- Rename(src string, dst string, account *model.Account) error
- // Copy 拷贝
- Copy(src string, dst string, account *model.Account) error
- // Delete 删除
- Delete(path string, account *model.Account) error
- // Upload 上传
- Upload(file *model.FileStream, account *model.Account) error
- // TODO
- //Search(path string, keyword string, account *model.Account) ([]*model.File, error)
-}
-
-type Item struct {
- Name string `json:"name"`
- Label string `json:"label"`
- Type string `json:"type"`
- Default string `json:"default"`
- Values string `json:"values"`
- Required bool `json:"required"`
- Description string `json:"description"`
-}
-
-var driversMap = map[string]Driver{}
-
-func RegisterDriver(driver Driver) {
- log.Infof("register driver: [%s]", driver.Config().Name)
- driversMap[driver.Config().Name] = driver
-}
-
-func GetDriver(name string) (driver Driver, ok bool) {
- driver, ok = driversMap[name]
- return
-}
-
-func GetDriversMap() map[string]Driver {
- return driversMap
-}
-
-func GetDrivers() map[string][]Item {
- res := make(map[string][]Item)
- for k, v := range driversMap {
- webdavDirect := Item{
- Name: "webdav_direct",
- Label: "webdav direct",
- Type: TypeBool,
- Required: true,
- Description: "Transfer the WebDAV of this account through the native",
- }
- if v.Config().OnlyProxy {
- res[k] = append([]Item{
- webdavDirect,
- }, v.Items()...)
- } else {
- res[k] = append([]Item{
- {
- Name: "proxy",
- Label: "proxy",
- Type: TypeBool,
- Required: true,
- Description: "web proxy",
- },
- {
- Name: "webdav_proxy",
- Label: "webdav proxy",
- Type: TypeBool,
- Required: true,
- Description: "Transfer the WebDAV of this account through the server",
- },
- webdavDirect,
- }, v.Items()...)
- }
- res[k] = append([]Item{
- {
- Name: "down_proxy_url",
- Label: "down_proxy_url",
- Type: TypeText,
- },
- {
- Name: "extract_folder",
- Label: "extract_folder",
- Values: "front,back",
- Type: TypeSelect,
- },
- }, res[k]...)
- if v.Config().ApiProxy {
- res[k] = append([]Item{
- {
- Name: "api_proxy_url",
- Label: "api_proxy_url",
- Type: TypeString,
- },
- }, res[k]...)
- }
- if v.Config().LocalSort {
- res[k] = append(res[k], []Item{
- {
- Name: "order_by",
- Label: "order_by",
- Type: TypeSelect,
- Values: "name,size,updated_at",
- Required: false,
- },
- {
- Name: "order_direction",
- Label: "order_direction",
- Type: TypeSelect,
- Values: "ASC,DESC",
- Required: false,
- },
- }...)
- }
- }
- return res
-}
-
-var NoRedirectClient *resty.Client
-var RestyClient = resty.New()
-var HttpClient = &http.Client{}
-var UserAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Safari/537.36"
-var DefaultTimeout = time.Second * 20
-
-func init() {
- NoRedirectClient = resty.New().SetRedirectPolicy(
- resty.RedirectPolicyFunc(func(req *http.Request, via []*http.Request) error {
- return http.ErrUseLastResponse
- }),
- )
- NoRedirectClient.SetHeader("user-agent", UserAgent)
- RestyClient.SetHeader("user-agent", UserAgent)
- RestyClient.SetRetryCount(3)
- RestyClient.SetTimeout(DefaultTimeout)
-}
diff --git a/drivers/base/types.go b/drivers/base/types.go
deleted file mode 100644
index 81539ad1..00000000
--- a/drivers/base/types.go
+++ /dev/null
@@ -1,55 +0,0 @@
-package base
-
-import (
- "errors"
- "io"
- "net/http"
-)
-
-var (
- ErrPathNotFound = errors.New("path not found")
- ErrNotFile = errors.New("not file")
- ErrNotImplement = errors.New("not implement")
- ErrNotSupport = errors.New("not support")
- ErrNotFolder = errors.New("not a folder")
- ErrEmptyFile = errors.New("empty file")
- ErrRelativePath = errors.New("access using relative path is not allowed")
- ErrEmptyToken = errors.New("empty token")
-)
-
-const (
- TypeString = "string"
- TypeSelect = "select"
- TypeBool = "bool"
- TypeNumber = "number"
- TypeText = "text"
-)
-
-const (
- Get = iota
- Post
- Put
- Delete
- Patch
-)
-
-type Json map[string]interface{}
-
-type TokenResp struct {
- AccessToken string `json:"access_token"`
- RefreshToken string `json:"refresh_token"`
-}
-
-type Header struct {
- Name string `json:"name"`
- Value string `json:"value"`
-}
-
-type Link struct {
- Url string `json:"url"`
- Headers []Header `json:"headers"`
- Data io.ReadCloser
- FilePath string `json:"path"` // for native
- Status int
- Header http.Header
-}
diff --git a/drivers/ftp/driver.go b/drivers/ftp/driver.go
deleted file mode 100644
index 53f1a4e7..00000000
--- a/drivers/ftp/driver.go
+++ /dev/null
@@ -1,262 +0,0 @@
-package ftp
-
-import (
- "github.com/Xhofe/alist/conf"
- "github.com/Xhofe/alist/drivers/base"
- "github.com/Xhofe/alist/model"
- "github.com/Xhofe/alist/utils"
- "github.com/jlaffaye/ftp"
- log "github.com/sirupsen/logrus"
- "path/filepath"
-)
-
-type FTP struct{}
-
-func (driver FTP) Config() base.DriverConfig {
- return base.DriverConfig{
- Name: "FTP",
- OnlyProxy: true,
- OnlyLocal: true,
- NoNeedSetLink: true,
- LocalSort: true,
- }
-}
-
-func (driver FTP) Items() []base.Item {
- return []base.Item{
- {
- Name: "site_url",
- Label: "ftp host url",
- Type: base.TypeString,
- Required: true,
- },
- {
- Name: "username",
- Label: "username",
- Type: base.TypeString,
- Required: true,
- },
- {
- Name: "password",
- Label: "password",
- Type: base.TypeString,
- Required: true,
- },
- {
- Name: "root_folder",
- Label: "root folder path",
- Type: base.TypeString,
- Required: false,
- },
- }
-}
-
-func (driver FTP) Save(account *model.Account, old *model.Account) error {
- if old != nil {
- conn, ok := connMap[old.Name]
- if ok {
- err := conn.Quit()
- log.Error("ftp:", err)
- delete(connMap, old.Name)
- }
- }
- if account == nil {
- return nil
- }
- if account.RootFolder == "" {
- account.RootFolder = "/"
- }
- _, err := driver.Login(account)
- if err != nil {
- account.Status = err.Error()
- } else {
- account.Status = "work"
- }
- _ = model.SaveAccount(account)
- return err
-}
-
-func (driver FTP) File(path string, account *model.Account) (*model.File, error) {
- log.Debugf("file: %s", path)
- path = utils.ParsePath(path)
- if path == "/" {
- return &model.File{
- Id: account.RootFolder,
- Name: account.Name,
- Size: 0,
- Type: conf.FOLDER,
- Driver: driver.Config().Name,
- UpdatedAt: account.UpdatedAt,
- }, nil
- }
- dir, name := filepath.Split(path)
- files, err := driver.Files(dir, account)
- if err != nil {
- return nil, err
- }
- for _, file := range files {
- if file.Name == name {
- return &file, nil
- }
- }
- return nil, base.ErrPathNotFound
-}
-
-func (driver FTP) Files(path string, account *model.Account) ([]model.File, error) {
- log.Debugf("files: %s", path)
- path = utils.ParsePath(path)
- cache, err := base.GetCache(path, account)
- if err == nil {
- files, _ := cache.([]model.File)
- return files, nil
- }
- realPath := utils.Join(account.RootFolder, path)
- conn, err := driver.Login(account)
- if err != nil {
- return nil, err
- }
- //defer func() { _ = conn.Quit() }()
- entries, err := conn.List(realPath)
- if err != nil {
- return nil, err
- }
- res := make([]model.File, 0)
- for i, _ := range entries {
- entry := entries[i]
- if entry.Name == "." || entry.Name == ".." {
- continue
- }
- f := model.File{
- Name: entry.Name,
- Size: int64(entry.Size),
- UpdatedAt: &entry.Time,
- Driver: driver.Config().Name,
- }
- if entry.Type == ftp.EntryTypeFolder {
- f.Type = conf.FOLDER
- } else {
- f.Type = utils.GetFileType(filepath.Ext(entry.Name))
- }
- res = append(res, f)
- }
- if len(res) > 0 {
- _ = base.SetCache(path, res, account)
- }
- return res, nil
-}
-
-func (driver FTP) Link(args base.Args, account *model.Account) (*base.Link, error) {
- path := args.Path
- path = utils.ParsePath(path)
- realPath := utils.Join(account.RootFolder, path)
- conn, err := driver.Login(account)
- if err != nil {
- return nil, err
- }
- //defer func() { _ = conn.Quit() }()
- resp, err := conn.Retr(realPath)
- if err != nil {
- return nil, err
- }
- //defer func() { _ = resp.Close() }()
- //data, err := ioutil.ReadAll(resp)
- //if err != nil {
- // return nil, err
- //}
- return &base.Link{
- Data: resp,
- }, nil
-}
-
-func (driver FTP) Path(path string, account *model.Account) (*model.File, []model.File, error) {
- log.Debugf("ftp path: %s", path)
- file, err := driver.File(path, account)
- if err != nil {
- return nil, nil, err
- }
- if !file.IsDir() {
- //file.Url, _ = driver.Link(path, account)
- return file, nil, nil
- }
- files, err := driver.Files(path, account)
- if err != nil {
- return nil, nil, err
- }
- return nil, files, nil
-}
-
-//func (driver FTP) Proxy(r *http.Request, account *model.Account) {
-//
-//}
-
-func (driver FTP) Preview(path string, account *model.Account) (interface{}, error) {
- return nil, base.ErrNotSupport
-}
-
-func (driver FTP) MakeDir(path string, account *model.Account) error {
- path = utils.ParsePath(path)
- realPath := utils.Join(account.RootFolder, path)
- conn, err := driver.Login(account)
- if err != nil {
- return err
- }
- //defer func() { _ = conn.Quit() }()
- err = conn.MakeDir(realPath)
- return err
-}
-
-func (driver FTP) Move(src string, dst string, account *model.Account) error {
- realSrc := utils.Join(account.RootFolder, src)
- realDst := utils.Join(account.RootFolder, dst)
- conn, err := driver.Login(account)
- if err != nil {
- return err
- }
- //defer func() { _ = conn.Quit() }()
- err = conn.Rename(realSrc, realDst)
- return err
-}
-
-func (driver FTP) Rename(src string, dst string, account *model.Account) error {
- return driver.Move(src, dst, account)
-}
-
-func (driver FTP) Copy(src string, dst string, account *model.Account) error {
- return base.ErrNotSupport
-}
-
-func (driver FTP) Delete(path string, account *model.Account) error {
- path = utils.ParsePath(path)
- file, err := driver.File(path, account)
- if err != nil {
- return err
- }
- realPath := utils.Join(account.RootFolder, path)
- conn, err := driver.Login(account)
- if err != nil {
- return err
- }
- //defer func() { _ = conn.Quit() }()
- if file.IsDir() {
- err = conn.RemoveDirRecur(realPath)
- } else {
- err = conn.Delete(realPath)
- }
- return err
-}
-
-func (driver FTP) Upload(file *model.FileStream, account *model.Account) error {
- if file == nil {
- return base.ErrEmptyFile
- }
- realPath := utils.Join(account.RootFolder, file.ParentPath, file.Name)
- conn, err := driver.Login(account)
- if err != nil {
- return err
- }
- //defer func() { _ = conn.Quit() }()
- err = conn.Stor(realPath, file)
- return err
-}
-
-var _ base.Driver = (*FTP)(nil)
diff --git a/drivers/ftp/ftp.go b/drivers/ftp/ftp.go
deleted file mode 100644
index e3f7353b..00000000
--- a/drivers/ftp/ftp.go
+++ /dev/null
@@ -1,36 +0,0 @@
-package ftp
-
-import (
- "github.com/Xhofe/alist/drivers/base"
- "github.com/Xhofe/alist/model"
- "github.com/jlaffaye/ftp"
-)
-
-var connMap map[string]*ftp.ServerConn
-
-func (driver FTP) Login(account *model.Account) (*ftp.ServerConn, error) {
- conn, ok := connMap[account.Name]
- if ok {
- _, err := conn.CurrentDir()
- if err == nil {
- return conn, nil
- } else {
- delete(connMap, account.Name)
- }
- }
- conn, err := ftp.Connect(account.SiteUrl)
- if err != nil {
- return nil, err
- }
- err = conn.Login(account.Username, account.Password)
- if err != nil {
- return nil, err
- }
- connMap[account.Name] = conn
- return conn, nil
-}
-
-func init() {
- base.RegisterDriver(&FTP{})
- connMap = make(map[string]*ftp.ServerConn)
-}
diff --git a/drivers/google/driver.go b/drivers/google/driver.go
deleted file mode 100644
index bb99fc76..00000000
--- a/drivers/google/driver.go
+++ /dev/null
@@ -1,289 +0,0 @@
-package google
-
-import (
- "fmt"
- "github.com/Xhofe/alist/conf"
- "github.com/Xhofe/alist/drivers/base"
- "github.com/Xhofe/alist/model"
- "github.com/Xhofe/alist/utils"
- log "github.com/sirupsen/logrus"
- "io/ioutil"
- "path/filepath"
-)
-
-type GoogleDrive struct{}
-
-func (driver GoogleDrive) Config() base.DriverConfig {
- return base.DriverConfig{
- Name: "GoogleDrive",
- OnlyProxy: true,
- ApiProxy: true,
- NoNeedSetLink: true,
- }
-}
-
-func (driver GoogleDrive) Items() []base.Item {
- return []base.Item{
- {
- Name: "client_id",
- Label: "client id",
- Type: base.TypeString,
- Required: true,
- Default: "202264815644.apps.googleusercontent.com",
- },
- {
- Name: "client_secret",
- Label: "client secret",
- Type: base.TypeString,
- Required: true,
- Default: "X4Z3ca8xfWDb1Voo-F9a7ZxJ",
- },
- {
- Name: "refresh_token",
- Label: "refresh token",
- Type: base.TypeString,
- Required: true,
- },
- {
- Name: "root_folder",
- Label: "root folder file_id",
- Type: base.TypeString,
- Required: false,
- },
- {
- Name: "order_by",
- Label: "order_by",
- Type: base.TypeString,
- Required: false,
- Description: "such as: folder,name,modifiedTime",
- },
- {
- Name: "order_direction",
- Label: "order_direction",
- Type: base.TypeSelect,
- Values: "asc,desc",
- Required: false,
- },
- }
-}
-
-func (driver GoogleDrive) Save(account *model.Account, old *model.Account) error {
- if account == nil {
- return nil
- }
- account.Proxy = true
- err := driver.RefreshToken(account)
- if err != nil {
- account.Status = err.Error()
- _ = model.SaveAccount(account)
- return err
- }
- if account.RootFolder == "" {
- account.RootFolder = "root"
- }
- account.Status = "work"
- _ = model.SaveAccount(account)
- return nil
-}
-
-func (driver GoogleDrive) File(path string, account *model.Account) (*model.File, error) {
- path = utils.ParsePath(path)
- if path == "/" {
- return &model.File{
- Id: account.RootFolder,
- Name: account.Name,
- Size: 0,
- Type: conf.FOLDER,
- Driver: driver.Config().Name,
- UpdatedAt: account.UpdatedAt,
- }, nil
- }
- dir, name := filepath.Split(path)
- files, err := driver.Files(dir, account)
- if err != nil {
- return nil, err
- }
- for _, file := range files {
- if file.Name == name {
- return &file, nil
- }
- }
- return nil, base.ErrPathNotFound
-}
-
-func (driver GoogleDrive) Files(path string, account *model.Account) ([]model.File, error) {
- path = utils.ParsePath(path)
- var rawFiles []File
- cache, err := base.GetCache(path, account)
- if err == nil {
- rawFiles, _ = cache.([]File)
- } else {
- file, err := driver.File(path, account)
- if err != nil {
- return nil, err
- }
- rawFiles, err = driver.GetFiles(file.Id, account)
- if err != nil {
- return nil, err
- }
- if len(rawFiles) > 0 {
- _ = base.SetCache(path, rawFiles, account)
- }
- }
- files := make([]model.File, 0)
- for _, file := range rawFiles {
- files = append(files, *driver.FormatFile(&file, account))
- }
- return files, nil
-}
-
-func (driver GoogleDrive) Link(args base.Args, account *model.Account) (*base.Link, error) {
- file, err := driver.File(args.Path, account)
- if err != nil {
- return nil, err
- }
- if file.Type == conf.FOLDER {
- return nil, base.ErrNotFile
- }
- url := fmt.Sprintf("https://www.googleapis.com/drive/v3/files/%s?includeItemsFromAllDrives=true&supportsAllDrives=true", file.Id)
- _, err = driver.Request(url, base.Get, nil, nil, nil, nil, nil, account)
- if err != nil {
- return nil, err
- }
- link := base.Link{
- Url: url + "&alt=media",
- Headers: []base.Header{
- {
- Name: "Authorization",
- Value: "Bearer " + account.AccessToken,
- },
- },
- }
- return &link, nil
-}
-
-func (driver GoogleDrive) Path(path string, account *model.Account) (*model.File, []model.File, error) {
- path = utils.ParsePath(path)
- log.Debugf("google path: %s", path)
- file, err := driver.File(path, account)
- if err != nil {
- return nil, nil, err
- }
- if !file.IsDir() {
- return file, nil, nil
- }
- files, err := driver.Files(path, account)
- if err != nil {
- return nil, nil, err
- }
- return nil, files, nil
-}
-
-//func (driver GoogleDrive) Proxy(r *http.Request, account *model.Account) {
-// r.Header.Add("Authorization", "Bearer "+account.AccessToken)
-//}
-
-func (driver GoogleDrive) Preview(path string, account *model.Account) (interface{}, error) {
- return nil, base.ErrNotSupport
-}
-
-func (driver GoogleDrive) MakeDir(path string, account *model.Account) error {
- parentFile, err := driver.File(utils.Dir(path), account)
- if err != nil {
- return err
- }
- data := base.Json{
- "name": utils.Base(path),
- "parents": []string{parentFile.Id},
- "mimeType": "application/vnd.google-apps.folder",
- }
- _, err = driver.Request("https://www.googleapis.com/drive/v3/files", base.Post, nil, nil, nil, &data, nil, account)
- return err
-}
-
-func (driver GoogleDrive) Move(src string, dst string, account *model.Account) error {
- srcFile, err := driver.File(src, account)
- url := "https://www.googleapis.com/drive/v3/files/" + srcFile.Id
- if err != nil {
- return err
- }
- dstParentFile, err := driver.File(utils.Dir(dst), account)
- if err != nil {
- return err
- }
- query := map[string]string{
- "addParents": dstParentFile.Id,
- "removeParents": "root",
- }
- _, err = driver.Request(url, base.Patch, nil, query, nil, nil, nil, account)
- return err
-}
-
-func (driver GoogleDrive) Rename(src string, dst string, account *model.Account) error {
- srcFile, err := driver.File(src, account)
- url := "https://www.googleapis.com/drive/v3/files/" + srcFile.Id
- if err != nil {
- return err
- }
- data := base.Json{
- "name": utils.Base(dst),
- }
- _, err = driver.Request(url, base.Patch, nil, nil, nil, &data, nil, account)
- return err
-}
-
-func (driver GoogleDrive) Copy(src string, dst string, account *model.Account) error {
- return base.ErrNotSupport
-}
-
-func (driver GoogleDrive) Delete(path string, account *model.Account) error {
- file, err := driver.File(path, account)
- url := "https://www.googleapis.com/drive/v3/files/" + file.Id
- if err != nil {
- return err
- }
- _, err = driver.Request(url, base.Delete, nil, nil, nil, nil, nil, account)
- return err
-}
-
-func (driver GoogleDrive) Upload(file *model.FileStream, account *model.Account) error {
- if file == nil {
- return base.ErrEmptyFile
- }
- parentFile, err := driver.File(file.ParentPath, account)
- if err != nil {
- return err
- }
- data := base.Json{
- "name": file.Name,
- "parents": []string{parentFile.Id},
- }
- var e Error
- url := "https://www.googleapis.com/upload/drive/v3/files?uploadType=resumable&supportsAllDrives=true"
- if account.APIProxyUrl != "" {
- url = fmt.Sprintf("%s/%s", account.APIProxyUrl, url)
- }
- res, err := base.NoRedirectClient.R().SetHeader("Authorization", "Bearer "+account.AccessToken).
- SetError(&e).SetBody(data).
- Post(url)
- if err != nil {
- return err
- }
- if e.Error.Code != 0 {
- if e.Error.Code == 401 {
- err = driver.RefreshToken(account)
- if err != nil {
- _ = model.SaveAccount(account)
- return err
- }
- return driver.Upload(file, account)
- }
- return fmt.Errorf("%s: %v", e.Error.Message, e.Error.Errors)
- }
- putUrl := res.Header().Get("location")
- byteData, _ := ioutil.ReadAll(file)
- _, err = driver.Request(putUrl, base.Put, nil, nil, nil, byteData, nil, account)
- return err
-}
-
-var _ base.Driver = (*GoogleDrive)(nil)
diff --git a/drivers/google/googledrive.go b/drivers/google/googledrive.go
deleted file mode 100644
index c3c47b49..00000000
--- a/drivers/google/googledrive.go
+++ /dev/null
@@ -1,175 +0,0 @@
-package google
-
-import (
- "fmt"
- "github.com/Xhofe/alist/drivers/base"
- "github.com/Xhofe/alist/model"
- "github.com/go-resty/resty/v2"
- log "github.com/sirupsen/logrus"
-)
-
-type TokenError struct {
- Error string `json:"error"`
- ErrorDescription string `json:"error_description"`
-}
-
-func (driver GoogleDrive) RefreshToken(account *model.Account) error {
- url := "https://www.googleapis.com/oauth2/v4/token"
- if account.APIProxyUrl != "" {
- url = fmt.Sprintf("%s/%s", account.APIProxyUrl, url)
- }
- var resp base.TokenResp
- var e TokenError
- res, err := base.RestyClient.R().SetResult(&resp).SetError(&e).
- SetFormData(map[string]string{
- "client_id": account.ClientId,
- "client_secret": account.ClientSecret,
- "refresh_token": account.RefreshToken,
- "grant_type": "refresh_token",
- }).Post(url)
- if err != nil {
- return err
- }
- log.Debug(res.String())
- if e.Error != "" {
- return fmt.Errorf(e.Error)
- }
- account.AccessToken = resp.AccessToken
- account.Status = "work"
- return nil
-}
-
-func (driver GoogleDrive) FormatFile(file *File, account *model.Account) *model.File {
- f := &model.File{
- Id: file.Id,
- Name: file.Name,
- Driver: driver.Config().Name,
- UpdatedAt: file.ModifiedTime,
- Url: "",
- }
- f.Size = int64(file.GetSize())
- f.Type = file.GetType()
- if file.ThumbnailLink != "" {
- if account.APIProxyUrl != "" {
- f.Thumbnail = fmt.Sprintf("%s/%s", account.APIProxyUrl, file.ThumbnailLink)
- } else {
- f.Thumbnail = file.ThumbnailLink
- }
- }
- return f
-}
-
-type Files struct {
- NextPageToken string `json:"nextPageToken"`
- Files []File `json:"files"`
-}
-
-type Error struct {
- Error struct {
- Errors []struct {
- Domain string `json:"domain"`
- Reason string `json:"reason"`
- Message string `json:"message"`
- LocationType string `json:"location_type"`
- Location string `json:"location"`
- }
- Code int `json:"code"`
- Message string `json:"message"`
- } `json:"error"`
-}
-
-func (driver GoogleDrive) GetFiles(id string, account *model.Account) ([]File, error) {
- pageToken := "first"
- res := make([]File, 0)
- for pageToken != "" {
- if pageToken == "first" {
- pageToken = ""
- }
- var resp Files
- orderBy := "folder,name,modifiedTime desc"
- if account.OrderBy != "" {
- orderBy = account.OrderBy + " " + account.OrderDirection
- }
- query := map[string]string{
- "orderBy": orderBy,
- "fields": "files(id,name,mimeType,size,modifiedTime,thumbnailLink),nextPageToken",
- "pageSize": "1000",
- "q": fmt.Sprintf("'%s' in parents and trashed = false", id),
- //"includeItemsFromAllDrives": "true",
- //"supportsAllDrives": "true",
- "pageToken": pageToken,
- }
- _, err := driver.Request("https://www.googleapis.com/drive/v3/files",
- base.Get, nil, query, nil, nil, &resp, account)
- if err != nil {
- return nil, err
- }
- pageToken = resp.NextPageToken
- res = append(res, resp.Files...)
- }
- return res, nil
-}
-
-func (driver GoogleDrive) Request(url string, method int, headers, query, form map[string]string, data interface{}, resp interface{}, account *model.Account) ([]byte, error) {
- rawUrl := url
- if account.APIProxyUrl != "" {
- url = fmt.Sprintf("%s/%s", account.APIProxyUrl, url)
- }
- req := base.RestyClient.R()
- req.SetHeader("Authorization", "Bearer "+account.AccessToken)
- req.SetQueryParam("includeItemsFromAllDrives", "true")
- req.SetQueryParam("supportsAllDrives", "true")
- if headers != nil {
- req.SetHeaders(headers)
- }
- if query != nil {
- req.SetQueryParams(query)
- }
- if form != nil {
- req.SetFormData(form)
- }
- if data != nil {
- req.SetBody(data)
- }
- if resp != nil {
- req.SetResult(resp)
- }
- var res *resty.Response
- var err error
- var e Error
- req.SetError(&e)
- switch method {
- case base.Get:
- res, err = req.Get(url)
- case base.Post:
- res, err = req.Post(url)
- case base.Delete:
- res, err = req.Delete(url)
- case base.Patch:
- res, err = req.Patch(url)
- case base.Put:
- res, err = req.Put(url)
- default:
- return nil, base.ErrNotSupport
- }
- if err != nil {
- return nil, err
- }
- log.Debug(res.String())
- if e.Error.Code != 0 {
- if e.Error.Code == 401 {
- err = driver.RefreshToken(account)
- if err != nil {
- _ = model.SaveAccount(account)
- return nil, err
- }
- return driver.Request(rawUrl, method, headers, query, form, data, resp, account)
- }
- return nil, fmt.Errorf("%s: %v", e.Error.Message, e.Error.Errors)
- }
- return res.Body(), nil
-}
-
-func init() {
- base.RegisterDriver(&GoogleDrive{})
-}
diff --git a/drivers/google/types.go b/drivers/google/types.go
deleted file mode 100644
index 67752a2b..00000000
--- a/drivers/google/types.go
+++ /dev/null
@@ -1,38 +0,0 @@
-package google
-
-import (
- "github.com/Xhofe/alist/conf"
- "github.com/Xhofe/alist/utils"
- "path"
- "strconv"
- "time"
-)
-
-type File struct {
- Id string `json:"id"`
- Name string `json:"name"`
- MimeType string `json:"mimeType"`
- ModifiedTime *time.Time `json:"modifiedTime"`
- Size string `json:"size"`
- ThumbnailLink string `json:"thumbnailLink"`
-}
-
-func (f File) GetSize() uint64 {
- if f.GetType() == conf.FOLDER {
- return 0
- }
- size, _ := strconv.ParseUint(f.Size, 10, 64)
- return size
-}
-
-func (f File) GetName() string {
- return f.Name
-}
-
-func (f File) GetType() int {
- mimeType := f.MimeType
- if mimeType == "application/vnd.google-apps.folder" || mimeType == "application/vnd.google-apps.shortcut" {
- return conf.FOLDER
- }
- return utils.GetFileType(path.Ext(f.Name))
-}
diff --git a/drivers/lanzou/driver.go b/drivers/lanzou/driver.go
deleted file mode 100644
index acba5c70..00000000
--- a/drivers/lanzou/driver.go
+++ /dev/null
@@ -1,202 +0,0 @@
-package lanzou
-
-import (
- "github.com/Xhofe/alist/conf"
- "github.com/Xhofe/alist/drivers/base"
- "github.com/Xhofe/alist/model"
- "github.com/Xhofe/alist/utils"
- log "github.com/sirupsen/logrus"
- "path/filepath"
-)
-
-type Lanzou struct{}
-
-func (driver Lanzou) Config() base.DriverConfig {
- return base.DriverConfig{
- Name: "Lanzou",
- NoCors: true,
- }
-}
-
-func (driver Lanzou) Items() []base.Item {
- return []base.Item{
- {
- Name: "internal_type",
- Label: "lanzou type",
- Type: base.TypeSelect,
- Required: true,
- Values: "cookie,url",
- },
- {
- Name: "access_token",
- Label: "cookie",
- Type: base.TypeString,
- Description: "about 15 days valid",
- Required: true,
- },
- {
- Name: "site_url",
- Label: "share url",
- Type: base.TypeString,
- Required: true,
- },
- {
- Name: "root_folder",
- Label: "root folder file_id",
- Type: base.TypeString,
- },
- {
- Name: "password",
- Label: "share password",
- Type: base.TypeString,
- },
- }
-}
-
-func (driver Lanzou) Save(account *model.Account, old *model.Account) error {
- if account == nil {
- return nil
- }
- if account.InternalType == "cookie" {
- if account.RootFolder == "" {
- account.RootFolder = "-1"
- }
- }
- account.Status = "work"
- _ = model.SaveAccount(account)
- return nil
-}
-
-func (driver Lanzou) File(path string, account *model.Account) (*model.File, error) {
- path = utils.ParsePath(path)
- if path == "/" {
- return &model.File{
- Id: account.RootFolder,
- Name: account.Name,
- Size: 0,
- Type: conf.FOLDER,
- Driver: driver.Config().Name,
- UpdatedAt: account.UpdatedAt,
- }, nil
- }
- dir, name := filepath.Split(path)
- files, err := driver.Files(dir, account)
- if err != nil {
- return nil, err
- }
- for _, file := range files {
- if file.Name == name {
- return &file, nil
- }
- }
- return nil, base.ErrPathNotFound
-}
-
-func (driver Lanzou) Files(path string, account *model.Account) ([]model.File, error) {
- path = utils.ParsePath(path)
- var rawFiles []LanZouFile
- cache, err := base.GetCache(path, account)
- if err == nil {
- rawFiles, _ = cache.([]LanZouFile)
- } else {
- file, err := driver.File(path, account)
- if err != nil {
- return nil, err
- }
- rawFiles, err = driver.GetFiles(file.Id, account)
- if err != nil {
- return nil, err
- }
- if len(rawFiles) > 0 {
- _ = base.SetCache(path, rawFiles, account)
- }
- }
- files := make([]model.File, 0)
- for _, file := range rawFiles {
- files = append(files, *driver.FormatFile(&file))
- }
- return files, nil
-}
-
-func (driver Lanzou) Link(args base.Args, account *model.Account) (*base.Link, error) {
- file, err := driver.File(args.Path, account)
- if err != nil {
- return nil, err
- }
- log.Debugf("down file: %+v", file)
- downId := file.Id
- pwd := ""
- if account.InternalType == "cookie" {
- downId, pwd, err = driver.GetDownPageId(file.Id, account)
- if err != nil {
- return nil, err
- }
- }
- var url string
- //if pwd != "" {
- //url, err = driver.GetLinkWithPassword(downId, pwd, account)
- //} else {
- url, err = driver.GetLink(downId, pwd, account)
- //}
- if err != nil {
- return nil, err
- }
- link := base.Link{
- Url: url,
- Headers: []base.Header{
- {Name: "User-Agent", Value: base.UserAgent},
- },
- }
- return &link, nil
-}
-
-func (driver Lanzou) Path(path string, account *model.Account) (*model.File, []model.File, error) {
- path = utils.ParsePath(path)
- log.Debugf("lanzou path: %s", path)
- file, err := driver.File(path, account)
- if err != nil {
- return nil, nil, err
- }
- if !file.IsDir() {
- return file, nil, nil
- }
- files, err := driver.Files(path, account)
- if err != nil {
- return nil, nil, err
- }
- return nil, files, nil
-}
-
-//func (driver Lanzou) Proxy(r *http.Request, account *model.Account) {
-// r.Header.Del("Origin")
-//}
-
-func (driver Lanzou) Preview(path string, account *model.Account) (interface{}, error) {
- return nil, base.ErrNotSupport
-}
-
-func (driver *Lanzou) MakeDir(path string, account *model.Account) error {
- return base.ErrNotImplement
-}
-
-func (driver *Lanzou) Move(src string, dst string, account *model.Account) error {
- return base.ErrNotImplement
-}
-
-func (driver *Lanzou) Rename(src string, dst string, account *model.Account) error {
- return base.ErrNotImplement
-}
-
-func (driver *Lanzou) Copy(src string, dst string, account *model.Account) error {
- return base.ErrNotImplement
-}
-
-func (driver *Lanzou) Delete(path string, account *model.Account) error {
- return base.ErrNotImplement
-}
-
-func (driver *Lanzou) Upload(file *model.FileStream, account *model.Account) error {
- return base.ErrNotImplement
-}
-
-var _ base.Driver = (*Lanzou)(nil)
diff --git a/drivers/lanzou/lanzou.go b/drivers/lanzou/lanzou.go
deleted file mode 100644
index 9e43b676..00000000
--- a/drivers/lanzou/lanzou.go
+++ /dev/null
@@ -1,271 +0,0 @@
-package lanzou
-
-import (
- "fmt"
- "github.com/Xhofe/alist/drivers/base"
- "github.com/Xhofe/alist/model"
- log "github.com/sirupsen/logrus"
- "net/url"
- "regexp"
- "strconv"
- "time"
-)
-
-func (driver *Lanzou) FormatFile(file *LanZouFile) *model.File {
- now := time.Now()
- f := &model.File{
- Id: file.Id,
- Name: file.Name,
- Driver: driver.Config().Name,
- SizeStr: file.Size,
- TimeStr: file.Time,
- UpdatedAt: &now,
- }
- if file.Folder {
- f.Id = file.FolId
- } else {
- f.Name = file.NameAll
- }
- f.Type = file.GetType()
- return f
-}
-
-type LanZouFilesResp struct {
- Zt int `json:"zt"`
- Info interface{} `json:"info"`
- Text []LanZouFile `json:"text"`
-}
-
-func (driver *Lanzou) GetFiles(folderId string, account *model.Account) ([]LanZouFile, error) {
- if account.InternalType == "cookie" {
- files := make([]LanZouFile, 0)
- var resp LanZouFilesResp
- // folders
- res, err := base.RestyClient.R().SetResult(&resp).SetHeader("Cookie", account.AccessToken).
- SetFormData(map[string]string{
- "task": "47",
- "folder_id": folderId,
- }).Post("https://pc.woozooo.com/doupload.php")
- if err != nil {
- return nil, err
- }
- log.Debug(res.String())
- if resp.Zt != 1 && resp.Zt != 2 {
- return nil, fmt.Errorf("%v", resp.Info)
- }
- for _, file := range resp.Text {
- file.Folder = true
- files = append(files, file)
- }
- // files
- pg := 1
- for {
- _, err = base.RestyClient.R().SetResult(&resp).SetHeader("Cookie", account.AccessToken).
- SetFormData(map[string]string{
- "task": "5",
- "folder_id": folderId,
- "pg": strconv.Itoa(pg),
- }).Post("https://pc.woozooo.com/doupload.php")
- if err != nil {
- return nil, err
- }
- if resp.Zt != 1 {
- return nil, fmt.Errorf("%v", resp.Info)
- }
- if len(resp.Text) == 0 {
- break
- }
- files = append(files, resp.Text...)
- pg++
- }
- return files, nil
- } else {
- return driver.GetFilesByUrl(account)
- }
-}
-
-func (driver *Lanzou) GetFilesByUrl(account *model.Account) ([]LanZouFile, error) {
- files := make([]LanZouFile, 0)
- shareUrl := account.SiteUrl
- u, err := url.Parse(shareUrl)
- if err != nil {
- return nil, err
- }
- res, err := base.RestyClient.R().Get(shareUrl)
- if err != nil {
- return nil, err
- }
- lxArr := regexp.MustCompile(`'lx':(.+?),`).FindStringSubmatch(res.String())
- if len(lxArr) == 0 {
- return nil, fmt.Errorf("get empty page")
- }
- lx := lxArr[1]
- fid := regexp.MustCompile(`'fid':(.+?),`).FindStringSubmatch(res.String())[1]
- uid := regexp.MustCompile(`'uid':'(.+?)',`).FindStringSubmatch(res.String())[1]
- rep := regexp.MustCompile(`'rep':'(.+?)',`).FindStringSubmatch(res.String())[1]
- up := regexp.MustCompile(`'up':(.+?),`).FindStringSubmatch(res.String())[1]
- ls := ""
- if account.Password != "" {
- ls = regexp.MustCompile(`'ls':(.+?),`).FindStringSubmatch(res.String())[1]
- }
- tName := regexp.MustCompile(`'t':(.+?),`).FindStringSubmatch(res.String())[1]
- kName := regexp.MustCompile(`'k':(.+?),`).FindStringSubmatch(res.String())[1]
- t := regexp.MustCompile(`var ` + tName + ` = '(.+?)';`).FindStringSubmatch(res.String())[1]
- k := regexp.MustCompile(`var ` + kName + ` = '(.+?)';`).FindStringSubmatch(res.String())[1]
- pg := 1
- for {
- var resp LanZouFilesResp
- res, err = base.RestyClient.R().SetResult(&resp).SetFormData(map[string]string{
- "lx": lx,
- "fid": fid,
- "uid": uid,
- "pg": strconv.Itoa(pg),
- "rep": rep,
- "t": t,
- "k": k,
- "up": up,
- "ls": ls,
- "pwd": account.Password,
- }).Post(fmt.Sprintf("https://%s/filemoreajax.php", u.Host))
- if err != nil {
- log.Debug(err)
- break
- }
- log.Debug(res.String())
- if resp.Zt != 1 {
- return nil, fmt.Errorf("%v", resp.Info)
- }
- if len(resp.Text) == 0 {
- break
- }
- pg++
- time.Sleep(time.Second)
- files = append(files, resp.Text...)
- }
- return files, nil
-}
-
-//type LanzouDownInfo struct {
-// FId string `json:"f_id"`
-// IsNewd string `json:"is_newd"`
-//}
-
-// GetDownPageId 获取下载页面的ID
-func (driver *Lanzou) GetDownPageId(fileId string, account *model.Account) (string, string, error) {
- var resp DownPageResp
- res, err := base.RestyClient.R().SetResult(&resp).SetHeader("Cookie", account.AccessToken).
- SetFormData(map[string]string{
- "task": "22",
- "file_id": fileId,
- }).Post("https://pc.woozooo.com/doupload.php")
- if err != nil {
- return "", "", err
- }
- log.Debug(res.String())
- if resp.Zt != 1 {
- return "", "", fmt.Errorf("%v", resp.Info)
- }
- return resp.Info.FId, resp.Info.Pwd, nil
-}
-
-type LanzouLinkResp struct {
- Dom string `json:"dom"`
- Url string `json:"url"`
- Zt int `json:"zt"`
-}
-
-func (driver *Lanzou) GetLink(downId string, pwd string, account *model.Account) (string, error) {
- shareUrl := account.SiteUrl
- u, err := url.Parse(shareUrl)
- if err != nil {
- return "", err
- }
- log.Debugln(fmt.Sprintf("https://%s/%s", u.Host, downId))
- res, err := base.RestyClient.R().Get(fmt.Sprintf("https://%s/%s", u.Host, downId))
- if err != nil {
- return "", err
- }
- iframe := regexp.MustCompile(`