Merge 721f007e0242cbbb9fd6aa9fb80c33d75de617c8 into 86c72937792b2fd695d16d0a4e4c95a73b7fed32

This commit is contained in:
Francesco Grazioso 2025-05-30 16:04:57 +02:00 committed by GitHub
commit a88e0ae890
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
14 changed files with 440 additions and 6 deletions

4
.gitignore vendored
View File

@ -53,4 +53,6 @@ bot_config.json
scripts.json
active_requests.json
domains.json
working_proxies.json
working_proxies.json
.vscode/
.idea/

View File

@ -112,17 +112,17 @@ pip install --upgrade StreamingCommunity
Create a simple script (`run_streaming.py`) to launch the main application:
```python
from StreamingCommunity.run import main
Install requirements:
if __name__ == "__main__":
main()
```bash
pip install -r requirements.txt
```
Run the script:
```bash
python run_streaming.py
python streaming_gui.py
```
## Modules

0
gui/__init__.py Normal file
View File

39
gui/main_window.py Normal file
View File

@ -0,0 +1,39 @@
from PyQt5.QtWidgets import QMainWindow, QWidget, QVBoxLayout
from PyQt5.QtCore import QProcess
import sys
from .tabs.run_tab import RunTab
from .utils.stream_redirect import Stream
class StreamingGUI(QMainWindow):
def __init__(self):
super().__init__()
self.process = None
self.init_ui()
self.setup_output_redirect()
def init_ui(self):
self.setWindowTitle("StreamingCommunity GUI")
self.setGeometry(100, 100, 1000, 700)
central_widget = QWidget()
main_layout = QVBoxLayout()
self.run_tab = RunTab(self)
main_layout.addWidget(self.run_tab)
central_widget.setLayout(main_layout)
self.setCentralWidget(central_widget)
def setup_output_redirect(self):
self.stdout_stream = Stream()
self.stdout_stream.newText.connect(self.run_tab.update_output)
sys.stdout = self.stdout_stream
def closeEvent(self, event):
if self.process and self.process.state() == QProcess.Running:
self.process.terminate()
if not self.process.waitForFinished(1000):
self.process.kill()
sys.stdout = sys.__stdout__
event.accept()

0
gui/tabs/__init__.py Normal file
View File

281
gui/tabs/run_tab.py Normal file
View File

@ -0,0 +1,281 @@
from PyQt5.QtWidgets import (
QWidget,
QVBoxLayout,
QHBoxLayout,
QTabWidget,
QGroupBox,
QFormLayout,
QLineEdit,
QComboBox,
QPushButton,
QCheckBox,
QLabel,
QTextEdit,
)
from PyQt5.QtCore import Qt, QProcess
from ..widgets.results_table import ResultsTable
from ..utils.site_manager import sites
import sys
class RunTab(QTabWidget):
def __init__(self, parent=None):
super().__init__(parent)
self.parent = parent
self.process = None
self.current_context = None
self.selected_season = None
self.buffer = ""
self.init_ui()
def init_ui(self):
run_tab = QWidget()
run_layout = QVBoxLayout()
# Add search group
run_layout.addWidget(self.create_search_group())
# Add control buttons
run_layout.addLayout(self.create_control_layout())
# Add status label
self.status_label = QLabel("Richiesta in corso...")
self.status_label.setAlignment(Qt.AlignCenter)
self.status_label.hide()
run_layout.addWidget(self.status_label)
# Add output group
run_layout.addWidget(self.create_output_group())
run_tab.setLayout(run_layout)
self.addTab(run_tab, "Esecuzione")
def create_search_group(self):
search_group = QGroupBox("Parametri di Ricerca")
search_layout = QFormLayout()
self.search_terms = QLineEdit()
search_layout.addRow("Termini di ricerca:", self.search_terms)
self.site_combo = QComboBox()
for site in sites:
self.site_combo.addItem(f"{site['name']}", site["index"])
self.site_combo.setItemData(site["index"], site["flag"], Qt.ToolTipRole)
if self.site_combo.count() > 0:
self.site_combo.setCurrentIndex(0)
search_layout.addRow("Seleziona sito:", self.site_combo)
search_group.setLayout(search_layout)
return search_group
def create_control_layout(self):
control_layout = QHBoxLayout()
self.run_button = QPushButton("Esegui Script")
self.run_button.clicked.connect(self.run_script)
control_layout.addWidget(self.run_button)
self.stop_button = QPushButton("Ferma Script")
self.stop_button.clicked.connect(self.stop_script)
self.stop_button.setEnabled(False)
control_layout.addWidget(self.stop_button)
self.console_checkbox = QCheckBox("Mostra Console")
self.console_checkbox.setChecked(False)
self.console_checkbox.stateChanged.connect(self.toggle_console)
control_layout.addWidget(self.console_checkbox)
return control_layout
def create_output_group(self):
output_group = QGroupBox("Output")
output_layout = QVBoxLayout()
self.results_table = ResultsTable()
output_layout.addWidget(self.results_table)
self.output_text = QTextEdit()
self.output_text.setReadOnly(True)
self.output_text.hide()
output_layout.addWidget(self.output_text)
input_layout = QHBoxLayout()
self.input_field = QLineEdit()
self.input_field.setPlaceholderText("Inserisci l'indice del media...")
self.input_field.returnPressed.connect(self.send_input)
self.send_button = QPushButton("Invia")
self.send_button.clicked.connect(self.send_input)
self.input_field.hide()
self.send_button.hide()
input_layout.addWidget(self.input_field)
input_layout.addWidget(self.send_button)
output_layout.addLayout(input_layout)
output_group.setLayout(output_layout)
return output_group
def toggle_console(self, state):
self.output_text.setVisible(state == Qt.Checked)
self.results_table.setVisible(state == Qt.Checked)
def run_script(self):
if self.process is not None and self.process.state() == QProcess.Running:
print("Script già in esecuzione.")
return
self.current_context = None
self.selected_season = None
self.buffer = ""
self.results_table.setVisible(False)
self.status_label.setText("Richiesta in corso...")
self.status_label.show()
args = []
search_terms = self.search_terms.text()
if search_terms:
args.extend(["-s", search_terms])
site_index = self.site_combo.currentIndex()
if site_index >= 0:
site_text = sites[site_index]["flag"]
site_name = site_text.split()[0].upper()
args.append(f"-{site_name}")
self.output_text.clear()
print(f"Avvio script con argomenti: {' '.join(args)}")
self.process = QProcess()
self.process.readyReadStandardOutput.connect(self.handle_stdout)
self.process.readyReadStandardError.connect(self.handle_stderr)
self.process.finished.connect(self.process_finished)
python_executable = sys.executable
script_path = "run_streaming.py"
self.process.start(python_executable, [script_path] + args)
self.run_button.setEnabled(False)
self.stop_button.setEnabled(True)
def handle_stdout(self):
data = self.process.readAllStandardOutput()
stdout = bytes(data).decode("utf8", errors="replace")
self.update_output(stdout)
self.buffer += stdout
if "Episodes find:" in self.buffer:
self.current_context = "episodes"
self.input_field.setPlaceholderText(
"Inserisci l'indice dell'episodio (es: 1, *, 1-2, 3-*)"
)
elif "Seasons found:" in self.buffer:
self.current_context = "seasons"
self.input_field.setPlaceholderText(
"Inserisci il numero della stagione (es: 1, *, 1-2, 3-*)"
)
if "Episodes find:" in self.buffer:
self.results_table.hide()
self.current_context = "episodes"
text_to_show = f"Trovati {self.buffer.split('Episodes find:')[1].split()[0]} episodi!"
self.status_label.setText(text_to_show)
self.status_label.show()
elif (("" in self.buffer or "" in self.buffer) and
("" in self.buffer or "" in self.buffer or "" in self.buffer)) or "Seasons found:" in self.buffer:
self.parse_and_show_results(self.buffer)
if "Insert" in self.buffer:
self.input_field.show()
self.send_button.show()
self.input_field.setFocus()
self.output_text.verticalScrollBar().setValue(
self.output_text.verticalScrollBar().maximum()
)
def parse_and_show_results(self, text):
if "Seasons found:" in text and not "Insert media index (e.g., 1)" in text:
self.status_label.hide()
num_seasons = int(text.split("Seasons found:")[1].split()[0])
self.results_table.update_with_seasons(num_seasons)
return
if ("┏━━━━━━━┳" in text or "┌───────┬" in text) and "└───────┴" in text:
chars_to_find = []
if "" in text:
chars_to_find.append("")
chars_to_find.append("")
elif "" in text:
chars_to_find.append("")
chars_to_find.append("")
if not chars_to_find or len(chars_to_find) == 0:
return
self.status_label.hide()
table_lines = text[text.find(chars_to_find[0]) : text.find("")].split("\n")
headers = [h.strip() for h in table_lines[1].split(chars_to_find[1])[1:-1]]
rows = []
for line in table_lines[3:]:
if line.strip() and "" in line:
cells = [cell.strip() for cell in line.split("")[1:-1]]
rows.append(cells)
self.results_table.update_with_results(headers, rows)
def send_input(self):
if not self.process or self.process.state() != QProcess.Running:
return
user_input = self.input_field.text().strip()
if self.current_context == "seasons":
if "-" in user_input or user_input == "*":
self.results_table.hide()
else:
self.selected_season = user_input
elif self.current_context == "episodes":
if "-" in user_input or user_input == "*":
self.results_table.hide()
self.process.write(f"{user_input}\n".encode())
self.input_field.clear()
self.input_field.hide()
self.send_button.hide()
if self.current_context == "seasons" and not (
"-" in user_input or user_input == "*"
):
self.status_label.setText("Caricamento episodi...")
self.status_label.show()
def handle_stderr(self):
data = self.process.readAllStandardError()
stderr = bytes(data).decode("utf8", errors="replace")
self.update_output(stderr)
def process_finished(self):
self.run_button.setEnabled(True)
self.stop_button.setEnabled(False)
self.input_field.hide()
self.send_button.hide()
self.status_label.hide()
print("Script terminato.")
def update_output(self, text):
cursor = self.output_text.textCursor()
cursor.movePosition(cursor.End)
cursor.insertText(text)
self.output_text.setTextCursor(cursor)
self.output_text.ensureCursorVisible()
def stop_script(self):
if self.process is not None and self.process.state() == QProcess.Running:
self.process.terminate()
if not self.process.waitForFinished(3000):
self.process.kill()
print("Script terminato.")
self.run_button.setEnabled(True)
self.stop_button.setEnabled(False)

0
gui/utils/__init__.py Normal file
View File

18
gui/utils/site_manager.py Normal file
View File

@ -0,0 +1,18 @@
from StreamingCommunity.run import load_search_functions
def get_sites():
search_functions = load_search_functions()
sites = []
for alias, (_, use_for) in search_functions.items():
sites.append(
{
"index": len(sites),
"name": alias.split("_")[0],
"flag": alias[:3].upper(),
}
)
return sites
sites = get_sites()

View File

@ -0,0 +1,13 @@
from PyQt5.QtCore import QObject, pyqtSignal
class Stream(QObject):
"""Redirect script output to GUI"""
newText = pyqtSignal(str)
def write(self, text):
self.newText.emit(str(text))
def flush(self):
pass

0
gui/widgets/__init__.py Normal file
View File

View File

@ -0,0 +1,62 @@
from PyQt5.QtWidgets import QTableWidget, QTableWidgetItem, QHeaderView
from PyQt5.QtCore import Qt
class ResultsTable(QTableWidget):
def __init__(self, parent=None):
super().__init__(parent)
self.setup_table()
def setup_table(self):
self.setVisible(False)
self.setSelectionMode(QTableWidget.NoSelection)
self.setEditTriggers(QTableWidget.NoEditTriggers)
self.setFocusPolicy(Qt.NoFocus)
self.setDragDropMode(QTableWidget.NoDragDrop)
self.setContextMenuPolicy(Qt.NoContextMenu)
self.verticalHeader().setVisible(False)
# set custom style for diabled table
self.setStyleSheet(
"""
QTableWidget:disabled {
color: white;
background-color: #323232;
}
"""
)
self.setEnabled(False)
def update_with_seasons(self, num_seasons):
self.clear()
self.setColumnCount(2)
self.setHorizontalHeaderLabels(["Index", "Season"])
self.setRowCount(num_seasons)
for i in range(num_seasons):
index_item = QTableWidgetItem(str(i + 1))
season_item = QTableWidgetItem(f"Stagione {i + 1}")
index_item.setFlags(Qt.ItemIsEnabled)
season_item.setFlags(Qt.ItemIsEnabled)
self.setItem(i, 0, index_item)
self.setItem(i, 1, season_item)
self.horizontalHeader().setSectionResizeMode(QHeaderView.ResizeToContents)
self.horizontalHeader().setEnabled(False)
self.setVisible(True)
def update_with_results(self, headers, rows):
self.clear()
self.setColumnCount(len(headers))
self.setHorizontalHeaderLabels(headers)
self.setRowCount(len(rows))
for i, row in enumerate(rows):
for j, cell in enumerate(row):
item = QTableWidgetItem(cell)
item.setFlags(Qt.ItemIsEnabled)
self.setItem(i, j, item)
self.horizontalHeader().setSectionResizeMode(QHeaderView.ResizeToContents)
self.horizontalHeader().setEnabled(False)
self.setVisible(True)

View File

@ -13,3 +13,4 @@ pycryptodomex
ua-generator
qbittorrent-api
pyTelegramBotAPI
PyQt5

4
run_streaming.py Normal file
View File

@ -0,0 +1,4 @@
from StreamingCommunity.run import main
if __name__ == "__main__":
main()

14
streaming_gui.py Normal file
View File

@ -0,0 +1,14 @@
import sys
from PyQt5.QtWidgets import QApplication
from gui.main_window import StreamingGUI
def main():
app = QApplication(sys.argv)
gui = StreamingGUI()
gui.show()
sys.exit(app.exec_())
if __name__ == "__main__":
main()