From e8402791029272d44373b60a027c389af5ef596b Mon Sep 17 00:00:00 2001 From: Zoe Roux Date: Tue, 19 Sep 2023 17:09:42 +0200 Subject: [PATCH] Create a dockerfile for aria2 --- .env.example | 6 ++-- api/main.go | 6 +++- api/models/item.go | 2 ++ api/services/aria2.go | 74 +++++++++++++++++++++++++++++++++++++++--- aria2/Dockerfile | 26 +++++++++++++++ aria2/aria2.conf | 3 ++ docker-compose.dev.yml | 5 ++- docker-compose.yml | 2 +- 8 files changed, 112 insertions(+), 12 deletions(-) create mode 100644 aria2/Dockerfile create mode 100644 aria2/aria2.conf diff --git a/.env.example b/.env.example index 86c366e..3ce1ef5 100644 --- a/.env.example +++ b/.env.example @@ -1,10 +1,8 @@ +DOWNLOAD_DIR=./downloads +ARIA2_DIR=./.aria2 # IMPORTANT: Change that to actually secure your aria2 connection RPC_SECRET=wertyui -# User/Group IDs of newly downloaded files. To know your ids, run the `id` command. -PUID=$UID -PGID=$GID - ARIA_URI=aria2c:6800 # Database things POSTGRES_USER=tideUser diff --git a/api/main.go b/api/main.go index 6c75adc..931af72 100644 --- a/api/main.go +++ b/api/main.go @@ -35,10 +35,14 @@ func main() { http.Error(w, "Bad request", http.StatusBadRequest) return } + if newItem.Uri == "" { + http.Error(w, "Uri is a required field", http.StatusBadRequest) + return + } item, err := controller.NewItem(newItem) if err != nil { - http.Error(w, "Internal Server Error", http.StatusInternalServerError) + http.Error(w, err.Error(), http.StatusBadRequest) return } json.NewEncoder(w).Encode(item) diff --git a/api/models/item.go b/api/models/item.go index dd40f94..60a5dcf 100644 --- a/api/models/item.go +++ b/api/models/item.go @@ -5,6 +5,7 @@ import "time" type State string const ( + Unknown State = "unknown" Stale State = "stale" Downloading State = "downloading" Seeding State = "seeding" @@ -41,6 +42,7 @@ type Item struct { State State `json:"state"` Size uint64 `json:"size"` AvailableSize uint64 `json:"availableSize"` + Percent uint `json:"percent"` UploadedSize uint64 `json:"uploadedSize"` // Hexadecimal representation of the download progress. // The highest bit corresponds to the piece at index 0. Any set bits indicate loaded pieces, diff --git a/api/services/aria2.go b/api/services/aria2.go index 7485f9b..8ec7fa1 100644 --- a/api/services/aria2.go +++ b/api/services/aria2.go @@ -2,7 +2,10 @@ package services import ( "fmt" + "log" "os" + "time" + models "tide/api/models" "github.com/siku2/arigo" @@ -15,7 +18,7 @@ type Service interface { type Aria2 struct { client *arigo.Client - token string + token string } func NewAria2() (*Aria2, error) { @@ -29,15 +32,76 @@ func NewAria2() (*Aria2, error) { return p, nil } +func toState(status arigo.DownloadStatus, percent uint) models.State { + switch status { + case arigo.StatusActive: + if percent == 100 { + return models.Seeding + } + return models.Downloading + case arigo.StatusWaiting: + return models.Stale + case arigo.StatusPaused: + return models.Paused + case arigo.StatusError: + return models.Errored + case arigo.StatusCompleted: + return models.Finished + case arigo.StatusRemoved: + fallthrough + default: + return models.Unknown + } +} + func (x *Aria2) AddItem(uri string) (*models.Item, error) { id, err := x.client.AddURI([]string{uri}, nil) if err != nil { return nil, err } - item := new(models.Item) - item.Id = id.GID - // TODO: Download other datas - return item, nil + status, err := id.TellStatus() + if err != nil { + log.Println("Tell status error") + return nil, err + } + + percent := status.CompletedLength / status.TotalLength + files := make([]models.File, 0, len(status.Files)) + for _, file := range status.Files { + priority := models.Medium + if !file.Selected { + priority = models.None + } + + files = append(files, models.File{ + Index: uint(file.Index), + Name: "???", + Path: "???", + Priority: priority, + Size: uint64(file.Length), + AvailableSize: uint64(file.CompletedLength), + }) + } + return &models.Item{ + Id: id.GID, + + Name: "??", + Path: "??", + AddedDate: time.Now(), + Files: files, + + State: toState(status.Status, percent), + Size: uint64(status.TotalLength), + AvailableSize: uint64(status.CompletedLength), + Percent: percent, + UploadedSize: uint64(status.UploadLength), + BitField: status.BitField, + DownloadSpeed: status.DownloadSpeed, + UploadSpeed: status.UploadSpeed, + SeedCount: status.NumSeeders, + Connections: status.Connections, + ErrorMessage: &status.ErrorMessage, + }, nil } func (x *Aria2) List() []models.Item { diff --git a/aria2/Dockerfile b/aria2/Dockerfile new file mode 100644 index 0000000..150fef2 --- /dev/null +++ b/aria2/Dockerfile @@ -0,0 +1,26 @@ +FROM alpine + +RUN apk add --no-cache --update aria2 +WORKDIR /private + + +ENV LISTEN_PORT=6888 \ + RPC_PORT=6800 \ + RPC_SECRET= \ + DISABLE_IPV6=true \ + ENABLE_DHT6=false + +COPY ./aria2.conf ./aria2.conf +EXPOSE 6888 +EXPOSE 6888/udp +CMD touch /aria2/aria2.session && \ + aria2c --conf-path ./aria2.conf \ + --dht-file-path=/dht/dht.data \ + --dht-file-path6=/dht/dht6.data \ + --save-session=/aria2/aria2.session \ + --input-file=/aria2/aria2.session \ + # --rpc-secret=$RPC_SECRET \ + --rpc-listen-port=$RPC_PORT \ + --listen-port=$LISTEN_PORT \ + --disable-ipv6=$DISABLE_IPV6 \ + --enable-dht6=$ENABLE_DHT6 diff --git a/aria2/aria2.conf b/aria2/aria2.conf new file mode 100644 index 0000000..caa7101 --- /dev/null +++ b/aria2/aria2.conf @@ -0,0 +1,3 @@ +enable-rpc=true +rpc-listen-all=true +dir=/downloads diff --git a/docker-compose.dev.yml b/docker-compose.dev.yml index f49233d..8b1a383 100644 --- a/docker-compose.dev.yml +++ b/docker-compose.dev.yml @@ -14,11 +14,14 @@ services: - .env aria2: - image: p3terx/aria2-pro + build: ./aria2 ports: - "6888:6888" - "6888:6888/udp" restart: on-failure + volumes: + - $DOWNLOAD_DIR:/downloads + - $ARIA2_DIR:/aria2 env_file: - .env diff --git a/docker-compose.yml b/docker-compose.yml index e42c3d3..e76b112 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -8,7 +8,7 @@ services: - .env aria2: - image: p3terx/aria2-pro + build: ./aria2 restart: on-failure env_file: - .env