StreamingCommunity 2.7.0__py3-none-any.whl → 2.9.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.
- StreamingCommunity/Api/Player/ddl.py +2 -2
- StreamingCommunity/Api/Player/maxstream.py +7 -13
- StreamingCommunity/Api/Player/supervideo.py +7 -33
- StreamingCommunity/Api/Player/vixcloud.py +8 -80
- StreamingCommunity/Api/Site/1337xx/__init__.py +8 -1
- StreamingCommunity/Api/Site/1337xx/site.py +10 -16
- StreamingCommunity/Api/Site/1337xx/title.py +4 -1
- StreamingCommunity/Api/Site/animeunity/__init__.py +9 -2
- StreamingCommunity/Api/Site/animeunity/film_serie.py +7 -1
- StreamingCommunity/Api/Site/animeunity/site.py +8 -10
- StreamingCommunity/Api/Site/animeunity/util/ScrapeSerie.py +1 -1
- StreamingCommunity/Api/Site/cb01new/__init__.py +8 -1
- StreamingCommunity/Api/Site/cb01new/film.py +10 -6
- StreamingCommunity/Api/Site/cb01new/site.py +16 -15
- StreamingCommunity/Api/Site/ddlstreamitaly/__init__.py +9 -2
- StreamingCommunity/Api/Site/ddlstreamitaly/series.py +7 -1
- StreamingCommunity/Api/Site/ddlstreamitaly/site.py +10 -15
- StreamingCommunity/Api/Site/ddlstreamitaly/util/ScrapeSerie.py +1 -1
- StreamingCommunity/Api/Site/guardaserie/__init__.py +9 -2
- StreamingCommunity/Api/Site/guardaserie/series.py +13 -8
- StreamingCommunity/Api/Site/guardaserie/site.py +12 -17
- StreamingCommunity/Api/Site/guardaserie/util/ScrapeSerie.py +1 -1
- StreamingCommunity/Api/Site/mostraguarda/__init__.py +6 -2
- StreamingCommunity/Api/Site/mostraguarda/film.py +10 -8
- StreamingCommunity/Api/Site/streamingcommunity/__init__.py +9 -2
- StreamingCommunity/Api/Site/streamingcommunity/film.py +11 -6
- StreamingCommunity/Api/Site/streamingcommunity/series.py +17 -10
- StreamingCommunity/Api/Site/streamingcommunity/site.py +10 -15
- StreamingCommunity/Api/Site/streamingcommunity/util/ScrapeSerie.py +2 -2
- StreamingCommunity/Api/Template/Util/__init__.py +0 -1
- StreamingCommunity/Api/Template/Util/get_domain.py +24 -66
- StreamingCommunity/Api/Template/Util/manage_ep.py +10 -5
- StreamingCommunity/Api/Template/config_loader.py +8 -8
- StreamingCommunity/Api/Template/site.py +3 -6
- StreamingCommunity/Lib/Downloader/HLS/downloader.py +15 -14
- StreamingCommunity/Lib/Downloader/HLS/segments.py +11 -31
- StreamingCommunity/Lib/Downloader/MP4/downloader.py +12 -9
- StreamingCommunity/Lib/Downloader/TOR/downloader.py +109 -101
- StreamingCommunity/Lib/FFmpeg/__init__.py +1 -1
- StreamingCommunity/Lib/FFmpeg/capture.py +10 -12
- StreamingCommunity/Lib/FFmpeg/command.py +15 -14
- StreamingCommunity/Lib/FFmpeg/util.py +9 -38
- StreamingCommunity/Lib/M3U8/decryptor.py +72 -146
- StreamingCommunity/Lib/M3U8/estimator.py +8 -16
- StreamingCommunity/Lib/M3U8/parser.py +25 -27
- StreamingCommunity/Lib/M3U8/url_fixer.py +1 -4
- StreamingCommunity/Lib/TMBD/__init__.py +2 -0
- StreamingCommunity/Lib/TMBD/obj_tmbd.py +3 -17
- StreamingCommunity/Lib/TMBD/tmdb.py +4 -9
- StreamingCommunity/TelegramHelp/telegram_bot.py +50 -50
- StreamingCommunity/Upload/update.py +3 -2
- StreamingCommunity/Upload/version.py +1 -1
- StreamingCommunity/Util/color.py +1 -1
- StreamingCommunity/Util/{_jsonConfig.py → config_json.py} +148 -54
- StreamingCommunity/Util/headers.py +2 -38
- StreamingCommunity/Util/logger.py +72 -42
- StreamingCommunity/Util/message.py +8 -3
- StreamingCommunity/Util/os.py +41 -93
- StreamingCommunity/Util/table.py +8 -17
- StreamingCommunity/run.py +26 -34
- {StreamingCommunity-2.7.0.dist-info → StreamingCommunity-2.9.0.dist-info}/METADATA +165 -92
- StreamingCommunity-2.9.0.dist-info/RECORD +75 -0
- StreamingCommunity/Api/Template/Util/recall_search.py +0 -37
- StreamingCommunity/Lib/Downloader/HLS/proxyes.py +0 -110
- StreamingCommunity/Util/call_stack.py +0 -42
- StreamingCommunity/Util/console.py +0 -12
- StreamingCommunity-2.7.0.dist-info/RECORD +0 -79
- {StreamingCommunity-2.7.0.dist-info → StreamingCommunity-2.9.0.dist-info}/LICENSE +0 -0
- {StreamingCommunity-2.7.0.dist-info → StreamingCommunity-2.9.0.dist-info}/WHEEL +0 -0
- {StreamingCommunity-2.7.0.dist-info → StreamingCommunity-2.9.0.dist-info}/entry_points.txt +0 -0
- {StreamingCommunity-2.7.0.dist-info → StreamingCommunity-2.9.0.dist-info}/top_level.txt +0 -0
|
@@ -10,47 +10,11 @@ import ua_generator
|
|
|
10
10
|
# Variable
|
|
11
11
|
ua = ua_generator.generate(device='desktop', browser=('chrome', 'edge'))
|
|
12
12
|
|
|
13
|
+
|
|
13
14
|
def get_userAgent() -> str:
|
|
14
|
-
"""
|
|
15
|
-
Generate a random user agent to use in HTTP requests.
|
|
16
|
-
|
|
17
|
-
Returns:
|
|
18
|
-
- str: A random user agent string.
|
|
19
|
-
"""
|
|
20
|
-
|
|
21
|
-
# Get a random user agent string from the user agent rotator
|
|
22
15
|
user_agent = ua_generator.generate().text
|
|
23
16
|
return user_agent
|
|
24
17
|
|
|
25
18
|
|
|
26
19
|
def get_headers() -> dict:
|
|
27
|
-
return ua.headers.get()
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
def random_headers(referer: str = None):
|
|
31
|
-
"""
|
|
32
|
-
Generate random HTTP headers to simulate human-like behavior.
|
|
33
|
-
|
|
34
|
-
Returns:
|
|
35
|
-
dict: Generated HTTP headers.
|
|
36
|
-
"""
|
|
37
|
-
ua = ua_generator.generate()
|
|
38
|
-
|
|
39
|
-
headers = {
|
|
40
|
-
'User-Agent': ua.text,
|
|
41
|
-
'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8',
|
|
42
|
-
'Accept-Language': random.choice(['en-US', 'en-GB', 'fr-FR', 'es-ES', 'de-DE']),
|
|
43
|
-
'Accept-Encoding': 'gzip, deflate, br',
|
|
44
|
-
'Connection': 'keep-alive',
|
|
45
|
-
'Upgrade-Insecure-Requests': '1',
|
|
46
|
-
'Sec-Fetch-Dest': 'document',
|
|
47
|
-
'Sec-Fetch-Mode': 'navigate',
|
|
48
|
-
'Sec-Fetch-Site': 'none',
|
|
49
|
-
'Sec-Fetch-User': '?1',
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
if referer:
|
|
53
|
-
headers['Origin'] = referer
|
|
54
|
-
headers['Referer'] = referer
|
|
55
|
-
|
|
56
|
-
return headers
|
|
20
|
+
return ua.headers.get()
|
|
@@ -6,57 +6,87 @@ from logging.handlers import RotatingFileHandler
|
|
|
6
6
|
|
|
7
7
|
|
|
8
8
|
# Internal utilities
|
|
9
|
-
from StreamingCommunity.Util.
|
|
9
|
+
from StreamingCommunity.Util.config_json import config_manager
|
|
10
10
|
|
|
11
11
|
|
|
12
12
|
class Logger:
|
|
13
|
+
_instance = None
|
|
14
|
+
|
|
15
|
+
def __new__(cls):
|
|
16
|
+
# Singleton pattern to avoid multiple logger instances
|
|
17
|
+
if cls._instance is None:
|
|
18
|
+
cls._instance = super(Logger, cls).__new__(cls)
|
|
19
|
+
cls._instance._initialized = False
|
|
20
|
+
return cls._instance
|
|
21
|
+
|
|
13
22
|
def __init__(self):
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
23
|
+
# Initialize only once
|
|
24
|
+
if getattr(self, '_initialized', False):
|
|
25
|
+
return
|
|
26
|
+
|
|
27
|
+
# Fetch only the debug setting from config
|
|
28
|
+
self.debug_mode = config_manager.get_bool("DEFAULT", "debug")
|
|
29
|
+
|
|
30
|
+
# Configure root logger
|
|
31
|
+
self.logger = logging.getLogger('')
|
|
32
|
+
|
|
33
|
+
# Remove any existing handlers to avoid duplication
|
|
34
|
+
for handler in self.logger.handlers[:]:
|
|
35
|
+
self.logger.removeHandler(handler)
|
|
36
|
+
|
|
37
|
+
# Reduce logging level for external libraries
|
|
20
38
|
logging.getLogger("httpx").setLevel(logging.WARNING)
|
|
21
39
|
logging.getLogger("httpcore").setLevel(logging.WARNING)
|
|
22
|
-
|
|
23
40
|
|
|
24
|
-
#
|
|
25
|
-
if self.
|
|
26
|
-
|
|
41
|
+
# Set logging level based on debug_mode
|
|
42
|
+
if self.debug_mode:
|
|
43
|
+
self.logger.setLevel(logging.DEBUG)
|
|
44
|
+
self._configure_console_log_file()
|
|
27
45
|
|
|
28
|
-
# Configure file logging if debug mode and logging to file are both enabled
|
|
29
|
-
if self.log_to_file:
|
|
30
|
-
self.remove_existing_log_file()
|
|
31
|
-
self.configure_file_logging()
|
|
32
46
|
else:
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
self.
|
|
39
|
-
|
|
40
|
-
def
|
|
41
|
-
"""
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
logging.basicConfig(level=logging.DEBUG, format='[%(filename)s:%(lineno)s - %(funcName)20s() ] %(asctime)s - %(levelname)s - %(message)s')
|
|
45
|
-
|
|
46
|
-
def configure_file_logging(self):
|
|
47
|
-
"""
|
|
48
|
-
Configure file logging if enabled.
|
|
49
|
-
"""
|
|
50
|
-
|
|
51
|
-
file_handler = RotatingFileHandler(self.log_file, maxBytes=10*1024*1024, backupCount=5)
|
|
52
|
-
file_handler.setLevel(logging.DEBUG)
|
|
47
|
+
self.logger.setLevel(logging.ERROR)
|
|
48
|
+
|
|
49
|
+
# Configure console logging (terminal output) regardless of debug mode
|
|
50
|
+
self._configure_console_logging()
|
|
51
|
+
|
|
52
|
+
self._initialized = True
|
|
53
|
+
|
|
54
|
+
def _configure_console_logging(self):
|
|
55
|
+
"""Configure console logging output to terminal."""
|
|
56
|
+
console_handler = logging.StreamHandler()
|
|
57
|
+
console_handler.setLevel(logging.DEBUG if self.debug_mode else logging.ERROR)
|
|
53
58
|
formatter = logging.Formatter('[%(filename)s:%(lineno)s - %(funcName)20s() ] %(asctime)s - %(levelname)s - %(message)s')
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
def
|
|
59
|
+
console_handler.setFormatter(formatter)
|
|
60
|
+
self.logger.addHandler(console_handler)
|
|
61
|
+
|
|
62
|
+
def _configure_console_log_file(self):
|
|
63
|
+
"""Create a console.log file only when debug mode is enabled."""
|
|
64
|
+
console_log_path = "console.log"
|
|
65
|
+
try:
|
|
66
|
+
# Remove existing file if present
|
|
67
|
+
if os.path.exists(console_log_path):
|
|
68
|
+
os.remove(console_log_path)
|
|
69
|
+
|
|
70
|
+
# Create handler for console.log
|
|
71
|
+
console_file_handler = RotatingFileHandler(
|
|
72
|
+
console_log_path,
|
|
73
|
+
maxBytes=5*1024*1024, # 5 MB
|
|
74
|
+
backupCount=3
|
|
75
|
+
)
|
|
76
|
+
console_file_handler.setLevel(logging.DEBUG)
|
|
77
|
+
formatter = logging.Formatter('[%(filename)s:%(lineno)s - %(funcName)20s() ] %(asctime)s - %(levelname)s - %(message)s')
|
|
78
|
+
console_file_handler.setFormatter(formatter)
|
|
79
|
+
self.logger.addHandler(console_file_handler)
|
|
80
|
+
|
|
81
|
+
except Exception as e:
|
|
82
|
+
print(f"Error creating console.log: {e}")
|
|
83
|
+
|
|
84
|
+
@staticmethod
|
|
85
|
+
def get_logger(name=None):
|
|
58
86
|
"""
|
|
59
|
-
|
|
87
|
+
Get a specific logger for a module/component.
|
|
88
|
+
If name is None, returns the root logger.
|
|
60
89
|
"""
|
|
61
|
-
|
|
62
|
-
|
|
90
|
+
# Ensure Logger instance is initialized
|
|
91
|
+
Logger()
|
|
92
|
+
return logging.getLogger(name)
|
|
@@ -3,12 +3,17 @@
|
|
|
3
3
|
import os
|
|
4
4
|
import platform
|
|
5
5
|
|
|
6
|
+
|
|
7
|
+
# External library
|
|
8
|
+
from rich.console import Console
|
|
9
|
+
|
|
10
|
+
|
|
6
11
|
# Internal utilities
|
|
7
|
-
from StreamingCommunity.Util.
|
|
8
|
-
from StreamingCommunity.Util._jsonConfig import config_manager
|
|
12
|
+
from StreamingCommunity.Util.config_json import config_manager
|
|
9
13
|
|
|
10
14
|
|
|
11
15
|
# Variable
|
|
16
|
+
console = Console()
|
|
12
17
|
CLEAN = config_manager.get_bool('DEFAULT', 'clean_console')
|
|
13
18
|
SHOW = config_manager.get_bool('DEFAULT', 'show_message')
|
|
14
19
|
|
|
@@ -33,4 +38,4 @@ def start_message():
|
|
|
33
38
|
|
|
34
39
|
# Print a decorative separator line using asterisks
|
|
35
40
|
separator = "_" * (console.width - 2) # Ridotto di 2 per il padding
|
|
36
|
-
console.print(f"[cyan]{separator}[/cyan]\n")
|
|
41
|
+
console.print(f"[cyan]{separator}[/cyan]\n")
|
StreamingCommunity/Util/os.py
CHANGED
|
@@ -9,9 +9,9 @@ import shutil
|
|
|
9
9
|
import hashlib
|
|
10
10
|
import logging
|
|
11
11
|
import platform
|
|
12
|
+
import inspect
|
|
12
13
|
import subprocess
|
|
13
14
|
import contextlib
|
|
14
|
-
import urllib.request
|
|
15
15
|
import importlib.metadata
|
|
16
16
|
from pathlib import Path
|
|
17
17
|
|
|
@@ -19,14 +19,19 @@ from pathlib import Path
|
|
|
19
19
|
# External library
|
|
20
20
|
import httpx
|
|
21
21
|
from unidecode import unidecode
|
|
22
|
+
from rich.console import Console
|
|
23
|
+
from rich.prompt import Prompt
|
|
22
24
|
from pathvalidate import sanitize_filename, sanitize_filepath
|
|
23
25
|
|
|
24
26
|
|
|
25
27
|
# Internal utilities
|
|
26
28
|
from .ffmpeg_installer import check_ffmpeg
|
|
27
|
-
from StreamingCommunity.Util.console import console, msg
|
|
28
29
|
|
|
29
30
|
|
|
31
|
+
# Variable
|
|
32
|
+
msg = Prompt()
|
|
33
|
+
console = Console()
|
|
34
|
+
|
|
30
35
|
|
|
31
36
|
class OsManager:
|
|
32
37
|
def __init__(self):
|
|
@@ -243,7 +248,6 @@ class OsManager:
|
|
|
243
248
|
|
|
244
249
|
|
|
245
250
|
class InternManager():
|
|
246
|
-
|
|
247
251
|
def format_file_size(self, size_bytes: float) -> str:
|
|
248
252
|
"""
|
|
249
253
|
Formats a file size from bytes into a human-readable string representation.
|
|
@@ -283,20 +287,8 @@ class InternManager():
|
|
|
283
287
|
else:
|
|
284
288
|
return f"{bytes / (1024 * 1024):.2f} MB/s"
|
|
285
289
|
|
|
286
|
-
@staticmethod
|
|
287
|
-
def check_internet():
|
|
288
|
-
while True:
|
|
289
|
-
try:
|
|
290
|
-
httpx.get("https://www.google.com", timeout=5)
|
|
291
|
-
break
|
|
292
|
-
|
|
293
|
-
except Exception as e:
|
|
294
|
-
console.log("[bold red]Internet is not available. Waiting...[/bold red]")
|
|
295
|
-
time.sleep(2)
|
|
296
|
-
|
|
297
290
|
|
|
298
291
|
class OsSummary:
|
|
299
|
-
|
|
300
292
|
def __init__(self):
|
|
301
293
|
self.ffmpeg_path = None
|
|
302
294
|
self.ffprobe_path = None
|
|
@@ -343,32 +335,6 @@ class OsSummary:
|
|
|
343
335
|
except importlib.metadata.PackageNotFoundError:
|
|
344
336
|
return f"{lib_name}-not installed"
|
|
345
337
|
|
|
346
|
-
def download_requirements(self, url: str, filename: str):
|
|
347
|
-
"""
|
|
348
|
-
Download the requirements.txt file from the specified URL if not found locally using requests.
|
|
349
|
-
|
|
350
|
-
Args:
|
|
351
|
-
url (str): The URL to download the requirements file from.
|
|
352
|
-
filename (str): The local filename to save the requirements file as.
|
|
353
|
-
"""
|
|
354
|
-
try:
|
|
355
|
-
import requests
|
|
356
|
-
|
|
357
|
-
logging.info(f"{filename} not found locally. Downloading from {url}...")
|
|
358
|
-
response = requests.get(url)
|
|
359
|
-
|
|
360
|
-
if response.status_code == 200:
|
|
361
|
-
with open(filename, 'wb') as f:
|
|
362
|
-
f.write(response.content)
|
|
363
|
-
|
|
364
|
-
else:
|
|
365
|
-
logging.error(f"Failed to download {filename}. HTTP Status code: {response.status_code}")
|
|
366
|
-
sys.exit(0)
|
|
367
|
-
|
|
368
|
-
except Exception as e:
|
|
369
|
-
logging.error(f"Failed to download {filename}: {e}")
|
|
370
|
-
sys.exit(0)
|
|
371
|
-
|
|
372
338
|
def install_library(self, lib_name: str):
|
|
373
339
|
"""
|
|
374
340
|
Install a Python library using pip.
|
|
@@ -399,17 +365,6 @@ class OsSummary:
|
|
|
399
365
|
|
|
400
366
|
def get_system_summary(self):
|
|
401
367
|
self.check_python_version()
|
|
402
|
-
InternManager().check_internet()
|
|
403
|
-
|
|
404
|
-
# Python info
|
|
405
|
-
python_version = sys.version.split()[0]
|
|
406
|
-
python_implementation = platform.python_implementation()
|
|
407
|
-
arch = platform.machine()
|
|
408
|
-
os_info = platform.platform()
|
|
409
|
-
glibc_version = 'glibc ' + '.'.join(map(str, platform.libc_ver()[1]))
|
|
410
|
-
|
|
411
|
-
console.print(f"[cyan]Python[white]: [bold red]{python_version} ({python_implementation} {arch}) - {os_info} ({glibc_version})[/bold red]")
|
|
412
|
-
logging.info(f"Python: {python_version} ({python_implementation} {arch}) - {os_info} ({glibc_version})")
|
|
413
368
|
|
|
414
369
|
# FFmpeg detection
|
|
415
370
|
binary_dir = self.get_binary_directory()
|
|
@@ -453,33 +408,7 @@ class OsSummary:
|
|
|
453
408
|
console.log("[red]Can't locate ffmpeg or ffprobe")
|
|
454
409
|
sys.exit(0)
|
|
455
410
|
|
|
456
|
-
console.print(f"[cyan]Path
|
|
457
|
-
|
|
458
|
-
# Handle requirements.txt
|
|
459
|
-
if not getattr(sys, 'frozen', False):
|
|
460
|
-
requirements_file = 'requirements.txt'
|
|
461
|
-
|
|
462
|
-
requirements_file = Path(__file__).parent.parent.parent / requirements_file
|
|
463
|
-
|
|
464
|
-
if not os.path.exists(requirements_file):
|
|
465
|
-
self.download_requirements(
|
|
466
|
-
'https://raw.githubusercontent.com/Arrowar/StreamingCommunity/refs/heads/main/requirements.txt',
|
|
467
|
-
requirements_file
|
|
468
|
-
)
|
|
469
|
-
|
|
470
|
-
optional_libraries = [line.strip().split("=")[0] for line in open(requirements_file, 'r', encoding='utf-8-sig')]
|
|
471
|
-
|
|
472
|
-
for lib in optional_libraries:
|
|
473
|
-
installed_version = self.get_library_version(lib.split("<")[0])
|
|
474
|
-
if 'not installed' in installed_version:
|
|
475
|
-
user_response = msg.ask(f"{lib} is not installed. Do you want to install it? (yes/no)", default="y")
|
|
476
|
-
if user_response.lower().strip() in ["yes", "y"]:
|
|
477
|
-
self.install_library(lib)
|
|
478
|
-
else:
|
|
479
|
-
logging.info(f"Library: {installed_version}")
|
|
480
|
-
|
|
481
|
-
#console.print(f"[cyan]Libraries[white]: [bold red]{', '.join([self.get_library_version(lib) for lib in optional_libraries])}[/bold red]\n")
|
|
482
|
-
logging.info(f"Libraries: {', '.join([self.get_library_version(lib) for lib in optional_libraries])}")
|
|
411
|
+
console.print(f"[cyan]Path: [red]ffmpeg [bold yellow]'{self.ffmpeg_path}'[/bold yellow][white], [red]ffprobe '[bold yellow]{self.ffprobe_path}'[/bold yellow]")
|
|
483
412
|
|
|
484
413
|
|
|
485
414
|
os_manager = OsManager()
|
|
@@ -493,17 +422,36 @@ def suppress_output():
|
|
|
493
422
|
yield
|
|
494
423
|
|
|
495
424
|
def compute_sha1_hash(input_string: str) -> str:
|
|
496
|
-
"""
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
425
|
+
"""Computes the SHA-1 hash of the input string."""
|
|
426
|
+
return hashlib.sha1(input_string.encode()).hexdigest()
|
|
427
|
+
|
|
428
|
+
def get_call_stack():
|
|
429
|
+
"""Retrieves the current call stack with details about each call."""
|
|
430
|
+
stack = inspect.stack()
|
|
431
|
+
call_stack = []
|
|
432
|
+
|
|
433
|
+
for frame_info in stack:
|
|
434
|
+
function_name = frame_info.function
|
|
435
|
+
filename = frame_info.filename
|
|
436
|
+
lineno = frame_info.lineno
|
|
437
|
+
folder_name = os.path.dirname(filename)
|
|
438
|
+
folder_base = os.path.basename(folder_name)
|
|
439
|
+
script_name = os.path.basename(filename)
|
|
440
|
+
|
|
441
|
+
call_stack.append({
|
|
442
|
+
"function": function_name,
|
|
443
|
+
"folder": folder_name,
|
|
444
|
+
"folder_base": folder_base,
|
|
445
|
+
"script": script_name,
|
|
446
|
+
"line": lineno
|
|
447
|
+
})
|
|
448
|
+
|
|
449
|
+
return call_stack
|
|
450
|
+
|
|
451
|
+
def get_ffmpeg_path():
|
|
452
|
+
"""Returns the path of FFmpeg."""
|
|
453
|
+
return os_summary.ffmpeg_path
|
|
454
|
+
|
|
455
|
+
def get_ffprobe_path():
|
|
456
|
+
"""Returns the path of FFprobe."""
|
|
457
|
+
return os_summary.ffprobe_path
|
StreamingCommunity/Util/table.py
CHANGED
|
@@ -16,12 +16,13 @@ from rich.style import Style
|
|
|
16
16
|
|
|
17
17
|
|
|
18
18
|
# Internal utilities
|
|
19
|
+
from .os import get_call_stack
|
|
19
20
|
from .message import start_message
|
|
20
|
-
|
|
21
|
+
|
|
21
22
|
|
|
22
23
|
# Telegram bot instance
|
|
23
24
|
from StreamingCommunity.TelegramHelp.telegram_bot import get_bot_instance
|
|
24
|
-
from StreamingCommunity.Util.
|
|
25
|
+
from StreamingCommunity.Util.config_json import config_manager
|
|
25
26
|
TELEGRAM_BOT = config_manager.get_bool('DEFAULT', 'telegram_bot')
|
|
26
27
|
|
|
27
28
|
|
|
@@ -31,21 +32,11 @@ class TVShowManager:
|
|
|
31
32
|
"""Initialize TVShowManager with default values."""
|
|
32
33
|
self.console = Console()
|
|
33
34
|
self.tv_shows: List[Dict[str, Any]] = []
|
|
34
|
-
self.slice_start
|
|
35
|
-
self.slice_end
|
|
36
|
-
self.step
|
|
35
|
+
self.slice_start = 0
|
|
36
|
+
self.slice_end = 10
|
|
37
|
+
self.step = self.slice_end
|
|
37
38
|
self.column_info = []
|
|
38
39
|
|
|
39
|
-
def set_slice_end(self, new_slice: int) -> None:
|
|
40
|
-
"""
|
|
41
|
-
Set the end of the slice for displaying TV shows.
|
|
42
|
-
|
|
43
|
-
Parameters:
|
|
44
|
-
- new_slice (int): The new value for the slice end.
|
|
45
|
-
"""
|
|
46
|
-
self.slice_end = new_slice
|
|
47
|
-
self.step = new_slice
|
|
48
|
-
|
|
49
40
|
def add_column(self, column_info: Dict[str, Dict[str, str]]) -> None:
|
|
50
41
|
"""
|
|
51
42
|
Add column information.
|
|
@@ -164,7 +155,7 @@ class TVShowManager:
|
|
|
164
155
|
else:
|
|
165
156
|
choices = [str(i) for i in range(max_int_input + 1)] + ["q", "quit", "b", "back"]
|
|
166
157
|
prompt_msg = "[cyan]Insert media [red]index"
|
|
167
|
-
telegram_msg = "Scegli il contenuto da scaricare:\n
|
|
158
|
+
telegram_msg = "Scegli il contenuto da scaricare:\n Serie TV - Film - Anime\noppure `back` per tornare indietro"
|
|
168
159
|
|
|
169
160
|
if is_telegram:
|
|
170
161
|
key = bot.ask("select_title", telegram_msg, None)
|
|
@@ -200,7 +191,7 @@ class TVShowManager:
|
|
|
200
191
|
else:
|
|
201
192
|
choices = [str(i) for i in range(max_int_input + 1)] + ["q", "quit", "b", "back"]
|
|
202
193
|
prompt_msg = "[cyan]Insert media [red]index"
|
|
203
|
-
telegram_msg = "Scegli il contenuto da scaricare:\n
|
|
194
|
+
telegram_msg = "Scegli il contenuto da scaricare:\n Serie TV - Film - Anime\noppure `back` per tornare indietro"
|
|
204
195
|
|
|
205
196
|
if is_telegram:
|
|
206
197
|
key = bot.ask("select_title", telegram_msg, None)
|
StreamingCommunity/run.py
CHANGED
|
@@ -12,17 +12,18 @@ import threading, asyncio
|
|
|
12
12
|
from typing import Callable
|
|
13
13
|
|
|
14
14
|
|
|
15
|
+
# External library
|
|
16
|
+
from rich.console import Console
|
|
17
|
+
from rich.prompt import Prompt
|
|
18
|
+
|
|
19
|
+
|
|
15
20
|
# Internal utilities
|
|
16
21
|
from StreamingCommunity.Util.message import start_message
|
|
17
|
-
from StreamingCommunity.Util.
|
|
18
|
-
from StreamingCommunity.Util._jsonConfig import config_manager
|
|
22
|
+
from StreamingCommunity.Util.config_json import config_manager
|
|
19
23
|
from StreamingCommunity.Util.os import os_summary
|
|
20
24
|
from StreamingCommunity.Util.logger import Logger
|
|
21
25
|
from StreamingCommunity.Upload.update import update as git_update
|
|
22
26
|
from StreamingCommunity.Lib.TMBD import tmdb
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
# Telegram util
|
|
26
27
|
from StreamingCommunity.TelegramHelp.telegram_bot import get_bot_instance, TelegramSession
|
|
27
28
|
|
|
28
29
|
|
|
@@ -32,6 +33,10 @@ CLOSE_CONSOLE = config_manager.get_bool('DEFAULT', 'not_close')
|
|
|
32
33
|
TELEGRAM_BOT = config_manager.get_bool('DEFAULT', 'telegram_bot')
|
|
33
34
|
|
|
34
35
|
|
|
36
|
+
# Variable
|
|
37
|
+
console = Console()
|
|
38
|
+
msg = Prompt()
|
|
39
|
+
|
|
35
40
|
|
|
36
41
|
def run_function(func: Callable[..., None], close_console: bool = False, search_terms: str = None) -> None:
|
|
37
42
|
"""
|
|
@@ -149,7 +154,7 @@ def initialize():
|
|
|
149
154
|
|
|
150
155
|
def restart_script():
|
|
151
156
|
"""Riavvia lo script con gli stessi argomenti della riga di comando."""
|
|
152
|
-
print("\
|
|
157
|
+
print("\nRiavvio dello script...\n")
|
|
153
158
|
python = sys.executable
|
|
154
159
|
os.execv(python, [python] + sys.argv)
|
|
155
160
|
|
|
@@ -157,31 +162,31 @@ def restart_script():
|
|
|
157
162
|
def force_exit():
|
|
158
163
|
"""Forza la chiusura dello script in qualsiasi contesto."""
|
|
159
164
|
|
|
160
|
-
print("\
|
|
165
|
+
print("\nChiusura dello script in corso...")
|
|
161
166
|
|
|
162
|
-
# 1
|
|
167
|
+
# 1 Chiudi tutti i thread tranne il principale
|
|
163
168
|
for t in threading.enumerate():
|
|
164
169
|
if t is not threading.main_thread():
|
|
165
|
-
print(f"
|
|
170
|
+
print(f"Chiusura thread: {t.name}")
|
|
166
171
|
t.join(timeout=1)
|
|
167
172
|
|
|
168
|
-
# 2
|
|
173
|
+
# 2 Ferma asyncio, se attivo
|
|
169
174
|
try:
|
|
170
175
|
loop = asyncio.get_event_loop()
|
|
171
176
|
if loop.is_running():
|
|
172
|
-
print("
|
|
177
|
+
print("Arresto del loop asyncio...")
|
|
173
178
|
loop.stop()
|
|
174
179
|
except RuntimeError:
|
|
175
180
|
pass
|
|
176
181
|
|
|
177
|
-
# 3
|
|
182
|
+
# 3 Esce con sys.exit(), se fallisce usa os._exit()
|
|
178
183
|
try:
|
|
179
|
-
print("
|
|
184
|
+
print("Uscita con sys.exit(0)")
|
|
180
185
|
sys.exit(0)
|
|
181
186
|
except SystemExit:
|
|
182
187
|
pass
|
|
183
188
|
|
|
184
|
-
print("
|
|
189
|
+
print("Uscita forzata con os._exit(0)")
|
|
185
190
|
os._exit(0)
|
|
186
191
|
|
|
187
192
|
|
|
@@ -189,7 +194,7 @@ def main(script_id = 0):
|
|
|
189
194
|
|
|
190
195
|
if TELEGRAM_BOT:
|
|
191
196
|
bot = get_bot_instance()
|
|
192
|
-
bot.send_message(f"
|
|
197
|
+
bot.send_message(f"Avviato script {script_id}", None)
|
|
193
198
|
|
|
194
199
|
start = time.time()
|
|
195
200
|
|
|
@@ -212,9 +217,6 @@ def main(script_id = 0):
|
|
|
212
217
|
parser.add_argument(
|
|
213
218
|
'--add_siteName', type=bool, help='Enable or disable adding the site name to the file name (e.g., true/false).'
|
|
214
219
|
)
|
|
215
|
-
parser.add_argument(
|
|
216
|
-
'--disable_searchDomain', type=bool, help='Enable or disable searching in configured domains (e.g., true/false).'
|
|
217
|
-
)
|
|
218
220
|
parser.add_argument(
|
|
219
221
|
'--not_close', type=bool, help='If set to true, the script will not close the console after execution (e.g., true/false).'
|
|
220
222
|
)
|
|
@@ -260,8 +262,6 @@ def main(script_id = 0):
|
|
|
260
262
|
|
|
261
263
|
if args.add_siteName is not None:
|
|
262
264
|
config_updates['DEFAULT.add_siteName'] = args.add_siteName
|
|
263
|
-
if args.disable_searchDomain is not None:
|
|
264
|
-
config_updates['DEFAULT.disable_searchDomain'] = args.disable_searchDomain
|
|
265
265
|
if args.not_close is not None:
|
|
266
266
|
config_updates['DEFAULT.not_close'] = args.not_close
|
|
267
267
|
if args.default_video_worker is not None:
|
|
@@ -305,24 +305,15 @@ def main(script_id = 0):
|
|
|
305
305
|
) + "[white])"
|
|
306
306
|
|
|
307
307
|
if TELEGRAM_BOT:
|
|
308
|
-
|
|
309
|
-
# Mappa delle emoji per i colori
|
|
310
|
-
emoji_map = {
|
|
311
|
-
"yellow": "🟡", # Giallo
|
|
312
|
-
"red": "🔴", # Rosso
|
|
313
|
-
"blue": "🔵", # Blu
|
|
314
|
-
"green": "🟢" # Verde
|
|
315
|
-
}
|
|
316
|
-
|
|
308
|
+
|
|
317
309
|
# Display the category legend in a single line
|
|
318
310
|
category_legend_str = "Categorie: \n" + " | ".join([
|
|
319
|
-
f"{
|
|
320
|
-
for category, color in color_map.items()
|
|
311
|
+
f"{category.capitalize()}" for category in color_map.keys()
|
|
321
312
|
])
|
|
322
313
|
|
|
323
|
-
# Costruisci il messaggio
|
|
314
|
+
# Costruisci il messaggio senza emoji
|
|
324
315
|
prompt_message = "Inserisci il sito:\n" + "\n".join(
|
|
325
|
-
[f"{key}: {
|
|
316
|
+
[f"{key}: {label[0]}" for key, label in choice_labels.items()]
|
|
326
317
|
)
|
|
327
318
|
|
|
328
319
|
console.print(f"\n{prompt_message}")
|
|
@@ -340,6 +331,7 @@ def main(script_id = 0):
|
|
|
340
331
|
# Run the corresponding function based on user input
|
|
341
332
|
if category in input_to_function:
|
|
342
333
|
run_function(input_to_function[category], search_terms = args.search)
|
|
334
|
+
|
|
343
335
|
else:
|
|
344
336
|
|
|
345
337
|
if TELEGRAM_BOT:
|
|
@@ -358,4 +350,4 @@ def main(script_id = 0):
|
|
|
358
350
|
# Delete script_id
|
|
359
351
|
script_id = TelegramSession.get_session()
|
|
360
352
|
if script_id != "unknown":
|
|
361
|
-
TelegramSession.deleteScriptId(script_id)
|
|
353
|
+
TelegramSession.deleteScriptId(script_id)
|