feat (ui): timezone
This commit is contained in:
@@ -11,6 +11,7 @@ from app.config import APP_DATA_DIR
|
||||
|
||||
class SessionService:
|
||||
FILE_DATE_SETTING_KEY = "set_file_date_to_first_aired_date"
|
||||
MAX_FILENAME_LEN = 220
|
||||
|
||||
def __init__(self) -> None:
|
||||
self._db_path = Path(APP_DATA_DIR) / "session_state.sqlite3"
|
||||
@@ -461,7 +462,9 @@ class SessionService:
|
||||
)
|
||||
year = episode.get("year") or "0000"
|
||||
series = self._normalize_series_name(series, year)
|
||||
series = self.sanitize_filename_component(series)
|
||||
title = episode.get("title") or "Untitled"
|
||||
title = self.sanitize_filename_component(title)
|
||||
|
||||
season_raw = episode.get("season_number") or episode.get("season") or 0
|
||||
episode_raw = episode.get("episode_number") or episode.get("number") or 0
|
||||
@@ -481,6 +484,7 @@ class SessionService:
|
||||
proposed_filename = (
|
||||
f"{series} ({year}) - S{season_number:02}E{episode_number:02} - {title}{ext}"
|
||||
)
|
||||
proposed_filename = self._finalize_filename(proposed_filename, ext)
|
||||
|
||||
previews.append(
|
||||
{
|
||||
@@ -510,6 +514,29 @@ class SessionService:
|
||||
pattern = re.compile(rf"\s*\({re.escape(year_str)}\)\s*$")
|
||||
return pattern.sub("", text).strip()
|
||||
|
||||
def sanitize_filename_component(self, value: str) -> str:
|
||||
text = str(value or "")
|
||||
# Replace Windows/SMB disallowed characters with spaces.
|
||||
text = re.sub(r'[\\/:*?"<>|]', " ", text)
|
||||
# Normalize any repeated whitespace and trim trailing/leading dot/space.
|
||||
text = re.sub(r"\s+", " ", text).strip(" .")
|
||||
return text or "Untitled"
|
||||
|
||||
def _finalize_filename(self, filename: str, ext: str) -> str:
|
||||
extension = str(ext or "")
|
||||
stem = filename[: -len(extension)] if extension and filename.endswith(extension) else filename
|
||||
stem = re.sub(r"\s+", " ", stem).strip(" .")
|
||||
if not stem:
|
||||
stem = "Untitled"
|
||||
|
||||
max_stem_len = max(1, self.MAX_FILENAME_LEN - len(extension))
|
||||
if len(stem) > max_stem_len:
|
||||
stem = stem[:max_stem_len].rstrip(" .")
|
||||
if not stem:
|
||||
stem = "Untitled"
|
||||
|
||||
return f"{stem}{extension}"
|
||||
|
||||
def execute_rename(self, session_id: str, confirm: bool) -> dict:
|
||||
if not confirm:
|
||||
raise ValueError("confirm=true is required to execute rename")
|
||||
@@ -644,15 +671,20 @@ class SessionService:
|
||||
except ValueError:
|
||||
return None
|
||||
|
||||
local_noon = datetime(
|
||||
# Convert with local-time semantics (host/container local timezone),
|
||||
# avoiding implicit UTC conversion paths.
|
||||
local_struct = (
|
||||
date_part.year,
|
||||
date_part.month,
|
||||
date_part.day,
|
||||
12,
|
||||
0,
|
||||
0,
|
||||
-1,
|
||||
-1,
|
||||
-1,
|
||||
)
|
||||
return local_noon.timestamp()
|
||||
return time.mktime(local_struct)
|
||||
|
||||
def _log_rename_run(self, session_id: str, result: dict, duration_ms: int) -> None:
|
||||
created_at = datetime.now(timezone.utc).isoformat()
|
||||
|
||||
Reference in New Issue
Block a user