simplified the irc client
This commit is contained in:
parent
3829a76d8c
commit
576e82aa6b
@ -19,7 +19,6 @@ import logging
|
|||||||
import socket
|
import socket
|
||||||
|
|
||||||
from oyoyo.parse import parse_raw_irc_command
|
from oyoyo.parse import parse_raw_irc_command
|
||||||
from oyoyo.cmdhandler import CommandError
|
|
||||||
|
|
||||||
class IRCClientError(Exception):
|
class IRCClientError(Exception):
|
||||||
pass
|
pass
|
||||||
@ -71,7 +70,7 @@ class IRCClient(object):
|
|||||||
self.blocking = True
|
self.blocking = True
|
||||||
|
|
||||||
self.__dict__.update(kwargs)
|
self.__dict__.update(kwargs)
|
||||||
self.command_handler = cmd_handler(self)
|
self.command_handler = cmd_handler
|
||||||
|
|
||||||
self._end = 0
|
self._end = 0
|
||||||
|
|
||||||
@ -146,9 +145,20 @@ class IRCClient(object):
|
|||||||
|
|
||||||
for el in data:
|
for el in data:
|
||||||
prefix, command, args = parse_raw_irc_command(el)
|
prefix, command, args = parse_raw_irc_command(el)
|
||||||
|
logging.debug("processCommand {0}({1})".format(command,
|
||||||
|
[arg.decode('utf_8')
|
||||||
|
for arg in args
|
||||||
|
if isinstance(arg, bytes)]))
|
||||||
try:
|
try:
|
||||||
self.command_handler.run(command, prefix, *args)
|
largs = list(args)
|
||||||
|
if prefix:
|
||||||
|
largs.insert(0, prefix)
|
||||||
|
for i,arg in enumerate(largs):
|
||||||
|
if arg: largs[i] = arg.decode('utf_8')
|
||||||
|
if command in self.command_handler:
|
||||||
|
self.command_handler[command](self, *largs)
|
||||||
|
elif "" in self.command_handler:
|
||||||
|
self.command_handler[""](self, command, *largs)
|
||||||
except CommandError:
|
except CommandError:
|
||||||
# error will of already been logged by the handler
|
# error will of already been logged by the handler
|
||||||
pass
|
pass
|
||||||
|
@ -1,124 +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.
|
|
||||||
|
|
||||||
import logging
|
|
||||||
import sys
|
|
||||||
import traceback
|
|
||||||
|
|
||||||
from oyoyo.parse import parse_nick
|
|
||||||
|
|
||||||
def protected(func):
|
|
||||||
""" decorator to protect functions from being called """
|
|
||||||
func.protected = True
|
|
||||||
return func
|
|
||||||
|
|
||||||
|
|
||||||
class CommandError(Exception):
|
|
||||||
def __init__(self, cmd):
|
|
||||||
self.cmd = cmd
|
|
||||||
|
|
||||||
class NoSuchCommandError(CommandError):
|
|
||||||
def __str__(self):
|
|
||||||
return 'No such command "{0}"'.format(".".join(self.cmd))
|
|
||||||
|
|
||||||
class ProtectedCommandError(CommandError):
|
|
||||||
def __str__(self):
|
|
||||||
return 'Command "{0}" is protected'.format(".".join(self.cmd))
|
|
||||||
|
|
||||||
|
|
||||||
class CommandHandler(object):
|
|
||||||
""" The most basic CommandHandler """
|
|
||||||
|
|
||||||
def __init__(self, client):
|
|
||||||
self.client = client
|
|
||||||
|
|
||||||
@protected
|
|
||||||
def get(self, in_command_parts):
|
|
||||||
""" finds a command
|
|
||||||
commands may be dotted. each command part is checked that it does
|
|
||||||
not start with and underscore and does not have an attribute
|
|
||||||
"protected". if either of these is true, ProtectedCommandError
|
|
||||||
is raised.
|
|
||||||
its possible to pass both "command.sub.func" and
|
|
||||||
["command", "sub", "func"].
|
|
||||||
"""
|
|
||||||
|
|
||||||
if isinstance(in_command_parts, bytes):
|
|
||||||
in_command_parts = in_command_parts.split(b'.')
|
|
||||||
else:
|
|
||||||
in_command_parts = in_command_parts.split('.')
|
|
||||||
|
|
||||||
command_parts = []
|
|
||||||
for cmdpart in in_command_parts:
|
|
||||||
if isinstance(cmdpart, bytes):
|
|
||||||
cmdpart = cmdpart.decode('utf_8')
|
|
||||||
command_parts.append(cmdpart)
|
|
||||||
|
|
||||||
p = self
|
|
||||||
while command_parts:
|
|
||||||
cmd = command_parts.pop(0)
|
|
||||||
if cmd.startswith('_'):
|
|
||||||
raise ProtectedCommandError(in_command_parts)
|
|
||||||
|
|
||||||
try:
|
|
||||||
f = getattr(p, cmd)
|
|
||||||
except AttributeError:
|
|
||||||
raise NoSuchCommandError(in_command_parts)
|
|
||||||
|
|
||||||
if hasattr(f, 'protected'):
|
|
||||||
raise ProtectedCommandError(in_command_parts)
|
|
||||||
|
|
||||||
if isinstance(f, CommandHandler) and command_parts:
|
|
||||||
return f.get(command_parts)
|
|
||||||
p = f
|
|
||||||
|
|
||||||
return f
|
|
||||||
|
|
||||||
@protected
|
|
||||||
def run(self, command, *args):
|
|
||||||
""" finds and runs a command """
|
|
||||||
logging.debug("processCommand {0}({1})".format(command,
|
|
||||||
[arg.decode('utf_8')
|
|
||||||
for arg in args
|
|
||||||
if isinstance(arg, bytes)]))
|
|
||||||
|
|
||||||
try:
|
|
||||||
f = self.get(command)
|
|
||||||
except NoSuchCommandError:
|
|
||||||
self.__unhandled__(command, *args)
|
|
||||||
return
|
|
||||||
|
|
||||||
logging.debug('f {0}'.format(f))
|
|
||||||
try:
|
|
||||||
largs = list(args)
|
|
||||||
for i,arg in enumerate(largs):
|
|
||||||
if arg: largs[i] = arg.decode('utf_8')
|
|
||||||
f(*largs)
|
|
||||||
self.__unhandled__(command, *args)
|
|
||||||
except Exception as e:
|
|
||||||
logging.error('command raised {0}'.format(e))
|
|
||||||
logging.error(traceback.format_exc())
|
|
||||||
raise CommandError(command)
|
|
||||||
|
|
||||||
@protected
|
|
||||||
def __unhandled__(self, cmd, *args):
|
|
||||||
"""The default handler for commands. Override this method to
|
|
||||||
apply custom behavior (example, printing) unhandled commands.
|
|
||||||
"""
|
|
||||||
logging.debug('Unhandled command {0}({1})'.format(cmd, [arg.decode('utf_8')
|
|
||||||
for arg in args
|
|
||||||
if isinstance(arg, bytes)]))
|
|
63
wolfbot.py
63
wolfbot.py
@ -1,45 +1,44 @@
|
|||||||
from oyoyo.client import IRCClient
|
from oyoyo.client import IRCClient
|
||||||
from oyoyo.cmdhandler import CommandHandler, protected
|
|
||||||
from oyoyo.parse import parse_nick
|
from oyoyo.parse import parse_nick
|
||||||
import logging
|
import logging
|
||||||
import botconfig
|
import botconfig
|
||||||
import wolfgame
|
import wolfgame
|
||||||
|
|
||||||
class WolfBotHandler(CommandHandler):
|
def on_privmsg(cli, rawnick, chan, msg):
|
||||||
def __init__(self, client):
|
if chan != botconfig.NICK: #not a PM
|
||||||
super().__init__(client)
|
for x in wolfgame.COMMANDS.keys():
|
||||||
|
if msg.lower().startswith(x):
|
||||||
def privmsg(self, rawnick, chan, msg):
|
h = msg[len(x):]
|
||||||
if chan != botconfig.NICK: #not a PM
|
if not h or h[0] == " " or not x:
|
||||||
for x in wolfgame.COMMANDS.keys():
|
wolfgame.COMMANDS[x](cli, rawnick, chan, h.lstrip())
|
||||||
if msg.lower().startswith(x):
|
else:
|
||||||
h = msg[len(x):]
|
for x in wolfgame.PM_COMMANDS.keys():
|
||||||
if not h or h[0] == " " or not x:
|
if msg.lower().startswith(x):
|
||||||
wolfgame.COMMANDS[x](self.client, rawnick, chan, h.lstrip())
|
h = msg[len(x):]
|
||||||
else:
|
if not h or h[0] == " " or not x:
|
||||||
for x in wolfgame.PM_COMMANDS.keys():
|
wolfgame.PM_COMMANDS[x](cli, rawnick, h.lstrip())
|
||||||
if msg.lower().startswith(x):
|
|
||||||
h = msg[len(x):]
|
|
||||||
if not h or h[0] == " " or not x:
|
|
||||||
wolfgame.PM_COMMANDS[x](self.client, rawnick, h.lstrip())
|
|
||||||
|
|
||||||
@protected
|
def __unhandled__(cli, cmd, *args):
|
||||||
def __unhandled__(self, cmd, *args):
|
if cmd in wolfgame.HOOKS.keys():
|
||||||
if cmd in wolfgame.HOOKS.keys():
|
largs = list(args)
|
||||||
largs = list(args)
|
for i,arg in enumerate(largs):
|
||||||
for i,arg in enumerate(largs):
|
if isinstance(arg, bytes): largs[i] = arg.decode('ascii')
|
||||||
if isinstance(arg, bytes): largs[i] = arg.decode('ascii')
|
wolfgame.HOOKS[cmd](cli, *largs)
|
||||||
wolfgame.HOOKS[cmd](self.client, *largs)
|
else:
|
||||||
else:
|
logging.debug('Unhandled command {0}({1})'.format(cmd, [arg.decode('utf_8')
|
||||||
logging.debug('Unhandled command {0}({1})'.format(cmd, [arg.decode('utf_8')
|
for arg in args
|
||||||
for arg in args
|
if isinstance(arg, bytes)]))
|
||||||
if isinstance(arg, bytes)]))
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
logging.basicConfig(level=logging.DEBUG)
|
logging.basicConfig(level=logging.DEBUG)
|
||||||
cli = IRCClient(WolfBotHandler, host=botconfig.HOST, port=botconfig.PORT, nickname=botconfig.NICK,
|
cli = IRCClient(
|
||||||
connect_cb=wolfgame.connect_callback)
|
{"privmsg":on_privmsg,
|
||||||
|
"":__unhandled__},
|
||||||
|
host=botconfig.HOST,
|
||||||
|
port=botconfig.PORT,
|
||||||
|
nickname=botconfig.NICK,
|
||||||
|
connect_cb=wolfgame.connect_callback
|
||||||
|
)
|
||||||
cli.mainLoop()
|
cli.mainLoop()
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user