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.
This commit is contained in:
parent
0554492b79
commit
4424dec668
20 changed files with 9 additions and 1786 deletions
|
|
@ -70,6 +70,3 @@ class PlayerCmdSet(CmdSet):
|
||||||
self.add(comms.CmdPage())
|
self.add(comms.CmdPage())
|
||||||
self.add(comms.CmdIRC2Chan())
|
self.add(comms.CmdIRC2Chan())
|
||||||
self.add(comms.CmdRSS2Chan())
|
self.add(comms.CmdRSS2Chan())
|
||||||
#self.add(comms.CmdIMC2Chan())
|
|
||||||
#self.add(comms.CmdIMCInfo())
|
|
||||||
#self.add(comms.CmdIMCTell())
|
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,6 @@ for easy handling.
|
||||||
from past.builtins import cmp
|
from past.builtins import cmp
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from evennia.comms.models import ChannelDB, Msg
|
from evennia.comms.models import ChannelDB, Msg
|
||||||
#from evennia.comms import irc, imc2, rss
|
|
||||||
from evennia.players.models import PlayerDB
|
from evennia.players.models import PlayerDB
|
||||||
from evennia.players import bots
|
from evennia.players import bots
|
||||||
from evennia.comms.channelhandler import CHANNELHANDLER
|
from evennia.comms.channelhandler import CHANNELHANDLER
|
||||||
|
|
@ -24,8 +23,7 @@ COMMAND_DEFAULT_CLASS = class_from_module(settings.COMMAND_DEFAULT_CLASS)
|
||||||
__all__ = ("CmdAddCom", "CmdDelCom", "CmdAllCom",
|
__all__ = ("CmdAddCom", "CmdDelCom", "CmdAllCom",
|
||||||
"CmdChannels", "CmdCdestroy", "CmdCBoot", "CmdCemit",
|
"CmdChannels", "CmdCdestroy", "CmdCBoot", "CmdCemit",
|
||||||
"CmdCWho", "CmdChannelCreate", "CmdClock", "CmdCdesc",
|
"CmdCWho", "CmdChannelCreate", "CmdClock", "CmdCdesc",
|
||||||
"CmdPage", "CmdIRC2Chan", "CmdRSS2Chan")#, "CmdIMC2Chan", "CmdIMCInfo",
|
"CmdPage", "CmdIRC2Chan", "CmdRSS2Chan")
|
||||||
#"CmdIMCTell")
|
|
||||||
_DEFAULT_WIDTH = settings.CLIENT_DEFAULT_WIDTH
|
_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 = create.create_player(botname, None, None, typeclass=bots.RSSBot)
|
||||||
bot.start(ev_channel=channel, rss_url=url, rss_rate=10)
|
bot.start(ev_channel=channel, rss_url=url, rss_rate=10)
|
||||||
self.msg("RSS reporter created. Fetching RSS.")
|
self.msg("RSS reporter created. Fetching RSS.")
|
||||||
|
|
||||||
|
|
||||||
#class CmdIMC2Chan(COMMAND_DEFAULT_CLASS):
|
|
||||||
# """
|
|
||||||
# link an evennia channel to an external IMC2 channel
|
|
||||||
#
|
|
||||||
# Usage:
|
|
||||||
# @imc2chan[/switches] <evennia_channel> = <imc2_channel>
|
|
||||||
#
|
|
||||||
# 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] <evennia_channel> = <imc2_channel>"
|
|
||||||
# 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 <playername> - 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 <playername>")
|
|
||||||
# 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 = <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)"
|
|
||||||
# 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 = <msg>"
|
|
||||||
# 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))
|
|
||||||
#
|
|
||||||
#
|
|
||||||
|
|
|
||||||
|
|
@ -44,7 +44,6 @@ MSSPTable = {
|
||||||
# Roleplaying, Simulation, Social or Strategy
|
# Roleplaying, Simulation, Social or Strategy
|
||||||
"STATUS": "Open Beta", # Alpha, Closed Beta, Open Beta, Live
|
"STATUS": "Open Beta", # Alpha, Closed Beta, Open Beta, Live
|
||||||
"GAMESYSTEM": "Custom", # D&D, d20 System, World of Darkness, etc. Use Custom if homebrew
|
"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,
|
"SUBGENRE": "None", # LASG, Medieval Fantasy, World War II, Frankenstein,
|
||||||
# Cyberpunk, Dragonlance, etc. Or None if not available.
|
# Cyberpunk, Dragonlance, etc. Or None if not available.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -240,24 +240,6 @@ msgstr "Utilisateur #1."
|
||||||
msgid "Limbo"
|
msgid "Limbo"
|
||||||
msgstr "Limbes."
|
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
|
#: server/sessionhandler.py:258
|
||||||
msgid " ... Server restarted."
|
msgid " ... Server restarted."
|
||||||
msgstr " ... Serveur redémarré."
|
msgstr " ... Serveur redémarré."
|
||||||
|
|
|
||||||
|
|
@ -241,24 +241,6 @@ msgstr "Questo è l'Utente #1."
|
||||||
msgid "Limbo"
|
msgid "Limbo"
|
||||||
msgstr "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
|
#: .\server\sessionhandler.py:192
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "Connection dropped: %s %s (%s)"
|
msgid "Connection dropped: %s %s (%s)"
|
||||||
|
|
|
||||||
|
|
@ -231,24 +231,6 @@ msgstr "Este é o Usuário #1."
|
||||||
msgid "Limbo"
|
msgid "Limbo"
|
||||||
msgstr "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
|
#: server/sessionhandler.py:244
|
||||||
msgid " ... Server restarted."
|
msgid " ... Server restarted."
|
||||||
msgstr " ... Servidor reiniciado."
|
msgstr " ... Servidor reiniciado."
|
||||||
|
|
|
||||||
|
|
@ -230,24 +230,6 @@ msgstr "Detta är användare #1."
|
||||||
msgid "Limbo"
|
msgid "Limbo"
|
||||||
msgstr "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
|
#: server/sessionhandler.py:221
|
||||||
msgid " ... Server restarted."
|
msgid " ... Server restarted."
|
||||||
msgstr "... Servern startades om."
|
msgstr "... Servern startades om."
|
||||||
|
|
@ -373,29 +355,12 @@ msgstr "Timeout. Kopplar ur."
|
||||||
#~ msgid " (exit to %s)"
|
#~ msgid " (exit to %s)"
|
||||||
#~ msgstr "(utgång till %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."
|
#~ msgid "Successfully authenticated to the '%s' network."
|
||||||
#~ msgstr "Identifierade sig framgångsrikt till nätverket '%s'."
|
#~ msgstr "Identifierade sig framgångsrikt till nätverket '%s'."
|
||||||
|
|
||||||
#~ msgid "Connection lost: %s"
|
#~ msgid "Connection lost: %s"
|
||||||
#~ msgstr "Uppkopplingen förlorades: %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."
|
#~ msgid "joined %s."
|
||||||
#~ msgstr "lyssnar till %s."
|
#~ msgstr "lyssnar till %s."
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -312,100 +312,3 @@ class RSSBot(Bot):
|
||||||
self.ndb.ev_channel = self.db.ev_channel
|
self.ndb.ev_channel = self.db.ev_channel
|
||||||
if self.ndb.ev_channel:
|
if self.ndb.ev_channel:
|
||||||
self.ndb.ev_channel.msg(text, senders=self.id)
|
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)
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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_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_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_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_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)),
|
('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')),
|
('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')),
|
||||||
|
|
|
||||||
|
|
@ -91,7 +91,7 @@ class PlayerDB(TypedObject, AbstractUser):
|
||||||
db_cmdset_storage = models.CharField('cmdset', max_length=255, null=True,
|
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.")
|
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
|
# 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
|
# Database manager
|
||||||
objects = PlayerDBManager()
|
objects = PlayerDBManager()
|
||||||
|
|
|
||||||
|
|
@ -48,7 +48,7 @@ SDISCONN = chr(5) # server session disconnect
|
||||||
SDISCONNALL = chr(6) # server session disconnect all
|
SDISCONNALL = chr(6) # server session disconnect all
|
||||||
SSHUTD = chr(7) # server shutdown
|
SSHUTD = chr(7) # server shutdown
|
||||||
SSYNC = chr(8) # server session sync
|
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
|
PCONNSYNC = chr(12) # portal post-syncing a session
|
||||||
PDISCONNALL = chr(13) # portal session disconnect all
|
PDISCONNALL = chr(13) # portal session disconnect all
|
||||||
AMP_MAXLEN = amp.MAX_VALUE_LENGTH # max allowed data length in AMP protocol (cannot be changed)
|
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
|
# set a flag in case we are about to shut down soon
|
||||||
self.factory.server_restart_mode = True
|
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)
|
portal_sessionhandler.server_connect(**kwargs)
|
||||||
|
|
||||||
else:
|
else:
|
||||||
|
|
|
||||||
|
|
@ -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 <servername> <serverpw> version=<version#> <networkname>
|
|
||||||
|
|
||||||
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)
|
|
||||||
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
|
|
@ -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)
|
|
||||||
|
|
@ -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:
|
|
||||||
# <sender>@<origin> <sequence> <route> <packet-type> <target>@<destination> <data...>
|
|
||||||
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 <mudname> <clientpw> version=<version#> autosetup <serverpw> (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=<string>
|
|
||||||
Where <string> is the text version ID of the client. ("IMC2 4.5 MUD-Net")
|
|
||||||
|
|
||||||
url=<string>
|
|
||||||
Where <string> is the proper URL of the client. (http://www.domain.com)
|
|
||||||
|
|
||||||
host=<string>
|
|
||||||
Where <string> is the telnet address of the MUD. (telnet://domain.com)
|
|
||||||
|
|
||||||
port=<int>
|
|
||||||
Where <int> is the telnet port of the MUD.
|
|
||||||
|
|
||||||
(These data fields are not sent by the MUD, they are added by the server.)
|
|
||||||
networkname=<string>
|
|
||||||
Where <string> is the network name that the MUD/server is on. ("MyNetwork")
|
|
||||||
|
|
||||||
sha256=<int>
|
|
||||||
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=<string>
|
|
||||||
The channel's network name in the format of ServerName:ChannelName
|
|
||||||
|
|
||||||
owner=<string>
|
|
||||||
The Name@MUD of the channel's owner
|
|
||||||
|
|
||||||
operators=<string>
|
|
||||||
A space-seperated list of the Channel's operators, (format: Person@MUD)
|
|
||||||
|
|
||||||
policy=<string>
|
|
||||||
The policy is either "open" or "private" with no quotes.
|
|
||||||
|
|
||||||
invited=<string>
|
|
||||||
The space-seperated list of invited User@MUDs, only valid for a
|
|
||||||
"private" channel.
|
|
||||||
|
|
||||||
excluded=<string>
|
|
||||||
The space-seperated list of banned User@MUDs, only valid for "open"
|
|
||||||
channels.
|
|
||||||
|
|
||||||
level=<string> The default level of the channel: Admin, Imp, Imm,
|
|
||||||
Mort, or None
|
|
||||||
|
|
||||||
localname=<string> 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@<server>, where
|
|
||||||
<server> is the server hosting the channel.
|
|
||||||
|
|
||||||
Data:
|
|
||||||
realfrom=<string>
|
|
||||||
The User@MUD the message came from.
|
|
||||||
|
|
||||||
channel=<string>
|
|
||||||
The Server:Channel the message is intended to be displayed on.
|
|
||||||
|
|
||||||
text=<string>
|
|
||||||
The message text.
|
|
||||||
|
|
||||||
emote=<int>
|
|
||||||
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@<server> of the server hosting the channel.
|
|
||||||
|
|
||||||
Data:
|
|
||||||
channel=<string>
|
|
||||||
The Server:Channel the message is intended to be displayed on.
|
|
||||||
|
|
||||||
text=<string>
|
|
||||||
The message text.
|
|
||||||
|
|
||||||
emote=<int>
|
|
||||||
An integer value designating emotes. 0 for no emote, 1 for an emote,
|
|
||||||
and 2 for a social.
|
|
||||||
|
|
||||||
echo=<int>
|
|
||||||
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=<string>
|
|
||||||
The Server:Channel the message is intended to be displayed on.
|
|
||||||
|
|
||||||
text=<string>
|
|
||||||
The message text.
|
|
||||||
|
|
||||||
emote=<int>
|
|
||||||
An integer value designating emotes. 0 for no emote, 1 for an emote,
|
|
||||||
and 2 for a social.
|
|
||||||
|
|
||||||
*echo=<int>
|
|
||||||
This stays on broadcasted messages. It tells the channel's server to
|
|
||||||
relay an echo back.
|
|
||||||
|
|
||||||
*sender=<string>
|
|
||||||
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=<int> 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=<string> 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=<string>
|
|
||||||
The Person@MUD whose data the MUD requested.
|
|
||||||
|
|
||||||
gender=<int>
|
|
||||||
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=<string> Message text
|
|
||||||
isreply=<int> 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=<int>
|
|
||||||
Unsure of what this means. The channel seen in both creation and
|
|
||||||
destruction packets is 15.
|
|
||||||
|
|
||||||
level=<int>
|
|
||||||
I am assuming this is the permission level of the sender. In both
|
|
||||||
creation and destruction messages, this is -1.
|
|
||||||
|
|
||||||
text=<string>
|
|
||||||
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=<string>
|
|
||||||
The command being sent to the server for processing.
|
|
||||||
|
|
||||||
data=<string>
|
|
||||||
Data associated with the command. This is not always required.
|
|
||||||
|
|
||||||
hash=<string>
|
|
||||||
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=<hash goes here>
|
|
||||||
"""
|
|
||||||
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=<string>
|
|
||||||
The target server:channel for the command.
|
|
||||||
|
|
||||||
command=<string>
|
|
||||||
The command to be processed.
|
|
||||||
|
|
||||||
data=<string>
|
|
||||||
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=<string> 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=<string> Types: who, info, "finger <name>", 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=<string> 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=<int> 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=<string> 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=<int>
|
|
||||||
Sender's permission level.
|
|
||||||
|
|
||||||
channel=<string>
|
|
||||||
The server:chan name of the channel.
|
|
||||||
|
|
||||||
lname=<string>
|
|
||||||
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=<string>
|
|
||||||
The server:chan of the requested channel.
|
|
||||||
|
|
||||||
list=<string>
|
|
||||||
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=<string> 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=<string>
|
|
||||||
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))
|
|
||||||
|
|
||||||
|
|
@ -114,7 +114,6 @@ class Mssp(object):
|
||||||
# Roleplaying, Simulation, Social or Strategy
|
# Roleplaying, Simulation, Social or Strategy
|
||||||
"STATUS": "Open Beta", # Alpha, Closed Beta, Open Beta, Live
|
"STATUS": "Open Beta", # Alpha, Closed Beta, Open Beta, Live
|
||||||
"GAMESYSTEM": "Custom", # D&D, d20 System, World of Darkness, etc. Use Custom if homebrew
|
"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,
|
"SUBGENRE": "None", # LASG, Medieval Fantasy, World War II, Frankenstein,
|
||||||
# Cyberpunk, Dragonlance, etc. Or None if not available.
|
# Cyberpunk, Dragonlance, etc. Or None if not available.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -201,7 +201,7 @@ class PortalSessionHandler(SessionHandler):
|
||||||
Called by server to force the initialization of a new protocol
|
Called by server to force the initialization of a new protocol
|
||||||
instance. Server wants this instance to get a unique sessid
|
instance. Server wants this instance to get a unique sessid
|
||||||
and to be connected back as normal. This is used to initiate
|
and to be connected back as normal. This is used to initiate
|
||||||
irc/imc2/rss etc connections.
|
irc/rss etc connections.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
protocol_path (st): Full python path to the class factory
|
protocol_path (st): Full python path to the class factory
|
||||||
|
|
|
||||||
|
|
@ -76,7 +76,6 @@ GUEST_ENABLED = settings.GUEST_ENABLED
|
||||||
|
|
||||||
# server-channel mappings
|
# server-channel mappings
|
||||||
WEBSERVER_ENABLED = settings.WEBSERVER_ENABLED and WEBSERVER_PORTS and WEBSERVER_INTERFACES
|
WEBSERVER_ENABLED = settings.WEBSERVER_ENABLED and WEBSERVER_PORTS and WEBSERVER_INTERFACES
|
||||||
IMC2_ENABLED = settings.IMC2_ENABLED
|
|
||||||
IRC_ENABLED = settings.IRC_ENABLED
|
IRC_ENABLED = settings.IRC_ENABLED
|
||||||
RSS_ENABLED = settings.RSS_ENABLED
|
RSS_ENABLED = settings.RSS_ENABLED
|
||||||
WEBCLIENT_ENABLED = settings.WEBCLIENT_ENABLED
|
WEBCLIENT_ENABLED = settings.WEBCLIENT_ENABLED
|
||||||
|
|
@ -537,10 +536,6 @@ if IRC_ENABLED:
|
||||||
# IRC channel connections
|
# IRC channel connections
|
||||||
ENABLED.append('irc')
|
ENABLED.append('irc')
|
||||||
|
|
||||||
if IMC2_ENABLED:
|
|
||||||
# IMC2 channel connections
|
|
||||||
ENABLED.append('imc2')
|
|
||||||
|
|
||||||
if RSS_ENABLED:
|
if RSS_ENABLED:
|
||||||
# RSS feed channel connections
|
# RSS feed channel connections
|
||||||
ENABLED.append('rss')
|
ENABLED.append('rss')
|
||||||
|
|
|
||||||
|
|
@ -520,8 +520,8 @@ DEFAULT_CHANNELS = [
|
||||||
# Note: You do *not* have to make your MUD open to
|
# Note: You do *not* have to make your MUD open to
|
||||||
# the public to use the external connections, they
|
# the public to use the external connections, they
|
||||||
# operate as long as you have an internet connection,
|
# operate as long as you have an internet connection,
|
||||||
# just like stand-alone chat clients. IRC and IMC2
|
# just like stand-alone chat clients. IRC requires
|
||||||
# requires that you have twisted.words installed.
|
# that you have twisted.words installed.
|
||||||
|
|
||||||
# Evennia can connect to external IRC channels and
|
# Evennia can connect to external IRC channels and
|
||||||
# echo what is said on the channel to IRC and vice
|
# echo what is said on the channel to IRC and vice
|
||||||
|
|
@ -537,26 +537,6 @@ IRC_ENABLED = False
|
||||||
RSS_ENABLED=False
|
RSS_ENABLED=False
|
||||||
RSS_UPDATE_INTERVAL = 60*10 # 10 minutes
|
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
|
# Django web features
|
||||||
######################################################################
|
######################################################################
|
||||||
|
|
|
||||||
|
|
@ -28,7 +28,7 @@ except AttributeError:
|
||||||
PLAYER_RELATED = ['Players']
|
PLAYER_RELATED = ['Players']
|
||||||
GAME_ENTITIES = ['Objects', 'Scripts', 'Comms', 'Help']
|
GAME_ENTITIES = ['Objects', 'Scripts', 'Comms', 'Help']
|
||||||
GAME_SETUP = ['Permissions', 'Config']
|
GAME_SETUP = ['Permissions', 'Config']
|
||||||
CONNECTIONS = ['Irc', 'Imc2']
|
CONNECTIONS = ['Irc']
|
||||||
WEBSITE = ['Flatpages', 'News', 'Sites']
|
WEBSITE = ['Flatpages', 'News', 'Sites']
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue