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.

Files changed (38) hide show
  1. StreamingCommunity/Api/Site/1337xx/__init__.py +1 -2
  2. StreamingCommunity/Api/Site/1337xx/site.py +6 -1
  3. StreamingCommunity/Api/Site/altadefinizione/__init__.py +1 -2
  4. StreamingCommunity/Api/Site/altadefinizione/site.py +6 -1
  5. StreamingCommunity/Api/Site/animeunity/__init__.py +1 -2
  6. StreamingCommunity/Api/Site/animeunity/site.py +63 -35
  7. StreamingCommunity/Api/Site/animeunity/util/ScrapeSerie.py +28 -24
  8. StreamingCommunity/Api/Site/animeworld/__init__.py +1 -2
  9. StreamingCommunity/Api/Site/animeworld/site.py +6 -1
  10. StreamingCommunity/Api/Site/cb01new/__init__.py +1 -2
  11. StreamingCommunity/Api/Site/cb01new/site.py +7 -1
  12. StreamingCommunity/Api/Site/ddlstreamitaly/__init__.py +1 -2
  13. StreamingCommunity/Api/Site/ddlstreamitaly/site.py +6 -1
  14. StreamingCommunity/Api/Site/guardaserie/__init__.py +1 -2
  15. StreamingCommunity/Api/Site/guardaserie/site.py +7 -1
  16. StreamingCommunity/Api/Site/raiplay/__init__.py +1 -2
  17. StreamingCommunity/Api/Site/raiplay/film.py +1 -1
  18. StreamingCommunity/Api/Site/raiplay/series.py +1 -1
  19. StreamingCommunity/Api/Site/raiplay/site.py +9 -2
  20. StreamingCommunity/Api/Site/raiplay/util/ScrapeSerie.py +1 -1
  21. StreamingCommunity/Api/Site/streamingcommunity/__init__.py +1 -2
  22. StreamingCommunity/Api/Site/streamingcommunity/site.py +7 -1
  23. StreamingCommunity/Lib/Downloader/HLS/segments.py +7 -15
  24. StreamingCommunity/Lib/Downloader/TOR/downloader.py +7 -14
  25. StreamingCommunity/Lib/FFmpeg/capture.py +1 -5
  26. StreamingCommunity/Lib/FFmpeg/util.py +48 -40
  27. StreamingCommunity/Lib/M3U8/estimator.py +20 -33
  28. StreamingCommunity/Upload/version.py +1 -1
  29. StreamingCommunity/Util/ffmpeg_installer.py +26 -1
  30. StreamingCommunity/Util/os.py +13 -15
  31. StreamingCommunity/global_search.py +1 -4
  32. StreamingCommunity/run.py +1 -4
  33. {streamingcommunity-2.9.9.dist-info → streamingcommunity-3.0.0.dist-info}/METADATA +1 -1
  34. {streamingcommunity-2.9.9.dist-info → streamingcommunity-3.0.0.dist-info}/RECORD +38 -38
  35. {streamingcommunity-2.9.9.dist-info → streamingcommunity-3.0.0.dist-info}/WHEEL +1 -1
  36. {streamingcommunity-2.9.9.dist-info → streamingcommunity-3.0.0.dist-info}/entry_points.txt +0 -0
  37. {streamingcommunity-2.9.9.dist-info → streamingcommunity-3.0.0.dist-info}/licenses/LICENSE +0 -0
  38. {streamingcommunity-2.9.9.dist-info → streamingcommunity-3.0.0.dist-info}/top_level.txt +0 -0
@@ -22,8 +22,7 @@ from .title import download_title
22
22
  # Variable
23
23
  indice = 3
24
24
  _useFor = "film_serie"
25
- _deprecate = False
26
- _priority = 2
25
+ _priority = 0
27
26
  _engineDownload = "tor"
28
27
 
29
28
  console = Console()
@@ -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(search_url, headers={'user-agent': get_userAgent()}, timeout=max_timeout, follow_redirects=True)
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:
@@ -25,8 +25,7 @@ from .series import download_series
25
25
  # Variable
26
26
  indice = 2
27
27
  _useFor = "film_serie"
28
- _deprecate = False
29
- _priority = 1
28
+ _priority = 0
30
29
  _engineDownload = "hls"
31
30
 
32
31
  msg = Prompt()
@@ -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(search_url, headers={'user-agent': get_userAgent()}, timeout=max_timeout, follow_redirects=True)
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:
@@ -25,8 +25,7 @@ from .serie import download_series
25
25
  # Variable
26
26
  indice = 1
27
27
  _useFor = "anime"
28
- _deprecate = False
29
- _priority = 2
28
+ _priority = 0
30
29
  _engineDownload = "mp4"
31
30
 
32
31
  msg = Prompt()
@@ -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 a provided query.
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 = {'animeunity_session': data.get('animeunity_session')}
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
- # Send a POST request to the API endpoint for live search
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
- response = httpx.post(
113
- f'{site_constant.FULL_URL}/livesearch',
114
- cookies=cookies,
115
- headers=headers,
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
- response.raise_for_status()
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}, request search error: {e}")
123
- return 0
150
+ console.print(f"Site: {site_constant.SITE_NAME}, archivio search error: {e}")
124
151
 
125
- # Inizializza la lista delle scelte
126
- if site_constant.TELEGRAM_BOT:
127
- choices = []
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
- for dict_title in response.json()['records']:
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
- # Rename keys for consistency
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
- media_search_manager.add_media({
136
- 'id': dict_title.get('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 site_constant.TELEGRAM_BOT:
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 film entry: {e}")
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 get_info_episode(self, index_ep: int) -> Episode:
66
+ def _fetch_all_episodes(self):
66
67
  """
67
- Fetch detailed information for a specific episode.
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
- params = {
78
- "start_range": index_ep,
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}/{index_ep}",
84
- headers=self.headers,
85
- params=params,
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
- # Return information about the episode
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 episode information: {e}")
96
- return None
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)
@@ -20,8 +20,7 @@ from .film import download_film
20
20
  # Variable
21
21
  indice = 8
22
22
  _useFor = "anime"
23
- _deprecate = False
24
- _priority = 2
23
+ _priority = 0
25
24
  _engineDownload = "mp4"
26
25
 
27
26
  msg = Prompt()
@@ -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(search_url, headers={'User-Agent': get_userAgent()})
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}")
@@ -22,8 +22,7 @@ from .film import download_film
22
22
  # Variable
23
23
  indice = 4
24
24
  _useFor = "film"
25
- _deprecate = False
26
- _priority = 2
25
+ _priority = 0
27
26
  _engineDownload = "mp4"
28
27
 
29
28
  msg = Prompt()
@@ -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(url=search_url, headers={'user-agent': get_userAgent()}, timeout=max_timeout, follow_redirects=True)
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:
@@ -23,8 +23,7 @@ from .series import download_thread
23
23
  # Variable
24
24
  indice = 6
25
25
  _useFor = "serie"
26
- _deprecate = False
27
- _priority = 2
26
+ _priority = 0
28
27
  _engineDownload = "mp4"
29
28
 
30
29
  msg = Prompt()
@@ -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(search_url, headers={'user-agent': get_userAgent()}, timeout=max_timeout, follow_redirects=True)
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:
@@ -22,8 +22,7 @@ from .series import download_series
22
22
  # Variable
23
23
  indice = 5
24
24
  _useFor = "serie"
25
- _deprecate = False
26
- _priority = 2
25
+ _priority = 0
27
26
  _engineDownload = "hls"
28
27
 
29
28
  msg = Prompt()
@@ -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(search_url, headers={'user-agent': get_userAgent()}, timeout=max_timeout, follow_redirects=True)
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:
@@ -21,8 +21,7 @@ from .film import download_film
21
21
  # Variable
22
22
  indice = 8
23
23
  _useFor = "film_serie"
24
- _deprecate = False
25
- _priority = 3
24
+ _priority = 1 # NOTE: Site search need the use of tmbd obj
26
25
  _engineDownload = "hls"
27
26
 
28
27
  msg = Prompt()
@@ -1,4 +1,4 @@
1
- # 3.12.23
1
+ # 21.05.24
2
2
 
3
3
  import os
4
4
  from typing import Tuple
@@ -1,4 +1,4 @@
1
- # 3.12.23
1
+ # 21.05.24
2
2
 
3
3
  import os
4
4
  from typing import Tuple
@@ -1,8 +1,9 @@
1
- # 10.12.23
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(search_url, headers={'user-agent': get_userAgent()}, json=json_data, timeout=max_timeout, follow_redirects=True)
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:
@@ -1,4 +1,4 @@
1
- # 01.03.24
1
+ # 21.05.24
2
2
 
3
3
  import logging
4
4
 
@@ -26,8 +26,7 @@ from .series import download_series
26
26
  # Variable
27
27
  indice = 0
28
28
  _useFor = "film_serie"
29
- _deprecate = False
30
- _priority = 1
29
+ _priority = 0
31
30
  _engineDownload = "hls"
32
31
 
33
32
  msg = Prompt()
@@ -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(search_url, headers={'user-agent': get_userAgent()}, timeout=max_timeout, follow_redirects=True)
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, get_use_large_bar
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
- if not get_use_large_bar():
411
- return (
412
- f"{Colors.YELLOW}Proc{Colors.WHITE}: "
413
- f"{Colors.RED}{{percentage:.2f}}% "
414
- f"{Colors.CYAN}{{remaining}}{{postfix}} {Colors.WHITE}]"
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, get_use_large_bar
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 based on device
320
- if get_use_large_bar():
321
- bar_format = (
322
- f"{Colors.YELLOW}[TOR] {Colors.WHITE}({Colors.CYAN}video{Colors.WHITE}): "
323
- f"{Colors.RED}{{percentage:.2f}}% {Colors.MAGENTA}{{bar}} {Colors.WHITE}[ "
324
- f"{Colors.YELLOW}{{elapsed}} {Colors.WHITE}< {Colors.CYAN}{{remaining}}{{postfix}} {Colors.WHITE}]"
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"FFMPEG line: {line}")
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
- # Use subprocess.Popen instead of run to better handle crashes
149
- cmd = [get_ffprobe_path(), '-v', 'error', '-show_format', '-show_streams', '-print_format', 'json', file_path]
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
- with subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True) as proc:
153
- stdout, stderr = proc.communicate()
154
-
155
- if proc.returncode != 0:
156
- logging.error(f"FFprobe failed with return code {proc.returncode} for file {file_path}")
157
- if stderr:
158
- logging.error(f"FFprobe stderr: {stderr}")
159
- return {
160
- 'format_name': None,
161
- 'codec_names': []
162
- }
163
-
164
- # Make sure we have valid JSON before parsing
165
- if not stdout or not stdout.strip():
166
- logging.warning(f"FFprobe returned empty output for file {file_path}")
167
- return {
168
- 'format_name': None,
169
- 'codec_names': []
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': 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"Failed to get ffprobe info for file {file_path}: {e}")
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
- if get_use_large_bar():
37
- logging.debug("USE_LARGE_BAR is True, starting speed capture thread")
38
- self.speed_thread = threading.Thread(target=self.capture_speed)
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
- if get_use_large_bar():
137
- # Get speed data outside of any locks
138
- speed_data = ["N/A", ""]
139
- with self.lock:
140
- download_speed = self.speed['download']
141
-
142
- if download_speed != "N/A":
143
- speed_data = download_speed.split(" ")
144
-
145
- average_internet_speed = speed_data[0] if len(speed_data) >= 1 else "N/A"
146
- average_internet_unit = speed_data[1] if len(speed_data) >= 2 else ""
147
-
148
- progress_str = (
149
- f"{Colors.GREEN}{number_file_total_size} {Colors.RED}{units_file_total_size}"
150
- f"{Colors.WHITE}, {Colors.CYAN}{average_internet_speed} {Colors.RED}{average_internet_unit} "
151
- #f"{Colors.WHITE}, {Colors.GREEN}CRR {Colors.RED}{retry_count} "
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
 
@@ -1,5 +1,5 @@
1
1
  __title__ = 'StreamingCommunity'
2
- __version__ = '2.9.9'
2
+ __version__ = '3.0.0'
3
3
  __author__ = 'Arrowar'
4
4
  __description__ = 'A command-line program to download film'
5
5
  __copyright__ = 'Copyright 2024'
@@ -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
@@ -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 path.startswith('\\\\') or path.startswith('//'):
119
- parts = path.replace('/', '\\').split('\\')
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(path) >= 2 and path[1] == ':':
133
- drive = path[:2]
134
- rest = path[2:].lstrip('\\').lstrip('/')
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 = path.replace('/', '\\').split('\\')
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 = path.startswith('/')
149
- parts = path.replace('\\', '/').split('/')
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
  Metadata-Version: 2.4
2
2
  Name: StreamingCommunity
3
- Version: 2.9.9
3
+ Version: 3.0.0
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
@@ -1,6 +1,6 @@
1
1
  StreamingCommunity/__init__.py,sha256=Cw-N0VCg7sef1WqdtvVwrhs1zc4LoUhs5C8k7vpM1lQ,207
2
- StreamingCommunity/global_search.py,sha256=1U74JtXLWDGC_r5KCsQt4kC-XRO76QIWk3QnUz-1AqY,12126
3
- StreamingCommunity/run.py,sha256=G4n1n6BrJv0Y32jCs25LKgUzXaSkFe3F5DaZknnehdA,13212
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=epPpqKWmrNnPegZhOr23fS4KEKZd68KG0lBjZuG-cGg,2018
13
- StreamingCommunity/Api/Site/1337xx/site.py,sha256=XHG2Ojhmj2eutyWJPIICZkJUSvpa4IEB7xsNs1Dqcfk,2222
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=Kk1DRi9zLwGF1bM9WyYTw-t41ZkPbaUdt2Prsr9MeY8,4164
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=oO7-6h1jLyFo5BiV8diHR16VtYDCkaKUX_cRrYLZvZo,2799
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=usma9w5aMo-glI0osJDcq94Zp0qM2Jpd94rpw4UuBJA,4050
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=2YPoT3aICpIXVSKmtRRTpqmn82lVGDYOxm0GGKd1KuI,4861
24
- StreamingCommunity/Api/Site/animeunity/util/ScrapeSerie.py,sha256=1mVRmNQcIp4RpNxh0Iin4l4_t6P5kbPAhGm5SG-UQQw,3188
25
- StreamingCommunity/Api/Site/animeworld/__init__.py,sha256=_0-aGTpjfyVs-5Hvbm9YaXFBEN9OkRP0dzCdCWu4kcg,2809
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=tmTOsSBlDnCpTqF96dR2rVEfyYJ8gpjjYU_MOFucuLc,3556
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=1A2UaDkDY42GTJS8h0ASXx5_fyff4-9HvBtfHp3KL2E,2058
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=_JPKP2BMK5SL_QZPtt7mbDdef_t0J7QO7QDKVw6xm-4,2068
33
- StreamingCommunity/Api/Site/ddlstreamitaly/__init__.py,sha256=YRxyKamo566VyMQVGZV640xzn2D3oG3gTekJZvcIjYo,2160
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=t9fR7safcenl_wR46wuZofydKPEfo0z9ZdmwE9nEAPg,2535
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=qz-BcSx_bpSylKY-fJ15X2prqokMmIZLZ_0ZWycYE5Y,2787
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=L_7GTbPkOLXGugAfUv0QtKdE86bHvuIemq7wikg6UTQ,2233
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=b2wT8il9ez9SjaCfJktzRIxBGBg8rgknKnNDy0wXkA8,3091
42
- StreamingCommunity/Api/Site/raiplay/film.py,sha256=lEsl9QPnqd37V7Zgk0H0dK-_zLs8J-1HtBy8D58lDxU,1981
43
- StreamingCommunity/Api/Site/raiplay/series.py,sha256=XNZTENH1LcI7c7Mwat5LTPUjxKaEmuKSkeH8OGwK34w,6160
44
- StreamingCommunity/Api/Site/raiplay/site.py,sha256=bZMUWfENihmtdz83JxYr08Rkm6B84tQUOoW7qDt4e9k,5079
45
- StreamingCommunity/Api/Site/raiplay/util/ScrapeSerie.py,sha256=7Tj6wqym24iqtKEoBu84rGepwCdIQnfpY0dyPeKVN-8,5002
46
- StreamingCommunity/Api/Site/streamingcommunity/__init__.py,sha256=5K0BV2uOff0_ZcJz9MZZvjY1nuTHDCRJiWxaNdwemiY,3815
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=IN1QguMznYkEHppvCDOLlcZHGQghWlU0I-xJbV4j2Yo,3041
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=neyguz95O2TIvqjVAHnfm9tbhNrazdXES-XsuNY2iX4,18380
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=8WC4_vXAjqkoWVtXAaA6EOzlA45qBwHr_DCMQO7mYNw,19608
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=73BEpTijksErZOu46iRxwl3idKzZ-sVXXRr4nocIGY0,5168
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=KbYzQ0sKEu8nJQDxU4atBfjt_0407fioAIeiBZyf-EY,8976
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=zI6zGxcjni8m2ACX92xdIUMcsvzih5XZHWLYA1_3Q7o,6558
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=hIxfVUyMRZT4Rei72y8Gxb_eQelKIjd-qiaif3nguAc,171
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=q5yb_ZXKe9PhcG7JbKLfo1AZa8DNukgHqymPbudDuAY,13585
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=MUGJKQbNMWeoUrnJ2Ug3hoyYlrPDqU9BY94UmiUbxfA,14858
84
+ StreamingCommunity/Util/os.py,sha256=0AD2DYoan9dl1ZC1pjDoUM7D8sRa9p81cGdI-lP1OX4,14993
85
85
  StreamingCommunity/Util/table.py,sha256=Nw5PlsvfEIOQZWy5VhsU5OK3heuBXGwsqmLl0k8yQzc,9813
86
- streamingcommunity-2.9.9.dist-info/licenses/LICENSE,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
87
- streamingcommunity-2.9.9.dist-info/METADATA,sha256=h-OgYPUHv0omVOC1eBCAiURr--kmZO4WNgA4QqzjdTc,25012
88
- streamingcommunity-2.9.9.dist-info/WHEEL,sha256=CmyFI0kx5cdEMTLiONQRbGQwjIoR1aIYB7eCAQ4KPJ0,91
89
- streamingcommunity-2.9.9.dist-info/entry_points.txt,sha256=Qph9XYfDC8n4LfDLOSl6gJGlkb9eFb5f-JOr_Wb_5rk,67
90
- streamingcommunity-2.9.9.dist-info/top_level.txt,sha256=YsOcxKP-WOhWpIWgBlh0coll9XUx7aqmRPT7kmt3fH0,19
91
- streamingcommunity-2.9.9.dist-info/RECORD,,
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,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (78.1.0)
2
+ Generator: setuptools (79.0.0)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5