Compare commits

..

3 Commits

Author SHA1 Message Date
WithoutPants
e685f80e3d Update changelog 2023-04-08 08:17:21 +10:00
WithoutPants
9b8d124ac8 Fix empty strings overwriting during scrape (#3647) 2023-04-08 08:15:09 +10:00
WithoutPants
0cd0151251 Don't regenerate covers if present during scan (#3646)
* Don't regenerate covers if present during scan
* Fix performer unit test (unrelated)
2023-04-07 11:57:10 +10:00
6 changed files with 45 additions and 10 deletions

View File

@@ -23,12 +23,19 @@ func (t *GenerateCoverTask) GetDescription() string {
func (t *GenerateCoverTask) Start(ctx context.Context) {
scenePath := t.Scene.Path
var required bool
if err := t.txnManager.WithReadTxn(ctx, func(ctx context.Context) error {
// don't generate the screenshot if it already exists
required = t.required(ctx)
return t.Scene.LoadPrimaryFile(ctx, t.txnManager.File)
}); err != nil {
logger.Error(err)
}
if !required {
return
}
videoFile := t.Scene.Files.Primary()
if videoFile == nil {
return

View File

@@ -1114,11 +1114,14 @@ func verifyPerformerAge(t *testing.T, ageCriterion models.IntCriterionInput) {
d := performer.Birthdate.Time
age := cd.Year() - d.Year()
if cd.YearDay() < d.YearDay() {
// using YearDay screws up on leap years
if cd.Month() < d.Month() || (cd.Month() == d.Month() && cd.Day() < d.Day()) {
age = age - 1
}
verifyInt(t, age, ageCriterion)
if !verifyInt(t, age, ageCriterion) {
t.Errorf("Performer birthdate: %s, deathdate: %s", performer.Birthdate.String(), performer.DeathDate.String())
}
}
return nil

View File

@@ -2836,21 +2836,23 @@ func verifyScenesOCounter(t *testing.T, oCounterCriterion models.IntCriterionInp
})
}
func verifyInt(t *testing.T, value int, criterion models.IntCriterionInput) {
func verifyInt(t *testing.T, value int, criterion models.IntCriterionInput) bool {
t.Helper()
assert := assert.New(t)
if criterion.Modifier == models.CriterionModifierEquals {
assert.Equal(criterion.Value, value)
return assert.Equal(criterion.Value, value)
}
if criterion.Modifier == models.CriterionModifierNotEquals {
assert.NotEqual(criterion.Value, value)
return assert.NotEqual(criterion.Value, value)
}
if criterion.Modifier == models.CriterionModifierGreaterThan {
assert.Greater(value, criterion.Value)
return assert.Greater(value, criterion.Value)
}
if criterion.Modifier == models.CriterionModifierLessThan {
assert.Less(value, criterion.Value)
return assert.Less(value, criterion.Value)
}
return true
}
func TestSceneQueryDuration(t *testing.T) {

View File

@@ -19,6 +19,7 @@ import {
ScrapedInputGroupRow,
ScrapedTextAreaRow,
ScrapeResult,
ZeroableScrapeResult,
} from "../Shared/ScrapeDialog";
import { clone, uniq } from "lodash-es";
import {
@@ -65,8 +66,9 @@ const SceneMergeDetails: React.FC<ISceneMergeDetailsProps> = ({
);
const [rating, setRating] = useState(
new ScrapeResult<number>(dest.rating100)
new ZeroableScrapeResult<number>(dest.rating100)
);
// zero values can be treated as missing for these fields
const [oCounter, setOCounter] = useState(
new ScrapeResult<number>(dest.o_counter)
);
@@ -118,7 +120,7 @@ const SceneMergeDetails: React.FC<ISceneMergeDetailsProps> = ({
const [stashIDs, setStashIDs] = useState(new ScrapeResult<GQL.StashId[]>([]));
const [organized, setOrganized] = useState(
new ScrapeResult<boolean>(dest.organized)
new ZeroableScrapeResult<boolean>(dest.organized)
);
const [image, setImage] = useState<ScrapeResult<string>>(

View File

@@ -36,7 +36,9 @@ export class ScrapeResult<T> {
) {
this.originalValue = originalValue ?? undefined;
this.newValue = newValue ?? undefined;
const hasNewValue = this.newValue !== undefined;
// NOTE: this means that zero values are treated as null
// this is incorrect for numbers and booleans, but correct for strings
const hasNewValue = !!this.newValue;
const valuesEqual = isEqual(originalValue, newValue);
this.useNewValue = useNewValue ?? (hasNewValue && !valuesEqual);
@@ -68,6 +70,23 @@ export class ScrapeResult<T> {
}
}
// for types where !!value is a valid value (boolean and number)
export class ZeroableScrapeResult<T> extends ScrapeResult<T> {
public constructor(
originalValue?: T | null,
newValue?: T | null,
useNewValue?: boolean
) {
super(originalValue, newValue, useNewValue);
const hasNewValue = this.newValue !== undefined;
const valuesEqual = isEqual(originalValue, newValue);
this.useNewValue = useNewValue ?? (hasNewValue && !valuesEqual);
this.scraped = hasNewValue && !valuesEqual;
}
}
// eslint-disable-next-line @typescript-eslint/no-explicit-any
export function hasScrapedValues(values: ScrapeResult<any>[]) {
return values.some((r) => r.scraped);

View File

@@ -38,6 +38,8 @@ Once migrated, these files can be deleted. The files can be optionally deleted d
* Overhauled and improved HLS streaming. ([#3274](https://github.com/stashapp/stash/pull/3274))
### 🐛 Bug fixes
* **[0.20.2]** Fixed empty strings being preferred in scrape dialog. ([#3647](https://github.com/stashapp/stash/pull/3647))
* **[0.20.2]** Fixed scene covers being regenerated when video file was moved. ([#3646](https://github.com/stashapp/stash/pull/3646))
* **[0.20.1]** Fixed null values being preferred in scrape dialog. ([#3621](https://github.com/stashapp/stash/pull/3621))
* Fixed login screen not working correctly from the logout screen. ([#3555](https://github.com/stashapp/stash/pull/3555))
* Fixed incorrect stash ID being overwritten when updating performer with multiple stash-box endpoints. ([#3543](https://github.com/stashapp/stash/pull/3543)