diff --git a/scripts/dev_ipad_run.sh b/scripts/dev_ipad_run.sh index 09f34ca..9dd2264 100755 --- a/scripts/dev_ipad_run.sh +++ b/scripts/dev_ipad_run.sh @@ -13,4 +13,5 @@ trap "trap_ctrlc" 2 cd src export KETRACEL_DEBUG=yes export KETRACEL_SPASS=hunter2 -lua5.3 -l set_paths ketracel.lua +lua5.3 -l set_paths ketracel/main.lua +trap_ctrlc diff --git a/spec/ngircd_harness_spec.moon b/spec/ngircd_harness_spec.moon index 832eb0e..2059f04 100644 --- a/spec/ngircd_harness_spec.moon +++ b/spec/ngircd_harness_spec.moon @@ -1,29 +1,28 @@ irce = require "irce" socket = require "socket" test = require "ketracel.test" +Server = require("ketracel.server").Server +uuid = require "uuid" describe "ngircd protocol support", -> - local file - local last_msg - client = socket.tcp! - client\settimeout 1 - irc = irce.new! - irc\set_send_func (message) => - last_msg = message - print "[server] > " .. message - client\send message - irc\load_module require "irce.modules.ngircd" + local server + local client setup -> print "got here" file = io.popen "ngircd -n -f ./spec/ngircd.conf", "r" + server = Server + server: "127.0.0.1" + sname: "ketracel.akua" + spass: "hunter2" + sreal: "Ketracel" + nicklen: "31" + debug: true + client = test.Client "test_user" teardown -> with io.popen "killall ngircd", "r" \close! - with file - print \read "*all" - \close! it "actually is running ngircd", -> with io.popen "pstree" @@ -31,21 +30,14 @@ describe "ngircd protocol support", -> assert.truthy string.find data, "ngircd" it "registers", -> - bursted = false - irc\set_callback "376", => - bursted = true - - client\connect "127.0.0.1", 6667 - irc\REGISTER "hunter2", "kc-test", "0.0.1", "ketracel.akua", "test", "31" - - while not bursted - msg = client\receive! - print "[server] " .. msg - irc\process msg - - @irc\clear_callback "376" + server\wait_for "376" it "can use the Client class", -> - cli = test.Client "test_user" - cli\wait_for "005" - cli\quit! + client\wait_for "005" + + it "sees the client", -> + server\wait_for "NICK" + + it "sees the client join a new channel", -> + client.irc\JOIN "#" .. uuid() + server\wait_for "JOIN" diff --git a/src/bots/ketracel.moon b/src/bots/ketracel.moon deleted file mode 100644 index 2981584..0000000 --- a/src/bots/ketracel.moon +++ /dev/null @@ -1,45 +0,0 @@ -irce = require "irce" -ln = require "ln" -moon = require "moon" -stringx = require "pl.stringx" - -{ - hooks: - ["376"]: (state) => - self\NICK "Ketracel", "white", "the.dominion", "+io", "Ketracel White" - self\NJOIN "#ketracel", "@Ketracel" - - --["NJOIN"]: (state, chan) => - -- self\NJOIN chan, "Ketracel" - - ["PRIVMSG"]: (state, sender, params) => - cmdchar = params[2]\sub 1, 1 - destsigil = params[1]\sub 1, 1 - - if params[1]\lower! == "ketracel" - sp = stringx.split params[2] - cmd = sp[1] - table.remove sp, 1 - self\handle("Ketracel command", sender[1], params[1], cmd, sp) - - if cmdchar == "?" and destsigil == "#" - sp = stringx.split params[2] - cmd = string.sub sp[1], 2 - table.remove sp, 1 - self\handle("Ketracel command", sender[1], params[1], cmd, sp) - - ["Ketracel command"]: (state, sender, target, cmd, args) => - switch string.upper cmd - when "STATE" - 1 + 1 - when "VHOST" - if #args > 0 - ln.log - :sender, vhost: args[1], action: "setting vhost" - self\VHOST sender, args[1] - self\NOTICE "Ketracel", sender, "your vhost is now " ..args[1] - else - self\NOTICE "Ketracel", sender, "usage: VHOST " - else - self\NOTICE "Ketracel", sender, "i don't know " .. cmd -} diff --git a/src/irce/modules/ngircd/init.moon b/src/irce/modules/ngircd/init.moon index 74308f0..7cde10e 100644 --- a/src/irce/modules/ngircd/init.moon +++ b/src/irce/modules/ngircd/init.moon @@ -71,6 +71,9 @@ moon = require "moon" string.format ":%s PART %s :%s", nick, chan, why handlers: + ["461"]: (state, sender, params) => + self\handle "DIE", string.format("%s: %s", sender[1], params[1]) + ["ERROR"]: (state, sender, params) => error string.format "%s: %s", sender[1], params[1] @@ -96,6 +99,8 @@ moon = require "moon" state.channels[chan] = {name: chan, mode: "", members: {}, topic: ""} state.channels[chan].members[nick] = mode + state.channels[chan] + ["PART"]: (state, sender, params) => chan = params[1] nick = string.lower sender[1] diff --git a/src/ketracel.moon b/src/ketracel.moon deleted file mode 100644 index 1ec4767..0000000 --- a/src/ketracel.moon +++ /dev/null @@ -1,45 +0,0 @@ -irce = require "irce" -ln = require "ln" -socket = require "socket" - -config = - server: os.getenv("IRC_HOST") or "127.0.0.1" - sname: os.getenv("KETRACEL_SNAME") or "ketracel.akua" - spass: os.getenv("KETRACEL_SPASS") or error("need KETRACEL_SPASS") - sreal: os.getenv("KETRACEL_SREAL") or "The favorite of the Jem'Hadar" - debug: os.getenv("KETRACEL_DEBUG") - nicklen: os.getenv("KETRACEL_NICKLEN") or "31" - -irc = irce.new! -running = true - --- load IRC modules -assert irc\load_module require "irce.modules.ngircd" -assert irc\load_module require "bots.ketracel" - -client = socket.tcp! -client\settimeout 1 - -irc\set_send_func (message) => - client\send message - -if config.debug - ln.log config - irc\set_callback irce.RAW, (send, message) => - print string.format "%s %s", (send and ">" or "<"), message - -ln.log msg: "Ketracel loaded", irce: irce._VERSION, lua: _VERSION - --- connect to irc server -assert client\connect config.server, 6667 - -assert irc\REGISTER config.spass, "ketracel", "0.0.1", config.sname, config.sreal, config.nicklen - -if config.oper - irc\OPER config.nick, config.oper - print "IRC operator status requested for " .. config.nick - -while running - irc\process client\receive! - -client\close! diff --git a/src/bots/Tupfile b/src/ketracel/bots/Tupfile similarity index 100% rename from src/bots/Tupfile rename to src/ketracel/bots/Tupfile diff --git a/src/ketracel/bots/commands.moon b/src/ketracel/bots/commands.moon new file mode 100644 index 0000000..47d34f8 --- /dev/null +++ b/src/ketracel/bots/commands.moon @@ -0,0 +1,38 @@ +ln = require "ln" +stringx = require "pl.stringx" + +class CommandRouter + new: (bot, cmdchar = "?") => + @bot = bot + @cmdchar = cmdchar + @commands = {} + + register: (verb, action) => + self.commands[verb] = action + + run: (sender, target, verb, args) => + verb = string.upper verb + cmd = self.commands[verb] + if cmd == nil + @bot.irc\NOTICE @bot.name, sender, "unknown command verb " .. verb + return + + cmd sender, target, verb, args + + privmsg: (sender, params) => + cmdchar = params[2]\sub 1, 1 + destsigil = params[1]\sub 1, 1 + + if params[1]\lower! == @bot.name\lower! + sp = stringx.split params[2] + cmd = sp[1] + table.remove sp, 1 + @run sender[1], params[1], cmd, sp + + if cmdchar == @cmdchar and destsigil == "#" + sp = stringx.split params[2] + cmd = string.sub sp[1], (#@cmdchar + 1) + table.remove sp, 1 + @run sender[1], params[1], cmd, sp + +CommandRouter diff --git a/src/ketracel/bots/ketracel.moon b/src/ketracel/bots/ketracel.moon new file mode 100644 index 0000000..209fb00 --- /dev/null +++ b/src/ketracel/bots/ketracel.moon @@ -0,0 +1,47 @@ +irce = require "irce" +ln = require "ln" +moon = require "moon" +stringx = require "pl.stringx" +CommandRouter = require "ketracel.bots.commands" + +class Ketracel + new: (irc) => + @name = "Ketracel" + @irc = irc + router = CommandRouter self + router\register "DIE", (sender, target, verb, args) -> @die sender, target, verb, args + router\register "VHOST", (...) -> @set_vhost ... + self.router = router + + burst: => + @irc\NICK "Ketracel", "white", "the.dominion", "+io", "Ketracel White" + @irc\NJOIN "#ketracel", "&@Ketracel" + + njoin: (chan) => + @irc\NJOIN chan, "Ketracel" + + die: (sender, target, verb, args) => + @irc\handle "DIE", string.format("%s asked me to die in %s", sender, target) + + set_vhost: (sender, target, verb, args) => + if #args > 0 + ln.log :sender, vhost: args[1], action: "setting vhost" + @irc\VHOST sender, args[1] + @irc\NOTICE "Ketracel", sender, "your vhost is now " ..args[1] + else + @irc\NOTICE "Ketracel", sender, "usage: VHOST " + +{ + init: (state) => + state.bot = Ketracel self + + hooks: + ["376"]: (state) => + state.bot\burst! + + ["NJOIN"]: (state, chan) => + state.bot\njoin chan + + ["PRIVMSG"]: (state, sender, params) => + state.bot.router\privmsg sender, params +} diff --git a/src/ketracel/main.moon b/src/ketracel/main.moon new file mode 100644 index 0000000..40dd234 --- /dev/null +++ b/src/ketracel/main.moon @@ -0,0 +1,15 @@ +irce = require "irce" +ln = require "ln" +socket = require "socket" +server = require "ketracel.server" + +config = + server: os.getenv("IRC_HOST") or "127.0.0.1" + sname: os.getenv("KETRACEL_SNAME") or "ketracel.akua" + spass: os.getenv("KETRACEL_SPASS") or error("need KETRACEL_SPASS") + sreal: os.getenv("KETRACEL_SREAL") or "The favorite of the Jem'Hadar" + debug: os.getenv("KETRACEL_DEBUG") + nicklen: os.getenv("KETRACEL_NICKLEN") or "31" + +with server.Server config + \run! diff --git a/src/ketracel/server.moon b/src/ketracel/server.moon new file mode 100644 index 0000000..28d0756 --- /dev/null +++ b/src/ketracel/server.moon @@ -0,0 +1,54 @@ +irce = require "irce" +ln = require "ln" +socket = require "socket" + +class Server + new: (config) => + @config = config + socket = socket.tcp! + irc = irce.new! + + irc\load_module require "irce.modules.ngircd" + irc\load_module require "ketracel.bots.ketracel" + + irc\set_send_func (message) => + socket\send message + + if config.debug + ln.log {"msg": "debug enabled"}, config + irc\set_callback irce.RAW, (send, message) => + sigil = send and ">" or "<" + print string.format "%s %s", (send and ">" or "<"), message + + ln.log msg: "Ketracel loaded", irce: irce._VERSION, lua: _VERSION + + assert socket\connect config.server, 6667 + assert irc\REGISTER config.spass, "ketracel", "0.0.1", config.sname, config.sreal, config.nicklen + + @irc = irc + @socket = socket + + wait_for: (event) => + running = true + + @irc\set_callback event, => + running = false + + while running + @irc\process @socket\receive! + + run: => + running = true + + @irc\set_callback "DIE", (why) => + ln.err why, {msg: "told to die"} + running = false + + while running + @irc\process @socket\receive! + + @socket\close! + +{ + :Server +}