IP2Area Description - LUA 5.1x [Strict][API 2]
 

IP2Area Description - LUA 5.1x [Strict][API 2]

Started by speedX, 18 May, 2009, 21:34:03

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.

speedX

--[[

      IP2Area Description Script [API 2]
      Made by speedX    (19/05/2009)
      Version 2.0
      (Based on Hungarista's Area Script)
     
      Description:
        Adds Area in Description according to IP Range
       
      For Example:
       If the area name of range 192.168.1.0-192.168.1.255 is stored as "New York"
       then the user within that range will have "New York" as his Description
     
      Changes by speedX:
        + If user doesn't want to reveal his area then put "NO AREA" in capital(without quotes) in description
        + Added command:
          +unknownrange - Gets unknown IP range of users currently logged on hub
       
]]--

RegDbFile = "IP2AREA.dat"
NickFile = "noarea.dat"
sBot = SetMan.GetString(21)

function OnStartup()
  RegDbFile = Core.GetPtokaXPath().."scripts/"..RegDbFile
  NickFile = Core.GetPtokaXPath().."scripts/"..NickFile
  TmrMan.AddTimer(30000)
  if loadfile(RegDbFile) ~= nil then
    dofile(RegDbFile)
  else
      IPRanges ={}
      Save_File(RegDbFile,IPRanges,"IPRanges")
  end
  if loadfile(NickFile) ~= nil then
    dofile(NickFile)
  else
      tNicks = {}
      Save_File(NickFile,tNicks,"tNicks")
  end
end

UserConnected = function(user)
  Core.SendToNick(user.sNick,"<"..sBot.."> Welcome "..user.sNick..", speedX's IP2Area 2.0 is enabled. RightClick for menu.")
  if Core.GetUserValue(user,12) then
      for i,v in pairs(tCommands) do
         if v.tLevels[user.iProfile] then
            for n in ipairs(v.tRC) do
               Core.SendToNick(user.sNick, "$UserCommand 1 3 IP2Area\\"..v.tRC[n][1].."$<%[mynick]> +"..i..v.tRC[n][2].."&#124;")
            end
         end
      end
   end
end
OpConnected = UserConnected
RegConnected = UserConnected

function MyINFOArrival(user,data)
  local usr,desc,clt,ver,mode,hubs,slots = data:match("$MyINFO $ALL (%S+) (.*)<(%S+) V:(.+),M:(%S),H:([0-9/]+),S:(%d+)")
  local nick = user.sNick:lower()
  if desc ~= "NO AREA" then
    if tNicks[nick] then
      tNicks[nick] = nil
      Save_File(NickFile,tNicks,"tNicks")
    end
  elseif desc == "NO AREA" then
      if not tNicks[nick] then
        tNicks[nick] = 1
        Save_File(NickFile,tNicks,"tNicks")
      end
  end
end 
 
function OnTimer()
  for i,v in ipairs(Core.GetOnlineUsers(true)) do
  local nick = v.sNick:lower()
    if not tNicks[nick] then
      if CheckRanges(v.sIP) then
        local myinfo = "$MyINFO $ALL "..v.sNick.." "..CheckRanges(v.sIP).." - "..(v.sDescription or "")..(v.sTag or "").."$ $"..(v.sConnection or "")..string.char(v.iMagicByte or "").."$"..(v.sEmail or "").."$"..(v.iShareSize or "").."$"
        Core.SendToAll(myinfo)
        Clear()
      end
    end
  end
end

ChatArrival = function(user,data)
  local _,_,to = string.find(data,"^$To:%s(%S+)%s+From:")
  local _,_,cmd = string.find(data,"%b<> %p(%w+)")
  if cmd and tCommands[cmd:lower()] then
    cmd = cmd:lower()
    if tCommands[cmd].tLevels[user.iProfile] then
      return tCommands[cmd].sFunction(user,data)
    else
      return Core.SendToNick(user.sNick,"<"..sBot.."> Error: You are not allowed to use this command!"), true
    end
  end
end
ToArrival = ChatArrival

tCommands = {
  addrange = {
    sFunction = function(user,data)
      local _,_,from,to,area = string.find(data,"%b<> %p%w+ (%d+.%d+.%d+.%d+)-(%d+.%d+.%d+.%d+) (.*)|")
      if from and to and area then
          table.insert(IPRanges,{from,to,area})
          Save_File(RegDbFile,IPRanges,"IPRanges")
          Core.SendToNick(user.sNick,"<"..sBot.."> IP-Range: "..from.." - "..to.." has been successfully added with Area: "..area)
          return true
      else
        Core.SendToNick(user.sNick,"<"..sBot.."> Invalid IP or Area. Use +addrange <Start_Range>-<End_Range> <Area_name>")
        return true
      end
    end,
  tLevels = {[-1] = false,[0] = true,[1] = true,[2] = false,[3] = false},
  tRC = { { "Add Range", " %[line:Start Range]-%[line:End Range] %[line:Area]" } },
  },
  getrangelist = {
    sFunction = function(user,data)
      local border = "\r\n\t"..string.rep("-",100).."\r\n\t"
      local str = border.."Sr.\tFrom:\t\tTo:\t\tArea"..border
      for a,b in pairs(IPRanges) do
        str = str.."[ "..a.." ]\t"..b[1].."\t"..b[2].."\t"..b[3].."\r\n\t"
      end
      Core.SendPmToNick(user.sNick,sBot,str)
      return true
    end,
   tLevels = {[-1] = false,[0] = true,[1] = true,[2] = false,[3] = false},
   tRC = { { "Get RangeList", "" } },
   },
  delrange = {
    sFunction = function(user,data)
      local _,_,n = string.find(data,"%b<> %p%w+ (%d+)|")
      n = tonumber(n)
      if n > #IPRanges then
        Core.SendToNick(user.sNick,"<"..sBot.."> Invalid range no.")
        return true
      else
        table.remove(IPRanges,n)
        Save_File(RegDbFile,IPRanges,"IPRanges")
        Core.SendToNick(user.sNick,"<"..sBot.."> Range No. "..n.." has been deleted from database.")
        return true
      end
    end,
  tLevels = {[-1] = false,[0] = true,[1] = true,[2] = false,[3] = false},
  tRC = { { "Delete Range", " %[line:Range no.]" } },
  },
  unknownrange = {
    sFunction = function(user,data)
      for i,v in ipairs(Core.GetOnlineUsers()) do
        if not CheckRanges(v.sIP) then
          Core.SendPmToNick(user.sNick,sBot,"Unrecognized IP: "..v.sIP.." from Nick: "..v.sNick)
        end
      end
      return true
    end,
    tLevels = {[-1] = false,[0] = true,[1] = true,[2] = false,[3] = false},
    tRC = { { "Unknown Range", "" } },
  }
}

Clear = function()
   collectgarbage()
   io.flush()
end

ComputeIP = function(IP)
   local _,_,a,b,c,d = string.find(IP,"(%d+).(%d+).(%d+).(%d+)")
   if a and b and c and d then
      a,b,c,d = tonumber(a),tonumber(b),tonumber(c),tonumber(d)
      return ((a*16777216) + (b*65536) + (c*256) + d)
   end
end

CheckRanges = function(IP)
   if IP then
      local ip = ComputeIP(IP)
      for i,v in ipairs(IPRanges) do
         local x,y = v[1],v[2]
         local a,b = ComputeIP(x),ComputeIP(y)
         if ip >= a and ip <= b then
            return v[3]
         end
      end
   end
end
 
Save_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
         Save_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

Save_File = function(file,table , tablename )
   local hFile = io.open (file , "w")
   Save_Serialize(table, tablename, hFile);
   hFile:close()
   Clear()
end


Add an IP-Range with its Area name.
So the users logging in within that range will have the preset Area name in their Description.
Thanking You,

speedX

Pedja

I copied this script, pasted it into Scipts form in Ptokax, started Check Syntax and got:

Syntax [string "--[[..."]:24: attempt to index global 'SetMan' (a nil value)

I guess this is too old for Ptokax 0.4.1.2?

speedX

Nope...
You must start the hub before enabling the script.
Thanking You,

speedX

Pedja


speedX

Thanking You,

speedX

Pedja

It seems this syntax eror is not iportant, as I found out that scripts seem to be working anyways.

It recognizes commands +unknownrange and +addrange

Comamnd +addrange  says

Invalid IP or Area. Use +addip <Start_Range>-<End_Range> <Area_name>


but +addip seems as not recognized. I tried

+addip 192.168.1.1-192.168.1.254 local


But hub acts I did not type the command. Is this correct syntax for +addip ?

What is poroper syntax for contents of IP2AREA.dat? May I add ip ranges by editing this file?

Pedja

Ok, I got it. There is error in script that states that comand is +addip. It is actually +addrange

So, here is a little help for novice users like me:


- Copy script code form first message
- Open Ptokax GUI, click on Scripts
- Paste code in top left window (the biggest)
- Click Save and save it as IP2AreaDescription.lua
- Click Refresh Scripts
- check CheckBox for IP2AreaDescription.lua
- connect to Hub as Master
- type +unknownrange. if bot reponds with private mesage everything is ok

Commands:

+unknownrange
Shows list of IP ranges used by connected users which are not part of any known IP lists

+addrange <Start_Range>-<End_Range> <Area_name>
Adds IP range to list. Example: +addrange 192.168.1.1-192.168.1.254 mylocalnet

+getrangelist
shows list od known IP ranges

+delrange <Range_Number>
Delete range form list. <Range_Number> is order number shown with +getrangelist


speedX

Quote from: Pedja on 16 February, 2011, 10:31:04
Ok, I got it. There is error in script that states that comand is +addip. It is actually +addrange

Fixed and Updated first post. Thanks for the report. ;)
Thanking You,

speedX

Pedja

I have added some new functionality to the script, and fixed some more things:

        + data structure is expanded for Prefix field
        + there is ForcePrefix to set if prefix will be used in user Nicks
        + if prefix is set, user must put it in his Nick. Otherwise he will not be allowed
        to connect
        + several prefixes may be defined for single IP range. User may set any of them
        + if Prefix is set to empty, nil or contains # prefix will not be forced for that IP range
        + welcome message is now optional, use ShowWelcome to enable it
        + user is optionally hailed on connection with info what IP area he belongs to
        + other users are optionaly informed of IP range info for connected user      
      + script responds in the same window command is sent. Both public Chat and Private Chat
        are supported
      + if there are no unknown IP's +unknownrange returns that info too. Originaly, in such
        cases there would be no reposnd, which is confusing
        + display of ip ranges fixed to be more readable       


speedX, should I post source here or send zou as private message to checkout?


Pedja

As there is no response, here is the slightly altered version of this script available to everyone.

--[[

      IP2Area Description and Prefix Script [API 2]
      Made by speedX    (19/05/2009) as IP2Area Description Script [API 2]
	  Altered by Pedja (17/02/2011)
      Version 2.0.14
      (Based on Hungarista's Area Script)
      (Based on IP2Area Description Script [API 2] v 2.0, http://forum.ptokax.org/index.php?topic=8380.0)
      
      Description:
        Adds Area in Description according to IP Range
		Optionally forces prefixes in user names according to IP range. Several prefixes 
		may pre defined for single IP range by delimting them with comma.
        
      For Example:
       If the area name of range 192.168.1.0-192.168.1.255 is stored as area "New York"
	   with prefix [ny],[apple] then the user within that range will be forced to place 
	   prefix ([ny] or [apple]) in his Nick and have "New York" as his Description 
	   
      
	  Changes by speedX:
        + If user doesn't want to reveal his area then put "NO AREA" in capital(without quotes) in description
        + Added command:
        +unknownrange - Gets unknown IP range of users currently logged on hub
		  
      Changes by Pedja
        + data structure is expanded for Prefix field
        + there is ForcePrefix to set if prefix will be used in user Nicks
        + if prefix is set, user must put it in his Nick. Otherwise he will not be allowed 
		  to connect
        + several prefixes may be defined for single IP range. User may set any of them
        + if Prefix is set to empty, nil or contains # prefix will not be forced for that IP range
        + welcome message is now optional, use ShowWelcome to enable it
        + user is optionally hailed on connection with info what IP area he belongs to
        + other users are optionaly informed of IP range info for connected user		
		+ script responds in the same window command is sent. Both public Chat and Private Chat 
		  are supported
		+ if there are no unknown IP's +unknownrange returns that info too. Originaly, in such 
		  cases there would be no reposnd, which is confusing
        + display of ip ranges fixed to be more readable		  
		
		

      Commands:

       +unknownrange
       Shows list of IP ranges used by connected users which are not part of any known IP lists

       +addrange <Start_Range>-<End_Range> <Area_name> <Prefixes>
       Adds IP range to list. You may set several optional prefixes delimited by comma. 
	   If you do not want prefiox for IP range, put # as Prefix
	   Example: +addrange 192.168.1.1-192.168.1.254 mylocalnet [mynet],[local]

       +getrangelist
       Shows list od known IP ranges

       +delrange <Range_Number>
       Delete range form list. <Range_Number> is order number shown with +getrangelist
	   
		
		
        
]]--

RegDbFile = "DescLogs/IP2AREA.dat"
NickFile = "DescLogs/noarea.dat"
sBot = SetMan.GetString(21)

-- set ForcePrefix to true if you want to force prefixes on user names
ForcePrefix = true

-- show IP2Area welcome to user?
ShowWelcome = false

-- show Hail to user with IP range info?
ShowIPRangeInfo = true

-- Notify everyone in public chat about IP range info of connected user
NotifyEveryone = true

function OnStartup()
  TmrMan.AddTimer(30000)
  if loadfile(RegDbFile) ~= nil then
    dofile(RegDbFile)
  else
      os.execute("mkdir DescLogs")
      IPRanges ={}
      Save_File(RegDbFile,IPRanges,"IPRanges")
  end
  if loadfile(NickFile) ~= nil then
    dofile(NickFile)
  else
      os.execute("mkdir DescLogs")
      tNicks = {}
      Save_File(NickFile,tNicks,"tNicks")
  end
end

UserConnected = function(user)

  local mNickPrefix = user.sNick:match("%[(.*)%]")
  if mNickPrefix == nil then 
    mNickPrefix = "" 
  end

  -- Optionally show wellcome message to user
  if ShowWelcome then
    Core.SendToNick(user.sNick,"<"..sBot.."> Welcome "..user.sNick..", speedX's IP2Area 2.0 is enabled. RightClick for menu.")
  end
  
  if Core.GetUserValue(user,12) then
      for i,v in pairs(tCommands) do
         if v.tLevels[user.iProfile] then
            for n in ipairs(v.tRC) do
               Core.SendToNick(user.sNick, "$UserCommand 1 3 IP2Area\\"..v.tRC[n][1].."$<%[mynick]> +"..i..v.tRC[n][2].."&#124;")
            end
         end
      end
   end

  -- Get description for user's IP range
  local mNetworkDesc = CheckRanges(user.sIP)
  -- Get allowed prefixes for user's IP range (if several prefixes they will be delimited by comma)
  local mNetworkPrefix = CheckRangesPrefix(user.sIP)
  
  -- Optionally show IP range information to user
  if (ShowIPRangeInfo) then
    Core.SendToNick(user.sNick,"<"..sBot.."> "..user.sNick..", your IP is " ..user.sIP.. " and your network is "..mNetworkDesc)
  end
  
  
  local user_connected = true
  
  -- Now deal with prefixes
  if ForcePrefix and (mNetworkPrefix ~= "") then
  
	mPrefixpos = string.find ("," ..mNetworkPrefix.. ",", ",%[" ..mNickPrefix.. "%],")

	if mPrefixpos == nil then
		if mNickPrefix == "" then
		  mNickPrefix = "none"
		else
		  mNickPrefix = "[" ..mNickPrefix.. "]"
		end
		Core.SendToNick(user.sNick,"<"..sBot.."> Your prefix must be one from this list: " ..mNetworkPrefix.. ". You use " ..mNickPrefix.. ".")
		Core.SendToNick(user.sNick,"<"..sBot.."> Change prefix and then reconnect, please.")
		Core.Disconnect(user.sNick)
		user_connected = false
	end
  end

  -- Optionaly notify everyone on the hub about network user is coming from
  if NotifyEveryone and user_connected then
    Core.SendToAll("User " ..user.sNick.." from " ..mNetworkDesc.. " connected.")
  end

end
OpConnected = UserConnected
RegConnected = UserConnected

function MyINFOArrival(user,data)
  local usr,desc,clt,ver,mode,hubs,slots = data:match("$MyINFO $ALL (%S+) (.*)<(%S+) V:(.+),M:(%S),H:([0-9/]+),S:(%d+)")
  local nick = user.sNick:lower()
  if desc ~= "NO AREA" then
    if tNicks[nick] then
      tNicks[nick] = nil
      Save_File(NickFile,tNicks,"tNicks")
    end
  elseif desc == "NO AREA" then
      if not tNicks[nick] then
        tNicks[nick] = 1
        Save_File(NickFile,tNicks,"tNicks")
      end
  end
end  
  
function OnTimer()
  for i,v in ipairs(Core.GetOnlineUsers(true)) do
  local nick = v.sNick:lower()
    if not tNicks[nick] then
      if CheckRanges(v.sIP) then
        local myinfo = "$MyINFO $ALL "..v.sNick.." "..CheckRanges(v.sIP).." - "..(v.sDescription or "")..(v.sTag or "").."$ $"..(v.sConnection or "")..string.char(v.iMagicByte or "").."$"..(v.sEmail or "").."$"..(v.iShareSize or "").."$"
        Core.SendToAll(myinfo)
        Clear()
      end
    end
  end
end

ChatCommand = function(user,data,chattype)
  local _,_,to = string.find(data,"^$To:%s(%S+)%s+From:")
  local _,_,cmd = string.find(data,"%b<> %p(%w+)")
  if cmd and tCommands[cmd:lower()] then
    cmd = cmd:lower()
    if tCommands[cmd].tLevels[user.iProfile] then
      return tCommands[cmd].sFunction(user,data,chattype)
    else
	  return SendChatResponse (user.sNick, sBot, "Error: You are not allowed to use this command!", chattype), true
    end
  end
end

ChatArrival = function (user,data)
  return ChatCommand (user,data,"pub")
end

ToArrival = function (user,data)
  return ChatCommand (user,data,"priv")
end

tCommands = {
  addrange = {
    sFunction = function(user,data,chattype)
      local _,_,from,to,area,prefix = string.find(data,"%b<> %p%w+ (%d+.%d+.%d+.%d+)-(%d+.%d+.%d+.%d+) (.*) (.*)|")
	  
	  -- If prefix is empty or contains # then prefix will not be enforced for this IP range. 
	  -- Generaly prefix = "" means "do not force prefix".
	  if (prefix == nil) or (prefix == "#") then
	     prefix = ""
	  end
      if from and to and area then
          table.insert(IPRanges,{from,to,area,prefix})
          Save_File(RegDbFile,IPRanges,"IPRanges")

		  SendChatResponse (user.sNick, sBot, "IP-Range: "..from.." - "..to.." has been successfully added with Area: "..area.. " and prefix " ..prefix, chattype)

          return true
      else
		SendChatResponse (user.sNick, sBot, "Invalid IP or Area. Use +addrange <Start_Range>-<End_Range> <Area_name> <Prefix>", chattype)
        return true
      end
    end,
  tLevels = {[-1] = false,[0] = true,[1] = true,[2] = false,[3] = false},
  tRC = { { "Add Range", " %[line:Start Range]-%[line:End Range] %[line:Area] %[line:Prefix]" } },
  },
  getrangelist = {
    sFunction = function(user,data,chattype)
	  
      --local border = "\r\n\t"..string.rep("-",100).."\r\n\t"
      local str = "\r\n\r\n  Sr.\tFrom - To\t\t\tArea:Prefix\r\n"
	  str = str .. string.rep("-",100).."\r\n"
	  
      for a,b in pairs(IPRanges) do
        str = str .. " [ "..a.." ]\t"..b[1].."  -  "..b[2].."\t"..b[3].."  :  "..b[4].."\r\n"
      end

	  SendChatResponse (user.sNick, sBot, str, chattype)

      return true
    end,
   tLevels = {[-1] = false,[0] = true,[1] = true,[2] = false,[3] = false},
   tRC = { { "Get RangeList", "" } },
   },
  delrange = {
    sFunction = function(user,data,chattype)
      local _,_,n = string.find(data,"%b<> %p%w+ (%d+)|")
      n = tonumber(n)
      if n > #IPRanges then
		SendChatResponse (user.sNick, sBot, "Invalid range no.", chattype)
        return true
      else
        table.remove(IPRanges,n)
        Save_File(RegDbFile,IPRanges,"IPRanges")
		SendChatResponse (user.sNick, sBot, "Range No. "..n.." has been deleted from database.", chattype)
        return true
      end
    end,
  tLevels = {[-1] = false,[0] = true,[1] = true,[2] = false,[3] = false},
  tRC = { { "Delete Range", " %[line:Range no.]" } },
  },
  unknownrange = {
    sFunction = function(user,data,chattype)
	  local NoUnknown = true
      for i,v in ipairs(Core.GetOnlineUsers()) do
        if not CheckRanges(v.sIP) then
		  NoUnknown = false
		  SendChatResponse (user.sNick, sBot, "Unrecognized IP: "..v.sIP.." from Nick: "..v.sNick, chattype)
        end
      end
	  
	  if NoUnknown then
          SendChatResponse (user.sNick, sBot, "There are no unrecognized IP addresses", chattype)
	  end
	  
	  
      return true
    end,
    tLevels = {[-1] = false,[0] = true,[1] = true,[2] = false,[3] = false},
    tRC = { { "Unknown Range", "" } },
  }
}

Clear = function()
   collectgarbage()
   io.flush()
end

ComputeIP = function(IP)
   local _,_,a,b,c,d = string.find(IP,"(%d+).(%d+).(%d+).(%d+)")
   if a and b and c and d then
      a,b,c,d = tonumber(a),tonumber(b),tonumber(c),tonumber(d)
      return ((a*16777216) + (b*65536) + (c*256) + d)
   end
end

CheckRanges = function(IP)
   if IP then
      local ip = ComputeIP(IP)
      for i,v in ipairs(IPRanges) do
         local x,y = v[1],v[2]
         local a,b = ComputeIP(x),ComputeIP(y)
         if ip >= a and ip <= b then
            return v[3]
         end
      end
   end
end

CheckRangesPrefix = function(IP)
   if IP then
      local ip = ComputeIP(IP)
      for i,v in ipairs(IPRanges) do
         local x,y = v[1],v[2]
         local a,b = ComputeIP(x),ComputeIP(y)
         if ip >= a and ip <= b then
            return v[4]
         end
      end
   end
end

  
Save_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
         Save_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

Save_File = function(file,table , tablename )
   local hFile = io.open (file , "w")
   Save_Serialize(table, tablename, hFile);
   hFile:close()
   Clear()
end

SendChatResponse = function (nick, bot, user_message, chattype)
  if chattype == "pub" then
    return Core.SendToNick(nick,"<"..bot.."> " ..user_message)
  else
    return Core.SendPmToNick(nick,bot,user_message)
  end
  
end

speedX

#10
Hey guys, this is a new version of script wich also includes additions by Pedja and some bug fixes. Its kindof a beta release and i'll be posting a new version in a few days till then keep testing and post bugs if any :)

Quote
Note: The location of files has been changed to the main scripts folder. So move ur files from DescLogs folder to scripts folder.

--[[

      IP2Area Description and Prefix Script [API 2]
      Made by speedX    (19/05/2009)
      Altered by Pedja (17/02/2011)
      Version 2.0.18
      (Based on Hungarista's Area Script)
     
      Description:
     
      Adds Area in Description according to IP Range
     
      Optionally forces prefixes in user names according to IP range. Several prefixes
      may pre defined for single IP range by delimiting them with comma.
     
      For Example: if the area name of range 192.168.1.0-192.168.1.255 is stored as area "New York"
       with prefix [ny],[apple] then the user within that range will be forced to place
       prefix ([ny] or [apple]) in his Nick and have "New York" as his Description       
     
      There is option to set minimum share for each IP Area. Minimum share may be enforced by disconnecting
      user, or by just waring user. Sharing size check occurs when user connects to the hub and repeats
      periodicaly. Repeating is adjustable and may be turned off.
     
      Option to block download for users is also provided. It may be set to disallow any download for user
      who has share less than MinShare. If user has share less than NormShare, he will be allowed to download
      only from users who also have share less than NormShare. Users who have share larger than NormShare are
      allowed to download from everyone. This is all optional for whole hub, or for each IP area.
     
      There is another option to block downloading by assigning IP Areas to share groups. Users belonging to
      different share groups will not be able to download from each other. This is optional for whole hub,
      or for ecah IP Area separately.
     
      IP areas may overlap. For instance, you may seet one large IP Area, and then set some subranges within
      it. When matching IP Area, narower area will always be used.

      
     
      Version 1.0:
        + If user doesn't want to reveal his area then put "NO AREA" in capital(without quotes) in description
        + Added command: +unknownrange - Gets unknown IP range of users currently logged on hub
       
      Version 2.0.14
        + data structure is expanded for Prefix field
        + there is ForcePrefix to set if prefix will be used in user Nicks
        + if prefix is set, user must put it in his Nick. Otherwise he will not be allowed
          to connect
        + several prefixes may be defined for single IP range. User may set any of them
        + if Prefix is set to empty, nil or contains # prefix will not be forced for that IP range
        + welcome message is now optional, use ShowWelcome to enable it
        + user is optionally hailed on connection with info what IP area he belongs to
        + other users are optionaly informed of IP range info for connected user      
        + script responds in the same window command is sent. Both public Chat and Private Chat
          are supported
        + if there are no unknown IP's +unknownrange returns that info too. Originaly, in such
          cases there would be no reposnd, which is confusing
        + display of ip ranges fixed to be more readable       

      Version 2.0.15
        + user may be warned or disconnected if sharesize is lower than set for his network     
        + size of share may be set for each network
        + default share size may be set to be used if network share size is not set
        + sharesize may be optionally checked every n minutes
       
      Version 2.0.16
        + fixed problem with relative path to tables
        + ShareSize parameter replaced with MinShareSize
        + Parameter NormShareSize introduced
        + new function: blocking file download by share size (per network). If user has share size
          lower than MinShareSize (GB) he is not allowed to downlaod from anyone. If user has share
          size lower than NormShareSize (GB) he is alowed to download only from users that also have share
          size lower than NormShareSize. Users with share size larger than NormShareSize are allowed
          to download from anyone. MinShareSize and NormShareSize are settable for each IP area. If
          not set, then DefaultMinShareSize and DefaultNormShareSize are used.
        + blocking file download by share size is optional
        + new function: blocking file download by share group. Each IP area may be assigned to share group.
          Several IP areas may be assigned to the same group. If ForceShareGroups is true, only users who
          belong to the same share group will be able to download from each other. If share group is not
          set then IP area is assigned to DefaultShareGroup.
        + fixed issue when several ranges overlap. Now, if IP matches to several areas, area with the most
          narrow IP range is used. This allows to set one big IP range and then also add different settings
          for it's subranges.
        + optimized ip range matching. Until now, matching was repeated to get value for each table field. It
          is fixed to match just once and get all fields.
         
      Version 2.0.17
        + fixed problem with typecasting numeric values from table
        + fixed problem with nul values from table
        
      Version 2.0.18
        + added a help menu wich can be triggered by +ip2area.
        + fixed error when unrecognized ip enters the hub.
        + changed addrange command structure.
        + added option to set Description Refresh Time.
        + changed addrange display structure.
        + changed and optimized the way commands will be replied.
        + revised script structure.
        + changed file path to avoid errors. 

      Commands:

       +unknownrange
       Shows list of IP ranges used by connected users which are not part of any known IP lists

       +addrange <Start_Range>*<End_Range>*<Area_name>*<Prefixes>*<MinShareSize>*<NormShareSize>*<ShareGroup>
       Adds IP range to list. You may set several optional prefixes delimited by comma.
       If you do not want prefix for IP range, put # as Prefixes

       Parameters Start_Range, End_Range and Area_name are reqired. Other parameters are optional.
       
       Example: +addrange 192.168.1.1*192.168.1.254*mylocalnet*[mynet],[local]*10*100*mynet

       
       +getrangelist
       Shows list od known IP ranges

       +delrange <Range_Number>
       Delete range form list. <Range_Number> is order number shown with +getrangelist
       
       +ip2area
       Returns Help Menu 
      
           
]]--

-- Database Files
RegDbFile = "IP2AREA.dat"
NickFile = "noarea.dat"

-- Bot Name
sBot = SetMan.GetString(21)

-- set ForcePrefix to true if you want to force prefixes on user names
ForcePrefix = true

-- show IP2Area welcome to user?
ShowWelcome = true

-- show Hail to user with IP range info?
ShowIPRangeInfo = true

-- Notify everyone in public chat about IP range info of connected user
NotifyEveryone = true

-- set ForceShareSize to true if you want to force sharesize for users
ForceShareSize = false

-- Warn user who has too low share size
WarnShareSize = false

-- Repeat share size checked every ShareSizeTimer minutes. If 0, do not repeat
-- but check only on connection.
ShareSizeTimer = 30

-- set ForceDownloadBlocking to true if you want to prevent users to download
-- regarding their share size
ForceDownloadBlocking = false

-- Refresh Description of users every DescRefreshTimer minutes.
-- If 0, refresh after every 1 minute.
DescRefreshTimer = 1

-- Default min share size id network share size is not set (GB)
DefaultMinShareSize = 10

-- Default normal share size id network share size is not set (GB)
DefaultNormShareSize = 60

-- set ForceShareGroups to true if you want to prevent users to download
-- from users not belonging to their share group
ForceShareGroups = false

-- Default sharegroup used if IP area does not have specified group
DefaultShareGroup = "<none>"

function OnStartup()
  RegDbFile = Core.GetPtokaXPath().."scripts/"..RegDbFile
  NickFile = Core.GetPtokaXPath().."scripts/"..NickFile
  TmrMan.AddTimer(60000)
  if loadfile(RegDbFile) ~= nil then
    dofile(RegDbFile)
  else
      IPRanges ={}
      Save_File(RegDbFile,IPRanges,"IPRanges")
  end
  if loadfile(NickFile) ~= nil then
    dofile(NickFile)
  else
      tNicks = {}
      Save_File(NickFile,tNicks,"tNicks")
  end
end

UserConnected = function(user)

  local mNickPrefix = user.sNick:match("%[(.*)%]")
  if mNickPrefix == nil then
    mNickPrefix = ""
  end

  -- Optionally show wellcome message to user
  if ShowWelcome then
    Core.SendToNick(user.sNick,"<"..sBot.."> Welcome "..user.sNick..", speedX's IP2Area Description is enabled. RightClick for menu or type "..SetMan.GetString(29):sub(1,1).."ip2area.")
  end
 
  if Core.GetUserValue(user,12) then
      for i,v in pairs(tCommands) do
         if v.tLevels[user.iProfile] then
            for n in ipairs(v.tRC) do
               Core.SendToNick(user.sNick, "$UserCommand 1 3 IP2Area\\"..v.tRC[n][1].."$<%[mynick]> "..SetMan.GetString(29):sub(1,1)..i..v.tRC[n][2].."&#124;")
            end
         end
      end
   end

  if GetRange(user.sIP) then 
    local mUserNetwork = GetRange(user.sIP)

    -- Get description for user's IP range
    local mNetworkDesc = GetRangeDesc(mUserNetwork)
    -- Get allowed prefixes for user's IP range (if several prefixes they will be delimited by comma)
    local mNetworkPrefix = GetRangePrefix(mUserNetwork)
 
    -- Optionally show IP range information to user
    if (ShowIPRangeInfo) then
      Core.SendToNick(user.sNick,"<"..sBot.."> "..user.sNick..", your IP is "..user.sIP.." and your network is "..mNetworkDesc)
      if ForceShareGroups then
        local mUserShareGroup = GetRangeShareGroup(mUserNetwork)
        if mUserShareGroup ~= "" then
          Core.SendToNick(user.sNick,"<"..sBot.."> You belong to share group: "..mUserShareGroup)
        end
      end
    end
    local user_connected = true
 
    -- Now deal with prefixes
    if ForcePrefix and (mNetworkPrefix ~= "") then
      mPrefixpos = string.find ("," ..mNetworkPrefix.. ",", ",%[" ..mNickPrefix.. "%],")

      if mPrefixpos == nil then
        if mNickPrefix == "" then
          mNickPrefix = "none"
        else
          mNickPrefix = "[" ..mNickPrefix.. "]"
        end
        Core.SendToNick(user.sNick,"<"..sBot.."> Your prefix must be one from this list: "..mNetworkPrefix..". You use "..mNickPrefix..".")
        Core.SendToNick(user.sNick,"<"..sBot.."> Change prefix and then reconnect, please.")
        Core.Disconnect(user.sNick)
        user_connected = false
      end
    end

    -- Optionaly notify everyone on the hub about network user is coming from
    if NotifyEveryone and user_connected then
      Core.SendToAll("User " ..user.sNick.." from " ..mNetworkDesc.. " connected.")
    end

    HandleShareSize(user)
  end

end
OpConnected = UserConnected
RegConnected = UserConnected

function MyINFOArrival(user,data)
  local usr,desc,clt,ver,mode,hubs,slots = data:match("$MyINFO $ALL (%S+) (.*)<(%S+) V:(.+),M:(%S),H:([0-9/]+),S:(%d+)")
  local nick = user.sNick:lower()
  if desc ~= "NO AREA" then
    if tNicks[nick] then
      tNicks[nick] = nil
      Save_File(NickFile,tNicks,"tNicks")
    end
  elseif desc == "NO AREA" then
      if not tNicks[nick] then
        tNicks[nick] = 1
        Save_File(NickFile,tNicks,"tNicks")
      end
  end
end 

ConnectToMeArrival = function(user,data)
  local _,_,mSourceUserName = data:find("%$ConnectToMe%s(%S+)%s.*|")
  return HandleConnection(user,data,mSourceUserName)
end

RevConnectToMeArrival = function(user,data)
  local _,_,mSourceUserName = data:find("%$RevConnectToMe%s%S+%s(%S+)|")
  return HandleConnection(user,data,mSourceUserName)
end

 
function OnTimer()
  local CheckShareSize = false;
  local RefreshDesc = true;
 
  if ShareSizeTimer > 0 then
    if TimeCounter == nil then
      TimeCounter = 0
    end
    
    -- timer is triggeed every minute.
    TimeCounter = TimeCounter + 1
    
    if (TimeCounter >= (ShareSizeTimer)) then
      CheckShareSize = true
      TimeCounter = 0
    else
      CheckShareSize = false
    end
  end
  
  if DescRefreshTimer > 1 then
    RefreshDesc = false
    if RefreshTime == nil then
      RefreshTime = 0
    end
    
    RefreshTime = RefreshTime + 1
    
    if (RefreshTime >= (DescRefreshTimer)) then
      RefreshDesc = true
      RefreshTime = 0
    else
      RefreshDesc = false
    end
  end

  if RefreshDesc then
    for i,v in ipairs(Core.GetOnlineUsers(true)) do
    local nick = v.sNick:lower()
      if not tNicks[nick] then
        if GetRange(v.sIP) then
          if CheckShareSize then
            HandleShareSize(v)   
          end
          local mUserNetwork = GetRange(v.sIP)
          local mUserNetworkDesc = GetRangeDesc(mUserNetwork)
          if mUserNetworkDesc then
            local myinfo = "$MyINFO $ALL "..v.sNick.." "..mUserNetworkDesc.." - "..(v.sDescription or "")..(v.sTag or "").."$ $"..(v.sConnection or "")..string.char(v.iMagicByte or "").."$"..(v.sEmail or "").."$"..(v.iShareSize or "").."$"
            Core.SendToAll(myinfo)
            Clear()
          end
        end
      end
    end
  end
end

ChatArrival = function(user, data)
  local _,_,to = string.find(data,"^$To:%s(%S+)%s+From:")
  local _,_,cmd = string.find(data,"%b<> %p(%w+)")
  -- Message sent to Bot or in Main
  if (to and to == sBot) or not to then
    -- 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 == sBot then
          return Core.SendPmToNick(user.sNick,sBot,tCommands[cmd].sFunction(user,data)), true
        else
          return Core.SendToNick(user.sNick,"<"..sBot.."> "..tCommands[cmd].sFunction(user,data)), true
        end
      else
        if to and to == sBot then
          return Core.SendPmToNick(user.sNick,sBot,"*** Error: You are not allowed to use this command!"), true
        else
          return Core.SendToNick(user.sNick,"<"..sBot.."> *** Error: You are not allowed to use this command!"), true
        end
      end
    end
  end
end
ToArrival = ChatArrival

tCommands = {
  addrange = {
    sFunction = function(user,data)
    local _,_,from,to,area,prefix,minsharesize,normsharesize,sharegroup = string.find(data,"%b<> %p%w+ (%d+.%d+.%d+.%d+)%*(%d+.%d+.%d+.%d+)%*(.*)%*(%S+)%*(%d*)%*(%d*)%*(.*)|")
    
     -- If prefix is empty or contains # then prefix will not be enforced for this IP range.
     -- Generaly prefix = "" means "do not force prefix".
     if (prefix == nil) or (prefix == "#") then
        prefix = ""
     end
   
    minsharesize = tonumber(minsharesize)   
    normsharesize = tonumber(normsharesize)
   
    if (sharegroup == nil) then
      sharegroup = ""
    end
       
    if from and to and area then
      table.insert(IPRanges,{from,to,area,prefix,minsharesize,normsharesize,sharegroup})
      Save_File(RegDbFile,IPRanges,"IPRanges")
     
      if (minsharesize == nil) then
         minsharesize = "none"
      end
     
      if (normsharesize == nil) then
         normsharesize = "none"
      end
     
      if (sharegroup == "") then
        sharegroup = DefaultShareGroup
      end

      return "\r\n\tIP-Range: "..from.." - "..to.." has been successfully added with: \r\n\tArea: "..area.."\r\n\tPrefix: "..prefix.."\r\n\tShare Size: "..minsharesize.."/".. normsharesize .." GB\r\n\tSharegroup: "..sharegroup

    else
      return "Invalid IP or Area. Use +addrange <Start_Range>*<End_Range>*<Area_name>*<Prefixes>*<MinShareSize>*<NormShareSize>*<ShareGroup>"
      end
    end,
    tLevels = {[-1] = false,[0] = true,[1] = true,[2] = false,[3] = false},
    tHelp = " <Start_Range>*<End_Range>*<Area_name>*<Prefixes>*<MinShareSize>*<NormShareSize>*<ShareGroup>\tTo Add a New Range",
    tRC = { { "Add Range", " %[line:Start Range]*%[line:End Range]*%[line:Area]*%[line:Prefix]*%[line:MinShareSize]*%[line:NormShareSize]*%[line:ShareGroup]" } },
  },
  getrangelist = {
    sFunction = function(user,data)
    
      --local border = "\r\n\t"..string.rep("-",100).."\r\n\t"
      local str = "\r\n\r\n  Sr.\tFrom - To\t\t\tArea : Prefix - ShareSize min/max - Sharegroup\r\n"
      str = str..string.rep("-",140).."\r\n"

      local mMinsharesize = ""
      local mNormsharesize = ""
     
      for a,b in pairs(IPRanges) do

        if b[4] == nil then
          b[4] = ""
        end

        if (b[5] == nil) or (b[5] == "") then
          b[5] = ""
          mMinsharesize = "not set (" .. DefaultMinShareSize .. " GB)"
        else
          mMinsharesize = b[5] .. " GB"
        end

        if (b[6] == nil) or (b[6] == "") then
          b[6] = ""
          mNormsharesize = "not set (" .. DefaultNormShareSize .. " GB)"
        else
          mNormsharesize = b[6] .. " GB"
        end
       
        if (b[7] == nil) then
          mSharegroup = DefaultShareGroup
        else
          mSharegroup = b[7]
        end

        str = str .. " [ "..a.." ]\t"..b[1].."  -  "..b[2].."\t"..b[3].."  :  "..b[4].." - Share Size: "..mMinsharesize.."/"..mNormsharesize.." - Sharegroup: " .. mSharegroup .. "\r\n"
      end

     return str

    end,
   tLevels = {[-1] = false,[0] = true,[1] = true,[2] = false,[3] = false},
   tHelp = "\t\t\t\t\t\t\t\t\t\t\tView Range List",
   tRC = { { "Get RangeList", "" } },
   },
  delrange = {
    sFunction = function(user,data)
      local _,_,n = string.find(data,"%b<> %p%w+ (%d+)|")
      n = tonumber(n)
      if n > #IPRanges then
      return "Invalid range no."
      else
        table.remove(IPRanges,n)
        Save_File(RegDbFile,IPRanges,"IPRanges")
        return "Range No. "..n.." has been deleted from database."
      end
    end,
  tLevels = {[-1] = false,[0] = true,[1] = true,[2] = false,[3] = false},
  tHelp = " <Range_Number>\t\t\t\t\t\t\t\t\t\tTo Delete a Range",
  tRC = { { "Delete Range", " %[line:Range no.]" } },
  },
  unknownrange = {
    sFunction = function(user,data)
      local NoUnknown = true
      for i,v in ipairs(Core.GetOnlineUsers()) do
        if not GetRange(v.sIP) then
        NoUnknown = false
        return "Unrecognized IP: "..v.sIP.." from Nick: "..v.sNick
        end
      end
    
      if NoUnknown then
        return "There are no unrecognized IP addresses"
      end
    end,
    tLevels = {[-1] = false,[0] = true,[1] = true,[2] = false,[3] = false},
    tHelp = "\t\t\t\t\t\t\t\t\t\t\tGets unknown IP of users currently logged on hub",
    tRC = { { "Unknown Range", "" } },
  },
  ip2area = {
    sFunction = function(user,data)
      local msg,p = "\r\n\r\n\tIP2Area Description Help\r\n",SetMan.GetString(29):sub(1,1)
      for i,v in pairs(tCommands) do
        if v.tLevels[user.iProfile] then
          msg = msg.."\r\n\t"..p..i..v.tHelp
        end
      end
      return msg
    end,
    tLevels = {[-1] = false,[0] = true,[1] = true,[2] = false,[3] = false},
    tHelp = "\t\t\t\t\t\t\t\t\t\t\t\tDisplays This Help Message",
    tRC = { { "IP2Area Help", "" } },
  }
}

Clear = function()
   collectgarbage()
   io.flush()
end

ComputeIP = function(IP)
   local _,_,a,b,c,d = string.find(IP,"(%d+).(%d+).(%d+).(%d+)")
   if a and b and c and d then
      a,b,c,d = tonumber(a),tonumber(b),tonumber(c),tonumber(d)
      return ((a*16777216) + (b*65536) + (c*256) + d)
   end
end


GetRange = function(IP)
  local mResult = nil
  if IP then
    local ip = ComputeIP(IP)
    local size = 255*255*255*255
    for i,v in ipairs(IPRanges) do
       local x,y = v[1],v[2]
       local a,b = ComputeIP(x),ComputeIP(y)
       if ip >= a and ip <= b then
          local rangesize = b - a
          if (rangesize < size) then
            mResult = v
            size = rangesize
          end
       end
    end
  end
  return mResult
end

GetRangeStart = function(Range)
   return Range[1]
end

GetRangeEnd = function(Range)
   return Range[2]
end

GetRangeDesc = function(Range)
   if Range[3] ~= nil then
    return Range[3]
   else
    return ""
   end
end

GetRangePrefix = function(Range)
   if Range[4] ~= nil then
    return Range[4]
   else
    return ""
   end
end

GetRangeMinShare = function(Range)
  if (Range[5] ~= nil) and (Range[5] ~= "") then
   return tonumber (Range[5])
  else
    return DefaultMinShareSize
  end
end

GetRangeNormShare = function(Range)
  if (Range[6] ~= nil) and (Range[6] ~= "") then
   return tonumber (Range[6])
  else
    return DefaultNormShareSize
  end
end

GetRangeShareGroup = function(Range)
   if Range[7] ~= nil then
    return Range[7]
   else
    return ""
   end
end

Save_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
         Save_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

Save_File = function(file,table , tablename )
   local hFile = io.open (file , "w")
   Save_Serialize(table, tablename, hFile);
   hFile:close()
   Clear()
end

HandleShareSize = function(user)

  -- Optionaly warn user if his share size is too low
  if WarnShareSize then
 
    local iUserShareSize
    if Core then
      Core.GetUserData(user,16)
    end
    iUserShareSizeBytes = user.iShareSize / (1024 * 1024 * 1024)
    iUserShareSize = math.floor( iUserShareSizeBytes * 100 + 0.5 ) / 100

    local mUserNetwork = GetRange(user.sIP)
     
    -- Get share size limitation for IP
    local mMinShareSize = GetRangeMinShare(mUserNetwork)

    if (iUserShareSize < mMinShareSize) then
      Core.SendToNick(user.sNick,"<"..sBot.."> " ..user.sNick.. ", your share size is too low (" .. iUserShareSize .. " GB). It should be at least " .. mMinShareSize .. " GB")
      if ForceShareSize then
        Core.SendToNick(user.sNick,"<"..sBot.."> Increase your share and then reconnect, please.")
        Core.Disconnect(user.sNick)   
      end
    end
   
   end

end


HandleConnection = function(user,data,PolledUserName)

  local mDownloadProhibited = false
 
  if ForceShareGroups then
    
    if GetRange(user.sIP) then
 
      local mUserNetwork = GetRange(user.sIP)
      local mUserShareGroup = GetRangeShareGroup(mUserNetwork)
   
      local PolledUser = Core.GetUser(PolledUserName, true)     
      local mPolledUserNetwork = GetRange(PolledUser.sIP)
      local mPolledUserShareGroup = GetRangeShareGroup(mPolledUserNetwork)

      if mUserShareGroup ~= mPolledUserShareGroup then
   
        Core.SendToNick(user.sNick,"<"..sBot.."> ---")
        Core.SendToNick(user.sNick,"<"..sBot.."> "..user.sNick.." You requested download from " .. PolledUserName)
        Core.SendToNick(user.sNick,"<"..sBot.."> Sorry, you and " .. PolledUserName .. " do not belong to the same share group.")
        Core.SendToNick(user.sNick,"<"..sBot.."> Your share group is '" .. mUserShareGroup .. "' and " .. PolledUserName .. " is from '" .. mPolledUserShareGroup .. "'")
        Core.SendToNick(user.sNick,"<"..sBot.."> ---")   

        mDownloadProhibited = true
     
      end
    else
      Core.SendToNick(user.sNick,"<"..sBot.."> Your download has been blocked from "..PolledUserName.." because your IP is not in our list. Please contact the hub operator.")
      mDownloadProhibited = true
    end
   
  end -- if ForceShareGroups
 
  if ForceDownloadBlocking and (mDownloadProhibited == false) then
    
    if GetRange(user.sIP) then
      Core.GetUserData(user,16)
      local mUserShareBytes = user.iShareSize
      local mUserShare = BytesToGBytes(mUserShareBytes)
   
      local mUserNetwork = GetRange(user.sIP)
      local mUserMinShareSize = GetRangeMinShare(mUserNetwork)
      local mUserNormShareSize = GetRangeNormShare(mUserNetwork)
   
      if (mUserShare < mUserMinShareSize) then
        Core.SendToNick(user.sNick,"<"..sBot.."> ---")
        Core.SendToNick(user.sNick,"<"..sBot.."> "..user.sNick.." You requested download from " .. PolledUserName)
        Core.SendToNick(user.sNick,"<"..sBot.."> Sorry, your share is to low (" .. mUserShare .. " GB). You cannot download from other users.")
        Core.SendToNick(user.sNick,"<"..sBot.."> You must have share larger than (" .. mUserMinShareSize .. " GB).")
        Core.SendToNick(user.sNick,"<"..sBot.."> ---")
        mDownloadProhibited = true
      else
   
        if (mUserShare < mUserNormShareSize) then 
       
          local PolledUser = Core.GetUser(PolledUserName, true) 

          mPolledUserShareBytes = PolledUser.iShareSize
          mPolledUserShare = BytesToGBytes(mPolledUserShareBytes)
     
          if (mPolledUserShare > mUserNormShareSize) then
            Core.SendToNick(user.sNick,"<"..sBot.."> ---")
            Core.SendToNick(user.sNick,"<"..sBot.."> " .. user.sNick.. " You requested download from " .. PolledUserName)
            Core.SendToNick(user.sNick,"<"..sBot.."> Sorry, your share is to low (" .. mUserShare .. " GB). You cannot download from this user.")
            Core.SendToNick(user.sNick,"<"..sBot.."> Only users with share larger than " .. mUserNormShareSize .. " GB may download from users with share larger than " .. mUserNormShareSize .. " GB")
            Core.SendToNick(user.sNick,"<"..sBot.."> ---")     
            mDownloadProhibited = true
          end
       
        end
     
      end
    else
      Core.SendToNick(user.sNick,"<"..sBot.."> Your download has been blocked from "..PolledUserName.." because your IP is not in our list. Please contact the hub operator.")
      mDownloadProhibited = true 
    end
    end -- if ForceDownloadBlocking
 
    return mDownloadProhibited
 

end

BytesToMBytes = function (SizeBytes)
  local mSizeMB  = math.floor( ((SizeBytes / 1024 / 1024) * 100 + 0.5 )) / 100
  return mSizeMB
end

BytesToGBytes = function (SizeBytes)
  local mSizeGB  = math.floor( ((SizeBytes / 1024 / 1024 / 1024) * 100 + 0.5 )) / 100
  return mSizeGB
end
Thanking You,

speedX

Popeye

We have total 12 profiles on our Hub from which top 5 Profiles have Key / is OP
but we only want to give access to the top most profile "Owner" and non of the other profile should get access to this script

is it possible ?

Quote from: speedX on 06 March, 2011, 14:07:18
Hey guys, this is a new version of script wich also includes additions by Pedja and some bug fixes. Its kindof a beta release and i'll be posting a new version in a few days till then keep testing and post bugs if any :)

--[[

      IP2Area Description and Prefix Script [API 2]
      Made by speedX    (19/05/2009)
      Altered by Pedja (17/02/2011)
      Version 2.0.18
      (Based on Hungarista's Area Script)
     
      Description:
     
      Adds Area in Description according to IP Range
     
      Optionally forces prefixes in user names according to IP range. Several prefixes
      may pre defined for single IP range by delimiting them with comma.
     
      For Example: if the area name of range 192.168.1.0-192.168.1.255 is stored as area "New York"
       with prefix [ny],[apple] then the user within that range will be forced to place
       prefix ([ny] or [apple]) in his Nick and have "New York" as his Description       
     
      There is option to set minimum share for each IP Area. Minimum share may be enforced by disconnecting
      user, or by just waring user. Sharing size check occurs when user connects to the hub and repeats
      periodicaly. Repeating is adjustable and may be turned off.
     
      Option to block download for users is also provided. It may be set to disallow any download for user
      who has share less than MinShare. If user has share less than NormShare, he will be allowed to download
      only from users who also have share less than NormShare. Users who have share larger than NormShare are
      allowed to download from everyone. This is all optional for whole hub, or for each IP area.
     
      There is another option to block downloading by assigning IP Areas to share groups. Users belonging to
      different share groups will not be able to download from each other. This is optional for whole hub,
      or for ecah IP Area separately.
     
      IP areas may overlap. For instance, you may seet one large IP Area, and then set some subranges within
      it. When matching IP Area, narower area will always be used.

      
     
      Version 1.0:
        + If user doesn't want to reveal his area then put "NO AREA" in capital(without quotes) in description
        + Added command: +unknownrange - Gets unknown IP range of users currently logged on hub
       
      Version 2.0.14
        + data structure is expanded for Prefix field
        + there is ForcePrefix to set if prefix will be used in user Nicks
        + if prefix is set, user must put it in his Nick. Otherwise he will not be allowed
          to connect
        + several prefixes may be defined for single IP range. User may set any of them
        + if Prefix is set to empty, nil or contains # prefix will not be forced for that IP range
        + welcome message is now optional, use ShowWelcome to enable it
        + user is optionally hailed on connection with info what IP area he belongs to
        + other users are optionaly informed of IP range info for connected user      
        + script responds in the same window command is sent. Both public Chat and Private Chat
          are supported
        + if there are no unknown IP's +unknownrange returns that info too. Originaly, in such
          cases there would be no reposnd, which is confusing
        + display of ip ranges fixed to be more readable       

      Version 2.0.15
        + user may be warned or disconnected if sharesize is lower than set for his network     
        + size of share may be set for each network
        + default share size may be set to be used if network share size is not set
        + sharesize may be optionally checked every n minutes
       
      Version 2.0.16
        + fixed problem with relative path to tables
        + ShareSize parameter replaced with MinShareSize
        + Parameter NormShareSize introduced
        + new function: blocking file download by share size (per network). If user has share size
          lower than MinShareSize (GB) he is not allowed to downlaod from anyone. If user has share
          size lower than NormShareSize (GB) he is alowed to download only from users that also have share
          size lower than NormShareSize. Users with share size larger than NormShareSize are allowed
          to download from anyone. MinShareSize and NormShareSize are settable for each IP area. If
          not set, then DefaultMinShareSize and DefaultNormShareSize are used.
        + blocking file download by share size is optional
        + new function: blocking file download by share group. Each IP area may be assigned to share group.
          Several IP areas may be assigned to the same group. If ForceShareGroups is true, only users who
          belong to the same share group will be able to download from each other. If share group is not
          set then IP area is assigned to DefaultShareGroup.
        + fixed issue when several ranges overlap. Now, if IP matches to several areas, area with the most
          narrow IP range is used. This allows to set one big IP range and then also add different settings
          for it's subranges.
        + optimized ip range matching. Until now, matching was repeated to get value for each table field. It
          is fixed to match just once and get all fields.
         
      Version 2.0.17
        + fixed problem with typecasting numeric values from table
        + fixed problem with nul values from table
        
      Version 2.0.18
        + added a help menu wich can be triggered by +ip2area.
        + fixed error when unrecognized ip enters the hub.
        + changed addrange command structure.
        + added option to set Description Refresh Time.
        + changed addrange display structure.
        + changed and optimized the way commands will be replied.
        + revised script structure.
        + changed file path to avoid errors. 

      Commands:

       +unknownrange
       Shows list of IP ranges used by connected users which are not part of any known IP lists

       +addrange <Start_Range>*<End_Range>*<Area_name>*<Prefixes>*<MinShareSize>*<NormShareSize>*<ShareGroup>
       Adds IP range to list. You may set several optional prefixes delimited by comma.
       If you do not want prefix for IP range, put # as Prefixes

       Parameters Start_Range, End_Range and Area_name are reqired. Other parameters are optional.
       
       Example: +addrange 192.168.1.1*192.168.1.254*mylocalnet*[mynet],[local]*10*100*mynet

       
       +getrangelist
       Shows list od known IP ranges

       +delrange <Range_Number>
       Delete range form list. <Range_Number> is order number shown with +getrangelist
       
       +ip2area
       Returns Help Menu 
      
           
]]--

-- Database Files
RegDbFile = "IP2AREA.dat"
NickFile = "noarea.dat"

-- Bot Name
sBot = SetMan.GetString(21)

-- set ForcePrefix to true if you want to force prefixes on user names
ForcePrefix = true

-- show IP2Area welcome to user?
ShowWelcome = true

-- show Hail to user with IP range info?
ShowIPRangeInfo = true

-- Notify everyone in public chat about IP range info of connected user
NotifyEveryone = true

-- set ForceShareSize to true if you want to force sharesize for users
ForceShareSize = false

-- Warn user who has too low share size
WarnShareSize = false

-- Repeat share size checked every ShareSizeTimer minutes. If 0, do not repeat
-- but check only on connection.
ShareSizeTimer = 30

-- set ForceDownloadBlocking to true if you want to prevent users to download
-- regarding their share size
ForceDownloadBlocking = false

-- Refresh Description of users every DescRefreshTimer minutes.
-- If 0, refresh after every 1 minute.
DescRefreshTimer = 1

-- Default min share size id network share size is not set (GB)
DefaultMinShareSize = 10

-- Default normal share size id network share size is not set (GB)
DefaultNormShareSize = 60

-- set ForceShareGroups to true if you want to prevent users to download
-- from users not belonging to their share group
ForceShareGroups = false

-- Default sharegroup used if IP area does not have specified group
DefaultShareGroup = "<none>"

function OnStartup()
  RegDbFile = Core.GetPtokaXPath().."scripts/"..RegDbFile
  NickFile = Core.GetPtokaXPath().."scripts/"..NickFile
  TmrMan.AddTimer(60000)
  if loadfile(RegDbFile) ~= nil then
    dofile(RegDbFile)
  else
      IPRanges ={}
      Save_File(RegDbFile,IPRanges,"IPRanges")
  end
  if loadfile(NickFile) ~= nil then
    dofile(NickFile)
  else
      tNicks = {}
      Save_File(NickFile,tNicks,"tNicks")
  end
end

UserConnected = function(user)

  local mNickPrefix = user.sNick:match("%[(.*)%]")
  if mNickPrefix == nil then
    mNickPrefix = ""
  end

  -- Optionally show wellcome message to user
  if ShowWelcome then
    Core.SendToNick(user.sNick,"<"..sBot.."> Welcome "..user.sNick..", speedX's IP2Area Description is enabled. RightClick for menu or type "..SetMan.GetString(29):sub(1,1).."ip2area.")
  end
 
  if Core.GetUserValue(user,12) then
      for i,v in pairs(tCommands) do
         if v.tLevels[user.iProfile] then
            for n in ipairs(v.tRC) do
               Core.SendToNick(user.sNick, "$UserCommand 1 3 IP2Area\\"..v.tRC[n][1].."$<%[mynick]> "..SetMan.GetString(29):sub(1,1)..i..v.tRC[n][2].."&#124;")
            end
         end
      end
   end

  if GetRange(user.sIP) then 
    local mUserNetwork = GetRange(user.sIP)

    -- Get description for user's IP range
    local mNetworkDesc = GetRangeDesc(mUserNetwork)
    -- Get allowed prefixes for user's IP range (if several prefixes they will be delimited by comma)
    local mNetworkPrefix = GetRangePrefix(mUserNetwork)
 
    -- Optionally show IP range information to user
    if (ShowIPRangeInfo) then
      Core.SendToNick(user.sNick,"<"..sBot.."> "..user.sNick..", your IP is "..user.sIP.." and your network is "..mNetworkDesc)
      if ForceShareGroups then
        local mUserShareGroup = GetRangeShareGroup(mUserNetwork)
        if mUserShareGroup ~= "" then
          Core.SendToNick(user.sNick,"<"..sBot.."> You belong to share group: "..mUserShareGroup)
        end
      end
    end
    local user_connected = true
 
    -- Now deal with prefixes
    if ForcePrefix and (mNetworkPrefix ~= "") then
      mPrefixpos = string.find ("," ..mNetworkPrefix.. ",", ",%[" ..mNickPrefix.. "%],")

      if mPrefixpos == nil then
        if mNickPrefix == "" then
          mNickPrefix = "none"
        else
          mNickPrefix = "[" ..mNickPrefix.. "]"
        end
        Core.SendToNick(user.sNick,"<"..sBot.."> Your prefix must be one from this list: "..mNetworkPrefix..". You use "..mNickPrefix..".")
        Core.SendToNick(user.sNick,"<"..sBot.."> Change prefix and then reconnect, please.")
        Core.Disconnect(user.sNick)
        user_connected = false
      end
    end

    -- Optionaly notify everyone on the hub about network user is coming from
    if NotifyEveryone and user_connected then
      Core.SendToAll("User " ..user.sNick.." from " ..mNetworkDesc.. " connected.")
    end

    HandleShareSize(user)
  end

end
OpConnected = UserConnected
RegConnected = UserConnected

function MyINFOArrival(user,data)
  local usr,desc,clt,ver,mode,hubs,slots = data:match("$MyINFO $ALL (%S+) (.*)<(%S+) V:(.+),M:(%S),H:([0-9/]+),S:(%d+)")
  local nick = user.sNick:lower()
  if desc ~= "NO AREA" then
    if tNicks[nick] then
      tNicks[nick] = nil
      Save_File(NickFile,tNicks,"tNicks")
    end
  elseif desc == "NO AREA" then
      if not tNicks[nick] then
        tNicks[nick] = 1
        Save_File(NickFile,tNicks,"tNicks")
      end
  end
end 

ConnectToMeArrival = function(user,data)
  local _,_,mSourceUserName = data:find("%$ConnectToMe%s(%S+)%s.*|")
  return HandleConnection(user,data,mSourceUserName)
end

RevConnectToMeArrival = function(user,data)
  local _,_,mSourceUserName = data:find("%$RevConnectToMe%s%S+%s(%S+)|")
  return HandleConnection(user,data,mSourceUserName)
end

 
function OnTimer()
  local CheckShareSize = false;
  local RefreshDesc = true;
 
  if ShareSizeTimer > 0 then
    if TimeCounter == nil then
      TimeCounter = 0
    end
    
    -- timer is triggeed every minute.
    TimeCounter = TimeCounter + 1
    
    if (TimeCounter >= (ShareSizeTimer)) then
      CheckShareSize = true
      TimeCounter = 0
    else
      CheckShareSize = false
    end
  end
  
  if DescRefreshTimer > 1 then
    RefreshDesc = false
    if RefreshTime == nil then
      RefreshTime = 0
    end
    
    RefreshTime = RefreshTime + 1
    
    if (RefreshTime >= (DescRefreshTimer)) then
      RefreshDesc = true
      RefreshTime = 0
    else
      RefreshDesc = false
    end
  end

  if RefreshDesc then
    for i,v in ipairs(Core.GetOnlineUsers(true)) do
    local nick = v.sNick:lower()
      if not tNicks[nick] then
        if GetRange(v.sIP) then
          if CheckShareSize then
            HandleShareSize(v)   
          end
          local mUserNetwork = GetRange(v.sIP)
          local mUserNetworkDesc = GetRangeDesc(mUserNetwork)
          if mUserNetworkDesc then
            local myinfo = "$MyINFO $ALL "..v.sNick.." "..mUserNetworkDesc.." - "..(v.sDescription or "")..(v.sTag or "").."$ $"..(v.sConnection or "")..string.char(v.iMagicByte or "").."$"..(v.sEmail or "").."$"..(v.iShareSize or "").."$"
            Core.SendToAll(myinfo)
            Clear()
          end
        end
      end
    end
  end
end

ChatArrival = function(user, data)
  local _,_,to = string.find(data,"^$To:%s(%S+)%s+From:")
  local _,_,cmd = string.find(data,"%b<> %p(%w+)")
  -- Message sent to Bot or in Main
  if (to and to == sBot) or not to then
    -- 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 == sBot then
          return Core.SendPmToNick(user.sNick,sBot,tCommands[cmd].sFunction(user,data)), true
        else
          return Core.SendToNick(user.sNick,"<"..sBot.."> "..tCommands[cmd].sFunction(user,data)), true
        end
      else
        if to and to == sBot then
          return Core.SendPmToNick(user.sNick,sBot,"*** Error: You are not allowed to use this command!"), true
        else
          return Core.SendToNick(user.sNick,"<"..sBot.."> *** Error: You are not allowed to use this command!"), true
        end
      end
    end
  end
end
ToArrival = ChatArrival

tCommands = {
  addrange = {
    sFunction = function(user,data)
    local _,_,from,to,area,prefix,minsharesize,normsharesize,sharegroup = string.find(data,"%b<> %p%w+ (%d+.%d+.%d+.%d+)%*(%d+.%d+.%d+.%d+)%*(.*)%*(%S+)%*(%d*)%*(%d*)%*(.*)|")
    
     -- If prefix is empty or contains # then prefix will not be enforced for this IP range.
     -- Generaly prefix = "" means "do not force prefix".
     if (prefix == nil) or (prefix == "#") then
        prefix = ""
     end
   
    minsharesize = tonumber(minsharesize)   
    normsharesize = tonumber(normsharesize)
   
    if (sharegroup == nil) then
      sharegroup = ""
    end
       
    if from and to and area then
      table.insert(IPRanges,{from,to,area,prefix,minsharesize,normsharesize,sharegroup})
      Save_File(RegDbFile,IPRanges,"IPRanges")
     
      if (minsharesize == nil) then
         minsharesize = "none"
      end
     
      if (normsharesize == nil) then
         normsharesize = "none"
      end
     
      if (sharegroup == "") then
        sharegroup = DefaultShareGroup
      end

      return "\r\n\tIP-Range: "..from.." - "..to.." has been successfully added with: \r\n\tArea: "..area.."\r\n\tPrefix: "..prefix.."\r\n\tShare Size: "..minsharesize.."/".. normsharesize .." GB\r\n\tSharegroup: "..sharegroup

    else
      return "Invalid IP or Area. Use +addrange <Start_Range>*<End_Range>*<Area_name>*<Prefixes>*<MinShareSize>*<NormShareSize>*<ShareGroup>"
      end
    end,
    tLevels = {[-1] = false,[0] = true,[1] = true,[2] = false,[3] = false},
    tHelp = " <Start_Range>*<End_Range>*<Area_name>*<Prefixes>*<MinShareSize>*<NormShareSize>*<ShareGroup>\tTo Add a New Range",
    tRC = { { "Add Range", " %[line:Start Range]*%[line:End Range]*%[line:Area]*%[line:Prefix]*%[line:MinShareSize]*%[line:NormShareSize]*%[line:ShareGroup]" } },
  },
  getrangelist = {
    sFunction = function(user,data)
    
      --local border = "\r\n\t"..string.rep("-",100).."\r\n\t"
      local str = "\r\n\r\n  Sr.\tFrom - To\t\t\tArea : Prefix - ShareSize min/max - Sharegroup\r\n"
      str = str..string.rep("-",140).."\r\n"

      local mMinsharesize = ""
      local mNormsharesize = ""
     
      for a,b in pairs(IPRanges) do

        if b[4] == nil then
          b[4] = ""
        end

        if (b[5] == nil) or (b[5] == "") then
          b[5] = ""
          mMinsharesize = "not set (" .. DefaultMinShareSize .. " GB)"
        else
          mMinsharesize = b[5] .. " GB"
        end

        if (b[6] == nil) or (b[6] == "") then
          b[6] = ""
          mNormsharesize = "not set (" .. DefaultNormShareSize .. " GB)"
        else
          mNormsharesize = b[6] .. " GB"
        end
       
        if (b[7] == nil) then
          mSharegroup = DefaultShareGroup
        else
          mSharegroup = b[7]
        end

        str = str .. " [ "..a.." ]\t"..b[1].."  -  "..b[2].."\t"..b[3].."  :  "..b[4].." - Share Size: "..mMinsharesize.."/"..mNormsharesize.." - Sharegroup: " .. mSharegroup .. "\r\n"
      end

     return str

    end,
   tLevels = {[-1] = false,[0] = true,[1] = true,[2] = false,[3] = false},
   tHelp = "\t\t\t\t\t\t\t\t\t\t\tView Range List",
   tRC = { { "Get RangeList", "" } },
   },
  delrange = {
    sFunction = function(user,data)
      local _,_,n = string.find(data,"%b<> %p%w+ (%d+)|")
      n = tonumber(n)
      if n > #IPRanges then
      return "Invalid range no."
      else
        table.remove(IPRanges,n)
        Save_File(RegDbFile,IPRanges,"IPRanges")
        return "Range No. "..n.." has been deleted from database."
      end
    end,
  tLevels = {[-1] = false,[0] = true,[1] = true,[2] = false,[3] = false},
  tHelp = " <Range_Number>\t\t\t\t\t\t\t\t\t\tTo Delete a Range",
  tRC = { { "Delete Range", " %[line:Range no.]" } },
  },
  unknownrange = {
    sFunction = function(user,data)
      local NoUnknown = true
      for i,v in ipairs(Core.GetOnlineUsers()) do
        if not GetRange(v.sIP) then
        NoUnknown = false
        return "Unrecognized IP: "..v.sIP.." from Nick: "..v.sNick
        end
      end
    
      if NoUnknown then
        return "There are no unrecognized IP addresses"
      end
    end,
    tLevels = {[-1] = false,[0] = true,[1] = true,[2] = false,[3] = false},
    tHelp = "\t\t\t\t\t\t\t\t\t\t\tGets unknown IP of users currently logged on hub",
    tRC = { { "Unknown Range", "" } },
  },
  ip2area = {
    sFunction = function(user,data)
      local msg,p = "\r\n\r\n\tIP2Area Description Help\r\n",SetMan.GetString(29):sub(1,1)
      for i,v in pairs(tCommands) do
        if v.tLevels[user.iProfile] then
          msg = msg.."\r\n\t"..p..i..v.tHelp
        end
      end
      return msg
    end,
    tLevels = {[-1] = false,[0] = true,[1] = true,[2] = false,[3] = false},
    tHelp = "\t\t\t\t\t\t\t\t\t\t\t\tDisplays This Help Message",
    tRC = { { "IP2Area Help", "" } },
  }
}

Clear = function()
   collectgarbage()
   io.flush()
end

ComputeIP = function(IP)
   local _,_,a,b,c,d = string.find(IP,"(%d+).(%d+).(%d+).(%d+)")
   if a and b and c and d then
      a,b,c,d = tonumber(a),tonumber(b),tonumber(c),tonumber(d)
      return ((a*16777216) + (b*65536) + (c*256) + d)
   end
end


GetRange = function(IP)
  local mResult = nil
  if IP then
    local ip = ComputeIP(IP)
    local size = 255*255*255*255
    for i,v in ipairs(IPRanges) do
       local x,y = v[1],v[2]
       local a,b = ComputeIP(x),ComputeIP(y)
       if ip >= a and ip <= b then
          local rangesize = b - a
          if (rangesize < size) then
            mResult = v
            size = rangesize
          end
       end
    end
  end
  return mResult
end

GetRangeStart = function(Range)
   return Range[1]
end

GetRangeEnd = function(Range)
   return Range[2]
end

GetRangeDesc = function(Range)
   if Range[3] ~= nil then
    return Range[3]
   else
    return ""
   end
end

GetRangePrefix = function(Range)
   if Range[4] ~= nil then
    return Range[4]
   else
    return ""
   end
end

GetRangeMinShare = function(Range)
  if (Range[5] ~= nil) and (Range[5] ~= "") then
   return tonumber (Range[5])
  else
    return DefaultMinShareSize
  end
end

GetRangeNormShare = function(Range)
  if (Range[6] ~= nil) and (Range[6] ~= "") then
   return tonumber (Range[6])
  else
    return DefaultNormShareSize
  end
end

GetRangeShareGroup = function(Range)
   if Range[7] ~= nil then
    return Range[7]
   else
    return ""
   end
end

Save_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
         Save_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

Save_File = function(file,table , tablename )
   local hFile = io.open (file , "w")
   Save_Serialize(table, tablename, hFile);
   hFile:close()
   Clear()
end

HandleShareSize = function(user)

  -- Optionaly warn user if his share size is too low
  if WarnShareSize then
 
    local iUserShareSize
    if Core then
      Core.GetUserData(user,16)
    end
    iUserShareSizeBytes = user.iShareSize / (1024 * 1024 * 1024)
    iUserShareSize = math.floor( iUserShareSizeBytes * 100 + 0.5 ) / 100

    local mUserNetwork = GetRange(user.sIP)
     
    -- Get share size limitation for IP
    local mMinShareSize = GetRangeMinShare(mUserNetwork)

    if (iUserShareSize < mMinShareSize) then
      Core.SendToNick(user.sNick,"<"..sBot.."> " ..user.sNick.. ", your share size is too low (" .. iUserShareSize .. " GB). It should be at least " .. mMinShareSize .. " GB")
      if ForceShareSize then
        Core.SendToNick(user.sNick,"<"..sBot.."> Increase your share and then reconnect, please.")
        Core.Disconnect(user.sNick)   
      end
    end
   
   end

end


HandleConnection = function(user,data,PolledUserName)

  local mDownloadProhibited = false
 
  if ForceShareGroups then
    
    if GetRange(user.sIP) then
 
      local mUserNetwork = GetRange(user.sIP)
      local mUserShareGroup = GetRangeShareGroup(mUserNetwork)
   
      local PolledUser = Core.GetUser(PolledUserName, true)     
      local mPolledUserNetwork = GetRange(PolledUser.sIP)
      local mPolledUserShareGroup = GetRangeShareGroup(mPolledUserNetwork)

      if mUserShareGroup ~= mPolledUserShareGroup then
   
        Core.SendToNick(user.sNick,"<"..sBot.."> ---")
        Core.SendToNick(user.sNick,"<"..sBot.."> "..user.sNick.." You requested download from " .. PolledUserName)
        Core.SendToNick(user.sNick,"<"..sBot.."> Sorry, you and " .. PolledUserName .. " do not belong to the same share group.")
        Core.SendToNick(user.sNick,"<"..sBot.."> Your share group is '" .. mUserShareGroup .. "' and " .. PolledUserName .. " is from '" .. mPolledUserShareGroup .. "'")
        Core.SendToNick(user.sNick,"<"..sBot.."> ---")   

        mDownloadProhibited = true
     
      end
    else
      Core.SendToNick(user.sNick,"<"..sBot.."> Your download has been blocked from "..PolledUserName.." because your IP is not in our list. Please contact the hub operator.")
      mDownloadProhibited = true
    end
   
  end -- if ForceShareGroups
 
  if ForceDownloadBlocking and (mDownloadProhibited == false) then
    
    if GetRange(user.sIP) then
      Core.GetUserData(user,16)
      local mUserShareBytes = user.iShareSize
      local mUserShare = BytesToGBytes(mUserShareBytes)
   
      local mUserNetwork = GetRange(user.sIP)
      local mUserMinShareSize = GetRangeMinShare(mUserNetwork)
      local mUserNormShareSize = GetRangeNormShare(mUserNetwork)
   
      if (mUserShare < mUserMinShareSize) then
        Core.SendToNick(user.sNick,"<"..sBot.."> ---")
        Core.SendToNick(user.sNick,"<"..sBot.."> "..user.sNick.." You requested download from " .. PolledUserName)
        Core.SendToNick(user.sNick,"<"..sBot.."> Sorry, your share is to low (" .. mUserShare .. " GB). You cannot download from other users.")
        Core.SendToNick(user.sNick,"<"..sBot.."> You must have share larger than (" .. mUserMinShareSize .. " GB).")
        Core.SendToNick(user.sNick,"<"..sBot.."> ---")
        mDownloadProhibited = true
      else
   
        if (mUserShare < mUserNormShareSize) then 
       
          local PolledUser = Core.GetUser(PolledUserName, true) 

          mPolledUserShareBytes = PolledUser.iShareSize
          mPolledUserShare = BytesToGBytes(mPolledUserShareBytes)
     
          if (mPolledUserShare > mUserNormShareSize) then
            Core.SendToNick(user.sNick,"<"..sBot.."> ---")
            Core.SendToNick(user.sNick,"<"..sBot.."> " .. user.sNick.. " You requested download from " .. PolledUserName)
            Core.SendToNick(user.sNick,"<"..sBot.."> Sorry, your share is to low (" .. mUserShare .. " GB). You cannot download from this user.")
            Core.SendToNick(user.sNick,"<"..sBot.."> Only users with share larger than " .. mUserNormShareSize .. " GB may download from users with share larger than " .. mUserNormShareSize .. " GB")
            Core.SendToNick(user.sNick,"<"..sBot.."> ---")     
            mDownloadProhibited = true
          end
       
        end
     
      end
    else
      Core.SendToNick(user.sNick,"<"..sBot.."> Your download has been blocked from "..PolledUserName.." because your IP is not in our list. Please contact the hub operator.")
      mDownloadProhibited = true 
    end
    end -- if ForceDownloadBlocking
 
    return mDownloadProhibited
 

end

BytesToMBytes = function (SizeBytes)
  local mSizeMB  = math.floor( ((SizeBytes / 1024 / 1024) * 100 + 0.5 )) / 100
  return mSizeMB
end

BytesToGBytes = function (SizeBytes)
  local mSizeGB  = math.floor( ((SizeBytes / 1024 / 1024 / 1024) * 100 + 0.5 )) / 100
  return mSizeGB
end


For_Ever_MeXxX

tLevels = .... <-- There u can change the rights for the profiles...

If u want only Owner to use the commands use:

tLevels = {[0] = true},

U have to change that in all commands.. Just let ur Editor search for tLevels = and change them all to the one above

Popeye

Thank you for this helpful reply! :-)

Quote from: For_Ever_MeXxX on 01 June, 2012, 15:56:06
tLevels = .... <-- There u can change the rights for the profiles...

If u want only Owner to use the commands use:

tLevels = {[0] = true},

U have to change that in all commands.. Just let ur Editor search for tLevels = and change them all to the one above

SMF spam blocked by CleanTalk