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

Many fixes

- Move _nicktoUid to utils.py
- Make _sendFromUser arguments more consistent (irc, sendfrom, message) instead of (irc, message, sendfrom=None)
- Add admin only kickclient, partclient, and nickclient commands
- proto.joinClient: take UIDs instead of an IrcUser object, in order to be more consistent

Closes #4, Closes #12.
This commit is contained in:
James Lu 2015-06-07 19:31:56 -07:00
parent 8bbf4ba387
commit 43a46d3d99
3 changed files with 107 additions and 42 deletions

View File

@ -31,19 +31,19 @@ def spawnclient(irc, source, args):
proto.spawnClient(irc, nick, ident, host) proto.spawnClient(irc, nick, ident, host)
@utils.add_cmd @utils.add_cmd
def removeclient(irc, source, args): def quitclient(irc, source, args):
checkauthenticated(irc, source) checkauthenticated(irc, source)
try: try:
nick = args[0].lower() nick = args[0]
except IndexError: except IndexError:
utils.msg(irc, source, "Error: not enough arguments. Needs 1: nick.") utils.msg(irc, source, "Error: not enough arguments. Needs 1: nick.")
return return
u = _nicktoUid(nick) if irc.pseudoclient.uid == utils._nicktoUid(irc, nick):
if u is None or u not in irc.server[irc.sid].users: utils.msg(irc, source, "Error: cannot quit the main PyLink PseudoClient!")
utils.msg(irc, source, "Error: user %r not found." % nick)
return return
_sendFromUser(irc, u, "QUIT :Client Quit") u = utils._nicktoUid(irc, nick)
proto.removeClient(irc, nick, ident, host) quitmsg = ' '.join(args[1:]) or 'Client quit'
proto.quitClient(irc, u, quitmsg)
@utils.add_cmd @utils.add_cmd
def joinclient(irc, source, args): def joinclient(irc, source, args):
@ -56,12 +56,56 @@ def joinclient(irc, source, args):
except IndexError: except IndexError:
utils.msg(irc, source, "Error: not enough arguments. Needs 2: nick, comma separated list of channels.") utils.msg(irc, source, "Error: not enough arguments. Needs 2: nick, comma separated list of channels.")
return return
u = _nicktoUid(nick) u = utils._nicktoUid(irc, nick)
if u is None or u not in irc.server[irc.sid].users:
utils.msg(irc, source, "Error: user %r not found." % nick)
return
for channel in clist: for channel in clist:
if not channel.startswith('#'): if not channel.startswith('#'):
utils.msg(irc, source, "Error: channel names must start with #.") utils.msg(irc, source, "Error: channel names must start with #.")
return return
joinClient(irc, ','.join(clist)) proto.joinClient(irc, u, channel)
@utils.add_cmd
def nickclient(irc, source, args):
checkauthenticated(irc, source)
try:
nick = args[0]
newnick = args[1]
except IndexError:
utils.msg(irc, source, "Error: not enough arguments. Needs 2: nick, newnick.")
return
u = utils._nicktoUid(irc, nick)
proto.nickClient(irc, u, newnick)
@utils.add_cmd
def partclient(irc, source, args):
checkauthenticated(irc, source)
try:
nick = args[0]
clist = args[1].split(',')
reason = ' '.join(args[2:])
except IndexError:
utils.msg(irc, source, "Error: not enough arguments. Needs 2: nick, comma separated list of channels.")
return
u = utils._nicktoUid(irc, nick)
for channel in clist:
if not channel.startswith('#'):
utils.msg(irc, source, "Error: channel names must start with #.")
return
proto.partClient(irc, u, channel, reason)
@utils.add_cmd
def kickclient(irc, source, args):
checkauthenticated(irc, source)
try:
nick = args[0]
channel = args[1]
target = args[2]
reason = ' '.join(args[3:])
except IndexError:
utils.msg(irc, source, "Error: not enough arguments. Needs 3-4: nick, channel, target, reason (optional).")
return
u = utils._nicktoUid(irc, nick)
targetu = utils._nicktoUid(irc, target)
if not channel.startswith('#'):
utils.msg(irc, source, "Error: channel names must start with #.")
return
proto.kickClient(irc, u, channel, targetu, reason)

View File

@ -9,15 +9,8 @@ from classes import *
def _sendFromServer(irc, msg): def _sendFromServer(irc, msg):
irc.send(':%s %s' % (irc.sid, msg)) irc.send(':%s %s' % (irc.sid, msg))
def _sendFromUser(irc, msg, user=None): def _sendFromUser(irc, numeric, msg):
if user is None: irc.send(':%s %s' % (numeric, msg))
user = irc.pseudoclient.uid
irc.send(':%s %s' % (user, msg))
def _nicktoUid(irc, nick):
for k, v in irc.users.items():
if v.nick == nick:
return k
def spawnClient(irc, nick, ident, host, *args): def spawnClient(irc, nick, ident, host, *args):
uid = next_uid(irc.sid) uid = next_uid(irc.sid)
@ -30,12 +23,19 @@ def spawnClient(irc, nick, ident, host, *args):
return u return u
def joinClient(irc, client, channel): def joinClient(irc, client, channel):
# Channel list can be a comma-separated list of channels, per the # One channel per line here!
# IRC specification.
if not isInternalClient(irc, client): if not isInternalClient(irc, client):
raise LookupError('No user/PyLink PseudoClient %r exists.' % client) raise LookupError('No such PyLink PseudoClient exists.')
_sendFromUser(irc, "JOIN {channel} {ts} +nt :,{uid}".format(sid=irc.sid, _sendFromServer(irc, "FJOIN {channel} {ts} + :,{uid}".format(
ts=int(time.time()), uid=client.uid, channel=channel)) ts=int(time.time()), uid=client, channel=channel))
def partClient(irc, client, channel, reason=None):
if not isInternalClient(irc, client):
raise LookupError('No such PyLink PseudoClient exists.')
msg = "PART %s" % channel
if reason:
msg += " :%s" % reason
_sendFromUser(irc, client, msg)
def removeClient(irc, numeric): def removeClient(irc, numeric):
"""<irc object> <client numeric> """<irc object> <client numeric>
@ -60,34 +60,36 @@ def isInternalClient(irc, numeric):
""" """
return numeric in irc.servers[irc.sid].users return numeric in irc.servers[irc.sid].users
def quitClient(irc, numeric): def quitClient(irc, numeric, reason):
"""<irc object> <client numeric> """<irc object> <client numeric>
Quits a PyLink PseudoClient.""" Quits a PyLink PseudoClient."""
if isInternalClient(irc, numeric): if isInternalClient(irc, numeric):
_sendFromUser(irc, numeric, "QUIT :Client quit") _sendFromUser(irc, numeric, "QUIT :%s" % reason)
removeClient(irc, numeric)
else: else:
raise LookupError("No user %r exists. If you're trying to remove " raise LookupError("No such PyLink PseudoClient exists. If you're trying to remove "
"a user that's not a PyLink PseudoClient from " "a user that's not a PyLink PseudoClient from "
"the internal state, use removeClient() instead.") "the internal state, use removeClient() instead.")
def kickClient(irc, channel, numeric, target, reason=None): def kickClient(irc, numeric, channel, target, reason=None):
"""<irc object> <kicker client numeric> """<irc object> <kicker client numeric>
Sends a kick from a PyLink PseudoClient.""" Sends a kick from a PyLink PseudoClient."""
if not isInternalClient(irc, numeric): if not isInternalClient(irc, numeric):
raise LookupError('No user/PyLink PseudoClient %r exists.' % numeric) raise LookupError('No such PyLink PseudoClient exists.')
if reason is None: if not reason:
reason = irc.users[target].nick reason = 'No reason given'
_sendFromUser(irc, numeric, 'KICK %s %s :%s' % (channel, target, reason)) _sendFromUser(irc, numeric, 'KICK %s %s :%s' % (channel, target, reason))
def nickClient(irc, numeric, newnick, reason=None): def nickClient(irc, numeric, newnick):
"""<irc object> <client numeric> <new nickname> """<irc object> <client numeric> <new nickname>
Changes the nick of a PyLink PseudoClient.""" Changes the nick of a PyLink PseudoClient."""
if not isInternalClient(irc, numeric): if not isInternalClient(irc, numeric):
raise LookupError('No user/PyLink PseudoClient %r exists.' % numeric) raise LookupError('No such PyLink PseudoClient exists.')
_sendFromUser(irc, numeric, 'NICK %s' % newnick) _sendFromUser(irc, numeric, 'NICK %s %s' % (newnick, int(time.time())))
irc.users[numeric].nick = newnick
def connect(irc): def connect(irc):
irc.start_ts = ts = int(time.time()) irc.start_ts = ts = int(time.time())
@ -110,7 +112,8 @@ def connect(irc):
# +ACKNOQcdfgklnoqtx :Craig Edwards # +ACKNOQcdfgklnoqtx :Craig Edwards
irc.pseudoclient = spawnClient(irc, 'PyLink', 'pylink', host) irc.pseudoclient = spawnClient(irc, 'PyLink', 'pylink', host)
f(':%s ENDBURST' % (irc.sid)) f(':%s ENDBURST' % (irc.sid))
joinClient(irc, irc.pseudoclient, ','.join(irc.serverdata['channels'])) for chan in irc.serverdata['channels']:
joinClient(irc, irc.pseudoclient.uid, chan)
# :7NU PING 7NU 0AL # :7NU PING 7NU 0AL
def handle_ping(irc, servernumeric, command, args): def handle_ping(irc, servernumeric, command, args):
@ -143,7 +146,8 @@ def handle_kill(irc, source, command, args):
removeClient(irc, killed) removeClient(irc, killed)
if killed == irc.pseudoclient.uid: if killed == irc.pseudoclient.uid:
irc.pseudoclient = spawnClient(irc, 'PyLink', 'pylink', irc.serverdata["hostname"]) irc.pseudoclient = spawnClient(irc, 'PyLink', 'pylink', irc.serverdata["hostname"])
joinClient(irc, irc.pseudoclient, ','.join(irc.serverdata['channels'])) for chan in irc.serverdata['channels']:
joinClient(irc, irc.pseudoclient.uid, chan)
def handle_kick(irc, source, command, args): def handle_kick(irc, source, command, args):
# :70MAAAAAA KICK #endlessvoid 70MAAAAAA :some reason # :70MAAAAAA KICK #endlessvoid 70MAAAAAA :some reason
@ -151,7 +155,7 @@ def handle_kick(irc, source, command, args):
kicked = args[1] kicked = args[1]
irc.channels[channel].users.discard(kicked) irc.channels[channel].users.discard(kicked)
if kicked == irc.pseudoclient.uid: if kicked == irc.pseudoclient.uid:
joinClient(irc, irc.pseudoclient, channel) joinClient(irc, irc.pseudoclient.uid, channel)
def handle_part(irc, source, command, args): def handle_part(irc, source, command, args):
channel = args[0] channel = args[0]
@ -211,11 +215,24 @@ def handle_nick(irc, numeric, command, args):
newnick = args[0] newnick = args[0]
irc.users[numeric].nick = newnick irc.users[numeric].nick = newnick
def handle_save(irc, numeric, command, args):
# This is used to handle nick collisions. Here, the client Derp_ already exists,
# so trying to change nick to it will cause a nick collision. On InspIRCd,
# this will simply set the collided user's nick to its UID.
# <- :70MAAAAAA PRIVMSG 0AL000001 :nickclient PyLink Derp_
# -> :0AL000001 NICK Derp_ 1433728673
# <- :70M SAVE 0AL000001 1433728673
user = args[0]
irc.users[user].nick = user
'''
def handle_fmode(irc, numeric, command, args): def handle_fmode(irc, numeric, command, args):
# <- :70MAAAAAA FMODE #chat 1433653462 +hhT 70MAAAAAA 70MAAAAAD # <- :70MAAAAAA FMODE #chat 1433653462 +hhT 70MAAAAAA 70MAAAAAD
# Oh god, how are we going to handle this?! # Oh god, how are we going to handle this?!
channel = args[0] channel = args[0]
modestrings = args[3:] modestrings = args[3:]
'''
def handle_squit(irc, numeric, command, args): def handle_squit(irc, numeric, command, args):
# :70M SQUIT 1ML :Server quit by GL!gl@0::1 # :70M SQUIT 1ML :Server quit by GL!gl@0::1
@ -238,8 +255,7 @@ def handle_idle(irc, numeric, command, args):
# -> :1MLAAAAIG IDLE 70MAAAAAA 1433036797 319 # -> :1MLAAAAIG IDLE 70MAAAAAA 1433036797 319
sourceuser = numeric sourceuser = numeric
targetuser = args[0] targetuser = args[0]
_sendFromUser(irc, 'IDLE %s %s 0' % (sourceuser, irc.start_ts), _sendFromUser(irc, targetuser, 'IDLE %s %s 0' % (sourceuser, irc.start_ts))
user=targetuser)
def handle_events(irc, data): def handle_events(irc, data):
# Each server message looks something like this: # Each server message looks something like this:

View File

@ -19,10 +19,15 @@ def next_uid(sid, level=-1):
def msg(irc, target, text, notice=False): def msg(irc, target, text, notice=False):
command = 'NOTICE' if notice else 'PRIVMSG' command = 'NOTICE' if notice else 'PRIVMSG'
proto._sendFromUser(irc, '%s %s :%s' % (command, target, text)) proto._sendFromUser(irc, irc.pseudoclient.uid, '%s %s :%s' % (command, target, text))
def add_cmd(func, name=None): def add_cmd(func, name=None):
if name is None: if name is None:
name = func.__name__ name = func.__name__
name = name.lower() name = name.lower()
bot_commands[name] = func bot_commands[name] = func
def _nicktoUid(irc, nick):
for k, v in irc.users.items():
if v.nick == nick:
return k