qbittorrent tracing

This commit is contained in:
royalcat 2024-09-08 21:39:11 +03:00
parent abcd073643
commit 0bc6227427
10 changed files with 353 additions and 122 deletions

View file

@ -240,6 +240,9 @@ type Preferences struct {
} }
func (c *client) Version(ctx context.Context) (string, error) { func (c *client) Version(ctx context.Context) (string, error) {
ctx, span := trace.Start(ctx, "qbittorrent.Application.Version")
defer span.End()
apiUrl := fmt.Sprintf("%s/api/v2/app/version", c.config.Address) apiUrl := fmt.Sprintf("%s/api/v2/app/version", c.config.Address)
result, err := c.doRequest(ctx, &requestData{ result, err := c.doRequest(ctx, &requestData{
@ -257,6 +260,9 @@ func (c *client) Version(ctx context.Context) (string, error) {
} }
func (c *client) WebApiVersion(ctx context.Context) (string, error) { func (c *client) WebApiVersion(ctx context.Context) (string, error) {
ctx, span := trace.Start(ctx, "qbittorrent.Application.WebApiVersion")
defer span.End()
apiUrl := fmt.Sprintf("%s/api/v2/app/webapiVersion", c.config.Address) apiUrl := fmt.Sprintf("%s/api/v2/app/webapiVersion", c.config.Address)
result, err := c.doRequest(ctx, &requestData{ result, err := c.doRequest(ctx, &requestData{
url: apiUrl, url: apiUrl,
@ -273,6 +279,9 @@ func (c *client) WebApiVersion(ctx context.Context) (string, error) {
} }
func (c *client) BuildInfo(ctx context.Context) (*BuildInfo, error) { func (c *client) BuildInfo(ctx context.Context) (*BuildInfo, error) {
ctx, span := trace.Start(ctx, "qbittorrent.Application.BuildInfo")
defer span.End()
apiUrl := fmt.Sprintf("%s/api/v2/app/buildInfo", c.config.Address) apiUrl := fmt.Sprintf("%s/api/v2/app/buildInfo", c.config.Address)
result, err := c.doRequest(ctx, &requestData{ result, err := c.doRequest(ctx, &requestData{
url: apiUrl, url: apiUrl,
@ -294,6 +303,9 @@ func (c *client) BuildInfo(ctx context.Context) (*BuildInfo, error) {
} }
func (c *client) Shutdown(ctx context.Context) error { func (c *client) Shutdown(ctx context.Context) error {
ctx, span := trace.Start(ctx, "qbittorrent.Application.Shutdown")
defer span.End()
apiUrl := fmt.Sprintf("%s/api/v2/app/shutdown", c.config.Address) apiUrl := fmt.Sprintf("%s/api/v2/app/shutdown", c.config.Address)
result, err := c.doRequest(ctx, &requestData{ result, err := c.doRequest(ctx, &requestData{
method: http.MethodPost, method: http.MethodPost,
@ -311,6 +323,9 @@ func (c *client) Shutdown(ctx context.Context) error {
} }
func (c *client) GetPreferences(ctx context.Context) (*Preferences, error) { func (c *client) GetPreferences(ctx context.Context) (*Preferences, error) {
ctx, span := trace.Start(ctx, "qbittorrent.Application.GetPreferences")
defer span.End()
apiUrl := fmt.Sprintf("%s/api/v2/app/preferences", c.config.Address) apiUrl := fmt.Sprintf("%s/api/v2/app/preferences", c.config.Address)
result, err := c.doRequest(ctx, &requestData{ result, err := c.doRequest(ctx, &requestData{
url: apiUrl, url: apiUrl,
@ -332,6 +347,9 @@ func (c *client) GetPreferences(ctx context.Context) (*Preferences, error) {
} }
func (c *client) SetPreferences(ctx context.Context, prefs *Preferences) error { func (c *client) SetPreferences(ctx context.Context, prefs *Preferences) error {
ctx, span := trace.Start(ctx, "qbittorrent.Application.SetPreferences")
defer span.End()
apiUrl := fmt.Sprintf("%s/api/v2/app/setPreferences", c.config.Address) apiUrl := fmt.Sprintf("%s/api/v2/app/setPreferences", c.config.Address)
data, err := json.Marshal(prefs) data, err := json.Marshal(prefs)
if err != nil { if err != nil {
@ -359,6 +377,9 @@ func (c *client) SetPreferences(ctx context.Context, prefs *Preferences) error {
} }
func (c *client) DefaultSavePath(ctx context.Context) (string, error) { func (c *client) DefaultSavePath(ctx context.Context) (string, error) {
ctx, span := trace.Start(ctx, "qbittorrent.Application.DefaultSavePath")
defer span.End()
apiUrl := fmt.Sprintf("%s/api/v2/app/defaultSavePath", c.config.Address) apiUrl := fmt.Sprintf("%s/api/v2/app/defaultSavePath", c.config.Address)
result, err := c.doRequest(ctx, &requestData{ result, err := c.doRequest(ctx, &requestData{
url: apiUrl, url: apiUrl,

View file

@ -19,6 +19,9 @@ type Authentication interface {
} }
func (c *client) Login(ctx context.Context) error { func (c *client) Login(ctx context.Context) error {
ctx, span := trace.Start(ctx, "qbittorrent.Authentication.Login")
defer span.End()
if c.config.Username == "" || c.config.Password == "" { if c.config.Username == "" || c.config.Password == "" {
return errors.New("username or password is empty") return errors.New("username or password is empty")
} }
@ -51,8 +54,8 @@ func (c *client) Login(ctx context.Context) error {
return errors.New("login failed: " + string(result.body)) return errors.New("login failed: " + string(result.body))
} }
if c.cookieJar == nil { if c.client.Jar == nil {
c.cookieJar, err = cookiejar.New(nil) c.client.Jar, err = cookiejar.New(nil)
if err != nil { if err != nil {
return err return err
} }
@ -62,12 +65,15 @@ func (c *client) Login(ctx context.Context) error {
if err != nil { if err != nil {
return err return err
} }
c.cookieJar.SetCookies(u, result.cookies) c.client.Jar.SetCookies(u, result.cookies)
return nil return nil
} }
func (c *client) Logout(ctx context.Context) error { func (c *client) Logout(ctx context.Context) error {
ctx, span := trace.Start(ctx, "qbittorrent.Authentication.Logout")
defer span.End()
apiUrl := fmt.Sprintf("%s/api/v2/auth/logout", c.config.Address) apiUrl := fmt.Sprintf("%s/api/v2/auth/logout", c.config.Address)
result, err := c.doRequest(ctx, &requestData{ result, err := c.doRequest(ctx, &requestData{
method: http.MethodPost, method: http.MethodPost,

View file

@ -1,6 +1,16 @@
package qbittorrent package qbittorrent
import "context" import (
"context"
"crypto/tls"
"net"
"net/http"
"time"
"go.opentelemetry.io/otel"
)
var trace = otel.Tracer("git.kmsign.ru/royalcat/tstor/pkg/qbittorrent")
// Client represents a qBittorrent client // Client represents a qBittorrent client
type Client interface { type Client interface {
@ -23,12 +33,12 @@ type Client interface {
} }
func NewClient(ctx context.Context, cfg *Config) (Client, error) { func NewClient(ctx context.Context, cfg *Config) (Client, error) {
var c = &client{config: cfg, clientPool: newClientPool(cfg.ConnectionMaxIdles, cfg.ConnectionTimeout)} var c = &client{config: cfg, client: newClient(cfg.ConnectionMaxIdles, cfg.ConnectionTimeout)}
return c, nil return c, nil
} }
func LoginClient(ctx context.Context, cfg *Config) (Client, error) { func LoginClient(ctx context.Context, cfg *Config) (Client, error) {
var c = &client{config: cfg, clientPool: newClientPool(cfg.ConnectionMaxIdles, cfg.ConnectionTimeout)} var c = &client{config: cfg, client: newClient(cfg.ConnectionMaxIdles, cfg.ConnectionTimeout)}
if err := c.Authentication().Login(ctx); err != nil { if err := c.Authentication().Login(ctx); err != nil {
return nil, err return nil, err
} }
@ -37,3 +47,26 @@ func LoginClient(ctx context.Context, cfg *Config) (Client, error) {
} }
return c, nil return c, nil
} }
// newClient creates and returns a new clientPool
func newClient(maxIdle int, timeout time.Duration) *http.Client {
if maxIdle == 0 {
maxIdle = 128
}
if timeout == 0 {
timeout = time.Second * 3
}
return &http.Client{
Transport: &http.Transport{
Proxy: http.ProxyFromEnvironment,
DialContext: (&net.Dialer{
Timeout: 30 * time.Second,
KeepAlive: 30 * time.Second,
}).DialContext,
TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
MaxIdleConns: maxIdle,
},
Timeout: timeout,
}
}

View file

@ -5,7 +5,6 @@ import (
"fmt" "fmt"
"io" "io"
"net/http" "net/http"
"net/http/cookiejar"
"net/url" "net/url"
"strings" "strings"
"time" "time"
@ -27,9 +26,8 @@ type requestData struct {
var _ Client = (*client)(nil) var _ Client = (*client)(nil)
type client struct { type client struct {
config *Config config *Config
clientPool *clientPool client *http.Client
cookieJar *cookiejar.Jar
} }
func (c *client) Authentication() Authentication { func (c *client) Authentication() Authentication {
@ -81,13 +79,8 @@ func (c *client) doRequest(ctx context.Context, data *requestData) (*responseRes
for key, value := range c.config.CustomHeaders { for key, value := range c.config.CustomHeaders {
request.Header.Set(key, value) request.Header.Set(key, value)
} }
hc := c.clientPool.GetClient()
defer c.clientPool.ReleaseClient(hc)
if c.cookieJar != nil {
hc.Jar = c.cookieJar
}
resp, err := hc.Do(request) resp, err := c.client.Do(request)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -102,14 +95,14 @@ func (c *client) doRequest(ctx context.Context, data *requestData) (*responseRes
} }
func (c *client) cookies() (string, error) { func (c *client) cookies() (string, error) {
if c.cookieJar == nil { if c.client.Jar == nil {
return "", ErrNotLogin return "", ErrNotLogin
} }
u, err := url.Parse(c.config.Address) u, err := url.Parse(c.config.Address)
if err != nil { if err != nil {
return "", err return "", err
} }
cookies := c.cookieJar.Cookies(u) cookies := c.client.Jar.Cookies(u)
if len(cookies) == 0 { if len(cookies) == 0 {
return "", ErrNotLogin return "", ErrNotLogin
} }

View file

@ -1,53 +0,0 @@
package qbittorrent
import (
"crypto/tls"
"net"
"net/http"
"sync"
"time"
)
// clientPool defines a pool of HTTP clients
type clientPool struct {
// pool store http.Client instances
*sync.Pool
}
// newClientPool creates and returns a new clientPool
func newClientPool(maxIdle int, timeout time.Duration) *clientPool {
if maxIdle == 0 {
maxIdle = 128
}
if timeout == 0 {
timeout = time.Second * 3
}
return &clientPool{
Pool: &sync.Pool{
New: func() any {
return &http.Client{
Transport: &http.Transport{
Proxy: http.ProxyFromEnvironment,
DialContext: (&net.Dialer{
Timeout: 30 * time.Second,
KeepAlive: 30 * time.Second,
}).DialContext,
TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
MaxIdleConns: maxIdle,
},
Timeout: timeout,
}
},
},
}
}
// GetClient retrieves a http.Client from the pool
func (p *clientPool) GetClient() *http.Client {
return p.Get().(*http.Client)
}
// ReleaseClient returns a http.Client back to the pool
func (p *clientPool) ReleaseClient(client *http.Client) {
p.Put(client)
}

View file

@ -36,6 +36,9 @@ type Log interface {
} }
func (c *client) GetLog(ctx context.Context, option *LogOption) ([]*LogEntry, error) { func (c *client) GetLog(ctx context.Context, option *LogOption) ([]*LogEntry, error) {
ctx, span := trace.Start(ctx, "qbittorrent.Log.GetLog")
defer span.End()
var form = url.Values{} var form = url.Values{}
err := encoder.Encode(option, form) err := encoder.Encode(option, form)
if err != nil { if err != nil {
@ -64,6 +67,9 @@ func (c *client) GetLog(ctx context.Context, option *LogOption) ([]*LogEntry, er
} }
func (c *client) GetPeerLog(ctx context.Context, lastKnownId int) ([]*LogEntry, error) { func (c *client) GetPeerLog(ctx context.Context, lastKnownId int) ([]*LogEntry, error) {
ctx, span := trace.Start(ctx, "qbittorrent.Log.GetPeerLog")
defer span.End()
apiUrl := fmt.Sprintf("%s/api/v2/log/peers", c.config.Address) apiUrl := fmt.Sprintf("%s/api/v2/log/peers", c.config.Address)
var form = url.Values{} var form = url.Values{}
form.Add("last_known_id", strconv.Itoa(lastKnownId)) form.Add("last_known_id", strconv.Itoa(lastKnownId))

View file

@ -87,6 +87,9 @@ type RssAutoDownloadingRuleDef struct {
} }
func (c *client) AddFolder(ctx context.Context, path string) error { func (c *client) AddFolder(ctx context.Context, path string) error {
ctx, span := trace.Start(ctx, "qbittorrent.RSS.AddFolder")
defer span.End()
var formData = url.Values{} var formData = url.Values{}
formData.Add("path", path) formData.Add("path", path)
var apiUrl = fmt.Sprintf("%s/api/v2/rss/addFolder", c.config.Address) var apiUrl = fmt.Sprintf("%s/api/v2/rss/addFolder", c.config.Address)
@ -106,6 +109,9 @@ func (c *client) AddFolder(ctx context.Context, path string) error {
} }
func (c *client) AddFeed(ctx context.Context, opt *RssAddFeedOption) error { func (c *client) AddFeed(ctx context.Context, opt *RssAddFeedOption) error {
ctx, span := trace.Start(ctx, "qbittorrent.RSS.AddFeed")
defer span.End()
var formData = url.Values{} var formData = url.Values{}
err := encoder.Encode(opt, formData) err := encoder.Encode(opt, formData)
if err != nil { if err != nil {
@ -128,6 +134,9 @@ func (c *client) AddFeed(ctx context.Context, opt *RssAddFeedOption) error {
} }
func (c *client) RemoveItem(ctx context.Context, path string) error { func (c *client) RemoveItem(ctx context.Context, path string) error {
ctx, span := trace.Start(ctx, "qbittorrent.RSS.RemoveItem")
defer span.End()
var formData = url.Values{} var formData = url.Values{}
formData.Add("path", path) formData.Add("path", path)
var apiUrl = fmt.Sprintf("%s/api/v2/rss/removeItem", c.config.Address) var apiUrl = fmt.Sprintf("%s/api/v2/rss/removeItem", c.config.Address)
@ -147,6 +156,9 @@ func (c *client) RemoveItem(ctx context.Context, path string) error {
} }
func (c *client) MoveItem(ctx context.Context, srcPath, destPath string) error { func (c *client) MoveItem(ctx context.Context, srcPath, destPath string) error {
ctx, span := trace.Start(ctx, "qbittorrent.RSS.MoveItem")
defer span.End()
var formData = url.Values{} var formData = url.Values{}
formData.Add("itemPath", srcPath) formData.Add("itemPath", srcPath)
formData.Add("destPath", destPath) formData.Add("destPath", destPath)
@ -167,6 +179,9 @@ func (c *client) MoveItem(ctx context.Context, srcPath, destPath string) error {
} }
func (c *client) GetItems(ctx context.Context, withData bool) (map[string]interface{}, error) { func (c *client) GetItems(ctx context.Context, withData bool) (map[string]interface{}, error) {
ctx, span := trace.Start(ctx, "qbittorrent.RSS.GetItems")
defer span.End()
var apiUrl = fmt.Sprintf("%s/api/v2/rss/items?withData=%t", c.config.Address, withData) var apiUrl = fmt.Sprintf("%s/api/v2/rss/items?withData=%t", c.config.Address, withData)
result, err := c.doRequest(ctx, &requestData{ result, err := c.doRequest(ctx, &requestData{
url: apiUrl, url: apiUrl,
@ -185,6 +200,9 @@ func (c *client) GetItems(ctx context.Context, withData bool) (map[string]interf
} }
func (c *client) MarkAsRead(ctx context.Context, opt *RssMarkAsReadOption) error { func (c *client) MarkAsRead(ctx context.Context, opt *RssMarkAsReadOption) error {
ctx, span := trace.Start(ctx, "qbittorrent.RSS.MarkAsRead")
defer span.End()
var formData = url.Values{} var formData = url.Values{}
err := encoder.Encode(opt, formData) err := encoder.Encode(opt, formData)
if err != nil { if err != nil {
@ -207,6 +225,9 @@ func (c *client) MarkAsRead(ctx context.Context, opt *RssMarkAsReadOption) error
} }
func (c *client) RefreshItem(ctx context.Context, itemPath string) error { func (c *client) RefreshItem(ctx context.Context, itemPath string) error {
ctx, span := trace.Start(ctx, "qbittorrent.RSS.RefreshItem")
defer span.End()
var formData = url.Values{} var formData = url.Values{}
formData.Add("itemPath", itemPath) formData.Add("itemPath", itemPath)
var apiUrl = fmt.Sprintf("%s/api/v2/rss/refreshItem", c.config.Address) var apiUrl = fmt.Sprintf("%s/api/v2/rss/refreshItem", c.config.Address)
@ -226,6 +247,9 @@ func (c *client) RefreshItem(ctx context.Context, itemPath string) error {
} }
func (c *client) SetAutoDownloadingRule(ctx context.Context, ruleName string, ruleDef *RssAutoDownloadingRuleDef) error { func (c *client) SetAutoDownloadingRule(ctx context.Context, ruleName string, ruleDef *RssAutoDownloadingRuleDef) error {
ctx, span := trace.Start(ctx, "qbittorrent.RSS.SetAutoDownloadingRule")
defer span.End()
var formData = url.Values{} var formData = url.Values{}
formData.Add("ruleName", ruleName) formData.Add("ruleName", ruleName)
ruleDefBytes, err := json.Marshal(ruleDef) ruleDefBytes, err := json.Marshal(ruleDef)
@ -250,6 +274,9 @@ func (c *client) SetAutoDownloadingRule(ctx context.Context, ruleName string, ru
} }
func (c *client) RenameAutoDownloadingRule(ctx context.Context, ruleName, newRuleName string) error { func (c *client) RenameAutoDownloadingRule(ctx context.Context, ruleName, newRuleName string) error {
ctx, span := trace.Start(ctx, "qbittorrent.RSS.RenameAutoDownloadingRule")
defer span.End()
var formData = url.Values{} var formData = url.Values{}
formData.Add("ruleName", ruleName) formData.Add("ruleName", ruleName)
formData.Add("newRuleName", newRuleName) formData.Add("newRuleName", newRuleName)
@ -270,6 +297,9 @@ func (c *client) RenameAutoDownloadingRule(ctx context.Context, ruleName, newRul
} }
func (c *client) RemoveAutoDownloadingRule(ctx context.Context, ruleName string) error { func (c *client) RemoveAutoDownloadingRule(ctx context.Context, ruleName string) error {
ctx, span := trace.Start(ctx, "qbittorrent.RSS.RemoveAutoDownloadingRule")
defer span.End()
var formData = url.Values{} var formData = url.Values{}
formData.Add("ruleName", ruleName) formData.Add("ruleName", ruleName)
var apiUrl = fmt.Sprintf("%s/api/v2/rss/removeRule", c.config.Address) var apiUrl = fmt.Sprintf("%s/api/v2/rss/removeRule", c.config.Address)
@ -289,6 +319,9 @@ func (c *client) RemoveAutoDownloadingRule(ctx context.Context, ruleName string)
} }
func (c *client) GetAllAutoDownloadingRules(ctx context.Context) (map[string]*RssAutoDownloadingRuleDef, error) { func (c *client) GetAllAutoDownloadingRules(ctx context.Context) (map[string]*RssAutoDownloadingRuleDef, error) {
ctx, span := trace.Start(ctx, "qbittorrent.RSS.GetAllAutoDownloadingRules")
defer span.End()
var apiUrl = fmt.Sprintf("%s/api/v2/rss/matchingArticles", c.config.Address) var apiUrl = fmt.Sprintf("%s/api/v2/rss/matchingArticles", c.config.Address)
result, err := c.doRequest(ctx, &requestData{ result, err := c.doRequest(ctx, &requestData{
url: apiUrl, url: apiUrl,
@ -305,6 +338,9 @@ func (c *client) GetAllAutoDownloadingRules(ctx context.Context) (map[string]*Rs
} }
func (c *client) GetAllArticlesMatchingRule(ctx context.Context, ruleName string) (map[string][]string, error) { func (c *client) GetAllArticlesMatchingRule(ctx context.Context, ruleName string) (map[string][]string, error) {
ctx, span := trace.Start(ctx, "qbittorrent.RSS.GetAllArticlesMatchingRule")
defer span.End()
var formData = url.Values{} var formData = url.Values{}
formData.Add("ruleName", ruleName) formData.Add("ruleName", ruleName)
var apiUrl = fmt.Sprintf("%s/api/v2/rss/matchingArticles?%s", c.config.Address, formData.Encode()) var apiUrl = fmt.Sprintf("%s/api/v2/rss/matchingArticles?%s", c.config.Address, formData.Encode())

View file

@ -76,6 +76,9 @@ type SyncTorrentPeer struct {
} }
func (c *client) MainData(ctx context.Context, rid int) (*SyncMainData, error) { func (c *client) MainData(ctx context.Context, rid int) (*SyncMainData, error) {
ctx, span := trace.Start(ctx, "qbittorrent.Sync.MainData")
defer span.End()
apiUrl := fmt.Sprintf("%s/api/v2/sync/maindata?rid=%d", c.config.Address, rid) apiUrl := fmt.Sprintf("%s/api/v2/sync/maindata?rid=%d", c.config.Address, rid)
result, err := c.doRequest(ctx, &requestData{ result, err := c.doRequest(ctx, &requestData{
url: apiUrl, url: apiUrl,
@ -97,6 +100,9 @@ func (c *client) MainData(ctx context.Context, rid int) (*SyncMainData, error) {
} }
func (c *client) TorrentPeersData(ctx context.Context, hash string, rid int) (*SyncTorrentPeers, error) { func (c *client) TorrentPeersData(ctx context.Context, hash string, rid int) (*SyncTorrentPeers, error) {
ctx, span := trace.Start(ctx, "qbittorrent.Sync.TorrentPeersData")
defer span.End()
var formData = url.Values{} var formData = url.Values{}
formData.Add("hash", hash) formData.Add("hash", hash)
formData.Add("rid", strconv.Itoa(rid)) formData.Add("rid", strconv.Itoa(rid))

View file

@ -138,58 +138,82 @@ type TorrentOption struct {
Hashes []string `schema:"-"` Hashes []string `schema:"-"`
} }
type TorrentState string
const (
TorrentStateError TorrentState = "error"
TorrentStateMissingFiles TorrentState = "missingFiles"
TorrentStateUploading TorrentState = "uploading"
TorrentStatePausedUP TorrentState = "pausedUP"
TorrentStateQueuedUP TorrentState = "queuedUP"
TorrentStateStalledUP TorrentState = "stalledUP"
TorrentStateCheckingUP TorrentState = "checkingUP"
TorrentStateForcedUP TorrentState = "forcedUP"
TorrentStateAllocating TorrentState = "allocating"
TorrentStateDownloading TorrentState = "downloading"
TorrentStateMetaDL TorrentState = "metaDL"
TorrentStatePausedDL TorrentState = "pausedDL"
TorrentStateQueuedDL TorrentState = "queuedDL"
TorrentStateStalledDL TorrentState = "stalledDL"
TorrentStateCheckingDL TorrentState = "checkingDL"
TorrentStateForcedDL TorrentState = "forcedDL"
TorrentStateCheckingResumeData TorrentState = "checkingResumeData"
TorrentStateMoving TorrentState = "moving"
TorrentStateUnknown TorrentState = "unknown"
)
type TorrentInfo struct { type TorrentInfo struct {
AddedOn int `json:"added_on"` AddedOn int `json:"added_on"`
AmountLeft int `json:"amount_left"` AmountLeft int `json:"amount_left"`
AutoTmm bool `json:"auto_tmm"` AutoTmm bool `json:"auto_tmm"`
Availability float64 `json:"availability"` Availability float64 `json:"availability"`
Category string `json:"category"` Category string `json:"category"`
Completed int `json:"completed"` Completed int `json:"completed"`
CompletionOn int `json:"completion_on"` CompletionOn int `json:"completion_on"`
ContentPath string `json:"content_path"` ContentPath string `json:"content_path"`
DlLimit int `json:"dl_limit"` DlLimit int `json:"dl_limit"`
Dlspeed int `json:"dlspeed"` Dlspeed int `json:"dlspeed"`
DownloadPath string `json:"download_path"` DownloadPath string `json:"download_path"`
Downloaded int `json:"downloaded"` Downloaded int `json:"downloaded"`
DownloadedSession int `json:"downloaded_session"` DownloadedSession int `json:"downloaded_session"`
Eta int `json:"eta"` Eta int `json:"eta"`
FLPiecePrio bool `json:"f_l_piece_prio"` FLPiecePrio bool `json:"f_l_piece_prio"`
ForceStart bool `json:"force_start"` ForceStart bool `json:"force_start"`
Hash string `json:"hash"` Hash string `json:"hash"`
InactiveSeedingTimeLimit int `json:"inactive_seeding_time_limit"` InactiveSeedingTimeLimit int `json:"inactive_seeding_time_limit"`
InfohashV1 string `json:"infohash_v1"` InfohashV1 string `json:"infohash_v1"`
InfohashV2 string `json:"infohash_v2"` InfohashV2 string `json:"infohash_v2"`
LastActivity int `json:"last_activity"` LastActivity int `json:"last_activity"`
MagnetURI string `json:"magnet_uri"` MagnetURI string `json:"magnet_uri"`
MaxInactiveSeedingTime int `json:"max_inactive_seeding_time"` MaxInactiveSeedingTime int `json:"max_inactive_seeding_time"`
MaxRatio int `json:"max_ratio"` MaxRatio int `json:"max_ratio"`
MaxSeedingTime int `json:"max_seeding_time"` MaxSeedingTime int `json:"max_seeding_time"`
Name string `json:"name"` Name string `json:"name"`
NumComplete int `json:"num_complete"` NumComplete int `json:"num_complete"`
NumIncomplete int `json:"num_incomplete"` NumIncomplete int `json:"num_incomplete"`
NumLeechs int `json:"num_leechs"` NumLeechs int `json:"num_leechs"`
NumSeeds int `json:"num_seeds"` NumSeeds int `json:"num_seeds"`
Priority int `json:"priority"` Priority int `json:"priority"`
Progress float64 `json:"progress"` Progress float64 `json:"progress"`
Ratio float64 `json:"ratio"` Ratio float64 `json:"ratio"`
RatioLimit int `json:"ratio_limit"` RatioLimit int `json:"ratio_limit"`
SavePath string `json:"save_path"` SavePath string `json:"save_path"`
SeedingTime int `json:"seeding_time"` SeedingTime int `json:"seeding_time"`
SeedingTimeLimit int `json:"seeding_time_limit"` SeedingTimeLimit int `json:"seeding_time_limit"`
SeenComplete int `json:"seen_complete"` SeenComplete int `json:"seen_complete"`
SeqDl bool `json:"seq_dl"` SeqDl bool `json:"seq_dl"`
Size int `json:"size"` Size int `json:"size"`
State string `json:"state"` State TorrentState `json:"state"`
SuperSeeding bool `json:"super_seeding"` SuperSeeding bool `json:"super_seeding"`
Tags string `json:"tags"` Tags string `json:"tags"`
TimeActive int `json:"time_active"` TimeActive int `json:"time_active"`
TotalSize int `json:"total_size"` TotalSize int `json:"total_size"`
Tracker string `json:"tracker"` Tracker string `json:"tracker"`
TrackersCount int `json:"trackers_count"` TrackersCount int `json:"trackers_count"`
UpLimit int `json:"up_limit"` UpLimit int `json:"up_limit"`
Uploaded int `json:"uploaded"` Uploaded int `json:"uploaded"`
UploadedSession int `json:"uploaded_session"` UploadedSession int `json:"uploaded_session"`
Upspeed int `json:"upspeed"` Upspeed int `json:"upspeed"`
} }
type TorrentProperties struct { type TorrentProperties struct {
@ -294,6 +318,9 @@ type TorrentCategory struct {
} }
func (c *client) GetTorrents(ctx context.Context, opt *TorrentOption) ([]*TorrentInfo, error) { func (c *client) GetTorrents(ctx context.Context, opt *TorrentOption) ([]*TorrentInfo, error) {
ctx, span := trace.Start(ctx, "qbittorrent.Torrent.GetTorrents")
defer span.End()
var formData = url.Values{} var formData = url.Values{}
err := encoder.Encode(opt, formData) err := encoder.Encode(opt, formData)
if err != nil { if err != nil {
@ -324,6 +351,9 @@ func (c *client) GetTorrents(ctx context.Context, opt *TorrentOption) ([]*Torren
} }
func (c *client) GetProperties(ctx context.Context, hash string) (*TorrentProperties, error) { func (c *client) GetProperties(ctx context.Context, hash string) (*TorrentProperties, error) {
ctx, span := trace.Start(ctx, "qbittorrent.Torrent.GetProperties")
defer span.End()
apiUrl := fmt.Sprintf("%s/api/v2/torrents/properties?hash=%s", c.config.Address, hash) apiUrl := fmt.Sprintf("%s/api/v2/torrents/properties?hash=%s", c.config.Address, hash)
result, err := c.doRequest(ctx, &requestData{ result, err := c.doRequest(ctx, &requestData{
url: apiUrl, url: apiUrl,
@ -345,6 +375,9 @@ func (c *client) GetProperties(ctx context.Context, hash string) (*TorrentProper
} }
func (c *client) GetTrackers(ctx context.Context, hash string) ([]*TorrentTracker, error) { func (c *client) GetTrackers(ctx context.Context, hash string) ([]*TorrentTracker, error) {
ctx, span := trace.Start(ctx, "qbittorrent.Torrent.GetTrackers")
defer span.End()
apiUrl := fmt.Sprintf("%s/api/v2/torrents/trackers?hash=%s", c.config.Address, hash) apiUrl := fmt.Sprintf("%s/api/v2/torrents/trackers?hash=%s", c.config.Address, hash)
result, err := c.doRequest(ctx, &requestData{ result, err := c.doRequest(ctx, &requestData{
url: apiUrl, url: apiUrl,
@ -366,6 +399,9 @@ func (c *client) GetTrackers(ctx context.Context, hash string) ([]*TorrentTracke
} }
func (c *client) GetWebSeeds(ctx context.Context, hash string) ([]*TorrentWebSeed, error) { func (c *client) GetWebSeeds(ctx context.Context, hash string) ([]*TorrentWebSeed, error) {
ctx, span := trace.Start(ctx, "qbittorrent.Torrent.GetWebSeeds")
defer span.End()
apiUrl := fmt.Sprintf("%s/api/v2/torrents/webseeds?hash=%s", c.config.Address, hash) apiUrl := fmt.Sprintf("%s/api/v2/torrents/webseeds?hash=%s", c.config.Address, hash)
result, err := c.doRequest(ctx, &requestData{ result, err := c.doRequest(ctx, &requestData{
url: apiUrl, url: apiUrl,
@ -395,6 +431,9 @@ func sliceItoa[E constraints.Integer](in []E) []string {
} }
func (c *client) GetContents(ctx context.Context, hash string, indexes ...int) ([]*TorrentContent, error) { func (c *client) GetContents(ctx context.Context, hash string, indexes ...int) ([]*TorrentContent, error) {
ctx, span := trace.Start(ctx, "qbittorrent.Torrent.GetContents")
defer span.End()
var apiUrl string var apiUrl string
if len(indexes) != 0 { if len(indexes) != 0 {
@ -422,6 +461,9 @@ func (c *client) GetContents(ctx context.Context, hash string, indexes ...int) (
} }
func (c *client) GetPiecesStates(ctx context.Context, hash string) ([]int, error) { func (c *client) GetPiecesStates(ctx context.Context, hash string) ([]int, error) {
ctx, span := trace.Start(ctx, "qbittorrent.Torrent.GetPiecesStates")
defer span.End()
var apiUrl = fmt.Sprintf("%s/api/v2/torrents/pieceStates?hash=%s", c.config.Address, hash) var apiUrl = fmt.Sprintf("%s/api/v2/torrents/pieceStates?hash=%s", c.config.Address, hash)
result, err := c.doRequest(ctx, &requestData{ result, err := c.doRequest(ctx, &requestData{
url: apiUrl, url: apiUrl,
@ -443,6 +485,9 @@ func (c *client) GetPiecesStates(ctx context.Context, hash string) ([]int, error
} }
func (c *client) GetPiecesHashes(ctx context.Context, hash string) ([]string, error) { func (c *client) GetPiecesHashes(ctx context.Context, hash string) ([]string, error) {
ctx, span := trace.Start(ctx, "qbittorrent.Torrent.GetPiecesHashes")
defer span.End()
var apiUrl = fmt.Sprintf("%s/api/v2/torrents/pieceHashes?hash=%s", c.config.Address, hash) var apiUrl = fmt.Sprintf("%s/api/v2/torrents/pieceHashes?hash=%s", c.config.Address, hash)
result, err := c.doRequest(ctx, &requestData{ result, err := c.doRequest(ctx, &requestData{
url: apiUrl, url: apiUrl,
@ -464,6 +509,9 @@ func (c *client) GetPiecesHashes(ctx context.Context, hash string) ([]string, er
} }
func (c *client) PauseTorrents(ctx context.Context, hashes []string) error { func (c *client) PauseTorrents(ctx context.Context, hashes []string) error {
ctx, span := trace.Start(ctx, "qbittorrent.Torrent.PauseTorrents")
defer span.End()
if len(hashes) == 0 { if len(hashes) == 0 {
return errors.New("no torrent hashes provided") return errors.New("no torrent hashes provided")
} }
@ -486,6 +534,9 @@ func (c *client) PauseTorrents(ctx context.Context, hashes []string) error {
} }
func (c *client) ResumeTorrents(ctx context.Context, hashes []string) error { func (c *client) ResumeTorrents(ctx context.Context, hashes []string) error {
ctx, span := trace.Start(ctx, "qbittorrent.Torrent.ResumeTorrents")
defer span.End()
if len(hashes) == 0 { if len(hashes) == 0 {
return errors.New("no torrent hashes provided") return errors.New("no torrent hashes provided")
} }
@ -508,6 +559,9 @@ func (c *client) ResumeTorrents(ctx context.Context, hashes []string) error {
} }
func (c *client) DeleteTorrents(ctx context.Context, hashes []string, deleteFile bool) error { func (c *client) DeleteTorrents(ctx context.Context, hashes []string, deleteFile bool) error {
ctx, span := trace.Start(ctx, "qbittorrent.Torrent.DeleteTorrents")
defer span.End()
if len(hashes) == 0 { if len(hashes) == 0 {
return errors.New("no torrent hashes provided") return errors.New("no torrent hashes provided")
} }
@ -531,6 +585,9 @@ func (c *client) DeleteTorrents(ctx context.Context, hashes []string, deleteFile
} }
func (c *client) RecheckTorrents(ctx context.Context, hashes []string) error { func (c *client) RecheckTorrents(ctx context.Context, hashes []string) error {
ctx, span := trace.Start(ctx, "qbittorrent.Torrent.RecheckTorrents")
defer span.End()
if len(hashes) == 0 { if len(hashes) == 0 {
return errors.New("no torrent hashes provided") return errors.New("no torrent hashes provided")
} }
@ -553,6 +610,9 @@ func (c *client) RecheckTorrents(ctx context.Context, hashes []string) error {
} }
func (c *client) ReAnnounceTorrents(ctx context.Context, hashes []string) error { func (c *client) ReAnnounceTorrents(ctx context.Context, hashes []string) error {
ctx, span := trace.Start(ctx, "qbittorrent.Torrent.ReAnnounceTorrents")
defer span.End()
if len(hashes) == 0 { if len(hashes) == 0 {
return errors.New("no torrent hashes provided") return errors.New("no torrent hashes provided")
} }
@ -575,6 +635,9 @@ func (c *client) ReAnnounceTorrents(ctx context.Context, hashes []string) error
} }
func (c *client) AddNewTorrent(ctx context.Context, opt *TorrentAddOption) error { func (c *client) AddNewTorrent(ctx context.Context, opt *TorrentAddOption) error {
ctx, span := trace.Start(ctx, "qbittorrent.Torrent.AddNewTorrent")
defer span.End()
var requestBody bytes.Buffer var requestBody bytes.Buffer
var writer = multipart.NewWriter(&requestBody) var writer = multipart.NewWriter(&requestBody)
@ -662,6 +725,9 @@ func (c *client) AddNewTorrent(ctx context.Context, opt *TorrentAddOption) error
} }
func (c *client) AddTrackers(ctx context.Context, hash string, urls []string) error { func (c *client) AddTrackers(ctx context.Context, hash string, urls []string) error {
ctx, span := trace.Start(ctx, "qbittorrent.Torrent.AddTrackers")
defer span.End()
if len(urls) == 0 { if len(urls) == 0 {
return errors.New("no torrent tracker provided") return errors.New("no torrent tracker provided")
} }
@ -685,6 +751,9 @@ func (c *client) AddTrackers(ctx context.Context, hash string, urls []string) er
} }
func (c *client) EditTrackers(ctx context.Context, hash, origUrl, newUrl string) error { func (c *client) EditTrackers(ctx context.Context, hash, origUrl, newUrl string) error {
ctx, span := trace.Start(ctx, "qbittorrent.Torrent.EditTrackers")
defer span.End()
var formData = url.Values{} var formData = url.Values{}
formData.Add("origUrl", origUrl) formData.Add("origUrl", origUrl)
formData.Add("newUrl", newUrl) formData.Add("newUrl", newUrl)
@ -706,6 +775,9 @@ func (c *client) EditTrackers(ctx context.Context, hash, origUrl, newUrl string)
} }
func (c *client) RemoveTrackers(ctx context.Context, hash string, urls []string) error { func (c *client) RemoveTrackers(ctx context.Context, hash string, urls []string) error {
ctx, span := trace.Start(ctx, "qbittorrent.Torrent.RemoveTrackers")
defer span.End()
if len(urls) == 0 { if len(urls) == 0 {
return errors.New("no torrent tracker provided") return errors.New("no torrent tracker provided")
} }
@ -729,6 +801,9 @@ func (c *client) RemoveTrackers(ctx context.Context, hash string, urls []string)
} }
func (c *client) AddPeers(ctx context.Context, hashes []string, peers []string) error { func (c *client) AddPeers(ctx context.Context, hashes []string, peers []string) error {
ctx, span := trace.Start(ctx, "qbittorrent.Torrent.AddPeers")
defer span.End()
if len(hashes) == 0 { if len(hashes) == 0 {
return errors.New("no hashes provided") return errors.New("no hashes provided")
} }
@ -755,6 +830,9 @@ func (c *client) AddPeers(ctx context.Context, hashes []string, peers []string)
} }
func (c *client) IncreasePriority(ctx context.Context, hashes []string) error { func (c *client) IncreasePriority(ctx context.Context, hashes []string) error {
ctx, span := trace.Start(ctx, "qbittorrent.Torrent.IncreasePriority")
defer span.End()
if len(hashes) == 0 { if len(hashes) == 0 {
return errors.New("no hashes provided") return errors.New("no hashes provided")
} }
@ -777,6 +855,9 @@ func (c *client) IncreasePriority(ctx context.Context, hashes []string) error {
} }
func (c *client) DecreasePriority(ctx context.Context, hashes []string) error { func (c *client) DecreasePriority(ctx context.Context, hashes []string) error {
ctx, span := trace.Start(ctx, "qbittorrent.Torrent.DecreasePriority")
defer span.End()
if len(hashes) == 0 { if len(hashes) == 0 {
return errors.New("no hashes provided") return errors.New("no hashes provided")
} }
@ -799,6 +880,9 @@ func (c *client) DecreasePriority(ctx context.Context, hashes []string) error {
} }
func (c *client) MaxPriority(ctx context.Context, hashes []string) error { func (c *client) MaxPriority(ctx context.Context, hashes []string) error {
ctx, span := trace.Start(ctx, "qbittorrent.Torrent.MaxPriority")
defer span.End()
if len(hashes) == 0 { if len(hashes) == 0 {
return errors.New("no hashes provided") return errors.New("no hashes provided")
} }
@ -821,6 +905,9 @@ func (c *client) MaxPriority(ctx context.Context, hashes []string) error {
} }
func (c *client) MinPriority(ctx context.Context, hashes []string) error { func (c *client) MinPriority(ctx context.Context, hashes []string) error {
ctx, span := trace.Start(ctx, "qbittorrent.Torrent.MinPriority")
defer span.End()
if len(hashes) == 0 { if len(hashes) == 0 {
return errors.New("no hashes provided") return errors.New("no hashes provided")
} }
@ -843,6 +930,9 @@ func (c *client) MinPriority(ctx context.Context, hashes []string) error {
} }
func (c *client) SetFilePriority(ctx context.Context, hash string, id string, priority int) error { func (c *client) SetFilePriority(ctx context.Context, hash string, id string, priority int) error {
ctx, span := trace.Start(ctx, "qbittorrent.Torrent.SetFilePriority")
defer span.End()
var formData = url.Values{} var formData = url.Values{}
formData.Add("hash", hash) formData.Add("hash", hash)
formData.Add("id", id) formData.Add("id", id)
@ -864,6 +954,9 @@ func (c *client) SetFilePriority(ctx context.Context, hash string, id string, pr
} }
func (c *client) GetDownloadLimit(ctx context.Context, hashes []string) (map[string]int, error) { func (c *client) GetDownloadLimit(ctx context.Context, hashes []string) (map[string]int, error) {
ctx, span := trace.Start(ctx, "qbittorrent.Torrent.GetDownloadLimit")
defer span.End()
if len(hashes) == 0 { if len(hashes) == 0 {
return nil, errors.New("no hashes provided") return nil, errors.New("no hashes provided")
} }
@ -888,6 +981,9 @@ func (c *client) GetDownloadLimit(ctx context.Context, hashes []string) (map[str
} }
func (c *client) SetDownloadLimit(ctx context.Context, hashes []string, limit int) error { func (c *client) SetDownloadLimit(ctx context.Context, hashes []string, limit int) error {
ctx, span := trace.Start(ctx, "qbittorrent.Torrent.SetDownloadLimit")
defer span.End()
if len(hashes) == 0 { if len(hashes) == 0 {
return errors.New("no hashes provided") return errors.New("no hashes provided")
} }
@ -911,6 +1007,9 @@ func (c *client) SetDownloadLimit(ctx context.Context, hashes []string, limit in
} }
func (c *client) SetShareLimit(ctx context.Context, hashes []string, ratioLimit float64, seedingTimeLimit, inactiveSeedingTimeLimit int) error { func (c *client) SetShareLimit(ctx context.Context, hashes []string, ratioLimit float64, seedingTimeLimit, inactiveSeedingTimeLimit int) error {
ctx, span := trace.Start(ctx, "qbittorrent.Torrent.SetShareLimit")
defer span.End()
if len(hashes) == 0 { if len(hashes) == 0 {
return errors.New("no hashes provided") return errors.New("no hashes provided")
} }
@ -936,6 +1035,9 @@ func (c *client) SetShareLimit(ctx context.Context, hashes []string, ratioLimit
} }
func (c *client) GetUploadLimit(ctx context.Context, hashes []string) (map[string]int, error) { func (c *client) GetUploadLimit(ctx context.Context, hashes []string) (map[string]int, error) {
ctx, span := trace.Start(ctx, "qbittorrent.Torrent.GetUploadLimit")
defer span.End()
if len(hashes) == 0 { if len(hashes) == 0 {
return nil, errors.New("no hashes provided") return nil, errors.New("no hashes provided")
} }
@ -960,6 +1062,9 @@ func (c *client) GetUploadLimit(ctx context.Context, hashes []string) (map[strin
} }
func (c *client) SetUploadLimit(ctx context.Context, hashes []string, limit int) error { func (c *client) SetUploadLimit(ctx context.Context, hashes []string, limit int) error {
ctx, span := trace.Start(ctx, "qbittorrent.Torrent.SetUploadLimit")
defer span.End()
if len(hashes) == 0 { if len(hashes) == 0 {
return errors.New("no hashes provided") return errors.New("no hashes provided")
} }
@ -983,6 +1088,9 @@ func (c *client) SetUploadLimit(ctx context.Context, hashes []string, limit int)
} }
func (c *client) SetLocation(ctx context.Context, hashes []string, location string) error { func (c *client) SetLocation(ctx context.Context, hashes []string, location string) error {
ctx, span := trace.Start(ctx, "qbittorrent.Torrent.SetLocation")
defer span.End()
if len(hashes) == 0 { if len(hashes) == 0 {
return errors.New("no hashes provided") return errors.New("no hashes provided")
} }
@ -1006,6 +1114,9 @@ func (c *client) SetLocation(ctx context.Context, hashes []string, location stri
} }
func (c *client) SetName(ctx context.Context, hash string, name string) error { func (c *client) SetName(ctx context.Context, hash string, name string) error {
ctx, span := trace.Start(ctx, "qbittorrent.Torrent.SetName")
defer span.End()
var formData = url.Values{} var formData = url.Values{}
formData.Add("hash", hash) formData.Add("hash", hash)
formData.Add("name", name) formData.Add("name", name)
@ -1026,6 +1137,9 @@ func (c *client) SetName(ctx context.Context, hash string, name string) error {
} }
func (c *client) SetCategory(ctx context.Context, hashes []string, category string) error { func (c *client) SetCategory(ctx context.Context, hashes []string, category string) error {
ctx, span := trace.Start(ctx, "qbittorrent.Torrent.SetCategory")
defer span.End()
if len(hashes) == 0 { if len(hashes) == 0 {
return errors.New("no hashes provided") return errors.New("no hashes provided")
} }
@ -1049,6 +1163,9 @@ func (c *client) SetCategory(ctx context.Context, hashes []string, category stri
} }
func (c *client) GetCategories(ctx context.Context) (map[string]*TorrentCategory, error) { func (c *client) GetCategories(ctx context.Context) (map[string]*TorrentCategory, error) {
ctx, span := trace.Start(ctx, "qbittorrent.Torrent.GetCategories")
defer span.End()
var apiUrl = fmt.Sprintf("%s/api/v2/torrents/categories", c.config.Address) var apiUrl = fmt.Sprintf("%s/api/v2/torrents/categories", c.config.Address)
result, err := c.doRequest(ctx, &requestData{ result, err := c.doRequest(ctx, &requestData{
url: apiUrl, url: apiUrl,
@ -1067,6 +1184,9 @@ func (c *client) GetCategories(ctx context.Context) (map[string]*TorrentCategory
} }
func (c *client) AddNewCategory(ctx context.Context, category, savePath string) error { func (c *client) AddNewCategory(ctx context.Context, category, savePath string) error {
ctx, span := trace.Start(ctx, "qbittorrent.Torrent.AddNewCategory")
defer span.End()
var formData = url.Values{} var formData = url.Values{}
formData.Add("category", category) formData.Add("category", category)
formData.Add("savePath", savePath) formData.Add("savePath", savePath)
@ -1087,6 +1207,9 @@ func (c *client) AddNewCategory(ctx context.Context, category, savePath string)
} }
func (c *client) EditCategory(ctx context.Context, category, savePath string) error { func (c *client) EditCategory(ctx context.Context, category, savePath string) error {
ctx, span := trace.Start(ctx, "qbittorrent.Torrent.EditCategory")
defer span.End()
var formData = url.Values{} var formData = url.Values{}
formData.Add("category", category) formData.Add("category", category)
formData.Add("savePath", savePath) formData.Add("savePath", savePath)
@ -1107,6 +1230,9 @@ func (c *client) EditCategory(ctx context.Context, category, savePath string) er
} }
func (c *client) RemoveCategories(ctx context.Context, categories []string) error { func (c *client) RemoveCategories(ctx context.Context, categories []string) error {
ctx, span := trace.Start(ctx, "qbittorrent.Torrent.RemoveCategories")
defer span.End()
var formData = url.Values{} var formData = url.Values{}
formData.Add("categories", strings.Join(categories, "\n")) formData.Add("categories", strings.Join(categories, "\n"))
var apiUrl = fmt.Sprintf("%s/api/v2/torrents/removeCategories", c.config.Address) var apiUrl = fmt.Sprintf("%s/api/v2/torrents/removeCategories", c.config.Address)
@ -1146,6 +1272,9 @@ func (c *client) AddTags(ctx context.Context, hashes []string, tags []string) er
} }
func (c *client) RemoveTags(ctx context.Context, hashes []string, tags []string) error { func (c *client) RemoveTags(ctx context.Context, hashes []string, tags []string) error {
ctx, span := trace.Start(ctx, "qbittorrent.Torrent.RemoveTags")
defer span.End()
var formData = url.Values{} var formData = url.Values{}
formData.Add("hashes", strings.Join(hashes, "|")) formData.Add("hashes", strings.Join(hashes, "|"))
formData.Add("tags", strings.Join(tags, ",")) formData.Add("tags", strings.Join(tags, ","))
@ -1166,6 +1295,9 @@ func (c *client) RemoveTags(ctx context.Context, hashes []string, tags []string)
} }
func (c *client) GetTags(ctx context.Context) ([]string, error) { func (c *client) GetTags(ctx context.Context) ([]string, error) {
ctx, span := trace.Start(ctx, "qbittorrent.Torrent.GetTags")
defer span.End()
var apiUrl = fmt.Sprintf("%s/api/v2/torrents/tags", c.config.Address) var apiUrl = fmt.Sprintf("%s/api/v2/torrents/tags", c.config.Address)
result, err := c.doRequest(ctx, &requestData{ result, err := c.doRequest(ctx, &requestData{
url: apiUrl, url: apiUrl,
@ -1184,6 +1316,9 @@ func (c *client) GetTags(ctx context.Context) ([]string, error) {
} }
func (c *client) CreateTags(ctx context.Context, tags []string) error { func (c *client) CreateTags(ctx context.Context, tags []string) error {
ctx, span := trace.Start(ctx, "qbittorrent.Torrent.CreateTags")
defer span.End()
var formData = url.Values{} var formData = url.Values{}
formData.Add("tags", strings.Join(tags, ",")) formData.Add("tags", strings.Join(tags, ","))
var apiUrl = fmt.Sprintf("%s/api/v2/torrents/createTags", c.config.Address) var apiUrl = fmt.Sprintf("%s/api/v2/torrents/createTags", c.config.Address)
@ -1203,6 +1338,9 @@ func (c *client) CreateTags(ctx context.Context, tags []string) error {
} }
func (c *client) DeleteTags(ctx context.Context, tags []string) error { func (c *client) DeleteTags(ctx context.Context, tags []string) error {
ctx, span := trace.Start(ctx, "qbittorrent.Torrent.DeleteTags")
defer span.End()
var formData = url.Values{} var formData = url.Values{}
formData.Add("tags", strings.Join(tags, ",")) formData.Add("tags", strings.Join(tags, ","))
var apiUrl = fmt.Sprintf("%s/api/v2/torrents/deleteTags", c.config.Address) var apiUrl = fmt.Sprintf("%s/api/v2/torrents/deleteTags", c.config.Address)
@ -1222,6 +1360,9 @@ func (c *client) DeleteTags(ctx context.Context, tags []string) error {
} }
func (c *client) SetAutomaticManagement(ctx context.Context, hashes []string, enable bool) error { func (c *client) SetAutomaticManagement(ctx context.Context, hashes []string, enable bool) error {
ctx, span := trace.Start(ctx, "qbittorrent.Torrent.SetAutomaticManagement")
defer span.End()
var formData = url.Values{} var formData = url.Values{}
formData.Add("hashes", strings.Join(hashes, "|")) formData.Add("hashes", strings.Join(hashes, "|"))
formData.Add("enable", strconv.FormatBool(enable)) formData.Add("enable", strconv.FormatBool(enable))
@ -1242,6 +1383,9 @@ func (c *client) SetAutomaticManagement(ctx context.Context, hashes []string, en
} }
func (c *client) ToggleSequentialDownload(ctx context.Context, hashes []string) error { func (c *client) ToggleSequentialDownload(ctx context.Context, hashes []string) error {
ctx, span := trace.Start(ctx, "qbittorrent.Torrent.ToggleSequentialDownload")
defer span.End()
var formData = url.Values{} var formData = url.Values{}
formData.Add("hashes", strings.Join(hashes, "|")) formData.Add("hashes", strings.Join(hashes, "|"))
var apiUrl = fmt.Sprintf("%s/api/v2/torrents/toggleSequentialDownload", c.config.Address) var apiUrl = fmt.Sprintf("%s/api/v2/torrents/toggleSequentialDownload", c.config.Address)
@ -1261,6 +1405,9 @@ func (c *client) ToggleSequentialDownload(ctx context.Context, hashes []string)
} }
func (c *client) SetFirstLastPiecePriority(ctx context.Context, hashes []string) error { func (c *client) SetFirstLastPiecePriority(ctx context.Context, hashes []string) error {
ctx, span := trace.Start(ctx, "qbittorrent.Torrent.SetFirstLastPiecePriority")
defer span.End()
var formData = url.Values{} var formData = url.Values{}
formData.Add("hashes", strings.Join(hashes, "|")) formData.Add("hashes", strings.Join(hashes, "|"))
var apiUrl = fmt.Sprintf("%s/api/v2/torrents/toggleFirstLastPiecePrio", c.config.Address) var apiUrl = fmt.Sprintf("%s/api/v2/torrents/toggleFirstLastPiecePrio", c.config.Address)
@ -1280,6 +1427,9 @@ func (c *client) SetFirstLastPiecePriority(ctx context.Context, hashes []string)
} }
func (c *client) SetForceStart(ctx context.Context, hashes []string, force bool) error { func (c *client) SetForceStart(ctx context.Context, hashes []string, force bool) error {
ctx, span := trace.Start(ctx, "qbittorrent.Torrent.SetForceStart")
defer span.End()
var formData = url.Values{} var formData = url.Values{}
formData.Add("hashes", strings.Join(hashes, "|")) formData.Add("hashes", strings.Join(hashes, "|"))
formData.Add("value", strconv.FormatBool(force)) formData.Add("value", strconv.FormatBool(force))
@ -1300,6 +1450,9 @@ func (c *client) SetForceStart(ctx context.Context, hashes []string, force bool)
} }
func (c *client) SetSuperSeeding(ctx context.Context, hashes []string, enable bool) error { func (c *client) SetSuperSeeding(ctx context.Context, hashes []string, enable bool) error {
ctx, span := trace.Start(ctx, "qbittorrent.Torrent.SetSuperSeeding")
defer span.End()
var formData = url.Values{} var formData = url.Values{}
formData.Add("hashes", strings.Join(hashes, "|")) formData.Add("hashes", strings.Join(hashes, "|"))
formData.Add("value", strconv.FormatBool(enable)) formData.Add("value", strconv.FormatBool(enable))
@ -1320,6 +1473,9 @@ func (c *client) SetSuperSeeding(ctx context.Context, hashes []string, enable bo
} }
func (c *client) RenameFile(ctx context.Context, hash, oldPath, newPath string) error { func (c *client) RenameFile(ctx context.Context, hash, oldPath, newPath string) error {
ctx, span := trace.Start(ctx, "qbittorrent.Torrent.RenameFile")
defer span.End()
var formData = url.Values{} var formData = url.Values{}
formData.Add("oldPath", oldPath) formData.Add("oldPath", oldPath)
formData.Add("newPath", newPath) formData.Add("newPath", newPath)
@ -1341,6 +1497,9 @@ func (c *client) RenameFile(ctx context.Context, hash, oldPath, newPath string)
} }
func (c *client) RenameFolder(ctx context.Context, hash, oldPath, newPath string) error { func (c *client) RenameFolder(ctx context.Context, hash, oldPath, newPath string) error {
ctx, span := trace.Start(ctx, "qbittorrent.Torrent.RenameFolder")
defer span.End()
var formData = url.Values{} var formData = url.Values{}
formData.Add("oldPath", oldPath) formData.Add("oldPath", oldPath)
formData.Add("newPath", newPath) formData.Add("newPath", newPath)

View file

@ -47,6 +47,9 @@ type Transfer interface {
} }
func (c *client) GlobalStatusBar(ctx context.Context) (*TransferStatusBar, error) { func (c *client) GlobalStatusBar(ctx context.Context) (*TransferStatusBar, error) {
ctx, span := trace.Start(ctx, "qbittorrent.Transfer.GlobalStatusBar")
defer span.End()
apiUrl := fmt.Sprintf("%s/api/v2/transfer/info", c.config.Address) apiUrl := fmt.Sprintf("%s/api/v2/transfer/info", c.config.Address)
result, err := c.doRequest(ctx, &requestData{ result, err := c.doRequest(ctx, &requestData{
url: apiUrl, url: apiUrl,
@ -68,6 +71,9 @@ func (c *client) GlobalStatusBar(ctx context.Context) (*TransferStatusBar, error
} }
func (c *client) BanPeers(ctx context.Context, peers []string) error { func (c *client) BanPeers(ctx context.Context, peers []string) error {
ctx, span := trace.Start(ctx, "qbittorrent.Transfer.BanPeers")
defer span.End()
apiUrl := fmt.Sprintf("%s/api/v2/transfer/banPeers", c.config.Address) apiUrl := fmt.Sprintf("%s/api/v2/transfer/banPeers", c.config.Address)
var form = url.Values{} var form = url.Values{}
form.Add("peers", strings.Join(peers, "|")) form.Add("peers", strings.Join(peers, "|"))
@ -88,6 +94,9 @@ func (c *client) BanPeers(ctx context.Context, peers []string) error {
} }
func (c *client) GetSpeedLimitsMode(ctx context.Context) (string, error) { func (c *client) GetSpeedLimitsMode(ctx context.Context) (string, error) {
ctx, span := trace.Start(ctx, "qbittorrent.Transfer.GetSpeedLimitsMode")
defer span.End()
apiUrl := fmt.Sprintf("%s/api/v2/transfer/speedLimitsMode", c.config.Address) apiUrl := fmt.Sprintf("%s/api/v2/transfer/speedLimitsMode", c.config.Address)
result, err := c.doRequest(ctx, &requestData{ result, err := c.doRequest(ctx, &requestData{
url: apiUrl, url: apiUrl,
@ -104,6 +113,9 @@ func (c *client) GetSpeedLimitsMode(ctx context.Context) (string, error) {
} }
func (c *client) ToggleSpeedLimitsMode(ctx context.Context) error { func (c *client) ToggleSpeedLimitsMode(ctx context.Context) error {
ctx, span := trace.Start(ctx, "qbittorrent.Transfer.ToggleSpeedLimitsMode")
defer span.End()
apiUrl := fmt.Sprintf("%s/api/v2/transfer/toggleSpeedLimitsMode", c.config.Address) apiUrl := fmt.Sprintf("%s/api/v2/transfer/toggleSpeedLimitsMode", c.config.Address)
result, err := c.doRequest(ctx, &requestData{ result, err := c.doRequest(ctx, &requestData{
url: apiUrl, url: apiUrl,
@ -121,6 +133,9 @@ func (c *client) ToggleSpeedLimitsMode(ctx context.Context) error {
} }
func (c *client) GetGlobalUploadLimit(ctx context.Context) (string, error) { func (c *client) GetGlobalUploadLimit(ctx context.Context) (string, error) {
ctx, span := trace.Start(ctx, "qbittorrent.Transfer.GetGlobalUploadLimit")
defer span.End()
apiUrl := fmt.Sprintf("%s/api/v2/transfer/uploadLimit", c.config.Address) apiUrl := fmt.Sprintf("%s/api/v2/transfer/uploadLimit", c.config.Address)
result, err := c.doRequest(ctx, &requestData{ result, err := c.doRequest(ctx, &requestData{
url: apiUrl, url: apiUrl,
@ -137,6 +152,9 @@ func (c *client) GetGlobalUploadLimit(ctx context.Context) (string, error) {
} }
func (c *client) SetGlobalUploadLimit(ctx context.Context, limit int) error { func (c *client) SetGlobalUploadLimit(ctx context.Context, limit int) error {
ctx, span := trace.Start(ctx, "qbittorrent.Transfer.SetGlobalUploadLimit")
defer span.End()
apiUrl := fmt.Sprintf("%s/api/v2/transfer/setUploadLimit?limit=%d", c.config.Address, limit) apiUrl := fmt.Sprintf("%s/api/v2/transfer/setUploadLimit?limit=%d", c.config.Address, limit)
result, err := c.doRequest(ctx, &requestData{ result, err := c.doRequest(ctx, &requestData{
url: apiUrl, url: apiUrl,
@ -153,6 +171,9 @@ func (c *client) SetGlobalUploadLimit(ctx context.Context, limit int) error {
} }
func (c *client) GetGlobalDownloadLimit(ctx context.Context) (string, error) { func (c *client) GetGlobalDownloadLimit(ctx context.Context) (string, error) {
ctx, span := trace.Start(ctx, "qbittorrent.Transfer.GetGlobalDownloadLimit")
defer span.End()
apiUrl := fmt.Sprintf("%s/api/v2/transfer/downloadLimit", c.config.Address) apiUrl := fmt.Sprintf("%s/api/v2/transfer/downloadLimit", c.config.Address)
result, err := c.doRequest(ctx, &requestData{ result, err := c.doRequest(ctx, &requestData{
url: apiUrl, url: apiUrl,
@ -169,6 +190,9 @@ func (c *client) GetGlobalDownloadLimit(ctx context.Context) (string, error) {
} }
func (c *client) SetGlobalDownloadLimit(ctx context.Context, limit int) error { func (c *client) SetGlobalDownloadLimit(ctx context.Context, limit int) error {
ctx, span := trace.Start(ctx, "qbittorrent.Transfer.SetGlobalDownloadLimit")
defer span.End()
apiUrl := fmt.Sprintf("%s/api/v2/transfer/setDownloadLimit?limit=%d", c.config.Address, limit) apiUrl := fmt.Sprintf("%s/api/v2/transfer/setDownloadLimit?limit=%d", c.config.Address, limit)
result, err := c.doRequest(ctx, &requestData{ result, err := c.doRequest(ctx, &requestData{
url: apiUrl, url: apiUrl,