Eseguire BAN+KICK automatico degli utenti che, quando entrano nel canale, risultano essere presenti in uno o più canali elencati in una "blacklist" (file $HOME/.xchat2/buduscript/badchannel.txt)
Soluzione da inserire all'interno di "botconnetct.mcr" (ATTENZIONE: dalla prossima release del BOT (11.6) questa funzionalità sarà già inclusa e andrà tolta da "botconnect.mcr"):
Codice: Seleziona tutto
/ECHO %C8,1Aggiunge la gestione dei BADCHANNEL.
/event add 0 spcl_badchannel * /budus set buduscript_bot_badchannel_joined_list _NONE_\;/budus if "'$(grep -F \( 319 \) "$HOME/$mxchat_path/buduscript/$hostname.log" | grep -F \( $ru :\) | grep -F \($channel \) | tail -n1 | sed \(s@.* :@@\))'" ! '' /budus set buduscript_bot_badchannel_joined_list $output\;/budus InsertCommandInQueue() /budus cmd /budus pipe_script for chan_join in $(cat "$HOME/$mxchat_path/buduscript/badchannel.txt") ; do find_channel=$(echo \($buduscript_bot_badchannel_joined_list\) | grep -F "${chan_join} ") ; if test "${find_channel}" != "" ; then echo \(/budus sendsess $server/$channel /budus ban + *!*@$domain init( $buduscript_bot_badchannel_ban_time,3600 ) $ru\); echo "/budus sendsess $server/$channel /KICK $ru Non sono graditi gli utenti di ${chan_join}"; fi; done
/event add 0 jchannel '$nick'!'$ru' /whois $ru\;/budus InsertCommandInQueueTimed() 3 /budus sendsess $server/$channel /event event spcl_badchannel $event_params
Spiegazione: come al solito, se non si scompone i comandi, difficilmente si può capire qualcosa, perché "per ragioni tecniche", siamo obbligati a creare le cose con "comandi" che, necessariamente, devono contenere tutto il necessario.
Parto dalla sentinella più semplice:
Codice: Seleziona tutto
/event add 0 jchannel '$nick'!'$ru' /whois $ru\;/budus InsertCommandInQueueTimed() 3 /budus sendsess $server/$channel /event event spcl_badchannel $event_params
Tradotta significa:
Aggiungi una sentinella (add) che ogni volta (0) che entra un utente (jchannel) con nickname ($ru) diverso da quello dell'utente locale ($nick) esegui questi 2 comandi:
Codice: Seleziona tutto
/whois $ru
Direi che il comando si commenta da solo: esegui il "whois" dell'utente che è appena entrato ($ru).Codice: Seleziona tutto
/budus InsertCommandInQueueTimed() 3 /budus sendsess $server/$channel /event event spcl_badchannel $event_params
Significato: Inserisci un comando nella "coda dei comandi" in modo temporizzato, con un ritardo di 3 secondi. Il comando inserito:Codice: Seleziona tutto
/budus sendsess $server/$channel /event event spcl_badchanne $event_params
significa: invia alla sessione che ha generato l'evento, la generazione di un evento di tipo "spcl_badchannel" con i parametri standard ($event_params).
In sintesi: la sentinella ha il compito di fare il "whois" degli utenti che entrano e di invocare una seconda sentinella (quella più corposa e che risponde all'evento "spcl_badchannel").
Ora passo alla seconda sentinella:
Codice: Seleziona tutto
/event add 0 spcl_badchannel * /budus set buduscript_bot_badchannel_joined_list _NONE_\;/budus if "'$(grep -F \( 319 \) "$HOME/$mxchat_path/buduscript/$hostname.log" | grep -F \( $ru :\) | grep -F \($channel \) | tail -n1 | sed \(s@.* :@@\))'" ! '' /budus set buduscript_bot_badchannel_joined_list $output\;/budus InsertCommandInQueue() /budus cmd /budus pipe_script for chan_join in $(cat "$HOME/$mxchat_path/buduscript/badchannel.txt") ; do find_channel=$(echo \($buduscript_bot_badchannel_joined_list\) | grep -F "${chan_join} ") ; if test "${find_channel}" != "" ; then echo \(/budus sendsess $server/$channel /budus ban + *!*@$domain init( $buduscript_bot_badchannel_ban_time,3600 ) $ru\); echo "/budus sendsess $server/$channel /KICK $ru Non sono graditi gli utenti di ${chan_join}"; fi; done
Questa sentinella reagisce all'evento "spcl_badchannel" (che quindi è speciale e "va generato") e, non avendo condizione (*), esegue sempre i suoi comandi.
Partiamo dal primo comando che viene eseguito:
Codice: Seleziona tutto
/budus set buduscript_bot_badchannel_joined_list _NONE_Qui viene creata o comunque re-inizializzata la variabile "buduscript_bot_badchannel_joined_list" al valore "_NONE_".
Questa variabile ha il compito di contenere la lista dei canali che l'utente appena entrato risulta essere presente.
Il secondo comando:
Codice: Seleziona tutto
/budus if "'$(grep -F \( 319 \) "$HOME/$mxchat_path/buduscript/$hostname.log" | grep -F \( $ru :\) | grep -F \($channel \) | tail -n1 | sed \(s@.* :@@\))'" ! '' /budus set buduscript_bot_badchannel_joined_list $output
è una condizione abbastanza complicata.
Sinteticamente serve per verificare se il "whois" è stato eseguito e, in caso affermativo, estrapolare la lista dei canali che l'utente che ha effettuato il join risulta essere presente, per poi andarli a memorizzare nella variabile "buduscript_bot_badchannel_joined_list".
Per fare tutto questo, procede in questo modo:
- Esegue il seguente comando (quello compreso in "$(...)") in un terminale fittizio del sistema operativo:
Codice: Seleziona tutto
grep -F \( 319 \) "$HOME/$mxchat_path/buduscript/$hostname.log" | grep -F \( $ru :\) | grep -F \($channel \) | tail -n1 | sed \(s@.* :@@\)
Per essere precisi, il comando non viene eseguito esattamente così, perché prima viene "risolto"; supponendo che l'utente si chiami "pippo", il canale "#buduscript" e il network "irc.budus.net", la risoluzione è la seguente:Codice: Seleziona tutto
grep -F ' 319 ' "$HOME/.xchat2/buduscript/irc.budus.net.log" | grep -F ' pippo :' | grep -F '#buduscript ' | tail -n1 | sed 's@.* :@@'N.B.: Le sequenze "\(" e "\)" vengono opportunamente sostituite da apici. Si usa questo sistema perché se una variabile contiene un apice, la protezione del parametro deve rispettarlo; ad esempio, se una variabile "$prova" ha valore "prova'variabile" per proteggerla dobbiamo scrivere "\($prova\)" in modo che, quando risolta, il sistema userà: 'prova'\''variabile'
Il comando invoca dei comandi del sistema operativo utilizzando la "pipe" (carattere "|"); ovvero:- Cerca (grep) il testo (-F) "spazio319spazio" (in linea di massima rimarranno solo i messaggi del server che appartengono al codice "319", cioè i "WHOIS") all'interno del file "$HOME/.xchat2/buduscript/irc.budus.net.log"
- quindi l'output filtralo (grep) lasciando solo le righe che contengono il testo (-F) "spaziopippospazio:"
- quindi filtra ulteriormente (grep) lasciando le righe che contengono il testo (-F) "#buduscriptspazio"
- tieni solo l'ultima riga (tail -n1)
- e di quest'ultima togli tutto quello che viene prima di "spazio:" (sed 's@.* :@@').
- Mette il risultato ottenuto nella variabile "$output" e verifica se: '$output' diverso da ''
- Se la condizione è vera esegue il comando:
Codice: Seleziona tutto
/budus set buduscript_bot_badchannel_joined_list $output
il cui significato è: metti il risultato ottenuto dal comando descritto sopra (che ora è contenuto in "$output") nella variabile "buduscript_bot_badchannel_joined_list"
Codice: Seleziona tutto
/budus InsertCommandInQueue() /budus cmd /budus pipe_script for chan_join in $(cat "$HOME/$mxchat_path/buduscript/badchannel.txt") ; do find_channel=$(echo \($buduscript_bot_badchannel_joined_list\) | grep -F "${chan_join} ") ; if test "${find_channel}" != "" ; then echo \(/budus sendsess $server/$channel /budus ban + *!*@$domain init( $buduscript_bot_badchannel_ban_time,3600 ) $ru\); echo "/budus sendsess $server/$channel /KICK $ru Non sono graditi gli utenti di ${chan_join}"; fi; done
Sì, mi rendo conto che anche questo non è banale
Ma, scomponendolo, non è neanche poi così terribile, anzi, proviamo a dividerlo su più righe (dopo aver risolto alcune cose), in modo che prenda un altro aspetto:
Codice: Seleziona tutto
/budus InsertCommandInQueue()
>/budus cmd
>>/budus pipe_script
>>>for chan_join in $(cat "$HOME/.xchat2/buduscript/badchannel.txt") ; do
>>>>find_channel=$(echo '$buduscript_bot_badchannel_joined_list' | grep -F "${chan_join} ") ;
>>>>if test "${find_channel}" != "" ; then
>>>>>echo '/budus sendsess $server/$channel /budus ban + *!*@$domain init( $buduscript_bot_badchannel_ban_time,3600 ) $ru';
>>>>>echo "/budus sendsess $server/$channel /KICK $ru Non sono graditi gli utenti di ${chan_join}";
>>>>fi;
>>>done
Bene, analizziamo una riga alla volta, dandole un significato:
- Inserisci il comando nella coda dei comandi
Codice: Seleziona tutto
/budus InsertCommandInQueue() - Esegui un comando risolvendo variabili utente, funzioni avanzate, ecc... :
Codice: Seleziona tutto
/budus cmd - Esegui un comando del sistema operativo, catturane l'output ed utilizzalo come fosse un qualcosa che scrive l'utente:
Codice: Seleziona tutto
/budus pipe_script - Esegui il seguente comando del sistema operativo (quindi, quelli che seguono, sono comandi BASH, non X-Chat):
Codice: Seleziona tutto
for chan_join in $(cat "$HOME/.xchat2/buduscript/badchannel.txt") ; do
che significa: ogni riga contenuta nel file "$HOME/.xchat2/buduscript/badchannel.txt" (il comando cat serve per stampare il contenuto del file specificato) mettila nella variabile "${chan_join}" ed esegui quello che viene dopo, fino al "done". - Cerca, nella lista contenente i canali che l'utente è presente (la variabile "$buduscript_bot_badchannel_joined_list'" viene risolta prima che il comando venga eseguito), se è presente il testo (grep -F) "#nomecanalespazio", dove "#nomecanale" è il valore della variabile "${chan_join}" che viene ciclicamente (for) cambiato, e vallo a mettere nella variabile "${find_channel}".
Codice: Seleziona tutto
find_channel=$(echo '$buduscript_bot_badchannel_joined_list' | grep -F "${chan_join} ") ; - Se la variabile "${find_channel}" non risulta vuota, allora ...
Codice: Seleziona tutto
if test "${find_channel}" != "" ; then - Stampa (echo) quello che poi verrà interpretato come un comando dello script:
Codice: Seleziona tutto
echo '/budus sendsess $server/$channel /budus ban + *!*@$domain init( $buduscript_bot_badchannel_ban_time,3600 ) $ru';N.B.: Il comando che viene eseguito non è banalissimo, vale la pena fare alcune considerazioni:- Il comando che viene eseguito per primo è "/budus sendsess $server/$channel " e serve per eseguire il comando successivo in una sessione ben determinata.
- Il comando "/budus ban" serve per eseguire il BAN di un utente sfruttandone alcuni dati; nel nostro caso il BAN utilizzerà il dominio ("*!*@$domain").
- Se la variabile "$buduscript_bot_badchannel_ban_time" non è stata creata/inizializzata precedentemente, tramite la funzione avanzata "init( nomevariabile,valore) la si crea e inizializza al valore "3600". Questo valore determina "quando il BAN dovrà essere tolto". E' possibile personalizzare questo valore inizializzando (in "botconnect.mcr") la variabile, ad esempio:
Codice: Seleziona tutto
/budus set buduscript_bot_badchannel_ban_time 1800
ridurrebbe a 30min il BAN. - La variabile "$ru" contiene il nickname dell'utente da bannare.
- Stampa (echo) quello che poi verrà interpretato come un comando dello script:
Codice: Seleziona tutto
echo "/budus sendsess $server/$channel /KICK $ru Non sono graditi gli utenti di ${chan_join}";
visto quanto scritto sopra, direi che qui dovrebbe essere abbastanza chiaro cosa avviene; in sintesi: avviene il KICK dell'utente.
Ho cercato di risolvere il problema senza ricorrere ad un file script (.sh) esterno, ma solo con l'uso di sentinelle e, laddove non era possibile diversamente, qualche comando del sistema operativo.
In pratica, affinché il sistema funzioni, sarà necessario elencare nel file "badchannel.txt" i canali che si intende "bannare"; quando un utente effettua il join, viene verificato in quali canali è presente e controllato se uno di questi combacia con quelli "bannati".
E' chiaro che, se un utente entra prima nel nostro canale e poi in uno di quelli "proibiti", il sistema non funziona.
Se proprio non gestite canali particolarmente affollati, forse è affrontabile un "controllo periodico" che, ad esempio, operi sugli utenti che non hanno nessuna modalità. Per fare questo è sufficiente ricorrere ad una "funzione avanzata" come la "exec( filter,command )" (vedere: "/budus help function") che viene periodicamente invocata (vedere: "/HELP TIMER").