summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNatanael Copa <ncopa@alpinelinux.org>2018-08-08 12:23:09 +0200
committerNatanael Copa <ncopa@alpinelinux.org>2018-08-08 12:23:09 +0200
commitb67d71c3b65bafe1375d66747fd29940b83564df (patch)
tree5da0e92c7515b0cfa7ba8e8d96d1a425f3fb770e
parent552e8b29dc0f35f1d18539d76ea59ba1a23abbc5 (diff)
downloadalbotty-b67d71c3b65bafe1375d66747fd29940b83564df.tar.bz2
albotty-b67d71c3b65bafe1375d66747fd29940b83564df.tar.xz
add support for hooks and autojoin channels
-rw-r--r--bot.lua177
1 files changed, 163 insertions, 14 deletions
diff --git a/bot.lua b/bot.lua
index d218771..f35f742 100644
--- a/bot.lua
+++ b/bot.lua
@@ -1,6 +1,7 @@
local cqueues = require("cqueues")
local socket = require("cqueues.socket")
+local errno = require("cqueues.errno")
local loop = cqueues.new()
@@ -17,11 +18,21 @@ function irc.new(nick, username, password, realname)
nick = nick or "albotty",
username = username or "albotty",
password = password,
- realname = realname or "albotty"
+ realname = realname or "albotty",
+ hooks = {},
+ channels = {}
}
return setmetatable(self, { __index = irc })
end
+function irc:autojoin(channels)
+ for _,chan in pairs(channels) do
+ self.channels[chan] = self.channels[chan] or {}
+ self.channels[chan].autojoin = true
+ self.channels[chan].joined = false
+ end
+end
+
function irc:connect(host, port)
local hostname, password, tls, timeout
if type(host) == "table" then
@@ -34,11 +45,14 @@ function irc:connect(host, port)
hostname = host
end
self.conn = socket.connect(hostname, port)
- self.conn:settimeout(timeout or 30)
+ self.conn:settimeout(timeout or 10)
self:send("NICK %s", self.nick)
self:send("USER %s 0 * :%s", self.username, self.realname)
+--[[
+-- self.conn:settimeout(-1)
+
local loop = cqueues.new()
loop:wrap(function()
for line in sess.conn:lines("*L") do
@@ -56,6 +70,7 @@ function irc:connect(host, port)
error("loop.step: "..err)
end
end
+]]--
return self
end
@@ -72,11 +87,38 @@ function irc:send(msg, ...)
if select("#", ...) > 0 then
msg = msg:format(...)
end
- -- call send hook
+ self:run_hooks("OnSend", msg)
self.conn:write(msg.."\r\n")
self.conn:flush()
end
+function irc:send_chat(target, message)
+ for line in message:gmatch("([^\r\n]+)") do
+ self:send("PRIVMSG %s :%s", target, line)
+ end
+end
+
+function irc:join(channel)
+ self.channels[channel] = self.channels[channel] or {}
+ self.channels[channel].joined = true
+ self:send("JOIN %s", channel)
+end
+
+function irc:hook(event, id, func)
+ func = func or id
+ self.hooks[event] = self.hooks[event] or {}
+ self.hooks[event][id] = func
+ return self
+end
+
+function irc:run_hooks(event, ...)
+ for id, func in pairs(self.hooks[event] or {}) do
+ if func(self, ...) then
+ return true
+ end
+ end
+end
+
local function irc_parse(line)
local prefix
local lineStart = 1
@@ -126,9 +168,11 @@ end
irc.callbacks["001"] = function(self, prefix, me)
self.authed = true
self.nick = me
-end
-
-irc.callbacks["NOTICE"] = function(self, prefix, channel, msg)
+ for name, chan in pairs(self.channels) do
+ if chan.autojoin then
+ self:join(name)
+ end
+ end
end
irc.callbacks["NICK"] = function(self, prefix, newnick)
@@ -143,12 +187,81 @@ irc.callbacks["NICK"] = function(self, prefix, newnick)
if self.nick == user.nick then
self.nick = newnick
end
+ self:run_hooks("OnNick", user, newnick)
end
irc.callbacks["PING"] = function(self, prefix, query)
- self:send("PONG :%", query)
+ self:send("PONG :%s", query)
+end
+
+irc.callbacks["PRIVMSG"] = function(self, prefix, channel, message)
+ self:run_hooks("OnChat", parse_prefix(prefix), channel, message)
+end
+
+irc.callbacks["NOTICE"] = function(self, prefix, channel, message)
+ self:run_hooks("OnNotice", parse_prefix(prefix), channel, message)
+end
+
+irc.callbacks["JOIN"] = function(self, prefix, channel)
+ self:run_hooks("OnJoin", parse_prefix(prefix), channel)
+end
+
+irc.callbacks["PART"] = function(self, prefix, channel, reason)
+ local user = parse_prefix(prefix)
+ self:run_hooks("OnPart", user, channel, reason)
+end
+
+irc.callbacks["KICK"] = function(self, prefix, channel, kicked, reason)
+ self:run_hooks("OnKick", channel, kicked, parse_prefix(prefix), reason)
+end
+
+irc.callbacks["QUIT"] = function(self, prefix, message)
+ local user = parse_prefix(prefix)
+ self:run_hooks("OnQuit", user, message)
+end
+
+-- nick in use
+irc.callbacks["432"] = function(self, prefix, target, badnick)
+ local n,i = string.match(self.nick, "(.*)(%d+)$")
+ local newnick
+ newnick = string.format("%s%d",n or self.nick, i+1)
+ self:send("NICK %s", newnick)
end
+irc.callbacks["433"] = irc.callbacks["422"]
+
+-- no topic
+irc.callbacks["331"] = function(self, prefix, me, channel)
+ self:run_hooks("OnTopic", channel, nil)
+end
+
+irc.callbacks["332"] = function(self, prefix, me, channel, topic)
+ self:run_hooks("OnTopic", channel, topic)
+end
+
+irc.callbacks["333"] = function(self, prefix, me, channel, nick, time)
+ self:run_hooks("OnTopicInfo", channel, nick, tonumber(time))
+end
+
+irc.callbacks["TOPIC"] = function(self, prefix, channel, topic)
+ self:run_hooks("OnTopic", channel, topic)
+end
+
+-- RPL_UMODEIS
+irc.callbacks["221"] = function(self, prefix, user, modes)
+ self:run_hooks("OnUserMode", modes)
+end
+
+-- RPL_CHANNELMODEIS
+irc.callbacks["324"] = function(self, prefix, channel, modes)
+ self:run_hooks("OnChannelMode", channel, modes)
+end
+
+irc.callbacks["MODE"] = function(self, prefix, target, modes, ...)
+ self:run_hooks("OnModeChange", parse_prefix(prefix), target, modes, ...)
+end
+
+
function irc:handle(line)
local prefix, cmd, params = irc_parse(line)
callback = self.callbacks[cmd]
@@ -162,25 +275,61 @@ end
function irc:step()
- local line, why, errmsg = self.conn:read("*L")
+ local line, why = self.conn:read("*L")
if not line or #line == 0 then
- return nil
+ if why == errno.ETIMEDOUT then
+ self:run_hooks("OnTimeout")
+ end
+ return nil, why
end
self:handle(line)
return line
end
+---------------------------------------------------------------------------
sess = irc.new()
-sess:connect("chat.freenode.net", "6667")
-print("CONNECTED!!!!!!!!!!!!!!!!!!!!!!!!!!!!11")
+sess:hook("OnChat", function(self, user, channel, message)
+ print("PRIVMSG:")
+ print(" nick:", user.nick)
+ print(" channel:", channel)
+ print(" message:", message)
+ if channel == self.nick then
+ self:send_chat(user.nick, "Hi there")
+ else
+ self:send_chat(channel, "Hi "..user.nick)
+ end
+end)
-loop:wrap(function()
- while sess:step() do
- print("witing for next")
+sess:hook("OnJoin", function(self, user, channel)
+ print("JOIN:")
+ print(" nick:", user.nick)
+ print(" channel:", channel)
+end)
+
+sess:hook("OnKick", function(self, channel, kicked, user, reason)
+ print("Kicked:")
+ print((" %s kicked %s from %s"):format(user.nick, kicked, channel))
+ if kicked == self.nick then
+ self:join(channel)
end
end)
+sess:autojoin{"#alpine-test", "#alpine"}
+
+sess:connect("172.16.3.54", "6667")
+
+
+print("CONNECTED!")
+
+loop:wrap(function()
+ repeat
+ local ok, err = sess:step()
+ print("DEBUG step:", ok, err)
+ until not ok and err ~= errno.ETIMEDOUT
+ return true --nil, err
+end)
+
while not loop:empty() do
local ok, err = loop:step()
if not ok then