Skip to content

Commit 27d8695

Browse files
authored
Bump v3.4.8
* Update README Added sponsor badge and last commit badge to README. * Fix #432 * Update README Added sponsor badge and last commit badge to README. * rufus si incazza * Bump v3.4.8 * Update README.md * Update version.py * Bumpv v3.4.8
1 parent 1cc99c7 commit 27d8695

File tree

42 files changed

+2037
-576
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

42 files changed

+2037
-576
lines changed

GUI/manage.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,14 @@
22
import os
33
import sys
44

5+
56
# Fix PYTHONPATH
67
current_dir = os.path.dirname(os.path.abspath(__file__))
78
parent_dir = os.path.dirname(current_dir)
89
if parent_dir not in sys.path:
910
sys.path.insert(0, parent_dir)
1011

1112

12-
1313
def main():
1414
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "webgui.settings")
1515
from django.core.management import execute_from_command_line

GUI/searchapp/__init__.py

Lines changed: 0 additions & 1 deletion
This file was deleted.

GUI/searchapp/api/__init__.py

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
# 06-06-2025 By @FrancescoGrazioso -> "https://github.com/FrancescoGrazioso"
2+
3+
4+
from typing import Dict, Type
5+
6+
7+
# Internal utilities
8+
from .base import BaseStreamingAPI
9+
from .streamingcommunity import StreamingCommunityAPI
10+
from .animeunity import AnimeUnityAPI
11+
12+
13+
_API_REGISTRY: Dict[str, Type[BaseStreamingAPI]] = {
14+
'streamingcommunity': StreamingCommunityAPI,
15+
'animeunity': AnimeUnityAPI,
16+
}
17+
18+
19+
def get_api(site_name: str) -> BaseStreamingAPI:
20+
"""
21+
Get API instance for a specific site.
22+
23+
Args:
24+
site_name: Name of the streaming site
25+
26+
Returns:
27+
Instance of the appropriate API class
28+
"""
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()
39+
40+
41+
def get_available_sites() -> list:
42+
"""
43+
Get list of available streaming sites.
44+
45+
Returns:
46+
List of site names
47+
"""
48+
return list(_API_REGISTRY.keys())
49+
50+
51+
def register_api(site_name: str, api_class: Type[BaseStreamingAPI]):
52+
"""
53+
Register a new API class.
54+
55+
Args:
56+
site_name: Name of the site
57+
api_class: API class that inherits from BaseStreamingAPI
58+
"""
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
63+
64+
65+
__all__ = [
66+
'BaseStreamingAPI',
67+
'StreamingCommunityAPI',
68+
'AnimeUnityAPI',
69+
'get_api',
70+
'get_available_sites',
71+
'register_api'
72+
]

GUI/searchapp/api/animeunity.py

Lines changed: 142 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,142 @@
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.config_json import config_manager
14+
from StreamingCommunity.Api.Site.animeunity.util.ScrapeSerie import ScrapeSerieAnime
15+
16+
17+
18+
class AnimeUnityAPI(BaseStreamingAPI):
19+
def __init__(self):
20+
super().__init__()
21+
self.site_name = "animeunity"
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("animeunity", "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("StreamingCommunity.Api.Site.animeunity")
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 AnimeUnity.
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+
id=item_dict.get('id'),
57+
title=item_dict.get('name'),
58+
slug=item_dict.get('slug', ''),
59+
type=item_dict.get('type'),
60+
url=item_dict.get('url'),
61+
poster=item_dict.get('image'),
62+
raw_data=item_dict
63+
)
64+
results.append(media_item)
65+
66+
return results
67+
68+
except Exception as e:
69+
raise Exception(f"AnimeUnity search error: {e}")
70+
71+
def get_series_metadata(self, media_item: MediaItem) -> Optional[List[Season]]:
72+
"""
73+
Get seasons and episodes for an AnimeUnity series.
74+
Note: AnimeUnity typically has single season anime.
75+
76+
Args:
77+
media_item: MediaItem to get metadata for
78+
79+
Returns:
80+
List of Season objects (usually one season), or None if not a series
81+
"""
82+
# Check if it's a movie or OVA
83+
if media_item.is_movie:
84+
return None
85+
86+
try:
87+
scraper = ScrapeSerieAnime(self.base_url)
88+
scraper.setup(series_name=media_item.slug, media_id=media_item.id)
89+
90+
episodes_count = scraper.get_count_episodes()
91+
if not episodes_count:
92+
return None
93+
94+
# AnimeUnity typically has single season
95+
episodes = []
96+
for ep_num in range(1, episodes_count + 1):
97+
episode = Episode(
98+
number=ep_num,
99+
name=f"Episodio {ep_num}",
100+
id=ep_num
101+
)
102+
episodes.append(episode)
103+
104+
season = Season(number=1, episodes=episodes)
105+
return [season]
106+
107+
except Exception as e:
108+
raise Exception(f"Error getting series metadata: {e}")
109+
110+
def start_download(self, media_item: MediaItem, season: Optional[str] = None, episodes: Optional[str] = None) -> bool:
111+
"""
112+
Start downloading from AnimeUnity.
113+
114+
Args:
115+
media_item: MediaItem to download
116+
season: Season number (typically 1 for anime)
117+
episodes: Episode selection
118+
119+
Returns:
120+
True if download started successfully
121+
"""
122+
try:
123+
search_fn = self._get_search_fn()
124+
125+
# Prepare direct_item from MediaItem
126+
direct_item = media_item.raw_data or media_item.to_dict()
127+
128+
# For AnimeUnity, we only use episode selection
129+
selections = None
130+
if episodes:
131+
selections = {'episode': episodes}
132+
133+
elif not media_item.is_movie:
134+
# Default: download all episodes
135+
selections = {'episode': '*'}
136+
137+
# Execute download
138+
search_fn(direct_item=direct_item, selections=selections)
139+
return True
140+
141+
except Exception as e:
142+
raise Exception(f"Download error: {e}")

0 commit comments

Comments
 (0)