3
0
mirror of https://github.com/jlu5/PyLink.git synced 2024-11-23 19:19:31 +01:00

It's almost June! Updates:

- Move config handling into separate module
- Implement identify and status commands, currently only supporting the admin account defined in the config. Closes #1.
- Move proto.add_cmd to utils.py, rename _msg() to msg()
- Allow sending the command name as an optional argument in add_cmd
- Add catch-all exception handling in plugins to prevent them from crashing the program!
This commit is contained in:
James Lu 2015-05-31 12:20:09 -07:00
parent 0e53a0fee4
commit d9db7e1b9e
6 changed files with 79 additions and 31 deletions

5
conf.py Normal file
View File

@ -0,0 +1,5 @@
import yaml
with open("config.yml", 'r') as f:
global conf
conf = yaml.load(f)

16
main.py
View File

@ -1,20 +1,17 @@
#!/usr/bin/python3
import yaml
import imp
import os
import socket
import time
import sys
from conf import conf
import proto
print('PyLink starting...')
with open("config.yml", 'r') as f:
conf = yaml.load(f)
# if conf['login']['password'] == 'changeme':
# print("You have not set the login details correctly! Exiting...")
if conf['login']['password'] == 'changeme':
print("You have not set the login details correctly! Exiting...")
sys.exit(2)
class Irc():
def __init__(self):
@ -74,5 +71,6 @@ class Irc():
self.loaded.append(imp.load_source(plugin, moduleinfo[1]))
print("loaded plugins: %s" % self.loaded)
irc_obj = Irc()
if __name__ == '__main__':
print('PyLink starting...')
irc_obj = Irc()

View File

@ -3,22 +3,54 @@ import sys, os
sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
import proto
import utils
from conf import conf
@proto.add_cmd
@utils.add_cmd
def tell(irc, source, args):
try:
target, text = args[0], ' '.join(args[1:])
except IndexError:
utils._msg(irc, source, 'Error: not enough arguments.', notice=False)
utils.msg(irc, source, 'Error: not enough arguments.')
return
targetuid = proto._nicktoUid(irc, target)
if targetuid is None:
utils._msg(irc, source, 'Error: unknown user %r' % target, notice=False)
utils.msg(irc, source, 'Error: unknown user %r' % target)
return
utils._msg(irc, target, text)
if not text:
utils.msg(irc, source, "Error: can't send an empty message!")
return
utils.msg(irc, target, text, notice=True)
@proto.add_cmd
@utils.add_cmd
def debug(irc, source, args):
utils._msg(irc, source, 'Debug info printed to console.')
utils.msg(irc, source, 'Debug info printed to console.')
print(irc.users)
print(irc.servers)
@utils.add_cmd
def status(irc, source, args):
identified = irc.users[source].identified
if identified:
utils.msg(irc, source, 'You are identified as %s.' % identified)
else:
utils.msg(irc, source, 'You are not identified as anyone.')
@utils.add_cmd
def identify(irc, source, args):
try:
username, password = args[0], args[1]
except IndexError:
utils.msg(irc, source, 'Error: not enough arguments.')
return
if username.lower() == conf['login']['user'].lower() and password == conf['login']['password']:
realuser = conf['login']['user']
irc.users[source].identified = realuser
utils.msg(irc, source, 'Successfully logged in as %s.' % realuser)
else:
utils.msg(irc, source, 'Incorrect credentials.')
def listcommands(irc, source, args):
cmds = list(utils.bot_commands.keys())
cmds.sort()
utils.msg(irc, source, 'Available commands include: %s' % ', '.join(cmds))
utils.add_cmd(listcommands, 'list')

View File

@ -1,7 +1,7 @@
import sys, os
sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
import proto
import utils
@proto.add_cmd
@utils.add_cmd
def hello(irc, source, args):
proto._sendFromUser(irc, 'PRIVMSG %s :hello!' % source)
utils.msg(irc, source, 'hello!')

View File

@ -3,10 +3,7 @@ import time
import sys
from utils import *
from copy import copy
global bot_commands
# This should be a mapping of command names to functions
bot_commands = {}
import traceback
class IrcUser():
def __init__(self, nick, ts, uid, ident='null', host='null',
@ -21,6 +18,8 @@ class IrcUser():
self.ip = ip
self.realname = realname
self.identified = False
def __repr__(self):
return repr(self.__dict__)
@ -48,12 +47,12 @@ def _nicktoUid(irc, nick):
if v.nick == nick:
return k
def introduceUser(irc, nick, user, host):
def spawnClient(irc, nick, user, host, *args):
uid = next_uid(irc.sid)
_sendFromServer(irc, "UID {uid} {ts} {nick} {host} {host} {user} 0.0.0.0 {ts} +o +"
" :PyLink Client".format(ts=int(time.time()), host=host,
nick=nick, user=user, uid=uid))
irc.users[uid] = IrcUser(nick, ts, uid, ident, host, realname, realhost, ip)
irc.users[uid] = IrcUser(nick, ts, uid, ident, host, *args)
irc.servers[irc.sid].users.append(uid)
def connect(irc):
@ -96,15 +95,22 @@ def handle_privmsg(irc, source, command, args):
prefix = irc.conf['bot']['prefix']
if args[0] == irc.pseudoclient.uid:
cmd_args = args[1].split(' ')
cmd = cmd_args[0]
cmd = cmd_args[0].lower()
try:
cmd_args = cmd_args[1:]
except IndexError:
cmd_args = []
try:
bot_commands[cmd](irc, source, cmd_args)
func = bot_commands[cmd]
except KeyError:
_sendFromUser(irc, 'PRIVMSG %s :unknown command %r' % (source, cmd))
msg(irc, source, 'Unknown command %r.' % cmd)
return
try:
func(irc, source, cmd_args)
except Exception as e:
traceback.print_exc()
msg(irc, source, 'Uncaught exception in command %r: %s: %s' % (cmd, type(e).__name__, str(e)))
return
def handle_error(irc, numeric, command, args):
print('Received an ERROR, killing!')
@ -214,6 +220,3 @@ def handle_events(irc, data):
func(irc, numeric, command, args)
except KeyError: # unhandled event
pass
def add_cmd(func):
bot_commands[func.__name__.lower()] = func

View File

@ -1,6 +1,10 @@
import string
import proto
global bot_commands
# This should be a mapping of command names to functions
bot_commands = {}
# From http://www.inspircd.org/wiki/Modules/spanningtree/UUIDs.html
chars = string.digits + string.ascii_uppercase
iters = [iter(chars) for _ in range(6)]
@ -13,6 +17,12 @@ def next_uid(sid, level=-1):
except StopIteration:
return UID(level-1)
def _msg(irc, target, text, notice=True):
def msg(irc, target, text, notice=False):
command = 'NOTICE' if notice else 'PRIVMSG'
proto._sendFromUser(irc, '%s %s :%s' % (command, target, text))
def add_cmd(func, name=None):
if name is None:
name = func.__name__
name = name.lower()
bot_commands[name] = func