Код
local sDataBaseName = "123" -- имя базы данных (должна уже существовать!)
local sDbUser = "123" -- имя пользователя
local sDbPass = "123" -- пароль пользователя
local sDbHost = "localhost" -- адрес сервера бд
local sDbPort = 3306 -- порт сервера бд (3306 по умолчанию)
-- Впишите ваши ники сюда или используйте команды по правому клику мышки
Hidden = {"Артёмка",}
-- Скрыть от всех пользователей? true/false [false = Hide from non ops, ops may always list hidden users]
local HideFromAll = false
-- Interval in ms, where MyINFO will be resent
Int = 750
--
local tAllowProfiles = { --Доступность команд для профилей (true - да / false - нет):
[0] = true, --Главный администратор
[1] = true, --Администратор
[2] = true, --Шеф
[3] = true, --Оператор
[4] = true, --VIP
[5] = true, --Юзер
[-1] = true, --Незарегестрированный
}
tProfileName = { -- название профилей
[0] = "Главный администратор",
[1] = "Администратор",
[2] = "Шеф",
[3] = "Оператор",
}
local tProfileNames = {
[0] = "Главный администратор",
[1] = "Администратор",
[2] = "Шеф",
[3] = "Оператор",
[4] = "Шеф",
[5] = "Пользователь",
[-1] = "Незарегистрированный пользователь",
}
local tCmds = {
sGetNickInfo = "инфо",
sGetNicksIpInfo = "нсин",
sGetIpsInfo = "исин",
sInfo = "bd",
}
local tLang = {
NoData = "[отсутствует]",
OnLine = "Онлайн",
OffLine = "Оффлайн",
Yes = "Да",
No = "Нет",
From = "с",
To = "до",
sLowName = "Имя в БД",
sNick = "Ник",
sClient = "DC-Клиент",
sClientVersion = "Версия клиента",
bActive = "Прямое соединение",
sIP = "IP-Адрес",
bOperator = "Права администрации",
iShareSize = "Шара",
iProfile = "Статус",
iHubs = "Хабы",
iSlots = "Слоты",
sTag = "Тег",
sDescription = "Описание",
sEmail = "E-Mail",
InfoAbout = "Информация о пользователе",
MainInfo = "Общая информация",
IpHistory = "История посещения пользователя",
HistoryLimit = "лимит установлен в %s записей",
AlreadyAtHub = "текущее время (на хабе)",
UsedByNickIps = "Использованные ником IP-адреса:",
IpInfo = "Информация о никах IP-адреса %s пользователя %s (%s, #%s в базе)):",
IpInfoShot = "Информация о никах IP-адреса %s (#%s в базе):",
WasUsedMsg = "использовался %s раз, последнее время входа на хаб - %s",
BdAllInfo = "*** В базе данных скрипта userinfo находится: %s ников + %s уникальных IP-адресов; Нагрузка скрипта на процессор сервера",
EnterNick = "*** %s, введите ник, чтобы посмотреть оффлайн информацию о нем!",
EnterIP = "*** %s, введите IP-адрес, чтобы посмотреть оффлайн информацию о нем!",
NoSuchNick = "*** %s, ника \"%s\" нет в базе скрипта!",
NoSuchIP = "*** %s, IP-адреса \"%s\" нет в базе скрипта!",
NoAccess = "*** %s, у тебя нет доступа к команде \"%s%s\"!",
OnOrOff = "*** Статистика ведётся с 11.01.2010",
EnterNickHere = "Введите ник:",
EnterIpHere = "Введите IP-Адрес:",
GetInfoOnEnterUser = "Информация по нику",
GetInfoOnThisUser = "Информация по этому нику",
GetNicksIpInfoOnEnterUser = "Информация о пользователе по IP",
GetNicksIpInfoOnThisUser = "Информация этого пользователя по IP",
GetIpsInfoOnEnterUser = "Информация по IP",
GetIpsInfoOnEnterThisUser = "Информация о его(её) IP",
GetDbInfo = "Статистика базы данных",
}
local tFormat = {
"sLowName",
"sNick",
"sIP",
"sTag",
"sDescription",
"sEmail",
"sClient",
"sClientVersion",
"bActive",
"bOperator",
"iShareSize",
"iProfile",
"iHubs",
"iSlots",
}
Mem = function() collectgarbage("collect") return string.format("%-.2f Kb.",collectgarbage("count")) end
local sLine = string.rep("-", 150)
local sUserCmdsWay = "Информация\\"
local sDataFormat = "%H:%M:%S %d-%m-%y"
local tShareUnits = {"Б", "КБ", "МБ", "ГБ", "ТБ", "ПБ"}
local tRusLowerLetters = {["А"]="а",["Б"]="б",["В"]="в",["Г"]="г",["Д"]="д",["Е"]="е",["Ё"]="ё",["Ж"]="ж",["З"]="з",["И"]="и",["Й"]="й",["К"]="к",["Л"]="л",["М"]="м",["Н"]="н",["О"]="о",["П"]="п",["Р"]="р",["С"]="с",["Т"]="т",["У"]="у",["Ф"]="ф",["Х"]="х",["Ц"]="ц",["Ч"]="ч",["Ш"]="ш",["Щ"]="щ",["Ъ"]="ъ",["Ы"]="ы",["Ь"]="ь",["Э"]="э",["Ю"]="ю",["Я"]="я"}
local iUserVisitsLimit = 10 -- сколько записей о посещении хранить в базе данных
local bUpdateDataOnMyInfo = true -- обновлять ли данные при отправке юзером MyINFO
local Scp,File,Tmr = "HideMe 1.0b","Hidden.dat",0
OnStartup = function() if loadfile(File) then dofile(File) else Save(Hidden) end Hide() Int = math.max(Int,250) end
OnExit = function() Restore() end
UserConnected = function(user) Hide(user) end
RegConnected = UserConnected
MyINFOArrival = function(user,data) if Check(user.sNick:lower()) and Tmr == 0 then Tmr = TmrMan.AddTimer(750) end end
OnTimer = function(Id) if Id == Tmr then TmrMan.RemoveTimer(Tmr) Tmr = 0 Hide() end end
--[[ конец настроек! ]]
local con, env, sBot, sBotQ, sMenu
local iShareUnitsTableSize = #tShareUnits
local iFormatParamsCount = #tFormat
local sRn, sOq, sZp, sSp = "\r\n", "'", ",", " "
local tIpIds, tNickIds = {}, {}
local tMakeFunctions = {
sClientVersion = function(sData) if sData == "" then return tLang.NoData end return sData end,
bActive = function(sData) if sData == true then return tLang.Yes else return tLang.No end end,
bOperator = function(sData) if sData == true then return tLang.Yes else return tLang.No end end,
iShareSize = function(sData) return DoShareUnits(sData).." ("..sData.." "..tShareUnits[1]..")" end,
iProfile = function(sData) return tProfileNames[tonumber(sData)].." ("..sData..")" end,
sTag = function(sData) if sData == "" then return tLang.NoData end return sData end,
sEmail = function(sData) if not sData then return tLang.NoData end return sData end,
}
function OnStartup()
sBot = SetMan.GetString(21)
sBotQ = "<"..sBot.."> "
Load()
MakeMenu()
TmrMan.AddTimer(1000, "ClearMemory")
ClearMemory()
local tAll = Core.GetOnlineUsers(true)
for _, tUser in ipairs(tAll) do
UserConnected(tUser, 1)
end
OnStartup = nil
end
function OnExit()
local tAll = Core.GetOnlineUsers()
for _, tUser in ipairs(tAll) do
UserDisconnected(tUser, 2)
end
con:close() -- закрытие соединения с базой данных
env:close() -- уничтожение вызова библиотеки
end
function OnError(sErrorMsg)
OnExit()
local tScript = ScriptMan.GetScript() -- sName, bEnabled, iMemUsage
Core.SendToOps((sBotQ.."*** В скрипте %s произошла ошибка: %s|"):format(tScript.sName, sErrorMsg))
ScriptMan.StopScript(ScriptMan.GetScript().sName)
end
function ClearMemory()
collectgarbage("collect")
end
function Load()
require "luasql.mysql" -- подключаем библиотеку
env = assert (luasql.mysql()) -- вызываем основную функцию из библиотеки
-- соединяемся с базой данных (название_бд = "test", пользователь = "root", пароль_пользователя = "")
con = assert (env:connect(sDataBaseName, sDbUser, sDbPass, sDbHost, sDbPort))
con:execute("SET NAMES cp1251")
CreateDbTables()
Load = nil
end
function CreateDbTables()
con:execute("CREATE TABLE IF NOT EXISTS `ipsinfo` (iId INT PRIMARY KEY AUTO_INCREMENT, iIp VARCHAR(10) UNIQUE NOT NULL, sData TEXT NOT NULL)")
con:execute("CREATE TABLE IF NOT EXISTS `nicksinfo` (iId INT PRIMARY KEY AUTO_INCREMENT, sNick VARCHAR(64) UNIQUE NOT NULL, sData TEXT NOT NULL, sIps TEXT NOT NULL, sAllIps TEXT NOT NULL)")
CreateDbTables = nil
end
function MakeMenu()
local tMenu = {
"$UserCommand 1 1 "..sUserCmdsWay..tLang.GetInfoOnEnterUser.."$<%[mynick]> !"..tCmds.sGetNickInfo.." %[line:"..tLang.EnterNickHere.."]|",
"$UserCommand 1 2 "..sUserCmdsWay..tLang.GetInfoOnThisUser.."$<%[mynick]> !"..tCmds.sGetNickInfo.." %[nick]|",
"$UserCommand 1 1 "..sUserCmdsWay..tLang.GetNicksIpInfoOnEnterUser.."$<%[mynick]> !"..tCmds.sGetNicksIpInfo.." %[line:"..tLang.EnterNickHere.."]|",
"$UserCommand 1 2 "..sUserCmdsWay..tLang.GetNicksIpInfoOnThisUser.."$<%[mynick]> !"..tCmds.sGetNicksIpInfo.." %[nick]|",
"$UserCommand 1 1 "..sUserCmdsWay..tLang.GetIpsInfoOnEnterUser.."$<%[mynick]> !"..tCmds.sGetIpsInfo.." %[line:"..tLang.EnterIpHere.."]|",
"$UserCommand 1 2 "..sUserCmdsWay..tLang.GetIpsInfoOnEnterThisUser.."$<%[mynick]> !"..tCmds.sGetIpsInfo.." %[ip]|",
"$UserCommand 1 1 "..sUserCmdsWay..tLang.GetDbInfo.."$<%[mynick]> !"..tCmds.sInfo.."|",
}
sMenu = table.concat(tMenu, "|")
MakeMenu = nil
end
function LowString(sString)
for sBigLetter, sLowLetter in pairs(tRusLowerLetters) do
sString = sString:g(sBigLetter, sLowLetter)
end
return sString:lower()
end
function DoShareUnits(iSize)
local sFormatData = "%0.2f"
local iSize = tonumber(iSize) or 0
local sUnits = ""
for iTablePos = 1, iShareUnitsTableSize do
if iSize < 1024 or iTablePos == iShareUnitsTableSize then
sUnits = tShareUnits[iTablePos]
break
else
iSize = iSize / 1024
end
end
local sSize = sFormatData:format(iSize):g("%.", ",")
local s1stChar, s2ndChar = sSize:match("^%d+,(%d)(%d)$")
s1stChar, s2ndChar = tonumber(s1stChar), tonumber(s2ndChar)
if s2ndChar == 0 then
sSize = sSize:sub(1, -2)
if s1stChar == 0 then
sSize = sSize:sub(1, -3)
end
end
return sSize.." "..sUnits
end
function SerializeToString(tTable, sTableName)
local sTmp = ""
if sTableName then
sTmp = sTmp..sTableName.."="
end
sTmp = sTmp.."{"
for key, value in pairs(tTable) do
if type(value) ~= "userdata" then
local sKey = (type(key) == "string") and ("[%q]"):format(key) or ("[%d]"):format(key)
if (type(value) == "table") then
sTmp = sTmp..SerializeToString(value, sKey)
else
local sValue = (type(value) == "string") and ("%q"):format(value) or tostring(value)
sTmp = sTmp..sKey.."="..sValue
end
sTmp = sTmp..","
end
end
sTmp = sTmp.."}"
return sTmp
end
function UserConnected(tUser, iStatus)
local iDataNum = os.time()
if not iStatus then
Core.GetUserAllData(tUser)
end
iStatus = iStatus or 0
tUser = GetNormalValue(tUser)
local sLowName = LowString(tUser.sNick)
tUser.sLowName = sLowName
local iIp = Ip2Num(tUser.sIP)
tUser.iIp = iIp
local cur = con:execute(("SELECT `iId`, `sIps`, `sAllIps` FROM `nicksinfo` WHERE `sNick`='%s'"):format(sLowName:q()))
if cur:numrows() == 0 then
con:execute(("INSERT INTO `nicksinfo` VALUES (NULL, '%s', '{}', '{}', '{}')"):format(sLowName:q()))
cur = con:execute(("SELECT `iId`, `sIps`, `sAllIps` FROM `nicksinfo` WHERE `sNick`='%s'"):format(sLowName:q()))
end
local row = cur:fetch ({}, "a")
tNickIds[tUser.sNick] = {sLowName, row.iId}
local tSessions = loadstring("return "..row.sIps)()
if #tSessions >= iUserVisitsLimit then
local iRem = #tSessions - iUserVisitsLimit + 1
for i = 1, iRem do
table.remove(tSessions, 1)
end
end
table.insert(tSessions, {tUser.sIP, iStatus, iDataNum, 0})
local tAllIps = loadstring("return "..row.sAllIps)()
if tAllIps[tUser.sIP] then
tAllIps[tUser.sIP] = {tAllIps[tUser.sIP][1] + 1, iDataNum}
else
tAllIps[tUser.sIP] = {1, iDataNum}
end
cur:close()
con:execute(("UPDATE `nicksinfo` SET `sData`='%s', `sIps`='%s', `sAllIps`='%s' WHERE `iId`='%s'"):format(SerializeToString(tUser):q(), SerializeToString(tSessions):q(), SerializeToString(tAllIps):q(), row.iId))
cur = con:execute(("SELECT `iId`, `sData` FROM `ipsinfo` WHERE `iIp`='%s'"):format(iIp))
if cur:numrows() == 0 then
con:execute(("INSERT INTO `ipsinfo` VALUES (NULL, %s, '{}')"):format(iIp))
cur = con:execute(("SELECT `iId`, `sData` FROM `ipsinfo` WHERE `iIp`='%s'"):format(iIp))
end
row = cur:fetch ({}, "a")
tIpIds[tUser.sIP] = {iIp, row.iId}
local tDataInfo = loadstring("return "..row.sData)()
if tDataInfo[tUser.sNick] then
tDataInfo[tUser.sNick] = {tDataInfo[tUser.sNick][1] + 1, iDataNum}
else
tDataInfo[tUser.sNick] = {1, iDataNum}
end
cur:close()
con:execute(("UPDATE `ipsinfo` SET `sData`='%s' WHERE `iId`='%s'"):format(SerializeToString(tDataInfo):q(), row.iId))
if iStatus == 0 then
if tAllowProfiles[tUser.iProfile] then
if tUser.bUserCommand then
Core.SendToUser(tUser, sMenu)
end
end
end
end
OpConnected = UserConnected
RegConnected = UserConnected
function UserDisconnected(tUser, iStatus)
if not tNickIds[tUser.sNick] then
return
end
local iId = tNickIds[tUser.sNick][2]
iStatus = iStatus or 0
local sLowName = tNickIds[tUser.sNick][1]
local cur = con:execute(("SELECT `sIps` FROM `nicksinfo` WHERE `iId`='%s'"):format(iId))
local row = cur:fetch ({}, "a")
local tSessions = loadstring("return "..row.sIps)()
cur:close()
tSessions[#tSessions][4] = os.time()
if tSessions[#tSessions][2] == 1 then
if iStatus == 2 then
iStatus = 3
else
iStatus = 1
end
end
tSessions[#tSessions][2] = iStatus
con:execute(("UPDATE `nicksinfo` SET `sIps`='%s' WHERE `iId`='%s'"):format(SerializeToString(tSessions):q(), iId))
end
OpDisconnected = UserDisconnected
RegDisconnected = UserDisconnected
function MyINFOArrival(tUser)
if bUpdateDataOnMyInfo and tNickIds[tUser.sNick] and tIpIds[tUser.sIP] then
Core.GetUserAllData(tUser)
tUser = GetNormalValue(tUser)
tUser.sLowName = tNickIds[tUser.sNick][1]
tUser.iIp = tIpIds[tUser.sIP][1]
con:execute(("UPDATE `nicksinfo` SET `sData`='%s' WHERE `iId`='%s'"):format(SerializeToString(tUser):q(), tNickIds[tUser.sNick][2]))
end
end
function ChatArrival(tUser, sData)
if Core.GetUserValue(tUser,11) then
local _,_,cmd,elsedata = sData:lower():find("%b<> ["..SetMan.GetString(29).."](%S+)%s*(%S*)|")
local _,_,to = sData:find("^$To: (%S+) From:")
if cmd then
local msg,bot,bool = "",SetMan.GetString(21),false
cmd = cmd:lower()
if cmd == "inv" or cmd == "инв" then
msg,bool = "скрылся",true
local ret = Check(tUser.sNick:lower())
if ret then
table.remove(Hidden,ret) msg = "показался" Hide(nil,tUser.sNick) Restore(tUser.sNick)
else
table.insert(Hidden,tUser.sNick) Hide()
end
Save(Hidden)
msg = ""..tProfileName[tUser.iProfile].." "..tUser.sNick.." "..msg.." в списке юзеров.|"
elseif cmd == "invs" or cmd == "инвс" then
msg,bool = "На данный момент нет скрытых ников.",true
if next(Hidden) then
msg = "\n\n\tСписок [ "..tostring(#Hidden).." ] Спрятаных Юзеров\n\n\t"
msg = msg..table.concat(Hidden,"\n\t").."\n\n"
end
elseif cmd == "invuser" or cmd == "инвюзер" then
msg,bool = "скрыл в списке юзера",true
local ret = Check(elsesData:lower())
if ret then
table.remove(Hidden,ret) msg = "возвратил видимость в списке юзеру" Hide(nil,elsesData) Restore(elsesData)
else
table.insert(Hidden,elsesData) Hide()
end
Save(Hidden)
msg = ""..tProfileName[tUser.iProfile].." "..tUser.sNick.." "..msg.." "..elsesData..".|"
end
if bool and msg:len() > 0 then
if to then Core.SendPmToUser(tUser,bot,msg) else Core.SendToOps("<"..bot.."> "..msg) end
return bool
end
end
end
sData = sData:sub(1, -2)
local sChatMsg = sData:match("^%b<>%s(.*)")
local sPref, sCmd, sElseData = sChatMsg:match("^%s*(%p)(%S+)%s*(%S*)")
if sCmd then
sCmd = sCmd:lower()
local sLowElseData = LowString(sElseData)
if sCmd == tCmds.sGetNickInfo or sCmd == "info" then
if not tAllowProfiles[tUser.iProfile] then
Core.SendToUser(tUser, sBotQ..tLang.NoAccess:format(tUser.sNick, sPref, sCmd))
return true
end
if sElseData == "" then
Core.SendToUser(tUser, sBotQ..tLang.EnterNick:format(tUser.sNick))
else
local sMsg = MakeNickInfoData(sElseData, sLowElseData)
if not sMsg then
sMsg = tLang.NoSuchNick:format(tUser.sNick, sElseData)
end
Core.SendToUser(tUser, sBotQ..sMsg)
end
return true
elseif sCmd == tCmds.sGetNicksIpInfo or sCmd == "nseen" then
if not tAllowProfiles[tUser.iProfile] then
Core.SendToUser(tUser, sBotQ..tLang.NoAccess:format(tUser.sNick, sPref, sCmd))
return true
end
if sElseData == "" then
Core.SendToUser(tUser, sBotQ..tLang.EnterNick:format(tUser.sNick))
else
local sMsg = MakeNicksIpInfoData(sElseData, sLowElseData)
if not sMsg then
sMsg = tLang.NoSuchNick:format(tUser.sNick, sElseData)
end
Core.SendToUser(tUser, sBotQ..sMsg)
end
return true
elseif sCmd == tCmds.sGetIpsInfo or sCmd == "iseen" then
if not tAllowProfiles[tUser.iProfile] then
Core.SendToUser(tUser, sBotQ..tLang.NoAccess:format(tUser.sNick, sPref, sCmd))
return true
end
if sElseData == "" then
Core.SendToUser(tUser, sBotQ..tLang.EnterIP:format(tUser.sNick))
else
local sMsg = MakeIpInfoData(sElseData)
if not sMsg then
sMsg = tLang.NoSuchIP:format(tUser.sNick, sElseData)
end
Core.SendToUser(tUser, sBotQ..sMsg)
end
return true
elseif sCmd == tCmds.sInfo or sCmd == "бд" or sCmd == "стат" or sCmd == "статс" or sCmd == "stat" then
if not tAllowProfiles[tUser.iProfile] then
Core.SendToAll(sBotQ..tLang.NoAccess:format(tUser.sNick, sPref, sCmd))
return true
end
local cur = con:execute("SELECT `iId` FROM `nicksinfo`")
local iNum1 = cur:numrows()
cur:close()
local cur = con:execute("SELECT `iId` FROM `ipsinfo`")
local iNum2 = cur:numrows()
cur:close()
local sMsg = tLang.BdAllInfo:format(iNum1, iNum2)
Core.SendToAll(sData)
Core.SendToAll(sBotQ..sMsg.." "..Mem())
return true
end
end
end
Check = function(nick) for i,v in ipairs(Hidden) do if nick == v:lower() then return i end end return false end
Hide = function(user,op)
if op then local usr = Core.GetUser(op) if usr then return Core.SendToAll(Core.GetUserValue(usr,1).."|") end end
for i,v in ipairs(Hidden) do
local msg = "$Quit "..v.."|"
if user then
Core.SendToUser(user,msg)
else
if HideFromAll then
Core.SendToAll(msg)
else
Core.SendToProfile(-1,msg)
for i,v in ipairs(ProfMan.GetProfiles()) do
if not ProfMan.GetProfile(i-1).tProfilePermissions.bIsOP then
Core.SendToProfile(i-1,msg)
end
end
end
end
end
end
function MakeNickInfoData(sElseData, sLowElseData)
local cur = con:execute(("SELECT * FROM `nicksinfo` WHERE `sNick`='%s'"):format(sLowElseData:q()))
if cur:numrows() == 0 then
return
end
local row = cur:fetch ({}, "a")
cur:close()
local tNeedUserData = loadstring("return "..row.sData)()
local tNeedIPsData = loadstring("return "..row.sIps)()
local tAllIps = loadstring("return "..row.sAllIps)()
local tHubNeedUser = Core.GetUser(tNeedUserData.sNick)
local sOnLine = tLang.OnLine
if not tHubNeedUser then
sOnLine = tLang.OffLine
end
local sMsg = sRn..sLine..sRn.."¦ "..tLang.InfoAbout..": "..sElseData.." ( "..sOnLine.." )"..sRn..sLine..sRn.."¦ "..tLang.MainInfo..":"..sRn
for sMakeDataName in pairs(tMakeFunctions) do
tNeedUserData[sMakeDataName] = tMakeFunctions[sMakeDataName](tNeedUserData[sMakeDataName])
end
for _, sDataName in ipairs(tFormat) do
sMsg = sMsg.."¦ "..tLang[sDataName]..": "..tNeedUserData[sDataName]..sRn
end
sMsg = sMsg..sLine..sRn.."¦ "..tLang.IpHistory.." ("..tLang.HistoryLimit:format(iUserVisitsLimit).."):"..sRn
for i, tCurIPsData in ipairs(tNeedIPsData) do
local sForm = os.date(sDataFormat, tCurIPsData[3])
local iStatus = tCurIPsData[2]
local sTo = ""
if tCurIPsData[4] == 0 then
sTo = tLang.AlreadyAtHub
else
sTo = os.date(sDataFormat, tCurIPsData[4])
end
local sSp = ""
if i < 10 then
sSp = " "
end
local sOnStartup, sOnExit = "", ""
if iStatus == 1 then
sOnStartup = "*"
elseif iStatus == 2 then
sOnExit = "*"
elseif iStatus == 3 then
sOnStartup = "*"
sOnExit = "*"
end
sMsg = sMsg.."¦_ "..sSp..i.."\t"..tCurIPsData[1].."\t\t"..tLang.From..": "..sForm..sOnStartup.."\t"..tLang.To..": "..sTo..sOnExit.."\t - "..GetNormalTime(((tCurIPsData[4] ~= 0 and tCurIPsData[4]) or os.time()) - tCurIPsData[3])..sRn
end
sMsg = sMsg.."¦ "..tLang.OnOrOff..sRn..sLine..sRn..
"¦ "..tLang.UsedByNickIps..sRn
for sIP, tData in pairs(tAllIps) do
sMsg = sMsg.."¦_ "..sIP..": "..tLang.WasUsedMsg:format(tData[1], os.date(sDataFormat, tData[2]))..sRn
end
sMsg = sMsg..sLine
return sMsg
end
function MakeNicksIpInfoData(sElseData, sLowElseData)
local cur = con:execute(("SELECT `sData` FROM `nicksinfo` WHERE `sNick`='%s'"):format(sLowElseData:q()))
if cur:numrows() == 0 then
return
end
local row = cur:fetch ({}, "a")
cur:close()
local tNeedUserData = loadstring("return "..row.sData)()
local sIP = tNeedUserData.sIP
local sMadeData, iId = MakeIpData(sIP)
return sRn..sLine..sRn.."¦ "..tLang.IpInfo:format(sIP, sElseData, sLowElseData, iId)..sRn..sLine..sRn..sMadeData..sLine
end
function MakeIpInfoData(sIP)
local sMsg, iId = MakeIpData(sIP)
if not sMsg then
return
end
return sRn..sLine..sRn.."¦ "..tLang.IpInfoShot:format(sIP, iId)..sRn..sLine..sRn..sMsg..sLine
end
function MakeIpData(sIP)
local sMsg = ""
local cur = con:execute(("SELECT `iId`, `sData` FROM `ipsinfo` WHERE `iIp`='%s'"):format(Ip2Num(sIP)))
if cur:numrows() == 0 then
return
end
local tIpData = cur:fetch ({}, "a")
cur:close()
local tDataInfo = loadstring("return "..tIpData.sData)()
for sNick, tData in pairs(tDataInfo) do
sMsg = sMsg.."¦_ "..sNick..": "..tLang.WasUsedMsg:format(tData[1], os.date(sDataFormat, tData[2]))..sRn
end
return sMsg, tIpData.iId
end
function string.q(sData)
return sData:g("'", "\\'")
end
function Return(sData)
if type(sData) == "function" then
return sData
end
return function()
return sData
end
end
Restore = function(arg)
local o,t = "$OpList ",{}
for _,user in ipairs(Core.GetOnlineOps()) do
u,ul = user.sNick,user.sNick:lower()
if arg then if not Check(ul) then table.insert(t,u) end else table.insert(t,u) end
end
if next(t) then o = o..table.concat(t,"$$").."$$" end
Core.SendToAll(o.."|")
end
Save = function(tab)
local f,e = io.open(File,"wb")
if f then
local s = ""
if next(tab) then
for i,v in pairs(tab) do s = s..string.format("%q",v).."," end
s = "{"..s:sub(1,-2).."}"
else
s = "{}"
end
if s:len() > 0 then f:write("Hidden = "..s) end
f:flush() f:close()
end
end
function string.g(sData, s1, s2)
return sData:gsub(s1, Return(s2))
end
function GetNormalTime(s)
s=tonumber(s) or 0
local r=""
if s>=31104000 then r=math.floor(s/31104000).." г " s=math.fmod(s,31104000) end
if s>=2592000 then r=r..math.floor(s/2592000).." мес " s=math.fmod(s,2592000) end
if s>=86400 then r=r..math.floor(s/86400).." д " s=math.fmod(s,86400) end
if s>=3600 then r=r..math.floor(s/3600).." ч " s=math.fmod(s,3600) end
if s>=60 then r=r..math.floor(s/60).." мин " s=math.fmod(s,60) end
return r..s.." с"
end
-- by Setuper
function Ip2Num(sIP)
local a,b,c,d=sIP:match"^(%d+)%.(%d+)%.(%d+)%.(%d+)$"
if not a or not b or not c or not d then return 0 end
return a*16777216+b*65536+c*256+d
end
function GetNormalValue(tUser)
if not tUser.sTag then
local sDescription,sTag,sClient,sClientVersion,sMode,iNormalHubs,iRegHubs,iOpHubs,iSlots,iLlimit = tUser.sDescription:match"(.*)(<(.+)%sV?:?(.-),M:(.-),H:(%d+)/(%d+)/(%d+),S:(%d+)>)$"
if not sDescription then
sDescription,sTag,sClient,sClientVersion,sMode,iNormalHubs,iRegHubs,iOpHubs,iSlots,iLlimit = tUser.sDescription:match"(.*)(<(.+)%sV?:?(.-),M:(.-),H:(%d+)/(%d+)/(%d+),S:(%d+),L:(%d+)>)$"
end
if not sDescription then
sDescription,sTag,sClient,sClientVersion,sMode,iNormalHubs,iRegHubs,iOpHubs,iSlots,iLlimit = tUser.sDescription:match"(.*)(<(.+)%sV?:?(.-),M:(.-),H:(%d+)/(%d+)/(%d+),S:(%d+),B:(%d+)>)$"
end
tUser.sDescription=sDescription
tUser.sTag=sTag
tUser.sClient=sClient
tUser.sClientVersion=sClientVersion
tUser.sMode=sMode
tUser.iNormalHubs=iNormalHubs
tUser.iRegHubs=iRegHubs
tUser.iOpHubs=iOpHubs
tUser.iHubs=iNormalHubs and iRegHubs and iOpHubs and (iNormalHubs + iRegHubs + iOpHubs)
tUser.iSlots=iSlots
tUser.iLlimit=iLlimit
end
return tUser
end