Skip to content

Commit

Permalink
allow delete torrents by conditions; show cmd allow filtering by trac…
Browse files Browse the repository at this point in the history
…ker domain or torrent size
  • Loading branch information
sagan committed Oct 19, 2023
1 parent 32c0fd8 commit cf7bd67
Show file tree
Hide file tree
Showing 3 changed files with 116 additions and 31 deletions.
75 changes: 71 additions & 4 deletions cmd/delete/delete.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,25 +7,44 @@ import (

"github.com/sagan/ptool/client"
"github.com/sagan/ptool/cmd"
"github.com/sagan/ptool/util"
)

var command = &cobra.Command{
Use: "delete {client} {infoHash}...",
Use: "delete {client} [--category category] [--tag tag] [--filter filter] [infoHash]...",
Annotations: map[string]string{"cobra-prompt-dynamic-suggestions": "delete"},
Aliases: []string{"rm"},
Short: "Delete torrents from client.",
Long: `Delete torrents from client.
{infoHash}...: infoHash list of torrents.`,
[infoHash]...: infoHash list of torrents. It's possible to use state filter to target multiple torrents:
_all, _active, _done, _undone, _downloading, _seeding, _paused, _completed, _error.
It will ask for confirmation if used to delete torrents by any condition other than infoHash,
unless --force-dangerous flag is set.`,
Args: cobra.MatchAll(cobra.MinimumNArgs(2), cobra.OnlyValidArgs),
RunE: delete,
}

var (
preserve = false
preserve = false
force = false
filter = ""
category = ""
tag = ""
tracker = ""
minTorrentSizeStr = ""
maxTorrentSizeStr = ""
)

func init() {
command.Flags().BoolVarP(&preserve, "preserve", "p", false, "Preserve (don't delete) torrent content files on the disk")
command.Flags().BoolVarP(&force, "force-dangerous", "", false, "Force deletion. Do NOT prompt for confirm")
command.Flags().StringVarP(&filter, "filter", "", "", "Filter torrents by name")
command.Flags().StringVarP(&category, "category", "", "", "Filter torrents by category")
command.Flags().StringVarP(&tag, "tag", "", "", "Filter torrents by tag. Comma-separated string list. Torrent which tags contain any one in the list will match")
command.Flags().StringVarP(&tracker, "tracker", "", "", "Filter torrents by tracker domain")
command.Flags().StringVarP(&minTorrentSizeStr, "min-torrent-size", "", "-1", "Skip torrent with size smaller than (<) this value. Default (-1) == no limit")
command.Flags().StringVarP(&maxTorrentSizeStr, "max-torrent-size", "", "-1", "Skip torrent with size large than (>) this value. Default (-1) == no limit")
cmd.RootCmd.AddCommand(command)
}

Expand All @@ -36,10 +55,58 @@ func delete(cmd *cobra.Command, args []string) error {
if err != nil {
return fmt.Errorf("failed to create client: %v", err)
}
minTorrentSize, _ := util.RAMInBytes(minTorrentSizeStr)
maxTorrentSize, _ := util.RAMInBytes(maxTorrentSizeStr)
quickMode := true
if category != "" || tag != "" || filter != "" || minTorrentSize >= 0 || maxTorrentSize >= 0 {
quickMode = false
} else {
for _, infoHash := range infoHashes {
if !client.IsValidInfoHash(infoHash) {
quickMode = false
break
}
}
}

if quickMode {
err = clientInstance.DeleteTorrents(infoHashes, !preserve)
if err != nil {
return fmt.Errorf("failed to delete torrents: %v", err)
}
return nil
}
torrents, err := client.QueryTorrents(clientInstance, category, tag, filter, infoHashes...)
if err != nil {
return fmt.Errorf("failed to fetch client torrents: %v", err)
}
if tracker != "" || minTorrentSize >= 0 || maxTorrentSize >= 0 {
torrents = util.Filter(torrents, func(t client.Torrent) bool {
if tracker != "" && t.TrackerDomain != tracker ||
minTorrentSize >= 0 && t.Size < minTorrentSize ||
maxTorrentSize >= 0 && t.Size > maxTorrentSize {
return false
}
return true
})
}
if !force {
client.PrintTorrents(torrents, "", 1)
fmt.Printf("\n")
fmt.Printf("Above %d torrents will be deteled, are you sure? (yes/no): ", len(torrents))
input := ""
fmt.Scanf("%s", &input)
if input != "yes" {
return fmt.Errorf("abort")
}
}
infoHashes = util.Map(torrents, func(t client.Torrent) string {
return t.InfoHash
})
err = clientInstance.DeleteTorrents(infoHashes, !preserve)
if err != nil {
return fmt.Errorf("failed to delete torrent: %v", err)
return fmt.Errorf("failed to delete torrents: %v", err)
}
fmt.Printf("%d torrents deleted.\n", len(torrents))
return nil
}
68 changes: 43 additions & 25 deletions cmd/show/show.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,20 +28,23 @@ If no flags or args are provided, it will display current active torrents.`,
}

var (
largestFlag bool
showTrackers bool
showFiles bool
showInfoHashOnly bool
maxTorrents = int64(0)
filter = ""
category = ""
tag = ""
showAll = false
showRaw = false
showJson = false
showSum = false
sortFlag string
orderFlag string
largestFlag bool
showTrackers bool
showFiles bool
showInfoHashOnly bool
maxTorrents = int64(0)
filter = ""
category = ""
tag = ""
tracker = ""
minTorrentSizeStr = ""
maxTorrentSizeStr = ""
showAll = false
showRaw = false
showJson = false
showSum = false
sortFlag string
orderFlag string
)

func init() {
Expand All @@ -57,14 +60,17 @@ func init() {
command.Flags().StringVarP(&filter, "filter", "", "", "Filter torrents by name")
command.Flags().StringVarP(&category, "category", "", "", "Filter torrents by category")
command.Flags().StringVarP(&tag, "tag", "", "", "Filter torrents by tag. Comma-separated string list. Torrent which tags contain any one in the list will match")
command.Flags().StringVarP(&tracker, "tracker", "", "", "Filter torrents by tracker domain")
command.Flags().StringVarP(&minTorrentSizeStr, "min-torrent-size", "", "-1", "Skip torrent with size smaller than (<) this value. Default (-1) == no limit")
command.Flags().StringVarP(&maxTorrentSizeStr, "max-torrent-size", "", "-1", "Skip torrent with size large than (>) this value. Default (-1) == no limit")
cmd.AddEnumFlagP(command, &sortFlag, "sort", "", common.ClientTorrentSortFlag)
cmd.AddEnumFlagP(command, &orderFlag, "order", "", common.OrderFlag)
cmd.RootCmd.AddCommand(command)
}

func show(cmd *cobra.Command, args []string) error {
clientName := args[0]
args = args[1:]
infoHashes := args[1:]
if showJson && showInfoHashOnly {
return fmt.Errorf("--json and --info-hash flags are NOT compatible")
}
Expand All @@ -83,24 +89,26 @@ func show(cmd *cobra.Command, args []string) error {
if orderFlag == "desc" {
desc = true
}
minTorrentSize, _ := util.RAMInBytes(minTorrentSizeStr)
maxTorrentSize, _ := util.RAMInBytes(maxTorrentSizeStr)

var torrents []client.Torrent
if showAll {
torrents, err = client.QueryTorrents(clientInstance, "", "", "")
} else if category == "" && tag == "" && filter == "" && len(args) == 0 {
} else if category == "" && tag == "" && filter == "" && len(infoHashes) == 0 {
torrents, err = client.QueryTorrents(clientInstance, "", "", "", "_active")
} else if category == "" && tag == "" && filter == "" &&
len(args) == 1 && !strings.HasPrefix(args[0], "_") {
len(infoHashes) == 1 && !strings.HasPrefix(infoHashes[0], "_") {
// display single torrent details
if !client.IsValidInfoHash(args[0]) {
return fmt.Errorf("%s is not a valid infoHash", args[0])
if !client.IsValidInfoHash(infoHashes[0]) {
return fmt.Errorf("%s is not a valid infoHash", infoHashes[0])
}
torrent, err := clientInstance.GetTorrent(args[0])
torrent, err := clientInstance.GetTorrent(infoHashes[0])
if err != nil {
return fmt.Errorf("failed to get torrent %s details: %v", args[0], err)
return fmt.Errorf("failed to get torrent %s details: %v", infoHashes[0], err)
}
if torrent == nil {
return fmt.Errorf("torrent %s not found", args[0])
return fmt.Errorf("torrent %s not found", infoHashes[0])
}
if showJson {
bytes, err := json.Marshal(torrent)
Expand All @@ -113,7 +121,7 @@ func show(cmd *cobra.Command, args []string) error {
client.PrintTorrent(torrent)
if showTrackers {
fmt.Printf("\n")
trackers, err := clientInstance.GetTorrentTrackers(args[0])
trackers, err := clientInstance.GetTorrentTrackers(infoHashes[0])
if err != nil {
log.Errorf("Failed to get torrent trackers: %v", err)
} else {
Expand All @@ -122,7 +130,7 @@ func show(cmd *cobra.Command, args []string) error {
}
if showFiles {
fmt.Printf("\n")
files, err := clientInstance.GetTorrentContents(args[0])
files, err := clientInstance.GetTorrentContents(infoHashes[0])
if err != nil {
log.Errorf("Failed to get torrent contents: %v", err)
} else {
Expand All @@ -131,11 +139,21 @@ func show(cmd *cobra.Command, args []string) error {
}
return nil
} else {
torrents, err = client.QueryTorrents(clientInstance, category, tag, filter, args...)
torrents, err = client.QueryTorrents(clientInstance, category, tag, filter, infoHashes...)
}
if err != nil {
return fmt.Errorf("failed to fetch client torrents: %v", err)
}
if tracker != "" || minTorrentSize >= 0 || maxTorrentSize >= 0 {
torrents = util.Filter(torrents, func(t client.Torrent) bool {
if tracker != "" && t.TrackerDomain != tracker ||
minTorrentSize >= 0 && t.Size < minTorrentSize ||
maxTorrentSize >= 0 && t.Size > maxTorrentSize {
return false
}
return true
})
}
if sortFlag != "" && sortFlag != "none" {
sort.Slice(torrents, func(i, j int) bool {
switch sortFlag {
Expand Down
4 changes: 2 additions & 2 deletions version/version.go
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
package version

var (
VersionSuffix = "" // eg. DEV
VersionTag = "v0.1.7"
VersionSuffix = "DEV" // eg. DEV
VersionTag = "v0.1.8"
Version = ""
)

Expand Down

0 comments on commit cf7bd67

Please sign in to comment.