StreamingCommunity 2.5.7__py3-none-any.whl → 2.5.8__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 -3
- StreamingCommunity/Api/Site/1337xx/__init__.py +5 -6
- StreamingCommunity/Api/Site/1337xx/site.py +7 -14
- StreamingCommunity/Api/Site/1337xx/title.py +3 -5
- StreamingCommunity/Api/Site/altadefinizionegratis/__init__.py +7 -6
- StreamingCommunity/Api/Site/altadefinizionegratis/film.py +14 -19
- StreamingCommunity/Api/Site/altadefinizionegratis/site.py +6 -14
- StreamingCommunity/Api/Site/animeunity/__init__.py +7 -7
- StreamingCommunity/Api/Site/animeunity/film_serie.py +29 -31
- StreamingCommunity/Api/Site/animeunity/site.py +14 -22
- StreamingCommunity/Api/Site/cb01new/__init__.py +5 -4
- StreamingCommunity/Api/Site/cb01new/film.py +2 -5
- StreamingCommunity/Api/Site/cb01new/site.py +5 -13
- StreamingCommunity/Api/Site/ddlstreamitaly/__init__.py +5 -4
- StreamingCommunity/Api/Site/ddlstreamitaly/series.py +12 -49
- StreamingCommunity/Api/Site/ddlstreamitaly/site.py +6 -16
- StreamingCommunity/Api/Site/ddlstreamitaly/util/ScrapeSerie.py +2 -3
- StreamingCommunity/Api/Site/guardaserie/__init__.py +5 -4
- StreamingCommunity/Api/Site/guardaserie/series.py +11 -46
- StreamingCommunity/Api/Site/guardaserie/site.py +5 -13
- StreamingCommunity/Api/Site/guardaserie/util/ScrapeSerie.py +10 -14
- StreamingCommunity/Api/Site/ilcorsaronero/__init__.py +5 -4
- StreamingCommunity/Api/Site/ilcorsaronero/site.py +5 -13
- StreamingCommunity/Api/Site/ilcorsaronero/title.py +3 -5
- StreamingCommunity/Api/Site/mostraguarda/__init__.py +2 -2
- StreamingCommunity/Api/Site/mostraguarda/film.py +4 -8
- StreamingCommunity/Api/Site/streamingcommunity/__init__.py +8 -7
- StreamingCommunity/Api/Site/streamingcommunity/film.py +14 -18
- StreamingCommunity/Api/Site/streamingcommunity/series.py +25 -76
- StreamingCommunity/Api/Site/streamingcommunity/site.py +11 -23
- StreamingCommunity/Api/Template/Util/__init__.py +8 -1
- StreamingCommunity/Api/Template/Util/manage_ep.py +46 -2
- StreamingCommunity/Api/Template/config_loader.py +71 -0
- StreamingCommunity/Lib/Downloader/HLS/downloader.py +60 -59
- StreamingCommunity/Lib/Downloader/HLS/segments.py +40 -14
- StreamingCommunity/Lib/Downloader/MP4/downloader.py +47 -40
- StreamingCommunity/Lib/FFmpeg/command.py +59 -3
- StreamingCommunity/Lib/M3U8/estimator.py +5 -5
- StreamingCommunity/Lib/M3U8/parser.py +12 -51
- StreamingCommunity/Lib/TMBD/tmdb.py +66 -99
- StreamingCommunity/TelegramHelp/telegram_bot.py +222 -68
- StreamingCommunity/Util/_jsonConfig.py +14 -13
- StreamingCommunity/Util/ffmpeg_installer.py +70 -64
- StreamingCommunity/Util/headers.py +11 -122
- StreamingCommunity/Util/os.py +64 -55
- StreamingCommunity/Util/table.py +62 -108
- StreamingCommunity/run.py +15 -10
- {StreamingCommunity-2.5.7.dist-info → StreamingCommunity-2.5.8.dist-info}/METADATA +56 -22
- StreamingCommunity-2.5.8.dist-info/RECORD +86 -0
- StreamingCommunity/Api/Site/1337xx/costant.py +0 -15
- StreamingCommunity/Api/Site/altadefinizionegratis/costant.py +0 -21
- StreamingCommunity/Api/Site/animeunity/costant.py +0 -21
- StreamingCommunity/Api/Site/cb01new/costant.py +0 -19
- StreamingCommunity/Api/Site/ddlstreamitaly/costant.py +0 -20
- StreamingCommunity/Api/Site/guardaserie/costant.py +0 -19
- StreamingCommunity/Api/Site/ilcorsaronero/costant.py +0 -19
- StreamingCommunity/Api/Site/mostraguarda/costant.py +0 -19
- StreamingCommunity/Api/Site/streamingcommunity/costant.py +0 -21
- StreamingCommunity/TelegramHelp/request_manager.py +0 -82
- StreamingCommunity/TelegramHelp/session.py +0 -56
- StreamingCommunity-2.5.7.dist-info/RECORD +0 -96
- {StreamingCommunity-2.5.7.dist-info → StreamingCommunity-2.5.8.dist-info}/LICENSE +0 -0
- {StreamingCommunity-2.5.7.dist-info → StreamingCommunity-2.5.8.dist-info}/WHEEL +0 -0
- {StreamingCommunity-2.5.7.dist-info → StreamingCommunity-2.5.8.dist-info}/entry_points.txt +0 -0
- {StreamingCommunity-2.5.7.dist-info → StreamingCommunity-2.5.8.dist-info}/top_level.txt +0 -0
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# 04.02.
|
|
1
|
+
# 04.02.26
|
|
2
2
|
# Made by: @GiuPic
|
|
3
3
|
|
|
4
4
|
import os
|
|
@@ -9,16 +9,141 @@ import uuid
|
|
|
9
9
|
import json
|
|
10
10
|
import threading
|
|
11
11
|
import subprocess
|
|
12
|
-
|
|
12
|
+
import threading
|
|
13
|
+
from typing import Optional
|
|
13
14
|
|
|
14
15
|
# External libraries
|
|
15
16
|
import telebot
|
|
16
17
|
|
|
18
|
+
session_data = {}
|
|
19
|
+
|
|
20
|
+
class TelegramSession:
|
|
21
|
+
|
|
22
|
+
def set_session(value):
|
|
23
|
+
session_data['script_id'] = value
|
|
24
|
+
|
|
25
|
+
def get_session():
|
|
26
|
+
return session_data.get('script_id', 'unknown')
|
|
27
|
+
|
|
28
|
+
def updateScriptId(screen_id, titolo):
|
|
29
|
+
json_file = "../../scripts.json"
|
|
30
|
+
try:
|
|
31
|
+
with open(json_file, 'r') as f:
|
|
32
|
+
scripts_data = json.load(f)
|
|
33
|
+
except FileNotFoundError:
|
|
34
|
+
scripts_data = []
|
|
35
|
+
|
|
36
|
+
# cerco lo script con lo screen_id
|
|
37
|
+
for script in scripts_data:
|
|
38
|
+
if script["screen_id"] == screen_id:
|
|
39
|
+
# se trovo il match, aggiorno il titolo
|
|
40
|
+
script["titolo"] = titolo
|
|
41
|
+
|
|
42
|
+
# aggiorno il file json
|
|
43
|
+
with open(json_file, 'w') as f:
|
|
44
|
+
json.dump(scripts_data, f, indent=4)
|
|
45
|
+
|
|
46
|
+
return
|
|
47
|
+
|
|
48
|
+
print(f"Screen_id {screen_id} non trovato.")
|
|
49
|
+
|
|
50
|
+
def deleteScriptId(screen_id):
|
|
51
|
+
json_file = "../../scripts.json"
|
|
52
|
+
try:
|
|
53
|
+
with open(json_file, 'r') as f:
|
|
54
|
+
scripts_data = json.load(f)
|
|
55
|
+
except FileNotFoundError:
|
|
56
|
+
scripts_data = []
|
|
57
|
+
|
|
58
|
+
for script in scripts_data:
|
|
59
|
+
if script["screen_id"] == screen_id:
|
|
60
|
+
# se trovo il match, elimino lo script
|
|
61
|
+
scripts_data.remove(script)
|
|
62
|
+
|
|
63
|
+
# aggiorno il file json
|
|
64
|
+
with open(json_file, 'w') as f:
|
|
65
|
+
json.dump(scripts_data, f, indent=4)
|
|
66
|
+
|
|
67
|
+
print(f"Script eliminato per screen_id {screen_id}")
|
|
68
|
+
return
|
|
69
|
+
|
|
70
|
+
print(f"Screen_id {screen_id} non trovato.")
|
|
71
|
+
|
|
72
|
+
class TelegramRequestManager:
|
|
73
|
+
_instance = None
|
|
74
|
+
|
|
75
|
+
def __new__(cls, *args, **kwargs):
|
|
76
|
+
if not cls._instance:
|
|
77
|
+
cls._instance = super().__new__(cls)
|
|
78
|
+
return cls._instance
|
|
79
|
+
|
|
80
|
+
def __init__(self, json_file: str = "active_requests.json"):
|
|
81
|
+
if not hasattr(self, 'initialized'):
|
|
82
|
+
self.json_file = json_file
|
|
83
|
+
self.initialized = True
|
|
84
|
+
self.on_response_callback = None
|
|
85
|
+
|
|
86
|
+
def create_request(self, type: str) -> str:
|
|
87
|
+
request_data = {
|
|
88
|
+
"type": type,
|
|
89
|
+
"response": None,
|
|
90
|
+
"timestamp": time.time()
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
with open(self.json_file, "w") as f:
|
|
94
|
+
json.dump(request_data, f)
|
|
95
|
+
|
|
96
|
+
return "Ok"
|
|
97
|
+
|
|
98
|
+
def save_response(self, message_text: str) -> bool:
|
|
99
|
+
try:
|
|
100
|
+
# Carica il file JSON
|
|
101
|
+
with open(self.json_file, "r") as f:
|
|
102
|
+
data = json.load(f)
|
|
103
|
+
|
|
104
|
+
# Controlla se esiste la chiave 'type' e se la risposta è presente
|
|
105
|
+
if "type" in data and "response" in data:
|
|
106
|
+
data["response"] = message_text # Aggiorna la risposta
|
|
17
107
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
from StreamingCommunity.TelegramHelp.request_manager import RequestManager
|
|
108
|
+
with open(self.json_file, "w") as f:
|
|
109
|
+
json.dump(data, f, indent=4)
|
|
21
110
|
|
|
111
|
+
return True
|
|
112
|
+
else:
|
|
113
|
+
return False
|
|
114
|
+
|
|
115
|
+
except (FileNotFoundError, json.JSONDecodeError) as e:
|
|
116
|
+
print(f"⚠️ save_response - errore: {e}")
|
|
117
|
+
return False
|
|
118
|
+
|
|
119
|
+
def get_response(self) -> Optional[str]:
|
|
120
|
+
try:
|
|
121
|
+
with open(self.json_file, "r") as f:
|
|
122
|
+
data = json.load(f)
|
|
123
|
+
|
|
124
|
+
# Verifica se esiste la chiave "response"
|
|
125
|
+
if "response" in data:
|
|
126
|
+
response = data["response"] # Ottieni la risposta direttamente
|
|
127
|
+
|
|
128
|
+
if response is not None and self.on_response_callback:
|
|
129
|
+
self.on_response_callback(response)
|
|
130
|
+
|
|
131
|
+
return response
|
|
132
|
+
|
|
133
|
+
except (FileNotFoundError, json.JSONDecodeError) as e:
|
|
134
|
+
print(f"get_response - errore: {e}")
|
|
135
|
+
return None
|
|
136
|
+
|
|
137
|
+
def clear_file(self) -> bool:
|
|
138
|
+
try:
|
|
139
|
+
with open(self.json_file, "w") as f:
|
|
140
|
+
json.dump({}, f)
|
|
141
|
+
print(f"File {self.json_file} è stato svuotato con successo.")
|
|
142
|
+
return True
|
|
143
|
+
|
|
144
|
+
except Exception as e:
|
|
145
|
+
print(f"⚠️ clear_file - errore: {e}")
|
|
146
|
+
return False
|
|
22
147
|
|
|
23
148
|
# Funzione per caricare variabili da un file .env
|
|
24
149
|
def load_env(file_path="../../.env"):
|
|
@@ -44,13 +169,17 @@ class TelegramBot:
|
|
|
44
169
|
if os.path.exists(cls._config_file):
|
|
45
170
|
with open(cls._config_file, "r") as f:
|
|
46
171
|
config = json.load(f)
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
)
|
|
172
|
+
|
|
173
|
+
# Assicura che authorized_user_id venga trattato come una lista
|
|
174
|
+
authorized_users = config.get('authorized_user_id', [])
|
|
175
|
+
if isinstance(authorized_users, str):
|
|
176
|
+
authorized_users = [int(uid) for uid in authorized_users.split(",") if uid.strip().isdigit()]
|
|
177
|
+
|
|
178
|
+
cls._instance = cls.init_bot(config['token'], authorized_users)
|
|
179
|
+
#cls._instance = cls.init_bot(config['token'], config['authorized_user_id'])
|
|
180
|
+
|
|
50
181
|
else:
|
|
51
|
-
raise Exception(
|
|
52
|
-
"Bot non ancora inizializzato. Chiamare prima init_bot() con token e authorized_user_id"
|
|
53
|
-
)
|
|
182
|
+
raise Exception("Bot non ancora inizializzato. Chiamare prima init_bot() con token e authorized_user_id")
|
|
54
183
|
return cls._instance
|
|
55
184
|
|
|
56
185
|
@classmethod
|
|
@@ -63,7 +192,8 @@ class TelegramBot:
|
|
|
63
192
|
json.dump(config, f)
|
|
64
193
|
return cls._instance
|
|
65
194
|
|
|
66
|
-
def __init__(self, token,
|
|
195
|
+
def __init__(self, token, authorized_users):
|
|
196
|
+
|
|
67
197
|
def monitor_scripts():
|
|
68
198
|
while True:
|
|
69
199
|
try:
|
|
@@ -132,10 +262,10 @@ class TelegramBot:
|
|
|
132
262
|
)
|
|
133
263
|
|
|
134
264
|
self.token = token
|
|
135
|
-
self.
|
|
136
|
-
self.chat_id =
|
|
265
|
+
self.authorized_users = authorized_users
|
|
266
|
+
self.chat_id = authorized_users
|
|
137
267
|
self.bot = telebot.TeleBot(token)
|
|
138
|
-
self.request_manager =
|
|
268
|
+
self.request_manager = TelegramRequestManager()
|
|
139
269
|
|
|
140
270
|
# Registra gli handler
|
|
141
271
|
self.register_handlers()
|
|
@@ -171,7 +301,7 @@ class TelegramBot:
|
|
|
171
301
|
self.handle_response(message)
|
|
172
302
|
|
|
173
303
|
def is_authorized(self, user_id):
|
|
174
|
-
return user_id
|
|
304
|
+
return user_id in self.authorized_users
|
|
175
305
|
|
|
176
306
|
def handle_get_id(self, message):
|
|
177
307
|
if not self.is_authorized(message.from_user.id):
|
|
@@ -194,7 +324,6 @@ class TelegramBot:
|
|
|
194
324
|
|
|
195
325
|
screen_id = str(uuid.uuid4())[:8]
|
|
196
326
|
debug_mode = os.getenv("DEBUG")
|
|
197
|
-
verbose = debug_mode
|
|
198
327
|
|
|
199
328
|
if debug_mode == "True":
|
|
200
329
|
subprocess.Popen(["python3", "../../test_run.py", screen_id])
|
|
@@ -407,6 +536,13 @@ class TelegramBot:
|
|
|
407
536
|
temp_file = f"/tmp/screen_output_{screen_id}.txt"
|
|
408
537
|
|
|
409
538
|
try:
|
|
539
|
+
# Verifica se lo screen con l'ID specificato esiste
|
|
540
|
+
existing_screens = subprocess.check_output(["screen", "-list"]).decode('utf-8')
|
|
541
|
+
if screen_id not in existing_screens:
|
|
542
|
+
print(f"⚠️ La sessione screen con ID {screen_id} non esiste.")
|
|
543
|
+
self.bot.send_message(message.chat.id, f"⚠️ La sessione screen con ID {screen_id} non esiste.")
|
|
544
|
+
return
|
|
545
|
+
|
|
410
546
|
# Cattura l'output della screen
|
|
411
547
|
subprocess.run(
|
|
412
548
|
["screen", "-X", "-S", screen_id, "hardcopy", "-h", temp_file],
|
|
@@ -440,51 +576,22 @@ class TelegramBot:
|
|
|
440
576
|
"\n\n", "\n"
|
|
441
577
|
) # Rimuovi newline multipli
|
|
442
578
|
|
|
443
|
-
#
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
if download_matches:
|
|
448
|
-
# Serie TV e Film StreamingCommunity
|
|
449
|
-
|
|
450
|
-
proc_matches = re.findall(r"Proc: ([\d\.]+%)", cleaned_output)
|
|
451
|
-
|
|
452
|
-
# Creare una stringa unica con tutti i risultati
|
|
453
|
-
result_string = "\n".join(
|
|
454
|
-
[
|
|
455
|
-
f"Download: {download_matches[i].strip()}\nDownload al {proc_matches[i]}"
|
|
456
|
-
for i in range(len(download_matches))
|
|
457
|
-
if i < len(proc_matches)
|
|
458
|
-
]
|
|
459
|
-
)
|
|
460
|
-
|
|
461
|
-
if result_string != "":
|
|
462
|
-
cleaned_output = result_string
|
|
463
|
-
else:
|
|
464
|
-
print(f"❌ La parola 'Download:' non è stata trovata nella stringa.")
|
|
465
|
-
else:
|
|
466
|
-
|
|
467
|
-
download_list = []
|
|
468
|
-
|
|
469
|
-
# Estrai tutte le righe che iniziano con "Download:" fino al prossimo "Download" o alla fine della riga
|
|
470
|
-
matches = re.findall(r"Download:\s*(.*?)(?=Download|$)", cleaned_output)
|
|
579
|
+
# Dentro cleaned_output c'è una stringa recupero quello che si trova tra ## ##
|
|
580
|
+
download_section = re.search(r"##(.*?)##", cleaned_output, re.DOTALL)
|
|
581
|
+
if download_section:
|
|
582
|
+
cleaned_output_0 = "Download: " + download_section.group(1).strip()
|
|
471
583
|
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
match = re.sub(r"downloader.py:\d+Result:400", "", match)
|
|
477
|
-
match = match.strip() # Rimuovo gli spazi bianchi in eccesso
|
|
478
|
-
if match: # Assicurati che la stringa non sia vuota
|
|
479
|
-
print(f"Download {i}: {match}")
|
|
584
|
+
# Recupero tutto quello che viene dopo con ####
|
|
585
|
+
download_section_bottom = re.search(r"####(.*)", cleaned_output, re.DOTALL)
|
|
586
|
+
if download_section_bottom:
|
|
587
|
+
cleaned_output_1 = download_section_bottom.group(1).strip()
|
|
480
588
|
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
print("❌ Nessun download trovato")
|
|
589
|
+
# Unico i due risultati se esistono
|
|
590
|
+
if cleaned_output_0 and cleaned_output_1:
|
|
591
|
+
cleaned_output = f"{cleaned_output_0}\n{cleaned_output_1}"
|
|
592
|
+
# Rimuovo 'segments.py:302' e 'downloader.py:385' se presente
|
|
593
|
+
cleaned_output = re.sub(r'downloader\.py:\d+', '', cleaned_output)
|
|
594
|
+
cleaned_output = re.sub(r'segments\.py:\d+', '', cleaned_output)
|
|
488
595
|
|
|
489
596
|
# Invia l'output pulito
|
|
490
597
|
print(f"📄 Output della screen {screen_id}:\n{cleaned_output}")
|
|
@@ -505,7 +612,16 @@ class TelegramBot:
|
|
|
505
612
|
os.remove(temp_file)
|
|
506
613
|
|
|
507
614
|
def send_message(self, message, choices):
|
|
508
|
-
|
|
615
|
+
|
|
616
|
+
formatted_message = message
|
|
617
|
+
if choices:
|
|
618
|
+
formatted_choices = "\n".join(choices)
|
|
619
|
+
formatted_message = f"{message}\n\n{formatted_choices}"
|
|
620
|
+
|
|
621
|
+
for chat_id in self.authorized_users:
|
|
622
|
+
self.bot.send_message(chat_id, formatted_message)
|
|
623
|
+
|
|
624
|
+
""" if choices is None:
|
|
509
625
|
if self.chat_id:
|
|
510
626
|
print(f"{message}")
|
|
511
627
|
self.bot.send_message(self.chat_id, message)
|
|
@@ -514,7 +630,7 @@ class TelegramBot:
|
|
|
514
630
|
message = f"{message}\n\n{formatted_choices}"
|
|
515
631
|
if self.chat_id:
|
|
516
632
|
print(f"{message}")
|
|
517
|
-
self.bot.send_message(self.chat_id, message)
|
|
633
|
+
self.bot.send_message(self.chat_id, message) """
|
|
518
634
|
|
|
519
635
|
def _send_long_message(self, chat_id, text, chunk_size=4096):
|
|
520
636
|
"""Suddivide e invia un messaggio troppo lungo in più parti."""
|
|
@@ -527,16 +643,20 @@ class TelegramBot:
|
|
|
527
643
|
|
|
528
644
|
if choices is None:
|
|
529
645
|
print(f"{prompt_message}")
|
|
530
|
-
self.bot.send_message(
|
|
646
|
+
""" self.bot.send_message(
|
|
531
647
|
self.chat_id,
|
|
532
648
|
f"{prompt_message}",
|
|
533
|
-
)
|
|
649
|
+
) """
|
|
650
|
+
for chat_id in self.authorized_users: # Manda a tutti gli ID autorizzati
|
|
651
|
+
self.bot.send_message(chat_id, f"{prompt_message}")
|
|
534
652
|
else:
|
|
535
653
|
print(f"{prompt_message}\n\nOpzioni: {', '.join(choices)}")
|
|
536
|
-
self.bot.send_message(
|
|
654
|
+
""" self.bot.send_message(
|
|
537
655
|
self.chat_id,
|
|
538
656
|
f"{prompt_message}\n\nOpzioni: {', '.join(choices)}",
|
|
539
|
-
)
|
|
657
|
+
) """
|
|
658
|
+
for chat_id in self.authorized_users: # Manda a tutti gli ID autorizzati
|
|
659
|
+
self.bot.send_message(chat_id, f"{prompt_message}\n\nOpzioni: {', '.join(choices)}")
|
|
540
660
|
|
|
541
661
|
start_time = time.time()
|
|
542
662
|
while time.time() - start_time < timeout:
|
|
@@ -546,7 +666,8 @@ class TelegramBot:
|
|
|
546
666
|
time.sleep(1)
|
|
547
667
|
|
|
548
668
|
print(f"⚠️ Timeout: nessuna risposta ricevuta.")
|
|
549
|
-
|
|
669
|
+
for chat_id in self.authorized_users: # Manda a tutti gli ID autorizzati
|
|
670
|
+
self.bot.send_message(chat_id, "⚠️ Timeout: nessuna risposta ricevuta.")
|
|
550
671
|
self.request_manager.clear_file()
|
|
551
672
|
return None
|
|
552
673
|
|
|
@@ -558,4 +679,37 @@ class TelegramBot:
|
|
|
558
679
|
|
|
559
680
|
|
|
560
681
|
def get_bot_instance():
|
|
561
|
-
return TelegramBot.get_instance()
|
|
682
|
+
return TelegramBot.get_instance()
|
|
683
|
+
|
|
684
|
+
# Esempio di utilizzo
|
|
685
|
+
if __name__ == "__main__":
|
|
686
|
+
|
|
687
|
+
# Usa le variabili
|
|
688
|
+
token = os.getenv("TOKEN_TELEGRAM")
|
|
689
|
+
authorized_users = os.getenv("AUTHORIZED_USER_ID")
|
|
690
|
+
|
|
691
|
+
# Controlla se le variabili sono presenti
|
|
692
|
+
if not token:
|
|
693
|
+
print("Errore: TOKEN_TELEGRAM non è definito nel file .env.")
|
|
694
|
+
sys.exit(1)
|
|
695
|
+
|
|
696
|
+
if not authorized_users:
|
|
697
|
+
print("Errore: AUTHORIZED_USER_ID non è definito nel file .env.")
|
|
698
|
+
sys.exit(1)
|
|
699
|
+
|
|
700
|
+
try:
|
|
701
|
+
TOKEN = token # Inserisci il token del tuo bot Telegram sul file .env
|
|
702
|
+
AUTHORIZED_USER_ID = list(map(int, authorized_users.split(","))) # Inserisci il tuo ID utente Telegram sul file .env
|
|
703
|
+
except ValueError as e:
|
|
704
|
+
print(f"Errore nella conversione degli ID autorizzati: {e}. Controlla il file .env e assicurati che gli ID siano numeri interi separati da virgole.")
|
|
705
|
+
sys.exit(1)
|
|
706
|
+
|
|
707
|
+
# Inizializza il bot
|
|
708
|
+
bot = TelegramBot.init_bot(TOKEN, AUTHORIZED_USER_ID)
|
|
709
|
+
bot.run()
|
|
710
|
+
|
|
711
|
+
"""
|
|
712
|
+
start - Avvia lo script
|
|
713
|
+
list - Lista script attivi
|
|
714
|
+
get - Mostra ID utente Telegram
|
|
715
|
+
"""
|
|
@@ -4,17 +4,18 @@ import os
|
|
|
4
4
|
import sys
|
|
5
5
|
import json
|
|
6
6
|
import logging
|
|
7
|
+
from pathlib import Path
|
|
7
8
|
from typing import Any, List
|
|
8
9
|
|
|
9
10
|
|
|
10
11
|
class ConfigManager:
|
|
11
|
-
def __init__(self,
|
|
12
|
+
def __init__(self, file_name: str = 'config.json') -> None:
|
|
12
13
|
"""Initialize the ConfigManager.
|
|
13
14
|
|
|
14
15
|
Parameters:
|
|
15
16
|
- file_path (str, optional): The path to the configuration file. Default is 'config.json'.
|
|
16
17
|
"""
|
|
17
|
-
self.file_path =
|
|
18
|
+
self.file_path = Path(__file__).parent.parent.parent / file_name
|
|
18
19
|
self.config = {}
|
|
19
20
|
self.cache = {}
|
|
20
21
|
|
|
@@ -50,17 +51,17 @@ class ConfigManager:
|
|
|
50
51
|
def download_requirements(self, url: str, filename: str):
|
|
51
52
|
"""
|
|
52
53
|
Download the requirements.txt file from the specified URL if not found locally using requests.
|
|
53
|
-
|
|
54
|
+
|
|
54
55
|
Args:
|
|
55
56
|
url (str): The URL to download the requirements file from.
|
|
56
57
|
filename (str): The local filename to save the requirements file as.
|
|
57
58
|
"""
|
|
58
59
|
try:
|
|
59
60
|
import requests
|
|
60
|
-
|
|
61
|
+
|
|
61
62
|
logging.info(f"{filename} not found locally. Downloading from {url}...")
|
|
62
63
|
response = requests.get(url)
|
|
63
|
-
|
|
64
|
+
|
|
64
65
|
if response.status_code == 200:
|
|
65
66
|
with open(filename, 'wb') as f:
|
|
66
67
|
f.write(response.content)
|
|
@@ -68,7 +69,7 @@ class ConfigManager:
|
|
|
68
69
|
else:
|
|
69
70
|
logging.error(f"Failed to download {filename}. HTTP Status code: {response.status_code}")
|
|
70
71
|
sys.exit(0)
|
|
71
|
-
|
|
72
|
+
|
|
72
73
|
except Exception as e:
|
|
73
74
|
logging.error(f"Failed to download {filename}: {e}")
|
|
74
75
|
sys.exit(0)
|
|
@@ -89,15 +90,15 @@ class ConfigManager:
|
|
|
89
90
|
|
|
90
91
|
if cache_key in self.cache:
|
|
91
92
|
return self.cache[cache_key]
|
|
92
|
-
|
|
93
|
+
|
|
93
94
|
if section in self.config and key in self.config[section]:
|
|
94
95
|
value = self.config[section][key]
|
|
95
96
|
else:
|
|
96
97
|
raise ValueError(f"Key '{key}' not found in section '{section}'")
|
|
97
|
-
|
|
98
|
+
|
|
98
99
|
value = self._convert_to_data_type(value, data_type)
|
|
99
100
|
self.cache[cache_key] = value
|
|
100
|
-
|
|
101
|
+
|
|
101
102
|
return value
|
|
102
103
|
|
|
103
104
|
def _convert_to_data_type(self, value: str, data_type: type) -> Any:
|
|
@@ -120,7 +121,7 @@ class ConfigManager:
|
|
|
120
121
|
return None
|
|
121
122
|
else:
|
|
122
123
|
return value
|
|
123
|
-
|
|
124
|
+
|
|
124
125
|
def get(self, section: str, key: str) -> Any:
|
|
125
126
|
"""Read a value from the configuration file.
|
|
126
127
|
|
|
@@ -144,7 +145,7 @@ class ConfigManager:
|
|
|
144
145
|
int: The integer value.
|
|
145
146
|
"""
|
|
146
147
|
return self.read_key(section, key, int)
|
|
147
|
-
|
|
148
|
+
|
|
148
149
|
def get_float(self, section: str, key: str) -> int:
|
|
149
150
|
"""Read an float value from the configuration file.
|
|
150
151
|
|
|
@@ -180,7 +181,7 @@ class ConfigManager:
|
|
|
180
181
|
list: The list value.
|
|
181
182
|
"""
|
|
182
183
|
return self.read_key(section, key, list)
|
|
183
|
-
|
|
184
|
+
|
|
184
185
|
def get_dict(self, section: str, key: str) -> dict:
|
|
185
186
|
"""Read a dictionary value from the configuration file.
|
|
186
187
|
|
|
@@ -220,7 +221,7 @@ class ConfigManager:
|
|
|
220
221
|
json.dump(self.config, f, indent=4)
|
|
221
222
|
except Exception as e:
|
|
222
223
|
print(f"Error writing configuration file: {e}")
|
|
223
|
-
|
|
224
|
+
|
|
224
225
|
|
|
225
226
|
# Initialize
|
|
226
227
|
config_manager = ConfigManager()
|
|
@@ -4,8 +4,6 @@ import os
|
|
|
4
4
|
import glob
|
|
5
5
|
import gzip
|
|
6
6
|
import shutil
|
|
7
|
-
import tarfile
|
|
8
|
-
import zipfile
|
|
9
7
|
import logging
|
|
10
8
|
import platform
|
|
11
9
|
import subprocess
|
|
@@ -179,64 +177,59 @@ class FFMPEGDownloader:
|
|
|
179
177
|
size = file.write(chunk)
|
|
180
178
|
progress.update(download_task, advance=size)
|
|
181
179
|
return True
|
|
180
|
+
|
|
182
181
|
except Exception as e:
|
|
183
182
|
logging.error(f"Download error: {e}")
|
|
184
183
|
return False
|
|
185
184
|
|
|
186
|
-
def
|
|
185
|
+
def _extract_file(self, gz_path: str, final_path: str) -> bool:
|
|
187
186
|
"""
|
|
188
|
-
Extract
|
|
187
|
+
Extract a gzipped file and set proper permissions.
|
|
189
188
|
|
|
190
189
|
Parameters:
|
|
191
|
-
|
|
190
|
+
gz_path (str): Path to the gzipped file
|
|
191
|
+
final_path (str): Path where the extracted file should be saved
|
|
192
192
|
|
|
193
193
|
Returns:
|
|
194
|
-
|
|
195
|
-
ffprobe, and ffplay executables. Returns None for each executable that couldn't be extracted.
|
|
194
|
+
bool: True if extraction was successful, False otherwise
|
|
196
195
|
"""
|
|
197
196
|
try:
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
if
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
197
|
+
logging.info(f"Attempting to extract {gz_path} to {final_path}")
|
|
198
|
+
|
|
199
|
+
# Check if source file exists and is readable
|
|
200
|
+
if not os.path.exists(gz_path):
|
|
201
|
+
logging.error(f"Source file {gz_path} does not exist")
|
|
202
|
+
return False
|
|
203
|
+
|
|
204
|
+
if not os.access(gz_path, os.R_OK):
|
|
205
|
+
logging.error(f"Source file {gz_path} is not readable")
|
|
206
|
+
return False
|
|
207
|
+
|
|
208
|
+
# Extract the file
|
|
209
|
+
with gzip.open(gz_path, 'rb') as f_in:
|
|
210
|
+
# Test if the gzip file is valid
|
|
211
|
+
try:
|
|
212
|
+
f_in.read(1)
|
|
213
|
+
f_in.seek(0)
|
|
214
|
+
except Exception as e:
|
|
215
|
+
logging.error(f"Invalid gzip file {gz_path}: {e}")
|
|
216
|
+
return False
|
|
217
|
+
|
|
218
|
+
# Extract the file
|
|
219
|
+
with open(final_path, 'wb') as f_out:
|
|
211
220
|
shutil.copyfileobj(f_in, f_out)
|
|
212
|
-
else:
|
|
213
|
-
raise ValueError("Unsupported archive format")
|
|
214
|
-
|
|
215
|
-
config = FFMPEG_CONFIGURATION[self.os_name]
|
|
216
|
-
executables = config['executables']
|
|
217
|
-
found_paths = []
|
|
218
|
-
|
|
219
|
-
for executable in executables:
|
|
220
|
-
exe_paths = glob.glob(os.path.join(extraction_path, '**', executable), recursive=True)
|
|
221
|
-
if exe_paths:
|
|
222
|
-
dest_path = os.path.join(self.base_dir, executable)
|
|
223
|
-
shutil.copy2(exe_paths[0], dest_path)
|
|
224
|
-
|
|
225
|
-
if self.os_name != 'windows':
|
|
226
|
-
os.chmod(dest_path, 0o755)
|
|
227
|
-
|
|
228
|
-
found_paths.append(dest_path)
|
|
229
|
-
else:
|
|
230
|
-
found_paths.append(None)
|
|
231
221
|
|
|
232
|
-
|
|
233
|
-
os.
|
|
234
|
-
|
|
235
|
-
|
|
222
|
+
# Set executable permissions
|
|
223
|
+
os.chmod(final_path, 0o755)
|
|
224
|
+
logging.info(f"Successfully extracted {gz_path} to {final_path}")
|
|
225
|
+
|
|
226
|
+
# Remove the gzip file
|
|
227
|
+
os.remove(gz_path)
|
|
228
|
+
return True
|
|
236
229
|
|
|
237
230
|
except Exception as e:
|
|
238
|
-
logging.error(f"Extraction
|
|
239
|
-
return
|
|
231
|
+
logging.error(f"Extraction error for {gz_path}: {e}")
|
|
232
|
+
return False
|
|
240
233
|
|
|
241
234
|
def download(self) -> Tuple[Optional[str], Optional[str], Optional[str]]:
|
|
242
235
|
"""
|
|
@@ -244,30 +237,43 @@ class FFMPEGDownloader:
|
|
|
244
237
|
|
|
245
238
|
Returns:
|
|
246
239
|
Tuple[Optional[str], Optional[str], Optional[str]]: Paths to ffmpeg, ffprobe, and ffplay executables.
|
|
247
|
-
Returns None for each executable that couldn't be downloaded or set up.
|
|
248
240
|
"""
|
|
249
241
|
config = FFMPEG_CONFIGURATION[self.os_name]
|
|
250
242
|
executables = [exe.format(arch=self.arch) for exe in config['executables']]
|
|
251
|
-
|
|
243
|
+
successful_extractions = []
|
|
244
|
+
|
|
252
245
|
for executable in executables:
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
246
|
+
try:
|
|
247
|
+
download_url = f"https://github.com/eugeneware/ffmpeg-static/releases/latest/download/{executable}.gz"
|
|
248
|
+
download_path = os.path.join(self.base_dir, f"{executable}.gz")
|
|
249
|
+
final_path = os.path.join(self.base_dir, executable)
|
|
250
|
+
|
|
251
|
+
# Log the current operation
|
|
252
|
+
logging.info(f"Processing {executable}")
|
|
253
|
+
console.print(f"[bold blue]Downloading {executable} from GitHub[/]")
|
|
254
|
+
|
|
255
|
+
# Download the file
|
|
256
|
+
if not self._download_file(download_url, download_path):
|
|
257
|
+
console.print(f"[bold red]Failed to download {executable}[/]")
|
|
258
|
+
continue
|
|
259
|
+
|
|
260
|
+
# Extract the file
|
|
261
|
+
if self._extract_file(download_path, final_path):
|
|
262
|
+
successful_extractions.append(final_path)
|
|
263
|
+
console.print(f"[bold green]Successfully installed {executable}[/]")
|
|
264
|
+
else:
|
|
265
|
+
console.print(f"[bold red]Failed to extract {executable}[/]")
|
|
266
|
+
|
|
267
|
+
except Exception as e:
|
|
268
|
+
logging.error(f"Error processing {executable}: {e}")
|
|
269
|
+
console.print(f"[bold red]Error processing {executable}: {str(e)}[/]")
|
|
270
|
+
continue
|
|
271
|
+
|
|
272
|
+
# Return the results based on successful extractions
|
|
267
273
|
return (
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
None
|
|
274
|
+
successful_extractions[0] if len(successful_extractions) > 0 else None,
|
|
275
|
+
successful_extractions[1] if len(successful_extractions) > 1 else None,
|
|
276
|
+
None # ffplay is not included in the current implementation
|
|
271
277
|
)
|
|
272
278
|
|
|
273
279
|
def check_ffmpeg() -> Tuple[Optional[str], Optional[str], Optional[str]]:
|