Created
November 4, 2012 20:21
-
-
Save fowlmouth/4013528 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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