Add infobot example

This commit is contained in:
Neale Pickett 2012-11-27 18:26:54 -07:00
parent 98aced9bbc
commit 45d4b56873
11 changed files with 79 additions and 30 deletions

View File

@ -1,11 +1,14 @@
CFLAGS = -Wall -Werror
TARGETS = bot
TARGETS += extras/factoids
TARGETS = bot factoids
all: $(TARGETS)
extras/factoids: extras/factoids.o extras/cdb.o extras/cdbmake.o
%: src/%
cp $< $@
src/bot:
src/factoids: src/factoids.o src/cdb.o src/cdbmake.o
.PHONY: clean
clean:
rm -f $(TARGETS) *.o extras/*.o
rm -f $(TARGETS) $(addprefix src/, $(TARGETS)) src/*.o

30
README
View File

@ -84,6 +84,16 @@ want, and you don't even need to restart anything to apply your changes,
since a new handler is launched for each message.
factoids
========
A program to maintain a low-overhead, read-optimized database file, which
can store multiple values for each key. This was written to help develop
infobots, but can also be used for any other key/value store needed.
The `infobot.py` program in `contrib/` has a simple infobot implementation.
Caution
=======
@ -103,26 +113,6 @@ much more difficult to accidentally create an exploit. Or create a new
handler in Python, Ruby, etc.
Extras
======
Included AT NO ADDITIONAL COST, in the `extras/` directory, are:
newmont
-------
A simple handler, written in lua.
factoids
--------
A program to maintain a low-overhead, read-optimized database file, which
can store multiple values for each key. This was written to help develop
infobots, but can also be used for any other key/value store needed.
Author
======

1
TODO
View File

@ -1 +0,0 @@

48
contrib/infobot.py Executable file
View File

@ -0,0 +1,48 @@
#! /usr/bin/python
##
## Example of an infobot, using the provided helper.
##
import sys
import os
from subprocess import *
db = "infobot.cdb"
command = os.environ.get("command")
sender = os.environ.get("sender")
forum = os.environ.get("forum")
text = os.environ.get("text")
def factoids(*args):
cmd = ["./factoids"]
cmd.extend(args)
p = Popen(cmd, stdout=PIPE, stderr=STDOUT)
for bline in p.stdout:
line = bline.decode('utf-8')[:-1]
print("PRIVMSG %s :%s" % (forum, line))
# Create db if it doesn't exist
if not os.path.exists(db):
factoids("-n", db)
if command == "_INIT_":
print("NICK infotest")
print("USER infotest infotest infotest: Infobot example")
elif command == "001":
print("JOIN #infotest")
elif command == "PRIVMSG":
if text[0] == "!":
txt = text[1:]
if " += " in txt:
key, val = txt.split(' += ', 1)
factoids("-a", val, db, key)
elif " -= " in txt:
key, glob = txt.split(' -= ', 1)
factoids("-r", glob, db, key)
else:
factoids("-l", db, txt)
else:
factoids(db, text)

View File

@ -2,12 +2,12 @@
--
-- A very simple bot which will join IRC, join #newmont, and
-- respond to any messages with "strawberry" in them. It also
-- has some naïve nickname collision avoidance.
-- talk about strawberries. It also has some naïve nickname
-- collision avoidance.
--
-- This is a good place to start if you're not going to write
-- your handler in lua. If you *do* want to use lua, you should
-- take a look at bot.lua instead.
-- think about how to make a better design :)
--
prefix = os.getenv("prefix")
@ -21,17 +21,23 @@ io.stderr:write(">>> [" .. command .. "] " ..
(forum or "-") .. " " ..
(text or "") .. "\n")
--
-- Our behavior depends on what the command is
--
if (command == "_INIT_") then
-- bot sends this when it first starts up, so we can log in
print("NICK nemont")
print("USER newmont newmont newmont :Sample bot")
elseif (command == "433") then
-- Couldn't get the nickname we asked for
print("NICK bot_" .. (os.time() % 500))
elseif (command == "001") then
-- IRC server sends this after successful login
print("JOIN #newmont")
elseif (command == "PRIVMSG") then
-- Somebody said something!
if (text:find("strawberry")) then

View File

View File

@ -129,7 +129,10 @@ cdb_find(struct cdb_ctx *ctx, char *key, size_t keylen)
fseek(ctx->f, (ctx->hash_val % 256) * 8, SEEK_SET);
ctx->hash_pos = read_u32le(ctx->f);
ctx->hash_len = read_u32le(ctx->f);
ctx->entry = (ctx->hash_val / 256) % ctx->hash_len;
if (ctx->hash_len > 0) {
ctx->entry = (ctx->hash_val / 256) % ctx->hash_len;
}
}
uint32_t
@ -140,7 +143,7 @@ cdb_next(struct cdb_ctx *ctx, char *buf, size_t buflen)
uint32_t klen;
uint32_t dlen;
for (;;) {
for (; ctx->hash_len > 0;) {
fseek(ctx->f, ctx->hash_pos + (ctx->entry * 8), SEEK_SET);
ctx->entry = (ctx->entry + 1) % ctx->hash_len;