Skip to content

Instantly share code, notes, and snippets.

@fowlmouth
Created November 4, 2012 20:21
Show Gist options
  • Save fowlmouth/4013528 to your computer and use it in GitHub Desktop.
Save fowlmouth/4013528 to your computer and use it in GitHub Desktop.
import irc, re, tables, macros, macro_dsl
var
commands = initTable[string, proc(event: var TircEvent;
args: string){.closure.}]()
handlers: seq[tuple[
pattern: TRegex;
match: proc(event: var TircEvent; args: var openarray[string]){.
closure.}]] = @[]
matchPattern: TRegex
proc setPrefix*(prefix: string) =
matchPattern = re(prefix & r"(\S+)\s*") ##match for commands
template def_pattern*(pattern: TRegex, body: stmt): stmt =
bind handlers
handlers.add((pattern, proc(event: var TircEvent; args: var openarray[string]){.
closure.} = body))
template def_command*(match: string; body: stmt): stmt =
bind commands
commands[match] = (proc(event: var TircEvent; args: string) = body)
macro parseArgs*(argnames: varargs[expr]): stmt {.immediate.} =
## parse a string for arguments. Only useful from inside a command.
## parseArgs(arg1, ...arg2) will parse for (\S+)\s*(.*)\s*
## with those names. Support for matching quotes will be added one day.
var
rgx = ""
injectVars = newNimNode(nnkVarSection)
matchesSize = 0
let cs = callsite()
for i in 1.. <len(cs):
let this = cs[i]
injectVars.add(newNimNode(nnkIdentDefs).und(
this.basename(),
!!"string",
newNimNode(nnkBracketExpr).und(
!!"matches",
newIntLitNode(matchesSize))))
if this.kind == nnkPrefix and this[0].ident == !"...":
rgx.add(r"(.*)")
else:
rgx.add(r"(\S+)")
rgx.add(r"\s*")
inc matchesSize
result = newNimNode(nnkStmtList).und(
newNimNode(nnkVarSection).und(
newNimNode(nnkIdentDefs).und(
!!"matches",
newNimNode(nnkBracketExpr).und(
!!"array",
newNimNode(nnkInfix).und(
!!"..",
newIntLitNode(0),
newNimNode(nnkPrefix).und(
!!"<",
newIntLitNode(matchesSize))),
!!"string"),
newEmptyNode())),
newNimNode(nnkDiscardStmt).und(
newCall(!!"match", !!"args", newCall(!!"re", newStrLitNode(rgx)), !!"matches")),
injectVars)
when defined(Debug):
echo(repr(result))
proc dispatch*(event: var TIRCevent) =
var ms: array[0..0, string]
let n = event.params[1].matchlen(matchPattern, ms)
if n > -1:
let command = commands[ms[0]]
if not command.isNil:
let args = event.params[1][n.. -1]
echo(repr(args))
command(event, args)
else:
## look in generic handlers
for pattern, matchfunc in items(handlers):
if event.params[1] =~ pattern:
matchfunc(event, matches)
##break
import irc, re, tables, macros, macro_dsl, irc_commands
when defined(LuaTest):
import lua, lauxlib, lualib
from sockets import TPort
from strutils import format
var client = irc(address = "irc.freenode.net",
port = 6667.TPort,
nick = "clementine",
user = "nobody",
realname = "nobody",
joinChans = @["#fancyfeast"])
setPrefix("^!")
var
running = true
when defined(LuaTest):
var L = newstate()
openlibs(L)
template luaL_typename(L: PState; index: int): cstring =
lua.typename(L, lua_type(L, i))
proc stackdump(L: PState) =
var top = L.get_top
echo "top is ", top
var res = ""
for i in 1..top:
case luatype(L, i)
of TSTRING:
res.add("str:")
res.add($tostring(L, i))
of TBOOLEAN:
res.add("bool:")
res.add($toboolean(L, i))
of lua.TNUMBER:
res.add("num:")
res.add($tonumber(L, i.cint))
of lua.TFUNCTION:
res.add("func:")
res.add($lual_typename(L, i))
else:
res.add("other:")
res.add($luaType(L,i))
res.add(",")
res.add($typename(L, i))
res.add(' ')
echo res
proc lua_print(L: PState): int {.cdecl.} =
let num_args = L.get_top
var res = ""
L.get_global "tostring"
for i in 1..num_args:
L.push_value(-1)
L.push_value(i)
L.call 1, 1
var s = L.tostring(-1)
if s == nil:
stackdump(L)
break
res.add($s)
if i < num_args:
res.add ", "
L.pop 1
#luaOutput.add_output(res)
stackdump(L)
return 0
proc Lprintirc(L: PState): int {.cdecl.} =
return 0
def_pattern re"^>>\s+(.+)":
let s = args[0]
var error = loadbuffer(L, s, s.len(), "line") != 0 or
pcall(L, 0, 0, 0) != 0
if error:
echo($toString(L, -1))
stackdump(L)
pop(L, 1)
for name, func in items({"print": lua_print}):
#echo("importing ", name, repr(func))
#register(L, cstring(name), func)
push_c_closure(L, func, 0)
#stackdump(L)
setglobal(L, cstring(name))
proc onChannel*(some: var TIRCevent; channel: string): bool {.
inline.} = (some.typ == EvMsg and some.origin == channel)
proc isChannel*(some: string): bool {.inline.} = (some[0] == '#')
var authUsers = @["fowl"]
template userAuth(): stmt {.immediate.} =
if not(event.nick in authUsers): return
template enforcePrivate(): stmt {.immediate.}=
if isChannel(event.origin): return
var channelForwards: seq[tuple[a, b: string]] = @[]
proc `$`[A](some: seq[A]): string =
result = "("
for hit in items(some): result.add($hit)
result.add ")"
def_command "ls_forwards":
enforcePrivate()
client.privmsg event.origin, $channelForwards
def_command "clear_forwards":
enforcePrivate()
channelForwards = @[]
iterator findForwards(chanA: string): string =
for a, b in items(channelForwards):
if a == ChanA: yield b
def_pattern re"^(.*)":
for chan in findForwards(event.origin):
client.privmsg(chan, "<$1> $2".format(event.nick, args[0]))
def_command "quit":
running = false
def_command "part":
parseArgs(channel, ...msg)
if not channel.isNil:
client.part(channel, if msg.isNil: "" else: msg)
def_command "join":
parseArgs(channel)
if not channel.isNil:
client.join channel
def_command "add_forward":
userAuth()
parseArgs fromChannel, toChannel
if not isnil(fromchannel) and not isNil(tochannel):
echo "new forward ", fromchannel, " -> ", tochannel
if not ischannel(fromchannel) or not ischannel(tochannel):
client.privmsg event.origin, "invalid arguments"
else:
client.join(fromchannel)
client.join(tochannel)
channelForwards.add((fromchannel, tochannel))
def_command "say":
userAuth()
enforcePrivate()
parseArgs chan, ...msg
if not isNil(chan) and not isNil(msg):
client.privmsg chan, msg
echo "Connecting..."
client.connect()
while running:
var event: TIRCEvent
if client.poll(event):
case event.typ
of EvDisconnected:
echo "Disconnected!"
#echo repr(event)
running = false
of EvMsg:
#echo("message: ", repr(event))
if event.cmd == MPrivMsg:
dispatch(event)
elif event.cmd == MUnknown:
echo(repr(event))
client.close()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment