Compare commits

..

76 Commits

Author SHA1 Message Date
微凉 f31fc9155a 🔖 release v1.0.5 2021-06-30 21:25:27 +08:00
微凉 d3db012dd0 🚡 move response struct 2021-06-30 21:13:29 +08:00
微凉 74b86ef5e5 🔧 修改每次请求文件数量 2021-06-30 19:32:38 +08:00
微凉 6be90429ad :anguished: remove sponsor 2021-06-30 11:28:22 +08:00
微凉 a6bbff2199 🎇 创建默认配置文件 2021-05-26 19:14:58 +08:00
微凉 3827d3ed67 Merge pull request #111 from daofeng2015/main
fix:api格式修改,新增加生成默认配置文件
2021-05-26 10:54:38 +08:00
daofeng e242867f41 fix:api格式修改,新增加生成默认配置文件 2021-05-26 00:50:37 +08:00
微凉 e09a75a87c ✨ close #109 文件夹软链接 2021-05-17 16:36:55 +08:00
微凉 e0a80b1477 Update README.md 2021-05-15 22:34:35 +08:00
微凉 d693e27ec0 🔖 release 1.0.4 2021-05-01 20:42:00 +08:00
微凉 b20f0717fe :bug: fix: #101 分次请求文件 2021-04-30 19:01:40 +08:00
微凉 427244d8d5 🎇 指定路径与深度rebuild 2021-04-14 13:34:14 +08:00
zsbai b613598c2b 在线预览视频时间延长到4小时 (#96)
* Update request.go

* Update req_bean.go
2021-04-13 23:37:20 +08:00
微凉 f0013320a6 🔖 release v1.0.3 2021-04-09 10:45:16 +08:00
微凉 974caf74d9 :fire: 只初始化一次client 2021-04-09 10:38:57 +08:00
Hello_海生 0bb02664c7 :bug: fix: #85 修复 x509: certificate signed by unknown authority (#86)
* 修复 x509: certificate signed by unknown authority

* 添加忽略证书验证
2021-04-09 10:30:03 +08:00
微凉 6c5a0cba6e :bug: 修复refresh_token失效时无限刷新的bug 2021-03-31 11:05:39 +08:00
微凉 7e21e12e11 👷 release增加Linux386 2021-03-31 09:08:06 +08:00
微凉 11489d8856 Merge pull request #68 from 122cygf/main
修复了因为Referer导致不能下载的问题
2021-03-31 08:04:51 +08:00
lzz 6d824a4ee9 Update auth.go 2021-03-31 00:23:51 +08:00
lzz 8d74d070d4 Update req_bean.go 2021-03-31 00:21:49 +08:00
Xhofe 77aae6660e ✨ 增加视频接口 2021-03-30 10:22:07 +08:00
微凉 76081a81a6 💚 linux_386构建出错 2021-03-21 10:31:53 +08:00
微凉 8760ab283d 💚 linux_386构建出错 2021-03-21 10:23:00 +08:00
微凉 61ab27398c 👷 添加linux386测试 2021-03-21 10:14:59 +08:00
微凉 2e64df7e3d Merge pull request #48 from phoon/main
自定义监听地址配置
2021-03-19 18:45:53 +08:00
Peven 9561f0c951 update conf.yml.example 2021-03-17 18:25:20 +08:00
Peven 03f5a54764 allow to set address in configuration file 2021-03-17 18:08:22 +08:00
微凉 9952c3e90b 💚 版本号 2021-03-17 13:01:02 +08:00
微凉 d94e319df3 🔖 release v1.0.1 2021-03-17 12:56:47 +08:00
微凉 b51b2deea1 💚 错误的文件名 2021-03-17 11:46:53 +08:00
微凉 7dda701f1e 💚 CI重复ID 2021-03-17 11:40:45 +08:00
微凉 3b93445648 👷 release ci surpoort cgo 2021-03-17 11:34:24 +08:00
微凉 a353081126 :bug: 重建时删除不完全 2021-03-16 23:52:41 +08:00
微凉 a5b2f998ab 🎇 支持mysql 2021-03-16 23:15:37 +08:00
微凉 4d0d892ce7 🎇 多盘支持 2021-03-16 21:25:16 +08:00
微凉 8e9ddcf81e :bug: fix: #43 直链密码错误 2021-03-16 16:25:02 +08:00
微凉 5c6344cac0 🎇 直链url密码哈希 2021-03-14 19:13:09 +08:00
微凉 7076efb6be 💚 降低构建系统版本 2021-03-13 23:04:13 +08:00
微凉 6d19b49a8d 🔖 release v1.0.0 2021-03-13 20:25:18 +08:00
微凉 4fa11879f2 :bug: 目录名 2021-03-12 22:03:50 +08:00
微凉 abe9d9237a 🚧 获取链接 2021-03-12 18:12:56 +08:00
微凉 e4d206d59c 🔹 删除list与get接口 2021-03-08 20:28:44 +08:00
微凉 8636014397 🚧 合并get与list 2021-03-08 20:26:02 +08:00
微凉 c0f50ffeff 🚧 参数校验 2021-03-07 21:51:26 +08:00
微凉 b677d6ad21 :heavy_minus_sign: 去除缓存 2021-03-07 21:02:56 +08:00
微凉 443067b80f 🚧 密码逻辑 2021-03-06 23:19:16 +08:00
微凉 3138e031f5 🐝 reformat code 2021-03-05 21:25:44 +08:00
微凉 d137ef8759 🚧 构建目录树 2021-03-05 21:07:45 +08:00
微凉 389226662c 🚧 添加model 2021-03-04 23:50:51 +08:00
微凉 9cb548d4f7 ⭐ 跳过检查更新 2021-02-27 20:06:09 +08:00
微凉 0e7083a713 Merge pull request #27 from 122cygf/main
⭐ 下载链接有效期延长到四小时
2021-02-26 13:14:55 +08:00
122cygf 46f09836f3 下载链接有效期延长到四小时 2021-02-26 12:37:44 +08:00
微凉 e146054679 📝 add notes 2021-02-04 10:02:34 +08:00
微凉 3b2a729dc6 🔧 修改配置文件 2021-01-22 14:27:03 +08:00
微凉 d18a752732 ✨ 添加了office接口 2021-01-19 17:20:14 +08:00
微凉 b9676182c9 🌿 优化了一些代码 2021-01-19 17:19:48 +08:00
微凉 434eb25408 ☁️ origin 2021-01-12 14:58:33 +08:00
微凉 858291876b 🉑 origin优化 2021-01-11 16:53:48 +08:00
微凉 dcebf5257f :bug: 多域名跨域 2021-01-08 16:32:02 +08:00
微凉 0cd4624a36 🆕 新版本 2021-01-05 16:51:31 +08:00
微凉 fcd9c59089 🔧 fix: #8 增加了多个文件预览 2021-01-05 16:40:02 +08:00
微凉 b394711859 ✨ 自定义脚本 2020-12-31 17:08:54 +08:00
微凉 495c3f25e9 🆕 检查更新 2020-12-31 16:15:15 +08:00
微凉 d5e3527bfb 🍃 去除文件缓存 2020-12-31 15:03:25 +08:00
微凉 ba7c33a2bb :bug: 配置名 2020-12-29 13:54:08 +08:00
微凉 bf3f741b22 🐎 加入缓存 2020-12-29 13:37:58 +08:00
微凉 02e665ae37 ✨ 多个自定义内容 2020-12-28 11:22:54 +08:00
微凉 bacbf7bc1b ✨ 文件301直链与password文件隐藏 2020-12-28 10:23:54 +08:00
微凉 4af469efed :bug: 时间超出int范围 2020-12-26 18:11:17 +08:00
微凉 52cddc431a 📝 添加教程 2020-12-25 19:12:27 +08:00
微凉 17f8c4ae1c :bug: 刷新token与跨域问题 2020-12-24 20:25:40 +08:00
微凉 070b6294cb 📝 更新Readme 2020-12-24 19:55:57 +08:00
微凉 c05c6b9a50 👷 自动版本发布 2020-12-24 15:27:37 +08:00
微凉 a7ce9451f3 🚧 添加了静态资源 2020-12-24 15:21:49 +08:00
微凉 430b4cf723 Initial commit 2020-12-24 01:39:45 +08:00
72 changed files with 2152 additions and 3178 deletions
+2
View File
@@ -0,0 +1,2 @@
# Auto detect text files and perform LF normalization
* text=auto
+58 -35
View File
@@ -2,58 +2,81 @@ name: build
on:
push:
branches: [ v2 ]
branches: [ main ]
pull_request:
branches: [ v2 ]
branches: [ main ]
jobs:
build:
strategy:
matrix:
platform: [ubuntu-latest]
go-version: [1.17]
platform: [ubuntu-16.04]
go-version: [1.15]
name: Build
runs-on: ${{ matrix.platform }}
steps:
- name: Setup Go
- name: Set up 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: Setup docker
# uses: docker-practice/actions-setup-docker@master
- name: Checkout
- name: Check out code into the Go module directory
uses: actions/checkout@v2
with:
ref: v2
path: alist
- name: Checkout web repo
uses: actions/checkout@v2
with:
repository: Xhofe/alist-web
ref: v2
path: alist-web
- name: Set up xgo
- name: Get dependencies
run: |
docker pull techknowlogick/xgo:latest
go install src.techknowlogick.com/xgo@latest
sudo apt install upx
- name: Build
sudo apt-get update
sudo apt-get -y install gcc-mingw-w64-x86-64
sudo apt-get -y install gcc-arm-linux-gnueabihf libc6-dev-armhf-cross
sudo apt-get -y install gcc-aarch64-linux-gnu libc6-dev-arm64-cross
go get -v -t -d ./...
if [ -f Gopkg.toml ]; then
curl https://raw.githubusercontent.com/golang/dep/master/install.sh | sh
dep ensure
fi
- name: Build linux
run: |
mv alist/build.sh .
bash build.sh
CC=gcc CGO_ENABLED=1 GOOS=linux GOARCH=amd64 go build -o alist_linux_amd64 alist.go
CC=aarch64-linux-gnu-gcc CGO_ENABLED=1 GOOS=linux GOARCH=arm64 go build -o alist_linux_arm64 alist.go
CC=arm-linux-gnueabihf-gcc CGO_ENABLED=1 GOOS=linux GOARCH=arm go build -o alist_linux_arm alist.go
- name: Upload artifact
- name: Build windows
run: |
CC=x86_64-w64-mingw32-gcc CGO_ENABLED=1 GOOS=windows GOARCH=amd64 go build -o alist_windows_amd64.exe alist.go
- name: Build linux_386
run: |
sudo apt-get -y install libc6-dev-i386
CC=gcc CGO_ENABLED=1 GOOS=linux GOARCH=386 go build -o alist_linux_386 alist.go
- name: Upload artifacts linux_amd64
uses: actions/upload-artifact@v2
with:
name: artifact
path: alist/build
name: alist_linux_amd64
path: alist_linux_amd64
- name: Upload artifacts linux_arm64
uses: actions/upload-artifact@v2
with:
name: alist_linux_arm64
path: alist_linux_arm64
- name: Upload artifacts linux_arm
uses: actions/upload-artifact@v2
with:
name: alist_linux_arm
path: alist_linux_arm
- name: Upload artifacts windows_amd64
uses: actions/upload-artifact@v2
with:
name: alist_windows_amd64
path: alist_windows_amd64.exe
- name: Upload artifacts linux_386
uses: actions/upload-artifact@v2
with:
name: alist_linux_386
path: alist_linux_386
-48
View File
@@ -1,48 +0,0 @@
name: docker
on:
push:
branches:
- 'v2'
tags:
- 'v*'
pull_request:
branches:
- 'v2'
jobs:
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
- 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/ppc64le,linux/s390x
+109 -44
View File
@@ -1,5 +1,4 @@
name: release
on:
push:
tags:
@@ -9,61 +8,127 @@ jobs:
release:
strategy:
matrix:
platform: [ubuntu-latest]
go-version: [1.17]
name: Release
platform: [ ubuntu-16.04 ]
go-version: [ 1.15 ]
name: Build
runs-on: ${{ matrix.platform }}
steps:
- name: Setup Go
- name: Set up Go
uses: actions/setup-go@v2
with:
go-version: ${{ matrix.go-version }}
# - name: Setup docker
# uses: docker-practice/actions-setup-docker@master
- name: Get version
id: get_version
run: echo ::set-output name=VERSION::${GITHUB_REF/refs\/tags\//}
- name: Setup Node
uses: actions/setup-node@v2
with:
node-version: '16'
- name: Checkout
- name: Check out code into the Go module directory
uses: actions/checkout@v2
with:
ref: v2
path: alist
persist-credentials: false
fetch-depth: 0
- name: Checkout web repo
uses: actions/checkout@v2
with:
repository: Xhofe/alist-web
ref: v2
path: alist-web
persist-credentials: false
fetch-depth: 0
- name: Set up xgo
- name: Get dependencies
run: |
docker pull techknowlogick/xgo:latest
go install src.techknowlogick.com/xgo@latest
sudo apt install upx
sudo apt-get update
sudo apt-get -y install gcc-mingw-w64-x86-64
sudo apt-get -y install gcc-arm-linux-gnueabihf libc6-dev-armhf-cross
sudo apt-get -y install gcc-aarch64-linux-gnu libc6-dev-arm64-cross
go get -v -t -d ./...
if [ -f Gopkg.toml ]; then
curl https://raw.githubusercontent.com/golang/dep/master/install.sh | sh
dep ensure
fi
- name: Build
- name: Build linux
run: |
mv alist/build.sh .
bash build.sh release
CC=gcc CGO_ENABLED=1 GOOS=linux GOARCH=amd64 go build -o linux_amd64/alist alist.go
CC=aarch64-linux-gnu-gcc CGO_ENABLED=1 GOOS=linux GOARCH=arm64 go build -o linux_arm64/alist alist.go
CC=arm-linux-gnueabihf-gcc CGO_ENABLED=1 GOOS=linux GOARCH=arm go build -o linux_arm/alist alist.go
- name: Upload asserts files
uses: ad-m/github-push-action@master
with:
github_token: ${{ secrets.MY_TOKEN }}
branch: cdn
directory: alist-web
repository: Xhofe/alist-web
- name: Build windows
run: |
CC=x86_64-w64-mingw32-gcc CGO_ENABLED=1 GOOS=windows GOARCH=amd64 go build -o windows_amd64/alist.exe alist.go
- name: Release
uses: softprops/action-gh-release@v1
- name: Build linux_386
run: |
sudo apt-get -y install libc6-dev-i386
CC=gcc CGO_ENABLED=1 GOOS=linux GOARCH=386 go build -o linux_386/alist alist.go
- name: compress
run: |
tar -czvf alist_linux_amd64.tar.gz linux_amd64/alist conf.yml.example
tar -czvf alist_linux_arm64.tar.gz linux_arm64/alist conf.yml.example
tar -czvf alist_linux_arm.tar.gz linux_arm/alist conf.yml.example
tar -czvf alist_linux_386.tar.gz linux_386/alist conf.yml.example
zip alist_windows_amd64.zip windows_amd64/alist.exe conf.yml.example
- name: Build Changelog
id: github_release
uses: mikepenz/release-changelog-builder-action@main
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Create Release
id: create_release
uses: actions/create-release@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
files: alist/build/compress/*
tag_name: ${{ github.ref }}
release_name: Release ${{ github.ref }}
body: ${{steps.github_release.outputs.changelog}}
draft: false
prerelease: false
- name: Upload alist_linux_amd64
id: upload-release-linux-amd64
uses: actions/upload-release-asset@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
upload_url: ${{ steps.create_release.outputs.upload_url }}
asset_path: alist_linux_amd64.tar.gz
asset_name: alist_${{ steps.get_version.outputs.VERSION }}_linux_amd64.tar.gz
asset_content_type: application/gzip
- name: Upload alist_linux_arm64
id: upload-release-linux-arm64
uses: actions/upload-release-asset@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
upload_url: ${{ steps.create_release.outputs.upload_url }}
asset_path: alist_linux_arm64.tar.gz
asset_name: alist_${{ steps.get_version.outputs.VERSION }}_linux_arm64.tar.gz
asset_content_type: application/gzip
- name: Upload alist_linux_arm
id: upload-release-linux-arm
uses: actions/upload-release-asset@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
upload_url: ${{ steps.create_release.outputs.upload_url }}
asset_path: alist_linux_arm.tar.gz
asset_name: alist_${{ steps.get_version.outputs.VERSION }}_linux_arm.tar.gz
asset_content_type: application/gzip
- name: Upload alist_linux_386
id: upload-release-linux-386
uses: actions/upload-release-asset@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
upload_url: ${{ steps.create_release.outputs.upload_url }}
asset_path: alist_linux_386.tar.gz
asset_name: alist_${{ steps.get_version.outputs.VERSION }}_linux_386.tar.gz
asset_content_type: application/gzip
- name: Upload alist_windows_amd64
id: upload-release-windows-amd64
uses: actions/upload-release-asset@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
upload_url: ${{ steps.create_release.outputs.upload_url }}
asset_path: alist_windows_amd64.zip
asset_name: alist_${{ steps.get_version.outputs.VERSION }}_windows_amd64.zip
asset_content_type: application/zip
+2 -5
View File
@@ -20,9 +20,6 @@ dist/
# Dependency directories (remove the comment below to include it)
# vendor/
*.yml
bin/*
alist
*.json
public/index.html
public/assets/
data/
alist
-14
View File
@@ -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; \
sh 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" ]
+21
View File
@@ -0,0 +1,21 @@
MIT License
Copyright (c) 2020 微凉
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
+30 -9
View File
@@ -1,4 +1,6 @@
<h2 align="center">Alist</h2>
<p align="center">
<img src="https://img.oez.cc/2020/12/24/1fb16bc25a4f6.png" alt="AList Logo" width=200/>
</p>
<p align="center">
<a href="https://github.com/Xhofe/alist/releases"><img src="https://img.shields.io/github/release/Xhofe/alist?style=flat-square" alt="Release version"></a>
<a href="https://github.com/Xhofe/alist/actions?query=workflow%3ABuild"><img src="https://img.shields.io/github/workflow/status/Xhofe/alist/build?style=flat-square" alt="Build status"></a>
@@ -13,7 +15,7 @@
### 这是什么?
一款支持多种存储的目录文件列表程序,后端基于`gin`,前端使用`react`。
一款阿里云盘的目录文件列表程序,后端基于`golang`最好的`http`框架`gin`,前端使用`vue`和`ant design`。
### 前端项目地址
@@ -21,18 +23,37 @@
### 演示地址
- https://alist.nn.ci
- https://alist.nn.ci (稳定版本)
- https://alist.now.sh (开发版本)
- https://alist-plyr.now.sh (plyr分支版本)
### 预览
<a href="https://alist.nn.ci/"><img src="https://store.heytapimage.com/cdo-portal/feedback/202111/03/695ef77854a144e928518efde38db97a.png"></a>
<a href="https://alist.nn.ci/"><img src="https://img.oez.cc/2020/12/24/d81d2dab3e5f0.png"></a>
### 支持的存储
### 支持的功能
- 本地存储
- 阿里云盘
- Onedrive/世纪互联
- ...
- 自动刷新`token`,`refresh_token`自动更新,失效时间未知,本人使用过程中没有失效过。
- 图片、视频、音频预览
- 目录加密
- `Readme`渲染
- 自定义根目录
- 文件直链下载
- …
#### TODO
- [x] 排序
- [x] 文件预览
- [x] 图片
- [x] 视频
- [x] 音频
- [x] `Readme`渲染
- [x] 密码加密
- [ ] 搜索与翻页
- [x] 文件直链
- [ ] 路径优化
- [x] 缓存
### 如何使用
+49
View File
@@ -0,0 +1,49 @@
package alidrive
import (
"encoding/json"
"github.com/Xhofe/alist/conf"
"github.com/Xhofe/alist/utils"
log "github.com/sirupsen/logrus"
)
// refresh access_token token by refresh_token
func RefreshToken(drive *conf.Drive) bool {
log.Infof("刷新[%s]token...", drive.Name)
url := "https://auth.aliyundrive.com/v2/account/token"
req := RefreshTokenReq{RefreshToken: drive.RefreshToken , GrantType: "refresh_token"}
var token TokenResp
if body, err := DoPost(url, req, ""); err != nil {
log.Errorf("tokenLogin-doPost出错:%s", err.Error())
return false
} else {
if err = json.Unmarshal(body, &token); err != nil {
log.Errorf("解析json[%s]出错:%s", string(body), err.Error())
log.Errorf("此处json解析失败应该是[%s]refresh_token失效", drive.Name)
return false
}
}
if token.Code != "" {
log.Errorf("盘[%s]刷新token出错:%s", drive.Name, token.Message)
return false
}
//刷新成功 更新token
drive.AccessToken = token.AccessToken
drive.RefreshToken = token.RefreshToken
return true
}
func RefreshTokenAll() string {
log.Infof("刷新所有token...")
res := ""
for i, drive := range conf.Conf.AliDrive.Drives {
if !RefreshToken(&conf.Conf.AliDrive.Drives[i]) {
res = res + drive.Name + ","
}
}
utils.WriteToYml(conf.ConfigFile, conf.Conf)
if res != "" {
return res[:len(res)-1]
}
return ""
}
+80
View File
@@ -0,0 +1,80 @@
package alidrive
import (
"bytes"
"encoding/json"
"fmt"
"github.com/Xhofe/alist/conf"
log "github.com/sirupsen/logrus"
"io/ioutil"
"net/http"
"strings"
"time"
)
// convert body to json
func BodyToJson(url string, req interface{}, resp RespHandle, drive *conf.Drive) error {
if body, err := DoPost(url, req, drive.AccessToken); err != nil {
log.Errorf("doPost出错:%s", err.Error())
return err
} else {
if err = json.Unmarshal(body, &resp); err != nil {
log.Errorf("解析json[%s]出错:%s", string(body), err.Error())
return err
}
}
if resp.IsAvailable() {
return nil
}
if resp.GetCode() == conf.AccessTokenInvalid {
resp.SetCode("")
if RefreshToken(drive) {
return BodyToJson(url, req, resp, drive)
}
}
return fmt.Errorf(resp.GetMessage())
}
// do post request
func DoPost(url string, request interface{}, auth string) (body []byte, err error) {
var (
resp *http.Response
)
requestBody := new(bytes.Buffer)
err = json.NewEncoder(requestBody).Encode(request)
if err != nil {
log.Errorf("创建requestBody出错:%s", err.Error())
}
req, err := http.NewRequest("POST", url, requestBody)
log.Debugf("do_post_req:%+v", req)
if err != nil {
log.Errorf("创建request出错:%s", err.Error())
return
}
if auth != "" {
req.Header.Set("authorization", conf.Bearer+auth)
}
req.Header.Add("content-type", "application/json")
req.Header.Add("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")
req.Header.Add("origin", "https://aliyundrive.com")
req.Header.Add("accept", "*/*")
req.Header.Add("Accept-Language", "zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3")
req.Header.Add("Connection", "keep-alive")
for retryCount := 3; retryCount >= 0; retryCount-- {
if resp, err = conf.Client.Do(req); err != nil && strings.Contains(err.Error(), "timeout") {
<-time.After(time.Second)
} else {
break
}
}
if err != nil {
log.Errorf("请求阿里云盘api时出错:%s", err.Error())
return
}
if body, err = ioutil.ReadAll(resp.Body); err != nil {
log.Errorf("读取api返回内容失败")
}
log.Debugf("请求返回信息:%s", string(body))
return
}
+75
View File
@@ -0,0 +1,75 @@
package alidrive
// ListReq list request bean
type ListReq struct {
DriveId string `json:"drive_id"`
Fields string `json:"fields"`
ImageThumbnailProcess string `json:"image_thumbnail_process"`
ImageUrlProcess string `json:"image_url_process"`
Limit int `json:"limit"`
Marker string `json:"marker"`
OrderBy string `json:"order_by"`
OrderDirection string `json:"order_direction"`
ParentFileId string `json:"parent_file_id"`
VideoThumbnailProcess string `json:"video_thumbnail_process"`
}
// GetReq get request bean
type GetReq struct {
DriveId string `json:"drive_id"`
FileId string `json:"file_id"`
ImageThumbnailProcess string `json:"image_thumbnail_process"`
VideoThumbnailProcess string `json:"video_thumbnail_process"`
}
// DownloadReq download request bean
type DownloadReq struct {
DriveId string `json:"drive_id"`
FileId string `json:"file_id"`
ExpireSec int `json:"expire_sec"`
FileName string `json:"file_name"`
}
// SearchReq search request bean
type SearchReq struct {
DriveId string `json:"drive_id"`
ImageThumbnailProcess string `json:"image_thumbnail_process"`
ImageUrlProcess string `json:"image_url_process"`
Limit int `json:"limit"`
Marker string `json:"marker"`
OrderBy string `json:"order_by"` //"type ASC,updated_at DESC"
Query string `json:"query"` // "name match '测试文件'"
VideoThumbnailProcess string `json:"video_thumbnail_process"`
}
// TokenLoginReq token_login request bean
type TokenLoginReq struct {
Token string `json:"token"`
}
// GetTokenReq get_token request bean
type GetTokenReq struct {
Code string `json:"code"`
}
// RefreshTokenReq refresh_token request bean
type RefreshTokenReq struct {
RefreshToken string `json:"refresh_token"`
GrantType string `json:"grant_type"`
}
// OfficePreviewUrlReq office_preview_url request bean
type OfficePreviewUrlReq struct {
AccessToken string `json:"access_token"`
DriveId string `json:"drive_id"`
FileId string `json:"file_id"`
}
// VideoPreviewUrlReq video preview url request bean
type VideoPreviewUrlReq struct {
DriveId string `json:"drive_id"`
FileId string `json:"file_id"`
ExpireSec int `json:"expire_sec"`
}
+124
View File
@@ -0,0 +1,124 @@
package alidrive
import (
"fmt"
"github.com/Xhofe/alist/conf"
)
// get file
func GetFile(fileId string, drive *conf.Drive) (*File, error) {
url := conf.Conf.AliDrive.ApiUrl + "/file/get"
req := GetReq{
DriveId: drive.DefaultDriveId,
FileId: fileId,
ImageThumbnailProcess: conf.ImageThumbnailProcess,
VideoThumbnailProcess: conf.VideoThumbnailProcess,
}
var resp File
if err := BodyToJson(url, req, &resp, drive); err != nil {
return nil, err
}
return &resp, nil
}
// get download_url
func GetDownLoadUrl(fileId string, drive *conf.Drive) (*DownloadResp, error) {
url := conf.Conf.AliDrive.ApiUrl + "/file/get_download_url"
req := DownloadReq{
DriveId: drive.DefaultDriveId,
FileId: fileId,
ExpireSec: 14400,
}
var resp DownloadResp
if err := BodyToJson(url, req, &resp, drive); err != nil {
return nil, err
}
return &resp, nil
}
// search by keyword
func Search(key string, limit int, marker string, drive *conf.Drive) (*Files, error) {
url := conf.Conf.AliDrive.ApiUrl + "/file/search"
req := SearchReq{
DriveId: drive.DefaultDriveId,
ImageThumbnailProcess: conf.ImageThumbnailProcess,
ImageUrlProcess: conf.ImageUrlProcess,
Limit: limit,
Marker: marker,
OrderBy: conf.OrderSearch,
Query: fmt.Sprintf("name match '%s'", key),
VideoThumbnailProcess: conf.VideoThumbnailProcess,
}
var resp Files
if err := BodyToJson(url, req, &resp, drive); err != nil {
return nil, err
}
return &resp, nil
}
// get root folder
func GetRoot(limit int, marker string, orderBy string, orderDirection string, drive *conf.Drive) (*Files, error) {
return GetList(drive.RootFolder, limit, marker, orderBy, orderDirection, drive)
}
// get folder list by file_id
func GetList(parent string, limit int, marker string, orderBy string, orderDirection string, drive *conf.Drive) (*Files, error) {
url := conf.Conf.AliDrive.ApiUrl + "/file/list"
req := ListReq{
DriveId: drive.DefaultDriveId,
Fields: "*",
ImageThumbnailProcess: conf.ImageThumbnailProcess,
ImageUrlProcess: conf.ImageUrlProcess,
Limit: limit,
Marker: marker,
OrderBy: orderBy,
OrderDirection: orderDirection,
ParentFileId: parent,
VideoThumbnailProcess: conf.VideoThumbnailProcess,
}
var resp Files
if err := BodyToJson(url, req, &resp, drive); err != nil {
return nil, err
}
return &resp, nil
}
// get user info
func GetUserInfo(drive *conf.Drive) (*UserInfo, error) {
url := conf.Conf.AliDrive.ApiUrl + "/user/get"
var resp UserInfo
if err := BodyToJson(url, map[string]interface{}{}, &resp, drive); err != nil {
return nil, err
}
return &resp, nil
}
// get office preview url and token
func GetOfficePreviewUrl(fileId string, drive *conf.Drive) (*OfficePreviewUrlResp, error) {
url := conf.Conf.AliDrive.ApiUrl + "/file/get_office_preview_url"
req := OfficePreviewUrlReq{
AccessToken: drive.AccessToken,
DriveId: drive.DefaultDriveId,
FileId: fileId,
}
var resp OfficePreviewUrlResp
if err := BodyToJson(url, req, &resp, drive); err != nil {
return nil, err
}
return &resp, nil
}
// get video preview url
func GetVideoPreviewUrl(fileId string, drive *conf.Drive) (*VideoPreviewUrlResp, error) {
url := conf.Conf.AliDrive.ApiUrl + "/databox/get_video_play_info"
req := VideoPreviewUrlReq{
DriveId: drive.DefaultDriveId,
FileId: fileId,
ExpireSec: 14400,
}
var resp VideoPreviewUrlResp
if err := BodyToJson(url, req, &resp, drive); err != nil {
return nil, err
}
return &resp, nil
}
+164
View File
@@ -0,0 +1,164 @@
package alidrive
import (
"time"
)
// response bean methods
type RespHandle interface {
IsAvailable() bool // check available
GetCode() string // get err code
GetMessage() string // get err message
SetCode(code string) // set err code
}
// common response bean
type RespError struct {
Code string `json:"code"`
Message string `json:"message"`
}
func (resp *RespError) IsAvailable() bool {
return resp.Code == ""
}
func (resp *RespError) GetCode() string {
return resp.Code
}
func (resp *RespError) GetMessage() string {
return resp.Message
}
func (resp *RespError) SetCode(code string) {
resp.Code = code
}
// user_info response bean
type UserInfo struct {
RespError
DomainId string `json:"domain_id"`
UserId string `json:"user_id"`
Avatar string `json:"avatar"`
CreatedAt int64 `json:"created_at"`
UpdatedAt int64 `json:"updated_at"`
Email string `json:"email"`
NickName string `json:"nick_name"`
Phone string `json:"phone"`
Role string `json:"role"`
Status string `json:"status"`
UserName string `json:"user_name"`
Description string `json:"description"`
DefaultDriveId string `json:"default_drive_id"`
UserData map[string]interface{} `json:"user_data"`
}
// folder files response bean
type Files struct {
RespError
Items []File `json:"items"`
NextMarker string `json:"next_marker"`
Readme string `json:"readme"` // Deprecated
Paths []Path `json:"paths"`
}
// path bean
type Path struct {
Name string `json:"name"`
FileId string `json:"file_id"`
}
/** 秒传
{
"name":"mikuclub.mp4",
"content_hash":"C733AC50D1F964C0398D0E403F3A30C37EFC2ADD",
"size":1141068377,
"content_type":"video/mp4"
}
*/
// file response bean
type File struct {
RespError
DriveId string `json:"drive_id"`
CreatedAt *time.Time `json:"created_at"`
DomainId string `json:"domain_id"`
EncryptMode string `json:"encrypt_mode"`
FileExtension string `json:"file_extension"`
FileId string `json:"file_id"`
Hidden bool `json:"hidden"`
Name string `json:"name"`
ParentFileId string `json:"parent_file_id"`
Starred bool `json:"starred"`
Status string `json:"status"`
Type string `json:"type"`
UpdatedAt *time.Time `json:"updated_at"`
// 文件多出部分
Category string `json:"category"`
ContentHash string `json:"content_hash"`
ContentHashName string `json:"content_hash_name"`
ContentType string `json:"content_type"`
Crc64Hash string `json:"crc_64_hash"`
DownloadUrl string `json:"download_url"`
PunishFlag int64 `json:"punish_flag"`
Size int64 `json:"size"`
Thumbnail string `json:"thumbnail"`
Url string `json:"url"`
ImageMediaMetadata map[string]interface{} `json:"image_media_metadata"`
Paths []Path `json:"paths"`
}
type DownloadResp struct {
RespError
Expiration string `json:"expiration"`
Method string `json:"method"`
Size int64 `json:"size"`
Url string `json:"url"`
//RateLimit struct{
// PartSize int `json:"part_size"`
// PartSpeed int `json:"part_speed"`
//} `json:"rate_limit"`//rate limit
}
// token_login response bean
type TokenLoginResp struct {
RespError
Goto string `json:"goto"`
}
// token response bean
type TokenResp struct {
RespError
AccessToken string `json:"access_token"`
RefreshToken string `json:"refresh_token"`
ExpiresIn int `json:"expires_in"`
TokenType string `json:"token_type"`
UserInfo
DefaultSboxDriveId string `json:"default_sbox_drive_id"`
ExpireTime *time.Time `json:"expire_time"`
State string `json:"state"`
ExistLink []interface{} `json:"exist_link"`
NeedLink bool `json:"need_link"`
PinSetup bool `json:"pin_setup"`
IsFirstLogin bool `json:"is_first_login"`
NeedRpVerify bool `json:"need_rp_verify"`
DeviceId string `json:"device_id"`
}
// office_preview_url response bean
type OfficePreviewUrlResp struct {
RespError
PreviewUrl string `json:"preview_url"`
AccessToken string `json:"access_token"`
}
type VideoPreviewUrlResp struct {
RespError
TemplateList []struct {
TemplateId string `json:"template_id"`
Status string `json:"status"`
Url string `json:"url"`
} `json:"template_list"`
}
+41
View File
@@ -0,0 +1,41 @@
package alidrive
import (
log "github.com/sirupsen/logrus"
"io/ioutil"
"net/http"
"strings"
)
// check password
func HasPassword(files *Files) string {
fileList := files.Items
for i, file := range fileList {
if strings.HasPrefix(file.Name, ".password-") {
files.Items = fileList[:i+copy(fileList[i:], fileList[i+1:])]
return file.Name[10:]
}
}
return ""
}
// Deprecated: check readme, implemented by the front end now
func HasReadme(files *Files) string {
fileList := files.Items
for _, file := range fileList {
if file.Name == "Readme.md" {
resp, err := http.Get(file.Url)
if err != nil {
log.Errorf("Get Readme出错:%s", err.Error())
return ""
}
data, err := ioutil.ReadAll(resp.Body)
if err != nil {
log.Errorf("读取 Readme出错:%s", err.Error())
return ""
}
return string(data)
}
}
return ""
}
+4 -41
View File
@@ -1,45 +1,8 @@
package main
import (
"flag"
"fmt"
"github.com/Xhofe/alist/bootstrap"
"github.com/Xhofe/alist/conf"
"github.com/Xhofe/alist/server"
"github.com/gin-gonic/gin"
log "github.com/sirupsen/logrus"
)
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.Parse()
}
func Init() {
bootstrap.InitLog()
bootstrap.InitConf()
bootstrap.InitCron()
bootstrap.InitModel()
bootstrap.InitCache()
}
import "github.com/Xhofe/alist/bootstrap"
// main function
func main() {
if conf.Version {
fmt.Printf("Built At: %s\nGo Version: %s\nAuthor: %s\nCommit ID: %s\nVersion: %s\n", conf.BuiltAt, conf.GoVersion, conf.GitAuthor, conf.GitCommit, conf.GitTag)
return
}
Init()
if !conf.Debug {
gin.SetMode(gin.ReleaseMode)
}
r := gin.Default()
server.InitApiRouter(r)
log.Info("starting server")
err := r.Run(fmt.Sprintf("%s:%d", conf.Conf.Address, conf.Conf.Port))
if err != nil {
log.Errorf("failed to start: %s", err.Error())
}
}
bootstrap.Run()
}
-12
View File
@@ -1,12 +0,0 @@
package main
import (
"fmt"
"net/url"
"testing"
)
func TestUrl(t *testing.T) {
s,_ := url.QueryUnescape("/ali/%E7%8C%AA%E5%A4%B4%E7%9A%84%E6%96%87%E4%BB%B6%5B%E5%98%BF%E5%98%BF%5D/%E9%82%B9%E9%82%B9%E7%9A%84%E6%96%87%E4%BB%B6/%E6%A1%8C%E9%9D%A2%E5%A3%81%E7%BA%B8/v2-e8f266ba17ae387eefed1cb22b2b5e4e_r.jpg")
fmt.Print(s)
}
+33
View File
@@ -0,0 +1,33 @@
package bootstrap
import (
"github.com/Xhofe/alist/alidrive"
"github.com/Xhofe/alist/conf"
log "github.com/sirupsen/logrus"
)
// init aliyun drive
func InitAliDrive() bool {
log.Infof("初始化阿里云盘...")
//首先token_login
res := alidrive.RefreshTokenAll()
if res != "" {
log.Errorf("盘[%s]refresh_token失效,请检查", res)
}
log.Debugf("config:%+v", conf.Conf)
for i, _ := range conf.Conf.AliDrive.Drives {
InitDriveId(&conf.Conf.AliDrive.Drives[i])
}
return true
}
func InitDriveId(drive *conf.Drive) bool {
user, err := alidrive.GetUserInfo(drive)
if err != nil {
log.Errorf("初始化盘[%s]失败:%s", drive.Name, err.Error())
return false
}
drive.DefaultDriveId = user.DefaultDriveId
log.Infof("初始化盘[%s]成功:%+v", drive.Name, user)
return true
}
-18
View File
@@ -1,18 +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...")
goCacheClient := goCache.New(60*time.Minute, 120*time.Minute)
goCacheStore := store.NewGoCache(goCacheClient, nil)
conf.Cache = cache.New(goCacheStore)
}
+17
View File
@@ -0,0 +1,17 @@
package bootstrap
import (
"crypto/tls"
"github.com/Xhofe/alist/conf"
log "github.com/sirupsen/logrus"
"net/http"
)
// init request client
func InitClient() {
log.Infof("初始化client...")
tr := &http.Transport{
TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
}
conf.Client = &http.Client{Transport: tr}
}
+83
View File
@@ -0,0 +1,83 @@
package bootstrap
import (
"flag"
"fmt"
"github.com/Xhofe/alist/conf"
serv "github.com/Xhofe/alist/server"
"github.com/gin-gonic/gin"
log "github.com/sirupsen/logrus"
)
func init() {
flag.BoolVar(&conf.Debug, "debug", false, "use debug mode")
flag.BoolVar(&conf.Help, "help", false, "show usage help")
flag.BoolVar(&conf.Version, "version", false, "show version info")
flag.StringVar(&conf.ConfigFile, "conf", "conf.yml", "config file")
flag.BoolVar(&conf.SkipUpdate, "skip-update", false, "skip update")
}
// bootstrap run
func Run() {
flag.Parse()
if conf.Help {
flag.Usage()
return
}
if conf.Version {
fmt.Println("Current version:" + conf.VERSION)
return
}
start()
}
// print asc
func printASC() {
log.Info(`
________ ___ ___ ________ _________
|\ __ \|\ \ |\ \|\ ____\|\___ ___\
\ \ \|\ \ \ \ \ \ \ \ \___|\|___ \ \_|
\ \ __ \ \ \ \ \ \ \_____ \ \ \ \
\ \ \ \ \ \ \____\ \ \|____|\ \ \ \ \
\ \__\ \__\ \_______\ \__\____\_\ \ \ \__\
\|__|\|__|\|_______|\|__|\_________\ \|__|
\|_________|
`)
}
// start server
func start() {
InitLog()
printASC()
if !conf.SkipUpdate {
CheckUpdate()
}
if !ReadConf(conf.ConfigFile) {
log.Errorf("读取配置文件时出现错误,启动失败.")
return
}
InitClient()
if !InitAliDrive() {
log.Errorf("初始化阿里云盘出现错误,启动失败.")
return
}
if !InitModel() {
log.Errorf("初始化数据库出现错误,启动失败.")
return
}
InitCron()
server()
}
// start http server
func server() {
baseServer := conf.Conf.Server.Address + ":" + conf.Conf.Server.Port
r := gin.Default()
serv.InitRouter(r)
log.Infof("Starting server @ %s", baseServer)
err := r.Run(baseServer)
if err != nil {
log.Errorf("Server failed start:%s", err.Error())
}
}

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