Adopt old comm commands to new channel system. Allow using page without an equal sign if target name has no spaces. Not passing tests
This commit is contained in:
parent
67908c5af0
commit
2da679cdd1
6 changed files with 205 additions and 435 deletions
21
CHANGELOG.md
21
CHANGELOG.md
|
|
@ -17,7 +17,7 @@
|
||||||
initial game database state. (volund)
|
initial game database state. (volund)
|
||||||
- Added new Traits contrib, converted and expanded from Ainneve project.
|
- Added new Traits contrib, converted and expanded from Ainneve project.
|
||||||
- Added new `requirements_extra.txt` file for easily getting all optional dependencies.
|
- Added new `requirements_extra.txt` file for easily getting all optional dependencies.
|
||||||
- Change default multimatch syntax from 1-obj, 2-obj to obj-1, obj-2.
|
- Change default multi-match syntax from 1-obj, 2-obj to obj-1, obj-2.
|
||||||
- Make `object.search` support 'stacks=0' keyword - if ``>0``, the method will return
|
- Make `object.search` support 'stacks=0' keyword - if ``>0``, the method will return
|
||||||
N identical matches instead of triggering a multi-match error.
|
N identical matches instead of triggering a multi-match error.
|
||||||
- Add `tags.has()` method for checking if an object has a tag or tags (PR by ChrisLR)
|
- Add `tags.has()` method for checking if an object has a tag or tags (PR by ChrisLR)
|
||||||
|
|
@ -32,26 +32,27 @@
|
||||||
- Latin (la) i18n translation (jamalainm)
|
- Latin (la) i18n translation (jamalainm)
|
||||||
- Made the `evennia` dir possible to use without gamedir for purpose of doc generation.
|
- Made the `evennia` dir possible to use without gamedir for purpose of doc generation.
|
||||||
- Make Scripts' timer component independent from script object deletion; can now start/stop
|
- Make Scripts' timer component independent from script object deletion; can now start/stop
|
||||||
timer without deleting Script. The `.persistent` flag now only controls if timer survives
|
timer without deleting Script. The `.persistent` flag now only controls if timer survives
|
||||||
reload - Script has to be removed with `.delete()` like other typeclassed entities.
|
reload - Script has to be removed with `.delete()` like other typeclassed entities.
|
||||||
- Add `utils.repeat` and `utils.unrepeat` as shortcuts to TickerHandler add/remove, similar
|
- Add `utils.repeat` and `utils.unrepeat` as shortcuts to TickerHandler add/remove, similar
|
||||||
to how `utils.delay` is a shortcut for TaskHandler add.
|
to how `utils.delay` is a shortcut for TaskHandler add.
|
||||||
- Refactor the classic `red_button` example to use `utils.delay/repeat` and modern recommended
|
- Refactor the classic `red_button` example to use `utils.delay/repeat` and modern recommended
|
||||||
code style and paradigms instead of relying on `Scripts` for everything.
|
code style and paradigms instead of relying on `Scripts` for everything.
|
||||||
- Expand `CommandTest` with ability to check multipler msg-receivers; inspired by PR by
|
- Expand `CommandTest` with ability to check multiple message-receivers; inspired by PR by
|
||||||
user davewiththenicehat. Also add new doc string.
|
user davewiththenicehat. Also add new doc string.
|
||||||
- Add central `FuncParser` as a much more powerful replacement for the old `parse_inlinefunc`
|
- Add central `FuncParser` as a much more powerful replacement for the old `parse_inlinefunc`
|
||||||
function.
|
function.
|
||||||
- Add `evennia/utils/verb_conjugation` for automatic verb conjugation (English only). This
|
- Add `evennia/utils/verb_conjugation` for automatic verb conjugation (English only). This
|
||||||
is useful for implementing actor-stance emoting for sending a string to different targets.
|
is useful for implementing actor-stance emoting for sending a string to different targets.
|
||||||
- New version of Italian translation (rpolve)
|
- New version of Italian translation (rpolve)
|
||||||
- `utils.evmenu.ask_yes_no` is a helper function that makes it easy to ask a yes/no question
|
- `utils.evmenu.ask_yes_no` is a helper function that makes it easy to ask a yes/no question
|
||||||
to the user and respond to their input. This complements the existing `get_input` helper.
|
to the user and respond to their input. This complements the existing `get_input` helper.
|
||||||
|
- Allow sending messages with `page/tell` without a `=` if target name contains no spaces.
|
||||||
|
|
||||||
### Evennia 0.9.5 (2019-2020)
|
### Evennia 0.9.5 (2019-2020)
|
||||||
|
|
||||||
Released 2020-11-14.
|
Released 2020-11-14.
|
||||||
A transitional release, including new doc system.
|
A transitional release, including new doc system.
|
||||||
|
|
||||||
- `is_typeclass(obj (Object), exact (bool))` now defaults to exact=False
|
- `is_typeclass(obj (Object), exact (bool))` now defaults to exact=False
|
||||||
- `py` command now reroutes stdout to output results in-game client. `py`
|
- `py` command now reroutes stdout to output results in-game client. `py`
|
||||||
|
|
@ -115,13 +116,13 @@ without arguments starts a full interactive Python console.
|
||||||
- Make `INLINEFUNC_STACK_MAXSIZE` default visible in `settings_default.py`.
|
- Make `INLINEFUNC_STACK_MAXSIZE` default visible in `settings_default.py`.
|
||||||
- Change how `ic` finds puppets; non-priveleged users will use `_playable_characters` list as
|
- Change how `ic` finds puppets; non-priveleged users will use `_playable_characters` list as
|
||||||
candidates, Builders+ will use list, local search and only global search if no match found.
|
candidates, Builders+ will use list, local search and only global search if no match found.
|
||||||
- Make `cmd.at_post_cmd()` always run after `cmd.func()`, even when the latter uses delays
|
- Make `cmd.at_post_cmd()` always run after `cmd.func()`, even when the latter uses delays
|
||||||
with yield.
|
with yield.
|
||||||
- `EvMore` support for db queries and django paginators as well as easier to override for custom
|
- `EvMore` support for db queries and django paginators as well as easier to override for custom
|
||||||
pagination (e.g. to create EvTables for every page instead of splittine one table)
|
pagination (e.g. to create EvTables for every page instead of splittine one table)
|
||||||
- Using `EvMore pagination`, dramatically improves performance of `spawn/list` and `scripts` listings
|
- Using `EvMore pagination`, dramatically improves performance of `spawn/list` and `scripts` listings
|
||||||
(100x speed increase for displaying 1000+ prototypes/scripts).
|
(100x speed increase for displaying 1000+ prototypes/scripts).
|
||||||
- `EvMenu` now uses the more logically named `.ndb._evmenu` instead of `.ndb._menutree` to store itself.
|
- `EvMenu` now uses the more logically named `.ndb._evmenu` instead of `.ndb._menutree` to store itself.
|
||||||
Both still work for backward compatibility, but `_menutree` is deprecated.
|
Both still work for backward compatibility, but `_menutree` is deprecated.
|
||||||
- `EvMenu.msg(txt)` added as a central place to send text to the user, makes it easier to override.
|
- `EvMenu.msg(txt)` added as a central place to send text to the user, makes it easier to override.
|
||||||
Default `EvMenu.msg` sends with OOB type="menu" for use with OOB and webclient pane-redirects.
|
Default `EvMenu.msg` sends with OOB type="menu" for use with OOB and webclient pane-redirects.
|
||||||
|
|
|
||||||
|
|
@ -11,11 +11,10 @@ from django.conf import settings
|
||||||
from evennia.comms.models import Msg
|
from evennia.comms.models import Msg
|
||||||
from evennia.accounts.models import AccountDB
|
from evennia.accounts.models import AccountDB
|
||||||
from evennia.accounts import bots
|
from evennia.accounts import bots
|
||||||
from evennia.comms.channelhandler import CHANNELHANDLER
|
|
||||||
from evennia.locks.lockhandler import LockException
|
from evennia.locks.lockhandler import LockException
|
||||||
from evennia.utils import create, logger, utils
|
from evennia.utils import create, logger, utils
|
||||||
from evennia.utils.logger import tail_log_file
|
from evennia.utils.logger import tail_log_file
|
||||||
from evennia.utils.utils import make_iter, class_from_module
|
from evennia.utils.utils import class_from_module
|
||||||
from evennia.utils.evmenu import ask_yes_no
|
from evennia.utils.evmenu import ask_yes_no
|
||||||
|
|
||||||
COMMAND_DEFAULT_CLASS = class_from_module(settings.COMMAND_DEFAULT_CLASS)
|
COMMAND_DEFAULT_CLASS = class_from_module(settings.COMMAND_DEFAULT_CLASS)
|
||||||
|
|
@ -29,10 +28,8 @@ __all__ = (
|
||||||
"CmdAddCom",
|
"CmdAddCom",
|
||||||
"CmdDelCom",
|
"CmdDelCom",
|
||||||
"CmdAllCom",
|
"CmdAllCom",
|
||||||
"CmdChannels",
|
|
||||||
"CmdCdestroy",
|
"CmdCdestroy",
|
||||||
"CmdCBoot",
|
"CmdCBoot",
|
||||||
"CmdCemit",
|
|
||||||
"CmdCWho",
|
"CmdCWho",
|
||||||
"CmdChannelCreate",
|
"CmdChannelCreate",
|
||||||
"CmdClock",
|
"CmdClock",
|
||||||
|
|
@ -72,7 +69,7 @@ class CmdChannel(COMMAND_DEFAULT_CLASS):
|
||||||
channel/unlock channelname = lockstring
|
channel/unlock channelname = lockstring
|
||||||
channel/boot[/quiet] channelname[,channelname,...] = subscribername [: reason]
|
channel/boot[/quiet] channelname[,channelname,...] = subscribername [: reason]
|
||||||
channel/ban channelname (list bans)
|
channel/ban channelname (list bans)
|
||||||
channel/ban[/quiet] channelname[, channelname, ...] = subscribername [: reason]
|
channe/ban[/quiet] channelname[, channelname, ...] = subscribername [: reason]
|
||||||
channel/unban[/quiet] channelname[, channelname, ...] = subscribername
|
channel/unban[/quiet] channelname[, channelname, ...] = subscribername
|
||||||
channel/who channelname
|
channel/who channelname
|
||||||
|
|
||||||
|
|
@ -100,7 +97,7 @@ class CmdChannel(COMMAND_DEFAULT_CLASS):
|
||||||
channel_msg_nick_alias = r"{alias}\s*?|{alias}\s+?(?P<arg1>.+?)"
|
channel_msg_nick_alias = r"{alias}\s*?|{alias}\s+?(?P<arg1>.+?)"
|
||||||
channel_msg_nick_replacement = "channel {channelname} = $1"
|
channel_msg_nick_replacement = "channel {channelname} = $1"
|
||||||
|
|
||||||
def search_channel(self, channelname, exact=False):
|
def search_channel(self, channelname, exact=False, handle_errors=True):
|
||||||
"""
|
"""
|
||||||
Helper function for searching for a single channel with some error
|
Helper function for searching for a single channel with some error
|
||||||
handling.
|
handling.
|
||||||
|
|
@ -111,9 +108,12 @@ class CmdChannel(COMMAND_DEFAULT_CLASS):
|
||||||
exact (bool, optional): If an exact or fuzzy-match of the name should be done.
|
exact (bool, optional): If an exact or fuzzy-match of the name should be done.
|
||||||
Note that even for a fuzzy match, an exactly given, unique channel name
|
Note that even for a fuzzy match, an exactly given, unique channel name
|
||||||
will always be returned.
|
will always be returned.
|
||||||
|
handle_errors (bool): If true, use `self.msg` to report errors if
|
||||||
|
there are non/multiple matches. If so, the return will always be
|
||||||
|
a single match or None.
|
||||||
Returns:
|
Returns:
|
||||||
list: A list of zero, one or more channels found.
|
object, list or None: If `handle_errors` is `True`, this is either a found Channel
|
||||||
|
or `None`. Otherwise it's a list of zero, one or more channels found.
|
||||||
Notes:
|
Notes:
|
||||||
The 'listen' and 'control' accesses are checked before returning.
|
The 'listen' and 'control' accesses are checked before returning.
|
||||||
|
|
||||||
|
|
@ -133,11 +133,22 @@ class CmdChannel(COMMAND_DEFAULT_CLASS):
|
||||||
channels = [channel for channel in channels
|
channels = [channel for channel in channels
|
||||||
if channel.access(caller, 'listen') or channel.access(caller, 'control')]
|
if channel.access(caller, 'listen') or channel.access(caller, 'control')]
|
||||||
|
|
||||||
if not channels:
|
if handle_errors:
|
||||||
return []
|
if not channels:
|
||||||
elif len(channels) > 1:
|
self.msk(f"No channel found matching '{channelname}' "
|
||||||
return list(channels)
|
"could also be due to missing access).")
|
||||||
return [channels[0]]
|
return None
|
||||||
|
elif len(channels) > 1:
|
||||||
|
self.msg("Multiple possible channel matches/alias for "
|
||||||
|
"'{channelname}':\n" + ", ".join(chan.key for chan in channels))
|
||||||
|
return None
|
||||||
|
return channels[0]
|
||||||
|
else:
|
||||||
|
if not channels:
|
||||||
|
return []
|
||||||
|
elif len(channels) > 1:
|
||||||
|
return list(channels)
|
||||||
|
return [channels[0]]
|
||||||
|
|
||||||
def msg_channel(self, channel, message, **kwargs):
|
def msg_channel(self, channel, message, **kwargs):
|
||||||
"""
|
"""
|
||||||
|
|
@ -284,7 +295,7 @@ class CmdChannel(COMMAND_DEFAULT_CLASS):
|
||||||
"""
|
"""
|
||||||
caller = self.caller
|
caller = self.caller
|
||||||
if caller.nicks.get(alias, category="channel", **kwargs):
|
if caller.nicks.get(alias, category="channel", **kwargs):
|
||||||
caller.nicks.remove(alias, category="channel", **kwargs)
|
caller.nicks.remove(alias, category="chan nel", **kwargs)
|
||||||
msg_alias = self.channel_msg_nick_alias.format(alias=alias)
|
msg_alias = self.channel_msg_nick_alias.format(alias=alias)
|
||||||
caller.nicks.remove(msg_alias, category="inputline", **kwargs)
|
caller.nicks.remove(msg_alias, category="inputline", **kwargs)
|
||||||
return True, ""
|
return True, ""
|
||||||
|
|
@ -747,13 +758,8 @@ class CmdChannel(COMMAND_DEFAULT_CLASS):
|
||||||
# 'listen/control' perms.
|
# 'listen/control' perms.
|
||||||
channel = self.search_channel(channel_name, exact=False)
|
channel = self.search_channel(channel_name, exact=False)
|
||||||
if not channel:
|
if not channel:
|
||||||
self.msg(f"No channel found matching '{channel_name}'.")
|
|
||||||
return
|
return
|
||||||
elif len(channel) > 1:
|
channels.append(channel)
|
||||||
self.msg("Multiple possible channel matches/alias for "
|
|
||||||
"'{channel_name}':\n" + ", ".join(chan.key for chan in channel))
|
|
||||||
return
|
|
||||||
channels.extend(channel)
|
|
||||||
|
|
||||||
# we have at least one channel at this point
|
# we have at least one channel at this point
|
||||||
channel = channels[0]
|
channel = channels[0]
|
||||||
|
|
@ -795,8 +801,8 @@ class CmdChannel(COMMAND_DEFAULT_CLASS):
|
||||||
return
|
return
|
||||||
|
|
||||||
if 'sub' in switches:
|
if 'sub' in switches:
|
||||||
# subscribe to a channel
|
# subscribe to a channel aliases = set(alias.strip().lower() for
|
||||||
aliases = set(alias.strip().lower() for alias in self.rhs.split(";"))
|
# alias in self.rhs.split(";"))
|
||||||
success, err = self.sub_to_channel(channel)
|
success, err = self.sub_to_channel(channel)
|
||||||
if success:
|
if success:
|
||||||
for alias in aliases:
|
for alias in aliases:
|
||||||
|
|
@ -1056,9 +1062,9 @@ class CmdChannel(COMMAND_DEFAULT_CLASS):
|
||||||
return
|
return
|
||||||
|
|
||||||
|
|
||||||
class CmdAddCom(COMMAND_DEFAULT_CLASS):
|
class CmdAddCom(CmdChannel):
|
||||||
"""
|
"""
|
||||||
add a channel alias and/or subscribe to a channel
|
Add a channel alias and/or subscribe to a channel
|
||||||
|
|
||||||
Usage:
|
Usage:
|
||||||
addcom [alias=] <channel>
|
addcom [alias=] <channel>
|
||||||
|
|
@ -1082,7 +1088,6 @@ class CmdAddCom(COMMAND_DEFAULT_CLASS):
|
||||||
|
|
||||||
caller = self.caller
|
caller = self.caller
|
||||||
args = self.args
|
args = self.args
|
||||||
account = caller
|
|
||||||
|
|
||||||
if not args:
|
if not args:
|
||||||
self.msg("Usage: addcom [alias =] channelname.")
|
self.msg("Usage: addcom [alias =] channelname.")
|
||||||
|
|
@ -1096,42 +1101,37 @@ class CmdAddCom(COMMAND_DEFAULT_CLASS):
|
||||||
channelname = self.args
|
channelname = self.args
|
||||||
alias = None
|
alias = None
|
||||||
|
|
||||||
channel = find_channel(caller, channelname)
|
channel = self.search_channel(channelname)
|
||||||
if not channel:
|
if not channel:
|
||||||
# we use the custom search method to handle errors.
|
|
||||||
return
|
|
||||||
|
|
||||||
# check permissions
|
|
||||||
if not channel.access(account, "listen"):
|
|
||||||
self.msg("%s: You are not allowed to listen to this channel." % channel.key)
|
|
||||||
return
|
return
|
||||||
|
|
||||||
string = ""
|
string = ""
|
||||||
if not channel.has_connection(account):
|
if not channel.has_connection(caller):
|
||||||
# we want to connect as well.
|
# we want to connect as well.
|
||||||
if not channel.connect(account):
|
success, err = self.sub_to_channel(channel)
|
||||||
|
if success:
|
||||||
# if this would have returned True, the account is connected
|
# if this would have returned True, the account is connected
|
||||||
self.msg("%s: You are not allowed to join this channel." % channel.key)
|
self.msg(f"You now listen to the channel {channel.key}")
|
||||||
|
else:
|
||||||
|
self.msg(f"{channel.key}: You are not allowed to join this channel.")
|
||||||
return
|
return
|
||||||
else:
|
|
||||||
string += "You now listen to the channel %s. " % channel.key
|
if channel.unmute(caller):
|
||||||
|
string += "You unmute channel %s." % channel.key
|
||||||
else:
|
else:
|
||||||
if channel.unmute(account):
|
string += "You are already connected to channel %s." % channel.key
|
||||||
string += "You unmute channel %s." % channel.key
|
|
||||||
else:
|
|
||||||
string += "You are already connected to channel %s." % channel.key
|
|
||||||
|
|
||||||
if alias:
|
if alias:
|
||||||
# create a nick and add it to the caller.
|
# create a nick and add it to the caller.
|
||||||
caller.nicks.add(alias, channel.key, category="channel")
|
self.add_alias(channel, alias)
|
||||||
string += " You can now refer to the channel %s with the alias '%s'."
|
self.msg(f" You can now refer to the channel {channel} with the alias '{alias}'.")
|
||||||
self.msg(string % (channel.key, alias))
|
self.msg(string % (channel.key, alias))
|
||||||
else:
|
else:
|
||||||
string += " No alias added."
|
string += " No alias added."
|
||||||
self.msg(string)
|
self.msg(string)
|
||||||
|
|
||||||
|
|
||||||
class CmdDelCom(COMMAND_DEFAULT_CLASS):
|
class CmdDelCom(CmdChannel):
|
||||||
"""
|
"""
|
||||||
remove a channel alias and/or unsubscribe from channel
|
remove a channel alias and/or unsubscribe from channel
|
||||||
|
|
||||||
|
|
@ -1157,49 +1157,42 @@ class CmdDelCom(COMMAND_DEFAULT_CLASS):
|
||||||
"""Implementing the command. """
|
"""Implementing the command. """
|
||||||
|
|
||||||
caller = self.caller
|
caller = self.caller
|
||||||
account = caller
|
|
||||||
|
|
||||||
if not self.args:
|
if not self.args:
|
||||||
self.msg("Usage: delcom <alias or channel>")
|
self.msg("Usage: delcom <alias or channel>")
|
||||||
return
|
return
|
||||||
ostring = self.args.lower()
|
ostring = self.args.lower().strip()
|
||||||
|
|
||||||
channel = find_channel(caller, ostring, silent=True, noaliases=True)
|
channel = self.search_channel(ostring)
|
||||||
if channel:
|
if not channel:
|
||||||
# we have given a channel name - unsubscribe
|
return
|
||||||
if not channel.has_connection(account):
|
|
||||||
self.msg("You are not listening to that channel.")
|
if not channel.has_connection(caller):
|
||||||
return
|
self.msg("You are not listening to that channel.")
|
||||||
chkey = channel.key.lower()
|
return
|
||||||
|
|
||||||
|
if ostring == channel.key.lower():
|
||||||
|
# an exact channel name - unsubscribe
|
||||||
delnicks = "all" in self.switches
|
delnicks = "all" in self.switches
|
||||||
# find all nicks linked to this channel and delete them
|
# find all nicks linked to this channel and delete them
|
||||||
if delnicks:
|
if delnicks:
|
||||||
for nick in [
|
aliases = self.get_channel_aliases(channel)
|
||||||
nick
|
for alias in aliases:
|
||||||
for nick in make_iter(caller.nicks.get(category="channel", return_obj=True))
|
self.remove_alias(alias)
|
||||||
if nick and nick.pk and nick.value[3].lower() == chkey
|
success, err = self.unsub_from_channel(channel)
|
||||||
]:
|
if success:
|
||||||
nick.delete()
|
|
||||||
disconnect = channel.disconnect(account)
|
|
||||||
if disconnect:
|
|
||||||
wipednicks = " Eventual aliases were removed." if delnicks else ""
|
wipednicks = " Eventual aliases were removed." if delnicks else ""
|
||||||
self.msg("You stop listening to channel '%s'.%s" % (channel.key, wipednicks))
|
self.msg(f"You stop listening to channel '{channel.key}'.{wipednicks}")
|
||||||
|
else:
|
||||||
|
self.msg(err)
|
||||||
return
|
return
|
||||||
else:
|
else:
|
||||||
# we are removing a channel nick
|
# we are removing a channel nick
|
||||||
channame = caller.nicks.get(key=ostring, category="channel")
|
self.remove_alias(ostring)
|
||||||
channel = find_channel(caller, channame, silent=True)
|
self.msg(f"Any alias '{ostring}' for channel {channel.key} was cleared.")
|
||||||
if not channel:
|
|
||||||
self.msg("No channel with alias '%s' was found." % ostring)
|
|
||||||
else:
|
|
||||||
if caller.nicks.get(ostring, category="channel"):
|
|
||||||
caller.nicks.remove(ostring, category="channel")
|
|
||||||
self.msg("Your alias '%s' for channel %s was cleared." % (ostring, channel.key))
|
|
||||||
else:
|
|
||||||
self.msg("You had no such alias defined for this channel.")
|
|
||||||
|
|
||||||
|
|
||||||
class CmdAllCom(COMMAND_DEFAULT_CLASS):
|
class CmdAllCom(CmdChannel):
|
||||||
"""
|
"""
|
||||||
perform admin operations on all channels
|
perform admin operations on all channels
|
||||||
|
|
||||||
|
|
@ -1271,125 +1264,7 @@ class CmdAllCom(COMMAND_DEFAULT_CLASS):
|
||||||
# wrong input
|
# wrong input
|
||||||
self.msg("Usage: allcom on | off | who | clear")
|
self.msg("Usage: allcom on | off | who | clear")
|
||||||
|
|
||||||
|
class CmdCdestroy(CmdChannel):
|
||||||
class CmdChannels(COMMAND_DEFAULT_CLASS):
|
|
||||||
"""
|
|
||||||
list all channels available to you
|
|
||||||
|
|
||||||
Usage:
|
|
||||||
channels
|
|
||||||
clist
|
|
||||||
comlist
|
|
||||||
|
|
||||||
Lists all channels available to you, whether you listen to them or not.
|
|
||||||
Use 'comlist' to only view your current channel subscriptions.
|
|
||||||
Use addcom/delcom to join and leave channels
|
|
||||||
"""
|
|
||||||
|
|
||||||
key = "channels"
|
|
||||||
aliases = ["clist", "comlist", "chanlist", "channellist", "all channels"]
|
|
||||||
help_category = "Comms"
|
|
||||||
locks = "cmd: not pperm(channel_banned)"
|
|
||||||
|
|
||||||
# this is used by the COMMAND_DEFAULT_CLASS parent
|
|
||||||
account_caller = True
|
|
||||||
|
|
||||||
def func(self):
|
|
||||||
"""Implement function"""
|
|
||||||
|
|
||||||
caller = self.caller
|
|
||||||
|
|
||||||
# all channels we have available to listen to
|
|
||||||
channels = [
|
|
||||||
chan
|
|
||||||
for chan in CHANNEL_DEFAULT_TYPECLASS.objects.get_all_channels()
|
|
||||||
if chan.access(caller, "listen")
|
|
||||||
]
|
|
||||||
if not channels:
|
|
||||||
self.msg("No channels available.")
|
|
||||||
return
|
|
||||||
# all channel we are already subscribed to
|
|
||||||
subs = CHANNEL_DEFAULT_TYPECLASS.objects.get_subscriptions(caller)
|
|
||||||
|
|
||||||
if self.cmdstring == "comlist":
|
|
||||||
# just display the subscribed channels with no extra info
|
|
||||||
comtable = self.styled_table(
|
|
||||||
"|wchannel|n",
|
|
||||||
"|wmy aliases|n",
|
|
||||||
"|wdescription|n",
|
|
||||||
align="l",
|
|
||||||
maxwidth=_DEFAULT_WIDTH,
|
|
||||||
)
|
|
||||||
for chan in subs:
|
|
||||||
clower = chan.key.lower()
|
|
||||||
nicks = caller.nicks.get(category="channel", return_obj=True)
|
|
||||||
comtable.add_row(
|
|
||||||
*[
|
|
||||||
"%s%s"
|
|
||||||
% (
|
|
||||||
chan.key,
|
|
||||||
chan.aliases.all() and "(%s)" % ",".join(chan.aliases.all()) or "",
|
|
||||||
),
|
|
||||||
"%s"
|
|
||||||
% ",".join(
|
|
||||||
nick.db_key
|
|
||||||
for nick in make_iter(nicks)
|
|
||||||
if nick and nick.value[3].lower() == clower
|
|
||||||
),
|
|
||||||
chan.db.desc,
|
|
||||||
]
|
|
||||||
)
|
|
||||||
self.msg(
|
|
||||||
"\n|wChannel subscriptions|n (use |wchannels|n to list all,"
|
|
||||||
" |waddcom|n/|wdelcom|n to sub/unsub):|n\n%s" % comtable
|
|
||||||
)
|
|
||||||
else:
|
|
||||||
# full listing (of channels caller is able to listen to)
|
|
||||||
comtable = self.styled_table(
|
|
||||||
"|wsub|n",
|
|
||||||
"|wchannel|n",
|
|
||||||
"|wmy aliases|n",
|
|
||||||
"|wlocks|n",
|
|
||||||
"|wdescription|n",
|
|
||||||
maxwidth=_DEFAULT_WIDTH,
|
|
||||||
)
|
|
||||||
for chan in channels:
|
|
||||||
clower = chan.key.lower()
|
|
||||||
nicks = caller.nicks.get(category="channel", return_obj=True)
|
|
||||||
nicks = nicks or []
|
|
||||||
if chan not in subs:
|
|
||||||
substatus = "|rNo|n"
|
|
||||||
elif caller in chan.mutelist:
|
|
||||||
substatus = "|rMuted|n"
|
|
||||||
else:
|
|
||||||
substatus = "|gYes|n"
|
|
||||||
comtable.add_row(
|
|
||||||
*[
|
|
||||||
substatus,
|
|
||||||
"%s%s"
|
|
||||||
% (
|
|
||||||
chan.key,
|
|
||||||
chan.aliases.all() and "(%s)" % ",".join(chan.aliases.all()) or "",
|
|
||||||
),
|
|
||||||
"%s"
|
|
||||||
% ",".join(
|
|
||||||
nick.db_key
|
|
||||||
for nick in make_iter(nicks)
|
|
||||||
if nick.value[3].lower() == clower
|
|
||||||
),
|
|
||||||
str(chan.locks),
|
|
||||||
chan.db.desc,
|
|
||||||
]
|
|
||||||
)
|
|
||||||
comtable.reformat_column(0, width=9)
|
|
||||||
comtable.reformat_column(3, width=14)
|
|
||||||
self.msg(
|
|
||||||
"\n|wAvailable channels|n (use |wcomlist|n,|waddcom|n and |wdelcom|n"
|
|
||||||
" to manage subscriptions):\n%s" % comtable
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
class CmdCdestroy(COMMAND_DEFAULT_CLASS):
|
|
||||||
"""
|
"""
|
||||||
destroy a channel you created
|
destroy a channel you created
|
||||||
|
|
||||||
|
|
@ -1408,12 +1283,15 @@ class CmdCdestroy(COMMAND_DEFAULT_CLASS):
|
||||||
|
|
||||||
def func(self):
|
def func(self):
|
||||||
"""Destroy objects cleanly."""
|
"""Destroy objects cleanly."""
|
||||||
|
|
||||||
caller = self.caller
|
caller = self.caller
|
||||||
|
|
||||||
if not self.args:
|
if not self.args:
|
||||||
self.msg("Usage: cdestroy <channelname>")
|
self.msg("Usage: cdestroy <channelname>")
|
||||||
return
|
return
|
||||||
channel = find_channel(caller, self.args)
|
|
||||||
|
channel = self.search_channel(self.args)
|
||||||
|
|
||||||
if not channel:
|
if not channel:
|
||||||
self.msg("Could not find channel %s." % self.args)
|
self.msg("Could not find channel %s." % self.args)
|
||||||
return
|
return
|
||||||
|
|
@ -1421,11 +1299,8 @@ class CmdCdestroy(COMMAND_DEFAULT_CLASS):
|
||||||
self.msg("You are not allowed to do that.")
|
self.msg("You are not allowed to do that.")
|
||||||
return
|
return
|
||||||
channel_key = channel.key
|
channel_key = channel.key
|
||||||
message = "%s is being destroyed. Make sure to change your aliases." % channel_key
|
message = f"{channel.key} is being destroyed. Make sure to change your aliases."
|
||||||
msgobj = create.create_message(caller, message, channel)
|
self.destroy_channel(channel, message)
|
||||||
channel.msg(msgobj)
|
|
||||||
channel.delete()
|
|
||||||
CHANNELHANDLER.update()
|
|
||||||
self.msg("Channel '%s' was destroyed." % channel_key)
|
self.msg("Channel '%s' was destroyed." % channel_key)
|
||||||
logger.log_sec(
|
logger.log_sec(
|
||||||
"Channel Deleted: %s (Caller: %s, IP: %s)."
|
"Channel Deleted: %s (Caller: %s, IP: %s)."
|
||||||
|
|
@ -1433,7 +1308,7 @@ class CmdCdestroy(COMMAND_DEFAULT_CLASS):
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
class CmdCBoot(COMMAND_DEFAULT_CLASS):
|
class CmdCBoot(CmdChannel):
|
||||||
"""
|
"""
|
||||||
kick an account from a channel you control
|
kick an account from a channel you control
|
||||||
|
|
||||||
|
|
@ -1463,17 +1338,21 @@ class CmdCBoot(COMMAND_DEFAULT_CLASS):
|
||||||
self.msg(string)
|
self.msg(string)
|
||||||
return
|
return
|
||||||
|
|
||||||
channel = find_channel(self.caller, self.lhs)
|
channel = self.search_channel(self.lhs)
|
||||||
if not channel:
|
if not channel:
|
||||||
return
|
return
|
||||||
|
|
||||||
reason = ""
|
reason = ""
|
||||||
if ":" in self.rhs:
|
if ":" in self.rhs:
|
||||||
accountname, reason = self.rhs.rsplit(":", 1)
|
target, reason = self.rhs.rsplit(":", 1)
|
||||||
searchstring = accountname.lstrip("*")
|
is_account = target.strip().startswith("*")
|
||||||
|
searchstring = target.lstrip("*")
|
||||||
else:
|
else:
|
||||||
|
is_account = target.strip().startswith("*")
|
||||||
searchstring = self.rhs.lstrip("*")
|
searchstring = self.rhs.lstrip("*")
|
||||||
account = self.caller.search(searchstring, account=True)
|
|
||||||
if not account:
|
target = self.caller.search(searchstring, account=is_account)
|
||||||
|
if not target:
|
||||||
return
|
return
|
||||||
if reason:
|
if reason:
|
||||||
reason = " (reason: %s)" % reason
|
reason = " (reason: %s)" % reason
|
||||||
|
|
@ -1481,79 +1360,19 @@ class CmdCBoot(COMMAND_DEFAULT_CLASS):
|
||||||
string = "You don't control this channel."
|
string = "You don't control this channel."
|
||||||
self.msg(string)
|
self.msg(string)
|
||||||
return
|
return
|
||||||
if not channel.subscriptions.has(account):
|
|
||||||
string = "Account %s is not connected to channel %s." % (account.key, channel.key)
|
success, err = self.boot_user(target, quiet='quiet' in self.switches)
|
||||||
self.msg(string)
|
if success:
|
||||||
return
|
self.msg(f"Booted {target.key} from {channel.key}")
|
||||||
if "quiet" not in self.switches:
|
logger.log_sec(
|
||||||
string = "%s boots %s from channel.%s" % (self.caller, account.key, reason)
|
"Channel Boot: %s (Channel: %s, Reason: %s, Caller: %s, IP: %s)."
|
||||||
channel.msg(string)
|
% (self.caller, channel, reason, self.caller, self.session.address)
|
||||||
# find all account's nicks linked to this channel and delete them
|
)
|
||||||
for nick in [
|
else:
|
||||||
nick
|
self.msg(err)
|
||||||
for nick in account.character.nicks.get(category="channel") or []
|
|
||||||
if nick.value[3].lower() == channel.key
|
|
||||||
]:
|
|
||||||
nick.delete()
|
|
||||||
# disconnect account
|
|
||||||
channel.disconnect(account)
|
|
||||||
CHANNELHANDLER.update()
|
|
||||||
logger.log_sec(
|
|
||||||
"Channel Boot: %s (Channel: %s, Reason: %s, Caller: %s, IP: %s)."
|
|
||||||
% (account, channel, reason, self.caller, self.session.address)
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
class CmdCemit(COMMAND_DEFAULT_CLASS):
|
class CmdCWho(CmdChannel):
|
||||||
"""
|
|
||||||
send an admin message to a channel you control
|
|
||||||
|
|
||||||
Usage:
|
|
||||||
cemit[/switches] <channel> = <message>
|
|
||||||
|
|
||||||
Switches:
|
|
||||||
sendername - attach the sender's name before the message
|
|
||||||
quiet - don't echo the message back to sender
|
|
||||||
|
|
||||||
Allows the user to broadcast a message over a channel as long as
|
|
||||||
they control it. It does not show the user's name unless they
|
|
||||||
provide the /sendername switch.
|
|
||||||
|
|
||||||
"""
|
|
||||||
|
|
||||||
key = "cemit"
|
|
||||||
aliases = ["cmsg"]
|
|
||||||
switch_options = ("sendername", "quiet")
|
|
||||||
locks = "cmd: not pperm(channel_banned) and pperm(Player)"
|
|
||||||
help_category = "Comms"
|
|
||||||
|
|
||||||
# this is used by the COMMAND_DEFAULT_CLASS parent
|
|
||||||
account_caller = True
|
|
||||||
|
|
||||||
def func(self):
|
|
||||||
"""Implement function"""
|
|
||||||
|
|
||||||
if not self.args or not self.rhs:
|
|
||||||
string = "Usage: cemit[/switches] <channel> = <message>"
|
|
||||||
self.msg(string)
|
|
||||||
return
|
|
||||||
channel = find_channel(self.caller, self.lhs)
|
|
||||||
if not channel:
|
|
||||||
return
|
|
||||||
if not channel.access(self.caller, "control"):
|
|
||||||
string = "You don't control this channel."
|
|
||||||
self.msg(string)
|
|
||||||
return
|
|
||||||
message = self.rhs
|
|
||||||
if "sendername" in self.switches:
|
|
||||||
message = "%s: %s" % (self.caller.key, message)
|
|
||||||
channel.msg(message)
|
|
||||||
if "quiet" not in self.switches:
|
|
||||||
string = "Sent to channel %s: %s" % (channel.key, message)
|
|
||||||
self.msg(string)
|
|
||||||
|
|
||||||
|
|
||||||
class CmdCWho(COMMAND_DEFAULT_CLASS):
|
|
||||||
"""
|
"""
|
||||||
show who is listening to a channel
|
show who is listening to a channel
|
||||||
|
|
||||||
|
|
@ -1578,7 +1397,7 @@ class CmdCWho(COMMAND_DEFAULT_CLASS):
|
||||||
self.msg(string)
|
self.msg(string)
|
||||||
return
|
return
|
||||||
|
|
||||||
channel = find_channel(self.caller, self.lhs)
|
channel = self.search_channel(self.lhs)
|
||||||
if not channel:
|
if not channel:
|
||||||
return
|
return
|
||||||
if not channel.access(self.caller, "listen"):
|
if not channel.access(self.caller, "listen"):
|
||||||
|
|
@ -1590,7 +1409,7 @@ class CmdCWho(COMMAND_DEFAULT_CLASS):
|
||||||
self.msg(string.strip())
|
self.msg(string.strip())
|
||||||
|
|
||||||
|
|
||||||
class CmdChannelCreate(COMMAND_DEFAULT_CLASS):
|
class CmdChannelCreate(CmdChannel):
|
||||||
"""
|
"""
|
||||||
create a new channel
|
create a new channel
|
||||||
|
|
||||||
|
|
@ -1611,8 +1430,6 @@ class CmdChannelCreate(COMMAND_DEFAULT_CLASS):
|
||||||
def func(self):
|
def func(self):
|
||||||
"""Implement the command"""
|
"""Implement the command"""
|
||||||
|
|
||||||
caller = self.caller
|
|
||||||
|
|
||||||
if not self.args:
|
if not self.args:
|
||||||
self.msg("Usage ccreate <channelname>[;alias;alias..] = description")
|
self.msg("Usage ccreate <channelname>[;alias;alias..] = description")
|
||||||
return
|
return
|
||||||
|
|
@ -1627,19 +1444,15 @@ class CmdChannelCreate(COMMAND_DEFAULT_CLASS):
|
||||||
if ";" in lhs:
|
if ";" in lhs:
|
||||||
channame, aliases = lhs.split(";", 1)
|
channame, aliases = lhs.split(";", 1)
|
||||||
aliases = [alias.strip().lower() for alias in aliases.split(";")]
|
aliases = [alias.strip().lower() for alias in aliases.split(";")]
|
||||||
channel = CHANNEL_DEFAULT_TYPECLASS.objects.channel_search(channame)
|
|
||||||
if channel:
|
new_chan, err = self.create_channel(channame, description, aliases=aliases)
|
||||||
self.msg("A channel with that name already exists.")
|
if new_chan:
|
||||||
return
|
self.msg(f"Created channel {new_chan.key} and connected to it.")
|
||||||
# Create and set the channel up
|
else:
|
||||||
lockstring = "send:all();listen:all();control:id(%s)" % caller.id
|
self.msg(err)
|
||||||
new_chan = create.create_channel(channame.strip(), aliases, description, locks=lockstring)
|
|
||||||
new_chan.connect(caller)
|
|
||||||
CHANNELHANDLER.update()
|
|
||||||
self.msg("Created channel %s and connected to it." % new_chan.key)
|
|
||||||
|
|
||||||
|
|
||||||
class CmdClock(COMMAND_DEFAULT_CLASS):
|
class CmdClock(CmdChannel):
|
||||||
"""
|
"""
|
||||||
change channel locks of a channel you control
|
change channel locks of a channel you control
|
||||||
|
|
||||||
|
|
@ -1666,14 +1479,13 @@ class CmdClock(COMMAND_DEFAULT_CLASS):
|
||||||
self.msg(string)
|
self.msg(string)
|
||||||
return
|
return
|
||||||
|
|
||||||
channel = find_channel(self.caller, self.lhs)
|
channel = self.search_channel(self.lhs)
|
||||||
if not channel:
|
if not channel:
|
||||||
return
|
return
|
||||||
|
|
||||||
if not self.rhs:
|
if not self.rhs:
|
||||||
# no =, so just view the current locks
|
# no =, so just view the current locks
|
||||||
string = "Current locks on %s:" % channel.key
|
self.msg(f"Current locks on {channel.key}\n{channel.locks}")
|
||||||
string = "%s\n %s" % (string, channel.locks)
|
|
||||||
self.msg(string)
|
|
||||||
return
|
return
|
||||||
# we want to add/change a lock.
|
# we want to add/change a lock.
|
||||||
if not channel.access(self.caller, "control"):
|
if not channel.access(self.caller, "control"):
|
||||||
|
|
@ -1681,18 +1493,13 @@ class CmdClock(COMMAND_DEFAULT_CLASS):
|
||||||
self.msg(string)
|
self.msg(string)
|
||||||
return
|
return
|
||||||
# Try to add the lock
|
# Try to add the lock
|
||||||
try:
|
success, err = self.set_lock(channel, self.rhs)
|
||||||
channel.locks.add(self.rhs)
|
if success:
|
||||||
except LockException as err:
|
self.msg(f"Lock(s) applied. Current locks on {channel.key}:\n{channel.locks}")
|
||||||
|
else:
|
||||||
self.msg(err)
|
self.msg(err)
|
||||||
return
|
|
||||||
string = "Lock(s) applied. "
|
|
||||||
string += "Current locks on %s:" % channel.key
|
|
||||||
string = "%s\n %s" % (string, channel.locks)
|
|
||||||
self.msg(string)
|
|
||||||
|
|
||||||
|
class CmdCdesc(CmdChannel):
|
||||||
class CmdCdesc(COMMAND_DEFAULT_CLASS):
|
|
||||||
"""
|
"""
|
||||||
describe a channel you control
|
describe a channel you control
|
||||||
|
|
||||||
|
|
@ -1701,6 +1508,7 @@ class CmdCdesc(COMMAND_DEFAULT_CLASS):
|
||||||
|
|
||||||
Changes the description of the channel as shown in
|
Changes the description of the channel as shown in
|
||||||
channel lists.
|
channel lists.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
key = "cdesc"
|
key = "cdesc"
|
||||||
|
|
@ -1718,18 +1526,15 @@ class CmdCdesc(COMMAND_DEFAULT_CLASS):
|
||||||
if not self.rhs:
|
if not self.rhs:
|
||||||
self.msg("Usage: cdesc <channel> = <description>")
|
self.msg("Usage: cdesc <channel> = <description>")
|
||||||
return
|
return
|
||||||
channel = find_channel(caller, self.lhs)
|
channel = self.search_channel(self.lhs)
|
||||||
if not channel:
|
if not channel:
|
||||||
self.msg("Channel '%s' not found." % self.lhs)
|
|
||||||
return
|
return
|
||||||
# check permissions
|
# check permissions
|
||||||
if not channel.access(caller, "control"):
|
if not channel.access(caller, "control"):
|
||||||
self.msg("You cannot admin this channel.")
|
self.msg("You cannot admin this channel.")
|
||||||
return
|
return
|
||||||
# set the description
|
self.set_desc(channel, self.rhs)
|
||||||
channel.db.desc = self.rhs
|
self.msg(f"Description of channel '{channel.key}' set to '{self.rhs}'.")
|
||||||
channel.save()
|
|
||||||
self.msg("Description of channel '%s' set to '%s'." % (channel.key, self.rhs))
|
|
||||||
|
|
||||||
|
|
||||||
class CmdPage(COMMAND_DEFAULT_CLASS):
|
class CmdPage(COMMAND_DEFAULT_CLASS):
|
||||||
|
|
@ -1737,16 +1542,19 @@ class CmdPage(COMMAND_DEFAULT_CLASS):
|
||||||
send a private message to another account
|
send a private message to another account
|
||||||
|
|
||||||
Usage:
|
Usage:
|
||||||
|
page <account> <message>
|
||||||
page[/switches] [<account>,<account>,... = <message>]
|
page[/switches] [<account>,<account>,... = <message>]
|
||||||
tell ''
|
tell ''
|
||||||
page <number>
|
page <number>
|
||||||
|
|
||||||
Switch:
|
Switches:
|
||||||
last - shows who you last messaged
|
last - shows who you last messaged
|
||||||
list - show your last <number> of tells/pages (default)
|
list - show your last <number> of tells/pages (default)
|
||||||
|
|
||||||
Send a message to target user (if online). If no
|
Send a message to target user (if online). If no argument is given, you will
|
||||||
argument is given, you will get a list of your latest messages.
|
get a list of your latest messages. The equal sign is needed for multiple
|
||||||
|
targets or if sending to target with space in the name.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
key = "page"
|
key = "page"
|
||||||
|
|
@ -1768,6 +1576,7 @@ class CmdPage(COMMAND_DEFAULT_CLASS):
|
||||||
pages_we_sent = Msg.objects.get_messages_by_sender(caller, exclude_channel_messages=True)
|
pages_we_sent = Msg.objects.get_messages_by_sender(caller, exclude_channel_messages=True)
|
||||||
# get last messages we've got
|
# get last messages we've got
|
||||||
pages_we_got = Msg.objects.get_messages_by_receiver(caller)
|
pages_we_got = Msg.objects.get_messages_by_receiver(caller)
|
||||||
|
targets, message, number = [], None, None
|
||||||
|
|
||||||
if "last" in self.switches:
|
if "last" in self.switches:
|
||||||
if pages_we_sent:
|
if pages_we_sent:
|
||||||
|
|
@ -1778,19 +1587,75 @@ class CmdPage(COMMAND_DEFAULT_CLASS):
|
||||||
self.msg("You haven't paged anyone yet.")
|
self.msg("You haven't paged anyone yet.")
|
||||||
return
|
return
|
||||||
|
|
||||||
if not self.args or not self.rhs:
|
if self.args:
|
||||||
pages = pages_we_sent + pages_we_got
|
if self.rhs:
|
||||||
pages = sorted(pages, key=lambda page: page.date_created)
|
for target in self.lhslist:
|
||||||
|
target_obj = self.caller.search(target)
|
||||||
|
if not target_obj:
|
||||||
|
return
|
||||||
|
targets.append(target_obj)
|
||||||
|
message = self.rhs.strip()
|
||||||
|
else:
|
||||||
|
target, *message = self.args.split(" ", 4)
|
||||||
|
if target and target.isnumeric():
|
||||||
|
# a number to specify a historic page
|
||||||
|
number = int(target)
|
||||||
|
elif target:
|
||||||
|
target_obj = self.caller.search(target, quiet=True)
|
||||||
|
if target_obj:
|
||||||
|
# a proper target
|
||||||
|
targets = [target_obj[0]]
|
||||||
|
else:
|
||||||
|
# a message with a space in it - put it back together
|
||||||
|
message = target + " " + (message[0] if message else "")
|
||||||
|
else:
|
||||||
|
# a single-word message
|
||||||
|
message = message[0].strip()
|
||||||
|
|
||||||
number = 5
|
pages = pages_we_sent + pages_we_got
|
||||||
if self.args:
|
pages = sorted(pages, key=lambda page: page.date_created)
|
||||||
try:
|
|
||||||
number = int(self.args)
|
if message:
|
||||||
except ValueError:
|
# send a message
|
||||||
self.msg("Usage: tell [<account> = msg]")
|
if not targets:
|
||||||
|
# no target given - send to last person we paged
|
||||||
|
if pages_we_sent:
|
||||||
|
targets = pages_we_sent[-1].receivers
|
||||||
|
else:
|
||||||
|
self.msg("Who do you want page?")
|
||||||
return
|
return
|
||||||
|
|
||||||
if len(pages) > number:
|
header = "|wAccount|n |c%s|n |wpages:|n" % caller.key
|
||||||
|
if message.startswith(":"):
|
||||||
|
message = "%s %s" % (caller.key, message.strip(":").strip())
|
||||||
|
|
||||||
|
# create the persistent message object
|
||||||
|
create.create_message(caller, message, receivers=targets)
|
||||||
|
|
||||||
|
# tell the accounts they got a message.
|
||||||
|
received = []
|
||||||
|
rstrings = []
|
||||||
|
for target in targets:
|
||||||
|
if not target.access(caller, "msg"):
|
||||||
|
rstrings.append(f"You are not allowed to page {target}.")
|
||||||
|
continue
|
||||||
|
target.msg(f"{header} {message}")
|
||||||
|
if hasattr(target, "sessions") and not target.sessions.count():
|
||||||
|
received.append(f"|C{target.name}|n")
|
||||||
|
rstrings.append(
|
||||||
|
f"{received[-1]} is offline. They will see your message "
|
||||||
|
"if they list their pages later."
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
received.append(f"|c{target.name}|n")
|
||||||
|
if rstrings:
|
||||||
|
self.msg("\n".join(rstrings))
|
||||||
|
self.msg("You paged %s with: '%s'." % (", ".join(received), message))
|
||||||
|
return
|
||||||
|
|
||||||
|
else:
|
||||||
|
# no message to send
|
||||||
|
if number is not None and len(pages) > number:
|
||||||
lastpages = pages[-number:]
|
lastpages = pages[-number:]
|
||||||
else:
|
else:
|
||||||
lastpages = pages
|
lastpages = pages
|
||||||
|
|
@ -1819,7 +1684,7 @@ class CmdPage(COMMAND_DEFAULT_CLASS):
|
||||||
receiver = f"|n,{clr}".join([obj.name for obj in page.receivers])
|
receiver = f"|n,{clr}".join([obj.name for obj in page.receivers])
|
||||||
if sending:
|
if sending:
|
||||||
template = to_template
|
template = to_template
|
||||||
sender = f"{sender} " if multi_send else ""
|
sender = f"{sender} " if multi_send else ""
|
||||||
receiver = f" {receiver}" if multi_recv else f" {receiver}"
|
receiver = f" {receiver}" if multi_recv else f" {receiver}"
|
||||||
else:
|
else:
|
||||||
template = from_template
|
template = from_template
|
||||||
|
|
@ -1845,64 +1710,6 @@ class CmdPage(COMMAND_DEFAULT_CLASS):
|
||||||
self.msg(string)
|
self.msg(string)
|
||||||
return
|
return
|
||||||
|
|
||||||
# We are sending. Build a list of targets
|
|
||||||
|
|
||||||
if not self.lhs:
|
|
||||||
# If there are no targets, then set the targets
|
|
||||||
# to the last person we paged.
|
|
||||||
if pages_we_sent:
|
|
||||||
receivers = pages_we_sent[-1].receivers
|
|
||||||
else:
|
|
||||||
self.msg("Who do you want to page?")
|
|
||||||
return
|
|
||||||
else:
|
|
||||||
receivers = self.lhslist
|
|
||||||
|
|
||||||
recobjs = []
|
|
||||||
for receiver in set(receivers):
|
|
||||||
if isinstance(receiver, str):
|
|
||||||
pobj = caller.search(receiver)
|
|
||||||
elif hasattr(receiver, "character"):
|
|
||||||
pobj = receiver
|
|
||||||
else:
|
|
||||||
self.msg("Who do you want to page?")
|
|
||||||
return
|
|
||||||
if pobj:
|
|
||||||
recobjs.append(pobj)
|
|
||||||
if not recobjs:
|
|
||||||
self.msg("Noone found to page.")
|
|
||||||
return
|
|
||||||
|
|
||||||
header = "|wAccount|n |c%s|n |wpages:|n" % caller.key
|
|
||||||
message = self.rhs
|
|
||||||
|
|
||||||
# if message begins with a :, we assume it is a 'page-pose'
|
|
||||||
if message.startswith(":"):
|
|
||||||
message = "%s %s" % (caller.key, message.strip(":").strip())
|
|
||||||
|
|
||||||
# create the persistent message object
|
|
||||||
create.create_message(caller, message, receivers=recobjs)
|
|
||||||
|
|
||||||
# tell the accounts they got a message.
|
|
||||||
received = []
|
|
||||||
rstrings = []
|
|
||||||
for pobj in recobjs:
|
|
||||||
if not pobj.access(caller, "msg"):
|
|
||||||
rstrings.append("You are not allowed to page %s." % pobj)
|
|
||||||
continue
|
|
||||||
pobj.msg("%s %s" % (header, message))
|
|
||||||
if hasattr(pobj, "sessions") and not pobj.sessions.count():
|
|
||||||
received.append("|C%s|n" % pobj.name)
|
|
||||||
rstrings.append(
|
|
||||||
"%s is offline. They will see your message if they list their pages later."
|
|
||||||
% received[-1]
|
|
||||||
)
|
|
||||||
else:
|
|
||||||
received.append("|c%s|n" % pobj.name)
|
|
||||||
if rstrings:
|
|
||||||
self.msg("\n".join(rstrings))
|
|
||||||
self.msg("You paged %s with: '%s'." % (", ".join(received), message))
|
|
||||||
|
|
||||||
|
|
||||||
def _list_bots(cmd):
|
def _list_bots(cmd):
|
||||||
"""
|
"""
|
||||||
|
|
@ -1943,7 +1750,6 @@ def _list_bots(cmd):
|
||||||
else:
|
else:
|
||||||
return "No irc bots found."
|
return "No irc bots found."
|
||||||
|
|
||||||
|
|
||||||
class CmdIRC2Chan(COMMAND_DEFAULT_CLASS):
|
class CmdIRC2Chan(COMMAND_DEFAULT_CLASS):
|
||||||
"""
|
"""
|
||||||
Link an evennia channel to an external IRC channel
|
Link an evennia channel to an external IRC channel
|
||||||
|
|
|
||||||
|
|
@ -11,13 +11,11 @@ import re
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from collections import defaultdict
|
from collections import defaultdict
|
||||||
from evennia.utils.utils import fill, dedent
|
from evennia.utils.utils import fill, dedent
|
||||||
from evennia.commands.command import Command
|
|
||||||
from evennia.help.models import HelpEntry
|
from evennia.help.models import HelpEntry
|
||||||
from evennia.utils import create, evmore
|
from evennia.utils import create, evmore
|
||||||
from evennia.utils.ansi import ANSIString
|
from evennia.utils.ansi import ANSIString
|
||||||
from evennia.utils.eveditor import EvEditor
|
from evennia.utils.eveditor import EvEditor
|
||||||
from evennia.utils.utils import (
|
from evennia.utils.utils import (
|
||||||
string_suggestions,
|
|
||||||
class_from_module,
|
class_from_module,
|
||||||
inherits_from,
|
inherits_from,
|
||||||
format_grid, pad
|
format_grid, pad
|
||||||
|
|
@ -500,8 +498,6 @@ class CmdHelp(COMMAND_DEFAULT_CLASS):
|
||||||
"""
|
"""
|
||||||
caller = self.caller
|
caller = self.caller
|
||||||
query, subtopics, cmdset = self.topic, self.subtopics, self.cmdset
|
query, subtopics, cmdset = self.topic, self.subtopics, self.cmdset
|
||||||
suggestion_cutoff = self.suggestion_cutoff
|
|
||||||
suggestion_maxnum = self.suggestion_maxnum
|
|
||||||
|
|
||||||
# removing doublets in cmdset, caused by cmdhandler
|
# removing doublets in cmdset, caused by cmdhandler
|
||||||
# having to allow doublet commands to manage exits etc.
|
# having to allow doublet commands to manage exits etc.
|
||||||
|
|
@ -514,9 +510,8 @@ class CmdHelp(COMMAND_DEFAULT_CLASS):
|
||||||
]
|
]
|
||||||
all_categories = list(set(
|
all_categories = list(set(
|
||||||
[HelpCategory(cmd.help_category) for cmd in all_cmds]
|
[HelpCategory(cmd.help_category) for cmd in all_cmds]
|
||||||
+ [HelpCategory(topic.help_category) for topic in all_db_topics]
|
+ [HelpCategory(topic.help_category) for topic in all_db_topics]
|
||||||
)
|
))
|
||||||
)
|
|
||||||
|
|
||||||
if not query:
|
if not query:
|
||||||
# list all available help entries, grouped by category. We want to
|
# list all available help entries, grouped by category. We want to
|
||||||
|
|
@ -593,7 +588,7 @@ class CmdHelp(COMMAND_DEFAULT_CLASS):
|
||||||
topic = match.key
|
topic = match.key
|
||||||
help_text = match.get_help(caller, cmdset)
|
help_text = match.get_help(caller, cmdset)
|
||||||
aliases = match.aliases
|
aliases = match.aliases
|
||||||
suggested=suggestions[1:]
|
suggested = suggestions[1:]
|
||||||
else:
|
else:
|
||||||
# a database match
|
# a database match
|
||||||
topic = match.key
|
topic = match.key
|
||||||
|
|
|
||||||
|
|
@ -563,7 +563,7 @@ class TestHelp(CommandTest):
|
||||||
"Help for test/more/second-more\n\n"
|
"Help for test/more/second-more\n\n"
|
||||||
"The Second More text.\n\n"
|
"The Second More text.\n\n"
|
||||||
"Subtopics:\n"
|
"Subtopics:\n"
|
||||||
" test/more/second-more/more again\n\n"
|
" test/more/second-more/more again\n"
|
||||||
" test/more/second-more/third more"
|
" test/more/second-more/third more"
|
||||||
),
|
),
|
||||||
("test/More/-more", # partial match
|
("test/More/-more", # partial match
|
||||||
|
|
@ -574,7 +574,7 @@ class TestHelp(CommandTest):
|
||||||
" test/more/second-more/third more"
|
" test/more/second-more/third more"
|
||||||
),
|
),
|
||||||
("test/more/second/more again",
|
("test/more/second/more again",
|
||||||
"Help for test/more/second-more/more again\n"
|
"Help for test/more/second-more/more again\n\n"
|
||||||
"Even more text.\n"
|
"Even more text.\n"
|
||||||
),
|
),
|
||||||
("test/more/second/third",
|
("test/more/second/third",
|
||||||
|
|
|
||||||
|
|
@ -1069,34 +1069,6 @@ class TestGetAndMergeCmdSets(TwistedTestCase, EvenniaTest):
|
||||||
deferred.addCallback(_callback)
|
deferred.addCallback(_callback)
|
||||||
return deferred
|
return deferred
|
||||||
|
|
||||||
def test_autocmdsets(self):
|
|
||||||
import evennia
|
|
||||||
from evennia.commands.default.cmdset_account import AccountCmdSet
|
|
||||||
from evennia.comms.channelhandler import CHANNEL_HANDLER
|
|
||||||
|
|
||||||
testchannel = evennia.create_channel("channeltest", locks="listen:all();send:all()")
|
|
||||||
CHANNEL_HANDLER.add(testchannel)
|
|
||||||
CHANNEL_HANDLER.update()
|
|
||||||
self.assertTrue(testchannel.connect(self.account))
|
|
||||||
self.assertTrue(testchannel.has_connection(self.account))
|
|
||||||
a, b, c, d = self.cmdset_a, self.cmdset_b, self.cmdset_c, self.cmdset_d
|
|
||||||
self.set_cmdsets(self.account, a, b, c, d)
|
|
||||||
deferred = cmdhandler.get_and_merge_cmdsets(
|
|
||||||
self.session, self.session, self.account, self.char1, "session", ""
|
|
||||||
)
|
|
||||||
|
|
||||||
def _callback(cmdset):
|
|
||||||
pcmdset = AccountCmdSet()
|
|
||||||
pcmdset.at_cmdset_creation()
|
|
||||||
pcmds = [cmd.key for cmd in pcmdset.commands] + ["a", "b", "c", "d"] + ["out"]
|
|
||||||
self.assertTrue(
|
|
||||||
all(cmd.key or hasattr(cmd, "is_channel") in pcmds for cmd in cmdset.commands)
|
|
||||||
)
|
|
||||||
self.assertTrue(any(hasattr(cmd, "is_channel") for cmd in cmdset.commands))
|
|
||||||
|
|
||||||
deferred.addCallback(_callback)
|
|
||||||
return deferred
|
|
||||||
|
|
||||||
def test_duplicates(self):
|
def test_duplicates(self):
|
||||||
a, b, c, d = self.cmdset_a, self.cmdset_b, self.cmdset_c, self.cmdset_d
|
a, b, c, d = self.cmdset_a, self.cmdset_b, self.cmdset_c, self.cmdset_d
|
||||||
a.no_exits = True
|
a.no_exits = True
|
||||||
|
|
|
||||||
|
|
@ -13,10 +13,6 @@ autobahn >= 17.9.3
|
||||||
lunr == 0.5.6
|
lunr == 0.5.6
|
||||||
simpleeval <= 1.0
|
simpleeval <= 1.0
|
||||||
|
|
||||||
# conjugation library, py3 version
|
|
||||||
git+https://github.com/markrogersjr/nodebox_linguistics_extended.git
|
|
||||||
|
|
||||||
|
|
||||||
# try to resolve dependency issue in py3.7
|
# try to resolve dependency issue in py3.7
|
||||||
attrs >= 19.2.0
|
attrs >= 19.2.0
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue