mirror of
https://github.com/StuffAnThings/qbit_manage.git
synced 2025-10-06 20:05:57 +08:00
commit
cb6592e5f8
8 changed files with 189 additions and 156 deletions
|
@ -17,5 +17,6 @@ config
|
|||
Dockerfile
|
||||
venv
|
||||
.idea
|
||||
.env
|
||||
test.py
|
||||
!config/config.yml.sample
|
4
.gitignore
vendored
4
.gitignore
vendored
|
@ -6,4 +6,6 @@ __pycache__/
|
|||
*.log*
|
||||
*.yml
|
||||
.vscode/*
|
||||
!.github/**
|
||||
!.github/**
|
||||
*.svg
|
||||
.env
|
10
README.md
10
README.md
|
@ -1,4 +1,4 @@
|
|||
# qBit Management
|
||||
# <img src="qbm_logo.png" width="75"> qBit Management
|
||||
|
||||
[](https://github.com/StuffAnThings/qbit_manage/releases)
|
||||
[](https://github.com/StuffAnThings/qbit_manage/tree/develop)
|
||||
|
@ -9,10 +9,10 @@
|
|||
|
||||
This is a program used to manage your qBittorrent instance such as:
|
||||
|
||||
* Tag torrents based on tracker URL (only tag torrents that have no tags)
|
||||
* Tag torrents based on tracker URL and set seed goals/limit upload speed by tag (only tag torrents that have no tags)
|
||||
* Update categories based on save directory
|
||||
* Remove unregistered torrents (delete data & torrent if it is not being cross-seeded, otherwise it will just remove the torrent)
|
||||
* Automatically add [cross-seed](https://github.com/mmgoodnow/cross-seed) torrents in paused state (used in conjunction with the [cross-seed](https://github.com/mmgoodnow/cross-seed) script) <-- cross-seed now allows for torrent injections directly to qBit.
|
||||
* Automatically add [cross-seed](https://github.com/mmgoodnow/cross-seed) torrents in paused state. **\*Note: cross-seed now allows for torrent injections directly to qBit, making this feature obsolete.\***
|
||||
* Recheck paused torrents sorted by lowest size and resume if completed
|
||||
* Remove orphaned files from your root directory that are not referenced by qBittorrent
|
||||
* Tag any torrents that have no hard links and allows optional cleanup to delete these torrents and contents based on maximum ratio and/or time seeded
|
||||
|
@ -30,7 +30,7 @@ To run the script in an interactive terminal run:
|
|||
* add your qBittorrent host, user and pass. If you are not using a username and password you can remove the `user` and `pass` lines.
|
||||
* add your `cross_seed` and `root_dir`. If you're running cross-seed in a docker container you must fill out `remote_dir` as well.
|
||||
* Add your categories and save path to match with what is being used in your qBittorrent instance. I suggest using the full path when defining `save_path`
|
||||
* Add the `tag` definition based on tracker URL
|
||||
* Add the `tag` definition based on tracker URL (optional add seed goals/limit upload speed by tag)
|
||||
* Modify the `nohardlinks` by specifying your completed movies/series category to match with qBittorrent. Please ensure the `root_dir` and/or `remote_dir` is added in the `directory` section
|
||||
* `root_dir` needs to be defined in order to use the RecycleBin function. If optional `empty_after_x_days` is not defined then it will never empty the RecycleBin. Setting it to 0 will empty the RecycleBin immediately.
|
||||
* Modify the `orphaned` section to define file patterns not to consider as orphans. Use this to exclude your incomplete torrents directory, or to ignore auto-generated files such as Thumbs.db.
|
||||
|
@ -51,7 +51,7 @@ python qbit_manage.py -h
|
|||
| `-cs` or `--cross-seed` | QBT_CROSS_SEED | Use this after running [cross-seed script](https://github.com/mmgoodnow/cross-seed) to add torrents from the cross-seed output folder to qBittorrent | False |
|
||||
| `-re` or `--recheck` | QBT_RECHECK | Recheck paused torrents sorted by lowest size. Resume if Completed. | False |
|
||||
| `-cu` or `--cat-update` | QBT_CAT_UPDATE | Use this if you would like to update your categories. | False |
|
||||
| `-tu` or `--tag-update` | QBT_TAG_UPDATE | Use this if you would like to update your tags. (Only adds tags to untagged torrents) | False |
|
||||
| `-tu` or `--tag-update` | QBT_TAG_UPDATE | Use this if you would like to update your tags and/or set seed goals/limit upload speed by tag. (Only adds tags to untagged torrents) | False |
|
||||
| `-ru` or `--rem-unregistered` | QBT_REM_UNREGISTERED | Use this if you would like to remove unregistered torrents. (It will the delete data & torrent if it is not being cross-seeded, otherwise it will just remove the torrent without deleting data) | False |
|
||||
| `-ro` or `--rem-orphaned` | QBT_REM_ORPHANED | Use this if you would like to remove orphaned files from your `root_dir` directory that are not referenced by any torrents. It will scan your `root_dir` directory and compare it with what is in qBittorrent. Any data not referenced in qBittorrent will be moved into `/data/torrents/orphaned_data` folder for you to review/delete. | False |
|
||||
| `-tnhl` or `--tag-nohardlinks` | QBT_TAG_NOHARDLINKS | Use this to tag any torrents that do not have any hard links associated with any of the files. This is useful for those that use Sonarr/Radarr that hard links your media files with the torrents for seeding. When files get upgraded they no longer become linked with your media therefore will be tagged with a new tag noHL. You can then safely delete/remove these torrents to free up any extra space that is not being used by your media folder. | False |
|
||||
|
|
2
VERSION
2
VERSION
|
@ -1 +1 @@
|
|||
2.1
|
||||
2.2
|
|
@ -1,87 +0,0 @@
|
|||
# qBittorrent parameters
|
||||
qbt:
|
||||
host: "localhost:8080"
|
||||
user: "username"
|
||||
pass: "password"
|
||||
|
||||
directory:
|
||||
# Do not remove these
|
||||
# Cross-seed var: </your/path/here/> #Output directory of cross-seed
|
||||
# root_dir var: </your/path/here/> #Root downloads directory used to check for orphaned files and used in RecycleBin
|
||||
# <OPTIONAL> remote_dir var: </your/path/here/> # Path of docker host mapping of root_dir. Must be set if you are using docker!
|
||||
cross_seed: "/your/path/here/"
|
||||
root_dir: "/data/torrents/"
|
||||
remote_dir: "/mnt/user/data/torrents/"
|
||||
|
||||
# Category/Pathing Parameters
|
||||
cat:
|
||||
# <Category Name> : <save_path> #Path of your save directory. Can be a keyword or full path
|
||||
movies: "/data/torrents/Movies"
|
||||
tv: "TV"
|
||||
|
||||
# Tag Parameters
|
||||
tags:
|
||||
# <Tracker URL Keyword>: <Tag Name>
|
||||
animebytes.tv: AnimeBytes
|
||||
avistaz: Avistaz
|
||||
beyond-hd: Beyond-HD
|
||||
blutopia: Blutopia
|
||||
cartoonchaos: CartoonChaos
|
||||
digitalcore: DigitalCore
|
||||
gazellegames: GGn
|
||||
hdts: HDTorrents
|
||||
landof.tv: BroadcasTheNet
|
||||
myanonamouse: MaM
|
||||
passthepopcorn: PassThePopcorn
|
||||
privatehd: PrivateHD
|
||||
tleechreload: TorrentLeech
|
||||
torrentdb: TorrentDB
|
||||
torrentleech: TorrentLeech
|
||||
tv-vault: TV-Vault
|
||||
|
||||
#Tag Movies/Series that are not hard linked
|
||||
nohardlinks:
|
||||
# Mandatory to fill out directory parameter above to use this function (root_dir/remote_dir)
|
||||
# This variable should be set to your category name of your completed movies/completed series in qbit. Acceptable variable can be any category you would like to tag if there are no hardlinks found
|
||||
movies-completed:
|
||||
#<OPTIONAL> exclude_tags var: Will exclude the following tags when searching through the category.
|
||||
exclude_tags:
|
||||
- Beyond-HD
|
||||
- AnimeBytes
|
||||
- MaM
|
||||
#<OPTIONAL> cleanup var: WARNING!! Setting this as true Will remove and delete contents of any torrents that are in paused state and has the NoHL tag
|
||||
cleanup: false
|
||||
#<OPTIONAL> max_ratio var: Will set the torrent Maximum share ratio until torrent is stopped from seeding/uploading
|
||||
max_ratio: 4.0
|
||||
#<OPTIONAL> seeding time var: Will set the torrent Maximum seeding time (min) until torrent is stopped from seeding
|
||||
max_seeding_time: 86400
|
||||
|
||||
#Can have additional categories set with separate ratio/seeding times defined.
|
||||
series-completed:
|
||||
#<OPTIONAL> exclude_tags var: Will exclude the following tags when searching through the category.
|
||||
exclude_tags:
|
||||
- Beyond-HD
|
||||
- BroadcasTheNet
|
||||
#<OPTIONAL> cleanup var: WARNING!! Setting this as true Will remove and delete contents of any torrents that are in paused state and has the NoHL tag
|
||||
cleanup: false
|
||||
#<OPTIONAL> max_ratio var: Will set the torrent Maximum share ratio until torrent is stopped from seeding/uploading
|
||||
max_ratio: 4.0
|
||||
#<OPTIONAL> seeding time var: Will set the torrent Maximum seeding time (min) until torrent is stopped from seeding
|
||||
max_seeding_time: 86400
|
||||
|
||||
#Recycle Bin method of deletion will move files into the recycle bin instead of directly deleting them in qbit
|
||||
recyclebin:
|
||||
enabled: true
|
||||
#<OPTIONAL> empty_after_x_days var: Will automatically remove all files and folders in recycle bin after x days.
|
||||
# If this variable is not defined it, the RecycleBin will never be emptied.
|
||||
# Setting this variable to 0 will delete files immediately.
|
||||
empty_after_x_days: 60
|
||||
|
||||
# Orphaned files are those in the root_dir download directory that are not referenced by any active torrents.
|
||||
orphaned:
|
||||
# File patterns that will not be considered orphaned files. Handy for generated files that aren't part of the torrent but belong with the torrent's files
|
||||
exclude_patterns:
|
||||
- "**/.DS_Store"
|
||||
- "**/Thumbs.db"
|
||||
- "**/@eaDir"
|
||||
- "/data/torrents/temp/**"
|
|
@ -20,17 +20,25 @@ cat:
|
|||
movies: "/data/torrents/Movies"
|
||||
tv: "TV"
|
||||
|
||||
# Tag Parameters
|
||||
# Tag Parameters (Use either Format 1 or Format 2)
|
||||
tags:
|
||||
# Format 1
|
||||
# <Tracker URL Keyword>: <Tag Name>
|
||||
# Format 2
|
||||
# <Tracker URL Keyword>:
|
||||
# tag: <Tag Name>
|
||||
# <MANDATORY> Will set the torrent Maximum share ratio until torrent is stopped from seeding/uploading. -2 means the global limit should be used, -1 means no limit.
|
||||
# max_ratio: 5.0
|
||||
# <OPTIONAL> Will set the torrent Maximum seeding time (min) until torrent is stopped from seeding. -2 means the global limit should be used, -1 means no limit.
|
||||
# max_seeding_time: 129600
|
||||
# <OPTIONAL> Will limit the upload speed KiB/s (KiloBytes/second) (-1 sets the limit to infinity)
|
||||
# limit_upload_speed: 150
|
||||
|
||||
#Format 1 Examples
|
||||
animebytes.tv: AnimeBytes
|
||||
avistaz: Avistaz
|
||||
beyond-hd: Beyond-HD
|
||||
blutopia: Blutopia
|
||||
cartoonchaos: CartoonChaos
|
||||
digitalcore: DigitalCore
|
||||
gazellegames: GGn
|
||||
hdts: HDTorrents
|
||||
landof.tv: BroadcasTheNet
|
||||
myanonamouse: MaM
|
||||
passthepopcorn: PassThePopcorn
|
||||
|
@ -39,6 +47,22 @@ tags:
|
|||
torrentdb: TorrentDB
|
||||
torrentleech: TorrentLeech
|
||||
tv-vault: TV-Vault
|
||||
|
||||
#Format 2 Examples
|
||||
avistaz:
|
||||
tag: Avistaz
|
||||
max_ratio: 5.0
|
||||
max_seeding_time: 129600
|
||||
limit_upload_speed: 150
|
||||
digitalcore
|
||||
tag: DigitalCore
|
||||
max_ratio: 5.0
|
||||
gazellegames:
|
||||
tag: GGn
|
||||
limit_upload_speed: 150
|
||||
hdts:
|
||||
tag: HDTorrents
|
||||
max_seeding_time: 129600
|
||||
|
||||
#Tag Movies/Series that are not hard linked
|
||||
nohardlinks:
|
||||
|
|
207
qbit_manage.py
207
qbit_manage.py
|
@ -1,6 +1,6 @@
|
|||
#!/usr/bin/python3
|
||||
|
||||
import argparse, logging, os, sys, time, shutil, urllib3, stat, fnmatch
|
||||
import argparse, logging, os, sys, time, shutil, stat, fnmatch
|
||||
from logging.handlers import RotatingFileHandler
|
||||
from datetime import timedelta,datetime
|
||||
from collections import Counter
|
||||
|
@ -8,7 +8,7 @@ from pathlib import Path
|
|||
|
||||
try:
|
||||
import yaml, schedule
|
||||
from qbittorrentapi import Client
|
||||
from qbittorrentapi import Client, LoginFailed, APIConnectionError
|
||||
from modules.docker import GracefulKiller
|
||||
from modules import util
|
||||
except ModuleNotFoundError:
|
||||
|
@ -28,7 +28,7 @@ parser.add_argument('-lf', '--log-file', dest='logfile', action='store',default=
|
|||
parser.add_argument('-cs', '--cross-seed', dest='cross_seed', action="store_true", default=False, help='Use this after running cross-seed script to add torrents from the cross-seed output folder to qBittorrent')
|
||||
parser.add_argument('-re', '--recheck', dest='recheck', action="store_true", default=False, help='Recheck paused torrents sorted by lowest size. Resume if Completed.')
|
||||
parser.add_argument('-cu', '--cat-update', dest='cat_update', action="store_true", default=False, help='Use this if you would like to update your categories.')
|
||||
parser.add_argument('-tu', '--tag-update', dest='tag_update', action="store_true", default=False, help='Use this if you would like to update your tags. (Only adds tags to untagged torrents)')
|
||||
parser.add_argument('-tu', '--tag-update', dest='tag_update', action="store_true", default=False, help='Use this if you would like to update your tags and/or set seed goals/limit upload speed by tag. (Only adds tags to untagged torrents)')
|
||||
parser.add_argument('-ru', '--rem-unregistered', dest='rem_unregistered', action="store_true", default=False, help='Use this if you would like to remove unregistered torrents.')
|
||||
parser.add_argument('-ro', '--rem-orphaned', dest='rem_orphaned', action="store_true", default=False, help='Use this if you would like to remove unregistered torrents.')
|
||||
parser.add_argument('-tnhl', '--tag-nohardlinks', dest='tag_nohardlinks', action="store_true", default=False, help='Use this to tag any torrents that do not have any hard links associated with any of the files. This is useful for those that use Sonarr/Radarr which hard link your media files with the torrents for seeding. When files get upgraded they no longer become linked with your media therefore will be tagged with a new tag noHL. You can then safely delete/remove these torrents to free up any extra space that is not being used by your media folder.')
|
||||
|
@ -132,8 +132,6 @@ else:
|
|||
|
||||
|
||||
os.makedirs(os.path.join(default_dir, "logs"), exist_ok=True)
|
||||
urllib3.disable_warnings()
|
||||
|
||||
|
||||
logger = logging.getLogger('qBit Manage')
|
||||
logging.DRYRUN = 25
|
||||
|
@ -180,10 +178,12 @@ if 'pass' in cfg['qbt']:
|
|||
else:
|
||||
password = ''
|
||||
|
||||
client = Client(host=host,
|
||||
username=username,
|
||||
password=password)
|
||||
|
||||
client = Client(host=host, username=username, password=password)
|
||||
try:
|
||||
client.auth_log_in()
|
||||
except (LoginFailed,APIConnectionError)as e:
|
||||
logger.error(e)
|
||||
sys.exit(0)
|
||||
|
||||
############FUNCTIONS##############
|
||||
#truncate the value of the torrent url to remove sensitive information
|
||||
|
@ -203,24 +203,42 @@ def get_category(path):
|
|||
category = ''
|
||||
return category
|
||||
category = ''
|
||||
logger.warning('No categories matched. Check your config.yml file. - Setting category to NULL')
|
||||
logger.warning(f'No categories matched for the save path {path}. Check your config.yml file. - Setting category to NULL')
|
||||
return category
|
||||
|
||||
#Get tags from config file based on keyword
|
||||
def get_tags(urls):
|
||||
if 'tags' in cfg and cfg["tags"] != None:
|
||||
tag_path = cfg['tags']
|
||||
for i, f in tag_path.items():
|
||||
new_tag = ''
|
||||
max_ratio = ''
|
||||
max_seeding_time = ''
|
||||
limit_upload_speed = ''
|
||||
url = trunc_val(urls[0], '/')
|
||||
if 'tags' in cfg and cfg["tags"] != None and urls:
|
||||
tag_values = cfg['tags']
|
||||
for tag_url, tag_details in tag_values.items():
|
||||
new_tag = ''
|
||||
max_ratio = ''
|
||||
max_seeding_time = ''
|
||||
limit_upload_speed = ''
|
||||
# If using Format 1
|
||||
if(type(tag_details) == str):
|
||||
new_tag = tag_details
|
||||
# Using Format 2
|
||||
else:
|
||||
if 'tag' in tag_details:
|
||||
new_tag = tag_details['tag']
|
||||
else:
|
||||
logger.warning(f'No tags defined for {tag_url}. Please check your config.yml file.')
|
||||
if 'max_ratio' in tag_details: max_ratio = tag_details['max_ratio']
|
||||
if 'max_seeding_time' in tag_details: max_seeding_time = tag_details['max_seeding_time']
|
||||
if 'limit_upload_speed' in tag_details: limit_upload_speed = tag_details['limit_upload_speed']
|
||||
for url in urls:
|
||||
if i in url:
|
||||
tag = f
|
||||
if tag: return tag,trunc_val(url, '/')
|
||||
if tag_url in url:
|
||||
return (new_tag,trunc_val(url, '/'),max_ratio,max_seeding_time,limit_upload_speed)
|
||||
else:
|
||||
tag = ('','')
|
||||
return tag
|
||||
tag = ('','')
|
||||
logger.warning('No tags matched. Check your config.yml file. Setting tag to NULL')
|
||||
return tag
|
||||
return (new_tag,url,max_ratio,max_seeding_time,limit_upload_speed)
|
||||
logger.warning(f'No tags matched for {url}. Please check your config.yml file. Setting tag to NULL')
|
||||
return (new_tag,url,max_ratio,max_seeding_time,limit_upload_speed)
|
||||
|
||||
|
||||
#Move files from source to destination, mod variable is to change the date modified of the file being moved
|
||||
|
@ -266,6 +284,8 @@ def get_torrent_info(t_list):
|
|||
save_path = torrent.save_path
|
||||
category = get_category(save_path)
|
||||
is_complete = False
|
||||
msg = None
|
||||
status = None
|
||||
if torrent.name in torrentdict:
|
||||
t_count = torrentdict[torrent.name]['count'] + 1
|
||||
msg_list = torrentdict[torrent.name]['msg']
|
||||
|
@ -278,9 +298,12 @@ def get_torrent_info(t_list):
|
|||
status_list = []
|
||||
is_complete = torrent.state_enum.is_complete
|
||||
first_hash = torrent.hash
|
||||
msg,status = [(x.msg,x.status) for x in torrent.trackers if x.url.startswith('http')][0]
|
||||
msg_list.append(msg)
|
||||
status_list.append(status)
|
||||
try:
|
||||
msg,status = [(x.msg,x.status) for x in torrent.trackers if x.url.startswith('http')][0]
|
||||
except IndexError:
|
||||
pass
|
||||
if msg != None: msg_list.append(msg)
|
||||
if status != None: status_list.append(status)
|
||||
torrentattr = {'Category': category, 'save_path': save_path, 'count': t_count, 'msg': msg_list, 'status': status_list, 'is_complete': is_complete, 'first_hash':first_hash}
|
||||
torrentdict[torrent.name] = torrentattr
|
||||
return torrentdict
|
||||
|
@ -293,8 +316,7 @@ def set_recheck():
|
|||
torrent_sorted_list = client.torrents.info(status_filter='paused',sort='size')
|
||||
if torrent_sorted_list:
|
||||
for torrent in torrent_sorted_list:
|
||||
new_tag,t_url = get_tags([x.url for x in torrent.trackers if x.url.startswith('http')])
|
||||
if torrent.tags == '' or ('cross-seed' in torrent.tags and len([e for e in torrent.tags.split(",") if not 'noHL' in e]) == 1): torrent.add_tags(tags=new_tag)
|
||||
new_tag = get_tags([x.url for x in torrent.trackers if x.url.startswith('http')])[0]
|
||||
#Resume torrent if completed
|
||||
if torrent.progress == 1:
|
||||
#Check to see if torrent meets AutoTorrentManagement criteria
|
||||
|
@ -304,16 +326,16 @@ def set_recheck():
|
|||
logger.debug(util.insert_space(f'-- Seeding Time vs Max Seed Time: {timedelta(seconds=torrent.seeding_time)} < {timedelta(minutes=torrent.max_seeding_time)}',4))
|
||||
if torrent.ratio < torrent.max_ratio and (torrent.seeding_time < (torrent.max_seeding_time * 60)):
|
||||
if dry_run:
|
||||
logger.dryrun(f'Not Resuming {new_tag} - {torrent.name}')
|
||||
logger.dryrun(f'Not Resuming [{new_tag}] - {torrent.name}')
|
||||
else:
|
||||
logger.info(f'Resuming {new_tag} - {torrent.name}')
|
||||
logger.info(f'Resuming [{new_tag}] - {torrent.name}')
|
||||
torrent.resume()
|
||||
#Recheck
|
||||
elif torrent.progress == 0 and torrentdict[torrent.name]['is_complete'] and not torrent.state_enum.is_checking:
|
||||
if dry_run:
|
||||
logger.dryrun(f'Not Rechecking {new_tag} - {torrent.name}')
|
||||
logger.dryrun(f'Not Rechecking [{new_tag}] - {torrent.name}')
|
||||
else:
|
||||
logger.info(f'Rechecking {new_tag} - {torrent.name}')
|
||||
logger.info(f'Rechecking [{new_tag}] - {torrent.name}')
|
||||
torrent.recheck()
|
||||
|
||||
# Function used to move any torrents from the cross seed directory to the correct save directory
|
||||
|
@ -406,21 +428,22 @@ def set_category():
|
|||
num_cat = 0
|
||||
for torrent in torrent_list:
|
||||
if torrent.category == '':
|
||||
for x in torrent.trackers:
|
||||
if x.url.startswith('http'):
|
||||
t_url = trunc_val(x.url, '/')
|
||||
new_cat = get_category(torrent.save_path)
|
||||
if dry_run:
|
||||
logger.dryrun(util.insert_space(f'Torrent Name: {torrent.name}',3))
|
||||
logger.dryrun(util.insert_space(f'New Category: {new_cat}',3))
|
||||
logger.dryrun(util.insert_space(f'Tracker: {t_url}',8))
|
||||
num_cat += 1
|
||||
else:
|
||||
logger.info(util.insert_space(f'- Torrent Name: {torrent.name}',1))
|
||||
logger.info(util.insert_space(f'-- New Category: {new_cat}',5))
|
||||
logger.info(util.insert_space(f'-- Tracker: {t_url}',5))
|
||||
torrent.set_category(category=new_cat)
|
||||
num_cat += 1
|
||||
new_cat = get_category(torrent.save_path)
|
||||
try:
|
||||
t_url = [trunc_val(x.url, '/') for x in torrent.trackers if x.url.startswith('http')][0]
|
||||
except IndexError:
|
||||
t_url = None
|
||||
if dry_run:
|
||||
logger.dryrun(util.insert_space(f'Torrent Name: {torrent.name}',3))
|
||||
logger.dryrun(util.insert_space(f'New Category: {new_cat}',3))
|
||||
logger.dryrun(util.insert_space(f'Tracker: {t_url}',8))
|
||||
num_cat += 1
|
||||
else:
|
||||
logger.info(util.insert_space(f'- Torrent Name: {torrent.name}',1))
|
||||
logger.info(util.insert_space(f'-- New Category: {new_cat}',5))
|
||||
logger.info(util.insert_space(f'-- Tracker: {t_url}',5))
|
||||
torrent.set_category(category=new_cat)
|
||||
num_cat += 1
|
||||
if dry_run:
|
||||
if num_cat >= 1:
|
||||
logger.dryrun(f'Did not update {num_cat} new categories.')
|
||||
|
@ -439,18 +462,84 @@ def set_tags():
|
|||
num_tags = 0
|
||||
for torrent in torrent_list:
|
||||
if torrent.tags == '' or ('cross-seed' in torrent.tags and len([e for e in torrent.tags.split(",") if not 'noHL' in e]) == 1):
|
||||
new_tag,t_url = get_tags([x.url for x in torrent.trackers if x.url.startswith('http')])
|
||||
if dry_run:
|
||||
logger.dryrun(util.insert_space(f'Torrent Name: {torrent.name}',3))
|
||||
logger.dryrun(util.insert_space(f'New Tag: {new_tag}',8))
|
||||
logger.dryrun(util.insert_space(f'Tracker: {t_url}',8))
|
||||
num_tags += 1
|
||||
else:
|
||||
logger.info(util.insert_space(f'Torrent Name: {torrent.name}',3))
|
||||
logger.info(util.insert_space(f'New Tag: {new_tag}',8))
|
||||
logger.info(util.insert_space(f'Tracker: {t_url}',8))
|
||||
torrent.add_tags(tags=new_tag)
|
||||
num_tags += 1
|
||||
new_tag,url,max_ratio,max_seeding_time,limit_upload_speed = get_tags([x.url for x in torrent.trackers if x.url.startswith('http')])
|
||||
if new_tag:
|
||||
if dry_run:
|
||||
num_tags += 1
|
||||
logger.dryrun(util.insert_space(f'Torrent Name: {torrent.name}',3))
|
||||
logger.dryrun(util.insert_space(f'New Tag: {new_tag}',8))
|
||||
logger.dryrun(util.insert_space(f'Tracker: {url}',8))
|
||||
if limit_upload_speed:
|
||||
if limit_upload_speed == -1:
|
||||
logger.dryrun(util.insert_space(f'Limit UL Speed: Infinity',1))
|
||||
else:
|
||||
logger.dryrun(util.insert_space(f'Limit UL Speed: {limit_upload_speed} kB/s',1))
|
||||
if max_ratio:
|
||||
if max_ratio == -2:
|
||||
logger.dryrun(util.insert_space(f'Share Limit: Use Global Share Limit',4))
|
||||
continue
|
||||
elif max_ratio == -1:
|
||||
logger.dryrun(util.insert_space(f'Share Limit: Set No Share Limit',4))
|
||||
continue
|
||||
else:
|
||||
max_ratio = torrent.max_ratio
|
||||
if max_seeding_time:
|
||||
if max_seeding_time == -2:
|
||||
logger.dryrun(util.insert_space(f'Share Limit: Use Global Share Limit',4))
|
||||
continue
|
||||
elif max_seeding_time == -1:
|
||||
logger.dryrun(util.insert_space(f'Share Limit: Set No Share Limit',4))
|
||||
continue
|
||||
else:
|
||||
max_seeding_time = torrent.max_seeding_time
|
||||
if max_ratio != torrent.max_ratio and max_seeding_time != torrent.max_seeding_time:
|
||||
logger.dryrun(util.insert_space(f'Share Limit: Max Ratio = {max_ratio}, Max Seed Time = {max_seeding_time} min',4))
|
||||
elif max_ratio != torrent.max_ratio:
|
||||
logger.dryrun(util.insert_space(f'Share Limit: Max Ratio = {max_ratio}',4))
|
||||
elif max_seeding_time != torrent.max_seeding_time:
|
||||
logger.dryrun(util.insert_space(f'Share Limit: Max Seed Time = {max_seeding_time} min',4))
|
||||
else:
|
||||
torrent.add_tags(tags=new_tag)
|
||||
num_tags += 1
|
||||
logger.info(util.insert_space(f'Torrent Name: {torrent.name}',3))
|
||||
logger.info(util.insert_space(f'New Tag: {new_tag}',8))
|
||||
logger.info(util.insert_space(f'Tracker: {url}',8))
|
||||
if limit_upload_speed:
|
||||
if limit_upload_speed == -1:
|
||||
logger.info(util.insert_space(f'Limit UL Speed: Infinity',1))
|
||||
else:
|
||||
logger.info(util.insert_space(f'Limit UL Speed: {limit_upload_speed} kB/s',1))
|
||||
torrent.set_upload_limit(limit_upload_speed*1024)
|
||||
if max_ratio:
|
||||
if max_ratio == -2:
|
||||
logger.info(util.insert_space(f'Share Limit: Use Global Share Limit',4))
|
||||
torrent.set_share_limits(-2,-2)
|
||||
continue
|
||||
elif max_ratio == -1:
|
||||
logger.info(util.insert_space(f'Share Limit: Set No Share Limit',4))
|
||||
torrent.set_share_limits(-1,-1)
|
||||
continue
|
||||
else:
|
||||
max_ratio = torrent.max_ratio
|
||||
if max_seeding_time:
|
||||
if max_seeding_time == -2:
|
||||
logger.info(util.insert_space(f'Share Limit: Use Global Share Limit',4))
|
||||
torrent.set_share_limits(-2,-2)
|
||||
continue
|
||||
elif max_seeding_time == -1:
|
||||
logger.info(util.insert_space(f'Share Limit: Set No Share Limit',4))
|
||||
torrent.set_share_limits(-1,-1)
|
||||
continue
|
||||
else:
|
||||
max_seeding_time = torrent.max_seeding_time
|
||||
if max_ratio != torrent.max_ratio and max_seeding_time != torrent.max_seeding_time:
|
||||
logger.info(util.insert_space(f'Share Limit: Max Ratio = {max_ratio}, Max Seed Time = {max_seeding_time} min',4))
|
||||
elif max_ratio != torrent.max_ratio:
|
||||
logger.info(util.insert_space(f'Share Limit: Max Ratio = {max_ratio}',4))
|
||||
elif max_seeding_time != torrent.max_seeding_time:
|
||||
logger.info(util.insert_space(f'Share Limit: Max Seed Time = {max_seeding_time} min',4))
|
||||
torrent.set_share_limits(max_ratio,max_seeding_time)
|
||||
|
||||
if dry_run:
|
||||
if num_tags >= 1:
|
||||
logger.dryrun(f'Did not update {num_tags} new tags.')
|
||||
|
@ -552,6 +641,7 @@ def set_rem_unregistered():
|
|||
def set_rem_orphaned():
|
||||
if rem_orphaned:
|
||||
util.separator(f"Checking for Orphaned Files", space=False, border=False)
|
||||
global torrent_list
|
||||
torrent_files = []
|
||||
root_files = []
|
||||
orphaned_files = []
|
||||
|
@ -562,6 +652,9 @@ def set_rem_orphaned():
|
|||
root_files = [os.path.join(path.replace(remote_path,root_path), name) for path, subdirs, files in os.walk(remote_path) for name in files if os.path.join(remote_path,'orphaned_data') not in path and os.path.join(remote_path,'.RecycleBin') not in path]
|
||||
else:
|
||||
root_files = [os.path.join(path, name) for path, subdirs, files in os.walk(root_path) for name in files if os.path.join(root_path,'orphaned_data') not in path and os.path.join(root_path,'.RecycleBin') not in path]
|
||||
|
||||
#Get an updated list of torrents
|
||||
torrent_list = client.torrents.info(sort='added_on')
|
||||
|
||||
for torrent in torrent_list:
|
||||
for file in torrent.files:
|
||||
|
|
BIN
qbm_logo.png
Normal file
BIN
qbm_logo.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 316 KiB |
Loading…
Add table
Reference in a new issue