ServerX commited on
Commit
f4042ee
·
verified ·
1 Parent(s): da196a6

Create app.py

Browse files
Files changed (1) hide show
  1. app.py +202 -0
app.py ADDED
@@ -0,0 +1,202 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import gradio as gr
2
+ import requests, zipfile, os, shutil, io, json
3
+
4
+ # FILE DI CONFIGURAZIONE
5
+ SETTINGS_FILE = "settings.json"
6
+ DEFAULT_SETTINGS = {
7
+ "videolibrarypath": "special://profile/addon_data/plugin.video.s4me/videolibrary/",
8
+ "folder_tvshows": "Serie TV",
9
+ "folder_movies": "Film",
10
+ "videolibrary_kodi": False
11
+ }
12
+
13
+ def load_settings():
14
+ """Carica le impostazioni dal file JSON, se presente, altrimenti usa quelle di default."""
15
+ if os.path.exists(SETTINGS_FILE):
16
+ try:
17
+ with open(SETTINGS_FILE, "r", encoding="utf-8") as f:
18
+ return json.load(f)
19
+ except Exception:
20
+ return DEFAULT_SETTINGS
21
+ else:
22
+ return DEFAULT_SETTINGS
23
+
24
+ def save_settings(new_settings):
25
+ """Salva le impostazioni su file JSON."""
26
+ try:
27
+ with open(SETTINGS_FILE, "w", encoding="utf-8") as f:
28
+ json.dump(new_settings, f, indent=4, ensure_ascii=False)
29
+ return "Impostazioni salvate correttamente."
30
+ except Exception as e:
31
+ return f"Errore nel salvataggio delle impostazioni: {str(e)}"
32
+
33
+ def get_current_settings():
34
+ """Restituisce le impostazioni correnti in formato JSON formattato."""
35
+ settings = load_settings()
36
+ return json.dumps(settings, indent=4, ensure_ascii=False)
37
+
38
+ def update_settings(videolibrarypath, folder_tvshows, folder_movies, videolibrary_kodi):
39
+ """Aggiorna le impostazioni a partire dai valori forniti."""
40
+ new_settings = {
41
+ "videolibrarypath": videolibrarypath,
42
+ "folder_tvshows": folder_tvshows,
43
+ "folder_movies": folder_movies,
44
+ "videolibrary_kodi": videolibrary_kodi
45
+ }
46
+ return save_settings(new_settings)
47
+
48
+ def get_branches():
49
+ """
50
+ Recupera la lista dei branch disponibili dal repository GitHub.
51
+ Priorità a 'stable' e 'master', il resto in ordine.
52
+ """
53
+ url = "https://api.github.com/repos/stream4me/addon/branches"
54
+ try:
55
+ response = requests.get(url)
56
+ response.raise_for_status()
57
+ branches = [branch["name"] for branch in response.json()]
58
+ ordered = []
59
+ for b in ['stable', 'master']:
60
+ if b in branches:
61
+ ordered.append(b)
62
+ ordered.extend([b for b in branches if b not in ['stable', 'master']])
63
+ return ordered
64
+ except Exception:
65
+ return ["stable", "master"]
66
+
67
+ def update_from_zip(branch: str) -> str:
68
+ """
69
+ Scarica lo zip del branch selezionato da GitHub,
70
+ lo estrae e sostituisce la cartella target 'plugin.video.s4me'.
71
+ Viene restituito un log delle operazioni.
72
+ """
73
+ log = []
74
+ try:
75
+ url = f"https://github.com/stream4me/addon/archive/{branch}.zip"
76
+ log.append(f"Avvio download da: {url}")
77
+ response = requests.get(url, stream=True)
78
+ response.raise_for_status()
79
+ zip_filename = f"{branch}.zip"
80
+ with open(zip_filename, "wb") as f:
81
+ for chunk in response.iter_content(chunk_size=8192):
82
+ if chunk:
83
+ f.write(chunk)
84
+ log.append("Download completato.")
85
+
86
+ # Definizione delle directory
87
+ extract_base = f"plugin.video.s4me_{branch}"
88
+ target_dir = "plugin.video.s4me"
89
+
90
+ # Rimozione della cartella target se esiste già
91
+ if os.path.isdir(target_dir):
92
+ shutil.rmtree(target_dir)
93
+ log.append(f"Vecchia cartella '{target_dir}' rimossa.")
94
+
95
+ log.append("Inizio estrazione...")
96
+ with zipfile.ZipFile(zip_filename, "r") as zip_ref:
97
+ zip_ref.extractall(extract_base)
98
+ log.append("Estrazione completata.")
99
+
100
+ # GitHub estrae in una cartella denominata 'addon-<branch>'
101
+ extracted_folder = os.path.join(extract_base, f"addon-{branch}")
102
+ if os.path.isdir(extracted_folder):
103
+ os.rename(extracted_folder, target_dir)
104
+ log.append(f"Cartella rinominata in '{target_dir}'.")
105
+ else:
106
+ log.append("Errore: cartella estratta non trovata.")
107
+
108
+ # Pulizia finale
109
+ os.remove(zip_filename)
110
+ shutil.rmtree(extract_base)
111
+ log.append("Pulizia completata. Aggiornamento eseguito con successo.")
112
+ except Exception as e:
113
+ log.append(f"Errore durante l'aggiornamento: {str(e)}")
114
+ return "\n".join(log)
115
+
116
+ def perform_update(selected_branch: str) -> str:
117
+ """Funzione chiamata dal pulsante di aggiornamento nell’interfaccia."""
118
+ return update_from_zip(selected_branch)
119
+
120
+ def build_interface():
121
+ """Costruisce l’interfaccia completa utilizzando Gradio."""
122
+ branches = get_branches()
123
+
124
+ # CSS personalizzato per Smart TV: font ingranditi e margini per una migliore usabilità
125
+ css_custom = """
126
+ body { font-size: 32px; }
127
+ .gradio-container { font-size: 32px; }
128
+ .gr-button { font-size: 32px; padding: 20px; }
129
+ .gr-input { font-size: 32px; padding: 10px; }
130
+ .gr-dropdown { font-size: 32px; padding: 10px; }
131
+ /* Aggiungi margini maggiori per facilitare la navigazione con telecomando */
132
+ .gradio-container * {
133
+ margin: 20px;
134
+ }
135
+ """
136
+ # Script JS per navigazione via tasti freccia (arrow keys)
137
+ js_script = """
138
+ <script>
139
+ document.addEventListener('keydown', function(event) {
140
+ let focused = document.activeElement;
141
+ if (!focused) return;
142
+ let focusable = Array.from(document.querySelectorAll('button, input, select, textarea, a'));
143
+ let index = focusable.indexOf(focused);
144
+ if (event.key === 'ArrowDown') {
145
+ index = (index + 1) % focusable.length;
146
+ focusable[index].focus();
147
+ } else if (event.key === 'ArrowUp') {
148
+ index = (index - 1 + focusable.length) % focusable.length;
149
+ focusable[index].focus();
150
+ }
151
+ });
152
+ </script>
153
+ """
154
+
155
+ with gr.Blocks(css=css_custom, title="Stream4Me Update per Smart TV") as demo:
156
+ gr.Markdown("# Stream4Me - Aggiornamento e Configurazione per Smart TV")
157
+ gr.HTML(js_script) # Iniezione dello script JS per la navigazione via tasti
158
+ with gr.Tabs():
159
+ with gr.TabItem("Aggiornamento"):
160
+ gr.Markdown("## Aggiorna l'addon dal repository GitHub")
161
+ branch_dropdown = gr.Dropdown(choices=branches, value=branches[0], label="Seleziona Branch")
162
+ update_button = gr.Button("Avvia Aggiornamento")
163
+ update_log = gr.Textbox(label="Log di Aggiornamento", lines=10)
164
+ update_button.click(fn=perform_update, inputs=branch_dropdown, outputs=update_log)
165
+
166
+ with gr.TabItem("Impostazioni"):
167
+ gr.Markdown("## Configura le impostazioni")
168
+ settings = load_settings()
169
+ input_videolibrarypath = gr.Textbox(value=settings.get("videolibrarypath", ""), label="Percorso Video Library")
170
+ input_folder_tvshows = gr.Textbox(value=settings.get("folder_tvshows", ""), label="Cartella Serie TV")
171
+ input_folder_movies = gr.Textbox(value=settings.get("folder_movies", ""), label="Cartella Film")
172
+ input_videolibrary_kodi = gr.Checkbox(value=settings.get("videolibrary_kodi", False), label="Integrazione Video Library Kodi")
173
+ save_button = gr.Button("Salva Impostazioni")
174
+ settings_status = gr.Textbox(label="Stato Impostazioni", lines=2)
175
+ save_button.click(fn=update_settings,
176
+ inputs=[input_videolibrarypath, input_folder_tvshows, input_folder_movies, input_videolibrary_kodi],
177
+ outputs=settings_status)
178
+ gr.Markdown("### Impostazioni Correnti")
179
+ current_settings_box = gr.Textbox(value=get_current_settings(), label="Impostazioni Correnti", lines=8)
180
+ refresh_button = gr.Button("Ricarica Impostazioni")
181
+ refresh_button.click(fn=get_current_settings, inputs=[], outputs=current_settings_box)
182
+
183
+ with gr.TabItem("Informazioni"):
184
+ gr.Markdown("## Informazioni sul Progetto")
185
+ gr.Markdown("""
186
+ **Stream4Me** è un progetto per gestire e aggiornare l'addon per Kodi, ora migrato ad una interfaccia web ottimizzata per Smart TV.
187
+
188
+ **Funzionalità:**
189
+ - Aggiornamento automatico dall'API GitHub.
190
+ - Configurazione personalizzata tramite interfaccia web.
191
+ - Ottimizzato per dispositivi Smart TV con interfaccia responsive e navigazione semplificata.
192
+
193
+ **Repository:** [Stream4Me su GitHub](https://github.com/Stream4me/addon)
194
+
195
+ **Autore:** S4Me Team
196
+ """)
197
+
198
+ return demo
199
+
200
+ if __name__ == "__main__":
201
+ demo = build_interface()
202
+ demo.launch()