Skip to content

Commit

Permalink
chore: maintenance and renaming project
Browse files Browse the repository at this point in the history
  • Loading branch information
buroa committed Jan 10, 2024
1 parent 8706e12 commit 2c79d27
Show file tree
Hide file tree
Showing 11 changed files with 39 additions and 41 deletions.
2 changes: 1 addition & 1 deletion .github/renovate.json5
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@
"extends": [
"config:base"
]
}
}
1 change: 0 additions & 1 deletion .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ jobs:
with:
images: |
ghcr.io/${{ github.repository }}
ghcr.io/buroa/qbittools
tags: |
type=ref,event=branch
type=ref,event=pr
Expand Down
1 change: 0 additions & 1 deletion .github/workflows/release.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ jobs:
with:
images: |
ghcr.io/${{ github.repository }}
ghcr.io/buroa/qbittools
flavor: |
latest=true
prefix=v
Expand Down
6 changes: 3 additions & 3 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,12 @@ RUN pip install --no-cache-dir --prefix=/install -r /requirements.txt \

FROM base as app
WORKDIR /app
COPY qbittools/ .
COPY qbtools/ .
COPY config.yaml .
RUN python3 -m compileall qbittools.py commands/
RUN python3 -m compileall qbtools.py commands/

FROM base as final
WORKDIR /app
COPY --from=pip /install /usr/local
COPY --from=app /app .
ENTRYPOINT ["python3", "qbittools.py"]
ENTRYPOINT ["python3", "qbtools.py"]
22 changes: 11 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ This is an opinionated fork of the upstream project at https://gitlab.com/AlexKM

## Description

qbittools is a feature rich CLI for the management of torrents in qBittorrent.
qbtools is a feature rich CLI for the management of torrents in qBittorrent.

## Table of contents

Expand All @@ -29,23 +29,23 @@ qbittools is a feature rich CLI for the management of torrents in qBittorrent.
Run a container with access to host network:

```bash
docker run -it --rm --network host github.com/buroa/qbittools tagging --unregistered
docker run -it --rm --network host github.com/buroa/qbtools tagging --unregistered
```

### Building

```bash
# clone the repository
git clone https://github.com/buroa/qbittools.git && cd qbittools
git clone https://github.com/buroa/qbtools.git && cd qbtools
# build the image
docker build -t qbittools:latest --pull .
docker build -t qbtools:latest --pull .
# run a container with the resulting binary and access to host network
docker run -it --rm --network host qbittools reannounce -p 12345
docker run -it --rm --network host qbtools reannounce -p 12345
```

## Configuration

You have to specify your password every time with `-P` flag unless you enable `Web UI -> Bypass authentication for clients on localhost` in qBittorrent's settings, because there is no way for qBittools to retrieve it in plaintext.
You have to specify your password every time with `-P` flag unless you enable `Web UI -> Bypass authentication for clients on localhost` in qBittorrent's settings, because there is no way for qbtools to retrieve it in plaintext.

You also can specify host, port and username manually without a configuration file with `-s`, `-p` and `-U` flags accordingly.

Expand All @@ -58,8 +58,8 @@ There is also a `config.yaml` file which can be overrideen to add your own index
All commands have extensive help with all available options.

```bash
$ qbittools export -h
usage: qbittools.py reannounce [-h] [--pause-resume] [--process-seeding]
$ qbtools export -h
usage: qbtools.py reannounce [-h] [--pause-resume] [--process-seeding]
[-c /app/config.yaml] [-p 12345] [-s 127.0.0.1] [-U username]
[-P password]

Expand All @@ -83,15 +83,15 @@ options:
Create useful tags to group torrents by tracker domains, not working trackers, unregistered torrents and duplicates

```bash
$ qbittools tagging --duplicates --unregistered --not-working --added-on --trackers
$ qbtools tagging --duplicates --unregistered --not-working --added-on --trackers
```

#### Reannounce

Automatic reannounce on problematic trackers

```bash
$ qbittools reannounce
$ qbtools reannounce
07:40:40 PM --------------------------
07:40:40 PM [Movie.2020.2160p.WEB-DL.H264-GROUP] is not working, active for 1s, reannouncing...
07:41:20 PM --------------------------
Expand Down Expand Up @@ -129,5 +129,5 @@ This is how I have my paths laid out where `/downloads/qbittorrent/complete` is
```

```bash
$ qbittools orphaned --ignore-pattern "*_unpackerred" --ignore-pattern "*/manual/*"
$ qbtools orphaned --ignore-pattern "*_unpackerred" --ignore-pattern "*/manual/*"
```
10 changes: 5 additions & 5 deletions qbittools/commands/orphaned.py → qbtools/commands/orphaned.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,12 @@
import shutil
from fnmatch import fnmatch

import qbittools
import qbtools

def __init__(args, logger):
logger.info(f"Checking for orphaned files on disk not in qBittorrent...")

client = qbittools.qbit_client(args)
client = qbtools.qbit_client(args)

completed_dir = client.application.preferences.save_path
categories = [
Expand Down Expand Up @@ -74,12 +74,12 @@ def add_arguments(subparser):
Description:
Search for files on disk that are not in qBittorrent and delete them. Pair this with the prune command to delete torrents that are not in qBittorrent.
Usage:
qbittools.py orphaned --help
qbtools.py orphaned --help
Example:
# Delete all files in the completed directory that are not in qBittorrent and don't match the exclude patterns
qbittools.py orphaned --exclude-pattern "*_unpackerred" --exclude-pattern "*/manual/*" --dry-run
qbtools.py orphaned --exclude-pattern "*_unpackerred" --exclude-pattern "*/manual/*" --dry-run
"""
parser = subparser.add_parser('orphaned')
parser.add_argument('--exclude-pattern', nargs='*', action='append', metavar='mypattern', default=[], help='Exclude pattern, can be repeated multiple times', required=False)
parser.add_argument('--dry-run', action='store_true', help='Do not delete any data on disk', default=False, required=False)
qbittools.add_default_args(parser)
qbtools.add_default_args(parser)
12 changes: 6 additions & 6 deletions qbittools/commands/prune.py → qbtools/commands/prune.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
from fnmatch import fnmatch

import qbittools
import qbtools

def __init__(args, logger):
client = qbittools.qbit_client(args)
client = qbtools.qbit_client(args)

categories = list(client.torrent_categories.categories.keys())
if len(args.include_category) > 0:
Expand Down Expand Up @@ -35,7 +35,7 @@ def __init__(args, logger):
logger.info(f"Pruning torrents with tags [{' AND '.join(include_tags)}] but does not contain tags [{' OR '.join(exclude_tags)}]...")

for t in filtered_torrents:
logger.info(f"Pruned torrent {t['name']} with category [{t.category}] and tags [{t.tags}] and ratio [{round(t['ratio'], 2)}] and seeding time [{qbittools.utils.dhms(t['seeding_time'])}]")
logger.info(f"Pruned torrent {t['name']} with category [{t.category}] and tags [{t.tags}] and ratio [{round(t['ratio'], 2)}] and seeding time [{qbtools.utils.dhms(t['seeding_time'])}]")
if not args.dry_run:
t.delete(delete_files=args.with_data)

Expand All @@ -46,10 +46,10 @@ def add_arguments(subparser):
Description:
Prune torrents that have matching tags. Pair this with the tagging command to tag torrents.
Usage:
qbittools.py prune --help
qbtools.py prune --help
Example:
# Delete torrents with the tag 'expired' and 'added:30d', however if the torrent also has the tags 'site:oink' or 'site:whatcd' exclude it from being deleted
qbittools.py prune --include-tag expired --include-tag added:30d --exclude-tag site:oink --exclude-tag site:whatcd --dry-run
qbtools.py prune --include-tag expired --include-tag added:30d --exclude-tag site:oink --exclude-tag site:whatcd --dry-run
"""
parser = subparser.add_parser('prune')
parser.add_argument('--include-tag', nargs='*', action='append', metavar='mytag', default=[], help='Include torrents containing all of these tags, can be repeated multiple times', required=True)
Expand All @@ -58,4 +58,4 @@ def add_arguments(subparser):
parser.add_argument('--exclude-category', nargs='*', action='append', metavar='mycategory', default=[], help='Exclude torrents from category that matches this pattern, can be repeated multiple times', required=False)
parser.add_argument('--dry-run', action='store_true', help='Do not delete torrents', default=False, required=False)
parser.add_argument('--with-data', action='store_true', help='Delete torrents with data', default=False, required=False)
qbittools.add_default_args(parser)
qbtools.add_default_args(parser)
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import time
import qbittools
import qbtools

def __init__(args, logger):
client = qbittools.qbit_client(args)
client = qbtools.qbit_client(args)

iterations = 0
timeout = 5
Expand Down Expand Up @@ -73,4 +73,4 @@ def add_arguments(subparser):
parser = subparser.add_parser("reannounce")
parser.add_argument("--pause-resume", action="store_true", help="Pause+resume torrents that are invalid.")
parser.add_argument("--process-seeding", action="store_true", help="Include seeding torrents for reannouncements.")
qbittools.add_default_args(parser)
qbtools.add_default_args(parser)
20 changes: 10 additions & 10 deletions qbittools/commands/tagging.py → qbtools/commands/tagging.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
import collections
from datetime import datetime

import qbittools
import qbtools

DEFAULT_TAGS = [
'activity:',
Expand Down Expand Up @@ -56,8 +56,8 @@
def __init__(args, logger):
logger.info(f"Tagging torrents in qBittorrent...")

client = qbittools.qbit_client(args)
trackers = qbittools.get_config(args, "trackers", [])
client = qbtools.qbit_client(args)
trackers = qbtools.get_config(args, "trackers", [])

extractTLD = tldextract.TLDExtract(cache_dir=None)
today = datetime.today()
Expand All @@ -80,7 +80,7 @@ def __init__(args, logger):
# TODO: Optimize - this slows down the script a lot
filtered_trackers = list(filter(lambda s: not s.url in DHT_MATCHES, t.trackers))
domain = extractTLD(sorted(filtered_trackers, key=lambda x: x.url)[0].url).registered_domain
tracker = qbittools.utils.filter_tracker_by_domain(domain, trackers)
tracker = qbtools.utils.filter_tracker_by_domain(domain, trackers)

if args.added_on:
added_on = datetime.fromtimestamp(t.added_on)
Expand Down Expand Up @@ -135,7 +135,7 @@ def __init__(args, logger):
if args.expired and tracker and t.state_enum.is_complete:
if tracker['required_seed_ratio'] != 0 and t.ratio >= tracker['required_seed_ratio']:
tags_to_add.append('expired')
elif tracker['required_seed_days'] != 0 and t.seeding_time >= qbittools.utils.seconds(tracker['required_seed_days']):
elif tracker['required_seed_days'] != 0 and t.seeding_time >= qbtools.utils.seconds(tracker['required_seed_days']):
tags_to_add.append('expired')

if args.duplicates:
Expand All @@ -148,7 +148,7 @@ def __init__(args, logger):

content_paths.append((t.hash, t.content_path, t.size))

if args.not_linked and not qbittools.utils.is_linked(t.content_path):
if args.not_linked and not qbtools.utils.is_linked(t.content_path):
tags_to_add.append('not-linked')

for tag in tags_to_add:
Expand All @@ -173,7 +173,7 @@ def __init__(args, logger):
# Apply tags
for tag in tag_hashes:
if args.size:
size = qbittools.utils.format_bytes(tag_sizes[tag])
size = qbtools.utils.format_bytes(tag_sizes[tag])
client.torrents_add_tags(tags=f"{tag} [{size}]", torrent_hashes=tag_hashes[tag])
else:
client.torrents_add_tags(tags=tag, torrent_hashes=tag_hashes[tag])
Expand All @@ -185,10 +185,10 @@ def add_arguments(subparser):
Description:
Tag torrents. This command can be used to tag torrents with various tags, such as torrents that have not been active for a while, torrents that have not been working for a while, torrents that have expired an ratio or seeding time, torrents that have the same content path, etc.
Usage:
qbittools.py tagging --help
qbtools.py tagging --help
Example:
# Tag torrents
qbittools.py tagging --exclude-category manual --added-on --expired --last-activity --sites --unregistered
qbtools.py tagging --exclude-category manual --added-on --expired --last-activity --sites --unregistered
"""
parser = subparser.add_parser('tagging')
parser.add_argument('--exclude-category', nargs='*', action='append', metavar='mycategory', default=[], help='Exclude all torrent with this category, can be repeated multiple times', required=False)
Expand All @@ -204,4 +204,4 @@ def add_arguments(subparser):
parser.add_argument('--size', action='store_true', help='Add size of tagged torrents to created tags')
parser.add_argument('--tracker-down', action='store_true', help='Tag torrents with temporarily down trackers')
parser.add_argument('--unregistered', action='store_true', help='Tag torrents with unregistered tracker status message')
qbittools.add_default_args(parser)
qbtools.add_default_args(parser)
File renamed without changes.
File renamed without changes.

0 comments on commit 2c79d27

Please sign in to comment.