Skip to content

Commit

Permalink
core: handle RPL_ISUPPORT
Browse files Browse the repository at this point in the history
  • Loading branch information
Exirel committed Nov 26, 2019
1 parent 3f3bc17 commit 62a60c3
Show file tree
Hide file tree
Showing 4 changed files with 101 additions and 1 deletion.
21 changes: 21 additions & 0 deletions sopel/coretasks.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
from sopel.tools import Identifier, iteritems, events
from sopel.tools.target import User, Channel
import base64
from sopel.irc import isupport

if sys.version_info.major >= 3:
unicode = str
Expand Down Expand Up @@ -65,6 +66,7 @@ def auth_after_register(bot):
@sopel.module.event(events.RPL_WELCOME, events.RPL_LUSERCLIENT)
@sopel.module.thread(False)
@sopel.module.unblockable
@sopel.module.priority('high')
def startup(bot, trigger):
"""Do tasks related to connecting to the network.
Expand Down Expand Up @@ -112,6 +114,25 @@ def startup(bot, trigger):
bot.say(msg, bot.config.core.owner)


@sopel.module.event(events.RPL_ISUPPORT)
@sopel.module.thread(False)
@sopel.module.unblockable
@sopel.module.priority('high')
@sopel.module.rule('are supported by this server')
def handle_isupport(bot, trigger):
"""Handle ``RPL_ISUPPORT`` events."""
parameters = {}
for arg in trigger.args:
try:
key, value = isupport.parse_parameter(arg)
parameters[key] = value
except ValueError:
# ignore malformated parameter: log a warning and continue
LOGGER.warning('Unable to parse ISUPPORT parameter: %r', arg)

bot._isupport = bot._isupport.apply(**parameters)


@sopel.module.require_privmsg()
@sopel.module.require_owner()
@sopel.module.commands('useserviceauth')
Expand Down
7 changes: 7 additions & 0 deletions sopel/irc/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@
from sopel.trigger import PreTrigger

from .backends import AsynchatBackend, SSLAsynchatBackend
from .isupport import ISupport
from .utils import safe, CapReq

if sys.version_info.major >= 3:
Expand All @@ -67,6 +68,7 @@ def __init__(self, settings):
self._nick = tools.Identifier(settings.core.nick)
self._user = settings.core.user
self._name = settings.core.name
self._isupport = ISupport()

self.backend = None
"""IRC Connection Backend."""
Expand Down Expand Up @@ -108,6 +110,11 @@ def config(self):
# TODO: Deprecate config, replaced by settings
return self.settings

@property
def isupport(self):
"""Features advertised by the server. (:class:`~.isupport.ISupport`)"""
return self._isupport

# Connection

def get_irc_backend(self):
Expand Down
2 changes: 1 addition & 1 deletion sopel/irc/isupport.py
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,7 @@ def parse_parameter(arg):
# ignore value for removed parameters
return (key, None)

parser = ISUPPORT_PARSER.get(key, str)
parser = ISUPPORT_PARSER.get(key, _optional(str))
return (key, parser(value))


Expand Down
72 changes: 72 additions & 0 deletions test/test_coretasks.py
Original file line number Diff line number Diff line change
Expand Up @@ -111,3 +111,75 @@ def test_mode_colon(mockbot, ircfactory):

assert mockbot.channels["#test"].privileges[Identifier("Uvoice")] == VOICE
assert mockbot.channels["#test"].privileges[Identifier("Uadmin")] == ADMIN


def test_handle_isupport(mockbot):
mockbot.on_message(
':irc.example.com 005 Sopel '
'CHANTYPES=# EXCEPTS INVEX CHANMODES=eIbq,k,flj,CFLMPQScgimnprstz '
'CHANLIMIT=#:120 PREFIX=(ov)@+ MAXLIST=bqeI:100 MODES=4 '
'NETWORK=example STATUSMSG=@+ CALLERID=g CASEMAPPING=rfc1459 '
':are supported by this server')

assert hasattr(mockbot, 'isupport')
assert 'CHANTYPES' in mockbot.isupport
assert 'EXCEPTS' in mockbot.isupport
assert 'INVEX' in mockbot.isupport
assert 'CHANMODES' in mockbot.isupport
assert 'CHANLIMIT' in mockbot.isupport
assert 'PREFIX' in mockbot.isupport
assert 'NETWORK' in mockbot.isupport
assert 'STATUSMSG' in mockbot.isupport
assert 'CALLERID' in mockbot.isupport
assert 'CASEMAPPING' in mockbot.isupport

assert mockbot.isupport['CHANTYPES'] == ('#',)
assert mockbot.isupport['EXCEPTS'] == 'e'
assert mockbot.isupport['INVEX'] == 'I'
assert mockbot.isupport['CHANMODES'] == (
'eIbq', 'k', 'flj', 'CFLMPQScgimnprstz', tuple())
assert hasattr(mockbot.isupport, 'CHANMODES')
assert mockbot.isupport.CHANMODES == {
'A': 'eIbq',
'B': 'k',
'C': 'flj',
'D': 'CFLMPQScgimnprstz',
}
assert mockbot.isupport['CHANLIMIT'] == (('#', 120),)
assert mockbot.isupport['PREFIX'] == (('o', '@'), ('v', '+'))
assert mockbot.isupport['NETWORK'] == 'example'

# not yet advertised
assert 'CHARSET' not in mockbot.isupport

# update
mockbot.on_message(
':irc.example.com 005 Sopel '
'CHARSET=ascii NICKLEN=16 CHANNELLEN=50 TOPICLEN=390 DEAF=D FNC '
'TARGMAX=NAMES:1,LIST:1,KICK:1,WHOIS:1,PRIVMSG:4,NOTICE:4,ACCEPT:,'
'MONITOR: EXTBAN=$,ajrxz CLIENTVER=3.0 ETRACE WHOX KNOCK '
':are supported by this server')

# now they are advertised
assert 'CHARSET' in mockbot.isupport
assert 'NICKLEN' in mockbot.isupport
assert 'CHANNELLEN' in mockbot.isupport
assert 'TOPICLEN' in mockbot.isupport
assert 'DEAF' in mockbot.isupport
assert 'FNC' in mockbot.isupport
assert 'TARGMAX' in mockbot.isupport
assert 'EXTBAN' in mockbot.isupport
assert 'CLIENTVER' in mockbot.isupport
assert 'ETRACE' in mockbot.isupport
assert 'WHOX' in mockbot.isupport
assert 'KNOCK' in mockbot.isupport

mockbot.on_message(
':irc.example.com 005 Sopel '
'SAFELIST ELIST=CTU CPRIVMSG CNOTICE '
':are supported by this server')

assert 'SAFELIST' in mockbot.isupport
assert 'ELIST' in mockbot.isupport
assert 'CPRIVMSG' in mockbot.isupport
assert 'CNOTICE' in mockbot.isupport

0 comments on commit 62a60c3

Please sign in to comment.