Make grapevine connect and work

This commit is contained in:
Griatch 2019-06-23 18:59:45 +02:00
parent 59bc475708
commit 8a6ec779da
8 changed files with 102 additions and 71 deletions

View File

@ -15,7 +15,7 @@ _IDLE_TIMEOUT = settings.IDLE_TIMEOUT
_IRC_ENABLED = settings.IRC_ENABLED
_RSS_ENABLED = settings.RSS_ENABLED
_GRAPEWINE_ENABLED = settings.GRAPEWINE_ENABLED
_GRAPEVINE_ENABLED = settings.GRAPEVINE_ENABLED
_SESSIONS = None
@ -270,10 +270,13 @@ class IRCBot(Bot):
"""
from_obj = kwargs.get("from_obj", None)
options = kwargs.get("options", None) or {}
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_channel" in options and text and
self.ndb.ev_channel.dbid == options["from_channel"]):
if not from_obj or from_obj != [self]:
super().msg(channel=text)
@ -289,13 +292,16 @@ class IRCBot(Bot):
Kwargs:
user (str): The name of the user who sent the message.
channel (str): The name of channel the message was sent to.
type (str): Nature of message. Either 'msg', 'action', 'nicklist' or 'ping'.
nicklist (list, optional): Set if `type='nicklist'`. This is a list of nicks returned by calling
the `self.get_nicklist`. It must look for a list `self._nicklist_callers`
which will contain all callers waiting for the nicklist.
timings (float, optional): Set if `type='ping'`. This is the return (in seconds) of a
ping request triggered with `self.ping`. The return must look for a list
`self._ping_callers` which will contain all callers waiting for the ping return.
type (str): Nature of message. Either 'msg', 'action', 'nicklist'
or 'ping'.
nicklist (list, optional): Set if `type='nicklist'`. This is a list
of nicks returned by calling the `self.get_nicklist`. It must look
for a list `self._nicklist_callers` which will contain all callers
waiting for the nicklist.
timings (float, optional): Set if `type='ping'`. This is the return
(in seconds) of a ping request triggered with `self.ping`. The
return must look for a list `self._ping_callers` which will contain
all callers waiting for the ping return.
"""
if kwargs["type"] == "nicklist":
@ -354,6 +360,7 @@ class IRCBot(Bot):
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)
@ -428,22 +435,22 @@ class RSSBot(Bot):
self.ndb.ev_channel.msg(txt, senders=self.id)
# Grapewine bot
# Grapevine bot
class GrapewineBot(Bot):
class GrapevineBot(Bot):
"""
A Grapewine (https://grapewine.haus) relayer. The channel to connect to is the first
name in the settings.GRAPEWINE_CHANNELS list.
g Grapevine (https://grapevine.haus) relayer. The channel to connect to is the first
name in the settings.GRAPEVINE_CHANNELS list.
"""
factory_path = "evennia.server.portal.grapewine.RestartingWebsocketServerFactory"
factory_path = "evennia.server.portal.grapevine.RestartingWebsocketServerFactory"
def start(self, ev_channel=None, grapewine_channel=None):
def start(self, ev_channel=None, grapevine_channel=None):
"""
Start by telling the portal to connect to the grapewine network.
Start by telling the portal to connect to the grapevine network.
"""
if not _GRAPEWINE_ENABLED:
if not _GRAPEVINE_ENABLED:
self.delete()
return
@ -461,12 +468,12 @@ class GrapewineBot(Bot):
channel.connect(self)
self.db.ev_channel = channel
if grapewine_channel:
self.db.grapewine_channel = grapewine_channel
if grapevine_channel:
self.db.grapevine_channel = grapevine_channel
# these will be made available as properties on the protocol factory
configdict = {"uid": self.dbid,
"grapewine_channel": self.db.grapewine_channel}
"grapevine_channel": self.db.grapevine_channel}
_SESSIONS.start_bot_session(self.factory_path, configdict)
@ -489,16 +496,25 @@ class GrapewineBot(Bot):
"""
from_obj = kwargs.get("from_obj", None)
options = kwargs.get("options", None) or {}
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 not from_obj or from_obj != [self]:
# send outputfunc text(msg, chan, sender)
super().msg(text=(text, self.db.grapewine_channel, from_obj.key))
# send outputfunc channel(msg, chan, sender)
def execute_cmd(self, txt=None, session=None, event=None, grapewine_channel=None,
# TODO we should refactor channel formatting to operate on the
# account/object level instead. For now, remove the channel/name
# prefix since we pass that explicitly anyway
prefix, text = text.split(":", 1)
super().msg(channel=(text.strip(), self.db.grapevine_channel,
", ".join(obj.key for obj in from_obj), {}))
def execute_cmd(self, txt=None, session=None, event=None, grapevine_channel=None,
sender=None, game=None, **kwargs):
"""
Take incoming data from protocol and send it to connected channel. This is

View File

@ -74,4 +74,4 @@ class AccountCmdSet(CmdSet):
self.add(comms.CmdIRC2Chan())
self.add(comms.CmdIRCStatus())
self.add(comms.CmdRSS2Chan())
self.add(comms.CmdGrapewine2Chan())
self.add(comms.CmdGrapevine2Chan())

View File

@ -1094,58 +1094,58 @@ class CmdRSS2Chan(COMMAND_DEFAULT_CLASS):
self.msg("RSS reporter created. Fetching RSS.")
class CmdGrapewine2Chan(COMMAND_DEFAULT_CLASS):
class CmdGrapevine2Chan(COMMAND_DEFAULT_CLASS):
"""
Link an Evennia channel to an exteral Grapewine channel
Link an Evennia channel to an exteral Grapevine channel
Usage:
grapewine2chan[/switches] <evennia_channel> = <grapewine_channel>
grapewine2chan/disconnect <connection #id>
grapevine2chan[/switches] <evennia_channel> = <grapevine_channel>
grapevine2chan/disconnect <connection #id>
Switches:
/list - (or no switch): show existing grapewine <-> Evennia
mappings and available grapewine chans
/list - (or no switch): show existing grapevine <-> Evennia
mappings and available grapevine chans
/remove - alias to disconnect
/delete - alias to disconnect
Example:
grapewine2chan mygrapewine = gossip
grapevine2chan mygrapevine = gossip
This creates a link between an in-game Evennia channel and an external
Grapewine channel. The game must be registered with the Grapewine network
(register at https://grapewine.haus) and the GRAPEWINE_* auth information
Grapevine channel. The game must be registered with the Grapevine network
(register at https://grapevine.haus) and the GRAPEVINE_* auth information
must be added to game settings.
"""
key = "grapewine2chan"
key = "grapevine2chan"
switch_options = ("disconnect", "remove", "delete", "list")
locks = "cmd:serversetting(GRAPEWINE_ENABLED) and pperm(Developer)"
locks = "cmd:serversetting(GRAPEVINE_ENABLED) and pperm(Developer)"
help_category = "Comms"
def func(self):
"""Setup the Grapewine channel mapping"""
"""Setup the Grapevine channel mapping"""
if not settings.GRAPEWINE_ENABLED:
self.msg("Set GRAPEWINE_ENABLED=True in settings to enable.")
if not settings.GRAPEVINE_ENABLED:
self.msg("Set GRAPEVINE_ENABLED=True in settings to enable.")
return
if "list" in self.switches:
# show all connections
gwbots = [bot for bot in
AccountDB.objects.filter(db_is_bot=True,
username__startswith="grapewinebot-")]
username__startswith="grapevinebot-")]
if gwbots:
table = self.styled_table("|wdbid|n", "|wev-channel",
"|wgw-channel|n", border="cells", maxwidth=_DEFAULT_WIDTH)
for gwbot in gwbots:
table.add_row(gwbot.id, gwbot.db.ev_channel, gwbot.db.grapewine_channel)
table.add_row(gwbot.id, gwbot.db.ev_channel, gwbot.db.grapevine_channel)
self.msg(table)
else:
self.msg("No grapewine bots found.")
self.msg("No grapevine bots found.")
return
if 'disconnect' in self.switches or 'remove' in self.switches or 'delete' in self.switches:
botname = "grapewinebot-%s" % self.lhs
botname = "grapevinebot-%s" % self.lhs
matches = AccountDB.objects.filter(db_is_bot=True, db_key=botname)
if not matches:
@ -1153,20 +1153,20 @@ class CmdGrapewine2Chan(COMMAND_DEFAULT_CLASS):
matches = AccountDB.objects.filter(db_is_bot=True, id=self.args.lstrip("#"))
if matches:
matches[0].delete()
self.msg("Grapewine connection destroyed.")
self.msg("Grapevine connection destroyed.")
else:
self.msg("Grapewine connection/bot could not be removed, does it exist?")
self.msg("Grapevine connection/bot could not be removed, does it exist?")
return
if not self.args or not self.rhs:
string = "Usage: grapewine2chan[/switches] <evennia_channel> = <grapewine_channel>"
string = "Usage: grapevine2chan[/switches] <evennia_channel> = <grapevine_channel>"
self.msg(string)
return
channel = self.lhs
grapewine_channel = self.rhs
grapevine_channel = self.rhs
botname = "grapewinebot-%s-%s" % (channel, grapewine_channel)
botname = "grapewinebot-%s-%s" % (channel, grapevine_channel)
bot = AccountDB.objects.filter(username__iexact=botname)
if bot:
# re-use existing bot
@ -1174,9 +1174,11 @@ class CmdGrapewine2Chan(COMMAND_DEFAULT_CLASS):
if not bot.is_bot:
self.msg("Account '%s' already exists and is not a bot." % botname)
return
else:
self.msg("Reusing bot '%s' (%s)" % (botname, bot.dbref))
else:
# create a new bot
bot = create.create_account(botname, None, None, typeclass=bots.GrapewineBot)
bot = create.create_account(botname, None, None, typeclass=bots.GrapevineBot)
bot.start(ev_channel=channel, grapewine_channel=grapewine_channel)
self.msg(f"Grapewine connection created {channel} <-> {grapewine_channel}.")
bot.start(ev_channel=channel, grapevine_channel=grapevine_channel)
self.msg(f"Grapevine connection created {channel} <-> {grapevine_channel}.")

View File

@ -1,9 +1,9 @@
# -*- coding: utf-8 -*-
"""
Connection screen
Connection screen
This is the text to show the user when they first connect to the game (before
they log in).
they log in).
To change the login screen in this module, do one of the following:
@ -12,7 +12,7 @@ To change the login screen in this module, do one of the following:
This can be used to produce more dynamic screens.
- Alternatively, define a string variable in the outermost scope of this module
with the connection string that should be displayed. If more than one such
variable is given, Evennia will pick one of them at random.
variable is given, Evennia will pick one of them at random.
The commands available to the user when the connection screen is shown
are defined in evennia.default_cmds.UnloggedinCmdSet. The parsing and display
@ -35,4 +35,4 @@ CONNECTION_SCREEN = """
If you have spaces in your username, enclose it in quotes.
Enter |whelp|n for more info. |wlook|n will re-show this screen.
|b==============================================================|n""" \
.format(settings.SERVERNAME, utils.get_evennia_version())
.format(settings.SERVERNAME, utils.get_evennia_version("short"))

View File

@ -140,7 +140,7 @@ class RSSBotFactory(object):
def start(self):
"""
Called by portalsessionhandler. Starts te bot.
Called by portalsessionhandler. Starts the bot.
"""
def errback(fail):
logger.log_err(fail.value)

View File

@ -72,7 +72,7 @@ GUEST_ENABLED = settings.GUEST_ENABLED
WEBSERVER_ENABLED = settings.WEBSERVER_ENABLED and WEBSERVER_PORTS and WEBSERVER_INTERFACES
IRC_ENABLED = settings.IRC_ENABLED
RSS_ENABLED = settings.RSS_ENABLED
GRAPEWINE_ENABLED = settings.GRAPEWINE_ENABLED
GRAPEVINE_ENABLED = settings.GRAPEVINE_ENABLED
WEBCLIENT_ENABLED = settings.WEBCLIENT_ENABLED
INFO_DICT = {"servername": SERVERNAME, "version": VERSION,
@ -584,9 +584,9 @@ if RSS_ENABLED:
# RSS feed channel connections
ENABLED.append('rss')
if GRAPEWINE_ENABLED:
# Grapewine channel connections
ENABLED.append('grapewine')
if GRAPEVINE_ENABLED:
# Grapevine channel connections
ENABLED.append('grapevine')
if ENABLED:
INFO_DICT["irc_rss"] = ", ".join(ENABLED) + " enabled."

View File

@ -706,21 +706,21 @@ IRC_ENABLED = False
RSS_ENABLED = False
RSS_UPDATE_INTERVAL = 60 * 10 # 10 minutes
# Grapewine (grapewine.haus) is a network for listing MUDs as well as allow
# Grapevine (grapevine.haus) is a network for listing MUDs as well as allow
# users of said MUDs to communicate with each other on shared channels. To use,
# your game must first be registered by logging in and creating a game entry at
# https://grapewine.haus. Evennia links grapewine channels to in-game channels
# with the @grapewine2chan command, available once this flag is set
# Grapewine requires installing the pyopenssl library (pip install pyopenssl)
GRAPEWINE_ENABLED = False
# Grapewine channels to allow connection to. See https://grapevine.haus/chat
# https://grapevine.haus. Evennia links grapevine channels to in-game channels
# with the @grapevine2chan command, available once this flag is set
# Grapevine requires installing the pyopenssl library (pip install pyopenssl)
GRAPEVINE_ENABLED = False
# Grapevine channels to allow connection to. See https://grapevine.haus/chat
# for the available channels. Only channels in this list can be linked to in-game
# channels later.
GRAPEWINE_CHANNELS = ["gossip", "testing"]
# Grapewine authentication. Register your game at https://grapewine.haus to get
GRAPEVINE_CHANNELS = ["gossip", "testing"]
# Grapevine authentication. Register your game at https://grapevine.haus to get
# them. These are secret and should thus be overridden in secret_settings file
GRAPEWINE_CLIENT_ID = ""
GRAPEWINE_CLIENT_SECRET = ""
GRAPEVINE_CLIENT_ID = ""
GRAPEVINE_CLIENT_SECRET = ""
######################################################################
# Django web features

View File

@ -603,16 +603,29 @@ def host_os_is(osname):
return os.name == osname
def get_evennia_version():
def get_evennia_version(mode="long"):
"""
Helper method for getting the current evennia version.
Args:
mode (str, optional): One of:
- long: 0.9.0 rev342453534
- short: 0.9.0
- pretty: Evennia 0.9.0
Returns:
version (str): The version string.
"""
import evennia
return evennia.__version__
vers = evennia.__version__
if mode == "short":
return vers.split()[0].strip()
elif mode == "pretty":
vers = vers.split()[0].strip()
return f"Evennia {vers}"
else: # mode "long":
return vers
def pypath_to_realpath(python_path, file_ending='.py', pypath_prefixes=None):