diff --git a/evennia/accounts/bots.py b/evennia/accounts/bots.py index 302f9db8b4..35e73d4aaa 100644 --- a/evennia/accounts/bots.py +++ b/evennia/accounts/bots.py @@ -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 diff --git a/evennia/commands/default/cmdset_account.py b/evennia/commands/default/cmdset_account.py index d48c140d2c..553c7fdf7d 100644 --- a/evennia/commands/default/cmdset_account.py +++ b/evennia/commands/default/cmdset_account.py @@ -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()) diff --git a/evennia/commands/default/comms.py b/evennia/commands/default/comms.py index 53c0aef813..8beaf9956f 100644 --- a/evennia/commands/default/comms.py +++ b/evennia/commands/default/comms.py @@ -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] = - grapewine2chan/disconnect + grapevine2chan[/switches] = + grapevine2chan/disconnect 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] = " + string = "Usage: grapevine2chan[/switches] = " 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}.") diff --git a/evennia/game_template/server/conf/connection_screens.py b/evennia/game_template/server/conf/connection_screens.py index cc85287f8a..713cf318b8 100644 --- a/evennia/game_template/server/conf/connection_screens.py +++ b/evennia/game_template/server/conf/connection_screens.py @@ -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")) diff --git a/evennia/server/portal/rss.py b/evennia/server/portal/rss.py index b297719401..351a5d3f5f 100644 --- a/evennia/server/portal/rss.py +++ b/evennia/server/portal/rss.py @@ -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) diff --git a/evennia/server/server.py b/evennia/server/server.py index 1ee8d9642c..0a87ab6b3b 100644 --- a/evennia/server/server.py +++ b/evennia/server/server.py @@ -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." diff --git a/evennia/settings_default.py b/evennia/settings_default.py index c4f8c3cb07..226f187a7e 100644 --- a/evennia/settings_default.py +++ b/evennia/settings_default.py @@ -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 diff --git a/evennia/utils/utils.py b/evennia/utils/utils.py index 6555051a75..b0903010c1 100644 --- a/evennia/utils/utils.py +++ b/evennia/utils/utils.py @@ -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):