StreamingCommunity 2.6.0__py3-none-any.whl → 2.7.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 (47) hide show
  1. StreamingCommunity/Api/Player/Helper/Vixcloud/util.py +26 -2
  2. StreamingCommunity/Api/Player/ddl.py +2 -2
  3. StreamingCommunity/Api/Player/maxstream.py +3 -3
  4. StreamingCommunity/Api/Player/supervideo.py +2 -2
  5. StreamingCommunity/Api/Player/vixcloud.py +16 -18
  6. StreamingCommunity/Api/Site/1337xx/site.py +11 -4
  7. StreamingCommunity/Api/Site/1337xx/title.py +3 -4
  8. StreamingCommunity/Api/Site/animeunity/film_serie.py +5 -4
  9. StreamingCommunity/Api/Site/animeunity/site.py +9 -3
  10. StreamingCommunity/Api/Site/animeunity/util/ScrapeSerie.py +8 -9
  11. StreamingCommunity/Api/Site/cb01new/site.py +12 -4
  12. StreamingCommunity/Api/Site/ddlstreamitaly/site.py +10 -4
  13. StreamingCommunity/Api/Site/ddlstreamitaly/util/ScrapeSerie.py +2 -2
  14. StreamingCommunity/Api/Site/guardaserie/site.py +17 -11
  15. StreamingCommunity/Api/Site/guardaserie/util/ScrapeSerie.py +4 -3
  16. StreamingCommunity/Api/Site/mostraguarda/film.py +11 -6
  17. StreamingCommunity/Api/Site/streamingcommunity/__init__.py +3 -5
  18. StreamingCommunity/Api/Site/streamingcommunity/film.py +1 -1
  19. StreamingCommunity/Api/Site/streamingcommunity/series.py +6 -7
  20. StreamingCommunity/Api/Site/streamingcommunity/site.py +14 -63
  21. StreamingCommunity/Api/Site/streamingcommunity/util/ScrapeSerie.py +9 -24
  22. StreamingCommunity/Api/Template/Util/get_domain.py +11 -72
  23. StreamingCommunity/Api/Template/Util/manage_ep.py +28 -23
  24. StreamingCommunity/Api/Template/config_loader.py +6 -2
  25. StreamingCommunity/Lib/Downloader/HLS/downloader.py +2 -2
  26. StreamingCommunity/Lib/Downloader/HLS/proxyes.py +2 -2
  27. StreamingCommunity/Lib/Downloader/HLS/segments.py +5 -5
  28. StreamingCommunity/Lib/Downloader/MP4/downloader.py +2 -2
  29. StreamingCommunity/Upload/update.py +3 -3
  30. StreamingCommunity/Upload/version.py +1 -1
  31. StreamingCommunity/Util/_jsonConfig.py +209 -96
  32. StreamingCommunity/Util/headers.py +8 -1
  33. StreamingCommunity/Util/table.py +6 -6
  34. StreamingCommunity/run.py +13 -9
  35. {StreamingCommunity-2.6.0.dist-info → StreamingCommunity-2.7.0.dist-info}/METADATA +39 -24
  36. {StreamingCommunity-2.6.0.dist-info → StreamingCommunity-2.7.0.dist-info}/RECORD +40 -47
  37. StreamingCommunity/Api/Site/altadefinizionegratis/__init__.py +0 -76
  38. StreamingCommunity/Api/Site/altadefinizionegratis/film.py +0 -76
  39. StreamingCommunity/Api/Site/altadefinizionegratis/site.py +0 -109
  40. StreamingCommunity/Api/Site/ilcorsaronero/__init__.py +0 -53
  41. StreamingCommunity/Api/Site/ilcorsaronero/site.py +0 -64
  42. StreamingCommunity/Api/Site/ilcorsaronero/title.py +0 -42
  43. StreamingCommunity/Api/Site/ilcorsaronero/util/ilCorsarScraper.py +0 -149
  44. {StreamingCommunity-2.6.0.dist-info → StreamingCommunity-2.7.0.dist-info}/LICENSE +0 -0
  45. {StreamingCommunity-2.6.0.dist-info → StreamingCommunity-2.7.0.dist-info}/WHEEL +0 -0
  46. {StreamingCommunity-2.6.0.dist-info → StreamingCommunity-2.7.0.dist-info}/entry_points.txt +0 -0
  47. {StreamingCommunity-2.6.0.dist-info → StreamingCommunity-2.7.0.dist-info}/top_level.txt +0 -0
@@ -4,97 +4,230 @@ import os
4
4
  import sys
5
5
  import json
6
6
  import logging
7
- from pathlib import Path
7
+ import requests
8
8
  from typing import Any, List
9
9
 
10
10
 
11
+ # External library
12
+ from rich.console import Console
13
+
14
+
15
+ # Variable
16
+ console = Console()
17
+
18
+
11
19
  class ConfigManager:
12
20
  def __init__(self, file_name: str = 'config.json') -> None:
13
21
  """Initialize the ConfigManager.
14
22
 
15
23
  Parameters:
16
- - file_path (str, optional): The path to the configuration file. Default is 'config.json'.
24
+ - file_name (str, optional): The name of the configuration file. Default is 'config.json'.
17
25
  """
18
- self.file_path = Path(__file__).parent.parent.parent / file_name
26
+ if getattr(sys, 'frozen', False):
27
+ base_path = os.path.join(".")
28
+ else:
29
+ base_path = os.path.abspath(os.path.join(os.path.dirname(__file__), '..', '..'))
30
+
31
+ self.file_path = os.path.join(base_path, file_name)
32
+ self.domains_path = os.path.join(base_path, 'domains.json')
19
33
  self.config = {}
34
+ self.configSite = {}
20
35
  self.cache = {}
36
+ self.reference_config_url = 'https://raw.githubusercontent.com/Arrowar/StreamingCommunity/refs/heads/main/config.json'
37
+
38
+ # Validate and update config before proceeding
39
+ self._validate_and_update_config()
40
+ self._read_initial_config()
41
+
42
+ console.print(f"[bold cyan]📂 Configuration file path:[/bold cyan] [green]{self.file_path}[/green]")
43
+
44
+ def _validate_and_update_config(self) -> None:
45
+ """Validate local config against reference config and update missing keys."""
46
+ try:
47
+ # Load local config if exists
48
+ local_config = {}
49
+ if os.path.exists(self.file_path):
50
+ with open(self.file_path, 'r') as f:
51
+ local_config = json.load(f)
52
+ console.print("[bold cyan]📖 Local configuration found.[/bold cyan]")
53
+
54
+ # Download reference config
55
+ console.print("[bold cyan]🌍 Downloading reference configuration...[/bold cyan]")
56
+ response = requests.get(self.reference_config_url)
57
+ if response.status_code != 200:
58
+ raise Exception(f"Failed to download reference config. Status code: {response.status_code}")
59
+ reference_config = response.json()
60
+
61
+ # Compare and update missing keys
62
+ merged_config = self._deep_merge_configs(local_config, reference_config)
63
+
64
+ if merged_config != local_config:
65
+ # Save the merged config
66
+ with open(self.file_path, 'w') as f:
67
+ json.dump(merged_config, f, indent=4)
68
+ console.print("[bold green]✅ Configuration updated with missing keys.[/bold green]")
69
+ else:
70
+ console.print("[bold green]✅ Configuration is up to date.[/bold green]")
71
+
72
+ self.config = merged_config
73
+
74
+ except Exception as e:
75
+ console.print(f"[bold red]❌ Error validating configuration: {e}[/bold red]")
76
+ if not self.config:
77
+ # If validation failed and we have no config, download the reference config
78
+ self.download_requirements(self.reference_config_url, self.file_path)
79
+ with open(self.file_path, 'r') as f:
80
+ self.config = json.load(f)
81
+
82
+ def _deep_merge_configs(self, local_config: dict, reference_config: dict) -> dict:
83
+ """
84
+ Recursively merge reference config into local config, preserving local values.
85
+
86
+ Args:
87
+ local_config (dict): The local configuration
88
+ reference_config (dict): The reference configuration
89
+
90
+ Returns:
91
+ dict: Merged configuration
92
+ """
93
+ merged = local_config.copy()
94
+
95
+ for key, value in reference_config.items():
96
+ if key not in merged:
97
+ merged[key] = value
98
+ elif isinstance(value, dict) and isinstance(merged[key], dict):
99
+ merged[key] = self._deep_merge_configs(merged[key], value)
100
+
101
+ return merged
102
+
103
+ def _read_initial_config(self) -> None:
104
+ """Read initial configuration to get use_api setting."""
105
+ try:
106
+ if os.path.exists(self.file_path):
107
+ with open(self.file_path, 'r') as f:
108
+ self.config = json.load(f)
109
+ self.use_api = self.config.get('DEFAULT', {}).get('use_api', True)
110
+ else:
111
+ self.use_api = True # Default to True if config file doesn't exist
112
+ console.print("[bold yellow]⚠️ Configuration file not found. Using default settings.[/bold yellow]")
113
+
114
+ except Exception as e:
115
+ self.use_api = True # Default to True in case of error
116
+ logging.error(f"❌ Error reading initial configuration: {e}")
21
117
 
22
118
  def read_config(self) -> None:
23
119
  """Read the configuration file."""
24
120
  try:
25
- logging.info(f"Reading file: {self.file_path}")
121
+ logging.info(f"📖 Reading file: {self.file_path}")
26
122
 
27
123
  # Check if file exists
28
124
  if os.path.exists(self.file_path):
29
125
  with open(self.file_path, 'r') as f:
30
126
  self.config = json.load(f)
31
- logging.info("Configuration file loaded successfully.")
32
-
33
- # Download config.json if it doesn't exist locally
127
+ console.print("[bold green]✅ Configuration file loaded successfully.[/bold green]")
34
128
  else:
35
- logging.info("Configuration file does not exist. Downloading...")
36
- self.download_requirements(
37
- 'https://raw.githubusercontent.com/Arrowar/StreamingCommunity/refs/heads/main/config.json',
38
- self.file_path
39
- )
129
+ console.print("[bold yellow]⚠️ Configuration file not found. Downloading...[/bold yellow]")
130
+ self.download_requirements(self.reference_config_url, self.file_path)
40
131
 
41
132
  # Load the downloaded config.json into the config attribute
42
133
  with open(self.file_path, 'r') as f:
43
134
  self.config = json.load(f)
44
- logging.info("Configuration file downloaded and saved.")
135
+ console.print("[bold green]✅ Configuration file downloaded and saved.[/bold green]")
45
136
 
46
- logging.info("Configuration file processed successfully.")
137
+ # Update site configuration separately
138
+ self.update_site_config()
139
+
140
+ console.print("[bold cyan]🔧 Configuration file processing complete.[/bold cyan]")
47
141
 
48
142
  except Exception as e:
49
- logging.error(f"Error reading configuration file: {e}")
143
+ logging.error(f"Error reading configuration file: {e}")
50
144
 
51
- def download_requirements(self, url: str, filename: str):
145
+ def download_requirements(self, url: str, filename: str) -> None:
52
146
  """
53
- Download the requirements.txt file from the specified URL if not found locally using requests.
147
+ Download a file from the specified URL if not found locally using requests.
54
148
 
55
149
  Args:
56
- url (str): The URL to download the requirements file from.
57
- filename (str): The local filename to save the requirements file as.
150
+ url (str): The URL to download the file from.
151
+ filename (str): The local filename to save the file as.
58
152
  """
59
153
  try:
60
- import requests
61
-
62
- logging.info(f"{filename} not found locally. Downloading from {url}...")
154
+ logging.info(f"🌍 Downloading {filename} from {url}...")
63
155
  response = requests.get(url)
64
156
 
65
157
  if response.status_code == 200:
66
158
  with open(filename, 'wb') as f:
67
159
  f.write(response.content)
68
-
160
+ console.print(f"[bold green]✅ Successfully downloaded {filename}.[/bold green]")
161
+
69
162
  else:
70
- logging.error(f"Failed to download {filename}. HTTP Status code: {response.status_code}")
163
+ logging.error(f"Failed to download {filename}. HTTP Status code: {response.status_code}")
71
164
  sys.exit(0)
72
165
 
73
166
  except Exception as e:
74
- logging.error(f"Failed to download {filename}: {e}")
167
+ logging.error(f"Failed to download {filename}: {e}")
75
168
  sys.exit(0)
76
169
 
77
- def read_key(self, section: str, key: str, data_type: type = str) -> Any:
78
- """Read a key from the configuration file.
170
+ def update_site_config(self) -> None:
171
+ """Fetch and update the site configuration with data from the API or local file."""
172
+ if self.use_api:
173
+ headers = {
174
+ "apikey": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6Inp2Zm5ncG94d3Jnc3duenl0YWRoIiwicm9sZSI6ImFub24iLCJpYXQiOjE3NDAxNTIxNjMsImV4cCI6MjA1NTcyODE2M30.FNTCCMwi0QaKjOu8gtZsT5yQttUW8QiDDGXmzkn89QE",
175
+ "Authorization": f"Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6Inp2Zm5ncG94d3Jnc3duenl0YWRoIiwicm9sZSI6ImFub24iLCJpYXQiOjE3NDAxNTIxNjMsImV4cCI6MjA1NTcyODE2M30.FNTCCMwi0QaKjOu8gtZsT5yQttUW8QiDDGXmzkn89QE",
176
+ "Content-Type": "application/json"
177
+ }
178
+
179
+ try:
180
+ console.print("[bold cyan]🌍 Fetching SITE data from API...[/bold cyan]")
181
+ response = requests.get("https://zvfngpoxwrgswnzytadh.supabase.co/rest/v1/public", headers=headers)
182
+
183
+ if response.status_code == 200:
184
+ self.configSite = response.json()[0]['data']
185
+ console.print("[bold green]✅ SITE data successfully fetched.[/bold green]")
186
+ else:
187
+ console.print(f"[bold red]❌ Failed to fetch SITE data. HTTP Status code: {response.status_code}[/bold red]")
188
+
189
+ except Exception as e:
190
+ console.print(f"[bold red]❌ Error fetching SITE data: {e}[/bold red]")
191
+ else:
192
+ try:
193
+ if os.path.exists(self.domains_path):
194
+ console.print("[bold cyan]📖 Reading domains from local file...[/bold cyan]")
195
+ with open(self.domains_path, 'r') as f:
196
+ self.configSite = json.load(f)
197
+ console.print("[bold green]✅ Domains loaded successfully from local file.[/bold green]")
198
+ else:
199
+ error_msg = "❌ domains.json not found and API usage is disabled"
200
+ console.print(f"[bold red]{error_msg}[/bold red]")
201
+ raise FileNotFoundError(error_msg)
202
+
203
+ except Exception as e:
204
+ console.print(f"[bold red]❌ Error reading domains file: {e}[/bold red]")
205
+ raise
206
+
207
+ def read_key(self, section: str, key: str, data_type: type = str, from_site: bool = False) -> Any:
208
+ """Read a key from the configuration.
79
209
 
80
210
  Parameters:
81
- - section (str): The section in the configuration file.
211
+ - section (str): The section in the configuration.
82
212
  - key (str): The key to be read.
83
213
  - data_type (type, optional): The expected data type of the key's value. Default is str.
214
+ - from_site (bool, optional): Whether to read from site config. Default is False.
84
215
 
85
216
  Returns:
86
217
  The value of the key converted to the specified data type.
87
218
  """
88
- cache_key = f"{section}.{key}"
219
+ cache_key = f"{'site' if from_site else 'config'}.{section}.{key}"
89
220
  logging.info(f"Read key: {cache_key}")
90
221
 
91
222
  if cache_key in self.cache:
92
223
  return self.cache[cache_key]
93
224
 
94
- if section in self.config and key in self.config[section]:
95
- value = self.config[section][key]
225
+ config_source = self.configSite if from_site else self.config
226
+
227
+ if section in config_source and key in config_source[section]:
228
+ value = config_source[section][key]
96
229
  else:
97
- raise ValueError(f"Key '{key}' not found in section '{section}'")
230
+ raise ValueError(f"Key '{key}' not found in section '{section}' of {'site' if from_site else 'main'} config")
98
231
 
99
232
  value = self._convert_to_data_type(value, data_type)
100
233
  self.cache[cache_key] = value
@@ -122,100 +255,80 @@ class ConfigManager:
122
255
  else:
123
256
  return value
124
257
 
258
+ # Main config getters
125
259
  def get(self, section: str, key: str) -> Any:
126
- """Read a value from the configuration file.
127
-
128
- Parameters:
129
- - section (str): The section in the configuration file.
130
- - key (str): The key to be read.
131
-
132
- Returns:
133
- The value associated with the key.
134
- """
260
+ """Read a value from the main configuration."""
135
261
  return self.read_key(section, key)
136
262
 
137
263
  def get_int(self, section: str, key: str) -> int:
138
- """Read an integer value from the configuration file.
139
-
140
- Parameters:
141
- - section (str): The section in the configuration file.
142
- - key (str): The key to be read.
143
-
144
- Returns:
145
- int: The integer value.
146
- """
264
+ """Read an integer value from the main configuration."""
147
265
  return self.read_key(section, key, int)
148
266
 
149
- def get_float(self, section: str, key: str) -> int:
150
- """Read an float value from the configuration file.
151
-
152
- Parameters:
153
- - section (str): The section in the configuration file.
154
- - key (str): The key to be read.
155
-
156
- Returns:
157
- float: The float value.
158
- """
267
+ def get_float(self, section: str, key: str) -> float:
268
+ """Read a float value from the main configuration."""
159
269
  return self.read_key(section, key, float)
160
270
 
161
271
  def get_bool(self, section: str, key: str) -> bool:
162
- """Read a boolean value from the configuration file.
163
-
164
- Parameters:
165
- - section (str): The section in the configuration file.
166
- - key (str): The key to be read.
167
-
168
- Returns:
169
- bool: The boolean value.
170
- """
272
+ """Read a boolean value from the main configuration."""
171
273
  return self.read_key(section, key, bool)
172
274
 
173
275
  def get_list(self, section: str, key: str) -> List[str]:
174
- """Read a list value from the configuration file.
175
-
176
- Parameters:
177
- - section (str): The section in the configuration file.
178
- - key (str): The key to be read.
179
-
180
- Returns:
181
- list: The list value.
182
- """
276
+ """Read a list value from the main configuration."""
183
277
  return self.read_key(section, key, list)
184
278
 
185
279
  def get_dict(self, section: str, key: str) -> dict:
186
- """Read a dictionary value from the configuration file.
280
+ """Read a dictionary value from the main configuration."""
281
+ return self.read_key(section, key, dict)
187
282
 
188
- Parameters:
189
- - section (str): The section in the configuration file.
190
- - key (str): The key to be read.
283
+ # Site config getters
284
+ def get_site(self, section: str, key: str) -> Any:
285
+ """Read a value from the site configuration."""
286
+ return self.read_key(section, key, from_site=True)
191
287
 
192
- Returns:
193
- dict: The dictionary value.
194
- """
195
- return self.read_key(section, key, dict)
288
+ def get_site_int(self, section: str, key: str) -> int:
289
+ """Read an integer value from the site configuration."""
290
+ return self.read_key(section, key, int, from_site=True)
291
+
292
+ def get_site_float(self, section: str, key: str) -> float:
293
+ """Read a float value from the site configuration."""
294
+ return self.read_key(section, key, float, from_site=True)
295
+
296
+ def get_site_bool(self, section: str, key: str) -> bool:
297
+ """Read a boolean value from the site configuration."""
298
+ return self.read_key(section, key, bool, from_site=True)
299
+
300
+ def get_site_list(self, section: str, key: str) -> List[str]:
301
+ """Read a list value from the site configuration."""
302
+ return self.read_key(section, key, list, from_site=True)
303
+
304
+ def get_site_dict(self, section: str, key: str) -> dict:
305
+ """Read a dictionary value from the site configuration."""
306
+ return self.read_key(section, key, dict, from_site=True)
196
307
 
197
- def set_key(self, section: str, key: str, value: Any) -> None:
198
- """Set a key in the configuration file.
308
+ def set_key(self, section: str, key: str, value: Any, to_site: bool = False) -> None:
309
+ """Set a key in the configuration.
199
310
 
200
311
  Parameters:
201
- - section (str): The section in the configuration file.
312
+ - section (str): The section in the configuration.
202
313
  - key (str): The key to be set.
203
314
  - value (Any): The value to be associated with the key.
315
+ - to_site (bool, optional): Whether to set in site config. Default is False.
204
316
  """
205
317
  try:
206
- if section not in self.config:
207
- self.config[section] = {}
318
+ config_target = self.configSite if to_site else self.config
319
+
320
+ if section not in config_target:
321
+ config_target[section] = {}
208
322
 
209
- self.config[section][key] = value
210
- cache_key = f"{section}.{key}"
323
+ config_target[section][key] = value
324
+ cache_key = f"{'site' if to_site else 'config'}.{section}.{key}"
211
325
  self.cache[cache_key] = value
212
- self.write_config()
213
326
 
214
327
  except Exception as e:
215
- print(f"Error setting key '{key}' in section '{section}': {e}")
328
+ print(f"Error setting key '{key}' in section '{section}' of {'site' if to_site else 'main'} config: {e}")
216
329
 
217
330
  def write_config(self) -> None:
218
- """Write the configuration to the file."""
331
+ """Write the main configuration to the file."""
219
332
  try:
220
333
  with open(self.file_path, 'w') as f:
221
334
  json.dump(self.config, f, indent=4)
@@ -7,7 +7,10 @@ import random
7
7
  import ua_generator
8
8
 
9
9
 
10
- def get_headers() -> str:
10
+ # Variable
11
+ ua = ua_generator.generate(device='desktop', browser=('chrome', 'edge'))
12
+
13
+ def get_userAgent() -> str:
11
14
  """
12
15
  Generate a random user agent to use in HTTP requests.
13
16
 
@@ -20,6 +23,10 @@ def get_headers() -> str:
20
23
  return user_agent
21
24
 
22
25
 
26
+ def get_headers() -> dict:
27
+ return ua.headers.get()
28
+
29
+
23
30
  def random_headers(referer: str = None):
24
31
  """
25
32
  Generate random HTTP headers to simulate human-like behavior.
@@ -85,8 +85,9 @@ class TVShowManager:
85
85
  table.add_row(*row_data)
86
86
 
87
87
  self.console.print(table)
88
-
89
- def run_back_command(self, research_func: dict) -> None:
88
+
89
+ @staticmethod
90
+ def run_back_command(research_func: dict) -> None:
90
91
  """
91
92
  Executes a back-end search command by dynamically importing a module and invoking its search function.
92
93
 
@@ -116,8 +117,7 @@ class TVShowManager:
116
117
  search_func(None)
117
118
 
118
119
  except Exception as e:
119
- self.console.print(f"[red]Error during search: {e}")
120
- logging.exception("Error during search execution")
120
+ logging.error("Error during search execution")
121
121
 
122
122
  finally:
123
123
  if project_root in sys.path:
@@ -181,7 +181,7 @@ class TVShowManager:
181
181
  if self.slice_end > total_items:
182
182
  self.slice_end = total_items
183
183
  elif (key.lower() in ["b", "back"]) and research_func:
184
- self.run_back_command(research_func)
184
+ TVShowManager.run_back_command(research_func)
185
185
  else:
186
186
  break
187
187
 
@@ -215,7 +215,7 @@ class TVShowManager:
215
215
  self.slice_start = 0
216
216
  self.slice_end = self.step
217
217
  elif (key.lower() in ["b", "back"]) and research_func:
218
- self.run_back_command(research_func)
218
+ TVShowManager.run_back_command(research_func)
219
219
  else:
220
220
  break
221
221
 
StreamingCommunity/run.py CHANGED
@@ -27,24 +27,26 @@ from StreamingCommunity.TelegramHelp.telegram_bot import get_bot_instance, Teleg
27
27
 
28
28
 
29
29
  # Config
30
+ SHOW_TRENDING = config_manager.get_bool('DEFAULT', 'show_trending')
30
31
  CLOSE_CONSOLE = config_manager.get_bool('DEFAULT', 'not_close')
31
32
  TELEGRAM_BOT = config_manager.get_bool('DEFAULT', 'telegram_bot')
32
33
 
33
34
 
34
35
 
35
- def run_function(func: Callable[..., None], close_console: bool = False) -> None:
36
+ def run_function(func: Callable[..., None], close_console: bool = False, search_terms: str = None) -> None:
36
37
  """
37
38
  Run a given function indefinitely or once, depending on the value of close_console.
38
39
 
39
40
  Parameters:
40
41
  func (Callable[..., None]): The function to run.
41
42
  close_console (bool, optional): Whether to close the console after running the function once. Defaults to False.
43
+ search_terms (str, optional): Search terms to use for the function. Defaults to None.
42
44
  """
43
45
  if close_console:
44
46
  while 1:
45
- func()
47
+ func(search_terms)
46
48
  else:
47
- func()
49
+ func(search_terms)
48
50
 
49
51
 
50
52
  def load_search_functions():
@@ -134,10 +136,10 @@ def initialize():
134
136
  sys.exit(0)
135
137
 
136
138
  # Trending tmbd
137
- print()
138
- tmdb.display_trending_films()
139
- tmdb.display_trending_tv_shows()
140
-
139
+ if SHOW_TRENDING:
140
+ print()
141
+ tmdb.display_trending_films()
142
+ tmdb.display_trending_tv_shows()
141
143
 
142
144
  # Attempting GitHub update
143
145
  try:
@@ -248,9 +250,11 @@ def main(script_id = 0):
248
250
  long_option = alias
249
251
  parser.add_argument(f'-{short_option}', f'--{long_option}', action='store_true', help=f'Search for {alias.split("_")[0]} on streaming platforms.')
250
252
 
253
+ parser.add_argument('-s', '--search', default=None, help='Search terms')
251
254
  # Parse command-line arguments
252
255
  args = parser.parse_args()
253
256
 
257
+ search_terms = args.search
254
258
  # Map command-line arguments to the config values
255
259
  config_updates = {}
256
260
 
@@ -282,7 +286,7 @@ def main(script_id = 0):
282
286
  # Check which argument is provided and run the corresponding function
283
287
  for arg, func in arg_to_function.items():
284
288
  if getattr(args, arg):
285
- run_function(func)
289
+ run_function(func, search_terms=search_terms)
286
290
  return
287
291
 
288
292
  # Mapping user input to functions
@@ -335,7 +339,7 @@ def main(script_id = 0):
335
339
 
336
340
  # Run the corresponding function based on user input
337
341
  if category in input_to_function:
338
- run_function(input_to_function[category])
342
+ run_function(input_to_function[category], search_terms = args.search)
339
343
  else:
340
344
 
341
345
  if TELEGRAM_BOT:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: StreamingCommunity
3
- Version: 2.6.0
3
+ Version: 2.7.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
@@ -19,7 +19,6 @@ Requires-Dist: unidecode
19
19
  Requires-Dist: jsbeautifier
20
20
  Requires-Dist: pathvalidate
21
21
  Requires-Dist: pycryptodomex
22
- Requires-Dist: googlesearch-python
23
22
  Requires-Dist: ua-generator
24
23
  Requires-Dist: qbittorrent-api
25
24
  Requires-Dist: python-qbittorrent
@@ -59,7 +58,7 @@ Requires-Dist: pyTelegramBotAPI
59
58
 
60
59
  # 📋 Table of Contents
61
60
 
62
- - 🌐 [Website available](#website-status)
61
+ - 🔄 [Update Domains](#update-domains)
63
62
  - 🛠️ [Installation](#installation)
64
63
  - 📦 [PyPI Installation](#1-pypi-installation)
65
64
  - 🔄 [Automatic Installation](#2-automatic-installation)
@@ -86,18 +85,15 @@ Requires-Dist: pyTelegramBotAPI
86
85
  # Installation
87
86
 
88
87
  <p align="center">
89
- <a href="https://github.com/Arrowar/StreamingCommunity/releases/latest/download/StreamingCommunity_win.exe">
88
+ <a href="https://github.com/Arrowar/StreamingCommunity/releases/latest/download/StreamingCommunity_win.exe" style="margin: 0 20px;">
90
89
  <img src="https://img.shields.io/badge/-Windows-blue.svg?style=for-the-badge&logo=windows" alt="Windows">
91
90
  </a>
92
- <a href="https://github.com/Arrowar/StreamingCommunity/releases/latest/download/StreamingCommunity_mac">
91
+ <a href="https://github.com/Arrowar/StreamingCommunity/releases/latest/download/StreamingCommunity_mac" style="margin: 0 20px;">
93
92
  <img src="https://img.shields.io/badge/-macOS-black.svg?style=for-the-badge&logo=apple" alt="macOS">
94
93
  </a>
95
- <a href="https://github.com/Arrowar/StreamingCommunity/releases/latest/download/StreamingCommunity_linux">
94
+ <a href="https://github.com/Arrowar/StreamingCommunity/releases/latest/download/StreamingCommunity_linux" style="margin: 0 20px;">
96
95
  <img src="https://img.shields.io/badge/-Linux-orange.svg?style=for-the-badge&logo=linux" alt="Linux">
97
96
  </a>
98
- <a href="https://github.com/Arrowar/StreamingCommunity/releases">
99
- <img src="https://img.shields.io/badge/-All_Versions-lightgrey.svg?style=for-the-badge" alt="All Versions">
100
- </a>
101
97
  </p>
102
98
 
103
99
 
@@ -478,6 +474,40 @@ You can download VLC Media Player from the [official website](https://www.videol
478
474
  - `get_only_link`: Return M3U8 playlist/index URL instead of downloading
479
475
 
480
476
 
477
+ ## Update Domains
478
+
479
+ There are two ways to update the domains for the supported websites:
480
+
481
+ ### 1. Using Local Configuration
482
+
483
+ 1. Create a `domains.json` file in the root directory of the project
484
+
485
+ 2. Add your domain configuration in the following format:
486
+ ```json
487
+ {
488
+ "altadefinizione": {
489
+ "domain": "si",
490
+ "full_url": "https://altadefinizione.si/"
491
+ },
492
+ ...
493
+ }
494
+ ```
495
+
496
+ 3. Set `use_api` to `false` in the `DEFAULT` section of your `config.json`:
497
+ ```json
498
+ {
499
+ "DEFAULT": {
500
+ "use_api": false
501
+ }
502
+ }
503
+ ```
504
+
505
+ ### 2. Using API (Legacy)
506
+
507
+ The API-based domain updates are currently deprecated. To use it anyway, set `use_api` to `true` in your `config.json` file.
508
+
509
+ Note: If `use_api` is set to `false` and no `domains.json` file is found, the script will raise an error.
510
+
481
511
  # COMMAND
482
512
 
483
513
  - Download a specific season by entering its number.
@@ -587,21 +617,6 @@ Start the bot from the folder /StreamingCommunity/TelegramHelp
587
617
  python3 telegram_bot.py
588
618
  ```
589
619
 
590
- # Website Status
591
-
592
- | Website | Status | Command |
593
- |:-------------------|:------:|:--------:|
594
- | [1337xx](https://1337xx.to/) | ✅ | -133 |
595
- | [AltadefinizioneGratis](https://altadefinizionegratis.pro/) | ✅ | -ALT |
596
- | [AnimeUnity](https://animeunity.so/) | ✅ | -ANI |
597
- | [Ilcorsaronero](https://ilcorsaronero.link/) | ✅ | `-ILC` |
598
- | [CB01New](https://cb01new.gold/) | ✅ | -CB0 |
599
- | [DDLStreamItaly](https://ddlstreamitaly.co/) | ✅ | -DDL |
600
- | [GuardaSerie](https://guardaserie.now/) | ✅ | -GUA |
601
- | [MostraGuarda](https://mostraguarda.stream/) | ✅ | -MOS |
602
- | [StreamingCommunity](https://streamingcommunity.paris/) | ✅ | -STR |
603
-
604
-
605
620
  # Tutorials
606
621
 
607
622
  - [Windows Tutorial](https://www.youtube.com/watch?v=mZGqK4wdN-k)