// vi: set ts=4 sw=4 :
// vim: set ft=cpp :
// plugin_sank_antiflood.sma
// Author: Luke Sankey
// Date March 30, 2001
//
// Fuctions included in this plugin:
// It is a flooding filter so people don't say too much too fast.
// It determines that a user is flooding the server if they say
// approximately 3 things in less than 2 seconds.
//
// It was originally in my plugin_sank_sounds.sma file, but figured
// it would be better to make it its own plugin, so I broke it out.

// some modification by Will Day
// 2001/04/18

#include <core>
#include <console>
#include <string>
#include <admin>
#include <adminlib>
//#include <sound>

new STRING_VERSION[MAX_DATA_LENGTH] = "2.50.0";

// We still don't like spammers, so if they say things too fast, then kick them.
new SndFreq[MAX_PLAYERS][3];
#define	COUNT	0
#define	TIME	1
#define VIOLATIONS	2

#define SPAM_LIMIT	4	// number of messages accumulated that constitute a spam violation

#define GAG_AFTER	1	// gag after this many spam violations
#define KICK_AFTER	3	// kick after this many spam violations

#define GAG_TIME	3	// minutes for gag to last

/*****************************************************************************/
/*****************************************************************************/
/*****************************************************************************/


public plugin_init() 
{
	plugin_registerinfo("Sank Anti-Flood Plugin", "Auto kicks chat flooders", STRING_VERSION);
	
	plugin_registercmd("say", "HandleSay", ACCESS_ALL);
	plugin_registercmd("team_say", "HandleSay", ACCESS_ALL);

	return PLUGIN_CONTINUE;
}

reset_data(UserIndex) {
	if (UserIndex >= 1 && UserIndex <= MAX_PLAYERS) {
		SndFreq[UserIndex][COUNT] = 0;
		SndFreq[UserIndex][TIME] = 0;
		SndFreq[UserIndex][VIOLATIONS] = 0;
	}
}

public plugin_connect(HLUserName, HLIP, UserIndex) 
{
	reset_data(UserIndex);
	return PLUGIN_CONTINUE;
}

public plugin_disconnect(HLUserName, UserIndex) 
{
	reset_data(UserIndex);
	return PLUGIN_CONTINUE;
}


/*****************************************************************************/
/*****************************************************************************/
/*****************************************************************************/


///////////////////////////////////////////////////////////////////////////////
// Returns 0 if the user is allowed to say things
// Returns 1 and kicks the user if the user is saying things too fast.
///////////////////////////////////////////////////////////////////////////////
FreqCheck(User[], UserIndex)
{
	if(check_immunity(User) == 0)
	{
		new Now = systemtime();
		new Text[MAX_TEXT_LENGTH];
		new Cmd[MAX_TEXT_LENGTH];
		new Before = 0;
		new Count = 0;
		new Violations = 0;

		Before = SndFreq[UserIndex][TIME];		// Time of last chat messages
		Count = SndFreq[UserIndex][COUNT];		// Number of chat messages accumulated
		Violations = SndFreq[UserIndex][VIOLATIONS];	// Number of spam violations

		// If we're in the same or next second. (cstrike won't allow two chat messages in the same second).
		if (Now <= Before+1)
			Count += 1;
		else {
			Count -= (Now-Before-1);
		}
		if(Count < 0)
			Count = 0;

		if(getvar("admin_debug")!=0) {
			snprintf(Text, sizeof(Text), "spamcheck: user=%s, before=%i, now=%i, count=%i, violations=%i", 
					User, Before, Now, Count, Violations);
			log(Text);
		}
		if(Count >= SPAM_LIMIT) {
			if(Violations >= KICK_AFTER) {
				// It's even funnier if the clients have this sound loaded,
				// which you can get from the plugin_sank_sounds.sma plugin
				// and put on your server. It also requires the sound.inc file
				// Get them from www.adminmod.org/ascript on the plugins page.

				//playsoundall("misc\comeagain.wav");

				snprintf(Text, sizeof(Text), "You are being kicked for spamming.");
				messageex(User, Text, print_center);
				messageex(User, Text, print_console);
				snprintf(Cmd, MAX_TEXT_LENGTH, "kick %s", User);
				exec(Cmd);
				snprintf(Text, MAX_TEXT_LENGTH, "Kicked %s for spamming.", User);
				log(Text);
				Count = 0;
			}
			else if(Violations >= GAG_AFTER) {
				snprintf(Text, sizeof(Text), "You have been gagged (%im) for spamming.", GAG_TIME);
				messageex(User, Text, print_center);
				messageex(User, Text, print_console);
				snprintf(Cmd, MAX_TEXT_LENGTH, "admin_command admin_gag %s %i", User, GAG_TIME);
				exec(Cmd);
				snprintf(Text, MAX_TEXT_LENGTH, "Gagged %s for spamming.", User);
				log(Text);
				Count = 0;
			}
			else {
				snprintf(Text, sizeof(Text), "Do not chat-spam the server!");
				messageex(User, Text, print_center);
				messageex(User, Text, print_console);
				snprintf(Text, MAX_TEXT_LENGTH, "Warned %s for spamming.", User);
				log(Text);
				Count = 0;
			}
			Violations++;
		}

		SndFreq[UserIndex][COUNT] = Count;
		SndFreq[UserIndex][VIOLATIONS] = Violations;
		SndFreq[UserIndex][TIME] = Now;
	}

	return 0;
}


///////////////////////////////////////////////////////////////////////////////
// Everything a person says goes through here, and we determine if they are
// chatting too fast or not.
///////////////////////////////////////////////////////////////////////////////
public HandleSay(HLCommand, HLData, HLUserName, UserIndex) 
{
	new User[MAX_NAME_LENGTH];
	convert_string(HLUserName, User, MAX_NAME_LENGTH);

	// If they are talking too fast, have a key bound to say something, or
	// we just think they are flooding the chat then kick them.
	FreqCheck(User, UserIndex);
	return PLUGIN_CONTINUE;
}
