aboutsummaryrefslogtreecommitdiff
path: root/http2irc.py
diff options
context:
space:
mode:
Diffstat (limited to 'http2irc.py')
-rw-r--r--http2irc.py22
1 files changed, 15 insertions, 7 deletions
diff --git a/http2irc.py b/http2irc.py
index 7a38122..15f21a3 100644
--- a/http2irc.py
+++ b/http2irc.py
@@ -374,6 +374,7 @@ class IRCClientProtocol(asyncio.Protocol):
self.whoxReply = [] # List of (nickname, account) tuples from the currently running WHO query
self.whoxStartTime = None
self.userChannels = collections.defaultdict(set) # List of which channels a user is known to be in; nickname:str -> {channel:str, ...}
+ self.linelen = 510
@staticmethod
def nick_command(nick: str):
@@ -402,13 +403,13 @@ class IRCClientProtocol(asyncio.Protocol):
# command: b'JOIN' or b'PART'; channels: set[str]
channels = [x.encode('utf-8') for x in channels]
- if len(command) + sum(1 + len(x) for x in channels) <= 510: # Total length = command + (separator + channel name for each channel, where the separator is a space for the first and then a comma)
+ if len(command) + sum(1 + len(x) for x in channels) <= self.linelen: # Total length = command + (separator + channel name for each channel, where the separator is a space for the first and then a comma)
# Everything fits into one command.
self.send(command + b' ' + b','.join(channels))
return
# List too long, need to split.
- limit = 510 - len(command)
+ limit = self.linelen - len(command)
lengths = [1 + len(x) for x in channels] # separator + channel name
chanLengthAcceptable = [l <= limit for l in lengths]
if not all(chanLengthAcceptable):
@@ -444,8 +445,8 @@ class IRCClientProtocol(asyncio.Protocol):
def send(self, data):
self.logger.debug(f'Queueing for send: {data!r}')
- if len(data) > 510:
- raise RuntimeError(f'IRC message too long ({len(data)} > 510): {data!r}')
+ if len(data) > self.linelen:
+ raise RuntimeError(f'IRC message too long ({len(data)} > {self.linelen}): {data!r}')
self.sendQueue.put_nowait(data)
def _direct_send(self, data):
@@ -529,12 +530,12 @@ class IRCClientProtocol(asyncio.Protocol):
channelB = channel.encode('utf-8')
messageB = message.encode('utf-8')
usermaskPrefixLength = 1 + self._self_usermask_length() + 1 # :usermask<SP>
- if usermaskPrefixLength + len(b'PRIVMSG ' + channelB + b' :' + messageB) > 510:
+ if usermaskPrefixLength + len(b'PRIVMSG ' + channelB + b' :' + messageB) > self.linelen:
# Message too long, need to split or truncate. First try to split on spaces, then on codepoints. Ideally, would use graphemes between, but that's too complicated.
self.logger.debug(f'Message too long, overlongmode = {overlongmode}')
prefix = b'PRIVMSG ' + channelB + b' :'
prefixLength = usermaskPrefixLength + len(prefix) # Need to account for the origin prefix included by the ircd when sending to others
- maxMessageLength = 510 - prefixLength # maximum length of the message part within each line
+ maxMessageLength = self.linelen - prefixLength # maximum length of the message part within each line
if overlongmode == 'truncate':
maxMessageLength -= 3 # Make room for an ellipsis at the end
messages = []
@@ -553,7 +554,7 @@ class IRCClientProtocol(asyncio.Protocol):
continue
# No space found, need to search for a suitable codepoint location.
- pMessage = message[:maxMessageLength] # at most 510 codepoints which expand to at least 510 bytes
+ pMessage = message[:maxMessageLength] # at most linelen codepoints which expand to at least linelen bytes
pLengths = [len(x.encode('utf-8')) for x in pMessage] # byte size of each codepoint
pRunningLengths = list(itertools.accumulate(pLengths)) # byte size up to each codepoint
if pRunningLengths[-1] <= maxMessageLength: # Special case: entire pMessage is short enough
@@ -657,6 +658,13 @@ class IRCClientProtocol(asyncio.Protocol):
self.logger.error('SASL error, terminating connection')
self.transport.close()
+ elif line.command in (ircstates.numerics.RPL_ENDOFMOTD, ircstates.numerics.ERR_NOMOTD):
+ if 'LINELEN' in self.server.isupport.raw:
+ try:
+ self.linelen = int(self.server.isupport.raw['LINELEN'])-2
+ except ValueError as e:
+ self.logger.error(f'IRC server sent invalid LINELEN, ignoring: {value}')
+
# NICK errors
elif line.command in ('431', ircstates.numerics.ERR_ERRONEUSNICKNAME, ircstates.numerics.ERR_NICKNAMEINUSE, '436'):
self.logger.error(f'Failed to set nickname: {message!r}, terminating connection')