synchronize data between configured servers

This commit is contained in:
2026-05-23 20:32:04 +02:00
parent f9d09d5357
commit 330d414e72
6 changed files with 250 additions and 123 deletions
+38 -24
View File
@@ -10,6 +10,7 @@ from datetime import datetime
from enum import Enum, auto
from pathlib import Path
from logging import Logger
from typing import Any, Dict, Optional
from uuid import UUID
from api import Option, OptionType, Server, get_api_config, get_logger
@@ -25,6 +26,10 @@ args = parser.parse_args()
class FileStatus(Enum):
"""
Status of video file.
"""
DOWNLOADED = auto()
RENAMED = auto()
UNKNOWN = auto()
@@ -35,7 +40,10 @@ def download_file(
file_info: dict,
download_dir: str = "/data/media",
dl_tool: str = "yt-dlp",
) -> dict:
) -> Dict[str, Any]:
"""
Download file from url.
"""
print(f"download file for {url} to {download_dir}")
result = subprocess.run(
[dl_tool, url], cwd=download_dir, capture_output=True, text=True
@@ -45,7 +53,7 @@ def download_file(
output = re.sub(" +", " ", output)
lines_list = output.splitlines()
file_name = __parse_output__(lines_list)
log.info(f"found file: {file_name}")
logger.info("found file: %s", file_name)
if file_name is None or not file_name.strip():
file_info["review"] = True
file_info["should_download"] = True
@@ -60,14 +68,14 @@ def download_file(
return file_info
def __parse_output__(lines_list: list[str]) -> str | None:
def __parse_output__(lines_list: list[str]) -> Optional[str]:
file_name = None
for line in lines_list:
log.debug(f"parse line: {line}")
logger.debug("parse line: %s", line)
if "has already been downloaded" in line:
end_len = len(" has already been downloaded")
file_name = line[11:-end_len]
log.info(f"file_name: {file_name}")
logger.info("file_name: %s", file_name)
break
if "Destination" in line:
line_len = len(line)
@@ -80,24 +88,27 @@ def __parse_output__(lines_list: list[str]) -> str | None:
return file_name
def is_file_downloaded(media_file: dict, dir: Path) -> FileStatus:
def is_file_downloaded(media_file: dict, path: Path) -> FileStatus:
"""
Check, if file is already downloaded.
"""
file_name_as_title = f"{media_file['file_name']}"
if not file_name_as_title:
log.info("title has not been set - start download")
logger.info("title has not been set - start download")
return FileStatus.UNKNOWN
file_title = Path(dir, f"{file_name_as_title}.mp4")
file_title = Path(path, f"{file_name_as_title}.mp4")
if file_title.exists():
log.info(f"{file_name_as_title} has been downloaded")
logger.info("%s has been downloaded", file_name_as_title)
media_file["should_download"] = False
return FileStatus.DOWNLOADED
file_name_as_id = f"{media_file['id']}"
file_with_id_as_name = Path(dir, f"{file_name_as_id}.mp4")
file_with_id_as_name = Path(path, f"{file_name_as_id}.mp4")
if file_with_id_as_name.exists():
log.info(f"{file_with_id_as_name} has been downloaded and renamed")
media_file['cloud_link'] = str(file_with_id_as_name)
media_file['should_download'] = False
return FileStatus.RENAMED
log.info("could not find file - start download")
logger.info("could not find file - start download")
return FileStatus.UNKNOWN
@@ -108,16 +119,19 @@ def update_status(item_id: UUID, file_info: dict):
def rename_file(file_info: dict):
"""
Rename file.
"""
item_id = file_info["id"]
file_name = file_info["file_name"]
if file_name is None or not file_name.strip():
log.info("file_name is not set, rename is not executed")
logger.info("file_name is not set, rename is not executed")
file_info["review"] = True
file_info["should_download"] = True
return
file = Path(args.dir, file_name)
new_file_path = file.with_name(f"{item_id}{file.suffix}")
log.info(f"rename {file} to {new_file_path}")
logger.info("rename %s to %s", file, new_file_path)
file.rename(Path(new_file_path))
file_info["cloud_link"] = str(new_file_path)
@@ -129,33 +143,33 @@ if __name__ == "__main__":
log.info(f"Status: {response.status_code}")
data = response.json()
entries_count = len(data)
log.info(f"data: {entries_count}")
logger.info("data: %s", entries_count)
mediafile_index = 1
log.debug(f"data: {data}")
logger.debug("data: %s", data)
missing_actors = {}
if args.dry_run:
sys.exit(0)
if args.limit:
log.warning(f"check the first {args.limit} links")
logger.warning("check the first %s links", args.limit)
for item in data:
link = item["url"]
file_id = item["id"]
log.info(f"{file_id} - {link}")
logger.info("%s - %s", file_id, link)
download_status: FileStatus = is_file_downloaded(item, args.dir)
match download_status:
case FileStatus.DOWNLOADED:
rename_file(item)
update_status(file_id, item, server=server, log=log)
update_status(file_id, item, api_server=server, log=logger)
case FileStatus.RENAMED:
log.info("update status")
update_status(file_id, item, server=server, log=log)
logger.info("update status")
update_status(file_id, item, api_server=server, log=logger)
case FileStatus.UNKNOWN:
download_file(link, item, args.dir)
rename_file(item)
log.info(f"{item}")
update_status(file_id, item, server=server, log=log)
log.warning(f"processed {mediafile_index}/{entries_count}")
logger.info(item)
update_status(file_id, item, api_server=server, log=logger)
logger.warning("processed %s/%s", mediafile_index, entries_count)
if args.limit and args.limit <= mediafile_index:
break
mediafile_index += 1
log.info("kontor.download finished")
logger.info("kontor.download finished")