--[[

	CleanReg 1.1 LUA 5.1x [Strict] [API 2]
	By Mutor	01/18/08
	Requested by Gnuff™
	translated by KauH

	Чистка регистраций зарегистрированных юзеров для API2
	*Удаление аккаунтов юзеров после 'x' дней of inactivity.

	-настройки интервала для профиля
	-исключение для ника
	-контекстное меню [right click]
	-опция для сообщений только в личку
	-репорт OpNick или ОпЧат
	-Данные скрипта сохраняются в файл при перезагрузке хаба/скрипта
	-Non-excluded users are reminded of account purge time at disconnect.

	+изменения от версии 1.0	10/10/08
		+Добавлены команды / оставшееся время регистрации юзера / оставшееся время регистрации всех юзеров  by quicky2g

]]

-- -- "имябота" ["" = бот хаба]
local Bot = ""
-- Ник для репорта ["" = в опчат]
local ReportNick = ""
-- Если  true  то только в личку
local PmOnly = false
-- User data
local File = "RegUser.dat"
-- Excluded nicks
local ExcFile = "ExcUser.dat"
-- Profile data
local ProfFile = "Profiles.dat"
-- Command prefix ["" = first char set in PtokaX]
local Prefix = ""
-- Интервал [в минутах] для проверки юзеров
local Mins = 30
-- Интервал регистрации [в днях] до того как юзер удалится из списка зарегистрированных юзеров [0 = disable]
-- [#] = days,
local Profiles  = {
	[0] = 365,	--Master
	[1] = 180,	--Operator
	[2] = 90,	--VIP
	[3] = 30,	--Registered User
	[4] = 180,	--Server
	}

-- Ник,пароль и профиль для тестирования функций скрипта [укажите TestNick = "" для выключения]
local TestNick,TestPass,TestProf = "","",3 --"TestNick","Password",3
--//--

local Cmds,Tmr = {},0
OnStartup = function()
	local chg
	Mins = math.max(Mins,1)
	Tmr = TmrMan.AddTimer(Mins*60000)
	if Bot == "" then Bot = SetMan.GetString(21) end
	if Prefix == "" then Prefix = SetMan.GetString(29):sub(1,1) end
	local Path = Core.GetPtokaXPath().."scripts/"
	if not ProfFile:find("^"..Path,1,true) then ProfFile = Path..ProfFile end
	if loadfile(ProfFile) then dofile(ProfFile) else SaveFile(ProfFile,Profiles,"Profiles") end
	if not ExcFile:find("^"..Path,1,true) then ExcFile = Path..ExcFile end
	if loadfile(ExcFile) then dofile(ExcFile) else Exclude = {"NewUser"} SaveFile(ExcFile,Exclude,"Exclude") end
	if not File:find("^"..Path,1,true) then File = Path..File end
	if loadfile(File) then
		dofile(File)
	else
		RegUsers = {}
		local tab,t = RegMan.GetRegs(),os.time()
		if next(tab) then
			for _,user in ipairs(tab) do
				local p,i,n = user.iProfile,Profiles[user.iProfile],user.sNick
				if not Exclude[n] then if i and i > 0 then RegUsers[n] = {t,p} chg = true end end
			end
		end
	end
	for k,v in pairs(RegUsers) do if not RegMan.GetReg(k) then RegUsers[k] = nil chg = true end end
	if TestNick:len() > 0 then
		local usr,pwd,prf,tm = TestNick,TestPass,TestProf,(os.time() - ((Profiles[TestProf]+1)*86400))
		if not RegMan.GetReg(TestNick) then RegMan.AddReg(usr,pwd,prf) RegUsers[usr] = {tm,prf} chg = true end
	end
	if chg then SaveFile(File,RegUsers,"RegUsers") end
	OnTimer(Tmr)
end

OnExit = function()
	SaveFile(File,RegUsers,"RegUsers")
end

ChatArrival = function(user,data)
	local _,_,cmd = data:find("^%b<> ["..SetMan.GetString(29).."](%a+)")
	if cmd then
		cmd = cmd:lower()
		if Cmds[cmd] and Cmds[cmd][2][user.iProfile] then
			return Core.SendToUser(user,"<"..Bot.."> "..Cmds[cmd][1](user,data,cmd).."|"),true
		end
	end
end

OnTimer = function(Id)
	if Id == Tmr then
		local cur,cnt,ru,chg = os.time(),0,#RegMan.GetRegs()
		for key,tab in pairs(RegUsers) do
			local user = Core.GetUser(key)
			if user then
				if Profiles[user.iProfile] then
					if not RegMan.GetReg(user.sNick) then
						RegUsers[user.sNick] = nil
					else
						RegUsers[user.sNick] = {os.time(),user.iProfile}
					end
				end
			else
				local td = os.difftime(os.time(),tab[1])/86400
				if Profiles[tab[2]] > 0 and td > Profiles[tab[2]] then
					cnt = cnt + 1
					Report(key.." не посещал хаб в течении "..Profiles[tab[2]]..
					" дней. ("..string.format("%.0f",(td))..")  "..key..
					" был удалён из списка зарегистрированных юзеров.")
					RegMan.DelReg(key)
					RegUsers[key] = nil
					chg = true
				end
			end
		end
		if chg then
			SaveFile(File,RegUsers,"RegUsers")
			Report(tostring(cnt).." из "..tostring(ru).." был удалён из списка зарегистрированных юзеров за <"..
			string.format("%.2f seconds.",os.difftime(os.time(),cur)+.01))
		end
	end
end

UserConnected = function(user,data)
	if Profiles[user.iProfile] and Profiles[user.iProfile] > 0 and not Exclude[user.sNick] then
		if RegUsers[user.sNick] then
			local td = os.difftime(os.time(),RegUsers[user.sNick][1])/86400
			if td >= 1 then
				Core.SendToUser(user,"<"..Bot.."> Hey "..user.sNick..
				", we've missed you for the last "..td.." days.|")
			end
		end
		RegUsers[user.sNick] = {os.time(),user.iProfile}
		SaveFile(File,RegUsers,"RegUsers")
	end
	local s,h  = "","Меню хаба"
	for i,v in pairs(Cmds) do
		if v[2][user.iProfile] then
			local d,a = v[3][1],v[3][2]
			s = s.."$UserCommand 1 1 "..h.."\\Чистка регистраций\\"..
			d.."$<%[mynick]> "..Prefix..i..a.."&#124;|"
		end
	end
	if s:len() > 0 then Core.SendToUser(user,s) end
end
OpConnected,RegConnected = UserConnected,UserConnected

UserDisconnected = function(user,data)
	if Profiles[user.iProfile] and Profiles[user.iProfile] > 0 and not Exclude[user.sNick] then
		local t = os.date("%c",os.time() + (86400 * Profiles[user.iProfile]))
		Core.SendToUser(user,"<"..Bot.."> До Свидания  "..user.sNick..". Ваша регистрация "..
		"будет активна ещё "..Profiles[user.iProfile].." дней.|")
		Core.SendToUser(user,"<"..Bot.."> After which it will be purged, be sure to return before "..t.."|")
		RegUsers[user.sNick] = {os.time(),user.iProfile}
		SaveFile(File,RegUsers,"RegUsers")
	end
end
RegDisconnected,OpDisconnected = UserDisconnected,UserDisconnected

Report = function(msg)
	if ReportNick:len() > 0 then
		local op = Core.GetUser(ReportNick)
		if msg and op then
			if PmOnly then
				Core.SendPmToUser(op,Bot,msg.."|")
			else
				Core.SendToUser(op,"<"..Bot.."> "..msg.."|")
			end
		end
	end
end

Cmds = {
	excuser = {function(user,data,cmd)
		if user then
			local _,_,nick = data:find("^%b<> %S+ (%S+)|")
			if nick then
				if RegMan.GetReg(nick) then
					for i,v in ipairs(Exclude) do
						if nick:lower() == v:lower() then
							table.remove(Exclude,i)
							SaveFile(ExcFile,Exclude,"Exclude")
							return nick.." исключён из исключений."
						end
					end
					table.insert(Exclude,nick)
					SaveFile(ExcFile,Exclude,"Exclude")
					return nick.." включён в исключения."
				else
					return " Ошибка ! Используйте: "..Prefix..cmd.." <зарегистрированный ник>"
				end
			else
				return " Ошибка ! Используйте: "..Prefix..cmd.." <ник>"
			end
		end
	end,{[-1] = false,[0] = true,[1] = true,[2] = false,[3] = false,[4] = true},
	{"Исключения / включить в исключения"," %[line:Введите ник]"}
	},
	usertime = {function(user,data,cmd)
		if user then
			local _,_,nick = data:find("^%b<> %S+ (%S+)|")
			if nick then
				if RegUsers[nick] then
					local remaining = Convert(RegUsers[nick][1] + (86400 * Profiles[RegUsers[nick][2]]))
					return " Оставшееся время регистрации  "..nick..": "..remaining
				else
					return " Ошибка ! ник "..nick.." не найден."
				end
			else
				return " Ошибка ! Используйте: "..Prefix..cmd.." <ник>"
			end
		end
	end,{[-1] = false,[0] = true,[1] = true,[2] = false,[3] = false,[4] = true},
	{"Показать оставшееся время регистрации юзера"," %[line:Введите ник]"}
	},
	regtimes = {function(user,data,cmd)
		if user then
			if RegUsers ~= {} then
				local s = ""
				for nick,tab in pairs(RegUsers) do
					local remaining = Convert(tab[1] + (86400 * Profiles[tab[2]]))
					s = s.."\t"..string.format("%-30.50s",nick).."\t\t\t"..remaining.."\r\n"
				end
				if s ~= "" then
					return "\r\n\r\n\tОставшееся время регистрации:\r\n\r\n"..s
				end
			else
				return " Нет юзеров в списке."
			end
		end
	end,{[-1] = false,[0] = true,[1] = true,[2] = false,[3] = false,[4] = true},
	{"Показать оставшееся время регистрации всех юзеров",""}
	},
	setprof = {function(user,data,cmd)
		local _,_,pnumb,days = data:find("^%b<> ["..SetMan.GetString(29).."]"..cmd.." (%d+) (%d+)|")
		if pnumb and days then
			if not Profiles[tonumber(pnumb)] then
				return " Ошибка ! "..pnumb.." неправильный номер профиля."
			else
				local x,p = Profiles[tonumber(pnumb)],ProfMan.GetProfile(tonumber(pnumb)).sProfileName
				Profiles[tonumber(pnumb)] = tonumber(days)
				SaveFile(ProfFile,Profiles,"Profiles")
				return p.."'s время чистки успешно изменено с "..x.." на "..days.." дней."
			end
		else
			return " Ошибка ! Используйте: "..Prefix..cmd.." <номер профиля> <кол-во дней>"
		end
	end,{[-1] = false,[0] = true,[1] = false,[2] = false,[3] = false,[4] = false},
	{"Установка времени чистки профиля"," %[line:Номер профиля] %[line:Интервал в днях]"}
	},
}

Convert = function(time)
	if time then
		local s,x,n = "",0,os.time()
		local tab = {{31556926,"лет"},{2592000,"месяца"},{604800,"недели"},
		{86400,"дней"},{3600,"часов"},{60,"минут"},{1,"секунд"}}
		if time > 0 then
			if time < 2145876659 then
				if n > time then
					time = n - time
				elseif n < time then
					time = time - n
				end
				for i,v in ipairs(tab) do
					if time > v[1] then
						x = math.floor(time/v[1])
						if x > 1 then v[2] = v[2].."" end
						if x > 0 then
							s = s..x.." "..v[2]..", "
							time = time-x*v[1]
						end
					end
				end
				collectgarbage("collect")
				return s:sub(1,-3)
			else
				return " Неправильные дата или время. [должно быть до 12/31/2037]"
			end
		else
			return " Неправильные дата или время. [должно быть после 01/01/1970]"
		end
	else
		return " Неправильные дата или время."
	end
end

Serialize = function(tTable, sTableName, hFile, sTab)
	sTab = sTab or "";
	hFile:write(sTab..sTableName.." = {\n" )
	for key, value in pairs(tTable) do
		local sKey = (type(key) == "string") and string.format("[%q]",key) or string.format("[%d]",key)
		if(type(value) == "table") then
			Serialize(value, sKey, hFile, sTab.."\t")
		else
			local sValue = (type(value) == "string") and string.format("%q",value) or tostring(value)
			hFile:write( sTab.."\t"..sKey.." = "..sValue)
		end
		hFile:write( ",\n")
	end
	hFile:write( sTab.."}")
end

SaveFile = function(file,table, tablename )
	local hFile = io.open (file , "wb")
	Serialize(table, tablename, hFile)
	hFile:close()
	collectgarbage("collect")
end
