StreamingCommunity 3.2.7__py3-none-any.whl → 3.2.9__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 (79) hide show
  1. StreamingCommunity/Api/Player/Helper/Vixcloud/util.py +2 -1
  2. StreamingCommunity/Api/Player/hdplayer.py +2 -2
  3. StreamingCommunity/Api/Player/sweetpixel.py +5 -8
  4. StreamingCommunity/Api/Site/altadefinizione/__init__.py +2 -2
  5. StreamingCommunity/Api/Site/altadefinizione/film.py +10 -8
  6. StreamingCommunity/Api/Site/altadefinizione/series.py +9 -7
  7. StreamingCommunity/Api/Site/altadefinizione/site.py +1 -1
  8. StreamingCommunity/Api/Site/animeunity/__init__.py +2 -2
  9. StreamingCommunity/Api/Site/animeunity/serie.py +2 -2
  10. StreamingCommunity/Api/Site/animeworld/site.py +3 -5
  11. StreamingCommunity/Api/Site/animeworld/util/ScrapeSerie.py +8 -10
  12. StreamingCommunity/Api/Site/cb01new/film.py +7 -5
  13. StreamingCommunity/Api/Site/crunchyroll/__init__.py +1 -3
  14. StreamingCommunity/Api/Site/crunchyroll/film.py +9 -7
  15. StreamingCommunity/Api/Site/crunchyroll/series.py +9 -7
  16. StreamingCommunity/Api/Site/crunchyroll/site.py +10 -1
  17. StreamingCommunity/Api/Site/guardaserie/series.py +8 -6
  18. StreamingCommunity/Api/Site/guardaserie/site.py +0 -3
  19. StreamingCommunity/Api/Site/guardaserie/util/ScrapeSerie.py +1 -2
  20. StreamingCommunity/Api/Site/mediasetinfinity/__init__.py +1 -1
  21. StreamingCommunity/Api/Site/mediasetinfinity/film.py +10 -16
  22. StreamingCommunity/Api/Site/mediasetinfinity/series.py +12 -18
  23. StreamingCommunity/Api/Site/mediasetinfinity/site.py +11 -3
  24. StreamingCommunity/Api/Site/mediasetinfinity/util/ScrapeSerie.py +214 -180
  25. StreamingCommunity/Api/Site/mediasetinfinity/util/get_license.py +2 -31
  26. StreamingCommunity/Api/Site/raiplay/__init__.py +1 -1
  27. StreamingCommunity/Api/Site/raiplay/film.py +41 -10
  28. StreamingCommunity/Api/Site/raiplay/series.py +44 -12
  29. StreamingCommunity/Api/Site/raiplay/site.py +4 -1
  30. StreamingCommunity/Api/Site/raiplay/util/ScrapeSerie.py +2 -1
  31. StreamingCommunity/Api/Site/raiplay/util/get_license.py +40 -0
  32. StreamingCommunity/Api/Site/streamingcommunity/__init__.py +0 -1
  33. StreamingCommunity/Api/Site/streamingcommunity/film.py +7 -5
  34. StreamingCommunity/Api/Site/streamingcommunity/series.py +9 -7
  35. StreamingCommunity/Api/Site/streamingcommunity/site.py +4 -2
  36. StreamingCommunity/Api/Site/streamingwatch/film.py +7 -5
  37. StreamingCommunity/Api/Site/streamingwatch/series.py +8 -6
  38. StreamingCommunity/Api/Site/streamingwatch/site.py +3 -1
  39. StreamingCommunity/Api/Site/streamingwatch/util/ScrapeSerie.py +3 -3
  40. StreamingCommunity/Api/Template/Util/__init__.py +10 -1
  41. StreamingCommunity/Api/Template/Util/manage_ep.py +4 -4
  42. StreamingCommunity/Api/Template/__init__.py +5 -1
  43. StreamingCommunity/Api/Template/site.py +10 -6
  44. StreamingCommunity/Lib/Downloader/DASH/cdm_helpher.py +5 -12
  45. StreamingCommunity/Lib/Downloader/DASH/decrypt.py +1 -1
  46. StreamingCommunity/Lib/Downloader/DASH/downloader.py +1 -1
  47. StreamingCommunity/Lib/Downloader/DASH/parser.py +1 -1
  48. StreamingCommunity/Lib/Downloader/DASH/segments.py +4 -3
  49. StreamingCommunity/Lib/Downloader/HLS/downloader.py +11 -9
  50. StreamingCommunity/Lib/Downloader/HLS/segments.py +253 -144
  51. StreamingCommunity/Lib/Downloader/MP4/downloader.py +4 -3
  52. StreamingCommunity/Lib/Downloader/TOR/downloader.py +3 -5
  53. StreamingCommunity/Lib/Downloader/__init__.py +9 -1
  54. StreamingCommunity/Lib/FFmpeg/__init__.py +10 -1
  55. StreamingCommunity/Lib/FFmpeg/command.py +4 -6
  56. StreamingCommunity/Lib/FFmpeg/util.py +1 -1
  57. StreamingCommunity/Lib/M3U8/__init__.py +9 -1
  58. StreamingCommunity/Lib/M3U8/decryptor.py +8 -4
  59. StreamingCommunity/Lib/M3U8/estimator.py +0 -6
  60. StreamingCommunity/Lib/M3U8/parser.py +1 -1
  61. StreamingCommunity/Lib/M3U8/url_fixer.py +1 -1
  62. StreamingCommunity/Lib/TMBD/__init__.py +6 -1
  63. StreamingCommunity/TelegramHelp/config.json +1 -5
  64. StreamingCommunity/TelegramHelp/telegram_bot.py +9 -10
  65. StreamingCommunity/Upload/version.py +2 -2
  66. StreamingCommunity/Util/config_json.py +139 -59
  67. StreamingCommunity/Util/http_client.py +201 -0
  68. StreamingCommunity/Util/message.py +1 -1
  69. StreamingCommunity/Util/os.py +5 -5
  70. StreamingCommunity/Util/table.py +3 -3
  71. StreamingCommunity/__init__.py +9 -1
  72. StreamingCommunity/run.py +396 -260
  73. {streamingcommunity-3.2.7.dist-info → streamingcommunity-3.2.9.dist-info}/METADATA +143 -45
  74. streamingcommunity-3.2.9.dist-info/RECORD +113 -0
  75. streamingcommunity-3.2.7.dist-info/RECORD +0 -111
  76. {streamingcommunity-3.2.7.dist-info → streamingcommunity-3.2.9.dist-info}/WHEEL +0 -0
  77. {streamingcommunity-3.2.7.dist-info → streamingcommunity-3.2.9.dist-info}/entry_points.txt +0 -0
  78. {streamingcommunity-3.2.7.dist-info → streamingcommunity-3.2.9.dist-info}/licenses/LICENSE +0 -0
  79. {streamingcommunity-3.2.7.dist-info → streamingcommunity-3.2.9.dist-info}/top_level.txt +0 -0
@@ -3,4 +3,12 @@
3
3
  from .decryptor import M3U8_Decryption
4
4
  from .estimator import M3U8_Ts_Estimator
5
5
  from .parser import M3U8_Parser, M3U8_Codec
6
- from .url_fixer import M3U8_UrlFix
6
+ from .url_fixer import M3U8_UrlFix
7
+
8
+ __all__ = [
9
+ "M3U8_Decryption",
10
+ "M3U8_Ts_Estimator",
11
+ "M3U8_Parser",
12
+ "M3U8_Codec",
13
+ "M3U8_UrlFix"
14
+ ]
@@ -1,7 +1,6 @@
1
1
  # 03.04.24
2
2
 
3
3
  import sys
4
- import time
5
4
  import logging
6
5
  import importlib.util
7
6
 
@@ -10,18 +9,23 @@ import importlib.util
10
9
  from rich.console import Console
11
10
 
12
11
 
12
+ # Cryptodome imports
13
+ from Cryptodome.Cipher import AES
14
+ from Cryptodome.Util.Padding import unpad
15
+
16
+
13
17
  # Check if Cryptodome module is installed
14
18
  console = Console()
15
19
  crypto_spec = importlib.util.find_spec("Cryptodome")
16
20
  crypto_installed = crypto_spec is not None
17
21
 
22
+
18
23
  if not crypto_installed:
19
24
  console.log("[red]pycryptodomex non è installato. Per favore installalo. Leggi readme.md [Requirement].")
20
25
  sys.exit(0)
21
26
 
22
- logging.info("[cyan]Decrypy use: Cryptodomex")
23
- from Cryptodome.Cipher import AES
24
- from Cryptodome.Util.Padding import unpad
27
+
28
+ logging.info("[cyan]Decryption use: Cryptodomex")
25
29
 
26
30
 
27
31
 
@@ -121,12 +121,6 @@ class M3U8_Ts_Estimator:
121
121
  number_file_total_size = file_total_size.split(' ')[0]
122
122
  units_file_total_size = file_total_size.split(' ')[1]
123
123
 
124
- # Reduce lock contention by acquiring data with minimal synchronization
125
- retry_count = 0
126
- if self.segments_instance:
127
- with self.segments_instance.active_retries_lock:
128
- retry_count = self.segments_instance.active_retries
129
-
130
124
  # Get speed data outside of any locks
131
125
  speed_data = ["N/A", ""]
132
126
  with self.lock:
@@ -485,7 +485,7 @@ class M3U8_Parser:
485
485
  try:
486
486
  for playlist in m3u8_obj.playlists:
487
487
 
488
- there_is_codec = not playlist.stream_info.codecs is None
488
+ there_is_codec = playlist.stream_info.codecs is not None
489
489
  logging.info(f"There is coded: {there_is_codec}")
490
490
 
491
491
  if there_is_codec:
@@ -33,7 +33,7 @@ class M3U8_UrlFix:
33
33
  Returns:
34
34
  str: The full URL for the specified resource.
35
35
  """
36
- if self.url_playlist == None:
36
+ if self.url_playlist is None:
37
37
  logging.error("[M3U8_UrlFix] Cant generate full url, playlist not present")
38
38
  raise
39
39
 
@@ -1,4 +1,9 @@
1
1
  # 17.09.24
2
2
 
3
3
  from .tmdb import tmdb
4
- from .obj_tmbd import Json_film
4
+ from .obj_tmbd import Json_film
5
+
6
+ __all__ = [
7
+ "tmdb",
8
+ "Json_film"
9
+ ]
@@ -2,10 +2,8 @@
2
2
  "DEFAULT": {
3
3
  "debug": false,
4
4
  "show_message": true,
5
- "clean_console": true,
6
5
  "show_trending": true,
7
6
  "use_api": true,
8
- "not_close": false,
9
7
  "telegram_bot": true,
10
8
  "download_site_data": true,
11
9
  "validate_github_config": true
@@ -45,9 +43,7 @@
45
43
  "use_acodec": true,
46
44
  "use_bitrate": true,
47
45
  "use_gpu": false,
48
- "default_preset": "ultrafast"
49
- },
50
- "M3U8_PARSER": {
46
+ "default_preset": "ultrafast",
51
47
  "force_resolution": "Best"
52
48
  },
53
49
  "REQUESTS": {
@@ -9,7 +9,6 @@ import uuid
9
9
  import json
10
10
  import threading
11
11
  import subprocess
12
- import threading
13
12
  from typing import Optional
14
13
 
15
14
  # External libraries
@@ -305,7 +304,7 @@ class TelegramBot:
305
304
 
306
305
  def handle_get_id(self, message):
307
306
  if not self.is_authorized(message.from_user.id):
308
- print(f" Non sei autorizzato.")
307
+ print(" Non sei autorizzato.")
309
308
  self.bot.send_message(message.chat.id, " Non sei autorizzato.")
310
309
  return
311
310
 
@@ -384,7 +383,7 @@ class TelegramBot:
384
383
 
385
384
  def handle_list_scripts(self, message):
386
385
  if not self.is_authorized(message.from_user.id):
387
- print(f" Non sei autorizzato.")
386
+ print(" Non sei autorizzato.")
388
387
  self.bot.send_message(message.chat.id, " Non sei autorizzato.")
389
388
  return
390
389
 
@@ -395,7 +394,7 @@ class TelegramBot:
395
394
  scripts_data = []
396
395
 
397
396
  if not scripts_data:
398
- print(f" Nessuno script registrato.")
397
+ print(" Nessuno script registrato.")
399
398
  self.bot.send_message(message.chat.id, " Nessuno script registrato.")
400
399
  return
401
400
 
@@ -437,7 +436,7 @@ class TelegramBot:
437
436
 
438
437
  def handle_stop_script(self, message):
439
438
  if not self.is_authorized(message.from_user.id):
440
- print(f" Non sei autorizzato.")
439
+ print(" Non sei autorizzato.")
441
440
  self.bot.send_message(message.chat.id, " Non sei autorizzato.")
442
441
  return
443
442
 
@@ -452,7 +451,7 @@ class TelegramBot:
452
451
  running_scripts = [s for s in scripts_data if s["status"] == "running"]
453
452
 
454
453
  if not running_scripts:
455
- print(f" Nessuno script attivo da fermare.")
454
+ print(" Nessuno script attivo da fermare.")
456
455
  self.bot.send_message(
457
456
  message.chat.id, " Nessuno script attivo da fermare."
458
457
  )
@@ -526,7 +525,7 @@ class TelegramBot:
526
525
  def handle_screen_status(self, message):
527
526
  command_parts = message.text.split()
528
527
  if len(command_parts) < 2:
529
- print(f" ID mancante nel comando. Usa: /screen <ID>")
528
+ print(" ID mancante nel comando. Usa: /screen <ID>")
530
529
  self.bot.send_message(
531
530
  message.chat.id, " ID mancante nel comando. Usa: /screen <ID>"
532
531
  )
@@ -557,9 +556,9 @@ class TelegramBot:
557
556
  return
558
557
 
559
558
  if not os.path.exists(temp_file):
560
- print(f" Impossibile catturare l'output della screen.")
559
+ print(" Impossibile catturare l'output della screen.")
561
560
  self.bot.send_message(
562
- message.chat.id, f" Impossibile catturare l'output della screen."
561
+ message.chat.id, " Impossibile catturare l'output della screen."
563
562
  )
564
563
  return
565
564
 
@@ -669,7 +668,7 @@ class TelegramBot:
669
668
  return response
670
669
  time.sleep(1)
671
670
 
672
- print(f" Timeout: nessuna risposta ricevuta.")
671
+ print(" Timeout: nessuna risposta ricevuta.")
673
672
  for chat_id in self.authorized_users: # Manda a tutti gli ID autorizzati
674
673
  self.bot.send_message(chat_id, " Timeout: nessuna risposta ricevuta.")
675
674
  self.request_manager.clear_file()
@@ -1,5 +1,5 @@
1
1
  __title__ = 'StreamingCommunity'
2
- __version__ = '3.2.7'
2
+ __version__ = '3.2.9'
3
3
  __author__ = 'Arrowar'
4
4
  __description__ = 'A command-line program to download film'
5
- __copyright__ = 'Copyright 2025'
5
+ __copyright__ = 'Copyright 2025'
@@ -18,8 +18,6 @@ from StreamingCommunity.Util.headers import get_userAgent
18
18
 
19
19
  # Variable
20
20
  console = Console()
21
- download_site_data = True
22
- validate_github_config = True
23
21
 
24
22
 
25
23
  class ConfigManager:
@@ -54,8 +52,7 @@ class ConfigManager:
54
52
  self.configSite = {}
55
53
  self.cache = {}
56
54
 
57
- self.use_api = False
58
- self.download_site_data = False
55
+ self.fetch_domain_online = True
59
56
  self.validate_github_config = False
60
57
 
61
58
  console.print(f"[bold cyan]Initializing ConfigManager:[/bold cyan] [green]{self.file_path}[/green]")
@@ -67,7 +64,7 @@ class ConfigManager:
67
64
  """Load the configuration and initialize all settings."""
68
65
  if not os.path.exists(self.file_path):
69
66
  console.print(f"[bold red]WARNING: Configuration file not found:[/bold red] {self.file_path}")
70
- console.print(f"[bold yellow]Attempting to download from reference repository...[/bold yellow]")
67
+ console.print("[bold yellow]Attempting to download from reference repository...[/bold yellow]")
71
68
  self._download_reference_config()
72
69
 
73
70
  # Load the configuration file
@@ -85,11 +82,8 @@ class ConfigManager:
85
82
  else:
86
83
  console.print("[bold yellow]GitHub validation disabled[/bold yellow]")
87
84
 
88
- # Load site data if requested
89
- if self.download_site_data:
90
- self._load_site_data()
91
- else:
92
- console.print("[bold yellow]Site data download disabled[/bold yellow]")
85
+ # Load site data based on fetch_domain_online setting
86
+ self._load_site_data()
93
87
 
94
88
  except json.JSONDecodeError as e:
95
89
  console.print(f"[bold red]Error parsing JSON:[/bold red] {str(e)}")
@@ -119,18 +113,11 @@ class ConfigManager:
119
113
  """Update internal settings from loaded configurations."""
120
114
  default_section = self.config.get('DEFAULT', {})
121
115
 
122
- # Save local values in temporary variables
123
- temp_use_api = default_section.get('use_api', False)
124
- temp_download_site_data = default_section.get('download_site_data', False)
125
- temp_validate_github_config = default_section.get('validate_github_config', False)
126
-
127
- # Update settings with found values (False by default)
128
- self.use_api = temp_use_api
129
- self.download_site_data = temp_download_site_data
130
- self.validate_github_config = temp_validate_github_config
116
+ # Get fetch_domain_online setting (True by default)
117
+ self.fetch_domain_online = default_section.get('fetch_domain_online', True)
118
+ self.validate_github_config = default_section.get('validate_github_config', False)
131
119
 
132
- console.print(f"[bold cyan]API Usage:[/bold cyan] [{'green' if self.use_api else 'yellow'}]{self.use_api}[/{'green' if self.use_api else 'yellow'}]")
133
- console.print(f"[bold cyan]Site data download:[/bold cyan] [{'green' if self.download_site_data else 'yellow'}]{self.download_site_data}[/{'green' if self.download_site_data else 'yellow'}]")
120
+ console.print(f"[bold cyan]Fetch domains online:[/bold cyan] [{'green' if self.fetch_domain_online else 'yellow'}]{self.fetch_domain_online}[/{'green' if self.fetch_domain_online else 'yellow'}]")
134
121
  console.print(f"[bold cyan]GitHub configuration validation:[/bold cyan] [{'green' if self.validate_github_config else 'yellow'}]{self.validate_github_config}[/{'green' if self.validate_github_config else 'yellow'}]")
135
122
 
136
123
  def _download_reference_config(self) -> None:
@@ -159,7 +146,7 @@ class ConfigManager:
159
146
  """Validate the local configuration against the reference one and update missing keys."""
160
147
  try:
161
148
  # Download the reference configuration
162
- console.print(f"[bold cyan]Validating configuration with GitHub...[/bold cyan]")
149
+ console.print("[bold cyan]Validating configuration with GitHub...[/bold cyan]")
163
150
  response = requests.get(self.reference_config_url, timeout=8, headers={'User-Agent': get_userAgent()})
164
151
 
165
152
  if not response.ok:
@@ -242,11 +229,9 @@ class ConfigManager:
242
229
  # Make sure control keys maintain local values
243
230
  merged_section = self._deep_merge_configs(merged[key], value)
244
231
 
245
- # Preserve local values for the three critical settings
246
- if 'use_api' in merged[key]:
247
- merged_section['use_api'] = merged[key]['use_api']
248
- if 'download_site_data' in merged[key]:
249
- merged_section['download_site_data'] = merged[key]['download_site_data']
232
+ # Preserve local values for critical settings
233
+ if 'fetch_domain_online' in merged[key]:
234
+ merged_section['fetch_domain_online'] = merged[key]['fetch_domain_online']
250
235
  if 'validate_github_config' in merged[key]:
251
236
  merged_section['validate_github_config'] = merged[key]['validate_github_config']
252
237
 
@@ -259,28 +244,31 @@ class ConfigManager:
259
244
  return merged
260
245
 
261
246
  def _load_site_data(self) -> None:
262
- """Load site data from API or local file."""
263
- if self.use_api:
264
- self._load_site_data_from_api()
247
+ """Load site data based on fetch_domain_online setting."""
248
+ if self.fetch_domain_online:
249
+ self._load_site_data_online()
265
250
  else:
266
251
  self._load_site_data_from_file()
267
252
 
268
- def _load_site_data_from_api(self) -> None:
269
- """Load site data from GitHub."""
253
+ def _load_site_data_online(self) -> None:
254
+ """Load site data from GitHub and update local domains.json file."""
270
255
  domains_github_url = "https://raw.githubusercontent.com/Arrowar/StreamingCommunity/refs/heads/main/.github/.domain/domains.json"
271
256
  headers = {
272
257
  "User-Agent": get_userAgent()
273
258
  }
274
259
 
275
260
  try:
276
- console.print("[bold cyan]Retrieving site data from GitHub:[/bold cyan]")
261
+ console.print("[bold cyan]Fetching domains from GitHub:[/bold cyan]")
277
262
  response = requests.get(domains_github_url, timeout=8, headers=headers)
278
263
 
279
264
  if response.ok:
280
265
  self.configSite = response.json()
281
266
 
267
+ # Determine which file to save to
268
+ self._save_domains_to_appropriate_location()
269
+
282
270
  site_count = len(self.configSite) if isinstance(self.configSite, dict) else 0
283
- console.print(f"[bold green]Site data loaded from GitHub:[/bold green] {site_count} streaming services found.")
271
+ console.print(f"[bold green]Domains loaded from GitHub:[/bold green] {site_count} streaming services found.")
284
272
 
285
273
  else:
286
274
  console.print(f"[bold red]GitHub request failed:[/bold red] HTTP {response.status_code}, {response.text[:100]}")
@@ -294,42 +282,129 @@ class ConfigManager:
294
282
  console.print(f"[bold red]GitHub connection error:[/bold red] {str(e)}")
295
283
  self._handle_site_data_fallback()
296
284
 
285
+ def _save_domains_to_appropriate_location(self) -> None:
286
+ """Save domains to the appropriate location based on existing files."""
287
+ if getattr(sys, 'frozen', False):
288
+ # If the application is frozen (e.g., PyInstaller)
289
+ base_path = os.path.dirname(sys.executable)
290
+ else:
291
+ # Use the current working directory where the script is executed
292
+ base_path = os.getcwd()
293
+
294
+ # Check for GitHub structure first
295
+ github_domains_path = os.path.join(base_path, '.github', '.domain', 'domains.json')
296
+
297
+ try:
298
+ if os.path.exists(github_domains_path):
299
+
300
+ # Update existing GitHub structure file
301
+ with open(github_domains_path, 'w', encoding='utf-8') as f:
302
+ json.dump(self.configSite, f, indent=4, ensure_ascii=False)
303
+ console.print(f"[bold green]Domains updated in GitHub structure:[/bold green] {github_domains_path}")
304
+
305
+ elif not os.path.exists(self.domains_path):
306
+
307
+ # Save to root only if it doesn't exist and GitHub structure doesn't exist
308
+ with open(self.domains_path, 'w', encoding='utf-8') as f:
309
+ json.dump(self.configSite, f, indent=4, ensure_ascii=False)
310
+ console.print(f"[bold green]Domains saved to:[/bold green] {self.domains_path}")
311
+
312
+ else:
313
+
314
+ # Root file exists, don't overwrite it
315
+ console.print(f"[bold yellow]Local domains.json already exists, not overwriting:[/bold yellow] {self.domains_path}")
316
+ console.print("[bold yellow]Tip: Delete the file if you want to recreate it from GitHub[/bold yellow]")
317
+
318
+ except Exception as save_error:
319
+ console.print(f"[bold yellow]Warning: Could not save domains to file:[/bold yellow] {str(save_error)}")
320
+
321
+ # Try to save to root as fallback only if it doesn't exist
322
+ if not os.path.exists(self.domains_path):
323
+ try:
324
+ with open(self.domains_path, 'w', encoding='utf-8') as f:
325
+ json.dump(self.configSite, f, indent=4, ensure_ascii=False)
326
+ console.print(f"[bold green]Domains saved to fallback location:[/bold green] {self.domains_path}")
327
+ except Exception as fallback_error:
328
+ console.print(f"[bold red]Failed to save to fallback location:[/bold red] {str(fallback_error)}")
329
+
297
330
  def _load_site_data_from_file(self) -> None:
298
- """Load site data from local file."""
331
+ """Load site data from local domains.json file."""
299
332
  try:
300
- if os.path.exists(self.domains_path):
301
- console.print(f"[bold cyan]Reading domains from:[/bold cyan] {self.domains_path}")
302
- with open(self.domains_path, 'r') as f:
333
+ # Determine the base path
334
+ if getattr(sys, 'frozen', False):
335
+
336
+ # If the application is frozen (e.g., PyInstaller)
337
+ base_path = os.path.dirname(sys.executable)
338
+ else:
339
+
340
+ # Use the current working directory where the script is executed
341
+ base_path = os.getcwd()
342
+
343
+ # Check for GitHub structure first
344
+ github_domains_path = os.path.join(base_path, '.github', '.domain', 'domains.json')
345
+
346
+ if os.path.exists(github_domains_path):
347
+ console.print(f"[bold cyan]Reading domains from GitHub structure:[/bold cyan] {github_domains_path}")
348
+ with open(github_domains_path, 'r', encoding='utf-8') as f:
349
+ self.configSite = json.load(f)
350
+
351
+ site_count = len(self.configSite) if isinstance(self.configSite, dict) else 0
352
+ console.print(f"[bold green]Domains loaded from GitHub structure:[/bold green] {site_count} streaming services")
353
+
354
+ elif os.path.exists(self.domains_path):
355
+ console.print(f"[bold cyan]Reading domains from root:[/bold cyan] {self.domains_path}")
356
+ with open(self.domains_path, 'r', encoding='utf-8') as f:
303
357
  self.configSite = json.load(f)
304
358
 
305
359
  site_count = len(self.configSite) if isinstance(self.configSite, dict) else 0
306
- console.print(f"[bold green]Site data loaded from file:[/bold green] {site_count} streaming services")
360
+ console.print(f"[bold green]Domains loaded from root file:[/bold green] {site_count} streaming services")
307
361
 
308
362
  else:
309
- error_msg = f"domains.json not found at {self.domains_path} and API usage is disabled"
363
+ error_msg = f"domains.json not found in GitHub structure ({github_domains_path}) or root ({self.domains_path}) and fetch_domain_online is disabled"
310
364
  console.print(f"[bold red]Configuration error:[/bold red] {error_msg}")
311
- self._handle_site_data_fallback()
365
+ console.print("[bold yellow]Tip: Set 'fetch_domain_online' to true to download domains from GitHub[/bold yellow]")
366
+ self.configSite = {}
312
367
 
313
368
  except Exception as e:
314
- console.print(f"[bold red]Domain file error:[/bold red] {str(e)}")
315
- self._handle_site_data_fallback()
369
+ console.print(f"[bold red]Local domain file error:[/bold red] {str(e)}")
370
+ self.configSite = {}
316
371
 
317
372
  def _handle_site_data_fallback(self) -> None:
318
373
  """Handle site data fallback in case of error."""
319
- if self.use_api and os.path.exists(self.domains_path):
320
- console.print("[bold yellow]Attempting fallback to local domains.json file...[/bold yellow]")
321
-
374
+ # Determine the base path
375
+ if getattr(sys, 'frozen', False):
376
+
377
+ # If the application is frozen (e.g., PyInstaller)
378
+ base_path = os.path.dirname(sys.executable)
379
+ else:
380
+ # Use the current working directory where the script is executed
381
+ base_path = os.getcwd()
382
+
383
+ # Check for GitHub structure first
384
+ github_domains_path = os.path.join(base_path, '.github', '.domain', 'domains.json')
385
+
386
+ if os.path.exists(github_domains_path):
387
+ console.print("[bold yellow]Attempting fallback to GitHub structure domains.json file...[/bold yellow]")
322
388
  try:
323
- with open(self.domains_path, 'r') as f:
389
+ with open(github_domains_path, 'r', encoding='utf-8') as f:
324
390
  self.configSite = json.load(f)
325
- console.print("[bold green]Fallback to local data successful[/bold green]")
391
+ console.print("[bold green]Fallback to GitHub structure successful[/bold green]")
392
+ return
326
393
  except Exception as fallback_error:
327
- console.print(f"[bold red]Fallback also failed:[/bold red] {str(fallback_error)}")
328
- self.configSite = {}
329
- else:
330
-
331
- # Initialize with an empty dictionary if there are no alternatives
332
- self.configSite = {}
394
+ console.print(f"[bold red]GitHub structure fallback failed:[/bold red] {str(fallback_error)}")
395
+
396
+ if os.path.exists(self.domains_path):
397
+ console.print("[bold yellow]Attempting fallback to root domains.json file...[/bold yellow]")
398
+ try:
399
+ with open(self.domains_path, 'r', encoding='utf-8') as f:
400
+ self.configSite = json.load(f)
401
+ console.print("[bold green]Fallback to root domains successful[/bold green]")
402
+ return
403
+ except Exception as fallback_error:
404
+ console.print(f"[bold red]Root domains fallback failed:[/bold red] {str(fallback_error)}")
405
+
406
+ console.print("[bold red]No local domains.json file available for fallback[/bold red]")
407
+ self.configSite = {}
333
408
 
334
409
  def download_file(self, url: str, filename: str) -> None:
335
410
  """
@@ -412,23 +487,28 @@ class ConfigManager:
412
487
  Any: Converted value
413
488
  """
414
489
  try:
415
- if data_type == int:
490
+ if data_type is int:
416
491
  return int(value)
417
- elif data_type == float:
492
+
493
+ elif data_type is float:
418
494
  return float(value)
419
- elif data_type == bool:
495
+
496
+ elif data_type is bool:
420
497
  if isinstance(value, str):
421
498
  return value.lower() in ("yes", "true", "t", "1")
422
499
  return bool(value)
423
- elif data_type == list:
500
+
501
+ elif data_type is list:
424
502
  if isinstance(value, list):
425
503
  return value
426
504
  if isinstance(value, str):
427
505
  return [item.strip() for item in value.split(',')]
428
506
  return [value]
429
- elif data_type == dict:
507
+
508
+ elif data_type is dict:
430
509
  if isinstance(value, dict):
431
510
  return value
511
+
432
512
  raise ValueError(f"Cannot convert {type(value).__name__} to dict")
433
513
  else:
434
514
  return value