StreamingCommunity 2.9.9__py3-none-any.whl → 3.0.0__py3-none-any.whl
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/Api/Site/1337xx/__init__.py +1 -2
- StreamingCommunity/Api/Site/1337xx/site.py +6 -1
- StreamingCommunity/Api/Site/altadefinizione/__init__.py +1 -2
- StreamingCommunity/Api/Site/altadefinizione/site.py +6 -1
- StreamingCommunity/Api/Site/animeunity/__init__.py +1 -2
- StreamingCommunity/Api/Site/animeunity/site.py +63 -35
- StreamingCommunity/Api/Site/animeunity/util/ScrapeSerie.py +28 -24
- StreamingCommunity/Api/Site/animeworld/__init__.py +1 -2
- StreamingCommunity/Api/Site/animeworld/site.py +6 -1
- StreamingCommunity/Api/Site/cb01new/__init__.py +1 -2
- StreamingCommunity/Api/Site/cb01new/site.py +7 -1
- StreamingCommunity/Api/Site/ddlstreamitaly/__init__.py +1 -2
- StreamingCommunity/Api/Site/ddlstreamitaly/site.py +6 -1
- StreamingCommunity/Api/Site/guardaserie/__init__.py +1 -2
- StreamingCommunity/Api/Site/guardaserie/site.py +7 -1
- StreamingCommunity/Api/Site/raiplay/__init__.py +1 -2
- StreamingCommunity/Api/Site/raiplay/film.py +1 -1
- StreamingCommunity/Api/Site/raiplay/series.py +1 -1
- StreamingCommunity/Api/Site/raiplay/site.py +9 -2
- StreamingCommunity/Api/Site/raiplay/util/ScrapeSerie.py +1 -1
- StreamingCommunity/Api/Site/streamingcommunity/__init__.py +1 -2
- StreamingCommunity/Api/Site/streamingcommunity/site.py +7 -1
- StreamingCommunity/Lib/Downloader/HLS/segments.py +7 -15
- StreamingCommunity/Lib/Downloader/TOR/downloader.py +7 -14
- StreamingCommunity/Lib/FFmpeg/capture.py +1 -5
- StreamingCommunity/Lib/FFmpeg/util.py +48 -40
- StreamingCommunity/Lib/M3U8/estimator.py +20 -33
- StreamingCommunity/Upload/version.py +1 -1
- StreamingCommunity/Util/ffmpeg_installer.py +26 -1
- StreamingCommunity/Util/os.py +13 -15
- StreamingCommunity/global_search.py +1 -4
- StreamingCommunity/run.py +1 -4
- {streamingcommunity-2.9.9.dist-info → streamingcommunity-3.0.0.dist-info}/METADATA +1 -1
- {streamingcommunity-2.9.9.dist-info → streamingcommunity-3.0.0.dist-info}/RECORD +38 -38
- {streamingcommunity-2.9.9.dist-info → streamingcommunity-3.0.0.dist-info}/WHEEL +1 -1
- {streamingcommunity-2.9.9.dist-info → streamingcommunity-3.0.0.dist-info}/entry_points.txt +0 -0
- {streamingcommunity-2.9.9.dist-info → streamingcommunity-3.0.0.dist-info}/licenses/LICENSE +0 -0
- {streamingcommunity-2.9.9.dist-info → streamingcommunity-3.0.0.dist-info}/top_level.txt +0 -0
|
@@ -43,7 +43,12 @@ def title_search(query: str) -> int:
|
|
|
43
43
|
console.print(f"[cyan]Search url: [yellow]{search_url}")
|
|
44
44
|
|
|
45
45
|
try:
|
|
46
|
-
response = httpx.get(
|
|
46
|
+
response = httpx.get(
|
|
47
|
+
search_url,
|
|
48
|
+
headers={'user-agent': get_userAgent()},
|
|
49
|
+
timeout=max_timeout,
|
|
50
|
+
follow_redirects=True
|
|
51
|
+
)
|
|
47
52
|
response.raise_for_status()
|
|
48
53
|
|
|
49
54
|
except Exception as e:
|
|
@@ -46,7 +46,12 @@ def title_search(query: str) -> int:
|
|
|
46
46
|
console.print(f"[cyan]Search url: [yellow]{search_url}")
|
|
47
47
|
|
|
48
48
|
try:
|
|
49
|
-
response = httpx.post(
|
|
49
|
+
response = httpx.post(
|
|
50
|
+
search_url,
|
|
51
|
+
headers={'user-agent': get_userAgent()},
|
|
52
|
+
timeout=max_timeout,
|
|
53
|
+
follow_redirects=True
|
|
54
|
+
)
|
|
50
55
|
response.raise_for_status()
|
|
51
56
|
|
|
52
57
|
except Exception as e:
|
|
@@ -51,10 +51,8 @@ def get_token() -> dict:
|
|
|
51
51
|
|
|
52
52
|
for html_meta in soup.find_all("meta"):
|
|
53
53
|
if html_meta.get('name') == "csrf-token":
|
|
54
|
-
|
|
55
54
|
find_csrf_token = html_meta.get('content')
|
|
56
55
|
|
|
57
|
-
logging.info(f"Extract: ('animeunity_session': {response.cookies['animeunity_session']}, 'csrf_token': {find_csrf_token})")
|
|
58
56
|
return {
|
|
59
57
|
'animeunity_session': response.cookies['animeunity_session'],
|
|
60
58
|
'csrf_token': find_csrf_token
|
|
@@ -64,9 +62,6 @@ def get_token() -> dict:
|
|
|
64
62
|
def get_real_title(record):
|
|
65
63
|
"""
|
|
66
64
|
Get the real title from a record.
|
|
67
|
-
|
|
68
|
-
This function takes a record, which is assumed to be a dictionary representing a row of JSON data.
|
|
69
|
-
It looks for a title in the record, prioritizing English over Italian titles if available.
|
|
70
65
|
|
|
71
66
|
Parameters:
|
|
72
67
|
- record (dict): A dictionary representing a row of JSON data.
|
|
@@ -84,7 +79,7 @@ def get_real_title(record):
|
|
|
84
79
|
|
|
85
80
|
def title_search(query: str) -> int:
|
|
86
81
|
"""
|
|
87
|
-
Function to perform an anime search using
|
|
82
|
+
Function to perform an anime search using both APIs and combine results.
|
|
88
83
|
|
|
89
84
|
Parameters:
|
|
90
85
|
- query (str): The query to search for.
|
|
@@ -97,43 +92,85 @@ def title_search(query: str) -> int:
|
|
|
97
92
|
|
|
98
93
|
media_search_manager.clear()
|
|
99
94
|
table_show_manager.clear()
|
|
95
|
+
seen_titles = set()
|
|
96
|
+
choices = [] if site_constant.TELEGRAM_BOT else None
|
|
100
97
|
|
|
101
98
|
# Create parameter for request
|
|
102
99
|
data = get_token()
|
|
103
|
-
cookies = {
|
|
100
|
+
cookies = {
|
|
101
|
+
'animeunity_session': data.get('animeunity_session')
|
|
102
|
+
}
|
|
104
103
|
headers = {
|
|
105
104
|
'user-agent': get_userAgent(),
|
|
106
105
|
'x-csrf-token': data.get('csrf_token')
|
|
107
106
|
}
|
|
108
|
-
json_data = {'title': query}
|
|
109
107
|
|
|
110
|
-
#
|
|
108
|
+
# First API call - livesearch
|
|
109
|
+
try:
|
|
110
|
+
response1 = httpx.post(
|
|
111
|
+
f'{site_constant.FULL_URL}/livesearch',
|
|
112
|
+
cookies=cookies,
|
|
113
|
+
headers=headers,
|
|
114
|
+
json={'title': query},
|
|
115
|
+
timeout=max_timeout
|
|
116
|
+
)
|
|
117
|
+
|
|
118
|
+
response1.raise_for_status()
|
|
119
|
+
process_results(response1.json()['records'], seen_titles, media_search_manager, choices)
|
|
120
|
+
|
|
121
|
+
except Exception as e:
|
|
122
|
+
console.print(f"Site: {site_constant.SITE_NAME}, livesearch error: {e}")
|
|
123
|
+
|
|
124
|
+
# Second API call - archivio
|
|
111
125
|
try:
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
126
|
+
json_data = {
|
|
127
|
+
'title': query,
|
|
128
|
+
'type': False,
|
|
129
|
+
'year': False,
|
|
130
|
+
'order': 'Lista A-Z',
|
|
131
|
+
'status': False,
|
|
132
|
+
'genres': False,
|
|
133
|
+
'offset': 0,
|
|
134
|
+
'dubbed': False,
|
|
135
|
+
'season': False
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
response2 = httpx.post(
|
|
139
|
+
f'{site_constant.FULL_URL}/archivio/get-animes',
|
|
140
|
+
cookies=cookies,
|
|
141
|
+
headers=headers,
|
|
116
142
|
json=json_data,
|
|
117
143
|
timeout=max_timeout
|
|
118
144
|
)
|
|
119
|
-
|
|
145
|
+
|
|
146
|
+
response2.raise_for_status()
|
|
147
|
+
process_results(response2.json()['records'], seen_titles, media_search_manager, choices)
|
|
120
148
|
|
|
121
149
|
except Exception as e:
|
|
122
|
-
console.print(f"Site: {site_constant.SITE_NAME},
|
|
123
|
-
return 0
|
|
150
|
+
console.print(f"Site: {site_constant.SITE_NAME}, archivio search error: {e}")
|
|
124
151
|
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
152
|
+
if site_constant.TELEGRAM_BOT and choices and len(choices) > 0:
|
|
153
|
+
bot.send_message(f"Lista dei risultati:", choices)
|
|
154
|
+
|
|
155
|
+
result_count = media_search_manager.get_length()
|
|
156
|
+
if result_count == 0:
|
|
157
|
+
console.print(f"Nothing matching was found for: {query}")
|
|
158
|
+
|
|
159
|
+
return result_count
|
|
128
160
|
|
|
129
|
-
|
|
161
|
+
def process_results(records: list, seen_titles: set, media_manager: MediaManager, choices: list = None) -> None:
|
|
162
|
+
"""Helper function to process search results and add unique entries."""
|
|
163
|
+
for dict_title in records:
|
|
130
164
|
try:
|
|
131
|
-
|
|
132
|
-
|
|
165
|
+
title_id = dict_title.get('id')
|
|
166
|
+
if title_id in seen_titles:
|
|
167
|
+
continue
|
|
168
|
+
|
|
169
|
+
seen_titles.add(title_id)
|
|
133
170
|
dict_title['name'] = get_real_title(dict_title)
|
|
134
171
|
|
|
135
|
-
|
|
136
|
-
'id':
|
|
172
|
+
media_manager.add_media({
|
|
173
|
+
'id': title_id,
|
|
137
174
|
'slug': dict_title.get('slug'),
|
|
138
175
|
'name': dict_title.get('name'),
|
|
139
176
|
'type': dict_title.get('type'),
|
|
@@ -142,18 +179,9 @@ def title_search(query: str) -> int:
|
|
|
142
179
|
'image': dict_title.get('imageurl')
|
|
143
180
|
})
|
|
144
181
|
|
|
145
|
-
if
|
|
146
|
-
|
|
147
|
-
# Crea una stringa formattata per ogni scelta con numero
|
|
182
|
+
if choices is not None:
|
|
148
183
|
choice_text = f"{len(choices)} - {dict_title.get('name')} ({dict_title.get('type')}) - Episodi: {dict_title.get('episodes_count')}"
|
|
149
184
|
choices.append(choice_text)
|
|
150
185
|
|
|
151
186
|
except Exception as e:
|
|
152
|
-
print(f"Error parsing a
|
|
153
|
-
|
|
154
|
-
if site_constant.TELEGRAM_BOT:
|
|
155
|
-
if choices:
|
|
156
|
-
bot.send_message(f"Lista dei risultati:", choices)
|
|
157
|
-
|
|
158
|
-
# Return the length of media search manager
|
|
159
|
-
return media_search_manager.get_length()
|
|
187
|
+
print(f"Error parsing a title entry: {e}")
|
|
@@ -29,6 +29,7 @@ class ScrapeSerieAnime:
|
|
|
29
29
|
self.is_series = False
|
|
30
30
|
self.headers = {'user-agent': get_userAgent()}
|
|
31
31
|
self.url = url
|
|
32
|
+
self.episodes_cache = None
|
|
32
33
|
|
|
33
34
|
def setup(self, version: str = None, media_id: int = None, series_name: str = None):
|
|
34
35
|
self.version = version
|
|
@@ -62,38 +63,41 @@ class ScrapeSerieAnime:
|
|
|
62
63
|
logging.error(f"Error fetching episode count: {e}")
|
|
63
64
|
return None
|
|
64
65
|
|
|
65
|
-
def
|
|
66
|
+
def _fetch_all_episodes(self):
|
|
66
67
|
"""
|
|
67
|
-
Fetch
|
|
68
|
-
|
|
69
|
-
Args:
|
|
70
|
-
index_ep (int): Zero-based index of the target episode
|
|
71
|
-
|
|
72
|
-
Returns:
|
|
73
|
-
Episode: Detailed episode information
|
|
68
|
+
Fetch all episodes data at once and cache it
|
|
74
69
|
"""
|
|
75
70
|
try:
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
"end_range": index_ep + 1
|
|
80
|
-
}
|
|
71
|
+
count = self.get_count_episodes()
|
|
72
|
+
if not count:
|
|
73
|
+
return
|
|
81
74
|
|
|
82
75
|
response = httpx.get(
|
|
83
|
-
url=f"{self.url}/info_api/{self.media_id}/
|
|
84
|
-
|
|
85
|
-
|
|
76
|
+
url=f"{self.url}/info_api/{self.media_id}/1",
|
|
77
|
+
params={
|
|
78
|
+
"start_range": 1,
|
|
79
|
+
"end_range": count
|
|
80
|
+
},
|
|
81
|
+
headers=self.headers,
|
|
86
82
|
timeout=max_timeout
|
|
87
83
|
)
|
|
88
84
|
response.raise_for_status()
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
json_data = response.json()["episodes"][-1]
|
|
92
|
-
return Episode(json_data)
|
|
93
|
-
|
|
85
|
+
|
|
86
|
+
self.episodes_cache = response.json()["episodes"]
|
|
94
87
|
except Exception as e:
|
|
95
|
-
logging.error(f"Error fetching
|
|
96
|
-
|
|
88
|
+
logging.error(f"Error fetching all episodes: {e}")
|
|
89
|
+
self.episodes_cache = None
|
|
90
|
+
|
|
91
|
+
def get_info_episode(self, index_ep: int) -> Episode:
|
|
92
|
+
"""
|
|
93
|
+
Get episode info from cache
|
|
94
|
+
"""
|
|
95
|
+
if self.episodes_cache is None:
|
|
96
|
+
self._fetch_all_episodes()
|
|
97
|
+
|
|
98
|
+
if self.episodes_cache and 0 <= index_ep < len(self.episodes_cache):
|
|
99
|
+
return Episode(self.episodes_cache[index_ep])
|
|
100
|
+
return None
|
|
97
101
|
|
|
98
102
|
|
|
99
103
|
# ------------- FOR GUI -------------
|
|
@@ -108,4 +112,4 @@ class ScrapeSerieAnime:
|
|
|
108
112
|
"""
|
|
109
113
|
Get information for a specific episode.
|
|
110
114
|
"""
|
|
111
|
-
return self.get_info_episode(episode_index)
|
|
115
|
+
return self.get_info_episode(episode_index)
|
|
@@ -70,7 +70,12 @@ def title_search(query: str) -> int:
|
|
|
70
70
|
|
|
71
71
|
# Make the GET request
|
|
72
72
|
try:
|
|
73
|
-
response = httpx.get(
|
|
73
|
+
response = httpx.get(
|
|
74
|
+
search_url,
|
|
75
|
+
headers={'User-Agent': get_userAgent()},
|
|
76
|
+
timeout=max_timeout,
|
|
77
|
+
verify=False
|
|
78
|
+
)
|
|
74
79
|
|
|
75
80
|
except Exception as e:
|
|
76
81
|
console.print(f"Site: {site_constant.SITE_NAME}, request search error: {e}")
|
|
@@ -44,7 +44,13 @@ def title_search(query: str) -> int:
|
|
|
44
44
|
console.print(f"[cyan]Search url: [yellow]{search_url}")
|
|
45
45
|
|
|
46
46
|
try:
|
|
47
|
-
response = httpx.get(
|
|
47
|
+
response = httpx.get(
|
|
48
|
+
search_url,
|
|
49
|
+
headers={'user-agent': get_userAgent()},
|
|
50
|
+
timeout=max_timeout,
|
|
51
|
+
follow_redirects=True,
|
|
52
|
+
verify=False
|
|
53
|
+
)
|
|
48
54
|
response.raise_for_status()
|
|
49
55
|
|
|
50
56
|
except Exception as e:
|
|
@@ -44,7 +44,12 @@ def title_search(query: str) -> int:
|
|
|
44
44
|
console.print(f"[cyan]Search url: [yellow]{search_url}")
|
|
45
45
|
|
|
46
46
|
try:
|
|
47
|
-
response = httpx.get(
|
|
47
|
+
response = httpx.get(
|
|
48
|
+
search_url,
|
|
49
|
+
headers={'user-agent': get_userAgent()},
|
|
50
|
+
timeout=max_timeout,
|
|
51
|
+
follow_redirects=True
|
|
52
|
+
)
|
|
48
53
|
response.raise_for_status()
|
|
49
54
|
|
|
50
55
|
except Exception as e:
|
|
@@ -44,7 +44,13 @@ def title_search(query: str) -> int:
|
|
|
44
44
|
console.print(f"[cyan]Search url: [yellow]{search_url}")
|
|
45
45
|
|
|
46
46
|
try:
|
|
47
|
-
response = httpx.get(
|
|
47
|
+
response = httpx.get(
|
|
48
|
+
search_url,
|
|
49
|
+
headers={'user-agent': get_userAgent()},
|
|
50
|
+
timeout=max_timeout,
|
|
51
|
+
follow_redirects=True,
|
|
52
|
+
verify=False
|
|
53
|
+
)
|
|
48
54
|
response.raise_for_status()
|
|
49
55
|
|
|
50
56
|
except Exception as e:
|
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
#
|
|
1
|
+
# 21.05.24
|
|
2
2
|
|
|
3
3
|
import threading
|
|
4
4
|
import queue
|
|
5
5
|
|
|
6
|
+
|
|
6
7
|
# External libraries
|
|
7
8
|
import httpx
|
|
8
9
|
from rich.console import Console
|
|
@@ -123,7 +124,13 @@ def title_search(query: str) -> int:
|
|
|
123
124
|
}
|
|
124
125
|
|
|
125
126
|
try:
|
|
126
|
-
response = httpx.post(
|
|
127
|
+
response = httpx.post(
|
|
128
|
+
search_url,
|
|
129
|
+
headers={'user-agent': get_userAgent()},
|
|
130
|
+
json=json_data,
|
|
131
|
+
timeout=max_timeout,
|
|
132
|
+
follow_redirects=True
|
|
133
|
+
)
|
|
127
134
|
response.raise_for_status()
|
|
128
135
|
|
|
129
136
|
except Exception as e:
|
|
@@ -45,7 +45,13 @@ def title_search(query: str) -> int:
|
|
|
45
45
|
console.print(f"[cyan]Search url: [yellow]{search_url}")
|
|
46
46
|
|
|
47
47
|
try:
|
|
48
|
-
response = httpx.get(
|
|
48
|
+
response = httpx.get(
|
|
49
|
+
search_url,
|
|
50
|
+
headers={'user-agent': get_userAgent()},
|
|
51
|
+
timeout=max_timeout,
|
|
52
|
+
follow_redirects=True,
|
|
53
|
+
verify=False
|
|
54
|
+
)
|
|
49
55
|
response.raise_for_status()
|
|
50
56
|
|
|
51
57
|
except Exception as e:
|
|
@@ -23,7 +23,7 @@ from rich.console import Console
|
|
|
23
23
|
# Internal utilities
|
|
24
24
|
from StreamingCommunity.Util.color import Colors
|
|
25
25
|
from StreamingCommunity.Util.headers import get_userAgent
|
|
26
|
-
from StreamingCommunity.Util.config_json import config_manager
|
|
26
|
+
from StreamingCommunity.Util.config_json import config_manager
|
|
27
27
|
|
|
28
28
|
|
|
29
29
|
# Logic class
|
|
@@ -407,20 +407,12 @@ class M3U8_Segments:
|
|
|
407
407
|
"""
|
|
408
408
|
Generate platform-appropriate progress bar format.
|
|
409
409
|
"""
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
else:
|
|
418
|
-
return (
|
|
419
|
-
f"{Colors.YELLOW}[HLS] {Colors.WHITE}({Colors.CYAN}{description}{Colors.WHITE}): "
|
|
420
|
-
f"{Colors.RED}{{percentage:.2f}}% "
|
|
421
|
-
f"{Colors.MAGENTA}{{bar}} "
|
|
422
|
-
f"{Colors.YELLOW}{{elapsed}}{Colors.WHITE} < {Colors.CYAN}{{remaining}}{Colors.WHITE}{{postfix}}{Colors.WHITE}"
|
|
423
|
-
)
|
|
410
|
+
return (
|
|
411
|
+
f"{Colors.YELLOW}[HLS] {Colors.WHITE}({Colors.CYAN}{description}{Colors.WHITE}): "
|
|
412
|
+
f"{Colors.RED}{{percentage:.2f}}% "
|
|
413
|
+
f"{Colors.MAGENTA}{{bar}} "
|
|
414
|
+
f"{Colors.YELLOW}{{elapsed}}{Colors.WHITE} < {Colors.CYAN}{{remaining}}{Colors.WHITE}{{postfix}}{Colors.WHITE}"
|
|
415
|
+
)
|
|
424
416
|
|
|
425
417
|
def _get_worker_count(self, stream_type: str) -> int:
|
|
426
418
|
"""
|
|
@@ -18,7 +18,7 @@ import qbittorrentapi
|
|
|
18
18
|
# Internal utilities
|
|
19
19
|
from StreamingCommunity.Util.color import Colors
|
|
20
20
|
from StreamingCommunity.Util.os import internet_manager
|
|
21
|
-
from StreamingCommunity.Util.config_json import config_manager
|
|
21
|
+
from StreamingCommunity.Util.config_json import config_manager
|
|
22
22
|
|
|
23
23
|
|
|
24
24
|
# Configuration
|
|
@@ -316,19 +316,12 @@ class TOR_downloader:
|
|
|
316
316
|
# Ensure the torrent is started
|
|
317
317
|
self.qb.torrents_resume(torrent_hashes=self.latest_torrent_hash)
|
|
318
318
|
|
|
319
|
-
# Configure progress bar display format
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
)
|
|
326
|
-
else:
|
|
327
|
-
bar_format = (
|
|
328
|
-
f"{Colors.YELLOW}Proc{Colors.WHITE}: "
|
|
329
|
-
f"{Colors.RED}{{percentage:.2f}}% {Colors.WHITE}| "
|
|
330
|
-
f"{Colors.CYAN}{{remaining}}{{postfix}} {Colors.WHITE}]"
|
|
331
|
-
)
|
|
319
|
+
# Configure progress bar display format
|
|
320
|
+
bar_format = (
|
|
321
|
+
f"{Colors.YELLOW}[TOR] {Colors.WHITE}({Colors.CYAN}video{Colors.WHITE}): "
|
|
322
|
+
f"{Colors.RED}{{percentage:.2f}}% {Colors.MAGENTA}{{bar}} {Colors.WHITE}[ "
|
|
323
|
+
f"{Colors.YELLOW}{{elapsed}} {Colors.WHITE}< {Colors.CYAN}{{remaining}}{{postfix}} {Colors.WHITE}]"
|
|
324
|
+
)
|
|
332
325
|
|
|
333
326
|
# Initialize progress bar
|
|
334
327
|
with tqdm(
|
|
@@ -36,11 +36,7 @@ def capture_output(process: subprocess.Popen, description: str) -> None:
|
|
|
36
36
|
if not line:
|
|
37
37
|
continue
|
|
38
38
|
|
|
39
|
-
logging.info(f"
|
|
40
|
-
|
|
41
|
-
# Capture only error
|
|
42
|
-
if "rror" in str(line):
|
|
43
|
-
console.log(f"[red]FFMPEG: {str(line).strip()}")
|
|
39
|
+
logging.info(f"CAPTURE ffmpeg line: {line}")
|
|
44
40
|
|
|
45
41
|
# Check if termination is requested
|
|
46
42
|
if terminate_flag.is_set():
|
|
@@ -132,10 +132,8 @@ def print_duration_table(file_path: str, description: str = "Duration", return_s
|
|
|
132
132
|
def get_ffprobe_info(file_path):
|
|
133
133
|
"""
|
|
134
134
|
Get format and codec information for a media file using ffprobe.
|
|
135
|
-
|
|
136
135
|
Parameters:
|
|
137
136
|
- file_path (str): Path to the media file.
|
|
138
|
-
|
|
139
137
|
Returns:
|
|
140
138
|
dict: A dictionary containing the format name and a list of codec names.
|
|
141
139
|
Returns None if file does not exist or ffprobe crashes.
|
|
@@ -143,48 +141,58 @@ def get_ffprobe_info(file_path):
|
|
|
143
141
|
if not os.path.exists(file_path):
|
|
144
142
|
logging.error(f"File not found: {file_path}")
|
|
145
143
|
return None
|
|
146
|
-
|
|
144
|
+
|
|
145
|
+
# Get ffprobe path and verify it exists
|
|
146
|
+
ffprobe_path = get_ffprobe_path()
|
|
147
|
+
if not ffprobe_path or not os.path.exists(ffprobe_path):
|
|
148
|
+
logging.error(f"FFprobe not found at path: {ffprobe_path}")
|
|
149
|
+
return None
|
|
150
|
+
|
|
151
|
+
# Verify file permissions
|
|
152
|
+
try:
|
|
153
|
+
file_stat = os.stat(file_path)
|
|
154
|
+
logging.info(f"File permissions: {oct(file_stat.st_mode)}")
|
|
155
|
+
if not os.access(file_path, os.R_OK):
|
|
156
|
+
logging.error(f"No read permission for file: {file_path}")
|
|
157
|
+
return None
|
|
158
|
+
except OSError as e:
|
|
159
|
+
logging.error(f"Cannot access file {file_path}: {e}")
|
|
160
|
+
return None
|
|
161
|
+
|
|
147
162
|
try:
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
logging.info(f"FFmpeg command: {cmd}")
|
|
163
|
+
cmd = [ffprobe_path, '-v', 'error', '-show_format', '-show_streams', '-print_format', 'json', file_path]
|
|
164
|
+
logging.info(f"Running FFprobe command: {' '.join(cmd)}")
|
|
151
165
|
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
info = json.loads(stdout)
|
|
173
|
-
|
|
174
|
-
format_name = info['format']['format_name'] if 'format' in info else None
|
|
175
|
-
codec_names = [stream['codec_name'] for stream in info['streams']] if 'streams' in info else []
|
|
176
|
-
|
|
166
|
+
# Use subprocess.run instead of Popen for better error handling
|
|
167
|
+
result = subprocess.run(
|
|
168
|
+
cmd,
|
|
169
|
+
capture_output=True,
|
|
170
|
+
text=True,
|
|
171
|
+
check=False # Don't raise exception on non-zero exit
|
|
172
|
+
)
|
|
173
|
+
|
|
174
|
+
if result.returncode != 0:
|
|
175
|
+
logging.error(f"FFprobe failed with return code {result.returncode}")
|
|
176
|
+
logging.error(f"FFprobe stderr: {result.stderr}")
|
|
177
|
+
logging.error(f"FFprobe stdout: {result.stdout}")
|
|
178
|
+
logging.error(f"Command: {' '.join(cmd)}")
|
|
179
|
+
logging.error(f"FFprobe path permissions: {oct(os.stat(ffprobe_path).st_mode)}")
|
|
180
|
+
return None
|
|
181
|
+
|
|
182
|
+
# Parse JSON output
|
|
183
|
+
try:
|
|
184
|
+
info = json.loads(result.stdout)
|
|
177
185
|
return {
|
|
178
|
-
'format_name': format_name,
|
|
179
|
-
'codec_names':
|
|
186
|
+
'format_name': info.get('format', {}).get('format_name'),
|
|
187
|
+
'codec_names': [stream.get('codec_name') for stream in info.get('streams', [])]
|
|
180
188
|
}
|
|
181
|
-
|
|
189
|
+
except json.JSONDecodeError as e:
|
|
190
|
+
logging.error(f"Failed to parse FFprobe output: {e}")
|
|
191
|
+
return None
|
|
192
|
+
|
|
182
193
|
except Exception as e:
|
|
183
|
-
logging.error(f"
|
|
184
|
-
return
|
|
185
|
-
'format_name': None,
|
|
186
|
-
'codec_names': []
|
|
187
|
-
}
|
|
194
|
+
logging.error(f"FFprobe execution failed: {e}")
|
|
195
|
+
return None
|
|
188
196
|
|
|
189
197
|
|
|
190
198
|
def is_png_format_or_codec(file_info):
|
|
@@ -255,4 +263,4 @@ def check_duration_v_a(video_path, audio_path, tolerance=1.0):
|
|
|
255
263
|
if duration_difference <= tolerance:
|
|
256
264
|
return True, duration_difference
|
|
257
265
|
else:
|
|
258
|
-
return False, duration_difference
|
|
266
|
+
return False, duration_difference
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
# 21.04.25
|
|
2
2
|
|
|
3
|
-
import sys
|
|
4
3
|
import time
|
|
5
4
|
import logging
|
|
6
5
|
import threading
|
|
@@ -14,7 +13,6 @@ from tqdm import tqdm
|
|
|
14
13
|
|
|
15
14
|
# Internal utilities
|
|
16
15
|
from StreamingCommunity.Util.color import Colors
|
|
17
|
-
from StreamingCommunity.Util.config_json import get_use_large_bar
|
|
18
16
|
from StreamingCommunity.Util.os import internet_manager
|
|
19
17
|
|
|
20
18
|
|
|
@@ -32,14 +30,10 @@ class M3U8_Ts_Estimator:
|
|
|
32
30
|
self.lock = threading.Lock()
|
|
33
31
|
self.speed = {"upload": "N/A", "download": "N/A"}
|
|
34
32
|
self._running = True
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
self.speed_thread.daemon = True
|
|
40
|
-
self.speed_thread.start()
|
|
41
|
-
else:
|
|
42
|
-
logging.debug("USE_LARGE_BAR is False, speed capture thread not started")
|
|
33
|
+
|
|
34
|
+
self.speed_thread = threading.Thread(target=self.capture_speed)
|
|
35
|
+
self.speed_thread.daemon = True
|
|
36
|
+
self.speed_thread.start()
|
|
43
37
|
|
|
44
38
|
def __del__(self):
|
|
45
39
|
"""Ensure thread is properly stopped when the object is destroyed."""
|
|
@@ -133,29 +127,22 @@ class M3U8_Ts_Estimator:
|
|
|
133
127
|
with self.segments_instance.active_retries_lock:
|
|
134
128
|
retry_count = self.segments_instance.active_retries
|
|
135
129
|
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
)
|
|
153
|
-
|
|
154
|
-
else:
|
|
155
|
-
progress_str = (
|
|
156
|
-
f"{Colors.GREEN}{number_file_total_size} {Colors.RED}{units_file_total_size} "
|
|
157
|
-
#f"{Colors.WHITE}, {Colors.GREEN}CRR {Colors.RED}{retry_count} "
|
|
158
|
-
)
|
|
130
|
+
# Get speed data outside of any locks
|
|
131
|
+
speed_data = ["N/A", ""]
|
|
132
|
+
with self.lock:
|
|
133
|
+
download_speed = self.speed['download']
|
|
134
|
+
|
|
135
|
+
if download_speed != "N/A":
|
|
136
|
+
speed_data = download_speed.split(" ")
|
|
137
|
+
|
|
138
|
+
average_internet_speed = speed_data[0] if len(speed_data) >= 1 else "N/A"
|
|
139
|
+
average_internet_unit = speed_data[1] if len(speed_data) >= 2 else ""
|
|
140
|
+
|
|
141
|
+
progress_str = (
|
|
142
|
+
f"{Colors.GREEN}{number_file_total_size} {Colors.RED}{units_file_total_size}"
|
|
143
|
+
f"{Colors.WHITE}, {Colors.CYAN}{average_internet_speed} {Colors.RED}{average_internet_unit} "
|
|
144
|
+
#f"{Colors.WHITE}, {Colors.GREEN}CRR {Colors.RED}{retry_count} "
|
|
145
|
+
)
|
|
159
146
|
|
|
160
147
|
progress_counter.set_postfix_str(progress_str)
|
|
161
148
|
|
|
@@ -238,6 +238,31 @@ class FFMPEGDownloader:
|
|
|
238
238
|
Returns:
|
|
239
239
|
Tuple[Optional[str], Optional[str], Optional[str]]: Paths to ffmpeg, ffprobe, and ffplay executables.
|
|
240
240
|
"""
|
|
241
|
+
if self.os_name == 'linux':
|
|
242
|
+
try:
|
|
243
|
+
# Attempt to install FFmpeg using apt
|
|
244
|
+
console.print("[bold blue]Trying to install FFmpeg using 'sudo apt install ffmpeg'[/]")
|
|
245
|
+
result = subprocess.run(
|
|
246
|
+
['sudo', 'apt', 'install', '-y', 'ffmpeg'],
|
|
247
|
+
stdout=subprocess.PIPE,
|
|
248
|
+
stderr=subprocess.PIPE,
|
|
249
|
+
text=True
|
|
250
|
+
)
|
|
251
|
+
if result.returncode == 0:
|
|
252
|
+
ffmpeg_path = shutil.which('ffmpeg')
|
|
253
|
+
ffprobe_path = shutil.which('ffprobe')
|
|
254
|
+
|
|
255
|
+
if ffmpeg_path and ffprobe_path:
|
|
256
|
+
console.print("[bold green]FFmpeg successfully installed via apt[/]")
|
|
257
|
+
return ffmpeg_path, ffprobe_path, None
|
|
258
|
+
else:
|
|
259
|
+
console.print("[bold yellow]Failed to install FFmpeg via apt. Proceeding with static download.[/]")
|
|
260
|
+
|
|
261
|
+
except Exception as e:
|
|
262
|
+
logging.error(f"Error during 'sudo apt install ffmpeg': {e}")
|
|
263
|
+
console.print("[bold red]Error during 'sudo apt install ffmpeg'. Proceeding with static download.[/]")
|
|
264
|
+
|
|
265
|
+
# Proceed with static download if apt installation fails or is not applicable
|
|
241
266
|
config = FFMPEG_CONFIGURATION[self.os_name]
|
|
242
267
|
executables = [exe.format(arch=self.arch) for exe in config['executables']]
|
|
243
268
|
successful_extractions = []
|
|
@@ -346,4 +371,4 @@ def check_ffmpeg() -> Tuple[Optional[str], Optional[str], Optional[str]]:
|
|
|
346
371
|
|
|
347
372
|
except Exception as e:
|
|
348
373
|
logging.error(f"Error checking or downloading FFmpeg executables: {e}")
|
|
349
|
-
return None, None, None
|
|
374
|
+
return None, None, None
|
StreamingCommunity/Util/os.py
CHANGED
|
@@ -4,7 +4,6 @@ import io
|
|
|
4
4
|
import os
|
|
5
5
|
import glob
|
|
6
6
|
import sys
|
|
7
|
-
import time
|
|
8
7
|
import shutil
|
|
9
8
|
import hashlib
|
|
10
9
|
import logging
|
|
@@ -13,11 +12,9 @@ import inspect
|
|
|
13
12
|
import subprocess
|
|
14
13
|
import contextlib
|
|
15
14
|
import importlib.metadata
|
|
16
|
-
from pathlib import Path
|
|
17
15
|
|
|
18
16
|
|
|
19
17
|
# External library
|
|
20
|
-
import httpx
|
|
21
18
|
from unidecode import unidecode
|
|
22
19
|
from rich.console import Console
|
|
23
20
|
from rich.prompt import Prompt
|
|
@@ -107,16 +104,14 @@ class OsManager:
|
|
|
107
104
|
if not path:
|
|
108
105
|
return path
|
|
109
106
|
|
|
110
|
-
# Decode unicode characters
|
|
107
|
+
# Decode unicode characters and perform basic sanitization
|
|
111
108
|
decoded = unidecode(path)
|
|
112
|
-
|
|
113
|
-
# Basic path sanitization
|
|
114
109
|
sanitized = sanitize_filepath(decoded)
|
|
115
110
|
|
|
116
111
|
if self.system == 'windows':
|
|
117
112
|
# Handle network paths (UNC or IP-based)
|
|
118
|
-
if
|
|
119
|
-
parts =
|
|
113
|
+
if sanitized.startswith('\\\\') or sanitized.startswith('//'):
|
|
114
|
+
parts = sanitized.replace('/', '\\').split('\\')
|
|
120
115
|
# Keep server/IP and share name as is
|
|
121
116
|
sanitized_parts = parts[:4]
|
|
122
117
|
# Sanitize remaining parts
|
|
@@ -129,9 +124,9 @@ class OsManager:
|
|
|
129
124
|
return '\\'.join(sanitized_parts)
|
|
130
125
|
|
|
131
126
|
# Handle drive letters
|
|
132
|
-
elif len(
|
|
133
|
-
drive =
|
|
134
|
-
rest =
|
|
127
|
+
elif len(sanitized) >= 2 and sanitized[1] == ':':
|
|
128
|
+
drive = sanitized[:2]
|
|
129
|
+
rest = sanitized[2:].lstrip('\\').lstrip('/')
|
|
135
130
|
path_parts = [drive] + [
|
|
136
131
|
self.get_sanitize_file(part)
|
|
137
132
|
for part in rest.replace('/', '\\').split('\\')
|
|
@@ -141,12 +136,12 @@ class OsManager:
|
|
|
141
136
|
|
|
142
137
|
# Regular path
|
|
143
138
|
else:
|
|
144
|
-
parts =
|
|
139
|
+
parts = sanitized.replace('/', '\\').split('\\')
|
|
145
140
|
return '\\'.join(p for p in parts if p)
|
|
146
141
|
else:
|
|
147
142
|
# Handle Unix-like paths (Linux and macOS)
|
|
148
|
-
is_absolute =
|
|
149
|
-
parts =
|
|
143
|
+
is_absolute = sanitized.startswith('/')
|
|
144
|
+
parts = sanitized.replace('\\', '/').split('/')
|
|
150
145
|
sanitized_parts = [
|
|
151
146
|
self.get_sanitize_file(part)
|
|
152
147
|
for part in parts
|
|
@@ -357,12 +352,15 @@ class OsSummary:
|
|
|
357
352
|
Exits with a message if not the official version.
|
|
358
353
|
"""
|
|
359
354
|
python_implementation = platform.python_implementation()
|
|
355
|
+
python_version = platform.python_version()
|
|
360
356
|
|
|
361
357
|
if python_implementation != "CPython":
|
|
362
358
|
console.print(f"[bold red]Warning: You are using a non-official Python distribution: {python_implementation}.[/bold red]")
|
|
363
359
|
console.print("Please install the official Python from [bold blue]https://www.python.org[/bold blue] and try again.", style="bold yellow")
|
|
364
360
|
sys.exit(0)
|
|
365
361
|
|
|
362
|
+
console.print(f"[cyan]Python version: [bold red]{python_version}[/bold red]")
|
|
363
|
+
|
|
366
364
|
def get_system_summary(self):
|
|
367
365
|
self.check_python_version()
|
|
368
366
|
|
|
@@ -454,4 +452,4 @@ def get_ffmpeg_path():
|
|
|
454
452
|
|
|
455
453
|
def get_ffprobe_path():
|
|
456
454
|
"""Returns the path of FFprobe."""
|
|
457
|
-
return os_summary.ffprobe_path
|
|
455
|
+
return os_summary.ffprobe_path
|
|
@@ -57,11 +57,8 @@ def load_search_functions():
|
|
|
57
57
|
|
|
58
58
|
# Get 'indice' from the module
|
|
59
59
|
indice = getattr(mod, 'indice', 0)
|
|
60
|
-
is_deprecate = bool(getattr(mod, '_deprecate', True))
|
|
61
60
|
use_for = getattr(mod, '_useFor', 'other')
|
|
62
|
-
|
|
63
|
-
if not is_deprecate:
|
|
64
|
-
modules.append((module_name, indice, use_for))
|
|
61
|
+
modules.append((module_name, indice, use_for))
|
|
65
62
|
|
|
66
63
|
except Exception as e:
|
|
67
64
|
console.print(f"[red]Failed to import module {module_name}: {str(e)}")
|
StreamingCommunity/run.py
CHANGED
|
@@ -90,11 +90,8 @@ def load_search_functions():
|
|
|
90
90
|
|
|
91
91
|
# Get 'indice' from the module
|
|
92
92
|
indice = getattr(mod, 'indice', 0)
|
|
93
|
-
is_deprecate = bool(getattr(mod, '_deprecate', True))
|
|
94
93
|
use_for = getattr(mod, '_useFor', 'other')
|
|
95
|
-
|
|
96
|
-
if not is_deprecate:
|
|
97
|
-
modules.append((module_name, indice, use_for))
|
|
94
|
+
modules.append((module_name, indice, use_for))
|
|
98
95
|
|
|
99
96
|
except Exception as e:
|
|
100
97
|
console.print(f"[red]Failed to import module {module_name}: {str(e)}")
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
StreamingCommunity/__init__.py,sha256=Cw-N0VCg7sef1WqdtvVwrhs1zc4LoUhs5C8k7vpM1lQ,207
|
|
2
|
-
StreamingCommunity/global_search.py,sha256=
|
|
3
|
-
StreamingCommunity/run.py,sha256=
|
|
2
|
+
StreamingCommunity/global_search.py,sha256=LgRTjVBJYyLiKYa3EIb33vRnVQ-COoQT7gASfVW8-Dg,12022
|
|
3
|
+
StreamingCommunity/run.py,sha256=xBq2GS3JznLZBAF5DnJplNtJBzqOl_zHQXVmXxDMnBs,13108
|
|
4
4
|
StreamingCommunity/Api/Player/ddl.py,sha256=S3UZFonJl3d3xU1fQrosRFXFhwAm8hGVQ8Ff8g-6xSI,2071
|
|
5
5
|
StreamingCommunity/Api/Player/maxstream.py,sha256=WXg8xncFXFiaUmTVXxB3NyknQtbvd0sF1eRaoDO24bU,4822
|
|
6
6
|
StreamingCommunity/Api/Player/mediapolisvod.py,sha256=OcdnE1BMSwPZM-nw74GXNJ44E9RYwGnc_kFEA-G8XyY,2294
|
|
@@ -9,44 +9,44 @@ StreamingCommunity/Api/Player/sweetpixel.py,sha256=gJSe1fop5J216CB3u8vstxLPP5Ybc
|
|
|
9
9
|
StreamingCommunity/Api/Player/vixcloud.py,sha256=qI9ppYEMGaJ1B5y693BOMeRQri-F4-94SfRkS-9udfM,6287
|
|
10
10
|
StreamingCommunity/Api/Player/Helper/Vixcloud/js_parser.py,sha256=U-8QlD5kGzIk3-4t4D6QyYmiDe8UBrSuVi1YHRQb7AU,4295
|
|
11
11
|
StreamingCommunity/Api/Player/Helper/Vixcloud/util.py,sha256=QLUgbwQrpuPIVNzdBlAiEJXnd-eCj_JQFckZZEEL55w,5214
|
|
12
|
-
StreamingCommunity/Api/Site/1337xx/__init__.py,sha256=
|
|
13
|
-
StreamingCommunity/Api/Site/1337xx/site.py,sha256=
|
|
12
|
+
StreamingCommunity/Api/Site/1337xx/__init__.py,sha256=OdQxYoJ9UyGSAutZwqH1FgmOH-Z6vGVHb0CLKhwEZGM,1999
|
|
13
|
+
StreamingCommunity/Api/Site/1337xx/site.py,sha256=lwpZt8ALBd9_ImuFWKrRx6KCIqPmDMdqZCM-n-pxvGI,2283
|
|
14
14
|
StreamingCommunity/Api/Site/1337xx/title.py,sha256=8T3cVRb-Mt9QdOtKWVVFHz8iOHqspf7iw28E7bfTV78,1865
|
|
15
|
-
StreamingCommunity/Api/Site/altadefinizione/__init__.py,sha256=
|
|
15
|
+
StreamingCommunity/Api/Site/altadefinizione/__init__.py,sha256=Oxjfyg6VolwV6n2VGgICLvdRVPPMzJXMSdz8oI2Xs0M,4145
|
|
16
16
|
StreamingCommunity/Api/Site/altadefinizione/film.py,sha256=0XeqMrMHnk5nbFkVTFaNZWtlXI8pETl7dsORDtIMbjg,4395
|
|
17
17
|
StreamingCommunity/Api/Site/altadefinizione/series.py,sha256=-rCYx-Fa7aZiYepcIne7OdH1aaUFZZAPX-ToBv6mxFs,8192
|
|
18
|
-
StreamingCommunity/Api/Site/altadefinizione/site.py,sha256=
|
|
18
|
+
StreamingCommunity/Api/Site/altadefinizione/site.py,sha256=S-ucgLNXUYZPjgSNjEYVxlkpMkJyjpr7mYf_jBcYwqM,2860
|
|
19
19
|
StreamingCommunity/Api/Site/altadefinizione/util/ScrapeSerie.py,sha256=bSApjfY9xd5dw0tZ1t7vB6ifAo5vAkeeEwX6IS7yH1o,3756
|
|
20
|
-
StreamingCommunity/Api/Site/animeunity/__init__.py,sha256=
|
|
20
|
+
StreamingCommunity/Api/Site/animeunity/__init__.py,sha256=EayZqxyWltgjRRDNfM32JRzgeyElK85o6s0_YJ0dpBk,4031
|
|
21
21
|
StreamingCommunity/Api/Site/animeunity/film.py,sha256=Vqg6yag2siR-Y3ougBsV8mzdQXChxg6ghz_KVXFQ3pE,998
|
|
22
22
|
StreamingCommunity/Api/Site/animeunity/serie.py,sha256=ib86sLXYsYbrvrFNbzKdhlwMUO3DT7JS5yTTrrSr2jk,5711
|
|
23
|
-
StreamingCommunity/Api/Site/animeunity/site.py,sha256=
|
|
24
|
-
StreamingCommunity/Api/Site/animeunity/util/ScrapeSerie.py,sha256=
|
|
25
|
-
StreamingCommunity/Api/Site/animeworld/__init__.py,sha256=
|
|
23
|
+
StreamingCommunity/Api/Site/animeunity/site.py,sha256=KLBQ08TAMyzsrZ3SAxw8hZefreCtZAuU1KwEbaJnUAE,5646
|
|
24
|
+
StreamingCommunity/Api/Site/animeunity/util/ScrapeSerie.py,sha256=9q108tS2St3ogR73nGZhMlCTHoZH-taE_CTBC6LY6d0,3374
|
|
25
|
+
StreamingCommunity/Api/Site/animeworld/__init__.py,sha256=UzHQbfxx_i6qzM586LL940CoiI3Y98IGIVP4-hXUxn4,2790
|
|
26
26
|
StreamingCommunity/Api/Site/animeworld/film.py,sha256=W9KOS9Wvx3Mlqx5WojR-NgnF9WX8mI79JZPS7UwG-dc,1763
|
|
27
27
|
StreamingCommunity/Api/Site/animeworld/serie.py,sha256=MXyV1fK05jPW4iV9NWrRKW-R4ect-TSN78-2APayniU,3516
|
|
28
|
-
StreamingCommunity/Api/Site/animeworld/site.py,sha256=
|
|
28
|
+
StreamingCommunity/Api/Site/animeworld/site.py,sha256=1Ah4CmKXdqsoCGTbyPRSVJRAxtcW449kpBnPKnzR1K8,3650
|
|
29
29
|
StreamingCommunity/Api/Site/animeworld/util/ScrapeSerie.py,sha256=CBTCH_wnTXUK_MKwq9a1k_XdvOlUrMpbUmpkD5fXVQ0,3589
|
|
30
|
-
StreamingCommunity/Api/Site/cb01new/__init__.py,sha256=
|
|
30
|
+
StreamingCommunity/Api/Site/cb01new/__init__.py,sha256=fy0dPL0NnZxSz3UL_i_zE809Rus7-ZI60WsXq9S4NUs,2039
|
|
31
31
|
StreamingCommunity/Api/Site/cb01new/film.py,sha256=vjd1ftm4LhxxG0TTKEwlOXtx0AYgxBbV5ZlQH8aSxGU,1695
|
|
32
|
-
StreamingCommunity/Api/Site/cb01new/site.py,sha256=
|
|
33
|
-
StreamingCommunity/Api/Site/ddlstreamitaly/__init__.py,sha256=
|
|
32
|
+
StreamingCommunity/Api/Site/cb01new/site.py,sha256=ROT3yh6mpC85qHJAvPkWply91tFd8-V7ayX_3KsdtR4,2152
|
|
33
|
+
StreamingCommunity/Api/Site/ddlstreamitaly/__init__.py,sha256=2FGeGNJ5SHPQzKEEmVMFWft4woGgJ-XLeNxjbSb6L9s,2141
|
|
34
34
|
StreamingCommunity/Api/Site/ddlstreamitaly/series.py,sha256=F_D_2lwHHWN5hgLs8oUDNCYe-4SEPtWzJoU4yT_Nzfg,3726
|
|
35
|
-
StreamingCommunity/Api/Site/ddlstreamitaly/site.py,sha256=
|
|
35
|
+
StreamingCommunity/Api/Site/ddlstreamitaly/site.py,sha256=hspimNOnIkLdJMrYLgXHmXepLz_mu8z257camnlGfaI,2596
|
|
36
36
|
StreamingCommunity/Api/Site/ddlstreamitaly/util/ScrapeSerie.py,sha256=tETaN-2GyFBeRsoLnGw3Kz4D4j2TMcnPzGjzlC62w_Y,3655
|
|
37
|
-
StreamingCommunity/Api/Site/guardaserie/__init__.py,sha256=
|
|
37
|
+
StreamingCommunity/Api/Site/guardaserie/__init__.py,sha256=p5hzqshw5hwDl9nJ8FBWbzfPe2j7c5eNYiaftDThGcU,2768
|
|
38
38
|
StreamingCommunity/Api/Site/guardaserie/series.py,sha256=U9rMZCjRqHLFjo468vikxl-2RqO6DCJjebB-G8Y6LDg,6492
|
|
39
|
-
StreamingCommunity/Api/Site/guardaserie/site.py,sha256=
|
|
39
|
+
StreamingCommunity/Api/Site/guardaserie/site.py,sha256=DrtHD365Ezh3GGcluvTIJxWYSjhaJpiY1w6pg4M1odw,2321
|
|
40
40
|
StreamingCommunity/Api/Site/guardaserie/util/ScrapeSerie.py,sha256=_aXU-YcUtSwbC2b6QpNnWDZR8m6vp9xzBEx_zdu5tgI,4196
|
|
41
|
-
StreamingCommunity/Api/Site/raiplay/__init__.py,sha256=
|
|
42
|
-
StreamingCommunity/Api/Site/raiplay/film.py,sha256=
|
|
43
|
-
StreamingCommunity/Api/Site/raiplay/series.py,sha256=
|
|
44
|
-
StreamingCommunity/Api/Site/raiplay/site.py,sha256=
|
|
45
|
-
StreamingCommunity/Api/Site/raiplay/util/ScrapeSerie.py,sha256=
|
|
46
|
-
StreamingCommunity/Api/Site/streamingcommunity/__init__.py,sha256=
|
|
41
|
+
StreamingCommunity/Api/Site/raiplay/__init__.py,sha256=xkxVkFsSxA6DHRqPuzQYXnCVNUBhfUG5xxlz6iwf1mw,3132
|
|
42
|
+
StreamingCommunity/Api/Site/raiplay/film.py,sha256=wBv5kQXx7-aCKhAZ5LABZ8zUzu_jPGdXOl9OM2p8dpY,1982
|
|
43
|
+
StreamingCommunity/Api/Site/raiplay/series.py,sha256=uQVbeA_g3Z1Ciqeq99gsY2F8mC5DssH3ueGbCW8gd9Q,6161
|
|
44
|
+
StreamingCommunity/Api/Site/raiplay/site.py,sha256=FtIR_oT-ag1sh5XnaOAhEOE8biHZmXtZnsFAjKszU8U,5154
|
|
45
|
+
StreamingCommunity/Api/Site/raiplay/util/ScrapeSerie.py,sha256=5F6abToCTtsvW8iIACbChZ0fPlymJiCSF_y8FRsDu7M,5002
|
|
46
|
+
StreamingCommunity/Api/Site/streamingcommunity/__init__.py,sha256=Ej-xZ6x99zeq3p5O7-e_Evi_529x3eq_VryBLejCBiA,3796
|
|
47
47
|
StreamingCommunity/Api/Site/streamingcommunity/film.py,sha256=TPt0yB1DKShDIz_1OEVG1IolMoAKBOaWIZ8lQF61dfM,2575
|
|
48
48
|
StreamingCommunity/Api/Site/streamingcommunity/series.py,sha256=jWwgawBovZkL7pafvd55L68AMAy7ZyvCPNZdh72bqq8,8859
|
|
49
|
-
StreamingCommunity/Api/Site/streamingcommunity/site.py,sha256=
|
|
49
|
+
StreamingCommunity/Api/Site/streamingcommunity/site.py,sha256=nKII_DjKN1ePeYdMn4titYgvPRMbm8PmEXIM6npGkeI,3129
|
|
50
50
|
StreamingCommunity/Api/Site/streamingcommunity/util/ScrapeSerie.py,sha256=3sNz9uD-o9xz0dKpSnQsLPC_45v5fnW9Mzas2rQ8-Uc,5579
|
|
51
51
|
StreamingCommunity/Api/Template/__init__.py,sha256=oyfd_4_g5p5q6mxb_rKwSsudZnTM3W3kg1tLwxg-v-Q,46
|
|
52
52
|
StreamingCommunity/Api/Template/config_loader.py,sha256=2RT_0mqQmWzXM4rYaqss-yhXztYAcfNkTalFPjzv270,2056
|
|
@@ -56,16 +56,16 @@ StreamingCommunity/Api/Template/Util/__init__.py,sha256=ZWQQd6iymNFDol9HaKPhVBoR
|
|
|
56
56
|
StreamingCommunity/Api/Template/Util/manage_ep.py,sha256=FYe2DC9SXIXzlRYI7fW4ieBpfrxYzsUgt2C47tYRk7U,9252
|
|
57
57
|
StreamingCommunity/Lib/Downloader/__init__.py,sha256=JhbBh5hOnSM7VmtkxJ7zZ_FtWEC1JdnKThsSBjLV5FY,140
|
|
58
58
|
StreamingCommunity/Lib/Downloader/HLS/downloader.py,sha256=wlujaWn5I5KtP0m61iYExtnEhwmsy_jdFqd9cM1A-2E,21588
|
|
59
|
-
StreamingCommunity/Lib/Downloader/HLS/segments.py,sha256=
|
|
59
|
+
StreamingCommunity/Lib/Downloader/HLS/segments.py,sha256=Q_YZxkWfUqd6TRkHoYt58Iy-xMWVLH6fCnBnQImQK2I,18059
|
|
60
60
|
StreamingCommunity/Lib/Downloader/MP4/downloader.py,sha256=L03fpjaJ2pvZ_McaOShv3iCsdbefCGW3WM1QIa2TGJo,7514
|
|
61
|
-
StreamingCommunity/Lib/Downloader/TOR/downloader.py,sha256=
|
|
61
|
+
StreamingCommunity/Lib/Downloader/TOR/downloader.py,sha256=CrRGdLGI_45AnhtTZm8r7KO7uGmU9k6pywy-qO18LG8,19242
|
|
62
62
|
StreamingCommunity/Lib/FFmpeg/__init__.py,sha256=6PBsZdE1jrD2EKOVyx3JEHnyDZzVeKlPkH5T0zyfOgU,130
|
|
63
|
-
StreamingCommunity/Lib/FFmpeg/capture.py,sha256=
|
|
63
|
+
StreamingCommunity/Lib/FFmpeg/capture.py,sha256=QZYtuUG3L5_BsHFdzBU-5pZrX1PYxfCTx8bXShGF_bs,5029
|
|
64
64
|
StreamingCommunity/Lib/FFmpeg/command.py,sha256=ubpffE02nsZM7xch5gbwGlEiUzecpxcFOd63n2cqM1k,10708
|
|
65
|
-
StreamingCommunity/Lib/FFmpeg/util.py,sha256=
|
|
65
|
+
StreamingCommunity/Lib/FFmpeg/util.py,sha256=byM5DzAA-8Ts0FtviEPfbFJKN_PuxVFGjELgD_FEhsk,9287
|
|
66
66
|
StreamingCommunity/Lib/M3U8/__init__.py,sha256=H_KS2eDd3kVXMziFJnD0FCPvPHEizaqfoA36ElTv_r8,170
|
|
67
67
|
StreamingCommunity/Lib/M3U8/decryptor.py,sha256=kuxxsd3eN0VGRrMJWXzHo8gCpT0u3fSZs_lwxlE5Fqs,2948
|
|
68
|
-
StreamingCommunity/Lib/M3U8/estimator.py,sha256=
|
|
68
|
+
StreamingCommunity/Lib/M3U8/estimator.py,sha256=8gwTxJ3poRqZdHUTD9_oqXegiPWSXFuqLmqCZBnXS8A,5893
|
|
69
69
|
StreamingCommunity/Lib/M3U8/parser.py,sha256=cSjXPOSgTewrfLgREyQ47wzoOeoYo3L4lOfEWZKxad8,22485
|
|
70
70
|
StreamingCommunity/Lib/M3U8/url_fixer.py,sha256=zldE4yOuNBV6AAvL1KI6p7XdRI_R5YZRscbDgT1564M,1735
|
|
71
71
|
StreamingCommunity/Lib/TMBD/__init__.py,sha256=XzE42tw3Ws59DD1PF8WmGtZ0D4D7Hk3Af8QthNE-22U,66
|
|
@@ -74,18 +74,18 @@ StreamingCommunity/Lib/TMBD/tmdb.py,sha256=byg0EFnlmd9JeLvn1N9K3QkB1KEfeMuFa7OVf
|
|
|
74
74
|
StreamingCommunity/TelegramHelp/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
75
75
|
StreamingCommunity/TelegramHelp/telegram_bot.py,sha256=Qe1__aoK4PpDuing8JtWgdHzLee8LuYYyfeLNA7yADU,26307
|
|
76
76
|
StreamingCommunity/Upload/update.py,sha256=mJTKUIOhC2j03sWXUK6oAZxHyObNP2r1fl3y0BC2jes,3351
|
|
77
|
-
StreamingCommunity/Upload/version.py,sha256=
|
|
77
|
+
StreamingCommunity/Upload/version.py,sha256=w7FJx8AjjjVxIMxI1IxHS70oEvmUKg7KBImjlhijaMI,171
|
|
78
78
|
StreamingCommunity/Util/color.py,sha256=NvD0Eni-25oOOkY-szCEoc0lGvzQxyL7xhM0RE4EvUM,458
|
|
79
79
|
StreamingCommunity/Util/config_json.py,sha256=xiE5JNw9HgbBdBqKhlywwWw1EnoyDdG47wcxFDTC8sA,24960
|
|
80
|
-
StreamingCommunity/Util/ffmpeg_installer.py,sha256=
|
|
80
|
+
StreamingCommunity/Util/ffmpeg_installer.py,sha256=yRVIPwbh05tZ-duZmXkH0qasLNxaQCAT_E4cTP79Z3c,14890
|
|
81
81
|
StreamingCommunity/Util/headers.py,sha256=TItkaFMx1GqsVNEIS3Tr0BGU5EHyF-HkZVliHORT3P8,308
|
|
82
82
|
StreamingCommunity/Util/logger.py,sha256=9kGD6GmWj2pM8ADpJc85o7jm8DD0c5Aguqnq-9kmxos,3314
|
|
83
83
|
StreamingCommunity/Util/message.py,sha256=SJaIPLvWeQqsIODVUKw3TgYRmBChovmlbcF6OUxqMI8,1425
|
|
84
|
-
StreamingCommunity/Util/os.py,sha256=
|
|
84
|
+
StreamingCommunity/Util/os.py,sha256=0AD2DYoan9dl1ZC1pjDoUM7D8sRa9p81cGdI-lP1OX4,14993
|
|
85
85
|
StreamingCommunity/Util/table.py,sha256=Nw5PlsvfEIOQZWy5VhsU5OK3heuBXGwsqmLl0k8yQzc,9813
|
|
86
|
-
streamingcommunity-
|
|
87
|
-
streamingcommunity-
|
|
88
|
-
streamingcommunity-
|
|
89
|
-
streamingcommunity-
|
|
90
|
-
streamingcommunity-
|
|
91
|
-
streamingcommunity-
|
|
86
|
+
streamingcommunity-3.0.0.dist-info/licenses/LICENSE,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
|
|
87
|
+
streamingcommunity-3.0.0.dist-info/METADATA,sha256=OwSAYErIcsUYH-VDC9VlXEpNByWJpCBCCZgC-vMu5UY,25012
|
|
88
|
+
streamingcommunity-3.0.0.dist-info/WHEEL,sha256=pxyMxgL8-pra_rKaQ4drOZAegBVuX-G_4nRHjjgWbmo,91
|
|
89
|
+
streamingcommunity-3.0.0.dist-info/entry_points.txt,sha256=Qph9XYfDC8n4LfDLOSl6gJGlkb9eFb5f-JOr_Wb_5rk,67
|
|
90
|
+
streamingcommunity-3.0.0.dist-info/top_level.txt,sha256=YsOcxKP-WOhWpIWgBlh0coll9XUx7aqmRPT7kmt3fH0,19
|
|
91
|
+
streamingcommunity-3.0.0.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|