#include <amxmodx>
#include <amxmisc>
#include <regex>
#include <sockets>

#define TASK2 33
#define PUNISH_DELAY 0.5

#define PLUGIN "AntiCommerce"
#define VERSION "1.2a"
#define AUTHOR "R3X"
#define MAX_EXC 15
#define LOGDIR "advert"

#define NEWNAME "Player"

new sip[22];			//server IP
new g_logit;			//cvar pointer:ac_log
new g_punish;			//cvar pointer:ac_punish
new g_bantime;			//cvar pointer:ac_bantime
new g_first;			//cvar pointer:ac_firstadvert
new g_Exceptions[MAX_EXC][50];	//array of exceptions
new g_eid=0; 			//counter of exceptions
new g_pn, g_ps, g_cn,g_bip; 	//cvar pointers
new g_pattern_chars;		//cvar pointer
new g_pattern_maxnum;		//cvar pointer
new g_search, g_search_value=3;	//cvar pointer:ac_what2search and buffer with value
new logFile[50];		//current logfile
new bool:g_firstCheck[33];	//if 1st round?
new bool:g_firstAdvert[33];	//if 1st advert?

public plugin_init() 
{
	register_plugin(PLUGIN, VERSION, AUTHOR);
	register_clcmd("say","checkThis"); 
	register_clcmd("say_team","checkThis"); 
	register_srvcmd("register_exception","registerException");
	register_concmd("showexc","showExceptions",ADMIN_KICK,"Show Exceptions");
	register_event("HLTV", "Nowa_Runda", "a", "1=0", "2=0")	
	register_dictionary("anticommerce.txt"); 
	g_logit=register_cvar("ac_log","1");
	g_punish=register_cvar("ac_punish","0");
	g_bantime=register_cvar("ac_bantime","1");
	g_pn=register_cvar("ac_punishbyname","1");
	g_cn=register_cvar("ac_changename","1");
	g_ps=register_cvar("ac_punishbysay","1");
	g_bip=register_cvar("ac_banip","0");
	g_search=register_cvar("ac_what2search","3");
	g_first=register_cvar("ac_firstadvert","1");
	g_pattern_chars=register_cvar("ac_ips_chars","[NALPHANUM]");
	g_pattern_maxnum=register_cvar("ac_max_chars","3");
	new m,d,y;
	date(y, m, d);
	new path[50];
	get_basedir (path, 49); 
	formatex(logFile,49,"%s/logs/%s/advert@%d-%d-%d.log",path,LOGDIR,d,m,y);
	if(!dir_exists(LOGDIR))
	{
		mkdir(LOGDIR);
	}
	get_user_ip (0, sip, 21, 1);
	for(new i=0;i<33;i++)
	{
		g_firstCheck[i]=true;
		g_firstAdvert[i]=true;
	}
}
public Nowa_Runda(id)
{
	new args[1];
	args[0]=id;
	new newname[128];
	get_user_name(id, newname,31);
	if(is_invalid(id,newname,2))
	{
		if(get_pcvar_num(g_cn)!=0 && get_pcvar_num(g_punish)==0)
		{
			server_cmd("amx_nick #%d ^"%s^"", get_user_userid(id), NEWNAME);
		}
		set_hudmessage(255, 0, 0, 0.0, 0.5, 1, 6.0, 4.0);
		show_hudmessage(id, "%L",LANG_PLAYER,"WARN3");
	}
	set_task(5.0, "firstChecked", id);
	set_task(10.0, "showWarning", TASK2+id);
	return PLUGIN_CONTINUE;	
}
public client_putinserver(id)
{
	new args[1];
	args[0]=id;
	new newname[128];
	get_user_name(id, newname,31);
	if(is_invalid(id,newname,2))
	{
		if(get_pcvar_num(g_cn)!=0 && get_pcvar_num(g_punish)==0)
		{
			server_cmd("amx_nick #%d ^"%s^"", get_user_userid(id), NEWNAME);
		}
		set_hudmessage(255, 0, 0, 0.0, 0.5, 1, 6.0, 4.0);
		show_hudmessage(id, "%L",LANG_PLAYER,"WARN3");
	}
	set_task(5.0, "firstChecked", id);
	set_task(10.0, "showWarning", TASK2+id);
	return PLUGIN_CONTINUE;	
}
public firstChecked(id)
{
	g_firstCheck[id]=false;
}
//check if contain WWW address
checkThis4www(id, teXt[128])
{
	if(g_search_value < 2)
		return false;
	new teXt_backup[128];
	copy(teXt_backup, 127, teXt);
	new error[50], hostname[50], error2; //errors or sth
	new ret; //return of regex_match
	new Regex:regex; //regex handle
	new bool:found = false; //found advert?
	new bool:suspect = false;//suspected match
	new sock; //sockets handle
	do
	{
		regex = regex_match (teXt, "([A-Za-z][A-Za-z0-9\-]+(\.|\-*\.))+[A-Za-z]{2,6}", ret, error, 49);
		if(regex!=REGEX_OK) break;
		regex_substr(regex, 0, hostname, 49 );
		if(ret > 0)
		{
			suspect=true;
			sock=socket_open (hostname, 80, SOCKET_TCP, error2);
			new buff[14];
			if(error2 == 0)
			{
				socket_send(sock, "GET: / HTTP/1.1^r^n", 50);
				socket_send(sock, "Host: host.com ^r^n^r^n", 50);
				socket_recv(sock, buff, 13); 
				found=(contain(buff,"HTTP/1.0 501")==0)?false:true;
			}
			socket_close(sock);
			regex_free(regex);
			replace_all(teXt, 255, hostname, "");
			if(found) break;
		}
	}
	while(ret > 0);
	if(!found && suspect)
	{
		logSth(3,id, teXt_backup);
	}
	return found;
}
prepareChars(chars[31])
{
	new chars2[61];
	remove_quotes(chars);
	if(equali(chars,"[NALPHANUM]"))
	{
		copy(chars2,30,"^^0-9A-Za-z");
	}
	else
	{
	
		copy(chars2,60,chars);
		replace_all(chars2,60,"\","\\\");
		replace_all(chars2,60,"^^","/^^");
		replace_all(chars2,60,"[q]","\^"");
	}
	return chars2;
	
}
//check if contain server`s IP
checkThis4server(teXt[128])
{
	if((g_search_value == 0)||(g_search_value == 2))
		return false;
	new chars[31];
	get_pcvar_string(g_pattern_chars,chars,30);
	new pattern[140], error[50], ret=0;
	new maxnum=get_pcvar_num(g_pattern_maxnum);
	if(maxnum<0)
		maxnum=0;
	new count[11];
	if(maxnum==0)
		copy(count,10,"{1,}");
	else
		format(count,10,"{1,%d}",maxnum);
	format(pattern,139,"(1?\d{1,2}|2([0-4]\d|5[0-5]))([%s]%s(1?\d{1,2}|2([0-4]\d|5[0-5]))){3}", prepareChars(chars),count);
	new Regex:regex=regex_match(teXt, pattern, ret, error, 49 );
	if(ret>0)
	{
		regex_free(regex);
	}
	return ret;
}
//give punishment
public punish(args[])
{
	new id=args[0];
	new type=args[1];
	new type_message[16];	
	new name[36];
	get_user_name(id,name,35);
	switch(type)
	{
		case 1:
			type_message="(www)";
		case 2:
			type_message="(server)";
		default:
			type_message="";
	}
	new uid=get_user_userid(id);
	new punishment=get_pcvar_num(g_punish);
	if(get_pcvar_num(g_first)==1 && g_firstAdvert[id])
	{
		punishment=0;
		g_firstAdvert[id]=false;
		
	}
	switch(punishment)
	{
		case 0:
		{
			//only warning
			client_print(id,print_chat,"[AC]%L",LANG_PLAYER,"WARN1");
		}
		case 1:
		{
			//kick
			server_cmd("kick #%d %L",uid, id, "WORD_ADVERT");
		}
		case 2:
		{
			//ban 1min
			new bantime=get_pcvar_num(g_bantime);
			console_print(id,"------------------------");
			console_print(id, "%L:%L",id,"WORD_REASON", id, "WORD_ADVERT")
			console_print(id,"%L",id,"INFO1",bantime);
			new bool:banip=get_pcvar_num(g_bip)==1;
			if(is_plugin_loaded("AMXBans")>=0)
			{
				if(banip)
					server_cmd("amx_banip %d #%d %L",bantime, uid, id,"WORD_ADVERT"); 
				else 
					server_cmd("amx_ban %d #%d %L", bantime,uid, id,"WORD_ADVERT");
			}
			else
			{
				if(banip)
					server_cmd("amx_banip #%d %d %L",uid, bantime, id,"WORD_ADVERT"); 
				else
					server_cmd("amx_ban #%d %d %L",uid, bantime, id,"WORD_ADVERT");
			}
		
		}
		
	}
	if(punishment)
	{
		set_hudmessage(255, 0, 0, 0.01, 0.50, 1, 6.0, 2.0);
		show_hudmessage(id, "%s %L %s.",name,LANG_SERVER,"INFO2", type_message);
	}
	
}
//preparing text string to check
clean(text[128])
{
	 
	replace_all(text,127,sip,"");
	for(new i=0;i<g_eid;i++)
	{
		replace_all(text,127,g_Exceptions[i],"");
	}
	return text;
}
//validation of text
bool:is_invalid(id,text[],mode)
{
	g_search_value = get_pcvar_num(g_search);
	new www,server;
	new text_buf[128];
	copy(text_buf, 127, text);
	text_buf=clean(text_buf);
	if((www=checkThis4www(id, text_buf))||(server=checkThis4server(text_buf)))
	{
		new type=0;
		if(www>0)
			type=1;
		else if(server>0)
			type=2;
		logSth(mode, id, text);
		if(get_pcvar_num(g_punish)>0)
		{
			console_print(id,"----AntiCommerce----");
			console_print(id,">> %s",text);
		}
		new args[2];
		args[0]=id;
		args[1]=type;
		set_task((get_pcvar_num(g_punish)>0)?PUNISH_DELAY:0.1, "punish",0 ,args, 2);
		return true;
	}
	return false;
}
//add to logfile
logSth(mode, id, text[])
{
	new name[36], authid[35];
	authid=getID(id);
	get_user_name(id, name,35);
	new log=get_pcvar_num(g_logit);
	if(log==1)
	{
		switch(mode)
		{
			case 1:
				log_to_file(logFile,"%s(%s) put into chat: %s",name,authid,text);
			case 2:
				log_to_file(logFile,"Found name: %s(%s)",text,authid);
			case 3:
				log_to_file(logFile,"Suspected match: %s(author:%s)",text,authid);
		}
	}
}
//return authid or ip
getID(id)
{
	new info[35];
	if(get_pcvar_num(g_bip)==0)
		get_user_authid (id, info, 34);
	else
		get_user_ip(id, info, 34, 1); 
	return info;
}
public showWarning(id)
{	
	id-=TASK2;
	if(is_user_connected(id))
		client_print(id,print_chat,"*[AC] %L", LANG_PLAYER,"INFO_GLOB");
}
//check say or say_team message
public checkThis(id)
{
	if(is_user_admin(id) || get_pcvar_num(g_ps)==0)
		return PLUGIN_CONTINUE;
	new text[128];
	read_args(text,127);
	if(is_invalid(id,text,1))
		return PLUGIN_HANDLED;
	return PLUGIN_CONTINUE;
}
//@register_exception
public registerException()
{
	if(g_eid>=MAX_EXC)
	{
		console_print(0,"%L",LANG_SERVER,"WARN2");
		return;
	}
	new except[50];
	read_args(except,49);
	remove_quotes(except);
	g_Exceptions[g_eid]=except;
	++g_eid;
}
//@showexc
public showExceptions(id, lvl, cid)
{
	if (!cmd_access(id,lvl,cid,0))
		return PLUGIN_HANDLED 
	console_print(id,"--- %L ---.",LANG_PLAYER,"WORD_EXCEPT");	
	if(g_eid==0)
	{
		console_print(id,"%L",LANG_PLAYER,"INFO3");	
	}
	for(new i=0;i<g_eid;i++)
	{
		console_print(id," >> %d: %s",i+1,g_Exceptions[i]);
	}
	return PLUGIN_HANDLED;
}
public client_disconnect(id)
{
	g_firstCheck[id]=true;
}
//called when set name
public client_infochanged(id)
{
	if(is_user_admin(id) || get_pcvar_num(g_pn)==0 || !is_user_connected(id) || (g_firstCheck[id] && get_pcvar_num(g_punish)==0))
		return PLUGIN_CONTINUE;
	new newname[128];
	get_user_info(id, "name", newname,31);
	if(is_invalid(id,newname,2))
	{
		if(get_pcvar_num(g_cn)!=0 && get_pcvar_num(g_punish)==0)
		{
			server_cmd("amx_nick #%d ^"%s^"", get_user_userid(id), NEWNAME);
		}
		set_hudmessage(255, 0, 0, 0.0, 0.5, 1, 6.0, 4.0);
		show_hudmessage(id, "%L",LANG_PLAYER,"WARN3");
	}
	return PLUGIN_CONTINUE;	
}
