diff --git a/plugins/renamer/README.md b/plugins/renamer/README.md deleted file mode 100644 index 053f7a8..0000000 --- a/plugins/renamer/README.md +++ /dev/null @@ -1,74 +0,0 @@ - -# SQLITE Renamer for Stash (Task) -Using metadata from your stash to rename your file. - -## Requirement -- Stash -- Python 3+ (Tested on Python v3.9.1 64bit, Win10) -- Request Module (https://pypi.org/project/requests/) -- Windows 10 ? (No idea if this work for all OS) - -## Installation - -- Download the whole folder 'renamer' (config.py, log.py, renamerTask.py/.yml) -- Place it in your **plugins** folder (where the `config.yml` is) -- Reload plugins (Settings > Plugins) -- renamerTask should appear. - -### :exclamation: Make sure to configure the plugin by editing `config.py` before running it :exclamation: - -## Usage - -- You have tasks (Settings > Task): - - **Dry-Run 🔍**: Don't edit any file, just show in log. It will create `renamer_scan.txt` that contains every edit. - - **[DRYRUN] Check 10 scenes**: Check 10 scenes (by newest updated). - - **[DRYRUN] Check all scenes**: Check all scenes. - - **Process :pencil2:**: Edit your files, **don't touch Stash while doing this task**. - - **Process scanned scene from Dry-Run task**: Read `renamer_scan.txt` instead of checking all scenes. - - **Process 10 scenes**: Check 10 scenes (by newest updated). - - **Process all scenes**: Check all scenes. - -## Configuration - -- Read/Edit `config.py` - - I recommend setting the **log_file** as it can be useful to revert. -- If you have the **renamerOnUpdate** plugin, you can copy the `config.py` from it. - -### Example - -> Note: The priority is Tag > Studio > Default - -The config will be: -```py -# Change filename for scenes from 'Vixen' or 'Slayed' studio. -studio_templates = { - "Slayed": "$date $performer - $title [$studio]", - "Vixen": "$performer - $title [$studio]" -} -# Change filename if the tag 'rename_tag' is present. -tag_templates = { - "rename_tag": "$year $title - $studio $resolution $video_codec", -} -# Change filename no matter what -use_default_template = True -default_template = "$date $title" -# Use space as a performer separator -performer_splitchar = " " -# If the scene has more than 3 performers, the $performer field will be ignored. -performer_limit = 3 -``` -The scene was just scanned, everything is default (Title = Filename). - -Current filename: `Slayed.21.09.02.Ariana.Marie.Emily.Willis.And.Eliza.Ibarra.XXX.1080p.mp4` - -|Stash Field | Value | Filename | Trigger template | -|--|:---:|--|--| -| - | *Default* |`Slayed.21.09.02.Ariana.Marie.Emily.Willis.And.Eliza.Ibarra.XXX.1080p.mp4` | default_template -| ~Title| **Driver**| `Driver.mp4` | default_template -| +Date| **2021-09-02**| `2021-09-02 Driver.mp4` | default_template -| +Performer | **Ariana Marie
Emily Willis
Eliza Ibarra**| `2021-09-02 Driver.mp4` | default_template -| +Studio | **Vixen**| `Ariana Marie Emily Willis Eliza Ibarra - Driver [Vixen].mp4` | studio_templates [Vixen] -| ~Studio | **Slayed**| `2021-09-02 Ariana Marie Emily Willis Eliza Ibarra - Driver [Slayed].mp4` | studio_templates [Slayed] -| +Performer | **Elsa Jean**| `2021-09-02 Driver [Slayed].mp4` | studio_templates [Slayed]
**Reach performer_limit**. -| +Tag | **rename_tag**| `2021 Driver - Slayed HD h264.mp4` | tag_templates [rename_tag] - diff --git a/plugins/renamer/config.py b/plugins/renamer/config.py deleted file mode 100644 index b2421d7..0000000 --- a/plugins/renamer/config.py +++ /dev/null @@ -1,88 +0,0 @@ -################################################################### -# -# ----------------------------------------------------------------- -# Available: $date $year $performer $title $height $resolution $studio $parent_studio $studio_family $video_codec $audio_codec -# -note: -# $studio_family: If parent studio exist use it, else use the studio name. -# $performer: If more than * performers, this field will be ignored. Limit to fix at Settings section below (default: 3) -# $resolution: SD/HD/UHD/VERTICAL (for phone) | $height: 720p 1080p 4k 8k -# ----------------------------------------------------------------- -# e.g.: -# $title == Her Fantasy Ball -# $date $title == 2016-12-29 Her Fantasy Ball -# $year $title $height == 2016 Her Fantasy Ball 1080p -# $date $performer - $title [$studio] == 2016-12-29 Eva Lovia - Her Fantasy Ball [Sneaky Sex] -# $parent_studio $date $performer - $title == Reality Kings 2016-12-29 Eva Lovia - Her Fantasy Ball -# -#################################################################### -# TEMPLATE # - -# Priority : Tags > Studios > Default - -# templates to use for given tags -# add or remove as needed -tag_templates = { - "!1. Western": "$date $performer - $title [$studio]", - "!1. JAV": "$title", - "!1. Anime": "$title $date [$studio]" -} - -# adjust the below if you want to use studio names instead of tags for the renaming templates -studio_templates = { - -} - -# change to True to use the default template if no specific tag/studio is found -use_default_template = False -# default template, adjust as needed -default_template = "$date $title" - -###################################### -# Logging # - -# File to save what is renamed, can be useful if you need to revert changes. -# Will look like: IDSCENE|OLD_PATH|NEW_PATH -# Leave Blank ("") or use None if you don't want to use a log file, or a working path like: C:\Users\USERNAME\.stash\plugins\Hooks\rename_log.txt -log_file = r"" - -###################################### -# Settings # - -# Character to use as a performer separator. -performer_splitchar = " " -# Maximum number of performer names in the filename. If there are more than that in a scene the filename will not include any performer names! -performer_limit = 3 -# ignore male performers. -performer_ignore_male = False - -# If $performer is before $title, prevent having duplicate text. -# e.g.: -# Template used: $year $performer - $title -# 2016 Dani Daniels - Dani Daniels in ***.mp4 --> 2016 Dani Daniels in ***.mp4 -prevent_title_performer = False - -# Only rename 'Organized' scenes. -only_organized = False -# Field to remove if the path is too long. First in list will be removed then second then ... if length is still too long. -order_field = ["$video_codec", "$audio_codec", "$resolution", "$height", "$studio_family", "$studio", "$parent_studio","$performer"] -# Alternate way to show diff. Not useful at all. -alt_diff_display = False - -###################################### -# Module Related # - -# ! OPTIONAL module settings. Not needed for basic operation ! - -# = psutil module (https://pypi.org/project/psutil/) = -# Gets a list of all processes instead of stopping after the first one. Enabling it slows down the plugin -process_getall = False -# If the file is used by a process, the plugin will kill it. IT CAN MAKE STASH CRASH TOO. -process_kill_attach = False -# ========================= - -# = Unidecode module (https://pypi.org/project/Unidecode/) = -# Check site mentioned for more details. -# TL;DR: Prevent having non common characters by replacing them. -# Warning: If you have non-latin characters (Cyrillic, Kanji, Arabic, ...), the result will be extremely different. -use_ascii = False -# ========================= diff --git a/plugins/renamer/log.py b/plugins/renamer/log.py deleted file mode 100644 index f381252..0000000 --- a/plugins/renamer/log.py +++ /dev/null @@ -1,52 +0,0 @@ -import sys - - -# Log messages sent from a plugin instance are transmitted via stderr and are -# encoded with a prefix consisting of special character SOH, then the log -# level (one of t, d, i, w, e, or p - corresponding to trace, debug, info, -# warning, error and progress levels respectively), then special character -# STX. -# -# The LogTrace, LogDebug, LogInfo, LogWarning, and LogError methods, and their equivalent -# formatted methods are intended for use by plugin instances to transmit log -# messages. The LogProgress method is also intended for sending progress data. -# - -def __prefix(level_char): - start_level_char = b'\x01' - end_level_char = b'\x02' - - ret = start_level_char + level_char + end_level_char - return ret.decode() - - -def __log(level_char, s): - if level_char == "": - return - - print(__prefix(level_char) + s + "\n", file=sys.stderr, flush=True) - - -def LogTrace(s): - __log(b't', s) - - -def LogDebug(s): - __log(b'd', s) - - -def LogInfo(s): - __log(b'i', s) - - -def LogWarning(s): - __log(b'w', s) - - -def LogError(s): - __log(b'e', s) - - -def LogProgress(p): - progress = min(max(0, p), 1) - __log(b'p', str(progress)) diff --git a/plugins/renamer/renamerTask.py b/plugins/renamer/renamerTask.py deleted file mode 100644 index b4fb40b..0000000 --- a/plugins/renamer/renamerTask.py +++ /dev/null @@ -1,647 +0,0 @@ -import difflib -import json -import os -import re -import sqlite3 -import subprocess -import sys -import time - -import requests - -try: - import psutil # pip install psutil - MODULE_PSUTIL = True -except: - MODULE_PSUTIL = False - -try: - import unidecode # pip install Unidecode - MODULE_UNIDECODE = True -except: - MODULE_UNIDECODE = False - -import config -import log - - -FRAGMENT = json.loads(sys.stdin.read()) -FRAGMENT_SERVER = FRAGMENT["server_connection"] -PLUGIN_DIR = FRAGMENT_SERVER["PluginDir"] -PLUGIN_ARGS = FRAGMENT['args'].get("mode") - -log.LogDebug("--Starting Plugin 'Renammer'--") - -#log.LogDebug("{}".format(FRAGMENT)) - -def callGraphQL(query, variables=None, raise_exception=True): - # Session cookie for authentication - graphql_port = FRAGMENT_SERVER['Port'] - graphql_scheme = FRAGMENT_SERVER['Scheme'] - graphql_cookies = { - 'session': FRAGMENT_SERVER.get('SessionCookie').get('Value') - } - graphql_headers = { - "Accept-Encoding": "gzip, deflate, br", - "Content-Type": "application/json", - "Accept": "application/json", - "Connection": "keep-alive", - "DNT": "1" - } - graphql_domain = 'localhost' - # Stash GraphQL endpoint - graphql_url = graphql_scheme + "://" + graphql_domain + ":" + str(graphql_port) + "/graphql" - - json = {'query': query} - if variables is not None: - json['variables'] = variables - try: - response = requests.post(graphql_url, json=json,headers=graphql_headers, cookies=graphql_cookies, timeout=20) - except Exception as e: - exit_plugin(err="[FATAL] Exception with GraphQL request. {}".format(e)) - if response.status_code == 200: - result = response.json() - if result.get("error"): - for error in result["error"]["errors"]: - if raise_exception: - raise Exception("GraphQL error: {}".format(error)) - else: - log.LogError("GraphQL error: {}".format(error)) - return None - if result.get("data"): - return result.get("data") - elif response.status_code == 401: - exit_plugin(err="HTTP Error 401, Unauthorised.") - else: - raise ConnectionError("GraphQL query failed: {} - {}".format(response.status_code, response.content)) - - -def graphql_getScene(scene_id): - query = """ - query FindScene($id: ID!, $checksum: String) { - findScene(id: $id, checksum: $checksum) { - ...SceneData - } - } - fragment SceneData on Scene { - id - checksum - oshash - title - details - url - date - rating - o_counter - organized - path - phash - interactive - file { - size - duration - video_codec - audio_codec - width - height - framerate - bitrate - } - studio { - ...SlimStudioData - } - movies { - movie { - ...MovieData - } - scene_index - } - tags { - ...SlimTagData - } - performers { - ...PerformerData - } - } - fragment SlimStudioData on Studio { - id - name - parent_studio { - id - name - } - details - rating - aliases - } - fragment MovieData on Movie { - id - checksum - name - aliases - date - rating - director - studio { - ...SlimStudioData - } - synopsis - url - } - fragment SlimTagData on Tag { - id - name - aliases - } - fragment PerformerData on Performer { - id - checksum - name - url - gender - twitter - instagram - birthdate - ethnicity - country - eye_color - height - measurements - fake_tits - career_length - tattoos - piercings - aliases - favorite - tags { - ...SlimTagData - } - rating - details - death_date - hair_color - weight - } - """ - variables = { - "id": scene_id - } - result = callGraphQL(query, variables) - return result.get('findScene') - - -def graphql_getConfiguration(): - query = """ - query Configuration { - configuration { - general { - databasePath - } - } - } - """ - result = callGraphQL(query) - return result.get('configuration') - - -def graphql_findScene(perPage,direc="DESC"): - query = """ - query FindScenes($filter: FindFilterType) { - findScenes(filter: $filter) { - count - scenes { - ...SlimSceneData - } - } - } - fragment SlimSceneData on Scene { - id - checksum - oshash - title - details - url - date - rating - o_counter - organized - path - phash - interactive - scene_markers { - id - title - seconds - } - galleries { - id - path - title - } - studio { - id - name - } - movies { - movie { - id - name - } - scene_index - } - tags { - id - name - } - performers { - id - name - gender - favorite - } - } - """ - # ASC DESC - variables = {'filter': {"direction": direc, "page": 1, "per_page": perPage, "sort": "updated_at"}} - result = callGraphQL(query, variables) - return result.get("findScenes") - - -def makeFilename(scene_information, query): - new_filename = str(query) - for field in TEMPLATE_FIELD: - field_name = field.replace("$","") - if field in new_filename: - if scene_information.get(field_name): - if field == "$performer": - if re.search(r"\$performer[-\s_]*\$title", new_filename) and scene_information.get('title') and PREVENT_TITLE_PERF: - if re.search("^{}".format(scene_information["performer"]), scene_information["title"]): - log.LogInfo("Ignoring the performer field because it's already in start of title") - new_filename = re.sub('\$performer[-\s_]*', '', new_filename) - continue - new_filename = new_filename.replace(field, scene_information[field_name]) - else: - new_filename = re.sub('\${}[-\s_]*'.format(field_name), '', new_filename) - - # remove [] - new_filename = re.sub('\[\W*]', '', new_filename) - # Remove multiple space/_ in row - new_filename = re.sub('[\s_]{2,}', ' ', new_filename) - # Remove multiple - in row - new_filename = re.sub('(?:[\s_]-){2,}', ' -', new_filename) - # Remove space at start/end - new_filename = new_filename.strip(" -") - return new_filename - - -def find_diff_text(a, b): - addi = minus = stay = "" - minus_ = addi_ = 0 - for _, s in enumerate(difflib.ndiff(a, b)): - if s[0] == ' ': - stay += s[-1] - minus += "*" - addi += "*" - elif s[0] == '-': - minus += s[-1] - minus_ += 1 - elif s[0] == '+': - addi += s[-1] - addi_ += 1 - if minus_ > 20 or addi_ > 20: - log.LogDebug("Diff Checker: +{}; -{};".format(addi_,minus_)) - log.LogDebug("OLD: {}".format(a)) - log.LogDebug("NEW: {}".format(b)) - else: - log.LogDebug("Original: {}\n- Charac: {}\n+ Charac: {}\n Result: {}".format(a, minus, addi, b)) - return - - -def has_handle(fpath,all_result=False): - lst = [] - for proc in psutil.process_iter(): - try: - for item in proc.open_files(): - if fpath == item.path: - if all_result: - lst.append(proc) - else: - return proc - except Exception: - pass - return lst - - -def exit_plugin(msg=None, err=None): - if msg is None and err is None: - msg = "plugin ended" - output_json = {"output": msg, "error": err} - print(json.dumps(output_json)) - sys.exit() - - -def renamer(scene_id): - filename_template = None - STASH_SCENE = graphql_getScene(scene_id) - # ================================================================ # - # RENAMER # - # Tags > Studios > Default - - # Default - if config.use_default_template: - filename_template = config.default_template - - # Change by Studio - if STASH_SCENE.get("studio") and config.studio_templates: - if config.studio_templates.get(STASH_SCENE["studio"]["name"]): - filename_template = config.studio_templates[STASH_SCENE["studio"]["name"]] - # by Parent - if STASH_SCENE["studio"].get("parent_studio"): - if config.studio_templates.get(STASH_SCENE["studio"]["name"]): - filename_template = config.studio_templates[STASH_SCENE["studio"]["name"]] - - # Change by Tag - if STASH_SCENE.get("tags") and config.tag_templates: - for tag in STASH_SCENE["tags"]: - if config.tag_templates.get(tag["name"]): - filename_template = config.tag_templates[tag["name"]] - break - - # END # - #################################################################### - - if config.only_organized and not STASH_SCENE["organized"]: - return("Scene ignored (not organized)") - - if not filename_template: - return("No template for this scene.") - - #log.LogDebug("Using this template: {}".format(filename_template)) - - current_path = STASH_SCENE["path"] - # note: contain the dot (.mp4) - file_extension = os.path.splitext(current_path)[1] - # note: basename contains the extension - current_filename = os.path.basename(current_path) - current_directory = os.path.dirname(current_path) - - # Grabbing things from Stash - scene_information = {} - - # Grab Title (without extension if present) - if STASH_SCENE.get("title"): - # Removing extension if present in title - scene_information["title"] = re.sub("{}$".format(file_extension), "", STASH_SCENE["title"]) - - # Grab Date - scene_information["date"] = STASH_SCENE.get("date") - - # Grab Performer - if STASH_SCENE.get("performers"): - perf_list = "" - perf_count = 0 - - for perf in STASH_SCENE["performers"]: - #log.LogDebug(performer) - if PERFORMER_IGNORE_MALE and perf["gender"] == "MALE": - continue - - if perf_count > PERFORMER_LIMIT: - # We've already exceeded the limit. No need to keep checking - break - - perf_list += perf["name"] + PERFORMER_SPLITCHAR - perf_count += 1 - - # Remove last character - perf_list = perf_list[:-len(PERFORMER_SPLITCHAR)] - - if perf_count > PERFORMER_LIMIT: - log.LogInfo("More than {} performer(s). Ignoring $performer".format(PERFORMER_LIMIT)) - perf_list = "" - - scene_information["performer"] = perf_list - - # Grab Studio name - if STASH_SCENE.get("studio"): - scene_information["studio"] = STASH_SCENE["studio"].get("name") - scene_information["studio_family"] = scene_information["studio"] - # Grab Parent name - if STASH_SCENE["studio"].get("parent_studio"): - scene_information["parent_studio"] = STASH_SCENE["studio"]["parent_studio"]["name"] - scene_information["studio_family"] = scene_information["parent_studio"] - - # Grab Height (720p,1080p,4k...) - scene_information["resolution"] = 'SD' - scene_information["height"] = "{}p".format(STASH_SCENE["file"]["height"]) - if STASH_SCENE["file"]["height"] >= 720: - scene_information["resolution"] = 'HD' - if STASH_SCENE["file"]["height"] >= 2160: - scene_information["height"] = '4k' - scene_information["resolution"] = 'UHD' - if STASH_SCENE["file"]["height"] >= 4320: - scene_information["height"] = '8k' - # For Phone ? - if STASH_SCENE["file"]["height"] > STASH_SCENE["file"]["width"]: - scene_information["resolution"] = 'VERTICAL' - - scene_information["video_codec"] = STASH_SCENE["file"]["video_codec"] - scene_information["audio_codec"] = STASH_SCENE["file"]["audio_codec"] - - log.LogDebug("[{}] Scene information: {}".format(scene_id,scene_information)) - - if scene_information.get("date"): - scene_information["year"] = scene_information["date"][0:4] - - - # Create the new filename - new_filename = makeFilename(scene_information, filename_template) + file_extension - - # Remove illegal character for Windows ('#' and ',' is not illegal you can remove it) - new_filename = re.sub('[\\/:"*?<>|#,]+', '', new_filename) - - # Trying to remove non standard character - if MODULE_UNIDECODE and UNICODE_USE: - new_filename = unidecode.unidecode(new_filename, errors='preserve') - else: - # Using typewriter for Apostrophe - new_filename = re.sub("[’‘]+", "'", new_filename) - - # Replace the old filename by the new in the filepath - new_path = current_path.rstrip(current_filename) + new_filename - - # Trying to prevent error with long path for Win10 - # https://docs.microsoft.com/en-us/windows/win32/fileio/maximum-file-path-limitation?tabs=cmd - if len(new_path) > 240: - log.LogWarning("The Path is too long ({})...".format(len(new_path))) - for word in ORDER_SHORTFIELD: - if word not in filename_template: - continue - filename_template = re.sub('\{}[-\s_]*'.format(word), '', filename_template).strip() - log.LogDebug("Removing field: {}".format(word)) - new_filename = makeFilename(scene_information, filename_template) + file_extension - new_path = current_path.rstrip(current_filename) + new_filename - if len(new_path) < 240: - log.LogInfo("Reduced filename to: {}".format(new_filename)) - break - if len(new_path) > 240: - return("Can't manage to reduce the path, operation aborted.") - - #log.LogDebug("Filename: {} -> {}".format(current_filename,new_filename)) - #log.LogDebug("Path: {} -> {}".format(current_path,new_path)) - - if (new_path == current_path): - return("Filename already correct. ({})".format(current_filename)) - - if ALT_DIFF_DISPLAY: - find_diff_text(current_filename,new_filename) - else: - log.LogDebug("[OLD] Filename: {}".format(current_filename)) - log.LogDebug("[NEW] Filename: {}".format(new_filename)) - if DRY_RUN: - with open(FILE_DRYRUN_RESULT, 'a', encoding='utf-8') as f: - f.write("{}|{}|{}\n".format(scene_id, current_filename, new_filename)) - return("[Dry-run] Writing in {}".format(FILE_DRYRUN_RESULT)) - - - # Connect to the DB - try: - sqliteConnection = sqlite3.connect(STASH_DATABASE) - cursor = sqliteConnection.cursor() - log.LogDebug("Python successfully connected to SQLite") - except sqlite3.Error as error: - return("FATAL SQLITE Error: {}".format(error)) - - # Looking for duplicate filename - folder_name = os.path.basename(os.path.dirname(new_path)) - cursor.execute("SELECT id FROM scenes WHERE path LIKE ? AND NOT id=?;", ["%" + folder_name + "_" + new_filename, scene_id]) - dupl_check = cursor.fetchall() - if len(dupl_check) > 0: - for dupl_row in dupl_check: - log.LogError("Same path: [{}]".format(dupl_row[0])) - return("Duplicate path detected, check log!") - - cursor.execute("SELECT id FROM scenes WHERE path LIKE ? AND NOT id=?;", ["%" + new_filename, scene_id]) - dupl_check = cursor.fetchall() - if len(dupl_check) > 0: - for dupl_row in dupl_check: - log.LogInfo("Same filename: [{}]".format(dupl_row[0])) - - # OS Rename - if (os.path.isfile(current_path) == True): - try: - os.rename(current_path, new_path) - except PermissionError as err: - if "[WinError 32]" in str(err) and MODULE_PSUTIL: - log.LogWarning("A process use this file, trying to find it (Probably FFMPEG)") - # Find what process access the file, it's ffmpeg for sure... - process_use = has_handle(current_path, PROCESS_ALLRESULT) - if process_use: - # Terminate the process then try again to rename - log.LogDebug("Process that use this file: {}".format(process_use)) - if PROCESS_KILL: - p = psutil.Process(process_use.pid) - p.terminate() - p.wait(10) - # If we don't manage to close it, this will create a error again. - os.rename(current_path, new_path) - else: - return("A process prevent editing the file.") - else: - log.LogError(err) - return "" - if (os.path.isfile(new_path) == True): - log.LogInfo("[OS] File Renamed!") - if LOGFILE: - with open(LOGFILE, 'a', encoding='utf-8') as f: - f.write("{}|{}|{}\n".format(scene_id, current_path, new_path)) - else: - # I don't think it's possible. - return("[OS] File failed to rename ? {}".format(new_path)) - else: - return("[OS] File don't exist in your Disk/Drive ({})".format(current_path)) - - # Database rename - cursor.execute("UPDATE scenes SET path=? WHERE id=?;", [new_path, scene_id]) - sqliteConnection.commit() - # Close DB - cursor.close() - sqliteConnection.close() - log.LogInfo("[SQLITE] Database updated and closed!") - return "" - - -# File that show what we will changed. -FILE_DRYRUN_RESULT = os.path.join(PLUGIN_DIR, "renamer_scan.txt") - -STASH_CONFIG = graphql_getConfiguration() -STASH_DATABASE = STASH_CONFIG["general"]["databasePath"] -TEMPLATE_FIELD = "$date $year $performer $title $height $resolution $studio $parent_studio $studio_family $video_codec $audio_codec".split(" ") - -# READING CONFIG - -LOGFILE = config.log_file -PERFORMER_SPLITCHAR = config.performer_splitchar -PERFORMER_LIMIT = config.performer_limit -PERFORMER_IGNORE_MALE = config.performer_ignore_male -PREVENT_TITLE_PERF = config.prevent_title_performer - -PROCESS_KILL = config.process_kill_attach -PROCESS_ALLRESULT = config.process_getall -UNICODE_USE = config.use_ascii - -ORDER_SHORTFIELD = config.order_field -ALT_DIFF_DISPLAY = config.alt_diff_display - -# Task -scenes = None -progress = 0 -start_time = time.time() - -if PLUGIN_ARGS in ["Process_test","Process_full","Process_dry"]: - DRY_RUN = False -else: - log.LogDebug("Dry-Run enable") - DRY_RUN = True - -if PLUGIN_ARGS in ["DRYRUN_test","Process_test"]: - scenes = graphql_findScene(10, "DESC") -if PLUGIN_ARGS in ["DRYRUN_full","Process_full"]: - scenes = graphql_findScene(-1, "ASC") -if PLUGIN_ARGS == "Process_dry": - if os.path.exists(FILE_DRYRUN_RESULT): - scenes = {"scenes":[]} - with open(FILE_DRYRUN_RESULT, 'r', encoding='utf-8') as f: - for line in f: - scene_id_file = line.split("|")[0] - scenes["scenes"].append({"id": scene_id_file}) - else: - exit_plugin(err="Can't find the file from the dry-run ({}). Be sure to run a Dry-Run task before.".format(FILE_DRYRUN_RESULT)) - -if not scenes: - exit_plugin(err="no scene") - -log.LogDebug("Count scenes: {}".format(len(scenes["scenes"]))) -progress_step = 1 / len(scenes["scenes"]) - -for scene in scenes["scenes"]: - msg = renamer(scene["id"]) - if msg: - log.LogDebug(msg) - progress += progress_step - log.LogProgress(progress) - -if PLUGIN_ARGS == "Process_dry": - os.remove(FILE_DRYRUN_RESULT) - -if DRY_RUN: - num_lines = 0 - if os.path.exists(FILE_DRYRUN_RESULT): - num_lines = sum(1 for _ in open(FILE_DRYRUN_RESULT, encoding='utf-8')) - if num_lines > 0: - log.LogInfo("[DRY-RUN] There wil be {} file(s) changed. Check {} for more details".format(num_lines, FILE_DRYRUN_RESULT)) - else: - log.LogInfo("[DRY-RUN] No change to do.") - -log.LogInfo("Took {} seconds".format(round(time.time() - start_time))) -exit_plugin("Successful!") diff --git a/plugins/renamer/renamerTask.yml b/plugins/renamer/renamerTask.yml deleted file mode 100644 index d629c50..0000000 --- a/plugins/renamer/renamerTask.yml +++ /dev/null @@ -1,29 +0,0 @@ -name: renamerTask -description: Rename filename based to a template. -url: https://github.com/stashapp/CommunityScripts -version: 1.1 -exec: - - python - - "{pluginDir}/renamerTask.py" -interface: raw -tasks: - - name: '[DRYRUN] Check 10 scenes' - description: Only check 10 scenes. Just show in log and create a file with the possible change. - defaultArgs: - mode: DRYRUN_test - - name: '[DRYRUN] Check all scenes' - description: Check all scenes. Just show in log and create a file with the possible change. - defaultArgs: - mode: DRYRUN_full - - name: 'Process scanned scene from Dry-Run task' - description: Edit scenes listed on the textfile from the Dry-Run task. ! Don't do anything in Stash in same time ! - defaultArgs: - mode: Process_dry - - name: 'Process 10 scenes' - description: Edit the filename (if needed) for 10 scenes. ! Don't do anything in Stash in same time ! - defaultArgs: - mode: Process_test - - name: 'Process all scenes' - description: Edit the filename (if needed) for all scenes. ! Don't do anything in Stash in same time ! - defaultArgs: - mode: Process_full