Respect RFC1459 casemapping rules

This commit is contained in:
jesopo 2018-09-11 08:52:12 +01:00
parent 7530bb7cbd
commit 6c8399fa0f
6 changed files with 45 additions and 17 deletions

View file

@ -1,4 +1,5 @@
import re
import Utils
class BufferLine(object):
def __init__(self, sender, message, action, from_self):
@ -28,7 +29,7 @@ class Buffer(object):
def find(self, pattern, **kwargs):
from_self = kwargs.get("from_self", True)
for_user = kwargs.get("for_user", "")
for_user = for_user.lower() if for_user else None
for_user = Utils.irc_lower(for_user) if for_user else None
not_pattern = kwargs.get("not_pattern", None)
for line in self.lines:
if line.from_self and not from_self:
@ -36,7 +37,7 @@ class Buffer(object):
elif re.search(pattern, line.message):
if not_pattern and re.search(not_pattern, line.message):
continue
if for_user and not line.sender.lower() == for_user:
if for_user and not Utils.irc_lower(line.sender) == for_user:
continue
return line
def skip_next(self):

View file

@ -1,9 +1,9 @@
import uuid
import IRCBuffer
import IRCBuffer, Utils
class Channel(object):
def __init__(self, name, id, server, bot):
self.name = name.lower()
self.name = Utils.irc_lower(name)
self.id = id
self.server = server
self.bot = bot

View file

@ -5,6 +5,7 @@ RE_PREFIXES = re.compile(r"\bPREFIX=\((\w+)\)(\W+)(?:\b|$)")
RE_CHANMODES = re.compile(
r"\bCHANMODES=(\w*),(\w*),(\w*),(\w*)(?:\b|$)")
RE_CHANTYPES = re.compile(r"\bCHANTYPES=(\W+)(?:\b|$)")
RE_CASEMAPPING = re.compile(r"\bCASEMAPPING=(\S+)")
RE_MODES = re.compile(r"[-+]\w+")
CAPABILITIES = {"multi-prefix", "chghost", "invite-notify", "account-tag",
@ -136,6 +137,11 @@ class LineHandler(object):
match = re.search(RE_CHANTYPES, isupport_line)
if match:
event["server"].channel_types = list(match.group(1))
match = re.search(RE_CASEMAPPING, isupport_line)
if match:
event["server"].case_mapping = match.group(1)
self.events.on("received.numeric.005").call(
isupport=isupport_line, server=event["server"])
@ -554,10 +560,11 @@ class LineHandler(object):
# we need a registered nickname for this channel
def handle_477(self, event):
if event["args"][1].lower() in event["server"].attempted_join:
channel_name = Utils.irc_lower(event["args"][1])
if channel_name in event["server"].attempted_join:
self.bot.add_timer("rejoin", 5,
channel_name=event["args"][1],
key=event["server"].attempted_join[event["args"][1].lower()],
key=event["server"].attempted_join[channel_name],
server_id=event["server"].id)
# someone's been kicked from a channel

View file

@ -47,6 +47,7 @@ class Server(object):
{"@": "o", "+": "v"})
self.channel_modes = []
self.channel_types = []
self.case_mapping = "rfc1459"
self.last_read = time.monotonic()
self.last_send = None
@ -130,9 +131,9 @@ class Server(object):
def set_own_nickname(self, nickname):
self.nickname = nickname
self.nickname_lower = nickname.lower()
self.nickname_lower = Utils.irc_lower(nickname)
def is_own_nickname(self, nickname):
return nickname.lower() == self.nickname_lower
return Utils.irc_equals(nickname, self.nickname)
def add_own_mode(self, mode, arg=None):
self.own_modes[mode] = arg
@ -145,7 +146,7 @@ class Server(object):
self.add_own_mode(mode, arg)
def has_user(self, nickname):
return nickname.lower() in self.users
return Utils.irc_lower(nickname) in self.users
def get_user(self, nickname):
if not self.has_user(nickname):
user_id = self.get_user_id(nickname)
@ -154,7 +155,7 @@ class Server(object):
user=new_user, server=self)
self.users[new_user.nickname_lower] = new_user
self.new_users.add(new_user)
return self.users[nickname.lower()]
return self.users[Utils.irc_lower(nickname)]
def get_user_id(self, nickname):
self.bot.database.users.add(self.id, nickname)
return self.bot.database.users.get_id(self.id, nickname)
@ -164,12 +165,12 @@ class Server(object):
channel.remove_user(user)
def change_user_nickname(self, old_nickname, new_nickname):
user = self.users.pop(old_nickname.lower())
user = self.users.pop(Utils.irc_lower(old_nickname))
user._id = self.get_user_id(new_nickname)
self.users[new_nickname.lower()] = user
self.users[Utils.irc_lower(new_nickname)] = user
def has_channel(self, channel_name):
return channel_name[0] in self.channel_types and channel_name.lower(
) in self.channels
return channel_name[0] in self.channel_types and Utils.irc_lower(
channel_name) in self.channels
def get_channel(self, channel_name):
if not self.has_channel(channel_name):
channel_id = self.get_channel_id(channel_name)
@ -178,7 +179,7 @@ class Server(object):
self.events.on("new").on("channel").call(
channel=new_channel, server=self)
self.channels[new_channel.name] = new_channel
return self.channels[channel_name.lower()]
return self.channels[Utils.irc_lower(channel_name)]
def get_channel_id(self, channel_name):
self.bot.database.channels.add(self.id, channel_name)
return self.bot.database.channels.get_id(self.id, channel_name)

View file

@ -1,5 +1,5 @@
import uuid
import IRCBuffer
import IRCBuffer, Utils
class User(object):
def __init__(self, nickname, id, server, bot):
@ -31,7 +31,7 @@ class User(object):
def set_nickname(self, nickname):
self.nickname = nickname
self.nickname_lower = nickname.lower()
self.nickname_lower = Utils.irc_lower(nickname)
self.name = self.nickname_lower
def join_channel(self, channel):
self.channels.add(channel)

View file

@ -1,10 +1,14 @@
import json, re, traceback, urllib.request, urllib.parse, urllib.error, ssl
import string
import bs4
USER_AGENT = ("Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 "
"(KHTML, like Gecko) Chrome/49.0.2623.87 Safari/537.36")
REGEX_HTTP = re.compile("https?://", re.I)
RFC1459_UPPER = r'\[]~'
RFC1459_UPPER = r'|{}^'
def remove_colon(s):
if s.startswith(":"):
s = s[1:]
@ -13,6 +17,21 @@ def remove_colon(s):
def arbitrary(s, n):
return remove_colon(" ".join(s[n:]))
def _rfc1459_lower(s):
for upper, lower in zip(RFC1459_UPPER, RFC1459_LOWER):
s = s.replace(upper, lower)
return s.lower()
def irc_lower(server, s):
if server.case_mapping == "ascii":
return s.lower()
elif server.case_mapping == "rfc1459":
return _rfc1459_lower(s)
else:
raise ValueError("unknown casemapping '%s'" % server.case_mapping)
def irc_equals(server, s1, s2):
return irc_lower(server, s1) == irc_lower(server, s2)
class IRCHostmask(object):
def __init__(self, nickname, username, hostname, hostmask):
self.nickname = nickname