StreamingCommunity 1.7.6__py3-none-any.whl → 1.9.1__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 (101) hide show
  1. StreamingCommunity/{Src/Api → Api}/Player/Helper/Vixcloud/js_parser.py +4 -1
  2. StreamingCommunity/{Src/Api → Api}/Player/Helper/Vixcloud/util.py +166 -166
  3. StreamingCommunity/{Src/Api → Api}/Player/ddl.py +89 -89
  4. StreamingCommunity/{Src/Api → Api}/Player/maxstream.py +151 -151
  5. StreamingCommunity/{Src/Api → Api}/Player/supervideo.py +193 -193
  6. StreamingCommunity/{Src/Api → Api}/Player/vixcloud.py +224 -212
  7. StreamingCommunity/{Src/Api → Api}/Site/1337xx/__init__.py +50 -50
  8. StreamingCommunity/{Src/Api → Api}/Site/1337xx/costant.py +15 -15
  9. StreamingCommunity/{Src/Api → Api}/Site/1337xx/site.py +83 -83
  10. StreamingCommunity/{Src/Api → Api}/Site/1337xx/title.py +66 -66
  11. StreamingCommunity/{Src/Api → Api}/Site/altadefinizione/__init__.py +50 -50
  12. StreamingCommunity/{Src/Api/Site/mostraguarda → Api/Site/altadefinizione}/costant.py +15 -15
  13. StreamingCommunity/{Src/Api → Api}/Site/altadefinizione/film.py +69 -69
  14. StreamingCommunity/{Src/Api → Api}/Site/altadefinizione/site.py +86 -86
  15. StreamingCommunity/{Src/Api → Api}/Site/animeunity/__init__.py +50 -50
  16. StreamingCommunity/{Src/Api/Site/altadefinizione → Api/Site/animeunity}/costant.py +15 -15
  17. StreamingCommunity/{Src/Api → Api}/Site/animeunity/film_serie.py +130 -131
  18. StreamingCommunity/{Src/Api → Api}/Site/animeunity/site.py +164 -164
  19. StreamingCommunity/{Src/Api → Api}/Site/animeunity/util/ScrapeSerie.py +3 -3
  20. StreamingCommunity/{Src/Api → Api}/Site/bitsearch/__init__.py +51 -51
  21. StreamingCommunity/{Src/Api → Api}/Site/bitsearch/costant.py +15 -15
  22. StreamingCommunity/{Src/Api → Api}/Site/bitsearch/site.py +84 -84
  23. StreamingCommunity/{Src/Api → Api}/Site/bitsearch/title.py +47 -47
  24. StreamingCommunity/{Src/Api → Api}/Site/cb01new/__init__.py +51 -51
  25. StreamingCommunity/{Src/Api → Api}/Site/cb01new/costant.py +15 -15
  26. StreamingCommunity/{Src/Api → Api}/Site/cb01new/film.py +69 -69
  27. StreamingCommunity/{Src/Api → Api}/Site/cb01new/site.py +74 -74
  28. StreamingCommunity/{Src/Api → Api}/Site/ddlstreamitaly/__init__.py +57 -57
  29. StreamingCommunity/{Src/Api → Api}/Site/ddlstreamitaly/costant.py +16 -16
  30. StreamingCommunity/{Src/Api → Api}/Site/ddlstreamitaly/series.py +141 -142
  31. StreamingCommunity/{Src/Api → Api}/Site/ddlstreamitaly/site.py +92 -92
  32. StreamingCommunity/{Src/Api → Api}/Site/ddlstreamitaly/util/ScrapeSerie.py +84 -82
  33. StreamingCommunity/{Src/Api → Api}/Site/guardaserie/__init__.py +52 -52
  34. StreamingCommunity/{Src/Api/Site/piratebays → Api/Site/guardaserie}/costant.py +15 -15
  35. StreamingCommunity/{Src/Api → Api}/Site/guardaserie/series.py +195 -195
  36. StreamingCommunity/{Src/Api → Api}/Site/guardaserie/site.py +84 -84
  37. StreamingCommunity/{Src/Api → Api}/Site/guardaserie/util/ScrapeSerie.py +110 -110
  38. StreamingCommunity/{Src/Api → Api}/Site/mostraguarda/__init__.py +48 -48
  39. StreamingCommunity/{Src/Api/Site/animeunity → Api/Site/mostraguarda}/costant.py +15 -15
  40. StreamingCommunity/{Src/Api → Api}/Site/mostraguarda/film.py +94 -94
  41. StreamingCommunity/{Src/Api → Api}/Site/piratebays/__init__.py +50 -50
  42. StreamingCommunity/{Src/Api/Site/guardaserie → Api/Site/piratebays}/costant.py +15 -15
  43. StreamingCommunity/{Src/Api → Api}/Site/piratebays/site.py +88 -88
  44. StreamingCommunity/{Src/Api → Api}/Site/piratebays/title.py +45 -45
  45. StreamingCommunity/{Src/Api → Api}/Site/streamingcommunity/__init__.py +55 -55
  46. StreamingCommunity/{Src/Api → Api}/Site/streamingcommunity/costant.py +15 -15
  47. StreamingCommunity/{Src/Api → Api}/Site/streamingcommunity/film.py +70 -70
  48. StreamingCommunity/{Src/Api → Api}/Site/streamingcommunity/series.py +205 -203
  49. StreamingCommunity/{Src/Api → Api}/Site/streamingcommunity/site.py +125 -125
  50. StreamingCommunity/{Src/Api → Api}/Site/streamingcommunity/util/ScrapeSerie.py +3 -3
  51. StreamingCommunity/{Src/Api → Api}/Template/Class/SearchType.py +101 -101
  52. StreamingCommunity/{Src/Api → Api}/Template/Util/__init__.py +4 -4
  53. StreamingCommunity/{Src/Api → Api}/Template/Util/get_domain.py +137 -137
  54. StreamingCommunity/{Src/Api → Api}/Template/Util/manage_ep.py +153 -153
  55. StreamingCommunity/{Src/Api → Api}/Template/Util/recall_search.py +37 -37
  56. StreamingCommunity/Api/Template/__init__.py +3 -0
  57. StreamingCommunity/{Src/Api → Api}/Template/site.py +87 -87
  58. StreamingCommunity/{Src/Lib → Lib}/Downloader/HLS/downloader.py +968 -968
  59. StreamingCommunity/{Src/Lib → Lib}/Downloader/HLS/proxyes.py +110 -110
  60. StreamingCommunity/{Src/Lib → Lib}/Downloader/HLS/segments.py +538 -540
  61. StreamingCommunity/{Src/Lib → Lib}/Downloader/MP4/downloader.py +156 -156
  62. StreamingCommunity/{Src/Lib → Lib}/Downloader/TOR/downloader.py +222 -222
  63. StreamingCommunity/{Src/Lib → Lib}/Downloader/__init__.py +4 -4
  64. StreamingCommunity/{Src/Lib → Lib}/Driver/driver_1.py +76 -76
  65. StreamingCommunity/{Src/Lib → Lib}/FFmpeg/__init__.py +4 -4
  66. StreamingCommunity/{Src/Lib → Lib}/FFmpeg/capture.py +170 -170
  67. StreamingCommunity/{Src/Lib → Lib}/FFmpeg/command.py +292 -292
  68. StreamingCommunity/{Src/Lib → Lib}/FFmpeg/util.py +241 -241
  69. StreamingCommunity/{Src/Lib → Lib}/M3U8/__init__.py +5 -5
  70. StreamingCommunity/{Src/Lib → Lib}/M3U8/decryptor.py +164 -129
  71. StreamingCommunity/{Src/Lib → Lib}/M3U8/estimator.py +175 -172
  72. StreamingCommunity/{Src/Lib → Lib}/M3U8/parser.py +666 -666
  73. StreamingCommunity/{Src/Lib → Lib}/M3U8/url_fixer.py +51 -51
  74. StreamingCommunity/Lib/TMBD/__init__.py +2 -0
  75. StreamingCommunity/{Src/Lib → Lib}/TMBD/obj_tmbd.py +39 -39
  76. StreamingCommunity/{Src/Lib → Lib}/TMBD/tmdb.py +345 -345
  77. StreamingCommunity/{Src/Upload → Upload}/update.py +68 -64
  78. StreamingCommunity/{Src/Upload → Upload}/version.py +5 -5
  79. StreamingCommunity/{Src/Util → Util}/_jsonConfig.py +204 -204
  80. StreamingCommunity/{Src/Util → Util}/call_stack.py +42 -42
  81. StreamingCommunity/{Src/Util → Util}/color.py +20 -20
  82. StreamingCommunity/{Src/Util → Util}/console.py +12 -12
  83. StreamingCommunity/Util/ffmpeg_installer.py +275 -0
  84. StreamingCommunity/{Src/Util → Util}/headers.py +147 -147
  85. StreamingCommunity/{Src/Util → Util}/logger.py +53 -53
  86. StreamingCommunity/{Src/Util → Util}/message.py +46 -46
  87. StreamingCommunity/{Src/Util → Util}/os.py +514 -417
  88. StreamingCommunity/{Src/Util → Util}/table.py +163 -163
  89. StreamingCommunity/run.py +202 -196
  90. {StreamingCommunity-1.7.6.dist-info → StreamingCommunity-1.9.1.dist-info}/METADATA +126 -60
  91. StreamingCommunity-1.9.1.dist-info/RECORD +95 -0
  92. {StreamingCommunity-1.7.6.dist-info → StreamingCommunity-1.9.1.dist-info}/WHEEL +1 -1
  93. StreamingCommunity/Src/Api/Site/animeunity/anime.py +0 -126
  94. StreamingCommunity/Src/Api/Site/ddlstreamitaly/Player/ScrapeSerie.py +0 -83
  95. StreamingCommunity/Src/Api/Site/guardaserie/Player/ScrapeSerie.py +0 -110
  96. StreamingCommunity/Src/Api/Template/__init__.py +0 -3
  97. StreamingCommunity/Src/Lib/TMBD/__init__.py +0 -2
  98. StreamingCommunity-1.7.6.dist-info/RECORD +0 -97
  99. {StreamingCommunity-1.7.6.dist-info → StreamingCommunity-1.9.1.dist-info}/LICENSE +0 -0
  100. {StreamingCommunity-1.7.6.dist-info → StreamingCommunity-1.9.1.dist-info}/entry_points.txt +0 -0
  101. {StreamingCommunity-1.7.6.dist-info → StreamingCommunity-1.9.1.dist-info}/top_level.txt +0 -0
StreamingCommunity/run.py CHANGED
@@ -1,196 +1,202 @@
1
- # 10.12.23
2
-
3
- import os
4
- import sys
5
- import time
6
- import glob
7
- import logging
8
- import platform
9
- import argparse
10
- import importlib
11
- from typing import Callable
12
-
13
-
14
- # Internal utilities
15
- from StreamingCommunity.Src.Util.message import start_message
16
- from StreamingCommunity.Src.Util.console import console, msg
17
- from StreamingCommunity.Src.Util._jsonConfig import config_manager
18
- from StreamingCommunity.Src.Upload.update import update as git_update
19
- from StreamingCommunity.Src.Util.os import os_summary
20
- from StreamingCommunity.Src.Lib.TMBD import tmdb
21
- from StreamingCommunity.Src.Util.logger import Logger
22
-
23
-
24
- # Config
25
- CLOSE_CONSOLE = config_manager.get_bool('DEFAULT', 'not_close')
26
- SHOW_TRENDING = config_manager.get_bool('DEFAULT', 'show_trending')
27
-
28
-
29
- def run_function(func: Callable[..., None], close_console: bool = False) -> None:
30
- """
31
- Run a given function indefinitely or once, depending on the value of close_console.
32
-
33
- Parameters:
34
- func (Callable[..., None]): The function to run.
35
- close_console (bool, optional): Whether to close the console after running the function once. Defaults to False.
36
- """
37
- if close_console:
38
- while 1:
39
- func()
40
- else:
41
- func()
42
-
43
-
44
- def load_search_functions():
45
- modules = []
46
- loaded_functions = {}
47
-
48
- # Traverse the Api directory
49
- api_dir = os.path.join(os.path.dirname(__file__), 'Src', 'Api', 'Site')
50
- init_files = glob.glob(os.path.join(api_dir, '*', '__init__.py'))
51
-
52
- # Retrieve modules and their indices
53
- for init_file in init_files:
54
-
55
- # Get folder name as module name
56
- module_name = os.path.basename(os.path.dirname(init_file))
57
- logging.info(f"Load module name: {module_name}")
58
-
59
- try:
60
- # Dynamically import the module
61
- mod = importlib.import_module(f'StreamingCommunity.Src.Api.Site.{module_name}')
62
-
63
- # Get 'indice' from the module
64
- indice = getattr(mod, 'indice', 0)
65
- is_deprecate = bool(getattr(mod, '_deprecate', True))
66
- use_for = getattr(mod, '_useFor', 'other')
67
-
68
- if not is_deprecate:
69
- modules.append((module_name, indice, use_for))
70
-
71
- except Exception as e:
72
- console.print(f"[red]Failed to import module {module_name}: {str(e)}")
73
-
74
- # Sort modules by 'indice'
75
- modules.sort(key=lambda x: x[1])
76
-
77
- # Load search functions in the sorted order
78
- for module_name, _, use_for in modules:
79
-
80
- # Construct a unique alias for the module
81
- module_alias = f'{module_name}_search'
82
-
83
- try:
84
-
85
- # Dynamically import the module
86
- mod = importlib.import_module(f'StreamingCommunity.Src.Api.Site.{module_name}')
87
-
88
- # Get the search function from the module (assuming the function is named 'search' and defined in __init__.py)
89
- search_function = getattr(mod, 'search')
90
-
91
- # Add the function to the loaded functions dictionary
92
- loaded_functions[module_alias] = (search_function, use_for)
93
-
94
- except Exception as e:
95
- console.print(f"[red]Failed to load search function from module {module_name}: {str(e)}")
96
-
97
- return loaded_functions
98
-
99
-
100
- def initialize():
101
-
102
- # Get start message
103
- start_message()
104
-
105
- # Get system info
106
- os_summary.get_system_summary()
107
-
108
- # Set terminal size for win 7
109
- if platform.system() == "Windows" and "7" in platform.version():
110
- os.system('mode 120, 40')
111
-
112
- # Check python version
113
- if sys.version_info < (3, 7):
114
- console.log("[red]Install python version > 3.7.16")
115
- sys.exit(0)
116
-
117
- # Attempting GitHub update
118
- try:
119
- git_update()
120
- print()
121
- except:
122
- console.log("[red]Error with loading github.")
123
-
124
- # Show trending film and series
125
- if SHOW_TRENDING:
126
- tmdb.display_trending_films()
127
- print()
128
- tmdb.display_trending_tv_shows()
129
- print()
130
-
131
-
132
- def main():
133
-
134
- start = time.time()
135
-
136
- # Create logger
137
- log_not = Logger()
138
- initialize()
139
-
140
- # Load search functions
141
- search_functions = load_search_functions()
142
- logging.info(f"Load module in: {time.time() - start} s")
143
-
144
- # Create dynamic argument parser
145
- parser = argparse.ArgumentParser(description='Script to download film and series from the internet.')
146
-
147
- color_map = {
148
- "anime": "red",
149
- "film_serie": "yellow",
150
- "film": "blue",
151
- "serie": "green",
152
- "other": "white"
153
- }
154
-
155
- # Add dynamic arguments based on loaded search modules
156
- for alias, (_, use_for) in search_functions.items():
157
- short_option = alias[:3].upper()
158
- long_option = alias
159
- parser.add_argument(f'-{short_option}', f'--{long_option}', action='store_true', help=f'Search for {alias.split("_")[0]} on streaming platforms.')
160
-
161
- # Parse command line arguments
162
- args = parser.parse_args()
163
-
164
- # Mapping command-line arguments to functions
165
- arg_to_function = {alias: func for alias, (func, _) in search_functions.items()}
166
-
167
- # Check which argument is provided and run the corresponding function
168
- for arg, func in arg_to_function.items():
169
- if getattr(args, arg):
170
- run_function(func)
171
- return
172
-
173
- # Mapping user input to functions
174
- input_to_function = {str(i): func for i, (alias, (func, _)) in enumerate(search_functions.items())}
175
-
176
- # Create dynamic prompt message and choices
177
- choice_labels = {str(i): (alias.split("_")[0].capitalize(), use_for) for i, (alias, (_, use_for)) in enumerate(search_functions.items())}
178
-
179
- # Display the category legend in a single line
180
- legend_text = " | ".join([f"[{color}]{category.capitalize()}[/{color}]" for category, color in color_map.items()])
181
- console.print(f"[bold green]Category Legend:[/bold green] {legend_text}")
182
-
183
- # Construct the prompt message with color-coded site names
184
- prompt_message = "[green]Insert category [white](" + ", ".join(
185
- [f"{key}: [{color_map[label[1]]}]{label[0]}[/{color_map[label[1]]}]" for key, label in choice_labels.items()]
186
- ) + "[white])"
187
-
188
- # Ask the user for input
189
- category = msg.ask(prompt_message, choices=list(choice_labels.keys()), default="0", show_choices=False, show_default=False)
190
-
191
- # Run the corresponding function based on user input
192
- if category in input_to_function:
193
- run_function(input_to_function[category])
194
- else:
195
- console.print("[red]Invalid category.")
196
- sys.exit(0)
1
+ # 10.12.23
2
+
3
+ import os
4
+ import sys
5
+ import time
6
+ import glob
7
+ import logging
8
+ import platform
9
+ import argparse
10
+ import importlib
11
+ from typing import Callable
12
+
13
+
14
+ # Internal utilities
15
+ from StreamingCommunity.Util.message import start_message
16
+ from StreamingCommunity.Util.console import console, msg
17
+ from StreamingCommunity.Util._jsonConfig import config_manager
18
+ from StreamingCommunity.Upload.update import update as git_update
19
+ from StreamingCommunity.Util.os import OsSummary
20
+ from StreamingCommunity.Lib.TMBD import tmdb
21
+ from StreamingCommunity.Util.logger import Logger
22
+
23
+
24
+ # Config
25
+ CLOSE_CONSOLE = config_manager.get_bool('DEFAULT', 'not_close')
26
+ SHOW_TRENDING = config_manager.get_bool('DEFAULT', 'show_trending')
27
+
28
+
29
+ def run_function(func: Callable[..., None], close_console: bool = False) -> None:
30
+ """
31
+ Run a given function indefinitely or once, depending on the value of close_console.
32
+
33
+ Parameters:
34
+ func (Callable[..., None]): The function to run.
35
+ close_console (bool, optional): Whether to close the console after running the function once. Defaults to False.
36
+ """
37
+ if close_console:
38
+ while 1:
39
+ func()
40
+ else:
41
+ func()
42
+
43
+
44
+ def load_search_functions():
45
+ modules = []
46
+ loaded_functions = {}
47
+
48
+ # Find api home directory
49
+ if getattr(sys, 'frozen', False): # Modalità PyInstaller
50
+ base_path = os.path.join(sys._MEIPASS, "StreamingCommunity")
51
+ else:
52
+ base_path = os.path.dirname(__file__)
53
+
54
+ api_dir = os.path.join(base_path, 'Api', 'Site')
55
+ init_files = glob.glob(os.path.join(api_dir, '*', '__init__.py'))
56
+
57
+ # Retrieve modules and their indices
58
+ for init_file in init_files:
59
+
60
+ # Get folder name as module name
61
+ module_name = os.path.basename(os.path.dirname(init_file))
62
+ logging.info(f"Load module name: {module_name}")
63
+
64
+ try:
65
+ # Dynamically import the module
66
+ mod = importlib.import_module(f'StreamingCommunity.Api.Site.{module_name}')
67
+
68
+ # Get 'indice' from the module
69
+ indice = getattr(mod, 'indice', 0)
70
+ is_deprecate = bool(getattr(mod, '_deprecate', True))
71
+ use_for = getattr(mod, '_useFor', 'other')
72
+
73
+ if not is_deprecate:
74
+ modules.append((module_name, indice, use_for))
75
+
76
+ except Exception as e:
77
+ console.print(f"[red]Failed to import module {module_name}: {str(e)}")
78
+
79
+ # Sort modules by 'indice'
80
+ modules.sort(key=lambda x: x[1])
81
+
82
+ # Load search functions in the sorted order
83
+ for module_name, _, use_for in modules:
84
+
85
+ # Construct a unique alias for the module
86
+ module_alias = f'{module_name}_search'
87
+
88
+ try:
89
+
90
+ # Dynamically import the module
91
+ mod = importlib.import_module(f'StreamingCommunity.Api.Site.{module_name}')
92
+
93
+ # Get the search function from the module (assuming the function is named 'search' and defined in __init__.py)
94
+ search_function = getattr(mod, 'search')
95
+
96
+ # Add the function to the loaded functions dictionary
97
+ loaded_functions[module_alias] = (search_function, use_for)
98
+
99
+ except Exception as e:
100
+ console.print(f"[red]Failed to load search function from module {module_name}: {str(e)}")
101
+
102
+ return loaded_functions
103
+
104
+
105
+ def initialize():
106
+
107
+ # Get start message
108
+ start_message()
109
+
110
+ # Get system info
111
+ os_summary = OsSummary()
112
+ os_summary.get_system_summary()
113
+
114
+ # Set terminal size for win 7
115
+ if platform.system() == "Windows" and "7" in platform.version():
116
+ os.system('mode 120, 40')
117
+
118
+ # Check python version
119
+ if sys.version_info < (3, 7):
120
+ console.log("[red]Install python version > 3.7.16")
121
+ sys.exit(0)
122
+
123
+ # Attempting GitHub update
124
+ try:
125
+ git_update()
126
+ print()
127
+ except:
128
+ console.log("[red]Error with loading github.")
129
+
130
+ # Show trending film and series
131
+ if SHOW_TRENDING:
132
+ tmdb.display_trending_films()
133
+ print()
134
+ tmdb.display_trending_tv_shows()
135
+ print()
136
+
137
+
138
+ def main():
139
+
140
+ start = time.time()
141
+
142
+ # Create logger
143
+ log_not = Logger()
144
+ initialize()
145
+
146
+ # Load search functions
147
+ search_functions = load_search_functions()
148
+ logging.info(f"Load module in: {time.time() - start} s")
149
+
150
+ # Create dynamic argument parser
151
+ parser = argparse.ArgumentParser(description='Script to download film and series from the internet.')
152
+
153
+ color_map = {
154
+ "anime": "red",
155
+ "film_serie": "yellow",
156
+ "film": "blue",
157
+ "serie": "green",
158
+ "other": "white"
159
+ }
160
+
161
+ # Add dynamic arguments based on loaded search modules
162
+ for alias, (_, use_for) in search_functions.items():
163
+ short_option = alias[:3].upper()
164
+ long_option = alias
165
+ parser.add_argument(f'-{short_option}', f'--{long_option}', action='store_true', help=f'Search for {alias.split("_")[0]} on streaming platforms.')
166
+
167
+ # Parse command line arguments
168
+ args = parser.parse_args()
169
+
170
+ # Mapping command-line arguments to functions
171
+ arg_to_function = {alias: func for alias, (func, _) in search_functions.items()}
172
+
173
+ # Check which argument is provided and run the corresponding function
174
+ for arg, func in arg_to_function.items():
175
+ if getattr(args, arg):
176
+ run_function(func)
177
+ return
178
+
179
+ # Mapping user input to functions
180
+ input_to_function = {str(i): func for i, (alias, (func, _)) in enumerate(search_functions.items())}
181
+
182
+ # Create dynamic prompt message and choices
183
+ choice_labels = {str(i): (alias.split("_")[0].capitalize(), use_for) for i, (alias, (_, use_for)) in enumerate(search_functions.items())}
184
+
185
+ # Display the category legend in a single line
186
+ legend_text = " | ".join([f"[{color}]{category.capitalize()}[/{color}]" for category, color in color_map.items()])
187
+ console.print(f"\n[bold green]Category Legend:[/bold green] {legend_text}")
188
+
189
+ # Construct the prompt message with color-coded site names
190
+ prompt_message = "[green]Insert category [white](" + ", ".join(
191
+ [f"{key}: [{color_map[label[1]]}]{label[0]}[/{color_map[label[1]]}]" for key, label in choice_labels.items()]
192
+ ) + "[white])"
193
+
194
+ # Ask the user for input
195
+ category = msg.ask(prompt_message, choices=list(choice_labels.keys()), default="0", show_choices=False, show_default=False)
196
+
197
+ # Run the corresponding function based on user input
198
+ if category in input_to_function:
199
+ run_function(input_to_function[category])
200
+ else:
201
+ console.print("[red]Invalid category.")
202
+ sys.exit(0)