From 3f1b4a9a5b532a54105a15a25768f9f1bffe54c3 Mon Sep 17 00:00:00 2001 From: Zoe Roux Date: Sun, 17 Sep 2023 16:27:40 +0200 Subject: [PATCH] Create a basic addItem --- api/controllers/rest.go | 29 +++++++++++++++++++ api/main.go | 28 ++++++++++++------ api/models/dto.go | 15 ++++++++++ api/models/item.go | 61 +++++++++++++++++++++++++++++----------- api/services/aria2.go | 11 ++++++-- api/services/database.go | 34 ++++++++++++++++++++-- 6 files changed, 148 insertions(+), 30 deletions(-) create mode 100644 api/controllers/rest.go create mode 100644 api/models/dto.go diff --git a/api/controllers/rest.go b/api/controllers/rest.go new file mode 100644 index 0000000..33dda54 --- /dev/null +++ b/api/controllers/rest.go @@ -0,0 +1,29 @@ +package controllers + +import ( + models "tide/api/models" + services "tide/api/services" +) + +type Controller struct { + Database *services.Database + Aria2 *services.Aria2 +} + +func NewController(db *services.Database, aria2 *services.Aria2) *Controller { + c := new(Controller) + c.Database = db + c.Aria2 = aria2 + return c +} + +func (c *Controller) NewItem(newItem models.NewItem) (*models.Item, error) { + item, err := c.Aria2.AddItem(newItem.Uri) + if err != nil { + return nil, err + } + if newItem.Path != nil { + item.Path = *newItem.Path + } + return c.Database.AddItem(item) +} diff --git a/api/main.go b/api/main.go index a09e5b6..6c75adc 100644 --- a/api/main.go +++ b/api/main.go @@ -1,40 +1,52 @@ package main import ( + "encoding/json" "log" "net/http" - "encoding/json" - services "tide/api/services" controllers "tide/api/controllers" + models "tide/api/models" + services "tide/api/services" ) func main() { - d, err := services.NewDatabase() + db, err := services.NewDatabase() if err != nil { log.Fatal("Could not create database: ", err) } - err = d.Migrate() + err = db.Migrate() if err != nil { log.Fatal("Could not migrate database: ", err) } + aria2, err := services.NewAria2() + if err != nil { + log.Fatal("Could not connect to aria2", err) + } + controller := controllers.NewController(db, aria2) + http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { switch r.Method { case http.MethodPost: - // r.Body - var newItem NewItem - err := json.NewDecoder(r.Body).Decode(newItem) + var newItem models.NewItem + err := json.NewDecoder(r.Body).Decode(&newItem) if err != nil { http.Error(w, "Bad request", http.StatusBadRequest) return } - item := controllers.NewItem() + + item, err := controller.NewItem(newItem) + if err != nil { + http.Error(w, "Internal Server Error", http.StatusInternalServerError) + return + } json.NewEncoder(w).Encode(item) w.WriteHeader(http.StatusCreated) default: http.Error(w, "Method not allowed", http.StatusMethodNotAllowed) } }) + log.Print("Listening on :7890") http.ListenAndServe(":7890", nil) } diff --git a/api/models/dto.go b/api/models/dto.go new file mode 100644 index 0000000..d45d6fd --- /dev/null +++ b/api/models/dto.go @@ -0,0 +1,15 @@ +package models + +type ItemType string + +const ( + Torrent ItemType = "torrent" + Magnet ItemType = "magnet" + Direct ItemType = "direct" +) + +type NewItem struct { + Uri string + Type *ItemType + Path *string +} diff --git a/api/models/item.go b/api/models/item.go index 7ae7832..dd40f94 100644 --- a/api/models/item.go +++ b/api/models/item.go @@ -1,30 +1,57 @@ package models -import "time"; +import "time" type State string + const ( - Stale State = "stale" + Stale State = "stale" Downloading State = "downloading" - Seeding State = "seeding" - Finished State = "finished" + Seeding State = "seeding" + Finished State = "finished" + Paused State = "paused" + Errored State = "errored" +) + +type Priority string + +const ( + None Priority = "none" + Low Priority = "low" + Medium Priority = "medium" + High Priority = "high" ) type File struct { - Name string - Priority int - Size uint64 - AvailableSize uint64 - Path string + Index uint `json:"index"` + Name string `json:"name"` + Priority Priority `json:"priority"` + Size uint64 `json:"size"` + AvailableSize uint64 `json:"availableSize"` + Path string `json:"path"` } type Item struct { - Id string - Name string - State State - Size uint64 - AvailableSize uint64 - Path string - AddedDate time.Time - Files []File + Id string `json:"id"` + Name string `json:"name"` + Path string `json:"path"` + AddedDate time.Time `json:"addedDate"` + Files []File `json:"files"` + + State State `json:"state"` + Size uint64 `json:"size"` + AvailableSize uint64 `json:"availableSize"` + 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, + // while unset bits indicate not yet loaded and/or missing pieces. + // Any overflow bits at the end are set to zero. + // When the download was not started yet, this will be an empty string. + BitField string `json:"bitfield"` + DownloadSpeed uint `json:"downloadSpeed"` + UploadSpeed uint `json:"uploadSpeed"` + SeedCount uint `json:"seedCount"` + Connections uint `json:"connections"` + + ErrorMessage *string `json:"errorMessage"` } diff --git a/api/services/aria2.go b/api/services/aria2.go index 765cd4a..7485f9b 100644 --- a/api/services/aria2.go +++ b/api/services/aria2.go @@ -29,8 +29,15 @@ func NewAria2() (*Aria2, error) { return p, nil } -func (x *Aria2) AddItem(item string) { - x.client.AddURI([]string{item}, nil) +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 } func (x *Aria2) List() []models.Item { diff --git a/api/services/database.go b/api/services/database.go index 4f67c75..9842da6 100644 --- a/api/services/database.go +++ b/api/services/database.go @@ -4,8 +4,12 @@ import ( "database/sql" "fmt" "os" + "tide/api/models" + "github.com/golang-migrate/migrate/v4" + "github.com/golang-migrate/migrate/v4/database/postgres" + _ "github.com/golang-migrate/migrate/v4/source/file" _ "github.com/lib/pq" ) @@ -16,14 +20,14 @@ type Database struct { func NewDatabase() (*Database, error) { d := new(Database) con := fmt.Sprintf( - "postgresql://%v:%v@%v:%v/%v", + "postgresql://%v:%v@%v:%v/%v?sslmode=disable", os.Getenv("POSTGRES_USER"), os.Getenv("POSTGRES_PASSWORD"), os.Getenv("POSTGRES_SERVER"), os.Getenv("POSTGRES_PORT"), os.Getenv("POSTGRES_DB"), ) - db, err := sql.Open("posgres", con) + db, err := sql.Open("postgres", con) if err != nil { return nil, err } @@ -31,8 +35,32 @@ func NewDatabase() (*Database, error) { return d, nil } +func (db *Database) Migrate() error { + driver, err := postgres.WithInstance(db.Connection, &postgres.Config{}) + if err != nil { + return err + } + m, err := migrate.NewWithDatabaseInstance( + "file:///app/migrations", + "postgres", + driver, + ) + if err != nil { + return err + } + m.Up() + return nil +} + func (d *Database) AddItem(item *models.Item) (*models.Item, error) { - _, err := d.Connection.Exec("INSERT INTO items (id) VALUES (?)", item.Id) + _, err := d.Connection.Exec( + "INSERT INTO items (id, name, path, size, files) VALUES (?, ?, ?, ?, ?)", + item.Id, + item.Name, + item.Path, + item.Size, + item.Files, + ) if err != nil { return nil, err }