Browse Source

added !ping, !exec (temporary), and fixed bugs

master
jcao219 13 years ago
parent
commit
f2ccca335d
  1. 33
      oyoyo/client.py
  2. 72
      oyoyo/cmdhandler.py
  3. 45
      oyoyo/examplebot.py
  4. 90
      oyoyo/helpers.py
  5. 11
      vars.py
  6. 73
      wolfbot.py

33
oyoyo/client.py

@ -26,7 +26,6 @@ import os @@ -26,7 +26,6 @@ import os
import traceback
from oyoyo.parse import *
from oyoyo import helpers
from oyoyo.cmdhandler import CommandError
import collections
@ -42,20 +41,19 @@ class IRCClientError(Exception): @@ -42,20 +41,19 @@ class IRCClientError(Exception):
def add_commands(d):
def dec(cls):
for key in d:
for c in d:
def func(x):
def gen(self, *a):
self.send(x, *a)
self.send(x.upper(), *a)
return gen
setattr(cls, d[key], func(key))
setattr(cls, c, func(c))
return cls
return dec
@add_commands({"JOIN": "join",
"MODE": "mode",
"USER": "user",
"NICK": "nick",
"NOTICE": "notice",
"PART": "part"})
@add_commands(("join",
"mode",
"nick",
"notice",
"part"))
class IRCClient:
""" IRC Client class. This handles one connection to a server.
This can be used either with or without IRCApp ( see connect() docs )
@ -84,7 +82,7 @@ class IRCClient: @@ -84,7 +82,7 @@ class IRCClient:
... print "%s said %s" % (prefix, args[1])
...
>>> def connect_callback(c):
... helpers.join(c, '#myroom')
... c.join('#myroom')
...
>>> cli = IRCClient(My_Handler,
... host="irc.freenode.net",
@ -98,8 +96,8 @@ class IRCClient: @@ -98,8 +96,8 @@ class IRCClient:
...
"""
self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.nick = None
self.real_name = None
self.nickname = ""
self.real_name = ""
self.host = None
self.port = None
self.connect_cb = None
@ -132,6 +130,8 @@ class IRCClient: @@ -132,6 +130,8 @@ class IRCClient:
bargs.append(bytes(arg, encoding))
elif isinstance(arg, bytes):
bargs.append(arg)
elif arg is None:
continue
else:
raise IRCClientError('Refusing to send one of the args from provided: %s'
% repr([(type(arg), arg) for arg in args]))
@ -157,8 +157,8 @@ class IRCClient: @@ -157,8 +157,8 @@ class IRCClient:
if not self.blocking:
self.socket.setblocking(0)
helpers.nick(self, self.nick)
helpers.user(self, self.nick, self.real_name)
self.nick(self.nickname)
self.user(self.nickname, self.real_name)
if self.connect_cb:
self.connect_cb(self)
@ -201,6 +201,9 @@ class IRCClient: @@ -201,6 +201,9 @@ class IRCClient:
self.send("QUIT :" + msg)
def identify(self, passwd, authuser="NickServ"):
self.msg(authuser, "IDENTIFY {0}".format(passwd))
def user(self, uname, rname):
self.send("USER", uname, self.host, self.host,
rname or uname)
class IRCApp:
""" This class manages several IRCClient instances without the use of threads.

72
oyoyo/cmdhandler.py

@ -20,7 +20,6 @@ import logging @@ -20,7 +20,6 @@ import logging
import sys
import traceback
from oyoyo import helpers
from oyoyo.parse import parse_nick
# Python < 3 compatibility
@ -150,74 +149,3 @@ class DefaultBotCommandHandler(CommandHandler): @@ -150,74 +149,3 @@ class DefaultBotCommandHandler(CommandHandler):
if (not m.startswith('_') and
not hasattr(getattr(obj, m), 'protected'))]
def help(self, sender, dest, arg=None):
"""list all available commands or get help on a specific command"""
logging.info('help sender=%s dest=%s arg=%s' % (sender, dest, arg))
if not arg:
commands = self.getVisibleCommands()
commands.sort()
helpers.msg(self.client, dest,
"available commands: %s" % " ".join(commands))
else:
try:
f = self.get(arg)
except CommandError as e:
helpers.msg(self.client, dest, str(e))
return
doc = f.__doc__.strip() if f.__doc__ else "No help available"
if not inspect.ismethod(f):
subcommands = self.getVisibleCommands(f)
if subcommands:
doc += " [sub commands: %s]" % " ".join(subcommands)
helpers.msg(self.client, dest, "%s: %s" % (arg, doc))
class BotCommandHandler(DefaultCommandHandler):
""" complete command handler for bots """
def __init__(self, client, command_handler):
DefaultCommandHandler.__init__(self, client)
self.command_handler = command_handler
def privmsg(self, prefix, dest, msg):
self.tryBotCommand(prefix, dest, msg)
@protected
def tryBotCommand(self, prefix, dest, msg):
""" tests a command to see if its a command for the bot, returns True
and calls self.processBotCommand(cmd, sender) if its is.
"""
logging.debug("tryBotCommand('%s' '%s' '%s')" % (prefix, dest, msg))
if dest == self.client.nick:
dest = parse_nick(prefix)[0]
elif msg.startswith(self.client.nick):
msg = msg[len(self.client.nick)+1:]
else:
return False
msg = msg.strip()
parts = msg.split(' ', 1)
command = parts[0]
arg = parts[1:]
try:
self.command_handler.run(command, prefix, dest, *arg)
except CommandError as e:
helpers.msg(self.client, dest, str(e))
return True

45
oyoyo/examplebot.py

@ -1,45 +0,0 @@ @@ -1,45 +0,0 @@
#!/usr/bin/python
"""Example bot for oyoyo that responds to !say"""
import logging
import re
from oyoyo.client import IRCClient
from oyoyo.cmdhandler import DefaultCommandHandler
from oyoyo import helpers
HOST = 'irc.freenode.net'
PORT = 6667
NICK = 'oyoyo-example'
CHANNEL = '#oyoyo-test'
class MyHandler(DefaultCommandHandler):
def privmsg(self, nick, chan, msg):
msg = msg.decode()
match = re.match('\!say (.*)', msg)
if match:
to_say = match.group(1).strip()
print(('Saying, "%s"' % to_say))
helpers.msg(self.client, chan, to_say)
def connect_cb(cli):
helpers.join(cli, CHANNEL)
def main():
logging.basicConfig(level=logging.DEBUG)
cli = IRCClient(MyHandler, host=HOST, port=PORT, nick=NICK,
connect_cb=connect_cb)
conn = cli.connect()
while True:
next(conn) ## python 2
# next(conn) ## python 3
if __name__ == '__main__':
main()

90
oyoyo/helpers.py

@ -1,90 +0,0 @@ @@ -1,90 +0,0 @@
# Copyright (c) 2008 Duncan Fordyce
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
""" contains helper functions for common irc commands """
import random
def msg(cli, user, msg):
for line in msg.split('\n'):
cli.send("PRIVMSG", user, ":%s" % line)
def msgrandom(cli, choices, dest, user=None):
o = "%s: " % user if user else ""
o += random.choice(choices)
msg(cli, dest, o)
def _makeMsgRandomFunc(choices):
def func(cli, dest, user=None):
msgrandom(cli, choices, dest, user)
return func
msgYes = _makeMsgRandomFunc(['yes', 'alright', 'ok'])
msgOK = _makeMsgRandomFunc(['ok', 'done'])
msgNo = _makeMsgRandomFunc(['no', 'no-way'])
def ns(cli, *args):
msg(cli, "NickServ", " ".join(args))
def cs(cli, *args):
msg(cli, "ChanServ", " ".join(args))
def identify(cli, passwd, authuser="NickServ"):
msg(cli, authuser, "IDENTIFY %s" % passwd)
def quit(cli, msg='gone'):
cli.send("QUIT :%s" % msg)
cli._end = 1
def mode(cli, chan, mod):
cli.send("MODE", chan, mod)
def user(cli, username, realname=None):
cli.send("USER", username, cli.host, cli.host,
realname or username)
_simple = (
'join',
'part',
'nick',
'notice',
)
def _addsimple():
import sys
def simplecmd(cmd_name):
def f(cli, *args):
cli.send(cmd_name, *args)
return f
m = sys.modules[__name__]
for t in _simple:
setattr(m, t, simplecmd(t.upper()))
_addsimple()
def _addNumerics():
import sys
from oyoyo import ircevents
def numericcmd(cmd_num, cmd_name):
def f(cli, *args):
cli.send(cmd_num, *args)
return f
m = sys.modules[__name__]
for num, name in ircevents.numeric_events.items():
setattr(m, name, numericcmd(num, name))
_addNumerics()

11
vars.py

@ -1,4 +1,13 @@ @@ -1,4 +1,13 @@
GAME_STARTED = False
ROLES = {"person" : []}
ORIGINAL_ROLES = None
PHASE = "none" # "join", "day", or "night"
PHASE = "none" # "join", "day", or "night"
GUNNERS = {}
MAX_SHOTS = 2
is_role = lambda plyr, rol: rol in ROLES and plyr in ROLES[rol]
def plural(role):
if role == "wolf": return "wolves"
elif role == "person": return "people"
else: return role + "s"

73
wolfbot.py

@ -1,6 +1,5 @@ @@ -1,6 +1,5 @@
from oyoyo.client import IRCClient
from oyoyo.cmdhandler import DefaultCommandHandler
from oyoyo import helpers
from oyoyo.cmdhandler import DefaultCommandHandler, protected
from oyoyo.parse import parse_nick
import logging
import botconfig
@ -53,12 +52,19 @@ class WolfBotHandler(DefaultCommandHandler): @@ -53,12 +52,19 @@ class WolfBotHandler(DefaultCommandHandler):
msg = msg.replace(x, "", 1)
PM_COMMANDS[x](self.client, rawnick, msg.lstrip())
def nick(self, fro, to):
print(fro, to)
@protected
def __unhandled__(self, cmd, *args):
if cmd in HOOKS.keys():
largs = list(args)
for i,arg in enumerate(largs):
if arg: largs[i] = arg.decode('ascii')
HOOKS[cmd](*largs)
else:
logging.debug('unhandled command %s(%s)' % (cmd, args))
def main():
logging.basicConfig(level=logging.DEBUG)
cli = IRCClient(WolfBotHandler, host="irc.freenode.net", port=6667, nick="wolfbot2-alpha",
cli = IRCClient(WolfBotHandler, host="irc.freenode.net", port=6667, nickname=botconfig.NICK,
connect_cb=connect_callback)
conn = cli.connect()
@ -80,13 +86,47 @@ def reset_game(): @@ -80,13 +86,47 @@ def reset_game():
def say(cli, rawnick, rest): # To be removed later
cli.msg(botconfig.CHANNEL, "{0} says: {1}".format(parse_nick(rawnick)[0], rest))
@cmd("!bye", pm=True)
@cmd("!bye", pm=False)
def forced_exit(cli, rawnick, *rest): # Admin Only
if parse_nick(rawnick)[0] in botconfig.ADMINS:
cli.quit("Forced quit from admin")
raise SystemExit
@cmd("!exec", pm=False)
def py(cli, rawnick, chan, rest):
if parse_nick(rawnick)[0] in botconfig.ADMINS:
exec(rest)
@cmd("!ping", pm=False)
def pinger(cli, rawnick, chan, rest):
vars.PINGING = True
TO_PING = []
@hook("whoreply")
def on_whoreply(server, dunno, chan, dunno1, dunno2, dunno3, user, status, dunno4):
if not vars.PINGING: return
if user in (botconfig.NICK, parse_nick(rawnick)[0]): return # Don't ping self.
if vars.PINGING and 'G' not in status and '+' not in status:
# TODO: check if the user has AWAY'D himself
TO_PING.append(user)
@hook("endofwho")
def do_ping(*args):
if not vars.PINGING: return
chan = args[2]
cli.msg(chan, "PING! "+" ".join(TO_PING))
vars.PINGING = False
HOOKS.pop("whoreply")
HOOKS.pop("endofwho")
cli.send("WHO "+chan)
@cmd("!join", pm=False)
def join(cli, rawnick, chan, rest):
if vars.PHASE != "none":
@ -111,9 +151,28 @@ def stats(cli, rawnick, chan, rest): @@ -111,9 +151,28 @@ def stats(cli, rawnick, chan, rest):
nick = parse_nick(rawnick)[0]
pl = []
for x in vars.ROLES.values(): pl.extend(x)
cli.msg(chan, '{0}: {1} players: {2}'.format(nick,
len(pl), ", ".join(pl)))
if len(pl) > 1:
cli.msg(chan, '{0}: {1} players: {2}'.format(nick,
len(pl), ", ".join(pl)))
else:
cli.msg(chan, '{0}: 1 player: {1}'.format(nick, pl[0]))
msg = []
for role in vars.ROLES.keys():
num = len(vars.ROLES[role])
if num > 1:
msg.append("{0} {1}".format(num, plural(role)))
else:
msg.append("{0} {1}".format(num, role))
if len(msg) > 2: # More than 2 roles to say
msg[-1] = "and "+msg[-1]+"."
msg[0] = "{0}: There are ".format(nick) + msg[0]
cli.msg(chan, ", ".join(msg))
elif len(msg) == 2: # 2 roles to say
cli.msg(chan, "{0}: There are ".format(nick) + msg[0],
"and", msg[1] + ".")
elif len(msg) == 1:
cli.msg(chan, "{0}: There is ".format(nick) + msg[0] + ".")
# Game Logic Ends

Loading…
Cancel
Save