2021-02-20 13:04:02 +08:00
#!/usr/bin/python3
2022-08-21 10:14:28 +08:00
import argparse , os , sys , time , glob
2021-12-29 01:19:58 +08:00
from datetime import datetime , timedelta
2021-11-23 03:53:01 +08:00
try :
2021-12-13 11:06:34 +08:00
import schedule
2022-08-21 10:14:28 +08:00
from modules . logs import MyLogger
2021-11-23 03:53:01 +08:00
except ModuleNotFoundError :
print ( " Requirements Error: Requirements are not installed " )
sys . exit ( 0 )
2021-02-25 02:28:07 +08:00
2021-11-23 10:51:32 +08:00
2021-11-21 11:54:20 +08:00
if sys . version_info [ 0 ] != 3 or sys . version_info [ 1 ] < 6 :
print ( " Version Error: Version: %s . %s . %s incompatible please use Python 3.6+ " % ( sys . version_info [ 0 ] , sys . version_info [ 1 ] , sys . version_info [ 2 ] ) )
sys . exit ( 0 )
2021-02-20 13:04:02 +08:00
2021-11-23 03:53:01 +08:00
parser = argparse . ArgumentParser ( ' qBittorrent Manager. ' , description = ' A mix of scripts combined for managing qBittorrent. ' )
2021-12-17 22:19:40 +08:00
parser . add_argument ( " -db " , " --debug " , dest = " debug " , help = argparse . SUPPRESS , action = " store_true " , default = False )
parser . add_argument ( " -tr " , " --trace " , dest = " trace " , help = argparse . SUPPRESS , action = " store_true " , default = False )
2021-11-23 03:53:01 +08:00
parser . add_argument ( ' -r ' , ' --run ' , dest = ' run ' , action = ' store_true ' , default = False , help = ' Run without the scheduler. Script will exit after completion. ' )
2021-12-23 23:45:15 +08:00
parser . add_argument ( ' -sch ' , ' --schedule ' , dest = ' min ' , default = ' 1440 ' , type = str , help = ' Schedule to run every x minutes. (Default set to 1440 (1 day)) ' )
2022-01-11 05:21:13 +08:00
parser . add_argument ( ' -sd ' , ' --startup-delay ' , dest = ' startupDelay ' , default = ' 0 ' , type = str , help = ' Set delay in seconds on the first run of a schedule (Default set to 0) ' )
2022-08-15 09:41:33 +08:00
parser . add_argument ( ' -c ' , ' --config-file ' , dest = ' configfiles ' , action = ' store ' , default = ' config.yml ' , type = str ,
help = ' This is used if you want to use a different name for your config.yml or if you want to load multiple config files using *. Example: tv.yml or config*.yml ' )
2022-08-21 10:14:28 +08:00
parser . add_argument ( ' -lf ' , ' --log-file ' , dest = ' logfile ' , action = ' store ' , default = ' qbit_manage.log ' , type = str ,
help = ' This is used if you want to use a different name for your log file. Example: tv.log ' , )
2021-12-29 01:19:58 +08:00
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 ' )
2021-11-23 03:53:01 +08:00
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. ' )
2021-12-29 01:19:58 +08:00
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) ' )
2021-11-23 03:53:01 +08:00
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. ' )
2022-01-11 11:00:43 +08:00
parser . add_argument ( ' -tte ' , ' --tag-tracker-error ' , dest = ' tag_tracker_error ' , action = " store_true " , default = False , help = ' Use this if you would like to tag torrents that do not have a working tracker. ' )
2021-11-23 03:53:01 +08:00
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. ' )
2021-12-29 01:19:58 +08:00
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 . ' )
2022-09-26 09:48:57 +08:00
parser . add_argument ( ' -sc ' , ' --skip-cleanup ' , dest = ' skip_cleanup ' , action = " store_true " , default = False , help = ' Use this to skip cleaning up Reycle Bin/Orphaned directory. ' )
2021-12-29 01:19:58 +08:00
parser . add_argument ( ' -dr ' , ' --dry-run ' , dest = ' dry_run ' , action = " store_true " , default = False ,
help = ' If you would like to see what is gonna happen but not actually move/delete or tag/categorize anything. ' )
2021-11-23 03:53:01 +08:00
parser . add_argument ( ' -ll ' , ' --log-level ' , dest = ' log_level ' , action = " store " , default = ' INFO ' , type = str , help = ' Change your log level. ' )
2021-11-24 04:45:16 +08:00
parser . add_argument ( " -d " , " --divider " , dest = " divider " , help = " Character that divides the sections (Default: ' = ' ) " , default = " = " , type = str )
parser . add_argument ( " -w " , " --width " , dest = " width " , help = " Screen Width (Default: 100) " , default = 100 , type = int )
2021-02-20 13:04:02 +08:00
args = parser . parse_args ( )
2021-12-29 01:19:58 +08:00
2021-11-21 11:54:20 +08:00
def get_arg ( env_str , default , arg_bool = False , arg_int = False ) :
2022-08-21 10:14:28 +08:00
env_vars = [ env_str ] if not isinstance ( env_str , list ) else env_str
final_value = None
for env_var in env_vars :
env_value = os . environ . get ( env_var )
if env_value is not None :
final_value = env_value
break
if final_value is not None :
2021-11-21 11:54:20 +08:00
if arg_bool :
2022-08-21 10:14:28 +08:00
if final_value is True or final_value is False :
return final_value
elif final_value . lower ( ) in [ " t " , " true " ] :
2021-11-21 11:54:20 +08:00
return True
else :
return False
elif arg_int :
2022-08-21 10:14:28 +08:00
return int ( final_value )
2021-11-21 11:54:20 +08:00
else :
2022-08-21 10:14:28 +08:00
return str ( final_value )
2021-11-21 11:54:20 +08:00
else :
return default
2021-12-29 01:19:58 +08:00
2021-11-22 04:49:32 +08:00
run = get_arg ( " QBT_RUN " , args . run , arg_bool = True )
2021-11-23 03:53:01 +08:00
sch = get_arg ( " QBT_SCHEDULE " , args . min )
2022-01-11 05:21:13 +08:00
startupDelay = get_arg ( " QBT_STARTUP_DELAY " , args . startupDelay )
2022-08-15 09:41:33 +08:00
config_files = get_arg ( " QBT_CONFIG " , args . configfiles )
2021-11-21 11:54:20 +08:00
log_file = get_arg ( " QBT_LOGFILE " , args . logfile )
2021-11-23 03:53:01 +08:00
cross_seed = get_arg ( " QBT_CROSS_SEED " , args . cross_seed , arg_bool = True )
recheck = get_arg ( " QBT_RECHECK " , args . recheck , arg_bool = True )
cat_update = get_arg ( " QBT_CAT_UPDATE " , args . cat_update , arg_bool = True )
tag_update = get_arg ( " QBT_TAG_UPDATE " , args . tag_update , arg_bool = True )
rem_unregistered = get_arg ( " QBT_REM_UNREGISTERED " , args . rem_unregistered , arg_bool = True )
2022-01-11 11:00:43 +08:00
tag_tracker_error = get_arg ( " QBT_TAG_TRACKER_ERROR " , args . tag_tracker_error , arg_bool = True )
2021-11-23 03:53:01 +08:00
rem_orphaned = get_arg ( " QBT_REM_ORPHANED " , args . rem_orphaned , arg_bool = True )
tag_nohardlinks = get_arg ( " QBT_TAG_NOHARDLINKS " , args . tag_nohardlinks , arg_bool = True )
2022-09-26 09:48:57 +08:00
skip_cleanup = get_arg ( " QBT_SKIP_CLEANUP " , args . skip_cleanup , arg_bool = True )
2021-11-23 03:53:01 +08:00
dry_run = get_arg ( " QBT_DRY_RUN " , args . dry_run , arg_bool = True )
log_level = get_arg ( " QBT_LOG_LEVEL " , args . log_level )
2021-11-24 04:45:16 +08:00
divider = get_arg ( " QBT_DIVIDER " , args . divider )
screen_width = get_arg ( " QBT_WIDTH " , args . width , arg_int = True )
2021-12-17 22:19:40 +08:00
debug = get_arg ( " QBT_DEBUG " , args . debug , arg_bool = True )
trace = get_arg ( " QBT_TRACE " , args . trace , arg_bool = True )
if debug or trace : log_level = ' DEBUG '
2021-12-13 11:06:34 +08:00
stats = { }
args = { }
2021-12-16 07:34:26 +08:00
2022-08-15 09:41:33 +08:00
if os . path . isdir ( ' /config ' ) and glob . glob ( os . path . join ( ' /config ' , config_files ) ) :
2021-12-17 02:34:03 +08:00
default_dir = ' /config '
else :
default_dir = os . path . join ( os . path . dirname ( os . path . abspath ( __file__ ) ) , " config " )
2021-12-16 07:34:26 +08:00
2022-08-15 09:41:33 +08:00
if ' * ' not in config_files :
config_files = [ config_files ]
else :
glob_configs = glob . glob ( os . path . join ( default_dir , config_files ) )
if glob_configs :
config_files = [ os . path . split ( x ) [ - 1 ] for x in glob_configs ]
else :
print ( f " Config Error: Unable to find any config files in the pattern ' { config_files } ' . " )
sys . exit ( 0 )
2021-12-29 01:19:58 +08:00
for v in [
' run ' ,
' sch ' ,
2022-01-11 05:21:13 +08:00
' startupDelay ' ,
2022-08-15 09:41:33 +08:00
' config_files ' ,
2021-12-29 01:19:58 +08:00
' log_file ' ,
' cross_seed ' ,
' recheck ' ,
' cat_update ' ,
' tag_update ' ,
' rem_unregistered ' ,
2022-01-11 11:00:43 +08:00
' tag_tracker_error ' ,
2021-12-29 01:19:58 +08:00
' rem_orphaned ' ,
' tag_nohardlinks ' ,
2022-09-26 09:48:57 +08:00
' skip_cleanup ' ,
2021-12-29 01:19:58 +08:00
' dry_run ' ,
' log_level ' ,
' divider ' ,
' screen_width ' ,
' debug ' ,
' trace '
] :
2021-12-13 11:06:34 +08:00
args [ v ] = eval ( v )
2021-11-21 11:54:20 +08:00
2021-11-24 04:45:16 +08:00
if screen_width < 90 or screen_width > 300 :
print ( f " Argument Error: width argument invalid: { screen_width } must be an integer between 90 and 300 using the default 100 " )
screen_width = 100
2021-12-29 01:19:58 +08:00
# Check if Schedule parameter is a number
2021-12-13 11:06:34 +08:00
try :
2021-11-22 05:38:04 +08:00
sch = int ( sch )
2021-12-13 11:06:34 +08:00
except ValueError :
2021-11-22 05:38:04 +08:00
print ( f " Schedule Error: Schedule is not a number. Current value is set to ' { sch } ' " )
sys . exit ( 0 )
2022-01-11 05:21:13 +08:00
# Check if StartupDelay parameter is a number
try :
startupDelay = int ( startupDelay )
except ValueError :
print ( f " startupDelay Error: startupDelay is not a number. Current value is set to ' { startupDelay } ' " )
sys . exit ( 0 )
2021-02-27 04:59:52 +08:00
2022-08-21 10:14:28 +08:00
logger = MyLogger ( ' qBit Manage ' , log_file , log_level , default_dir , screen_width , divider [ 0 ] , False , debug or trace )
from modules import util
util . logger = logger
from modules . config import Config
from modules . util import GracefulKiller
from modules . util import Failed
2021-12-29 01:19:58 +08:00
2021-02-27 04:59:52 +08:00
2022-08-21 10:14:28 +08:00
def my_except_hook ( exctype , value , tb ) :
if issubclass ( exctype , KeyboardInterrupt ) :
sys . __excepthook__ ( exctype , value , tb )
else :
logger . critical ( " Uncaught Exception " , exc_info = ( exctype , value , tb ) )
2021-12-29 01:19:58 +08:00
2021-11-24 04:45:16 +08:00
2022-08-21 10:14:28 +08:00
sys . excepthook = my_except_hook
2021-02-21 11:45:09 +08:00
2021-11-22 04:49:32 +08:00
version = " Unknown "
with open ( os . path . join ( os . path . dirname ( os . path . abspath ( __file__ ) ) , " VERSION " ) ) as handle :
for line in handle . readlines ( ) :
line = line . strip ( )
if len ( line ) > 0 :
version = line
break
2021-12-29 01:19:58 +08:00
2022-08-15 09:41:33 +08:00
def start_loop ( ) :
2022-08-21 10:14:28 +08:00
if len ( config_files ) == 1 :
args [ " config_file " ] = config_files [ 0 ]
2022-08-15 09:41:33 +08:00
start ( )
2022-08-21 10:14:28 +08:00
else :
for config_file in config_files :
args [ " config_file " ] = config_file
config_base = os . path . splitext ( config_file ) [ 0 ]
logger . add_config_handler ( config_base )
start ( )
logger . remove_config_handler ( config_base )
2022-08-15 09:41:33 +08:00
2021-11-22 04:49:32 +08:00
def start ( ) :
2021-11-24 04:45:16 +08:00
start_time = datetime . now ( )
2021-12-13 11:06:34 +08:00
args [ " time " ] = start_time . strftime ( " % H: % M " )
args [ " time_obj " ] = start_time
stats_summary = [ ]
2022-08-22 05:08:13 +08:00
logger . separator ( " Starting Run " )
2021-12-13 11:06:34 +08:00
cfg = None
2022-01-11 06:33:06 +08:00
body = ' '
run_time = ' '
end_time = None
next_run = None
2021-12-13 11:06:34 +08:00
global stats
2021-12-29 01:19:58 +08:00
stats = {
2021-12-13 11:06:34 +08:00
" added " : 0 ,
" deleted " : 0 ,
" deleted_contents " : 0 ,
" resumed " : 0 ,
" rechecked " : 0 ,
2021-12-29 01:19:58 +08:00
" orphaned " : 0 ,
2021-12-13 11:06:34 +08:00
" recycle_emptied " : 0 ,
2022-09-26 09:48:57 +08:00
" orphaned_emptied " : 0 ,
2021-12-13 11:06:34 +08:00
" tagged " : 0 ,
" categorized " : 0 ,
" rem_unreg " : 0 ,
2022-01-11 11:00:43 +08:00
" tagged_tracker_error " : 0 ,
" untagged_tracker_error " : 0 ,
" tagged_noHL " : 0 ,
" untagged_noHL " : 0
2021-12-13 11:06:34 +08:00
}
2022-01-11 06:33:06 +08:00
def FinishedRun ( ) :
2022-08-22 05:08:13 +08:00
nonlocal end_time , start_time , stats_summary , run_time , next_run , body
2022-01-11 06:33:06 +08:00
end_time = datetime . now ( )
run_time = str ( end_time - start_time ) . split ( ' . ' ) [ 0 ]
_ , nr = calc_next_run ( sch , True )
next_run_str = nr [ ' next_run_str ' ]
next_run = nr [ ' next_run ' ]
2022-08-22 05:08:13 +08:00
body = logger . separator ( f " Finished Run \n { os . linesep . join ( stats_summary ) if len ( stats_summary ) > 0 else ' ' } \n Run Time: { run_time } \n { next_run_str if len ( next_run_str ) > 0 else ' ' } "
2022-08-21 10:14:28 +08:00
. replace ( ' \n \n ' , ' \n ' ) . rstrip ( ) ) [ 0 ]
2022-01-11 06:33:06 +08:00
return next_run , body
2021-12-13 11:06:34 +08:00
try :
2021-12-29 01:19:58 +08:00
cfg = Config ( default_dir , args )
2021-12-13 11:06:34 +08:00
except Exception as e :
2022-01-11 06:33:06 +08:00
if ' Qbittorrent Error ' in e . args [ 0 ] :
2022-08-21 10:14:28 +08:00
logger . print_line ( e , ' CRITICAL ' )
logger . print_line ( ' Exiting scheduled Run. ' , ' CRITICAL ' )
2022-01-11 06:33:06 +08:00
FinishedRun ( )
return None
else :
2022-08-21 10:14:28 +08:00
logger . stacktrace ( )
logger . print_line ( e , ' CRITICAL ' )
2021-12-29 01:19:58 +08:00
2021-12-13 11:06:34 +08:00
if cfg :
2021-12-29 01:19:58 +08:00
# Set Category
2021-12-13 11:06:34 +08:00
num_categorized = cfg . qbt . category ( )
stats [ " categorized " ] + = num_categorized
2021-12-29 01:19:58 +08:00
# Set Tags
2021-12-13 11:06:34 +08:00
num_tagged = cfg . qbt . tags ( )
stats [ " tagged " ] + = num_tagged
2021-12-29 01:19:58 +08:00
# Remove Unregistered Torrents
2022-01-11 11:00:43 +08:00
num_deleted , num_deleted_contents , num_tagged , num_untagged = cfg . qbt . rem_unregistered ( )
2021-12-13 11:06:34 +08:00
stats [ " rem_unreg " ] + = ( num_deleted + num_deleted_contents )
stats [ " deleted " ] + = num_deleted
stats [ " deleted_contents " ] + = num_deleted_contents
2022-01-11 11:00:43 +08:00
stats [ " tagged_tracker_error " ] + = num_tagged
stats [ " untagged_tracker_error " ] + = num_untagged
stats [ " tagged " ] + = num_tagged
2021-12-13 11:06:34 +08:00
2021-12-29 01:19:58 +08:00
# Set Cross Seed
2021-12-13 11:06:34 +08:00
num_added , num_tagged = cfg . qbt . cross_seed ( )
stats [ " added " ] + = num_added
stats [ " tagged " ] + = num_tagged
2021-12-29 01:19:58 +08:00
# Recheck Torrents
2021-12-13 11:06:34 +08:00
num_resumed , num_rechecked = cfg . qbt . recheck ( )
stats [ " resumed " ] + = num_resumed
stats [ " rechecked " ] + = num_rechecked
2021-12-29 01:19:58 +08:00
# Tag NoHardLinks
num_tagged , num_untagged , num_deleted , num_deleted_contents = cfg . qbt . tag_nohardlinks ( )
2021-12-13 11:06:34 +08:00
stats [ " tagged " ] + = num_tagged
2022-01-11 11:00:43 +08:00
stats [ " tagged_noHL " ] + = num_tagged
stats [ " untagged_noHL " ] + = num_untagged
2021-12-13 11:06:34 +08:00
stats [ " deleted " ] + = num_deleted
stats [ " deleted_contents " ] + = num_deleted_contents
2021-12-29 01:19:58 +08:00
# Remove Orphaned Files
2021-12-13 11:06:34 +08:00
num_orphaned = cfg . qbt . rem_orphaned ( )
stats [ " orphaned " ] + = num_orphaned
2022-01-11 06:33:06 +08:00
# Empty RecycleBin
2022-09-26 09:48:57 +08:00
recycle_emptied = cfg . cleanup_dirs ( " Recycle Bin " )
2021-12-13 11:06:34 +08:00
stats [ " recycle_emptied " ] + = recycle_emptied
2022-09-26 09:48:57 +08:00
# Empty Orphaned Directory
orphaned_emptied = cfg . cleanup_dirs ( " Orphaned Data " )
stats [ " orphaned_emptied " ] + = orphaned_emptied
2021-12-13 11:06:34 +08:00
if stats [ " categorized " ] > 0 : stats_summary . append ( f " Total Torrents Categorized: { stats [ ' categorized ' ] } " )
if stats [ " tagged " ] > 0 : stats_summary . append ( f " Total Torrents Tagged: { stats [ ' tagged ' ] } " )
if stats [ " rem_unreg " ] > 0 : stats_summary . append ( f " Total Unregistered Torrents Removed: { stats [ ' rem_unreg ' ] } " )
2022-01-11 11:00:43 +08:00
if stats [ " tagged_tracker_error " ] > 0 : stats_summary . append ( f " Total { cfg . settings [ ' tracker_error_tag ' ] } Torrents Tagged: { stats [ ' tagged_tracker_error ' ] } " )
if stats [ " untagged_tracker_error " ] > 0 : stats_summary . append ( f " Total { cfg . settings [ ' tracker_error_tag ' ] } Torrents untagged: { stats [ ' untagged_tracker_error ' ] } " )
2021-12-13 11:06:34 +08:00
if stats [ " added " ] > 0 : stats_summary . append ( f " Total Torrents Added: { stats [ ' added ' ] } " )
if stats [ " resumed " ] > 0 : stats_summary . append ( f " Total Torrents Resumed: { stats [ ' resumed ' ] } " )
if stats [ " rechecked " ] > 0 : stats_summary . append ( f " Total Torrents Rechecked: { stats [ ' rechecked ' ] } " )
if stats [ " deleted " ] > 0 : stats_summary . append ( f " Total Torrents Deleted: { stats [ ' deleted ' ] } " )
if stats [ " deleted_contents " ] > 0 : stats_summary . append ( f " Total Torrents + Contents Deleted : { stats [ ' deleted_contents ' ] } " )
if stats [ " orphaned " ] > 0 : stats_summary . append ( f " Total Orphaned Files: { stats [ ' orphaned ' ] } " )
2022-01-11 11:00:43 +08:00
if stats [ " tagged_noHL " ] > 0 : stats_summary . append ( f " Total noHL Torrents Tagged: { stats [ ' tagged_noHL ' ] } " )
if stats [ " untagged_noHL " ] > 0 : stats_summary . append ( f " Total noHL Torrents untagged: { stats [ ' untagged_noHL ' ] } " )
2021-12-13 11:06:34 +08:00
if stats [ " recycle_emptied " ] > 0 : stats_summary . append ( f " Total Files Deleted from Recycle Bin: { stats [ ' recycle_emptied ' ] } " )
2022-09-26 09:48:57 +08:00
if stats [ " orphaned_emptied " ] > 0 : stats_summary . append ( f " Total Files Deleted from Orphaned Data: { stats [ ' orphaned_emptied ' ] } " )
2021-12-13 11:06:34 +08:00
2022-01-11 06:33:06 +08:00
FinishedRun ( )
2021-12-17 22:19:40 +08:00
if cfg :
try :
2022-01-01 22:54:59 +08:00
cfg . Webhooks . end_time_hooks ( start_time , end_time , run_time , next_run , stats , body )
2021-12-17 22:19:40 +08:00
except Failed as e :
2022-08-21 10:14:28 +08:00
logger . stacktrace ( )
2021-12-17 22:19:40 +08:00
logger . error ( f " Webhooks Error: { e } " )
2021-12-29 01:19:58 +08:00
2021-11-23 10:51:32 +08:00
def end ( ) :
logger . info ( " Exiting Qbit_manage " )
2022-08-21 10:14:28 +08:00
logger . remove_main_handler ( )
2021-11-23 10:51:32 +08:00
sys . exit ( 0 )
2021-11-24 04:45:16 +08:00
2021-12-29 01:19:58 +08:00
def calc_next_run ( sch , print = False ) :
2021-12-23 23:45:15 +08:00
current = datetime . now ( ) . strftime ( " % H: % M " )
seconds = sch * 60
2022-01-01 22:54:59 +08:00
time_to_run = datetime . now ( ) + timedelta ( minutes = sch )
time_to_run_str = time_to_run . strftime ( " % H: % M " )
new_seconds = ( datetime . strptime ( time_to_run_str , " % H: % M " ) - datetime . strptime ( current , " % H: % M " ) ) . total_seconds ( )
2021-12-23 23:45:15 +08:00
time_str = ' '
2022-01-01 22:54:59 +08:00
next_run = { }
if run is False :
next_run [ ' next_run ' ] = time_to_run
if new_seconds < 0 :
new_seconds + = 86400
if ( seconds is None or new_seconds < seconds ) and new_seconds > 0 :
seconds = new_seconds
if seconds is not None :
hours = int ( seconds / / 3600 )
minutes = int ( ( seconds % 3600 ) / / 60 )
time_str = f " { hours } Hour { ' s ' if hours > 1 else ' ' } { ' and ' if minutes > 1 else ' ' } " if hours > 0 else " "
time_str + = f " { minutes } Minute { ' s ' if minutes > 1 else ' ' } " if minutes > 0 else " "
if print : next_run [ ' next_run_str ' ] = ( f " Current Time: { current } | { time_str } until the next run at { time_to_run_str } " )
else :
next_run [ ' next_run ' ] = None
next_run [ ' next_run_str ' ] = ' '
return time_str , next_run
2021-12-23 23:45:15 +08:00
2021-12-29 01:19:58 +08:00
2021-02-28 11:47:49 +08:00
if __name__ == ' __main__ ' :
2021-11-23 10:51:32 +08:00
killer = GracefulKiller ( )
2022-08-21 10:14:28 +08:00
logger . add_main_handler ( )
logger . separator ( )
logger . info_center ( " _ _ _ " ) # noqa: W605
logger . info_center ( " | | (_) | " ) # noqa: W605
logger . info_center ( " __ _| |__ _| |_ _ __ ___ __ _ _ __ __ _ __ _ ___ " ) # noqa: W605
logger . info_center ( " / _` | ' _ \ | | __| | ' _ ` _ \ / _` | ' _ \ / _` |/ _` |/ _ \\ " ) # noqa: W605
logger . info_center ( " | (_| | |_) | | |_ | | | | | | (_| | | | | (_| | (_| | __/ " ) # noqa: W605
logger . info_center ( " \ __, |_.__/|_| \ __| |_| |_| |_| \ __,_|_| |_| \ __,_| \ __, | \ ___| " ) # noqa: W605
logger . info_center ( " | | ______ __/ | " ) # noqa: W605
logger . info_center ( " |_| |______| |___/ " ) # noqa: W605
2021-11-22 04:49:32 +08:00
logger . info ( f " Version: { version } " )
2021-12-13 11:06:34 +08:00
2022-08-21 10:14:28 +08:00
logger . separator ( loglevel = ' DEBUG ' )
2021-12-13 11:06:34 +08:00
logger . debug ( f " --run (QBT_RUN): { run } " )
logger . debug ( f " --schedule (QBT_SCHEDULE): { sch } " )
2022-01-11 05:21:13 +08:00
logger . debug ( f " --startup-delay (QBT_STARTUP_DELAY): { startupDelay } " )
2022-08-15 09:41:33 +08:00
logger . debug ( f " --config-file (QBT_CONFIG): { config_files } " )
2021-12-13 11:06:34 +08:00
logger . debug ( f " --log-file (QBT_LOGFILE): { log_file } " )
logger . debug ( f " --cross-seed (QBT_CROSS_SEED): { cross_seed } " )
logger . debug ( f " --recheck (QBT_RECHECK): { recheck } " )
logger . debug ( f " --cat-update (QBT_CAT_UPDATE): { cat_update } " )
logger . debug ( f " --tag-update (QBT_TAG_UPDATE): { tag_update } " )
logger . debug ( f " --rem-unregistered (QBT_REM_UNREGISTERED): { rem_unregistered } " )
2022-01-11 11:00:43 +08:00
logger . debug ( f " --tag-tracker-error (QBT_TAG_TRACKER_ERROR): { tag_tracker_error } " )
2021-12-13 11:06:34 +08:00
logger . debug ( f " --rem-orphaned (QBT_REM_ORPHANED): { rem_orphaned } " )
logger . debug ( f " --tag-nohardlinks (QBT_TAG_NOHARDLINKS): { tag_nohardlinks } " )
2022-09-26 09:48:57 +08:00
logger . debug ( f " --skip-cleanup (QBT_SKIP_CLEANUP): { skip_cleanup } " )
2021-12-13 11:06:34 +08:00
logger . debug ( f " --dry-run (QBT_DRY_RUN): { dry_run } " )
logger . debug ( f " --log-level (QBT_LOG_LEVEL): { log_level } " )
logger . debug ( f " --divider (QBT_DIVIDER): { divider } " )
logger . debug ( f " --width (QBT_WIDTH): { screen_width } " )
2021-12-17 22:19:40 +08:00
logger . debug ( f " --debug (QBT_DEBUG): { debug } " )
logger . debug ( f " --trace (QBT_TRACE): { trace } " )
2021-12-13 11:06:34 +08:00
logger . debug ( " " )
2021-11-22 04:49:32 +08:00
try :
if run :
2021-12-29 01:19:58 +08:00
logger . info ( " Run Mode: Script will exit after completion. " )
2022-08-15 09:41:33 +08:00
start_loop ( )
2021-11-22 04:49:32 +08:00
else :
2022-08-21 10:14:28 +08:00
schedule . every ( sch ) . minutes . do ( start_loop )
2022-01-01 22:54:59 +08:00
time_str , _ = calc_next_run ( sch )
logger . info ( f " Scheduled Mode: Running every { time_str } . " )
2022-01-11 05:21:13 +08:00
if startupDelay :
logger . info ( f " Startup Delay: Initial Run will start after { startupDelay } seconds " )
time . sleep ( startupDelay )
2022-08-15 09:41:33 +08:00
start_loop ( )
2021-11-23 10:51:32 +08:00
while not killer . kill_now :
2021-11-22 04:49:32 +08:00
schedule . run_pending ( )
2021-12-23 23:45:15 +08:00
time . sleep ( 60 )
2021-11-23 10:51:32 +08:00
end ( )
2021-11-22 04:49:32 +08:00
except KeyboardInterrupt :
2021-12-29 01:19:58 +08:00
end ( )