добавил обработчик задач
All checks were successful
Deploy timelaps / deploy (push) Successful in 5s

This commit is contained in:
ack
2026-04-19 19:41:33 +03:00
parent a3df30184e
commit 4a10958445
11 changed files with 434 additions and 7 deletions

View File

@@ -2,6 +2,7 @@ import logging
from pathlib import Path
from django.conf import settings
from django.utils.text import slugify
from ..models import Camera
@@ -16,6 +17,19 @@ def _storage_root() -> Path:
return Path(storage_path)
def generate_unique_camera_slug(directory_name: str, storage_path: str) -> str:
base_slug = (slugify(directory_name) or f'camera-{directory_name.lower()}')[:70]
slug = base_slug
suffix = 1
while Camera.objects.filter(slug=slug).exclude(storage_path=storage_path).exists():
suffix_part = f'-{suffix}'
slug = f"{base_slug[:80 - len(suffix_part)]}{suffix_part}"
suffix += 1
return slug
def is_storage_available() -> bool:
logger.info('cameras:storage_available:start')
try:
@@ -57,4 +71,53 @@ def get_camera_lastsnap_path(camera: Camera) -> Path | None:
return candidate
except Exception:
logger.exception('cameras:lastsnap_path:error camera_id=%s', camera.id)
raise
def discover_camera_candidates() -> list[dict[str, str]]:
logger.info('cameras:discover_candidates:start')
try:
root = _storage_root()
if not root.exists() or not root.is_dir():
logger.info('cameras:discover_candidates:done count=0')
return []
existing_paths = set(Camera.objects.values_list('storage_path', flat=True))
dirs = [p for p in root.iterdir() if p.is_dir() and not p.name.startswith('.') and p.name != 'timelapses']
candidates = []
for directory in sorted(dirs, key=lambda d: d.name.lower()):
storage_path = directory.name
if storage_path in existing_paths:
continue
candidates.append({'name': directory.name, 'storage_path': storage_path})
logger.info('cameras:discover_candidates:done count=%s', len(candidates))
return candidates
except Exception:
logger.exception('cameras:discover_candidates:error')
raise
def create_cameras_from_candidates(selected_storage_paths: list[str]) -> int:
logger.info('cameras:create_from_candidates:start count=%s', len(selected_storage_paths))
try:
created = 0
for storage_path in selected_storage_paths:
path = storage_path.strip()
if not path:
continue
slug = generate_unique_camera_slug(path, path)
_, was_created = Camera.objects.get_or_create(
storage_path=path,
defaults={'name': path, 'slug': slug, 'is_active': True},
)
if was_created:
created += 1
logger.info('cameras:create_from_candidates:done created=%s', created)
return created
except Exception:
logger.exception('cameras:create_from_candidates:error')
raise