fix setup process

This commit is contained in:
Nick
2025-11-03 20:31:52 +01:00
parent 4246d13339
commit 221e1ad318
6 changed files with 343 additions and 483 deletions

View File

@@ -63,8 +63,8 @@ class UserProfile:
self.username = username
self.role: Optional[str] = None
self.display_name: Optional[str] = None
self.channels: List[int] = [] # Canali assegnati
self.mixes: List[int] = [] # Mix/aux assegnati
self.channel_labels: List[str] = [] # Etichette dei canali assegnati
self.mix_labels: List[str] = [] # Etichette dei mix/aux assegnati
self.setup_completed = False
self.created_at = time.time()
self.last_updated = time.time()
@@ -76,8 +76,8 @@ class UserProfile:
"username": self.username,
"role": self.role,
"display_name": self.display_name,
"channels": self.channels,
"mixes": self.mixes,
"channel_labels": self.channel_labels,
"mix_labels": self.mix_labels,
"setup_completed": self.setup_completed,
"created_at": self.created_at,
"created_at_str": time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(self.created_at)),
@@ -91,8 +91,8 @@ class UserProfile:
profile = cls(data["user_id"], data["username"])
profile.role = data.get("role")
profile.display_name = data.get("display_name")
profile.channels = data.get("channels", [])
profile.mixes = data.get("mixes", [])
profile.channel_labels = data.get("channel_labels", [])
profile.mix_labels = data.get("mix_labels", [])
profile.setup_completed = data.get("setup_completed", False)
profile.created_at = data.get("created_at", time.time())
profile.last_updated = data.get("last_updated", time.time())
@@ -102,36 +102,6 @@ class UserProfile:
"""Restituisce le info sul ruolo."""
return self.ROLES.get(self.role, {})
def can_access_channel(self, channel: int) -> bool:
"""Verifica se l'utente può accedere a un canale."""
if not self.role:
return False
permissions = self.get_role_info().get("permissions", [])
if "all" in permissions:
return True
if "own_channel" in permissions:
return channel in self.channels
return False
def can_access_mix(self, mix: int) -> bool:
"""Verifica se l'utente può accedere a un mix."""
if not self.role:
return False
permissions = self.get_role_info().get("permissions", [])
if "all" in permissions:
return True
if "own_mix" in permissions:
return mix in self.mixes
return False
def get_summary(self) -> str:
"""Restituisce un riepilogo del profilo."""
if not self.setup_completed:
@@ -140,15 +110,14 @@ class UserProfile:
role_info = self.get_role_info()
msg = f"{role_info['emoji']} **{self.display_name}** ({role_info['name']})\n\n"
if self.channels:
msg += f"🎚️ Canali: {', '.join(map(str, self.channels))}\n"
if self.channel_labels:
msg += f"🎚️ Canali: {', '.join(self.channel_labels)}\n"
if self.mixes:
msg += f"🔊 Mix: {', '.join(map(str, self.mixes))}\n"
if self.mix_labels:
msg += f"🔊 Mix: {', '.join(self.mix_labels)}\n"
return msg
class ProfileManager:
"""Gestisce i profili utente."""
@@ -221,7 +190,6 @@ class ProfileManager:
return profiles
class ConversationManager:
"""Gestisce il salvataggio delle conversazioni su file JSON."""
@@ -289,7 +257,6 @@ class ConversationManager:
print(f"❌ Errore nell'eliminazione conversazione {user_id}: {e}")
return False
class TelegramBot:
"""Bot Telegram base con long polling."""
@@ -423,7 +390,7 @@ class TF5TelegramBot:
self.controller.set_channel_to_mix_level,
self.controller.set_channel_to_mix_on_off,
self.controller.get_channel_to_mix_info,
self.controller.get_full_mix_details, # <-- NUOVA FUNZIONE AGGIUNTA
self.controller.get_full_mix_details,
],
temperature=0,
)
@@ -568,13 +535,17 @@ Devi essere veloce, chiaro e capire anche richieste approssimative.
instruction += f"Nome: {profile.display_name}\n"
instruction += f"Ruolo: {role_info['name']} {role_info['emoji']}\n"
if profile.channels:
instruction += f"\nCanali assegnati: {', '.join(map(str, profile.channels))}\n"
instruction += "Quando l'utente dice 'il mio canale' o 'il mio mic/strumento', si riferisce a questi.\n"
if profile.channel_labels:
labels_str = ', '.join([f"'{l}'" for l in profile.channel_labels])
instruction += f"\nNomi dei canali assegnati: {labels_str}\n"
instruction += "Quando l'utente dice 'il mio canale' o 'il mio mic/strumento', si riferisce a questi. "
instruction += "**DEVI usare `search_channels_by_name` con questi nomi per trovare il numero di canale corretto prima di eseguire qualsiasi altra azione.**\n"
if profile.mixes:
instruction += f"\nMix assegnati: {', '.join(map(str, profile.mixes))}\n"
instruction += "Quando l'utente dice 'le mie cuffie', 'il mio monitor', 'in cuffia', si riferisce a questi mix.\n"
if profile.mix_labels:
labels_str = ', '.join([f"'{l}'" for l in profile.mix_labels])
instruction += f"\nNomi dei mix assegnati: {labels_str}\n"
instruction += "Quando l'utente dice 'le mie cuffie', 'il mio monitor', 'in cuffia', si riferisce a questi mix. "
instruction += "**DEVI usare `search_mixes_by_name` con questi nomi per trovare il numero di mix corretto prima di eseguire qualsiasi altra azione.**\n"
# Istruzioni specifiche per ruolo
permissions = role_info.get("permissions", [])
@@ -587,77 +558,27 @@ Devi essere veloce, chiaro e capire anche richieste approssimative.
else:
instruction += f"\n⚠️ LIMITAZIONI DI ACCESSO ({role_info['name']}):\n"
if "own_channel" in permissions and profile.channels:
instruction += f"- Canali controllabili: SOLO {', '.join(map(str, profile.channels))}\n"
if "own_channel" in permissions and profile.channel_labels:
instruction += f"- Canali controllabili: SOLO quelli che corrispondono ai nomi nel tuo profilo.\n"
if "own_mix" in permissions and profile.mixes:
instruction += f"- Mix controllabili: SOLO {', '.join(map(str, profile.mixes))}\n"
instruction += f"- Puoi gestire i send di QUALSIASI canale verso i TUOI mix ({', '.join(map(str, profile.mixes))})\n"
if "own_mix" in permissions and profile.mix_labels:
instruction += f"- Mix controllabili: SOLO quelli che corrispondono ai nomi nel tuo profilo.\n"
instruction += f"- Puoi gestire i send di QUALSIASI canale verso i TUOI mix.\n"
instruction += "\n❌ NON puoi:\n"
if "own_channel" not in permissions:
instruction += "- Modificare il volume/stato dei canali\n"
if "own_mix" not in permissions:
instruction += "- Modificare il volume/stato dei mix\n"
instruction += "- Caricare scene (solo i mixeristi)\n"
instruction += "- Accedere a canali/mix non assegnati\n"
instruction += "- Caricare scene (solo i mixeristi).\n"
instruction += "- Accedere a canali/mix non associati al tuo profilo.\n"
instruction += "\n💡 INTERPRETAZIONE RICHIESTE:\n"
instruction += "- 'alzami la chitarra' = alza il send della chitarra nel TUO mix\n"
instruction += "- 'più voce' = alza il send della voce nel TUO mix\n"
instruction += "- 'meno batteria in cuffia' = abbassa il send della batteria nel TUO mix\n"
instruction += "- Se l'utente chiede di fare qualcosa fuori dai suoi permessi, spiega gentilmente che non può e suggerisci di chiedere al mixerista\n"
instruction += "- 'alzami la chitarra' = alza il send della chitarra nel TUO mix (identificato dal suo nome).\n"
instruction += "- 'più voce' = alza il send della voce nel TUO mix.\n"
instruction += "- 'meno batteria in cuffia' = abbassa il send della batteria nel TUO mix.\n"
instruction += "- Se l'utente chiede di fare qualcosa fuori dai suoi permessi, spiega gentilmente che non può e suggerisci di chiedere al mixerista.\n"
instruction += f"\n{'='*70}\n"
return instruction
def _check_permission(self, profile: UserProfile, operation: str,
channel: Optional[int] = None,
mix: Optional[int] = None) -> tuple[bool, str]:
"""
Verifica se l'utente ha i permessi per un'operazione.
Ritorna (permitted, error_message)
"""
if not profile.setup_completed:
return False, "⚠️ Devi prima configurare il tuo profilo con /setup"
role_info = profile.get_role_info()
permissions = role_info.get("permissions", [])
# Mixeristi possono fare tutto
if "all" in permissions:
return True, ""
# Verifica permessi specifici
if operation in ["set_channel_level", "set_channel_on_off", "set_channel_pan",
"mute_multiple_channels", "unmute_multiple_channels"]:
if "own_channel" not in permissions:
return False, "❌ Solo i mixeristi possono controllare i canali direttamente"
if channel and not profile.can_access_channel(channel):
return False, f"❌ Non hai accesso al canale {channel}. I tuoi canali: {', '.join(map(str, profile.channels))}"
if operation in ["set_mix_level", "set_mix_on_off", "get_full_mix_details"]:
if "own_mix" not in permissions:
return False, "❌ Non hai permessi per controllare i mix"
if mix and not profile.can_access_mix(mix):
return False, f"❌ Non hai accesso al mix {mix}. I tuoi mix: {', '.join(map(str, profile.mixes))}"
if operation == "recall_scene":
return False, "❌ Solo i mixeristi possono caricare scene"
# Le operazioni di send ai mix sono permesse se hai accesso al mix di destinazione
if operation in ["set_channel_to_mix_level", "set_channel_to_mix_on_off"]:
if "own_mix" not in permissions:
return False, "❌ Non hai permessi per controllare i send ai mix"
if mix and not profile.can_access_mix(mix):
return False, f"❌ Non hai accesso al mix {mix}. I tuoi mix: {', '.join(map(str, profile.mixes))}"
return True, ""
def get_profile(self, user_id: int, username: str) -> UserProfile:
"""Ottiene il profilo di un utente."""
if user_id not in self.profiles:
@@ -726,7 +647,6 @@ Devi essere veloce, chiaro e capire anche richieste approssimative.
role_info = profile.get_role_info()
permissions = role_info.get("permissions", [])
# Se è mixerista, ha finito
if "all" in permissions:
profile.setup_completed = True
self.profile_manager.save_profile(profile)
@@ -740,59 +660,47 @@ Devi essere veloce, chiaro e capire anche richieste approssimative.
f"'Richiama la scena A10'\n"
f"'Mostrami tutti i canali'")
# Altrimenti, chiedi i canali (se necessario)
if "own_channel" in permissions:
self.bot.send_message(
user_id,
f"🎚️ Quali canali usi?\n\n"
f"Esempi:\n"
f"• Un canale: 5\n"
f"• Più canali: 5, 7, 12\n"
f"• Range: 5-8 (canali 5, 6, 7, 8)\n"
f"• Misti: 3, 5-7, 10\n\n"
f"(Scrivi 0 se non usi canali diretti)"
f"🎚️ **Come si chiama il tuo canale/strumento?**\n\n"
f"Scrivi il nome esatto che vedi sull'etichetta del mixer (es: 'VOX Marco', 'CH Acustica').\n"
f"Se hai più canali, separali con una virgola (es: 'Tastiera L', 'Tastiera R').\n\n"
f"(Scrivi 'nessuno' se non hai un canale specifico)"
)
self.setup_states[user_id] = {"step": "channels", "role": profile.role}
return ""
else:
# Salta direttamente ai mix
self.setup_states[user_id] = {"step": "channels"}
elif "own_mix" in permissions:
self.bot.send_message(
user_id,
f"🔊 Quali mix/aux usi per le tue cuffie o uscita?\n\n"
f"Esempi:\n"
f"• Un mix: 3\n"
f"• Più mix: 3, 5\n"
f"• Range: 3-5\n"
f"• Mix stereo: 9, 10 (in-ear stereo)\n\n"
f"(Scrivi 0 se non usi mix specifici)"
f"🔊 **Come si chiama il tuo mix per le cuffie/monitor?**\n\n"
f"Scrivi il nome esatto (es: 'InEar Marco', 'Cuffia Palco Sx').\n"
f"Se usi un mix stereo, scrivi entrambi i nomi separati da virgola (es: 'IEM L', 'IEM R').\n\n"
f"(Scrivi 'nessuno' se non usi un mix specifico)"
)
self.setup_states[user_id] = {"step": "mixes", "role": profile.role}
return ""
self.setup_states[user_id] = {"step": "mixes"}
return ""
# Step: inserimento canali
# Step: inserimento etichette canali
elif step == "channels":
channels = self._parse_channel_list(text)
profile.channels = channels
labels_text = text.strip()
if labels_text.lower() != 'nessuno':
profile.channel_labels = [label.strip() for label in labels_text.split(',')]
role_info = profile.get_role_info()
permissions = role_info.get("permissions", [])
# Chiedi i mix se necessario
if "own_mix" in permissions:
self.bot.send_message(
user_id,
f"🔊 Quali mix/aux usi per le tue cuffie o uscita?\n\n"
f"Esempi:\n"
f"• Un mix: 3\n"
f"• Più mix: 3, 5\n"
f"• Range: 3-5\n"
f"• Mix stereo: 9, 10 (in-ear stereo)\n\n"
f"(Scrivi 0 se non usi mix specifici)"
f"🔊 **Come si chiama il tuo mix per le cuffie/monitor?**\n\n"
f"Scrivi il nome esatto (es: 'InEar Marco', 'Cuffia Palco Sx').\n"
f"Se usi un mix stereo, scrivi entrambi i nomi separati da virgola (es: 'IEM L', 'IEM R').\n\n"
f"(Scrivi 'nessuno' se non usi un mix specifico)"
)
self.setup_states[user_id] = {"step": "mixes", "role": profile.role}
self.setup_states[user_id] = {"step": "mixes"}
return ""
else:
# Finito
profile.setup_completed = True
self.profile_manager.save_profile(profile)
del self.setup_states[user_id]
@@ -803,59 +711,32 @@ Devi essere veloce, chiaro e capire anche richieste approssimative.
f"'Alza il mio canale'\n"
f"'Spegni il mio mic'")
# Step: inserimento mix
# Step: inserimento etichette mix
elif step == "mixes":
mixes = self._parse_channel_list(text) # Stessa logica per i mix
profile.mixes = mixes
labels_text = text.strip()
if labels_text.lower() != 'nessuno':
profile.mix_labels = [label.strip() for label in labels_text.split(',')]
profile.setup_completed = True
self.profile_manager.save_profile(profile)
del self.setup_states[user_id]
role_info = profile.get_role_info()
example_commands = []
if profile.channels:
example_commands.append("'Alza il mio canale'")
if profile.mixes:
if profile.channel_labels:
example_commands.append("'Alza il volume del mio canale'")
if profile.mix_labels:
example_commands.extend([
"'Alzami la chitarra' (nel tuo mix)",
"'Alzami la chitarra nel mio monitor'",
"'Più voce in cuffia'",
"'Meno batteria'"
])
return (f"✅ Configurazione completata!\n\n"
f"{profile.get_summary()}\n"
f"Esempi di comandi:\n" + "\n".join(example_commands))
f"{profile.get_summary()}\n\n"
f"Esempi di comandi che puoi usare:\n" + "\n".join(example_commands))
return ""
def _parse_channel_list(self, text: str) -> List[int]:
"""Parse una lista di canali/mix dal testo utente."""
channels = []
# Rimuovi spazi e split per virgola
parts = [p.strip() for p in text.split(',')]
for part in parts:
# Range (es: 5-8)
if '-' in part:
try:
start, end = map(int, part.split('-'))
channels.extend(range(start, end + 1))
except:
pass
# Singolo numero
else:
try:
num = int(part)
if num > 0: # Ignora 0
channels.append(num)
except:
pass
return sorted(list(set(channels))) # Rimuovi duplicati e ordina
def _get_file_path(self, file_id: str) -> str:
"""Richiede a Telegram il percorso di un file."""
result = self.bot._make_request("getFile", {"file_id": file_id})
@@ -1006,10 +887,10 @@ Devi essere veloce, chiaro e capire anche richieste approssimative.
msg += "'Analizza il mix 15 per la diretta'\n"
else:
msg += "**Esempi di comandi:**\n"
if profile.channels:
if profile.channel_labels:
msg += "'Alza il mio canale'\n"
msg += "'Spegni il mio mic'\n"
if profile.mixes:
if profile.mix_labels:
msg += "'Alzami la chitarra' (nel tuo mix)\n"
msg += "'Più voce in cuffia'\n"
msg += "'Analizza il mio mix per la diretta'\n"