mirror of
https://github.com/GopeedLab/gopeed.git
synced 2026-11-12 19:33:41 +00:00
Compare commits
1
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
63210dce63 |
No files matched your search
@@ -1,16 +0,0 @@
|
|||||||
.git
|
|
||||||
|
|
||||||
*.data
|
|
||||||
*.log
|
|
||||||
|
|
||||||
node_modules
|
|
||||||
**/node_modules
|
|
||||||
|
|
||||||
Dockerfile
|
|
||||||
.dockerignore
|
|
||||||
|
|
||||||
.github
|
|
||||||
_docs
|
|
||||||
_examples
|
|
||||||
bin
|
|
||||||
ui
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
* @monkeyWie
|
|
||||||
@@ -1,15 +0,0 @@
|
|||||||
# These are supported funding model platforms
|
|
||||||
|
|
||||||
#github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2]
|
|
||||||
#patreon: # Replace with a single Patreon username
|
|
||||||
#open_collective: # Replace with a single Open Collective username
|
|
||||||
#ko_fi: # Replace with a single Ko-fi username
|
|
||||||
#tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
|
|
||||||
#community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
|
|
||||||
#liberapay: # Replace with a single Liberapay username
|
|
||||||
#issuehunt: # Replace with a single IssueHunt username
|
|
||||||
#otechie: # Replace with a single Otechie username
|
|
||||||
#custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2']
|
|
||||||
# github: monkeyWie
|
|
||||||
ko_fi: gopeed
|
|
||||||
custom: https://docs.gopeed.com/donate.html
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
<!--
|
|
||||||
Please use the following template to create an issue.
|
|
||||||
-->
|
|
||||||
### Description(required)
|
|
||||||
### App Version(required)
|
|
||||||
### OS Version(required)
|
|
||||||
### Snapshots
|
|
||||||
### Log
|
|
||||||
@@ -1,46 +0,0 @@
|
|||||||
name-template: 'v$NEXT_PATCH_VERSION 🌈'
|
|
||||||
tag-template: 'v$NEXT_PATCH_VERSION'
|
|
||||||
categories:
|
|
||||||
- title: '🆕 Features'
|
|
||||||
labels:
|
|
||||||
- 'feat'
|
|
||||||
- 'feature'
|
|
||||||
- 'enhancement'
|
|
||||||
- title: '🐛 Bug Fixes'
|
|
||||||
labels:
|
|
||||||
- 'fix'
|
|
||||||
- 'bugfix'
|
|
||||||
- 'bug'
|
|
||||||
- title: '🔧 Performance Improvements'
|
|
||||||
labels:
|
|
||||||
- 'perf'
|
|
||||||
- title: '🧪 Tests'
|
|
||||||
label: 'test'
|
|
||||||
- title: '🧰 Maintenance'
|
|
||||||
label: 'chore'
|
|
||||||
- title: '📖 Document'
|
|
||||||
label: 'docs'
|
|
||||||
- title: '🚀 CI/CD'
|
|
||||||
label: 'ci'
|
|
||||||
- title: '🌎 Internationalization'
|
|
||||||
label: 'translation'
|
|
||||||
change-template: '- $TITLE @$AUTHOR (#$NUMBER)'
|
|
||||||
version-resolver:
|
|
||||||
major:
|
|
||||||
labels:
|
|
||||||
- 'major'
|
|
||||||
minor:
|
|
||||||
labels:
|
|
||||||
- 'minor'
|
|
||||||
patch:
|
|
||||||
labels:
|
|
||||||
- 'patch'
|
|
||||||
default: patch
|
|
||||||
template: |
|
|
||||||
# Release notes
|
|
||||||
|
|
||||||
$CHANGES
|
|
||||||
|
|
||||||
# 更新日志
|
|
||||||
|
|
||||||
$CHANGES
|
|
||||||
File diff suppressed because it is too large.
Load diff
@@ -1,40 +0,0 @@
|
|||||||
name: release
|
|
||||||
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
branches:
|
|
||||||
- main
|
|
||||||
paths:
|
|
||||||
- "bind/**"
|
|
||||||
- "cmd/**"
|
|
||||||
- "internal/**"
|
|
||||||
- "pkg/**"
|
|
||||||
- "ui/**"
|
|
||||||
- ".github/workflows/release.yml"
|
|
||||||
- ".github/release-drafter.yml"
|
|
||||||
- "go.mod"
|
|
||||||
- "go.sum"
|
|
||||||
- "Dockerfile"
|
|
||||||
|
|
||||||
env:
|
|
||||||
GO_VERSION: "1.23"
|
|
||||||
|
|
||||||
permissions:
|
|
||||||
contents: write
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
release:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
outputs:
|
|
||||||
tag_name: ${{ steps.create_release.outputs.tag_name }}
|
|
||||||
upload_url: ${{ steps.create_release.outputs.upload_url }}
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v3
|
|
||||||
- uses: actions/setup-go@v4
|
|
||||||
with:
|
|
||||||
go-version: ${{ env.GO_VERSION }}
|
|
||||||
- uses: release-drafter/release-drafter@v5
|
|
||||||
id: create_release
|
|
||||||
env:
|
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
@@ -1,167 +0,0 @@
|
|||||||
name: test
|
|
||||||
|
|
||||||
on:
|
|
||||||
pull_request:
|
|
||||||
branches:
|
|
||||||
- main
|
|
||||||
paths:
|
|
||||||
- "bind/**"
|
|
||||||
- "cmd/**"
|
|
||||||
- "internal/**"
|
|
||||||
- "pkg/**"
|
|
||||||
- "ui/**"
|
|
||||||
- ".github/workflows/test.yml"
|
|
||||||
- "go.mod"
|
|
||||||
- "go.sum"
|
|
||||||
push:
|
|
||||||
branches:
|
|
||||||
- main
|
|
||||||
paths:
|
|
||||||
- "bind/**"
|
|
||||||
- "cmd/**"
|
|
||||||
- "internal/**"
|
|
||||||
- "pkg/**"
|
|
||||||
- "ui/**"
|
|
||||||
- ".github/workflows/test.yml"
|
|
||||||
- "go.mod"
|
|
||||||
- "go.sum"
|
|
||||||
|
|
||||||
env:
|
|
||||||
GO_VERSION: "1.23"
|
|
||||||
FLUTTER_VERSION: "3.16.8"
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
# lint:
|
|
||||||
# name: Lint
|
|
||||||
# runs-on: ubuntu-latest
|
|
||||||
# steps:
|
|
||||||
# - uses: actions/setup-go@v2
|
|
||||||
# with:
|
|
||||||
# go-version: '^1.19'
|
|
||||||
# - uses: actions/checkout@v2
|
|
||||||
# - name: Lint Go Code
|
|
||||||
# run: |
|
|
||||||
# export PATH=$PATH:$(go env GOPATH)/bin # temporary fix. See https://github.com/actions/setup-go/issues/14
|
|
||||||
# go get -u golang.org/x/lint/golint
|
|
||||||
# golint -set_exit_status ./...
|
|
||||||
test:
|
|
||||||
name: Test check
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v3
|
|
||||||
- uses: actions/setup-go@v4
|
|
||||||
with:
|
|
||||||
go-version: ${{ env.GO_VERSION }}
|
|
||||||
- name: Run Unit tests.
|
|
||||||
run: go test $(go list ./... | grep -v /cmd/ | grep -v /bind/ ) -v -covermode=count -coverprofile=coverage.txt
|
|
||||||
- uses: codecov/codecov-action@v4
|
|
||||||
with:
|
|
||||||
files: ./coverage.txt
|
|
||||||
token: ${{ secrets.CODECOV_UPLOAD_TOKEN }}
|
|
||||||
build-desktop:
|
|
||||||
name: Build desktop check
|
|
||||||
runs-on: ${{ matrix.os }}
|
|
||||||
strategy:
|
|
||||||
matrix:
|
|
||||||
os: [ windows-latest, macos-latest, ubuntu-latest ]
|
|
||||||
needs: [ test ]
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v3
|
|
||||||
- uses: actions/setup-go@v4
|
|
||||||
with:
|
|
||||||
go-version: ${{ env.GO_VERSION }}
|
|
||||||
- uses: subosito/flutter-action@v2
|
|
||||||
with:
|
|
||||||
flutter-version: ${{ env.FLUTTER_VERSION }}
|
|
||||||
- if: runner.os == 'windows'
|
|
||||||
run: |
|
|
||||||
go build -tags nosqlite -ldflags="-w -s" -buildmode=c-shared -o ui/flutter/windows/libgopeed.dll github.com/GopeedLab/gopeed/bind/desktop
|
|
||||||
cd ui/flutter
|
|
||||||
flutter build windows
|
|
||||||
- if: runner.os == 'macOS'
|
|
||||||
run: |
|
|
||||||
go build -tags nosqlite -ldflags="-w -s" -buildmode=c-shared -o ui/flutter/macos/Frameworks/libgopeed.dylib github.com/GopeedLab/gopeed/bind/desktop
|
|
||||||
cd ui/flutter
|
|
||||||
flutter build macos
|
|
||||||
- if: runner.os == 'Linux'
|
|
||||||
run: |
|
|
||||||
sudo apt-get update -y
|
|
||||||
sudo apt-get install -y ninja-build libgtk-3-dev libayatana-appindicator3-dev
|
|
||||||
go build -tags nosqlite -ldflags="-w -s" -buildmode=c-shared -o ui/flutter/linux/bundle/lib/libgopeed.so github.com/GopeedLab/gopeed/bind/desktop
|
|
||||||
cd ui/flutter
|
|
||||||
flutter build linux
|
|
||||||
build-mobile:
|
|
||||||
name: Build mobile check
|
|
||||||
runs-on: ${{ matrix.os }}
|
|
||||||
strategy:
|
|
||||||
matrix:
|
|
||||||
os: [ macos-latest, ubuntu-latest ]
|
|
||||||
needs: [ test ]
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v3
|
|
||||||
- uses: actions/setup-go@v4
|
|
||||||
with:
|
|
||||||
go-version: ${{ env.GO_VERSION }}
|
|
||||||
- uses: subosito/flutter-action@v2
|
|
||||||
with:
|
|
||||||
flutter-version: ${{ env.FLUTTER_VERSION }}
|
|
||||||
- run: |
|
|
||||||
go install golang.org/x/mobile/cmd/gomobile@latest
|
|
||||||
go get golang.org/x/mobile/bind
|
|
||||||
gomobile init
|
|
||||||
- if: runner.os == 'macOS'
|
|
||||||
run: |
|
|
||||||
gomobile bind -tags nosqlite -ldflags="-w -s" -o ui/flutter/ios/Frameworks/Libgopeed.xcframework -target=ios github.com/GopeedLab/gopeed/bind/mobile
|
|
||||||
cd ui/flutter
|
|
||||||
flutter build ipa --no-codesign
|
|
||||||
- if: runner.os == 'Linux'
|
|
||||||
uses: actions/setup-java@v3
|
|
||||||
with:
|
|
||||||
distribution: "zulu"
|
|
||||||
java-version: "17"
|
|
||||||
- if: runner.os == 'Linux'
|
|
||||||
run: |
|
|
||||||
gomobile bind -tags nosqlite -ldflags="-w -s -checklinkname=0" -o ui/flutter/android/app/libs/libgopeed.aar -target=android -androidapi 21 -javapkg=com.gopeed github.com/GopeedLab/gopeed/bind/mobile
|
|
||||||
cd ui/flutter
|
|
||||||
flutter build apk
|
|
||||||
|
|
||||||
build-web:
|
|
||||||
name: Build web check
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
needs: [ test ]
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v3
|
|
||||||
- uses: actions/setup-go@v4
|
|
||||||
with:
|
|
||||||
go-version: ${{ env.GO_VERSION }}
|
|
||||||
- uses: subosito/flutter-action@v2
|
|
||||||
with:
|
|
||||||
flutter-version: ${{ env.FLUTTER_VERSION }}
|
|
||||||
- name: Build
|
|
||||||
run: |
|
|
||||||
cd ui/flutter
|
|
||||||
flutter build web --web-renderer html
|
|
||||||
cd ../../
|
|
||||||
rm -rf cmd/web/dist
|
|
||||||
cp -r ui/flutter/build/web cmd/web/dist
|
|
||||||
go build -tags nosqlite,web -ldflags="-s -w" github.com/GopeedLab/gopeed/cmd/web
|
|
||||||
build-docker:
|
|
||||||
name: Build docker check
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
needs: [ test ]
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v3
|
|
||||||
- uses: actions/setup-go@v4
|
|
||||||
with:
|
|
||||||
go-version: ${{ env.GO_VERSION }}
|
|
||||||
- uses: subosito/flutter-action@v2
|
|
||||||
with:
|
|
||||||
flutter-version: ${{ env.FLUTTER_VERSION }}
|
|
||||||
- name: Build
|
|
||||||
run: |
|
|
||||||
cd ui/flutter
|
|
||||||
flutter build web --web-renderer html
|
|
||||||
cd ../../
|
|
||||||
rm -rf cmd/web/dist
|
|
||||||
cp -r ui/flutter/build/web cmd/web/dist
|
|
||||||
docker build -t gopeed .
|
|
||||||
@@ -1,30 +0,0 @@
|
|||||||
# name: 'translator'
|
|
||||||
|
|
||||||
# on:
|
|
||||||
# issues:
|
|
||||||
# types: [opened, edited]
|
|
||||||
# issue_comment:
|
|
||||||
# types: [created, edited]
|
|
||||||
# discussion:
|
|
||||||
# types: [created, edited]
|
|
||||||
# discussion_comment:
|
|
||||||
# types: [created, edited]
|
|
||||||
# pull_request_target:
|
|
||||||
# types: [opened, edited]
|
|
||||||
# pull_request_review_comment:
|
|
||||||
# types: [created, edited]
|
|
||||||
|
|
||||||
# jobs:
|
|
||||||
# translate:
|
|
||||||
# permissions:
|
|
||||||
# issues: write
|
|
||||||
# discussions: write
|
|
||||||
# pull-requests: write
|
|
||||||
# runs-on: ubuntu-latest
|
|
||||||
# steps:
|
|
||||||
# - uses: lizheming/[email protected]
|
|
||||||
# env:
|
|
||||||
# GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
# with:
|
|
||||||
# IS_MODIFY_TITLE: true
|
|
||||||
# APPEND_TRANSLATION: true
|
|
||||||
+3
-19
@@ -4,29 +4,13 @@
|
|||||||
*.dll
|
*.dll
|
||||||
*.so
|
*.so
|
||||||
*.dylib
|
*.dylib
|
||||||
ui/flutter/dist/
|
|
||||||
# Test binary, built with `go test -c`
|
# Test binary, built with `go test -c`
|
||||||
*.test
|
*.test
|
||||||
|
|
||||||
# Output of the go coverage tool, specifically when used with LiteIDE
|
# Output of the go coverage tool, specifically when used with LiteIDE
|
||||||
*.out
|
*.out
|
||||||
|
|
||||||
|
debug
|
||||||
|
|
||||||
.idea/
|
.idea/
|
||||||
|
|
||||||
bin/
|
|
||||||
|
|
||||||
.torrent.db
|
|
||||||
.torrent.db-shm
|
|
||||||
.torrent.db-wal
|
|
||||||
|
|
||||||
*.data
|
|
||||||
*.db
|
|
||||||
*.log
|
|
||||||
|
|
||||||
.DS_Store
|
|
||||||
|
|
||||||
node_modules/
|
|
||||||
cmd/web/dist/
|
|
||||||
.test_storage/
|
|
||||||
.test_download/
|
|
||||||
/extensions
|
|
||||||
Vendored
+17
@@ -0,0 +1,17 @@
|
|||||||
|
{
|
||||||
|
// Use IntelliSense to learn about possible attributes.
|
||||||
|
// Hover to view descriptions of existing attributes.
|
||||||
|
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
|
||||||
|
"version": "0.2.0",
|
||||||
|
"configurations": [
|
||||||
|
{
|
||||||
|
"name": "Launch",
|
||||||
|
"type": "go",
|
||||||
|
"request": "launch",
|
||||||
|
"mode": "auto",
|
||||||
|
"program": "${fileDirname}",
|
||||||
|
"env": {},
|
||||||
|
"args": []
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
Vendored
+9
@@ -0,0 +1,9 @@
|
|||||||
|
{
|
||||||
|
"go.useLanguageServer": true,
|
||||||
|
"[go]": {
|
||||||
|
"editor.formatOnSave": true,
|
||||||
|
"editor.codeActionsOnSave": {
|
||||||
|
"source.organizeImports": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
@@ -1,34 +0,0 @@
|
|||||||
# Gopeed contributors guide
|
|
||||||
|
|
||||||
Firstly, thank you for your interest in contributing to Gopeed. This guide will help you better
|
|
||||||
participate in the development of Gopeed.
|
|
||||||
|
|
||||||
## Branch description
|
|
||||||
|
|
||||||
This project only has one main branch, namely the `main` branch. If you want to participate in the
|
|
||||||
development of Gopeed, please fork this project first, and then develop in your fork project. After
|
|
||||||
development is completed, submit a PR to this project and merge it into the `main` branch.
|
|
||||||
|
|
||||||
## Local development
|
|
||||||
|
|
||||||
It is recommended to develop and debug through the web. First, start the backend service, and start
|
|
||||||
it by the command line `go run cmd/api/main.go`, the default port of the service is `9999`, and then
|
|
||||||
start the front-end flutter project in `debug` mode to run.
|
|
||||||
|
|
||||||
## Translation
|
|
||||||
|
|
||||||
The internationalization files of Gopeed are located in the `ui/flutter/lib/i18n/langs` directory.
|
|
||||||
You only need to add the corresponding language file in this directory.
|
|
||||||
|
|
||||||
Please refer to `en_us.dart` for translation.
|
|
||||||
words prefixed with `@` are not meant to be translated.
|
|
||||||
|
|
||||||
## flutter development
|
|
||||||
|
|
||||||
Don't forget to run`dart format ./ui/flutter`before you commit to keep your code in standard dart format
|
|
||||||
|
|
||||||
Turn on build_runner watcher if you want to edit api/models:
|
|
||||||
|
|
||||||
```
|
|
||||||
flutter pub run build_runner watch
|
|
||||||
```
|
|
||||||
@@ -1,33 +0,0 @@
|
|||||||
# Gopeed コントリビューターガイド
|
|
||||||
|
|
||||||
まず最初に、Gopeed への貢献に興味を持っていただきありがとうございます。このガイドは、あなたが Gopeed の
|
|
||||||
開発に参加するための手助けとなるでしょう。
|
|
||||||
|
|
||||||
## ブランチの説明
|
|
||||||
|
|
||||||
このプロジェクトのメインブランチは `main` ブランチのみです。Gopeed の開発に参加したい場合は、
|
|
||||||
まずこのプロジェクトをフォークし、フォークしたプロジェクトで開発を行ってください。開発が完了したら、
|
|
||||||
このプロジェクトに PR を提出し、`main` ブランチにマージしてください。
|
|
||||||
|
|
||||||
## ローカル開発
|
|
||||||
|
|
||||||
開発およびデバッグはウェブ上で行うことを推奨する。まずバックエンドのサービスを起動し、
|
|
||||||
コマンドライン `go run cmd/api/main.go` で起動する。サービスのデフォルトポートは `9999` で、
|
|
||||||
次にフロントエンドの flutter プロジェクトを `debug` モードで起動して実行します。
|
|
||||||
|
|
||||||
## 翻訳
|
|
||||||
|
|
||||||
Gopeed の国際化ファイルは `ui/flutter/lib/i18n/langs` ディレクトリにあります。
|
|
||||||
このディレクトリに対応する言語ファイルを追加するだけでよいです。
|
|
||||||
|
|
||||||
翻訳については `en_us.dart` を参照してください。
|
|
||||||
|
|
||||||
## flutter での開発
|
|
||||||
|
|
||||||
コミットする前に `dart format ./ui/flutter` を実行し、コードを標準の dart フォーマットにしておくことを忘れないでください
|
|
||||||
|
|
||||||
api/models を編集したい場合は build_runner watcher をオンにします:
|
|
||||||
|
|
||||||
```
|
|
||||||
flutter pub run build_runner watch
|
|
||||||
```
|
|
||||||
@@ -1,29 +0,0 @@
|
|||||||
# Hướng dẫn đóng góp cho Gopeed
|
|
||||||
|
|
||||||
Trước tiên, cảm ơn bạn đã quan tâm đến việc đóng góp cho Gopeed. Hướng dẫn này sẽ giúp bạn tham gia
|
|
||||||
phát triển Gopeed một cách tốt hơn.
|
|
||||||
|
|
||||||
## Mô tả nhánh
|
|
||||||
|
|
||||||
Dự án này chỉ có một nhánh chính duy nhất, đó là nhánh `main`. Nếu bạn muốn tham gia vào
|
|
||||||
phát triển Gopeed, hãy fork dự án này trước, sau đó phát triển trong dự án fork của bạn. Sau khi
|
|
||||||
hoàn thành phát triển, gửi một PR đến dự án này và merge vào nhánh `main`.
|
|
||||||
|
|
||||||
## Phát triển cục bộ
|
|
||||||
|
|
||||||
Đề nghị phát triển và gỡ lỗi thông qua web. Đầu tiên, khởi động dịch vụ backend bằng cách chạy
|
|
||||||
lệnh `go run cmd/api/main.go` trong dòng lệnh, cổng mặc định của dịch vụ là `9999`, sau đó
|
|
||||||
khởi động dự án flutter frontend trong chế độ `debug` để chạy.
|
|
||||||
|
|
||||||
## Dịch thuật
|
|
||||||
|
|
||||||
Các tệp quốc tế hóa của Gopeed được đặt trong thư mục `ui/flutter/lib/i18n/langs`.
|
|
||||||
Bạn chỉ cần thêm tệp ngôn ngữ tương ứng trong thư mục này.
|
|
||||||
|
|
||||||
Vui lòng tham khảo `en_us.dart` để biết cách dịch thuật.
|
|
||||||
|
|
||||||
## Phát triển flutter
|
|
||||||
|
|
||||||
Đừng quên chạy `dart format ./ui/flutter` trước khi commit để giữ mã của bạn theo định dạng dart chuẩn.
|
|
||||||
|
|
||||||
Bật build_runner watcher nếu bạn muốn chỉnh sửa api/models:
|
|
||||||
@@ -1,30 +0,0 @@
|
|||||||
# Gopeed 贡献指南
|
|
||||||
|
|
||||||
首先感谢您对贡献代码感兴趣,这份指南将帮助您更好的参与到 Gopeed 的开发中来。
|
|
||||||
|
|
||||||
## 分支说明
|
|
||||||
|
|
||||||
本项目只有一个主分支,即 `main` 分支,如果您想要参与到 Gopeed 的开发中来,请先 fork 本项目,然后在您的 fork 项目中进行开发,开发完成后再向本项目提交
|
|
||||||
PR,合并到 `main` 分支。
|
|
||||||
|
|
||||||
## 本地开发
|
|
||||||
|
|
||||||
建议通过 web 端进行开发调试,首先启动后端服务,通过命令行 `go run cmd/api/main.go` 启动 ,服务启动默认端口为 `9999`,然后以 `debug` 模式启动前端
|
|
||||||
flutter 项目即可运行。
|
|
||||||
|
|
||||||
## 翻译
|
|
||||||
|
|
||||||
Gopeed 的国际化文件位于 `ui/flutter/lib/i18n/langs` 目录下,只需要在该目录下添加对应的语言文件即可。
|
|
||||||
|
|
||||||
请注意以 `en_us.dart` 为参照进行翻译。
|
|
||||||
|
|
||||||
## flutter开发
|
|
||||||
|
|
||||||
每次提交前请务必`dart format ./ui/flutter`
|
|
||||||
|
|
||||||
如果要编辑api/models,请打开build_runner watcher:
|
|
||||||
|
|
||||||
```
|
|
||||||
flutter pub run build_runner watch
|
|
||||||
```
|
|
||||||
|
|
||||||
@@ -1,28 +0,0 @@
|
|||||||
# Gopeed 協助指南
|
|
||||||
|
|
||||||
首先感謝您願意幫助我們改進並優化該項目,這份指南將會幫助您更好的參與 Gopeed 的開發。
|
|
||||||
|
|
||||||
## 分支說明
|
|
||||||
|
|
||||||
本項目只有一個分支,即 `main` 分支,如果您想要參與 Gopeed 的開發,請先 fork 該項目,再在您自己的 fork 中進行開發,開發完成後再開啟PR,以合併至 `main` 分支。
|
|
||||||
|
|
||||||
## 離線開發
|
|
||||||
|
|
||||||
建議使用 web 端進行開發與調試,首先啟動服務,使用指令 `go run cmd/api/main.go` 啟動 ,該服務默認連接埠為 `9999`,接著以 `debug` 模式啟動前端 flutter 項目即可。
|
|
||||||
|
|
||||||
## 翻譯
|
|
||||||
|
|
||||||
Gopeed 的翻譯文件位於 `ui/flutter/lib/i18n/langs` 目錄中,只需要修改或新建翻譯文件即可。
|
|
||||||
|
|
||||||
|
|
||||||
請以 `en_us.dart` 作為參照。
|
|
||||||
|
|
||||||
## flutter開發
|
|
||||||
|
|
||||||
每次提交PR前請務必執行 `dart format ./ui/flutter`
|
|
||||||
|
|
||||||
如果需要編輯 api/models,請打開build_runner watcher:
|
|
||||||
|
|
||||||
```
|
|
||||||
flutter pub run build_runner watch
|
|
||||||
```
|
|
||||||
-23
@@ -1,23 +0,0 @@
|
|||||||
FROM golang:1.23.3 AS go
|
|
||||||
WORKDIR /app
|
|
||||||
COPY ./go.mod ./go.sum ./
|
|
||||||
RUN go mod download
|
|
||||||
COPY . .
|
|
||||||
ARG VERSION=dev
|
|
||||||
RUN CGO_ENABLED=0 go build -tags nosqlite,web \
|
|
||||||
-ldflags="-s -w -X github.com/GopeedLab/gopeed/pkg/base.Version=$VERSION -X github.com/GopeedLab/gopeed/pkg/base.InDocker=true" \
|
|
||||||
-o dist/gopeed github.com/GopeedLab/gopeed/cmd/web
|
|
||||||
|
|
||||||
FROM alpine:3.18
|
|
||||||
LABEL maintainer="monkeyWie"
|
|
||||||
WORKDIR /app
|
|
||||||
COPY --from=go /app/dist/gopeed ./
|
|
||||||
COPY entrypoint.sh ./entrypoint.sh
|
|
||||||
RUN apk update && \
|
|
||||||
apk add --no-cache su-exec ; \
|
|
||||||
chmod +x ./entrypoint.sh && \
|
|
||||||
rm -rf /var/cache/apk/*
|
|
||||||
VOLUME ["/app/storage"]
|
|
||||||
ENV PUID=0 PGID=0 UMASK=022
|
|
||||||
EXPOSE 9999
|
|
||||||
ENTRYPOINT ["./entrypoint.sh"]
|
|
||||||
@@ -1,217 +1,20 @@
|
|||||||
# [](https://gopeed.com)
|
## gopeed
|
||||||
|
支持多协议(HTTP、BitTorrent)下载的客户端,提供命令行、RESTful API、WebSocket、Go类库方式来使用。
|
||||||
|
|
||||||
[](https://github.com/GopeedLab/gopeed/actions?query=workflow%3Atest)
|
## TODO
|
||||||
[](https://codecov.io/gh/GopeedLab/gopeed)
|
- [x] HTTP下载实现
|
||||||
[](https://github.com/GopeedLab/gopeed/releases)
|
- [ ] BitTorrent下载实现
|
||||||
[](https://github.com/GopeedLab/gopeed/releases)
|
- [x] .torrent文件解析
|
||||||
[](https://docs.gopeed.com/donate.html)
|
- [x] tracker协议实现
|
||||||
[](https://discord.gg/ZUJqJrwCGB)
|
- [x] peer wire protocol协议实现
|
||||||
|
- [ ] DHT协议实现
|
||||||
|
- [ ] 磁力链接支持
|
||||||
|
- [ ] uTP协议实现
|
||||||
|
- [ ] 下载接口抽象(不关心具体协议)
|
||||||
|
- [ ] 支持自定义配置
|
||||||
|
- [ ] 限速功能实现
|
||||||
|
- [ ] 命令行工具提供
|
||||||
|
- [ ] RESTful服务提供
|
||||||
|
|
||||||
<a href="https://trendshift.io/repositories/7953" target="_blank"><img src="https://trendshift.io/api/badge/repositories/7953" alt="GopeedLab%2Fgopeed | Trendshift" style="width: 250px; height: 55px;" width="250" height="55"/></a>
|
## 参与
|
||||||
|
由于项目目前还未定型,代码可能随时有大的调整,所以暂不接受PR,当然如果有什么好的想法可以在issue区提出来。
|
||||||
[](https://ko-fi.com/R6R6IJGN6)
|
|
||||||
|
|
||||||
[English](/README.md) | [中文](/README_zh-CN.md) | [日本語](/README_ja-JP.md) | [正體中文](/README_zh-TW.md) | [Tiếng Việt](/README_vi-VN.md)
|
|
||||||
|
|
||||||
## Introduction
|
|
||||||
|
|
||||||
Gopeed (full name Go Speed), a high-speed downloader developed by `Golang` + `Flutter`, supports (HTTP, BitTorrent, Magnet) protocol, and supports all platforms. In addition to basic download functions, Gopeed is also a highly customizable downloader that supports implementing more features through integration with [APIs](https://docs.gopeed.com/dev-api.html) or installation and development of [extensions](https://docs.gopeed.com/dev-extension.html).
|
|
||||||
|
|
||||||
Visit ✈ [Official Website](https://gopeed.com) | 📖 [Official Docs](https://docs.gopeed.com)
|
|
||||||
|
|
||||||
## Download
|
|
||||||
|
|
||||||
<table>
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th>Platform</th>
|
|
||||||
<th>Package Type</th>
|
|
||||||
<th>Download Link</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
<tr>
|
|
||||||
<td rowspan=2>Windows</td>
|
|
||||||
<td><code>EXE Installer</code></td>
|
|
||||||
<td><a href="https://gopeed.com/api/download?tpl=Gopeed-$version-windows-amd64.zip">Link</a></td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td><code>Portable ZIP</code></td>
|
|
||||||
<td><a href="https://gopeed.com/api/download?tpl=Gopeed-$version-windows-amd64-portable.zip">Link</a></td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>MacOS</td>
|
|
||||||
<td><code>DMG Installer</code></td>
|
|
||||||
<td><a href="https://gopeed.com/api/download?tpl=Gopeed-$version-macos.dmg">Link</a></td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td rowspan=4>Linux</td>
|
|
||||||
<td><code>Flathub</code></td>
|
|
||||||
<td><a href="https://flathub.org/apps/com.gopeed.Gopeed">Link</a></td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td><code>SNAP</code></td>
|
|
||||||
<td><a href="https://snapcraft.io/gopeed">Link</a></td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td><code>DEB</code></td>
|
|
||||||
<td><a href="https://gopeed.com/api/download?tpl=Gopeed-$version-linux-amd64.deb">Link</a></td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td><code>AppImage</code></td>
|
|
||||||
<td><a href="https://gopeed.com/api/download?tpl=Gopeed-$version-linux-x86_64.AppImage">Link</a></td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>Android</td>
|
|
||||||
<td><code>APK</code></td>
|
|
||||||
<td><a href="https://gopeed.com/api/download?tpl=Gopeed-$version-android.apk">Link</a></td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>iOS</td>
|
|
||||||
<td><code>IPA</code></td>
|
|
||||||
<td><a href="https://gopeed.com/api/download?tpl=Gopeed-$version-ios.ipa">Link</a></td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>Web</td>
|
|
||||||
<td></td>
|
|
||||||
<td><a href="https://github.com/GopeedLab/gopeed/releases/latest">Link</a></td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>Docker</td>
|
|
||||||
<td></td>
|
|
||||||
<td><a href="https://hub.docker.com/r/liwei2633/gopeed">Link</a></td>
|
|
||||||
</tr>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
|
|
||||||
More about installation, please refer to [Installation](https://docs.gopeed.com/install.html)
|
|
||||||
|
|
||||||
### Command tool
|
|
||||||
|
|
||||||
use `go install`:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
go install github.com/GopeedLab/gopeed/cmd/gopeed@latest
|
|
||||||
```
|
|
||||||
|
|
||||||
## Browser Extension
|
|
||||||
|
|
||||||
Gopeed also provides a browser extension to take over browser downloads, supporting browsers such as Chrome, Edge, Firefox, etc., please refer to: [https://github.com/GopeedLab/browser-extension](https://github.com/GopeedLab/browser-extension)
|
|
||||||
|
|
||||||
## Donate
|
|
||||||
|
|
||||||
If you like this project, please consider [donating](https://docs.gopeed.com/donate.html) to support the development of this project, thank you!
|
|
||||||
|
|
||||||
## Showcase
|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
## Development
|
|
||||||
|
|
||||||
This project is divided into two parts, the front end uses `flutter`, the back end uses `Golang`, and the two sides communicate through the `http` protocol. On the unix system, `unix socket` is used, and on the windows system, `tcp` protocol is used.
|
|
||||||
|
|
||||||
> The front code is located in the `ui/flutter` directory.
|
|
||||||
|
|
||||||
### Environment
|
|
||||||
|
|
||||||
1. Golang 1.23+
|
|
||||||
2. Flutter 3.16+
|
|
||||||
|
|
||||||
### Clone
|
|
||||||
|
|
||||||
```bash
|
|
||||||
git clone [email protected]:GopeedLab/gopeed.git
|
|
||||||
```
|
|
||||||
|
|
||||||
### Contributing
|
|
||||||
|
|
||||||
Please refer to [CONTRIBUTING.md](/CONTRIBUTING.md)
|
|
||||||
|
|
||||||
### Build
|
|
||||||
|
|
||||||
#### Desktop
|
|
||||||
|
|
||||||
First, you need to configure the environment according to the official [Flutter desktop website documention](https://docs.flutter.dev/development/platform-integration/desktop), then you will need to ensure the cgo environment is set up accordingly. For detailed instructions on setting up the cgo environment, please refer to relevant resources available online.
|
|
||||||
|
|
||||||
command:
|
|
||||||
|
|
||||||
- windows
|
|
||||||
|
|
||||||
```bash
|
|
||||||
go build -tags nosqlite -ldflags="-w -s" -buildmode=c-shared -o ui/flutter/windows/libgopeed.dll github.com/GopeedLab/gopeed/bind/desktop
|
|
||||||
cd ui/flutter
|
|
||||||
flutter build windows
|
|
||||||
```
|
|
||||||
|
|
||||||
- macos
|
|
||||||
|
|
||||||
```bash
|
|
||||||
go build -tags nosqlite -ldflags="-w -s" -buildmode=c-shared -o ui/flutter/macos/Frameworks/libgopeed.dylib github.com/GopeedLab/gopeed/bind/desktop
|
|
||||||
cd ui/flutter
|
|
||||||
flutter build macos
|
|
||||||
```
|
|
||||||
|
|
||||||
- linux
|
|
||||||
|
|
||||||
```bash
|
|
||||||
go build -tags nosqlite -ldflags="-w -s" -buildmode=c-shared -o ui/flutter/linux/bundle/lib/libgopeed.so github.com/GopeedLab/gopeed/bind/desktop
|
|
||||||
cd ui/flutter
|
|
||||||
flutter build linux
|
|
||||||
```
|
|
||||||
|
|
||||||
#### Mobile
|
|
||||||
|
|
||||||
Same as before, you also need to prepare the `cgo` environment, and then install `gomobile`:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
go install golang.org/x/mobile/cmd/gomobile@latest
|
|
||||||
go get golang.org/x/mobile/bind
|
|
||||||
gomobile init
|
|
||||||
```
|
|
||||||
|
|
||||||
command:
|
|
||||||
|
|
||||||
- android
|
|
||||||
|
|
||||||
```bash
|
|
||||||
gomobile bind -tags nosqlite -ldflags="-w -s" -o ui/flutter/android/app/libs/libgopeed.aar -target=android -androidapi 21 -javapkg="com.gopeed" github.com/GopeedLab/gopeed/bind/mobile
|
|
||||||
cd ui/flutter
|
|
||||||
flutter build apk
|
|
||||||
```
|
|
||||||
|
|
||||||
- ios
|
|
||||||
|
|
||||||
```bash
|
|
||||||
gomobile bind -tags nosqlite -ldflags="-w -s" -o ui/flutter/ios/Frameworks/Libgopeed.xcframework -target=ios github.com/GopeedLab/gopeed/bind/mobile
|
|
||||||
cd ui/flutter
|
|
||||||
flutter build ios --no-codesign
|
|
||||||
```
|
|
||||||
|
|
||||||
#### Web
|
|
||||||
|
|
||||||
command:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
cd ui/flutter
|
|
||||||
flutter build web
|
|
||||||
cd ../../
|
|
||||||
rm -rf cmd/web/dist
|
|
||||||
cp -r ui/flutter/build/web cmd/web/dist
|
|
||||||
go build -tags nosqlite,web -ldflags="-s -w" -o bin/ github.com/GopeedLab/gopeed/cmd/web
|
|
||||||
```
|
|
||||||
|
|
||||||
## Credits
|
|
||||||
|
|
||||||
### Contributors
|
|
||||||
|
|
||||||
<a href="https://github.com/GopeedLab/gopeed/graphs/contributors">
|
|
||||||
<img src="https://contrib.rocks/image?repo=GopeedLab/gopeed" />
|
|
||||||
</a>
|
|
||||||
|
|
||||||
### JetBrains
|
|
||||||
|
|
||||||
[](https://www.jetbrains.com/?from=gopeed)
|
|
||||||
|
|
||||||
## License
|
|
||||||
|
|
||||||
[GPLv3](LICENSE)
|
|
||||||
-205
@@ -1,205 +0,0 @@
|
|||||||
# [](https://gopeed.com)
|
|
||||||
|
|
||||||
[](https://github.com/GopeedLab/gopeed/actions?query=workflow%3Atest)
|
|
||||||
[](https://codecov.io/gh/GopeedLab/gopeed)
|
|
||||||
[](https://github.com/GopeedLab/gopeed/releases)
|
|
||||||
[](https://github.com/GopeedLab/gopeed/releases)
|
|
||||||
[](https://docs.gopeed.com/donate.html)
|
|
||||||
[](https://discord.gg/ZUJqJrwCGB)
|
|
||||||
|
|
||||||
<a href="https://trendshift.io/repositories/7953" target="_blank"><img src="https://trendshift.io/api/badge/repositories/7953" alt="GopeedLab%2Fgopeed | Trendshift" style="width: 250px; height: 55px;" width="250" height="55"/></a>
|
|
||||||
|
|
||||||
[](https://ko-fi.com/R6R6IJGN6)
|
|
||||||
|
|
||||||
[English](/README.md) | [中文](/README_zh-CN.md) | [日本語](/README_ja-JP.md) | [正體中文](/README_zh-TW.md) | [Tiếng Việt](/README_vi-VN.md)
|
|
||||||
|
|
||||||
## はじめに
|
|
||||||
|
|
||||||
Gopeed (正式名 Go Speed) は `Golang` + `Flutter` によって開発された高速ダウンローダーで、(HTTP、BitTorrent、Magnet) プロトコルをサポートし、すべてのプラットフォームをサポートします。基本的なダウンロード機能に加え、[APIs](https://docs.gopeed.com/dev-api.html)との連動や[拡張機能](https://docs.gopeed.com/dev-extension.html)のインストール・開発による追加機能にも対応した、カスタマイズ性の高いダウンローダーです。
|
|
||||||
|
|
||||||
見て下さい ✈ [公式ウェブサイト](https://gopeed.com) | 📖 [開発ドキュメント](https://docs.gopeed.com)
|
|
||||||
|
|
||||||
## インストール
|
|
||||||
|
|
||||||
<table>
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th>Platform</th>
|
|
||||||
<th>Package Type</th>
|
|
||||||
<th>Download Link</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
<tr>
|
|
||||||
<td rowspan=2>Windows</td>
|
|
||||||
<td><code>EXE Installer</code></td>
|
|
||||||
<td><a href="https://gopeed.com/api/download?tpl=Gopeed-$version-windows-amd64.zip">Link</a></td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td><code>Portable ZIP</code></td>
|
|
||||||
<td><a href="https://gopeed.com/api/download?tpl=Gopeed-$version-windows-amd64-portable.zip">Link</a></td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>MacOS</td>
|
|
||||||
<td><code>DMG Installer</code></td>
|
|
||||||
<td><a href="https://gopeed.com/api/download?tpl=Gopeed-$version-macos.dmg">Link</a></td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td rowspan=4>Linux</td>
|
|
||||||
<td><code>Flathub</code></td>
|
|
||||||
<td><a href="https://flathub.org/apps/com.gopeed.Gopeed">Link</a></td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td><code>SNAP</code></td>
|
|
||||||
<td><a href="https://snapcraft.io/gopeed">Link</a></td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td><code>DEB</code></td>
|
|
||||||
<td><a href="https://gopeed.com/api/download?tpl=Gopeed-$version-linux-amd64.deb">Link</a></td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td><code>AppImage</code></td>
|
|
||||||
<td><a href="https://gopeed.com/api/download?tpl=Gopeed-$version-linux-x86_64.AppImage">Link</a></td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>Android</td>
|
|
||||||
<td><code>APK</code></td>
|
|
||||||
<td><a href="https://gopeed.com/api/download?tpl=Gopeed-$version-android.apk">Link</a></td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>iOS</td>
|
|
||||||
<td><code>IPA</code></td>
|
|
||||||
<td><a href="https://gopeed.com/api/download?tpl=Gopeed-$version-ios.ipa">Link</a></td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>Web</td>
|
|
||||||
<td></td>
|
|
||||||
<td><a href="https://github.com/GopeedLab/gopeed/releases/latest">Link</a></td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>Docker</td>
|
|
||||||
<td></td>
|
|
||||||
<td><a href="https://hub.docker.com/r/liwei2633/gopeed">Link</a></td>
|
|
||||||
</tr>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
|
|
||||||
インストールについての詳細は、[インストール](https://docs.gopeed.com/install.html)を参照してください。
|
|
||||||
|
|
||||||
## 寄付
|
|
||||||
|
|
||||||
もしこのプロジェクトがお気に召しましたら、このプロジェクトの発展を支援するために[寄付](https://docs.gopeed.com/donate.html)をご検討ください!
|
|
||||||
|
|
||||||
## ショーケース
|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
## 開発
|
|
||||||
|
|
||||||
このプロジェクトは二つの部分に分かれており、フロントエンドでは `flutter` を、バックエンドでは `Golang` を使用し、両者は `http` プロトコルで通信する。ユニックスシステムでは `unix socket` を、ウィンドウズシステムでは `tcp` プロトコルを使用します。
|
|
||||||
|
|
||||||
> フロントコードは `ui/flutter` ディレクトリにあります。
|
|
||||||
|
|
||||||
### 環境
|
|
||||||
|
|
||||||
1. Go 言語 1.23+
|
|
||||||
2. Flutter 3.16+
|
|
||||||
|
|
||||||
### クローン
|
|
||||||
|
|
||||||
```bash
|
|
||||||
git clone [email protected]:GopeedLab/gopeed.git
|
|
||||||
```
|
|
||||||
|
|
||||||
### コントリビュート
|
|
||||||
|
|
||||||
[CONTRIBUTING.md](/CONTRIBUTING_ja-JP.md) をご参照ください
|
|
||||||
|
|
||||||
### ビルド
|
|
||||||
|
|
||||||
#### デスクトップ
|
|
||||||
|
|
||||||
まず、[flutter デスクトップ公式サイトドキュメント](https://docs.flutter.dev/development/platform-integration/desktop)に従って環境を設定し、自分で検索できる `cgo` 環境を用意します。
|
|
||||||
|
|
||||||
コマンド:
|
|
||||||
|
|
||||||
- windows
|
|
||||||
|
|
||||||
```bash
|
|
||||||
go build -tags nosqlite -ldflags="-w -s" -buildmode=c-shared -o ui/flutter/windows/libgopeed.dll github.com/GopeedLab/gopeed/bind/desktop
|
|
||||||
cd ui/flutter
|
|
||||||
flutter build windows
|
|
||||||
```
|
|
||||||
|
|
||||||
- macos
|
|
||||||
|
|
||||||
```bash
|
|
||||||
go build -tags nosqlite -ldflags="-w -s" -buildmode=c-shared -o ui/flutter/macos/Frameworks/libgopeed.dylib github.com/GopeedLab/gopeed/bind/desktop
|
|
||||||
cd ui/flutter
|
|
||||||
flutter build macos
|
|
||||||
```
|
|
||||||
|
|
||||||
- linux
|
|
||||||
|
|
||||||
```bash
|
|
||||||
go build -tags nosqlite -ldflags="-w -s" -buildmode=c-shared -o ui/flutter/linux/bundle/lib/libgopeed.so github.com/GopeedLab/gopeed/bind/desktop
|
|
||||||
cd ui/flutter
|
|
||||||
flutter build linux
|
|
||||||
```
|
|
||||||
|
|
||||||
#### モバイル
|
|
||||||
|
|
||||||
先ほどと同じように、`cgo` 環境を準備し、`gomobile` をインストールする必要があります:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
go install golang.org/x/mobile/cmd/gomobile@latest
|
|
||||||
go get golang.org/x/mobile/bind
|
|
||||||
gomobile init
|
|
||||||
```
|
|
||||||
|
|
||||||
コマンド:
|
|
||||||
|
|
||||||
- android
|
|
||||||
|
|
||||||
```bash
|
|
||||||
gomobile bind -tags nosqlite -ldflags="-w -s" -o ui/flutter/android/app/libs/libgopeed.aar -target=android -androidapi 21 -javapkg="com.gopeed" github.com/GopeedLab/gopeed/bind/mobile
|
|
||||||
cd ui/flutter
|
|
||||||
flutter build apk
|
|
||||||
```
|
|
||||||
|
|
||||||
- ios
|
|
||||||
|
|
||||||
```bash
|
|
||||||
gomobile bind -tags nosqlite -ldflags="-w -s" -o ui/flutter/ios/Frameworks/Libgopeed.xcframework -target=ios github.com/GopeedLab/gopeed/bind/mobile
|
|
||||||
cd ui/flutter
|
|
||||||
flutter build ios --no-codesign
|
|
||||||
```
|
|
||||||
|
|
||||||
#### Web
|
|
||||||
|
|
||||||
コマンド:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
cd ui/flutter
|
|
||||||
flutter build web
|
|
||||||
cd ../../
|
|
||||||
rm -rf cmd/web/dist
|
|
||||||
cp -r ui/flutter/build/web cmd/web/dist
|
|
||||||
go build -tags nosqlite,web -ldflags="-s -w" -o bin/ github.com/GopeedLab/gopeed/cmd/web
|
|
||||||
```
|
|
||||||
|
|
||||||
## 感謝
|
|
||||||
|
|
||||||
### コントリビューター
|
|
||||||
|
|
||||||
<a href="https://github.com/GopeedLab/gopeed/graphs/contributors">
|
|
||||||
<img src="https://contrib.rocks/image?repo=GopeedLab/gopeed" />
|
|
||||||
</a>
|
|
||||||
|
|
||||||
### JetBrains
|
|
||||||
|
|
||||||
[](https://www.jetbrains.com/?from=gopeed)
|
|
||||||
|
|
||||||
## ライセンス
|
|
||||||
|
|
||||||
[GPLv3](LICENSE)
|
|
||||||
-213
@@ -1,213 +0,0 @@
|
|||||||
# [](https://gopeed.com)
|
|
||||||
|
|
||||||
[](https://github.com/GopeedLab/gopeed/actions?query=workflow%3Atest)
|
|
||||||
[](https://codecov.io/gh/GopeedLab/gopeed)
|
|
||||||
[](https://github.com/GopeedLab/gopeed/releases)
|
|
||||||
[](https://github.com/GopeedLab/gopeed/releases)
|
|
||||||
[](https://docs.gopeed.com/donate.html)
|
|
||||||
[](https://discord.gg/ZUJqJrwCGB)
|
|
||||||
|
|
||||||
<a href="https://trendshift.io/repositories/7953" target="_blank"><img src="https://trendshift.io/api/badge/repositories/7953" alt="GopeedLab%2Fgopeed | Trendshift" style="width: 250px; height: 55px;" width="250" height="55"/></a>
|
|
||||||
|
|
||||||
[](https://ko-fi.com/R6R6IJGN6)
|
|
||||||
|
|
||||||
[English](/README.md) | [中文](/README_zh-CN.md) | [日本語](/README_ja-JP.md) | [正體中文](/README_zh-TW.md) | [Tiếng Việt](/README_vi-VN.md)
|
|
||||||
|
|
||||||
## Giới thiệu
|
|
||||||
|
|
||||||
Gopeed (tên đầy đủ Go Speed), một công cụ tải xuống tốc độ cao được phát triển bởi `Golang` + `Flutter`, hỗ trợ giao thức (HTTP, BitTorrent, Magnet) và hỗ trợ tất cả các nền tảng. Ngoài các chức năng tải xuống cơ bản, Gopeed còn là một công cụ tải xuống có thể tùy chỉnh cao cho phép triển khai thêm tính năng thông qua việc tích hợp với [APIs](https://docs.gopeed.com/dev-api.html) hoặc cài đặt và phát triển các [tiện ích mở rộng](https://docs.gopeed.com/dev-extension.html).
|
|
||||||
|
|
||||||
Truy cập ✈ [Trang web chính thức](https://gopeed.com) | 📖 [Tài liệu chính thức](https://docs.gopeed.com)
|
|
||||||
|
|
||||||
## Tải về
|
|
||||||
|
|
||||||
<table>
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th>Nền tảng</th>
|
|
||||||
<th>Loại gói</th>
|
|
||||||
<th>Liên kết tải xuống</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
<tr>
|
|
||||||
<td rowspan=2>Windows</td>
|
|
||||||
<td><code>Bộ cài đặt EXE</code></td>
|
|
||||||
<td><a href="https://gopeed.com/api/download?tpl=Gopeed-$version-windows-amd64.zip">Liên kết</a></td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td><code>ZIP Portable</code></td>
|
|
||||||
<td><a href="https://gopeed.com/api/download?tpl=Gopeed-$version-windows-amd64-portable.zip">Liên kết</a></td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>MacOS</td>
|
|
||||||
<td><code>Bộ cài đặt DMG</code></td>
|
|
||||||
<td><a href="https://gopeed.com/api/download?tpl=Gopeed-$version-macos.dmg">Liên kết</a></td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td rowspan=4>Linux</td>
|
|
||||||
<td><code>Flathub</code></td>
|
|
||||||
<td><a href="https://flathub.org/apps/com.gopeed.Gopeed">Liên kết</a></td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td><code>SNAP</code></td>
|
|
||||||
<td><a href="https://snapcraft.io/gopeed">Liên kết</a></td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td><code>DEB</code></td>
|
|
||||||
<td><a href="https://gopeed.com/api/download?tpl=Gopeed-$version-linux-amd64.deb">Liên kết</a></td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td><code>AppImage</code></td>
|
|
||||||
<td><a href="https://gopeed.com/api/download?tpl=Gopeed-$version-linux-x86_64.AppImage">Liên kết</a></td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>Android</td>
|
|
||||||
<td><code>APK</code></td>
|
|
||||||
<td><a href="https://gopeed.com/api/download?tpl=Gopeed-$version-android.apk">Liên kết</a></td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>iOS</td>
|
|
||||||
<td><code>IPA</code></td>
|
|
||||||
<td><a href="https://gopeed.com/api/download?tpl=Gopeed-$version-ios.ipa">Liên kết</a></td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>Web</td>
|
|
||||||
<td></td>
|
|
||||||
<td><a href="https://github.com/GopeedLab/gopeed/releases/latest">Liên kết</a></td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>Docker</td>
|
|
||||||
<td></td>
|
|
||||||
<td><a href="https://hub.docker.com/r/liwei2633/gopeed">Liên kết</a></td>
|
|
||||||
</tr>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
|
|
||||||
Thêm thông tin về cài đặt, vui lòng tham khảo [Cài đặt](https://docs.gopeed.com/install.html)
|
|
||||||
|
|
||||||
### Command tool
|
|
||||||
|
|
||||||
Sử dụng `go install`:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
go install github.com/GopeedLab/gopeed/cmd/gopeed@latest
|
|
||||||
```
|
|
||||||
|
|
||||||
## Quyên góp
|
|
||||||
|
|
||||||
Nếu bạn thích dự án này, xin vui lòng xem xét [quyên góp](https://docs.gopeed.com/donate.html) để hỗ trợ phát triển dự án này, cảm ơn bạn!
|
|
||||||
|
|
||||||
## Trưng bày
|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
## Development
|
|
||||||
|
|
||||||
Dự án này được chia thành hai phần, phần giao diện sử dụng `flutter`, phần backend sử dụng `Golang`, và hai phía giao tiếp thông qua giao thức `http`. Trên hệ thống unix, sử dụng `unix socket`, và trên hệ thống windows, sử dụng giao thức `tcp`.
|
|
||||||
|
|
||||||
> Mã giao diện nằm trong thư mục `ui/flutter`.
|
|
||||||
|
|
||||||
### Environment
|
|
||||||
|
|
||||||
1. Golang 1.23+
|
|
||||||
2. Flutter 3.16+
|
|
||||||
|
|
||||||
### Clone
|
|
||||||
|
|
||||||
```bash
|
|
||||||
git clone [email protected]:GopeedLab/gopeed.git
|
|
||||||
```
|
|
||||||
|
|
||||||
### Đóng góp
|
|
||||||
|
|
||||||
Vui lòng tham khảo [CONTRIBUTING_vi-VN.md](/CONTRIBUTING_vi-VN.md)
|
|
||||||
|
|
||||||
### Xây dựng
|
|
||||||
|
|
||||||
#### Desktop
|
|
||||||
|
|
||||||
Trước tiên, bạn cần cấu hình môi trường theo tài liệu chính thức của [Tài liệu trang web máy tính để bàn Flutter](https://docs.flutter.dev/development/platform-integration/desktop), sau đó bạn cần đảm bảo môi trường cgo được thiết lập đúng. Để biết hướng dẫn chi tiết về cách thiết lập môi trường cgo, vui lòng tham khảo các tài liệu tương ứng có sẵn trực tuyến.
|
|
||||||
|
|
||||||
command:
|
|
||||||
|
|
||||||
- windows
|
|
||||||
|
|
||||||
```bash
|
|
||||||
go build -tags nosqlite -ldflags="-w -s" -buildmode=c-shared -o ui/flutter/windows/libgopeed.dll github.com/GopeedLab/gopeed/bind/desktop
|
|
||||||
cd ui/flutter
|
|
||||||
flutter build windows
|
|
||||||
```
|
|
||||||
|
|
||||||
- macos
|
|
||||||
|
|
||||||
```bash
|
|
||||||
go build -tags nosqlite -ldflags="-w -s" -buildmode=c-shared -o ui/flutter/macos/Frameworks/libgopeed.dylib github.com/GopeedLab/gopeed/bind/desktop
|
|
||||||
cd ui/flutter
|
|
||||||
flutter build macos
|
|
||||||
```
|
|
||||||
|
|
||||||
- linux
|
|
||||||
|
|
||||||
```bash
|
|
||||||
go build -tags nosqlite -ldflags="-w -s" -buildmode=c-shared -o ui/flutter/linux/bundle/lib/libgopeed.so github.com/GopeedLab/gopeed/bind/desktop
|
|
||||||
cd ui/flutter
|
|
||||||
flutter build linux
|
|
||||||
```
|
|
||||||
|
|
||||||
#### Mobile
|
|
||||||
|
|
||||||
Giống như trước đây, bạn cũng cần chuẩn bị môi trường `cgo` và sau đó cài đặt `gomobile`:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
go install golang.org/x/mobile/cmd/gomobile@latest
|
|
||||||
go get golang.org/x/mobile/bind
|
|
||||||
gomobile init
|
|
||||||
```
|
|
||||||
|
|
||||||
command:
|
|
||||||
|
|
||||||
- android
|
|
||||||
|
|
||||||
```bash
|
|
||||||
gomobile bind -tags nosqlite -ldflags="-w -s" -o ui/flutter/android/app/libs/libgopeed.aar -target=android -androidapi 21 -javapkg="com.gopeed" github.com/GopeedLab/gopeed/bind/mobile
|
|
||||||
cd ui/flutter
|
|
||||||
flutter build apk
|
|
||||||
```
|
|
||||||
|
|
||||||
- ios
|
|
||||||
|
|
||||||
```bash
|
|
||||||
gomobile bind -tags nosqlite -ldflags="-w -s" -o ui/flutter/ios/Frameworks/Libgopeed.xcframework -target=ios github.com/GopeedLab/gopeed/bind/mobile
|
|
||||||
cd ui/flutter
|
|
||||||
flutter build ios --no-codesign
|
|
||||||
```
|
|
||||||
|
|
||||||
#### Web
|
|
||||||
|
|
||||||
command:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
cd ui/flutter
|
|
||||||
flutter build web
|
|
||||||
cd ../../
|
|
||||||
rm -rf cmd/web/dist
|
|
||||||
cp -r ui/flutter/build/web cmd/web/dist
|
|
||||||
go build -tags nosqlite,web -ldflags="-s -w" -o bin/ github.com/GopeedLab/gopeed/cmd/web
|
|
||||||
```
|
|
||||||
|
|
||||||
## Tín dụng
|
|
||||||
|
|
||||||
### Người đóng góp
|
|
||||||
|
|
||||||
<a href="https://github.com/GopeedLab/gopeed/graphs/contributors">
|
|
||||||
<img src="https://contrib.rocks/image?repo=GopeedLab/gopeed" />
|
|
||||||
</a>
|
|
||||||
|
|
||||||
### JetBrains
|
|
||||||
|
|
||||||
[](https://www.jetbrains.com/?from=gopeed)
|
|
||||||
|
|
||||||
## Giấy phép
|
|
||||||
|
|
||||||
[GPLv3](LICENSE)
|
|
||||||
-217
@@ -1,217 +0,0 @@
|
|||||||
# [](https://gopeed.com)
|
|
||||||
|
|
||||||
[](https://github.com/GopeedLab/gopeed/actions?query=workflow%3Atest)
|
|
||||||
[](https://codecov.io/gh/GopeedLab/gopeed)
|
|
||||||
[](https://github.com/GopeedLab/gopeed/releases)
|
|
||||||
[](https://github.com/GopeedLab/gopeed/releases)
|
|
||||||
[](https://docs.gopeed.com/zh/donate.html)
|
|
||||||
[](https://discord.gg/ZUJqJrwCGB)
|
|
||||||
|
|
||||||
<a href="https://trendshift.io/repositories/7953" target="_blank"><img src="https://trendshift.io/api/badge/repositories/7953" alt="GopeedLab%2Fgopeed | Trendshift" style="width: 250px; height: 55px;" width="250" height="55"/></a>
|
|
||||||
|
|
||||||
[](https://ko-fi.com/R6R6IJGN6)
|
|
||||||
|
|
||||||
[English](/README.md) | [中文](/README_zh-CN.md) | [日本語](/README_ja-JP.md) | [正體中文](/README_zh-TW.md) | [Tiếng Việt](/README_vi-VN.md)
|
|
||||||
|
|
||||||
## 介绍
|
|
||||||
|
|
||||||
Gopeed(全称 Go Speed),直译过来中文名叫做`够快下载器`(不是狗屁下载器!),是一款由`Golang`+`Flutter`开发的高速下载器,支持(HTTP、BitTorrent、Magnet)协议下载,并且支持全平台使用。除了基本的下载功能外,Gopeed 还是一款高度可定制化的下载器,支持通过对接[APIs](https://docs.gopeed.com/zh/dev-api.html)或者安装和开发[扩展](https://docs.gopeed.com/zh/dev-extension.html)来实现更多的功能。
|
|
||||||
|
|
||||||
访问 ✈ [官方网站](https://gopeed.com/zh-CN) | 📖 [官方文档](https://docs.gopeed.com/zh/)
|
|
||||||
|
|
||||||
## 下载
|
|
||||||
|
|
||||||
<table>
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th>运行平台</th>
|
|
||||||
<th>安装包类型</th>
|
|
||||||
<th>下载链接</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
<tr>
|
|
||||||
<td rowspan=2>Windows</td>
|
|
||||||
<td><code>EXE Installer</code></td>
|
|
||||||
<td><a href="https://gopeed.com/api/download?tpl=Gopeed-$version-windows-amd64.zip">前往</a></td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td><code>Portable ZIP</code></td>
|
|
||||||
<td><a href="https://gopeed.com/api/download?tpl=Gopeed-$version-windows-amd64-portable.zip">前往</a></td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>MacOS</td>
|
|
||||||
<td><code>DMG Installer</code></td>
|
|
||||||
<td><a href="https://gopeed.com/api/download?tpl=Gopeed-$version-macos.dmg">前往</a></td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td rowspan=4>Linux</td>
|
|
||||||
<td><code>Flathub</code></td>
|
|
||||||
<td><a href="https://flathub.org/apps/com.gopeed.Gopeed">前往</a></td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td><code>SNAP</code></td>
|
|
||||||
<td><a href="https://snapcraft.io/gopeed">前往</a></td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td><code>DEB</code></td>
|
|
||||||
<td><a href="https://gopeed.com/api/download?tpl=Gopeed-$version-linux-amd64.deb">前往</a></td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td><code>AppImage</code></td>
|
|
||||||
<td><a href="https://gopeed.com/api/download?tpl=Gopeed-$version-linux-x86_64.AppImage">前往</a></td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>Android</td>
|
|
||||||
<td><code>APK</code></td>
|
|
||||||
<td><a href="https://gopeed.com/api/download?tpl=Gopeed-$version-android.apk">前往</a></td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>iOS</td>
|
|
||||||
<td><code>IPA</code></td>
|
|
||||||
<td><a href="https://gopeed.com/api/download?tpl=Gopeed-$version-ios.ipa">前往</a></td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>Web</td>
|
|
||||||
<td></td>
|
|
||||||
<td><a href="https://github.com/GopeedLab/gopeed/releases/latest">前往</a></td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>Docker</td>
|
|
||||||
<td></td>
|
|
||||||
<td><a href="https://hub.docker.com/r/liwei2633/gopeed">前往</a></td>
|
|
||||||
</tr>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
|
|
||||||
更多关于安装的内容请参考[安装文档](https://docs.gopeed.com/zh/install.html)
|
|
||||||
|
|
||||||
### 命令行工具
|
|
||||||
|
|
||||||
使用`go install`安装:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
go install github.com/GopeedLab/gopeed/cmd/gopeed@latest
|
|
||||||
```
|
|
||||||
|
|
||||||
## 浏览器扩展
|
|
||||||
|
|
||||||
Gopeed 还提供了浏览器扩展用于接管浏览器下载,支持 Chrome、Edge、Firefox 等浏览器,具体请参考:[https://github.com/GopeedLab/browser-extension](https://github.com/GopeedLab/browser-extension)
|
|
||||||
|
|
||||||
## 赞助
|
|
||||||
|
|
||||||
如果觉得项目对你有帮助,请考虑[赞助](https://docs.gopeed.com/zh/donate)以支持这个项目的发展,非常感谢!
|
|
||||||
|
|
||||||
## 界面展示
|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
## 开发
|
|
||||||
|
|
||||||
本项目分为前端和后端两个部分,前端使用`flutter`,后端使用`Golang`,两边通过`http`协议进行通讯,在 unix 系统下,使用的是`unix socket`,在 windows 系统下,使用的是`tcp`协议。
|
|
||||||
|
|
||||||
> 前端代码位于`ui/flutter`目录下。
|
|
||||||
|
|
||||||
### 环境要求
|
|
||||||
|
|
||||||
1. Golang 1.23+
|
|
||||||
2. Flutter 3.16+
|
|
||||||
|
|
||||||
### 克隆项目
|
|
||||||
|
|
||||||
```bash
|
|
||||||
git clone [email protected]:GopeedLab/gopeed.git
|
|
||||||
```
|
|
||||||
|
|
||||||
### 贡献代码
|
|
||||||
|
|
||||||
请参考[贡献指南](CONTRIBUTING_zh-CN.md)
|
|
||||||
|
|
||||||
### 编译
|
|
||||||
|
|
||||||
#### 桌面端
|
|
||||||
|
|
||||||
首先需要按照[flutter desktop 官网文档](https://docs.flutter.dev/development/platform-integration/desktop)进行环境配置,然后需要准备好`cgo`环境,具体可以自行搜索。
|
|
||||||
|
|
||||||
构建命令:
|
|
||||||
|
|
||||||
- windows
|
|
||||||
|
|
||||||
```bash
|
|
||||||
go build -tags nosqlite -ldflags="-w -s" -buildmode=c-shared -o ui/flutter/windows/libgopeed.dll github.com/GopeedLab/gopeed/bind/desktop
|
|
||||||
cd ui/flutter
|
|
||||||
flutter build windows
|
|
||||||
```
|
|
||||||
|
|
||||||
- macos
|
|
||||||
|
|
||||||
```bash
|
|
||||||
go build -tags nosqlite -ldflags="-w -s" -buildmode=c-shared -o ui/flutter/macos/Frameworks/libgopeed.dylib github.com/GopeedLab/gopeed/bind/desktop
|
|
||||||
cd ui/flutter
|
|
||||||
flutter build macos
|
|
||||||
```
|
|
||||||
|
|
||||||
- linux
|
|
||||||
|
|
||||||
```bash
|
|
||||||
go build -tags nosqlite -ldflags="-w -s" -buildmode=c-shared -o ui/flutter/linux/bundle/lib/libgopeed.so github.com/GopeedLab/gopeed/bind/desktop
|
|
||||||
cd ui/flutter
|
|
||||||
flutter build linux
|
|
||||||
```
|
|
||||||
|
|
||||||
#### 移动端
|
|
||||||
|
|
||||||
同样的也是需要准备好`cgo`环境,接着安装`gomobile`:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
go install golang.org/x/mobile/cmd/gomobile@latest
|
|
||||||
go get golang.org/x/mobile/bind
|
|
||||||
gomobile init
|
|
||||||
```
|
|
||||||
|
|
||||||
构建命令:
|
|
||||||
|
|
||||||
- android
|
|
||||||
|
|
||||||
```bash
|
|
||||||
gomobile bind -tags nosqlite -ldflags="-w -s" -o ui/flutter/android/app/libs/libgopeed.aar -target=android -androidapi 21 -javapkg="com.gopeed" github.com/GopeedLab/gopeed/bind/mobile
|
|
||||||
cd ui/flutter
|
|
||||||
flutter build apk
|
|
||||||
```
|
|
||||||
|
|
||||||
- ios
|
|
||||||
|
|
||||||
```bash
|
|
||||||
gomobile bind -tags nosqlite -ldflags="-w -s" -o ui/flutter/ios/Frameworks/Libgopeed.xcframework -target=ios github.com/GopeedLab/gopeed/bind/mobile
|
|
||||||
cd ui/flutter
|
|
||||||
flutter build ios --no-codesign
|
|
||||||
```
|
|
||||||
|
|
||||||
#### Web 端
|
|
||||||
|
|
||||||
构建命令:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
cd ui/flutter
|
|
||||||
flutter build web
|
|
||||||
cd ../../
|
|
||||||
rm -rf cmd/web/dist
|
|
||||||
cp -r ui/flutter/build/web cmd/web/dist
|
|
||||||
go build -tags nosqlite,web -ldflags="-s -w" -o bin/ github.com/GopeedLab/gopeed/cmd/web
|
|
||||||
```
|
|
||||||
|
|
||||||
## 感谢
|
|
||||||
|
|
||||||
### 贡献者
|
|
||||||
|
|
||||||
<a href="https://github.com/GopeedLab/gopeed/graphs/contributors">
|
|
||||||
<img src="https://contrib.rocks/image?repo=GopeedLab/gopeed" />
|
|
||||||
</a>
|
|
||||||
|
|
||||||
### JetBrains
|
|
||||||
|
|
||||||
[](https://www.jetbrains.com/?from=gopeed)
|
|
||||||
|
|
||||||
## 开源许可
|
|
||||||
|
|
||||||
基于 [GPLv3](LICENSE) 协议开源。
|
|
||||||
-213
@@ -1,213 +0,0 @@
|
|||||||
# [](https://gopeed.com)
|
|
||||||
|
|
||||||
[](https://github.com/GopeedLab/gopeed/actions?query=workflow%3Atest)
|
|
||||||
[](https://codecov.io/gh/GopeedLab/gopeed)
|
|
||||||
[](https://github.com/GopeedLab/gopeed/releases)
|
|
||||||
[](https://github.com/GopeedLab/gopeed/releases)
|
|
||||||
[](https://docs.gopeed.com/donate.html)
|
|
||||||
[](https://discord.gg/ZUJqJrwCGB)
|
|
||||||
|
|
||||||
<a href="https://trendshift.io/repositories/7953" target="_blank"><img src="https://trendshift.io/api/badge/repositories/7953" alt="GopeedLab%2Fgopeed | Trendshift" style="width: 250px; height: 55px;" width="250" height="55"/></a>
|
|
||||||
|
|
||||||
[](https://ko-fi.com/R6R6IJGN6)
|
|
||||||
|
|
||||||
[English](/README.md) | [中文](/README_zh-CN.md) | [日本語](/README_ja-JP.md) | [正體中文](/README_zh-TW.md) | [Tiếng Việt](/README_vi-VN.md)
|
|
||||||
|
|
||||||
## 簡介
|
|
||||||
|
|
||||||
Gopeed(全稱 Go Speed),是一款使用`Golang`+`Flutter`編寫的高速下載軟體,支援(HTTP、BitTorrent、Magnet)協定,同時支援所有的平台。
|
|
||||||
|
|
||||||
前往 ✈ [主頁](https://gopeed.com/zh-CN) | 📖 [文檔](https://docs.gopeed.com/zh/)
|
|
||||||
|
|
||||||
## 下載
|
|
||||||
|
|
||||||
<table>
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th>運行平台</th>
|
|
||||||
<th>安裝包類型</th>
|
|
||||||
<th>下載鏈接</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
<tr>
|
|
||||||
<td rowspan=2>Windows</td>
|
|
||||||
<td><code>EXE Installer</code></td>
|
|
||||||
<td><a href="https://gopeed.com/api/download?tpl=Gopeed-$version-windows-amd64.zip">前往</a></td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td><code>Portable ZIP</code></td>
|
|
||||||
<td><a href="https://gopeed.com/api/download?tpl=Gopeed-$version-windows-amd64-portable.zip">前往</a></td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>MacOS</td>
|
|
||||||
<td><code>DMG Installer</code></td>
|
|
||||||
<td><a href="https://gopeed.com/api/download?tpl=Gopeed-$version-macos.dmg">前往</a></td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td rowspan=4>Linux</td>
|
|
||||||
<td><code>Flathub</code></td>
|
|
||||||
<td><a href="https://flathub.org/apps/com.gopeed.Gopeed">前往</a></td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td><code>SNAP</code></td>
|
|
||||||
<td><a href="https://snapcraft.io/gopeed">前往</a></td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td><code>DEB</code></td>
|
|
||||||
<td><a href="https://gopeed.com/api/download?tpl=Gopeed-$version-linux-amd64.deb">前往</a></td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td><code>AppImage</code></td>
|
|
||||||
<td><a href="https://gopeed.com/api/download?tpl=Gopeed-$version-linux-x86_64.AppImage">前往</a></td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>Android</td>
|
|
||||||
<td><code>APK</code></td>
|
|
||||||
<td><a href="https://gopeed.com/api/download?tpl=Gopeed-$version-android.apk">前往</a></td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>iOS</td>
|
|
||||||
<td><code>IPA</code></td>
|
|
||||||
<td><a href="https://gopeed.com/api/download?tpl=Gopeed-$version-ios.ipa">前往</a></td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>Web</td>
|
|
||||||
<td></td>
|
|
||||||
<td><a href="https://github.com/GopeedLab/gopeed/releases/latest">前往</a></td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>Docker</td>
|
|
||||||
<td></td>
|
|
||||||
<td><a href="https://hub.docker.com/r/liwei2633/gopeed">前往</a></td>
|
|
||||||
</tr>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
|
|
||||||
更多關於安裝的內容請參考[安裝文檔](https://docs.gopeed.com/zh/install.html)
|
|
||||||
|
|
||||||
### 使用CLI安裝
|
|
||||||
|
|
||||||
使用`go install`安裝:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
go install github.com/GopeedLab/gopeed/cmd/gopeed@latest
|
|
||||||
```
|
|
||||||
|
|
||||||
## 贊助
|
|
||||||
|
|
||||||
如果你認為該項目對你有所幫助,請考慮[贊助](https://docs.gopeed.com/zh/donate)以支持該項目的持續發展,謝謝!
|
|
||||||
|
|
||||||
## 軟體介面
|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
## 開發
|
|
||||||
|
|
||||||
該項目分為前端與後端,前端使用`flutter`編寫,後端使用`Golang`編寫,兩邊通過`http`協定進行通訊,在 unix 系統下,則使用`unix socket`,在 windows 系統下,則使用`tcp`協定。
|
|
||||||
|
|
||||||
> 前端代碼位於`ui/flutter`目錄內。
|
|
||||||
|
|
||||||
### 開發環境
|
|
||||||
|
|
||||||
1. Golang 1.23+
|
|
||||||
2. Flutter 3.16+
|
|
||||||
|
|
||||||
### 克隆項目
|
|
||||||
|
|
||||||
```bash
|
|
||||||
git clone [email protected]:GopeedLab/gopeed.git
|
|
||||||
```
|
|
||||||
|
|
||||||
### 協助開發
|
|
||||||
|
|
||||||
請參考[協助指南](CONTRIBUTING_zh-TW.md)
|
|
||||||
|
|
||||||
### 編譯
|
|
||||||
|
|
||||||
#### 桌面端
|
|
||||||
|
|
||||||
首先需要按照[flutter desktop 官方文檔](https://docs.flutter.dev/development/platform-integration/desktop)配置開發環境,並準備好`cgo`環境,具體方法可以自行搜索。
|
|
||||||
|
|
||||||
組建指令:
|
|
||||||
|
|
||||||
- windows
|
|
||||||
|
|
||||||
```bash
|
|
||||||
go build -tags nosqlite -ldflags="-w -s" -buildmode=c-shared -o ui/flutter/windows/libgopeed.dll github.com/GopeedLab/gopeed/bind/desktop
|
|
||||||
cd ui/flutter
|
|
||||||
flutter build windows
|
|
||||||
```
|
|
||||||
|
|
||||||
- macos
|
|
||||||
|
|
||||||
```bash
|
|
||||||
go build -tags nosqlite -ldflags="-w -s" -buildmode=c-shared -o ui/flutter/macos/Frameworks/libgopeed.dylib github.com/GopeedLab/gopeed/bind/desktop
|
|
||||||
cd ui/flutter
|
|
||||||
flutter build macos
|
|
||||||
```
|
|
||||||
|
|
||||||
- linux
|
|
||||||
|
|
||||||
```bash
|
|
||||||
go build -tags nosqlite -ldflags="-w -s" -buildmode=c-shared -o ui/flutter/linux/bundle/lib/libgopeed.so github.com/GopeedLab/gopeed/bind/desktop
|
|
||||||
cd ui/flutter
|
|
||||||
flutter build linux
|
|
||||||
```
|
|
||||||
|
|
||||||
#### 移動設備
|
|
||||||
|
|
||||||
需要`cgo`環境,並安裝`gomobile`:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
go install golang.org/x/mobile/cmd/gomobile@latest
|
|
||||||
go get golang.org/x/mobile/bind
|
|
||||||
gomobile init
|
|
||||||
```
|
|
||||||
|
|
||||||
組建指令:
|
|
||||||
|
|
||||||
- android
|
|
||||||
|
|
||||||
```bash
|
|
||||||
gomobile bind -tags nosqlite -ldflags="-w -s" -o ui/flutter/android/app/libs/libgopeed.aar -target=android -androidapi 21 -javapkg="com.gopeed" github.com/GopeedLab/gopeed/bind/mobile
|
|
||||||
cd ui/flutter
|
|
||||||
flutter build apk
|
|
||||||
```
|
|
||||||
|
|
||||||
- ios
|
|
||||||
|
|
||||||
```bash
|
|
||||||
gomobile bind -tags nosqlite -ldflags="-w -s" -o ui/flutter/ios/Frameworks/Libgopeed.xcframework -target=ios github.com/GopeedLab/gopeed/bind/mobile
|
|
||||||
cd ui/flutter
|
|
||||||
flutter build ios --no-codesign
|
|
||||||
```
|
|
||||||
|
|
||||||
#### 網頁端
|
|
||||||
|
|
||||||
組建指令:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
cd ui/flutter
|
|
||||||
flutter build web
|
|
||||||
cd ../../
|
|
||||||
rm -rf cmd/web/dist
|
|
||||||
cp -r ui/flutter/build/web cmd/web/dist
|
|
||||||
go build -tags nosqlite,web -ldflags="-s -w" -o bin/ github.com/GopeedLab/gopeed/cmd/web
|
|
||||||
```
|
|
||||||
|
|
||||||
## 感謝
|
|
||||||
|
|
||||||
### 貢獻者
|
|
||||||
|
|
||||||
<a href="https://github.com/GopeedLab/gopeed/graphs/contributors">
|
|
||||||
<img src="https://contrib.rocks/image?repo=GopeedLab/gopeed" />
|
|
||||||
</a>
|
|
||||||
|
|
||||||
### JetBrains
|
|
||||||
|
|
||||||
[](https://www.jetbrains.com/?from=gopeed)
|
|
||||||
|
|
||||||
## 軟體許可
|
|
||||||
|
|
||||||
該軟體遵循 [GPLv3](LICENSE) 。
|
|
||||||
Binary file not shown.
|
Before Width: | Height: | Size: 51 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 12 KiB |
@@ -1 +0,0 @@
|
|||||||
<svg height="105" viewBox="0 0 105 105" width="105" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><linearGradient id="a" gradientUnits="userSpaceOnUse" x1="99.03" x2="61.54" y1="59.18" y2="90.91"><stop offset="0" stop-color="#087cfa"/><stop offset=".02" stop-color="#0d7bfa"/><stop offset=".37" stop-color="#5566f9"/><stop offset=".66" stop-color="#8a57f8"/><stop offset=".88" stop-color="#ab4ef7"/><stop offset="1" stop-color="#b74af7"/></linearGradient><linearGradient id="b" x1="37.54" x2="60.33" xlink:href="#a" y1="34.26" y2="8.33"/><linearGradient id="c" gradientUnits="userSpaceOnUse" x1="17.84" x2="87.09" y1="88.36" y2="43.86"><stop offset="0" stop-color="#087cfa"/><stop offset=".1" stop-color="#1598d3"/><stop offset=".22" stop-color="#23b6aa"/><stop offset=".35" stop-color="#2dcc8b"/><stop offset=".46" stop-color="#35dd74"/><stop offset=".57" stop-color="#39e767"/><stop offset=".67" stop-color="#3bea62"/></linearGradient><path d="m89.06 41.63 11.44 25.37-19.58 33.5-12.06-29.28z" fill="url(#a)"/><path d="m68.86 71.22 12.06 29.28-30.34-10.43z" fill="#b74af7"/><path d="m72.13 31.61-6.22-27.11h-34.49l-26.92 41.18 7.79 18.92-7.79 17.27 55.75-47.43z" fill="url(#b)"/><path d="m100.5 24.88-40.25 9.56-55.75 47.43 35.96 18.63 28.4-29.28z" fill="url(#c)"/><path d="m22.5 22.5h60v60h-60z"/><g fill="#fff"><path d="m28.13 71.25h22.5v3.75h-22.5z"/><path d="m26.44 42.81v-.07a12.7 12.7 0 0 1 12.97-12.74 13.62 13.62 0 0 1 9.73 3.39l-3.43 4.14a9.13 9.13 0 0 0 -6.47-2.53c-4 0-7.11 3.5-7.11 7.7v.07c0 4.53 3.11 7.85 7.5 7.85a8.67 8.67 0 0 0 5.12-1.49v-3.56h-5.48v-4.7h10.73v10.74a16.07 16.07 0 0 1 -10.57 3.93c-7.69 0-12.99-5.41-12.99-12.73z"/><path d="m52.3 42.81v-.07a12.79 12.79 0 0 1 13.19-12.74c7.63 0 13.11 5.69 13.11 12.72v.07a12.79 12.79 0 0 1 -13.18 12.8c-7.64-.05-13.12-5.74-13.12-12.78zm20.61 0v-.07a7.51 7.51 0 0 0 -7.49-7.74 7.4 7.4 0 0 0 -7.42 7.67v.07a7.52 7.52 0 0 0 7.5 7.78 7.4 7.4 0 0 0 7.41-7.71z"/></g></svg>
|
|
||||||
|
Before Width: | Height: | Size: 1.9 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 309 KiB |
@@ -1,33 +0,0 @@
|
|||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"github.com/GopeedLab/gopeed/pkg/base"
|
|
||||||
"github.com/GopeedLab/gopeed/pkg/download"
|
|
||||||
"github.com/GopeedLab/gopeed/pkg/protocol/http"
|
|
||||||
)
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
finallyCh := make(chan error)
|
|
||||||
_, err := download.Boot().
|
|
||||||
URL("https://www.baidu.com/index.html").
|
|
||||||
Listener(func(event *download.Event) {
|
|
||||||
if event.Key == download.EventKeyFinally {
|
|
||||||
finallyCh <- event.Err
|
|
||||||
}
|
|
||||||
}).
|
|
||||||
Create(&base.Options{
|
|
||||||
Extra: http.OptsExtra{
|
|
||||||
Connections: 8,
|
|
||||||
},
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
err = <-finallyCh
|
|
||||||
if err != nil {
|
|
||||||
fmt.Printf("download fail:%v\n", err)
|
|
||||||
} else {
|
|
||||||
fmt.Println("download success")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,41 +0,0 @@
|
|||||||
package bind
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/json"
|
|
||||||
"errors"
|
|
||||||
"github.com/GopeedLab/gopeed/pkg/api"
|
|
||||||
"github.com/GopeedLab/gopeed/pkg/api/model"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Global singleton instance
|
|
||||||
var instance *api.Instance
|
|
||||||
|
|
||||||
func Init(config *model.StartConfig) (err error) {
|
|
||||||
if instance != nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
config.ProductionMode = true
|
|
||||||
instance, err = api.Create(config)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func Invoke(request *api.Request) string {
|
|
||||||
if instance == nil {
|
|
||||||
return BuildResult(errors.New("instance not initialized"))
|
|
||||||
}
|
|
||||||
return jsonEncode(api.Invoke(instance, request))
|
|
||||||
}
|
|
||||||
|
|
||||||
func BuildResult(data any) string {
|
|
||||||
if err, ok := data.(error); ok {
|
|
||||||
buf, _ := json.Marshal(model.NewErrorResult[any](err.Error()))
|
|
||||||
return string(buf)
|
|
||||||
}
|
|
||||||
return jsonEncode(model.NewOkResult(data))
|
|
||||||
}
|
|
||||||
|
|
||||||
func jsonEncode(data any) string {
|
|
||||||
buf, _ := json.Marshal(data)
|
|
||||||
return string(buf)
|
|
||||||
}
|
|
||||||
@@ -1,34 +0,0 @@
|
|||||||
package main
|
|
||||||
|
|
||||||
import "C"
|
|
||||||
import (
|
|
||||||
"encoding/json"
|
|
||||||
"github.com/GopeedLab/gopeed/bind"
|
|
||||||
"github.com/GopeedLab/gopeed/pkg/api"
|
|
||||||
"github.com/GopeedLab/gopeed/pkg/api/model"
|
|
||||||
)
|
|
||||||
|
|
||||||
func main() {}
|
|
||||||
|
|
||||||
//export Init
|
|
||||||
func Init(cfg *C.char) *C.char {
|
|
||||||
var config model.StartConfig
|
|
||||||
if err := json.Unmarshal([]byte(C.GoString(cfg)), &config); err != nil {
|
|
||||||
return C.CString(err.Error())
|
|
||||||
}
|
|
||||||
if err := bind.Init(&config); err != nil {
|
|
||||||
return C.CString(err.Error())
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
//export Invoke
|
|
||||||
func Invoke(req *C.char) *C.char {
|
|
||||||
var request api.Request
|
|
||||||
if err := json.Unmarshal([]byte(C.GoString(req)), &request); err != nil {
|
|
||||||
return C.CString(bind.BuildResult(err))
|
|
||||||
}
|
|
||||||
|
|
||||||
return C.CString(bind.Invoke(&request))
|
|
||||||
}
|
|
||||||
@@ -1,17 +0,0 @@
|
|||||||
package libgopeed
|
|
||||||
|
|
||||||
// #cgo LDFLAGS: -static-libstdc++
|
|
||||||
import "C"
|
|
||||||
import (
|
|
||||||
"github.com/GopeedLab/gopeed/bind"
|
|
||||||
"github.com/GopeedLab/gopeed/pkg/api"
|
|
||||||
"github.com/GopeedLab/gopeed/pkg/api/model"
|
|
||||||
)
|
|
||||||
|
|
||||||
func Init(cfg *model.StartConfig) error {
|
|
||||||
return bind.Init(cfg)
|
|
||||||
}
|
|
||||||
|
|
||||||
func Invoke(request *api.Request) string {
|
|
||||||
return bind.Invoke(request)
|
|
||||||
}
|
|
||||||
@@ -1,23 +0,0 @@
|
|||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/GopeedLab/gopeed/cmd"
|
|
||||||
"github.com/GopeedLab/gopeed/pkg/api/model"
|
|
||||||
"github.com/GopeedLab/gopeed/pkg/base"
|
|
||||||
)
|
|
||||||
|
|
||||||
// only for local development
|
|
||||||
func main() {
|
|
||||||
cfg := &model.StartConfig{
|
|
||||||
Storage: model.StorageBolt,
|
|
||||||
DownloadConfig: &base.DownloaderStoreConfig{
|
|
||||||
Http: &base.DownloaderHttpConfig{
|
|
||||||
Enable: true,
|
|
||||||
Host: "127.0.0.1",
|
|
||||||
Port: 9999,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
WebEnable: true,
|
|
||||||
}
|
|
||||||
cmd.Start(cfg)
|
|
||||||
}
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
|
|
||||||
_______ ______ .______ _______ _______ _______
|
|
||||||
/ _____| / __ \ | _ \ | ____|| ____|| \
|
|
||||||
| | __ | | | | | |_) | | |__ | |__ | .--. |
|
|
||||||
| | |_ | | | | | | ___/ | __| | __| | | | |
|
|
||||||
| |__| | | `--' | | | | |____ | |____ | '--' |
|
|
||||||
\______| \______/ | _| |_______||_______||_______/
|
|
||||||
@@ -1,41 +0,0 @@
|
|||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"flag"
|
|
||||||
"fmt"
|
|
||||||
"os"
|
|
||||||
)
|
|
||||||
|
|
||||||
type args struct {
|
|
||||||
url string
|
|
||||||
connections *int
|
|
||||||
dir *string
|
|
||||||
}
|
|
||||||
|
|
||||||
func parse() *args {
|
|
||||||
dir, err := os.Getwd()
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
var args args
|
|
||||||
args.connections = flag.Int("C", 16, "Concurrent connections.")
|
|
||||||
args.dir = flag.String("D", dir, "Store directory.")
|
|
||||||
flag.Parse()
|
|
||||||
t := flag.Args()
|
|
||||||
if len(t) > 0 {
|
|
||||||
args.url = t[0]
|
|
||||||
} else {
|
|
||||||
gPrintln("missing url parameter, for example: gopeed https://www.google.com or gopeed bt.torrent or gopeed magnet:?xt=urn:btih:...")
|
|
||||||
gPrintln("try 'gopeed -h' for more information")
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
return &args
|
|
||||||
}
|
|
||||||
|
|
||||||
func gPrint(msg string) {
|
|
||||||
fmt.Print("gopeed: " + msg)
|
|
||||||
}
|
|
||||||
|
|
||||||
func gPrintln(msg string) {
|
|
||||||
gPrint(msg + "\n")
|
|
||||||
}
|
|
||||||
@@ -1,97 +0,0 @@
|
|||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"github.com/GopeedLab/gopeed/internal/fetcher"
|
|
||||||
"github.com/GopeedLab/gopeed/pkg/base"
|
|
||||||
"github.com/GopeedLab/gopeed/pkg/download"
|
|
||||||
"github.com/GopeedLab/gopeed/pkg/protocol/http"
|
|
||||||
"github.com/GopeedLab/gopeed/pkg/util"
|
|
||||||
"strings"
|
|
||||||
"sync"
|
|
||||||
)
|
|
||||||
|
|
||||||
const progressWidth = 20
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
args := parse()
|
|
||||||
|
|
||||||
var wg sync.WaitGroup
|
|
||||||
wg.Add(1)
|
|
||||||
_, err := download.Boot().
|
|
||||||
URL(args.url).
|
|
||||||
Listener(func(event *download.Event) {
|
|
||||||
if event.Key == download.EventKeyProgress {
|
|
||||||
printProgress(event.Task, "downloading...")
|
|
||||||
}
|
|
||||||
if event.Key == download.EventKeyFinally {
|
|
||||||
var title string
|
|
||||||
if event.Err != nil {
|
|
||||||
title = "fail"
|
|
||||||
} else {
|
|
||||||
title = "complete"
|
|
||||||
}
|
|
||||||
printProgress(event.Task, title)
|
|
||||||
fmt.Println()
|
|
||||||
if event.Err != nil {
|
|
||||||
fmt.Printf("reason: %s", event.Err.Error())
|
|
||||||
} else {
|
|
||||||
fmt.Printf("saving path: %s", *args.dir)
|
|
||||||
}
|
|
||||||
wg.Done()
|
|
||||||
}
|
|
||||||
}).
|
|
||||||
Create(&base.Options{
|
|
||||||
Path: *args.dir,
|
|
||||||
Extra: http.OptsExtra{Connections: *args.connections},
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
printProgress(emptyTask, "downloading...")
|
|
||||||
wg.Wait()
|
|
||||||
}
|
|
||||||
|
|
||||||
var (
|
|
||||||
lastLineLen = 0
|
|
||||||
sb = new(strings.Builder)
|
|
||||||
emptyTask = &download.Task{
|
|
||||||
Progress: &download.Progress{},
|
|
||||||
Meta: &fetcher.FetcherMeta{
|
|
||||||
Res: &base.Resource{},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
func printProgress(task *download.Task, title string) {
|
|
||||||
var rate float64
|
|
||||||
if task.Meta.Res == nil {
|
|
||||||
task = emptyTask
|
|
||||||
}
|
|
||||||
if task.Meta.Res.Size <= 0 {
|
|
||||||
rate = 0
|
|
||||||
} else {
|
|
||||||
rate = float64(task.Progress.Downloaded) / float64(task.Meta.Res.Size)
|
|
||||||
}
|
|
||||||
completeWidth := int(progressWidth * rate)
|
|
||||||
speed := util.ByteFmt(task.Progress.Speed)
|
|
||||||
totalSize := util.ByteFmt(task.Meta.Res.Size)
|
|
||||||
sb.WriteString(fmt.Sprintf("\r%s [", title))
|
|
||||||
for i := 0; i < progressWidth; i++ {
|
|
||||||
if i < completeWidth {
|
|
||||||
sb.WriteString("■")
|
|
||||||
} else {
|
|
||||||
sb.WriteString("□")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
sb.WriteString(fmt.Sprintf("] %.1f%% %s/s %s", rate*100, speed, totalSize))
|
|
||||||
if lastLineLen != 0 {
|
|
||||||
paddingLen := lastLineLen - sb.Len()
|
|
||||||
if paddingLen > 0 {
|
|
||||||
sb.WriteString(strings.Repeat(" ", paddingLen))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
lastLineLen = sb.Len()
|
|
||||||
fmt.Print(sb.String())
|
|
||||||
sb.Reset()
|
|
||||||
}
|
|
||||||
+28
@@ -0,0 +1,28 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/monkeyWie/gopeed-core/download"
|
||||||
|
"github.com/monkeyWie/gopeed-core/download/common"
|
||||||
|
"github.com/monkeyWie/gopeed-core/download/http"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
downloader := buildDownloader()
|
||||||
|
res, err := downloader.Resolve(&common.Request{
|
||||||
|
URL: "http://192.168.200.163:8088/docker-compose",
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
err = downloader.Create(res, &common.Options{
|
||||||
|
Path: "E:\\test\\gopeed\\http",
|
||||||
|
Connections: 4,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func buildDownloader() *download.Downloader {
|
||||||
|
return download.NewDownloader(&http.Fetcher{BaseFetcher: &common.BaseFetcher{}})
|
||||||
|
}
|
||||||
@@ -1,76 +0,0 @@
|
|||||||
package cmd
|
|
||||||
|
|
||||||
import (
|
|
||||||
_ "embed"
|
|
||||||
"fmt"
|
|
||||||
"github.com/GopeedLab/gopeed/pkg/api"
|
|
||||||
"github.com/GopeedLab/gopeed/pkg/api/model"
|
|
||||||
"github.com/GopeedLab/gopeed/pkg/base"
|
|
||||||
"os"
|
|
||||||
"os/signal"
|
|
||||||
"path/filepath"
|
|
||||||
"syscall"
|
|
||||||
)
|
|
||||||
|
|
||||||
//go:embed banner.txt
|
|
||||||
var banner string
|
|
||||||
|
|
||||||
func Start(cfg *model.StartConfig) {
|
|
||||||
fmt.Println(banner)
|
|
||||||
instance, err := api.Create(cfg)
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
downloadCfgResult := instance.GetConfig()
|
|
||||||
if downloadCfgResult.HasError() {
|
|
||||||
panic(downloadCfgResult.Msg)
|
|
||||||
}
|
|
||||||
downloadCfg := downloadCfgResult.Data
|
|
||||||
if downloadCfg.FirstLoad {
|
|
||||||
// Set default download config
|
|
||||||
if cfg.DownloadConfig != nil {
|
|
||||||
cfg.DownloadConfig.Merge(downloadCfg)
|
|
||||||
// TODO Use PatchConfig
|
|
||||||
instance.PutConfig(cfg.DownloadConfig)
|
|
||||||
downloadCfg = cfg.DownloadConfig
|
|
||||||
}
|
|
||||||
|
|
||||||
downloadDir := downloadCfg.DownloadDir
|
|
||||||
// Set default download dir, in docker, it will be ${exe}/Downloads, else it will be ${user}/Downloads
|
|
||||||
if downloadDir == "" {
|
|
||||||
if base.InDocker == "true" {
|
|
||||||
downloadDir = filepath.Join(filepath.Dir(cfg.StorageDir), "Downloads")
|
|
||||||
} else {
|
|
||||||
userDir, err := os.UserHomeDir()
|
|
||||||
if err == nil {
|
|
||||||
downloadDir = filepath.Join(userDir, "Downloads")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if downloadDir != "" {
|
|
||||||
downloadCfg.DownloadDir = downloadDir
|
|
||||||
instance.PutConfig(downloadCfg)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
watchExit(instance)
|
|
||||||
|
|
||||||
port, start, err := api.ListenHttp(cfg.DownloadConfig.Http, instance)
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
fmt.Printf("Server start success on http://%s:%d\n", cfg.DownloadConfig.Http.Host, port)
|
|
||||||
start()
|
|
||||||
}
|
|
||||||
|
|
||||||
func watchExit(instance *api.Instance) {
|
|
||||||
sigs := make(chan os.Signal, 1)
|
|
||||||
signal.Notify(sigs, syscall.SIGINT, syscall.SIGTERM)
|
|
||||||
go func() {
|
|
||||||
sig := <-sigs
|
|
||||||
fmt.Printf("Server is shutting down due to signal: %s\n", sig)
|
|
||||||
instance.Close()
|
|
||||||
os.Exit(0)
|
|
||||||
}()
|
|
||||||
}
|
|
||||||
@@ -1,84 +0,0 @@
|
|||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/json"
|
|
||||||
"flag"
|
|
||||||
"fmt"
|
|
||||||
"github.com/GopeedLab/gopeed/pkg/base"
|
|
||||||
"os"
|
|
||||||
"path/filepath"
|
|
||||||
)
|
|
||||||
|
|
||||||
type args struct {
|
|
||||||
Host *string `json:"host"`
|
|
||||||
Port *int `json:"port"`
|
|
||||||
Username *string `json:"username"`
|
|
||||||
Password *string `json:"password"`
|
|
||||||
ApiToken *string `json:"apiToken"`
|
|
||||||
StorageDir *string `json:"storageDir"`
|
|
||||||
// DownloadConfig when the first time to start the server, it will be configured as initial value
|
|
||||||
DownloadConfig *base.DownloaderStoreConfig `json:"downloadConfig"`
|
|
||||||
|
|
||||||
configPath *string
|
|
||||||
}
|
|
||||||
|
|
||||||
func parse() *args {
|
|
||||||
var cliArgs args
|
|
||||||
cliArgs.Host = flag.String("H", "0.0.0.0", "Bind Host")
|
|
||||||
cliArgs.Port = flag.Int("P", 9999, "Bind Port")
|
|
||||||
cliArgs.Username = flag.String("u", "gopeed", "HTTP Basic Auth Username")
|
|
||||||
cliArgs.Password = flag.String("p", "", "HTTP Basic Auth Pwd")
|
|
||||||
cliArgs.ApiToken = flag.String("T", "", "API token, it must be configured when using HTTP API in the case of enabling basic authentication")
|
|
||||||
cliArgs.StorageDir = flag.String("d", "", "Storage directory")
|
|
||||||
cliArgs.configPath = flag.String("c", "./config.json", "Config file path")
|
|
||||||
flag.Parse()
|
|
||||||
|
|
||||||
// args priority: config file > cli args
|
|
||||||
cfgArgs := loadConfig(*cliArgs.configPath)
|
|
||||||
if cfgArgs.Host == nil {
|
|
||||||
cfgArgs.Host = cliArgs.Host
|
|
||||||
}
|
|
||||||
if cfgArgs.Port == nil {
|
|
||||||
cfgArgs.Port = cliArgs.Port
|
|
||||||
}
|
|
||||||
if cfgArgs.Username == nil {
|
|
||||||
cfgArgs.Username = cliArgs.Username
|
|
||||||
}
|
|
||||||
if cfgArgs.Password == nil {
|
|
||||||
cfgArgs.Password = cliArgs.Password
|
|
||||||
}
|
|
||||||
if cfgArgs.ApiToken == nil {
|
|
||||||
cfgArgs.ApiToken = cliArgs.ApiToken
|
|
||||||
}
|
|
||||||
if cfgArgs.StorageDir == nil {
|
|
||||||
cfgArgs.StorageDir = cliArgs.StorageDir
|
|
||||||
}
|
|
||||||
return cfgArgs
|
|
||||||
}
|
|
||||||
|
|
||||||
func loadConfig(path string) *args {
|
|
||||||
var args args
|
|
||||||
|
|
||||||
if !filepath.IsAbs(path) {
|
|
||||||
dir, err := os.Getwd()
|
|
||||||
if err != nil {
|
|
||||||
fmt.Println("config dir get failed, reason:" + err.Error())
|
|
||||||
return &args
|
|
||||||
}
|
|
||||||
path = filepath.Join(dir, path)
|
|
||||||
}
|
|
||||||
file, err := os.ReadFile(path)
|
|
||||||
if err != nil {
|
|
||||||
if os.IsNotExist(err) {
|
|
||||||
return &args
|
|
||||||
}
|
|
||||||
fmt.Println("config file read failed, reason:" + err.Error())
|
|
||||||
return &args
|
|
||||||
}
|
|
||||||
if err = json.Unmarshal(file, &args); err != nil {
|
|
||||||
fmt.Println("config file parse failed, reason:" + err.Error())
|
|
||||||
return &args
|
|
||||||
}
|
|
||||||
fmt.Printf("config file loaded: %s\n", path)
|
|
||||||
return &args
|
|
||||||
}
|
|
||||||
@@ -1,69 +0,0 @@
|
|||||||
//go:build web
|
|
||||||
// +build web
|
|
||||||
|
|
||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"embed"
|
|
||||||
"github.com/GopeedLab/gopeed/cmd"
|
|
||||||
"github.com/GopeedLab/gopeed/pkg/api/model"
|
|
||||||
"github.com/GopeedLab/gopeed/pkg/base"
|
|
||||||
"io/fs"
|
|
||||||
"os"
|
|
||||||
"path/filepath"
|
|
||||||
)
|
|
||||||
|
|
||||||
//go:embed dist/*
|
|
||||||
var dist embed.FS
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
sub, err := fs.Sub(dist, "dist")
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
args := parse()
|
|
||||||
var webBasicAuth *model.WebBasicAuth
|
|
||||||
if isNotBlank(args.Username) && isNotBlank(args.Password) {
|
|
||||||
webBasicAuth = &model.WebBasicAuth{
|
|
||||||
Username: *args.Username,
|
|
||||||
Password: *args.Password,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var dir string
|
|
||||||
if args.StorageDir != nil && *args.StorageDir != "" {
|
|
||||||
dir = *args.StorageDir
|
|
||||||
} else {
|
|
||||||
exe, err := os.Executable()
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
dir = filepath.Dir(exe)
|
|
||||||
}
|
|
||||||
|
|
||||||
if args.DownloadConfig == nil {
|
|
||||||
args.DownloadConfig = &base.DownloaderStoreConfig{}
|
|
||||||
}
|
|
||||||
args.DownloadConfig.Http = &base.DownloaderHttpConfig{
|
|
||||||
Enable: true,
|
|
||||||
Host: *args.Host,
|
|
||||||
Port: *args.Port,
|
|
||||||
ApiToken: *args.ApiToken,
|
|
||||||
}
|
|
||||||
|
|
||||||
cfg := &model.StartConfig{
|
|
||||||
Storage: model.StorageBolt,
|
|
||||||
StorageDir: filepath.Join(dir, "storage"),
|
|
||||||
DownloadConfig: args.DownloadConfig,
|
|
||||||
ProductionMode: true,
|
|
||||||
WebEnable: true,
|
|
||||||
WebFS: sub,
|
|
||||||
WebBasicAuth: webBasicAuth,
|
|
||||||
}
|
|
||||||
cmd.Start(cfg)
|
|
||||||
}
|
|
||||||
|
|
||||||
func isNotBlank(str *string) bool {
|
|
||||||
return str != nil && *str != ""
|
|
||||||
}
|
|
||||||
@@ -1,15 +0,0 @@
|
|||||||
services:
|
|
||||||
gopeed:
|
|
||||||
container_name: gopeed
|
|
||||||
ports:
|
|
||||||
- 9999:9999 # HTTP port (host:container)
|
|
||||||
environment:
|
|
||||||
- PUID=0
|
|
||||||
- PGID=0
|
|
||||||
- UMASK=022
|
|
||||||
volumes:
|
|
||||||
- ~/gopeed/Downloads:/app/Downloads # mount download path
|
|
||||||
#- ~/gopeed/storage:/app/storage # if you need to mount storage path, uncomment this line
|
|
||||||
restart: unless-stopped
|
|
||||||
image: liwei2633/gopeed
|
|
||||||
# command: -u Username -p Password # optional authentication
|
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
package common
|
||||||
|
|
||||||
|
import "errors"
|
||||||
|
|
||||||
|
type Status int
|
||||||
|
|
||||||
|
const (
|
||||||
|
DownloadStatusReady Status = iota
|
||||||
|
DownloadStatusStart
|
||||||
|
DownloadStatusPause
|
||||||
|
DownloadStatusError
|
||||||
|
DownloadStatusDone
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
HttpCodeOK = 200
|
||||||
|
HttpCodePartialContent = 206
|
||||||
|
|
||||||
|
HttpHeaderRange = "Range"
|
||||||
|
HttpHeaderContentLength = "Content-Length"
|
||||||
|
HttpHeaderContentRange = "Content-Range"
|
||||||
|
HttpHeaderContentDisposition = "Content-Disposition"
|
||||||
|
|
||||||
|
HttpHeaderRangeFormat = "bytes=%d-%d"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
PauseErr = errors.New("pause")
|
||||||
|
DeleteErr = errors.New("delete")
|
||||||
|
)
|
||||||
@@ -0,0 +1,149 @@
|
|||||||
|
package common
|
||||||
|
|
||||||
|
import (
|
||||||
|
"golang.org/x/net/proxy"
|
||||||
|
"net"
|
||||||
|
"os"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
// 下载请求
|
||||||
|
type Request struct {
|
||||||
|
// 下载链接
|
||||||
|
URL string
|
||||||
|
// 附加信息
|
||||||
|
Extra interface{}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 资源信息
|
||||||
|
type Resource struct {
|
||||||
|
Req *Request
|
||||||
|
// 资源总大小
|
||||||
|
Size int64
|
||||||
|
// 是否支持断点下载
|
||||||
|
Range bool
|
||||||
|
// 资源所包含的文件列表
|
||||||
|
Files []*FileInfo
|
||||||
|
}
|
||||||
|
|
||||||
|
type Options struct {
|
||||||
|
// 保存文件名
|
||||||
|
Name string
|
||||||
|
// 保存目录
|
||||||
|
Path string
|
||||||
|
// 并发连接数
|
||||||
|
Connections int
|
||||||
|
}
|
||||||
|
|
||||||
|
type FileInfo struct {
|
||||||
|
Name string
|
||||||
|
Path string
|
||||||
|
Size int64
|
||||||
|
}
|
||||||
|
|
||||||
|
type Process interface {
|
||||||
|
Start() error
|
||||||
|
Pause() error
|
||||||
|
Continue() error
|
||||||
|
Delete() error
|
||||||
|
}
|
||||||
|
|
||||||
|
type FileCreator interface {
|
||||||
|
Create(name string, size int64) (file *os.File, err error)
|
||||||
|
}
|
||||||
|
|
||||||
|
type Controller struct {
|
||||||
|
Files map[string]*os.File
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewController() *Controller {
|
||||||
|
return &Controller{Files: make(map[string]*os.File)}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Controller) Touch(name string, size int64) (file *os.File, err error) {
|
||||||
|
if size > 0 {
|
||||||
|
err := os.Truncate(name, size)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
file, err = os.OpenFile(name, os.O_RDWR, 0666)
|
||||||
|
} else {
|
||||||
|
file, err = os.Create(name)
|
||||||
|
}
|
||||||
|
if err == nil {
|
||||||
|
c.Files[name] = file
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Controller) Open(name string) (file *os.File, err error) {
|
||||||
|
file, err = os.OpenFile(name, os.O_RDWR, 0666)
|
||||||
|
if err == nil {
|
||||||
|
c.Files[name] = file
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Controller) Write(name string, offset int64, buf []byte) (int, error) {
|
||||||
|
return c.Files[name].WriteAt(buf, offset)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Controller) Close(name string) error {
|
||||||
|
err := c.Files[name].Close()
|
||||||
|
delete(c.Files, name)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Controller) ContextDialer() (proxy.Dialer, error) {
|
||||||
|
// return proxy.SOCKS5("tpc", "127.0.0.1:9999", nil, nil)
|
||||||
|
var dialer proxy.Dialer
|
||||||
|
return &DialerWarp{dialer: dialer}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type DialerWarp struct {
|
||||||
|
dialer proxy.Dialer
|
||||||
|
}
|
||||||
|
|
||||||
|
type ConnWarp struct {
|
||||||
|
conn net.Conn
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *ConnWarp) Read(b []byte) (n int, err error) {
|
||||||
|
return c.conn.Read(b)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *ConnWarp) Write(b []byte) (n int, err error) {
|
||||||
|
return c.conn.Write(b)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *ConnWarp) Close() error {
|
||||||
|
return c.conn.Close()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *ConnWarp) LocalAddr() net.Addr {
|
||||||
|
return c.conn.LocalAddr()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *ConnWarp) RemoteAddr() net.Addr {
|
||||||
|
return c.conn.RemoteAddr()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *ConnWarp) SetDeadline(t time.Time) error {
|
||||||
|
return c.conn.SetDeadline(t)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *ConnWarp) SetReadDeadline(t time.Time) error {
|
||||||
|
return c.conn.SetReadDeadline(t)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *ConnWarp) SetWriteDeadline(t time.Time) error {
|
||||||
|
return c.conn.SetWriteDeadline(t)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *DialerWarp) Dial(network, addr string) (c net.Conn, err error) {
|
||||||
|
conn, err := d.dialer.Dial(network, addr)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &ConnWarp{conn: conn}, nil
|
||||||
|
}
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
package common
|
||||||
|
|
||||||
|
// 对应协议的下载支持
|
||||||
|
type Fetcher interface {
|
||||||
|
BaseFetch
|
||||||
|
// 支持的协议列表
|
||||||
|
Protocols() []string
|
||||||
|
// 解析请求
|
||||||
|
Resolve(req *Request) (*Resource, error)
|
||||||
|
// 创建任务
|
||||||
|
Create(res *Resource, opts *Options) (Process, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
type BaseFetch interface {
|
||||||
|
InitCtl(ctl *Controller)
|
||||||
|
GetCtl() *Controller
|
||||||
|
}
|
||||||
|
|
||||||
|
type BaseFetcher struct {
|
||||||
|
ctl *Controller
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *BaseFetcher) InitCtl(ctl *Controller) {
|
||||||
|
b.ctl = ctl
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *BaseFetcher) GetCtl() *Controller {
|
||||||
|
return b.ctl
|
||||||
|
}
|
||||||
@@ -0,0 +1,81 @@
|
|||||||
|
package download
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"github.com/google/uuid"
|
||||||
|
"github.com/monkeyWie/gopeed-core/download/common"
|
||||||
|
"net/url"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
type TaskInfo struct {
|
||||||
|
ID string
|
||||||
|
Res *common.Resource
|
||||||
|
Opts *common.Options
|
||||||
|
Status common.Status
|
||||||
|
Files map[string]*common.FileInfo
|
||||||
|
|
||||||
|
process common.Process
|
||||||
|
}
|
||||||
|
|
||||||
|
type Downloader struct {
|
||||||
|
fetches map[string]common.Fetcher
|
||||||
|
tasks map[string]*TaskInfo
|
||||||
|
*common.Controller
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewDownloader(fetchers ...common.Fetcher) *Downloader {
|
||||||
|
d := &Downloader{Controller: common.NewController()}
|
||||||
|
d.fetches = make(map[string]common.Fetcher)
|
||||||
|
for _, f := range fetchers {
|
||||||
|
for _, p := range f.Protocols() {
|
||||||
|
d.fetches[strings.ToUpper(p)] = f
|
||||||
|
}
|
||||||
|
f.InitCtl(d.Controller)
|
||||||
|
}
|
||||||
|
d.tasks = make(map[string]*TaskInfo)
|
||||||
|
return d
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *Downloader) getFetcher(URL string) (common.Fetcher, error) {
|
||||||
|
url, err := url.Parse(URL)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if fetch, ok := d.fetches[strings.ToUpper(url.Scheme)]; ok {
|
||||||
|
return fetch, nil
|
||||||
|
}
|
||||||
|
return nil, errors.New("unsupported protocol")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *Downloader) Resolve(req *common.Request) (*common.Resource, error) {
|
||||||
|
fetcher, err := d.getFetcher(req.URL)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return fetcher.Resolve(req)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *Downloader) Create(res *common.Resource, opts *common.Options) error {
|
||||||
|
fetcher, err := d.getFetcher(res.Req.URL)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
process, err := fetcher.Create(res, opts)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
id := uuid.New().String()
|
||||||
|
d.tasks[id] = &TaskInfo{
|
||||||
|
ID: id,
|
||||||
|
Res: res,
|
||||||
|
Opts: opts,
|
||||||
|
Status: common.DownloadStatusReady,
|
||||||
|
process: process,
|
||||||
|
}
|
||||||
|
return process.Start()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *Downloader) Pause(id string) {
|
||||||
|
d.tasks[id].process.Pause()
|
||||||
|
}
|
||||||
@@ -0,0 +1,40 @@
|
|||||||
|
package download
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/monkeyWie/gopeed-core/download/common"
|
||||||
|
"github.com/monkeyWie/gopeed-core/download/http"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestDownloader_Resolve(t *testing.T) {
|
||||||
|
downloader := buildDownloader()
|
||||||
|
res, err := downloader.Resolve(&common.Request{
|
||||||
|
URL: "http://192.168.200.163:8088/docker-compose",
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
fmt.Println(res)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestDownloader_Create(t *testing.T) {
|
||||||
|
downloader := buildDownloader()
|
||||||
|
res, err := downloader.Resolve(&common.Request{
|
||||||
|
URL: "http://192.168.200.163:8088/docker-compose",
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
err = downloader.Create(res, &common.Options{
|
||||||
|
Path: "E:\\test\\gopeed\\http",
|
||||||
|
Connections: 4,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func buildDownloader() *Downloader {
|
||||||
|
return NewDownloader(&http.Fetcher{BaseFetcher: &common.BaseFetcher{}})
|
||||||
|
}
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
package file_allocate
|
||||||
|
|
||||||
|
import (
|
||||||
|
"os"
|
||||||
|
)
|
||||||
|
|
||||||
|
type FileAllocate interface {
|
||||||
|
Allocate(name string, size int64) (file *os.File, err error)
|
||||||
|
}
|
||||||
|
|
||||||
|
type DefaultFileAllocator struct {
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *DefaultFileAllocator) Allocate(name string, size int64) (file *os.File, err error) {
|
||||||
|
err = os.Truncate(name, size)
|
||||||
|
file, err = os.OpenFile(name, os.O_RDWR, 0644)
|
||||||
|
return
|
||||||
|
}
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
package file_allocate
|
||||||
|
|
||||||
|
import "os"
|
||||||
|
|
||||||
|
type PreFileAllocator struct {
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *PreFileAllocator) Allocate(name string, size int64) (file *os.File, err error) {
|
||||||
|
err = os.Truncate(name, size)
|
||||||
|
file, err = os.OpenFile(name, os.O_RDWR, 0644)
|
||||||
|
return
|
||||||
|
}
|
||||||
@@ -0,0 +1,167 @@
|
|||||||
|
package http
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"fmt"
|
||||||
|
"github.com/monkeyWie/gopeed-core/download/common"
|
||||||
|
"github.com/monkeyWie/gopeed-core/download/http/model"
|
||||||
|
"io/ioutil"
|
||||||
|
"mime"
|
||||||
|
"net/http"
|
||||||
|
"net/http/cookiejar"
|
||||||
|
"net/url"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
type RequestError struct {
|
||||||
|
Code int
|
||||||
|
Msg string
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewRequestError(code int, msg string) *RequestError {
|
||||||
|
return &RequestError{Code: code, Msg: msg}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (re *RequestError) Error() string {
|
||||||
|
return fmt.Sprintf("http request fail,code:%d", re.Code)
|
||||||
|
}
|
||||||
|
|
||||||
|
type Fetcher struct {
|
||||||
|
*common.BaseFetcher
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewFetcher() *Fetcher {
|
||||||
|
return &Fetcher{BaseFetcher: &common.BaseFetcher{}}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *Fetcher) Protocols() []string {
|
||||||
|
return []string{"HTTP", "HTTPS"}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *Fetcher) Resolve(req *common.Request) (*common.Resource, error) {
|
||||||
|
httpReq, err := BuildRequest(req)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
client := BuildClient()
|
||||||
|
// 只访问一个字节,测试资源是否支持Range请求
|
||||||
|
httpReq.Header.Set(common.HttpHeaderRange, fmt.Sprintf(common.HttpHeaderRangeFormat, 0, 0))
|
||||||
|
httpResp, err := client.Do(httpReq)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
// 拿到响应头就关闭,不用加defer
|
||||||
|
httpResp.Body.Close()
|
||||||
|
res := &common.Resource{
|
||||||
|
Req: req,
|
||||||
|
Range: false,
|
||||||
|
Files: []*common.FileInfo{},
|
||||||
|
}
|
||||||
|
if common.HttpCodePartialContent == httpResp.StatusCode {
|
||||||
|
// 返回206响应码表示支持断点下载
|
||||||
|
res.Range = true
|
||||||
|
// 解析资源大小: bytes 0-1000/1001 => 1001
|
||||||
|
contentTotal := subLastSlash(httpResp.Header.Get(common.HttpHeaderContentRange))
|
||||||
|
if contentTotal != "" {
|
||||||
|
parse, err := strconv.ParseInt(contentTotal, 10, 64)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
res.Size = parse
|
||||||
|
}
|
||||||
|
} else if common.HttpCodeOK == httpResp.StatusCode {
|
||||||
|
// 返回200响应码,不支持断点下载,通过Content-Length头获取文件大小,获取不到的话可能是chunked编码
|
||||||
|
contentLength := httpResp.Header.Get(common.HttpHeaderContentLength)
|
||||||
|
if contentLength != "" {
|
||||||
|
parse, err := strconv.ParseInt(contentLength, 10, 64)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
res.Size = parse
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return nil, NewRequestError(httpResp.StatusCode, httpResp.Status)
|
||||||
|
}
|
||||||
|
file := &common.FileInfo{
|
||||||
|
Size: res.Size,
|
||||||
|
}
|
||||||
|
contentDisposition := httpResp.Header.Get(common.HttpHeaderContentDisposition)
|
||||||
|
if contentDisposition != "" {
|
||||||
|
_, params, _ := mime.ParseMediaType(contentDisposition)
|
||||||
|
filename := params["filename"]
|
||||||
|
if filename != "" {
|
||||||
|
file.Name = filename
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Get file name by URL
|
||||||
|
if file.Name == "" {
|
||||||
|
parse, err := url.Parse(req.URL)
|
||||||
|
if err == nil {
|
||||||
|
// e.g. /files/test.txt => test.txt
|
||||||
|
file.Name = subLastSlash(parse.Path)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// unknown file name
|
||||||
|
if file.Name == "" {
|
||||||
|
file.Name = "unknown"
|
||||||
|
}
|
||||||
|
res.Files = append(res.Files, file)
|
||||||
|
return res, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h *Fetcher) Create(res *common.Resource, opts *common.Options) (common.Process, error) {
|
||||||
|
if opts.Connections != 1 && !res.Range {
|
||||||
|
opts.Connections = 1
|
||||||
|
}
|
||||||
|
return NewProcess(h, res, opts), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func subLastSlash(str string) string {
|
||||||
|
if str == "" {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
index := strings.LastIndex(str, "/")
|
||||||
|
if index != -1 {
|
||||||
|
return str[index+1:]
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
func BuildClient() *http.Client {
|
||||||
|
// Cookie handle
|
||||||
|
jar, _ := cookiejar.New(nil)
|
||||||
|
return &http.Client{
|
||||||
|
Jar: jar,
|
||||||
|
Timeout: time.Second * 10,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func BuildRequest(req *common.Request) (*http.Request, error) {
|
||||||
|
url, err := url.Parse(req.URL)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
httpReq := &http.Request{
|
||||||
|
URL: url,
|
||||||
|
Header: map[string][]string{},
|
||||||
|
}
|
||||||
|
|
||||||
|
if req.Extra != nil {
|
||||||
|
if extra, ok := req.Extra.(model.Extra); ok {
|
||||||
|
if extra.Method != "" {
|
||||||
|
httpReq.Method = extra.Method
|
||||||
|
} else {
|
||||||
|
httpReq.Method = http.MethodGet
|
||||||
|
}
|
||||||
|
if len(extra.Header) > 0 {
|
||||||
|
for k, v := range extra.Header {
|
||||||
|
httpReq.Header[k] = []string{v}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
httpReq.Body = ioutil.NopCloser(bytes.NewBufferString(extra.Body))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return httpReq, nil
|
||||||
|
}
|
||||||
@@ -0,0 +1,307 @@
|
|||||||
|
package http
|
||||||
|
|
||||||
|
import (
|
||||||
|
"crypto/md5"
|
||||||
|
"encoding/hex"
|
||||||
|
"fmt"
|
||||||
|
"github.com/monkeyWie/gopeed-core/download/common"
|
||||||
|
"io"
|
||||||
|
"math/rand"
|
||||||
|
"net"
|
||||||
|
"net/http"
|
||||||
|
"os"
|
||||||
|
"reflect"
|
||||||
|
"testing"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
const testDir = "./"
|
||||||
|
const buildSize = 200 * 1024 * 1024
|
||||||
|
const buildName = "build.data"
|
||||||
|
const buildFile = testDir + buildName
|
||||||
|
const downloadName = "download.data"
|
||||||
|
const downloadFile = testDir + downloadName
|
||||||
|
|
||||||
|
func TestFetcher_Resolve(t *testing.T) {
|
||||||
|
testResolve(startTestFileServer, &common.Resource{
|
||||||
|
Size: buildSize,
|
||||||
|
Range: true,
|
||||||
|
Files: []*common.FileInfo{
|
||||||
|
{
|
||||||
|
Name: buildName,
|
||||||
|
Size: buildSize,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}, t)
|
||||||
|
testResolve(startTestChunkedServer, &common.Resource{
|
||||||
|
Size: 0,
|
||||||
|
Range: false,
|
||||||
|
Files: []*common.FileInfo{
|
||||||
|
{
|
||||||
|
Name: buildName,
|
||||||
|
Size: 0,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}, t)
|
||||||
|
}
|
||||||
|
|
||||||
|
func testResolve(startTestServer func() net.Listener, want *common.Resource, t *testing.T) {
|
||||||
|
listener := startTestServer()
|
||||||
|
defer listener.Close()
|
||||||
|
fetcher := NewFetcher()
|
||||||
|
res, err := fetcher.Resolve(&common.Request{
|
||||||
|
URL: "http://" + listener.Addr().String() + "/" + buildName,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
res.Req = nil
|
||||||
|
if !reflect.DeepEqual(want, res) {
|
||||||
|
t.Errorf("Resolve error = %v, want %v", res, want)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestFetcher_DownloadNormal(t *testing.T) {
|
||||||
|
listener := startTestFileServer()
|
||||||
|
defer listener.Close()
|
||||||
|
// 正常下载
|
||||||
|
downloadNormal(listener, 1, t)
|
||||||
|
downloadNormal(listener, 5, t)
|
||||||
|
downloadNormal(listener, 8, t)
|
||||||
|
downloadNormal(listener, 16, t)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestFetcher_DownloadContinue(t *testing.T) {
|
||||||
|
listener := startTestFileServer()
|
||||||
|
defer listener.Close()
|
||||||
|
// 暂停继续
|
||||||
|
downloadContinue(listener, 1, t)
|
||||||
|
fmt.Println("d1")
|
||||||
|
downloadContinue(listener, 5, t)
|
||||||
|
fmt.Println("d5")
|
||||||
|
downloadContinue(listener, 8, t)
|
||||||
|
fmt.Println("d8")
|
||||||
|
downloadContinue(listener, 16, t)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestFetcher_DownloadChunked(t *testing.T) {
|
||||||
|
listener := startTestChunkedServer()
|
||||||
|
defer listener.Close()
|
||||||
|
// chunked编码下载
|
||||||
|
//downloadNormal(listener, 1, t)
|
||||||
|
downloadContinue(listener, 1, t)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestFetcher_DownloadRetry(t *testing.T) {
|
||||||
|
listener := startTestRetryServer()
|
||||||
|
defer listener.Close()
|
||||||
|
// chunked编码下载
|
||||||
|
downloadNormal(listener, 1, t)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestFetcher_DownloadError(t *testing.T) {
|
||||||
|
listener := startTestErrorServer()
|
||||||
|
defer listener.Close()
|
||||||
|
// chunked编码下载
|
||||||
|
downloadError(listener, 1, t)
|
||||||
|
}
|
||||||
|
|
||||||
|
func startTestFileServer() net.Listener {
|
||||||
|
return startTestServer(func() http.Handler {
|
||||||
|
return http.FileServer(http.Dir(testDir))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func startTestChunkedServer() net.Listener {
|
||||||
|
return startTestServer(func() http.Handler {
|
||||||
|
mux := http.NewServeMux()
|
||||||
|
mux.HandleFunc("/"+buildName, func(writer http.ResponseWriter, request *http.Request) {
|
||||||
|
file, err := os.Open(buildFile)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
defer file.Close()
|
||||||
|
io.Copy(writer, file)
|
||||||
|
})
|
||||||
|
return mux
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func startTestRetryServer() net.Listener {
|
||||||
|
counter := 0
|
||||||
|
return startTestServer(func() http.Handler {
|
||||||
|
mux := http.NewServeMux()
|
||||||
|
mux.HandleFunc("/"+buildName, func(writer http.ResponseWriter, request *http.Request) {
|
||||||
|
counter++
|
||||||
|
if counter != 1 && counter < 5 {
|
||||||
|
writer.WriteHeader(500)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
file, err := os.Open(buildFile)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
defer file.Close()
|
||||||
|
io.Copy(writer, file)
|
||||||
|
})
|
||||||
|
return mux
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func startTestErrorServer() net.Listener {
|
||||||
|
counter := 0
|
||||||
|
return startTestServer(func() http.Handler {
|
||||||
|
mux := http.NewServeMux()
|
||||||
|
mux.HandleFunc("/"+buildName, func(writer http.ResponseWriter, request *http.Request) {
|
||||||
|
counter++
|
||||||
|
if counter != 1 {
|
||||||
|
writer.WriteHeader(500)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
})
|
||||||
|
return mux
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func startTestServer(serverHandle func() http.Handler) net.Listener {
|
||||||
|
listener, err := net.Listen("tcp", "127.0.0.1:0")
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
file, err := os.Create(buildFile)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
// 随机生成一个文件
|
||||||
|
l := int64(8192)
|
||||||
|
buf := make([]byte, l)
|
||||||
|
size := int64(0)
|
||||||
|
for {
|
||||||
|
_, err := rand.Read(buf)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
if size+l >= buildSize {
|
||||||
|
file.WriteAt(buf[0:buildSize-size], size)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
file.WriteAt(buf, size)
|
||||||
|
size += l
|
||||||
|
}
|
||||||
|
server := &http.Server{}
|
||||||
|
server.Handler = serverHandle()
|
||||||
|
go server.Serve(listener)
|
||||||
|
|
||||||
|
return &delFileListener{
|
||||||
|
File: file,
|
||||||
|
Listener: listener,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type delFileListener struct {
|
||||||
|
*os.File
|
||||||
|
net.Listener
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *delFileListener) Close() error {
|
||||||
|
defer func() {
|
||||||
|
c.File.Close()
|
||||||
|
if err := ifExistAndRemove(c.File.Name()); err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
}
|
||||||
|
if err := ifExistAndRemove(downloadFile); err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
return c.Listener.Close()
|
||||||
|
}
|
||||||
|
|
||||||
|
func ifExistAndRemove(name string) error {
|
||||||
|
if _, err := os.Stat(name); !os.IsNotExist(err) {
|
||||||
|
return os.Remove(name)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func downloadReady(listener net.Listener, connections int, t *testing.T) common.Process {
|
||||||
|
fetcher := NewFetcher()
|
||||||
|
fetcher.InitCtl(common.NewController())
|
||||||
|
res, err := fetcher.Resolve(&common.Request{
|
||||||
|
URL: "http://" + listener.Addr().String() + "/" + buildName,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
process, err := fetcher.Create(res, &common.Options{
|
||||||
|
Name: downloadName,
|
||||||
|
Path: testDir,
|
||||||
|
Connections: connections,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
return process
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func downloadNormal(listener net.Listener, connections int, t *testing.T) {
|
||||||
|
process := downloadReady(listener, connections, t)
|
||||||
|
err := process.Start()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
want := fileMd5(buildFile)
|
||||||
|
got := fileMd5(downloadFile)
|
||||||
|
if want != got {
|
||||||
|
t.Errorf("Download error = %v, want %v", got, want)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func downloadContinue(listener net.Listener, connections int, t *testing.T) {
|
||||||
|
process := downloadReady(listener, connections, t)
|
||||||
|
go func() {
|
||||||
|
err := process.Start()
|
||||||
|
if err != nil && err != common.PauseErr {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
time.Sleep(time.Millisecond * 200)
|
||||||
|
if err := process.Pause(); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
time.Sleep(time.Millisecond * 200)
|
||||||
|
if err := process.Continue(); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
want := fileMd5(buildFile)
|
||||||
|
got := fileMd5(downloadFile)
|
||||||
|
if want != got {
|
||||||
|
t.Errorf("Download error = %v, want %v", got, want)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func downloadError(listener net.Listener, connections int, t *testing.T) {
|
||||||
|
process := downloadReady(listener, connections, t)
|
||||||
|
err := process.Start()
|
||||||
|
if err == nil {
|
||||||
|
t.Errorf("Download error = %v, want %v", err, nil)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func fileMd5(filePath string) string {
|
||||||
|
file, err := os.Open(filePath)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
// Tell the program to call the following function when the current function returns
|
||||||
|
defer file.Close()
|
||||||
|
|
||||||
|
// Open a new hash interface to write to
|
||||||
|
hash := md5.New()
|
||||||
|
|
||||||
|
// Copy the file in the hash interface and check for any error
|
||||||
|
if _, err := io.Copy(hash, file); err != nil {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
return hex.EncodeToString(hash.Sum(nil))
|
||||||
|
}
|
||||||
Loaded 50 of 457 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user