fix: unify task workspace directory resolution
This commit is contained in:
@ -4,6 +4,7 @@ import json
|
|||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
from biliup_next.app.retry_meta import retry_meta_for_step
|
from biliup_next.app.retry_meta import retry_meta_for_step
|
||||||
|
from biliup_next.infra.workspace_paths import resolve_task_work_dir
|
||||||
|
|
||||||
|
|
||||||
class ControlPlaneSerializer:
|
class ControlPlaneSerializer:
|
||||||
@ -78,7 +79,7 @@ class ControlPlaneSerializer:
|
|||||||
task = task or self.state["repo"].get_task(task_id)
|
task = task or self.state["repo"].get_task(task_id)
|
||||||
if task is None:
|
if task is None:
|
||||||
return {}
|
return {}
|
||||||
session_dir = Path(str(self.state["settings"]["paths"]["session_dir"])) / task.title
|
session_dir = resolve_task_work_dir(task)
|
||||||
source_path = Path(task.source_path)
|
source_path = Path(task.source_path)
|
||||||
split_dir = session_dir / "split_video"
|
split_dir = session_dir / "split_video"
|
||||||
|
|
||||||
@ -246,7 +247,7 @@ class ControlPlaneSerializer:
|
|||||||
task = task or self.state["repo"].get_task(task_id)
|
task = task or self.state["repo"].get_task(task_id)
|
||||||
if task is None:
|
if task is None:
|
||||||
return None
|
return None
|
||||||
session_dir = Path(str(self.state["settings"]["paths"]["session_dir"])) / task.title
|
session_dir = resolve_task_work_dir(task)
|
||||||
path = session_dir / filename
|
path = session_dir / filename
|
||||||
if not path.exists():
|
if not path.exists():
|
||||||
return None
|
return None
|
||||||
|
|||||||
@ -5,6 +5,7 @@ from pathlib import Path
|
|||||||
import re
|
import re
|
||||||
|
|
||||||
from biliup_next.core.models import ActionRecord, SessionBinding, TaskContext, utc_now_iso
|
from biliup_next.core.models import ActionRecord, SessionBinding, TaskContext, utc_now_iso
|
||||||
|
from biliup_next.infra.workspace_paths import resolve_task_work_dir
|
||||||
|
|
||||||
|
|
||||||
class SessionDeliveryService:
|
class SessionDeliveryService:
|
||||||
@ -222,10 +223,10 @@ class SessionDeliveryService:
|
|||||||
return None
|
return None
|
||||||
return bvid
|
return bvid
|
||||||
|
|
||||||
def _full_video_bvid_path(self, task_title: str) -> Path:
|
def _full_video_bvid_path(self, task) -> Path: # type: ignore[no-untyped-def]
|
||||||
session_dir = Path(str(self.settings["paths"]["session_dir"])) / task_title
|
work_dir = resolve_task_work_dir(task)
|
||||||
session_dir.mkdir(parents=True, exist_ok=True)
|
work_dir.mkdir(parents=True, exist_ok=True)
|
||||||
return session_dir / "full_video_bvid.txt"
|
return work_dir / "full_video_bvid.txt"
|
||||||
|
|
||||||
def _upsert_session_binding_for_context(self, context: TaskContext, full_video_bvid: str, now: str) -> None:
|
def _upsert_session_binding_for_context(self, context: TaskContext, full_video_bvid: str, now: str) -> None:
|
||||||
self.repo.upsert_session_binding(
|
self.repo.upsert_session_binding(
|
||||||
@ -253,6 +254,6 @@ class SessionDeliveryService:
|
|||||||
context.updated_at = now
|
context.updated_at = now
|
||||||
self.repo.upsert_task_context(context)
|
self.repo.upsert_task_context(context)
|
||||||
self._upsert_session_binding_for_context(context, full_video_bvid, now)
|
self._upsert_session_binding_for_context(context, full_video_bvid, now)
|
||||||
path = self._full_video_bvid_path(task.title)
|
path = self._full_video_bvid_path(task)
|
||||||
path.write_text(full_video_bvid, encoding="utf-8")
|
path.write_text(full_video_bvid, encoding="utf-8")
|
||||||
return path
|
return path
|
||||||
|
|||||||
@ -1,9 +1,9 @@
|
|||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
import shutil
|
import shutil
|
||||||
from pathlib import Path
|
|
||||||
|
|
||||||
from biliup_next.infra.task_repository import TaskRepository
|
from biliup_next.infra.task_repository import TaskRepository
|
||||||
|
from biliup_next.infra.workspace_paths import resolve_task_work_dir
|
||||||
|
|
||||||
|
|
||||||
class WorkspaceCleanupService:
|
class WorkspaceCleanupService:
|
||||||
@ -15,7 +15,7 @@ class WorkspaceCleanupService:
|
|||||||
if task is None:
|
if task is None:
|
||||||
raise RuntimeError(f"task not found: {task_id}")
|
raise RuntimeError(f"task not found: {task_id}")
|
||||||
|
|
||||||
session_dir = Path(str(settings["session_dir"])) / task.title
|
session_dir = resolve_task_work_dir(task)
|
||||||
removed: list[str] = []
|
removed: list[str] = []
|
||||||
skipped: list[str] = []
|
skipped: list[str] = []
|
||||||
|
|
||||||
|
|||||||
10
src/biliup_next/infra/workspace_paths.py
Normal file
10
src/biliup_next/infra/workspace_paths.py
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
|
||||||
|
def resolve_task_work_dir(task) -> Path: # type: ignore[no-untyped-def]
|
||||||
|
source = Path(task.source_path).resolve()
|
||||||
|
if source.is_file() or source.suffix:
|
||||||
|
return source.parent
|
||||||
|
return source
|
||||||
@ -11,6 +11,7 @@ from biliup_next.core.models import Task
|
|||||||
from biliup_next.core.providers import ProviderManifest
|
from biliup_next.core.providers import ProviderManifest
|
||||||
from biliup_next.infra.adapters.bilibili_api import BilibiliApiAdapter
|
from biliup_next.infra.adapters.bilibili_api import BilibiliApiAdapter
|
||||||
from biliup_next.infra.adapters.full_video_locator import resolve_full_video_bvid
|
from biliup_next.infra.adapters.full_video_locator import resolve_full_video_bvid
|
||||||
|
from biliup_next.infra.workspace_paths import resolve_task_work_dir
|
||||||
|
|
||||||
|
|
||||||
class BilibiliCollectionProvider:
|
class BilibiliCollectionProvider:
|
||||||
@ -29,7 +30,7 @@ class BilibiliCollectionProvider:
|
|||||||
)
|
)
|
||||||
|
|
||||||
def sync(self, task: Task, target: str, settings: dict[str, Any]) -> dict[str, object]:
|
def sync(self, task: Task, target: str, settings: dict[str, Any]) -> dict[str, object]:
|
||||||
session_dir = Path(str(settings["session_dir"])) / task.title
|
session_dir = resolve_task_work_dir(task)
|
||||||
cookies = self.bilibili_api.load_cookies(Path(str(settings["cookies_file"])))
|
cookies = self.bilibili_api.load_cookies(Path(str(settings["cookies_file"])))
|
||||||
csrf = cookies.get("bili_jct")
|
csrf = cookies.get("bili_jct")
|
||||||
if not csrf:
|
if not csrf:
|
||||||
|
|||||||
@ -11,6 +11,7 @@ from biliup_next.core.models import Task
|
|||||||
from biliup_next.core.providers import ProviderManifest
|
from biliup_next.core.providers import ProviderManifest
|
||||||
from biliup_next.infra.adapters.bilibili_api import BilibiliApiAdapter
|
from biliup_next.infra.adapters.bilibili_api import BilibiliApiAdapter
|
||||||
from biliup_next.infra.adapters.full_video_locator import resolve_full_video_bvid
|
from biliup_next.infra.adapters.full_video_locator import resolve_full_video_bvid
|
||||||
|
from biliup_next.infra.workspace_paths import resolve_task_work_dir
|
||||||
|
|
||||||
|
|
||||||
class BilibiliTopCommentProvider:
|
class BilibiliTopCommentProvider:
|
||||||
@ -28,7 +29,7 @@ class BilibiliTopCommentProvider:
|
|||||||
)
|
)
|
||||||
|
|
||||||
def comment(self, task: Task, settings: dict[str, Any]) -> dict[str, object]:
|
def comment(self, task: Task, settings: dict[str, Any]) -> dict[str, object]:
|
||||||
session_dir = Path(str(settings["session_dir"])) / task.title
|
session_dir = resolve_task_work_dir(task)
|
||||||
songs_path = session_dir / "songs.txt"
|
songs_path = session_dir / "songs.txt"
|
||||||
songs_json_path = session_dir / "songs.json"
|
songs_json_path = session_dir / "songs.json"
|
||||||
bvid_path = session_dir / "bvid.txt"
|
bvid_path = session_dir / "bvid.txt"
|
||||||
@ -164,14 +165,13 @@ class BilibiliTopCommentProvider:
|
|||||||
|
|
||||||
def _build_split_comment(self, task: Task, settings: dict[str, Any]) -> tuple[str, str | None]:
|
def _build_split_comment(self, task: Task, settings: dict[str, Any]) -> tuple[str, str | None]:
|
||||||
repo = settings.get("__repo")
|
repo = settings.get("__repo")
|
||||||
session_dir_root = Path(str(settings["session_dir"]))
|
|
||||||
if repo is None or not hasattr(repo, "get_task_context") or not hasattr(repo, "list_task_contexts_by_session_key"):
|
if repo is None or not hasattr(repo, "get_task_context") or not hasattr(repo, "list_task_contexts_by_session_key"):
|
||||||
session_dir = session_dir_root / task.title
|
session_dir = resolve_task_work_dir(task)
|
||||||
return self._build_split_comment_content(session_dir / "songs.json", session_dir / "songs.txt"), None
|
return self._build_split_comment_content(session_dir / "songs.json", session_dir / "songs.txt"), None
|
||||||
|
|
||||||
context = repo.get_task_context(task.id)
|
context = repo.get_task_context(task.id)
|
||||||
if context is None or not context.session_key or context.session_key.startswith("task:"):
|
if context is None or not context.session_key or context.session_key.startswith("task:"):
|
||||||
session_dir = session_dir_root / task.title
|
session_dir = resolve_task_work_dir(task)
|
||||||
return self._build_split_comment_content(session_dir / "songs.json", session_dir / "songs.txt"), None
|
return self._build_split_comment_content(session_dir / "songs.json", session_dir / "songs.txt"), None
|
||||||
|
|
||||||
ordered_contexts = self._ordered_session_contexts(repo, context.session_key)
|
ordered_contexts = self._ordered_session_contexts(repo, context.session_key)
|
||||||
@ -183,7 +183,10 @@ class BilibiliTopCommentProvider:
|
|||||||
|
|
||||||
blocks: list[str] = []
|
blocks: list[str] = []
|
||||||
for index, session_context in enumerate(ordered_contexts, start=1):
|
for index, session_context in enumerate(ordered_contexts, start=1):
|
||||||
task_dir = session_dir_root / session_context.task_id
|
session_task = repo.get_task(session_context.task_id)
|
||||||
|
if session_task is None:
|
||||||
|
continue
|
||||||
|
task_dir = resolve_task_work_dir(session_task)
|
||||||
content = self._build_split_comment_content(task_dir / "songs.json", task_dir / "songs.txt")
|
content = self._build_split_comment_content(task_dir / "songs.json", task_dir / "songs.txt")
|
||||||
if not content:
|
if not content:
|
||||||
continue
|
continue
|
||||||
@ -195,13 +198,13 @@ class BilibiliTopCommentProvider:
|
|||||||
def _build_full_comment_content(self, task: Task, settings: dict[str, Any]) -> tuple[str, str | None]:
|
def _build_full_comment_content(self, task: Task, settings: dict[str, Any]) -> tuple[str, str | None]:
|
||||||
repo = settings.get("__repo")
|
repo = settings.get("__repo")
|
||||||
if repo is None or not hasattr(repo, "get_task_context") or not hasattr(repo, "list_task_contexts_by_session_key"):
|
if repo is None or not hasattr(repo, "get_task_context") or not hasattr(repo, "list_task_contexts_by_session_key"):
|
||||||
session_dir = Path(str(settings["session_dir"])) / task.title
|
session_dir = resolve_task_work_dir(task)
|
||||||
content = session_dir.joinpath("songs.txt").read_text(encoding="utf-8").strip()
|
content = session_dir.joinpath("songs.txt").read_text(encoding="utf-8").strip()
|
||||||
return content, None if content else "timeline_comment_empty"
|
return content, None if content else "timeline_comment_empty"
|
||||||
|
|
||||||
context = repo.get_task_context(task.id)
|
context = repo.get_task_context(task.id)
|
||||||
if context is None or not context.session_key or context.session_key.startswith("task:"):
|
if context is None or not context.session_key or context.session_key.startswith("task:"):
|
||||||
session_dir = Path(str(settings["session_dir"])) / task.title
|
session_dir = resolve_task_work_dir(task)
|
||||||
content = session_dir.joinpath("songs.txt").read_text(encoding="utf-8").strip()
|
content = session_dir.joinpath("songs.txt").read_text(encoding="utf-8").strip()
|
||||||
return content, None if content else "timeline_comment_empty"
|
return content, None if content else "timeline_comment_empty"
|
||||||
|
|
||||||
@ -214,7 +217,10 @@ class BilibiliTopCommentProvider:
|
|||||||
|
|
||||||
blocks: list[str] = []
|
blocks: list[str] = []
|
||||||
for index, session_context in enumerate(ordered_contexts, start=1):
|
for index, session_context in enumerate(ordered_contexts, start=1):
|
||||||
task_dir = Path(str(settings["session_dir"])) / session_context.task_id
|
session_task = repo.get_task(session_context.task_id)
|
||||||
|
if session_task is None:
|
||||||
|
continue
|
||||||
|
task_dir = resolve_task_work_dir(session_task)
|
||||||
songs_path = task_dir / "songs.txt"
|
songs_path = task_dir / "songs.txt"
|
||||||
if not songs_path.exists():
|
if not songs_path.exists():
|
||||||
continue
|
continue
|
||||||
|
|||||||
@ -11,6 +11,7 @@ from biliup_next.core.errors import ModuleError
|
|||||||
from biliup_next.core.models import PublishRecord, Task, utc_now_iso
|
from biliup_next.core.models import PublishRecord, Task, utc_now_iso
|
||||||
from biliup_next.core.providers import ProviderManifest
|
from biliup_next.core.providers import ProviderManifest
|
||||||
from biliup_next.infra.adapters.biliup_cli import BiliupCliAdapter
|
from biliup_next.infra.adapters.biliup_cli import BiliupCliAdapter
|
||||||
|
from biliup_next.infra.workspace_paths import resolve_task_work_dir
|
||||||
|
|
||||||
|
|
||||||
class BiliupCliPublishProvider:
|
class BiliupCliPublishProvider:
|
||||||
@ -28,7 +29,7 @@ class BiliupCliPublishProvider:
|
|||||||
)
|
)
|
||||||
|
|
||||||
def publish(self, task: Task, clip_videos: list, settings: dict[str, Any]) -> PublishRecord:
|
def publish(self, task: Task, clip_videos: list, settings: dict[str, Any]) -> PublishRecord:
|
||||||
work_dir = Path(str(settings["session_dir"])) / task.title
|
work_dir = resolve_task_work_dir(task)
|
||||||
bvid_file = work_dir / "bvid.txt"
|
bvid_file = work_dir / "bvid.txt"
|
||||||
upload_done = work_dir / "upload_done.flag"
|
upload_done = work_dir / "upload_done.flag"
|
||||||
publish_log = work_dir / "publish.log"
|
publish_log = work_dir / "publish.log"
|
||||||
|
|||||||
@ -8,6 +8,7 @@ from typing import Any
|
|||||||
from biliup_next.core.models import Artifact, PublishRecord, TaskContext, utc_now_iso
|
from biliup_next.core.models import Artifact, PublishRecord, TaskContext, utc_now_iso
|
||||||
from biliup_next.core.registry import Registry
|
from biliup_next.core.registry import Registry
|
||||||
from biliup_next.infra.task_repository import TaskRepository
|
from biliup_next.infra.task_repository import TaskRepository
|
||||||
|
from biliup_next.infra.workspace_paths import resolve_task_work_dir
|
||||||
|
|
||||||
|
|
||||||
class PublishService:
|
class PublishService:
|
||||||
@ -26,7 +27,7 @@ class PublishService:
|
|||||||
if len(session_contexts) <= 1:
|
if len(session_contexts) <= 1:
|
||||||
clip_videos = self._clip_videos_for_task(task_id)
|
clip_videos = self._clip_videos_for_task(task_id)
|
||||||
record = provider.publish(task, clip_videos, settings)
|
record = provider.publish(task, clip_videos, settings)
|
||||||
self._persist_publish_success(task_id, task.title, record, settings)
|
self._persist_publish_success(task, record)
|
||||||
return record
|
return record
|
||||||
|
|
||||||
anchor_context = session_contexts[0]
|
anchor_context = session_contexts[0]
|
||||||
@ -41,7 +42,7 @@ class PublishService:
|
|||||||
title=task.title,
|
title=task.title,
|
||||||
published_at=utc_now_iso(),
|
published_at=utc_now_iso(),
|
||||||
)
|
)
|
||||||
self._persist_publish_success(task_id, task.title, record, settings)
|
self._persist_publish_success(task, record)
|
||||||
return record
|
return record
|
||||||
|
|
||||||
clip_videos = self._session_clip_videos(session_contexts)
|
clip_videos = self._session_clip_videos(session_contexts)
|
||||||
@ -64,7 +65,7 @@ class PublishService:
|
|||||||
title=record.title,
|
title=record.title,
|
||||||
published_at=record.published_at,
|
published_at=record.published_at,
|
||||||
)
|
)
|
||||||
self._persist_publish_success(context.task_id, session_task.title, session_record, settings)
|
self._persist_publish_success(session_task, session_record)
|
||||||
return PublishRecord(
|
return PublishRecord(
|
||||||
id=None,
|
id=None,
|
||||||
task_id=task_id,
|
task_id=task_id,
|
||||||
@ -75,12 +76,13 @@ class PublishService:
|
|||||||
published_at=record.published_at,
|
published_at=record.published_at,
|
||||||
)
|
)
|
||||||
|
|
||||||
def _persist_publish_success(self, task_id: str, task_title: str, record: PublishRecord, settings: dict[str, object]) -> None:
|
def _persist_publish_success(self, task, record: PublishRecord) -> None: # type: ignore[no-untyped-def]
|
||||||
|
task_id = task.id
|
||||||
self.repo.add_publish_record(record)
|
self.repo.add_publish_record(record)
|
||||||
if record.bvid:
|
if record.bvid:
|
||||||
session_dir = Path(str(settings.get("session_dir", "session"))) / task_title
|
work_dir = resolve_task_work_dir(task)
|
||||||
session_dir.mkdir(parents=True, exist_ok=True)
|
work_dir.mkdir(parents=True, exist_ok=True)
|
||||||
bvid_path_obj = session_dir / "bvid.txt"
|
bvid_path_obj = work_dir / "bvid.txt"
|
||||||
bvid_path_obj.write_text(record.bvid, encoding="utf-8")
|
bvid_path_obj.write_text(record.bvid, encoding="utf-8")
|
||||||
self.repo.add_artifact(
|
self.repo.add_artifact(
|
||||||
Artifact(
|
Artifact(
|
||||||
@ -120,12 +122,11 @@ class PublishService:
|
|||||||
return aggregated
|
return aggregated
|
||||||
|
|
||||||
def _shared_session_bvid(self, contexts: list[TaskContext], settings: dict[str, object]) -> str | None:
|
def _shared_session_bvid(self, contexts: list[TaskContext], settings: dict[str, object]) -> str | None:
|
||||||
session_dir_root = Path(str(settings.get("session_dir", "session")))
|
|
||||||
for context in contexts:
|
for context in contexts:
|
||||||
task = self.repo.get_task(context.task_id)
|
task = self.repo.get_task(context.task_id)
|
||||||
if task is None:
|
if task is None:
|
||||||
continue
|
continue
|
||||||
bvid_path = session_dir_root / task.title / "bvid.txt"
|
bvid_path = resolve_task_work_dir(task) / "bvid.txt"
|
||||||
if bvid_path.exists():
|
if bvid_path.exists():
|
||||||
bvid = bvid_path.read_text(encoding="utf-8").strip()
|
bvid = bvid_path.read_text(encoding="utf-8").strip()
|
||||||
if bvid.startswith("BV"):
|
if bvid.startswith("BV"):
|
||||||
@ -138,8 +139,7 @@ class PublishService:
|
|||||||
contexts: list[TaskContext],
|
contexts: list[TaskContext],
|
||||||
settings: dict[str, object],
|
settings: dict[str, object],
|
||||||
) -> dict[str, Any]: # type: ignore[no-untyped-def]
|
) -> dict[str, Any]: # type: ignore[no-untyped-def]
|
||||||
session_dir_root = Path(str(settings.get("session_dir", "session")))
|
anchor_work_dir = resolve_task_work_dir(anchor_task)
|
||||||
anchor_work_dir = (session_dir_root / anchor_task.title).resolve()
|
|
||||||
anchor_work_dir.mkdir(parents=True, exist_ok=True)
|
anchor_work_dir.mkdir(parents=True, exist_ok=True)
|
||||||
aggregate_txt_lines: list[str] = []
|
aggregate_txt_lines: list[str] = []
|
||||||
aggregate_songs: list[dict[str, object]] = []
|
aggregate_songs: list[dict[str, object]] = []
|
||||||
@ -148,7 +148,7 @@ class PublishService:
|
|||||||
task = self.repo.get_task(context.task_id)
|
task = self.repo.get_task(context.task_id)
|
||||||
if task is None:
|
if task is None:
|
||||||
continue
|
continue
|
||||||
task_work_dir = (session_dir_root / task.title).resolve()
|
task_work_dir = resolve_task_work_dir(task)
|
||||||
songs_txt = task_work_dir / "songs.txt"
|
songs_txt = task_work_dir / "songs.txt"
|
||||||
songs_json = task_work_dir / "songs.json"
|
songs_json = task_work_dir / "songs.json"
|
||||||
|
|
||||||
|
|||||||
@ -41,11 +41,11 @@ class BilibiliTopCommentProviderTests(unittest.TestCase):
|
|||||||
provider = BilibiliTopCommentProvider(bilibili_api=api)
|
provider = BilibiliTopCommentProvider(bilibili_api=api)
|
||||||
with tempfile.TemporaryDirectory() as tmpdir:
|
with tempfile.TemporaryDirectory() as tmpdir:
|
||||||
root = Path(tmpdir)
|
root = Path(tmpdir)
|
||||||
task = Task("task-1", "local_file", str(root / "source-1.mp4"), "task-1", "published", utc_now_iso(), utc_now_iso())
|
|
||||||
task_dir_1 = root / "task-1"
|
task_dir_1 = root / "task-1"
|
||||||
task_dir_2 = root / "task-2"
|
task_dir_2 = root / "task-2"
|
||||||
task_dir_1.mkdir(parents=True, exist_ok=True)
|
task_dir_1.mkdir(parents=True, exist_ok=True)
|
||||||
task_dir_2.mkdir(parents=True, exist_ok=True)
|
task_dir_2.mkdir(parents=True, exist_ok=True)
|
||||||
|
task = Task("task-1", "local_file", str(task_dir_1 / "source-1.mp4"), "task-1", "published", utc_now_iso(), utc_now_iso())
|
||||||
(task_dir_1 / "songs.txt").write_text("00:00:00 Song A — Artist A\n", encoding="utf-8")
|
(task_dir_1 / "songs.txt").write_text("00:00:00 Song A — Artist A\n", encoding="utf-8")
|
||||||
(task_dir_1 / "songs.json").write_text(json.dumps({"songs": [{"title": "Song A", "artist": "Artist A"}]}), encoding="utf-8")
|
(task_dir_1 / "songs.json").write_text(json.dumps({"songs": [{"title": "Song A", "artist": "Artist A"}]}), encoding="utf-8")
|
||||||
(task_dir_1 / "bvid.txt").write_text("BV1SPLIT111", encoding="utf-8")
|
(task_dir_1 / "bvid.txt").write_text("BV1SPLIT111", encoding="utf-8")
|
||||||
@ -65,6 +65,13 @@ class BilibiliTopCommentProviderTests(unittest.TestCase):
|
|||||||
def list_task_contexts_by_session_key(self, session_key): # noqa: ANN001
|
def list_task_contexts_by_session_key(self, session_key): # noqa: ANN001
|
||||||
return [self.get_task_context("task-1"), self.get_task_context("task-2")]
|
return [self.get_task_context("task-1"), self.get_task_context("task-2")]
|
||||||
|
|
||||||
|
def get_task(self, task_id): # noqa: ANN001
|
||||||
|
mapping = {
|
||||||
|
"task-1": Task("task-1", "local_file", str(task_dir_1 / "source-1.mp4"), "task-1", "published", utc_now_iso(), utc_now_iso()),
|
||||||
|
"task-2": Task("task-2", "local_file", str(task_dir_2 / "source-2.mp4"), "task-2", "published", utc_now_iso(), utc_now_iso()),
|
||||||
|
}
|
||||||
|
return mapping[task_id]
|
||||||
|
|
||||||
result = provider.comment(
|
result = provider.comment(
|
||||||
task,
|
task,
|
||||||
{
|
{
|
||||||
@ -88,9 +95,9 @@ class BilibiliTopCommentProviderTests(unittest.TestCase):
|
|||||||
provider = BilibiliTopCommentProvider(bilibili_api=api)
|
provider = BilibiliTopCommentProvider(bilibili_api=api)
|
||||||
with tempfile.TemporaryDirectory() as tmpdir:
|
with tempfile.TemporaryDirectory() as tmpdir:
|
||||||
root = Path(tmpdir)
|
root = Path(tmpdir)
|
||||||
task = Task("task-2", "local_file", str(root / "source-2.mp4"), "task-2", "published", utc_now_iso(), utc_now_iso())
|
|
||||||
task_dir = root / "task-2"
|
task_dir = root / "task-2"
|
||||||
task_dir.mkdir(parents=True, exist_ok=True)
|
task_dir.mkdir(parents=True, exist_ok=True)
|
||||||
|
task = Task("task-2", "local_file", str(task_dir / "source-2.mp4"), "task-2", "published", utc_now_iso(), utc_now_iso())
|
||||||
(task_dir / "songs.txt").write_text("00:00:00 Song B — Artist B\n", encoding="utf-8")
|
(task_dir / "songs.txt").write_text("00:00:00 Song B — Artist B\n", encoding="utf-8")
|
||||||
(task_dir / "songs.json").write_text(json.dumps({"songs": [{"title": "Song B", "artist": "Artist B"}]}), encoding="utf-8")
|
(task_dir / "songs.json").write_text(json.dumps({"songs": [{"title": "Song B", "artist": "Artist B"}]}), encoding="utf-8")
|
||||||
(task_dir / "bvid.txt").write_text("BV1SPLIT222", encoding="utf-8")
|
(task_dir / "bvid.txt").write_text("BV1SPLIT222", encoding="utf-8")
|
||||||
@ -108,6 +115,13 @@ class BilibiliTopCommentProviderTests(unittest.TestCase):
|
|||||||
def list_task_contexts_by_session_key(self, session_key): # noqa: ANN001
|
def list_task_contexts_by_session_key(self, session_key): # noqa: ANN001
|
||||||
return [self.get_task_context("task-1"), self.get_task_context("task-2")]
|
return [self.get_task_context("task-1"), self.get_task_context("task-2")]
|
||||||
|
|
||||||
|
def get_task(self, task_id): # noqa: ANN001
|
||||||
|
mapping = {
|
||||||
|
"task-1": Task("task-1", "local_file", str(root / "task-1" / "source-1.mp4"), "task-1", "published", utc_now_iso(), utc_now_iso()),
|
||||||
|
"task-2": Task("task-2", "local_file", str(task_dir / "source-2.mp4"), "task-2", "published", utc_now_iso(), utc_now_iso()),
|
||||||
|
}
|
||||||
|
return mapping[task_id]
|
||||||
|
|
||||||
result = provider.comment(
|
result = provider.comment(
|
||||||
task,
|
task,
|
||||||
{
|
{
|
||||||
@ -128,17 +142,17 @@ class BilibiliTopCommentProviderTests(unittest.TestCase):
|
|||||||
provider = BilibiliTopCommentProvider(bilibili_api=_FakeBilibiliApi())
|
provider = BilibiliTopCommentProvider(bilibili_api=_FakeBilibiliApi())
|
||||||
with tempfile.TemporaryDirectory() as tmpdir:
|
with tempfile.TemporaryDirectory() as tmpdir:
|
||||||
root = Path(tmpdir)
|
root = Path(tmpdir)
|
||||||
|
work_dir = root / "task-1"
|
||||||
|
work_dir.mkdir(parents=True, exist_ok=True)
|
||||||
task = Task(
|
task = Task(
|
||||||
id="task-1",
|
id="task-1",
|
||||||
source_type="local_file",
|
source_type="local_file",
|
||||||
source_path=str(root / "source.mp4"),
|
source_path=str(work_dir / "source.mp4"),
|
||||||
title="task-1",
|
title="task-1",
|
||||||
status="published",
|
status="published",
|
||||||
created_at=utc_now_iso(),
|
created_at=utc_now_iso(),
|
||||||
updated_at=utc_now_iso(),
|
updated_at=utc_now_iso(),
|
||||||
)
|
)
|
||||||
work_dir = root / task.title
|
|
||||||
work_dir.mkdir(parents=True, exist_ok=True)
|
|
||||||
(work_dir / "songs.txt").write_text("00:00:00 Test Song - Tester\n", encoding="utf-8")
|
(work_dir / "songs.txt").write_text("00:00:00 Test Song - Tester\n", encoding="utf-8")
|
||||||
(work_dir / "songs.json").write_text(json.dumps({"songs": [{"title": "Test Song", "artist": "Tester"}]}), encoding="utf-8")
|
(work_dir / "songs.json").write_text(json.dumps({"songs": [{"title": "Test Song", "artist": "Tester"}]}), encoding="utf-8")
|
||||||
(work_dir / "bvid.txt").write_text("BV1COMMENT123", encoding="utf-8")
|
(work_dir / "bvid.txt").write_text("BV1COMMENT123", encoding="utf-8")
|
||||||
@ -162,16 +176,52 @@ class BilibiliTopCommentProviderTests(unittest.TestCase):
|
|||||||
self.assertTrue((work_dir / "comment_full_done.flag").exists())
|
self.assertTrue((work_dir / "comment_full_done.flag").exists())
|
||||||
self.assertTrue((work_dir / "comment_done.flag").exists())
|
self.assertTrue((work_dir / "comment_done.flag").exists())
|
||||||
|
|
||||||
|
def test_comment_uses_source_path_parent_when_task_title_differs(self) -> None:
|
||||||
|
provider = BilibiliTopCommentProvider(bilibili_api=_FakeBilibiliApi())
|
||||||
|
with tempfile.TemporaryDirectory() as tmpdir:
|
||||||
|
root = Path(tmpdir)
|
||||||
|
work_dir = root / "task-id-dir"
|
||||||
|
work_dir.mkdir(parents=True, exist_ok=True)
|
||||||
|
task = Task(
|
||||||
|
id="task-id",
|
||||||
|
source_type="bilibili_url",
|
||||||
|
source_path=str(work_dir / "task-id.mp4"),
|
||||||
|
title="display-title",
|
||||||
|
status="published",
|
||||||
|
created_at=utc_now_iso(),
|
||||||
|
updated_at=utc_now_iso(),
|
||||||
|
)
|
||||||
|
(work_dir / "songs.txt").write_text("00:00:00 Test Song - Tester\n", encoding="utf-8")
|
||||||
|
(work_dir / "songs.json").write_text(json.dumps({"songs": [{"title": "Test Song", "artist": "Tester"}]}), encoding="utf-8")
|
||||||
|
(work_dir / "bvid.txt").write_text("BV1COMMENT123", encoding="utf-8")
|
||||||
|
cookies_file = root / "cookies.json"
|
||||||
|
cookies_file.write_text("{}", encoding="utf-8")
|
||||||
|
|
||||||
|
result = provider.comment(
|
||||||
|
task,
|
||||||
|
{
|
||||||
|
"session_dir": str(root),
|
||||||
|
"cookies_file": str(cookies_file),
|
||||||
|
"post_split_comment": True,
|
||||||
|
"post_full_video_timeline_comment": False,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
self.assertEqual(result["status"], "ok")
|
||||||
|
self.assertEqual(result["split"]["status"], "skipped")
|
||||||
|
self.assertEqual(result["split"]["reason"], "comment_disabled")
|
||||||
|
self.assertTrue((work_dir / "comment_done.flag").exists())
|
||||||
|
|
||||||
def test_full_comment_aggregates_session_parts_on_anchor_task(self) -> None:
|
def test_full_comment_aggregates_session_parts_on_anchor_task(self) -> None:
|
||||||
api = _FakeBilibiliApi()
|
api = _FakeBilibiliApi()
|
||||||
provider = BilibiliTopCommentProvider(bilibili_api=api)
|
provider = BilibiliTopCommentProvider(bilibili_api=api)
|
||||||
with tempfile.TemporaryDirectory() as tmpdir:
|
with tempfile.TemporaryDirectory() as tmpdir:
|
||||||
root = Path(tmpdir)
|
root = Path(tmpdir)
|
||||||
task = Task("task-1", "local_file", str(root / "source-1.mp4"), "task-1", "published", utc_now_iso(), utc_now_iso())
|
|
||||||
task_dir_1 = root / "task-1"
|
task_dir_1 = root / "task-1"
|
||||||
task_dir_2 = root / "task-2"
|
task_dir_2 = root / "task-2"
|
||||||
task_dir_1.mkdir(parents=True, exist_ok=True)
|
task_dir_1.mkdir(parents=True, exist_ok=True)
|
||||||
task_dir_2.mkdir(parents=True, exist_ok=True)
|
task_dir_2.mkdir(parents=True, exist_ok=True)
|
||||||
|
task = Task("task-1", "local_file", str(task_dir_1 / "source-1.mp4"), "task-1", "published", utc_now_iso(), utc_now_iso())
|
||||||
(task_dir_1 / "songs.txt").write_text("00:00:01 Song A\n00:02:00 Song B\n", encoding="utf-8")
|
(task_dir_1 / "songs.txt").write_text("00:00:01 Song A\n00:02:00 Song B\n", encoding="utf-8")
|
||||||
(task_dir_1 / "songs.json").write_text(json.dumps({"songs": [{"title": "Song A"}]}), encoding="utf-8")
|
(task_dir_1 / "songs.json").write_text(json.dumps({"songs": [{"title": "Song A"}]}), encoding="utf-8")
|
||||||
(task_dir_1 / "bvid.txt").write_text("BV1SPLIT111", encoding="utf-8")
|
(task_dir_1 / "bvid.txt").write_text("BV1SPLIT111", encoding="utf-8")
|
||||||
@ -191,6 +241,13 @@ class BilibiliTopCommentProviderTests(unittest.TestCase):
|
|||||||
def list_task_contexts_by_session_key(self, session_key): # noqa: ANN001
|
def list_task_contexts_by_session_key(self, session_key): # noqa: ANN001
|
||||||
return [self.get_task_context("task-1"), self.get_task_context("task-2")]
|
return [self.get_task_context("task-1"), self.get_task_context("task-2")]
|
||||||
|
|
||||||
|
def get_task(self, task_id): # noqa: ANN001
|
||||||
|
mapping = {
|
||||||
|
"task-1": Task("task-1", "local_file", str(task_dir_1 / "source-1.mp4"), "task-1", "published", utc_now_iso(), utc_now_iso()),
|
||||||
|
"task-2": Task("task-2", "local_file", str(task_dir_2 / "source-2.mp4"), "task-2", "published", utc_now_iso(), utc_now_iso()),
|
||||||
|
}
|
||||||
|
return mapping[task_id]
|
||||||
|
|
||||||
result = provider.comment(
|
result = provider.comment(
|
||||||
task,
|
task,
|
||||||
{
|
{
|
||||||
@ -214,9 +271,9 @@ class BilibiliTopCommentProviderTests(unittest.TestCase):
|
|||||||
provider = BilibiliTopCommentProvider(bilibili_api=api)
|
provider = BilibiliTopCommentProvider(bilibili_api=api)
|
||||||
with tempfile.TemporaryDirectory() as tmpdir:
|
with tempfile.TemporaryDirectory() as tmpdir:
|
||||||
root = Path(tmpdir)
|
root = Path(tmpdir)
|
||||||
task = Task("task-2", "local_file", str(root / "source-2.mp4"), "task-2", "published", utc_now_iso(), utc_now_iso())
|
|
||||||
task_dir = root / "task-2"
|
task_dir = root / "task-2"
|
||||||
task_dir.mkdir(parents=True, exist_ok=True)
|
task_dir.mkdir(parents=True, exist_ok=True)
|
||||||
|
task = Task("task-2", "local_file", str(task_dir / "source-2.mp4"), "task-2", "published", utc_now_iso(), utc_now_iso())
|
||||||
(task_dir / "songs.txt").write_text("00:00:03 Song C\n", encoding="utf-8")
|
(task_dir / "songs.txt").write_text("00:00:03 Song C\n", encoding="utf-8")
|
||||||
(task_dir / "songs.json").write_text(json.dumps({"songs": [{"title": "Song C"}]}), encoding="utf-8")
|
(task_dir / "songs.json").write_text(json.dumps({"songs": [{"title": "Song C"}]}), encoding="utf-8")
|
||||||
(task_dir / "bvid.txt").write_text("BV1SPLIT222", encoding="utf-8")
|
(task_dir / "bvid.txt").write_text("BV1SPLIT222", encoding="utf-8")
|
||||||
@ -235,6 +292,13 @@ class BilibiliTopCommentProviderTests(unittest.TestCase):
|
|||||||
def list_task_contexts_by_session_key(self, session_key): # noqa: ANN001
|
def list_task_contexts_by_session_key(self, session_key): # noqa: ANN001
|
||||||
return [self.get_task_context("task-1"), self.get_task_context("task-2")]
|
return [self.get_task_context("task-1"), self.get_task_context("task-2")]
|
||||||
|
|
||||||
|
def get_task(self, task_id): # noqa: ANN001
|
||||||
|
mapping = {
|
||||||
|
"task-1": Task("task-1", "local_file", str(root / "task-1" / "source-1.mp4"), "task-1", "published", utc_now_iso(), utc_now_iso()),
|
||||||
|
"task-2": Task("task-2", "local_file", str(task_dir / "source-2.mp4"), "task-2", "published", utc_now_iso(), utc_now_iso()),
|
||||||
|
}
|
||||||
|
return mapping[task_id]
|
||||||
|
|
||||||
result = provider.comment(
|
result = provider.comment(
|
||||||
task,
|
task,
|
||||||
{
|
{
|
||||||
|
|||||||
@ -50,22 +50,71 @@ class BiliupCliAdapterTests(unittest.TestCase):
|
|||||||
|
|
||||||
|
|
||||||
class BiliupCliPublishProviderTests(unittest.TestCase):
|
class BiliupCliPublishProviderTests(unittest.TestCase):
|
||||||
|
def test_publish_uses_source_path_parent_when_task_title_differs(self) -> None:
|
||||||
|
adapter = _FakeBiliupAdapter()
|
||||||
|
provider = BiliupCliPublishProvider(adapter=adapter)
|
||||||
|
with tempfile.TemporaryDirectory() as tmpdir:
|
||||||
|
root = Path(tmpdir)
|
||||||
|
work_dir = root / "task-id-dir"
|
||||||
|
work_dir.mkdir(parents=True, exist_ok=True)
|
||||||
|
task = Task(
|
||||||
|
id="task-id",
|
||||||
|
source_type="bilibili_url",
|
||||||
|
source_path=str(work_dir / "task-id.mp4"),
|
||||||
|
title="display-title",
|
||||||
|
status="split_done",
|
||||||
|
created_at=utc_now_iso(),
|
||||||
|
updated_at=utc_now_iso(),
|
||||||
|
)
|
||||||
|
(work_dir / "songs.txt").write_text("00:00:00 Test Song - Tester\n", encoding="utf-8")
|
||||||
|
(work_dir / "songs.json").write_text(json.dumps({"songs": [{"title": "Test Song"}]}), encoding="utf-8")
|
||||||
|
upload_config = root / "upload_config.json"
|
||||||
|
upload_config.write_text("{}", encoding="utf-8")
|
||||||
|
clip_path = work_dir / "clip-1.mp4"
|
||||||
|
clip_path.write_text("fake", encoding="utf-8")
|
||||||
|
clip = Artifact(
|
||||||
|
id=None,
|
||||||
|
task_id=task.id,
|
||||||
|
artifact_type="clip_video",
|
||||||
|
path=str(clip_path),
|
||||||
|
metadata_json="{}",
|
||||||
|
created_at=utc_now_iso(),
|
||||||
|
)
|
||||||
|
|
||||||
|
record = provider.publish(
|
||||||
|
task,
|
||||||
|
[clip],
|
||||||
|
{
|
||||||
|
"session_dir": str(root),
|
||||||
|
"upload_config_file": str(upload_config),
|
||||||
|
"biliup_path": "runtime/biliup",
|
||||||
|
"cookie_file": "runtime/cookies.json",
|
||||||
|
"retry_count": 1,
|
||||||
|
"command_timeout_seconds": 123,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
self.assertEqual(record.bvid, "BV1TEST12345")
|
||||||
|
self.assertEqual(adapter.optional_calls[0]["log_path"], work_dir / "publish.log")
|
||||||
|
self.assertTrue((work_dir / "bvid.txt").exists())
|
||||||
|
self.assertTrue((work_dir / "upload_done.flag").exists())
|
||||||
|
|
||||||
def test_publish_passes_timeout_and_log_path(self) -> None:
|
def test_publish_passes_timeout_and_log_path(self) -> None:
|
||||||
adapter = _FakeBiliupAdapter()
|
adapter = _FakeBiliupAdapter()
|
||||||
provider = BiliupCliPublishProvider(adapter=adapter)
|
provider = BiliupCliPublishProvider(adapter=adapter)
|
||||||
with tempfile.TemporaryDirectory() as tmpdir:
|
with tempfile.TemporaryDirectory() as tmpdir:
|
||||||
root = Path(tmpdir)
|
root = Path(tmpdir)
|
||||||
|
work_dir = root / "task-1"
|
||||||
|
work_dir.mkdir(parents=True, exist_ok=True)
|
||||||
task = Task(
|
task = Task(
|
||||||
id="task-1",
|
id="task-1",
|
||||||
source_type="local_file",
|
source_type="local_file",
|
||||||
source_path=str(root / "source.mp4"),
|
source_path=str(work_dir / "source.mp4"),
|
||||||
title="task-1",
|
title="task-1",
|
||||||
status="split_done",
|
status="split_done",
|
||||||
created_at=utc_now_iso(),
|
created_at=utc_now_iso(),
|
||||||
updated_at=utc_now_iso(),
|
updated_at=utc_now_iso(),
|
||||||
)
|
)
|
||||||
work_dir = root / task.title
|
|
||||||
work_dir.mkdir(parents=True, exist_ok=True)
|
|
||||||
(work_dir / "songs.txt").write_text("00:00:00 Test Song - Tester\n", encoding="utf-8")
|
(work_dir / "songs.txt").write_text("00:00:00 Test Song - Tester\n", encoding="utf-8")
|
||||||
(work_dir / "songs.json").write_text(json.dumps({"songs": [{"title": "Test Song"}]}), encoding="utf-8")
|
(work_dir / "songs.json").write_text(json.dumps({"songs": [{"title": "Test Song"}]}), encoding="utf-8")
|
||||||
upload_config = root / "upload_config.json"
|
upload_config = root / "upload_config.json"
|
||||||
@ -117,17 +166,17 @@ class BiliupCliPublishProviderTests(unittest.TestCase):
|
|||||||
provider = BiliupCliPublishProvider(adapter=adapter)
|
provider = BiliupCliPublishProvider(adapter=adapter)
|
||||||
with tempfile.TemporaryDirectory() as tmpdir:
|
with tempfile.TemporaryDirectory() as tmpdir:
|
||||||
root = Path(tmpdir)
|
root = Path(tmpdir)
|
||||||
|
work_dir = root / "task-1"
|
||||||
|
work_dir.mkdir(parents=True, exist_ok=True)
|
||||||
task = Task(
|
task = Task(
|
||||||
id="task-1",
|
id="task-1",
|
||||||
source_type="local_file",
|
source_type="local_file",
|
||||||
source_path=str(root / "source.mp4"),
|
source_path=str(work_dir / "source.mp4"),
|
||||||
title="task-1",
|
title="task-1",
|
||||||
status="split_done",
|
status="split_done",
|
||||||
created_at=utc_now_iso(),
|
created_at=utc_now_iso(),
|
||||||
updated_at=utc_now_iso(),
|
updated_at=utc_now_iso(),
|
||||||
)
|
)
|
||||||
work_dir = root / task.title
|
|
||||||
work_dir.mkdir(parents=True, exist_ok=True)
|
|
||||||
(work_dir / "songs.txt").write_text("00:00:00 Test Song - Tester\n", encoding="utf-8")
|
(work_dir / "songs.txt").write_text("00:00:00 Test Song - Tester\n", encoding="utf-8")
|
||||||
(work_dir / "songs.json").write_text(json.dumps({"songs": [{"title": "Test Song"}]}), encoding="utf-8")
|
(work_dir / "songs.json").write_text(json.dumps({"songs": [{"title": "Test Song"}]}), encoding="utf-8")
|
||||||
(work_dir / "bvid.txt").write_text("BVOLD1234567", encoding="utf-8")
|
(work_dir / "bvid.txt").write_text("BVOLD1234567", encoding="utf-8")
|
||||||
@ -165,17 +214,17 @@ class BiliupCliPublishProviderTests(unittest.TestCase):
|
|||||||
provider = BiliupCliPublishProvider(adapter=adapter)
|
provider = BiliupCliPublishProvider(adapter=adapter)
|
||||||
with tempfile.TemporaryDirectory() as tmpdir:
|
with tempfile.TemporaryDirectory() as tmpdir:
|
||||||
root = Path(tmpdir)
|
root = Path(tmpdir)
|
||||||
|
work_dir = root / "task-1"
|
||||||
|
work_dir.mkdir(parents=True, exist_ok=True)
|
||||||
task = Task(
|
task = Task(
|
||||||
id="task-1",
|
id="task-1",
|
||||||
source_type="local_file",
|
source_type="local_file",
|
||||||
source_path=str(root / "source.mp4"),
|
source_path=str(work_dir / "source.mp4"),
|
||||||
title="task-1",
|
title="task-1",
|
||||||
status="split_done",
|
status="split_done",
|
||||||
created_at=utc_now_iso(),
|
created_at=utc_now_iso(),
|
||||||
updated_at=utc_now_iso(),
|
updated_at=utc_now_iso(),
|
||||||
)
|
)
|
||||||
work_dir = root / task.title
|
|
||||||
work_dir.mkdir(parents=True, exist_ok=True)
|
|
||||||
(work_dir / "songs.txt").write_text("00:00:00 Test Song - Tester\n", encoding="utf-8")
|
(work_dir / "songs.txt").write_text("00:00:00 Test Song - Tester\n", encoding="utf-8")
|
||||||
(work_dir / "songs.json").write_text(json.dumps({"songs": [{"title": "Test Song"}]}), encoding="utf-8")
|
(work_dir / "songs.json").write_text(json.dumps({"songs": [{"title": "Test Song"}]}), encoding="utf-8")
|
||||||
(work_dir / "bvid.txt").write_text("BV1RESUME1234", encoding="utf-8")
|
(work_dir / "bvid.txt").write_text("BV1RESUME1234", encoding="utf-8")
|
||||||
@ -225,17 +274,17 @@ class BiliupCliPublishProviderTests(unittest.TestCase):
|
|||||||
provider = BiliupCliPublishProvider(adapter=adapter)
|
provider = BiliupCliPublishProvider(adapter=adapter)
|
||||||
with tempfile.TemporaryDirectory() as tmpdir:
|
with tempfile.TemporaryDirectory() as tmpdir:
|
||||||
root = Path(tmpdir)
|
root = Path(tmpdir)
|
||||||
|
work_dir = root / "task-1"
|
||||||
|
work_dir.mkdir(parents=True, exist_ok=True)
|
||||||
task = Task(
|
task = Task(
|
||||||
id="task-1",
|
id="task-1",
|
||||||
source_type="local_file",
|
source_type="local_file",
|
||||||
source_path=str(root / "source.mp4"),
|
source_path=str(work_dir / "source.mp4"),
|
||||||
title="task-1",
|
title="task-1",
|
||||||
status="split_done",
|
status="split_done",
|
||||||
created_at=utc_now_iso(),
|
created_at=utc_now_iso(),
|
||||||
updated_at=utc_now_iso(),
|
updated_at=utc_now_iso(),
|
||||||
)
|
)
|
||||||
work_dir = root / task.title
|
|
||||||
work_dir.mkdir(parents=True, exist_ok=True)
|
|
||||||
(work_dir / "songs.txt").write_text("00:00:00 Test Song - Tester\n", encoding="utf-8")
|
(work_dir / "songs.txt").write_text("00:00:00 Test Song - Tester\n", encoding="utf-8")
|
||||||
(work_dir / "songs.json").write_text(json.dumps({"songs": [{"title": "Test Song"}]}), encoding="utf-8")
|
(work_dir / "songs.json").write_text(json.dumps({"songs": [{"title": "Test Song"}]}), encoding="utf-8")
|
||||||
(work_dir / "bvid.txt").write_text("BV1RESUME1234", encoding="utf-8")
|
(work_dir / "bvid.txt").write_text("BV1RESUME1234", encoding="utf-8")
|
||||||
|
|||||||
@ -75,8 +75,10 @@ class PublishServiceTests(unittest.TestCase):
|
|||||||
provider = _FakePublishProvider()
|
provider = _FakePublishProvider()
|
||||||
with tempfile.TemporaryDirectory() as tmpdir:
|
with tempfile.TemporaryDirectory() as tmpdir:
|
||||||
root = Path(tmpdir)
|
root = Path(tmpdir)
|
||||||
task1 = Task("task-1", "local_file", "/tmp/a.mp4", "task-1", "split_done", "2026-01-01T00:00:00+00:00", "2026-01-01T00:00:00+00:00")
|
(root / "task-1").mkdir(parents=True, exist_ok=True)
|
||||||
task2 = Task("task-2", "local_file", "/tmp/b.mp4", "task-2", "split_done", "2026-01-01T00:00:00+00:00", "2026-01-01T00:00:00+00:00")
|
(root / "task-2").mkdir(parents=True, exist_ok=True)
|
||||||
|
task1 = Task("task-1", "local_file", str(root / "task-1" / "source.mp4"), "task-1", "split_done", "2026-01-01T00:00:00+00:00", "2026-01-01T00:00:00+00:00")
|
||||||
|
task2 = Task("task-2", "local_file", str(root / "task-2" / "source.mp4"), "task-2", "split_done", "2026-01-01T00:00:00+00:00", "2026-01-01T00:00:00+00:00")
|
||||||
ctx1 = TaskContext(None, "task-1", "session-1", "s", None, "part-1", "2026-04-04T09:23:00+08:00", None, None, task1.created_at, task1.updated_at)
|
ctx1 = TaskContext(None, "task-1", "session-1", "s", None, "part-1", "2026-04-04T09:23:00+08:00", None, None, task1.created_at, task1.updated_at)
|
||||||
ctx2 = TaskContext(None, "task-2", "session-1", "s", None, "part-2", "2026-04-04T09:25:00+08:00", None, None, task2.created_at, task2.updated_at)
|
ctx2 = TaskContext(None, "task-2", "session-1", "s", None, "part-2", "2026-04-04T09:25:00+08:00", None, None, task2.created_at, task2.updated_at)
|
||||||
artifacts = {
|
artifacts = {
|
||||||
@ -108,8 +110,9 @@ class PublishServiceTests(unittest.TestCase):
|
|||||||
root = Path(tmpdir)
|
root = Path(tmpdir)
|
||||||
(root / "task-1").mkdir(parents=True, exist_ok=True)
|
(root / "task-1").mkdir(parents=True, exist_ok=True)
|
||||||
(root / "task-1" / "bvid.txt").write_text("BV1SESSION123", encoding="utf-8")
|
(root / "task-1" / "bvid.txt").write_text("BV1SESSION123", encoding="utf-8")
|
||||||
task1 = Task("task-1", "local_file", "/tmp/a.mp4", "task-1", "published", "2026-01-01T00:00:00+00:00", "2026-01-01T00:00:00+00:00")
|
(root / "task-2").mkdir(parents=True, exist_ok=True)
|
||||||
task2 = Task("task-2", "local_file", "/tmp/b.mp4", "task-2", "split_done", "2026-01-01T00:00:00+00:00", "2026-01-01T00:00:00+00:00")
|
task1 = Task("task-1", "local_file", str(root / "task-1" / "source.mp4"), "task-1", "published", "2026-01-01T00:00:00+00:00", "2026-01-01T00:00:00+00:00")
|
||||||
|
task2 = Task("task-2", "local_file", str(root / "task-2" / "source.mp4"), "task-2", "split_done", "2026-01-01T00:00:00+00:00", "2026-01-01T00:00:00+00:00")
|
||||||
ctx1 = TaskContext(None, "task-1", "session-1", "s", None, "part-1", "2026-04-04T09:23:00+08:00", None, None, task1.created_at, task1.updated_at)
|
ctx1 = TaskContext(None, "task-1", "session-1", "s", None, "part-1", "2026-04-04T09:23:00+08:00", None, None, task1.created_at, task1.updated_at)
|
||||||
ctx2 = TaskContext(None, "task-2", "session-1", "s", None, "part-2", "2026-04-04T09:25:00+08:00", None, None, task2.created_at, task2.updated_at)
|
ctx2 = TaskContext(None, "task-2", "session-1", "s", None, "part-2", "2026-04-04T09:25:00+08:00", None, None, task2.created_at, task2.updated_at)
|
||||||
repo = _FakeRepo([task1, task2], [ctx1, ctx2], {"task-2": []})
|
repo = _FakeRepo([task1, task2], [ctx1, ctx2], {"task-2": []})
|
||||||
@ -132,8 +135,8 @@ class PublishServiceTests(unittest.TestCase):
|
|||||||
(root / "task-2" / "songs.txt").write_text("00:00:00 Song B — Artist B\n", encoding="utf-8")
|
(root / "task-2" / "songs.txt").write_text("00:00:00 Song B — Artist B\n", encoding="utf-8")
|
||||||
(root / "task-1" / "songs.json").write_text('{"songs":[{"title":"Song A"},{"title":"Song A2"}]}\n', encoding="utf-8")
|
(root / "task-1" / "songs.json").write_text('{"songs":[{"title":"Song A"},{"title":"Song A2"}]}\n', encoding="utf-8")
|
||||||
(root / "task-2" / "songs.json").write_text('{"songs":[{"title":"Song B"}]}\n', encoding="utf-8")
|
(root / "task-2" / "songs.json").write_text('{"songs":[{"title":"Song B"}]}\n', encoding="utf-8")
|
||||||
task1 = Task("task-1", "local_file", "/tmp/a.mp4", "task-1", "split_done", "2026-01-01T00:00:00+00:00", "2026-01-01T00:00:00+00:00")
|
task1 = Task("task-1", "local_file", str(root / "task-1" / "source.mp4"), "task-1", "split_done", "2026-01-01T00:00:00+00:00", "2026-01-01T00:00:00+00:00")
|
||||||
task2 = Task("task-2", "local_file", "/tmp/b.mp4", "task-2", "split_done", "2026-01-01T00:00:00+00:00", "2026-01-01T00:00:00+00:00")
|
task2 = Task("task-2", "local_file", str(root / "task-2" / "source.mp4"), "task-2", "split_done", "2026-01-01T00:00:00+00:00", "2026-01-01T00:00:00+00:00")
|
||||||
ctx1 = TaskContext(None, "task-1", "session-1", "s", None, "part-1", "2026-04-04T09:23:00+08:00", None, None, task1.created_at, task1.updated_at)
|
ctx1 = TaskContext(None, "task-1", "session-1", "s", None, "part-1", "2026-04-04T09:23:00+08:00", None, None, task1.created_at, task1.updated_at)
|
||||||
ctx2 = TaskContext(None, "task-2", "session-1", "s", None, "part-2", "2026-04-04T09:25:00+08:00", None, None, task2.created_at, task2.updated_at)
|
ctx2 = TaskContext(None, "task-2", "session-1", "s", None, "part-2", "2026-04-04T09:25:00+08:00", None, None, task2.created_at, task2.updated_at)
|
||||||
artifacts = {
|
artifacts = {
|
||||||
|
|||||||
Reference in New Issue
Block a user