diff --git a/Dockerfile b/Dockerfile index cf31b88..83df919 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,15 +1,11 @@ -FROM python:3.9-slim -RUN echo "**** install system packages ****" \ - && apt-get update \ - && apt-get upgrade -y --no-install-recommends \ - && apt-get install -y tzdata --no-install-recommends \ - && apt-get install -y gcc g++ libxml2-dev libxslt-dev libz-dev -COPY requirements.txt / +FROM hotio/base:alpine + +RUN apk add --no-cache py3-pip +COPY --chown=hotio:users requirements.txt / RUN echo "**** install python packages ****" \ - && pip3 install --no-cache-dir --upgrade --requirement /requirements.txt \ - && apt-get autoremove -y \ - && apt-get clean \ - && rm -rf /requirements.txt /tmp/* /var/tmp/* /var/lib/apt/lists/* -COPY . / -VOLUME /config -ENTRYPOINT ["python3","qbit_manage.py"] \ No newline at end of file + && pip3 install --user --no-cache-dir --upgrade --requirement /requirements.txt \ + && rm -rf /requirements.txt /tmp/* /var/tmp/* + +COPY --chown=hotio:users . "${APP_DIR}" +WORKDIR ${APP_DIR} +ENTRYPOINT ["python3", "qbit_manage.py"] \ No newline at end of file diff --git a/VERSION b/VERSION index 56fea8a..13d683c 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -3.0.0 \ No newline at end of file +3.0.1 \ No newline at end of file diff --git a/modules/config.py b/modules/config.py index 54636a2..f6ef1dd 100644 --- a/modules/config.py +++ b/modules/config.py @@ -57,7 +57,7 @@ class Config: self.nohardlinks[cat]['max_seeding_time'] = self.util.check_for_attribute(self.data, "max_seeding_time", parent="nohardlinks", subparent=cat, var_type="int", default_int=-2, default_is_none=True,do_print=False) self.nohardlinks[cat]['limit_upload_speed'] = self.util.check_for_attribute(self.data, "limit_upload_speed", parent="nohardlinks", subparent=cat, var_type="int", default_int=-1, default_is_none=True,do_print=False) else: - raise Failed(f"Config Error: Category {cat} is defined under nohardlinks attribute but is not defined in the cat attriute.") + raise Failed(f"Config Error: Category {cat} is defined under nohardlinks attribute but is not defined in the cat attribute.") else: if self.args["tag_nohardlinks"]: raise Failed("Config Error: nohardlinks attribute not found") @@ -129,7 +129,11 @@ class Config: if isinstance(tag_details,str): tags['new_tag'] = self.util.check_for_attribute(self.data, tag_url, parent="tags",default=default_tag) self.util.check_for_attribute(self.data, "tag", parent="tags",subparent=tag_url, default=tags['new_tag'],do_print=False) - if tags['new_tag'] == default_tag: self.data['tags'][tag_url]['tag'] = default_tag + if tags['new_tag'] == default_tag: + try: + self.data['tags'][tag_url]['tag'] = default_tag + except Exception as e: + self.data['tags'][tag_url] = {'tag': default_tag} # Using Format 2 else: tags['new_tag'] = self.util.check_for_attribute(self.data, "tag", parent="tags", subparent=tag_url, default=tag_url) @@ -141,7 +145,10 @@ class Config: if tags['url']: default_tag = tags['url'].split('/')[2].split(':')[0] tags['new_tag'] = self.util.check_for_attribute(self.data, "tag", parent="tags",subparent=default_tag, default=default_tag) - self.data['tags'][default_tag]['tag'] = default_tag + try: + self.data['tags'][default_tag]['tag'] = default_tag + except Exception as e: + self.data['tags'][default_tag] = {'tag': default_tag} logger.warning(f'No tags matched for {tags["url"]}. Please check your config.yml file. Setting tag to {default_tag}') return (tags) diff --git a/modules/qbittorrent.py b/modules/qbittorrent.py index cb92e22..42bd34a 100644 --- a/modules/qbittorrent.py +++ b/modules/qbittorrent.py @@ -202,8 +202,6 @@ class Qbt: else: # Deletes torrent with data if cleanup is set to true and meets the ratio/seeding requirements if (nohardlinks[category]['cleanup'] and torrent.state_enum.is_paused and len(nohardlinks[category])>0): - print_line(f'Torrent Name: {torrent.name} has no hard links found and meets ratio/seeding requirements.',loglevel) - print_line(util.insert_space(f"Cleanup flag set to true. {'Not Deleting' if dry_run else 'Deleting'} torrent + contents.",6),loglevel) tdel_dict[torrent.name] = torrent['content_path'].replace(root_dir,root_dir) #Checks to see if previous noHL tagged torrents now have hard links. if (not (util.nohardlink(torrent['content_path'].replace(root_dir,root_dir))) and ('noHL' in torrent.tags)): @@ -221,14 +219,16 @@ class Qbt: if torrent.name in tdel_dict.keys() and 'noHL' in torrent.tags: #Double check that the content path is the same before we delete anything if torrent['content_path'].replace(root_dir,root_dir) == tdel_dict[torrent.name]: + print_line(f'Torrent Name: {torrent.name}',loglevel) + print_line(util.insert_space(f"Cleanup: True [No hard links found and meets Share Limits.]",5),loglevel) if (os.path.exists(torrent['content_path'].replace(root_dir,root_dir))): if not dry_run: self.tor_delete_recycle(torrent) del_tor_cont += 1 - print_line(util.insert_space(f'Deleted .torrent AND content files.',8),loglevel) + print_line(util.insert_space(f'Deleted .torrent AND content files.',13),loglevel) else: if not dry_run: torrent.delete(hash=torrent.hash, delete_files=False) del_tor += 1 - print_line(util.insert_space(f'Deleted .torrent but NOT content files.',8),loglevel) + print_line(util.insert_space(f'Deleted .torrent but NOT content files.',13),loglevel) if num_tags >= 1: print_line(f"{'Did not Tag/set' if dry_run else 'Tag/set'} share limits for {num_tags} .torrent{'s.' if num_tags > 1 else '.'}",loglevel) else: @@ -341,8 +341,8 @@ class Qbt: print_line(util.insert_space(f'Save_Path: {dest}',6),loglevel) added += 1 if not dry_run: - client.torrents.add(torrent_files=src, save_path=dest, category=category, tags='cross-seed', is_paused=True) - shutil.move(src, dir_cs_out) + self.client.torrents.add(torrent_files=src, save_path=dest, category=category, tags='cross-seed', is_paused=True) + util.move_files(src,dir_cs_out) else: print_line(f'Found {t_name} in {dir_cs} but original torrent is not complete.',loglevel) print_line(f'Not adding to qBittorrent',loglevel) diff --git a/qbit_manage.py b/qbit_manage.py index 40195e5..5697918 100644 --- a/qbit_manage.py +++ b/qbit_manage.py @@ -72,7 +72,12 @@ divider = get_arg("QBT_DIVIDER", args.divider) screen_width = get_arg("QBT_WIDTH", args.width, arg_int=True) stats = {} args = {} -default_dir = os.path.join(os.path.dirname(os.path.abspath(__file__)), "config") + +if os.path.isdir('/config'): + default_dir = '/config' +else: + default_dir = os.path.join(os.path.dirname(os.path.abspath(__file__)), "config") + for v in ['run','sch','config_file','log_file','cross_seed','recheck','cat_update','tag_update','rem_unregistered','rem_orphaned','tag_nohardlinks','skip_recycle','dry_run','log_level','divider','screen_width']: args[v] = eval(v) @@ -101,7 +106,7 @@ logger.setLevel(log_lev) def fmt_filter(record): record.levelname = f"[{record.levelname}]" - #record.filename = f"[{record.filename}:{record.lineno}]" + record.filename = f"[{record.filename}:{record.lineno}]" return True cmd_handler = logging.StreamHandler() @@ -118,14 +123,14 @@ with open(os.path.join(os.path.dirname(os.path.abspath(__file__)), "VERSION")) a version = line break - -file_logger = os.path.join(default_dir, "logs", log_file) +log_path = os.path.join(default_dir, "logs") +file_logger = os.path.join(log_path, log_file) max_bytes = 1024 * 1024 * 2 file_handler = RotatingFileHandler(file_logger, delay=True, mode="w", maxBytes=max_bytes, backupCount=10, encoding="utf-8") util.apply_formatter(file_handler) file_handler.addFilter(fmt_filter) logger.addHandler(file_handler) - +os.chmod(log_path, 0o777) def start(): start_time = datetime.now() @@ -215,11 +220,11 @@ def start(): end_time = datetime.now() run_time = str(end_time - start_time).split('.')[0] - #util.separator(f"Finished {start_type}Run\n {', '.join(stats_summary) if len(stats_summary)>0 else ''} \nRun Time: {run_time}") util.separator(f"Finished {start_type}Run\n {os.linesep.join(stats_summary) if len(stats_summary)>0 else ''} \nRun Time: {run_time}") def end(): logger.info("Exiting Qbit_manage") + os.chmod(file_logger, 0o777) logger.removeHandler(file_handler) sys.exit(0) @@ -255,6 +260,7 @@ if __name__ == '__main__': logger.debug(f" --width (QBT_WIDTH): {screen_width}") logger.debug("") + os.chmod(file_logger, 0o777) try: if run: logger.info(f" Run Mode: Script will exit after completion.")