Skip to content

Commit

Permalink
feat(clients): add qbit v5 support (#2)
Browse files Browse the repository at this point in the history
* chore: rename module

* feat(clients): migrate qbit to autobrr/go-qbittorrent pkg

* feat(clients): get file contents

* feat(clients): go mod tidy

* build: update goreleaser build flags

* build: update build flags
  • Loading branch information
zze0s authored Dec 10, 2024
1 parent f8815e3 commit 3502288
Show file tree
Hide file tree
Showing 31 changed files with 178 additions and 157 deletions.
6 changes: 3 additions & 3 deletions .goreleaser.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,9 @@ builds:
- arm64
ldflags:
- -s -w
- -X "github.com/l3uddz/tqm/runtime.Version={{ .Version }}"
- -X "github.com/l3uddz/tqm/runtime.GitCommit={{ .ShortCommit }}"
- -X "github.com/l3uddz/tqm/runtime.Timestamp={{ .Timestamp }}"
- -X "github.com/autobrr/tqm/runtime.Version={{ .Version }}"
- -X "github.com/autobrr/tqm/runtime.GitCommit={{ .ShortCommit }}"
- -X "github.com/autobrr/tqm/runtime.Timestamp={{ .Timestamp }}"
flags:
- -trimpath

Expand Down
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ ${BUILD_PATH}/${CMD}: ${GO_FILES} go.sum
CGO_ENABLED=0 go build \
-mod vendor \
-trimpath \
-ldflags "-s -w -X github.com/l3uddz/tqm/runtime.Version=${VERSION} -X github.com/l3uddz/tqm/runtime.GitCommit=${GIT_COMMIT} -X github.com/l3uddz/tqm/runtime.Timestamp=${TIMESTAMP}" \
-ldflags "-s -w -X github.com/autobrr/tqm/runtime.Version=${VERSION} -X github.com/autobrr/tqm/runtime.GitCommit=${GIT_COMMIT} -X github.com/autobrr/tqm/runtime.Timestamp=${TIMESTAMP}" \
-o ${BUILD_PATH}/${CMD} \
.

Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
[![made-with-golang](https://img.shields.io/badge/Made%20with-Golang-blue.svg?style=flat-square)](https://golang.org/)
[![License: GPL v3](https://img.shields.io/badge/License-GPL%203-blue.svg?style=flat-square)](https://github.com/l3uddz/tqm/blob/master/LICENSE.md)
[![License: GPL v3](https://img.shields.io/badge/License-GPL%203-blue.svg?style=flat-square)](https://github.com/autobrr/tqm/blob/master/LICENSE.md)
[![Discord](https://img.shields.io/discord/381077432285003776.svg?colorB=177DC1&label=Discord&style=flat-square)](https://discord.io/cloudbox)
[![Contributing](https://img.shields.io/badge/Contributing-gray.svg?style=flat-square)](CONTRIBUTING.md)
[![Donate](https://img.shields.io/badge/Donate-gray.svg?style=flat-square)](#donate)
Expand Down
2 changes: 1 addition & 1 deletion client/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import (
"fmt"
"strings"

"github.com/l3uddz/tqm/expression"
"github.com/autobrr/tqm/expression"
)

func NewClient(clientType string, clientName string, exp *expression.Expressions) (Interface, error) {
Expand Down
10 changes: 4 additions & 6 deletions client/deluge.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,13 @@ import (
"path"
"time"

"github.com/dustin/go-humanize"

"github.com/l3uddz/tqm/expression"
"github.com/autobrr/tqm/config"
"github.com/autobrr/tqm/expression"
"github.com/autobrr/tqm/logger"

"github.com/dustin/go-humanize"
delugeclient "github.com/gdm85/go-libdeluge"
"github.com/sirupsen/logrus"

"github.com/l3uddz/tqm/config"
"github.com/l3uddz/tqm/logger"
)

/* Struct */
Expand Down
2 changes: 1 addition & 1 deletion client/interface.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package client

import (
"github.com/l3uddz/tqm/config"
"github.com/autobrr/tqm/config"
)

type Interface interface {
Expand Down
100 changes: 57 additions & 43 deletions client/qbittorrent.go
Original file line number Diff line number Diff line change
@@ -1,22 +1,23 @@
package client

import (
"context"
"fmt"
"io/ioutil"
"os"
"path/filepath"
"strings"
"time"

"github.com/autobrr/tqm/config"
"github.com/autobrr/tqm/expression"
"github.com/autobrr/tqm/logger"
"github.com/autobrr/tqm/sliceutils"
"github.com/autobrr/tqm/stringutils"

qbit "github.com/autobrr/go-qbittorrent"
"github.com/dustin/go-humanize"
qbittorrent "github.com/l3uddz/go-qbt"
"github.com/sirupsen/logrus"

"github.com/l3uddz/tqm/config"
"github.com/l3uddz/tqm/expression"
"github.com/l3uddz/tqm/logger"
"github.com/l3uddz/tqm/sliceutils"
"github.com/l3uddz/tqm/stringutils"
)

/* Struct */
Expand All @@ -30,7 +31,7 @@ type QBittorrent struct {
// internal
log *logrus.Entry
clientType string
client *qbittorrent.Client
client *qbit.Client

// need to be loaded by LoadLabelPathMap
labelPathMap map[string]string
Expand Down Expand Up @@ -65,7 +66,16 @@ func NewQBittorrent(name string, exp *expression.Expressions) (TagInterface, err
// init client
qbl := logrus.New()
qbl.Out = ioutil.Discard
tc.client = qbittorrent.NewClient(strings.TrimSuffix(*tc.Url, "/"), qbl)
//tc.client = qbittorrent.NewClient(strings.TrimSuffix(*tc.Url, "/"), qbl)
tc.client = qbit.NewClient(qbit.Config{
Host: *tc.Url,
Username: tc.User,
Password: tc.Password,
TLSSkipVerify: true,
BasicUser: tc.User,
BasicPass: tc.Password,
Log: nil,
})

return &tc, nil
}
Expand All @@ -78,12 +88,13 @@ func (c *QBittorrent) Type() string {

func (c *QBittorrent) Connect() error {
// login
if err := c.client.Login(c.User, c.Password); err != nil {
if err := c.client.Login(); err != nil {
return fmt.Errorf("login: %w", err)
}

// retrieve & validate api version
apiVersion, err := c.client.Application.GetAPIVersion()
//apiVersion, err := c.client.Application.GetAPIVersion()
apiVersion, err := c.client.GetWebAPIVersion()
if err != nil {
return fmt.Errorf("get api version: %w", err)
} else if stringutils.Atof64(apiVersion[0:3], 0.0) < 2.2 {
Expand All @@ -95,12 +106,12 @@ func (c *QBittorrent) Connect() error {
}

func (c *QBittorrent) LoadLabelPathMap() error {
p, err := c.client.Application.GetAppPreferences()
p, err := c.client.GetAppPreferences()
if err != nil {
return fmt.Errorf("get app preferences: %w", err)
}

cats, err := c.client.Torrent.GetCategories()
cats, err := c.client.GetCategories()
if err != nil {
return fmt.Errorf("get categories: %w", err)
}
Expand Down Expand Up @@ -130,7 +141,7 @@ func (c *QBittorrent) LabelPathMap() map[string]string {
func (c *QBittorrent) GetTorrents() (map[string]config.Torrent, error) {
// retrieve torrents from client
c.log.Tracef("Retrieving torrents...")
t, err := c.client.Torrent.GetList(nil)
t, err := c.client.GetTorrents(qbit.TorrentFilterOptions{})
if err != nil {
return nil, fmt.Errorf("get torrents: %w", err)
}
Expand All @@ -142,17 +153,18 @@ func (c *QBittorrent) GetTorrents() (map[string]config.Torrent, error) {
t := t

// get additional torrent details
td, err := c.client.Torrent.GetProperties(t.Hash)
//td, err := c.client.Torrent.GetProperties(t.Hash)
td, err := c.client.GetTorrentProperties(t.Hash)
if err != nil {
return nil, fmt.Errorf("get torrent properties: %v: %w", t.Hash, err)
}

ts, err := c.client.Torrent.GetTrackers(t.Hash)
ts, err := c.client.GetTorrentTrackers(t.Hash)
if err != nil {
return nil, fmt.Errorf("get torrent trackers: %v: %w", t.Hash, err)
}

tf, err := c.client.Torrent.GetContents(t.Hash)
tf, err := c.client.GetFilesInformation(t.Hash)
if err != nil {
return nil, fmt.Errorf("get torrent files: %v: %w", t.Hash, err)
}
Expand All @@ -163,23 +175,25 @@ func (c *QBittorrent) GetTorrents() (map[string]config.Torrent, error) {

for _, tracker := range ts {
// skip disabled trackers
if strings.Contains(tracker.URL, "[DHT]") || strings.Contains(tracker.URL, "[LSD]") ||
strings.Contains(tracker.URL, "[PeX]") {
if strings.Contains(tracker.Url, "[DHT]") || strings.Contains(tracker.Url, "[LSD]") ||
strings.Contains(tracker.Url, "[PeX]") {
continue
}

// use status of first enabled tracker
trackerName = parseTrackerDomain(tracker.URL)
trackerName = parseTrackerDomain(tracker.Url)
trackerStatus = tracker.Message
break
}

// added time
addedTimeSecs := int64(time.Since(td.AdditionDate).Seconds())
addedTimeSecs := int64(time.Since(time.Unix(int64(td.AdditionDate), 0)).Seconds())

seedingTime := time.Duration(td.SeedingTime) * time.Second

// torrent files
var files []string
for _, f := range tf {
for _, f := range *tf {
files = append(files, filepath.Join(td.SavePath, f.Name))
}

Expand All @@ -194,8 +208,8 @@ func (c *QBittorrent) GetTorrents() (map[string]config.Torrent, error) {
Hash: t.Hash,
Name: t.Name,
Path: td.SavePath,
TotalBytes: int64(t.Size),
DownloadedBytes: int64(td.TotalDownloaded),
TotalBytes: t.Size,
DownloadedBytes: td.TotalDownloaded,
State: string(t.State),
Files: files,
Tags: tags,
Expand All @@ -214,9 +228,9 @@ func (c *QBittorrent) GetTorrents() (map[string]config.Torrent, error) {
AddedSeconds: addedTimeSecs,
AddedHours: float32(addedTimeSecs) / 60 / 60,
AddedDays: float32(addedTimeSecs) / 60 / 60 / 24,
SeedingSeconds: int64(td.SeedingTime.Seconds()),
SeedingHours: float32(td.SeedingTime.Seconds()) / 60 / 60,
SeedingDays: float32(td.SeedingTime.Seconds()) / 60 / 60 / 24,
SeedingSeconds: int64(seedingTime.Seconds()),
SeedingHours: float32(seedingTime.Seconds()) / 60 / 60,
SeedingDays: float32(seedingTime.Seconds()) / 60 / 60 / 24,
Label: t.Category,
Seeds: int64(td.SeedsTotal),
Peers: int64(td.PeersTotal),
Expand All @@ -236,29 +250,29 @@ func (c *QBittorrent) GetTorrents() (map[string]config.Torrent, error) {

func (c *QBittorrent) RemoveTorrent(hash string, deleteData bool) (bool, error) {
// pause torrent
if err := c.client.Torrent.StopTorrents([]string{hash}); err != nil {
if err := c.client.Pause([]string{hash}); err != nil {
return false, fmt.Errorf("pause torrent: %v: %w", hash, err)
}

time.Sleep(1 * time.Second)

// resume torrent
if err := c.client.Torrent.ResumeTorrents([]string{hash}); err != nil {
if err := c.client.Resume([]string{hash}); err != nil {
return false, fmt.Errorf("resume torrent: %v: %w", hash, err)
}

// sleep before re-announcing torrent
time.Sleep(2 * time.Second)

if err := c.client.Torrent.ReannounceTorrents([]string{hash}); err != nil {
if err := c.client.ReAnnounceTorrents([]string{hash}); err != nil {
return false, fmt.Errorf("re-announce torrent: %v: %w", hash, err)
}

// sleep before removing torrent
time.Sleep(2 * time.Second)

// remove
if err := c.client.Torrent.DeleteTorrents([]string{hash}, deleteData); err != nil {
if err := c.client.DeleteTorrents([]string{hash}, deleteData); err != nil {
return false, fmt.Errorf("delete torrent: %v: %w", hash, err)
}

Expand All @@ -274,19 +288,19 @@ func (c *QBittorrent) SetTorrentLabel(hash string, label string, hardlink bool)
}

// get torrent details
td, err := c.client.Torrent.GetProperties(hash)
td, err := c.client.GetTorrentProperties(hash)
if err != nil {
return fmt.Errorf("get torrent properties: %w", err)
}

if filepath.Clean(td.SavePath) != filepath.Clean(lp) {
// get torrent files
tf, err := c.client.Torrent.GetContents(hash)
tf, err := c.client.GetFilesInformation(hash)
if err != nil {
return fmt.Errorf("get torrent files: %w", err)
}

for _, f := range tf {
for _, f := range *tf {
source := filepath.Join(td.SavePath, f.Name)
target := filepath.Join(lp, f.Name)
if _, err := os.Stat(source); err != nil {
Expand All @@ -309,22 +323,22 @@ func (c *QBittorrent) SetTorrentLabel(hash string, label string, hardlink bool)
// qbit force moves the files, overwriting existing files
// manually settings location, and then setting category works
// and causes qbit to recheck instead of move
if err := c.client.Torrent.SetAutomaticManagement([]string{hash}, false); err != nil {
if err := c.client.SetAutoManagement([]string{hash}, false); err != nil {
return fmt.Errorf("set automatic management: %w", err)
}
if err := c.client.Torrent.SetLocations([]string{hash}, lp); err != nil {
if err := c.client.SetLocation([]string{hash}, lp); err != nil {
return fmt.Errorf("set location: %w", err)
}
}

// set label
if err := c.client.Torrent.SetCategories([]string{hash}, label); err != nil {
if err := c.client.SetCategory([]string{hash}, label); err != nil {
return fmt.Errorf("set torrent label: %v: %w", label, err)
}

// enable autotmm
if c.EnableAutoTmmAfterRelabel && !hardlink {
if err := c.client.Torrent.SetAutomaticManagement([]string{hash}, true); err != nil {
if err := c.client.SetAutoManagement([]string{hash}, true); err != nil {
return fmt.Errorf("enable autotmm: %w", err)
}
}
Expand All @@ -334,7 +348,7 @@ func (c *QBittorrent) SetTorrentLabel(hash string, label string, hardlink bool)

func (c *QBittorrent) GetCurrentFreeSpace(path string) (int64, error) {
// get current main stats
data, err := c.client.Sync.GetMainData(0)
data, err := c.client.SyncMainDataCtx(context.Background(), 0)
if err != nil {
return 0, fmt.Errorf("get main data: %w", err)
}
Expand Down Expand Up @@ -422,7 +436,7 @@ func (c *QBittorrent) AddTags(hash string, tags []string) error {
return nil
}

if err := c.client.Torrent.AddTags([]string{hash}, tags); err != nil {
if err := c.client.AddTags([]string{hash}, strings.Join(tags, ",")); err != nil {
return fmt.Errorf("add torrent tags: %v: %w", tags, err)
}

Expand All @@ -434,7 +448,7 @@ func (c *QBittorrent) RemoveTags(hash string, tags []string) error {
return nil
}

if err := c.client.Torrent.RemoveTags([]string{hash}, tags); err != nil {
if err := c.client.RemoveTags([]string{hash}, strings.Join(tags, ",")); err != nil {
return fmt.Errorf("add torrent tags: %v: %w", tags, err)
}

Expand All @@ -446,7 +460,7 @@ func (c *QBittorrent) CreateTags(tags []string) error {
return nil
}

if err := c.client.Torrent.CreateTags(tags); err != nil {
if err := c.client.CreateTags(tags); err != nil {
return fmt.Errorf("create torrent tags: %v: %w", tags, err)
}

Expand All @@ -458,7 +472,7 @@ func (c *QBittorrent) DeleteTags(tags []string) error {
return nil
}

if err := c.client.Torrent.DeleteTags(tags); err != nil {
if err := c.client.DeleteTags(tags); err != nil {
return fmt.Errorf("delete torrent tags: %v: %w", tags, err)
}

Expand Down
2 changes: 1 addition & 1 deletion client/tagInterface.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package client

import (
"github.com/l3uddz/tqm/config"
"github.com/autobrr/tqm/config"
)

type RetagInfo struct {
Expand Down
Loading

0 comments on commit 3502288

Please # to comment.