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

defaultdict for channels, fix user tracking in {join|part}Client, isInternal* to utils

- collections.defaultdict for simpler channel handling
- proto/inspircd: fix join/partClient not updating the channel's user list
- move isInternal* to utils
This commit is contained in:
James Lu 2015-06-23 19:29:53 -07:00
parent 6370ad492f
commit 072cc72602
3 changed files with 33 additions and 29 deletions

View File

@ -5,8 +5,10 @@ import os
import socket import socket
import time import time
import sys import sys
from collections import defaultdict
from conf import conf from conf import conf
import classes
class Irc(): class Irc():
def __init__(self, proto): def __init__(self, proto):
@ -14,7 +16,7 @@ class Irc():
self.socket = socket.socket() self.socket = socket.socket()
self.connected = False self.connected = False
self.users = {} self.users = {}
self.channels = {} self.channels = defaultdict(classes.IrcChannel)
self.name = conf['server']['netname'] self.name = conf['server']['netname']
self.conf = conf self.conf = conf
self.servers = {} self.servers = {}

View File

@ -23,7 +23,7 @@ def _sendFromUser(irc, numeric, msg):
def spawnClient(irc, nick, ident, host, modes=[], server=None, *args): def spawnClient(irc, nick, ident, host, modes=[], server=None, *args):
server = server or irc.sid server = server or irc.sid
if not isInternalServer(irc, server): if not utils.isInternalServer(irc, server):
raise ValueError('Server %r is not a PyLink internal PseudoServer!' % server) raise ValueError('Server %r is not a PyLink internal PseudoServer!' % server)
# We need a separate UID generator instance for every PseudoServer # We need a separate UID generator instance for every PseudoServer
# we spawn. Otherwise, things won't wrap around properly. # we spawn. Otherwise, things won't wrap around properly.
@ -46,7 +46,7 @@ def spawnClient(irc, nick, ident, host, modes=[], server=None, *args):
return u return u
def joinClient(irc, client, channel): def joinClient(irc, client, channel):
server = isInternalClient(irc, client) server = utils.isInternalClient(irc, client)
if not server: if not server:
raise LookupError('No such PyLink PseudoClient exists.') raise LookupError('No such PyLink PseudoClient exists.')
if not utils.isChannel(channel): if not utils.isChannel(channel):
@ -54,9 +54,10 @@ def joinClient(irc, client, channel):
# One channel per line here! # One channel per line here!
_sendFromServer(irc, server, "FJOIN {channel} {ts} + :,{uid}".format( _sendFromServer(irc, server, "FJOIN {channel} {ts} + :,{uid}".format(
ts=int(time.time()), uid=client, channel=channel)) ts=int(time.time()), uid=client, channel=channel))
irc.channels[channel].users.add(client)
def partClient(irc, client, channel, reason=None): def partClient(irc, client, channel, reason=None):
if not isInternalClient(irc, client): if not utils.isInternalClient(irc, client):
raise LookupError('No such PyLink PseudoClient exists.') raise LookupError('No such PyLink PseudoClient exists.')
msg = "PART %s" % channel msg = "PART %s" % channel
if not utils.isChannel(channel): if not utils.isChannel(channel):
@ -64,6 +65,7 @@ def partClient(irc, client, channel, reason=None):
if reason: if reason:
msg += " :%s" % reason msg += " :%s" % reason
_sendFromUser(irc, client, msg) _sendFromUser(irc, client, msg)
handle_part(irc, client, 'PART', channel)
def removeClient(irc, numeric): def removeClient(irc, numeric):
"""<irc object> <client numeric> """<irc object> <client numeric>
@ -81,28 +83,11 @@ def removeClient(irc, numeric):
print('Removing client %s from irc.servers[%s]' % (numeric, sid)) print('Removing client %s from irc.servers[%s]' % (numeric, sid))
irc.servers[sid].users.remove(numeric) irc.servers[sid].users.remove(numeric)
def isInternalClient(irc, numeric):
"""<irc object> <client numeric>
Checks whether <client numeric> is a PyLink PseudoClient,
returning the SID of the PseudoClient's server if True.
"""
for sid in irc.servers:
if irc.servers[sid].internal and numeric in irc.servers[sid].users:
return sid
def isInternalServer(irc, sid):
"""<irc object> <sid>
Returns whether <sid> is an internal PyLink PseudoServer.
"""
return (sid in irc.servers and irc.servers[sid].internal)
def quitClient(irc, numeric, reason): 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 utils.isInternalClient(irc, numeric):
_sendFromUser(irc, numeric, "QUIT :%s" % reason) _sendFromUser(irc, numeric, "QUIT :%s" % reason)
removeClient(irc, numeric) removeClient(irc, numeric)
else: else:
@ -114,7 +99,7 @@ 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 utils.isInternalClient(irc, numeric):
raise LookupError('No such PyLink PseudoClient exists.') raise LookupError('No such PyLink PseudoClient exists.')
if not reason: if not reason:
reason = 'No reason given' reason = 'No reason given'
@ -124,7 +109,7 @@ 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 utils.isInternalClient(irc, numeric):
raise LookupError('No such PyLink PseudoClient exists.') raise LookupError('No such PyLink PseudoClient exists.')
if not utils.isNick(newnick): if not utils.isNick(newnick):
raise ValueError('Invalid nickname %r.' % nick) raise ValueError('Invalid nickname %r.' % nick)
@ -158,7 +143,7 @@ def connect(irc):
def handle_ping(irc, source, command, args): def handle_ping(irc, source, command, args):
# <- :70M PING 70M 0AL # <- :70M PING 70M 0AL
# -> :0AL PONG 0AL 70M # -> :0AL PONG 0AL 70M
if isInternalServer(irc, args[1]): if utils.isInternalServer(irc, args[1]):
_sendFromServer(irc, args[1], 'PONG %s %s' % (args[1], source)) _sendFromServer(irc, args[1], 'PONG %s %s' % (args[1], source))
def handle_privmsg(irc, source, command, args): def handle_privmsg(irc, source, command, args):
@ -202,6 +187,8 @@ def handle_part(irc, source, command, args):
channel = args[0] channel = args[0]
# We should only get PART commands for channels that exist, right?? # We should only get PART commands for channels that exist, right??
irc.channels[channel].users.discard(source) irc.channels[channel].users.discard(source)
if not irc.channels[channel].users:
del irc.channels[channel]
def handle_error(irc, numeric, command, args): def handle_error(irc, numeric, command, args):
print('Received an ERROR, killing!') print('Received an ERROR, killing!')
@ -211,8 +198,6 @@ def handle_error(irc, numeric, command, args):
def handle_fjoin(irc, servernumeric, command, args): def handle_fjoin(irc, servernumeric, command, args):
# :70M FJOIN #chat 1423790411 +AFPfjnt 6:5 7:5 9:5 :o,1SRAABIT4 v,1IOAAF53R <...> # :70M FJOIN #chat 1423790411 +AFPfjnt 6:5 7:5 9:5 :o,1SRAABIT4 v,1IOAAF53R <...>
channel = args[0] channel = args[0]
if channel not in irc.channels.keys():
irc.channels[channel] = IrcChannel()
# InspIRCd sends each user's channel data in the form of 'modeprefix(es),UID' # InspIRCd sends each user's channel data in the form of 'modeprefix(es),UID'
userlist = args[-1].split() userlist = args[-1].split()
for user in userlist: for user in userlist:
@ -318,7 +303,7 @@ def handle_rsquit(irc, numeric, command, args):
for (sid, server) in irc.servers.items(): for (sid, server) in irc.servers.items():
if server.name == target: if server.name == target:
target = sid target = sid
if isInternalServer(irc, target): if utils.isInternalServer(irc, target):
if irc.users[numeric].identified: if irc.users[numeric].identified:
uplink = irc.servers[target].uplink uplink = irc.servers[target].uplink
reason = 'Requested by %s' % irc.users[numeric].nick reason = 'Requested by %s' % irc.users[numeric].nick
@ -405,7 +390,7 @@ def spawnServer(irc, name, sid, uplink=None, desc='PyLink Server'):
for server in irc.servers.values(): for server in irc.servers.values():
if name == server.name: if name == server.name:
raise ValueError('A server named %r already exists!' % name) raise ValueError('A server named %r already exists!' % name)
if not isInternalServer(irc, uplink): if not utils.isInternalServer(irc, uplink):
raise ValueError('Server %r is not a PyLink internal PseudoServer!' % uplink) raise ValueError('Server %r is not a PyLink internal PseudoServer!' % uplink)
if not utils.isServerName(name): if not utils.isServerName(name):
raise ValueError('Invalid server name %r' % name) raise ValueError('Invalid server name %r' % name)

View File

@ -117,3 +117,20 @@ def applyModes(modelist, changedmodes):
def joinModes(modes): def joinModes(modes):
return '+' + ''.join(mode[1] for mode in modes) return '+' + ''.join(mode[1] for mode in modes)
def isInternalClient(irc, numeric):
"""<irc object> <client numeric>
Checks whether <client numeric> is a PyLink PseudoClient,
returning the SID of the PseudoClient's server if True.
"""
for sid in irc.servers:
if irc.servers[sid].internal and numeric in irc.servers[sid].users:
return sid
def isInternalServer(irc, sid):
"""<irc object> <sid>
Returns whether <sid> is an internal PyLink PseudoServer.
"""
return (sid in irc.servers and irc.servers[sid].internal)