Skip to content

Commit

Permalink
Merge branch 'stashapp:main' into main
Browse files Browse the repository at this point in the history
  • Loading branch information
Tetrax-10 authored Feb 17, 2024
2 parents cb9c911 + 983b28b commit 9ffc010
Show file tree
Hide file tree
Showing 12 changed files with 22,475 additions and 15 deletions.
1 change: 1 addition & 0 deletions plugins/phashDuplicateTagger/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
config.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
from pathlib import Path
import stashapi.log as log
from stashapi.tools import human_bytes, human_bits

Expand All @@ -14,6 +15,8 @@
"VC1": 6,
"SVQ3": 7,
}
# Path priority is from highest to lowest and works off the root of the path, to enable add "path" to the PRIORITY list
PATH_PRIORITY = ["/root/most/important/path", "/root/least/important/path"]

KEEP_TAG_NAME = "[PDT: Keep]"
REMOVE_TAG_NAME = "[PDT: Remove]"
Expand Down Expand Up @@ -113,18 +116,18 @@ def compare_size(self, other):


def compare_age(self, other):
if not (self.mod_time and other.mod_time):
if not (self.created_at and other.created_at):
return
if self.mod_time == other.mod_time:
if self.created_at == other.created_at:
return
if self.mod_time < other.mod_time:
if self.created_at < other.created_at:
better, worse = self, other
else:
worse, better = self, other
worse.remove_reason = "age"
return (
better,
f"Choose Oldest: Δ:{worse.mod_time-better.mod_time} | {better.id} older than {worse.id}",
f"Choose Oldest: Δ:{worse.created_at-better.created_at} | {better.id} older than {worse.id}",
)


Expand All @@ -145,3 +148,36 @@ def compare_encoding(self, other):
self,
f"Prefer Codec {better.codec}({better.id}) over {worse.codec}({worse.id})",
)


def compare_path(self, other):
if PATH_PRIORITY[0] == "/root/most/important/path":
return
if not self.path or not other.path:
return

self.path = Path(self.path)
other.path = Path(other.path)

min_score = len(PATH_PRIORITY)
self.score = min_score
other.score = min_score
for score, path in enumerate(PATH_PRIORITY):
path = Path(path)
if path in self.path.parents:
self.score = score
if path in other.path.parents:
other.score = score

if self.score == other.score:
return

if self.score < other.score:
better, worse = self, other
else:
worse, better = self, other
worse.remove_reason = "filepath"
return (
better,
f"Prefer Filepath {PATH_PRIORITY[better.score]} | {better.id} better than {worse.id}",
)
31 changes: 22 additions & 9 deletions plugins/phashDuplicateTagger/phashDuplicateTagger.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,12 @@
"You need to install the stashapi module. (pip install stashapp-tools)",
file=sys.stderr,
)

import config
try:
import config
except ModuleNotFoundError:
log.error(
"Could not import 'config.py' did you copy and rename 'config_example.py'?"
)

FRAGMENT = json.loads(sys.stdin.read())
MODE = FRAGMENT["args"]["mode"]
Expand All @@ -30,7 +34,7 @@
width
height
bit_rate
mod_time
created_at
duration
frame_rate
video_codec
Expand Down Expand Up @@ -68,10 +72,14 @@ def parse_timestamp(ts, format="%Y-%m-%dT%H:%M:%S%z"):
class StashScene:

def __init__(self, scene=None) -> None:
if len(scene["files"]) != 1:
raise Exception(
f"Scene has {len(scene['files'])} scene must have one file for comparing"
)
file = scene["files"][0]

self.id = int(scene["id"])
self.mod_time = parse_timestamp(file["mod_time"])
self.created_at = parse_timestamp(file["created_at"])
if scene.get("date"):
self.date = parse_timestamp(scene["date"], format="%Y-%m-%d")
else:
Expand Down Expand Up @@ -102,7 +110,7 @@ def __repr__(self) -> str:
return f"<StashScene ({self.id})>"

def __str__(self) -> str:
return f"id:{self.id}, height:{self.height}, size:{human_bytes(self.size)}, file_mod_time:{self.mod_time}, title:{self.title}"
return f"id:{self.id}, height:{self.height}, size:{human_bytes(self.size)}, file_created_at:{self.created_at}, title:{self.title}"

def compare(self, other):
if not (isinstance(other, StashScene)):
Expand Down Expand Up @@ -138,9 +146,14 @@ def process_duplicates(distance: PhashDistance = PhashDistance.EXACT):
log.info(f"Found {total} sets of duplicates.")

for i, group in enumerate(duplicate_list):
group = [StashScene(s) for s in group]
scene_group = []
for s in group:
try:
scene_group.append(StashScene(s))
except Exception as e:
log.warning(f"Issue parsing SceneID:{s['id']} - {e}")
filtered_group = []
for scene in group:
for scene in scene_group:
if ignore_tag_id in scene.tag_ids:
log.debug(f"Ignore {scene.id} {scene.title}")
else:
Expand All @@ -155,12 +168,12 @@ def process_duplicates(distance: PhashDistance = PhashDistance.EXACT):
def tag_files(group):

keep_reasons = []
keep_scene = None
keep_scene = group[0]

total_size = group[0].size
for scene in group[1:]:
total_size += scene.size
better, msg = scene.compare(group[0])
better, msg = scene.compare(keep_scene)
if better:
keep_scene = better
keep_reasons.append(msg)
Expand Down
108 changes: 108 additions & 0 deletions plugins/stashNotes/stashNotes.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
"use strict";
(function () {
const api = window.PluginApi;
const React = api.React;
const { Button, Modal } = api.libraries.Bootstrap;
const { faNoteSticky } = api.libraries.FontAwesomeSolid;
const NotesComponent = () => {
const storageKey = "Stash Notes";
const [display, setDisplay] = React.useState(false);
const [notes, setNotes] = React.useState("");
const enableModal = () => setDisplay(true);
const disableModal = () => setDisplay(false);
const saveNotes = (notes) => {
localStorage.setItem(storageKey, notes);
disableModal();
};
React.useEffect(() => {
const notesFromStorage = localStorage.getItem(storageKey);
if (notesFromStorage) {
setNotes(notesFromStorage);
}
}, []);
return React.createElement(
React.Fragment,
null,
React.createElement(NavButton, { onClickHandler: enableModal }),
React.createElement(NotesModal, {
displayState: display,
onCloseHandler: disableModal,
onSaveHandler: saveNotes,
notesState: notes,
notesChangeHandler: (n) => setNotes(n),
})
);
};
const NavButton = ({ onClickHandler }) => {
const { Icon } = api.components;
return React.createElement(
React.Fragment,
null,
React.createElement(
Button,
{
className: "nav-utility minimal",
title: "Notes",
onClick: onClickHandler,
},
React.createElement(Icon, { icon: faNoteSticky })
)
);
};
const NotesModal = ({
displayState,
onCloseHandler,
onSaveHandler,
notesState,
notesChangeHandler,
}) => {
return React.createElement(
Modal,
{ show: displayState, onHide: onCloseHandler },
React.createElement(
Modal.Header,
{ closeButton: true },
React.createElement(Modal.Title, null, "Notes")
),
React.createElement(
Modal.Body,
null,
React.createElement("textarea", {
className: "text-input form-control",
rows: 10,
value: notesState,
onChange: (e) => notesChangeHandler(e.target.value),
}),
React.createElement("hr", null),
React.createElement("h5", null, "Important!"),
"Notes are stored as plain text in your browser's local storage. Do not save sensitive information. Notes will be lost after closing a browser in incognito mode."
),
React.createElement(
Modal.Footer,
null,
React.createElement(
Button,
{ variant: "secondary", onClick: onCloseHandler },
"Close"
),
React.createElement(
Button,
{ variant: "primary", onClick: () => onSaveHandler(notesState) },
"Save Changes"
)
)
);
};
api.patch.before("MainNavBar.UtilityItems", function (props) {
return [
{
children: React.createElement(
React.Fragment,
null,
props.children,
React.createElement(NotesComponent, null)
),
},
];
});
})();
6 changes: 6 additions & 0 deletions plugins/stashNotes/stashNotes.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
name: Stash Notes
description: Adds a button to the navigation bar which opens a small window for writing notes to your browser's local storage.
version: 1.0
ui:
javascript:
- stashNotes.js
57 changes: 57 additions & 0 deletions plugins/themeSwitch/README.MD
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
# Theme Switch

## Information about plugin

Adds a button that shows a menu, allowing you to change CSS Themes and apply various CSS snippets for Stash App. The CSS isn't made by myself and in the CSS files authors where known are referenced.

Only the CSS of one theme can be applied at a time, and any amount of snippets can be applied.

Clicking on any radio/checkbox to apply the CSS, saves the CSS content of the Stylesheet in the browsers local storage, with an applied flag, eitehr true or false which allows the script upon page navigation and refresh to apply previously selected stylesheets

Under Change Order of Menu Bar, you can drag the elements to reorder the main menu and upon dropping it will generate the required CSS. It should work on touchscreens also, tested on Chrome IOS.

![Theme Plugin 1](https://github.com/elkorol/Stash-App-Theme-Switch-Plugin/blob/193f54fce3914991440027c4b98fd30aa9402d29/images/1.png)

![Theme Plugin 2](https://github.com/elkorol/Stash-App-Theme-Switch-Plugin/blob/193f54fce3914991440027c4b98fd30aa9402d29/images/2.png)

## Other Requirements

## Usage

1. Copy repository into Stash plugins folder.
2. Reload plugins from settings and enable

## Credit

The CSS code used is provided by [Stash Community Themes](https://docs.stashapp.cc/user-interface-ui/themes) and [Stash Community Custom CSS Snippets](https://docs.stashapp.cc/user-interface-ui/custom-css-snippets).

## Adding your own CSS

To add your own CSS open the themeSwitchCSS.js file. CSS is defined in const variables. They are ordered in categories. You can make your own categories too. Just define a variable to hold your css and put the css inbetween backticks ``.

Then look for the variable themeSwitchCSS at the bottom of the file. If adding to an existing category to just add a new number at the end. Or if you are reordering the CSS or themes. Be sure to update the numbering and there is no duplicate numbers within a theme or some won't render. It's stuctured like but can be seen better within the file itself.

const themeSwitchCSS = {
Theme: {
1: {
displayName: "Default",
styles: null,
key: "themeSwitchPlugin-theme-default",
version: null,
},
2: {
displayName: "Black Hole",
styles: blackHole,
key: "themeSwitchPlugin-theme-blackHole",
version: "2.0",
}
YourCategoryHere: {
1: {
displayName: "Your CSS Name Here",
styles: Your-CSS-Variable-Name-Here,
key: "themeSwitchPlugin-YourCategoryHere-AnIDforYourCSS",
version: VersionNumberOrNull,
}
}
}
}
12 changes: 12 additions & 0 deletions plugins/themeSwitch/themeSwitch.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
name: Theme Switch
description: Theme and CSS script manager located in main menu bar top right.
url:
version: 2.1
ui:
requires:
- stashUserscriptLibrary
javascript:
- themeSwitchMain.js
- themeSwitchCSS.js
css:
- themeSwtichDefault.css
Loading

0 comments on commit 9ffc010

Please sign in to comment.