diff --git a/pkg/sqlite/migrations/86_postmigrate.go b/pkg/sqlite/migrations/86_postmigrate.go index b80da32be..f39678e36 100644 --- a/pkg/sqlite/migrations/86_postmigrate.go +++ b/pkg/sqlite/migrations/86_postmigrate.go @@ -71,6 +71,8 @@ func (m *schema86Migrator) migrateFingerprintQueue(ctx context.Context) error { } // Migrate each endpoint's queue to the database + // Legacy format: fingerprintQueue[endpoint] = ["sceneId1", "sceneId2", ...] + // We need to look up the stash-box scene ID from scene_stash_ids table if err := m.withTxn(ctx, func(tx *sqlx.Tx) error { for endpoint, queueData := range fingerprintQueue { queue, ok := queueData.([]any) @@ -80,30 +82,39 @@ func (m *schema86Migrator) migrateFingerprintQueue(ctx context.Context) error { } for _, entryData := range queue { - entry, ok := entryData.(map[string]any) + // Legacy format: entries are just scene ID strings + sceneID, ok := entryData.(string) if !ok { - logger.Warnf("fingerprintQueue entry is not an object, skipping") + // Try parsing as float64 (JSON numbers) + if f, ok := entryData.(float64); ok { + sceneID = fmt.Sprintf("%d", int(f)) + } else { + logger.Warnf("fingerprintQueue entry is not a string or number, skipping: %T", entryData) + continue + } + } + + if sceneID == "" { + logger.Warnf("fingerprintQueue entry is empty, skipping") continue } - sceneID, _ := entry["sceneId"].(string) - stashBoxSceneID, _ := entry["stashBoxSceneId"].(string) - vote, _ := entry["vote"].(string) - - if sceneID == "" || stashBoxSceneID == "" { - logger.Warnf("fingerprintQueue entry missing sceneId or stashBoxSceneId, skipping") + // Look up the stash-box scene ID from scene_stash_ids + var stashBoxSceneID string + err := tx.QueryRow(` + SELECT stash_id FROM scene_stash_ids + WHERE scene_id = ? AND endpoint = ? + `, sceneID, endpoint).Scan(&stashBoxSceneID) + if err != nil { + logger.Warnf("Could not find stash_id for scene %s endpoint %s, skipping: %v", sceneID, endpoint, err) continue } - if vote == "" { - vote = "VALID" - } - // Insert into the new table, ignore conflicts (entry already exists) - _, err := tx.Exec(` + _, err = tx.Exec(` INSERT OR IGNORE INTO fingerprint_submissions (endpoint, stash_id, scene_id, vote) VALUES (?, ?, ?, ?) - `, endpoint, stashBoxSceneID, sceneID, vote) + `, endpoint, stashBoxSceneID, sceneID, "VALID") if err != nil { return fmt.Errorf("inserting fingerprint submission: %w", err) } diff --git a/ui/v2.5/src/components/Tagger/constants.ts b/ui/v2.5/src/components/Tagger/constants.ts index 5c244beb8..113d861e7 100644 --- a/ui/v2.5/src/components/Tagger/constants.ts +++ b/ui/v2.5/src/components/Tagger/constants.ts @@ -1,14 +1,8 @@ -import { - FingerprintVote, - GenderEnum, - ScraperSourceInput, -} from "src/core/generated-graphql"; +import { GenderEnum, ScraperSourceInput } from "src/core/generated-graphql"; export const STASH_BOX_PREFIX = "stashbox:"; export const SCRAPER_PREFIX = "scraper:"; -export { FingerprintVote }; - export interface ITaggerSource { id: string; sourceInput: ScraperSourceInput; diff --git a/ui/v2.5/src/components/Tagger/context.tsx b/ui/v2.5/src/components/Tagger/context.tsx index b88a53f7e..8d1ff6cb6 100644 --- a/ui/v2.5/src/components/Tagger/context.tsx +++ b/ui/v2.5/src/components/Tagger/context.tsx @@ -1,6 +1,5 @@ import React, { useState, useEffect, useRef, useCallback, useMemo } from "react"; import { - FingerprintVote, initialConfig, ITaggerConfig, } from "src/components/Tagger/constants"; @@ -296,6 +295,23 @@ export const TaggerContext: React.FC = ({ children }) => { if (!endpoint) return; try { + // If queueing an INVALID vote, first remove any existing submission for this stash ID + if (vote === GQL.FingerprintVote.Invalid) { + const existingSubmission = pendingFingerprints.find( + (fp) => fp.stashId === stashBoxSceneId + ); + if (existingSubmission) { + await removeFingerprintMutation({ + variables: { + input: { + endpoint, + stash_id: stashBoxSceneId, + }, + }, + }); + } + } + await queueFingerprintMutation({ variables: { input: { @@ -307,7 +323,7 @@ export const TaggerContext: React.FC = ({ children }) => { }, }); - refetchPending(); + await refetchPending(); } catch (err) { Toast.error(err); } @@ -326,7 +342,7 @@ export const TaggerContext: React.FC = ({ children }) => { }, }); - refetchPending(); + await refetchPending(); } catch (err) { Toast.error(err); }