tstor/pkg/qbittorrent/application.go
2024-09-08 21:39:11 +03:00

396 lines
21 KiB
Go

package qbittorrent
import (
"bytes"
"context"
"encoding/json"
"errors"
"fmt"
"net/http"
)
type Application interface {
// Version get application version
Version(context.Context) (string, error)
// WebApiVersion get webapi version
WebApiVersion(context.Context) (string, error)
// BuildInfo get build info
BuildInfo(context.Context) (*BuildInfo, error)
// Shutdown exit application
Shutdown(context.Context) error
// GetPreferences get application preferences
GetPreferences(context.Context) (*Preferences, error)
// SetPreferences set application preferences
SetPreferences(context.Context, *Preferences) error
// DefaultSavePath get default save path
DefaultSavePath(context.Context) (string, error)
}
type BuildInfo struct {
BitNess int `json:"bitness,omitempty"`
Boost string `json:"boost,omitempty"`
LibTorrent string `json:"libtorrent,omitempty"`
Openssl string `json:"openssl,omitempty"`
QT string `json:"qt,omitempty"`
Zlib string `json:"zlib,omitempty"`
}
type Preferences struct {
AddToTopOfQueue bool `json:"add_to_top_of_queue,omitempty"`
AddTrackers string `json:"add_trackers,omitempty"`
AddTrackersEnabled bool `json:"add_trackers_enabled,omitempty"`
AltDlLimit int `json:"alt_dl_limit,omitempty"`
AltUpLimit int `json:"alt_up_limit,omitempty"`
AlternativeWebuiEnabled bool `json:"alternative_webui_enabled,omitempty"`
AlternativeWebuiPath string `json:"alternative_webui_path,omitempty"`
AnnounceIP string `json:"announce_ip,omitempty"`
AnnounceToAllTiers bool `json:"announce_to_all_tiers,omitempty"`
AnnounceToAllTrackers bool `json:"announce_to_all_trackers,omitempty"`
AnonymousMode bool `json:"anonymous_mode,omitempty"`
AsyncIoThreads int `json:"async_io_threads,omitempty"`
AutoDeleteMode int `json:"auto_delete_mode,omitempty"`
AutoTmmEnabled bool `json:"auto_tmm_enabled,omitempty"`
AutorunEnabled bool `json:"autorun_enabled,omitempty"`
AutorunOnTorrentAddedEnabled bool `json:"autorun_on_torrent_added_enabled,omitempty"`
AutorunOnTorrentAddedProgram string `json:"autorun_on_torrent_added_program,omitempty"`
AutorunProgram string `json:"autorun_program,omitempty"`
BannedIPs string `json:"banned_IPs,omitempty"`
BdecodeDepthLimit int `json:"bdecode_depth_limit,omitempty"`
BdecodeTokenLimit int `json:"bdecode_token_limit,omitempty"`
BittorrentProtocol int `json:"bittorrent_protocol,omitempty"`
BlockPeersOnPrivilegedPorts bool `json:"block_peers_on_privileged_ports,omitempty"`
BypassAuthSubnetWhitelist string `json:"bypass_auth_subnet_whitelist,omitempty"`
BypassAuthSubnetWhitelistEnabled bool `json:"bypass_auth_subnet_whitelist_enabled,omitempty"`
BypassLocalAuth bool `json:"bypass_local_auth,omitempty"`
CategoryChangedTmmEnabled bool `json:"category_changed_tmm_enabled,omitempty"`
CheckingMemoryUse int `json:"checking_memory_use,omitempty"`
ConnectionSpeed int `json:"connection_speed,omitempty"`
CurrentInterfaceAddress string `json:"current_interface_address,omitempty"`
CurrentInterfaceName string `json:"current_interface_name,omitempty"`
CurrentNetworkInterface string `json:"current_network_interface,omitempty"`
Dht bool `json:"dht,omitempty"`
DiskCache int `json:"disk_cache,omitempty"`
DiskCacheTTL int `json:"disk_cache_ttl,omitempty"`
DiskIoReadMode int `json:"disk_io_read_mode,omitempty"`
DiskIoType int `json:"disk_io_type,omitempty"`
DiskIoWriteMode int `json:"disk_io_write_mode,omitempty"`
DiskQueueSize int `json:"disk_queue_size,omitempty"`
DlLimit int `json:"dl_limit,omitempty"`
DontCountSlowTorrents bool `json:"dont_count_slow_torrents,omitempty"`
DyndnsDomain string `json:"dyndns_domain,omitempty"`
DyndnsEnabled bool `json:"dyndns_enabled,omitempty"`
DyndnsPassword string `json:"dyndns_password,omitempty"`
DyndnsService int `json:"dyndns_service,omitempty"`
DyndnsUsername string `json:"dyndns_username,omitempty"`
EmbeddedTrackerPort int `json:"embedded_tracker_port,omitempty"`
EmbeddedTrackerPortForwarding bool `json:"embedded_tracker_port_forwarding,omitempty"`
EnableCoalesceReadWrite bool `json:"enable_coalesce_read_write,omitempty"`
EnableEmbeddedTracker bool `json:"enable_embedded_tracker,omitempty"`
EnableMultiConnectionsFromSameIP bool `json:"enable_multi_connections_from_same_ip,omitempty"`
EnablePieceExtentAffinity bool `json:"enable_piece_extent_affinity,omitempty"`
EnableUploadSuggestions bool `json:"enable_upload_suggestions,omitempty"`
Encryption int `json:"encryption,omitempty"`
ExcludedFileNames string `json:"excluded_file_names,omitempty"`
ExcludedFileNamesEnabled bool `json:"excluded_file_names_enabled,omitempty"`
ExportDir string `json:"export_dir,omitempty"`
ExportDirFin string `json:"export_dir_fin,omitempty"`
FileLogAge int `json:"file_log_age,omitempty"`
FileLogAgeType int `json:"file_log_age_type,omitempty"`
FileLogBackupEnabled bool `json:"file_log_backup_enabled,omitempty"`
FileLogDeleteOld bool `json:"file_log_delete_old,omitempty"`
FileLogEnabled bool `json:"file_log_enabled,omitempty"`
FileLogMaxSize int `json:"file_log_max_size,omitempty"`
FileLogPath string `json:"file_log_path,omitempty"`
FilePoolSize int `json:"file_pool_size,omitempty"`
HashingThreads int `json:"hashing_threads,omitempty"`
I2PAddress string `json:"i2p_address,omitempty"`
I2PEnabled bool `json:"i2p_enabled,omitempty"`
I2PInboundLength int `json:"i2p_inbound_length,omitempty"`
I2PInboundQuantity int `json:"i2p_inbound_quantity,omitempty"`
I2PMixedMode bool `json:"i2p_mixed_mode,omitempty"`
I2POutboundLength int `json:"i2p_outbound_length,omitempty"`
I2POutboundQuantity int `json:"i2p_outbound_quantity,omitempty"`
I2PPort int `json:"i2p_port,omitempty"`
IdnSupportEnabled bool `json:"idn_support_enabled,omitempty"`
IncompleteFilesExt bool `json:"incomplete_files_ext,omitempty"`
IPFilterEnabled bool `json:"ip_filter_enabled,omitempty"`
IPFilterPath string `json:"ip_filter_path,omitempty"`
IPFilterTrackers bool `json:"ip_filter_trackers,omitempty"`
LimitLanPeers bool `json:"limit_lan_peers,omitempty"`
LimitTCPOverhead bool `json:"limit_tcp_overhead,omitempty"`
LimitUtpRate bool `json:"limit_utp_rate,omitempty"`
ListenPort int `json:"listen_port,omitempty"`
Locale string `json:"locale,omitempty"`
Lsd bool `json:"lsd,omitempty"`
MailNotificationAuthEnabled bool `json:"mail_notification_auth_enabled,omitempty"`
MailNotificationEmail string `json:"mail_notification_email,omitempty"`
MailNotificationEnabled bool `json:"mail_notification_enabled,omitempty"`
MailNotificationPassword string `json:"mail_notification_password,omitempty"`
MailNotificationSender string `json:"mail_notification_sender,omitempty"`
MailNotificationSMTP string `json:"mail_notification_smtp,omitempty"`
MailNotificationSslEnabled bool `json:"mail_notification_ssl_enabled,omitempty"`
MailNotificationUsername string `json:"mail_notification_username,omitempty"`
MaxActiveCheckingTorrents int `json:"max_active_checking_torrents,omitempty"`
MaxActiveDownloads int `json:"max_active_downloads,omitempty"`
MaxActiveTorrents int `json:"max_active_torrents,omitempty"`
MaxActiveUploads int `json:"max_active_uploads,omitempty"`
MaxConcurrentHTTPAnnounces int `json:"max_concurrent_http_announces,omitempty"`
MaxConnec int `json:"max_connec,omitempty"`
MaxConnecPerTorrent int `json:"max_connec_per_torrent,omitempty"`
MaxInactiveSeedingTime int `json:"max_inactive_seeding_time,omitempty"`
MaxInactiveSeedingTimeEnabled bool `json:"max_inactive_seeding_time_enabled,omitempty"`
MaxRatio int `json:"max_ratio,omitempty"`
MaxRatioAct int `json:"max_ratio_act,omitempty"`
MaxRatioEnabled bool `json:"max_ratio_enabled,omitempty"`
MaxSeedingTime int `json:"max_seeding_time,omitempty"`
MaxSeedingTimeEnabled bool `json:"max_seeding_time_enabled,omitempty"`
MaxUploads int `json:"max_uploads,omitempty"`
MaxUploadsPerTorrent int `json:"max_uploads_per_torrent,omitempty"`
MemoryWorkingSetLimit int `json:"memory_working_set_limit,omitempty"`
MergeTrackers bool `json:"merge_trackers,omitempty"`
OutgoingPortsMax int `json:"outgoing_ports_max,omitempty"`
OutgoingPortsMin int `json:"outgoing_ports_min,omitempty"`
PeerTos int `json:"peer_tos,omitempty"`
PeerTurnover int `json:"peer_turnover,omitempty"`
PeerTurnoverCutoff int `json:"peer_turnover_cutoff,omitempty"`
PeerTurnoverInterval int `json:"peer_turnover_interval,omitempty"`
PerformanceWarning bool `json:"performance_warning,omitempty"`
Pex bool `json:"pex,omitempty"`
PreallocateAll bool `json:"preallocate_all,omitempty"`
ProxyAuthEnabled bool `json:"proxy_auth_enabled,omitempty"`
ProxyBittorrent bool `json:"proxy_bittorrent,omitempty"`
ProxyHostnameLookup bool `json:"proxy_hostname_lookup,omitempty"`
ProxyIP string `json:"proxy_ip,omitempty"`
ProxyMisc bool `json:"proxy_misc,omitempty"`
ProxyPassword string `json:"proxy_password,omitempty"`
ProxyPeerConnections bool `json:"proxy_peer_connections,omitempty"`
ProxyPort int `json:"proxy_port,omitempty"`
ProxyRss bool `json:"proxy_rss,omitempty"`
ProxyType string `json:"proxy_type,omitempty"`
ProxyUsername string `json:"proxy_username,omitempty"`
QueueingEnabled bool `json:"queueing_enabled,omitempty"`
RandomPort bool `json:"random_port,omitempty"`
ReannounceWhenAddressChanged bool `json:"reannounce_when_address_changed,omitempty"`
RecheckCompletedTorrents bool `json:"recheck_completed_torrents,omitempty"`
RefreshInterval int `json:"refresh_interval,omitempty"`
RequestQueueSize int `json:"request_queue_size,omitempty"`
ResolvePeerCountries bool `json:"resolve_peer_countries,omitempty"`
ResumeDataStorageType string `json:"resume_data_storage_type,omitempty"`
RssAutoDownloadingEnabled bool `json:"rss_auto_downloading_enabled,omitempty"`
RssDownloadRepackProperEpisodes bool `json:"rss_download_repack_proper_episodes,omitempty"`
RssMaxArticlesPerFeed int `json:"rss_max_articles_per_feed,omitempty"`
RssProcessingEnabled bool `json:"rss_processing_enabled,omitempty"`
RssRefreshInterval int `json:"rss_refresh_interval,omitempty"`
RssSmartEpisodeFilters string `json:"rss_smart_episode_filters,omitempty"`
SavePath string `json:"save_path,omitempty"`
SavePathChangedTmmEnabled bool `json:"save_path_changed_tmm_enabled,omitempty"`
SaveResumeDataInterval int `json:"save_resume_data_interval,omitempty"`
ScheduleFromHour int `json:"schedule_from_hour,omitempty"`
ScheduleFromMin int `json:"schedule_from_min,omitempty"`
ScheduleToHour int `json:"schedule_to_hour,omitempty"`
ScheduleToMin int `json:"schedule_to_min,omitempty"`
SchedulerDays int `json:"scheduler_days,omitempty"`
SchedulerEnabled bool `json:"scheduler_enabled,omitempty"`
SendBufferLowWatermark int `json:"send_buffer_low_watermark,omitempty"`
SendBufferWatermark int `json:"send_buffer_watermark,omitempty"`
SendBufferWatermarkFactor int `json:"send_buffer_watermark_factor,omitempty"`
SlowTorrentDlRateThreshold int `json:"slow_torrent_dl_rate_threshold,omitempty"`
SlowTorrentInactiveTimer int `json:"slow_torrent_inactive_timer,omitempty"`
SlowTorrentUlRateThreshold int `json:"slow_torrent_ul_rate_threshold,omitempty"`
SocketBacklogSize int `json:"socket_backlog_size,omitempty"`
SocketReceiveBufferSize int `json:"socket_receive_buffer_size,omitempty"`
SocketSendBufferSize int `json:"socket_send_buffer_size,omitempty"`
SsrfMitigation bool `json:"ssrf_mitigation,omitempty"`
StartPausedEnabled bool `json:"start_paused_enabled,omitempty"`
StopTrackerTimeout int `json:"stop_tracker_timeout,omitempty"`
TempPath string `json:"temp_path,omitempty"`
TempPathEnabled bool `json:"temp_path_enabled,omitempty"`
TorrentChangedTmmEnabled bool `json:"torrent_changed_tmm_enabled,omitempty"`
TorrentContentLayout string `json:"torrent_content_layout,omitempty"`
TorrentFileSizeLimit int `json:"torrent_file_size_limit,omitempty"`
TorrentStopCondition string `json:"torrent_stop_condition,omitempty"`
UpLimit int `json:"up_limit,omitempty"`
UploadChokingAlgorithm int `json:"upload_choking_algorithm,omitempty"`
UploadSlotsBehavior int `json:"upload_slots_behavior,omitempty"`
Upnp bool `json:"upnp,omitempty"`
UpnpLeaseDuration int `json:"upnp_lease_duration,omitempty"`
UseCategoryPathsInManualMode bool `json:"use_category_paths_in_manual_mode,omitempty"`
UseHTTPS bool `json:"use_https,omitempty"`
UseSubcategories bool `json:"use_subcategories,omitempty"`
UtpTCPMixedMode int `json:"utp_tcp_mixed_mode,omitempty"`
ValidateHTTPSTrackerCertificate bool `json:"validate_https_tracker_certificate,omitempty"`
WebUIAddress string `json:"web_ui_address,omitempty"`
WebUIBanDuration int `json:"web_ui_ban_duration,omitempty"`
WebUIClickjackingProtectionEnabled bool `json:"web_ui_clickjacking_protection_enabled,omitempty"`
WebUICsrfProtectionEnabled bool `json:"web_ui_csrf_protection_enabled,omitempty"`
WebUICustomHTTPHeaders string `json:"web_ui_custom_http_headers,omitempty"`
WebUIDomainList string `json:"web_ui_domain_list,omitempty"`
WebUIHostHeaderValidationEnabled bool `json:"web_ui_host_header_validation_enabled,omitempty"`
WebUIHTTPSCertPath string `json:"web_ui_https_cert_path,omitempty"`
WebUIHTTPSKeyPath string `json:"web_ui_https_key_path,omitempty"`
WebUIMaxAuthFailCount int `json:"web_ui_max_auth_fail_count,omitempty"`
WebUIPort int `json:"web_ui_port,omitempty"`
WebUIReverseProxiesList string `json:"web_ui_reverse_proxies_list,omitempty"`
WebUIReverseProxyEnabled bool `json:"web_ui_reverse_proxy_enabled,omitempty"`
WebUISecureCookieEnabled bool `json:"web_ui_secure_cookie_enabled,omitempty"`
WebUISessionTimeout int `json:"web_ui_session_timeout,omitempty"`
WebUIUpnp bool `json:"web_ui_upnp,omitempty"`
WebUIUseCustomHTTPHeadersEnabled bool `json:"web_ui_use_custom_http_headers_enabled,omitempty"`
WebUIUsername string `json:"web_ui_username,omitempty"`
}
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)
result, err := c.doRequest(ctx, &requestData{
url: apiUrl,
})
if err != nil {
return "", err
}
if result.code != 200 {
return "", errors.New("get version failed: " + string(result.body))
}
return string(result.body), nil
}
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)
result, err := c.doRequest(ctx, &requestData{
url: apiUrl,
})
if err != nil {
return "", err
}
if result.code != 200 {
return "", errors.New("get version failed: " + string(result.body))
}
return string(result.body), nil
}
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)
result, err := c.doRequest(ctx, &requestData{
url: apiUrl,
})
if err != nil {
return nil, err
}
if result.code != 200 {
return nil, errors.New("get build info failed: " + string(result.body))
}
var build = new(BuildInfo)
if err := json.Unmarshal(result.body, build); err != nil {
return nil, err
}
return build, nil
}
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)
result, err := c.doRequest(ctx, &requestData{
method: http.MethodPost,
url: apiUrl,
})
if err != nil {
return err
}
if result.code != 200 {
return errors.New("shutdown application failed: " + string(result.body))
}
return nil
}
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)
result, err := c.doRequest(ctx, &requestData{
url: apiUrl,
})
if err != nil {
return nil, err
}
if result.code != 200 {
return nil, errors.New("get preference failed: " + string(result.body))
}
var preferences = new(Preferences)
if err := json.Unmarshal(result.body, preferences); err != nil {
return nil, err
}
return preferences, nil
}
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)
data, err := json.Marshal(prefs)
if err != nil {
return err
}
var formData bytes.Buffer
formData.Write([]byte("json="))
formData.Write(data)
result, err := c.doRequest(ctx, &requestData{
method: http.MethodPost,
url: apiUrl,
contentType: ContentTypeFormUrlEncoded,
body: &formData,
})
if err != nil {
return err
}
if result.code != 200 {
return errors.New("set preference failed: " + string(result.body))
}
return nil
}
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)
result, err := c.doRequest(ctx, &requestData{
url: apiUrl,
})
if err != nil {
return "", err
}
if result.code != 200 {
return "", errors.New("get default save path failed: " + string(result.body))
}
return string(result.body), nil
}