mirror of
https://github.com/stashapp/CommunityScripts.git
synced 2025-12-15 14:23:15 -06:00
RenameFile Plugin - Changes for version 1.0.0 first full release version (#612)
This commit is contained in:
parent
9bca8a8cbe
commit
c1151f670b
@ -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)
|
||||

|
||||
- 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
|
||||
- 
|
||||
- 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.
|
||||
- 
|
||||
- Bottom extended portion of the Advanced Menu is for customizing the report.
|
||||
- 
|
||||
- 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!!!
|
||||
- 
|
||||
- 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
|
||||

|
||||
- 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
|
||||
- 
|
||||
- Full bottom extended portion of the Advanced Menu screen.
|
||||
- 
|
||||
- 
|
||||
|
||||
### 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.
|
||||
|
||||
@ -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.
|
||||
|
||||
|
||||
@ -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.
|
||||
|
||||
|
||||
@ -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 });
|
||||
})();
|
||||
|
||||
@ -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()}")
|
||||
|
||||
@ -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:
|
||||
|
||||
@ -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.
|
||||
|
||||
@ -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
|
||||
-
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user