
Security News
GitHub Actions Pricing Whiplash: Self-Hosted Actions Billing Change Postponed
GitHub postponed a new billing model for self-hosted Actions after developer pushback, but moved forward with hosted runner price cuts on January 1.
github.com/jfxdev/go-qbittorrent
Advanced tools
A high-performance Go client for the qBittorrent Web API with advanced optimizations for cookies and retries.
go get github.com/jfxdev/go-qbt
config := qbt.Config{
BaseURL: "http://localhost:8080",
Username: "admin",
Password: "password",
RequestTimeout: 45 * time.Second, // Custom timeout
MaxRetries: 5, // Number of attempts
RetryBackoff: 2 * time.Second, // Base delay between attempts
Debug: false, // Enable debug logging (default: false)
}
Enable debug logging to see detailed information about:
config := qbt.Config{
BaseURL: "http://localhost:8080",
Username: "admin",
Password: "password",
Debug: true, // Enable verbose logging
}
Note: In production environments, keep Debug: false to avoid excessive logging.
// Create client
client, err := qbt.New(config)
if err != nil {
log.Fatal(err)
}
defer client.Close()
// List torrents (automatic retry and cookie management)
torrents, err := client.ListTorrents(qbt.ListOptions{})
if err != nil {
log.Printf("Error: %v", err)
}
// Add torrent via magnet link
err = client.AddTorrentLink(qbt.TorrentConfig{
MagnetURI: "magnet:?xt=urn:btih:...",
Directory: "/downloads",
Category: "movies",
Paused: false,
})
if err != nil {
log.Printf("Error adding torrent: %v", err)
}
ListTorrents(opts ListOptions) - List all torrents with optional filteringAddTorrentLink(opts TorrentConfig) - Add a torrent via magnet linkPauseTorrents(hash string) - Pause specific torrentResumeTorrents(hash string) - Resume specific torrentDeleteTorrents(hash string, deleteFiles bool) - Delete torrent with optional file deletionIncreaseTorrentsPriority(hash string) - Increase torrent priorityDecreaseTorrentsPriority(hash string) - Decrease torrent priorityAddTorrentTags(hash string, tags []string) - Add tags to torrentDeleteTorrentTags(hash string, tags []string) - Remove tags from torrentSetCategory(hash string, category string) - Set torrent categoryRemoveCategory(hash string) - Remove torrent categoryGetTorrent(hash string) - Get specific torrent informationGetTorrentProperties(hash string) - Get detailed torrent propertiesGetTorrentFiles(hash string) - Get torrent file listGetTorrentTrackers(hash string) - Get torrent tracker informationGetTorrentPeers(hash string) - Get torrent peer informationForceRecheck(hash string) - Force torrent recheckForceReannounce(hash string) - Force torrent reannounceForceStart(hash string) - Force start torrentSetTorrentDownloadLimit(hash string, limit int) - Set torrent download speed limitSetTorrentUploadLimit(hash string, limit int) - Set torrent upload speed limitSetTorrentShareLimit(hash string, ratioLimit float64, seedingTimeLimit int) - Set torrent share limitsGetCategories() - Get all categoriesCreateCategory(name, savePath string) - Create new categoryDeleteCategory(name string) - Delete categoryGetGlobalSettings() - Get global qBittorrent settingsSetGlobalSettings(settings GlobalSettings) - Set global qBittorrent settingsSetDownloadSpeedLimit(limit int) - Set global download speed limitSetUploadSpeedLimit(limit int) - Set global upload speed limitToggleSpeedLimits() - Toggle speed limits modeSetMaxActiveDownloads(maxDownloads int) - Set maximum number of active downloadsSetMaxActiveUploads(maxUploads int) - Set maximum number of active uploadsSetMaxActiveTorrents(maxTorrents int) - Set maximum number of active torrentsSetMaxActiveCheckingTorrents(maxChecking int) - Set maximum number of active checking torrentsSetMaxActiveTorrentLimits(maxDownloads, maxUploads, maxTorrents, maxChecking int) - Set all maximum active torrent limits at onceGetMaxActiveDownloads() - Get current maximum number of active downloadsGetMaxActiveUploads() - Get current maximum number of active uploadsGetMaxActiveTorrents() - Get current maximum number of active torrentsGetMaxActiveCheckingTorrents() - Get current maximum number of active checking torrentsGetMainData() - Get main server data and sync informationGetTransferInfo() - Get transfer statistics and informationGetNetworkInfo() - Get network informationGetAppVersion() - Get qBittorrent application versionGetAPIVersion() - Get Web API versionGetBuildInfo() - Get build informationGetLogs(normal, info, warning, critical bool, lastKnownID int) - Get system logsGetRSSFeeds(withData bool) - Get RSS feedsAddRSSFeed(url, path string) - Add RSS feedRemoveRSSFeed(path string) - Remove RSS feedThis SDK has been specially optimized for seedbox usage, including essential features for daily management:
// Monitor tracker performance
trackers, err := client.GetTorrentTrackers("torrent_hash")
if err != nil {
log.Printf("Error getting trackers: %v", err)
}
// Configure ratio limit for seeding
err = client.SetTorrentShareLimit("torrent_hash", 2.0, 168) // 2.0 ratio, 168 hours
if err != nil {
log.Printf("Error configuring ratio: %v", err)
}
// Get system logs for debugging
logs, err := client.GetLogs(true, true, true, true, 0)
if err != nil {
log.Printf("Error getting logs: %v", err)
}
// Configure category for organization
err = client.CreateCategory("movies", "/downloads/movies")
if err != nil {
log.Printf("Error creating category: %v", err)
}
// Global timeout for all operations
config.RequestTimeout = 60 * time.Second
// Retry configuration
config.MaxRetries = 10 // Max attempts
config.RetryBackoff = 1 * time.Second // Base delay
// Cookie settings are automatic:
// - Expiration: 24 hours
// - Check: every 5 minutes
// - Cache: Smart with automatic invalidation
When debug mode is enabled (Debug: true), the client provides detailed logs for:
Example debug output:
Login successful, cookies cached
GET /api/v2/torrents/info failed (attempt 1/3), retrying in 2s: authentication error: status code 403
Login successful, cookies cached
GET /api/v2/torrents/info succeeded after 1 retries
Cookies expired, cleared from cache
package main
import (
"fmt"
"log"
"time"
"github.com/jfxdev/go-qbt"
)
func main() {
config := qbt.Config{
BaseURL: "http://localhost:8080",
Username: "admin",
Password: "password",
RequestTimeout: 30 * time.Second,
MaxRetries: 3,
RetryBackoff: 2 * time.Second,
Debug: false,
}
client, err := qbt.New(config)
if err != nil {
log.Fatal(err)
}
defer client.Close()
// Get current maximum active torrent limits
maxDownloads, _ := client.GetMaxActiveDownloads()
maxUploads, _ := client.GetMaxActiveUploads()
maxTorrents, _ := client.GetMaxActiveTorrents()
maxChecking, _ := client.GetMaxActiveCheckingTorrents()
fmt.Printf("Current limits - Downloads: %d, Uploads: %d, Torrents: %d, Checking: %d\n",
maxDownloads, maxUploads, maxTorrents, maxChecking)
// Set individual limits
err = client.SetMaxActiveDownloads(5)
if err != nil {
log.Printf("Error setting max downloads: %v", err)
}
err = client.SetMaxActiveUploads(3)
if err != nil {
log.Printf("Error setting max uploads: %v", err)
}
// Set all limits at once
err = client.SetMaxActiveTorrentLimits(8, 4, 15, 2)
if err != nil {
log.Printf("Error setting all limits: %v", err)
} else {
fmt.Println("Successfully set all maximum active torrent limits")
}
}
package main
import (
"fmt"
"log"
"time"
"github.com/jfxdev/go-qbt"
)
func main() {
// Configure client
config := qbt.Config{
BaseURL: "http://localhost:8080",
Username: "admin",
Password: "password",
RequestTimeout: 30 * time.Second,
MaxRetries: 3,
RetryBackoff: 2 * time.Second,
Debug: false, // Set to true for verbose logging
}
// Create client
client, err := qbt.New(config)
if err != nil {
log.Fatal(err)
}
defer client.Close()
// Get system information
version, err := client.GetAppVersion()
if err != nil {
log.Printf("Error getting version: %v", err)
} else {
fmt.Printf("qBittorrent version: %s\n", version)
}
// List torrents
torrents, err := client.ListTorrents(qbt.ListOptions{})
if err != nil {
log.Printf("Error listing torrents: %v", err)
return
}
fmt.Printf("Found %d torrents\n", len(torrents))
// Add a new torrent
err = client.AddTorrentLink(qbt.TorrentConfig{
MagnetURI: "magnet:?xt=urn:btih:...",
Directory: "/downloads",
Category: "movies",
Paused: false,
})
if err != nil {
log.Printf("Error adding torrent: %v", err)
}
// Get transfer info
info, err := client.GetTransferInfo()
if err != nil {
log.Printf("Error getting transfer info: %v", err)
} else {
fmt.Printf("Download speed: %d bytes/s\n", info.DlSpeed)
fmt.Printf("Upload speed: %d bytes/s\n", info.UpSpeed)
}
}
The client implements robust error handling:
The client now properly handles qBittorrent session timeouts. When the server returns a 403 (Forbidden) or 401 (Unauthorized) error due to an expired session:
This fixes the issue where, after several hours, the client would continuously return "forbidden" errors because the qBittorrent Web UI session had expired (configured via WebUISessionTimeout in qBittorrent settings), while the client still considered its cached cookies as valid.
Contributions are welcome! Please open an issue or pull request.
This project is licensed under the GNU General Public License v3.0 - see LICENSE for details.
FAQs
Unknown package
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Security News
GitHub postponed a new billing model for self-hosted Actions after developer pushback, but moved forward with hosted runner price cuts on January 1.

Research
Destructive malware is rising across open source registries, using delays and kill switches to wipe code, break builds, and disrupt CI/CD.

Security News
Socket CTO Ahmad Nassri shares practical AI coding techniques, tools, and team workflows, plus what still feels noisy and why shipping remains human-led.