From 4424dec668cf598d005d35a37733ed4a5c151b58 Mon Sep 17 00:00:00 2001 From: Greg Taylor Date: Fri, 28 Oct 2016 22:53:43 -0700 Subject: [PATCH] Remove broken and un-maintained IMC2 support. As discussed with @Griatch, IMC2 is now rarely seen in the wild. Also, this feature hasn't worked in ages. Time to de-clutter. --- evennia/commands/default/cmdset_player.py | 3 - evennia/commands/default/comms.py | 225 +---- evennia/game_template/server/conf/mssp.py | 1 - evennia/locale/fr/LC_MESSAGES/django.po | 18 - evennia/locale/it/LC_MESSAGES/django.po | 18 - evennia/locale/pt/LC_MESSAGES/django.po | 18 - evennia/locale/sv/LC_MESSAGES/django.po | 35 - evennia/players/bots.py | 97 --- evennia/players/migrations/0001_initial.py | 2 +- evennia/players/models.py | 2 +- evennia/server/amp.py | 4 +- evennia/server/portal/imc2.py | 480 ----------- evennia/server/portal/imc2lib/__init__.py | 1 - evennia/server/portal/imc2lib/imc2_ansi.py | 60 -- evennia/server/portal/imc2lib/imc2_packets.py | 797 ------------------ evennia/server/portal/mssp.py | 1 - evennia/server/portal/portalsessionhandler.py | 2 +- evennia/server/server.py | 5 - evennia/settings_default.py | 24 +- evennia/web/utils/general_context.py | 2 +- 20 files changed, 9 insertions(+), 1786 deletions(-) delete mode 100644 evennia/server/portal/imc2.py delete mode 100644 evennia/server/portal/imc2lib/__init__.py delete mode 100644 evennia/server/portal/imc2lib/imc2_ansi.py delete mode 100644 evennia/server/portal/imc2lib/imc2_packets.py diff --git a/evennia/commands/default/cmdset_player.py b/evennia/commands/default/cmdset_player.py index 10051e10dd..9a96a375a1 100644 --- a/evennia/commands/default/cmdset_player.py +++ b/evennia/commands/default/cmdset_player.py @@ -70,6 +70,3 @@ class PlayerCmdSet(CmdSet): self.add(comms.CmdPage()) self.add(comms.CmdIRC2Chan()) self.add(comms.CmdRSS2Chan()) - #self.add(comms.CmdIMC2Chan()) - #self.add(comms.CmdIMCInfo()) - #self.add(comms.CmdIMCTell()) diff --git a/evennia/commands/default/comms.py b/evennia/commands/default/comms.py index 4b667bebf3..f37dfdc448 100644 --- a/evennia/commands/default/comms.py +++ b/evennia/commands/default/comms.py @@ -10,7 +10,6 @@ for easy handling. from past.builtins import cmp from django.conf import settings from evennia.comms.models import ChannelDB, Msg -#from evennia.comms import irc, imc2, rss from evennia.players.models import PlayerDB from evennia.players import bots from evennia.comms.channelhandler import CHANNELHANDLER @@ -24,8 +23,7 @@ COMMAND_DEFAULT_CLASS = class_from_module(settings.COMMAND_DEFAULT_CLASS) __all__ = ("CmdAddCom", "CmdDelCom", "CmdAllCom", "CmdChannels", "CmdCdestroy", "CmdCBoot", "CmdCemit", "CmdCWho", "CmdChannelCreate", "CmdClock", "CmdCdesc", - "CmdPage", "CmdIRC2Chan", "CmdRSS2Chan")#, "CmdIMC2Chan", "CmdIMCInfo", - #"CmdIMCTell") + "CmdPage", "CmdIRC2Chan", "CmdRSS2Chan") _DEFAULT_WIDTH = settings.CLIENT_DEFAULT_WIDTH @@ -995,224 +993,3 @@ class CmdRSS2Chan(COMMAND_DEFAULT_CLASS): bot = create.create_player(botname, None, None, typeclass=bots.RSSBot) bot.start(ev_channel=channel, rss_url=url, rss_rate=10) self.msg("RSS reporter created. Fetching RSS.") - - -#class CmdIMC2Chan(COMMAND_DEFAULT_CLASS): -# """ -# link an evennia channel to an external IMC2 channel -# -# Usage: -# @imc2chan[/switches] = -# -# Switches: -# /disconnect - this clear the imc2 connection to the channel. -# /remove - " -# /list - show all imc2<->evennia mappings -# -# Example: -# @imc2chan myimcchan = ievennia -# -# Connect an existing evennia channel to a channel on an IMC2 -# network. The network contact information is defined in settings and -# should already be accessed at this point. Use @imcchanlist to see -# available IMC channels. -# -# """ -# -# key = "@imc2chan" -# locks = "cmd:serversetting(IMC2_ENABLED) and pperm(Immortals)" -# help_category = "Comms" -# -# 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.msg(string) -# return -# -# if 'list' in self.switches: -# # show all connections -# connections = ExternalChannelConnection.objects.filter(db_external_key__startswith='imc2_') -# if connections: -# table = prettytable.PrettyTable(["Evennia channel", "IMC channel"]) -# for conn in connections: -# table.add_row([conn.channel.key, conn.external_config]) -# string = "{wIMC connections:{n\n%s" % table -# self.msg(string) -# else: -# self.msg("No connections found.") -# return -# -# if not self.args or not self.rhs: -# string = "Usage: @imc2chan[/switches] = " -# self.msg(string) -# return -# -# channel = self.lhs -# imc2_channel = self.rhs -# -# 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 also if the channel no longer exists. -# ok = imc2.delete_connection(channel, imc2_channel) -# if not ok: -# self.msg("IMC2 connection could not be removed, does it exist?") -# else: -# self.msg("IMC2 connection destroyed.") -# return -# -# # actually get the channel object -# channel = find_channel(self.caller, channel) -# if not channel: -# return -# -# ok = imc2.create_connection(channel, imc2_channel) -# if not ok: -# self.msg("The connection %s <-> %s already exists." % (channel.key, imc2_channel)) -# return -# self.msg("Created connection channel %s <-> IMC channel %s." % (channel.key, imc2_channel)) -# -# -#class CmdIMCInfo(COMMAND_DEFAULT_CLASS): -# """ -# get various IMC2 information -# -# Usage: -# @imcinfo[/switches] -# @imcchanlist - list imc2 channels -# @imclist - list connected muds -# @imcwhois - whois info about a remote player -# -# Switches for @imcinfo: -# channels - as @imcchanlist (default) -# games or muds - as @imclist -# whois - as @imcwhois (requires an additional argument) -# update - force an update of all lists -# -# Shows lists of games or channels on the IMC2 network. -# """ -# -# key = "@imcinfo" -# aliases = ["@imcchanlist", "@imclist", "@imcwhois"] -# locks = "cmd: serversetting(IMC2_ENABLED) and pperm(Wizards)" -# help_category = "Comms" -# -# 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.msg(string) -# return -# -# if "update" in self.switches: -# # update the lists -# import time -# from evennia.comms.imc2lib import imc2_packets as pck -# from evennia.comms.imc2 import IMC2_MUDLIST, IMC2_CHANLIST, IMC2_CLIENT -# # update connected muds -# IMC2_CLIENT.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 -# IMC2_CLIENT.send_packet(pck.IMC2PacketIceRefresh()) -# self.msg("IMC2 lists were re-synced.") -# -# elif("games" in self.switches or "muds" in self.switches -# or self.cmdstring == "@imclist"): -# # list muds -# from evennia.comms.imc2 import IMC2_MUDLIST -# -# muds = IMC2_MUDLIST.get_mud_list() -# networks = set(mud.networkname for mud in muds) -# string = "" -# nmuds = 0 -# for network in networks: -# table = prettytable.PrettyTable(["Name", "Url", "Host", "Port"]) -# for mud in (mud for mud in muds if mud.networkname == network): -# nmuds += 1 -# table.add_row([mud.name, mud.url, mud.host, mud.port]) -# string += "\n{wMuds registered on %s:{n\n%s" % (network, table) -# string += "\n %i Muds found." % nmuds -# self.msg(string) -# -# elif "whois" in self.switches or self.cmdstring == "@imcwhois": -# # find out about a player -# if not self.args: -# self.msg("Usage: @imcwhois ") -# return -# from evennia.comms.imc2 import IMC2_CLIENT -# self.msg("Sending IMC whois request. If you receive no response, no matches were found.") -# IMC2_CLIENT.msg_imc2(None, -# from_obj=self.caller, -# packet_type="imcwhois", -# target=self.args) -# -# elif(not self.switches or "channels" in self.switches or -# self.cmdstring == "@imcchanlist"): -# # show channels -# from evennia.comms.imc2 import IMC2_CHANLIST, IMC2_CLIENT -# -# channels = IMC2_CHANLIST.get_channel_list() -# string = "" -# nchans = 0 -# table = prettytable.PrettyTable(["Full name", "Name", "Owner", "Perm", "Policy"]) -# for chan in channels: -# nchans += 1 -# table.add_row([chan.name, chan.localname, chan.owner, -# chan.level, chan.policy]) -# string += "\n{wChannels on %s:{n\n%s" % (IMC2_CLIENT.factory.network, table) -# string += "\n%i Channels found." % nchans -# self.msg(string) -# else: -# # no valid inputs -# string = "Usage: imcinfo|imcchanlist|imclist" -# self.msg(string) -# -# -## unclear if this is working ... -#class CmdIMCTell(COMMAND_DEFAULT_CLASS): -# """ -# send a page to a remote IMC player -# -# Usage: -# imctell User@MUD = -# 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)" -# 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.msg(string) -# return -# -# from evennia.comms.imc2 import IMC2_CLIENT -# -# if not self.args or not '@' in self.lhs or not self.rhs: -# string = "Usage: imctell User@Mud = " -# self.msg(string) -# return -# target, destination = self.lhs.split("@", 1) -# message = self.rhs.strip() -# data = {"target":target, "destination":destination} -# -# # send to imc2 -# IMC2_CLIENT.msg_imc2(message, from_obj=self.caller, packet_type="imctell", **data) -# -# self.msg("You paged {c%s@%s{n (over IMC): '%s'." % (target, destination, message)) -# -# diff --git a/evennia/game_template/server/conf/mssp.py b/evennia/game_template/server/conf/mssp.py index f862ace5a5..47f0f30941 100644 --- a/evennia/game_template/server/conf/mssp.py +++ b/evennia/game_template/server/conf/mssp.py @@ -44,7 +44,6 @@ MSSPTable = { # Roleplaying, Simulation, Social or Strategy "STATUS": "Open Beta", # Alpha, Closed Beta, Open Beta, Live "GAMESYSTEM": "Custom", # D&D, d20 System, World of Darkness, etc. Use Custom if homebrew - "INTERMUD": "IMC2", # evennia supports IMC2. "SUBGENRE": "None", # LASG, Medieval Fantasy, World War II, Frankenstein, # Cyberpunk, Dragonlance, etc. Or None if not available. diff --git a/evennia/locale/fr/LC_MESSAGES/django.po b/evennia/locale/fr/LC_MESSAGES/django.po index 5b6ec46fb1..c42a0c133d 100644 --- a/evennia/locale/fr/LC_MESSAGES/django.po +++ b/evennia/locale/fr/LC_MESSAGES/django.po @@ -240,24 +240,6 @@ msgstr "Utilisateur #1." msgid "Limbo" msgstr "Limbes." -#: server/portal/imc2.py:201 -#, python-format -msgid "Whois reply from %(origin)s: %(msg)s" -msgstr "Réponse whois de %(origin)s: %(msg)s" - -#: server/portal/imc2.py:213 -#, python-format -msgid "{c%(sender)s@%(origin)s{n {wpages (over IMC):{n %(msg)s" -msgstr "{c%(sender)s@%(origin)s{n {wpages (over IMC):{n %(msg)s" - -#: server/portal/imc2.py:238 -msgid "IMC2 server rejected connection." -msgstr "Serveur IMC2 a rejeté la connexion." - -#: server/portal/imc2.py:246 -msgid "IMC2: Autosetup response found." -msgstr "IMC2: Réponse autosetup trouvé." - #: server/sessionhandler.py:258 msgid " ... Server restarted." msgstr " ... Serveur redémarré." diff --git a/evennia/locale/it/LC_MESSAGES/django.po b/evennia/locale/it/LC_MESSAGES/django.po index 5f4663707e..9ecf460e2c 100644 --- a/evennia/locale/it/LC_MESSAGES/django.po +++ b/evennia/locale/it/LC_MESSAGES/django.po @@ -241,24 +241,6 @@ msgstr "Questo è l'Utente #1." msgid "Limbo" msgstr "Limbo" -#: .\server\portal\imc2.py:167 -#, python-format -msgid "Whois reply from %(origin)s: %(msg)s" -msgstr "Risposta Whois da %(origin)s: %(msg)s" - -#: .\server\portal\imc2.py:175 -#, python-format -msgid "{c%(sender)s@%(origin)s{n {wpages (over IMC):{n %(msg)s" -msgstr "{c%(sender)s@%(origin)s{n {wpages (over IMC):{n %(msg)s" - -#: .\server\portal\imc2.py:193 -msgid "IMC2 server rejected connection." -msgstr "Il server IMC2 ha rifiutato la connessione." - -#: .\server\portal\imc2.py:201 -msgid "IMC2: Autosetup response found." -msgstr "IMC2: Trovato responso di autosetup." - #: .\server\sessionhandler.py:192 #, python-format msgid "Connection dropped: %s %s (%s)" diff --git a/evennia/locale/pt/LC_MESSAGES/django.po b/evennia/locale/pt/LC_MESSAGES/django.po index cd6a664f22..46ae6f1d9c 100644 --- a/evennia/locale/pt/LC_MESSAGES/django.po +++ b/evennia/locale/pt/LC_MESSAGES/django.po @@ -231,24 +231,6 @@ msgstr "Este é o Usuário #1." msgid "Limbo" msgstr "Limbo" -#: server/portal/imc2.py:203 -#, python-format -msgid "Whois reply from %(origin)s: %(msg)s" -msgstr "Resposta Whois da %(origin)s: %(msg)s" - -#: server/portal/imc2.py:215 -#, python-format -msgid "{c%(sender)s@%(origin)s{n {wpages (over IMC):{n %(msg)s" -msgstr "{c%(sender)s@%(origin)s{n {wpages (over IMC):{n %(msg)s" - -#: server/portal/imc2.py:240 -msgid "IMC2 server rejected connection." -msgstr "Servidor IMC2 rejeitou a conexão." - -#: server/portal/imc2.py:248 -msgid "IMC2: Autosetup response found." -msgstr "IMC2: Encontrada resposta de autosetup." - #: server/sessionhandler.py:244 msgid " ... Server restarted." msgstr " ... Servidor reiniciado." diff --git a/evennia/locale/sv/LC_MESSAGES/django.po b/evennia/locale/sv/LC_MESSAGES/django.po index d000792f83..8d122b0234 100644 --- a/evennia/locale/sv/LC_MESSAGES/django.po +++ b/evennia/locale/sv/LC_MESSAGES/django.po @@ -230,24 +230,6 @@ msgstr "Detta är användare #1." msgid "Limbo" msgstr "Limbo" -#: server/portal/imc2.py:167 -#, python-format -msgid "Whois reply from %(origin)s: %(msg)s" -msgstr "Whois-svar från %(origin)s: %(msg)s" - -#: server/portal/imc2.py:175 -#, python-format -msgid "{c%(sender)s@%(origin)s{n {wpages (over IMC):{n %(msg)s" -msgstr "{c%(sender)s@%(origin)s{n {wskickar (over IMC):{n %(msg)s" - -#: server/portal/imc2.py:193 -msgid "IMC2 server rejected connection." -msgstr "IMC2 server avvisade uppkopplingen." - -#: server/portal/imc2.py:201 -msgid "IMC2: Autosetup response found." -msgstr "IMC2: Autosetup-svar hittat." - #: server/sessionhandler.py:221 msgid " ... Server restarted." msgstr "... Servern startades om." @@ -373,29 +355,12 @@ msgstr "Timeout. Kopplar ur." #~ msgid " (exit to %s)" #~ msgstr "(utgång till %s)" -#~ msgid "Send an IMC2 is-alive packet" -#~ msgstr "Skicka ett IMC2-is-alive paket" - -#~ msgid "Send an IMC2 keepalive-request packet" -#~ msgstr "Skicka ett IMC2 keepalive-request paket" - -#~ msgid "Check IMC2 list for inactive games" -#~ msgstr "Genomsök IMC2-listan efter inaktiva spel" - -#~ msgid "Re-sync IMC2 network channel list" -#~ msgstr "Återsynca nätverkslistan över IMC2 kanaler" - #~ msgid "Successfully authenticated to the '%s' network." #~ msgstr "Identifierade sig framgångsrikt till nätverket '%s'." #~ msgid "Connection lost: %s" #~ msgstr "Uppkopplingen förlorades: %s" -#~ msgid "Cannot attach IMC2<->Evennia: Evennia Channel '%s' not found" -#~ msgstr "" -#~ "Kan inte sammankoppla IMC2<->Evennia: Evennia-kanalen '%s' gick inte att " -#~ "hitta." - #~ msgid "joined %s." #~ msgstr "lyssnar till %s." diff --git a/evennia/players/bots.py b/evennia/players/bots.py index a5bec0d814..5d60e6de4d 100644 --- a/evennia/players/bots.py +++ b/evennia/players/bots.py @@ -312,100 +312,3 @@ class RSSBot(Bot): self.ndb.ev_channel = self.db.ev_channel if self.ndb.ev_channel: self.ndb.ev_channel.msg(text, senders=self.id) - -# IMC2 (not tested currently) - -class IMC2Bot(Bot): - """ - IMC2 Bot - - """ - def start(self, ev_channel=None, imc2_network=None, imc2_mudname=None, - imc2_port=None, imc2_client_pwd=None, imc2_server_pwd=None): - """ - Start by telling the portal to start a new session - - Args: - ev_channel (str, optional): Key of the Evennia channel to connect to. - imc2_network (str, optional): IMC2 network name. - imc2_mudname (str, optional): Registered mudname (if not given, use settings.SERVERNAME). - imc2_port (int, optional): Port number of the IMC2 network. - imc2_client_pwd (str, optional): Client password registered with IMC2 network. - imc2_server_pwd (str, optional): Server password registered with IMC2 network. - - Raises: - RuntimeError: If `ev_channel` was not found. - - """ - global _SESSIONS - if not _SESSIONS: - from evennia.server.sessionhandler import SESSIONS as _SESSIONS - 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 = channel[0] - channel.connect(self) - self.db.ev_channel = channel - if imc2_network: - self.db.imc2_network = imc2_network - if imc2_port: - self.db.imc2_port = imc2_port - if imc2_mudname: - self.db.imc2_mudname = imc2_mudname - elif not self.db.imc2_mudname: - self.db.imc2_mudname = settings.SERVERNAME - # storing imc2 passwords in attributes - a possible - # security issue? - if imc2_server_pwd: - self.db.imc2_server_pwd = imc2_server_pwd - if imc2_client_pwd: - self.db.imc2_client_pwd = imc2_client_pwd - - configdict = {"uid": self.dbid, - "mudname": self.db.imc2_mudname, - "network": self.db.imc2_network, - "port": self.db.imc2_port, - "client_pwd": self.db.client_pwd, - "server_pwd": self.db.server_pwd} - - _SESSIONS.start_bot_session("evennia.server.portal.imc2.IMC2BotFactory", configdict) - - def msg(self, text=None, **kwargs): - """ - Takes text from connected channel (only). - - Args: - text (str): Message from channel. - - Kwargs: - options (dict): Option dict with these allowed keys: - - from_channel (str): dbid of a channel this text originated from. - - from_obj (str): dbid of an object sending this text. - - """ - options = kwargs.get("options", {}) - if not self.ndb.ev_channel and self.db.ev_channel: - # cache channel lookup - self.ndb.ev_channel = self.db.ev_channel - if "from_channel" in options and text and self.ndb.ev_channel.dbid == options["from_channel"]: - if "from_obj" not in options or options["from_obj"] != [self.id]: - self.msg(text=text, options={"bot_data_out": True}) - - def execute_cmd(self, text=None, session=None): - """ - Relay incoming data to connected channel. - - Args: - text (str, optional): Command string. - session (Session, optional): Session responsible for this - command. - - """ - if not self.ndb.ev_channel and self.db.ev_channel: - # cache channel lookup - self.ndb.ev_channel = self.db.ev_channel - if self.ndb.ev_channel: - self.ndb.ev_channel.msg(text, senders=self.id) - diff --git a/evennia/players/migrations/0001_initial.py b/evennia/players/migrations/0001_initial.py index 902adb82d4..de2b93f5bd 100644 --- a/evennia/players/migrations/0001_initial.py +++ b/evennia/players/migrations/0001_initial.py @@ -34,7 +34,7 @@ class Migration(migrations.Migration): ('db_lock_storage', models.TextField(help_text=b"locks limit access to an entity. A lock is defined as a 'lock string' on the form 'type:lockfunctions', defining what functionality is locked and how to determine access. Not defining a lock means no access is granted.", verbose_name=b'locks', blank=True)), ('db_is_connected', models.BooleanField(default=False, help_text=b'If player is connected to game or not', verbose_name=b'is_connected')), ('db_cmdset_storage', models.CharField(help_text=b'optional python path to a cmdset class. If creating a Character, this will default to settings.CMDSET_CHARACTER.', max_length=255, null=True, verbose_name=b'cmdset')), - ('db_is_bot', models.BooleanField(default=False, help_text=b'Used to identify irc/imc2/rss bots', verbose_name=b'is_bot')), + ('db_is_bot', models.BooleanField(default=False, help_text=b'Used to identify irc/rss bots', verbose_name=b'is_bot')), ('db_attributes', models.ManyToManyField(help_text=b'attributes on this object. An attribute can hold any pickle-able python object (see docs for special cases).', to='typeclasses.Attribute', null=True)), ('db_tags', models.ManyToManyField(help_text=b'tags on this object. Tags are simple string markers to identify, group and alias objects.', to='typeclasses.Tag', null=True)), ('groups', models.ManyToManyField(related_query_name='user', related_name='user_set', to='auth.Group', blank=True, help_text='The groups this user belongs to. A user will get all permissions granted to each of his/her group.', verbose_name='groups')), diff --git a/evennia/players/models.py b/evennia/players/models.py index b4e2c4d9bc..bfa1824bcb 100644 --- a/evennia/players/models.py +++ b/evennia/players/models.py @@ -91,7 +91,7 @@ class PlayerDB(TypedObject, AbstractUser): db_cmdset_storage = models.CharField('cmdset', max_length=255, null=True, help_text="optional python path to a cmdset class. If creating a Character, this will default to settings.CMDSET_CHARACTER.") # marks if this is a "virtual" bot player object - db_is_bot = models.BooleanField(default=False, verbose_name="is_bot", help_text="Used to identify irc/imc2/rss bots") + db_is_bot = models.BooleanField(default=False, verbose_name="is_bot", help_text="Used to identify irc/rss bots") # Database manager objects = PlayerDBManager() diff --git a/evennia/server/amp.py b/evennia/server/amp.py index 88954d285b..6fbd221013 100644 --- a/evennia/server/amp.py +++ b/evennia/server/amp.py @@ -48,7 +48,7 @@ SDISCONN = chr(5) # server session disconnect SDISCONNALL = chr(6) # server session disconnect all SSHUTD = chr(7) # server shutdown SSYNC = chr(8) # server session sync -SCONN = chr(11) # server creating new connection (for irc/imc2 bots etc) +SCONN = chr(11) # server creating new connection (for irc bots and etc) PCONNSYNC = chr(12) # portal post-syncing a session PDISCONNALL = chr(13) # portal session disconnect all AMP_MAXLEN = amp.MAX_VALUE_LENGTH # max allowed data length in AMP protocol (cannot be changed) @@ -589,7 +589,7 @@ class AMPProtocol(amp.AMP): # set a flag in case we are about to shut down soon self.factory.server_restart_mode = True - elif operation == SCONN: # server_force_connection (for irc/imc2 etc) + elif operation == SCONN: # server_force_connection (for irc/etc) portal_sessionhandler.server_connect(**kwargs) else: diff --git a/evennia/server/portal/imc2.py b/evennia/server/portal/imc2.py deleted file mode 100644 index 4f5880e4ed..0000000000 --- a/evennia/server/portal/imc2.py +++ /dev/null @@ -1,480 +0,0 @@ -""" -IMC2 client module. Handles connecting to and communicating with an IMC2 server. -""" -from builtins import object -from future.utils import listitems - -from time import time -from twisted.internet import task -from twisted.application import internet -from twisted.internet import protocol -from twisted.conch import telnet - -from evennia.server.session import Session -from evennia.utils import logger, utils -from evennia.server.portal.imc2lib import imc2_ansi -from evennia.server.portal.imc2lib import imc2_packets as pck - -from django.utils.translation import ugettext as _ - - -# storage containers for IMC2 muds and channels - -class IMC2Mud(object): - """ - Stores information about other games connected to our current IMC2 network. - - """ - def __init__(self, packet): - self.name = packet.origin - self.versionid = packet.optional_data.get('versionid', None) - self.networkname = packet.optional_data.get('networkname', None) - self.url = packet.optional_data.get('url', None) - self.host = packet.optional_data.get('host', None) - self.port = packet.optional_data.get('port', None) - self.sha256 = packet.optional_data.get('sha256', None) - # This is used to determine when a Mud has fallen into inactive status. - self.last_updated = time() - - -class IMC2MudList(dict): - """ - Keeps track of other MUDs connected to the IMC network. - - """ - def get_mud_list(self): - """ - Returns a sorted list of connected Muds. - """ - muds = listitems(self) - muds.sort() - return [value for key, value in muds] - - def update_mud_from_packet(self, packet): - """ - This grabs relevant info from the packet and stuffs it in the - Mud list for later retrieval. - - Args: - packet (Packet): incoming packet. - - """ - mud = IMC2Mud(packet) - self[mud.name] = mud - - def remove_mud_from_packet(self, packet): - """ - Removes a mud from the Mud list when given a packet. - - Args: - packet (Packet): Incoming packet. - - """ - mud = IMC2Mud(packet) - try: - del self[mud.name] - except KeyError: - # No matching entry, no big deal. - pass - - -class IMC2Channel(object): - """ - Stores information about channels available on the network. - """ - def __init__(self, packet): - "Initialize channel." - self.localname = packet.optional_data.get('localname', None) - self.name = packet.optional_data.get('channel', None) - self.level = packet.optional_data.get('level', None) - self.owner = packet.optional_data.get('owner', None) - self.policy = packet.optional_data.get('policy', None) - self.last_updated = time() - - -class IMC2ChanList(dict): - """ - Keeps track of Channels on the IMC network. - """ - - def get_channel_list(self): - """ - Returns a sorted list of cached channels. - - """ - channels = listitems(self) - channels.sort() - return [value for key, value in channels] - - def update_channel_from_packet(self, packet): - """ - This grabs relevant info from the packet and stuffs it in the - channel list for later retrieval. - - Args: - packet (Packet): incoming packet. - - """ - channel = IMC2Channel(packet) - self[channel.name] = channel - - def remove_channel_from_packet(self, packet): - """ - Removes a channel from the Channel list when given a packet. - - Args: - packet (Packet): incoming packet. - - """ - channel = IMC2Channel(packet) - try: - del self[channel.name] - except KeyError: - # No matching entry, no big deal. - pass - - -# -# IMC2 protocol -# - -class IMC2Bot(telnet.StatefulTelnetProtocol, Session): - """ - Provides the abstraction for the IMC2 protocol. Handles connection, - authentication, and all necessary packets. - - """ - def __init__(self): - "Initialize bot." - self.is_authenticated = False - # only support plaintext passwords - self.auth_type = "plaintext" - self.sequence = None - self.imc2_mudlist = IMC2MudList() - self.imc2_chanlist = IMC2ChanList() - - def _send_packet(self, packet): - """ - Helper function to send packets across the wire. - - Args: - packet (Packet): Outgoing packet. - - """ - packet.imc2_protocol = self - packet_str = utils.to_str(packet.assemble(self.factory.mudname, - self.factory.client_pwd, self.factory.server_pwd)) - self.sendLine(packet_str) - - def _isalive(self): - "Send an isalive packet." - self._send_packet(pck.IMC2PacketIsAlive()) - - def _keepalive(self): - "Send a keepalive packet." - # send to channel? - self._send_packet(pck.IMC2PacketKeepAliveRequest()) - - def _channellist(self): - "Sync the network channel list." - checked_networks = [] - if not self.network in checked_networks: - self._send_packet(pck.IMC2PacketIceRefresh()) - checked_networks.append(self.network) - - def _prune(self): - "Prune active channel list." - t0 = time() - for name, mudinfo in self.imc2_mudlist.items(): - if t0 - mudinfo.last_updated > 3599: - del self.imc2_mudlist[name] - - def _whois_reply(self, packet): - """ - Handle reply from server from an imcwhois request. - - Args: - packet (Packet): Data packet. - - """ - # packet.target potentially contains the id of an character to target - # not using that here - response_text = imc2_ansi.parse_ansi(packet.optional_data.get('text', 'Unknown')) - string = _('Whois reply from %(origin)s: %(msg)s') % {"origin":packet.origin, "msg":response_text} - # somehow pass reply on to a given player, for now we just send to channel - self.data_in(string) - - def _format_tell(self, packet): - """ - Handle tells over IMC2 by formatting the text properly - - Args: - packet (Packet): Data packet. - - """ - return _("{c%(sender)s@%(origin)s{n {wpages (over IMC):{n %(msg)s") % {"sender": packet.sender, - "origin": packet.origin, - "msg": packet.optional_data.get('text', 'ERROR: No text provided.')} - - def _imc_login(self, line): - """ - Connect and identify to imc network as per the - `self.auth_type` setting. - - Args: - line (str): Incoming text. - - """ - - if self.auth_type == "plaintext": - # Only support Plain text passwords. - # SERVER Sends: PW version= - - logger.log_info("IMC2: AUTH< %s" % line) - - line_split = line.split(' ') - pw_present = line_split[0] == 'PW' - autosetup_present = line_split[0] == 'autosetup' - - if "reject" in line_split: - auth_message = _("IMC2 server rejected connection.") - logger.log_info(auth_message) - return - - if pw_present: - self.server_name = line_split[1] - self.network_name = line_split[4] - elif autosetup_present: - logger.log_info(_("IMC2: Autosetup response found.")) - self.server_name = line_split[1] - self.network_name = line_split[3] - self.is_authenticated = True - self.sequence = int(time()) - - # Log to stdout and notify over MUDInfo. - logger.log_info('IMC2: Authenticated to %s' % self.factory.network) - - # Ask to see what other MUDs are connected. - self._send_packet(pck.IMC2PacketKeepAliveRequest()) - # IMC2 protocol states that KeepAliveRequests should be followed - # up by the requester sending an IsAlive packet. - self._send_packet(pck.IMC2PacketIsAlive()) - # Get a listing of channels. - self._send_packet(pck.IMC2PacketIceRefresh()) - - def connectionMade(self): - """ - Triggered after connecting to the IMC2 network. - - """ - - self.stopping = False - self.factory.bot = self - address = "%s@%s" % (self.mudname, self.network) - self.init_session("ircbot", address, self.factory.sessionhandler) - # link back and log in - self.uid = int(self.factory.uid) - self.logged_in = True - self.factory.sessionhandler.connect(self) - logger.log_info("IMC2 bot connected to %s." % self.network) - # Send authentication packet. The reply will be caught by lineReceived - self._send_packet(pck.IMC2PacketAuthPlaintext()) - - def lineReceived(self, line): - """ - IMC2 -> Evennia - - Triggered when text is received from the IMC2 network. Figures out - what to do with the packet. This deals with the following - - Args: - line (str): Incoming text. - - """ - line = line.strip() - - if not self.is_authenticated: - # we are not authenticated yet. Deal with this. - self._imc_login(line) - return - - # Parse the packet and encapsulate it for easy access - packet = pck.IMC2Packet(self.mudname, packet_str=line) - - # Figure out what kind of packet we're dealing with and hand it - # off to the correct handler. - - if packet.packet_type == 'is-alive': - self.imc2_mudlist.update_mud_from_packet(packet) - elif packet.packet_type == 'keepalive-request': - # Don't need to check the destination, we only receive these - # packets when they are intended for us. - self.send_packet(pck.IMC2PacketIsAlive()) - elif packet.packet_type == 'ice-msg-b': - self.data_out(text=line, packettype="broadcast") - elif packet.packet_type == 'whois-reply': - # handle eventual whois reply - self._whois_reply(packet) - elif packet.packet_type == 'close-notify': - self.imc2_mudlist.remove_mud_from_packet(packet) - elif packet.packet_type == 'ice-update': - self.imc2_chanlist.update_channel_from_packet(packet) - elif packet.packet_type == 'ice-destroy': - self.imc2_chanlist.remove_channel_from_packet(packet) - elif packet.packet_type == 'tell': - # send message to identified player - pass - - def data_in(self, text=None, **kwargs): - """ - Data IMC2 -> Evennia. - - Kwargs: - text (str): Incoming text. - kwargs (any): Other data from protocol. - - """ - text = "bot_data_in " + text - self.sessionhandler.data_in(self, text=text, **kwargs) - - def data_out(self, text=None, **kwargs): - """ - Evennia -> IMC2. - - Kwargs: - text (str): Outgoing text. - packet_type (str): - - broadcast: Send to everyone on IMC channel. - - tell: Send a tell (see target keyword). - - whois: Get whois information (see target keyword). - sender (str): Used by tell to identify the mud sending. - target (str): Key identifier of target to tells or whois. If not - given "Unknown" will be used. - destination (str): Used by tell to specify mud - destination to send to. - - """ - - if self.sequence: - # This gets incremented with every command. - self.sequence += 1 - - packet_type = kwargs.get("packet_type", "imcbroadcast") - - if packet_type == "broadcast": - # broadcast to everyone on IMC channel - - if text.startswith("bot_data_out"): - text = text.split(" ", 1)[1] - else: - return - - # we remove the extra channel info since imc2 supplies this anyway - if ":" in text: - header, message = [part.strip() for part in text.split(":", 1)] - # Create imc2packet and send it - self._send_packet(pck.IMC2PacketIceMsgBroadcasted(self.servername, - self.channel, - header, text)) - elif packet_type == "tell": - # send an IMC2 tell - sender = kwargs.get("sender", self.mudname) - target = kwargs.get("target", "Unknown") - destination = kwargs.get("destination", "Unknown") - self._send_packet(pck.IMC2PacketTell(sender, target, destination, text)) - - elif packet_type == "whois": - # send a whois request - sender = kwargs.get("sender", self.mudname) - target = kwargs.get("target", "Unknown") - self._send_packet(pck.IMC2PacketWhois(sender, target)) - - -class IMC2BotFactory(protocol.ReconnectingClientFactory): - """ - Creates instances of the IMC2Protocol. Should really only ever - need to create one connection. Tied in via evennia/server.py. - - """ - initialDelay = 1 - factor = 1.5 - maxDelay = 60 - - def __init__(self, sessionhandler, uid=None, network=None, channel=None, - port=None, mudname=None, client_pwd=None, server_pwd=None): - "Initialize the bot factory." - self.uid = uid - self.network = network - sname, host = network.split(".", 1) - self.servername = sname.strip() - self.channel = channel - self.port = port - self.mudname = mudname - self.protocol_version = '2' - self.client_pwd = client_pwd - self.server_pwd = server_pwd - self.bot = None - self.task_isalive = None - self.task_keepalive = None - self.task_prune = None - self.task_channellist = None - - def buildProtocol(self, addr): - """ - Build the protocol. - - Args: - addr (str): Protocl address. - - Returns: - protocol (Protocol): The new protocol. - - """ - protocol = IMC2Bot() - protocol.factory = self - protocol.network = self.network - protocol.servername = self.servername - protocol.channel = self.channel - protocol.mudname = self.mudname - protocol.port = self.port - return protocol - - def clientConnectionFailed(self, connector, reason): - """ - Called when Client could not connect. - - Args: - connector (Connector): Reprsents the connection. - reason (str): Reason for the failure. - """ - self.retry(connector) - - def clientConnectionLost(self, connector, reason): - """ - Called when Client looses connection. - - Args: - connector (Connector): Reprsents the connection. - reason (str): Reason for the failure. - """ - if not self.bot.stopping: - self.retry(connector) - - def start(self): - "Connect session to sessionhandler" - def errback(fail): - logger.log_err(fail.value) - - if self.port: - service = internet.TCPClient(self.network, int(self.port), self) - self.sessionhandler.portal.services.addService(service) - # start tasks - self.task_isalive = task.LoopingCall(self.bot._isalive) - self.task_keepalive = task.LoopingCall(self.bot._keepalive) - self.task_prune = task.LoopingCall(self.bot._prune) - self.task_channellist = task.LoopingCall(self.bot._channellist) - self.task_isalive.start(900, now=False) - self.task_keepalive.start(3500, now=False) - self.task_prune.start(1800, now=False) - self.task_channellist.start(3600 * 24, now=False) - diff --git a/evennia/server/portal/imc2lib/__init__.py b/evennia/server/portal/imc2lib/__init__.py deleted file mode 100644 index 40a96afc6f..0000000000 --- a/evennia/server/portal/imc2lib/__init__.py +++ /dev/null @@ -1 +0,0 @@ -# -*- coding: utf-8 -*- diff --git a/evennia/server/portal/imc2lib/imc2_ansi.py b/evennia/server/portal/imc2lib/imc2_ansi.py deleted file mode 100644 index 23deb704e3..0000000000 --- a/evennia/server/portal/imc2lib/imc2_ansi.py +++ /dev/null @@ -1,60 +0,0 @@ -""" -ANSI parser - this adds colour to text according to -special markup strings. - -This is a IMC2 complacent version. -""" - -import re -from evennia.utils import ansi - - -class IMCANSIParser(ansi.ANSIParser): - """ - This parser is per the IMC2 specification. - """ - def __init__(self): - normal = ansi.ANSI_NORMAL - hilite = ansi.ANSI_HILITE - self.ansi_map = [ - (r'~Z', normal), # Random - (r'~x', normal + ansi.ANSI_BLACK), # Black - (r'~D', hilite + ansi.ANSI_BLACK), # Dark Grey - (r'~z', hilite + ansi.ANSI_BLACK), - (r'~w', normal + ansi.ANSI_WHITE), # Grey - (r'~W', hilite + ansi.ANSI_WHITE), # White - (r'~g', normal + ansi.ANSI_GREEN), # Dark Green - (r'~G', hilite + ansi.ANSI_GREEN), # Green - (r'~p', normal + ansi.ANSI_MAGENTA), # Dark magenta - (r'~m', normal + ansi.ANSI_MAGENTA), - (r'~M', hilite + ansi.ANSI_MAGENTA), # Magenta - (r'~P', hilite + ansi.ANSI_MAGENTA), - (r'~c', normal + ansi.ANSI_CYAN), # Cyan - (r'~y', normal + ansi.ANSI_YELLOW), # Dark Yellow (brown) - (r'~Y', hilite + ansi.ANSI_YELLOW), # Yellow - (r'~b', normal + ansi.ANSI_BLUE), # Dark Blue - (r'~B', hilite + ansi.ANSI_BLUE), # Blue - (r'~C', hilite + ansi.ANSI_BLUE), - (r'~r', normal + ansi.ANSI_RED), # Dark Red - (r'~R', hilite + ansi.ANSI_RED), # Red - - ## Formatting - (r'~L', hilite), # Bold/hilite - (r'~!', normal), # reset - (r'\\r', normal), - (r'\\n', ansi.ANSI_RETURN), - ] - # prepare regex matching - self.ansi_sub = [(re.compile(sub[0], re.DOTALL), sub[1]) - for sub in self.ansi_map] - # prepare matching ansi codes overall - self.ansi_regex = re.compile("\033\[[0-9;]+m") - -ANSI_PARSER = IMCANSIParser() - - -def parse_ansi(string, strip_ansi=False, parser=ANSI_PARSER): - """ - Shortcut to use the IMC2 ANSI parser. - """ - return parser.parse_ansi(string, strip_ansi=strip_ansi) diff --git a/evennia/server/portal/imc2lib/imc2_packets.py b/evennia/server/portal/imc2lib/imc2_packets.py deleted file mode 100644 index f4d8dede3f..0000000000 --- a/evennia/server/portal/imc2lib/imc2_packets.py +++ /dev/null @@ -1,797 +0,0 @@ -""" -IMC2 packets. These are pretty well documented at: -http://www.mudbytes.net/index.php?a=articles&s=imc2_protocol - -""" -from __future__ import print_function -from builtins import object -import shlex -from django.conf import settings - -class Lexxer(shlex.shlex): - """ - A lexical parser for interpreting IMC2 packets. - """ - def __init__(self, packet_str, posix=True): - shlex.shlex.__init__(self, packet_str, posix=True) - # Single-quotes are notably not present. This is important! - self.quotes = '"' - self.commenters = '' - # This helps denote what constitutes a continuous token. - self.wordchars += "~`!@#$%^&*()-_+=[{]}|\\;:',<.>/?" - -class IMC2Packet(object): - """ - Base IMC2 packet class. This is generally sub-classed, aside from using it - to parse incoming packets from the IMC2 network server. - """ - def __init__(self, mudname=None, packet_str=None): - """ - Optionally, parse a packet and load it up. - """ - # The following fields are all according to the basic packet format of: - # @ @ - self.sender = None - if not mudname: - mudname = settings.SERVERNAME - self.origin = mudname - self.sequence = None - self.route = mudname - self.packet_type = None - self.target = None - self.destination = None - # Optional data. - self.optional_data = {} - # Reference to the IMC2Protocol object doing the sending. - self.imc2_protocol = None - - if packet_str: - # The lexxer handles the double quotes correctly, unlike just - # splitting. Spaces throw things off, so shlex handles it - # gracefully, ala POSIX shell-style parsing. - lex = Lexxer(packet_str) - - # Token counter. - counter = 0 - for token in lex: - if counter == 0: - # This is the sender@origin token. - sender_origin = token - split_sender_origin = sender_origin.split('@') - self.sender = split_sender_origin[0].strip() - self.origin = split_sender_origin[1] - elif counter == 1: - # Numeric time-based sequence. - self.sequence = token - elif counter == 2: - # Packet routing info. - self.route = token - elif counter == 3: - # Packet type string. - self.packet_type = token - elif counter == 4: - # Get values for the target and destination attributes. - target_destination = token - split_target_destination = target_destination.split('@') - self.target = split_target_destination[0] - try: - self.destination = split_target_destination[1] - except IndexError: - # There is only one element to the target@dest segment - # of the packet. Wipe the target and move the captured - # value to the destination attrib. - self.target = '*' - self.destination = split_target_destination[0] - elif counter > 4: - # Populate optional data. - try: - key, value = token.split('=', 1) - self.optional_data[key] = value - except ValueError: - # Failed to split on equal sign, disregard. - pass - # Increment and continue to the next token (if applicable) - counter += 1 - - def __str__(self): - retval = """ - --IMC2 package (%s) - Sender: %s - Origin: %s - Sequence: %s - 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): - """ - Generates the optional data string to tack on to the end of the packet. - """ - if self.optional_data: - data_string = '' - for key, value in self.optional_data.items(): - # Determine the number of words in this value. - words = len(str(value).split(' ')) - # Anything over 1 word needs double quotes. - if words > 1: - value = '"%s"' % (value,) - data_string += '%s=%s ' % (key, value) - return data_string.strip() - else: - return '' - - def _get_sender_name(self): - """ - Calculates the sender name to be sent with the packet. - """ - if self.sender == '*': - # Some packets have no sender. - return '*' - elif str(self.sender).isdigit(): - return self.sender - elif type(self.sender) in [type(u""),type(str())]: - #this is used by e.g. IRC where no user object is present. - return self.sender.strip().replace(' ', '_') - elif self.sender: - # Player object. - name = self.sender.get_name(fullname=False, show_dbref=False, - show_flags=False, - no_ansi=True) - # IMC2 does not allow for spaces. - return name.strip().replace(' ', '_') - else: - # None value. Do something or other. - return 'Unknown' - - def assemble(self, mudname=None, client_pwd=None, server_pwd=None): - """ - Assembles the packet and returns the ready-to-send string. - Note that the arguments are not used, they are there for - consistency across all packets. - """ - self.sequence = self.imc2_protocol.sequence - packet = "%s@%s %s %s %s %s@%s %s\n" % ( - self._get_sender_name(), - self.origin, - self.sequence, - self.route, - self.packet_type, - self.target, - self.destination, - self._get_optional_data_string()) - return packet.strip() - - -class IMC2PacketAuthPlaintext(object): - """ - IMC2 plain-text authentication packet. Auth packets are strangely - formatted, so this does not sub-class IMC2Packet. The SHA and plain text - auth packets are the two only non-conformers. - - CLIENT Sends: - PW version= autosetup (SHA256) - - Optional Arguments( required if using the specified authentication method: - (SHA256) The literal string: SHA256. This is sent to notify the server - that the MUD is SHA256-Enabled. All future logins from this - client will be expected in SHA256-AUTH format if the server - supports it. - """ - def assemble(self, mudname=None, client_pwd=None, server_pwd=None): - """ - This is one of two strange packets, just assemble the packet manually - and go. - """ - return 'PW %s %s version=2 autosetup %s\n' %(mudname, client_pwd, server_pwd) - - -class IMC2PacketKeepAliveRequest(IMC2Packet): - """ - Description: - This packet is sent by a MUD to trigger is-alive packets from other MUDs. - This packet is usually followed by the sending MUD's own is-alive packet. - It is used in the filling of a client's MUD list, thus any MUD that doesn't - respond with an is-alive isn't marked as online on the sending MUD's - mudlist. - - Data: - (none) - - Example of a received keepalive-request: - *@YourMUD 1234567890 YourMUD!Hub1 keepalive-request *@* - - Example of a sent keepalive-request: - *@YourMUD 1234567890 YourMUD keepalive-request *@* - """ - def __init__(self): - super(IMC2PacketKeepAliveRequest, self).__init__() - self.sender = '*' - self.packet_type = 'keepalive-request' - self.target = '*' - self.destination = '*' - - -class IMC2PacketIsAlive(IMC2Packet): - """ - Description: - This packet is the reply to a keepalive-request packet. It is responsible - for filling a client's mudlist with the information about other MUDs on the - network. - - Data: - versionid= - Where is the text version ID of the client. ("IMC2 4.5 MUD-Net") - - url= - Where is the proper URL of the client. (http://www.domain.com) - - host= - Where is the telnet address of the MUD. (telnet://domain.com) - - port= - Where is the telnet port of the MUD. - - (These data fields are not sent by the MUD, they are added by the server.) - networkname= - Where is the network name that the MUD/server is on. ("MyNetwork") - - sha256= - This is an optional tag that denotes the SHA-256 capabilities of a - MUD or server. - - Example of a received is-alive: - *@SomeMUD 1234567890 SomeMUD!Hub2 is-alive *@YourMUD versionid="IMC2 4.5 MUD-Net" url="http://www.domain.com" networkname="MyNetwork" sha256=1 host=domain.com port=5500 - - Example of a sent is-alive: - *@YourMUD 1234567890 YourMUD is-alive *@* versionid="IMC2 4.5 MUD-Net" url="http://www.domain.com" host=domain.com port=5500 - """ - def __init__(self): - super(IMC2PacketIsAlive, self).__init__() - self.sender = '*' - self.packet_type = 'is-alive' - self.target = '*' - self.destination = '*' - self.optional_data = {'versionid': 'Evennia IMC2', - 'url': '"http://www.evennia.com"', - 'host': 'test.com', - 'port': '5555'} - - -class IMC2PacketIceRefresh(IMC2Packet): - """ - Description: - This packet is sent by the MUD to request data about the channels on the - network. Servers with channels reply with an ice-update packet for each - channel they control. The usual target for this packet is IMC@$. - - Data: - (none) - - Example: - *@YourMUD 1234567890 YourMUD!Hub1 ice-refresh IMC@$ - """ - def __init__(self): - super(IMC2PacketIceRefresh, self).__init__() - self.sender = '*' - self.packet_type = 'ice-refresh' - self.target = 'IMC' - self.destination = '$' - - -class IMC2PacketIceUpdate(IMC2Packet): - """ - Description: - A server returns this packet with the data of a channel when prompted with - an ice-refresh request. - - Data: - channel= - The channel's network name in the format of ServerName:ChannelName - - owner= - The Name@MUD of the channel's owner - - operators= - A space-seperated list of the Channel's operators, (format: Person@MUD) - - policy= - The policy is either "open" or "private" with no quotes. - - invited= - The space-seperated list of invited User@MUDs, only valid for a - "private" channel. - - excluded= - The space-seperated list of banned User@MUDs, only valid for "open" - channels. - - level= The default level of the channel: Admin, Imp, Imm, - Mort, or None - - localname= The suggested local name of the channel. - - Examples: - - Open Policy: - ICE@Hub1 1234567890 Hub1!Hub2 ice-update *@YourMUD channel=Hub1:ichat owner=Imm@SomeMUD operators=Other@SomeMUD policy=open excluded="Flamer@badMUD Jerk@dirtyMUD" level=Imm localname=ichat - - Private Policy: - ICE@Hub1 1234567890 Hub1!Hub2 ice-update *@YourMUD channel=Hub1:secretchat owner=Imm@SomeMUD operators=Other@SomeMUD policy=private invited="SpecialDude@OtherMUD CoolDude@WeirdMUD" level=Mort localname=schat - """ - pass - - -class IMC2PacketIceMsgRelayed(IMC2Packet): - """ - Description: - The -r in this ice-msg packet means it was relayed. This, along with the - ice-msg-p packet, are used with private policy channels. The 'r' stands - for 'relay'. All incoming channel messages are from ICE@, where - is the server hosting the channel. - - Data: - realfrom= - The User@MUD the message came from. - - channel= - The Server:Channel the message is intended to be displayed on. - - text= - The message text. - - emote= - An integer value designating emotes. 0 for no emote, 1 for an emote, - and 2 for a social. - - Examples: - ICE@Hub1 1234567890 Hub1!Hub2 ice-msg-r *@YourMUD realfrom=You@YourMUD channel=hub1:secret text="Aha! I got it!" emote=0 - - ICE@Hub1 1234567890 Hub1!Hub2 ice-msg-r *@YourMUD realfrom=You@YourMUD channel=hub1:secret text=Ahh emote=0 - - ICE@Hub1 1234567890 Hub1!Hub2 ice-msg-r *@YourMUD realfrom=You@YourMUD channel=hub1:secret text="grins evilly." emote=1 - - ICE@Hub1 1234567890 Hub1!Hub2 ice-msg-r *@YourMUD realfrom=You@YourMUD channel=hub1:secret text="You@YourMUD grins evilly!" emote=2 - """ - pass - - -class IMC2PacketIceMsgPrivate(IMC2Packet): - """ - Description: - This packet is sent when a player sends a message to a private channel. - This packet should never be seen as incoming to a client. The target of - this packet should be IMC@ of the server hosting the channel. - - Data: - channel= - The Server:Channel the message is intended to be displayed on. - - text= - The message text. - - emote= - An integer value designating emotes. 0 for no emote, 1 for an emote, - and 2 for a social. - - echo= - Tells the server to echo the message back to the sending MUD. This is only - seen on out-going messages. - - Examples: - You@YourMUD 1234567890 YourMUD ice-msg-p IMC@Hub1 channel=Hub1:secret text="Ahh! I got it!" emote=0 echo=1 - You@YourMUD 1234567890 YourMUD ice-msg-p IMC@Hub1 channel=Hub1:secret text=Ahh! emote=0 echo=1 - You@YourMUD 1234567890 YourMUD ice-msg-p IMC@Hub1 channel=Hub1:secret text="grins evilly." emote=1 echo=1 - You@YourMUD 1234567890 YourMUD ice-msg-p IMC@Hub1 channel=Hub1:secret text="You@YourMUD grins evilly." emote=2 echo=1 - """ - pass - - -class IMC2PacketIceMsgBroadcasted(IMC2Packet): - """ - Description: - This is the packet used to chat on open policy channels. When sent from a - MUD, it is broadcasted across the network. Other MUDs receive it in-tact - as it was sent by the originating MUD. The server that hosts the channel - sends the packet back to the originating MUD as an 'echo' by removing the - "echo=1" and attaching the "sender=Person@MUD" data field. - - Data: - channel= - The Server:Channel the message is intended to be displayed on. - - text= - The message text. - - emote= - An integer value designating emotes. 0 for no emote, 1 for an emote, - and 2 for a social. - - *echo= - This stays on broadcasted messages. It tells the channel's server to - relay an echo back. - - *sender= - The hosting server replaces "echo=1" with this when sending the echo back - to the originating MUD. - - Examples: - (See above for emote/social examples as they are pretty much the same) - - Return Echo Packet: - You-YourMUD@Hub1 1234567890 Hub1 ice-msg-b *@YourMUD text=Hi! channel=Hub1:ichat sender=You@YourMUD emote=0 - - Broadcasted Packet: - You@YourMUD 1234567890 YourMUD!Hub1 ice-msg-b *@* channel=Hub1:ichat text=Hi! emote=0 echo=1 - """ - def __init__(self, server, channel, pobject, message): - """ - Args: - 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. - """ - super(IMC2PacketIceMsgBroadcasted, self).__init__() - self.sender = pobject - self.packet_type = 'ice-msg-b' - self.target = '*' - self.destination = '*' - self.optional_data = {'channel': '%s:%s' % (server, channel), - 'text': message, - 'emote': 0, - 'echo': 1} - - -class IMC2PacketUserCache(IMC2Packet): - """ - Description: - Sent by a MUD with a new IMC2-able player or when a player's gender changes, - this packet contains only the gender for data. The packet's origination - should be the Player@MUD. - - Data: - gender= 0 is male, 1 is female, 2 is anything else such as neuter. - Will be referred to as "it". - - Example: - Dude@someMUD 1234567890 SomeMUD!Hub2!Hub1 user-cache *@* gender=0 - """ - pass - - -class IMC2PacketUserCacheRequest(IMC2Packet): - """ - Description: - The MUD sends this packet out when making a request for the user-cache - information of the user included in the data part of the packet. - - Data: - user= The Person@MUD whose data the MUD is seeking. - - Example: - *@YourMUD 1234567890 YourMUD user-cache-request *@SomeMUD user=Dude@SomeMUD - """ - pass - - -class IMC2PacketUserCacheReply(IMC2Packet): - """ - Description: - A reply to the user-cache-request packet. It contains the user and gender - for the user. - - Data: - user= - The Person@MUD whose data the MUD requested. - - gender= - The gender of the Person@MUD in the 'user' field. - - Example: - *@someMUD 1234567890 SomeMUD!Hub2!Hub1 user-cache-reply *@YourMUD user=Dude@SomeMUD gender=0 - """ - pass - - -class IMC2PacketTell(IMC2Packet): - """ - Description: - This packet is used to communicate private messages between users on MUDs - across the network. - - Data: - text= Message text - isreply= Two settings: 1 denotes a reply, 2 denotes a tell social. - - Example: - - Originating: - You@YourMUD 1234567890 YourMUD tell Dude@SomeMUD text="Having fun?" - - Reply from Dude: - Dude@SomeMUD 1234567890 SomeMUD!Hub1 tell You@YourMUD text="Yeah, this is cool!" isreply=1 - """ - 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: - This packet seems to be sent by servers when notifying the network of a new - channel or the destruction of a channel. - - Data: - channel= - Unsure of what this means. The channel seen in both creation and - destruction packets is 15. - - level= - I am assuming this is the permission level of the sender. In both - creation and destruction messages, this is -1. - - text= - This is the message to be sent to the users. - - Examples: - ICE@Hub1 1234567890 Hub1 emote *@* channel=15 level=-1 text="the - channel called hub1:test has been destroyed by You@YourMUD." - """ - pass - - -class IMC2PacketRemoteAdmin(IMC2Packet): - """ - Description: - This packet is used in remote server administration. Please note that - SHA-256 Support is *required* for a client to use this feature. The command - can vary, in fact this very packet is highly dependant on the server it's - being directed to. In most cases, sending the 'list' command will have a - remote-admin enabled server send you the list of commands it will accept. - - Data: - command= - The command being sent to the server for processing. - - data= - Data associated with the command. This is not always required. - - hash= - The SHA-256 hash that is verified by the server. This hash is generated in - the same manner as an authentication packet. - - Example: - You@YourMUD 1234567890 YourMUD remote-admin IMC@Hub1 command=list hash= - """ - pass - - -class IMC2PacketIceCmd(IMC2Packet): - """ - Description: - Used for remote channel administration. In most cases, one must be listed - as a channel creator on the target server in order to do much with this - packet. Other cases include channel operators. - - Data: - channel= - The target server:channel for the command. - - command= - The command to be processed. - - data= - Data associated with the command. This is not always required. - - Example: - You@YourMUD 1234567890 YourMUD ice-cmd IMC@hub1 channel=hub1:ichat command=list - """ - pass - - -class IMC2PacketDestroy(IMC2Packet): - """ - Description: - Sent by a server to indicate the destruction of a channel it hosted. - The mud should remove this channel from its local configuration. - - Data: - channel= The server:channel being destroyed. - """ - pass - - -class IMC2PacketWho(IMC2Packet): - """ - Description: - A seemingly mutli-purpose information-requesting packet. The istats - packet currently only works on servers, or at least that's the case on - MUD-Net servers. The 'finger' type takes a player name in addition to the - type name. - - Example: "finger Dude". The 'who' and 'info' types take no argument. - The MUD is responsible for building the reply text sent in the who-reply - packet. - - Data: - type= Types: who, info, "finger ", istats (server only) - - Example: - Dude@SomeMUD 1234567890 SomeMUD!Hub1 who *@YourMUD type=who - """ - pass - - -class IMC2PacketWhoReply(IMC2Packet): - """ - Description: - The multi-purpose reply to the multi-purpose information-requesting 'who' - packet. The MUD is responsible for building the return data, including the - format of it. The mud can use the permission level sent in the original who - packet to filter the output. The example below is the MUD-Net format. - - Data: - text= The formatted reply to a 'who' packet. - - Additional Notes: - The example below is for the who list packet. The same construction would - go into formatting the other types of who packets. - - Example: - *@YourMUD 1234567890 YourMUD who-reply Dude@SomeMUD text="\n\r~R-=< ~WPlayers on YourMUD ~R>=-\n\r ~Y-=< ~Wtelnet://yourmud.domain.com:1234 ~Y>=-\n\r\n\r~B--------------------------------=< ~WPlayers ~B>=---------------------------------\n\r\n\r ~BPlayer ~z<--->~G Mortal the Toy\n\r\n\r~R-------------------------------=< ~WImmortals ~R>=--------------------------------\n\r\n\r ~YStaff ~z<--->~G You the Immortal\n\r\n\r~Y<~W2 Players~Y> ~Y<~WHomepage: http://www.yourmud.com~Y> <~W 2 Max Since Reboot~Y>\n\r~Y<~W3 logins since last reboot on Tue Feb 24, 2004 6:55:59 PM EST~Y>" - """ - pass - - -class IMC2PacketWhois(IMC2Packet): - """ - Description: - Sends a request to the network for the location of the specified player. - - Data: - level= The permission level of the person making the request. - - Example: - You@YourMUD 1234567890 YourMUD whois dude@* level=5 - """ - def __init__(self, pobject_id, whois_target): - super(IMC2PacketWhois, self).__init__() - # Use the dbref, it's easier to trace back for the whois-reply. - self.sender = pobject_id - self.packet_type = 'whois' - self.target = whois_target - self.destination = '*' - self.optional_data = {'level': '5'} - - -class IMC2PacketWhoisReply(IMC2Packet): - """ - Description: - The reply to a whois packet. The MUD is responsible for building and formatting - the text sent back to the requesting player, and can use the permission level - sent in the original whois packet to filter or block the response. - - Data: - text= The whois text. - - Example: - *@SomeMUD 1234567890 SomeMUD!Hub1 whois-reply You@YourMUD text="~RIMC Locate: ~YDude@SomeMUD: ~cOnline.\n\r" - """ - pass - - -class IMC2PacketBeep(IMC2Packet): - """ - Description: - Sends out a beep packet to the Player@MUD. The client receiving this should - then send a bell-character to the target player to 'beep' them. - - Example: - You@YourMUD 1234567890 YourMUD beep dude@somemud - """ - pass - - -class IMC2PacketIceChanWho(IMC2Packet): - """ - Description: - Sends a request to the specified MUD or * to list all the users listening - to the specified channel. - - Data: - level= - Sender's permission level. - - channel= - The server:chan name of the channel. - - lname= - The localname of the channel. - - Example: - You@YourMUD 1234567890 YourMUD ice-chan-who somemud level=5 channel=Hub1:ichat lname=ichat - """ - pass - - -class IMC2PacketIceChanWhoReply(IMC2Packet): - """ - Description: - This is the reply packet for an ice-chan-who. The MUD is responsible for - creating and formatting the list sent back in the 'list' field. The - permission level sent in the original ice-chan-who packet can be used to - filter or block the response. - - Data: - channel= - The server:chan of the requested channel. - - list= - The formatted list of local listeners for that MUD. - - Example: - *@SomeMUD 1234567890 SomeMUD!Hub1 ice-chan-whoreply You@YourMUD channel=Hub1:ichat list="The following people are listening to ichat on SomeMUD:\n\r\n\rDude\n\r" - """ - pass - - -class IMC2PacketLaston(IMC2Packet): - """ - Description: - This packet queries the server the mud is connected to to find out when a - specified user was last seen by the network on a public channel. - - Data: - username= The user, user@mud, or "all" being queried. Responses - to this packet will be sent by the server in the form of a series of tells. - - Example: User@MUD 1234567890 MUD imc-laston SERVER username=somenamehere - """ - pass - - -class IMC2PacketCloseNotify(IMC2Packet): - """ - Description: - This packet alerts the network when a server or MUD has disconnected. The - server hosting the server or MUD is responsible for sending this packet - out across the network. Clients need only process the packet to remove the - disconnected MUD from their MUD list (or mark it as Disconnected). - - Data: - host= - The MUD or server that has disconnected from the network. - - Example: - *@Hub2 1234567890 Hub2!Hub1 close-notify *@* host=DisconnMUD - """ - pass - -if __name__ == "__main__": - packstr = "Kayle@MW 1234567 MW!Server02!Server01 ice-msg-b *@* channel=Server01:ichat text=\"*they're going woot\" emote=0 echo=1" - packstr = "*@Lythelian 1234567 Lythelian!Server01 is-alive *@* versionid=\"Tim's LPC IMC2 client 30-Jan-05 / Dead Souls integrated\" networkname=Mudbytes url=http://dead-souls.net host=70.32.76.142 port=6666 sha256=0" - print(IMC2Packet(packstr)) - diff --git a/evennia/server/portal/mssp.py b/evennia/server/portal/mssp.py index 62a8805ec2..d8c699cfe8 100644 --- a/evennia/server/portal/mssp.py +++ b/evennia/server/portal/mssp.py @@ -114,7 +114,6 @@ class Mssp(object): # Roleplaying, Simulation, Social or Strategy "STATUS": "Open Beta", # Alpha, Closed Beta, Open Beta, Live "GAMESYSTEM": "Custom", # D&D, d20 System, World of Darkness, etc. Use Custom if homebrew - "INTERMUD": "IMC2", # evennia supports IMC2. "SUBGENRE": "None", # LASG, Medieval Fantasy, World War II, Frankenstein, # Cyberpunk, Dragonlance, etc. Or None if not available. diff --git a/evennia/server/portal/portalsessionhandler.py b/evennia/server/portal/portalsessionhandler.py index e423635769..5ef4a66e63 100644 --- a/evennia/server/portal/portalsessionhandler.py +++ b/evennia/server/portal/portalsessionhandler.py @@ -201,7 +201,7 @@ class PortalSessionHandler(SessionHandler): Called by server to force the initialization of a new protocol instance. Server wants this instance to get a unique sessid and to be connected back as normal. This is used to initiate - irc/imc2/rss etc connections. + irc/rss etc connections. Args: protocol_path (st): Full python path to the class factory diff --git a/evennia/server/server.py b/evennia/server/server.py index e4525f5651..028447daa9 100644 --- a/evennia/server/server.py +++ b/evennia/server/server.py @@ -76,7 +76,6 @@ GUEST_ENABLED = settings.GUEST_ENABLED # server-channel mappings WEBSERVER_ENABLED = settings.WEBSERVER_ENABLED and WEBSERVER_PORTS and WEBSERVER_INTERFACES -IMC2_ENABLED = settings.IMC2_ENABLED IRC_ENABLED = settings.IRC_ENABLED RSS_ENABLED = settings.RSS_ENABLED WEBCLIENT_ENABLED = settings.WEBCLIENT_ENABLED @@ -537,10 +536,6 @@ if IRC_ENABLED: # IRC channel connections ENABLED.append('irc') -if IMC2_ENABLED: - # IMC2 channel connections - ENABLED.append('imc2') - if RSS_ENABLED: # RSS feed channel connections ENABLED.append('rss') diff --git a/evennia/settings_default.py b/evennia/settings_default.py index a7d73aacf7..3fdbd9b332 100644 --- a/evennia/settings_default.py +++ b/evennia/settings_default.py @@ -520,8 +520,8 @@ DEFAULT_CHANNELS = [ # Note: You do *not* have to make your MUD open to # the public to use the external connections, they # operate as long as you have an internet connection, -# just like stand-alone chat clients. IRC and IMC2 -# requires that you have twisted.words installed. +# just like stand-alone chat clients. IRC requires +# that you have twisted.words installed. # Evennia can connect to external IRC channels and # echo what is said on the channel to IRC and vice @@ -537,26 +537,6 @@ IRC_ENABLED = False RSS_ENABLED=False RSS_UPDATE_INTERVAL = 60*10 # 10 minutes -# IMC (Inter-MUD communication) allows to connect an Evennia channel -# to an IMC2 server. This lets them talk to people on other MUDs also -# using IMC. Evennia's IMC2 client was developed against MudByte's -# network. You must register your MUD on the network before you can -# use it, go to http://www.mudbytes.net/imc2-intermud-join-network. -# Choose 'Other unsupported IMC2 version' from the choices and and -# enter your information there. You should enter the same 'short mud -# name' as your SERVERNAME above, then choose imc network server as -# well as client/server passwords same as below. When enabled, the -# command @imc2chan becomes available in-game and allows you to -# connect Evennia channels to IMC channels on the network. The Evennia -# discussion channel 'ievennia' is on server01.mudbytes.net:5000. - -# NOTE - IMC2 is currently NOT FUNCTIONAL due to lack of testing means. -IMC2_ENABLED = False -IMC2_NETWORK = "server01.mudbytes.net" -IMC2_PORT = 5000 # this is the imc2 port, not on localhost -IMC2_CLIENT_PWD = "" -IMC2_SERVER_PWD = "" - ###################################################################### # Django web features ###################################################################### diff --git a/evennia/web/utils/general_context.py b/evennia/web/utils/general_context.py index b3bc313731..b5b5a1b69c 100644 --- a/evennia/web/utils/general_context.py +++ b/evennia/web/utils/general_context.py @@ -28,7 +28,7 @@ except AttributeError: PLAYER_RELATED = ['Players'] GAME_ENTITIES = ['Objects', 'Scripts', 'Comms', 'Help'] GAME_SETUP = ['Permissions', 'Config'] -CONNECTIONS = ['Irc', 'Imc2'] +CONNECTIONS = ['Irc'] WEBSITE = ['Flatpages', 'News', 'Sites']