Zrips / CMI

111 stars 98 forks source link

Command /reply conflicts with anti spam from ChatControl #6460

Open Qveshn opened 2 years ago

Qveshn commented 2 years ago

Description of issue: Hi I have a problem. Players can not reply to private messages, because of anti spam mechanics from plugin ChatControl. Players have permission cmi.command.reply But the problem is ChatControl anti spam system does not allow too fast commands from player. Delay is 1 second. Therefore player gets message like "Please wait 1 second before your next command" when he executes /cmi reply ... or /reply ... or /r .... Looks like CMI sends another command on /cmi reply via dispatchCommand or chat etc., and ChatControl intercepts it and blocks next command. May be CMI sends command /cmi msg on command /cmi reply...

Is it possible to solve this problem?


Cmi Version: CMI: 9.1.0.2 BungeeCord SqLite CMILib: 1.1.0.2 Server Type: Spigot 1.17.1-R0.1-SNAPSHOT Server Version: 3284a-Spigot-3892929-0ab8487 (MC: 1.17.1) Relevant plugins: ChatControl Pro 8.11.0 https://github.com/kangarko/ChatControl-Pro

Qveshn commented 2 years ago

Yes! I tested and found out that the command /cmi reply is immediately followed by the command /cmi msg I added in ChatControl settings the command /cmi msg to its whitelist, and now it works. But this is not good solution

ATM I am thinking about a better solution to the problem. But I need a little time. I will try to write a test plugin that will run several commands on behalf of the player one after another and at the same time bypass the ChatControl anti spam protection. The idea is to reset last command time for the player in ChatControl before executing next command. I found the public class org.mineacademy.chatcontrol.SimplePlayerCache with static public method SimplePlayerCache getFor(Player player). We can reset the last time by something like

    SimplePlayerCache.getFor(player).lastCommandTime = 0;

The field lastCommandTime is also public; And ChatControl uses the same class to get last command time to compare it with current time. The code is like next:

    now = System.currentTimeMillis() / 1000L;
    delayInSeconds = now - SimplePlayerCache.getFor(player).lastCommandTime
    if (delayInSeconds < delayFromSettings){
       // Cancel command
       return;
    }
    SimplePlayerCache.getFor(player).lastCommandTime = now;

Therefore, I think, all will be ok if we reset the lastCommandTime before second command. And this mechanics can be also used in multi-commands sending (ex. custom command aliases)