diff --git a/README.md b/README.md index 0eaaed9..4ea6aa7 100644 --- a/README.md +++ b/README.md @@ -5,11 +5,13 @@ [![Donate](https://img.shields.io/badge/Donate-gray.svg?style=flat-square)](#donate) # tqm + CLI tool to manage your torrent client queues. Primary focus is on removing torrents that meet specific criteria. This is a fork from [l3uddz](https://github.com/l3uddz/tqm). ## Example Configuration + ```yaml clients: deluge: @@ -105,6 +107,7 @@ filters: ``` ## Optional - Tracker Configuration + ```yaml trackers: bhd: @@ -113,45 +116,50 @@ trackers: api_user: your-api-user api_key: your-api-key ``` + Allows tqm to validate if a torrent was removed from the tracker using the tracker's own API. Currently implements: + - Beyond-HD - PTP ## Filtering Language Definition + The language definition used in the configuration filters is available [here](https://github.com/antonmedv/expr/blob/586b86b462d22497d442adbc924bfb701db3075d/docs/Language-Definition.md) ## Filterable Fields + The following torrent fields (along with their types) can be used in the configuration when filtering torrents: + ```go type Torrent struct { - Hash string - Name string - Path string - TotalBytes int64 - DownloadedBytes int64 - State string - Files []string - Tags []string - Downloaded bool - Seeding bool - Ratio float32 - AddedSeconds int64 - AddedHours float32 - AddedDays float32 - SeedingSeconds int64 - SeedingHours float32 - SeedingDays float32 - Label string - Seeds int64 - Peers int64 - - FreeSpaceGB func() float64 - FreeSpaceSet bool - - TrackerName string - TrackerStatus string + Hash string + Name string + Path string + TotalBytes int64 + DownloadedBytes int64 + State string + Files []string + Tags []string + Downloaded bool + Seeding bool + Ratio float32 + AddedSeconds int64 + AddedHours float32 + AddedDays float32 + SeedingSeconds int64 + SeedingHours float32 + SeedingDays float32 + Label string + Seeds int64 + Peers int64 + + FreeSpaceGB func() float64 + FreeSpaceSet bool + + TrackerName string + TrackerStatus string } ``` @@ -164,17 +172,22 @@ Fields of type `[]string` (lists) such as the `Tags` and `Files` fields support All of this and more can be noted in the [language definition](https://github.com/antonmedv/expr/blob/586b86b462d22497d442adbc924bfb701db3075d/docs/Language-Definition.md) mentioned above. ## Helper Filtering Options + The following helper functions are available for usage while filtering, usage examples are available in the example config above. + ```go IsUnregistered() bool // Evaluates to true if torrent is unregistered in the tracker HasAllTags(tags ...string) bool // True if torrent has ALL tags specified HasAnyTag(tags ...string) bool // True if torrent has at least one tag specified +HasMissingFiles() bool // True if any of the torrent's files are missing from disk Log(n float64) float64 // The natural logarithm function ``` ## BypassIgnoreIfUnregistered + If the top level config option `bypassIgnoreIfUnregistered` is set to `true`, unregistered torrents will not be ignored. This helps making the config less verbose, so this: + ```yaml filters: default: @@ -188,7 +201,9 @@ filters: # Filter based on qbittorrent tags (only qbit at the moment) - '"permaseed" in Tags && !IsUnregistered()' ``` + can turn into this: + ```yaml bypassIgnoreIfUnregistered: true @@ -208,10 +223,12 @@ filters: **Note:** If `TrackerStatus contains "Tracker is down"` then a torrent will not be considered unregistered anyways and will be ignored when tracker is down assuming the above filters. ## Supported Clients + - Deluge - qBittorrent ## Example Commands + 1. Clean - Retrieve torrent client queue and remove torrents matching its configured filters `tqm clean qbt --dry-run` diff --git a/config/torrent.go b/config/torrent.go index 899d128..01d71b0 100644 --- a/config/torrent.go +++ b/config/torrent.go @@ -2,6 +2,7 @@ package config import ( "math" + "os" "strings" "github.com/autobrr/tqm/sliceutils" @@ -137,6 +138,21 @@ func (t *Torrent) HasAnyTag(tags ...string) bool { return false } +func (t *Torrent) HasMissingFiles() bool { + if !t.Downloaded { + return false + } + + // check if files exist on disk + for _, f := range t.Files { + if _, err := os.Stat(f); os.IsNotExist(err) { + return true + } + } + + return false +} + func (t *Torrent) Log(n float64) float64 { return math.Log(n) }