Skip to content

Commit 1a9fbb7

Browse files
committed
Develop * 3
1 parent d543154 commit 1a9fbb7

File tree

10 files changed

+646
-134
lines changed

10 files changed

+646
-134
lines changed

GUI/searchapp/api/__init__.py

Lines changed: 42 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -1,72 +1,76 @@
11
# 06-06-2025 By @FrancescoGrazioso -> "https://github.com/FrancescoGrazioso"
22

33

4-
from typing import Dict, Type
4+
from typing import Dict, List
5+
from .base import BaseStreamingAPI
56

67

7-
# Internal utilities
8-
from .base import BaseStreamingAPI
8+
# Import APi
99
from .streamingcommunity import StreamingCommunityAPI
1010
from .animeunity import AnimeUnityAPI
11+
from .altadefinizione import AltaDefinizioneAPI
12+
from .raiplay import RaiPlayAPI
13+
from .mediasetinfinity import MediasetInfinityAPI
14+
from .tubitv import TubiTVAPI
1115

12-
13-
_API_REGISTRY: Dict[str, Type[BaseStreamingAPI]] = {
16+
_API_REGISTRY: Dict[str, type] = {
1417
'streamingcommunity': StreamingCommunityAPI,
1518
'animeunity': AnimeUnityAPI,
19+
'altadefinizione': AltaDefinizioneAPI,
20+
'raiplay': RaiPlayAPI,
21+
'mediasetinfinity': MediasetInfinityAPI,
22+
'tubitv': TubiTVAPI
1623
}
1724

1825

19-
def get_api(site_name: str) -> BaseStreamingAPI:
26+
def get_available_sites() -> List[str]:
2027
"""
21-
Get API instance for a specific site.
28+
Get list of all available streaming sites.
2229
23-
Args:
24-
site_name: Name of the streaming site
25-
2630
Returns:
27-
Instance of the appropriate API class
31+
List of site identifiers
2832
"""
29-
site_key = site_name.lower().split('_')[0]
30-
31-
if site_key not in _API_REGISTRY:
32-
raise ValueError(
33-
f"Unsupported site: {site_name}. "
34-
f"Available sites: {', '.join(_API_REGISTRY.keys())}"
35-
)
36-
37-
api_class = _API_REGISTRY[site_key]
38-
return api_class()
33+
return list(_API_REGISTRY.keys())
3934

4035

41-
def get_available_sites() -> list:
36+
def get_api(site: str) -> BaseStreamingAPI:
4237
"""
43-
Get list of available streaming sites.
38+
Get API instance for specified site.
4439
40+
Args:
41+
site: Site identifier (e.g., 'streamingcommunity', 'animeunity', 'altadefinizione')
42+
4543
Returns:
46-
List of site names
44+
API instance
45+
46+
Raises:
47+
ValueError: If site is not supported
4748
"""
48-
return list(_API_REGISTRY.keys())
49+
site_lower = site.lower().strip()
50+
51+
if site_lower not in _API_REGISTRY:
52+
available = ', '.join(_API_REGISTRY.keys())
53+
raise ValueError(f"Site '{site}' not supported. Available sites: {available}")
54+
55+
api_class = _API_REGISTRY[site_lower]
56+
return api_class()
4957

5058

51-
def register_api(site_name: str, api_class: Type[BaseStreamingAPI]):
59+
def is_site_available(site: str) -> bool:
5260
"""
53-
Register a new API class.
61+
Check if a site is available.
5462
5563
Args:
56-
site_name: Name of the site
57-
api_class: API class that inherits from BaseStreamingAPI
64+
site: Site identifier
65+
66+
Returns:
67+
True if site is available
5868
"""
59-
if not issubclass(api_class, BaseStreamingAPI):
60-
raise ValueError(f"{api_class} must inherit from BaseStreamingAPI")
61-
62-
_API_REGISTRY[site_name.lower()] = api_class
69+
return site.lower().strip() in _API_REGISTRY
6370

6471

6572
__all__ = [
66-
'BaseStreamingAPI',
67-
'StreamingCommunityAPI',
68-
'AnimeUnityAPI',
69-
'get_api',
7073
'get_available_sites',
71-
'register_api'
74+
'get_api',
75+
'is_site_available',
7276
]
Lines changed: 145 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,145 @@
1+
# 06-06-2025 By @FrancescoGrazioso -> "https://github.com/FrancescoGrazioso"
2+
3+
4+
import importlib
5+
from typing import List, Optional
6+
7+
8+
# Internal utilities
9+
from .base import BaseStreamingAPI, MediaItem, Season, Episode
10+
11+
12+
# External utilities
13+
from StreamingCommunity.Util import config_manager
14+
from StreamingCommunity.Api.Template.loader import get_folder_name
15+
from StreamingCommunity.Api.Service.altadefinizione.util.ScrapeSerie import GetSerieInfo
16+
17+
18+
class AltaDefinizioneAPI(BaseStreamingAPI):
19+
def __init__(self):
20+
super().__init__()
21+
self.site_name = "altadefinizione"
22+
self._load_config()
23+
self._search_fn = None
24+
25+
def _load_config(self):
26+
"""Load site configuration."""
27+
self.base_url = (config_manager.get_site("altadefinizione", "full_url") or "").rstrip("/")
28+
29+
def _get_search_fn(self):
30+
"""Lazy load the search function."""
31+
if self._search_fn is None:
32+
module = importlib.import_module(f"StreamingCommunity.Api.{get_folder_name()}.altadefinizione")
33+
self._search_fn = getattr(module, "search")
34+
return self._search_fn
35+
36+
def search(self, query: str) -> List[MediaItem]:
37+
"""
38+
Search for content on AltaDefinizione.
39+
40+
Args:
41+
query: Search term
42+
43+
Returns:
44+
List of MediaItem objects
45+
"""
46+
try:
47+
search_fn = self._get_search_fn()
48+
database = search_fn(query, get_onlyDatabase=True)
49+
50+
results = []
51+
if database and hasattr(database, 'media_list'):
52+
for element in database.media_list:
53+
item_dict = element.__dict__.copy() if hasattr(element, '__dict__') else {}
54+
55+
media_item = MediaItem(
56+
title=item_dict.get('name'),
57+
type=item_dict.get('type'),
58+
url=item_dict.get('url'),
59+
poster=item_dict.get('image'),
60+
raw_data=item_dict
61+
)
62+
results.append(media_item)
63+
64+
return results
65+
66+
except Exception as e:
67+
raise Exception(f"AltaDefinizione search error: {e}")
68+
69+
def get_series_metadata(self, media_item: MediaItem) -> Optional[List[Season]]:
70+
"""
71+
Get seasons and episodes for an AltaDefinizione series.
72+
73+
Args:
74+
media_item: MediaItem to get metadata for
75+
76+
Returns:
77+
List of Season objects, or None if not a series
78+
"""
79+
if media_item.is_movie:
80+
return None
81+
82+
try:
83+
scraper = GetSerieInfo(media_item.url)
84+
seasons_count = scraper.getNumberSeason()
85+
86+
if not seasons_count:
87+
return None
88+
89+
seasons = []
90+
for season_num in range(1, seasons_count + 1):
91+
try:
92+
episodes_raw = scraper.getEpisodeSeasons(season_num)
93+
episodes = []
94+
95+
for idx, ep in enumerate(episodes_raw or [], 1):
96+
episode = Episode(
97+
number=idx,
98+
name=getattr(ep, 'name', f"Episodio {idx}"),
99+
id=getattr(ep, 'id', idx)
100+
)
101+
episodes.append(episode)
102+
103+
season = Season(number=season_num, episodes=episodes)
104+
seasons.append(season)
105+
106+
except Exception:
107+
continue
108+
109+
return seasons if seasons else None
110+
111+
except Exception as e:
112+
raise Exception(f"Error getting series metadata: {e}")
113+
114+
def start_download(self, media_item: MediaItem, season: Optional[str] = None, episodes: Optional[str] = None) -> bool:
115+
"""
116+
Start downloading from AltaDefinizione.
117+
118+
Args:
119+
media_item: MediaItem to download
120+
season: Season number (for series)
121+
episodes: Episode selection
122+
123+
Returns:
124+
True if download started successfully
125+
"""
126+
try:
127+
search_fn = self._get_search_fn()
128+
129+
# Prepare direct_item from MediaItem
130+
direct_item = media_item.raw_data or media_item.to_dict()
131+
132+
# Prepare selections
133+
selections = None
134+
if season or episodes:
135+
selections = {
136+
'season': season,
137+
'episode': episodes
138+
}
139+
140+
# Execute download
141+
search_fn(direct_item=direct_item, selections=selections)
142+
return True
143+
144+
except Exception as e:
145+
raise Exception(f"Download error: {e}")

GUI/searchapp/api/base.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,11 @@
99
@dataclass
1010
class MediaItem:
1111
"""Standardized media item representation."""
12-
id: Any
1312
title: str
14-
slug: str
1513
type: str # 'film', 'series', 'ova', etc.
14+
slug: str = None
15+
id: Any = None
16+
path_id: Optional[str] = None
1617
url: Optional[str] = None
1718
poster: Optional[str] = None
1819
release_date: Optional[str] = None

0 commit comments

Comments
 (0)