Compare commits
6 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| de330dc146 | |||
| 4731fd644a | |||
| 9d52ff0c45 | |||
| ee5d719f37 | |||
| cbc44491e7 | |||
| e319cfecb8 |
@@ -1 +1 @@
|
||||
v1.4.15
|
||||
v1.4.17
|
||||
|
||||
1
Docs/key
1
Docs/key
@@ -5,3 +5,4 @@ API key : 299ae8f630a31bda814263c551361448
|
||||
|
||||
|
||||
SeriesApp initialized for directory:
|
||||
to remove:
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "aniworld-web",
|
||||
"version": "1.4.15",
|
||||
"version": "1.4.17",
|
||||
"description": "Aniworld Anime Download Manager - Web Frontend",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
|
||||
@@ -37,6 +37,7 @@ EXPECTED_TABLES = {
|
||||
"download_queue",
|
||||
"user_sessions",
|
||||
"system_settings",
|
||||
"unresolved_folders",
|
||||
}
|
||||
|
||||
# Expected indexes for performance
|
||||
|
||||
@@ -13,7 +13,7 @@ from __future__ import annotations
|
||||
|
||||
from datetime import datetime, timezone
|
||||
from enum import Enum
|
||||
from typing import List, Optional
|
||||
from typing import Any, Dict, List, Optional
|
||||
|
||||
from sqlalchemy import Boolean, DateTime, ForeignKey, Index, Integer, String, Text, func
|
||||
from sqlalchemy.orm import Mapped, mapped_column, relationship, validates
|
||||
@@ -210,6 +210,15 @@ class AnimeSeries(Base, TimestampMixin):
|
||||
episode_dict[season].append(ep.episode_number or 0)
|
||||
return episode_dict
|
||||
|
||||
@episodeDict.setter
|
||||
def episodeDict(self, value: dict[int, list[int]]) -> None:
|
||||
"""Set the episode dictionary via private cache.
|
||||
|
||||
Args:
|
||||
value: Dictionary mapping season numbers to lists of episode numbers
|
||||
"""
|
||||
self._episode_dict_cache = value
|
||||
|
||||
@property
|
||||
def name_with_year(self) -> str:
|
||||
"""Get series name with year appended if available.
|
||||
@@ -238,6 +247,21 @@ class AnimeSeries(Base, TimestampMixin):
|
||||
except ValueError:
|
||||
return sanitize_folder_name(self.key)
|
||||
|
||||
def to_dict(self) -> Dict[str, Any]:
|
||||
"""Convert to dictionary for cache serialization.
|
||||
|
||||
Returns:
|
||||
Dictionary with series data including episodeDict for
|
||||
auto-download functionality.
|
||||
"""
|
||||
return {
|
||||
"key": self.key,
|
||||
"name": self.name,
|
||||
"site": self.site,
|
||||
"folder": self.folder,
|
||||
"episodeDict": self.episodeDict,
|
||||
}
|
||||
|
||||
|
||||
class Episode(Base, TimestampMixin):
|
||||
"""SQLAlchemy model for anime episodes.
|
||||
|
||||
@@ -579,7 +579,7 @@ class NfoScanService:
|
||||
try:
|
||||
from src.server.nfo.tmdb_client import get_tmdb_client
|
||||
|
||||
client = get_tmdb_client()
|
||||
async with get_tmdb_client() as client:
|
||||
results = await client.search_tv_show(name)
|
||||
if results and results.get("results"):
|
||||
first_result = results["results"][0]
|
||||
@@ -601,7 +601,7 @@ class NfoScanService:
|
||||
try:
|
||||
from src.server.nfo.tmdb_client import get_tmdb_client
|
||||
|
||||
client = get_tmdb_client()
|
||||
async with get_tmdb_client() as client:
|
||||
data = await client.get_tv_show_details(tmdb_id)
|
||||
return data
|
||||
except Exception as exc:
|
||||
|
||||
@@ -473,12 +473,13 @@ async def test_validate_schema_with_inspection_error():
|
||||
def test_schema_constants():
|
||||
"""Test that schema constants are properly defined."""
|
||||
assert CURRENT_SCHEMA_VERSION == "1.0.1"
|
||||
assert len(EXPECTED_TABLES) == 5
|
||||
assert len(EXPECTED_TABLES) == 6
|
||||
assert "anime_series" in EXPECTED_TABLES
|
||||
assert "episodes" in EXPECTED_TABLES
|
||||
assert "download_queue" in EXPECTED_TABLES
|
||||
assert "user_sessions" in EXPECTED_TABLES
|
||||
assert "system_settings" in EXPECTED_TABLES
|
||||
assert "unresolved_folders" in EXPECTED_TABLES
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
@@ -14,6 +14,7 @@ from src.server.api.health import (
|
||||
get_system_metrics,
|
||||
ready_check,
|
||||
)
|
||||
from src.server.utils.version import APP_VERSION
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
@@ -29,7 +30,7 @@ async def test_basic_health_check_no_startup_checks():
|
||||
|
||||
assert isinstance(result, HealthStatus)
|
||||
assert result.status == "healthy"
|
||||
assert result.version == "v1.3.6"
|
||||
assert result.version == APP_VERSION
|
||||
assert result.service == "aniworld-api"
|
||||
assert result.timestamp is not None
|
||||
assert result.series_app_initialized is False
|
||||
|
||||
@@ -180,6 +180,7 @@ class TestTemplateHelpers:
|
||||
def test_get_base_context(self):
|
||||
"""Test getting base context."""
|
||||
from src.server.utils.template_helpers import get_base_context
|
||||
from src.server.utils.version import APP_VERSION
|
||||
|
||||
mock_request = MagicMock(spec=Request)
|
||||
context = get_base_context(mock_request, "Test Title")
|
||||
@@ -187,7 +188,7 @@ class TestTemplateHelpers:
|
||||
assert context["request"] == mock_request
|
||||
assert context["title"] == "Test Title"
|
||||
assert context["app_name"] == "Aniworld Download Manager"
|
||||
assert context["version"] == "v1.3.6"
|
||||
assert context["version"] == APP_VERSION
|
||||
|
||||
def test_get_base_context_default_title(self):
|
||||
"""Test getting base context with default title."""
|
||||
|
||||
@@ -199,7 +199,9 @@ class TestSerieScannerSingleSeries:
|
||||
|
||||
# Pre-populate keyDict
|
||||
scanner.keyDict[sample_serie.key] = sample_serie
|
||||
old_episode_dict = sample_serie.episodeDict.copy()
|
||||
# Use deepcopy because episodeDict is modified in-place
|
||||
import copy
|
||||
old_episode_dict = copy.deepcopy(sample_serie.episodeDict)
|
||||
|
||||
with patch.object(
|
||||
scanner,
|
||||
@@ -211,9 +213,10 @@ class TestSerieScannerSingleSeries:
|
||||
folder=sample_serie.folder
|
||||
)
|
||||
|
||||
# Verify existing entry was updated
|
||||
# Verify existing entry was updated - episodeDict is merged (not replaced)
|
||||
# Old episodes [2, 3, 4] + new episodes [10, 11, 12] = merged result
|
||||
assert scanner.keyDict[sample_serie.key].episodeDict != old_episode_dict
|
||||
assert scanner.keyDict[sample_serie.key].episodeDict == {1: [10, 11, 12]}
|
||||
assert scanner.keyDict[sample_serie.key].episodeDict == {1: [2, 3, 4, 10, 11, 12]}
|
||||
|
||||
def test_scan_single_series_empty_key_raises_error(
|
||||
self, temp_directory, mock_loader
|
||||
|
||||
@@ -16,6 +16,7 @@ from src.server.utils.template_helpers import (
|
||||
prepare_series_context,
|
||||
validate_template_exists,
|
||||
)
|
||||
from src.server.utils.version import APP_VERSION
|
||||
|
||||
|
||||
class TestTemplateHelpers:
|
||||
@@ -30,7 +31,7 @@ class TestTemplateHelpers:
|
||||
assert context["request"] == request
|
||||
assert context["title"] == "Test Title"
|
||||
assert context["app_name"] == "Aniworld Download Manager"
|
||||
assert context["version"] == "v1.3.6"
|
||||
assert context["version"] == APP_VERSION
|
||||
|
||||
def test_get_base_context_default_title(self):
|
||||
"""Test that default title is used."""
|
||||
|
||||
Reference in New Issue
Block a user