sorcio / python-italia-telegram-bot

0 stars 0 forks source link

[feature] Protezione da flood #7

Open sorcio opened 5 years ago

sorcio commented 5 years ago

Un'altra funzionalità ritenuta fondamentale è una protezione da flood.

Per flood credo che si intenda principalmente quello malevolo: un invio massivo di messaggi sul gruppo da parte di un utente (o più utenti organizzati), generalmente al fine di interrompere e rendere impossibile la normale conversazione. Questo è il caso prioritario.

Un'altra causa di flood può essere un utente con un client mal configurato che accidentalmente invia un numero eccessivo di messaggi, o un bot difettoso. In questo caso lo considero flood non malevolo, ed è più raro che capiti, ma probabilmente la stessa protezione che funziona per quello malevolo è efficace anche in casi accidentali.

Non considero flood un volume di scambio messaggi elevato durante la normale conversazione, anche se dati i limiti intrinseci della comunicazione su un solo canale la comunicazione può risultare disturbata. Credo che quel tipo di situazione, per quanto crei disagio, tenda ad auto-moderarsi. Può essere interessante (ma non prioritario) però applicare restrizioni temporanee anche in quel caso, ad esempio rimuovendo le preview dei link o impedendo l'invio di immagini e testo estremamente lungo.

Cosa significa invio massivo di messaggi? In generale, tutto ciò che: causa un eccessivo numero di notifiche, specialmente indesiderate; abusa dello "spazio verticale" della chat.

In generale si potrebbe immaginare di avere a disposizione un budget di "notifiche" (inteso come numero di messaggi, ma anche mention) e "spazio verticale" e volerlo distribuire equamente alle persone onestamente interessate alla conversazione. Se queste persone sono deprivate di questo budget allora si verifica una condizione che richiede intervento.

Non sono sicuro che esista una misura esatta di quanto si stia verificando una violazione, e in particolar modo è difficile distinguere chi siano le persone "onestamente interessati alla conversazione".

Approccio semplice: invio veloce da singolo utente

La via più semplice è misurare il tasso di invio di messaggi da parte di ogni utente. Il bot può mantenere per ogni utente una misura del tasso di invio, e intervenire quando questa misura eccede un qualche limite.

Anche in questo caso semplice ci sono alcune complicazioni: ad esempio due messaggi inviati nel giro di mezzo secondo equivalgono a un tasso di quattro messaggi al secondo, che sicuramente eccede una qualunque soglia stabilita. Ma due messaggi da soli (ignorando in questo momento la lunghezza) non rappresentano un problema. Ho visto due soluzioni e sperimentato con una di queste:

In aggiunta si può avere un contatore separato per le notifiche (singoli messaggi + menzioni).

Livello due: considerare la lunghezza del messaggio

Il limite dell'approccio sopra diventa evidente quando, durante un attacco malevolo, i messaggi di flood inviati sono pochi ma assomigliano a `"x\nx\nx\n...x\nx". Molti client Telegram non fanno folding automatico dei messaggi, e un singolo messaggio di molte righe può essere molto distruttivo.

Non so se Telegram sia in grado di darci una misura dello spazio verticale occupato da un messaggio. Possiamo stimarlo sulla base di numero di caratteri e del numero di andate a capo. Inoltre si può aggiungere una penalità di base per ogni singolo messaggio (dato che su molti client Telegram l'intestazione prende molto spazio) e per l'invio di sticker, allegati, immagini e preview di link.

Se si usa lo stimatore di frequenza di cui sopra, è relativamente semplice estenderlo in modo da pesare ogni evento con la sua lunghezza. Va usata cautela per non porre restrizioni alle persone che volevano semplicemente inviare un singolo messaggio lungo.

Livello tre: molteplici utenti

Il problema a misurare un flood da parte di molti utenti nello stesso momento è che diventa impossibile distinguere gli utenti malevoli dalle persone che stavano semplicemente prendendo parte ad una conversazione.

Gli approcci menzionati sopra si possono applicare al gruppo intero, e si possono applicare delle soglie collettive più alte. Ma serve una strategia per individuare gli utenti che sono all'origine del disturbo, oppure si rischia di applicare misure di restrizione che possono essere percepite come ingiuste o punitive nei confronti di persone non collegate con l'incidente.

Forse il problema è meno grave se si sospende temporaneamente l'attività sul canale per gli utenti che partecipavano al momento dell'incidente, e si lascia agl* admin la possibilità di decidere caso per caso.

Un'altra possibilità è che il bot costruisca dei bias positivi nei confronti di utenti che in passato hanno partecipato alla vita del gruppo senza incidenti. È ragionevolmente meno probabile che questi utenti attivamente creino una condizione di flood.

Livello quattro: fairness

In questo momento non so elaborare modelli più sofisticati, ma mi piace immaginare che possa esistere un modo per immaginare una distribuzione equa (fair) dello spazio di attenzione tra utenti diversi. Ad esempio potrebbe essere più interessante misurare il tempo tra un messaggio e quello successivo, e garantire che ci sia sempre un tempo tale che una persona partecipante (non malevola) possa introdursi nella discussione ed essere vista. Non so come questo genere di modello possa risolvere i problemi sollevati al "livello tre".


Ho perso di vista qualche aspetto? Qualche soluzione più banale? C'è qualche idea in più? Suggerimenti per l'implementazione?

nocturn9x commented 5 years ago

Credo che la soluzione che possa essere effettivamente utile per quanto riguarda la distinzione degli utenti malevoli da quelli non malevoli sia semplicemente istanziare un Thread object per ognuno di loro. Chiaro poi che la cosa diventa assai complicata quando ci sono 200 utenti in un gruppo ed istanziare 200 Thread (anche se venissero istanziati, ad esempio, solo quando un utente è online) sarebbe impensabile

Kavuti commented 5 years ago

Mi sembra ottima tutta l'analisi. Per quanto riguarda il flood distribuito su più utenti, lo ridurrei al caso base in cui un'utente non può inviare più di un certo numero di messaggi in un determinato arco di tempo. Penso che per evitare intasamenti, il gruppo potrebbe essere silenziato in caso di flood in arrivo da un numero di utenti estremamente alto, ovvero:

Kavuti commented 5 years ago

Credo che la soluzione che possa essere effettivamente utile per quanto riguarda la distinzione degli utenti malevoli da quelli non malevoli sia semplicemente istanziare un Thread object per ognuno di loro. Chiaro poi che la cosa diventa assai complicata quando ci sono 200 utenti in un gruppo ed istanziare 200 Thread (anche se venissero istanziati, ad esempio, solo quando un utente è online) sarebbe impensabile

Cerchiamo di non scendere troppo a livello tecnico in questa fase. Per il momento dobbiamo definire il "cosa" fare, poi penseremo al "come"

iflare3g commented 5 years ago

Al momento sia su @django che @python l'implementazione relativa alla cancellazione in automatico di messaggi da uno stesso utente in un lasso di tempo brevissimo, sembra funzionare Anche perchè è capitato che un utente floodasse messaggi e sono arrivati in bulk , il bot è riuscito subito a eliminarli quindi concordo al momento con la soluzione più semplice