Best way to filter spam on chat

Discussion in 'BungeeCord Plugin Development' started by Esmorall, Jul 11, 2019 at 10:42 PM.

  1. Hi, I used to use ChatControl a long time ago and it worked relatively well. But since a year ago I am learning java and I am making a Plugin to protect the server against spam. I want it to work only in BungeeCord.

    This is what I have done so far:
    • Block messages that are the same (ignoring capital letters)
    • Block similar messages using Levenshtein Distance
    • Limit the time between messages to 2 seconds
    However there are still spammers who have bypassed my methods: (waiting more than 2 seconds between messages and writing different messages)

    [​IMG]

    ¿What could i do? ¿what can I add to improve my plugin? I would not like the system to be rough to normal players
     
  2. Make this more harsh. My other suggestion is just to have active mods which can just mute the players.
     
  3. Code (Text):

    public class yourClass implements Listener{

    ArrayList<String> blacklistedWords;

    public yourClass(){
    blacklistedWords = new ArrayList<String>();
    blacklistedWords.add(/*add as words as you want*/);
    }

    @EventHandler
    public void onChat(ChatEvent event){
           ProxiedPlayer player = event.getPlayer(); // Do not remember if it was getPlayer or getProxiedPlayer.
           String message = event.getMessage();
           if(blacklistedWords.contains(message.toLowerCase()){
               // do stuff
           }
    }

    }
     
    That's what you needed?
     
  4. Or, you could map the message, prevent repetition of the message held in the map, remove the message from the map after X amount of time.
    If the message is repeated, update the time until the mapped message expires.
     
    • Agree Agree x 1
  5. Actually it's pretty simple, you should make an ArrayList<UUID>

    and on the ChatEvent:
    Code (Java):
    if (the array list doesn't contain player's uuid) {
        add the player in the arraylist
        new BukkitRunnable() {
            @Override
            public void run() {
              remove the player from the arraylist
              }
        }.runTaskLater(Instance of main, the delay between messages)
    }
    Edit: And when is sending a message, you should check if is in the arraylist, if yes, you cancel the event
    Edit 2: now i saw that is on BungeeCord, the BukkitRunnable doesn't exist. You should find other method to make a task
     
    #5 MrDarkness462, Jul 12, 2019 at 2:39 PM
    Last edited: Jul 12, 2019 at 2:45 PM
  6. Instead of using BukkitRunnable, you should use #BungeeScheduler and do this...
    Code (Java):

    public class Bungee extends Plugin{

        public static Bungee instance;
        public Map<UUID, Integer> uuids = new HashMap();
       
        public void onEnable() {
            instance = this;
           
            getProxy().getPluginManager().registerListener(this, new chatEvent());
        }
       
    }

    class chatEvent implements Listener {
       
        private Bungee b = Bungee.instance;
        private Map<UUID, Integer> uuids = Bungee.instance.uuids;
        @EventHandler
        public void chatCooldown(ChatEvent event) {
            ProxiedPlayer player = (ProxiedPlayer) event.getSender();
           
            if(Bungee.instance.uuids.containsKey(player.getUniqueId())) {
                event.setCancelled(true);
                player.sendMessage(new TextComponent(ChatColor.RED + "You are in chat cooldown, " + Bungee.instance.uuids.get(player.getUniqueId()) + " seconds left."));
            }else {
                uuids.put(player.getUniqueId(), 5);
                b.getProxy().getScheduler().schedule(b, () -> {
                    if(!uuids.containsKey(player.getUniqueId()))
                        return;
                    if(uuids.get(player.getUniqueId()) == 0) {
                        uuids.remove(player.getUniqueId());
                    }else {
                        uuids.replace(player.getUniqueId(), uuids.get(player.getUniqueId()) -1);
                    }
                },0, 1, TimeUnit.SECONDS);
            }
        }
       
    }
     
    I didn't test it out, you can try it, i think it will work.
     
  7. Code (Java):
    private Bungee b = Bungee.instance;
    Despite the fact, that it allows getting an instance of the main class in a very simple way, it is a very popular crutch. You should use

    Code (Java):
    private MainClass plugin;

    public YourClass(MainClass plugin) {
        this.plugin = plugin;
    }
    But you are allowed to do that, if you write API, as it is going to be the best way to work with it.
     
    #7 BestKvant, Jul 13, 2019 at 7:04 AM
    Last edited: Jul 13, 2019 at 7:09 AM