Contenido generado con IA — puede contener errores.

Módulo de chat

El filtro

chat/filter/: los interruptores generados, las reglas de palabras y cómo se compilan, la lista blanca y cómo los puntos se vuelven castigos.

El filtro son cinco archivos en chat/filter/. Uno se genera y guarda interruptores; los otros cuatro se escriben a mano y guardan el contenido.

ArchivoContiene
config.ymlTodos los interruptores y umbrales. Se escribe en el primer arranque con los valores de abajo
rules.ymlLas listas de palabras y los patrones escritos a mano, con los puntos que cuesta cada uno
leet.ymlQué puede hacer las veces de cada letra
whitelist.ymlLo que el filtro no debe tocar
punishments.ymlQué pasa a cuántos puntos

Todo lo que leen las comprobaciones es una instantánea inmutable, cambiada entera con /cca chat reload, así que un mensaje en vuelo en el hilo del chat nunca ve medio juego de reglas.

config.yml

SecciónClaves y valores por defecto
similarityenabled true, threshold 0.9 (0–1, Jaro-Winkler), cache-seconds 8.0
floodenabled true, max-length 120, max-repeated 5, alert-staff true
capsenabled true, max-caps 8, lowercase true
cooldownenabled true, seconds 1.5
ip url domain phoneenabled true, replace-with *, cancel true, alert-staff true, points 5
unicodelo mismo, pero enabled false
rulesenabled true, replace-with *, cancel true, alert-staff true
punishmentsenabled true, reset true, reset-after-minutes 60

Algunas merecen una frase.

  • similarity compara un mensaje con el anterior del mismo emisor y rechaza la repetición. El mensaje anterior solo se recuerda durante cache-seconds, así que decir lo mismo diez minutos después está bien. /cca chat similar <a> <b> imprime la puntuación de dos líneas, que es como ajustar threshold sin adivinar.
  • caps con lowercase: true reescribe el mensaje en vez de bloquearlo — todo en minúsculas salvo el primer carácter, una frase y no un susurro.
  • cooldown se cobra al final del pipeline, así que solo un mensaje que salió de verdad arranca la espera. Un mensaje que el filtro bloqueó no le cuesta al jugador su siguiente segundo y medio.
  • unicode viene apagado: los acentos y los símbolos son chat normal, y encenderlo sin rellenar whitelist.yml → unicodes bloquea el idioma de un servidor hispanohablante.
  • cancel: false en cualquier comprobación envía el mensaje con la coincidencia enmascarada por replace-with en lugar de bloquearlo. replace-with se repite hasta la longitud de la coincidencia, así que nunca mueve las posiciones de nada más; un replace-with vacío la borra.

Las cinco comprobaciones de patrón corren en un orden fijo — ip, url, domain, phone, unicode — para que una URL se encuentre antes de que lo haría su dominio, y cada una aporta sus propios points.

rules.yml

plugins/ExyliaChatCosmetics/chat/filter/rules.yml
rules:
  swearing-en:
    points: 2
    words:
      - fuck*
      - shit*
      - bitch
 
advanced:
  hate-symbols:
    points: 15
    regexes:
      - "[卐卍]"

rules.<nombre> toma palabras normales; advanced.<nombre> toma expresiones regulares escritas por alguien que sabe lo que hace. Las dos llevan points (por defecto 1) y las dos usan su nombre en la alerta al staff. Una regla que no lista nada se salta y se reporta, y una regex que no compila se reporta por su nombre en vez de tumbar el archivo entero.

Qué caza una palabra

Cada palabra se compila en un patrón que también caza las formas de esconderla:

  • escritura leet, desde leet.yml — f4ck, pµta
  • letras separadas — f.u.c.k, F U C K. Se permiten hasta cuatro caracteres que no sean letra ni dígito entre dos letras; acotado y no ilimitado, porque una carrera sin límite entre cada par de letras es lo que convierte una línea larga en un patrón que no termina nunca
  • letras repetidas — fuuuck

/cca chat regex <palabra> imprime exactamente en qué compila una palabra, que es además la forma de escribir un patrón advanced a mano: empieza por lo que produce el compilador y edítalo.

Dónde puede estar una palabra

Una palabra es una palabra entera por defecto, con una terminación común permitida.

EscritoCaza
putaputa, putas, putita, putazo — nunca dentro de disputa, reputación o computadora
puta*la palabra y todo lo que venga después
*putalo que venga antes, y luego la palabra
*puta*en cualquier sitio, que es la forma correcta solo para cadenas que nada inocente contiene

El español está lleno de palabras normales que llevan un insulto dentro, y un filtro que puntuaba todas ellas convertía la lista blanca en un segundo diccionario que nadie podía terminar. Las terminaciones que permite la forma por defecto son las productivas del español y el inglés — s, es, ita, azo, on, ing, er y compañía. Una terminación que se come la última vocal de la raíz, culito por culo, no se alcanza así y se lista como palabra propia.

Los acentos, y la ñ

Los acentos se pliegan antes de que una regla lea la línea, en los dos lados: maricon y maricón son una palabra y una regla. El plegado es un carácter dentro, un carácter fuera, porque el escaneo corre sobre la copia plegada y el enmascarado cae sobre el texto real en las posiciones que encontró el escaneo.

La ñ no se pliega, a propósito. Es una letra propia, no una n con acento, y plegarla convertiría año en una palabra que nadie escribió. Eso sí, hace de n en el mapa leet, así que coño también se caza escrito cono — que es justo por lo que el cono de helado y el geométrico están de vuelta en whitelist.yml.

Qué cubre el archivo que viene

Inglés y español, por niveles:

NivelPuntos
Palabrota corriente, swearing-en y swearing-es2
Insulto dirigido a alguien, insults-en, insults-es, abbreviations4
Insultos de odio, slurs12
Símbolos de odio, hate-symbols (una regla advanced)15

El español es regional, y el archivo lo dice a propósito. Las palabras que solo suenan a insulto en algún sitio están deliberadamente ausentes: wey y güey en México, weon, weón, wn y weá en Chile, marica usado como "colega" en Colombia, coger y concha donde son palabras corrientes, po, chaval y tío. Lo que es regional e insultante se diga donde se diga sí está — conchetumadre, culiao, hijueputa, ctm, qliao y el resto.

Ajústalo a tus jugadores, no al español

No hay una lista que sea correcta para todos los servidores. Una palabra que tus jugadores usan inocentemente va a whitelist.yml; una palabra que tu región sí trata como insulto va a rules.yml. El archivo que viene es el suelo, no la respuesta.

leet.yml

map:
  a: '@4^'
  e: '3€'
  s: '5$§'
  n: 'ñ'
  ñ: 'nñ'

map.<letra> lista qué puede hacer las veces de esa letra. La letra misma, en sus dos cajas, siempre está incluida, así que una letra que el archivo no nombra sigue coincidiendo consigo misma y un archivo que falta sigue cazando la escritura normal.

whitelist.yml

ClaveContiene
wordsPalabras que están bien por sí solas aunque escondan dentro una palabra de regla
domainsTus propios dominios; un subdominio de uno listado también cuenta
urlsEnlaces que se pueden publicar tal cual
ipsDirecciones que se pueden publicar
unicodesLos símbolos permitidos cuando la comprobación unicode está encendida, escritos como cadenas de caracteres

El orden importa. Una palabra de la lista blanca se escuda antes de que las reglas lean la línea: cada carácter suyo se sustituye, solo para el escaneo, por un carácter que ninguna clase de regla contiene y que ningún jugador puede escribir. Así cocktail nunca dispara cock, y ninguna regla puede reconstruir una palabra a través del escudo. Lo que se envía es el texto original; el escudo nunca llega a un lector.

Las words se comparan con los acentos plegados, así que escribir reputación escuda la palabra como sea que la escriba un jugador.

unicodes se comprueba carácter a carácter y no como subcadena, así que el orden en que escribas los símbolos no cambia la respuesta.

Como las palabras de regla son palabras enteras por defecto, casi toda esta lista es una segunda red: es lo que evita que una palabra escrita con asterisco — fuck*, *puta* — se lleve por delante una palabra inocente.

punishments.yml

plugins/ExyliaChatCosmetics/chat/filter/punishments.yml
punishments:
  warn:
    points: 6
    message: '%prefix%{warning}Mind the chat rules.'
    commands: []
  mute:
    points: 15
    message: '%prefix%{error}You were muted for breaking the chat rules.'
    commands:
      - 'console: mute %player_name% 1h Chat rules'
  ban:
    points: 40
    message: ''
    commands:
      - 'console: tempban %player_name% 1d Chat rules'

points es el total que dispara la línea; un castigo con points en cero o menos se salta y se reporta. message se le envía al jugador y puede estar vacío. Los commands son líneas de comando de ExyliaLib: console: … se ejecuta desde la consola, una línea a secas se ejecuta como el jugador, y %player_name% es él. Un comando que no se puede compilar se reporta por su nombre y el resto del castigo sigue funcionando.

Con las reglas que vienen, tres palabrotas corrientes avisan, un insulto de odio silencia, y un jugador que sigue insistiendo acaba baneado. Los comandos dan por hecho que existen un mute y un tempban en tu servidor; cámbialos por los que use tu plugin de castigos.

Cómo funcionan los puntos

Un mensaje los gana

Cada comprobación que salta suma sus puntos al mensaje: los points de cada comprobación de patrón y los de cada regla que coincidió. Un mensaje que dispara varias reglas paga por todas.

Se anotan salga o no salga el mensaje

Un mensaje bloqueado sigue costando sus puntos. Por eso el contable es un procesador propio en la etapa FORMAT y además se invoca a mano para los mensajes que el pipeline detuvo: un insulto de odio bloqueado cuenta igual.

Se desvanecen

Con punishments.reset encendido, un jugador que lleva reset-after-minutes callado vuelve a empezar desde cero. Su total guardado no se borra; simplemente deja de contar.

Se aplica la línea que cruzó

El castigo más alto que esté igual o por debajo del nuevo total y que estuviera por encima del anterior. Un mensaje que lleva a un jugador de 4 a 20 aplica el castigo de 15 puntos una vez, no también el de 6.

ChatInfractionEvent se lanza antes de que nada de eso se escriba, y un listener que lo cancele deja el mensaje filtrado pero los puntos sin anotar. Ver API.

/cca chat points <jugador> lee el total de un jugador; /cca chat points <jugador> <número> lo reescribe, que es la forma de perdonar a alguien sin editar la base de datos.

Qué lee el staff

NodoLee
exyliachatcosmetics.chat.staff.alertsCada salto: quién, cuántos puntos, qué reglas y el mensaje tal como se escribió
exyliachatcosmetics.chat.staff.filteredTambién los mensajes bloqueados, enteros, marcados con filtered-marker de chat/config.yml (por defecto {error}✖ )

El alert-staff de una comprobación decide si esa comprobación levanta alerta siquiera. Los saltos de flood y de longitud alertan con cero puntos, porque no cuestan ninguno.

La línea de la alerta es staff.alert en chat/messages.yml, con %player%, %points%, %rules% y %message%.

Relacionado

Los nodos de excepción — bypass.cooldown, .similarity, .flood, .caps, .filter — están en Permisos, y las herramientas /cca chat en Comandos.

¿Falta algo en esta página? Dínoslo en Discord