mirror of
https://github.com/evennia/evennia.git
synced 2026-03-27 18:26:32 +01:00
Added new IRC protocol implementation. Not tested yet.
This commit is contained in:
parent
2ae5d56928
commit
2108506a8a
7 changed files with 362 additions and 217 deletions
|
|
@ -264,8 +264,9 @@ class Object(TypeClass):
|
|||
def execute_cmd(self, raw_string, sessid=None):
|
||||
"""
|
||||
Do something as this object. This command transparently
|
||||
lets its typeclass execute the command. Evennia also calls
|
||||
this method whenever the player sends a command on the command line.
|
||||
lets its typeclass execute the command. This method is
|
||||
never called normally, it is only called explicitly in
|
||||
code.
|
||||
|
||||
Argument:
|
||||
raw_string (string) - raw command input
|
||||
|
|
|
|||
|
|
@ -9,9 +9,13 @@ from src.scripts.script import Script
|
|||
from src.commands.command import Command
|
||||
from src.commands.cmdset import CmdSet
|
||||
from src.commands.cmdhandler import CMD_NOMATCH
|
||||
from src.utils import search
|
||||
|
||||
_SESSIONS = None
|
||||
|
||||
|
||||
# Bot helper utilities
|
||||
|
||||
class BotStarter(Script):
|
||||
"""
|
||||
This non-repeating script has the
|
||||
|
|
@ -63,6 +67,8 @@ class BotCmdSet(CmdSet):
|
|||
self.add(CmdBotListen())
|
||||
|
||||
|
||||
# Bot base class
|
||||
|
||||
class Bot(Player):
|
||||
"""
|
||||
A Bot will start itself when the server
|
||||
|
|
@ -70,20 +76,25 @@ class Bot(Player):
|
|||
on a reload - that will be handled by the
|
||||
normal Portal session resync)
|
||||
"""
|
||||
def at_player_creation(self):
|
||||
|
||||
def basetype_setup(self):
|
||||
"""
|
||||
Called when the bot is first created. It sets
|
||||
up the cmdset and the botstarter script
|
||||
This sets up the basic properties for the bot.
|
||||
"""
|
||||
# the text encoding to use.
|
||||
self.db.encoding = "utf-8"
|
||||
# A basic security setup
|
||||
lockstring = "examine:perm(Wizards);edit:perm(Wizards);delete:perm(Wizards);boot:perm(Wizards);msg:all()"
|
||||
self.locks.add(lockstring)
|
||||
# set the basics of being a bot
|
||||
self.cmdset.add_default(BotCmdSet)
|
||||
script_key = "botstarter_%s" % self.key
|
||||
self.scripts.add(BotStarter, key=script_key)
|
||||
self.is_bot = True
|
||||
|
||||
def start(self):
|
||||
def start(self, **kwargs):
|
||||
"""
|
||||
This starts the bot, usually by connecting
|
||||
to a protocol.
|
||||
This starts the bot, whatever that may mean.
|
||||
"""
|
||||
pass
|
||||
|
||||
|
|
@ -100,23 +111,54 @@ class Bot(Player):
|
|||
pass
|
||||
|
||||
|
||||
# Bot implementations
|
||||
|
||||
class IRCBot(Bot):
|
||||
"""
|
||||
Bot for handling IRC connections
|
||||
Bot for handling IRC connections.
|
||||
"""
|
||||
def start(self):
|
||||
"Start by telling the portal to start a new session"
|
||||
global _SESSIONS
|
||||
def start(self, ev_channel=None, irc_botname=None, irc_channel=None, irc_network=None, irc_port=None):
|
||||
"""
|
||||
Start by telling the portal to start a new session.
|
||||
|
||||
ev_channel - key of the Evennia channel to connect to
|
||||
irc_botname - name of bot to connect to irc channel. If not set, use self.key
|
||||
irc_channel - name of channel on the form #channelname
|
||||
irc_network - url of network, like irc.freenode.net
|
||||
irc_port - port number of irc network, like 6667
|
||||
"""
|
||||
global _SESSIONS, _CHANNELDB
|
||||
if not _SESSIONS:
|
||||
from src.server.sessionhandler import SESSIONS as _SESSIONS
|
||||
# instruct the server and portal to create a new session
|
||||
_SESSIONS.start_bot_session("src.server.portal.irc.IRCClient", self.id)
|
||||
|
||||
def connect_to_channel(self, botkey, channelname):
|
||||
"""
|
||||
Connect the bot to an Evennia channel
|
||||
"""
|
||||
pass
|
||||
# if keywords are given, store (the BotStarter script
|
||||
# will not give any keywords, so this should normally only
|
||||
# happen at initialization)
|
||||
self.db.irc_botname = irc_botname if irc_botname else self.key
|
||||
if ev_channel:
|
||||
# connect to Evennia channel
|
||||
channel = search.channel_search(ev_channel)
|
||||
if not channel:
|
||||
raise RuntimeError("Evennia Channel '%s' not found." % ev_channel)
|
||||
channel.connect(self)
|
||||
self.db.ev_channel = channel
|
||||
if irc_channel:
|
||||
self.db.irc_channel = irc_channel
|
||||
if irc_network:
|
||||
self.db.irc_network = irc_network
|
||||
if irc_port:
|
||||
self.db.irc_port = irc_port
|
||||
|
||||
# cache channel
|
||||
self.ndb.ev_channel = self.db.ev_channel
|
||||
|
||||
# instruct the server and portal to create a new session with
|
||||
# the stored configuration
|
||||
configdict = {"botname": self.db.irc_botname,
|
||||
"channel": self.db.irc_channel ,
|
||||
"network": self.db.irc_network,
|
||||
"port": self.db.irc_port}
|
||||
_SESSIONS.start_bot_session("src.server.portal.irc.IRCClient", self.id, configdict)
|
||||
|
||||
def msg(self, text=None, **kwargs):
|
||||
"""
|
||||
|
|
@ -129,6 +171,10 @@ class IRCBot(Bot):
|
|||
text = "[%s] %s" % (ckey, text)
|
||||
self.dbobj.msg(text=text)
|
||||
|
||||
|
||||
def execute_cmd(self):
|
||||
pass
|
||||
def execute_cmd(self, text=None, sessid=None):
|
||||
"""
|
||||
Take incoming data and send it to connected channel. This is triggered
|
||||
by the CmdListen command in the BotCmdSet.
|
||||
"""
|
||||
if self.ndb.channel:
|
||||
self.ndb.channel.msg(text)
|
||||
|
|
|
|||
|
|
@ -78,6 +78,7 @@ class PlayerDB(TypedObject, AbstractUser):
|
|||
name - alias for user.username
|
||||
sessions - sessions connected to this player
|
||||
is_superuser - bool if this player is a superuser
|
||||
is_bot - bool if this player is a bot and not a real player
|
||||
|
||||
"""
|
||||
|
||||
|
|
@ -419,12 +420,11 @@ class PlayerDB(TypedObject, AbstractUser):
|
|||
"""
|
||||
Do something as this player. This method is never called normally,
|
||||
but only when the player object itself is supposed to execute the
|
||||
command. It does not take nicks on eventual puppets into account.
|
||||
command. It takes player nicks into account, but not nicks of
|
||||
eventual puppets.
|
||||
|
||||
raw_string - raw command input coming from the command line.
|
||||
"""
|
||||
# nick replacement - we require full-word matching.
|
||||
|
||||
raw_string = utils.to_unicode(raw_string)
|
||||
raw_string = self.nicks.nickreplace(raw_string,
|
||||
categories=("inputline", "channel"), include_player=False)
|
||||
|
|
|
|||
|
|
@ -136,8 +136,9 @@ class Player(TypeClass):
|
|||
def execute_cmd(self, raw_string, sessid=None):
|
||||
"""
|
||||
Do something as this object. This command transparently
|
||||
lets its typeclass execute the command. Evennia also calls
|
||||
this method whenever the player sends a command on the command line.
|
||||
lets its typeclass execute the command. This method
|
||||
is -not- called by Evennia normally, it is here to be
|
||||
called explicitly in code.
|
||||
|
||||
Argument:
|
||||
raw_string (string) - raw command input
|
||||
|
|
|
|||
|
|
@ -3,216 +3,309 @@ This connects to an IRC network/channel and launches an 'bot' onto it.
|
|||
The bot then pipes what is being said between the IRC channel and one or
|
||||
more Evennia channels.
|
||||
"""
|
||||
|
||||
from twisted.application import internet
|
||||
from twisted.words.protocols import irc
|
||||
from twisted.internet import protocol
|
||||
from django.conf import settings
|
||||
from src.comms.models import ExternalChannelConnection, ChannelDB
|
||||
from src.utils import logger, utils
|
||||
from src.server.sessionhandler import SESSIONS
|
||||
|
||||
from django.utils.translation import ugettext as _
|
||||
|
||||
INFOCHANNEL = ChannelDB.objects.channel_search(settings.CHANNEL_MUDINFO[0])
|
||||
IRC_CHANNELS = []
|
||||
from src.server.session import Session
|
||||
from src.utils import logger
|
||||
|
||||
|
||||
def msg_info(message):
|
||||
# IRC bot
|
||||
|
||||
class IRCBot(irc.IRCClient, Session):
|
||||
"""
|
||||
Send info to default info channel
|
||||
An IRC bot that tracks actitivity in a channel as well
|
||||
as sends text to it when prompted
|
||||
"""
|
||||
message = '[%s][IRC]: %s' % (INFOCHANNEL[0].key, message)
|
||||
try:
|
||||
INFOCHANNEL[0].msg(message)
|
||||
except AttributeError:
|
||||
logger.log_infomsg("MUDinfo (irc): %s" % message)
|
||||
lineRate = 1
|
||||
|
||||
# assigned by factory at creation
|
||||
|
||||
class IRC_Bot(irc.IRCClient):
|
||||
"""
|
||||
This defines an IRC bot that connects to an IRC channel
|
||||
and relays data to and from an evennia game.
|
||||
"""
|
||||
|
||||
def _get_nickname(self):
|
||||
"required for correct nickname setting"
|
||||
return self.factory.nickname
|
||||
nickname = property(_get_nickname)
|
||||
nickname = None
|
||||
logger = None
|
||||
factory = None
|
||||
channel = None
|
||||
|
||||
def signedOn(self):
|
||||
# This is the first point the protocol is instantiated.
|
||||
# add this protocol instance to the global list so we
|
||||
# can access it later to send data.
|
||||
global IRC_CHANNELS
|
||||
self.join(self.factory.channel)
|
||||
|
||||
IRC_CHANNELS.append(self)
|
||||
#msg_info("Client connecting to %s.'" % (self.factory.channel))
|
||||
|
||||
def joined(self, channel):
|
||||
msg = _("joined %s.") % self.factory.pretty_key
|
||||
msg_info(msg)
|
||||
logger.log_infomsg(msg)
|
||||
|
||||
def get_mesg_info(self, user, irc_channel, msg):
|
||||
"""
|
||||
Get basic information about a message posted in IRC.
|
||||
This is called when we successfully connect to
|
||||
the network. We make sure to store ourself
|
||||
on the factory.
|
||||
"""
|
||||
#find irc->evennia channel mappings
|
||||
conns = ExternalChannelConnection.objects.filter(db_external_key=self.factory.key)
|
||||
if not conns:
|
||||
return
|
||||
#format message:
|
||||
user = user.split("!")[0]
|
||||
if user:
|
||||
user.strip()
|
||||
else:
|
||||
user = _("Unknown")
|
||||
msg = msg.strip()
|
||||
sender_strings = ["%s@%s" % (user, irc_channel)]
|
||||
return conns, msg, sender_strings
|
||||
self.join(self.channel)
|
||||
self.factory.bot = self
|
||||
|
||||
def privmsg(self, user, irc_channel, msg):
|
||||
"Someone has written something in irc channel. Echo it to the evennia channel"
|
||||
conns, msg, sender_strings = self.get_mesg_info(user, irc_channel, msg)
|
||||
#logger.log_infomsg("<IRC: " + msg)
|
||||
for conn in conns:
|
||||
if conn.channel:
|
||||
conn.to_channel(msg, sender_strings=sender_strings)
|
||||
def privmsg(self, user, channel, msg):
|
||||
"A message was sent to channel"
|
||||
if not msg.startswith('***'):
|
||||
user = user.split('!', 1)[0]
|
||||
self.data_in
|
||||
|
||||
def action(self, user, irc_channel, msg):
|
||||
"Someone has performed an action, e.g. using /me <pose>"
|
||||
#find irc->evennia channel mappings
|
||||
conns = ExternalChannelConnection.objects.filter(db_external_key=self.factory.key)
|
||||
if not conns:
|
||||
return
|
||||
conns, msg, sender_strings = self.get_mesg_info(user, irc_channel, msg)
|
||||
# Transform this into a pose.
|
||||
msg = ':' + msg
|
||||
#logger.log_infomsg("<IRC: " + msg)
|
||||
for conn in conns:
|
||||
if conn.channel:
|
||||
conn.to_channel(msg, sender_strings=sender_strings)
|
||||
def action(self, user, channel, msg):
|
||||
"An action was done in channel"
|
||||
if not msg.startswith('**'):
|
||||
user = user.split('!', 1)[0]
|
||||
|
||||
def msg_irc(self, msg, senders=None):
|
||||
"""
|
||||
Called by evennia when sending something to mapped IRC channel.
|
||||
def data_in(self, text=None, **kwargs):
|
||||
"Data IRC -> Server"
|
||||
self.sessionhandler.data_in(self, text=text, **kwargs)
|
||||
|
||||
Note that this cannot simply be called msg() since that's the
|
||||
name of of the twisted irc hook as well, this leads to some
|
||||
initialization messages to be sent without checks, causing loops.
|
||||
"""
|
||||
self.msg(utils.to_str(self.factory.channel), utils.to_str(msg))
|
||||
def data_out(self, text=None, **kwargs):
|
||||
"Data from server-> IRC"
|
||||
self.say(self.channel, text)
|
||||
|
||||
def start(self):
|
||||
"Connect session to sessionhandler"
|
||||
service = internet.TCPClient(self.network, int(self.port), self)
|
||||
self.sessionhandler.portal.services.addService(service)
|
||||
self.sessionhandler.connect(self)
|
||||
|
||||
class IRCbotFactory(protocol.ClientFactory):
|
||||
protocol = IRC_Bot
|
||||
class IRCBotFactory(protocol.ReconnectingClientFactory):
|
||||
"""
|
||||
Creates instances of AnnounceBot, connecting with
|
||||
a staggered increase in delay
|
||||
"""
|
||||
# scaling reconnect time
|
||||
initialDelay = 1
|
||||
factor = 1.5
|
||||
maxDelay = 60
|
||||
|
||||
def __init__(self, key, channel, network, port, nickname, evennia_channel):
|
||||
self.key = key
|
||||
self.pretty_key = "%s:%s%s ('%s')" % (network, port, channel, nickname)
|
||||
def __init__(self, botname=None, channel=None, network=None, port=None):
|
||||
"Storing some important protocol properties"
|
||||
self.nickname = botname
|
||||
self.logger = logger
|
||||
self.channel = channel
|
||||
self.network = network
|
||||
self.port = port
|
||||
self.channel = channel
|
||||
self.nickname = nickname
|
||||
self.evennia_channel = evennia_channel
|
||||
self.bots = None
|
||||
|
||||
def clientConnectionLost(self, connector, reason):
|
||||
from twisted.internet.error import ConnectionDone
|
||||
if type(reason.type) == type(ConnectionDone):
|
||||
msg_info(_("Connection closed."))
|
||||
else:
|
||||
msg_info(_("Lost connection %(key)s. Reason: '%(reason)s'. Reconnecting.") % {"key":self.pretty_key, "reason":reason})
|
||||
connector.connect()
|
||||
def buildProtocol(self, addr):
|
||||
"Build the protocol and assign it some properties"
|
||||
protocol = IRCBot()
|
||||
protocol.factory = self
|
||||
protocol.nickname = self.nickname
|
||||
protocol.channel = self.channel
|
||||
protocol.network = self.network
|
||||
protocol.port = self.port
|
||||
return protocol
|
||||
|
||||
def clientConnectionFailed(self, connector, reason):
|
||||
msg = _("Could not connect %(key)s Reason: '%(reason)s'") % {"key":self.pretty_key, "reason":reason}
|
||||
msg_info(msg)
|
||||
logger.log_errmsg(msg)
|
||||
def startedConnecting(self, connector):
|
||||
"Tracks reconnections for debugging"
|
||||
logger.log_infomsg("(re)connecting to %s" % self.channel)
|
||||
|
||||
|
||||
def build_connection_key(channel, irc_network, irc_port, irc_channel, irc_bot_nick):
|
||||
"Build an id hash for the connection"
|
||||
if hasattr(channel, 'key'):
|
||||
channel = channel.key
|
||||
return "irc_%s:%s%s(%s)<>%s" % (irc_network, irc_port,
|
||||
irc_channel, irc_bot_nick, channel)
|
||||
|
||||
|
||||
def build_service_key(key):
|
||||
return "IRCbot:%s" % key
|
||||
|
||||
|
||||
def create_connection(channel, irc_network, irc_port,
|
||||
irc_channel, irc_bot_nick):
|
||||
"""
|
||||
This will create a new IRC<->channel connection.
|
||||
"""
|
||||
if not type(channel) == ChannelDB:
|
||||
new_channel = ChannelDB.objects.filter(db_key=channel)
|
||||
if not new_channel:
|
||||
logger.log_errmsg(_("Cannot attach IRC<->Evennia: Evennia Channel '%s' not found") % channel)
|
||||
return False
|
||||
channel = new_channel[0]
|
||||
key = build_connection_key(channel, irc_network, irc_port,
|
||||
irc_channel, irc_bot_nick)
|
||||
|
||||
old_conns = ExternalChannelConnection.objects.filter(db_external_key=key)
|
||||
if old_conns:
|
||||
return False
|
||||
config = "%s|%s|%s|%s" % (irc_network, irc_port, irc_channel, irc_bot_nick)
|
||||
# how the channel will be able to contact this protocol
|
||||
send_code = "from src.comms.irc import IRC_CHANNELS\n"
|
||||
send_code += "matched_ircs = [irc for irc in IRC_CHANNELS if irc.factory.key == '%s']\n" % key
|
||||
send_code += "[irc.msg_irc(message, senders=[self]) for irc in matched_ircs]\n"
|
||||
conn = ExternalChannelConnection(db_channel=channel,
|
||||
db_external_key=key,
|
||||
db_external_send_code=send_code,
|
||||
db_external_config=config)
|
||||
conn.save()
|
||||
|
||||
# connect
|
||||
connect_to_irc(conn)
|
||||
return True
|
||||
|
||||
def delete_connection(channel, irc_network, irc_port, irc_channel, irc_bot_nick):
|
||||
"Destroy a connection"
|
||||
if hasattr(channel, 'key'):
|
||||
channel = channel.key
|
||||
|
||||
key = build_connection_key(channel, irc_network, irc_port, irc_channel, irc_bot_nick)
|
||||
service_key = build_service_key(key)
|
||||
try:
|
||||
conn = ExternalChannelConnection.objects.get(db_external_key=key)
|
||||
except Exception:
|
||||
return False
|
||||
conn.delete()
|
||||
|
||||
try:
|
||||
service = SESSIONS.server.services.getServiceNamed(service_key)
|
||||
except Exception:
|
||||
return True
|
||||
if service.running:
|
||||
SESSIONS.server.services.removeService(service)
|
||||
return True
|
||||
|
||||
def connect_to_irc(connection):
|
||||
"Create the bot instance and connect to the IRC network and channel."
|
||||
# get config
|
||||
key = utils.to_str(connection.external_key)
|
||||
service_key = build_service_key(key)
|
||||
irc_network, irc_port, irc_channel, irc_bot_nick = [utils.to_str(conf) for conf in connection.external_config.split('|')]
|
||||
# connect
|
||||
bot = internet.TCPClient(irc_network, int(irc_port), IRCbotFactory(key, irc_channel, irc_network, irc_port, irc_bot_nick,
|
||||
connection.channel.key))
|
||||
bot.setName(service_key)
|
||||
SESSIONS.server.services.addService(bot)
|
||||
|
||||
def connect_all():
|
||||
"""
|
||||
Activate all irc bots.
|
||||
"""
|
||||
for connection in ExternalChannelConnection.objects.filter(db_external_key__startswith='irc_'):
|
||||
connect_to_irc(connection)
|
||||
|
||||
|
||||
#
|
||||
#from twisted.application import internet
|
||||
#from twisted.words.protocols import irc
|
||||
#from twisted.internet import protocol
|
||||
#from django.conf import settings
|
||||
#from src.comms.models import ExternalChannelConnection, ChannelDB
|
||||
#from src.utils import logger, utils
|
||||
#from src.server.sessionhandler import SESSIONS
|
||||
#
|
||||
#from django.utils.translation import ugettext as _
|
||||
#
|
||||
#INFOCHANNEL = ChannelDB.objects.channel_search(settings.CHANNEL_MUDINFO[0])
|
||||
#IRC_CHANNELS = []
|
||||
#
|
||||
#def msg_info(message):
|
||||
# """
|
||||
# Send info to default info channel
|
||||
# """
|
||||
# message = '[%s][IRC]: %s' % (INFOCHANNEL[0].key, message)
|
||||
# try:
|
||||
# INFOCHANNEL[0].msg(message)
|
||||
# except AttributeError:
|
||||
# logger.log_infomsg("MUDinfo (irc): %s" % message)
|
||||
#
|
||||
#
|
||||
#class IRC_Bot(irc.IRCClient):
|
||||
# """
|
||||
# This defines an IRC bot that connects to an IRC channel
|
||||
# and relays data to and from an evennia game.
|
||||
# """
|
||||
#
|
||||
# def _get_nickname(self):
|
||||
# "required for correct nickname setting"
|
||||
# return self.factory.nickname
|
||||
# nickname = property(_get_nickname)
|
||||
#
|
||||
# def signedOn(self):
|
||||
# # This is the first point the protocol is instantiated.
|
||||
# # add this protocol instance to the global list so we
|
||||
# # can access it later to send data.
|
||||
# global IRC_CHANNELS
|
||||
# self.join(self.factory.channel)
|
||||
#
|
||||
# IRC_CHANNELS.append(self)
|
||||
# #msg_info("Client connecting to %s.'" % (self.factory.channel))
|
||||
#
|
||||
# def joined(self, channel):
|
||||
# msg = _("joined %s.") % self.factory.pretty_key
|
||||
# msg_info(msg)
|
||||
# logger.log_infomsg(msg)
|
||||
#
|
||||
# def get_mesg_info(self, user, irc_channel, msg):
|
||||
# """
|
||||
# Get basic information about a message posted in IRC.
|
||||
# """
|
||||
# #find irc->evennia channel mappings
|
||||
# conns = ExternalChannelConnection.objects.filter(db_external_key=self.factory.key)
|
||||
# if not conns:
|
||||
# return
|
||||
# #format message:
|
||||
# user = user.split("!")[0]
|
||||
# if user:
|
||||
# user.strip()
|
||||
# else:
|
||||
# user = _("Unknown")
|
||||
# msg = msg.strip()
|
||||
# sender_strings = ["%s@%s" % (user, irc_channel)]
|
||||
# return conns, msg, sender_strings
|
||||
#
|
||||
# def privmsg(self, user, irc_channel, msg):
|
||||
# "Someone has written something in irc channel. Echo it to the evennia channel"
|
||||
# conns, msg, sender_strings = self.get_mesg_info(user, irc_channel, msg)
|
||||
# #logger.log_infomsg("<IRC: " + msg)
|
||||
# for conn in conns:
|
||||
# if conn.channel:
|
||||
# conn.to_channel(msg, sender_strings=sender_strings)
|
||||
#
|
||||
# def action(self, user, irc_channel, msg):
|
||||
# "Someone has performed an action, e.g. using /me <pose>"
|
||||
# #find irc->evennia channel mappings
|
||||
# conns = ExternalChannelConnection.objects.filter(db_external_key=self.factory.key)
|
||||
# if not conns:
|
||||
# return
|
||||
# conns, msg, sender_strings = self.get_mesg_info(user, irc_channel, msg)
|
||||
# # Transform this into a pose.
|
||||
# msg = ':' + msg
|
||||
# #logger.log_infomsg("<IRC: " + msg)
|
||||
# for conn in conns:
|
||||
# if conn.channel:
|
||||
# conn.to_channel(msg, sender_strings=sender_strings)
|
||||
#
|
||||
# def msg_irc(self, msg, senders=None):
|
||||
# """
|
||||
# Called by evennia when sending something to mapped IRC channel.
|
||||
#
|
||||
# Note that this cannot simply be called msg() since that's the
|
||||
# name of of the twisted irc hook as well, this leads to some
|
||||
# initialization messages to be sent without checks, causing loops.
|
||||
# """
|
||||
# self.msg(utils.to_str(self.factory.channel), utils.to_str(msg))
|
||||
#
|
||||
#
|
||||
#class IRCbotFactory(protocol.ClientFactory):
|
||||
# protocol = IRC_Bot
|
||||
#
|
||||
# def __init__(self, key, channel, network, port, nickname, evennia_channel):
|
||||
# self.key = key
|
||||
# self.pretty_key = "%s:%s%s ('%s')" % (network, port, channel, nickname)
|
||||
# self.network = network
|
||||
# self.port = port
|
||||
# self.channel = channel
|
||||
# self.nickname = nickname
|
||||
# self.evennia_channel = evennia_channel
|
||||
#
|
||||
# def clientConnectionLost(self, connector, reason):
|
||||
# from twisted.internet.error import ConnectionDone
|
||||
# if type(reason.type) == type(ConnectionDone):
|
||||
# msg_info(_("Connection closed."))
|
||||
# else:
|
||||
# msg_info(_("Lost connection %(key)s. Reason: '%(reason)s'. Reconnecting.") % {"key":self.pretty_key, "reason":reason})
|
||||
# connector.connect()
|
||||
#
|
||||
# def clientConnectionFailed(self, connector, reason):
|
||||
# msg = _("Could not connect %(key)s Reason: '%(reason)s'") % {"key":self.pretty_key, "reason":reason}
|
||||
# msg_info(msg)
|
||||
# logger.log_errmsg(msg)
|
||||
#
|
||||
#
|
||||
#def build_connection_key(channel, irc_network, irc_port, irc_channel, irc_bot_nick):
|
||||
# "Build an id hash for the connection"
|
||||
# if hasattr(channel, 'key'):
|
||||
# channel = channel.key
|
||||
# return "irc_%s:%s%s(%s)<>%s" % (irc_network, irc_port,
|
||||
# irc_channel, irc_bot_nick, channel)
|
||||
#
|
||||
#
|
||||
#def build_service_key(key):
|
||||
# return "IRCbot:%s" % key
|
||||
#
|
||||
#
|
||||
#def create_connection(channel, irc_network, irc_port,
|
||||
# irc_channel, irc_bot_nick):
|
||||
# """
|
||||
# This will create a new IRC<->channel connection.
|
||||
# """
|
||||
# if not type(channel) == ChannelDB:
|
||||
# new_channel = ChannelDB.objects.filter(db_key=channel)
|
||||
# if not new_channel:
|
||||
# logger.log_errmsg(_("Cannot attach IRC<->Evennia: Evennia Channel '%s' not found") % channel)
|
||||
# return False
|
||||
# channel = new_channel[0]
|
||||
# key = build_connection_key(channel, irc_network, irc_port,
|
||||
# irc_channel, irc_bot_nick)
|
||||
#
|
||||
# old_conns = ExternalChannelConnection.objects.filter(db_external_key=key)
|
||||
# if old_conns:
|
||||
# return False
|
||||
# config = "%s|%s|%s|%s" % (irc_network, irc_port, irc_channel, irc_bot_nick)
|
||||
# # how the channel will be able to contact this protocol
|
||||
# send_code = "from src.comms.irc import IRC_CHANNELS\n"
|
||||
# send_code += "matched_ircs = [irc for irc in IRC_CHANNELS if irc.factory.key == '%s']\n" % key
|
||||
# send_code += "[irc.msg_irc(message, senders=[self]) for irc in matched_ircs]\n"
|
||||
# conn = ExternalChannelConnection(db_channel=channel,
|
||||
# db_external_key=key,
|
||||
# db_external_send_code=send_code,
|
||||
# db_external_config=config)
|
||||
# conn.save()
|
||||
#
|
||||
# # connect
|
||||
# connect_to_irc(conn)
|
||||
# return True
|
||||
#
|
||||
#def delete_connection(channel, irc_network, irc_port, irc_channel, irc_bot_nick):
|
||||
# "Destroy a connection"
|
||||
# if hasattr(channel, 'key'):
|
||||
# channel = channel.key
|
||||
#
|
||||
# key = build_connection_key(channel, irc_network, irc_port, irc_channel, irc_bot_nick)
|
||||
# service_key = build_service_key(key)
|
||||
# try:
|
||||
# conn = ExternalChannelConnection.objects.get(db_external_key=key)
|
||||
# except Exception:
|
||||
# return False
|
||||
# conn.delete()
|
||||
#
|
||||
# try:
|
||||
# service = SESSIONS.server.services.getServiceNamed(service_key)
|
||||
# except Exception:
|
||||
# return True
|
||||
# if service.running:
|
||||
# SESSIONS.server.services.removeService(service)
|
||||
# return True
|
||||
#
|
||||
#def connect_to_irc(connection):
|
||||
# "Create the bot instance and connect to the IRC network and channel."
|
||||
# # get config
|
||||
# key = utils.to_str(connection.external_key)
|
||||
# service_key = build_service_key(key)
|
||||
# irc_network, irc_port, irc_channel, irc_bot_nick = [utils.to_str(conf) for conf in connection.external_config.split('|')]
|
||||
# # connect
|
||||
# bot = internet.TCPClient(irc_network, int(irc_port), IRCbotFactory(key, irc_channel, irc_network, irc_port, irc_bot_nick,
|
||||
# connection.channel.key))
|
||||
# bot.setName(service_key)
|
||||
# SESSIONS.server.services.addService(bot)
|
||||
#
|
||||
#def connect_all():
|
||||
# """
|
||||
# Activate all irc bots.
|
||||
# """
|
||||
# for connection in ExternalChannelConnection.objects.filter(db_external_key__startswith='irc_'):
|
||||
# connect_to_irc(connection)
|
||||
#
|
||||
#
|
||||
|
|
|
|||
|
|
@ -78,12 +78,12 @@ class PortalSessionHandler(SessionHandler):
|
|||
|
||||
protocol_path - full python path to the class factory
|
||||
for the protocol used, eg
|
||||
'src.server.portal.irc.IRCClient'
|
||||
'src.server.portal.irc.IRCClientFactory'
|
||||
uid - database uid to the connected player-bot
|
||||
config - dictionary of configuration options, fed as **kwarg
|
||||
to protocol class' __init__ method.
|
||||
|
||||
The called protocol class must have a method ConnectionMade
|
||||
The called protocol class must have a method start()
|
||||
that calls the portalsession.connect() as a normal protocol.
|
||||
"""
|
||||
global _MOD_IMPORT
|
||||
|
|
@ -93,7 +93,7 @@ class PortalSessionHandler(SessionHandler):
|
|||
cls = _MOD_IMPORT(path, clsname)
|
||||
protocol = cls(**config)
|
||||
protocol.sessionhandler = self
|
||||
protocol.connectionMade()
|
||||
protocol.start()
|
||||
|
||||
def server_disconnect(self, sessid, reason=""):
|
||||
"""
|
||||
|
|
|
|||
|
|
@ -177,7 +177,11 @@ class ServerSession(Session):
|
|||
"""
|
||||
Send User->Evennia. This will in effect
|
||||
execute a command string on the server.
|
||||
Eventual extra data moves through oob_data_in
|
||||
|
||||
Especially handled keywords:
|
||||
|
||||
oob - this should hold a dictionary of oob command calls from
|
||||
the oob-supporting protocol.
|
||||
"""
|
||||
if text:
|
||||
# this is treated as a command input
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue