PtokaX forum

Archive => Archived 4.0 boards => Help with Lua 4 scripts => Topic started by: Dj_OcTaGoN on 19 August, 2004, 21:13:28

Title: Chatbot Problem
Post by: Dj_OcTaGoN on 19 August, 2004, 21:13:28
Hey, i got an problem with this chatbotscript:

Syntax error: bad argument #1 to `getn' (table expected, got userdata)
stack traceback:
   1:  function `getn' [C]
   2:  function `unpickle' at line 198 [file `F:\-= PtokaX [debug] =-\scripts\chatbot.lua']
   3:  function `LoadFromFile' at line 127 [file `F:\-= PtokaX [debug] =-\scripts\chatbot.lua']
   4:  function `Main' at line 16 [file `F:\-= PtokaX [debug] =-\scripts\chatbot.lua']


And here is the code:
-----------------------------------------------------
-- Chat Bot v3.5 Coded by [aXs] Wellx 01/09-03
-- Formerly known as the Developer-Chat for TIC50
-- Based on the idea VIPChat from Piglja
-- Thx goes to Piglja & aMutex for Ideas and Help
-----------------------------------------------------

ChatBot = "Polish Chatroom" -- Chat Bot Name
CanUseCommands = { -1 , 0 , 1 , 2 , 3 } -- Can Use Chat Bot Commands Lvl ( 0 = Master ~~ 1 = Operators ~~ 2 = VIPs ~~ 3 = Reg ~~ etc.)

ChatArray={}
ChatFile = "Chatters.tbl"

function Main()
frmHub:RegBot(ChatBot)
ChatArray = LoadFromFile(ChatFile)
end

--======================================================== DataArrival: =========================================================--

function DataArrival(user, data)
if (strsub(data, 1, 1) == "<" ) then
data=strsub(data,1,strlen(data)-1)
_,_,cmd=strfind(data, "%b<>%s+(%S+)")
local Commands = (DeveloperCommands(user, data, cmd))
return Commands
elseif strsub(data, 1, 5) == "$To: " then
local s, e, to = strfind(data, "$To: (%S+)")
if to ~= ChatBot then
return 0
else
if to == ChatBot then
local data=strsub(data,1,strlen(data)-1)
local s,e,from,msg = strfind(data,"From:%s+(%S+)%s+$%b<>%s+(.+)")
if ChatArray[user.sName] ~= nil then
ChatArray[user.sName] = nil
for i,v in ChatArray do
Developer=GetItemByName(i)
if (Developer~=nil) then
Developer:SendData("$To: "..i.." From: "..ChatBot.." $<"..user.sName.."> "..msg.."|")
end
end
ChatArray[user.sName] = user.sName
else
user:SendPM(ChatBot,"You do not have permission to write inhere (Join or Talk to a Operator if you need permission)")
end
local _,_,cmd = strfind(data,"$%b<>%s+(%S+)")
local Commands = (DeveloperCommands(user, data, cmd))
end
end
end
end

--===================================================== Chat Commands: ======================================================--

function DeveloperCommands(user, data, cmd)
if tfind(CanUseCommands, user.iProfile) then
if (cmd == "+chathelp") then
DevHelp(user)
return 1
elseif (cmd == "+chat") then
local s,e,cmd,ChatName = strfind( data, "%b<>%s+(%S+)%s+(.*)" )
if (ChatName == nil) then
ChatName = user.sName
end
if ChatArray[ChatName] == nil then
ChatArray[ChatName] = ChatName
for index, value in ChatArray do
SendPmToNick(index, ChatBot, " "..ChatName.." Has joined the "..ChatBot)
end
else
for index, value in ChatArray do
SendPmToNick(index, ChatBot, " "..ChatName.." Has left the "..ChatBot)
end
ChatArray[ChatName] = nil
end
SaveToFile(ChatName,ChatFile,ChatArray)
return 1
elseif (cmd == "+showchatters") then
function DevList()
local DevList = ""
for index, value in ChatArray do
local line = index
if GetItemByName(index) then
if (strlen(index) <= 10) then
DevList = DevList.." ? "..line.."\t\t\t~ On-line ~\r\n"
else
DevList = DevList.." ? "..line.."\t\t~ On-line ~\r\n"
end
else
if (strlen(index) <= 10) then
DevList = DevList.." ? "..line.."\t\t\t? Off-Line ?\r\n"
else
DevList = DevList.." ? "..line.."\t\t? Off-Line ?\r\n"
end
end
end
return DevList
end
user:SendPM(ChatBot, "\r\n\r\n(? ?.??.-> "..ChatBot.." Chatters <-.??.???) \r\n\r\n"..DevList())
return 1
end
else user:SendData("You don't have permission to use the commands to the "..ChatBot.." ask a Operator for permission !!") return 0 end
end

function DevHelp (user)
local disp = "\r\n\r\n"
disp = disp.."~~ Scripted DeveloperChat Commands: ~~\r\n\r\n"
disp = disp.." +chat - Add or part a user to the list of people that can chat in the "..ChatBot.."\r\n"
disp = disp.." +showchatters - See witch users that can chat in the "..ChatBot.."\r\n"
disp = disp.."\r\n"
user:SendPM(ChatBot, disp)
end

--======================================================== Functions: ===========================================================--

function SaveToFile(arg,file,table)
local aString = pickle(table)
writeto(file)
write(aString)
writeto()
end

function LoadFromFile(file)
readfrom(file)
local aString = read("*all")
return unpickle(aString)
end

function tfind(table, key)
return foreachi(table, function(id, tmp) return (tmp == %key) and id end)
end

----------------------------------------------
-- Pickle.lua
-- An table serialization utility for lua
-- Steve Dekorte, http://www.dekorte.com, Apr 2000
-- Freeware
----------------------------------------------
function pickle(t)
return Pickle:clone():pickle_(t)
end

Pickle = {
clone = function (t) local nt={}; for i, v in t do nt=v end return nt end
}

function Pickle:pickle_(root)
if type(root) ~= "table" then
error("can only pickle tables, not ".. type(root).."s")
end
self._tableToRef = {}
self._refToTable = {}
local savecount = 0
self:ref_(root)
local s = ""
while getn(self._refToTable) > savecount do
savecount = savecount + 1
local t = self._refToTable[savecount]
s = s.."{\n"
for i, v in t do
s = format("%s[%s]=%s,\n", s, self:value_(i), self:value_(v))
end
s = s.."},\n"
end
return format("{%s}", s)
end

function Pickle:value_(v)
local vtype = type(v)
if vtype == "string" then return format("%q", v)
elseif vtype == "number" then return v
elseif vtype == "table" then return "{"..self:ref_(v).."}"
else --error("pickle a "..type(v).." is not supported")
end
end

function Pickle:ref_(t)
local ref = self._tableToRef[t]
if not ref then
if t == self then error("can't pickle the pickle class") end
tinsert(self._refToTable, t)
ref = getn(self._refToTable)
self._tableToRef[t] = ref
end
return ref
end

----------------------------------------------
-- unpickle
----------------------------------------------

function unpickle(s)
if type(s) ~= "string" then
error("can't unpickle a "..type(s)..", only strings")
end
local tables = dostring("return "..s)
for tnum = 1, getn(tables) do
local t = tables[tnum]
local tcopy = {}; for i, v in t do tcopy = v end
for i, v in tcopy do
local ni, nv
if type(i) == "table" then ni = tables[i[1]] else ni = i end
if type(v) == "table" then nv = tables[v[1]] else nv = v end
t[ni] = nv
end
end
return tables[1]
end
--========================= DeveloperChat Bot Coded By [aXs] Wellx For [DK] The Ice Cube? 50 GB ===========================--


Could u also change so all profiles incl. unreg users can participate in the chatbot? Im not sure what to change..
Title:
Post by: BottledHate on 21 August, 2004, 02:11:07
i changed it a bit... havn't tested yet.

--replaced pickle()'s causing error w/ much simpler serialization().
--replaced tfind() with hashed table values for CanUseCommands
--removed DevHelp().. put the help commands in the DeveloperCommands()
--Added "4" to the CanUseCommands... ( i think that makes it so unreg can use too...)
--209 lines to 135...

EDIT:  ...code removed... long and wrong.

*****EDIT:
not sure how the data looks in the save file as it is with
 the old script.. but you might want to change it
manually for the first run to this format in the tbl file.
you can also delete the old data and start fresh.
format example:
ChatArray = {
["nick1"] = "nick1",
["nick2"] = "nick2",
["nick3"] = "nick3"
}
*****EDIT


-BH

Title:
Post by: TheRevenge on 21 August, 2004, 03:24:44
This ist my VipChat , and this is running

----------------------- Script ------------------------------------

-----------------------------------------------------
-- Chat Bot v3.5 Coded by [aXs] Wellx 01/09-03
-- Formerly known as the Developer-Chat for TIC50
-- Based on the idea VIPChat from Piglja
-- Thx goes to Piglja & aMutex for Ideas and Help
-----------------------------------------------------

ChatBot = "?VipChat?" -- Chat Bot Name
sVer   = 3.5
CanUseCommands = { -1 , 0 , 1 , 2 , 3 } -- Can Use Chat Bot Commands Lvl ( 0 = Master ~~ 1 = Operators ~~ 2 = VIPs ~~ 3 = Reg ~~ etc.)

ChatArray={}
ChatFile = "Chatters.tbl"

function Main()
  bot = { sBotName  = ChatBot,
          sBotVer   = sVer,
          sBotEmail = "firebird1970@gmx.de",
          sBotSpeed = "T1",
          sBotDescr = "VIP-Chat",
          sBotTag   = "",
          iBotShare = 0 };

frmHub:RegBot(ChatBot)
ChatArray = LoadFromFile(ChatFile)
end

--======================================================== DataArrival: =========================================================--

function DataArrival(user, data)
if (strsub(data, 1, 1) == "<" ) then
data=strsub(data,1,strlen(data)-1)
_,_,cmd=strfind(data, "%b<>%s+(%S+)")
local Commands = (DeveloperCommands(user, data, cmd))
return Commands
elseif strsub(data, 1, 5) == "$To: " then
local s, e, to = strfind(data, "$To: (%S+)")
if to ~= ChatBot then
return 0
else
if to == ChatBot then
local data=strsub(data,1,strlen(data)-1)
local s,e,from,msg = strfind(data,"From:%s+(%S+)%s+$%b<>%s+(.+)")
if ChatArray[user.sName] ~= nil then
ChatArray[user.sName] = nil
for i,v in ChatArray do
Developer=GetItemByName(i)
if (Developer~=nil) then
Developer:SendData("$To: "..i.." From: "..ChatBot.." $<"..user.sName.."> "..msg.."|")
end
end
ChatArray[user.sName] = user.sName
else
user:SendPM(ChatBot,"You do not have permission to write inhere (Join or Talk to a Operator if you need permission)")
end
local _,_,cmd = strfind(data,"$%b<>%s+(%S+)")
local Commands = (DeveloperCommands(user, data, cmd))
end
end
end
end

--===================================================== Chat Commands: ======================================================--

function DeveloperCommands(user, data, cmd)
if tfind(CanUseCommands, user.iProfile) then
if (cmd == "+chathelp") then
DevHelp(user)
return 1
elseif (cmd == "+chat") then
local s,e,cmd,ChatName = strfind( data, "%b<>%s+(%S+)%s+(.*)" )
if (ChatName == nil) then
ChatName = user.sName
end
if ChatArray[ChatName] == nil then
ChatArray[ChatName] = ChatName
for index, value in ChatArray do
SendPmToNick(index, ChatBot, " "..ChatName.." Has joined the "..ChatBot)
end
else
for index, value in ChatArray do
SendPmToNick(index, ChatBot, " "..ChatName.." Has left the "..ChatBot)
end
ChatArray[ChatName] = nil
end
SaveToFile(ChatName,ChatFile,ChatArray)
return 1
elseif (cmd == "+showchatters") then
function DevList()
local DevList = ""
for index, value in ChatArray do
local line = index
if GetItemByName(index) then
if (strlen(index) <= 10) then
DevList = DevList.." ? "..line.."\t\t\t~ On-line ~\r\n"
else
DevList = DevList.." ? "..line.."\t\t~ On-line ~\r\n"
end
else
if (strlen(index) <= 10) then
DevList = DevList.." ? "..line.."\t\t\t? Off-Line ?\r\n"
else
DevList = DevList.." ? "..line.."\t\t? Off-Line ?\r\n"
end
end
end
return DevList
end
user:SendPM(ChatBot, "\r\n\r\n(? ?.??.-> "..ChatBot.." Chatters <-.??.???) \r\n\r\n"..DevList())
return 1
end
else user:SendData("You don't have permission to use the commands to the "..ChatBot.." ask a Operator for permission !!") return 0 end
end

function DevHelp (user)
local disp = "\r\n\r\n"
disp = disp.."~~ Scripted DeveloperChat Commands: ~~\r\n\r\n"
disp = disp.." +chat - Add or part a user to the list of people that can chat in the "..ChatBot.."\r\n"
disp = disp.." +showchatters - See witch users that can chat in the "..ChatBot.."\r\n"
disp = disp.."\r\n"
user:SendPM(ChatBot, disp)
end

--======================================================== Functions: ===========================================================--

function SaveToFile(arg,file,table)
local aString = pickle(table)
writeto(file)
write(aString)
writeto()
end

function LoadFromFile(file)
readfrom(file)
local aString = read("*all")
return unpickle(aString)
end

function tfind(table, key)
return foreachi(table, function(id, tmp) return (tmp == %key) and id end)
end

----------------------------------------------
-- Pickle.lua
-- An table serialization utility for lua
-- Steve Dekorte, http://www.dekorte.com, Apr 2000
-- Freeware
----------------------------------------------
function pickle(t)
return Pickle:clone():pickle_(t)
end

Pickle = {
clone = function (t) local nt={}; for i, v in t do nt=v end return nt end
}

function Pickle:pickle_(root)
if type(root) ~= "table" then
error("can only pickle tables, not ".. type(root).."s")
end
self._tableToRef = {}
self._refToTable = {}
local savecount = 0
self:ref_(root)
local s = ""
while getn(self._refToTable) > savecount do
savecount = savecount + 1
local t = self._refToTable[savecount]
s = s.."{\n"
for i, v in t do
s = format("%s[%s]=%s,\n", s, self:value_(i), self:value_(v))
end
s = s.."},\n"
end
return format("{%s}", s)
end

function Pickle:value_(v)
local vtype = type(v)
if vtype == "string" then return format("%q", v)
elseif vtype == "number" then return v
elseif vtype == "table" then return "{"..self:ref_(v).."}"
else --error("pickle a "..type(v).." is not supported")
end
end

function Pickle:ref_(t)
local ref = self._tableToRef[t]
if not ref then
if t == self then error("can't pickle the pickle class") end
tinsert(self._refToTable, t)
ref = getn(self._refToTable)
self._tableToRef[t] = ref
end
return ref
end

----------------------------------------------
-- unpickle
----------------------------------------------

function unpickle(s)
if type(s) ~= "string" then
error("can't unpickle a "..type(s)..", only strings")
end
local tables = dostring("return "..s)
for tnum = 1, getn(tables) do
local t = tables[tnum]
local tcopy = {}; for i, v in t do tcopy = v end
for i, v in tcopy do
local ni, nv
if type(i) == "table" then ni = tables[i[1]] else ni = i end
if type(v) == "table" then nv = tables[v[1]] else nv = v end
t[ni] = nv
end
end
return tables[1]
end
--========================= DeveloperChat Bot Coded By [aXs] Wellx For [DK] The Ice Cube? 50 GB ===========================--

-------------------------------- Script end ---------------------

sorry for my bad englisch

TheRevenge
Title:
Post by: BottledHate on 22 August, 2004, 02:49:09
ok this one works great.. tested it out and all. (finally stopped being lazy and installed pto)

so anyone can join this thing and use the commands...



-----------------------------------------------------
-- Chat Bot v3.5 Coded by [aXs] Wellx 01/09-03
-- Formerly known as the Developer-Chat for TIC50
-- Based on the idea VIPChat from Piglja
-- Thx goes to Piglja & aMutex for Ideas and Help
-- Edited by BH, Request from Dj_OcTaGoN
-- BH: Replaced picle w/ simple serialize... and dofile to read the table back in.(saved lots of lines!)  (209 down to 152)
-- BH: Removed tFind() ... using hashed table values instead.
-- BH: Anoyone can join and use commands.
-----------------------------------------------------
saveFile = "Chatters.tbl"
ChatBot = "ChatRoomName" -- Chat Bot Name

ChatArray={}
dofile(saveFile)
function Main()
frmHub:RegBot(ChatBot)
end
--======================================================== DataArrival: =========================================================--
function DataArrival(user, data)
   if (strsub(data, 1, 1) == "<" ) then
      data=strsub(data,1,strlen(data)-1)
      _,_,cmd=strfind(data, "%b<>%s+(%S+)")
      local Commands = (DeveloperCommands(user, data, cmd))
      return Commands
   elseif strsub(data, 1, 5) == "$To: " then
      local s, e, to = strfind(data, "$To: (%S+)")
      if to ~= ChatBot then
         return 0
      else
         if to == ChatBot then
            local data=strsub(data,1,strlen(data)-1)
            local s,e,from,msg = strfind(data,"From:%s+(%S+)%s+$%b<>%s+(.+)")
            if ChatArray[user.sName] ~= nil then
               ChatArray[user.sName] = nil
               for i,v in ChatArray do
                  Developer=GetItemByName(i)
                  if (Developer~=nil) then
                     Developer:SendData("$To: "..i.." From: "..ChatBot.." $<"..user.sName.."> "..msg.."|")
                  end
               end
               ChatArray[user.sName] = 1
            else
               user:SendPM(ChatBot,"You do not have permission to write inhere. Type +chat in the main to join.")
            end
            local _,_,cmd = strfind(data,"$%b<>%s+(%S+)")
            local Commands = (DeveloperCommands(user, data, cmd))
         end
      end
   end
end
--===================================================== Chat Commands: ======================================================--
function DeveloperCommands(user, data, cmd)
      if (cmd == "+chathelp") then
         user:SendPM(ChatBot,        
            "\r\n\r\n"..
            "~~ Scripted "..ChatBot.." Commands: ~~\r\n\r\n"..
            " +chat - Add or part a user to the list of people that can chat in the "..ChatBot.."\r\n"..
            " +showchatters - See witch users that can chat in the "..ChatBot.."\r\n"..
            "\r\n")
         return 1
      elseif (cmd == "+chat") then
         local s,e,cmd,ChatName = strfind( data, "%b<>%s+(%S+)%s+(.*)" )
         if (ChatName == nil) then
            ChatName = user.sName
         end
         if ChatArray[ChatName] == nil then
            ChatArray[ChatName] = 1
            for index, value in ChatArray do
               SendPmToNick(index, ChatBot, " "..ChatName.." Has joined the "..ChatBot)
            end
         else
            for index, value in ChatArray do
               SendPmToNick(index, ChatBot, " "..ChatName.." Has left the "..ChatBot)
            end
            ChatArray[ChatName] = nil
         end
         SerializeSave(ChatArray, "ChatArray", "")
         return 1
      elseif (cmd == "+showchatters") then
         function DevList()
         local DevList = ""
         for index, value in ChatArray do
            local line = index
               if GetItemByName(index) then
                  if (strlen(index) <= 10) then
                     DevList = DevList.." ? "..line.."\t\t\t~ On-line ~\r\n"
                  else
                     DevList = DevList.." ? "..line.."\t\t~ On-line ~\r\n"
                  end
               else
                  if (strlen(index) <= 10) then
                     DevList = DevList.." ? "..line.."\t\t\t? Off-Line ?\r\n"
                  else
                     DevList = DevList.." ? "..line.."\t\t? Off-Line ?\r\n"
                  end
               end
            end
            return DevList
         end
         user:SendPM(ChatBot, "\r\n\r\n(? ?.??.-> "..ChatBot.." Chatters <-.??.???) \r\n\r\n"..DevList())
         return 1
      end
 --  else user:SendData("You don't have permission to use the commands to the "..ChatBot.." ask a Operator for permission !!") return 0 end
end
--======================================================== Functions: ===========================================================--
function SaveToFile(file,string)
   local f,e = openfile( file, "w+" )
   if f then
     write(f, string )
     closefile(f)
   end
end
--//Simple Serialization.
function SerializeSave(tTable, sTableName, sTab)
   sTab = sTab or "";
   sTmp = ""
   sTmp = sTmp..sTab..sTableName.."={"
   local tStart = 0
for key, value in tTable do
      if tStart == 1 then
         sTmp = sTmp..",\r\n"
      else
         sTmp = sTmp.."\r\n"
         tStart = 1
      end
      local sKey = (type(key) == "string") and format("[%q]",key) or format("[%d]",key);
      if(type(value) == "table") then
         sTmp = sTmp..Serialize(value, sKey, sTab.."\t");
      else
         local sValue = (type(value) == "string") and format("%q",value) or tostring(value);
         sTmp = sTmp..sTab.."\t"..sKey.." = "..sValue
      end
   end
   sTmp = sTmp.."\r\n"..sTab.."}"
   SaveToFile(saveFile, sTmp)
end
--========================= DeveloperChat Bot Coded By [aXs] Wellx For [DK] The Ice Cube? 50 GB ===========================--


-BH
Title:
Post by: Dj_OcTaGoN on 22 August, 2004, 16:37:51
Yeah, it works, thank you very much!  :]
Title:
Post by: BottledHate on 22 August, 2004, 21:59:18
np... glad to help!

i made some more mods to this chatbot.. check it out in this THREAD (http://board.univ-angers.fr/thread.php?threadid=2619&boardid=12&styleid=1&sid=5cad0f592e09c7aca3db2610661a7fe3).....

-BH