StreamingCommunity 2.7.0__py3-none-any.whl → 2.8.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 (71) hide show
  1. StreamingCommunity/Api/Player/ddl.py +2 -2
  2. StreamingCommunity/Api/Player/maxstream.py +7 -13
  3. StreamingCommunity/Api/Player/supervideo.py +7 -33
  4. StreamingCommunity/Api/Player/vixcloud.py +8 -80
  5. StreamingCommunity/Api/Site/1337xx/__init__.py +8 -1
  6. StreamingCommunity/Api/Site/1337xx/site.py +10 -16
  7. StreamingCommunity/Api/Site/1337xx/title.py +4 -1
  8. StreamingCommunity/Api/Site/animeunity/__init__.py +9 -2
  9. StreamingCommunity/Api/Site/animeunity/film_serie.py +7 -1
  10. StreamingCommunity/Api/Site/animeunity/site.py +8 -10
  11. StreamingCommunity/Api/Site/animeunity/util/ScrapeSerie.py +1 -1
  12. StreamingCommunity/Api/Site/cb01new/__init__.py +8 -1
  13. StreamingCommunity/Api/Site/cb01new/film.py +7 -1
  14. StreamingCommunity/Api/Site/cb01new/site.py +16 -15
  15. StreamingCommunity/Api/Site/ddlstreamitaly/__init__.py +9 -2
  16. StreamingCommunity/Api/Site/ddlstreamitaly/series.py +7 -1
  17. StreamingCommunity/Api/Site/ddlstreamitaly/site.py +10 -15
  18. StreamingCommunity/Api/Site/ddlstreamitaly/util/ScrapeSerie.py +1 -1
  19. StreamingCommunity/Api/Site/guardaserie/__init__.py +9 -2
  20. StreamingCommunity/Api/Site/guardaserie/series.py +9 -1
  21. StreamingCommunity/Api/Site/guardaserie/site.py +12 -17
  22. StreamingCommunity/Api/Site/guardaserie/util/ScrapeSerie.py +1 -1
  23. StreamingCommunity/Api/Site/mostraguarda/__init__.py +6 -2
  24. StreamingCommunity/Api/Site/mostraguarda/film.py +7 -3
  25. StreamingCommunity/Api/Site/streamingcommunity/__init__.py +9 -2
  26. StreamingCommunity/Api/Site/streamingcommunity/film.py +8 -1
  27. StreamingCommunity/Api/Site/streamingcommunity/series.py +14 -5
  28. StreamingCommunity/Api/Site/streamingcommunity/site.py +10 -15
  29. StreamingCommunity/Api/Site/streamingcommunity/util/ScrapeSerie.py +2 -2
  30. StreamingCommunity/Api/Template/Util/__init__.py +0 -1
  31. StreamingCommunity/Api/Template/Util/get_domain.py +24 -66
  32. StreamingCommunity/Api/Template/Util/manage_ep.py +10 -5
  33. StreamingCommunity/Api/Template/config_loader.py +8 -8
  34. StreamingCommunity/Api/Template/site.py +3 -6
  35. StreamingCommunity/Lib/Downloader/HLS/downloader.py +10 -13
  36. StreamingCommunity/Lib/Downloader/HLS/segments.py +11 -31
  37. StreamingCommunity/Lib/Downloader/MP4/downloader.py +12 -9
  38. StreamingCommunity/Lib/Downloader/TOR/downloader.py +109 -101
  39. StreamingCommunity/Lib/FFmpeg/__init__.py +1 -1
  40. StreamingCommunity/Lib/FFmpeg/capture.py +10 -12
  41. StreamingCommunity/Lib/FFmpeg/command.py +15 -14
  42. StreamingCommunity/Lib/FFmpeg/util.py +9 -38
  43. StreamingCommunity/Lib/M3U8/decryptor.py +72 -146
  44. StreamingCommunity/Lib/M3U8/estimator.py +8 -16
  45. StreamingCommunity/Lib/M3U8/parser.py +1 -17
  46. StreamingCommunity/Lib/M3U8/url_fixer.py +1 -4
  47. StreamingCommunity/Lib/TMBD/__init__.py +2 -0
  48. StreamingCommunity/Lib/TMBD/obj_tmbd.py +3 -17
  49. StreamingCommunity/Lib/TMBD/tmdb.py +4 -9
  50. StreamingCommunity/TelegramHelp/telegram_bot.py +50 -50
  51. StreamingCommunity/Upload/update.py +3 -2
  52. StreamingCommunity/Upload/version.py +1 -1
  53. StreamingCommunity/Util/color.py +1 -1
  54. StreamingCommunity/Util/{_jsonConfig.py → config_json.py} +148 -54
  55. StreamingCommunity/Util/headers.py +2 -38
  56. StreamingCommunity/Util/logger.py +72 -42
  57. StreamingCommunity/Util/message.py +8 -3
  58. StreamingCommunity/Util/os.py +41 -93
  59. StreamingCommunity/Util/table.py +8 -17
  60. StreamingCommunity/run.py +26 -34
  61. {StreamingCommunity-2.7.0.dist-info → StreamingCommunity-2.8.0.dist-info}/METADATA +165 -92
  62. StreamingCommunity-2.8.0.dist-info/RECORD +75 -0
  63. StreamingCommunity/Api/Template/Util/recall_search.py +0 -37
  64. StreamingCommunity/Lib/Downloader/HLS/proxyes.py +0 -110
  65. StreamingCommunity/Util/call_stack.py +0 -42
  66. StreamingCommunity/Util/console.py +0 -12
  67. StreamingCommunity-2.7.0.dist-info/RECORD +0 -79
  68. {StreamingCommunity-2.7.0.dist-info → StreamingCommunity-2.8.0.dist-info}/LICENSE +0 -0
  69. {StreamingCommunity-2.7.0.dist-info → StreamingCommunity-2.8.0.dist-info}/WHEEL +0 -0
  70. {StreamingCommunity-2.7.0.dist-info → StreamingCommunity-2.8.0.dist-info}/entry_points.txt +0 -0
  71. {StreamingCommunity-2.7.0.dist-info → StreamingCommunity-2.8.0.dist-info}/top_level.txt +0 -0
@@ -3,163 +3,89 @@
3
3
  import sys
4
4
  import time
5
5
  import logging
6
- import subprocess
7
6
  import importlib.util
8
7
 
9
8
 
10
- # Internal utilities
11
- from StreamingCommunity.Util.console import console
9
+ # External library
10
+ from rich.console import Console
12
11
 
13
12
 
14
- # Check if Crypto module is installed
13
+ # Check if Cryptodome module is installed
14
+ console = Console()
15
15
  crypto_spec = importlib.util.find_spec("Cryptodome")
16
16
  crypto_installed = crypto_spec is not None
17
17
 
18
+ if not crypto_installed:
19
+ console.log("[red]pycryptodomex non è installato. Per favore installalo. Leggi readme.md [Requirement].")
20
+ sys.exit(0)
18
21
 
19
- if crypto_installed:
20
- logging.info("[cyan]Decrypy use: Cryptodomex")
21
- from Cryptodome.Cipher import AES
22
- from Cryptodome.Util.Padding import unpad
22
+ logging.info("[cyan]Decrypy use: Cryptodomex")
23
+ from Cryptodome.Cipher import AES
24
+ from Cryptodome.Util.Padding import unpad
23
25
 
24
- class M3U8_Decryption:
26
+
27
+
28
+ class M3U8_Decryption:
29
+ """
30
+ Class for decrypting M3U8 playlist content using AES with pycryptodomex.
31
+ """
32
+ def __init__(self, key: bytes, iv: bytes, method: str) -> None:
25
33
  """
26
- Class for decrypting M3U8 playlist content using AES encryption when the Crypto module is available.
34
+ Initialize the M3U8_Decryption object.
35
+
36
+ Parameters:
37
+ key (bytes): The encryption key.
38
+ iv (bytes): The initialization vector (IV).
39
+ method (str): The encryption method.
27
40
  """
28
- def __init__(self, key: bytes, iv: bytes, method: str) -> None:
29
- """
30
- Initialize the M3U8_Decryption object.
31
-
32
- Parameters:
33
- - key (bytes): The encryption key.
34
- - iv (bytes): The initialization vector (IV).
35
- - method (str): The encryption method.
36
- """
37
- self.key = key
38
- self.iv = iv
39
- if "0x" in str(iv):
40
- self.iv = bytes.fromhex(iv.replace("0x", ""))
41
- self.method = method
42
-
43
- # Precreate cipher based on encryption method
44
- if self.method == "AES":
45
- self.cipher = AES.new(self.key, AES.MODE_ECB)
46
- elif self.method == "AES-128":
47
- self.cipher = AES.new(self.key[:16], AES.MODE_CBC, iv=self.iv)
48
- elif self.method == "AES-128-CTR":
49
- self.cipher = AES.new(self.key[:16], AES.MODE_CTR, nonce=self.iv)
50
- else:
51
- raise ValueError("Invalid or unsupported method")
52
-
53
- def decrypt(self, ciphertext: bytes) -> bytes:
54
- """
55
- Decrypt the ciphertext using the specified encryption method.
56
-
57
- Parameters:
58
- - ciphertext (bytes): The encrypted content to decrypt.
59
-
60
- Returns:
61
- bytes: The decrypted content.
62
- """
63
- start = time.perf_counter_ns()
64
- #logging.info(f"Ciphertext: {ciphertext}")
65
-
66
- # Decrypt based on encryption method
67
- if self.method in {"AES", "AES-128"}:
68
- decrypted_data = self.cipher.decrypt(ciphertext)
69
- decrypted_content = unpad(decrypted_data, AES.block_size)
70
-
71
- elif self.method == "AES-128-CTR":
72
- decrypted_content = self.cipher.decrypt(ciphertext)
73
- else:
74
- raise ValueError("Invalid or unsupported method")
75
-
76
- end = time.perf_counter_ns()
77
-
78
- # Calculate elapsed time with high precision
79
- elapsed_nanoseconds = end - start
80
- elapsed_milliseconds = elapsed_nanoseconds / 1_000_000
81
- elapsed_seconds = elapsed_nanoseconds / 1_000_000_000
82
-
83
- # Print performance metrics
84
- logging.info(f"[Crypto Decryption Performance]")
85
- logging.info(f"Method: {self.method}")
86
- logging.info(f"Decryption Time: {elapsed_milliseconds:.4f} ms ({elapsed_seconds:.6f} s)")
87
- logging.info(f"Decrypted Content Length: {len(decrypted_content)} bytes")
88
-
89
- return decrypted_content
90
-
91
-
92
- else:
93
-
94
- # Check if openssl command is available
95
- try:
96
- openssl_available = subprocess.run(["openssl", "version"], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL).returncode == 0
97
- logging.info("[cyan]Decrypy use: OPENSSL")
98
- except:
99
- openssl_available = False
100
-
101
- if not openssl_available:
102
- console.log("[red]Neither python library: pycryptodomex nor openssl software is installed. Please install either one of them. Read readme.md [Requirement].")
103
- sys.exit(0)
104
-
105
- class M3U8_Decryption:
41
+ self.key = key
42
+ self.iv = iv
43
+ if "0x" in str(iv):
44
+ self.iv = bytes.fromhex(iv.replace("0x", ""))
45
+ self.method = method
46
+
47
+ # Pre-create the cipher based on the encryption method
48
+ if self.method == "AES":
49
+ self.cipher = AES.new(self.key, AES.MODE_ECB)
50
+ elif self.method == "AES-128":
51
+ self.cipher = AES.new(self.key[:16], AES.MODE_CBC, iv=self.iv)
52
+ elif self.method == "AES-128-CTR":
53
+ self.cipher = AES.new(self.key[:16], AES.MODE_CTR, nonce=self.iv)
54
+ else:
55
+ raise ValueError("Invalid or unsupported method")
56
+
57
+ def decrypt(self, ciphertext: bytes) -> bytes:
58
+ """
59
+ Decrypt the ciphertext using the specified encryption method.
60
+
61
+ Parameters:
62
+ ciphertext (bytes): The encrypted content to decrypt.
63
+
64
+ Returns:
65
+ bytes: The decrypted content.
66
+ """
67
+ #start = time.perf_counter_ns()
68
+
69
+ if self.method in {"AES", "AES-128"}:
70
+ decrypted_data = self.cipher.decrypt(ciphertext)
71
+ decrypted_content = unpad(decrypted_data, AES.block_size)
72
+ elif self.method == "AES-128-CTR":
73
+ decrypted_content = self.cipher.decrypt(ciphertext)
74
+ else:
75
+ raise ValueError("Invalid or unsupported method")
76
+
106
77
  """
107
- Class for decrypting M3U8 playlist content using OpenSSL when the Crypto module is not available.
78
+ end = time.perf_counter_ns()
79
+
80
+ # Calculate the elapsed time with high precision
81
+ elapsed_nanoseconds = end - start
82
+ elapsed_milliseconds = elapsed_nanoseconds / 1_000_000
83
+ elapsed_seconds = elapsed_nanoseconds / 1_000_000_000
84
+
85
+ # Log performance metrics
86
+ logging.info("[Crypto Decryption Performance]")
87
+ logging.info(f"Method: {self.method}")
88
+ logging.info(f"Decryption Time: {elapsed_milliseconds:.4f} ms ({elapsed_seconds:.6f} s)")
89
+ logging.info(f"Decrypted Content Length: {len(decrypted_content)} bytes")
108
90
  """
109
- def __init__(self, key: bytes, iv: bytes, method: str) -> None:
110
- """
111
- Initialize the M3U8_Decryption object.
112
-
113
- Parameters:
114
- - key (bytes): The encryption key.
115
- - iv (bytes): The initialization vector (IV).
116
- - method (str): The encryption method.
117
- """
118
- self.key = key
119
- self.iv = iv
120
- if "0x" in str(iv):
121
- self.iv = bytes.fromhex(iv.replace("0x", ""))
122
- self.method = method
123
- logging.info(f"Decrypt add: ('key': {self.key}, 'iv': {self.iv}, 'method': {self.method})")
124
-
125
- def decrypt(self, ciphertext: bytes) -> bytes:
126
- """
127
- Decrypt the ciphertext using the specified encryption method.
128
-
129
- Parameters:
130
- - ciphertext (bytes): The encrypted content to decrypt.
131
-
132
- Returns:
133
- bytes: The decrypted content.
134
- """
135
- start = time.perf_counter_ns()
136
-
137
- # Construct OpenSSL command based on encryption method
138
- if self.method == "AES":
139
- openssl_cmd = f'openssl enc -d -aes-256-ecb -K {self.key.hex()} -nosalt'
140
- elif self.method == "AES-128":
141
- openssl_cmd = f'openssl enc -d -aes-128-cbc -K {self.key[:16].hex()} -iv {self.iv.hex()}'
142
- elif self.method == "AES-128-CTR":
143
- openssl_cmd = f'openssl enc -d -aes-128-ctr -K {self.key[:16].hex()} -iv {self.iv.hex()}'
144
- else:
145
- raise ValueError("Invalid or unsupported method")
146
-
147
- try:
148
- decrypted_content = subprocess.check_output(openssl_cmd.split(), input=ciphertext, stderr=subprocess.STDOUT)
149
- except subprocess.CalledProcessError as e:
150
- raise ValueError(f"Decryption failed: {e.output.decode()}")
151
-
152
- end = time.perf_counter_ns()
153
-
154
- # Calculate elapsed time with high precision
155
- elapsed_nanoseconds = end - start
156
- elapsed_milliseconds = elapsed_nanoseconds / 1_000_000
157
- elapsed_seconds = elapsed_nanoseconds / 1_000_000_000
158
-
159
- # Print performance metrics
160
- logging.info(f"[OpenSSL Decryption Performance]")
161
- logging.info(f"Method: {self.method}")
162
- logging.info(f"Decryption Time: {elapsed_milliseconds:.4f} ms ({elapsed_seconds:.6f} s)")
163
- logging.info(f"Decrypted Content Length: {len(decrypted_content)} bytes")
164
-
165
- return decrypted_content
91
+ return decrypted_content
@@ -14,13 +14,10 @@ from tqdm import tqdm
14
14
 
15
15
  # Internal utilities
16
16
  from StreamingCommunity.Util.color import Colors
17
+ from StreamingCommunity.Util.config_json import get_use_large_bar
17
18
  from StreamingCommunity.Util.os import internet_manager
18
19
 
19
20
 
20
- # Variable
21
- USE_LARGE_BAR = not ("android" in sys.platform or "ios" in sys.platform)
22
-
23
-
24
21
  class M3U8_Ts_Estimator:
25
22
  def __init__(self, total_segments: int, segments_instance=None):
26
23
  """
@@ -36,7 +33,7 @@ class M3U8_Ts_Estimator:
36
33
  self.lock = threading.Lock()
37
34
  self.speed = {"upload": "N/A", "download": "N/A"}
38
35
 
39
- if USE_LARGE_BAR:
36
+ if get_use_large_bar():
40
37
  logging.debug("USE_LARGE_BAR is True, starting speed capture thread")
41
38
  self.speed_thread = threading.Thread(target=self.capture_speed)
42
39
  self.speed_thread.daemon = True
@@ -106,15 +103,11 @@ class M3U8_Ts_Estimator:
106
103
  try:
107
104
  self.add_ts_file(total_downloaded * self.total_segments, total_downloaded, duration)
108
105
 
109
- #downloaded_file_size_str = internet_manager.format_file_size(self.now_downloaded_size)
110
106
  file_total_size = self.calculate_total_size()
111
-
112
- #number_file_downloaded = downloaded_file_size_str.split(' ')[0]
113
107
  number_file_total_size = file_total_size.split(' ')[0]
114
- #units_file_downloaded = downloaded_file_size_str.split(' ')[1]
115
108
  units_file_total_size = file_total_size.split(' ')[1]
116
109
 
117
- if USE_LARGE_BAR:
110
+ if get_use_large_bar():
118
111
  speed_data = self.speed['download'].split(" ")
119
112
 
120
113
  if len(speed_data) >= 2:
@@ -126,17 +119,16 @@ class M3U8_Ts_Estimator:
126
119
 
127
120
  retry_count = self.segments_instance.active_retries if self.segments_instance else 0
128
121
  progress_str = (
129
- #f"{Colors.WHITE}[ {Colors.GREEN}{number_file_downloaded} {Colors.WHITE}< "
130
- f"{Colors.GREEN}{number_file_total_size} {Colors.RED}{units_file_total_size}"
122
+ f"{Colors.GREEN}{number_file_total_size} {Colors.WHITE}< {Colors.RED}{units_file_total_size}"
131
123
  f"{Colors.WHITE} {Colors.CYAN}{average_internet_speed} {Colors.RED}{average_internet_unit}"
132
- f"{Colors.WHITE} {Colors.GREEN}CRR {Colors.RED}{retry_count} "
124
+ f"{Colors.WHITE}, {Colors.GREEN}CRR {Colors.RED}{retry_count} "
133
125
  )
126
+
134
127
  else:
135
128
  retry_count = self.segments_instance.active_retries if self.segments_instance else 0
136
129
  progress_str = (
137
- #f"{Colors.WHITE}[ {Colors.GREEN}{number_file_downloaded} {Colors.WHITE}< "
138
- f"{Colors.GREEN}{number_file_total_size} {Colors.RED}{units_file_total_size}"
139
- f"{Colors.WHITE} {Colors.GREEN}CRR {Colors.RED}{retry_count} "
130
+ f"{Colors.GREEN}{number_file_total_size} {Colors.WHITE}< {Colors.RED}{units_file_total_size}"
131
+ f"{Colors.WHITE}, {Colors.GREEN}CRR {Colors.RED}{retry_count} "
140
132
  )
141
133
 
142
134
  progress_counter.set_postfix_str(progress_str)
@@ -9,10 +9,6 @@ from m3u8 import loads
9
9
  from StreamingCommunity.Util.os import internet_manager
10
10
 
11
11
 
12
- # External libraries
13
- import httpx
14
-
15
-
16
12
  # Costant
17
13
  CODEC_MAPPINGS = {
18
14
  "video": {
@@ -79,7 +75,6 @@ class M3U8_Codec:
79
75
  Extracted codecs are set as attributes: audio_codec and video_codec.
80
76
  """
81
77
  try:
82
- # Split the codecs string by comma
83
78
  codecs_list = self.codecs.split(',')
84
79
  except Exception as e:
85
80
  logging.error(f"Can't split codec list: {self.codecs} with error {e}")
@@ -407,10 +402,8 @@ class M3U8_Parser:
407
402
  Parameters:
408
403
  - m3u8_content (str): The content of the M3U8 file.
409
404
  """
410
-
411
- # Get obj of the m3u8 text content download, dictionary with video, audio, segments, subtitles
412
405
  m3u8_obj = loads(raw_content, uri)
413
-
406
+
414
407
  self.__parse_video_info__(m3u8_obj)
415
408
  self.__parse_subtitles_and_audio__(m3u8_obj)
416
409
  self.__parse_segments__(m3u8_obj)
@@ -469,7 +462,6 @@ class M3U8_Parser:
469
462
  Parameters:
470
463
  - m3u8_obj: The M3U8 object containing video playlists.
471
464
  """
472
-
473
465
  try:
474
466
  for playlist in m3u8_obj.playlists:
475
467
 
@@ -569,7 +561,6 @@ class M3U8_Parser:
569
561
  Parameters:
570
562
  - m3u8_obj: The M3U8 object containing segment data.
571
563
  """
572
-
573
564
  try:
574
565
  for segment in m3u8_obj.segments:
575
566
 
@@ -606,13 +597,6 @@ class M3U8_Parser:
606
597
  Returns:
607
598
  - formatted_duration (str): Formatted duration string with hours, minutes, and seconds if return_string is True.
608
599
  - duration_dict (dict): Dictionary with keys 'h', 'm', 's' representing hours, minutes, and seconds respectively if return_string is False.
609
-
610
- Example usage:
611
- >>> obj = YourClass(duration=3661)
612
- >>> obj.get_duration()
613
- '[yellow]1[red]h [yellow]1[red]m [yellow]1[red]s'
614
- >>> obj.get_duration(return_string=False)
615
- {'h': 1, 'm': 1, 's': 1}
616
600
  """
617
601
 
618
602
  # Calculate hours, minutes, and remaining seconds
@@ -33,8 +33,6 @@ class M3U8_UrlFix:
33
33
  Returns:
34
34
  str: The full URL for the specified resource.
35
35
  """
36
-
37
- # Check if m3u8 url playlist is present
38
36
  if self.url_playlist == None:
39
37
  logging.error("[M3U8_UrlFix] Cant generate full url, playlist not present")
40
38
  raise
@@ -54,5 +52,4 @@ class M3U8_UrlFix:
54
52
  """
55
53
  Reset the M3U8 playlist URL to its default state (None).
56
54
  """
57
- self.url_playlist = None
58
-
55
+ self.url_playlist = None
@@ -1,2 +1,4 @@
1
+ # 17.09.24
2
+
1
3
  from .tmdb import tmdb
2
4
  from .obj_tmbd import Json_film
@@ -5,35 +5,21 @@ from typing import Dict
5
5
 
6
6
  class Json_film:
7
7
  def __init__(self, data: Dict):
8
- self.adult = data.get('adult', False)
9
- self.backdrop_path = data.get('backdrop_path')
10
- self.budget = data.get('budget', 0)
11
- self.homepage = data.get('homepage')
12
8
  self.id = data.get('id', 0)
13
9
  self.imdb_id = data.get('imdb_id')
14
10
  self.origin_country = data.get('origin_country', [])
15
11
  self.original_language = data.get('original_language')
16
12
  self.original_title = data.get('original_title')
17
- self.overview = data.get('overview')
18
13
  self.popularity = data.get('popularity', 0.0)
19
14
  self.poster_path = data.get('poster_path')
20
15
  self.release_date = data.get('release_date')
21
- self.revenue = data.get('revenue', 0)
22
- self.runtime = data.get('runtime', 0)
23
16
  self.status = data.get('status')
24
- self.tagline = data.get('tagline')
25
17
  self.title = data.get('title')
26
- self.video = data.get('video', False)
27
18
  self.vote_average = data.get('vote_average', 0.0)
28
19
  self.vote_count = data.get('vote_count', 0)
29
20
 
30
21
  def __repr__(self):
31
- return (f"Film(adult={self.adult}, backdrop_path='{self.backdrop_path}', "
32
- f"budget={self.budget}, "
33
- f"homepage='{self.homepage}', id={self.id}, "
34
- f"imdb_id='{self.imdb_id}', origin_country={self.origin_country}, "
22
+ return (f"Json_film(id={self.id}, imdb_id='{self.imdb_id}', origin_country={self.origin_country}, "
35
23
  f"original_language='{self.original_language}', original_title='{self.original_title}', "
36
- f"overview='{self.overview}', popularity={self.popularity}, poster_path='{self.poster_path}', "
37
- f"release_date='{self.release_date}', revenue={self.revenue}, runtime={self.runtime}, "
38
- f"status='{self.status}', tagline='{self.tagline}', "
39
- f"title='{self.title}', video={self.video}, vote_average={self.vote_average}, vote_count={self.vote_count})")
24
+ f"popularity={self.popularity}, poster_path='{self.poster_path}', release_date='{self.release_date}', "
25
+ f"status='{self.status}', title='{self.title}', vote_average={self.vote_average}, vote_count={self.vote_count})")
@@ -6,22 +6,22 @@ from typing import Dict
6
6
 
7
7
  # External libraries
8
8
  import httpx
9
+ from rich.console import Console
9
10
 
10
11
 
11
12
  # Internal utilities
12
13
  from .obj_tmbd import Json_film
13
- from StreamingCommunity.Util.console import console
14
- from StreamingCommunity.Util._jsonConfig import config_manager
14
+ from StreamingCommunity.Util.config_json import config_manager
15
15
  from StreamingCommunity.Util.table import TVShowManager
16
16
 
17
17
 
18
18
  # Variable
19
+ console = Console()
19
20
  table_show_manager = TVShowManager()
20
21
  api_key = "a800ed6c93274fb857ea61bd9e7256c5"
21
22
  MAX_TIMEOUT = config_manager.get_int("REQUESTS", "timeout")
22
23
 
23
24
 
24
-
25
25
  def get_select_title(table_show_manager, generic_obj):
26
26
  """
27
27
  Display a selection of titles and prompt the user to choose one.
@@ -29,11 +29,6 @@ def get_select_title(table_show_manager, generic_obj):
29
29
  Returns:
30
30
  dict: The selected media item.
31
31
  """
32
-
33
- # Set up table for displaying titles
34
- table_show_manager.set_slice_end(10)
35
-
36
- # Check if the generic_obj list is empty
37
32
  if not generic_obj:
38
33
  console.print("\n[red]No media items available.")
39
34
  return None
@@ -158,7 +153,7 @@ class TheMovieDB:
158
153
 
159
154
  # Join with colored arrows and print with proper category label
160
155
  console.print(
161
- f"[bold purple]{category}:[/] {' [red][/] '.join(colored_items)}"
156
+ f"[bold purple]{category}:[/] {' [red]->[/] '.join(colored_items)}"
162
157
  )
163
158
 
164
159
  def display_trending_tv_shows(self):