TopHubbers 2.03 - LUA 5.1x [Strict][API 2] - Page 3
 

TopHubbers 2.03 - LUA 5.1x [Strict][API 2]

Started by jiten, 23 December, 2007, 11:53:53

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.

merlin_xl54

Quote from: Dreams on 20 January, 2010, 14:31:22
Anyone who can get this script to work.
I can use the RightClicks, but it wont send the Warning on login.

Ill post the whole script so that anyone can look at it.

As I said before, the warning/kick is for "Daily" average up times. You have 25 as the trigger. Our Hub is set to 14. Any user who's average uptime is under 14 hours (Per day), gets a warning upon connect.

M
Living is easy with eyes closed.

speedX

#51
Quote from: DeAn on 18 October, 2009, 14:45:05
I would like to have a function which returns numeric rank of the user on command +hubtime


try this....
--[[

	TopHubbers 2.03b - LUA 5.1.2 [Strict][API 2] by jiten
	????????????????????????????????????????????????????
	Based on: OnHub Time Logger 1.65 by chill and Robocop's layout

	Usage: !tophubbers; !tophubbers x-y; !hubtime <nick>; !myhubtime

	CHANGELOG:
	??????????
	Fixed: Typo in table.sort function;
	Added: OnExit (3/21/2006)
	Fixed: Missing pairs() in SaveToFile
	Changed: Removed iGlobalTime and added TotalTime count to OnTimer
	Changed: SecondsToTime function values (3/24/2006)
	Changed: math.floor/mod in TopHubbers' function; (3/5/2006)
	Changed: SecondsToTime month value (4/17/2006);
	Added: !hubtime <nick> - requested by speedX;
	Changed: SecondsToTime function and small code bits (8/16/2006)
	Changed: Table indexes;
	Changed: SecondsToTime function to MinutesToTime;
	Fixed: Inaccurate average uptime stuff (8/17/2006)
	Changed: Average uptime function;
	Changed: Session time for offline users doesn't get reset;
	Added: Average uptime warning on connect - requested by speedX (8/20/2006)
	Added: Customized profiles - requested by Naithif (8/20/2006)
	Added: User Commands - requested by TT;
	Added: Rankings and related commands [!myrank & !topranks] - requested by speedX;
	Added: Toggle rank info on connect - requested by TT;
	Fixed: !tophubbers x-y;
	Added: Comments to the code;
	Changed: Some code bits;
	Added: Toggle between total and average uptime (8/24/2006)
	Fixed: Minimum average uptime warning - reported by speedX;
	Added: Maximum shown hubbers - requested by Naithif (8/29/2006)
	Fixed: LUA 5.0/5.1 compatibility - reported by speedX (11/8/2006)
	Added: string.lower check - requested by SwapY and speedX (11/10/2006)

	Changed: Script converted to API 2 (11/24/2007)
	Fixed: Changed Serialize function (12/23/2007)
	
	+Changes from 2.03a	07/26/09
	
	Added: Send messages in PM (01/22/2008) by speedX
	Added: Timer to save data on regular intervals (07/18/2008) by speedX
	Added: Kick user below Minimum Average uptime (iMin) (6/20/2009) by merlin_xl54-CrazyGuy
	Added: Table to exclude certain nicks from kick (tExc) (6/24/2009) by merlin_xl54-CrazyGuy
	Added: Show total years added in displayed times (7/26/2009) by speedX

]]--

tSettings = {
	-- Bot Name
	sBot = SetMan.GetString(21),
	
	-- Top Hubbers' DB
	fOnline = "scripts/tOnliners.tbl",

	-- RightClick Menu
	sMenu = "Top Hubbers",

	-- Maximum hubbers to show when using !tophubbers
	iMax = 15,

	-- Send message to users with lower than specified Average uptime (AUT) [true = on; false = off]
	bWarning = true,
	
	-- Minimum Average uptime (hours) that triggers the warning
	iAUT = 12,
	
	-- Minimum Average uptime (hours) that triggers the kick [Disable = 0]
	iMin = 0,
	
	-- Send hubtime stats on connect [true = on; false = off]
	bRankOnConnect = false,

	-- Profiles checked [0 = off; 1 = on]
	tProfiles = { [-1] = 0, [0] = 1, [1] = 1, [2] = 1, [3] = 1, },

	-- Ranks criteria ["average" = Average total uptime; "total" = Total uptime]
	sCriteria = "average",
	
	-- Reply in PM ?
	bPmOnly = true,
	
	-- Set your interval time to save data(in Hours)
	iInterval = 24,
	
	--Exclude from kick
	tExc = {
	["merlin_xl54"] = true,
	["yournickhere"] = true,
	},

	-- Ranks
	tRanks = { 
--[[		
		
	The ranks must be added in ascending order [from the lowest to the highest]
	{ "Rank", [time][string] }

	[time] must be 1 or more digit(s)
	[string] must be: s = second; m = minute; h = hour; D = day; W = week; M = month; Y = year

	Example: { "God", "1M, 2D, 10s" } 
	Meaning: To become a God, your total uptime must be equal or higher than 1 month, 2 days and 10 seconds
]]--

-- Total uptime rank table
		total = {
			{ "Newbie", "1D, 1h, 1m, 1s" }, { "Member", "2D" }, { "Cool Member", "5D" }, 
			{ "Hub As", "10D" }, { "Smart As", "20D" }, { "Double As", "1M" }, 
			{ "Triple As", "2M" }, { "Conqueror", "3M" }, { "Viking", "4M" }, 
			{ "King", "6M" }, { "Emperor", "8M" }, { "Hub Legend", "10M" }, 
			{ "Hub God", "11M" }, { "God", "1Y, 1h, 1m, 1s" },
		},

-- Daily average uptime rank table
		average = { 
			{ "Newbie", "1h" }, { "Member", "6h" }, { "Cool Member", "12h" }, 
			{ "Hub-As", "1D" }, { "Smart As", "5D" }, { "Double-As", "15D" }, 
			{ "Triple-As", "1M" }, { "Conqueror", "2M" }, { "Viking", "3M" }, 
			{ "King", "4M" }, { "Emperor", "6M" }, { "Hub Legend", "9M" }, 
			{ "Hub God", "11M" }, { "God", "1Y" },
		},
	},
}

tOnline = {}

OnStartup = function()
	-- Register BotName if not registered
	if tSettings.sBot ~= SetMan.GetString(21) then Core.RegBot(tSettings.sBot,"","",true) end
	-- Load DB content
	if loadfile(tSettings.fOnline) then dofile(tSettings.fOnline) end
	-- Set and Start Timer
	tSettings.iTimer = TmrMan.AddTimer(60*1000)
	--Save Data Interval
	tSettings.SaveData = TmrMan.AddTimer(tSettings.iInterval*60*60*1000)
end 

OnTimer = function(iID)
	if tSettings.iTimer and iID == tSettings.iTimer then
		-- For each hubber
		for i, v in pairs(tOnline) do
			-- Online
			if Core.GetUser(i) then
				-- Sum
				v.SessionTime = v.SessionTime + 1; v.TotalTime = v.TotalTime + 1
			end
		end
  elseif tSettings.SaveData and iID == tSettings.SaveData then
			local hFile = io.open(tSettings.fOnline, "w+") Serialize(tOnline, "tOnline", hFile); hFile:close()
	end
end

OnExit = function()
	-- Save
	local hFile = io.open(tSettings.fOnline, "w+") Serialize(tOnline, "tOnline", hFile); hFile:close()
end

UserConnected = function(user)
	-- If profile has permission to be logged
	if tSettings.tProfiles[user.iProfile] and tSettings.tProfiles[user.iProfile] == 1 then
		local tNick = GetOnliner(user.sNick)
		-- User already in DB
		if tNick then
			-- Warning on connect
			if tSettings.bWarning then
				-- Days since first login
				local iAverage = os.difftime(os.time(os.date("!*t")), tNick.Julian)/(60*60*24)
				if iAverage < 1 then iAverage = 1 end
				-- Less than allowed
					if tNick.TotalTime/iAverage < tSettings.iMin*60 then 
					-- Kick if not excluded
						if not tSettings.tExc[user.sNick] then
						-- Add any custom message to kick
						Core.Kick(user, tSettings.sBot, "*** Your Average uptime (AUT) is less than "..tSettings.iMin..
						" hour(s). Please post to our forum before you try to connect again!")
						end
					end
					-- Warn if not kicked
					if tNick.TotalTime/iAverage < tSettings.iAUT*60 then 
					-- Add any custom message to warning
					Core.SendPmToNick(user.sNick, tSettings.sBot, "*** Your Average uptime (AUT) is less than "..tSettings.iAUT..
					" hour(s). Users above this average will be considered for VIP, and may log in when the Hub is full!")
					end
					--Warn if between iMin & iAUT and excluded from kick
					else
					if tNick.TotalTime/iAverage < tSettings.iAUT*60 then
						if tNick.TotalTime/iAverage > tSettings.iMin*60 then 
							if tSettings.tExc[user.sNick] then
							-- Add any custom message to warning
							Core.SendPmToNick(user.sNick, tSettings.sBot, "*** Your Average uptime (AUT) is less than "..tSettings.iAUT..
							" hour(s). Users above this average will be considered for VIP, and may log in when the Hub is full!")
							end
						end
					end
				
			end
			-- Reset and save time
			tNick.SessionTime = 0; tNick.Enter = os.date()
			-- Send rank info on connect
			if tSettings.bRankOnConnect then tCommands["myhubtime"].fFunction(user) end
		else
			-- Create new entry
			tOnline[user.sNick] = { Julian = os.time(os.date("!*t")), Enter = os.date(), SessionTime = 0, TotalTime = 0, Leave = os.date() }
		end
	end
	-- Supports UserCommands
	if Core.GetUserValue(user,12) then
		-- For each entry in table
		for i, v in pairs(tCommands) do
			-- If member
			if v.tLevels[user.iProfile] then
				-- For each type
				for n in ipairs(v.tRC) do
					-- Send
					Core.SendToNick(user.sNick, "$UserCommand 1 3 "..tSettings.sMenu.."\\"..v.tRC[n][1]..
					"$<%[mynick]> !"..i..v.tRC[n][2].."&#124;")
				end
			end
		end
	end
end

OpConnected = UserConnected
RegConnected = UserConnected

UserDisconnected = function(user)
	local tNick = GetOnliner(user.sNick)
	-- If profile must be logged and user is in DB
	if tSettings.tProfiles[user.iProfile] and tSettings.tProfiles[user.iProfile] == 1 and tNick then
		-- Log date
		tNick.Leave = os.date()
	end
end

OpDisconnected = UserDisconnected
RegDisconnected = UserDisconnected

ChatArrival = function(user,data)
	local _,_, to = data:find("^$To:%s(%S+)%s+From:")
	local _,_, msg = data:find("%b<>%s(.*)|$") 
	-- Message sent to Bot or in Main
	if (to and to == tSettings.sBot) or not to then
		-- Parse command
		local _,_, cmd = msg:find("^%p(%S+)")
		-- Exists
		if cmd and tCommands[cmd:lower()] then
			cmd = cmd:lower()
			-- If user has permission
			if tCommands[cmd].tLevels[user.iProfile] then
				if to and to == tSettings.sBot then
					return Core.SendPmToNick(user.sNick, tSettings.sBot, tCommands[cmd].fFunction(user, msg)), true
				else
					if tSettings.bPmOnly then
						return Core.SendPmToNick(user.sNick, tSettings.sBot, tCommands[cmd].fFunction(user, msg)), true
					else
					    return Core.SendToNick(user.sNick, "<"..tSettings.sBot.."> "..tCommands[cmd].fFunction(user, msg)), true
					end
				end
			else
				if to and to == tSettings.sBot then
					return Core.SendPmToNick(user.sNick, tSettings.sBot, "*** Error: You are not allowed to use this command!"), true
				else
					return Core.SendToNick(user.sNick, "<"..tSettings.sBot.."> *** Error: You are not allowed to use this command!"), true
				end
			end
		end
	end
end

ToArrival = ChatArrival

tCommands = {
	tophubbers = {
		fFunction = function(user, data)
			-- Table isn't empty
			if next(tOnline) then
				-- Parse limits
				local _,_, iStart, iEnd = data:find("^%S+%s+(%d+)%-(%d+)$")
				-- Set if not set
				iStart, iEnd = (iStart or 1), (iEnd or tSettings.iMax)
				-- Header
				local tCopy, msg = {}, "\r\n\t"..string.rep("=", 137).."\r\n\tNr.  Total:\t\t\t\t\tSession:\t"..
				"Entered Hub:\tLeft Hub:\t\tRank:\t\tStatus:\tName:\r\n\t"..string.rep("-", 240).."\r\n"
				-- Loop through hubbers
				for i, v in pairs(tOnline) do
					-- Insert stats to temp table
					table.insert(tCopy, { sEnter = v.Enter, iSessionTime = tonumber(v.SessionTime),
					iTotalTime = tonumber(v.TotalTime), sLeave = v.Leave, sNick = i, sRank = GetRank(i) } )
				end
				-- Sort by total time
				table.sort(tCopy, function(a, b) return (a.iTotalTime > b.iTotalTime) end)
				-- Loop through temp table
				for i = iStart, iEnd, 1 do
					-- i exists
					if tCopy[i] then
						-- Populate
						local sStatus, v = "*Offline*", tCopy[i]; local sRank = v.sRank
						if Core.GetUser(v.sNick) then sStatus = "*Online*" end
						if v.sRank:len() < 9 then sRank = sRank.."\t" end
						msg = msg.."\t"..i..".    "..MinutesToTime(v.iTotalTime).."\t"..v.iSessionTime..
						" min\t"..v.sEnter.."\t"..v.sLeave.."\t"..sRank.."\t"..sStatus.."\t"..v.sNick.."\r\n"
					end
				end
				msg = msg.."\t"..string.rep("-", 240)
				-- Send
				return  "Current Top Hubbers:\r\n"..msg.."\r\n"
			else
				return "*** Error: Top Hubbers' table is currently empty!"
			end
		end,
		tLevels = {
			[-1] = 0, [0] = 1, [1] = 1, [2] = 1, [3] = 1,
		},
		tRC = { { "Show Top "..tSettings.iMax.." Hubbers", "" }, { "Show Top x-y Hubbers", " %[line:x-y]" } }
	},
	hubtime = {
		fFunction = function(user, data)
			-- Parse nick
			local _,_, nick = data:find("^%S+%s+(%S+)$")
			-- Exists
			if nick then 
				-- Return
				return BuildStats(user, nick)
			else
				return "*** Syntax Error: Type !hubtime <nick>"
			end
		end,
		tLevels = { 
			[-1] = 0, [0] = 1, [1] = 1, [2] = 1, [3] = 1, 
		},
		tRC = { { "Show a User's Stats", " %[line:Nick]" } }
	},
	myhubtime = {
		fFunction = function(user)
			-- Return
			return BuildStats(user, user.sNick)
		end,
		tLevels = { 
			[-1] = 0, [0] = 1, [1] = 1, [2] = 1, [3] = 1, 
		},
		tRC = { { "Show My Stats", "" } }
	},
}

BuildStats = function(user, nick)
	local tNick = GetOnliner(nick)
	-- In DB
	if tNick then
		-- Average uptime in days
		local iAverage = os.difftime(os.time(os.date("!*t")), tNick.Julian)/(60*60*24)
		if iAverage < 1 then iAverage = 1 end
		-- Generate message
		local sMsg = "\r\n\r\n\t"..string.rep("=", 51).."\r\n\t\t\tStats:\r\n\t"..
		string.rep("-", 89).."\r\n\t- Nick: "..nick.."\r\n\t- Total uptime: "..
		MinutesToTime(tNick.TotalTime, true).."\r\n\t- Daily average uptime (AUT): "..
		MinutesToTime((tNick.TotalTime/iAverage), true).."\r\n\t- Status: "..GetRank(nick).."  Rank: "..GetNumber(nick).."\r\n"
		-- Send stats 
		--Add any custom message
		return "Here are the stats you requested for "..nick..". Remember, users with over "..tSettings.iAUT.." hour(s) (AUT) will be considered for VIP and may bypass the Hub full rule. Those below "..tSettings.iMin.." hour(s) (AUT) will be disconnected!"  ..sMsg
		else
			return "*** Error: No record found for '"..nick.."'!"
	end
end

GetRank = function(nick)
	local tNick = GetOnliner(nick)
	if tNick then
		-- Custom time table
		local tTime, sRank, iAverage = { s = 1/60, m = 1, h = 60, D = 60*24, W = 60*24*7, M = 60*24*30, Y = 60*24*30*12 }, tSettings.tRanks[tSettings.sCriteria:lower()][1][1]
		-- Average enabled
		if tSettings.bAverage then
			-- Days since first login
			iAverage = os.difftime(os.time(os.date("!*t")), tNick.Julian)/(60*60*24)
			if iAverage < 1 then iAverage = 1 end
		end
		-- For each rank
		for n in ipairs(tSettings.tRanks[tSettings.sCriteria:lower()]) do
			local iTime = 0
			-- For each digit and time string
			for i, v in tSettings.tRanks[string.lower(tSettings.sCriteria)][n][2]:gmatch("(%d+)(%w)") do
				-- Process
				if i and tTime[v] then iTime = iTime + i*tTime[v] end
			end
			local iValue = tNick.TotalTime
			-- Average
			if tSettings.bAverage then iValue = iValue/iAverage end
			-- Process rank if user hasn't logged in for the first time today
			if os.date("%d%m%y", tNick.Julian) ~= os.date("%d%m%y") and iValue > iTime then
				sRank = tSettings.tRanks[tSettings.sCriteria:lower()][n][1]
			end
		end
		return sRank
	end
end

GetNumber = function(nick)
  if next(tOnline) then
    local tCopy,iCount = {},0
    for i, v in pairs(tOnline) do
      table.insert(tCopy, { iTotalTime = tonumber(v.TotalTime), sNick = i } )
      iCount = iCount + 1
    end
    table.sort(tCopy, function(a, b) return (a.iTotalTime > b.iTotalTime) end)
    for i = 1, iCount do
      if tCopy[i] then
        local v = tCopy[i]
        if v.sNick:lower() == nick:lower() then
          return i
        end
      end
    end
  end
end

MinutesToTime = function(iSeconds, bSmall)
	-- Build table with time fields
	local T = os.date("!*t", tonumber(iSeconds*60)); 
	-- Format to string
	local sTime = string.format("%i year(s), %i month(s), %i day(s), %i hour(s), %i minute(s)", T.year-1970, T.month-1, T.day-1, T.hour, T.min)
	-- Small stat?
	if bSmall then
		-- For each digit
		for i in sTime:gmatch("%d+") do
			-- Reduce if is preceeded by 0
			if tonumber(i) == 0 then sTime = sTime:gsub("^"..i.."%s(%S+),%s", "") end
		end
	end
	-- Return
	return sTime
end

GetOnliner = function(user)
	-- For each hubber
	for i, v in pairs(tOnline) do
		-- Compare
		if i:lower() == user:lower() then
			-- Return
			return tOnline[i]
		end
	end
end

Serialize = function(tTable, sTableName, hFile, sTab)
	sTab = sTab or "";
	hFile:write(sTab..sTableName.." = {\n");
	for key, value in pairs(tTable) do
		if (type(value) ~= "function") then
			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
	end
	hFile:write(sTab.."}");
end
Thanking You,

speedX

DeAn

Thanks speedX for your effort. The script is working great. Just one thing I noticed in this is that the right click menu can only be seen by unregistered users. So I checked the profile permissions at the beginning. I changed

-- Profiles checked [0 = off; 1 = on]
	tProfiles = { [-1] = 0, [0] = 1, [1] = 1, [2] = 1, [3] = 1, },


to

-- Profiles checked [0 = off; 1 = on]
	tProfiles = { [-1] = 0, [0] = 0, [1] = 0, [2] = 0, [3] = 0, },


and now I'm able to see the right click menu. Not a big issue but I got it. Thanks.



Thanks,
DeAn
Thanks,

DeAn

merlin_xl54

#53
Quote from: DeAn on 28 March, 2010, 04:05:15
Thanks speedX for your effort. The script is working great. Just one thing I noticed in this is that the right click menu can only be seen by unregistered users. So I checked the profile permissions at the beginning. I changed

-- Profiles checked [0 = off; 1 = on]
	tProfiles = { [-1] = 0, [0] = 1, [1] = 1, [2] = 1, [3] = 1, },


to

-- Profiles checked [0 = off; 1 = on]
	tProfiles = { [-1] = 0, [0] = 0, [1] = 0, [2] = 0, [3] = 0, },


and now I'm able to see the right click menu. Not a big issue but I got it. Thanks.



Thanks,
DeAn


You've changed what profiles should be checked. The R Click options are set in "tCommands". Try this, it has been changed for the new PtokaX 0.4.1.2

M

--[[

	TopHubbers 2.03b - LUA 5.1.2 [Strict][API 2] by jiten
	????????????????????????????????????????????????????
	Based on: OnHub Time Logger 1.65 by chill and Robocop's layout

	Usage: !tophubbers; !tophubbers x-y; !hubtime <nick>; !myhubtime

	CHANGELOG:
	??????????
	Fixed: Typo in table.sort function;
	Added: OnExit (3/21/2006)
	Fixed: Missing pairs() in SaveToFile
	Changed: Removed iGlobalTime and added TotalTime count to OnTimer
	Changed: SecondsToTime function values (3/24/2006)
	Changed: math.floor/mod in TopHubbers' function; (3/5/2006)
	Changed: SecondsToTime month value (4/17/2006);
	Added: !hubtime <nick> - requested by speedX;
	Changed: SecondsToTime function and small code bits (8/16/2006)
	Changed: Table indexes;
	Changed: SecondsToTime function to MinutesToTime;
	Fixed: Inaccurate average uptime stuff (8/17/2006)
	Changed: Average uptime function;
	Changed: Session time for offline users doesn't get reset;
	Added: Average uptime warning on connect - requested by speedX (8/20/2006)
	Added: Customized profiles - requested by Naithif (8/20/2006)
	Added: User Commands - requested by TT;
	Added: Rankings and related commands [!myrank & !topranks] - requested by speedX;
	Added: Toggle rank info on connect - requested by TT;
	Fixed: !tophubbers x-y;
	Added: Comments to the code;
	Changed: Some code bits;
	Added: Toggle between total and average uptime (8/24/2006)
	Fixed: Minimum average uptime warning - reported by speedX;
	Added: Maximum shown hubbers - requested by Naithif (8/29/2006)
	Fixed: LUA 5.0/5.1 compatibility - reported by speedX (11/8/2006)
	Added: string.lower check - requested by SwapY and speedX (11/10/2006)
	Changed: Script converted to API 2 (11/24/2007)
	Fixed: Changed Serialize function (12/23/2007)
	
	+Changes from 2.03a	07/26/09
	
	Added: Send messages in PM (01/22/2008) by speedX
	Added: Timer to save data on regular intervals (07/18/2008) by speedX
	Added: Kick user below Minimum Average uptime (iMin) (6/20/2009) by merlin_xl54-CrazyGuy
	Added: Table to exclude certain nicks from kick (tExc) (6/24/2009) by merlin_xl54-CrazyGuy
	Added: Show total years added in displayed times (7/26/2009) by speedX
	Fixed: Error when bWarning is false (1-10-2010) by merlin_xl54
	Update for profile permission changes in PxLua API [version 0.4.1.2 and later] (1/22/2010) by merlin_xl54
	Added: Option to return stats by selecting nick in user list (3/1/2010) by merlin_xl54
	Added: Numeric rank in the hub stats for total time connected (3/17/2010) by speedX
]]--

tSettings = {
	-- Bot Name
	sBot = SetMan.GetString(21),
	
	-- Top Hubbers' DB
	fOnline = "scripts/tOnliners.tbl",

	-- RightClick Menu
	sMenu = "Top Hubbers",

	-- Maximum hubbers to show when using !tophubbers
	iMax = 15,

	-- Send message to users with lower than specified Average uptime (AUT) [true = on; false = off]
	bWarning = true,
	
	-- Minimum Average uptime (hours) that triggers the warning
	iAUT = 12,
	
	-- Minimum Average uptime (hours) that triggers the kick [Disable = 0]
	iMin = 0,
	
	-- Send hubtime stats on connect [true = on; false = off]
	bRankOnConnect = false,

	-- Profiles checked [false = off; true = on]
	tProfiles = { [-1] = false, [0] = true, [1] = true, [2] = true, [3] = true, [4] = true },

	-- Ranks criteria ["average" = Average total uptime; "total" = Total uptime]
	sCriteria = "average",
	
	-- Reply in PM ?
	sPmOnly = true,
	
	-- Set your interval time to save data(in Hours)
	iInterval = "24",
	
	--Exclude from kick
	tExc = {
	["yournickhere"] = true,
	},

	-- Ranks
	tRanks = { 
--[[		
		
	The ranks must be added in ascending order [from the lowest to the highest]
	{ "Rank", [time][string] }

	[time] must be 1 or more digit(s)
	[string] must be: s = second; m = minute; h = hour; D = day; W = week; M = month; Y = year

	Example: { "God", "1M, 2D, 10s" } 
	Meaning: To become a God, your total uptime must be equal or higher than 1 month, 2 days and 10 seconds
]]--

-- Total uptime rank table
		total = {
			{ "Newbie", "1D, 1h, 1m, 1s" }, { "Member", "2D" }, { "Cool Member", "5D" }, 
			{ "Hub As", "10D" }, { "Smart As", "20D" }, { "Double As", "1M" }, 
			{ "Triple As", "2M" }, { "Conqueror", "3M" }, { "Viking", "4M" }, 
			{ "King", "6M" }, { "Emperor", "8M" }, { "Hub Legend", "10M" }, 
			{ "Hub God", "11M" }, { "God", "1Y, 1h, 1m, 1s" },
		},

-- Daily average uptime rank table
		average = { 
			{ "Newbie", "1h" }, { "Member", "6h" }, { "Cool Member", "12h" }, 
			{ "Hub-As", "1D" }, { "Smart As", "5D" }, { "Double-As", "15D" }, 
			{ "Triple-As", "1M" }, { "Conqueror", "2M" }, { "Viking", "3M" }, 
			{ "King", "4M" }, { "Emperor", "6M" }, { "Hub Legend", "9M" }, 
			{ "Hub God", "11M" }, { "God", "1Y" },
		},
	},
}

tOnline = {}

OnStartup = function()
	-- Register BotName if not registered
	if tSettings.sBot ~= SetMan.GetString(21) then Core.RegBot(tSettings.sBot,"","",true) end
	-- Load DB content
	if loadfile(tSettings.fOnline) then dofile(tSettings.fOnline) end
	-- Set and Start Timer
	tSettings.iTimer = TmrMan.AddTimer(60*1000)
	--Save Data Interval
	tSettings.SaveData = TmrMan.AddTimer(tSettings.iInterval*60*60*1000)
end 

OnTimer = function(iID)
	if tSettings.iTimer and iID == tSettings.iTimer then
		-- For each hubber
		for i, v in pairs(tOnline) do
			-- Online
			if Core.GetUser(i) then
				-- Sum
				v.SessionTime = v.SessionTime + 1; v.TotalTime = v.TotalTime + 1
			end
		end
			elseif tSettings.SaveData and iID == tSettings.SaveData then
			local hFile = io.open(tSettings.fOnline, "w+") Serialize(tOnline, "tOnline", hFile); hFile:close()
	end
end

OnExit = function()
	-- Save
	local hFile = io.open(tSettings.fOnline, "w+") Serialize(tOnline, "tOnline", hFile); hFile:close()
end

UserConnected = function(user)
	-- If profile has permission to be logged
	if tSettings.tProfiles[user.iProfile] and tSettings.tProfiles[user.iProfile] == true then
		local tNick = GetOnliner(user.sNick)
		-- User already in DB
		if tNick then
			-- Warning on connect
			if tSettings.bWarning then
				-- Days since first login
				local iAverage = os.difftime(os.time(os.date("!*t")), tNick.Julian)/(60*60*24)
				if iAverage < 1 then iAverage = 1 end
				-- Less than allowed
					if tNick.TotalTime/iAverage < tSettings.iMin*60 then 
					-- Kick if not excluded
						if not tSettings.tExc[user.sNick] then
						-- Add any custom message to kick
						Core.Kick(user, tSettings.sBot, "*** Your Average uptime (AUT) is less than "..tSettings.iMin..
						" hour(s). Please post to our forum before you try to connect again!")
						end
					end
					-- Warn if not kicked
					if tNick.TotalTime/iAverage < tSettings.iAUT*60 then 
					-- Add any custom message to warning
					Core.SendPmToNick(user.sNick, tSettings.sBot, "*** Your Average uptime (AUT) is less than "..tSettings.iAUT..
					" hour(s). Users above this average will be considered for VIP, and may log in when the Hub is full. Those below "..tSettings.iMin.." hour(s) (AUT) will be disconnected!")
					--Warn if between iMin & iAUT and excluded from kick
					else
					if tNick.TotalTime/iAverage < tSettings.iAUT*60 then
						if tNick.TotalTime/iAverage > tSettings.iMin*60 then 
							if tSettings.tExc[user.sNick] then
							-- Add any custom message to warning
							Core.SendPmToNick(user.sNick, tSettings.sBot, "*** Your Average uptime (AUT) is less than "..tSettings.iAUT..
							" hour(s). Users above this average will be considered for VIP, and may log in when the Hub is full. Those below "..tSettings.iMin.." hour(s) (AUT) will be disconnected!")
							end
						end
					end
				end
			end
			-- Reset and save time
			tNick.SessionTime = 0; tNick.Enter = os.date()
			-- Send rank info on connect
			if tSettings.bRankOnConnect then tCommands["myhubtime"].fFunction(user) end
			else
			-- Create new entry
			tOnline[user.sNick] = { Julian = os.time(os.date("!*t")), Enter = os.date(), SessionTime = 0, TotalTime = 0, Leave = os.date() }
		end
	end
	-- Supports UserCommands
	if Core.GetUserValue(user,12) then
		-- For each entry in table
		for i, v in pairs(tCommands) do
			-- If member
			if v.tLevels[user.iProfile] then
				-- For each type
				for n in ipairs(v.tRC) do
					-- Send
					Core.SendToNick(user.sNick, "$UserCommand 1 3 "..tSettings.sMenu.."\\"..v.tRC[n][1]..
					"$<%[mynick]> !"..i..v.tRC[n][2].."&#124;")
				end
			end
		end
	end
end

OpConnected = UserConnected
RegConnected = UserConnected

UserDisconnected = function(user)
	local tNick = GetOnliner(user.sNick)
	-- If profile must be logged and user is in DB
	if tSettings.tProfiles[user.iProfile] and tSettings.tProfiles[user.iProfile] == true and tNick then
		-- Log date
		tNick.Leave = os.date()
	end
end

OpDisconnected = UserDisconnected
RegDisconnected = UserDisconnected

ChatArrival = function(user,data)
	local _,_, to = data:find("^$To:%s(%S+)%s+From:")
	local _,_, msg = data:find("%b<>%s(.*)|$") 
	-- Message sent to Bot or in Main
	if (to and to == tSettings.sBot) or not to then
		-- Parse command
		local _,_, cmd = msg:find("^%p(%S+)")
		-- Exists
		if cmd and tCommands[cmd:lower()] then
			cmd = cmd:lower()
			-- If user has permission
			if tCommands[cmd].tLevels[user.iProfile] then
				if to and to == tSettings.sBot then
					return Core.SendPmToNick(user.sNick, tSettings.sBot, tCommands[cmd].fFunction(user, msg)), true
				else
					if tSettings.sPmOnly then
						return Core.SendPmToNick(user.sNick, tSettings.sBot, tCommands[cmd].fFunction(user, msg)), true
					else
					    return Core.SendToNick(user.sNick, "<"..tSettings.sBot.."> "..tCommands[cmd].fFunction(user, msg)), true
					end
				end
			else
				if to and to == tSettings.sBot then
					return Core.SendPmToNick(user.sNick, tSettings.sBot, "*** Error: You are not allowed to use this command!"), true
				else
					return Core.SendToNick(user.sNick, "<"..tSettings.sBot.."> *** Error: You are not allowed to use this command!"), true
				end
			end
		end
	end
end

ToArrival = ChatArrival

tCommands = {
	tophubbers = {
		fFunction = function(user, data)
			-- Table isn't empty
			if next(tOnline) then
				-- Parse limits
				local _,_, iStart, iEnd = data:find("^%S+%s+(%d+)%-(%d+)$")
				-- Set if not set
				iStart, iEnd = (iStart or 1), (iEnd or tSettings.iMax)
				-- Header
				local tCopy, msg = {}, "\r\n\t"..string.rep("=", 137).."\r\n\tNr.  Total:\t\t\t\t\t\tSession:\t"..
				"Entered Hub:\tLeft Hub:\t\tRank:\t\tStatus:\tName:\r\n\t"..string.rep("-", 240).."\r\n"
				-- Loop through hubbers
				for i, v in pairs(tOnline) do
					-- Insert stats to temp table
					table.insert(tCopy, { sEnter = v.Enter, iSessionTime = tonumber(v.SessionTime),
					iTotalTime = tonumber(v.TotalTime), sLeave = v.Leave, sNick = i, sRank = GetRank(i) } )
				end
				-- Sort by total time
				table.sort(tCopy, function(a, b) return (a.iTotalTime > b.iTotalTime) end)
				-- Loop through temp table
				for i = iStart, iEnd, 1 do
					-- i exists
					if tCopy[i] then
						-- Populate
						local sStatus, v = "*Offline*", tCopy[i]; local sRank = v.sRank
						if Core.GetUser(v.sNick) then sStatus = "*Online*" end
						if v.sRank:len() < 9 then sRank = sRank.."\t" end
						msg = msg.."\t"..i..".    "..MinutesToTime(v.iTotalTime).."\t"..v.iSessionTime..
						" min\t"..v.sEnter.."\t"..v.sLeave.."\t"..sRank.."\t"..sStatus.."\t"..v.sNick.."\r\n"
					end
				end
				msg = msg.."\t"..string.rep("-", 240)
				-- Send
				return  "Current Top Hubbers:\r\n"..msg.."\r\n"
			else
				return "*** Error: Top Hubbers' table is currently empty!"
			end
		end,
		tLevels = {
			[-1] = false, [0] = true, [1] = true, [2] = true, [3] = true, [4] = true,
		},
		tRC = { { "Show Top "..tSettings.iMax.." Hubbers", "" }, { "Show Top x-y Hubbers", " %[line:x-y]" } }
	},
	hubtime = {
		fFunction = function(user, data)
			-- Parse nick
			local _,_, nick = data:find("^%S+%s+(%S+)$")
			-- Exists
			if nick then 
				-- Return
				return BuildStats(user, nick)
			else
				return "*** Select a user in the nick list!"
			end
		end,
		tLevels = { 
			[-1] = false, [0] = true, [1] = true, [2] = true, [3] = true, [4] = true,
		},
		tRC = { { "Click on any User to see their Stats", " %[nick]" }, { "Show a User's Stats [Enter Nick]", " %[line:Nick]" } }
	},
	myhubtime = {
		fFunction = function(user)
			-- Return
			return BuildStats(user, user.sNick)
		end,
		tLevels = { 
			[-1] = false, [0] = true, [1] = true, [2] = true, [3] = true, [4] = true,
		},
		tRC = { { "Show My Stats", "" } }
	},
}

BuildStats = function(user, nick)
	local tNick = GetOnliner(nick)
	-- In DB
	if tNick then
		-- Average uptime in days
		local iAverage = os.difftime(os.time(os.date("!*t")), tNick.Julian)/(60*60*24)
		if iAverage < 1 then iAverage = 1 end
		-- Generate message
		local sMsg = "\r\n\r\n\t"..string.rep("=", 51).."\r\n\t\t\tStats:\r\n\t"..
		string.rep("-", 89).."\r\n\t- Nick: "..nick.."\r\n\t- Total uptime: "..
		MinutesToTime(tNick.TotalTime, true).."\r\n\t- Daily average uptime (AUT): "..
		MinutesToTime((tNick.TotalTime/iAverage), true).."\r\n\t- Current Rank: "..GetRank(nick).."\n\t- Hub Standing: "..GetNumber(nick).."\r\n"
		-- Send stats 
		--Add any custom message
		return "Here are the stats you requested for "..nick..". Remember, users with over "..tSettings.iAUT.." hour(s) (AUT) will be considered for VIP, and may bypass the Hub full rule. Those below "..tSettings.iMin.." hour(s) (AUT) will be disconnected!"  ..sMsg
		else
			return "*** Error: No record found for '"..nick.."'!"
	end
end

GetRank = function(nick)
	local tNick = GetOnliner(nick)
	if tNick then
		-- Custom time table
		local tTime, sRank, iAverage = { s = 1/60, m = 1, h = 60, D = 60*24, W = 60*24*7, M = 60*24*30, Y = 60*24*30*12 }, tSettings.tRanks[tSettings.sCriteria:lower()][1][1]
		-- Average enabled
		if tSettings.bAverage then
			-- Days since first login
			iAverage = os.difftime(os.time(os.date("!*t")), tNick.Julian)/(60*60*24)
			if iAverage < 1 then iAverage = 1 end
		end
		-- For each rank
		for n in ipairs(tSettings.tRanks[tSettings.sCriteria:lower()]) do
			local iTime = 0
			-- For each digit and time string
			for i, v in tSettings.tRanks[string.lower(tSettings.sCriteria)][n][2]:gmatch("(%d+)(%w)") do
				-- Process
				if i and tTime[v] then iTime = iTime + i*tTime[v] end
			end
			local iValue = tNick.TotalTime
			-- Average
			if tSettings.bAverage then iValue = iValue/iAverage end
			-- Process rank if user hasn't logged in for the first time today
			if os.date("%d%m%y", tNick.Julian) ~= os.date("%d%m%y") and iValue > iTime then
				sRank = tSettings.tRanks[tSettings.sCriteria:lower()][n][1]
			end
		end
		return sRank
	end
end

GetNumber = function(nick)
  if next(tOnline) then
    local tCopy,iCount = {},0
    for i, v in pairs(tOnline) do
      table.insert(tCopy, { iTotalTime = tonumber(v.TotalTime), sNick = i } )
      iCount = iCount + 1
    end
    table.sort(tCopy, function(a, b) return (a.iTotalTime > b.iTotalTime) end)
    for i = 1, iCount do
      if tCopy[i] then
        local v = tCopy[i]
        if v.sNick:lower() == nick:lower() then
          return i
        end
      end
    end
  end
end

MinutesToTime = function(iSeconds, bSmall)
	-- Build table with time fields
	local T = os.date("!*t", tonumber(iSeconds*60)); 
	-- Format to string
	local sTime = string.format("%i year(s), %i month(s), %i day(s), %i hour(s), %i minute(s)", T.year-1970, T.month-1, T.day-1, T.hour, T.min)
	-- Small stat?
	if bSmall then
		-- For each digit
		for i in sTime:gmatch("%d+") do
			-- Reduce if is preceeded by 0
			if tonumber(i) == 0 then sTime = sTime:gsub("^"..i.."%s(%S+),%s", "") end
		end
	end
	-- Return
	return sTime
end

GetOnliner = function(user)
	-- For each hubber
	for i, v in pairs(tOnline) do
		-- Compare
		if i:lower() == user:lower() then
			-- Return
			return tOnline[i]
		end
	end
end

Serialize = function(tTable, sTableName, hFile, sTab)
	sTab = sTab or "";
	hFile:write(sTab..sTableName.." = {\n");
	for key, value in pairs(tTable) do
		if (type(value) ~= "function") then
			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
	end
	hFile:write(sTab.."}");
end
[\code]
Living is easy with eyes closed.

DeAn

Thanks merlin_xl54. But the script in API 1 version had this thing which I found missing in the API 2 version.
 bastya_elvtars:
    Changed: any user can use the hubtime command (01/27/2007)
    Changed:!hubtime without nick returns own hubtime (myhubtime kept for legacy reasons) (01/27/2007)
    Changed: + can also be used as a comand prefix (01/27/2007)


!hubtime without nick returns own hubtime


Can this be added ? Thanks in advance.
Thanks,

DeAn

merlin_xl54

Quote from: DeAn on 30 March, 2010, 16:05:01
Thanks merlin_xl54. But the script in API 1 version had this thing which I found missing in the API 2 version.

!hubtime without nick returns own hubtime

Can this be added ? Thanks in advance.

This script has "!myhubtime" which returns your own hubtime.

M
Living is easy with eyes closed.

DeAn

-- Send hubtime stats on connect [true = on; false = off]
	bRankOnConnect = false,


Even if I made this true, hubtime stats are not shown on startup. Any fix ?
Thanks,

DeAn

WitchHunter

Hi all

I have come across a strange problem.

If a user has the Away message activated and he/she checks his/her own uptime, he/she gets disconnected from the hub.
The hub is using PtokaX 0.4.1.1 as hubsoft and the script is a slightly modyfied version of the original Tophubbers 2.03 (additional profiles has been added).

It seems that the number of the profile is not the issue, since also Crew members with profile nr 1 (Operator) are getting disconnected for the same reason.

Anyone here who has experienced the same kind of behavior?

All help/advice is mostly appreciated :)

Regards

speedX

#58
Quote from: DeAn on 31 March, 2010, 20:44:37
Even if I made this true, hubtime stats are not shown on startup. Any fix ?

try this...
--[[

	TopHubbers 2.03b - LUA 5.1.2 [Strict][API 2] by jiten
	????????????????????????????????????????????????????
	Based on: OnHub Time Logger 1.65 by chill and Robocop's layout

	Usage: !tophubbers; !tophubbers x-y; !hubtime <nick>; !myhubtime

	CHANGELOG:
	??????????
	Fixed: Typo in table.sort function;
	Added: OnExit (3/21/2006)
	Fixed: Missing pairs() in SaveToFile
	Changed: Removed iGlobalTime and added TotalTime count to OnTimer
	Changed: SecondsToTime function values (3/24/2006)
	Changed: math.floor/mod in TopHubbers' function; (3/5/2006)
	Changed: SecondsToTime month value (4/17/2006);
	Added: !hubtime <nick> - requested by speedX;
	Changed: SecondsToTime function and small code bits (8/16/2006)
	Changed: Table indexes;
	Changed: SecondsToTime function to MinutesToTime;
	Fixed: Inaccurate average uptime stuff (8/17/2006)
	Changed: Average uptime function;
	Changed: Session time for offline users doesn't get reset;
	Added: Average uptime warning on connect - requested by speedX (8/20/2006)
	Added: Customized profiles - requested by Naithif (8/20/2006)
	Added: User Commands - requested by TT;
	Added: Rankings and related commands [!myrank & !topranks] - requested by speedX;
	Added: Toggle rank info on connect - requested by TT;
	Fixed: !tophubbers x-y;
	Added: Comments to the code;
	Changed: Some code bits;
	Added: Toggle between total and average uptime (8/24/2006)
	Fixed: Minimum average uptime warning - reported by speedX;
	Added: Maximum shown hubbers - requested by Naithif (8/29/2006)
	Fixed: LUA 5.0/5.1 compatibility - reported by speedX (11/8/2006)
	Added: string.lower check - requested by SwapY and speedX (11/10/2006)
	Changed: Script converted to API 2 (11/24/2007)
	Fixed: Changed Serialize function (12/23/2007)
	
	+Changes from 2.03a	07/26/09
	
	Added: Send messages in PM (01/22/2008) by speedX
	Added: Timer to save data on regular intervals (07/18/2008) by speedX
	Added: Kick user below Minimum Average uptime (iMin) (6/20/2009) by merlin_xl54-CrazyGuy
	Added: Table to exclude certain nicks from kick (tExc) (6/24/2009) by merlin_xl54-CrazyGuy
	Added: Show total years added in displayed times (7/26/2009) by speedX
	Fixed: Error when bWarning is false (1-10-2010) by merlin_xl54
	Update for profile permission changes in PxLua API [version 0.4.1.2 and later] (1/22/2010) by merlin_xl54
	Added: Option to return stats by selecting nick in user list (3/1/2010) by merlin_xl54
	Added: Numeric rank in the hub stats for total time connected (3/17/2010) by speedX
	Fixed: Option for RankOnConnect (5\6\2010) by speedX
   
]]--

tSettings = {
	-- Bot Name
	sBot = SetMan.GetString(21),
	
	-- Top Hubbers' DB
	fOnline = "scripts/tOnliners.tbl",

	-- RightClick Menu
	sMenu = "Top Hubbers",

	-- Maximum hubbers to show when using !tophubbers
	iMax = 15,

	-- Send message to users with lower than specified Average uptime (AUT) [true = on; false = off]
	bWarning = false,
	
	-- Minimum Average uptime (hours) that triggers the warning
	iAUT = 12,
	
	-- Minimum Average uptime (hours) that triggers the kick [Disable = 0]
	iMin = 0,
	
	-- Send hubtime stats on connect [true = on; false = off]
	bRankOnConnect = true,

	-- Profiles checked [false = off; true = on]
	tProfiles = { [-1] = false, [0] = true, [1] = true, [2] = true, [3] = true, [4] = true },

	-- Ranks criteria ["average" = Average total uptime; "total" = Total uptime]
	sCriteria = "average",
	
	-- Reply in PM ?
	bPmOnly = true,
	
	-- Set your interval time to save data(in Hours)
	iInterval = 24,
	
	--Exclude from kick
	tExc = {
	["yournickhere"] = true,
	},

	-- Ranks
	tRanks = { 
--[[		
		
	The ranks must be added in ascending order [from the lowest to the highest]
	{ "Rank", [time][string] }

	[time] must be 1 or more digit(s)
	[string] must be: s = second; m = minute; h = hour; D = day; W = week; M = month; Y = year

	Example: { "God", "1M, 2D, 10s" } 
	Meaning: To become a God, your total uptime must be equal or higher than 1 month, 2 days and 10 seconds
]]--

-- Total uptime rank table
		total = {
			{ "Newbie", "1D, 1h, 1m, 1s" }, { "Member", "2D" }, { "Cool Member", "5D" }, 
			{ "Hub As", "10D" }, { "Smart As", "20D" }, { "Double As", "1M" }, 
			{ "Triple As", "2M" }, { "Conqueror", "3M" }, { "Viking", "4M" }, 
			{ "King", "6M" }, { "Emperor", "8M" }, { "Hub Legend", "10M" }, 
			{ "Hub God", "11M" }, { "God", "1Y, 1h, 1m, 1s" },
		},

-- Daily average uptime rank table
		average = { 
			{ "Newbie", "1h" }, { "Member", "6h" }, { "Cool Member", "12h" }, 
			{ "Hub-As", "1D" }, { "Smart As", "5D" }, { "Double-As", "15D" }, 
			{ "Triple-As", "1M" }, { "Conqueror", "2M" }, { "Viking", "3M" }, 
			{ "King", "4M" }, { "Emperor", "6M" }, { "Hub Legend", "9M" }, 
			{ "Hub God", "11M" }, { "God", "1Y" },
		},
	},
}

tOnline = {}

OnStartup = function()
	-- Register BotName if not registered
	if tSettings.sBot ~= SetMan.GetString(21) then Core.RegBot(tSettings.sBot,"","",true) end
	-- Load DB content
	if loadfile(tSettings.fOnline) then dofile(tSettings.fOnline) end
	-- Set and Start Timer
	tSettings.iTimer = TmrMan.AddTimer(60*1000)
	--Save Data Interval
	tSettings.SaveData = TmrMan.AddTimer(tSettings.iInterval*60*60*1000)
end 

OnTimer = function(iID)
	if tSettings.iTimer and iID == tSettings.iTimer then
		-- For each hubber
		for i, v in pairs(tOnline) do
			-- Online
			if Core.GetUser(i) then
				-- Sum
				v.SessionTime = v.SessionTime + 1; v.TotalTime = v.TotalTime + 1
			end
		end
			elseif tSettings.SaveData and iID == tSettings.SaveData then
			local hFile = io.open(tSettings.fOnline, "w+") Serialize(tOnline, "tOnline", hFile); hFile:close()
	end
end

OnExit = function()
	-- Save
	local hFile = io.open(tSettings.fOnline, "w+") Serialize(tOnline, "tOnline", hFile); hFile:close()
end

UserConnected = function(user)
	-- If profile has permission to be logged
	if tSettings.tProfiles[user.iProfile] and tSettings.tProfiles[user.iProfile] == true then
		local tNick = GetOnliner(user.sNick)
		-- User already in DB
		if tNick then
			-- Warning on connect
			if tSettings.bWarning then
				-- Days since first login
				local iAverage = os.difftime(os.time(os.date("!*t")), tNick.Julian)/(60*60*24)
				if iAverage < 1 then iAverage = 1 end
				-- Less than allowed
					if tNick.TotalTime/iAverage < tSettings.iMin*60 then 
					-- Kick if not excluded
						if not tSettings.tExc[user.sNick] then
						-- Add any custom message to kick
						Core.Kick(user, tSettings.sBot, "*** Your Average uptime (AUT) is less than "..tSettings.iMin..
						" hour(s). Please post to our forum before you try to connect again!")
						end
					end
					-- Warn if not kicked
					if tNick.TotalTime/iAverage < tSettings.iAUT*60 then 
					-- Add any custom message to warning
					Core.SendPmToNick(user.sNick, tSettings.sBot, "*** Your Average uptime (AUT) is less than "..tSettings.iAUT..
					" hour(s). Users above this average will be considered for VIP, and may log in when the Hub is full. Those below "..tSettings.iMin.." hour(s) (AUT) will be disconnected!")
					--Warn if between iMin & iAUT and excluded from kick
					else
					if tNick.TotalTime/iAverage < tSettings.iAUT*60 then
						if tNick.TotalTime/iAverage > tSettings.iMin*60 then 
							if tSettings.tExc[user.sNick] then
							-- Add any custom message to warning
							Core.SendPmToNick(user.sNick, tSettings.sBot, "*** Your Average uptime (AUT) is less than "..tSettings.iAUT..
							" hour(s). Users above this average will be considered for VIP, and may log in when the Hub is full. Those below "..tSettings.iMin.." hour(s) (AUT) will be disconnected!")
							end
						end
					end
				end
			end
			-- Reset and save time
			tNick.SessionTime = 0; tNick.Enter = os.date()
			-- Send rank info on connect
			if tSettings.bRankOnConnect then Core.SendToNick(user.sNick,"<"..tSettings.sBot.."> "..tCommands["myhubtime"].fFunction(user)) end
			else
			-- Create new entry
			tOnline[user.sNick] = { Julian = os.time(os.date("!*t")), Enter = os.date(), SessionTime = 0, TotalTime = 0, Leave = os.date() }
		end
	end
	-- Supports UserCommands
	if Core.GetUserValue(user,12) then
		-- For each entry in table
		for i, v in pairs(tCommands) do
			-- If member
			if v.tLevels[user.iProfile] then
				-- For each type
				for n in ipairs(v.tRC) do
					-- Send
					Core.SendToNick(user.sNick, "$UserCommand 1 3 "..tSettings.sMenu.."\\"..v.tRC[n][1]..
					"$<%[mynick]> !"..i..v.tRC[n][2].."&#124;")
				end
			end
		end
	end
end

OpConnected = UserConnected
RegConnected = UserConnected

UserDisconnected = function(user)
	local tNick = GetOnliner(user.sNick)
	-- If profile must be logged and user is in DB
	if tSettings.tProfiles[user.iProfile] and tSettings.tProfiles[user.iProfile] == true and tNick then
		-- Log date
		tNick.Leave = os.date()
	end
end

OpDisconnected = UserDisconnected
RegDisconnected = UserDisconnected

ChatArrival = function(user,data)
	local _,_, to = data:find("^$To:%s(%S+)%s+From:")
	local _,_, msg = data:find("%b<>%s(.*)|$") 
	-- Message sent to Bot or in Main
	if (to and to == tSettings.sBot) or not to then
		-- Parse command
		local _,_, cmd = msg:find("^%p(%S+)")
		-- Exists
		if cmd and tCommands[cmd:lower()] then
			cmd = cmd:lower()
			-- If user has permission
			if tCommands[cmd].tLevels[user.iProfile] then
				if to and to == tSettings.sBot then
					return Core.SendPmToNick(user.sNick, tSettings.sBot, tCommands[cmd].fFunction(user, msg)), true
				else
					if tSettings.bPmOnly then
						return Core.SendPmToNick(user.sNick, tSettings.sBot, tCommands[cmd].fFunction(user, msg)), true
					else
					   return Core.SendToNick(user.sNick, "<"..tSettings.sBot.."> "..tCommands[cmd].fFunction(user, msg)), true
					end
				end
			else
				if to and to == tSettings.sBot then
					return Core.SendPmToNick(user.sNick, tSettings.sBot, "*** Error: You are not allowed to use this command!"), true
				else
					return Core.SendToNick(user.sNick, "<"..tSettings.sBot.."> *** Error: You are not allowed to use this command!"), true
				end
			end
		end
	end
end

ToArrival = ChatArrival

tCommands = {
	tophubbers = {
		fFunction = function(user, data)
			-- Table isn't empty
			if next(tOnline) then
				-- Parse limits
				local _,_, iStart, iEnd = data:find("^%S+%s+(%d+)%-(%d+)$")
				-- Set if not set
				iStart, iEnd = (iStart or 1), (iEnd or tSettings.iMax)
				-- Header
				local tCopy, msg = {}, "\r\n\t"..string.rep("=", 137).."\r\n\tNr.  Total:\t\t\t\t\t\tSession:\t"..
				"Entered Hub:\tLeft Hub:\t\tRank:\t\tStatus:\tName:\r\n\t"..string.rep("-", 240).."\r\n"
				-- Loop through hubbers
				for i, v in pairs(tOnline) do
					-- Insert stats to temp table
					table.insert(tCopy, { sEnter = v.Enter, iSessionTime = tonumber(v.SessionTime),
					iTotalTime = tonumber(v.TotalTime), sLeave = v.Leave, sNick = i, sRank = GetRank(i) } )
				end
				-- Sort by total time
				table.sort(tCopy, function(a, b) return (a.iTotalTime > b.iTotalTime) end)
				-- Loop through temp table
				for i = iStart, iEnd, 1 do
					-- i exists
					if tCopy[i] then
						-- Populate
						local sStatus, v = "*Offline*", tCopy[i]; local sRank = v.sRank
						if Core.GetUser(v.sNick) then sStatus = "*Online*" end
						if v.sRank:len() < 9 then sRank = sRank.."\t" end
						msg = msg.."\t"..i..".    "..MinutesToTime(v.iTotalTime).."\t"..v.iSessionTime..
						" min\t"..v.sEnter.."\t"..v.sLeave.."\t"..sRank.."\t"..sStatus.."\t"..v.sNick.."\r\n"
					end
				end
				msg = msg.."\t"..string.rep("-", 240)
				-- Send
				return  "Current Top Hubbers:\r\n"..msg.."\r\n"
			else
				return "*** Error: Top Hubbers' table is currently empty!"
			end
		end,
		tLevels = {
			[-1] = false, [0] = true, [1] = true, [2] = true, [3] = true, [4] = true,
		},
		tRC = { { "Show Top "..tSettings.iMax.." Hubbers", "" }, { "Show Top x-y Hubbers", " %[line:x-y]" } }
	},
	hubtime = {
		fFunction = function(user, data)
			-- Parse nick
			local _,_, nick = data:find("^%S+%s+(%S+)$")
			-- Exists
			if nick then 
				-- Return
				return BuildStats(user, nick)
			else
				return "*** Select a user in the nick list!"
			end
		end,
		tLevels = { 
			[-1] = false, [0] = true, [1] = true, [2] = true, [3] = true, [4] = true,
		},
		tRC = { { "Click on any User to see their Stats", " %[nick]" }, { "Show a User's Stats [Enter Nick]", " %[line:Nick]" } }
	},
	myhubtime = {
		fFunction = function(user)
			-- Return
			return BuildStats(user, user.sNick)
		end,
		tLevels = { 
			[-1] = false, [0] = true, [1] = true, [2] = true, [3] = true, [4] = true,
		},
		tRC = { { "Show My Stats", "" } }
	},
}

BuildStats = function(user, nick)
	local tNick = GetOnliner(nick)
	-- In DB
	if tNick then
		-- Average uptime in days
		local iAverage = os.difftime(os.time(os.date("!*t")), tNick.Julian)/(60*60*24)
		if iAverage < 1 then iAverage = 1 end
		-- Generate message
		local sMsg = "\r\n\r\n\t"..string.rep("=", 51).."\r\n\t\t\tStats:\r\n\t"..
		string.rep("-", 89).."\r\n\t- Nick: "..nick.."\r\n\t- Total uptime: "..
		MinutesToTime(tNick.TotalTime, true).."\r\n\t- Daily average uptime (AUT): "..
		MinutesToTime((tNick.TotalTime/iAverage), true).."\r\n\t- Current Rank: "..GetRank(nick).."\n\t- Hub Standing: "..GetNumber(nick).."\r\n"
		-- Send stats 
		--Add any custom message
		return "Here are the stats you requested for "..nick..". Remember, users with over "..tSettings.iAUT.." hour(s) (AUT) will be considered for VIP, and may bypass the Hub full rule. Those below "..tSettings.iMin.." hour(s) (AUT) will be disconnected!"  ..sMsg
		else
			return "*** Error: No record found for '"..nick.."'!"
	end
end

GetRank = function(nick)
	local tNick = GetOnliner(nick)
	if tNick then
		-- Custom time table
		local tTime, sRank, iAverage = { s = 1/60, m = 1, h = 60, D = 60*24, W = 60*24*7, M = 60*24*30, Y = 60*24*30*12 }, tSettings.tRanks[tSettings.sCriteria:lower()][1][1]
		-- Average enabled
		if tSettings.bAverage then
			-- Days since first login
			iAverage = os.difftime(os.time(os.date("!*t")), tNick.Julian)/(60*60*24)
			if iAverage < 1 then iAverage = 1 end
		end
		-- For each rank
		for n in ipairs(tSettings.tRanks[tSettings.sCriteria:lower()]) do
			local iTime = 0
			-- For each digit and time string
			for i, v in tSettings.tRanks[string.lower(tSettings.sCriteria)][n][2]:gmatch("(%d+)(%w)") do
				-- Process
				if i and tTime[v] then iTime = iTime + i*tTime[v] end
			end
			local iValue = tNick.TotalTime
			-- Average
			if tSettings.bAverage then iValue = iValue/iAverage end
			-- Process rank if user hasn't logged in for the first time today
			if os.date("%d%m%y", tNick.Julian) ~= os.date("%d%m%y") and iValue > iTime then
				sRank = tSettings.tRanks[tSettings.sCriteria:lower()][n][1]
			end
		end
		return sRank
	end
end

GetNumber = function(nick)
  if next(tOnline) then
    local tCopy,iCount = {},0
    for i, v in pairs(tOnline) do
      table.insert(tCopy, { iTotalTime = tonumber(v.TotalTime), sNick = i } )
      iCount = iCount + 1
    end
    table.sort(tCopy, function(a, b) return (a.iTotalTime > b.iTotalTime) end)
    for i = 1, iCount do
      if tCopy[i] then
        local v = tCopy[i]
        if v.sNick:lower() == nick:lower() then
          return i
        end
      end
    end
  end
end

MinutesToTime = function(iSeconds, bSmall)
	-- Build table with time fields
	local T = os.date("!*t", tonumber(iSeconds*60)); 
	-- Format to string
	local sTime = string.format("%i year(s), %i month(s), %i day(s), %i hour(s), %i minute(s)", T.year-1970, T.month-1, T.day-1, T.hour, T.min)
	-- Small stat?
	if bSmall then
		-- For each digit
		for i in sTime:gmatch("%d+") do
			-- Reduce if is preceeded by 0
			if tonumber(i) == 0 then sTime = sTime:gsub("^"..i.."%s(%S+),%s", "") end
		end
	end
	-- Return
	return sTime
end

GetOnliner = function(user)
	-- For each hubber
	for i, v in pairs(tOnline) do
		-- Compare
		if i:lower() == user:lower() then
			-- Return
			return tOnline[i]
		end
	end
end

Serialize = function(tTable, sTableName, hFile, sTab)
	sTab = sTab or "";
	hFile:write(sTab..sTableName.." = {\n");
	for key, value in pairs(tTable) do
		if (type(value) ~= "function") then
			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
	end
	hFile:write(sTab.."}");
end
Thanking You,

speedX

DeAn

The script is working great. Thanks a lot speedX  :)
Thanks,

DeAn

SMF spam blocked by CleanTalk