StreamingCommunity 3.2.0__tar.gz → 3.2.5__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of StreamingCommunity might be problematic. Click here for more details.
- {streamingcommunity-3.2.0/StreamingCommunity.egg-info → streamingcommunity-3.2.5}/PKG-INFO +4 -2
- {streamingcommunity-3.2.0 → streamingcommunity-3.2.5}/README.md +2 -0
- {streamingcommunity-3.2.0 → streamingcommunity-3.2.5}/StreamingCommunity/Api/Player/Helper/Vixcloud/util.py +4 -0
- {streamingcommunity-3.2.0 → streamingcommunity-3.2.5}/StreamingCommunity/Api/Player/hdplayer.py +2 -2
- {streamingcommunity-3.2.0 → streamingcommunity-3.2.5}/StreamingCommunity/Api/Player/mixdrop.py +1 -1
- {streamingcommunity-3.2.0 → streamingcommunity-3.2.5}/StreamingCommunity/Api/Player/vixcloud.py +4 -5
- {streamingcommunity-3.2.0 → streamingcommunity-3.2.5}/StreamingCommunity/Api/Site/animeunity/__init__.py +2 -2
- streamingcommunity-3.2.5/StreamingCommunity/Api/Site/crunchyroll/__init__.py +103 -0
- streamingcommunity-3.2.5/StreamingCommunity/Api/Site/crunchyroll/film.py +83 -0
- streamingcommunity-3.2.5/StreamingCommunity/Api/Site/crunchyroll/series.py +182 -0
- streamingcommunity-3.2.5/StreamingCommunity/Api/Site/crunchyroll/site.py +113 -0
- streamingcommunity-3.2.5/StreamingCommunity/Api/Site/crunchyroll/util/ScrapeSerie.py +218 -0
- streamingcommunity-3.2.5/StreamingCommunity/Api/Site/crunchyroll/util/get_license.py +227 -0
- {streamingcommunity-3.2.0 → streamingcommunity-3.2.5}/StreamingCommunity/Api/Site/guardaserie/site.py +1 -2
- {streamingcommunity-3.2.0 → streamingcommunity-3.2.5}/StreamingCommunity/Api/Site/guardaserie/util/ScrapeSerie.py +9 -8
- streamingcommunity-3.2.5/StreamingCommunity/Api/Site/mediasetinfinity/__init__.py +96 -0
- streamingcommunity-3.2.5/StreamingCommunity/Api/Site/mediasetinfinity/film.py +76 -0
- streamingcommunity-3.2.5/StreamingCommunity/Api/Site/mediasetinfinity/series.py +177 -0
- streamingcommunity-3.2.5/StreamingCommunity/Api/Site/mediasetinfinity/site.py +112 -0
- streamingcommunity-3.2.5/StreamingCommunity/Api/Site/mediasetinfinity/util/ScrapeSerie.py +259 -0
- streamingcommunity-3.2.5/StreamingCommunity/Api/Site/mediasetinfinity/util/fix_mpd.py +64 -0
- streamingcommunity-3.2.5/StreamingCommunity/Api/Site/mediasetinfinity/util/get_license.py +217 -0
- {streamingcommunity-3.2.0 → streamingcommunity-3.2.5}/StreamingCommunity/Api/Site/streamingcommunity/__init__.py +6 -17
- {streamingcommunity-3.2.0 → streamingcommunity-3.2.5}/StreamingCommunity/Api/Site/streamingcommunity/film.py +2 -2
- {streamingcommunity-3.2.0 → streamingcommunity-3.2.5}/StreamingCommunity/Api/Site/streamingcommunity/series.py +9 -9
- {streamingcommunity-3.2.0 → streamingcommunity-3.2.5}/StreamingCommunity/Api/Site/streamingcommunity/site.py +3 -4
- {streamingcommunity-3.2.0 → streamingcommunity-3.2.5}/StreamingCommunity/Api/Site/streamingcommunity/util/ScrapeSerie.py +3 -6
- {streamingcommunity-3.2.0 → streamingcommunity-3.2.5}/StreamingCommunity/Api/Site/streamingwatch/__init__.py +6 -14
- {streamingcommunity-3.2.0 → streamingcommunity-3.2.5}/StreamingCommunity/Api/Site/streamingwatch/film.py +2 -2
- {streamingcommunity-3.2.0 → streamingcommunity-3.2.5}/StreamingCommunity/Api/Site/streamingwatch/series.py +9 -9
- {streamingcommunity-3.2.0 → streamingcommunity-3.2.5}/StreamingCommunity/Api/Site/streamingwatch/site.py +5 -7
- {streamingcommunity-3.2.0 → streamingcommunity-3.2.5}/StreamingCommunity/Api/Site/streamingwatch/util/ScrapeSerie.py +2 -2
- streamingcommunity-3.2.5/StreamingCommunity/Lib/Downloader/DASH/cdm_helpher.py +131 -0
- streamingcommunity-3.2.5/StreamingCommunity/Lib/Downloader/DASH/decrypt.py +79 -0
- streamingcommunity-3.2.5/StreamingCommunity/Lib/Downloader/DASH/downloader.py +220 -0
- streamingcommunity-3.2.5/StreamingCommunity/Lib/Downloader/DASH/parser.py +249 -0
- streamingcommunity-3.2.5/StreamingCommunity/Lib/Downloader/DASH/segments.py +332 -0
- {streamingcommunity-3.2.0 → streamingcommunity-3.2.5}/StreamingCommunity/Lib/Downloader/HLS/downloader.py +1 -14
- {streamingcommunity-3.2.0 → streamingcommunity-3.2.5}/StreamingCommunity/Lib/Downloader/HLS/segments.py +3 -3
- {streamingcommunity-3.2.0 → streamingcommunity-3.2.5}/StreamingCommunity/Lib/Downloader/MP4/downloader.py +0 -5
- {streamingcommunity-3.2.0 → streamingcommunity-3.2.5}/StreamingCommunity/Lib/FFmpeg/capture.py +3 -3
- {streamingcommunity-3.2.0 → streamingcommunity-3.2.5}/StreamingCommunity/Lib/FFmpeg/command.py +1 -1
- {streamingcommunity-3.2.0 → streamingcommunity-3.2.5}/StreamingCommunity/TelegramHelp/config.json +3 -5
- {streamingcommunity-3.2.0 → streamingcommunity-3.2.5}/StreamingCommunity/Upload/version.py +2 -2
- {streamingcommunity-3.2.0 → streamingcommunity-3.2.5}/StreamingCommunity/Util/os.py +21 -0
- {streamingcommunity-3.2.0 → streamingcommunity-3.2.5}/StreamingCommunity/run.py +1 -1
- {streamingcommunity-3.2.0 → streamingcommunity-3.2.5/StreamingCommunity.egg-info}/PKG-INFO +4 -2
- {streamingcommunity-3.2.0 → streamingcommunity-3.2.5}/StreamingCommunity.egg-info/SOURCES.txt +18 -4
- {streamingcommunity-3.2.0 → streamingcommunity-3.2.5}/StreamingCommunity.egg-info/requires.txt +1 -1
- {streamingcommunity-3.2.0 → streamingcommunity-3.2.5}/requirements.txt +1 -1
- streamingcommunity-3.2.0/StreamingCommunity/Api/Site/1337xx/__init__.py +0 -72
- streamingcommunity-3.2.0/StreamingCommunity/Api/Site/1337xx/site.py +0 -82
- streamingcommunity-3.2.0/StreamingCommunity/Api/Site/1337xx/title.py +0 -61
- streamingcommunity-3.2.0/StreamingCommunity/Lib/Proxies/proxy.py +0 -72
- {streamingcommunity-3.2.0 → streamingcommunity-3.2.5}/LICENSE +0 -0
- {streamingcommunity-3.2.0 → streamingcommunity-3.2.5}/MANIFEST.in +0 -0
- {streamingcommunity-3.2.0 → streamingcommunity-3.2.5}/StreamingCommunity/Api/Player/Helper/Vixcloud/js_parser.py +0 -0
- {streamingcommunity-3.2.0 → streamingcommunity-3.2.5}/StreamingCommunity/Api/Player/ddl.py +0 -0
- {streamingcommunity-3.2.0 → streamingcommunity-3.2.5}/StreamingCommunity/Api/Player/maxstream.py +0 -0
- {streamingcommunity-3.2.0 → streamingcommunity-3.2.5}/StreamingCommunity/Api/Player/mediapolisvod.py +0 -0
- {streamingcommunity-3.2.0 → streamingcommunity-3.2.5}/StreamingCommunity/Api/Player/supervideo.py +0 -0
- {streamingcommunity-3.2.0 → streamingcommunity-3.2.5}/StreamingCommunity/Api/Player/sweetpixel.py +0 -0
- {streamingcommunity-3.2.0 → streamingcommunity-3.2.5}/StreamingCommunity/Api/Site/altadefinizione/__init__.py +0 -0
- {streamingcommunity-3.2.0 → streamingcommunity-3.2.5}/StreamingCommunity/Api/Site/altadefinizione/film.py +0 -0
- {streamingcommunity-3.2.0 → streamingcommunity-3.2.5}/StreamingCommunity/Api/Site/altadefinizione/series.py +0 -0
- {streamingcommunity-3.2.0 → streamingcommunity-3.2.5}/StreamingCommunity/Api/Site/altadefinizione/site.py +0 -0
- {streamingcommunity-3.2.0 → streamingcommunity-3.2.5}/StreamingCommunity/Api/Site/altadefinizione/util/ScrapeSerie.py +0 -0
- {streamingcommunity-3.2.0 → streamingcommunity-3.2.5}/StreamingCommunity/Api/Site/animeunity/film.py +0 -0
- {streamingcommunity-3.2.0 → streamingcommunity-3.2.5}/StreamingCommunity/Api/Site/animeunity/serie.py +0 -0
- {streamingcommunity-3.2.0 → streamingcommunity-3.2.5}/StreamingCommunity/Api/Site/animeunity/site.py +0 -0
- {streamingcommunity-3.2.0 → streamingcommunity-3.2.5}/StreamingCommunity/Api/Site/animeunity/util/ScrapeSerie.py +0 -0
- {streamingcommunity-3.2.0 → streamingcommunity-3.2.5}/StreamingCommunity/Api/Site/animeworld/__init__.py +0 -0
- {streamingcommunity-3.2.0 → streamingcommunity-3.2.5}/StreamingCommunity/Api/Site/animeworld/film.py +0 -0
- {streamingcommunity-3.2.0 → streamingcommunity-3.2.5}/StreamingCommunity/Api/Site/animeworld/serie.py +0 -0
- {streamingcommunity-3.2.0 → streamingcommunity-3.2.5}/StreamingCommunity/Api/Site/animeworld/site.py +0 -0
- {streamingcommunity-3.2.0 → streamingcommunity-3.2.5}/StreamingCommunity/Api/Site/animeworld/util/ScrapeSerie.py +0 -0
- {streamingcommunity-3.2.0 → streamingcommunity-3.2.5}/StreamingCommunity/Api/Site/cb01new/__init__.py +0 -0
- {streamingcommunity-3.2.0 → streamingcommunity-3.2.5}/StreamingCommunity/Api/Site/cb01new/film.py +0 -0
- {streamingcommunity-3.2.0 → streamingcommunity-3.2.5}/StreamingCommunity/Api/Site/cb01new/site.py +0 -0
- {streamingcommunity-3.2.0 → streamingcommunity-3.2.5}/StreamingCommunity/Api/Site/guardaserie/__init__.py +0 -0
- {streamingcommunity-3.2.0 → streamingcommunity-3.2.5}/StreamingCommunity/Api/Site/guardaserie/series.py +0 -0
- {streamingcommunity-3.2.0 → streamingcommunity-3.2.5}/StreamingCommunity/Api/Site/raiplay/__init__.py +0 -0
- {streamingcommunity-3.2.0 → streamingcommunity-3.2.5}/StreamingCommunity/Api/Site/raiplay/film.py +0 -0
- {streamingcommunity-3.2.0 → streamingcommunity-3.2.5}/StreamingCommunity/Api/Site/raiplay/series.py +0 -0
- {streamingcommunity-3.2.0 → streamingcommunity-3.2.5}/StreamingCommunity/Api/Site/raiplay/site.py +0 -0
- {streamingcommunity-3.2.0 → streamingcommunity-3.2.5}/StreamingCommunity/Api/Site/raiplay/util/ScrapeSerie.py +0 -0
- {streamingcommunity-3.2.0 → streamingcommunity-3.2.5}/StreamingCommunity/Api/Template/Class/SearchType.py +0 -0
- {streamingcommunity-3.2.0 → streamingcommunity-3.2.5}/StreamingCommunity/Api/Template/Util/__init__.py +0 -0
- {streamingcommunity-3.2.0 → streamingcommunity-3.2.5}/StreamingCommunity/Api/Template/Util/manage_ep.py +0 -0
- {streamingcommunity-3.2.0 → streamingcommunity-3.2.5}/StreamingCommunity/Api/Template/__init__.py +0 -0
- {streamingcommunity-3.2.0 → streamingcommunity-3.2.5}/StreamingCommunity/Api/Template/config_loader.py +0 -0
- {streamingcommunity-3.2.0 → streamingcommunity-3.2.5}/StreamingCommunity/Api/Template/site.py +0 -0
- {streamingcommunity-3.2.0 → streamingcommunity-3.2.5}/StreamingCommunity/Lib/Downloader/TOR/downloader.py +0 -0
- {streamingcommunity-3.2.0 → streamingcommunity-3.2.5}/StreamingCommunity/Lib/Downloader/__init__.py +0 -0
- {streamingcommunity-3.2.0 → streamingcommunity-3.2.5}/StreamingCommunity/Lib/FFmpeg/__init__.py +0 -0
- {streamingcommunity-3.2.0 → streamingcommunity-3.2.5}/StreamingCommunity/Lib/FFmpeg/util.py +0 -0
- {streamingcommunity-3.2.0 → streamingcommunity-3.2.5}/StreamingCommunity/Lib/M3U8/__init__.py +0 -0
- {streamingcommunity-3.2.0 → streamingcommunity-3.2.5}/StreamingCommunity/Lib/M3U8/decryptor.py +0 -0
- {streamingcommunity-3.2.0 → streamingcommunity-3.2.5}/StreamingCommunity/Lib/M3U8/estimator.py +0 -0
- {streamingcommunity-3.2.0 → streamingcommunity-3.2.5}/StreamingCommunity/Lib/M3U8/parser.py +0 -0
- {streamingcommunity-3.2.0 → streamingcommunity-3.2.5}/StreamingCommunity/Lib/M3U8/url_fixer.py +0 -0
- {streamingcommunity-3.2.0 → streamingcommunity-3.2.5}/StreamingCommunity/Lib/TMBD/__init__.py +0 -0
- {streamingcommunity-3.2.0 → streamingcommunity-3.2.5}/StreamingCommunity/Lib/TMBD/obj_tmbd.py +0 -0
- {streamingcommunity-3.2.0 → streamingcommunity-3.2.5}/StreamingCommunity/Lib/TMBD/tmdb.py +0 -0
- {streamingcommunity-3.2.0 → streamingcommunity-3.2.5}/StreamingCommunity/TelegramHelp/__init__.py +0 -0
- {streamingcommunity-3.2.0 → streamingcommunity-3.2.5}/StreamingCommunity/TelegramHelp/telegram_bot.py +0 -0
- {streamingcommunity-3.2.0 → streamingcommunity-3.2.5}/StreamingCommunity/Upload/update.py +0 -0
- {streamingcommunity-3.2.0 → streamingcommunity-3.2.5}/StreamingCommunity/Util/color.py +0 -0
- {streamingcommunity-3.2.0 → streamingcommunity-3.2.5}/StreamingCommunity/Util/config_json.py +0 -0
- {streamingcommunity-3.2.0 → streamingcommunity-3.2.5}/StreamingCommunity/Util/ffmpeg_installer.py +0 -0
- {streamingcommunity-3.2.0 → streamingcommunity-3.2.5}/StreamingCommunity/Util/headers.py +0 -0
- {streamingcommunity-3.2.0 → streamingcommunity-3.2.5}/StreamingCommunity/Util/logger.py +0 -0
- {streamingcommunity-3.2.0 → streamingcommunity-3.2.5}/StreamingCommunity/Util/message.py +0 -0
- {streamingcommunity-3.2.0 → streamingcommunity-3.2.5}/StreamingCommunity/Util/table.py +0 -0
- {streamingcommunity-3.2.0 → streamingcommunity-3.2.5}/StreamingCommunity/__init__.py +0 -0
- {streamingcommunity-3.2.0 → streamingcommunity-3.2.5}/StreamingCommunity/global_search.py +0 -0
- {streamingcommunity-3.2.0 → streamingcommunity-3.2.5}/StreamingCommunity.egg-info/dependency_links.txt +0 -0
- {streamingcommunity-3.2.0 → streamingcommunity-3.2.5}/StreamingCommunity.egg-info/entry_points.txt +0 -0
- {streamingcommunity-3.2.0 → streamingcommunity-3.2.5}/StreamingCommunity.egg-info/top_level.txt +0 -0
- {streamingcommunity-3.2.0 → streamingcommunity-3.2.5}/setup.cfg +0 -0
- {streamingcommunity-3.2.0 → streamingcommunity-3.2.5}/setup.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: StreamingCommunity
|
|
3
|
-
Version: 3.2.
|
|
3
|
+
Version: 3.2.5
|
|
4
4
|
Home-page: https://github.com/Lovi-0/StreamingCommunity
|
|
5
5
|
Author: Lovi-0
|
|
6
6
|
Project-URL: Bug Reports, https://github.com/Lovi-0/StreamingCommunity/issues
|
|
@@ -25,7 +25,7 @@ Requires-Dist: pycryptodomex
|
|
|
25
25
|
Requires-Dist: ua-generator
|
|
26
26
|
Requires-Dist: qbittorrent-api
|
|
27
27
|
Requires-Dist: pyTelegramBotAPI
|
|
28
|
-
Requires-Dist:
|
|
28
|
+
Requires-Dist: pywidevine
|
|
29
29
|
Dynamic: author
|
|
30
30
|
Dynamic: description
|
|
31
31
|
Dynamic: description-content-type
|
|
@@ -839,3 +839,5 @@ API non ufficiale per accedere ai contenuti del sito italiano StreamingCommunity
|
|
|
839
839
|
# Disclaimer
|
|
840
840
|
|
|
841
841
|
This software is provided "as is", without warranty of any kind, express or implied, including but not limited to the warranties of merchantability, fitness for a particular purpose, and noninfringement. In no event shall the authors or copyright holders be liable for any claim, damages, or other liability, whether in an action of contract, tort, or otherwise, arising from, out of, or in connection with the software or the use or other dealings in the software.
|
|
842
|
+
|
|
843
|
+
> **Note:** DASH downloads require a valid L3 CDM (Content Decryption Module) to proceed. This project does not provide, include, or facilitate obtaining any CDM. Users are responsible for ensuring compliance with all applicable laws and requirements regarding DRM and decryption modules.
|
|
@@ -801,3 +801,5 @@ API non ufficiale per accedere ai contenuti del sito italiano StreamingCommunity
|
|
|
801
801
|
# Disclaimer
|
|
802
802
|
|
|
803
803
|
This software is provided "as is", without warranty of any kind, express or implied, including but not limited to the warranties of merchantability, fitness for a particular purpose, and noninfringement. In no event shall the authors or copyright holders be liable for any claim, damages, or other liability, whether in an action of contract, tort, or otherwise, arising from, out of, or in connection with the software or the use or other dealings in the software.
|
|
804
|
+
|
|
805
|
+
> **Note:** DASH downloads require a valid L3 CDM (Content Decryption Module) to proceed. This project does not provide, include, or facilitate obtaining any CDM. Users are responsible for ensuring compliance with all applicable laws and requirements regarding DRM and decryption modules.
|
|
@@ -90,9 +90,13 @@ class SeasonManager:
|
|
|
90
90
|
Parameters:
|
|
91
91
|
- number (int): The season number (1-based index)
|
|
92
92
|
"""
|
|
93
|
+
if len(self.seasons) == 1:
|
|
94
|
+
return self.seasons[0]
|
|
95
|
+
|
|
93
96
|
for season in self.seasons:
|
|
94
97
|
if season.number == number:
|
|
95
98
|
return season
|
|
99
|
+
|
|
96
100
|
return None
|
|
97
101
|
|
|
98
102
|
def __len__(self) -> int:
|
{streamingcommunity-3.2.0 → streamingcommunity-3.2.5}/StreamingCommunity/Api/Player/hdplayer.py
RENAMED
|
@@ -18,8 +18,8 @@ REQUEST_VERIFY = config_manager.get_bool('REQUESTS', 'verify')
|
|
|
18
18
|
|
|
19
19
|
|
|
20
20
|
class VideoSource:
|
|
21
|
-
def __init__(self
|
|
22
|
-
self.client = httpx.Client(headers={'user-agent': get_userAgent()}, timeout=MAX_TIMEOUT,
|
|
21
|
+
def __init__(self):
|
|
22
|
+
self.client = httpx.Client(headers={'user-agent': get_userAgent()}, timeout=MAX_TIMEOUT, verify=REQUEST_VERIFY)
|
|
23
23
|
|
|
24
24
|
def extractLinkHdPlayer(self, response):
|
|
25
25
|
"""Extract iframe source from the page."""
|
{streamingcommunity-3.2.0 → streamingcommunity-3.2.5}/StreamingCommunity/Api/Player/vixcloud.py
RENAMED
|
@@ -25,7 +25,7 @@ console = Console()
|
|
|
25
25
|
|
|
26
26
|
|
|
27
27
|
class VideoSource:
|
|
28
|
-
def __init__(self, url: str, is_series: bool, media_id: int = None
|
|
28
|
+
def __init__(self, url: str, is_series: bool, media_id: int = None):
|
|
29
29
|
"""
|
|
30
30
|
Initialize video source for streaming site.
|
|
31
31
|
|
|
@@ -36,7 +36,6 @@ class VideoSource:
|
|
|
36
36
|
"""
|
|
37
37
|
self.headers = {'user-agent': get_userAgent()}
|
|
38
38
|
self.url = url
|
|
39
|
-
self.proxy = proxy
|
|
40
39
|
self.is_series = is_series
|
|
41
40
|
self.media_id = media_id
|
|
42
41
|
self.iframe_src = None
|
|
@@ -58,7 +57,7 @@ class VideoSource:
|
|
|
58
57
|
}
|
|
59
58
|
|
|
60
59
|
try:
|
|
61
|
-
response = httpx.get(f"{self.url}/iframe/{self.media_id}", headers=self.headers, params=params, timeout=MAX_TIMEOUT,
|
|
60
|
+
response = httpx.get(f"{self.url}/iframe/{self.media_id}", headers=self.headers, params=params, timeout=MAX_TIMEOUT, verify=REQUEST_VERIFY)
|
|
62
61
|
response.raise_for_status()
|
|
63
62
|
|
|
64
63
|
# Parse response with BeautifulSoup to get iframe source
|
|
@@ -123,12 +122,12 @@ class VideoSource:
|
|
|
123
122
|
logging.error(f"Error getting content: {e}")
|
|
124
123
|
raise
|
|
125
124
|
|
|
126
|
-
def get_playlist(self) -> str
|
|
125
|
+
def get_playlist(self) -> str:
|
|
127
126
|
"""
|
|
128
127
|
Generate authenticated playlist URL.
|
|
129
128
|
|
|
130
129
|
Returns:
|
|
131
|
-
str
|
|
130
|
+
str: Fully constructed playlist URL with authentication parameters, or None if content unavailable
|
|
132
131
|
"""
|
|
133
132
|
if not self.window_parameter:
|
|
134
133
|
return None
|
|
@@ -66,7 +66,7 @@ def process_search_result(select_title, selections=None):
|
|
|
66
66
|
selections (dict, optional): Dictionary containing selection inputs that bypass manual input
|
|
67
67
|
{'season': season_selection, 'episode': episode_selection}
|
|
68
68
|
"""
|
|
69
|
-
if select_title.type == 'Movie'
|
|
69
|
+
if select_title.type == 'Movie':
|
|
70
70
|
download_film(select_title)
|
|
71
71
|
|
|
72
72
|
else:
|
|
@@ -120,4 +120,4 @@ def search(string_to_search: str = None, get_onlyDatabase: bool = False, direct_
|
|
|
120
120
|
|
|
121
121
|
# If no results are found, ask again
|
|
122
122
|
string_to_search = get_user_input()
|
|
123
|
-
search(string_to_search, get_onlyDatabase, None, selections)
|
|
123
|
+
search(string_to_search, get_onlyDatabase, None, selections)
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
# 16.03.25
|
|
2
|
+
|
|
3
|
+
import sys
|
|
4
|
+
import subprocess
|
|
5
|
+
from urllib.parse import quote_plus
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
# External library
|
|
9
|
+
from rich.console import Console
|
|
10
|
+
from rich.prompt import Prompt
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
# Internal utilities
|
|
14
|
+
from StreamingCommunity.Api.Template import get_select_title
|
|
15
|
+
from StreamingCommunity.Api.Template.config_loader import site_constant
|
|
16
|
+
from StreamingCommunity.Api.Template.Class.SearchType import MediaItem
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
# Logic class
|
|
20
|
+
from .site import title_search, table_show_manager, media_search_manager
|
|
21
|
+
from .film import download_film
|
|
22
|
+
from .series import download_series
|
|
23
|
+
|
|
24
|
+
# Variable
|
|
25
|
+
indice = 8
|
|
26
|
+
_useFor = "Anime"
|
|
27
|
+
_priority = 0
|
|
28
|
+
_engineDownload = "hls"
|
|
29
|
+
_deprecate = False
|
|
30
|
+
|
|
31
|
+
msg = Prompt()
|
|
32
|
+
console = Console()
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
def get_user_input(string_to_search: str = None):
|
|
36
|
+
"""
|
|
37
|
+
Asks the user to input a search term.
|
|
38
|
+
Handles both Telegram bot input and direct input.
|
|
39
|
+
"""
|
|
40
|
+
if string_to_search is None:
|
|
41
|
+
string_to_search = msg.ask(f"\n[purple]Insert a word to search in [green]{site_constant.SITE_NAME}").strip()
|
|
42
|
+
|
|
43
|
+
return string_to_search
|
|
44
|
+
|
|
45
|
+
def process_search_result(select_title, selections=None):
|
|
46
|
+
"""
|
|
47
|
+
Handles the search result and initiates the download for either a film or series.
|
|
48
|
+
|
|
49
|
+
Parameters:
|
|
50
|
+
select_title (MediaItem): The selected media item
|
|
51
|
+
selections (dict, optional): Dictionary containing selection inputs that bypass manual input
|
|
52
|
+
{'season': season_selection, 'episode': episode_selection}
|
|
53
|
+
"""
|
|
54
|
+
if select_title.type == 'tv':
|
|
55
|
+
season_selection = None
|
|
56
|
+
episode_selection = None
|
|
57
|
+
|
|
58
|
+
if selections:
|
|
59
|
+
season_selection = selections.get('season')
|
|
60
|
+
episode_selection = selections.get('episode')
|
|
61
|
+
|
|
62
|
+
download_series(select_title, season_selection, episode_selection)
|
|
63
|
+
|
|
64
|
+
else:
|
|
65
|
+
download_film(select_title)
|
|
66
|
+
|
|
67
|
+
# search("Game of Thrones", selections={"season": "1", "episode": "1-3"})
|
|
68
|
+
def search(string_to_search: str = None, get_onlyDatabase: bool = False, direct_item: dict = None, selections: dict = None):
|
|
69
|
+
"""
|
|
70
|
+
Main function of the application for search.
|
|
71
|
+
|
|
72
|
+
Parameters:
|
|
73
|
+
string_to_search (str, optional): String to search for
|
|
74
|
+
get_onylDatabase (bool, optional): If True, return only the database object
|
|
75
|
+
direct_item (dict, optional): Direct item to process (bypass search)
|
|
76
|
+
selections (dict, optional): Dictionary containing selection inputs that bypass manual input
|
|
77
|
+
{'season': season_selection, 'episode': episode_selection}
|
|
78
|
+
"""
|
|
79
|
+
if direct_item:
|
|
80
|
+
select_title = MediaItem(**direct_item)
|
|
81
|
+
process_search_result(select_title, selections)
|
|
82
|
+
return
|
|
83
|
+
|
|
84
|
+
# Get the user input for the search term
|
|
85
|
+
string_to_search = get_user_input(string_to_search)
|
|
86
|
+
|
|
87
|
+
# Perform the database search
|
|
88
|
+
len_database = title_search(quote_plus(string_to_search))
|
|
89
|
+
|
|
90
|
+
# If only the database is needed, return the manager
|
|
91
|
+
if get_onlyDatabase:
|
|
92
|
+
return media_search_manager
|
|
93
|
+
|
|
94
|
+
if len_database > 0:
|
|
95
|
+
select_title = get_select_title(table_show_manager, media_search_manager, len_database)
|
|
96
|
+
process_search_result(select_title, selections)
|
|
97
|
+
|
|
98
|
+
else:
|
|
99
|
+
console.print(f"\n[red]Nothing matching was found for[white]: [purple]{string_to_search}")
|
|
100
|
+
|
|
101
|
+
# If no results are found, ask again
|
|
102
|
+
string_to_search = get_user_input()
|
|
103
|
+
search(string_to_search, get_onlyDatabase, None, selections)
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
# 16.03.25
|
|
2
|
+
|
|
3
|
+
import os
|
|
4
|
+
from urllib.parse import urlparse, parse_qs
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
# External library
|
|
8
|
+
from rich.console import Console
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
# Internal utilities
|
|
12
|
+
from StreamingCommunity.Util.os import os_manager
|
|
13
|
+
from StreamingCommunity.Util.message import start_message
|
|
14
|
+
from StreamingCommunity.Util.config_json import config_manager
|
|
15
|
+
from StreamingCommunity.Util.os import get_wvd_path
|
|
16
|
+
from StreamingCommunity.Lib.Downloader.DASH.downloader import DASH_Download
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
# Logic class
|
|
20
|
+
from StreamingCommunity.Api.Template.config_loader import site_constant
|
|
21
|
+
from StreamingCommunity.Api.Template.Class.SearchType import MediaItem
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
# Player
|
|
25
|
+
from .util.get_license import get_playback_session, get_auth_token, generate_device_id
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
# Variable
|
|
29
|
+
console = Console()
|
|
30
|
+
max_timeout = config_manager.get_int("REQUESTS", "timeout")
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
def download_film(select_title: MediaItem) -> str:
|
|
34
|
+
"""
|
|
35
|
+
Downloads a film using the provided film ID, title name, and domain.
|
|
36
|
+
|
|
37
|
+
Parameters:
|
|
38
|
+
- select_title (MediaItem): The selected media item.
|
|
39
|
+
|
|
40
|
+
Return:
|
|
41
|
+
- str: output path if successful, otherwise None
|
|
42
|
+
"""
|
|
43
|
+
start_message()
|
|
44
|
+
console.print(f"[bold yellow]Download:[/bold yellow] [red]{site_constant.SITE_NAME}[/red] → [cyan]{select_title.name}[/cyan] \n")
|
|
45
|
+
|
|
46
|
+
# Define filename and path for the downloaded video
|
|
47
|
+
mp4_name = os_manager.get_sanitize_file(select_title.name) + ".mp4"
|
|
48
|
+
mp4_path = os.path.join(site_constant.MOVIE_FOLDER, mp4_name.replace(".mp4", ""))
|
|
49
|
+
|
|
50
|
+
# Generate mpd and license URLs
|
|
51
|
+
url_id = select_title.get('url').split('/')[-1]
|
|
52
|
+
device_id = generate_device_id()
|
|
53
|
+
mpd_url, mpd_headers = get_playback_session(get_auth_token(device_id), device_id, url_id)
|
|
54
|
+
parsed_url = urlparse(mpd_url)
|
|
55
|
+
query_params = parse_qs(parsed_url.query)
|
|
56
|
+
|
|
57
|
+
# Download the episode
|
|
58
|
+
r_proc = DASH_Download(
|
|
59
|
+
cdm_device=get_wvd_path(),
|
|
60
|
+
license_url='https://www.crunchyroll.com/license/v1/license/widevine',
|
|
61
|
+
mpd_url=mpd_url,
|
|
62
|
+
output_path=os.path.join(mp4_path, mp4_name),
|
|
63
|
+
)
|
|
64
|
+
r_proc.parse_manifest(custom_headers=mpd_headers)
|
|
65
|
+
|
|
66
|
+
# Create headers for license request
|
|
67
|
+
license_headers = mpd_headers.copy()
|
|
68
|
+
license_headers.update({
|
|
69
|
+
"x-cr-content-id": url_id,
|
|
70
|
+
"x-cr-video-token": query_params['playbackGuid'][0],
|
|
71
|
+
})
|
|
72
|
+
|
|
73
|
+
if r_proc.download_and_decrypt(custom_headers=license_headers):
|
|
74
|
+
r_proc.finalize_output()
|
|
75
|
+
|
|
76
|
+
# Get final output path and status
|
|
77
|
+
status = r_proc.get_status()
|
|
78
|
+
|
|
79
|
+
if status['error'] is not None and status['path']:
|
|
80
|
+
try: os.remove(status['path'])
|
|
81
|
+
except Exception: pass
|
|
82
|
+
|
|
83
|
+
return status['path'], status['stopped']
|
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
# 16.03.25
|
|
2
|
+
|
|
3
|
+
import os
|
|
4
|
+
from typing import Tuple
|
|
5
|
+
from urllib.parse import urlparse, parse_qs
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
# External library
|
|
9
|
+
from rich.console import Console
|
|
10
|
+
from rich.prompt import Prompt
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
# Internal utilities
|
|
14
|
+
from StreamingCommunity.Util.message import start_message
|
|
15
|
+
from StreamingCommunity.Util.os import os_manager
|
|
16
|
+
from StreamingCommunity.Util.os import get_wvd_path
|
|
17
|
+
from StreamingCommunity.Lib.Downloader.DASH.downloader import DASH_Download
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
# Logic class
|
|
21
|
+
from .util.ScrapeSerie import GetSerieInfo
|
|
22
|
+
from StreamingCommunity.Api.Template.Util import (
|
|
23
|
+
manage_selection,
|
|
24
|
+
map_episode_title,
|
|
25
|
+
validate_selection,
|
|
26
|
+
validate_episode_selection,
|
|
27
|
+
display_episodes_list
|
|
28
|
+
)
|
|
29
|
+
from StreamingCommunity.Api.Template.config_loader import site_constant
|
|
30
|
+
from StreamingCommunity.Api.Template.Class.SearchType import MediaItem
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
# Player
|
|
34
|
+
from .util.get_license import get_playback_session, get_auth_token, generate_device_id
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
# Variable
|
|
38
|
+
msg = Prompt()
|
|
39
|
+
console = Console()
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
def download_video(index_season_selected: int, index_episode_selected: int, scrape_serie: GetSerieInfo) -> Tuple[str,bool]:
|
|
43
|
+
"""
|
|
44
|
+
Downloads a specific episode from a specified season.
|
|
45
|
+
|
|
46
|
+
Parameters:
|
|
47
|
+
- index_season_selected (int): Season number
|
|
48
|
+
- index_episode_selected (int): Episode index
|
|
49
|
+
- scrape_serie (GetSerieInfo): Scraper object with series information
|
|
50
|
+
|
|
51
|
+
Returns:
|
|
52
|
+
- str: Path to downloaded file
|
|
53
|
+
- bool: Whether download was stopped
|
|
54
|
+
"""
|
|
55
|
+
start_message()
|
|
56
|
+
|
|
57
|
+
# Get episode information
|
|
58
|
+
obj_episode = scrape_serie.selectEpisode(index_season_selected, index_episode_selected-1)
|
|
59
|
+
console.print(f"[bold yellow]Download:[/bold yellow] [red]{site_constant.SITE_NAME}[/red] → [bold magenta]{obj_episode.get('name')}[/bold magenta] ([cyan]S{index_season_selected}E{index_episode_selected}[/cyan]) \n")
|
|
60
|
+
|
|
61
|
+
# Define filename and path for the downloaded video
|
|
62
|
+
mp4_name = f"{map_episode_title(scrape_serie.series_name, index_season_selected, index_episode_selected, obj_episode.get('name'))}.mp4"
|
|
63
|
+
mp4_path = os_manager.get_sanitize_path(os.path.join(site_constant.SERIES_FOLDER, scrape_serie.series_name, f"S{index_season_selected}"))
|
|
64
|
+
|
|
65
|
+
# Generate mpd and license URLs
|
|
66
|
+
url_id = obj_episode.get('url').split('/')[-1]
|
|
67
|
+
device_id = generate_device_id()
|
|
68
|
+
mpd_url, mpd_headers = get_playback_session(get_auth_token(device_id), device_id, url_id)
|
|
69
|
+
parsed_url = urlparse(mpd_url)
|
|
70
|
+
query_params = parse_qs(parsed_url.query)
|
|
71
|
+
|
|
72
|
+
# Download the episode
|
|
73
|
+
r_proc = DASH_Download(
|
|
74
|
+
cdm_device=get_wvd_path(),
|
|
75
|
+
license_url='https://www.crunchyroll.com/license/v1/license/widevine',
|
|
76
|
+
mpd_url=mpd_url,
|
|
77
|
+
output_path=os.path.join(mp4_path, mp4_name),
|
|
78
|
+
)
|
|
79
|
+
r_proc.parse_manifest(custom_headers=mpd_headers)
|
|
80
|
+
|
|
81
|
+
# Create headers for license request
|
|
82
|
+
license_headers = mpd_headers.copy()
|
|
83
|
+
license_headers.update({
|
|
84
|
+
"x-cr-content-id": url_id,
|
|
85
|
+
"x-cr-video-token": query_params['playbackGuid'][0],
|
|
86
|
+
})
|
|
87
|
+
|
|
88
|
+
if r_proc.download_and_decrypt(custom_headers=license_headers):
|
|
89
|
+
r_proc.finalize_output()
|
|
90
|
+
|
|
91
|
+
# Get final output path and status
|
|
92
|
+
status = r_proc.get_status()
|
|
93
|
+
|
|
94
|
+
if status['error'] is not None and status['path']:
|
|
95
|
+
try: os.remove(status['path'])
|
|
96
|
+
except Exception: pass
|
|
97
|
+
|
|
98
|
+
return status['path'], status['stopped']
|
|
99
|
+
|
|
100
|
+
def download_episode(index_season_selected: int, scrape_serie: GetSerieInfo, download_all: bool = False, episode_selection: str = None) -> None:
|
|
101
|
+
"""
|
|
102
|
+
Handle downloading episodes for a specific season.
|
|
103
|
+
|
|
104
|
+
Parameters:
|
|
105
|
+
- index_season_selected (int): Season number
|
|
106
|
+
- scrape_serie (GetSerieInfo): Scraper object with series information
|
|
107
|
+
- download_all (bool): Whether to download all episodes
|
|
108
|
+
- episode_selection (str, optional): Pre-defined episode selection that bypasses manual input
|
|
109
|
+
"""
|
|
110
|
+
# Get episodes for the selected season
|
|
111
|
+
episodes = scrape_serie.getEpisodeSeasons(index_season_selected)
|
|
112
|
+
episodes_count = len(episodes)
|
|
113
|
+
|
|
114
|
+
if download_all:
|
|
115
|
+
for i_episode in range(1, episodes_count + 1):
|
|
116
|
+
path, stopped = download_video(index_season_selected, i_episode, scrape_serie)
|
|
117
|
+
|
|
118
|
+
if stopped:
|
|
119
|
+
break
|
|
120
|
+
|
|
121
|
+
console.print(f"\n[red]End downloaded [yellow]season: [red]{index_season_selected}.")
|
|
122
|
+
|
|
123
|
+
else:
|
|
124
|
+
if episode_selection is not None:
|
|
125
|
+
last_command = episode_selection
|
|
126
|
+
console.print(f"\n[cyan]Using provided episode selection: [yellow]{episode_selection}")
|
|
127
|
+
|
|
128
|
+
else:
|
|
129
|
+
last_command = display_episodes_list(episodes)
|
|
130
|
+
|
|
131
|
+
# Prompt user for episode selection
|
|
132
|
+
list_episode_select = manage_selection(last_command, episodes_count)
|
|
133
|
+
list_episode_select = validate_episode_selection(list_episode_select, episodes_count)
|
|
134
|
+
|
|
135
|
+
# Download selected episodes if not stopped
|
|
136
|
+
for i_episode in list_episode_select:
|
|
137
|
+
path, stopped = download_video(index_season_selected, i_episode, scrape_serie)
|
|
138
|
+
|
|
139
|
+
if stopped:
|
|
140
|
+
break
|
|
141
|
+
|
|
142
|
+
def download_series(select_season: MediaItem, season_selection: str = None, episode_selection: str = None) -> None:
|
|
143
|
+
"""
|
|
144
|
+
Handle downloading a complete series.
|
|
145
|
+
|
|
146
|
+
Parameters:
|
|
147
|
+
- select_season (MediaItem): Series metadata from search
|
|
148
|
+
- season_selection (str, optional): Pre-defined season selection that bypasses manual input
|
|
149
|
+
- episode_selection (str, optional): Pre-defined episode selection that bypasses manual input
|
|
150
|
+
"""
|
|
151
|
+
scrape_serie = GetSerieInfo(select_season.url.split("/")[-1])
|
|
152
|
+
|
|
153
|
+
# Get total number of seasons
|
|
154
|
+
seasons_count = scrape_serie.getNumberSeason()
|
|
155
|
+
|
|
156
|
+
# Prompt user for season selection and download episodes
|
|
157
|
+
console.print(f"\n[green]Seasons found: [red]{seasons_count}")
|
|
158
|
+
|
|
159
|
+
# If season_selection is provided, use it instead of asking for input
|
|
160
|
+
if season_selection is None:
|
|
161
|
+
index_season_selected = msg.ask(
|
|
162
|
+
"\n[cyan]Insert season number [yellow](e.g., 1), [red]* [cyan]to download all seasons, "
|
|
163
|
+
"[yellow](e.g., 1-2) [cyan]for a range of seasons, or [yellow](e.g., 3-*) [cyan]to download from a specific season to the end"
|
|
164
|
+
)
|
|
165
|
+
|
|
166
|
+
else:
|
|
167
|
+
index_season_selected = season_selection
|
|
168
|
+
console.print(f"\n[cyan]Using provided season selection: [yellow]{season_selection}")
|
|
169
|
+
|
|
170
|
+
# Validate the selection
|
|
171
|
+
list_season_select = manage_selection(index_season_selected, seasons_count)
|
|
172
|
+
list_season_select = validate_selection(list_season_select, seasons_count)
|
|
173
|
+
|
|
174
|
+
# Loop through the selected seasons and download episodes
|
|
175
|
+
for i_season in list_season_select:
|
|
176
|
+
if len(list_season_select) > 1 or index_season_selected == "*":
|
|
177
|
+
# Download all episodes if multiple seasons are selected or if '*' is used
|
|
178
|
+
download_episode(i_season, scrape_serie, download_all=True)
|
|
179
|
+
|
|
180
|
+
else:
|
|
181
|
+
# Otherwise, let the user select specific episodes for the single season
|
|
182
|
+
download_episode(i_season, scrape_serie, download_all=False, episode_selection=episode_selection)
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
# 16.03.25
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
# External libraries
|
|
5
|
+
from curl_cffi import requests
|
|
6
|
+
from rich.console import Console
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
# Internal utilities
|
|
10
|
+
from StreamingCommunity.Util.config_json import config_manager
|
|
11
|
+
from StreamingCommunity.Util.headers import get_headers
|
|
12
|
+
from StreamingCommunity.Util.table import TVShowManager
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
# Logic class
|
|
16
|
+
from StreamingCommunity.Api.Template.config_loader import site_constant
|
|
17
|
+
from StreamingCommunity.Api.Template.Class.SearchType import MediaManager
|
|
18
|
+
from .util.get_license import get_auth_token, generate_device_id
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
# Variable
|
|
22
|
+
console = Console()
|
|
23
|
+
media_search_manager = MediaManager()
|
|
24
|
+
table_show_manager = TVShowManager()
|
|
25
|
+
max_timeout = config_manager.get_int("REQUESTS", "timeout")
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
def title_search(query: str) -> int:
|
|
29
|
+
"""
|
|
30
|
+
Search for titles based on a search query.
|
|
31
|
+
|
|
32
|
+
Parameters:
|
|
33
|
+
- query (str): The query to search for.
|
|
34
|
+
|
|
35
|
+
Returns:
|
|
36
|
+
int: The number of titles found.
|
|
37
|
+
"""
|
|
38
|
+
media_search_manager.clear()
|
|
39
|
+
table_show_manager.clear()
|
|
40
|
+
|
|
41
|
+
# Build new Crunchyroll API search URL
|
|
42
|
+
api_url = f"https://www.crunchyroll.com/content/v2/discover/search"
|
|
43
|
+
|
|
44
|
+
params = {
|
|
45
|
+
"q": query,
|
|
46
|
+
"n": 20,
|
|
47
|
+
"type": "series,movie_listing",
|
|
48
|
+
"ratings": "true",
|
|
49
|
+
"preferred_audio_language": "it-IT",
|
|
50
|
+
"locale": "it-IT"
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
headers = get_headers()
|
|
54
|
+
headers['authorization'] = f"Bearer {get_auth_token(generate_device_id()).access_token}"
|
|
55
|
+
|
|
56
|
+
console.print(f"[cyan]Search url: [yellow]{api_url}")
|
|
57
|
+
|
|
58
|
+
try:
|
|
59
|
+
response = requests.get(
|
|
60
|
+
api_url,
|
|
61
|
+
params=params,
|
|
62
|
+
headers=headers,
|
|
63
|
+
timeout=max_timeout,
|
|
64
|
+
impersonate="chrome110"
|
|
65
|
+
)
|
|
66
|
+
response.raise_for_status()
|
|
67
|
+
|
|
68
|
+
except Exception as e:
|
|
69
|
+
console.print(f"[red]Site: {site_constant.SITE_NAME}, request search error: {e}")
|
|
70
|
+
return 0
|
|
71
|
+
|
|
72
|
+
data = response.json()
|
|
73
|
+
found = 0
|
|
74
|
+
|
|
75
|
+
# Parse results
|
|
76
|
+
for block in data.get("data", []):
|
|
77
|
+
if block.get("type") not in ("series", "movie_listing", "top_results"):
|
|
78
|
+
continue
|
|
79
|
+
|
|
80
|
+
for item in block.get("items", []):
|
|
81
|
+
tipo = None
|
|
82
|
+
|
|
83
|
+
if item.get("type") == "movie_listing":
|
|
84
|
+
tipo = "film"
|
|
85
|
+
elif item.get("type") == "series":
|
|
86
|
+
meta = item.get("series_metadata", {})
|
|
87
|
+
|
|
88
|
+
if meta.get("episode_count") == 1 and meta.get("season_count", 1) == 1 and meta.get("series_launch_year"):
|
|
89
|
+
tipo = "film" if "film" in item.get("description", "").lower() or "movie" in item.get("description", "").lower() else "tv"
|
|
90
|
+
else:
|
|
91
|
+
tipo = "tv"
|
|
92
|
+
|
|
93
|
+
else:
|
|
94
|
+
continue
|
|
95
|
+
|
|
96
|
+
url = ""
|
|
97
|
+
if tipo == "tv":
|
|
98
|
+
url = f"https://www.crunchyroll.com/series/{item.get('id')}"
|
|
99
|
+
elif tipo == "film":
|
|
100
|
+
url = f"https://www.crunchyroll.com/series/{item.get('id')}"
|
|
101
|
+
else:
|
|
102
|
+
continue
|
|
103
|
+
|
|
104
|
+
title = item.get("title", "")
|
|
105
|
+
|
|
106
|
+
media_search_manager.add_media({
|
|
107
|
+
'url': url,
|
|
108
|
+
'name': title,
|
|
109
|
+
'type': tipo
|
|
110
|
+
})
|
|
111
|
+
found += 1
|
|
112
|
+
|
|
113
|
+
return media_search_manager.get_length()
|