lsyncd/examples/lsayirc.lua

141 lines
4.0 KiB
Lua
Raw Normal View History

2010-12-01 14:11:18 +00:00
-----
-- An Lsyncd+IRC-Bot Config
--
-- Logs into an IRC channel and tells there everything that happens in the
2010-12-01 14:11:18 +00:00
-- watched directory tree.
--
-- The challenge coding Lsyncd configs taking use of TCP sockets is
-- that they must not block! Otherwise Lsyncd will block, no longer
-- empty the kernels monitor queue, no longer collecting zombie processes,
-- no longer spawning processes (this example doesnt do any, but maybe you
-- might want to do that as well), blocking is just bad.
--
-- This demo codes just minimal IRC functionality.
2010-12-01 14:11:18 +00:00
-- it does not respond to anything else than IRC PING messages.
2010-12-01 15:19:12 +00:00
--
-- There is no flood control, if a lot happens the IRC server will disconnect
-- the bot.
--
2010-12-01 14:11:18 +00:00
-- Requires "luasocket" to be installed
2010-12-01 12:19:17 +00:00
require("socket")
2010-12-01 14:11:18 +00:00
-- For demo reasons, do not detach
2010-12-01 12:19:17 +00:00
settings.nodaemon = true
2010-12-01 13:17:04 +00:00
hostname = "irc.freenode.org"
--hostname = "127.0.0.1"
2010-12-01 12:19:17 +00:00
port = 6667
nick = "lbot01"
chan = "##lfile01"
-- this blocks until the connection is established
2010-12-01 14:11:18 +00:00
-- for once lets say this ok since Lsyncd didnt yet actually
-- start.
2010-12-01 12:19:17 +00:00
local ircSocket, err = socket.connect(hostname, port)
if not ircSocket then
log("Error", "Cannot connect to IRC: ", err)
terminate(-1)
end
2010-12-01 14:11:18 +00:00
-- from now on, the socket must not block!
2010-12-01 12:19:17 +00:00
ircSocket:settimeout(0)
2010-12-01 14:11:18 +00:00
-- Buffers for stuff to send and receive on IRC:
2010-12-01 12:19:17 +00:00
local ircWBuf = ""
local ircRBuf = ""
2010-12-01 14:11:18 +00:00
-- Predeclaration for functions calling each other
local writeIRC
2010-12-01 12:19:17 +00:00
-----
2010-12-01 14:11:18 +00:00
-- Called when the IRC socket can be written again.
-- This happens when writeIRC (see below) couldnt write
-- its buffer in one go, call it again so it can continue its task.
2010-12-01 12:19:17 +00:00
local function ircWritey(fd)
2010-12-01 14:11:18 +00:00
writeIRC()
2010-12-01 12:19:17 +00:00
end
----
-- Called when there is data on the socket
2010-12-01 12:19:17 +00:00
local function ircReady(socket)
local l, err, ircRBuf = ircSocket:receive("*l", ircRBuf)
if not l then
2010-12-01 14:11:18 +00:00
if err ~= "timeout" then
2010-12-01 12:19:17 +00:00
log("Error", "IRC connection failed: ", err)
terminate(-1)
end
else
ircRBuf = ""
end
log("Normal", "ircin :", l)
--- answers ping messages
local ping = l:match("PING :(.*)")
if ping then
2010-12-01 14:11:18 +00:00
writeIRC("PONG :", ping, "\n")
2010-12-01 12:19:17 +00:00
end
end
-----
-- Writes on IRC socket
2010-12-01 14:11:18 +00:00
-- Do not forget to add an "/n".
function writeIRC(...)
-- Appends all arbuments into the write buffer
2010-12-01 12:19:17 +00:00
ircWBuf = ircWBuf..table.concat({...})
2010-12-01 14:11:18 +00:00
-- Gives it to the socket and sees how much it accepted
2010-12-01 12:19:17 +00:00
local s, err = ircSocket:send(ircWBuf)
2010-12-01 14:11:18 +00:00
-- If it cant the socket terminated.
2010-12-01 14:20:44 +00:00
if not s and err~="timeout" then
2010-12-01 12:19:17 +00:00
log("Error", "IRC connection failed: ", err)
terminate(-1)
end
2010-12-01 14:11:18 +00:00
--- logs what has been send, without the linefeed.
2010-12-01 12:19:17 +00:00
if (ircWBuf:sub(s, s) == "\n") then
2010-12-01 14:11:18 +00:00
log("Normal", "ircout:", ircWBuf:sub(1, s - 1))
2010-12-01 12:19:17 +00:00
else
log("Normal", "ircout: ", ircWBuf:sub(1, s), "\\")
end
2010-12-01 14:11:18 +00:00
---- reduces the buffer by the amount of data sent.
2010-12-01 12:19:17 +00:00
ircWBuf = ircWBuf:sub(s + 1, -1)
2010-12-01 14:11:18 +00:00
-- when the write buffer is empty tell the core to no longer
-- call ircWritey if data can be written on the socket. There
-- is nothing to be written. If there is data in the buffer
-- asks to be called as soon it can be written again
2010-12-01 12:19:17 +00:00
if ircWBuf == "" then
observefd(ircSocket:getfd(), ircReady, nil)
else
observefd(ircSocket:getfd(), ircReady, ircWritey)
end
end
2010-12-01 14:11:18 +00:00
-- Aquires the nick on IRC and joins the configured channel
-- This will also register the ircReady/ircWritey function at the core
-- to be called when the socket is ready to be read/written.
writeIRC("NICK ", nick, "\n")
writeIRC("USER ", nick, " 0 * :lsyncd-sayirc-bot", "\n")
writeIRC("JOIN ", chan, "\n")
2010-12-01 12:19:17 +00:00
2010-12-01 14:11:18 +00:00
-- As action tells on IRC what the action is, then instead of
-- spawning somthing, it discards the event.
2010-12-01 12:19:17 +00:00
local function action(inlet)
-- event2 is the target of a move event
local event, event2 = inlet.getEvent()
if not event2 then
2010-12-01 14:11:18 +00:00
writeIRC("PRIVMSG ",chan," :",event.etype," ",
2010-12-01 13:39:11 +00:00
event.path, "\n")
2010-12-01 12:19:17 +00:00
else
2010-12-01 14:11:18 +00:00
writeIRC("PRIVMSG ",chan," :",event.etype," ",
2010-12-01 13:39:11 +00:00
event.path," -> ",event2.path, "\n")
2010-12-01 12:19:17 +00:00
end
inlet.discardEvent(event)
end
2010-12-01 14:11:18 +00:00
-- Watch a directory, and use a second for delay to aggregate events a little.
sync{source = "src",
action = action,
2010-12-01 14:11:18 +00:00
delay = 1,
onMove = true}
2010-12-01 12:19:17 +00:00