StreamingCommunity 3.0.9__py3-none-any.whl → 3.1.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.

@@ -5,9 +5,9 @@ import logging
5
5
 
6
6
 
7
7
  # External libraries
8
- import httpx
9
8
  import jsbeautifier
10
9
  from bs4 import BeautifulSoup
10
+ from curl_cffi import requests
11
11
 
12
12
 
13
13
  # Internal utilities
@@ -28,7 +28,6 @@ class VideoSource:
28
28
  - url (str): The URL of the video source.
29
29
  """
30
30
  self.headers = get_headers()
31
- self.client = httpx.Client()
32
31
  self.url = url
33
32
 
34
33
  def make_request(self, url: str) -> str:
@@ -42,8 +41,10 @@ class VideoSource:
42
41
  - str: The response content if successful, None otherwise.
43
42
  """
44
43
  try:
45
- response = self.client.get(url, headers=self.headers, timeout=MAX_TIMEOUT, follow_redirects=True)
46
- response.raise_for_status()
44
+ response = requests.get(url, headers=self.headers, timeout=MAX_TIMEOUT, impersonate="chrome110")
45
+ if response.status_code >= 400:
46
+ logging.error(f"Request failed with status code: {response.status_code}")
47
+ return None
47
48
  return response.text
48
49
 
49
50
  except Exception as e:
@@ -39,6 +39,7 @@ class VideoSource:
39
39
  self.is_series = is_series
40
40
  self.media_id = media_id
41
41
  self.iframe_src = None
42
+ self.window_parameter = None
42
43
 
43
44
  def get_iframe(self, episode_id: int) -> None:
44
45
  """
@@ -109,41 +110,45 @@ class VideoSource:
109
110
  # Parse script to get video information
110
111
  self.parse_script(script_text=script)
111
112
 
113
+ except httpx.HTTPStatusError as e:
114
+ if e.response.status_code == 404:
115
+ console.print("[yellow]This content will be available soon![/yellow]")
116
+ return
117
+
118
+ logging.error(f"Error getting content: {e}")
119
+ raise
120
+
112
121
  except Exception as e:
113
122
  logging.error(f"Error getting content: {e}")
114
123
  raise
115
124
 
116
- def get_playlist(self) -> str:
125
+ def get_playlist(self) -> str | None:
117
126
  """
118
127
  Generate authenticated playlist URL.
119
128
 
120
129
  Returns:
121
- str: Fully constructed playlist URL with authentication parameters
130
+ str | None: Fully constructed playlist URL with authentication parameters, or None if content unavailable
122
131
  """
132
+ if not self.window_parameter:
133
+ return None
134
+
123
135
  params = {}
124
136
 
125
- # Add 'h' parameter if video quality is 1080p
126
137
  if self.canPlayFHD:
127
138
  params['h'] = 1
128
139
 
129
- # Parse the original URL
130
140
  parsed_url = urlparse(self.window_parameter.url)
131
141
  query_params = parse_qs(parsed_url.query)
132
142
 
133
- # Check specifically for 'b=1' in the query parameters
134
143
  if 'b' in query_params and query_params['b'] == ['1']:
135
144
  params['b'] = 1
136
145
 
137
- # Add authentication parameters (token and expiration)
138
146
  params.update({
139
147
  "token": self.window_parameter.token,
140
148
  "expires": self.window_parameter.expires
141
149
  })
142
150
 
143
- # Build the updated query string
144
151
  query_string = urlencode(params)
145
-
146
- # Construct the new URL with updated query parameters
147
152
  return urlunparse(parsed_url._replace(query=query_string))
148
153
 
149
154
 
@@ -61,16 +61,22 @@ def download_film(select_title: MediaItem) -> str:
61
61
  # Extract mostraguarda URL
62
62
  try:
63
63
  response = httpx.get(select_title.url, headers=get_headers(), timeout=10)
64
+ response.raise_for_status()
65
+
64
66
  soup = BeautifulSoup(response.text, 'html.parser')
65
67
  iframes = soup.find_all('iframe')
66
68
  mostraguarda = iframes[0]['src']
67
69
 
68
70
  except Exception as e:
69
71
  console.print(f"[red]Site: {site_constant.SITE_NAME}, request error: {e}, get mostraguarda")
72
+ return None
70
73
 
71
74
  # Extract supervideo URL
75
+ supervideo_url = None
72
76
  try:
73
77
  response = httpx.get(mostraguarda, headers=get_headers(), timeout=10)
78
+ response.raise_for_status()
79
+
74
80
  soup = BeautifulSoup(response.text, 'html.parser')
75
81
  pattern = r'//supervideo\.[^/]+/[a-z]/[a-zA-Z0-9]+'
76
82
  supervideo_match = re.search(pattern, response.text)
@@ -78,7 +84,9 @@ def download_film(select_title: MediaItem) -> str:
78
84
 
79
85
  except Exception as e:
80
86
  console.print(f"[red]Site: {site_constant.SITE_NAME}, request error: {e}, get supervideo URL")
81
-
87
+ console.print("[yellow]This content will be available soon![/yellow]")
88
+ return None
89
+
82
90
  # Init class
83
91
  video_source = VideoSource(supervideo_url)
84
92
  master_playlist = video_source.get_playlist()
@@ -38,38 +38,52 @@ class GetSerieInfo:
38
38
  soup = BeautifulSoup(response.text, "html.parser")
39
39
  self.series_name = soup.find("title").get_text(strip=True).split(" - ")[0]
40
40
 
41
- # Process all seasons
42
- season_items = soup.find_all('div', class_='accordion-item')
43
-
44
- for season_idx, season_item in enumerate(season_items, 1):
45
- season_header = season_item.find('div', class_='accordion-header')
46
- if not season_header:
47
- continue
48
-
49
- season_name = season_header.get_text(strip=True)
41
+ # Find all season dropdowns
42
+ seasons_dropdown = soup.find('div', class_='dropdown seasons')
43
+ if not seasons_dropdown:
44
+ return
45
+
46
+ # Get all season items
47
+ season_items = seasons_dropdown.find_all('span', {'data-season': True})
48
+
49
+ for season_item in season_items:
50
+ season_num = int(season_item['data-season'])
51
+ season_name = season_item.get_text(strip=True)
50
52
 
51
- # Create a new season and get a reference to it
53
+ # Create a new season
52
54
  current_season = self.seasons_manager.add_season({
53
- 'number': season_idx,
55
+ 'number': season_num,
54
56
  'name': season_name
55
57
  })
56
58
 
57
- # Find episodes for this season
58
- episode_divs = season_item.find_all('div', class_='down-episode')
59
- for ep_idx, ep_div in enumerate(episode_divs, 1):
60
- episode_name_tag = ep_div.find('b')
61
- if not episode_name_tag:
59
+ # Find all episodes for this season
60
+ episodes_container = soup.find('div', {'class': 'dropdown mirrors', 'data-season': str(season_num)})
61
+ if not episodes_container:
62
+ continue
63
+
64
+ # Get all episode mirrors for this season
65
+ episode_mirrors = soup.find_all('div', {'class': 'dropdown mirrors',
66
+ 'data-season': str(season_num)})
67
+
68
+ for mirror in episode_mirrors:
69
+ episode_data = mirror.get('data-episode', '').split('-')
70
+ if len(episode_data) != 2:
71
+ continue
72
+
73
+ ep_num = int(episode_data[1])
74
+
75
+ # Find supervideo link
76
+ supervideo_span = mirror.find('span', {'data-id': 'supervideo'})
77
+ if not supervideo_span:
62
78
  continue
63
79
 
64
- episode_name = episode_name_tag.get_text(strip=True)
65
- link_tag = ep_div.find('a', string=lambda text: text and "Supervideo" in text)
66
- episode_url = link_tag['href'] if link_tag else None
80
+ episode_url = supervideo_span.get('data-link', '')
67
81
 
68
82
  # Add episode to the season
69
83
  if current_season:
70
84
  current_season.episodes.add({
71
- 'number': ep_idx,
72
- 'name': episode_name,
85
+ 'number': ep_num,
86
+ 'name': f"Episodio {ep_num}",
73
87
  'url': episode_url
74
88
  })
75
89
 
@@ -1,11 +1,9 @@
1
1
  # 10.12.23
2
2
 
3
- import logging
4
-
5
-
6
3
  # External libraries
4
+ import urllib.parse
7
5
  import httpx
8
- from bs4 import BeautifulSoup
6
+ from curl_cffi import requests
9
7
  from rich.console import Console
10
8
 
11
9
 
@@ -20,92 +18,67 @@ from StreamingCommunity.TelegramHelp.telegram_bot import get_bot_instance
20
18
  from StreamingCommunity.Api.Template.config_loader import site_constant
21
19
  from StreamingCommunity.Api.Template.Class.SearchType import MediaManager
22
20
 
23
-
24
- # Variable
25
21
  console = Console()
26
22
  media_search_manager = MediaManager()
27
23
  table_show_manager = TVShowManager()
28
24
  max_timeout = config_manager.get_int("REQUESTS", "timeout")
29
25
 
30
26
 
31
- def get_token() -> dict:
27
+ def get_token(user_agent: str) -> dict:
32
28
  """
33
- Function to retrieve session tokens from a specified website.
34
-
35
- Parameters:
36
- - site_name (str): The name of the site.
37
- - domain (str): The domain of the site.
38
-
39
- Returns:
40
- - dict: A dictionary containing session tokens. The keys are 'XSRF_TOKEN', 'animeunity_session', and 'csrf_token'.
29
+ Retrieve session cookies from the site.
41
30
  """
42
- response = httpx.get(
43
- url=site_constant.FULL_URL,
44
- timeout=max_timeout
31
+ response = requests.get(
32
+ site_constant.FULL_URL,
33
+ headers={'user-agent': user_agent},
34
+ impersonate="chrome120"
45
35
  )
46
36
  response.raise_for_status()
37
+ all_cookies = {name: value for name, value in response.cookies.items()}
47
38
 
48
- # Initialize variables to store CSRF token
49
- find_csrf_token = None
50
- soup = BeautifulSoup(response.text, "html.parser")
51
-
52
- for html_meta in soup.find_all("meta"):
53
- if html_meta.get('name') == "csrf-token":
54
- find_csrf_token = html_meta.get('content')
55
-
56
- return {
57
- 'animeunity_session': response.cookies['animeunity_session'],
58
- 'csrf_token': find_csrf_token
59
- }
39
+ return {k: urllib.parse.unquote(v) for k, v in all_cookies.items()}
60
40
 
61
41
 
62
- def get_real_title(record):
42
+ def get_real_title(record: dict) -> str:
63
43
  """
64
- Get the real title from a record.
65
-
66
- Parameters:
67
- - record (dict): A dictionary representing a row of JSON data.
68
-
69
- Returns:
70
- - str: The title found in the record. If no title is found, returns None.
44
+ Return the most appropriate title from the record.
71
45
  """
72
- if record['title_eng'] is not None:
46
+ if record.get('title_eng'):
73
47
  return record['title_eng']
74
- elif record['title'] is not None:
48
+ elif record.get('title'):
75
49
  return record['title']
76
50
  else:
77
- return record['title_it']
51
+ return record.get('title_it', '')
78
52
 
79
53
 
80
54
  def title_search(query: str) -> int:
81
55
  """
82
- Function to perform an anime search using both APIs and combine results.
83
-
84
- Parameters:
85
- - query (str): The query to search for.
86
-
87
- Returns:
88
- - int: A number containing the length of media search manager.
56
+ Perform anime search on animeunity.so.
89
57
  """
90
- if site_constant.TELEGRAM_BOT:
58
+ if site_constant.TELEGRAM_BOT:
91
59
  bot = get_bot_instance()
92
-
60
+
93
61
  media_search_manager.clear()
94
62
  table_show_manager.clear()
95
63
  seen_titles = set()
96
64
  choices = [] if site_constant.TELEGRAM_BOT else None
97
65
 
98
- # Create parameter for request
99
- data = get_token()
66
+ user_agent = get_userAgent()
67
+ data = get_token(user_agent)
68
+
100
69
  cookies = {
101
- 'animeunity_session': data.get('animeunity_session')
70
+ 'XSRF-TOKEN': data.get('XSRF-TOKEN', ''),
71
+ 'animeunity_session': data.get('animeunity_session', ''),
102
72
  }
73
+
103
74
  headers = {
104
- 'user-agent': get_userAgent(),
105
- 'x-csrf-token': data.get('csrf_token')
75
+ 'origin': site_constant.FULL_URL,
76
+ 'referer': f"{site_constant.FULL_URL}/",
77
+ 'user-agent': user_agent,
78
+ 'x-xsrf-token': data.get('XSRF-TOKEN', ''),
106
79
  }
107
80
 
108
- # First API call - livesearch
81
+ # First call: /livesearch
109
82
  try:
110
83
  response1 = httpx.post(
111
84
  f'{site_constant.FULL_URL}/livesearch',
@@ -114,15 +87,14 @@ def title_search(query: str) -> int:
114
87
  json={'title': query},
115
88
  timeout=max_timeout
116
89
  )
117
-
118
90
  response1.raise_for_status()
119
- process_results(response1.json()['records'], seen_titles, media_search_manager, choices)
91
+ process_results(response1.json().get('records', []), seen_titles, media_search_manager, choices)
120
92
 
121
93
  except Exception as e:
122
94
  console.print(f"[red]Site: {site_constant.SITE_NAME}, request search error: {e}")
123
95
  return 0
124
96
 
125
- # Second API call - archivio
97
+ # Second call: /archivio/get-animes
126
98
  try:
127
99
  json_data = {
128
100
  'title': query,
@@ -135,7 +107,6 @@ def title_search(query: str) -> int:
135
107
  'dubbed': False,
136
108
  'season': False
137
109
  }
138
-
139
110
  response2 = httpx.post(
140
111
  f'{site_constant.FULL_URL}/archivio/get-animes',
141
112
  cookies=cookies,
@@ -143,30 +114,32 @@ def title_search(query: str) -> int:
143
114
  json=json_data,
144
115
  timeout=max_timeout
145
116
  )
146
-
147
117
  response2.raise_for_status()
148
- process_results(response2.json()['records'], seen_titles, media_search_manager, choices)
118
+ process_results(response2.json().get('records', []), seen_titles, media_search_manager, choices)
149
119
 
150
120
  except Exception as e:
151
121
  console.print(f"Site: {site_constant.SITE_NAME}, archivio search error: {e}")
152
122
 
153
123
  if site_constant.TELEGRAM_BOT and choices and len(choices) > 0:
154
- bot.send_message(f"Lista dei risultati:", choices)
155
-
124
+ bot.send_message("List of results:", choices)
125
+
156
126
  result_count = media_search_manager.get_length()
157
127
  if result_count == 0:
158
128
  console.print(f"Nothing matching was found for: {query}")
159
-
129
+
160
130
  return result_count
161
131
 
132
+
162
133
  def process_results(records: list, seen_titles: set, media_manager: MediaManager, choices: list = None) -> None:
163
- """Helper function to process search results and add unique entries."""
134
+ """
135
+ Add unique results to the media manager and to choices.
136
+ """
164
137
  for dict_title in records:
165
138
  try:
166
139
  title_id = dict_title.get('id')
167
140
  if title_id in seen_titles:
168
141
  continue
169
-
142
+
170
143
  seen_titles.add(title_id)
171
144
  dict_title['name'] = get_real_title(dict_title)
172
145
 
@@ -179,10 +152,9 @@ def process_results(records: list, seen_titles: set, media_manager: MediaManager
179
152
  'episodes_count': dict_title.get('episodes_count'),
180
153
  'image': dict_title.get('imageurl')
181
154
  })
182
-
155
+
183
156
  if choices is not None:
184
- choice_text = f"{len(choices)} - {dict_title.get('name')} ({dict_title.get('type')}) - Episodi: {dict_title.get('episodes_count')}"
157
+ choice_text = f"{len(choices)} - {dict_title.get('name')} ({dict_title.get('type')}) - Episodes: {dict_title.get('episodes_count')}"
185
158
  choices.append(choice_text)
186
-
187
159
  except Exception as e:
188
- print(f"Error parsing a title entry: {e}")
160
+ print(f"Error parsing a title entry: {e}")
@@ -62,6 +62,10 @@ def download_film(select_title: MediaItem, proxy: str = None) -> str:
62
62
  video_source.get_content()
63
63
  master_playlist = video_source.get_playlist()
64
64
 
65
+ if master_playlist is None:
66
+ console.print(f"[red]Site: {site_constant.SITE_NAME}, error: No master playlist found[/red]")
67
+ return None
68
+
65
69
  # Define the filename and path for the downloaded film
66
70
  title_name = os_manager.get_sanitize_file(select_title.name) + ".mp4"
67
71
  mp4_path = os.path.join(site_constant.MOVIE_FOLDER, title_name.replace(".mp4", ""))
@@ -156,7 +156,7 @@ class M3U8Manager:
156
156
  If it's a master playlist, only selects video stream.
157
157
  """
158
158
  if not self.is_master:
159
- self.video_url, self.video_res = self.m3u8_url, "0p"
159
+ self.video_url, self.video_res = self.m3u8_url, "undefined"
160
160
  self.audio_streams = []
161
161
  self.sub_streams = []
162
162
 
@@ -165,8 +165,9 @@ class M3U8Manager:
165
165
  self.video_url, self.video_res = self.parser._video.get_best_uri()
166
166
  elif str(FILTER_CUSTOM_REOLUTION) == "worst":
167
167
  self.video_url, self.video_res = self.parser._video.get_worst_uri()
168
- elif "p" in str(FILTER_CUSTOM_REOLUTION):
169
- self.video_url, self.video_res = self.parser._video.get_custom_uri(int(FILTER_CUSTOM_REOLUTION.replace("p", "")))
168
+ elif str(FILTER_CUSTOM_REOLUTION).replace("p", "").replace("px", "").isdigit():
169
+ resolution_value = int(str(FILTER_CUSTOM_REOLUTION).replace("p", "").replace("px", ""))
170
+ self.video_url, self.video_res = self.parser._video.get_custom_uri(resolution_value)
170
171
  else:
171
172
  logging.error("Resolution not recognized.")
172
173
  self.video_url, self.video_res = self.parser._video.get_best_uri()
@@ -180,10 +181,14 @@ class M3U8Manager:
180
181
 
181
182
  self.sub_streams = []
182
183
  if ENABLE_SUBTITLE:
183
- self.sub_streams = [
184
- s for s in (self.parser._subtitle.get_all_uris_and_names() or [])
185
- if s.get('language') in DOWNLOAD_SPECIFIC_SUBTITLE
186
- ]
184
+ if "*" in DOWNLOAD_SPECIFIC_SUBTITLE:
185
+ self.sub_streams = self.parser._subtitle.get_all_uris_and_names() or []
186
+
187
+ else:
188
+ self.sub_streams = [
189
+ s for s in (self.parser._subtitle.get_all_uris_and_names() or [])
190
+ if s.get('language') in DOWNLOAD_SPECIFIC_SUBTITLE
191
+ ]
187
192
 
188
193
  def log_selection(self):
189
194
  tuple_available_resolution = self.parser._video.get_list_resolution()
@@ -209,9 +214,13 @@ class M3U8Manager:
209
214
  f"[red]Set:[/red] {set_codec_info}"
210
215
  )
211
216
 
217
+ # Get available subtitles and their languages
212
218
  available_subtitles = self.parser._subtitle.get_all_uris_and_names() or []
213
219
  available_sub_languages = [sub.get('language') for sub in available_subtitles]
214
- downloadable_sub_languages = list(set(available_sub_languages) & set(DOWNLOAD_SPECIFIC_SUBTITLE))
220
+
221
+ # If "*" is in DOWNLOAD_SPECIFIC_SUBTITLE, all languages are downloadable
222
+ downloadable_sub_languages = available_sub_languages if "*" in DOWNLOAD_SPECIFIC_SUBTITLE else list(set(available_sub_languages) & set(DOWNLOAD_SPECIFIC_SUBTITLE))
223
+
215
224
  if available_sub_languages:
216
225
  console.print(
217
226
  f"[cyan bold]Subtitle [/cyan bold] [green]Available:[/green] [purple]{', '.join(available_sub_languages)}[/purple] | "
@@ -4,6 +4,7 @@ import os
4
4
  import sys
5
5
  import time
6
6
  import asyncio
7
+ import importlib.metadata
7
8
 
8
9
  # External library
9
10
  import httpx
@@ -11,7 +12,7 @@ from rich.console import Console
11
12
 
12
13
 
13
14
  # Internal utilities
14
- from .version import __version__, __author__, __title__
15
+ from .version import __version__ as source_code_version, __author__, __title__
15
16
  from StreamingCommunity.Util.config_json import config_manager
16
17
  from StreamingCommunity.Util.headers import get_userAgent
17
18
 
@@ -75,7 +76,11 @@ def update():
75
76
  percentual_stars = 0
76
77
 
77
78
  # Get the current version (installed version)
78
- current_version = __version__
79
+ try:
80
+ current_version = importlib.metadata.version(__title__)
81
+ except importlib.metadata.PackageNotFoundError:
82
+ #console.print(f"[yellow]Warning: Could not determine installed version for '{__title__}' via importlib.metadata. Falling back to source version.[/yellow]")
83
+ current_version = source_code_version
79
84
 
80
85
  # Get commit details
81
86
  latest_commit = response_commits[0] if response_commits else None
@@ -1,5 +1,5 @@
1
1
  __title__ = 'StreamingCommunity'
2
- __version__ = '3.0.9'
2
+ __version__ = '3.1.0'
3
3
  __author__ = 'Arrowar'
4
4
  __description__ = 'A command-line program to download film'
5
- __copyright__ = 'Copyright 2024'
5
+ __copyright__ = 'Copyright 2025'
@@ -275,7 +275,7 @@ class ConfigManager:
275
275
  }
276
276
 
277
277
  try:
278
- console.print(f"[bold cyan]Retrieving site data from GitHub:[/bold cyan] [green]{domains_github_url}[/green]")
278
+ console.print(f"[bold cyan]Retrieving site data from GitHub:[/bold cyan]")
279
279
  response = requests.get(domains_github_url, timeout=8, headers=headers)
280
280
 
281
281
  if response.ok:
@@ -35,7 +35,5 @@ def start_message():
35
35
 
36
36
  if SHOW:
37
37
  console.print(f"[purple]{msg}")
38
-
39
- # Print a decorative separator line using asterisks
40
- separator = "_" * (console.width - 2) # Ridotto di 2 per il padding
38
+ separator = "_" * (console.width - 2)
41
39
  console.print(f"[cyan]{separator}[/cyan]\n")
@@ -320,16 +320,19 @@ class InternManager():
320
320
  # except Exception:
321
321
  # return False
322
322
 
323
- def check_dns_resolve(self):
323
+ def check_dns_resolve(self, domains_list: list = None):
324
324
  """
325
325
  Check if the system's current DNS server can resolve a domain name.
326
326
  Works on both Windows and Unix-like systems.
327
327
 
328
+ Args:
329
+ domains_list (list, optional): List of domains to test. Defaults to common domains.
330
+
328
331
  Returns:
329
332
  bool: True if the current DNS server can resolve a domain name,
330
333
  False if can't resolve or in case of errors
331
334
  """
332
- test_domains = ["github.com", "google.com", "microsoft.com", "amazon.com"]
335
+ test_domains = domains_list or ["github.com", "google.com", "microsoft.com", "amazon.com"]
333
336
 
334
337
  try:
335
338
  for domain in test_domains:
@@ -157,7 +157,7 @@ def global_search(search_terms: str = None, selected_sites: list = None):
157
157
 
158
158
  # Display progress information
159
159
  console.print(f"\n[bold green]Searching for:[/bold green] [yellow]{search_terms}[/yellow]")
160
- console.print(f"[bold green]Searching across:[/bold green] {len(selected_sites)} sites")
160
+ console.print(f"[bold green]Searching across:[/bold green] {len(selected_sites)} sites \n")
161
161
 
162
162
  with Progress() as progress:
163
163
  search_task = progress.add_task("[cyan]Searching...", total=len(selected_sites))
@@ -188,7 +188,7 @@ def global_search(search_terms: str = None, selected_sites: list = None):
188
188
  item_dict['source_alias'] = alias
189
189
  all_results[alias].append(item_dict)
190
190
 
191
- console.print(f"[green]Found {len(database.media_list)} results from {site_name}")
191
+ console.print(f"\n[green]Found {len(database.media_list)} results from {site_name}")
192
192
 
193
193
  except Exception as e:
194
194
  console.print(f"[bold red]Error searching {site_name}:[/bold red] {str(e)}")
StreamingCommunity/run.py CHANGED
@@ -9,6 +9,7 @@ import platform
9
9
  import argparse
10
10
  import importlib
11
11
  import threading, asyncio
12
+ from urllib.parse import urlparse
12
13
  from typing import Callable
13
14
 
14
15
 
@@ -153,6 +154,7 @@ def initialize():
153
154
  except:
154
155
  console.log("[red]Error with loading github.")
155
156
 
157
+
156
158
  def restart_script():
157
159
  """Riavvia lo script con gli stessi argomenti della riga di comando."""
158
160
  print("\nRiavvio dello script...\n")
@@ -191,6 +193,11 @@ def force_exit():
191
193
  os._exit(0)
192
194
 
193
195
 
196
+ def _extract_hostname(url_string: str) -> str:
197
+ """Safely extracts the hostname from a URL string."""
198
+ return urlparse(url_string).hostname
199
+
200
+
194
201
  def main(script_id = 0):
195
202
 
196
203
  color_map = {
@@ -200,6 +207,13 @@ def main(script_id = 0):
200
207
  "torrent": "white"
201
208
  }
202
209
 
210
+ category_map = {
211
+ 1: "anime",
212
+ 2: "film_&_serie",
213
+ 3: "serie",
214
+ 4: "torrent"
215
+ }
216
+
203
217
  if TELEGRAM_BOT:
204
218
  bot = get_bot_instance()
205
219
  bot.send_message(f"Avviato script {script_id}", None)
@@ -209,20 +223,11 @@ def main(script_id = 0):
209
223
  # Create logger
210
224
  log_not = Logger()
211
225
  initialize()
212
-
213
- # if not internet_manager.check_dns_provider():
214
- # print()
215
- # console.print("[red]❌ ERROR: DNS configuration is required!")
216
- # console.print("[red]The program cannot function correctly without proper DNS settings.")
217
- # console.print("[yellow]Please configure one of these DNS servers:")
218
- # console.print("[blue]• Cloudflare (1.1.1.1) 'https://developers.cloudflare.com/1.1.1.1/setup/windows/'")
219
- # console.print("[blue]• Quad9 (9.9.9.9) 'https://docs.quad9.net/Setup_Guides/Windows/Windows_10/'")
220
- # console.print("\n[yellow]⚠️ The program will not work until you configure your DNS settings.")
221
-
222
- # time.sleep(2)
223
- # msg.ask("[yellow]Press Enter to continue ...")
224
-
225
- if not internet_manager.check_dns_resolve():
226
+
227
+ # Get all site hostname
228
+ hostname_list = [hostname for site_info in config_manager.configSite.values() if (hostname := _extract_hostname(site_info.get('full_url')))]
229
+
230
+ if not internet_manager.check_dns_resolve(hostname_list):
226
231
  print()
227
232
  console.print("[red]❌ ERROR: DNS configuration is required!")
228
233
  console.print("[red]The program cannot function correctly without proper DNS settings.")
@@ -273,6 +278,11 @@ def main(script_id = 0):
273
278
  '--global', action='store_true', help='Perform a global search across multiple sites.'
274
279
  )
275
280
 
281
+ # Add category selection argument
282
+ parser.add_argument(
283
+ '--category', type=int, help='Select category directly (1: anime, 2: film_&_serie, 3: serie, 4: torrent).'
284
+ )
285
+
276
286
  # Add arguments for search functions
277
287
  parser.add_argument('-s', '--search', default=None, help='Search terms')
278
288
 
@@ -322,35 +332,60 @@ def main(script_id = 0):
322
332
  except Exception as e:
323
333
  console.print(f"[red]Error mapping module {module_name}: {str(e)}")
324
334
 
325
- # Display the category legend
326
- legend_text = " | ".join([f"[{color}]{category.capitalize()}[/{color}]" for category, color in color_map.items()])
327
- console.print(f"\n[bold green]Category Legend:[/bold green] {legend_text}")
335
+ if args.category:
336
+ selected_category = category_map.get(args.category)
337
+ category_sites = []
338
+ for key, label in choice_labels.items():
339
+ if label[1] == selected_category:
340
+ category_sites.append((key, label[0]))
328
341
 
329
- # Construct prompt with proper color mapping
330
- prompt_message = "[green]Insert category [white](" + ", ".join(
331
- [f"[{color_map.get(label[1], 'white')}]{key}: {label[0]}[/{color_map.get(label[1], 'white')}]"
332
- for key, label in choice_labels.items()]
333
- ) + "[white])"
342
+ if len(category_sites) == 1:
343
+ category = category_sites[0][0]
344
+ console.print(f"[green]Selezionato automaticamente: {category_sites[0][1]}[/green]")
334
345
 
335
- if TELEGRAM_BOT:
336
- category_legend_str = "Categorie: \n" + " | ".join([
337
- f"{category.capitalize()}" for category in color_map.keys()
338
- ])
346
+ else:
347
+ sito_prompt_items = [f"[{color_map.get(selected_category, 'white')}]({k}) {v}[/{color_map.get(selected_category, 'white')}]"
348
+ for k, v in category_sites]
349
+ sito_prompt_line = ", ".join(sito_prompt_items)
350
+
351
+ if TELEGRAM_BOT:
352
+ console.print(f"\nInsert site: {sito_prompt_line}")
353
+ category = bot.ask(
354
+ "select_site",
355
+ f"Insert site: {sito_prompt_line}",
356
+ None
357
+ )
358
+ else:
359
+ category = msg.ask(f"\n[cyan]Insert site: {sito_prompt_line}", choices=[k for k, _ in category_sites], show_choices=False)
339
360
 
340
- prompt_message = "Inserisci il sito:\n" + "\n".join(
341
- [f"{key}: {label[0]}" for key, label in choice_labels.items()]
361
+ else:
362
+ legend_text = " | ".join([f"[{color}]{category.capitalize()}[/{color}]" for category, color in color_map.items()])
363
+ console.print(f"\n[bold cyan]Category Legend:[/bold cyan] {legend_text}")
364
+
365
+ prompt_message = "[cyan]Insert site: " + ", ".join(
366
+ [f"[{color_map.get(label[1], 'white')}]({key}) {label[0]}[/{color_map.get(label[1], 'white')}]"
367
+ for key, label in choice_labels.items()]
342
368
  )
343
369
 
344
- console.print(f"\n{prompt_message}")
370
+ if TELEGRAM_BOT:
371
+ category_legend_str = "Categorie: \n" + " | ".join([
372
+ f"{category.capitalize()}" for category in color_map.keys()
373
+ ])
345
374
 
346
- category = bot.ask(
347
- "select_provider",
348
- f"{category_legend_str}\n\n{prompt_message}",
349
- None
350
- )
375
+ prompt_message_telegram = "Inserisci il sito:\n" + "\n".join(
376
+ [f"{key}: {label[0]}" for key, label in choice_labels.items()]
377
+ )
351
378
 
352
- else:
353
- category = msg.ask(prompt_message, choices=list(choice_labels.keys()), default="0", show_choices=False, show_default=False)
379
+ console.print(f"\n{prompt_message_telegram}")
380
+
381
+ category = bot.ask(
382
+ "select_provider",
383
+ f"{category_legend_str}\n\n{prompt_message_telegram}",
384
+ None
385
+ )
386
+
387
+ else:
388
+ category = msg.ask(prompt_message, choices=list(choice_labels.keys()), default="0", show_choices=False, show_default=False)
354
389
 
355
390
  # Run the corresponding function based on user input
356
391
  if category in input_to_function:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: StreamingCommunity
3
- Version: 3.0.9
3
+ Version: 3.1.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
@@ -17,6 +17,7 @@ Requires-Dist: m3u8
17
17
  Requires-Dist: certifi
18
18
  Requires-Dist: psutil
19
19
  Requires-Dist: unidecode
20
+ Requires-Dist: curl_cffi
20
21
  Requires-Dist: dnspython
21
22
  Requires-Dist: jsbeautifier
22
23
  Requires-Dist: pathvalidate
@@ -24,6 +25,7 @@ Requires-Dist: pycryptodomex
24
25
  Requires-Dist: ua-generator
25
26
  Requires-Dist: qbittorrent-api
26
27
  Requires-Dist: pyTelegramBotAPI
28
+ Requires-Dist: beautifulsoup4
27
29
  Dynamic: author
28
30
  Dynamic: description
29
31
  Dynamic: description-content-type
@@ -34,36 +36,32 @@ Dynamic: project-url
34
36
  Dynamic: requires-dist
35
37
  Dynamic: requires-python
36
38
 
37
- <p align="center">
38
- <img src="https://i.ibb.co/v6RnT0wY/s2.jpg" alt="Project Logo" width="450"/>
39
- </p>
40
-
41
- <p align="center">
42
- <a href="https://pypi.org/project/streamingcommunity">
43
- <img src="https://img.shields.io/pypi/v/streamingcommunity?logo=pypi&labelColor=555555&style=for-the-badge" alt="PyPI"/>
44
- </a>
45
- <a href="https://www.paypal.com/donate/?hosted_button_id=UXTWMT8P6HE2C">
46
- <img src="https://img.shields.io/badge/_-Donate-red.svg?logo=githubsponsors&labelColor=555555&style=for-the-badge" alt="Donate"/>
47
- </a>
48
- <a href="https://github.com/Arrowar/StreamingCommunity/commits">
49
- <img src="https://img.shields.io/github/commit-activity/m/Arrowar/StreamingCommunity?label=commits&style=for-the-badge" alt="Commits"/>
50
- </a>
51
- <a href="https://github.com/Arrowar/StreamingCommunity/commits">
52
- <img src="https://img.shields.io/github/last-commit/Arrowar/StreamingCommunity/main?label=&style=for-the-badge&display_timestamp=committer" alt="Last Commit"/>
53
- </a>
54
- </p>
55
-
56
- <p align="center">
57
- <a href="https://github.com/Arrowar/StreamingCommunity/blob/main/LICENSE">
58
- <img src="https://img.shields.io/badge/License-GPL_3.0-blue.svg?style=for-the-badge" alt="License"/>
59
- </a>
60
- <a href="https://pypi.org/project/streamingcommunity">
61
- <img src="https://img.shields.io/pypi/dm/streamingcommunity?style=for-the-badge" alt="PyPI Downloads"/>
62
- </a>
63
- <a href="https://github.com/Arrowar/StreamingCommunity">
64
- <img src="https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/Arrowar/StreamingCommunity/main/.github/media/loc-badge.json&style=for-the-badge" alt="Lines of Code"/>
65
- </a>
66
- </p>
39
+ <div align="center">
40
+
41
+ ## 📊 Project Status & Info
42
+
43
+ [![PyPI Version](https://img.shields.io/pypi/v/streamingcommunity?logo=pypi&logoColor=white&labelColor=2d3748&color=3182ce&style=for-the-badge)](https://pypi.org/project/streamingcommunity)
44
+ [![Downloads](https://img.shields.io/pypi/dm/streamingcommunity?logo=pypi&logoColor=white&labelColor=2d3748&color=38a169&style=for-the-badge)](https://pypi.org/project/streamingcommunity)
45
+ [![License](https://img.shields.io/github/license/Arrowar/StreamingCommunity?logo=gnu&logoColor=white&labelColor=2d3748&color=e53e3e&style=for-the-badge)](https://github.com/Arrowar/StreamingCommunity/blob/main/LICENSE)
46
+
47
+ [![Code Lines](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/Arrowar/StreamingCommunity/main/.github/.domain/loc-badge.json&style=for-the-badge&labelColor=2d3748)](https://github.com/Arrowar/StreamingCommunity)
48
+ [![Last Commit](https://img.shields.io/github/last-commit/Arrowar/StreamingCommunity?logo=git&logoColor=white&labelColor=2d3748&color=805ad5&style=for-the-badge)](https://github.com/Arrowar/StreamingCommunity/commits)
49
+ [![Issues](https://img.shields.io/github/issues/Arrowar/StreamingCommunity?logo=github&logoColor=white&labelColor=2d3748&color=ed8936&style=for-the-badge)](https://github.com/Arrowar/StreamingCommunity/issues)
50
+
51
+ ## 💝 Support the Project
52
+
53
+ [![Donate PayPal](https://img.shields.io/badge/💳_Donate-PayPal-00457C?style=for-the-badge&logo=paypal&logoColor=white&labelColor=2d3748)](https://www.paypal.com/donate/?hosted_button_id=UXTWMT8P6HE2C)
54
+ ## 🚀 Download & Install
55
+
56
+ [![Windows](https://img.shields.io/badge/🪟_Windows-0078D4?style=for-the-badge&logo=windows&logoColor=white&labelColor=2d3748)](https://github.com/Arrowar/StreamingCommunity/releases/latest/download/StreamingCommunity_win.exe)
57
+ [![macOS](https://img.shields.io/badge/🍎_macOS-000000?style=for-the-badge&logo=apple&logoColor=white&labelColor=2d3748)](https://github.com/Arrowar/StreamingCommunity/releases/latest/download/StreamingCommunity_mac)
58
+ [![Linux latest](https://img.shields.io/badge/🐧_Linux_latest-FCC624?style=for-the-badge&logo=linux&logoColor=black&labelColor=2d3748)](https://github.com/Arrowar/StreamingCommunity/releases/latest/download/StreamingCommunity_linux_latest)
59
+ [![Linux 22.04](https://img.shields.io/badge/🐧_Linux_22.04-FCC624?style=for-the-badge&logo=linux&logoColor=black&labelColor=2d3748)](https://github.com/Arrowar/StreamingCommunity/releases/latest/download/StreamingCommunity_linux_previous)
60
+ ---
61
+
62
+ *⚡ **Quick Start:** `pip install streamingcommunity` or download the executable for your platform above*
63
+
64
+ </div>
67
65
 
68
66
  # 📋 Table of Contents
69
67
 
@@ -112,24 +110,6 @@ Dynamic: requires-python
112
110
 
113
111
  # Installation
114
112
 
115
- <p align="center">
116
- <a href="https://github.com/Arrowar/StreamingCommunity/releases/latest/download/StreamingCommunity_win.exe">
117
- <img src="https://img.shields.io/badge/-Windows-blue.svg?style=for-the-badge&logo=windows" alt="Windows">
118
- </a>
119
- <a href="https://github.com/Arrowar/StreamingCommunity/releases/latest/download/StreamingCommunity_mac">
120
- <img src="https://img.shields.io/badge/-macOS-black.svg?style=for-the-badge&logo=apple" alt="macOS">
121
- </a>
122
- <a href="https://github.com/Arrowar/StreamingCommunity/releases/latest/download/StreamingCommunity_linux">
123
- <img src="https://img.shields.io/badge/-Linux-orange.svg?style=for-the-badge&logo=linux" alt="Linux">
124
- </a>
125
- <a href="https://github.com/Arrowar/StreamingCommunity/releases/latest/download/StreamingCommunity_linux_previous">
126
- <img src="https://img.shields.io/badge/-Linux Previous-gray.svg?style=for-the-badge&logo=linux" alt="Linux Previous">
127
- </a>
128
- <a href="https://github.com/Arrowar/StreamingCommunity/releases">
129
- <img src="https://img.shields.io/badge/-All Versions-lightgrey.svg?style=for-the-badge&logo=github" alt="All Versions">
130
- </a>
131
- </p>
132
-
133
113
  ## 1. PyPI Installation
134
114
 
135
115
  Install directly from PyPI:
@@ -554,7 +534,7 @@ To enable qBittorrent integration, follow the setup guide [here](https://github.
554
534
  "download_subtitle": true,
555
535
  "merge_subs": true,
556
536
  "specific_list_subtitles": [
557
- "ita",
537
+ "ita", // Specify language codes or use ["*"] to download all available subtitles
558
538
  "eng"
559
539
  ],
560
540
  "cleanup_tmp_folder": true
@@ -580,6 +560,8 @@ To enable qBittorrent integration, follow the setup guide [here](https://github.
580
560
  - `download_subtitle`: Whether to download subtitles
581
561
  - `merge_subs`: Whether to merge subtitles with video
582
562
  - `specific_list_subtitles`: List of subtitle languages to download
563
+ * Use `["*"]` to download all available subtitles
564
+ * Or specify individual languages like `["ita", "eng"]`
583
565
  * Can be changed with `--specific_list_subtitles ita,eng`
584
566
 
585
567
  #### Cleanup
@@ -731,8 +713,14 @@ python test_run.py --specific_list_audio ita,eng --specific_list_subtitles eng,s
731
713
  # Keep console open after download
732
714
  python test_run.py --not_close true
733
715
 
734
- # Use global search
716
+ # Use global searchAdd commentMore actions
735
717
  python test_run.py --global -s "cars"
718
+
719
+ # Select specific category
720
+ python test_run.py --category 1 # Search in anime category
721
+ python test_run.py --category 2 # Search in movies & series
722
+ python test_run.py --category 3 # Search in series
723
+ python test_run.py --category 4 # Search in torrent category
736
724
  ```
737
725
 
738
726
  # Docker
@@ -826,10 +814,10 @@ python3 telegram_bot.py
826
814
 
827
815
  # Tutorials
828
816
 
829
- - [Windows Tutorial](https://www.youtube.com/watch?v=mZGqK4wdN-k)
830
- - [Linux Tutorial](https://www.youtube.com/watch?v=0qUNXPE_mTg)
831
- - [Pypy Tutorial](https://www.youtube.com/watch?v=C6m9ZKOK0p4)
832
- - [Compiled .exe Tutorial](https://www.youtube.com/watch?v=pm4lqsxkTVo)
817
+ - [Windows](https://www.youtube.com/watch?v=mZGqK4wdN-k)
818
+ - [Linux](https://www.youtube.com/watch?v=0qUNXPE_mTg)
819
+ - [Pypy](https://www.youtube.com/watch?v=C6m9ZKOK0p4)
820
+ - [Compiled](https://www.youtube.com/watch?v=pm4lqsxkTVo)
833
821
 
834
822
  # To Do
835
823
 
@@ -848,9 +836,6 @@ Addon per Stremio che consente lo streaming HTTPS di film, serie, anime e TV in
848
836
  ### 🧩 [streamingcommunity-unofficialapi](https://github.com/Blu-Tiger/streamingcommunity-unofficialapi)
849
837
  API non ufficiale per accedere ai contenuti del sito italiano StreamingCommunity.
850
838
 
851
- ### 🎥 [stream-buddy](https://github.com/Bbalduzz/stream-buddy)
852
- Tool per guardare o scaricare film dalla piattaforma StreamingCommunity.
853
-
854
839
  # Disclaimer
855
840
 
856
841
  This software is provided "as is", without warranty of any kind, express or implied, including but not limited to the warranties of merchantability, fitness for a particular purpose, and noninfringement. In no event shall the authors or copyright holders be liable for any claim, damages, or other liability, whether in an action of contract, tort, or otherwise, arising from, out of, or in connection with the software or the use or other dealings in the software.
@@ -1,28 +1,28 @@
1
1
  StreamingCommunity/__init__.py,sha256=Cw-N0VCg7sef1WqdtvVwrhs1zc4LoUhs5C8k7vpM1lQ,207
2
- StreamingCommunity/global_search.py,sha256=fAl_tRCP8SeQoBifXs7hGX9-7Bd9FlJw69NjsWNUUL0,12396
3
- StreamingCommunity/run.py,sha256=IOMEMkfn4p5hoYbDO2JNt8kIxz3GvgXOn8puzkXjS4I,13067
2
+ StreamingCommunity/global_search.py,sha256=ip3D0OKNRTXHpe_Wy7v2KM-yNZdnnbG5FOBYSSk6wB8,12401
3
+ StreamingCommunity/run.py,sha256=I-FXtuLuBOmn963vs9hkvURLRI6CdVhCsIuuoY8ALF4,14146
4
4
  StreamingCommunity/Api/Player/ddl.py,sha256=S3UZFonJl3d3xU1fQrosRFXFhwAm8hGVQ8Ff8g-6xSI,2071
5
5
  StreamingCommunity/Api/Player/hdplayer.py,sha256=zfPcmtt8f-NfH9yapwwWpVSts-7s47vJ4_XHKJFg0i8,1875
6
6
  StreamingCommunity/Api/Player/maxstream.py,sha256=6y2h7cMSA_kmaeiOWqqyMVBMrtX6HTt2WT0QXxirCxg,4839
7
7
  StreamingCommunity/Api/Player/mediapolisvod.py,sha256=OcdnE1BMSwPZM-nw74GXNJ44E9RYwGnc_kFEA-G8XyY,2294
8
8
  StreamingCommunity/Api/Player/mixdrop.py,sha256=B5KEv-S0xg8b8X2doSxPVcjgwDIlB5TP3m35zfn3v5w,4968
9
- StreamingCommunity/Api/Player/supervideo.py,sha256=hr9QViI-XD0Dqhcx90oaH8_j0d6cxpVaf-EuCjMs6hI,5199
9
+ StreamingCommunity/Api/Player/supervideo.py,sha256=8Gqn3rwlOT-_J9jTkpryo-ZI_hsaEbQg6UoYzg-k0GY,5301
10
10
  StreamingCommunity/Api/Player/sweetpixel.py,sha256=gJSe1fop5J216CB3u8vstxLPP5YbcyoGUH4y3X3-JaQ,1643
11
- StreamingCommunity/Api/Player/vixcloud.py,sha256=I929S-n7h0zBT_4J8ScVVUJsqEHQgz0pVP5Ct_opdTw,6402
11
+ StreamingCommunity/Api/Player/vixcloud.py,sha256=boMyliNNrwVcvbLxVoBq1pBqcMwaCPIQjSzCv_ilSoQ,6531
12
12
  StreamingCommunity/Api/Player/Helper/Vixcloud/js_parser.py,sha256=U-8QlD5kGzIk3-4t4D6QyYmiDe8UBrSuVi1YHRQb7AU,4295
13
13
  StreamingCommunity/Api/Player/Helper/Vixcloud/util.py,sha256=QLUgbwQrpuPIVNzdBlAiEJXnd-eCj_JQFckZZEEL55w,5214
14
14
  StreamingCommunity/Api/Site/1337xx/__init__.py,sha256=-lZenAXIv69E38G1AssvRbdQ5ghZS-DjV-SifsLLpn8,2032
15
15
  StreamingCommunity/Api/Site/1337xx/site.py,sha256=5XVUMTQn1UqMYgo7tPAw7bGMA-tqhQnfeOGKkgGh9OA,2349
16
16
  StreamingCommunity/Api/Site/1337xx/title.py,sha256=8T3cVRb-Mt9QdOtKWVVFHz8iOHqspf7iw28E7bfTV78,1865
17
17
  StreamingCommunity/Api/Site/altadefinizione/__init__.py,sha256=6CF9MCh3AstetNlTqG_uzRUQEmMR4iix2vPzGbl3EWM,4180
18
- StreamingCommunity/Api/Site/altadefinizione/film.py,sha256=nSAko9sWZWAdAZ_bSr0S3tEPJYyLmzNzUmUD8Zuq_eo,3493
18
+ StreamingCommunity/Api/Site/altadefinizione/film.py,sha256=sEPIZFU0Tvvgkk3-KD6yypmvISqLuQWNzl6Q2F76a00,3716
19
19
  StreamingCommunity/Api/Site/altadefinizione/series.py,sha256=-rCYx-Fa7aZiYepcIne7OdH1aaUFZZAPX-ToBv6mxFs,8192
20
20
  StreamingCommunity/Api/Site/altadefinizione/site.py,sha256=2kUNQ8ebYlX5dkSql-CvEhU01TOTNtuyEMIAD6SC3lg,2865
21
- StreamingCommunity/Api/Site/altadefinizione/util/ScrapeSerie.py,sha256=bSApjfY9xd5dw0tZ1t7vB6ifAo5vAkeeEwX6IS7yH1o,3756
21
+ StreamingCommunity/Api/Site/altadefinizione/util/ScrapeSerie.py,sha256=9iulNlnNAhTfI5iKNW3I6pZqYeYwovAswa13L3LPGDM,4251
22
22
  StreamingCommunity/Api/Site/animeunity/__init__.py,sha256=3T-F9Hsq1wlELOAHqYWCxNYHfDeYsQLRYifmQATjh0A,4063
23
23
  StreamingCommunity/Api/Site/animeunity/film.py,sha256=Vqg6yag2siR-Y3ougBsV8mzdQXChxg6ghz_KVXFQ3pE,998
24
24
  StreamingCommunity/Api/Site/animeunity/serie.py,sha256=ib86sLXYsYbrvrFNbzKdhlwMUO3DT7JS5yTTrrSr2jk,5711
25
- StreamingCommunity/Api/Site/animeunity/site.py,sha256=iRFMUdtHricrc09gmVS1kUOQ-EqH_8zafh8ag4HHiUA,5672
25
+ StreamingCommunity/Api/Site/animeunity/site.py,sha256=GLULPQATMHcXiH99d772v1ICH-PnnZgSM3q5__eN-gs,4977
26
26
  StreamingCommunity/Api/Site/animeunity/util/ScrapeSerie.py,sha256=UladSvOlTEVLiV0-rAz45zrET5qRHMuTGuKEpeQoumU,3872
27
27
  StreamingCommunity/Api/Site/animeworld/__init__.py,sha256=fjStJyOl6VBVDgoi6wr2yA0CQ_UQ4atTBzal0gOBgRM,2822
28
28
  StreamingCommunity/Api/Site/animeworld/film.py,sha256=W9KOS9Wvx3Mlqx5WojR-NgnF9WX8mI79JZPS7UwG-dc,1763
@@ -42,7 +42,7 @@ StreamingCommunity/Api/Site/raiplay/series.py,sha256=uQVbeA_g3Z1Ciqeq99gsY2F8mC5
42
42
  StreamingCommunity/Api/Site/raiplay/site.py,sha256=kWo2YPcUOPgsThJU_RahnDwJP4QpkmgzdzRqtoubR5U,3166
43
43
  StreamingCommunity/Api/Site/raiplay/util/ScrapeSerie.py,sha256=V7fFP9KLuMXitRsHtInxUJBcGClfSk_tOUNWFC8pG5A,5807
44
44
  StreamingCommunity/Api/Site/streamingcommunity/__init__.py,sha256=Qgy8nNtC05uwpSF6e0EE0WvsZkLKSKuqjWD1kligaPg,5977
45
- StreamingCommunity/Api/Site/streamingcommunity/film.py,sha256=HMfDve_4xuxeYbenDt9H5MEf1FwQBZNAkpcJEbiMRqA,2609
45
+ StreamingCommunity/Api/Site/streamingcommunity/film.py,sha256=bt6g0c20eQux_cAz-FfobvkIF0wnFhVlBreRxhzV17E,2764
46
46
  StreamingCommunity/Api/Site/streamingcommunity/series.py,sha256=W1KHSrF_rVl757dtLugvqVm7HCjovCHaHZXoGSRjOoI,8903
47
47
  StreamingCommunity/Api/Site/streamingcommunity/site.py,sha256=cqaVM4cNXVqN_5ImeS_c7FI6go3TZPKkDi3XbD93MSQ,4019
48
48
  StreamingCommunity/Api/Site/streamingcommunity/util/ScrapeSerie.py,sha256=Q05e8k2xvWd66jv3jlBtvpTau2J1C0zXw5uHvcimzxY,5664
@@ -58,7 +58,7 @@ StreamingCommunity/Api/Template/Class/SearchType.py,sha256=LOlE8UgraEM0UAVeNCThD
58
58
  StreamingCommunity/Api/Template/Util/__init__.py,sha256=ZWQQd6iymNFDol9HaKPhVBoRX1W-xHJZgU_mZvLVdsM,196
59
59
  StreamingCommunity/Api/Template/Util/manage_ep.py,sha256=FYe2DC9SXIXzlRYI7fW4ieBpfrxYzsUgt2C47tYRk7U,9252
60
60
  StreamingCommunity/Lib/Downloader/__init__.py,sha256=JhbBh5hOnSM7VmtkxJ7zZ_FtWEC1JdnKThsSBjLV5FY,140
61
- StreamingCommunity/Lib/Downloader/HLS/downloader.py,sha256=wlujaWn5I5KtP0m61iYExtnEhwmsy_jdFqd9cM1A-2E,21588
61
+ StreamingCommunity/Lib/Downloader/HLS/downloader.py,sha256=kU7DN7cqdU5Uwo8d3TGXMIdep7QQhtU71Oe0s-Kks1k,22117
62
62
  StreamingCommunity/Lib/Downloader/HLS/segments.py,sha256=Q_YZxkWfUqd6TRkHoYt58Iy-xMWVLH6fCnBnQImQK2I,18059
63
63
  StreamingCommunity/Lib/Downloader/MP4/downloader.py,sha256=L03fpjaJ2pvZ_McaOShv3iCsdbefCGW3WM1QIa2TGJo,7514
64
64
  StreamingCommunity/Lib/Downloader/TOR/downloader.py,sha256=CrRGdLGI_45AnhtTZm8r7KO7uGmU9k6pywy-qO18LG8,19242
@@ -78,19 +78,19 @@ StreamingCommunity/Lib/TMBD/tmdb.py,sha256=byg0EFnlmd9JeLvn1N9K3QkB1KEfeMuFa7OVf
78
78
  StreamingCommunity/TelegramHelp/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
79
79
  StreamingCommunity/TelegramHelp/config.json,sha256=x1rtclDIrlnFcmiAmCQnV3WpnlTl5ds1LRRqECIF7xk,1581
80
80
  StreamingCommunity/TelegramHelp/telegram_bot.py,sha256=zCqj7xBofh9FYfEYl55mgT945jqtKo7qJhn-SMLvAvA,26455
81
- StreamingCommunity/Upload/update.py,sha256=Tp7PdU49rk1bga76_DiaghrbE7Fb3p4iq5S4CqZZy2A,3462
82
- StreamingCommunity/Upload/version.py,sha256=aTDk5HZGG-MlYRi76ZutQ0dPdPG1Lsm1cLMGSfgy38A,171
81
+ StreamingCommunity/Upload/update.py,sha256=V1JrW666IdVKr9hQasGqSGiYYBdCR04sF8EkyMHWweE,3813
82
+ StreamingCommunity/Upload/version.py,sha256=yR3Xi2ywfo47V5pjiyGyHAqv8S3LrLalAH9XqxDkC0Y,170
83
83
  StreamingCommunity/Util/color.py,sha256=NvD0Eni-25oOOkY-szCEoc0lGvzQxyL7xhM0RE4EvUM,458
84
- StreamingCommunity/Util/config_json.py,sha256=bC55i7nJuBQSsdnqQo9QtW4l-Ho2BaF0pJhIVr0nJjA,24321
84
+ StreamingCommunity/Util/config_json.py,sha256=l-NJhmIwSdqenZ3CZFOgWfbLYyEdzfk_PPl5p6VuLYo,24285
85
85
  StreamingCommunity/Util/ffmpeg_installer.py,sha256=yRVIPwbh05tZ-duZmXkH0qasLNxaQCAT_E4cTP79Z3c,14890
86
86
  StreamingCommunity/Util/headers.py,sha256=TItkaFMx1GqsVNEIS3Tr0BGU5EHyF-HkZVliHORT3P8,308
87
87
  StreamingCommunity/Util/logger.py,sha256=9kGD6GmWj2pM8ADpJc85o7jm8DD0c5Aguqnq-9kmxos,3314
88
- StreamingCommunity/Util/message.py,sha256=SJaIPLvWeQqsIODVUKw3TgYRmBChovmlbcF6OUxqMI8,1425
89
- StreamingCommunity/Util/os.py,sha256=zCPlV9hb8hbBJglwnrJU0XGhBu538x3zgdNO5sLQ73c,17176
88
+ StreamingCommunity/Util/message.py,sha256=81vPmsGBusovIhheIO4Ec6p7BYvMj1wE_CthtRyp6OM,1333
89
+ StreamingCommunity/Util/os.py,sha256=8mAZhYsFJ9ZDt9hdFcDqBzAZ0Fv8tM3aqRkdiewK9ok,17330
90
90
  StreamingCommunity/Util/table.py,sha256=Nw5PlsvfEIOQZWy5VhsU5OK3heuBXGwsqmLl0k8yQzc,9813
91
- streamingcommunity-3.0.9.dist-info/licenses/LICENSE,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
92
- streamingcommunity-3.0.9.dist-info/METADATA,sha256=6QMVwuzxoNs3c1xmUXEe_XjNHDBK1_Wb2a70rJQOHqc,24958
93
- streamingcommunity-3.0.9.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
94
- streamingcommunity-3.0.9.dist-info/entry_points.txt,sha256=Qph9XYfDC8n4LfDLOSl6gJGlkb9eFb5f-JOr_Wb_5rk,67
95
- streamingcommunity-3.0.9.dist-info/top_level.txt,sha256=YsOcxKP-WOhWpIWgBlh0coll9XUx7aqmRPT7kmt3fH0,19
96
- streamingcommunity-3.0.9.dist-info/RECORD,,
91
+ streamingcommunity-3.1.0.dist-info/licenses/LICENSE,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
92
+ streamingcommunity-3.1.0.dist-info/METADATA,sha256=sfoMIrQBFMzlTFMNmefin7oNpG0AkKJCSVXhNBLFe5w,25190
93
+ streamingcommunity-3.1.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
94
+ streamingcommunity-3.1.0.dist-info/entry_points.txt,sha256=Qph9XYfDC8n4LfDLOSl6gJGlkb9eFb5f-JOr_Wb_5rk,67
95
+ streamingcommunity-3.1.0.dist-info/top_level.txt,sha256=YsOcxKP-WOhWpIWgBlh0coll9XUx7aqmRPT7kmt3fH0,19
96
+ streamingcommunity-3.1.0.dist-info/RECORD,,