diff --git a/evennia/commands/default/comms.py b/evennia/commands/default/comms.py index f93279c017..730400aa77 100644 --- a/evennia/commands/default/comms.py +++ b/evennia/commands/default/comms.py @@ -755,7 +755,7 @@ class CmdIRC2Chan(MuxCommand): link an evennia channel to an external IRC channel Usage: - @irc2chan[/switches] = <#irchannel> + @irc2chan[/switches] = <[+]port> <#irchannel> @irc2chan/list @irc2chan/delete botname|#dbid @@ -774,7 +774,8 @@ class CmdIRC2Chan(MuxCommand): vice versa. The bot will automatically connect at server start, so this comman need only be given once. The /disconnect switch will permanently delete the bot. To only temporarily deactivate it, use the {w@services{n - command instead. + command instead. To connect with SSL, add a plus sign (+) before the port + number. """ key = "@irc2chan" @@ -794,10 +795,10 @@ class CmdIRC2Chan(MuxCommand): ircbots = [bot for bot in PlayerDB.objects.filter(db_is_bot=True, username__startswith="ircbot-")] if ircbots: from evennia.utils.evtable import EvTable - table = EvTable("{wdbid{n", "{wbotname{n", "{wev-channel{n", "{wirc-channel{n", maxwidth=_DEFAULT_WIDTH) + table = EvTable("{wdbid{n", "{wbotname{n", "{wev-channel{n", "{wirc-channel{n", "{wSSL{n", maxwidth=_DEFAULT_WIDTH) for ircbot in ircbots: ircinfo = "%s (%s:%s)" % (ircbot.db.irc_channel, ircbot.db.irc_network, ircbot.db.irc_port) - table.add_row(ircbot.id, ircbot.db.irc_botname, ircbot.db.ev_channel, ircinfo) + table.add_row(ircbot.id, ircbot.db.irc_botname, ircbot.db.ev_channel, ircinfo, ircbot.db.irc_ssl) self.caller.msg(table) else: self.msg("No irc bots found.") @@ -820,7 +821,7 @@ class CmdIRC2Chan(MuxCommand): return if not self.args or not self.rhs: - string = "Usage: @irc2chan[/switches] = <#irchannel> " + string = "Usage: @irc2chan[/switches] = <[+]port> <#irchannel> " self.msg(string) return @@ -830,6 +831,9 @@ class CmdIRC2Chan(MuxCommand): irc_network, irc_port, irc_channel, irc_botname = \ [part.strip() for part in self.rhs.split(None, 3)] irc_channel = "#%s" % irc_channel + if "+" in irc_port: + irc_ssl = True + irc_port = irc_port[1:] except Exception: string = "IRC bot definition '%s' is not valid." % self.rhs self.msg(string) @@ -848,7 +852,7 @@ class CmdIRC2Chan(MuxCommand): else: bot = create.create_player(botname, None, None, typeclass=bots.IRCBot) bot.start(ev_channel=channel, irc_botname=irc_botname, irc_channel=irc_channel, - irc_network=irc_network, irc_port=irc_port) + irc_network=irc_network, irc_port=irc_port, irc_ssl=irc_ssl) self.msg("Connection created. Starting IRC bot.") # RSS connection diff --git a/evennia/players/bots.py b/evennia/players/bots.py index 4eacf54182..327354bbce 100644 --- a/evennia/players/bots.py +++ b/evennia/players/bots.py @@ -168,7 +168,7 @@ class IRCBot(Bot): Bot for handling IRC connections. """ - def start(self, ev_channel=None, irc_botname=None, irc_channel=None, irc_network=None, irc_port=None): + def start(self, ev_channel=None, irc_botname=None, irc_channel=None, irc_network=None, irc_port=None, irc_ssl=None): """ Start by telling the portal to start a new session. @@ -179,6 +179,7 @@ class IRCBot(Bot): irc_channel (str): Name of channel on the form `#channelname`. irc_network (str): URL of the IRC network, like `irc.freenode.net`. irc_port (str): Port number of the irc network, like `6667`. + irc_ssl (bool): Indicates whether to use SSL connection. """ global _SESSIONS @@ -206,6 +207,8 @@ class IRCBot(Bot): self.db.irc_network = irc_network if irc_port: self.db.irc_port = irc_port + if irc_ssl: + self.db.irc_ssl = irc_ssl # instruct the server and portal to create a new session with # the stored configuration @@ -213,7 +216,8 @@ class IRCBot(Bot): "botname": self.db.irc_botname, "channel": self.db.irc_channel , "network": self.db.irc_network, - "port": self.db.irc_port} + "port": self.db.irc_port, + "ssl": self.db.irc_ssl} _SESSIONS.start_bot_session("evennia.server.portal.irc.IRCBotFactory", configdict) def msg(self, text=None, **kwargs): diff --git a/evennia/server/portal/irc.py b/evennia/server/portal/irc.py index b09922473d..b44eef787a 100644 --- a/evennia/server/portal/irc.py +++ b/evennia/server/portal/irc.py @@ -9,7 +9,7 @@ from future.utils import viewkeys import re from twisted.application import internet from twisted.words.protocols import irc -from twisted.internet import protocol +from twisted.internet import protocol, reactor, ssl from evennia.server.session import Session from evennia.utils import logger, utils @@ -230,7 +230,7 @@ class IRCBotFactory(protocol.ReconnectingClientFactory): factor = 1.5 maxDelay = 60 - def __init__(self, sessionhandler, uid=None, botname=None, channel=None, network=None, port=None): + def __init__(self, sessionhandler, uid=None, botname=None, channel=None, network=None, port=None, ssl=None): """ Storing some important protocol properties. @@ -243,6 +243,7 @@ class IRCBotFactory(protocol.ReconnectingClientFactory): channel (str): IRC channel to connect to. network (str): Network address to connect to. port (str): Port of the network. + ssl (bool): Indicates SSL connection. """ self.sessionhandler = sessionhandler @@ -251,6 +252,7 @@ class IRCBotFactory(protocol.ReconnectingClientFactory): self.channel = str(channel) self.network = str(network) self.port = port + self.ssl = ssl self.bot = None def buildProtocol(self, addr): @@ -267,6 +269,7 @@ class IRCBotFactory(protocol.ReconnectingClientFactory): protocol.channel = self.channel protocol.network = self.network protocol.port = self.port + protocol.ssl = self.ssl return protocol def startedConnecting(self, connector): @@ -308,5 +311,13 @@ class IRCBotFactory(protocol.ReconnectingClientFactory): """ if self.port: - service = internet.TCPClient(self.network, int(self.port), self) + if ssl: + """ + Requires PyOpenSSL + + """ + service = reactor.connectSSL(self.network, int(self.port), self, ssl.ClientContextFactory()) + else: + service = internet.TCPClient(self.network, int(self.port), self) + self.sessionhandler.portal.services.addService(service) diff --git a/requirements.txt b/requirements.txt index d1e4790d4c..98b2375112 100644 --- a/requirements.txt +++ b/requirements.txt @@ -6,3 +6,4 @@ mock >= 1.0.1 pillow == 2.9.0 pytz future >= 0.15.2 +pyopenssl >= 16.0.0