Origin/hoster filter w /scenes + Filter modal
Dotąd nie dało się docelować sceny konkretnego hostera — search faworyzuje xnxx/xvideos (dominują bazę), brak filtra po źródle. Diagnostyka per-hoster (test cookie-fix, luluvid, porntrex) wymagała trafienia sceny danego tube'a. - /scenes?origin=<substr> — exists() na PlaybackSource.origin ilike, np. 'hqporner' łapie tube:hqpornercom - ScenesFilterModal: sekcja "Source / hoster" (TextInput) w FilterState.origin - ScenesScreen: filter.origin → listScenes; liczone do activeCount Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
parent
28273eda02
commit
b6e3b1cbb5
5 changed files with 38 additions and 1 deletions
|
|
@ -83,6 +83,13 @@ def list_scenes(
|
||||||
"po PlaybackSource.quality (string typu '720p' / '1080p Full HD')."
|
"po PlaybackSource.quality (string typu '720p' / '1080p Full HD')."
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
origin: str | None = Query(
|
||||||
|
default=None,
|
||||||
|
description=(
|
||||||
|
"Filtruj po playback origin (np. 'tube:hqpornercom'). Substring match — "
|
||||||
|
"'hqporner' złapie tube:hqpornercom. Diagnostyka per-hoster."
|
||||||
|
),
|
||||||
|
),
|
||||||
include_stubs: bool = Query(
|
include_stubs: bool = Query(
|
||||||
default=False,
|
default=False,
|
||||||
description=(
|
description=(
|
||||||
|
|
@ -164,6 +171,18 @@ def list_scenes(
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
if origin:
|
||||||
|
# Substring match na origin — 'hqporner' złapie 'tube:hqpornercom'.
|
||||||
|
base = base.where(
|
||||||
|
exists(
|
||||||
|
select(1).where(
|
||||||
|
PlaybackSource.scene_id == Scene.id,
|
||||||
|
PlaybackSource.dead_at.is_(None),
|
||||||
|
PlaybackSource.origin.ilike(f"%{origin}%"),
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
# Blacklisty — globalne wykluczenia. Jeśli scena ma JAKIEGOKOLWIEK blacklisted
|
# Blacklisty — globalne wykluczenia. Jeśli scena ma JAKIEGOKOLWIEK blacklisted
|
||||||
# performera, jest na blacklisted studio, lub ma JAKIKOLWIEK blacklisted tag → out.
|
# performera, jest na blacklisted studio, lub ma JAKIKOLWIEK blacklisted tag → out.
|
||||||
from app.models.blacklist import (
|
from app.models.blacklist import (
|
||||||
|
|
|
||||||
|
|
@ -116,6 +116,7 @@ export class GoonClient {
|
||||||
qs.set('released_within_days', String(params.released_within_days));
|
qs.set('released_within_days', String(params.released_within_days));
|
||||||
if (params.min_quality_p !== undefined) qs.set('min_quality_p', String(params.min_quality_p));
|
if (params.min_quality_p !== undefined) qs.set('min_quality_p', String(params.min_quality_p));
|
||||||
if (params.include_stubs !== undefined) qs.set('include_stubs', String(params.include_stubs));
|
if (params.include_stubs !== undefined) qs.set('include_stubs', String(params.include_stubs));
|
||||||
|
if (params.origin) qs.set('origin', params.origin);
|
||||||
if (params.sort) qs.set('sort', params.sort);
|
if (params.sort) qs.set('sort', params.sort);
|
||||||
qs.set('page', String(params.page ?? 1));
|
qs.set('page', String(params.page ?? 1));
|
||||||
qs.set('per_page', String(params.per_page ?? 50));
|
qs.set('per_page', String(params.per_page ?? 50));
|
||||||
|
|
|
||||||
|
|
@ -24,6 +24,7 @@ export interface FilterState {
|
||||||
sort: ScenesSort;
|
sort: ScenesSort;
|
||||||
hasPlayback: boolean;
|
hasPlayback: boolean;
|
||||||
includeStubs: boolean;
|
includeStubs: boolean;
|
||||||
|
origin: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const DEFAULT_FILTER: FilterState = {
|
export const DEFAULT_FILTER: FilterState = {
|
||||||
|
|
@ -33,6 +34,7 @@ export const DEFAULT_FILTER: FilterState = {
|
||||||
sort: 'created_at',
|
sort: 'created_at',
|
||||||
hasPlayback: true, // default: ukryj sceny bez playback linka (kompletność > świeżość)
|
hasPlayback: true, // default: ukryj sceny bez playback linka (kompletność > świeżość)
|
||||||
includeStubs: false, // default: ukryj 5-10min hqporner trailery bez release_date
|
includeStubs: false, // default: ukryj 5-10min hqporner trailery bez release_date
|
||||||
|
origin: '', // pusty = wszystkie źródła; substring match np. 'hqporner'
|
||||||
};
|
};
|
||||||
|
|
||||||
const SORT_OPTIONS: { value: ScenesSort; label: string }[] = [
|
const SORT_OPTIONS: { value: ScenesSort; label: string }[] = [
|
||||||
|
|
@ -161,6 +163,18 @@ export function ScenesFilterModal({
|
||||||
</View>
|
</View>
|
||||||
</Section>
|
</Section>
|
||||||
|
|
||||||
|
<Section title="Source / hoster">
|
||||||
|
<TextInput
|
||||||
|
style={styles.search}
|
||||||
|
value={draft.origin}
|
||||||
|
onChangeText={(v) => setDraft({ ...draft, origin: v })}
|
||||||
|
placeholder="np. hqporner, porntrex, xnxx — puste = wszystkie"
|
||||||
|
placeholderTextColor={theme.muted}
|
||||||
|
autoCapitalize="none"
|
||||||
|
autoCorrect={false}
|
||||||
|
/>
|
||||||
|
</Section>
|
||||||
|
|
||||||
<Section title={`Tags (${draft.tagSlugs.length} selected)`}>
|
<Section title={`Tags (${draft.tagSlugs.length} selected)`}>
|
||||||
<TextInput
|
<TextInput
|
||||||
style={styles.search}
|
style={styles.search}
|
||||||
|
|
|
||||||
|
|
@ -55,6 +55,7 @@ export function ScenesScreen() {
|
||||||
has_playback: filter.hasPlayback || undefined,
|
has_playback: filter.hasPlayback || undefined,
|
||||||
sort: filter.sort,
|
sort: filter.sort,
|
||||||
include_stubs: filter.includeStubs || undefined,
|
include_stubs: filter.includeStubs || undefined,
|
||||||
|
origin: filter.origin.trim() || undefined,
|
||||||
page: pageParam,
|
page: pageParam,
|
||||||
per_page: PER_PAGE,
|
per_page: PER_PAGE,
|
||||||
}),
|
}),
|
||||||
|
|
@ -71,7 +72,8 @@ export function ScenesScreen() {
|
||||||
filter.tagSlugs.length +
|
filter.tagSlugs.length +
|
||||||
filter.studioSlugs.length +
|
filter.studioSlugs.length +
|
||||||
filter.performerIds.length +
|
filter.performerIds.length +
|
||||||
(filter.hasPlayback ? 1 : 0);
|
(filter.hasPlayback ? 1 : 0) +
|
||||||
|
(filter.origin.trim() ? 1 : 0);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<View style={styles.container}>
|
<View style={styles.container}>
|
||||||
|
|
|
||||||
|
|
@ -118,6 +118,7 @@ export interface ScenesListParams {
|
||||||
released_within_days?: number;
|
released_within_days?: number;
|
||||||
min_quality_p?: number;
|
min_quality_p?: number;
|
||||||
include_stubs?: boolean;
|
include_stubs?: boolean;
|
||||||
|
origin?: string;
|
||||||
sort?: ScenesSort;
|
sort?: ScenesSort;
|
||||||
page?: number;
|
page?: number;
|
||||||
per_page?: number;
|
per_page?: number;
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue