RenameFile Plugin - Changes for version 1.0.0 first full release version (#612)

This commit is contained in:
David Maisonave 2025-09-07 07:08:32 -04:00 committed by GitHub
parent 9bca8a8cbe
commit c1151f670b
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
8 changed files with 328 additions and 142 deletions

View File

@ -2,14 +2,29 @@
https://discourse.stashapp.cc/t/dupfilemanager/1331
Please post any (**G-Rated**) bugs, feature request, help-request to the following link: [Issues](https://github.com/David-Maisonave/Axter-Stash/issues/new/choose).
DupFileManager is a [Stash](https://github.com/stashapp/stash) plugin which manages duplicate files in the Stash system.
It has both **task** and **tools-UI** components.
## Content
- [Features](#Features)
- [Requirements](#Requirements)
- [Installation](#Installation)
- [Options](#Options)
- [Advanced Options](#Advanced-Options)
- [Future Planned Features, Changes, or Fixes](#Future-Planned-Features-Changes-or-Fixes)
- [Stash Password](#Stash-Password)
- [Screenshots](#Screenshots)
- [Discourse](#Discourse)
### Features
- Creates a duplicate file report which can be accessed from the settings->tools menu options.The report is created as an HTML file and stored in local path under plugins\DupFileManager\report\DuplicateTagScenes.html.
- Creates a duplicate file report which can be accessed from the Stash->Settings->Tools menu options. The report is created as an HTML file and stored in local path under plugins\DupFileManager\report\DuplicateTagScenes.html.
- See screenshot at the bottom of this page for example report.
- Items on the left side of the report are the primary duplicates designated for deletion. By default, these duplicates are given a special \_duplicate tag.
- Items on the left side of the report are the primary duplicates designated for deletion. By default, these duplicates are given a special _duplicate tag.
- Items on the right side of the report are designated as primary duplicates to keep. They usually have higher resolution, duration and/or preferred paths.
- The report has the following options:
- Delete: Delete file and remove from Stash library.
@ -24,12 +39,11 @@ It has both **task** and **tools-UI** components.
- Merge: Copy Metadata (tags, performers,& studios) from left to right.
- Can merge potential source in the duplicate file names for tag names, performers, and studios.
- Normally when Stash searches the file name for tag names, performers, and studios, it only does so using the primary file.
- Advance menu (for specially tagged duplicates)
![Screenshot 2024-11-22 145139](https://github.com/user-attachments/assets/d76646f0-c5a8-4069-ad0f-a6e5e96e7ed0)
- Advance menu can be access from the Settings->Tools->**[DupFileManager Tools and Utilities]** menu or from the **reports**.
- Only access Advance Menu from the report when using Stash setup requiring a password.
- Advance menu
- ![Screenshot 2024-12-13 164930](https://github.com/user-attachments/assets/10098a4d-de2f-4e83-94ce-5988c5935404)
- Advance menu can be access from the Stash->Settings->Tools->**[Duplicate File Report]** menu or from the **DupFileManager Tools & Util**.
- Here are **some** of the options available in the **Advance Menu**.
- Delete only specially tagged duplicates in blacklist path.
- Delete specially tagged duplicates in blacklist path.
- Delete duplicates with specified file path.
- Delete duplicates with specific string in File name.
- Delete duplicates with specified file size range.
@ -38,14 +52,14 @@ It has both **task** and **tools-UI** components.
- Delete duplicates having specified tags.
- Delete duplicates with specified rating.
- Delete duplicates with any of the above combinations.
- Bottom extended portion of the Advanced Menu screen.
- ![Screenshot 2024-11-22 232005](https://github.com/user-attachments/assets/9a0d2e9d-783b-4ea2-8fa5-3805b40af4eb)
- Bottom extended portion of the Advanced Menu is for customizing the report.
- ![Screenshot 2025-01-14 141032](https://github.com/user-attachments/assets/a37e2074-cfec-47ae-9eed-a7769fc2245d)
- Delete duplicate file task with the following options:
- Tasks (Settings->Task->[Plugin Tasks]->DupFileManager)
- Tasks (Stash->Settings->Task->[Plugin Tasks]->DupFileManager)
- **Tag Duplicates** - Set tag DuplicateMarkForDeletion to the duplicates with lower resolution, duration, file name length, and/or black list path.
- **Delete Tagged Duplicates** - Delete scenes having DuplicateMarkForDeletion tag.
- **Delete Duplicates** - Deletes duplicate files. Performs deletion without first tagging.
- Plugin UI options (Settings->Plugins->Plugins->[DupFileManager])
- Plugin UI options (Stash->Settings->Plugins->Plugins->[DupFileManager])
- Has a 3 tier path selection to determine which duplicates to keep, and which should be candidates for deletions.
- **Whitelist** - List of paths NOT to be deleted.
- E.g. C:\Favorite\,E:\MustKeep\
@ -83,8 +97,39 @@ That's it!!!
### Options
- Options are accessible in the GUI via Settings->Plugins->Plugins->[DupFileManager].
- More options available in DupFileManager_config.py.
- Options are accessible in the GUI via Stash->Settings->Plugins->Plugins->[DupFileManager].
- Also see:
- Stash->Settings->Tools->[Duplicate File Report]
- Stash->Settings->Tools->[DupFileManager Tools and Utilities]
- More options available on the following link:
- [advance_options.html](https://stash.axter.com/1.1/advance_options.html)
- When using a Stash installation that requires a password or that is not using port 9999...
- Access above link from Stash->Settings->Tools->[Duplicate File Report]->[**Advance Duplicate File Menu**]
- Or add the GQL and apiKey as parameters to the URL.
- Example: https://stash.axter.com/1.1/advance_options.html?GQL=http://localhost:9999/graphql&apiKey=1234567890abcdefghijklmnop
- See following for more details: [Stash Password](README.md#Stash-Password)
### Advanced Options
Users can setup a private or alternate remote site by changing variables **remoteReportDirURL** and **js_DirURL** in file DupFileManager_report_config.py.
- The following files are needed at the remote site that is pointed to by **remoteReportDirURL**.
- DupFileManager_report.js
- DupFileManager_report.css
- file.html
- advance_options.html
- The **js_DirURL** path requires the following:
- jquery-3.7.1.min.js
- EasyUI associated files
- jquery.prompt.js and jquery.prompt.css
### Stash Password
- Stash installation configured with a password, need to generate an API-Key.
- To generate an API-Key:
- Go to Stash->Settings->Security->Authentication->[API Key]
- Click on [Generate API-Key]
- Once the API key is generated, DupFileManager will automatically fetch the key.
### Screenshots
@ -93,7 +138,7 @@ That's it!!!
- ![Screenshot 2024-11-22 225359](https://github.com/user-attachments/assets/dc705b24-e2d7-4663-92fd-1516aa7aacf5)
- If there's a scene on the left side that has a higher resolution or duration, it gets a yellow highlight on the report.
- There's an optional setting that allows both preview videos and preview images to be displayed on the report. See settings **htmlIncludeImagePreview** in the **DupFileManager_report_config.py** file.
- There are many more options available for how the report is created. These options are targeted for more advanced users. The options are all available in the **DupFileManager_report_config.py** file, and the settings have commented descriptions preceeding them. See the **DupFileManager_report_config.py** file in the DupFileManager plugin folder for more details.
- There are many more options available for how the report is created. These options are targeted for more advanced users. The options are all available in the **DupFileManager_report_config.py** file, and the settings have commented descriptions preceding them. See the **DupFileManager_report_config.py** file in the DupFileManager plugin folder for more details.
- Tools UI Menu
![Screenshot 2024-11-22 145512](https://github.com/user-attachments/assets/03e166eb-ddaa-4eb8-8160-4c9180ca1323)
- Can access either **Duplicate File Report (DupFileManager)** or **DupFileManager Tools and Utilities** menu options.
@ -102,12 +147,40 @@ That's it!!!
- DupFileManager Tools and Utilities
- ![Screenshot 2024-11-22 152023](https://github.com/user-attachments/assets/4daaea9e-f603-4619-b536-e6609135bab1)
- Full bottom extended portion of the Advanced Menu screen.
- ![Screenshot 2024-11-22 232208](https://github.com/user-attachments/assets/bf1f3021-3a8c-4875-9737-60ee3d7fe675)
- ![Screenshot 2025-01-14 141613](https://github.com/user-attachments/assets/77928538-e6f2-47b7-8717-45db054ffbf5)
### Future Planned Features
### Future Planned Features, Changes, or Fixes
- Scheduled Changes
- On Adv Menu, add option to set special _ToBeDeletedTag_ under Delete button menu.
- Remove [Max Dup Process] from the Stash->Plugins GUI. This option already exist in advance menu. Planned for 1.2.0 Version.
- Add chat icon to report which on hover, displays a popup window showing scene details content. Planned for 1.2.0 Version.
- Add studio icon to report; on hover show studio name. Planned for 1.2.0 Version.
- Add option on report to view rating and change it. Use an icon with a number on it to show rating. Planned for 1.2.0 Version.
- On report make flag toggle logic. In other words, when flag button is selected, and scene is already that color, remove the colored flag. Planned for 1.2.0 Version.
- Add report option to set flag to all scenes missing metadata on Scene-ToKeep or having higher resolution or longer duration on **Duplicate-to-Delete** scene. Planned for 1.2.0 Version.
- Add option to [**Advance Duplicate File Menu**] to display cover image for preview image. Planned for 1.2.0 Version.
- On report, when move operation is performed, have it automatically delete the **Duplicate-to-Delete** scene. Planned for 1.2.0 Version.
- On [**Advance Duplicate File Menu**], add a flag option to the menu on the left side, and shrink the tag option. Planned for 1.2.0 Version.
- Change the TagOrFlag option on the right side to a check mark.
- Add option to delete by file type. Planned for 1.2.0 Version.
- On report, have [Flag or Tag] option still enabled after manually disabling scene. Planned for 1.2.0 Version.
- On [**Advance Duplicate File Menu**], have the details section hide fully, or partially when the page is first displayed. Planned for 1.4.0 Version.
- Unscheduled Changes
- Change splitbutton so it hides tooltip when hovering over dropdown side of the button.
- Fix errors on HTML page listed in https://validator.w3.org.
- Add logic to merge performers and galleries separately from tag merging on report.
- Add logic to merge group metadata when selecting merge option on report.
- Add advanced menu directly to the Stash->Settings->Tools menu. (This change does not look doable!!!)
- Add report directly to the Stash->Settings->Tools menu. (This change does not look doable!!!)
- Add double strike-through option to flagging.
- Add option to report to automatically strip width & height from name on rename. Example: foofoo - 1920x1080P.mp4
- Move [Merge Duplicate Tags], [Whitelist Delete In Same Folder], and [Swap Better **] field options from the Stash->Plugins GUI to the advance menu.
### Discourse
[Discourse-DupFileManager](https://discourse.stashapp.cc/t/dupfilemanager/1331)
**Note:**
- The author of this plugin does **not** monitor Discourse. Please post any (**G-Rated**) bugs, feature request, help-request to the following link: [Issues](https://github.com/David-Maisonave/Axter-Stash/issues/new/choose).
- The [Discourse link](https://discourse.stashapp.cc/t/dupfilemanager/1331) should be use for discussion that would be inappropriate in GitHub.
- Add logic to merge performers and galaries seperatly from tag merging on report. Planned for 1.5.0 Version.
- Add code to report to make it when the report updates the screen (due to tag merging), it stays in the same row position. Planned for 1.5.0 Version.
- Add logic to merge group metadata when selecting merge option on report. Planned for 2.0.0 Version.
- Add advanced menu directly to the Settings->Tools menu. Planned for 2.0.0 Version.
- Add report directly to the Settings->Tools menu. Planned for 2.0.0 Version.

View File

@ -2,11 +2,28 @@
https://discourse.stashapp.cc/t/filemonitor/1333
Please post any (**G-Rated**) bugs, feature request, help-request to the following link: [Issues](https://github.com/David-Maisonave/Axter-Stash/issues/new/choose).
FileMonitor is a [Stash](https://github.com/stashapp/stash) plugin with the following two main features:
- Updates Stash when any file changes occurs in the Stash library.
- **Task Scheduler**: Runs scheduled task based on the scheduler configuration in **filemonitor_config.py**.
## Content
- [Starting FileMonitor from the UI](#Starting-FileMonitor-from-the-UI)
- [Using FileMonitor as a script](#Using-FileMonitor-as-a-script)
- [Task Scheduler](#Task-Scheduler)
- [Requirements](#Requirements)
- [Installation](#Installation)
- [Options](#Options)
- [Docker](#Docker)
- [Single Stash Docker Installation](#Single-Stash-Docker-Installation)
- [Multiple Stash Docker Configuration](#Multiple-Stash-Docker-Configuration)
- [Stash Docker Installer](#Stash-Docker-Installer)
- [Bugs and Feature Request](#Bugs-and-Feature-Request)
- [Future Planned Features or Fixes](#Future-Planned-Features-or-Fixes)
- [Discourse](#Discourse)
## Starting FileMonitor from the UI
From the GUI, FileMonitor can be started as a service or as a plugin. The recommended method is to start it as a service. When started as a service, it will jump on the Task Queue momentarily, and then disappear as it starts running in the background.
@ -178,15 +195,6 @@ That's it!!!
- The other options are self explanatory from the UI.
- Additional options available in filemonitor_config.py. The options are well documented in the commented code.
## Bugs and Feature Request
Please use the following link to report FileMonitor bugs:
[FileMonitor Bug Report](https://github.com/David-Maisonave/Axter-Stash/issues/new?assignees=&labels=Plugin_Bug&projects=&template=bug_report_plugin.yml&title=%F0%9F%AA%B2%5BFileMonitor%5D+Your_Short_title)
Please use the following link to report FileMonitor Feature Request:[FileMonitor Feature Reques](https://github.com/David-Maisonave/Axter-Stash/issues/new?assignees=&labels=Enhancement&projects=&template=feature_request_plugin.yml&title=%F0%9F%92%A1%EF%B8%8F%5BEnhancement%5D%3A%5BFileMonitor%5D+Your_Short_title)
Please do **NOT** use the feature request to include any problems associated with errors. Instead use the bug report for error issues.
## Docker
### Single Stash Docker Installation
@ -268,6 +276,22 @@ python filemonitor.py --url http://localhost:9999 --docker "C:\Users\MyUser\AppD
If you need help installing Stash Docker, use the Stash Docker installer in the following link: (https://github.com/David-Maisonave/Axter-Stash/tree/main/Docker)
## Future Planned Features or Fixes
## Bugs and Feature Request
Please use the following link to report FileMonitor bugs:
[FileMonitor Bug Report](https://github.com/David-Maisonave/Axter-Stash/issues/new?assignees=&labels=Plugin_Bug&projects=&template=bug_report_plugin.yml&title=%F0%9F%AA%B2%5BFileMonitor%5D+Your_Short_title)
Please use the following link to report FileMonitor Feature Request:[FileMonitor Feature Reques](https://github.com/David-Maisonave/Axter-Stash/issues/new?assignees=&labels=Enhancement&projects=&template=feature_request_plugin.yml&title=%F0%9F%92%A1%EF%B8%8F%5BEnhancement%5D%3A%5BFileMonitor%5D+Your_Short_title)
Please do **NOT** use the feature request to include any problems associated with errors. Instead use the bug report for error issues.
### Future Planned Features or Fixes
- Have the FileMonitor running status ICON update the icon without having to go to the Settings->Tools->FileMonitor page. Planned for version 1.2.0.
### Discourse
[Discourse-FileMonitor](https://discourse.stashapp.cc/t/filemonitor/1333)
**Note:**
- The author of this plugin does **not** monitor Discourse. Please post any (**G-Rated**) bugs, feature request, help-request to the following link: [Issues](https://github.com/David-Maisonave/Axter-Stash/issues/new/choose).
- The [Discourse link](https://discourse.stashapp.cc/t/filemonitor/1333) should be use for discussion that would be inappropriate in GitHub.

View File

@ -1,9 +1,24 @@
# RenameFile: Ver 0.5.7 (By David Maisonave)
# RenameFile: Ver 1.0.0 (By David Maisonave)
https://discourse.stashapp.cc/t/renamefile/1334
Please post any (**G-Rated**) bugs, feature request, help-request to the following link: [Issues](https://github.com/David-Maisonave/Axter-Stash/issues/new/choose).
RenameFile is a [Stash](https://github.com/stashapp/stash) plugin. Starting version 0.5.5, user can add the current title to the title input field by clicking on the current title. Also, the Stash database gets updated directly instead of running a scan task as long as the database is version 68.
## Content
- [Summary](#Summary)
- [RenameFile vs RenameOnUpdate](#RenameFile-vs-RenameOnUpdate)
- [Using RenameFile](#Using-RenameFile)
- [Requirements](#Requirements)
- [Installation](#Installation)
- [Options](#Options)
- [Bugs and Feature Request](#Bugs-and-Feature-Request)
- [Discourse](#Discourse)
## Summary
- The plugin allows user to rename one scene at a time by editing the **[Title]** field and then clicking **[Save]**.
<img width="270" alt="RenameFileViaTitleUnderEditTab" src="https://github.com/user-attachments/assets/f27d0205-d4ed-44fb-9bb2-5b9a75cba2e0">
@ -80,6 +95,23 @@ That's it!!!
- Main options are accessible in the GUI via Settings->Plugins->Plugins->[RenameFile].
- Advanced options are available in the **renamefile_settings.py** file. After making changes, go to http://localhost:9999/settings?tab=plugins, and click [Reload Plugins].
- **rename_associated_files_enable** - (Default=True). When value set to true, will enable feature for associated_files_to_rename. See **associated_files_to_rename**.
- **associated_files_to_rename** - This field is a list of file extension that are associated with the video file, and that are renamed when the video file is renamed. Requires **rename_associated_files_enable** to be True. User should add or remove extensions from this list for their particular requirements.
- By default, the following extensions are set to this list:
- **CAP**: Primarily used for Japanese subtitles
- **DFXP**: Distribution Format Exchange Profile
- **Funscript**: A file format that is the standard format for scripting interactive devices by syncing them up to a video.
- **INFO**: A ".info file" is a configuration or metadata file with different meanings depending on the context.
- **LRC**: A computer file format that synchronizes song lyrics with an audio file, such as MP3, AAC, or MIDI.
- **MCC**: MacCaption
- **SAMI**: Synchronized Accessible Media Interchange -> A Microsoft accessibility initiative released in the summer of 1998.
- **SCC**: Scenarist Closed Caption -> A format used by broadcast and digital media producers for TV and movies.
- **SRT**: SubRip Text -> A widely used, simple text file format that displays caption text with timecodes
- **STL**: Spruce Subtitle File -> Text file for Apple's DVD Studio Pro
- **TTML**: Timed Text Markup Language
- **TXT**: A plain text file containing information about the associated video file.
- **VTT**: WebVTT -> A text-based format that is part of the HTML5 standard
- **XML**: Extensible Markup Language -> A text-based file format used for storing and transporting data for the associated video file. It is designed to be both human-readable and machine-readable.
- **handleExe** - Populate this field in order to allow RenameFile plugin to close all open file handles.
- In Windows, a file can't be renamed if the file is opened by another process. In other words, if a file is being played by Stash or any other video player, the RenameFile plugin will get an access denied error when trying to rename the file.
- As a workaround, the 'handleExe' field can be populated with the full path to handle.exe or handle64.exe. (See requirements for download link)
@ -97,4 +129,10 @@ Please do **NOT** use the feature request to include any problems associated wit
**Note:** This script is **largely** based on the [Renamer](https://github.com/Serechops/Serechops-Stash/tree/main/plugins/Renamer) script.
### Future Planned Features or Fixes
### Discourse
[Discourse-RenameFile](https://discourse.stashapp.cc/t/renamefile/1334)
**Note:**
- The author of this plugin does **not** monitor Discourse. Please post any (**G-Rated**) bugs, feature request, help-request to the following link: [Issues](https://github.com/David-Maisonave/Axter-Stash/issues/new/choose).
- The [Discourse link](https://discourse.stashapp.cc/t/renamefile/1334) should be use for discussion that would be inappropriate in GitHub.

View File

@ -1,104 +1,101 @@
(function () {
"use strict";
function AppendTitleField(text, event) {
if ((!event.altKey && !event.ctrlKey) || event.shiftKey) {
try {
var titleInput = document.getElementById("title");
if (event.shiftKey) titleInput.value = text;
else titleInput.value += text;
console.log("Appended title to title field: " + text);
} catch (err) {
console.error("Failed to append text to title field:", err);
}
(function() {
'use strict';
function AppendTitleField(text, event) {
if ((!event.altKey && !event.ctrlKey) || event.shiftKey) {
try {
var titleInput = document.getElementById('title');
if (event.shiftKey)
titleInput.value = text;
else
titleInput.value += text;
console.log('Appended title to title field: ' + text);
} catch (err) {
console.error('Failed to append text to title field:', err);
}
}
var textArea = null;
var fileckUrl = null;
if (event.altKey) {
try {
const navElements = document.querySelectorAll("a");
for (const element of navElements)
{
var ckUrl = decodeURI(element.href);
if (ckUrl.startsWith("file://")){
fileckUrl = ckUrl;
ckUrl = ckUrl.replace("file:///", "");
ckUrl = ckUrl.replace("file://", "");
console.debug("Copping " + ckUrl + " to clipboard");
textArea = document.createElement("textarea");
textArea.value = ckUrl;
document.body.appendChild(textArea);
textArea.select();
break;
}
}
} catch (err) {
console.error('Failed to get file URL:', err);
}
}
else if (event.ctrlKey) {
try {
console.debug("Copping " + text + " to clipboard");
textArea = document.createElement("textarea");
textArea.value = text;
document.body.appendChild(textArea);
textArea.select();
} catch (err) {
console.error('Failed to get title:', err);
}
}
if (textArea != null)
{
try {
var successful = document.execCommand('copy');
var msg = successful ? 'successful' : 'unsuccessful';
console.log('Text copy ' + msg + ':', textArea.value);
} catch (err) {
console.error('Failed to copy text to clipboard:', err);
}
document.body.removeChild(textArea);
try {
if (fileckUrl != null && event.ctrlKey){
window.open(fileckUrl, "_blank");
console.log('Opening link ' + fileckUrl);
}
} catch (err) {
console.error("Failed to open link '" + fileckUrl + "' with error:", err);
}
}
}
var textArea = null;
var fileckUrl = null;
if (event.altKey) {
try {
const navElements = document.querySelectorAll("a");
for (const element of navElements) {
var ckUrl = decodeURI(element.href);
if (ckUrl.startsWith("file://")) {
fileckUrl = ckUrl;
ckUrl = ckUrl.replace("file:///", "");
ckUrl = ckUrl.replace("file://", "");
console.debug("Copping " + ckUrl + " to clipboard");
textArea = document.createElement("textarea");
textArea.value = ckUrl;
document.body.appendChild(textArea);
textArea.select();
break;
}
function wrapElement(element) {
var text = element.textContent.trim();
var anchor = document.createElement('a');
anchor.href = '#';
anchor.textContent = text;
anchor.classList.add('renamefile');
anchor.title = 'Click to append title to [Title] input field; OR ctrl-key & mouse click to copy title to clipboard; OR shift-key click to copy to [Title] input field; OR alt-key click to copy file URI to clipboard.';
anchor.addEventListener('click', function(event) {
event.preventDefault();
AppendTitleField(text, event);
});
element.innerHTML = '';
element.appendChild(anchor);
}
function handleMutations(mutationsList, observer) {
for(const mutation of mutationsList) {
for(const addedNode of mutation.addedNodes) {
if (addedNode.nodeType === Node.ELEMENT_NODE && addedNode.querySelector('.scene-header div.TruncatedText')) {
wrapElement(addedNode.querySelector('.scene-header div.TruncatedText'));
}
}
}
} catch (err) {
console.error("Failed to get file URL:", err);
}
} else if (event.ctrlKey) {
try {
console.debug("Copping " + text + " to clipboard");
textArea = document.createElement("textarea");
textArea.value = text;
document.body.appendChild(textArea);
textArea.select();
} catch (err) {
console.error("Failed to get title:", err);
}
}
if (textArea != null) {
try {
var successful = document.execCommand("copy");
var msg = successful ? "successful" : "unsuccessful";
console.log("Text copy " + msg + ":", textArea.value);
} catch (err) {
console.error("Failed to copy text to clipboard:", err);
}
document.body.removeChild(textArea);
try {
if (fileckUrl != null && event.ctrlKey) {
window.open(fileckUrl, "_blank");
console.log("Opening link " + fileckUrl);
}
} catch (err) {
console.error(
"Failed to open link '" + fileckUrl + "' with error:",
err
);
}
}
}
function wrapElement(element) {
var text = element.textContent.trim();
var anchor = document.createElement("a");
anchor.href = "#";
anchor.textContent = text;
anchor.classList.add("renamefile");
anchor.title =
"Click to append title to [Title] input field; OR ctrl-key & mouse click to copy title to clipboard; OR shift-key click to copy to [Title] input field; OR alt-key click to copy file URI to clipboard.";
anchor.addEventListener("click", function (event) {
event.preventDefault();
AppendTitleField(text, event);
});
element.innerHTML = "";
element.appendChild(anchor);
}
function handleMutations(mutationsList, observer) {
for (const mutation of mutationsList) {
for (const addedNode of mutation.addedNodes) {
if (
addedNode.nodeType === Node.ELEMENT_NODE &&
addedNode.querySelector(".scene-header div.TruncatedText")
) {
wrapElement(
addedNode.querySelector(".scene-header div.TruncatedText")
);
}
}
}
}
const observer = new MutationObserver(handleMutations);
observer.observe(document.body, { childList: true, subtree: true });
const observer = new MutationObserver(handleMutations);
observer.observe(document.body, { childList: true, subtree: true });
})();

View File

@ -1,5 +1,5 @@
# Description: This is a Stash plugin which allows users to rename the video (scene) file name by editing the [Title] field located in the scene [Edit] tab.
# By David Maisonave (aka Axter) Jul-2024 (https://www.axter.com/)
# By David Maisonave (aka Axter) Jul-2025 (https://www.axter.com/)
# Get the latest developers version from following link: https://github.com/David-Maisonave/Axter-Stash/tree/main/plugins/RenameFile
# Based on source code from https://github.com/Serechops/Serechops-Stash/tree/main/plugins/Renamer
@ -139,13 +139,20 @@ def should_exclude_path(scene_details):
return True
return False
include_keyField_if_in_name = stash.pluginSettings["z_keyFIeldsIncludeInFileName"]
excludeIgnoreAutoTags = config["excludeIgnoreAutoTags"]
include_keyField_if_in_name = stash.pluginSettings["z_keyFIeldsIncludeInFileName"]
excludeIgnoreAutoTags = config["excludeIgnoreAutoTags"]
max_performers = int(config["max_performers"])
rename_associated_files_enable = config["rename_associated_files_enable"]
associated_files_to_rename = config["associated_files_to_rename"]
def getPerformers(scene, title):
title = title.lower()
results = ""
qtyPerformers = 0
for performer in scene['performers']:
qtyPerformers += 1
if max_performers > -1 and qtyPerformers > max_performers:
break
name = performer['name']
stash.Trace(f"performer = {name}")
if not include_keyField_if_in_name:
@ -389,6 +396,8 @@ def rename_scene(scene_id):
new_filename = truncated_filename + '_' + hash_suffix + Path(original_file_path).suffix
newFilenameWithExt = new_filename + Path(original_file_path).suffix
new_file_path = f"{original_parent_directory}{os.sep}{new_filename}{Path(original_file_name).suffix}"
org_file_root_stem = f"{original_parent_directory}{os.sep}{original_file_stem}"
new_file_root_stem = f"{original_parent_directory}{os.sep}{new_filename}"
stash.Trace(f"(original_file_name={original_file_name}) (newFilenameWithExt={newFilenameWithExt})(new_file_path={new_file_path}) (FileID={scene_details['files'][0]['id']})")
if original_file_name == newFilenameWithExt or original_file_name == new_filename:
stash.Log(f"Nothing to do, because new file name matches original file name: (newFilenameWithExt={newFilenameWithExt})")
@ -401,12 +410,32 @@ def rename_scene(scene_id):
stash.Warn(f"Had to close '{original_file_path}', because it was opened by following pids:{results['pids']}")
if move_files:
if not dry_run:
stash.Trace(f"Moving file '{original_file_path}' to '{new_file_path}'")
shutil.move(original_file_path, new_file_path)
if rename_associated_files_enable:
stash.Trace(f"rename_associated_files_enable is enabled")
for ext in associated_files_to_rename:
associted_filename = org_file_root_stem + ext
# stash.Trace(f"Checking if file exist: '{associted_filename}'")
if os.path.isfile(associted_filename):
new_associted_filename = new_file_root_stem + ext
stash.Log(f"Renaming file '{associted_filename}' to '{new_associted_filename}'")
shutil.move(associted_filename, new_associted_filename)
exitMsg = f"{dry_run_prefix}Moved file to '{new_file_path}' from '{original_file_path}'"
else:
stash.Trace(f"Rename('{original_file_path}', '{new_file_path}')")
if not dry_run:
stash.Trace(f"Renaming file '{original_file_path}' to '{new_file_path}'")
os.rename(original_file_path, new_file_path)
if rename_associated_files_enable:
stash.Trace(f"rename_associated_files_enable is enabled...")
for ext in associated_files_to_rename:
associted_filename = org_file_root_stem + ext
# stash.Trace(f"Checking if file exist: '{associted_filename}'")
if os.path.isfile(associted_filename):
new_associted_filename = new_file_root_stem + ext
stash.Log(f"Renaming file '{associted_filename}' to '{new_associted_filename}'")
os.rename(associted_filename, new_associted_filename)
exitMsg = f"{dry_run_prefix}Renamed file to '{new_file_path}' from '{original_file_path}'"
except OSError as e:
exitMsg = f"Failed to move/rename file: From {original_file_path} to {new_file_path}; targetDidExist={targetDidExist}. Error: {e}"
@ -424,7 +453,9 @@ def rename_scene(scene_id):
# ToDo: Add delay rename here
raise
if stash.renameFileNameInDB(scene_details['files'][0]['id'], original_file_name, newFilenameWithExt):
if dry_run:
stash.Log("Dry-Run, so skipping DB renaming")
elif stash.renameFileNameInDB(scene_details['files'][0]['id'], original_file_name, newFilenameWithExt):
stash.Trace("DB rename success")
elif not taskqueue.tooManyScanOnTaskQueue(maxScanCountForUpdate):
stash.Trace(f"Calling [metadata_scan] for path {original_parent_directory.resolve().as_posix()}")

View File

@ -1,6 +1,6 @@
name: RenameFile
description: Renames video (scene) file names when the user edits the [Title] field located in the scene [Edit] tab.
version: 0.5.7
version: 1.0.0
url: https://github.com/David-Maisonave/Axter-Stash/tree/main/plugins/RenameFile
ui:
css:

View File

@ -1,4 +1,4 @@
# By David Maisonave (aka Axter) 2024
# By David Maisonave (aka Axter) 2025
# RenameFile plugin main configuration options are available on the Stash GUI under Settings->Plugins->Plugins->[RenameFile].
# Most users should only use the GUI options.
# The configuration options in this file are for advanced users ONLY!!!
@ -57,6 +57,23 @@ config = {
"tagAppendEnable": True,
# Enable to move file instead of rename file. (Not recommended for Windows OS)
"fileRenameViaMove": False,
# Maximum allowed performers to be added to file name. If value -1=no limit.
"max_performers": -1,
# When value set to true, will enable feature for associated_files_to_rename.
"rename_associated_files_enable": True, # See associated_files_to_rename option.
# Add or remove file extensions which are to get renamed when renaming a video file. For example if having a.mp4 and a.funscript, if a.mp4 gets renamed to foofoo.mp4, then a.funscript will get renamed to foofoo.funscript.
"associated_files_to_rename": [".funscript", ".srt", ".vtt", ".scc", ".ttml", ".dfxp", ".lrc", ".cap", ".sami", ".stl", ".mcc", ".info", ".txt", ".xml"],
# funscript = A file format that is the standard format for scripting interactive devices by syncing them up to a video
# SRT = SubRip Text -> A widely used, simple text file format that displays caption text with timecodes
# VTT = WebVTT -> A text-based format that is part of the HTML5 standard
# SCC = Scenarist Closed Caption -> A format used by broadcast and digital media producers for TV and movies.
# TTML = Timed Text Markup Language
# DFXP = Distribution Format Exchange Profile
# LRC = A computer file format that synchronizes song lyrics with an audio file, such as MP3, AAC, or MIDI.
# CAP = Primarily used for Japanese subtitles
# SAMI = Synchronized Accessible Media Interchange -> A Microsoft accessibility initiative released in the summer of 1998.
# STL = Spruce Subtitle File -> Text file for Apple's DVD Studio Pro
# MCC = MacCaption
# handleExe is for Windows only.
# In Windows, a file can't be renamed if the file is opened by another process.

View File

@ -1,12 +1,18 @@
##### This page was added starting on version 0.5.6 to keep track of newly added features between versions.
### 0.5.6
- Fixed bug with studio getting the studio ID instead of the name of the studio in rename process.
- Improved performance by having code get all required scene details in one call to stash.
- To remove UI clutter, move rarely used options (performerAppendEnable, studioAppendEnable, tagAppendEnable, & fileRenameViaMove) to renamefile_settings.py
- Change options (performerAppendEnable, studioAppendEnable, tagAppendEnable) to default to True (enabled)
### 0.5.7
- Uploaded missing renamefile.js and renamefile.css files to CommunityScripts
### 0.5.8
- Added setting max_performers to renamefile_settings.py, which allows limitting the quantity of performers added to file name.
### 0.5.9
- Added rename associated file feature. When video file is renamed, associated files will get renamed.
- Associated files are determind by file extensions listed in variable **associated_files_to_rename** which is in **renamefile_settings.py** file.
- Option **rename_associated_files_enable** can be used to disable this feature. It's turned on by default.
### 1.0.0
- Fixed Dry-Run bug, which changed the file name in the database when Dry-Run was enabled.
### 1.0.1
-