Further updates to the IMC2 system, making it a bit easier to use.

This commit is contained in:
Griatch 2011-04-20 00:27:19 +00:00
parent c70d59045a
commit 23462c626c
5 changed files with 147 additions and 183 deletions

View file

@ -921,19 +921,20 @@ class CmdIMC2Chan(MuxCommand):
imc2chan - link an evennia channel to imc2 imc2chan - link an evennia channel to imc2
Usage: Usage:
@imc2chan[/switches] <evennia_channel> = <imc2network> <port> <imc2channel> <imc2_client_pwd> <imc2_server_pwd> @imc2chan[/switches] <evennia_channel> = <imc2_channel>
Switches: Switches:
/disconnect - this will delete the bot and remove the imc2 connection to the channel. /disconnect - this clear the imc2 connection to the channel.
/remove - " /remove - "
/list - show all imc2<->evennia mappings /list - show all imc2<->evennia mappings
Example: Example:
@imc2chan myimcchan = server02.mudbytes.net 9000 ievennia Gjds8372 LAKdf84e @imc2chan myimcchan = ievennia
Connect an existing evennia channel to an IMC2 network and channel. You must have registered with the network Connect an existing evennia channel to a channel on an IMC2
beforehand and obtained valid server- and client passwords. You will always connect using the name of your network. The network contact information is defined in settings and
mud, as defined by settings.SERVERNAME, so make sure this was the name you registered to the imc2 network. should already be accessed at this point. Use @imcchanlist to see
available IMC channels.
""" """
@ -953,10 +954,11 @@ class CmdIMC2Chan(MuxCommand):
# show all connections # show all connections
connections = ExternalChannelConnection.objects.filter(db_external_key__startswith='imc2_') connections = ExternalChannelConnection.objects.filter(db_external_key__startswith='imc2_')
if connections: if connections:
cols = [["Evennia channel"], ["IMC channel"]] cols = [["Evennia channel"], ["<->"], ["IMC channel"]]
for conn in connections: for conn in connections:
cols[0].append(conn.channel.key) cols[0].append(conn.channel.key)
cols[1].append(" ".join(conn.external_config.split('|')[:-3])) cols[1].append("")
cols[2].append(conn.external_config)
ftable = utils.format_table(cols) ftable = utils.format_table(cols)
string = "" string = ""
for ir, row in enumerate(ftable): for ir, row in enumerate(ftable):
@ -969,44 +971,34 @@ class CmdIMC2Chan(MuxCommand):
self.caller.msg("No connections found.") self.caller.msg("No connections found.")
return return
if not settings.IMC2_ENABLED:
string = """IMC2 is not enabled. You need to activate it in game/settings.py."""
self.caller.msg(string)
return
if not self.args or not self.rhs: if not self.args or not self.rhs:
string = "Usage: @imc2chan[/switches] <evennia_channel> = <imc2network> <port> <imc2channel> <client_pwd> <server_pwd>" string = "Usage: @imc2chan[/switches] <evennia_channel> = <imc2_channel>"
self.caller.msg(string)
return
channel = self.lhs
try:
imc2_network, imc2_port, imc2_channel, imc2_client_pwd, imc2_server_pwd = [part.strip() for part in self.rhs.split(None, 4)]
except Exception:
string = "Usage: @imc2chan[/switches] <evennia_channel> = <imc2network> <port> <imc2channel> <client_pwd> <server_pwd>"
string += "\nYou must supply a value in every position to define the IMC2 connnection.\nFor deletion, the tree last arguments (imc2channel and the two passwords) may be dummy values."
self.caller.msg(string) self.caller.msg(string)
return return
# get the name to use for connecting channel = self.lhs
mudname = settings.SERVERNAME imc2_channel = self.rhs
if 'disconnect' in self.switches or 'remove' in self.switches or 'delete' in self.switches: if 'disconnect' in self.switches or 'remove' in self.switches or 'delete' in self.switches:
# we don't search for channels before this since we want to clear the link
ok = imc2.delete_connection(imc2_network, imc2_port, mudname) # also if the channel no longer exists.
ok = imc2.delete_connection(channel, imc2_channel)
if not ok: if not ok:
self.caller.msg("IMC2 connection could not be removed, does it exist?") self.caller.msg("IMC2 connection could not be removed, does it exist?")
else: else:
self.caller.msg("IMC2 connection destroyed.") self.caller.msg("IMC2 connection destroyed.")
return return
# actually get the channel object
channel = find_channel(self.caller, channel) channel = find_channel(self.caller, channel)
if not channel: if not channel:
return return
ok = imc2.create_connection(channel, imc2_network, imc2_port, imc2_channel, mudname, imc2_client_pwd, imc2_server_pwd) ok = imc2.create_connection(channel, imc2_channel)
if not ok: if not ok:
self.caller.msg("This IMC2 connection already exists.") self.caller.msg("The connection %s <-> %s already exists." % (channel.key, imc2_channel))
return return
self.caller.msg("Connection created. Connecting to IMC2 server.") self.caller.msg("Created connection channel %s <-> IMC channel %s." % (channel.key, imc2_channel))
class CmdIMCInfo(MuxCommand): class CmdIMCInfo(MuxCommand):
@ -1025,7 +1017,6 @@ class CmdIMCInfo(MuxCommand):
whois - as @imcwhois (requires an additional argument) whois - as @imcwhois (requires an additional argument)
update - force an update of all lists update - force an update of all lists
Shows lists of games or channels on the IMC2 network. Shows lists of games or channels on the IMC2 network.
""" """
@ -1046,21 +1037,15 @@ class CmdIMCInfo(MuxCommand):
# update the lists # update the lists
import time import time
from src.comms.imc2lib import imc2_packets as pck from src.comms.imc2lib import imc2_packets as pck
from src.comms.imc2 import IMC2_MUDLIST, IMC2_CHANLIST, IMC2_CONNECTIONS from src.comms.imc2 import IMC2_MUDLIST, IMC2_CHANLIST, IMC2_CLIENT
# update connected muds # update connected muds
for conn in IMC2_CONNECTIONS: IMC2_CLIENT.send_packet(pck.IMC2PacketKeepAliveRequest())
conn.send_packet(pck.IMC2PacketKeepAliveRequest())
# prune inactive muds # prune inactive muds
for name, mudinfo in IMC2_MUDLIST.mud_list.items(): for name, mudinfo in IMC2_MUDLIST.mud_list.items():
if time.time() - mudinfo.last_updated > 3599: if time.time() - mudinfo.last_updated > 3599:
del IMC2_MUDLIST.mud_list[name] del IMC2_MUDLIST.mud_list[name]
# update channel list # update channel list
checked_networks = [] IMC2_CLIENT.send_packet(pck.IMC2PacketIceRefresh())
for conn in IMC2_CONNECTIONS:
network = conn.factory.network
if not network in checked_networks:
conn.send_packet(pck.IMC2PacketIceRefresh())
checked_networks.append(network)
self.caller.msg("IMC2 lists were re-synced.") self.caller.msg("IMC2 lists were re-synced.")
elif "games" in self.switches or "muds" in self.switches or self.cmdstring == "@imclist": elif "games" in self.switches or "muds" in self.switches or self.cmdstring == "@imclist":
@ -1094,19 +1079,18 @@ class CmdIMCInfo(MuxCommand):
if not self.args: if not self.args:
self.caller.msg("Usage: @imcwhois <playername>") self.caller.msg("Usage: @imcwhois <playername>")
return return
from src.comms.imc2 import IMC2_CONNECTIONS from src.comms.imc2 import IMC2_CLIENT
self.caller.msg("Sending IMC whois request. If you receive no response, no matches were found.") self.caller.msg("Sending IMC whois request. If you receive no response, no matches were found.")
for comm in IMC2_CONNECTIONS: IMC2_CLIENT.msg_imc2(None, from_obj=self.caller.player, packet_type="imcwhois", data={"target":self.args})
comm.msg_imc2(None, from_obj=self.caller.player, packet_type="imcwhois", data={"target":self.args})
elif not self.switches or "channels" in self.switches or self.cmdstring == "@imcchanlist": elif not self.switches or "channels" in self.switches or self.cmdstring == "@imcchanlist":
# show channels # show channels
from src.comms.imc2 import IMC2_CHANLIST, IMC2_CONNECTIONS from src.comms.imc2 import IMC2_CHANLIST, IMC2_CLIENT
channels = IMC2_CHANLIST.get_channel_list() channels = IMC2_CHANLIST.get_channel_list()
string = "" string = ""
nchans = 0 nchans = 0
string += "\n {GChannels on %s:{n" % (", ".join(conn.factory.network for conn in IMC2_CONNECTIONS)) string += "\n {GChannels on %s:{n" % IMC2_CLIENT.factory.network
cols = [["Full name"], ["Name"], ["Owner"], ["Perm"], ["Policy"]] cols = [["Full name"], ["Name"], ["Owner"], ["Perm"], ["Policy"]]
for channel in channels: for channel in channels:
nchans += 1 nchans += 1
@ -1155,7 +1139,7 @@ class CmdIMCTell(MuxCommand):
self.caller.msg(string) self.caller.msg(string)
return return
from src.comms.imc2 import IMC2_CONNECTIONS from src.comms.imc2 import IMC2_CLIENT
if not self.args or not '@' in self.lhs or not self.rhs: if not self.args or not '@' in self.lhs or not self.rhs:
string = "Usage: imctell User@Mud = <msg>" string = "Usage: imctell User@Mud = <msg>"
@ -1165,8 +1149,7 @@ class CmdIMCTell(MuxCommand):
message = self.rhs.strip() message = self.rhs.strip()
data = {"target":target, "destination":destination} data = {"target":target, "destination":destination}
for comm in IMC2_CONNECTIONS: # send to imc2
# we don't know which connection we aim for, so we send to all. IMC2_CLIENT.msg_imc2(message, from_obj=self.caller.player, packet_type="imctell", data=data)
comm.msg_imc2(message, from_obj=self.caller.player, packet_type="imctell", data=data)
self.caller.msg("You paged {c%s@%s{n (over IMC): '%s'." % (target, destination, message)) self.caller.msg("You paged {c%s@%s{n (over IMC): '%s'." % (target, destination, message))

View file

@ -16,11 +16,17 @@ from src.comms.imc2lib import imc2_packets as pck
from src.comms.imc2lib.imc2_trackers import IMC2MudList, IMC2ChanList from src.comms.imc2lib.imc2_trackers import IMC2MudList, IMC2ChanList
from src.comms.imc2lib.imc2_listeners import handle_whois_reply from src.comms.imc2lib.imc2_listeners import handle_whois_reply
# IMC2 network setup
IMC2_MUDNAME = settings.SERVERNAME
IMC2_NETWORK = settings.IMC2_NETWORK
IMC2_PORT = settings.IMC2_PORT
IMC2_CLIENT_PWD = settings.IMC2_CLIENT_PWD
IMC2_SERVER_PWD = settings.IMC2_SERVER_PWD
# channel to send info to # channel to send info to
INFOCHANNEL = Channel.objects.channel_search(settings.CHANNEL_MUDINFO[0]) INFOCHANNEL = Channel.objects.channel_search(settings.CHANNEL_MUDINFO[0])
# all linked channel connections # all linked channel connections
IMC2_CONNECTIONS = [] IMC2_CLIENT = None
# IMC2 debug mode # IMC2 debug mode
IMC2_DEBUG = False IMC2_DEBUG = False
# Use this instance to keep track of the other games on the network. # Use this instance to keep track of the other games on the network.
@ -58,11 +64,10 @@ class Send_IsAlive(Script):
self.desc = "Send an IMC2 is-alive packet" self.desc = "Send an IMC2 is-alive packet"
self.persistent = True self.persistent = True
def at_repeat(self): def at_repeat(self):
for channel in IMC2_CONNECTIONS: IMC2_CLIENT.send_packet(pck.IMC2PacketIsAlive())
channel.send_packet(pck.IMC2PacketIsAlive())
def is_valid(self): def is_valid(self):
"Is only valid as long as there are channels to update" "Is only valid as long as there are channels to update"
return any(service for service in SESSIONS.server.services if service.name.startswith("IMC2:")) return any(service for service in SESSIONS.server.services if service.name.startswith("imc2_"))
class Send_Keepalive_Request(Script): class Send_Keepalive_Request(Script):
""" """
@ -75,11 +80,10 @@ class Send_Keepalive_Request(Script):
self.desc = "Send an IMC2 keepalive-request packet" self.desc = "Send an IMC2 keepalive-request packet"
self.persistent = True self.persistent = True
def at_repeat(self): def at_repeat(self):
for channel in IMC2_CONNECTIONS: IMC2_CLIENT.channel.send_packet(pck.IMC2PacketKeepAliveRequest())
channel.send_packet(pck.IMC2PacketKeepAliveRequest())
def is_valid(self): def is_valid(self):
"Is only valid as long as there are channels to update" "Is only valid as long as there are channels to update"
return any(service for service in SESSIONS.server.services if service.name.startswith("IMC2:")) return any(service for service in SESSIONS.server.services if service.name.startswith("imc2_"))
class Prune_Inactive_Muds(Script): class Prune_Inactive_Muds(Script):
""" """
@ -99,7 +103,7 @@ class Prune_Inactive_Muds(Script):
del IMC2_MUDLIST.mud_list[name] del IMC2_MUDLIST.mud_list[name]
def is_valid(self): def is_valid(self):
"Is only valid as long as there are channels to update" "Is only valid as long as there are channels to update"
return any(service for service in SESSIONS.server.services if service.name.startswith("IMC2:")) return any(service for service in SESSIONS.server.services if service.name.startswith("imc2_"))
class Sync_Server_Channel_List(Script): class Sync_Server_Channel_List(Script):
""" """
@ -115,13 +119,12 @@ class Sync_Server_Channel_List(Script):
self.persistent = True self.persistent = True
def at_repeat(self): def at_repeat(self):
checked_networks = [] checked_networks = []
for channel in self.IMC2_CONNECTIONS: network = IMC2_CLIENT.factory.network
network = channel.factory.network
if not network in checked_networks: if not network in checked_networks:
channel.send_packet(pkg.IMC2PacketIceRefresh()) channel.send_packet(pkg.IMC2PacketIceRefresh())
checked_networks.append(network) checked_networks.append(network)
def is_valid(self): def is_valid(self):
return any(service for service in SESSIONS.server.services if service.name.startswith("IMC2:")) return any(service for service in SESSIONS.server.services if service.name.startswith("imc2_"))
# #
# IMC2 protocol # IMC2 protocol
# #
@ -132,8 +135,8 @@ class IMC2Protocol(telnet.StatefulTelnetProtocol):
authentication, and all necessary packets. authentication, and all necessary packets.
""" """
def __init__(self): def __init__(self):
global IMC2_CONNECTIONS global IMC2_CLIENT
IMC2_CONNECTIONS.append(self) IMC2_CLIENT = self
self.is_authenticated = False self.is_authenticated = False
self.auth_type = None self.auth_type = None
self.server_name = None self.server_name = None
@ -146,6 +149,7 @@ class IMC2Protocol(telnet.StatefulTelnetProtocol):
Triggered after connecting to the IMC2 network. Triggered after connecting to the IMC2 network.
""" """
self.auth_type = "plaintext" self.auth_type = "plaintext"
if IMC2_DEBUG:
logger.log_infomsg("IMC2: Connected to network server.") logger.log_infomsg("IMC2: Connected to network server.")
logger.log_infomsg("IMC2: Sending authentication packet.") logger.log_infomsg("IMC2: Sending authentication packet.")
self.send_packet(pck.IMC2PacketAuthPlaintext()) self.send_packet(pck.IMC2PacketAuthPlaintext())
@ -155,7 +159,12 @@ class IMC2Protocol(telnet.StatefulTelnetProtocol):
This is executed when the connection is lost for This is executed when the connection is lost for
whatever reason. whatever reason.
""" """
pass # we don't need to do anything, it's cleaned up automatically. try:
service = SESSIONS.server.services.getServiceNamed("imc2_%s:%s(%s)" % (IMC2_NETWORK, IMC2_PORT, IMC2_MUDNAME))
except Exception:
return
if service.running:
service.stopService()
def send_packet(self, packet): def send_packet(self, packet):
""" """
@ -206,7 +215,7 @@ class IMC2Protocol(telnet.StatefulTelnetProtocol):
self.sequence = int(time()) self.sequence = int(time())
# Log to stdout and notify over MUDInfo. # Log to stdout and notify over MUDInfo.
auth_message = "Successfully authenticated to the '%s' network." % self.network_name auth_message = "Successfully authenticated to the '%s' network." % self.factory.network
logger.log_infomsg('IMC2: %s' % auth_message) logger.log_infomsg('IMC2: %s' % auth_message)
msg_info(auth_message) msg_info(auth_message)
@ -228,23 +237,18 @@ class IMC2Protocol(telnet.StatefulTelnetProtocol):
# If the packet lacks the 'echo' key, don't bother with it. # If the packet lacks the 'echo' key, don't bother with it.
if not conn_name or not packet.optional_data.get('echo', None): if not conn_name or not packet.optional_data.get('echo', None):
return return
chan_name = conn_name.split(':', 1)[1] imc2_channel = conn_name.split(':', 1)[1]
key = "imc2_%s" % conn_name # Look for matching IMC2 channel maps mapping to this imc2 channel.
# Look for matching IMC2 channel maps. conns = ExternalChannelConnection.objects.filter(db_external_key__startswith="imc2_")
conns = ExternalChannelConnection.objects.filter(db_external_key=self.factory.key) conns = [conn for conn in conns if imc2_channel in conn.db_external_config.split(",")]
if not conns: if not conns:
# we are not listening to this imc2 channel.
return return
# get channel subscriptions # Format the message to send to local channel(s).
chansubs = conns[0].db_external_config.split("|")[2].split(",") for conn in conns:
if not chan_name in chansubs: message = '[%s] %s@%s: %s' % (conn.channel.key, packet.sender, packet.origin, packet.optional_data.get('text'))
# we are not listening to this channel.
return
# Format the message to send to local channel.
message = '[%s] %s@%s: %s' % (self.factory.evennia_channel, packet.sender, packet.origin, packet.optional_data.get('text'))
for conn in (conn for conn in conns if conn.channel):
conn.to_channel(message) conn.to_channel(message)
def _format_tell(self, packet): def _format_tell(self, packet):
@ -308,9 +312,6 @@ class IMC2Protocol(telnet.StatefulTelnetProtocol):
""" """
Called by Evennia to send a message through the imc2 connection Called by Evennia to send a message through the imc2 connection
""" """
conns = ExternalChannelConnection.objects.filter(db_external_key=self.factory.key)
if not conns:
return
if from_obj: if from_obj:
if hasattr(from_obj, 'key'): if hasattr(from_obj, 'key'):
from_name = from_obj.key from_name = from_obj.key
@ -320,8 +321,17 @@ class IMC2Protocol(telnet.StatefulTelnetProtocol):
from_name = self.factory.mudname from_name = self.factory.mudname
if packet_type == "imcbroadcast": if packet_type == "imcbroadcast":
if type(data) == dict:
conns = ExternalChannelConnection.objects.filter(db_external_key__startswith="imc2_",
db_channel=data.get("channel", "Unknown"))
if not conns:
return
# we remove the extra channel info since imc2 supplies this anyway
if ":" in message:
header, message = [part.strip() for part in message.split(":", 1)]
# send the packet # send the packet
self.send_packet(pck.IMC2PacketIceMsgBroadcasted(self.factory.servername, self.factory.channel[0], imc2_channel = conns[0].db_external_config.split(',')[0] # only send to the first channel
self.send_packet(pck.IMC2PacketIceMsgBroadcasted(self.factory.servername, imc2_channel,
from_name, message)) from_name, message))
elif packet_type == "imctell": elif packet_type == "imctell":
# send a tell # send a tell
@ -338,24 +348,21 @@ class IMC2Protocol(telnet.StatefulTelnetProtocol):
class IMC2Factory(protocol.ClientFactory): class IMC2Factory(protocol.ClientFactory):
""" """
Creates instances of the IMC2Protocol. Should really only ever create one Creates instances of the IMC2Protocol. Should really only ever
in our particular instance. Tied in via src/server.py. need to create one connection. Tied in via src/server.py.
""" """
protocol = IMC2Protocol protocol = IMC2Protocol
def __init__(self, key, channel, network, port, mudname, client_pwd, server_pwd, evennia_channel): def __init__(self, network, port, mudname, client_pwd, server_pwd):
self.key = key self.pretty_key = "%s:%s(%s)" % (network, port, mudname)
self.mudname = mudname
self.channel = channel # this is a list!
self.pretty_key = "%s:%s/%s (%s)" % (network, port, channel, mudname)
self.network = network self.network = network
sname, host = network.split(".", 1) sname, host = network.split(".", 1)
self.servername = sname.strip() self.servername = sname.strip()
self.port = port
self.mudname = mudname
self.protocol_version = '2' self.protocol_version = '2'
self.client_pwd = client_pwd self.client_pwd = client_pwd
self.server_pwd = server_pwd self.server_pwd = server_pwd
self.evennia_channel = evennia_channel
def clientConnectionFailed(self, connector, reason): def clientConnectionFailed(self, connector, reason):
message = 'Connection failed: %s' % reason.getErrorMessage() message = 'Connection failed: %s' % reason.getErrorMessage()
@ -368,12 +375,11 @@ class IMC2Factory(protocol.ClientFactory):
logger.log_errmsg('IMC2: %s' % message) logger.log_errmsg('IMC2: %s' % message)
def build_connection_key(imc2_network, imc2_port, imc2_mudname): def build_connection_key(channel, imc2_channel):
"Build an id hash for the connection" "Build an id hash for the connection"
return "imc2_%s:%s(%s)<>Evennia" % (imc2_network, imc2_port, imc2_mudname) if hasattr(channel, "key"):
channel = channel.key
def build_service_key(key): return "imc2_%s:%s(%s)%s<>%s" % (IMC2_NETWORK, IMC2_PORT, IMC2_MUDNAME, imc2_channel, channel)
return "IMC2:%s" % key
def start_scripts(validate=False): def start_scripts(validate=False):
""" """
@ -393,97 +399,69 @@ def start_scripts(validate=False):
if not search.scripts("IMC2_Sync_Server_Channel_List"): if not search.scripts("IMC2_Sync_Server_Channel_List"):
create.create_script(Sync_Server_Channel_List) create.create_script(Sync_Server_Channel_List)
def create_connection(channel, imc2_network, imc2_port, imc2_channel, imc2_mudname, imc2_client_pwd, imc2_server_pwd): def create_connection(channel, imc2_channel):
""" """
This will create a new IMC2<->channel connection. This will create a new IMC2<->channel connection.
""" """
key = build_connection_key(imc2_network, imc2_port, imc2_mudname)
if not type(channel) == Channel: if not type(channel) == Channel:
new_channel = Channel.objects.filter(db_key=channel) new_channel = Channel.objects.filter(db_key=channel)
if not new_channel: if not new_channel:
logger.log_errmsg("Cannot attach IMC2<->Evennia: Evennia Channel '%s' not found" % channel) logger.log_errmsg("Cannot attach IMC2<->Evennia: Evennia Channel '%s' not found" % channel)
return False return False
channel = new_channel[0] channel = new_channel[0]
key = build_connection_key(channel, imc2_channel)
old_conns = ExternalChannelConnection.objects.filter(db_external_key=key) old_conns = ExternalChannelConnection.objects.filter(db_external_key=key)
if old_conns: if old_conns:
# this evennia channel is already connected to imc. Check if imc2_channel is different.
# connection already exists. We try to only connect a new channel # connection already exists. We try to only connect a new channel
old_config = old_conns[0].db_external_config.split('|',5) old_config = old_conns[0].db_external_config.split(",")
old_chan_subs = old_config[2].split(',') if imc2_channel in old_config:
if imc2_channel in old_chan_subs:
return False # we already listen to this channel return False # we already listen to this channel
else: else:
# We add thew new channel to the connection instead of creating a new connection. # We add a new imc2_channel to listen to
old_chan_subs.append(imc2_channel) old_config.append(imc2_channel)
old_chan_subs = ",".join(old_chan_subs) old_conns[0].db_external_config = ",".join(old_config)
old_config[2] = old_chan_subs # add a channel subscription to old config
old_conns[0].db_external_config = "|".join(old_config)
old_conns[0].save() old_conns[0].save()
return True return True
else:
# new connection # no old connection found; create a new one.
config = "%s|%s|%s|%s|%s|%s" % (imc2_network, imc2_port, imc2_channel, imc2_mudname, imc2_client_pwd, imc2_server_pwd) config = imc2_channel
# how the channel will be able to contact this protocol # how the evennia channel will be able to contact this protocol in reverse
send_code = "from src.comms.imc2 import IMC2_CONNECTIONS\n" send_code = "from src.comms.imc2 import IMC2_CLIENT\n"
send_code += "matched_imc2s = [imc2 for imc2 in IMC2_CONNECTIONS if imc2.factory.key == '%s']\n" % key send_code += "data={'channel':from_channel}\n"
send_code += "[imc2.msg_imc2(message, from_obj=from_obj) for imc2 in matched_imc2s]\n" send_code += "IMC2_CLIENT.msg_imc2(message, from_obj=from_obj, data=data)\n"
conn = ExternalChannelConnection(db_channel=channel, db_external_key=key, db_external_send_code=send_code, conn = ExternalChannelConnection(db_channel=channel, db_external_key=key, db_external_send_code=send_code,
db_external_config=config) db_external_config=config)
conn.save() conn.save()
# connect
connect_to_imc2(conn)
# start scripts (if needed)
start_scripts()
return True return True
def delete_connection(imc2_network, imc2_port, mudname): def delete_connection(channel, imc2_channel):
"Destroy a connection" "Destroy a connection"
if hasattr(channel, "key"):
channel = channel.key
key = build_connection_key(channel, imc2_channel)
key = build_connection_key(imc2_network, imc2_port, mudname)
service_key = build_service_key(key)
try: try:
conn = ExternalChannelConnection.objects.get(db_external_key=key) conn = ExternalChannelConnection.objects.get(db_external_key=key)
except Exception: except ExternalChannelConnection.DoesNotExist:
return False return False
conn.delete() conn.delete()
try:
service = SESSIONS.server.services.getServiceNamed(service_key)
except Exception:
return True
if service.running:
SESSIONS.server.services.removeService(service)
# validate scripts
start_scripts(validate=True)
return True return True
def connect_to_imc2(connection): def connect_to_imc2():
"Create the imc instance and connect to the IMC2 network and channel." "Create the imc instance and connect to the IMC2 network."
# get config
key = utils.to_str(connection.external_key)
service_key = build_service_key(key)
imc2_network, imc2_port, imc2_channel, imc2_mudname, imc2_client_pwd, imc2_server_pwd = \
[utils.to_str(conf) for conf in connection.external_config.split('|')]
imc2_channel = imc2_channel.split(",")
# connect # connect
imc = internet.TCPClient(imc2_network, int(imc2_port), IMC2Factory(key, imc2_channel, imc2_network, imc2_port, imc2_mudname, imc = internet.TCPClient(IMC2_NETWORK, int(IMC2_PORT), IMC2Factory(IMC2_NETWORK, IMC2_PORT, IMC2_MUDNAME,
imc2_client_pwd, imc2_server_pwd, connection.channel.key)) IMC2_CLIENT_PWD, IMC2_SERVER_PWD))
imc.setName(service_key) imc.setName("imc2_%s:%s(%s)" % (IMC2_NETWORK, IMC2_PORT, IMC2_MUDNAME))
SESSIONS.server.services.addService(imc) SESSIONS.server.services.addService(imc)
def connect_all(): def connect_all():
""" """
Activate all imc2 bots. Activates the imc2 system. Called by the server if IMC2_ENABLED=True.
Returns a list of (key, TCPClient) tuples for server to properly set services.
""" """
connections = ExternalChannelConnection.objects.filter(db_external_key__startswith='imc2_') connect_to_imc2()
for connection in connections:
connect_to_imc2(connection)
if connections:
start_scripts() start_scripts()

View file

@ -561,7 +561,7 @@ class Channel(SharedMemoryModel):
conn.player.msg(msg, from_obj) conn.player.msg(msg, from_obj)
except AttributeError: except AttributeError:
try: try:
conn.to_external(msg, from_obj) conn.to_external(msg, from_obj, from_channel=self)
except Exception: except Exception:
logger.log_trace("Cannot send msg to connection '%s'" % conn) logger.log_trace("Cannot send msg to connection '%s'" % conn)
return True return True
@ -780,7 +780,7 @@ class ExternalChannelConnection(SharedMemoryModel):
from_obj = self.external_key from_obj = self.external_key
self.channel.msg(message, from_obj=from_obj) self.channel.msg(message, from_obj=from_obj)
def to_external(self, message, from_obj=None): def to_external(self, message, from_obj=None, from_channel=None):
"Send channel -> external" "Send channel -> external"
# make sure we are not echoing back our own message to ourselves # make sure we are not echoing back our own message to ourselves
@ -792,7 +792,7 @@ class ExternalChannelConnection(SharedMemoryModel):
# we execute the code snippet that should make it possible for the # we execute the code snippet that should make it possible for the
# connection to contact the protocol correctly (as set by the protocol). # connection to contact the protocol correctly (as set by the protocol).
# Note that the code block has access to the variables here, such # Note that the code block has access to the variables here, such
# as message and from_obj. # as message, from_obj and from_channel.
exec(to_str(self.external_send_code)) exec(to_str(self.external_send_code))
except Exception: except Exception:
logger.log_trace("Channel %s could not send to External %s" % (self.channel, self.external_key)) logger.log_trace("Channel %s could not send to External %s" % (self.channel, self.external_key))

View file

@ -281,13 +281,16 @@ IRC_ENABLED = False
# use it, go to http://www.mudbytes.net/imc2-intermud-join-network. # use it, go to http://www.mudbytes.net/imc2-intermud-join-network.
# Choose 'Other unsupported IMC2 version' from the choices and and # Choose 'Other unsupported IMC2 version' from the choices and and
# enter your information there. You should enter the same 'short mud # enter your information there. You should enter the same 'short mud
# name' as your SERVERNAME above. When enabled, the command @imc2chan # name' as your SERVERNAME above, then choose imc network server as
# becomes available in-game. It will take 'client password' and # well as client/server passwords same as below. When enabled, the
# 'server password' as chosen when registering on mudbytes. The # command @imc2chan becomes available in-game and allows you to
# Evennia discussion channel 'ievennia' is on # connect Evennia channels to IMC channels on the network. The Evennia
# server02.mudbytes.net:9000. # discussion channel 'ievennia' is on server01.mudbytes.net:5000.
IMC2_ENABLED = False IMC2_ENABLED = False
IMC2_NETWORK = "server01.mudbytes.net"
IMC2_PORT = 5000
IMC2_CLIENT_PWD = ""
IMC2_SERVER_PWD = ""
################################################### ###################################################
# Config for Django web features # Config for Django web features