#include <sourcemod>
#include <steamworks>
#include <multicolors>
#include <RevEmuAPI>

#pragma newdecls required
#pragma	semicolon 1

/* INTEGERS */
int g_bStatus[MAXPLAYERS+1] = {0,...};

//----------------------------------------------------------------------------------------------------
// Purpose:
//----------------------------------------------------------------------------------------------------
public Plugin myinfo =
{
	name         = "VPN-Check",
	author       = "Neon",
	description  = "",
	version      = "1.0.0"
};

//----------------------------------------------------------------------------------------------------
// Purpose:
//----------------------------------------------------------------------------------------------------
public void OnPluginStart()
{
	RegAdminCmd("sm_vpn", Command_CheckVPN, ADMFLAG_RCON);
	for (int client = 1; client <= MaxClients; client++)
	{
		if (!IsValidClient(client) || IsClientSourceTV(client))
			continue;

		int iSerial = GetClientSerial(client);

		char sIP[32];
		GetClientIP(client, sIP, sizeof(sIP));

		char sRequest[256];
		FormatEx(sRequest, sizeof(sRequest), "http://proxy.mind-media.com/block/proxycheck.php?ip=%s", sIP);

		Handle hRequest = SteamWorks_CreateHTTPRequest(k_EHTTPMethodGET, sRequest);
		if (!hRequest ||
			!SteamWorks_SetHTTPCallbacks(hRequest, OnClientPostAdminCheck_OnTransferComplete) ||
			!SteamWorks_SetHTTPRequestContextValue(hRequest, iSerial) ||
			!SteamWorks_SendHTTPRequest(hRequest))
		{
			delete hRequest;
		}
	}
}

//----------------------------------------------------------------------------------------------------
// Purpose:
//----------------------------------------------------------------------------------------------------
public Action Command_CheckVPN(int client, int args)
{
	char sBuffer[4096];
	char sIP[32];
	char sSteamID[32];
	bool bFound = false;

	Format(sBuffer, sizeof(sBuffer), "VPN STATUS:\n");
	Format(sBuffer, sizeof(sBuffer), "%s#########################################\n", sBuffer);
	for (int i = 1; i <= MaxClients; i++)
	{
		if (!IsValidClient(i))
			continue;

		if (g_bStatus[i] == 0)
			continue;

		if (g_bStatus[i] == 1)
		{
			GetClientAuthId(i, AuthId_Steam2, sSteamID, sizeof(sSteamID));
			GetClientIP(i, sIP, sizeof(sIP));

			if(!RevEmu_IsPlayerSteam(i))
				Format(sBuffer, sizeof(sBuffer), "%s\"%L\"[NOSTEAM] is possibly using a VPN (%s).\n", sBuffer, i, sIP);
			else
				Format(sBuffer, sizeof(sBuffer), "%s\"%L\"[STEAM] is possibly using a VPN (%s).\n", sBuffer, i, sIP);

			bFound = true;
		}
		else if (g_bStatus[i] == 2)
		{
			Format(sBuffer, sizeof(sBuffer), "%s\"%L\" VPN-Check failed due to an API Error.\n", sBuffer, i);
			bFound = true;
		}
		else if (g_bStatus[i] == 3)
		{
			Format(sBuffer, sizeof(sBuffer), "%s\"%L\" VPN-Check failed due to an Request Error.\n", sBuffer, i);
			bFound = true;
		}
	}

	if (!bFound)
		Format(sBuffer, sizeof(sBuffer), "%sCould not find any possible VPNs\n", sBuffer);

	Format(sBuffer, sizeof(sBuffer), "%s#########################################", sBuffer);
	ReplyToCommand(client, sBuffer);
	return Plugin_Handled;
}

//----------------------------------------------------------------------------------------------------
// Purpose:
//----------------------------------------------------------------------------------------------------
public void OnClientConnected(int client)
{
	g_bStatus[client] = 0;
}

//----------------------------------------------------------------------------------------------------
// Purpose:
//----------------------------------------------------------------------------------------------------
public void OnClientDisconnect(int client)
{
	g_bStatus[client] = 0;
}
//----------------------------------------------------------------------------------------------------
// Purpose:
//----------------------------------------------------------------------------------------------------
public void OnClientPostAdminCheck(int client)
{
	if (!IsValidClient(client) || IsClientSourceTV(client))
		return;

	int iSerial = GetClientSerial(client);

	char sIP[32];
	GetClientIP(client, sIP, sizeof(sIP));

	char sRequest[256];
	FormatEx(sRequest, sizeof(sRequest), "http://proxy.mind-media.com/block/proxycheck.php?ip=%s", sIP);

	Handle hRequest = SteamWorks_CreateHTTPRequest(k_EHTTPMethodGET, sRequest);
	if (!hRequest ||
		!SteamWorks_SetHTTPCallbacks(hRequest, OnClientPostAdminCheck_OnTransferComplete) ||
		!SteamWorks_SetHTTPRequestContextValue(hRequest, iSerial) ||
		!SteamWorks_SendHTTPRequest(hRequest))
	{
		delete hRequest;
	}
}

//----------------------------------------------------------------------------------------------------
// Purpose:
//----------------------------------------------------------------------------------------------------
public int OnClientPostAdminCheck_OnTransferComplete(Handle hRequest, bool bFailure, bool bSuccessful, EHTTPStatusCode eStatusCode, int iSerial)
{
	int client = GetClientFromSerial(iSerial);

	if (!client) //Player disconnected.
	{
		delete hRequest;
		return;
	}

	if (bFailure || !bSuccessful || eStatusCode != k_EHTTPStatusCode200OK)
	{
		g_bStatus[client] = 3;
		delete hRequest;
		return;
	}

	SteamWorks_GetHTTPResponseBodyCallback(hRequest, OnClientPostAdminCheck_OnTransferResponse, iSerial);
}

//----------------------------------------------------------------------------------------------------
// Purpose:
//----------------------------------------------------------------------------------------------------
public int OnClientPostAdminCheck_OnTransferResponse(char[] sData, int iSerial)
{
	int client = GetClientFromSerial(iSerial);

	if (!client) //Player disconnected.
		return;

	TrimString(sData);
	StripQuotes(sData);

	if (strcmp(sData, "Y", false) == 0)
	{
		g_bStatus[client] = 1;

		char sIP[32];
		GetClientIP(client, sIP, sizeof(sIP));

		char sSteamID[32];
		GetClientAuthId(client, AuthId_Steam2, sSteamID, sizeof(sSteamID));

		for(int i = 1; i <= MaxClients; i++)
		{
			if(IsValidClient(i) && CheckCommandAccess(i, "sm_vpn", ADMFLAG_RCON))
			{
				if(!RevEmu_IsPlayerSteam(client))
				{
					CPrintToChat(i, "{green}[SM]{default} %L[NOSTEAM] is possibly using a {red}VPN {default}(IP: %s). Client will be kicked.", client, sIP);
					KickClient(client, "VPN not allowed");
					LogAction(client, -1, "\"%L\"[NOSTEAM] is possibly using a VPN (IP: %s). Client got kicked.", client, sIP);
				}
				else
					CPrintToChat(i, "{green}[SM]{default} %L[STEAM] is possibly using a {red}VPN {default}(IP: %s).", client, sIP);
			}
		}
	}
	else if (strcmp(sData, "N", false) == 0)
	{
		g_bStatus[client] = 0;
	}
	else if (strcmp(sData, "X", false) == 0)
	{
		g_bStatus[client] = 2;
	}
}

//----------------------------------------------------------------------------------------------------
// Purpose:
//----------------------------------------------------------------------------------------------------
stock int IsValidClient(int client, bool nobots = true)
{
	if (client <= 0 || client > MaxClients || !IsClientConnected(client) || (nobots && IsFakeClient(client)))
		return false;

	return IsClientInGame(client);
}