align with metadata standard
This commit is contained in:
@@ -75,7 +75,6 @@ export interface FileMetadata {
|
|||||||
|
|
||||||
// Title information (for folder organization)
|
// Title information (for folder organization)
|
||||||
title?: string;
|
title?: string;
|
||||||
titles?: { eng?: string; [key: string]: string | undefined };
|
|
||||||
originalTitle?: string;
|
originalTitle?: string;
|
||||||
fileName?: string;
|
fileName?: string;
|
||||||
|
|
||||||
@@ -623,12 +622,6 @@ export class RedisClient implements Partial<IKVClient> {
|
|||||||
mtime = isNaN(parsed) ? parseFloat(data.mtime) : parsed;
|
mtime = isNaN(parsed) ? parseFloat(data.mtime) : parsed;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Parse titles - can be nested object or simple string
|
|
||||||
let titles: { eng?: string; [key: string]: string | undefined } | undefined;
|
|
||||||
if (data['titles/eng']) {
|
|
||||||
titles = { eng: data['titles/eng'] };
|
|
||||||
}
|
|
||||||
|
|
||||||
// Parse season/episode (can be 0 for specials)
|
// Parse season/episode (can be 0 for specials)
|
||||||
const season = data.season !== undefined ? parseInt(data.season, 10) : undefined;
|
const season = data.season !== undefined ? parseInt(data.season, 10) : undefined;
|
||||||
const episode = data.episode !== undefined ? parseInt(data.episode, 10) : undefined;
|
const episode = data.episode !== undefined ? parseInt(data.episode, 10) : undefined;
|
||||||
@@ -660,7 +653,6 @@ export class RedisClient implements Partial<IKVClient> {
|
|||||||
|
|
||||||
// Title information
|
// Title information
|
||||||
title: data.title,
|
title: data.title,
|
||||||
titles,
|
|
||||||
originalTitle: data.originalTitle,
|
originalTitle: data.originalTitle,
|
||||||
fileName: data.fileName,
|
fileName: data.fileName,
|
||||||
|
|
||||||
|
|||||||
@@ -13,7 +13,6 @@
|
|||||||
*/
|
*/
|
||||||
export interface MediaMeta {
|
export interface MediaMeta {
|
||||||
// Title information
|
// Title information
|
||||||
titles?: { eng?: string; [key: string]: string | undefined };
|
|
||||||
originalTitle?: string;
|
originalTitle?: string;
|
||||||
title?: string;
|
title?: string;
|
||||||
|
|
||||||
@@ -62,7 +61,8 @@ export function renamingRule(metadata: Partial<MediaMeta>, filepath?: string): s
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Get title - try various fields
|
// Get title - try various fields
|
||||||
const title = metadata.titles?.eng || metadata.originalTitle;
|
// The display name — never the `titles/*` name set (METADATA_KEYS.md §3).
|
||||||
|
const title = metadata.title || metadata.originalTitle;
|
||||||
if (!title) {
|
if (!title) {
|
||||||
if (metadata.fileType !== 'torrent') {
|
if (metadata.fileType !== 'torrent') {
|
||||||
// Don't warn for torrent files because they don't always have a title
|
// Don't warn for torrent files because they don't always have a title
|
||||||
|
|||||||
@@ -174,12 +174,6 @@ export class VirtualFileSystem implements VFSUpdateCallback {
|
|||||||
mtime = isNaN(parsed) ? parseFloat(props.mtime) : parsed;
|
mtime = isNaN(parsed) ? parseFloat(props.mtime) : parsed;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Parse titles - can be from nested paths like 'titles/eng'
|
|
||||||
let titles: { eng?: string; [key: string]: string | undefined } | undefined;
|
|
||||||
if (props['titles/eng']) {
|
|
||||||
titles = { eng: props['titles/eng'] };
|
|
||||||
}
|
|
||||||
|
|
||||||
// Parse season/episode
|
// Parse season/episode
|
||||||
const season = props.season !== undefined ? parseInt(props.season, 10) : undefined;
|
const season = props.season !== undefined ? parseInt(props.season, 10) : undefined;
|
||||||
const episode = props.episode !== undefined ? parseInt(props.episode, 10) : undefined;
|
const episode = props.episode !== undefined ? parseInt(props.episode, 10) : undefined;
|
||||||
@@ -212,7 +206,6 @@ export class VirtualFileSystem implements VFSUpdateCallback {
|
|||||||
ctime: props.ctime ? parseFloat(props.ctime) : mtime,
|
ctime: props.ctime ? parseFloat(props.ctime) : mtime,
|
||||||
hashId,
|
hashId,
|
||||||
title: props.title,
|
title: props.title,
|
||||||
titles,
|
|
||||||
originalTitle: props.originalTitle,
|
originalTitle: props.originalTitle,
|
||||||
fileName,
|
fileName,
|
||||||
season,
|
season,
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
* Old behavior:
|
* Old behavior:
|
||||||
* - Only processes video, subtitle, torrent files
|
* - Only processes video, subtitle, torrent files
|
||||||
* - Requires extension
|
* - Requires extension
|
||||||
* - Title from titles.eng || originalTitle
|
* - Title from title || originalTitle
|
||||||
* - Files without title/extension are hidden (not in Unsorted)
|
* - Files without title/extension are hidden (not in Unsorted)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ export type ConditionOperator =
|
|||||||
*/
|
*/
|
||||||
export interface Condition {
|
export interface Condition {
|
||||||
type: ConditionOperator;
|
type: ConditionOperator;
|
||||||
field: string; // Metadata field path, e.g., "titles.eng", "season", "fileType"
|
field: string; // Metadata field path, e.g., "title", "season", "fileType"
|
||||||
value?: string | number | boolean; // Required for EQUALS, NOT_EQUALS, CONTAINS, MATCHES
|
value?: string | number | boolean; // Required for EQUALS, NOT_EQUALS, CONTAINS, MATCHES
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -83,7 +83,7 @@ export interface PreviewResponse {
|
|||||||
*/
|
*/
|
||||||
export interface TemplateVariable {
|
export interface TemplateVariable {
|
||||||
name: string; // Display name
|
name: string; // Display name
|
||||||
path: string; // Field path (e.g., "titles.eng")
|
path: string; // Field path (e.g., "title")
|
||||||
type: 'string' | 'number' | 'boolean';
|
type: 'string' | 'number' | 'boolean';
|
||||||
description: string;
|
description: string;
|
||||||
example?: string;
|
example?: string;
|
||||||
@@ -93,7 +93,6 @@ export interface TemplateVariable {
|
|||||||
* List of all available template variables
|
* List of all available template variables
|
||||||
*/
|
*/
|
||||||
export const TEMPLATE_VARIABLES: TemplateVariable[] = [
|
export const TEMPLATE_VARIABLES: TemplateVariable[] = [
|
||||||
{ name: 'English Title', path: 'titles.eng', type: 'string', description: 'English title from metadata', example: 'Breaking Bad' },
|
|
||||||
{ name: 'Original Title', path: 'originalTitle', type: 'string', description: 'Original/native title', example: 'Breaking Bad' },
|
{ name: 'Original Title', path: 'originalTitle', type: 'string', description: 'Original/native title', example: 'Breaking Bad' },
|
||||||
{ name: 'Title', path: 'title', type: 'string', description: 'Simple title field', example: 'Breaking Bad' },
|
{ name: 'Title', path: 'title', type: 'string', description: 'Simple title field', example: 'Breaking Bad' },
|
||||||
{ name: 'Season', path: 'season', type: 'number', description: 'Season number', example: '1' },
|
{ name: 'Season', path: 'season', type: 'number', description: 'Season number', example: '1' },
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ interface RulesEditorProps {
|
|||||||
// Available metadata fields for conditions
|
// Available metadata fields for conditions
|
||||||
const AVAILABLE_FIELDS = [
|
const AVAILABLE_FIELDS = [
|
||||||
{ value: 'fileType', label: 'File Type', type: 'string' },
|
{ value: 'fileType', label: 'File Type', type: 'string' },
|
||||||
{ value: 'titles.eng', label: 'English Title', type: 'string' },
|
{ value: 'title', label: 'Title', type: 'string' },
|
||||||
{ value: 'originalTitle', label: 'Original Title', type: 'string' },
|
{ value: 'originalTitle', label: 'Original Title', type: 'string' },
|
||||||
{ value: 'season', label: 'Season', type: 'number' },
|
{ value: 'season', label: 'Season', type: 'number' },
|
||||||
{ value: 'episode', label: 'Episode', type: 'number' },
|
{ value: 'episode', label: 'Episode', type: 'number' },
|
||||||
@@ -53,7 +53,7 @@ function createEmptyRule(): RenamingRule {
|
|||||||
function createEmptyCondition(): Condition {
|
function createEmptyCondition(): Condition {
|
||||||
return {
|
return {
|
||||||
type: 'EXISTS',
|
type: 'EXISTS',
|
||||||
field: 'titles.eng',
|
field: 'title',
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -197,7 +197,7 @@ function TemplateEditor({ template, onChange, variables }: TemplateEditorProps)
|
|||||||
<textarea
|
<textarea
|
||||||
value={template}
|
value={template}
|
||||||
onChange={e => onChange(e.target.value)}
|
onChange={e => onChange(e.target.value)}
|
||||||
placeholder="e.g., Movies/{titles.eng|originalTitle}{movieYear? ({movieYear})}/{fileName}.{extension}"
|
placeholder="e.g., Movies/{title|originalTitle}{movieYear? ({movieYear})}/{fileName}.{extension}"
|
||||||
rows={3}
|
rows={3}
|
||||||
className="template-input"
|
className="template-input"
|
||||||
/>
|
/>
|
||||||
|
|||||||
Reference in New Issue
Block a user