mirror of
https://github.com/stashapp/stash.git
synced 2025-12-18 04:44:37 +03:00
Fix scene tagger bugs (#1357)
This commit is contained in:
@@ -31,6 +31,7 @@
|
||||
* Change performer text query to search by name and alias only.
|
||||
|
||||
### 🐛 Bug fixes
|
||||
* Fix performer/studio being cleared when skipped in scene tagger.
|
||||
* Fixed error when auto-tagging for performers/studios/tags with regex characters in the name.
|
||||
* Fix scraped performer image not updating after clearing the current image when creating a new performer.
|
||||
* Fix error preventing adding a new library path when an existing library path is missing.
|
||||
|
||||
@@ -44,6 +44,8 @@ const Config: React.FC<IConfigProps> = ({ show, config, setConfig }) => {
|
||||
if (!blacklistRef.current) return;
|
||||
|
||||
const input = blacklistRef.current.value;
|
||||
if (input.length === 0) return;
|
||||
|
||||
setConfig({
|
||||
...config,
|
||||
blacklist: [...config.blacklist, input],
|
||||
|
||||
@@ -25,28 +25,38 @@ const getDurationStatus = (
|
||||
scene: IStashBoxScene,
|
||||
stashDuration: number | undefined | null
|
||||
) => {
|
||||
const fingerprintDuration =
|
||||
scene.fingerprints.map((f) => f.duration)?.[0] ?? null;
|
||||
const sceneDuration = scene.duration || fingerprintDuration;
|
||||
if (!sceneDuration || !stashDuration) return "";
|
||||
const diff = Math.abs(sceneDuration - stashDuration);
|
||||
if (diff < 5) {
|
||||
if (!stashDuration) return "";
|
||||
|
||||
const durations = scene.fingerprints
|
||||
.map((f) => f.duration)
|
||||
.map((d) => Math.abs(d - stashDuration));
|
||||
const matchCount = durations.filter((duration) => duration <= 5).length;
|
||||
|
||||
let match;
|
||||
if (matchCount > 0)
|
||||
match = `Duration matches ${matchCount}/${durations.length} fingerprints`;
|
||||
else if (Math.abs(scene.duration - stashDuration) < 5)
|
||||
match = "Duration is a match";
|
||||
|
||||
if (match)
|
||||
return (
|
||||
<div className="font-weight-bold">
|
||||
<SuccessIcon className="mr-2" />
|
||||
Duration is a match
|
||||
{match}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
return <div>Duration off by {Math.floor(diff)}s</div>;
|
||||
|
||||
const minDiff = Math.min(scene.duration, ...durations);
|
||||
return <div>Duration off by at least {Math.floor(minDiff)}s</div>;
|
||||
};
|
||||
|
||||
const getFingerprintStatus = (
|
||||
scene: IStashBoxScene,
|
||||
stashScene: GQL.SlimSceneDataFragment
|
||||
) => {
|
||||
const checksum = stashScene.checksum ?? stashScene.oshash ?? undefined;
|
||||
const checksumMatch = scene.fingerprints.some((f) => f.hash === checksum);
|
||||
const checksumMatch = scene.fingerprints.some(
|
||||
(f) => f.hash === stashScene.checksum || f.hash === stashScene.oshash
|
||||
);
|
||||
const phashMatch = scene.fingerprints.some(
|
||||
(f) => f.hash === stashScene.phash
|
||||
);
|
||||
@@ -176,6 +186,8 @@ const StashSearchResult: React.FC<IStashSearchResultProps> = ({
|
||||
studioID = res.data.studioUpdate.id;
|
||||
} else if (studio.type === "existing") {
|
||||
studioID = studio.data.id;
|
||||
} else if (studio.type === "skip") {
|
||||
studioID = stashScene.studio?.id;
|
||||
}
|
||||
|
||||
setSaveState("Saving performers");
|
||||
@@ -296,6 +308,10 @@ const StashSearchResult: React.FC<IStashSearchResultProps> = ({
|
||||
updatedTags = uniq(newTagIDs);
|
||||
}
|
||||
|
||||
const performer_ids = performerIDs.filter(
|
||||
(id) => id !== "Skip"
|
||||
) as string[];
|
||||
|
||||
const sceneUpdateResult = await updateScene({
|
||||
variables: {
|
||||
input: {
|
||||
@@ -303,9 +319,10 @@ const StashSearchResult: React.FC<IStashSearchResultProps> = ({
|
||||
title: scene.title,
|
||||
details: scene.details,
|
||||
date: scene.date,
|
||||
performer_ids: performerIDs.filter(
|
||||
(id) => id !== "Skip"
|
||||
) as string[],
|
||||
performer_ids:
|
||||
performer_ids.length === 0
|
||||
? stashScene.performers.map((p) => p.id)
|
||||
: performer_ids,
|
||||
studio_id: studioID,
|
||||
cover_image: imgData,
|
||||
url: scene.url,
|
||||
|
||||
@@ -171,12 +171,15 @@ const TaggerList: React.FC<ITaggerListProps> = ({
|
||||
const [selectedResult, setSelectedResult] = useState<
|
||||
Record<string, number>
|
||||
>();
|
||||
const [selectedFingerprintResult, setSelectedFingerprintResult] = useState<
|
||||
Record<string, number>
|
||||
>();
|
||||
const [taggedScenes, setTaggedScenes] = useState<
|
||||
Record<string, Partial<GQL.SlimSceneDataFragment>>
|
||||
>({});
|
||||
const [loadingFingerprints, setLoadingFingerprints] = useState(false);
|
||||
const [fingerprints, setFingerprints] = useState<
|
||||
Record<string, IStashBoxScene>
|
||||
Record<string, IStashBoxScene[]>
|
||||
>({});
|
||||
const [hideUnmatched, setHideUnmatched] = useState(false);
|
||||
const fingerprintQueue =
|
||||
@@ -269,7 +272,9 @@ const TaggerList: React.FC<ITaggerListProps> = ({
|
||||
|
||||
selectScenes(results.data?.queryStashBoxScene).forEach((scene) => {
|
||||
scene.fingerprints?.forEach((f) => {
|
||||
newFingerprints[f.hash] = scene;
|
||||
newFingerprints[f.hash] = newFingerprints[f.hash]
|
||||
? [...newFingerprints[f.hash], scene]
|
||||
: [scene];
|
||||
});
|
||||
});
|
||||
|
||||
@@ -428,21 +433,30 @@ const TaggerList: React.FC<ITaggerListProps> = ({
|
||||
|
||||
let searchResult;
|
||||
if (fingerprintMatch && !isTagged && !hasStashIDs) {
|
||||
searchResult = (
|
||||
searchResult = sortScenesByDuration(
|
||||
fingerprintMatch,
|
||||
scene.file.duration ?? 0
|
||||
).map((match, i) => (
|
||||
<StashSearchResult
|
||||
showMales={config.showMales}
|
||||
stashScene={scene}
|
||||
isActive
|
||||
setActive={() => {}}
|
||||
isActive={(selectedFingerprintResult?.[scene.id] ?? 0) === i}
|
||||
setActive={() =>
|
||||
setSelectedFingerprintResult({
|
||||
...selectedFingerprintResult,
|
||||
[scene.id]: i,
|
||||
})
|
||||
}
|
||||
setScene={handleTaggedScene}
|
||||
scene={fingerprintMatch}
|
||||
scene={match}
|
||||
setCoverImage={config.setCoverImage}
|
||||
setTags={config.setTags}
|
||||
tagOperation={config.tagOperation}
|
||||
endpoint={selectedEndpoint.endpoint}
|
||||
queueFingerprintSubmission={queueFingerprintSubmission}
|
||||
key={match.stash_id}
|
||||
/>
|
||||
);
|
||||
));
|
||||
} else if (
|
||||
searchResults[scene.id]?.length > 0 &&
|
||||
!isTagged &&
|
||||
|
||||
@@ -165,18 +165,22 @@ export const sortScenesByDuration = (
|
||||
targetDuration?: number
|
||||
) =>
|
||||
scenes.sort((a, b) => {
|
||||
const adur =
|
||||
a?.duration || (a?.fingerprints.map((f) => f.duration)?.[0] ?? null);
|
||||
const bdur =
|
||||
b?.duration || (b?.fingerprints.map((f) => f.duration)?.[0] ?? null);
|
||||
if (!adur && !bdur) return 0;
|
||||
if (adur && !bdur) return -1;
|
||||
if (!adur && bdur) return 1;
|
||||
|
||||
if (!targetDuration) return 0;
|
||||
|
||||
const aDiff = Math.abs((adur ?? 0) - targetDuration);
|
||||
const bDiff = Math.abs((bdur ?? 0) - targetDuration);
|
||||
const aDur = [
|
||||
a.duration,
|
||||
...a.fingerprints.map((f) => f.duration),
|
||||
].map((d) => Math.abs(d - targetDuration));
|
||||
const bDur = [
|
||||
b.duration,
|
||||
...b.fingerprints.map((f) => f.duration),
|
||||
].map((d) => Math.abs(d - targetDuration));
|
||||
|
||||
if (aDur.length > 0 && bDur.length === 0) return -1;
|
||||
if (aDur.length === 0 && bDur.length > 0) return 1;
|
||||
|
||||
const aDiff = Math.min(...aDur);
|
||||
const bDiff = Math.min(...bDur);
|
||||
|
||||
if (aDiff < bDiff) return -1;
|
||||
if (aDiff > bDiff) return 1;
|
||||
|
||||
Reference in New Issue
Block a user