mirror of
https://github.com/evennia/evennia.git
synced 2026-03-30 20:47:17 +02:00
IMC (inter-mud-communication) is working again. Evennia's implementation connects an existing Evennia channel to an IMC2 network/channel seamlessly. One can listen to more than one IMC2 channel, but only send to one IMC channel, as defined when setting up the connection. One can list imc channels and muds connected to the network. We have only limited support for imctell at this point: It works for IMC users to send imc-tells to users on Evennia, but seemingly not the other way around. Evennias imctell function at least doesn't seem to properly send tells to my Talon IMC user.
This commit is contained in:
parent
935bef1f43
commit
0ea95631bf
6 changed files with 247 additions and 149 deletions
|
|
@ -91,6 +91,7 @@ class DefaultCmdSet(CmdSet):
|
|||
self.add(comms.CmdIRC2Chan())
|
||||
self.add(comms.CmdIMC2Chan())
|
||||
self.add(comms.CmdIMCInfo())
|
||||
self.add(comms.CmdIMCTell())
|
||||
|
||||
# Batchprocessor commands
|
||||
self.add(batchprocess.CmdBatchCommands())
|
||||
|
|
|
|||
|
|
@ -856,6 +856,11 @@ class CmdIRC2Chan(MuxCommand):
|
|||
def func(self):
|
||||
"Setup the irc-channel mapping"
|
||||
|
||||
if not settings.IRC_ENABLED:
|
||||
string = """IRC is not enabled. You need to activate it in game/settings.py."""
|
||||
self.caller.msg(string)
|
||||
return
|
||||
|
||||
if 'list' in self.switches:
|
||||
# show all connections
|
||||
connections = ExternalChannelConnection.objects.filter(db_external_key__startswith='irc_')
|
||||
|
|
@ -876,10 +881,6 @@ class CmdIRC2Chan(MuxCommand):
|
|||
self.caller.msg("No connections found.")
|
||||
return
|
||||
|
||||
if not settings.IRC_ENABLED:
|
||||
string = """IRC 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:
|
||||
string = "Usage: @irc2chan[/switches] <evennia_channel> = <ircnetwork> <port> <#irchannel> <botname>"
|
||||
self.caller.msg(string)
|
||||
|
|
@ -943,6 +944,11 @@ class CmdIMC2Chan(MuxCommand):
|
|||
def func(self):
|
||||
"Setup the imc-channel mapping"
|
||||
|
||||
if not settings.IMC2_ENABLED:
|
||||
string = """IMC is not enabled. You need to activate it in game/settings.py."""
|
||||
self.caller.msg(string)
|
||||
return
|
||||
|
||||
if 'list' in self.switches:
|
||||
# show all connections
|
||||
connections = ExternalChannelConnection.objects.filter(db_external_key__startswith='imc2_')
|
||||
|
|
@ -975,7 +981,8 @@ class CmdIMC2Chan(MuxCommand):
|
|||
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 = "IMC2 connnection definition '%s' is not valid." % self.rhs
|
||||
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)
|
||||
return
|
||||
|
||||
|
|
@ -987,7 +994,7 @@ class CmdIMC2Chan(MuxCommand):
|
|||
if chanmatch:
|
||||
channel = chanmatch.key
|
||||
|
||||
ok = imc2.delete_connection(channel, imc2_network, imc2_port, imc2_channel, mudname)
|
||||
ok = imc2.delete_connection(channel, imc2_network, imc2_port, mudname)
|
||||
if not ok:
|
||||
self.caller.msg("IMC2 connection could not be removed, does it exist?")
|
||||
else:
|
||||
|
|
@ -1014,8 +1021,8 @@ class CmdIMCInfo(MuxCommand):
|
|||
@imclist - list connected muds
|
||||
|
||||
Switches:
|
||||
channels - as imcchanlist (default)
|
||||
games - as imclist
|
||||
channels - as @imcchanlist (default)
|
||||
games or muds - as @imclist
|
||||
update - force an update of all lists
|
||||
|
||||
|
||||
|
|
@ -1030,28 +1037,33 @@ class CmdIMCInfo(MuxCommand):
|
|||
def func(self):
|
||||
"Run the command"
|
||||
|
||||
if not settings.IMC2_ENABLED:
|
||||
string = """IMC is not enabled. You need to activate it in game/settings.py."""
|
||||
self.caller.msg(string)
|
||||
return
|
||||
|
||||
if "update" in self.switches:
|
||||
# update the lists
|
||||
import time
|
||||
from src.comms.imc2lib import imc2_packets as pck
|
||||
from src.comms.imc2 import IMC2_MUDLIST, IMC2_CHANLIST, IMC2_CHANNELS
|
||||
from src.comms.imc2 import IMC2_MUDLIST, IMC2_CHANLIST, IMC2_CONNECTIONS
|
||||
# update connected muds
|
||||
for chan in IMC2_CHANNELS:
|
||||
chan.send_packet(pck.IMC2PacketKeepAliveRequest())
|
||||
for conn in IMC2_CONNECTIONS:
|
||||
conn.send_packet(pck.IMC2PacketKeepAliveRequest())
|
||||
# prune inactive muds
|
||||
for name, mudinfo in IMC2_MUDLIST.mud_list.items():
|
||||
if time.time() - mudinfo.last_updated > 3599:
|
||||
del IMC2_MUDLIST.mud_list[name]
|
||||
# update channel list
|
||||
checked_networks = []
|
||||
for channel in IMC2_CHANNELS:
|
||||
network = channel.factory.network
|
||||
for conn in IMC2_CONNECTIONS:
|
||||
network = conn.factory.network
|
||||
if not network in checked_networks:
|
||||
channel.send_packet(pck.IMC2PacketIceRefresh())
|
||||
conn.send_packet(pck.IMC2PacketIceRefresh())
|
||||
checked_networks.append(network)
|
||||
self.caller.msg("IMC2 lists were re-synced.")
|
||||
|
||||
elif "games" in self.switches or self.cmdstring == "@imclist":
|
||||
elif "games" in self.switches or "muds" in self.switches or self.cmdstring == "@imclist":
|
||||
# list muds
|
||||
from src.comms.imc2 import IMC2_MUDLIST
|
||||
|
||||
|
|
@ -1078,12 +1090,12 @@ class CmdIMCInfo(MuxCommand):
|
|||
self.caller.msg(string)
|
||||
elif not self.switches or "channels" in self.switches or self.cmdstring == "@imcchanlist":
|
||||
# show channels
|
||||
from src.comms.imc2 import IMC2_CHANLIST, IMC2_CHANNELS
|
||||
from src.comms.imc2 import IMC2_CHANLIST, IMC2_CONNECTIONS
|
||||
|
||||
channels = IMC2_CHANLIST.get_channel_list()
|
||||
string = ""
|
||||
nchans = 0
|
||||
string += "\n {GChannels on %s:{n" % (", ".join(conn.factory.network for conn in IMC2_CHANNELS))
|
||||
string += "\n {GChannels on %s:{n" % (", ".join(conn.factory.network for conn in IMC2_CONNECTIONS))
|
||||
cols = [["Full name"], ["Name"], ["Owner"], ["Perm"], ["Policy"]]
|
||||
for channel in channels:
|
||||
nchans += 1
|
||||
|
|
@ -1104,4 +1116,46 @@ class CmdIMCInfo(MuxCommand):
|
|||
else:
|
||||
# no valid inputs
|
||||
string = "Usage: imcinfo|imcchanlist|imclist"
|
||||
self.caller(string)
|
||||
self.caller.msg(string)
|
||||
|
||||
# unclear if this is working ...
|
||||
class CmdIMCTell(MuxCommand):
|
||||
"""
|
||||
imctell - send a page to a remote IMC player
|
||||
|
||||
Usage:
|
||||
imctell User@MUD = <msg>
|
||||
imcpage "
|
||||
|
||||
Sends a page to a user on a remote MUD, connected
|
||||
over IMC2.
|
||||
"""
|
||||
|
||||
key = "imctell"
|
||||
aliases = ["imcpage", "imc2tell", "imc2page"]
|
||||
locks = "cmd: serversetting(IMC2_ENABLED) or perm(Immortals)"
|
||||
help_category = "Comms"
|
||||
|
||||
def func(self):
|
||||
"Send tell across IMC"
|
||||
|
||||
if not settings.IMC2_ENABLED:
|
||||
string = """IMC is not enabled. You need to activate it in game/settings.py."""
|
||||
self.caller.msg(string)
|
||||
return
|
||||
|
||||
from src.comms.imc2 import IMC2_CONNECTIONS
|
||||
|
||||
if not self.args or not '@' in self.lhs or not self.rhs:
|
||||
string = "Usage: imctell User@Mud = <msg>"
|
||||
self.caller.msg(string)
|
||||
return
|
||||
target, destination = self.lhs.split("@", 1)
|
||||
message = self.rhs.strip()
|
||||
data = {"target":target, "destination":destination}
|
||||
|
||||
for comm in IMC2_CONNECTIONS:
|
||||
# we don't know which connection we aim for, so we send to all.
|
||||
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))
|
||||
|
|
|
|||
|
|
@ -31,83 +31,83 @@ def cmd_imcwhois(command):
|
|||
imc2_conn.IMC2_PROTOCOL_INSTANCE.send_packet(packet)
|
||||
GLOBAL_CMD_TABLE.add_command("imcwhois", cmd_imcwhois, help_category="Comms")
|
||||
|
||||
def cmd_imcansi(command):
|
||||
"""
|
||||
imcansi
|
||||
# def cmd_imcansi(command):
|
||||
# """
|
||||
# imcansi
|
||||
|
||||
Usage:
|
||||
imcansi <string>
|
||||
# Usage:
|
||||
# imcansi <string>
|
||||
|
||||
Test IMC ANSI conversion.
|
||||
"""
|
||||
source_object = command.source_object
|
||||
if not command.command_argument:
|
||||
source_object.emit_to("You must provide a string to convert.")
|
||||
return
|
||||
else:
|
||||
retval = parse_ansi(command.command_argument, parser=IMCANSIParser())
|
||||
source_object.emit_to(retval)
|
||||
GLOBAL_CMD_TABLE.add_command("imcansi", cmd_imcansi, help_category="Comms")
|
||||
# Test IMC ANSI conversion.
|
||||
# """
|
||||
# source_object = command.source_object
|
||||
# if not command.command_argument:
|
||||
# source_object.emit_to("You must provide a string to convert.")
|
||||
# return
|
||||
# else:
|
||||
# retval = parse_ansi(command.command_argument, parser=IMCANSIParser())
|
||||
# source_object.emit_to(retval)
|
||||
# GLOBAL_CMD_TABLE.add_command("imcansi", cmd_imcansi, help_category="Comms")
|
||||
|
||||
def cmd_imcicerefresh(command):
|
||||
"""
|
||||
imcicerefresh
|
||||
# def cmd_imcicerefresh(command):
|
||||
# """
|
||||
# imcicerefresh
|
||||
|
||||
Usage:
|
||||
imcicerefresh
|
||||
# Usage:
|
||||
# imcicerefresh
|
||||
|
||||
IMC2: Semds an ice-refresh packet.
|
||||
"""
|
||||
source_object = command.source_object
|
||||
packet = IMC2PacketIceRefresh()
|
||||
imc2_conn.IMC2_PROTOCOL_INSTANCE.send_packet(packet)
|
||||
source_object.emit_to("Sent")
|
||||
GLOBAL_CMD_TABLE.add_command("imcicerefresh", cmd_imcicerefresh, help_category="Comms")
|
||||
# IMC2: Semds an ice-refresh packet.
|
||||
# """
|
||||
# source_object = command.source_object
|
||||
# packet = IMC2PacketIceRefresh()
|
||||
# imc2_conn.IMC2_PROTOCOL_INSTANCE.send_packet(packet)
|
||||
# source_object.emit_to("Sent")
|
||||
# GLOBAL_CMD_TABLE.add_command("imcicerefresh", cmd_imcicerefresh, help_category="Comms")
|
||||
|
||||
def cmd_imcchanlist(command):
|
||||
"""
|
||||
imcchanlist
|
||||
# def cmd_imcchanlist(command):
|
||||
# """
|
||||
# imcchanlist
|
||||
|
||||
Usage:
|
||||
imcchanlist
|
||||
# Usage:
|
||||
# imcchanlist
|
||||
|
||||
Shows the list of cached channels from the IMC2 Channel list.
|
||||
"""
|
||||
source_object = command.source_object
|
||||
# Shows the list of cached channels from the IMC2 Channel list.
|
||||
# """
|
||||
# source_object = command.source_object
|
||||
|
||||
retval = 'Channels on %s\n\r' % imc2_conn.IMC2_PROTOCOL_INSTANCE.network_name
|
||||
# retval = 'Channels on %s\n\r' % imc2_conn.IMC2_PROTOCOL_INSTANCE.network_name
|
||||
|
||||
retval += ' Full Name Name Owner Perm Policy\n\r'
|
||||
retval += ' --------- ---- ----- ---- ------\n\r'
|
||||
for channel in IMC2_CHANLIST.get_channel_list():
|
||||
retval += ' %-18s %-10s %-15s %-7s %s\n\r' % (channel.name,
|
||||
channel.localname,
|
||||
channel.owner,
|
||||
channel.level,
|
||||
channel.policy)
|
||||
retval += '%s channels found.' % len(IMC2_CHANLIST.chan_list)
|
||||
source_object.emit_to(retval)
|
||||
GLOBAL_CMD_TABLE.add_command("imcchanlist", cmd_imcchanlist, help_category="Comms")
|
||||
# retval += ' Full Name Name Owner Perm Policy\n\r'
|
||||
# retval += ' --------- ---- ----- ---- ------\n\r'
|
||||
# for channel in IMC2_CHANLIST.get_channel_list():
|
||||
# retval += ' %-18s %-10s %-15s %-7s %s\n\r' % (channel.name,
|
||||
# channel.localname,
|
||||
# channel.owner,
|
||||
# channel.level,
|
||||
# channel.policy)
|
||||
# retval += '%s channels found.' % len(IMC2_CHANLIST.chan_list)
|
||||
# source_object.emit_to(retval)
|
||||
# GLOBAL_CMD_TABLE.add_command("imcchanlist", cmd_imcchanlist, help_category="Comms")
|
||||
|
||||
def cmd_imclist(command):
|
||||
"""
|
||||
imclist
|
||||
# def cmd_imclist(command):
|
||||
# """
|
||||
# imclist
|
||||
|
||||
Usage:
|
||||
imclist
|
||||
# Usage:
|
||||
# imclist
|
||||
|
||||
Shows the list of cached games from the IMC2 Mud list.
|
||||
"""
|
||||
source_object = command.source_object
|
||||
# Shows the list of cached games from the IMC2 Mud list.
|
||||
# """
|
||||
# source_object = command.source_object
|
||||
|
||||
retval = 'Active MUDs on %s\n\r' % imc2_conn.IMC2_PROTOCOL_INSTANCE.network_name
|
||||
# retval = 'Active MUDs on %s\n\r' % imc2_conn.IMC2_PROTOCOL_INSTANCE.network_name
|
||||
|
||||
for mudinfo in IMC2_MUDLIST.get_mud_list():
|
||||
mudline = ' %-20s %s' % (mudinfo.name, mudinfo.versionid)
|
||||
retval += '%s\n\r' % mudline[:78]
|
||||
retval += '%s active MUDs found.' % len(IMC2_MUDLIST.mud_list)
|
||||
source_object.emit_to(retval)
|
||||
GLOBAL_CMD_TABLE.add_command("imclist", cmd_imclist, help_category="Comms")
|
||||
# for mudinfo in IMC2_MUDLIST.get_mud_list():
|
||||
# mudline = ' %-20s %s' % (mudinfo.name, mudinfo.versionid)
|
||||
# retval += '%s\n\r' % mudline[:78]
|
||||
# retval += '%s active MUDs found.' % len(IMC2_MUDLIST.mud_list)
|
||||
# source_object.emit_to(retval)
|
||||
# GLOBAL_CMD_TABLE.add_command("imclist", cmd_imclist, help_category="Comms")
|
||||
|
||||
# def cmd_imcstatus(command):
|
||||
# """
|
||||
|
|
|
|||
|
|
@ -19,10 +19,10 @@ from src.comms.imc2lib.imc2_listeners import handle_whois_reply
|
|||
|
||||
# channel to send info to
|
||||
INFOCHANNEL = Channel.objects.channel_search(settings.CHANNEL_MUDINFO[0])
|
||||
# all linked channel connection
|
||||
IMC2_CHANNELS = []
|
||||
# all linked channel connections
|
||||
IMC2_CONNECTIONS = []
|
||||
# IMC2 debug mode
|
||||
IMC2_DEBUG = True
|
||||
IMC2_DEBUG = False
|
||||
# Use this instance to keep track of the other games on the network.
|
||||
IMC2_MUDLIST = IMC2MudList()
|
||||
# Tracks the list of available channels on the network.
|
||||
|
|
@ -58,7 +58,7 @@ class Send_IsAlive(Script):
|
|||
self.desc = "Send an IMC2 is-alive packet"
|
||||
self.persistent = True
|
||||
def at_repeat(self):
|
||||
for channel in IMC2_CHANNELS:
|
||||
for channel in IMC2_CONNECTIONS:
|
||||
channel.send_packet(pck.IMC2PacketIsAlive())
|
||||
def is_valid(self):
|
||||
"Is only valid as long as there are channels to update"
|
||||
|
|
@ -75,7 +75,7 @@ class Send_Keepalive_Request(Script):
|
|||
self.desc = "Send an IMC2 keepalive-request packet"
|
||||
self.persistent = True
|
||||
def at_repeat(self):
|
||||
for channel in IMC2_CHANNELS:
|
||||
for channel in IMC2_CONNECTIONS:
|
||||
channel.send_packet(pck.IMC2PacketKeepAliveRequest())
|
||||
def is_valid(self):
|
||||
"Is only valid as long as there are channels to update"
|
||||
|
|
@ -115,7 +115,7 @@ class Sync_Server_Channel_List(Script):
|
|||
self.persistent = True
|
||||
def at_repeat(self):
|
||||
checked_networks = []
|
||||
for channel in self.IMC2_CHANNELS:
|
||||
for channel in self.IMC2_CONNECTIONS:
|
||||
network = channel.factory.network
|
||||
if not network in checked_networks:
|
||||
channel.send_packet(pkg.IMC2PacketIceRefresh())
|
||||
|
|
@ -132,8 +132,8 @@ class IMC2Protocol(telnet.StatefulTelnetProtocol):
|
|||
authentication, and all necessary packets.
|
||||
"""
|
||||
def __init__(self):
|
||||
global IMC2_CHANNELS
|
||||
IMC2_CHANNELS.append(self)
|
||||
global IMC2_CONNECTIONS
|
||||
IMC2_CONNECTIONS.append(self)
|
||||
self.is_authenticated = False
|
||||
self.auth_type = None
|
||||
self.server_name = None
|
||||
|
|
@ -159,11 +159,12 @@ class IMC2Protocol(telnet.StatefulTelnetProtocol):
|
|||
"""
|
||||
if self.sequence:
|
||||
# This gets incremented with every command.
|
||||
self.sequence += 1
|
||||
self.sequence += 1
|
||||
packet.imc2_protocol = self
|
||||
packet_str = utils.to_str(packet.assemble(self.factory.mudname, self.factory.client_pwd, self.factory.server_pwd))
|
||||
if IMC2_DEBUG:
|
||||
if IMC2_DEBUG and not (hasattr(packet, 'packet_type') and packet.packet_type == "is-alive"):
|
||||
logger.log_infomsg("IMC2: SENT> %s" % packet_str)
|
||||
logger.log_infomsg(str(packet))
|
||||
self.sendLine(packet_str)
|
||||
|
||||
def _parse_auth_response(self, line):
|
||||
|
|
@ -216,30 +217,33 @@ class IMC2Protocol(telnet.StatefulTelnetProtocol):
|
|||
(Message from IMC2 -> Evennia)
|
||||
"""
|
||||
conn_name = packet.optional_data.get('channel', None)
|
||||
|
||||
# If the packet lacks the 'echo' key, don't bother with it.
|
||||
has_echo = packet.optional_data.get('echo', None)
|
||||
if conn_name and has_echo:
|
||||
# The second half of this is the channel name: Server:Channel
|
||||
chan_name = conn_name.split(':', 1)[1]
|
||||
key = "imc2_%s" % conn_name
|
||||
# Look for matching IMC2 channel maps.
|
||||
conns = ExternalChannelConnection.objects.filter(db_external_key=self.factory.key)
|
||||
if not conns:
|
||||
return
|
||||
if not conn_name or not packet.optional_data.get('echo', None):
|
||||
return
|
||||
|
||||
chan_name = conn_name.split(':', 1)[1]
|
||||
if not chan_name in self.factory.channel:
|
||||
# we are not listening to this channel.
|
||||
return
|
||||
|
||||
key = "imc2_%s" % conn_name
|
||||
# Look for matching IMC2 channel maps.
|
||||
conns = ExternalChannelConnection.objects.filter(db_external_key=self.factory.key)
|
||||
if not conns:
|
||||
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 conns:
|
||||
if conn.channel:
|
||||
conn.to_channel(message)
|
||||
# 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)
|
||||
|
||||
def _format_tell(self, packet):
|
||||
"""
|
||||
Handle tells over IMC2 by formatting the text properly
|
||||
"""
|
||||
return "%s@%s IMC tells: %s" % (packet.sender, packet.origin,
|
||||
packet.optional_data.get('text', 'ERROR: No text provided.'))
|
||||
return "{c%s@%s{n {wpages (over IMC):{n %s" % (packet.sender, packet.origin,
|
||||
packet.optional_data.get('text', 'ERROR: No text provided.'))
|
||||
|
||||
def lineReceived(self, line):
|
||||
"""
|
||||
|
|
@ -247,24 +251,25 @@ class IMC2Protocol(telnet.StatefulTelnetProtocol):
|
|||
what to do with the packet.
|
||||
IMC2 -> Evennia
|
||||
"""
|
||||
line = line.strip()
|
||||
|
||||
if not self.is_authenticated:
|
||||
self._parse_auth_response(line)
|
||||
else:
|
||||
if IMC2_DEBUG and not 'is-alive' in line:
|
||||
# if IMC2_DEBUG mode is on, print the contents of the packet
|
||||
# to stdout.
|
||||
logger.log_infomsg("PACKET: %s" % line)
|
||||
# to stdout.
|
||||
logger.log_infomsg("IMC2: RECV> %s" % line)
|
||||
|
||||
# Parse the packet and encapsulate it for easy access
|
||||
packet = pck.IMC2Packet(self.factory.mudname, packet_str=line)
|
||||
|
||||
if IMC2_DEBUG and packet.packet_type not in ['is-alive', 'keepalive-request']:
|
||||
if IMC2_DEBUG and packet.packet_type not in ('is-alive', 'keepalive-request'):
|
||||
# Print the parsed packet's __str__ representation.
|
||||
# is-alive and keepalive-requests happen pretty frequently.
|
||||
# Don't bore us with them in stdout.
|
||||
logger.log_infomsg(str(packet))
|
||||
|
||||
|
||||
|
||||
# Figure out what kind of packet we're dealing with and hand it
|
||||
# off to the correct handler.
|
||||
|
||||
|
|
@ -288,9 +293,9 @@ class IMC2Protocol(telnet.StatefulTelnetProtocol):
|
|||
player = search.players(packet.target)
|
||||
if not player:
|
||||
return
|
||||
player.msg(self._format_tell(packet))
|
||||
player[0].msg(self._format_tell(packet))
|
||||
|
||||
def msg_imc2(self, message, from_obj=None):
|
||||
def msg_imc2(self, message, from_obj=None, packet_type="imcbroadcast", data=None):
|
||||
"""
|
||||
Called by Evennia to send a message through the imc2 connection
|
||||
"""
|
||||
|
|
@ -304,9 +309,18 @@ class IMC2Protocol(telnet.StatefulTelnetProtocol):
|
|||
from_name = from_obj
|
||||
else:
|
||||
from_name = self.factory.mudname
|
||||
# send the packet
|
||||
self.send_packet(pck.IMC2PacketIceMsgBroadcasted(self.factory.network, self.factory.channel,
|
||||
from_name, message))
|
||||
|
||||
if packet_type == "imcbroadcast":
|
||||
# send the packet
|
||||
self.send_packet(pck.IMC2PacketIceMsgBroadcasted(self.factory.servername, self.factory.channel[0],
|
||||
from_name, message))
|
||||
elif packet_type == "imctell":
|
||||
# send a tell
|
||||
if type(data) == dict:
|
||||
target = data.get("target", "Unknown")
|
||||
destination = data.get("destination", "Unknown")
|
||||
self.send_packet(pck.IMC2PacketTell(from_name, target, destination, message))
|
||||
|
||||
|
||||
class IMC2Factory(protocol.ClientFactory):
|
||||
"""
|
||||
|
|
@ -318,9 +332,11 @@ class IMC2Factory(protocol.ClientFactory):
|
|||
def __init__(self, key, channel, network, port, mudname, client_pwd, server_pwd, evennia_channel):
|
||||
self.key = key
|
||||
self.mudname = mudname
|
||||
self.channel = channel
|
||||
self.channel = channel
|
||||
self.pretty_key = "%s:%s/%s (%s)" % (network, port, channel, mudname)
|
||||
self.network = network
|
||||
sname, host = network.split(".", 1)
|
||||
self.servername = sname.strip()
|
||||
self.protocol_version = '2'
|
||||
self.client_pwd = client_pwd
|
||||
self.server_pwd = server_pwd
|
||||
|
|
@ -338,16 +354,15 @@ class IMC2Factory(protocol.ClientFactory):
|
|||
logger.log_errmsg('IMC2: %s' % message)
|
||||
|
||||
|
||||
def build_connection_key(channel, imc2_network, imc2_port, imc2_channel, imc2_mudname):
|
||||
def build_connection_key(channel, imc2_network, imc2_port, imc2_mudname):
|
||||
"Build an id hash for the connection"
|
||||
if hasattr(channel, 'key'):
|
||||
channel = channel.key
|
||||
return "imc2_%s:%s/%s(%s)<>%s" % (imc2_network, imc2_port, imc2_channel, imc2_mudname, channel)
|
||||
return "imc2_%s:%s(%s)<>%s" % (imc2_network, imc2_port, imc2_mudname, channel)
|
||||
|
||||
def build_service_key(key):
|
||||
return "IMC2:%s" % key
|
||||
|
||||
|
||||
def start_scripts(validate=False):
|
||||
"""
|
||||
Start all the needed scripts
|
||||
|
|
@ -368,7 +383,7 @@ def start_scripts(validate=False):
|
|||
|
||||
def create_connection(channel, imc2_network, imc2_port, imc2_channel, imc2_mudname, imc2_client_pwd, imc2_server_pwd):
|
||||
"""
|
||||
This will create a new IMC2<->channel connection.
|
||||
This will create a new IMC2<->channel connection.
|
||||
"""
|
||||
if not type(channel) == Channel:
|
||||
new_channel = Channel.objects.filter(db_key=channel)
|
||||
|
|
@ -376,15 +391,30 @@ def create_connection(channel, imc2_network, imc2_port, imc2_channel, imc2_mudna
|
|||
logger.log_errmsg("Cannot attach IMC2<->Evennia: Evennia Channel '%s' not found" % channel)
|
||||
return False
|
||||
channel = new_channel[0]
|
||||
key = build_connection_key(channel, imc2_network, imc2_port, imc2_channel, imc2_mudname)
|
||||
key = build_connection_key(channel, imc2_network, imc2_port, imc2_mudname)
|
||||
|
||||
old_conns = ExternalChannelConnection.objects.filter(db_external_key=key)
|
||||
if old_conns:
|
||||
return False
|
||||
return
|
||||
# connection already exists. We try to only connect a new channel
|
||||
old_config = old_conns[0].db_external_config.split('|',5)
|
||||
old_chan_subs = old_config[2].split(',')
|
||||
if imc2_channel in old_chan_subs:
|
||||
return False # we already listen to this channel
|
||||
else:
|
||||
# We add thew new channel to the connection instead of creating a new connection.
|
||||
old_chan_subs.append(imc2_channel)
|
||||
old_chan_subs = ",".join(old_chan_subs)
|
||||
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()
|
||||
return True
|
||||
|
||||
# new connection
|
||||
config = "%s|%s|%s|%s|%s|%s" % (imc2_network, imc2_port, imc2_channel, imc2_mudname, imc2_client_pwd, imc2_server_pwd)
|
||||
# how the channel will be able to contact this protocol
|
||||
send_code = "from src.comms.imc2 import IMC2_CHANNELS\n"
|
||||
send_code += "matched_imc2s = [imc2 for imc2 in IMC2_CHANNELS if imc2.factory.key == '%s']\n" % key
|
||||
send_code = "from src.comms.imc2 import IMC2_CONNECTIONS\n"
|
||||
send_code += "matched_imc2s = [imc2 for imc2 in IMC2_CONNECTIONS if imc2.factory.key == '%s']\n" % key
|
||||
send_code += "[imc2.msg_imc2(message, from_obj=from_obj) for imc2 in matched_imc2s]\n"
|
||||
conn = ExternalChannelConnection(db_channel=channel, db_external_key=key, db_external_send_code=send_code,
|
||||
db_external_config=config)
|
||||
|
|
@ -396,12 +426,12 @@ def create_connection(channel, imc2_network, imc2_port, imc2_channel, imc2_mudna
|
|||
start_scripts()
|
||||
return True
|
||||
|
||||
def delete_connection(channel, imc2_network, imc2_port, imc2_channel, mudname):
|
||||
def delete_connection(channel, imc2_network, imc2_port, mudname):
|
||||
"Destroy a connection"
|
||||
if hasattr(channel, 'key'):
|
||||
channel = channel.key
|
||||
|
||||
key = build_connection_key(channel, imc2_network, imc2_port, imc2_channel, mudname)
|
||||
key = build_connection_key(channel, imc2_network, imc2_port, mudname)
|
||||
service_key = build_service_key(key)
|
||||
try:
|
||||
conn = ExternalChannelConnection.objects.get(db_external_key=key)
|
||||
|
|
@ -427,6 +457,7 @@ def connect_to_imc2(connection):
|
|||
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
|
||||
imc = internet.TCPClient(imc2_network, int(imc2_port), IMC2Factory(key, imc2_channel, imc2_network, imc2_port, imc2_mudname,
|
||||
imc2_client_pwd, imc2_server_pwd, connection.channel.key))
|
||||
|
|
|
|||
|
|
@ -93,24 +93,22 @@ class IMC2Packet(object):
|
|||
|
||||
def __str__(self):
|
||||
retval = """
|
||||
-- Begin Packet Display --
|
||||
Sender: %s
|
||||
Origin: %s
|
||||
--IMC2 package (%s)
|
||||
Sender: %s
|
||||
Origin: %s
|
||||
Sequence: %s
|
||||
Route: %s
|
||||
Type: %s
|
||||
Target: %s
|
||||
Destination: %s
|
||||
Data: %s
|
||||
- End Packet Display --""" % (self.sender,
|
||||
self.origin,
|
||||
self.sequence,
|
||||
self.route,
|
||||
self.packet_type,
|
||||
self.target,
|
||||
self.destination,
|
||||
self.optional_data)
|
||||
return retval
|
||||
Route: %s
|
||||
Type: %s
|
||||
Target: %s
|
||||
Dest.: %s
|
||||
Data:
|
||||
%s
|
||||
------------------------""" % (self.packet_type, self.sender,
|
||||
self.origin, self.sequence,
|
||||
self.route, self.packet_type,
|
||||
self.target, self.destination,
|
||||
"\n ".join(["%s: %s" % items for items in self.optional_data.items()]))
|
||||
return retval.strip()
|
||||
|
||||
def _get_optional_data_string(self):
|
||||
"""
|
||||
|
|
@ -426,7 +424,7 @@ class IMC2PacketIceMsgBroadcasted(IMC2Packet):
|
|||
def __init__(self, server, channel, pobject, message):
|
||||
"""
|
||||
Args:
|
||||
server: (String) Server name the channel resides on.
|
||||
server: (String) Server name the channel resides on (obs - this is e.g. Server01, not the full network name!)
|
||||
channel: (String) Name of the IMC2 channel.
|
||||
pobject: (Object) Object sending the message.
|
||||
message: (String) Message to send.
|
||||
|
|
@ -507,8 +505,22 @@ class IMC2PacketTell(IMC2Packet):
|
|||
Reply from Dude:
|
||||
Dude@SomeMUD 1234567890 SomeMUD!Hub1 tell You@YourMUD text="Yeah, this is cool!" isreply=1
|
||||
"""
|
||||
pass
|
||||
|
||||
def __init__(self, pobject, target, destination, message):
|
||||
super(IMC2PacketTell, self).__init__()
|
||||
self.sender = pobject
|
||||
self.packet_type = "tell"
|
||||
self.target = target
|
||||
self.destination = destination
|
||||
self.optional_data = {"text": message,
|
||||
"isreply":None}
|
||||
|
||||
def assemble(self, mudname=None, client_pwd=None, server_pwd=None):
|
||||
self.sequence = self.imc2_protocol.sequence
|
||||
#self.route = "%s!%s" % (self.origin, self.imc2_protocol.factory.servername.capitalize())
|
||||
return '''"%s@%s %s %s tell %s@%s text="%s"''' % (self.sender, self.origin, self.sequence,
|
||||
self.route, self.target, self.destination,
|
||||
self.optional_data.get("text","NO TEXT GIVEN"))
|
||||
|
||||
class IMC2PacketEmote(IMC2Packet):
|
||||
"""
|
||||
Description:
|
||||
|
|
|
|||
|
|
@ -286,7 +286,7 @@ IRC_ENABLED = False
|
|||
# 'server password' as chosen when registering on mudbytes. The
|
||||
# Evennia discussion channel 'ievennia' is on
|
||||
# server02.mudbytes.net:9000.
|
||||
IMC2_ENABLED = False # OBS! DON'T CHANGE - IMC2 is not implemented yet!
|
||||
IMC2_ENABLED = False
|
||||
|
||||
|
||||
###################################################
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue