mirror of
https://github.com/jlu5/PyLink.git
synced 2024-11-01 01:09:22 +01:00
Attempt to make sender validation in protocols a bit less repetitive
This commit is contained in:
parent
05752d9f60
commit
7003ff848d
32
classes.py
32
classes.py
@ -907,6 +907,38 @@ class Protocol():
|
||||
target = self.irc.nickToUid(target) or target
|
||||
return target
|
||||
|
||||
def checkSender(check):
|
||||
"""
|
||||
Helper function for protocols which validates that the sender given is
|
||||
an internal client or server.
|
||||
|
||||
Check is given as a string, where 's' refers to server,
|
||||
'c' refers to client, and 'cs' refers to either server or client."""
|
||||
# We have to actually wrap this twice, to past checkSender('string')
|
||||
# arguments to the actual function that performs checks. Gross.
|
||||
def checkSender_get_check(func):
|
||||
def checkSender_wrapper(self, sender, *args, **kwargs):
|
||||
# 1) Perform checks.
|
||||
isclient = self.irc.isInternalClient(sender)
|
||||
isserver = self.irc.isInternalServer(sender)
|
||||
log.debug('checkServer: query is %s, target is %s', check, sender)
|
||||
log.debug('checkServer: isclient: %s, isserver: %s', isclient, isserver)
|
||||
|
||||
if check == 'cs':
|
||||
if not (isclient or isserver):
|
||||
raise LookupError('No such PyLink client/server exists.')
|
||||
elif check == 'c':
|
||||
if not isclient:
|
||||
raise LookupError('No such PyLink client exists.')
|
||||
elif check == 's':
|
||||
if not isserver:
|
||||
raise LookupError('No such PyLink server exists.')
|
||||
|
||||
# 2) Call and return the data of the original function.
|
||||
return func(self, sender, *args, **kwargs)
|
||||
return checkSender_wrapper
|
||||
return checkSender_get_check
|
||||
|
||||
### FakeIRC classes, used for test cases
|
||||
|
||||
class FakeIRC(Irc):
|
||||
|
@ -71,16 +71,15 @@ class InspIRCdProtocol(TS6BaseProtocol):
|
||||
self._operUp(uid, opertype)
|
||||
return u
|
||||
|
||||
@checkSender('c')
|
||||
def join(self, client, channel):
|
||||
"""Joins a PyLink client to a channel."""
|
||||
# InspIRCd doesn't distinguish between burst joins and regular joins,
|
||||
# so what we're actually doing here is sending FJOIN from the server,
|
||||
# on behalf of the clients that are joining.
|
||||
channel = utils.toLower(self.irc, channel)
|
||||
server = self.irc.isInternalClient(client)
|
||||
if not server:
|
||||
log.error('(%s) Error trying to join %r to %r (no such client exists)', self.irc.name, client, channel)
|
||||
raise LookupError('No such PyLink client exists.')
|
||||
server = self.irc.getServer(client)
|
||||
|
||||
# Strip out list-modes, they shouldn't be ever sent in FJOIN.
|
||||
modes = [m for m in self.irc.channels[channel].modes if m[0] not in self.irc.cmodes['*A']]
|
||||
self._send(server, "FJOIN {channel} {ts} {modes} :,{uid}".format(
|
||||
@ -89,6 +88,7 @@ class InspIRCdProtocol(TS6BaseProtocol):
|
||||
self.irc.channels[channel].users.add(client)
|
||||
self.irc.users[client].channels.add(channel)
|
||||
|
||||
@checkSender('s')
|
||||
def sjoin(self, server, channel, users, ts=None):
|
||||
"""Sends an SJOIN for a group of users to a channel.
|
||||
|
||||
@ -104,8 +104,6 @@ class InspIRCdProtocol(TS6BaseProtocol):
|
||||
server = server or self.irc.sid
|
||||
assert users, "sjoin: No users sent?"
|
||||
log.debug('(%s) sjoin: got %r for users', self.irc.name, users)
|
||||
if not server:
|
||||
raise LookupError('No such PyLink client exists.')
|
||||
|
||||
orig_ts = self.irc.channels[channel].ts
|
||||
ts = ts or orig_ts
|
||||
@ -163,15 +161,12 @@ class InspIRCdProtocol(TS6BaseProtocol):
|
||||
userobj.opertype = otype
|
||||
self._send(target, 'OPERTYPE %s' % otype.replace(" ", "_"))
|
||||
|
||||
@checkSender('cs')
|
||||
def mode(self, numeric, target, modes, ts=None):
|
||||
"""Sends mode changes from a PyLink client/server."""
|
||||
# -> :9PYAAAAAA FMODE #pylink 1433653951 +os 9PYAAAAAA
|
||||
# -> :9PYAAAAAA MODE 9PYAAAAAA -i+w
|
||||
|
||||
if (not self.irc.isInternalClient(numeric)) and \
|
||||
(not self.irc.isInternalServer(numeric)):
|
||||
raise LookupError('No such PyLink client/server exists.')
|
||||
|
||||
log.debug('(%s) inspircd._sendModes: received %r for mode list', self.irc.name, modes)
|
||||
if ('+o', None) in modes and not utils.isChannel(target):
|
||||
# https://github.com/inspircd/inspircd/blob/master/src/modules/m_spanningtree/opertype.cpp#L26-L28
|
||||
@ -185,12 +180,9 @@ class InspIRCdProtocol(TS6BaseProtocol):
|
||||
else:
|
||||
self._send(numeric, 'MODE %s %s' % (target, joinedmodes))
|
||||
|
||||
@checkSender('cs')
|
||||
def kill(self, numeric, target, reason):
|
||||
"""Sends a kill from a PyLink client/server."""
|
||||
if (not self.irc.isInternalClient(numeric)) and \
|
||||
(not self.irc.isInternalServer(numeric)):
|
||||
raise LookupError('No such PyLink client/server exists.')
|
||||
|
||||
# InspIRCd will show the raw kill message sent from our server as the quit message.
|
||||
# So, make the kill look actually like a kill instead of someone quitting with
|
||||
# an arbitrary message.
|
||||
@ -207,22 +199,23 @@ class InspIRCdProtocol(TS6BaseProtocol):
|
||||
if self.irc.isInternalClient(target):
|
||||
self.removeClient(target)
|
||||
|
||||
@checkSender('s')
|
||||
def topicBurst(self, numeric, target, text):
|
||||
"""Sends a topic change from a PyLink server. This is usually used on burst."""
|
||||
if not self.irc.isInternalServer(numeric):
|
||||
raise LookupError('No such PyLink server exists.')
|
||||
ts = int(time.time())
|
||||
servername = self.irc.servers[numeric].name
|
||||
self._send(numeric, 'FTOPIC %s %s %s :%s' % (target, ts, servername, text))
|
||||
self.irc.channels[target].topic = text
|
||||
self.irc.channels[target].topicset = True
|
||||
|
||||
@checkSender('c')
|
||||
def invite(self, numeric, target, channel):
|
||||
"""Sends an INVITE from a PyLink client.."""
|
||||
if not self.irc.isInternalClient(numeric):
|
||||
raise LookupError('No such PyLink client exists.')
|
||||
self._send(numeric, 'INVITE %s %s' % (target, channel))
|
||||
|
||||
@checkSender('c')
|
||||
def knock(self, numeric, target, text):
|
||||
"""Sends a KNOCK from a PyLink client."""
|
||||
if not self.irc.isInternalClient(numeric):
|
||||
@ -284,7 +277,7 @@ class InspIRCdProtocol(TS6BaseProtocol):
|
||||
"protocol module. WHOIS requests are handled "
|
||||
"locally by InspIRCd servers, so there is no "
|
||||
"need for PyLink to send numerics directly yet.")
|
||||
|
||||
@checkSender('c')
|
||||
def away(self, source, text):
|
||||
"""Sends an AWAY message from a PyLink client. <text> can be an empty string
|
||||
to unset AWAY status."""
|
||||
@ -334,6 +327,7 @@ class InspIRCdProtocol(TS6BaseProtocol):
|
||||
endburstf()
|
||||
return sid
|
||||
|
||||
@checkSender('cs')
|
||||
def squit(self, source, target, text='No reason given'):
|
||||
"""SQUITs a PyLink server."""
|
||||
# -> :9PY SQUIT 9PZ :blah, blah
|
||||
|
Loading…
Reference in New Issue
Block a user