Co-exist @-prefixes for management commands. Resolve 2353.

This commit is contained in:
Griatch 2021-11-13 02:15:30 +01:00
parent 297daf5492
commit 7cfb9e3b42
18 changed files with 840 additions and 711 deletions

View file

@ -120,6 +120,10 @@ Up requirements to Django 3.2+, Twisted 21+
the standard calendar form ... there is no month 0 every year after all).
- `AttributeProperty`/`NAttributeProperty` to allow managing Attributes/NAttributes
on typeclasses in the same way as Django fields.
- Give build/system commands a `@name` to fall back to if the non-@ name is used
by another command (like `open` and `@open`. If no duplicate, @ is optional.
- Move legacy channel-management commands (`ccreate`, `addcom` etc) to a contrib
since their work is now fully handled by the single `channel` command.
### Evennia 0.9.5 (2019-2020)

View file

@ -279,6 +279,32 @@ incoming string is already split up and parsed in suitable ways by its parent.
Before you can actually use the command in your game, you must now store it
within a *command set*. See the [Command Sets](./Command-Sets.md) page.
### Command prefixes
Historically, many MU* servers used to use prefix, such as `@` or `&` to signify that
a command is used for administration or requires staff privileges. The problem with this is that
newcomers to MU often find such extra symbols confusing. Evennia allows commands that can be
accessed both with- or without such a prefix.
CMD_IGNORE_PREFIXES = "@&/+`
This is a setting consisting of a string of characters. Each is a prefix that will be considered
a skippable prefix - _if the command is still unique in its cmdset when skipping the prefix_.
So if you wanted to write `@look` instead of `look` you can do so - the `@` will be ignored. But If
we added an actual `@look` command (with a `key` or alias `@look`) then we would need to use the
`@` to separate between the two.
This is also used in the default commands. For example, `@open` is a building
command that allows you to create new exits to link two rooms together. Its `key` is set to `@open`,
including the `@` (no alias is set). By default you can use both `@open` and `open` for
this command. But "open" is a pretty common word and let's say a developer adds a new `open` command
for opening a door. Now `@open` and `open` are two different commands and the `@` must be used to
separate them.
> The `help` command will prefer to show all command names without prefix if
> possible. Only if there is a collision, will the prefix be shown in the help system.
### On arg_regex
The command parser is very general and does not require a space to end your command name. This means

View file

@ -2,7 +2,7 @@
# Default Commands
The full set of default Evennia commands currently contains 97 commands in 9 source
The full set of default Evennia commands currently contains 88 commands in 9 source
files. Our policy for adding default commands is outlined [here](../Concepts/Using-MUX-as-a-Standard.md). The
[Commands](./Commands.md) documentation explains how Commands work as well as make new or customize
existing ones. Note that this page is auto-generated. Report problems to the [issue
@ -14,93 +14,84 @@ with [EvEditor](./EvEditor.md), flipping pages in [EvMore](./EvMore.md) or using
[Batch-Processor](./Batch-Processors.md)'s interactive mode.
```
- [**@about** [@version]](evennia.commands.default.system.CmdAbout) (cmdset: [CharacterCmdSet](evennia.commands.default.cmdset_character.CharacterCmdSet), help-category: _System_)
- [**@accounts** [@account]](evennia.commands.default.system.CmdAccounts) (cmdset: [CharacterCmdSet](evennia.commands.default.cmdset_character.CharacterCmdSet), help-category: _System_)
- [**@alias** [setobjalias]](evennia.commands.default.building.CmdSetObjAlias) (cmdset: [CharacterCmdSet](evennia.commands.default.cmdset_character.CharacterCmdSet), help-category: _Building_)
- [**@channel** [@channels, @chan]](evennia.commands.default.comms.CmdChannel) (cmdset: [AccountCmdSet](evennia.commands.default.cmdset_account.AccountCmdSet), help-category: _Comms_)
- [**@cmdsets**](evennia.commands.default.building.CmdListCmdSets) (cmdset: [CharacterCmdSet](evennia.commands.default.cmdset_character.CharacterCmdSet), help-category: _Building_)
- [**@copy**](evennia.commands.default.building.CmdCopy) (cmdset: [CharacterCmdSet](evennia.commands.default.cmdset_character.CharacterCmdSet), help-category: _Building_)
- [**@cpattr**](evennia.commands.default.building.CmdCpAttr) (cmdset: [CharacterCmdSet](evennia.commands.default.cmdset_character.CharacterCmdSet), help-category: _Building_)
- [**@create**](evennia.commands.default.building.CmdCreate) (cmdset: [CharacterCmdSet](evennia.commands.default.cmdset_character.CharacterCmdSet), help-category: _Building_)
- [**@desc**](evennia.commands.default.building.CmdDesc) (cmdset: [CharacterCmdSet](evennia.commands.default.cmdset_character.CharacterCmdSet), help-category: _Building_)
- [**@destroy** [@del, @delete]](evennia.commands.default.building.CmdDestroy) (cmdset: [CharacterCmdSet](evennia.commands.default.cmdset_character.CharacterCmdSet), help-category: _Building_)
- [**@dig**](evennia.commands.default.building.CmdDig) (cmdset: [CharacterCmdSet](evennia.commands.default.cmdset_character.CharacterCmdSet), help-category: _Building_)
- [**@examine** [@ex, @exam]](evennia.commands.default.building.CmdExamine) (cmdset: [AccountCmdSet](evennia.commands.default.cmdset_account.AccountCmdSet), help-category: _Building_)
- [**@find** [@search, @locate]](evennia.commands.default.building.CmdFind) (cmdset: [CharacterCmdSet](evennia.commands.default.cmdset_character.CharacterCmdSet), help-category: _Building_)
- [**@link**](evennia.commands.default.building.CmdLink) (cmdset: [CharacterCmdSet](evennia.commands.default.cmdset_character.CharacterCmdSet), help-category: _Building_)
- [**@lock** [@locks]](evennia.commands.default.building.CmdLock) (cmdset: [CharacterCmdSet](evennia.commands.default.cmdset_character.CharacterCmdSet), help-category: _Building_)
- [**@mvattr**](evennia.commands.default.building.CmdMvAttr) (cmdset: [CharacterCmdSet](evennia.commands.default.cmdset_character.CharacterCmdSet), help-category: _Building_)
- [**@name** [@rename]](evennia.commands.default.building.CmdName) (cmdset: [CharacterCmdSet](evennia.commands.default.cmdset_character.CharacterCmdSet), help-category: _Building_)
- [**@objects**](evennia.commands.default.building.CmdObjects) (cmdset: [CharacterCmdSet](evennia.commands.default.cmdset_character.CharacterCmdSet), help-category: _System_)
- [**@open**](evennia.commands.default.building.CmdOpen) (cmdset: [CharacterCmdSet](evennia.commands.default.cmdset_character.CharacterCmdSet), help-category: _Building_)
- [**@py** [@!]](evennia.commands.default.system.CmdPy) (cmdset: [AccountCmdSet](evennia.commands.default.cmdset_account.AccountCmdSet), help-category: _System_)
- [**@reload** [@restart]](evennia.commands.default.system.CmdReload) (cmdset: [AccountCmdSet](evennia.commands.default.cmdset_account.AccountCmdSet), help-category: _System_)
- [**@reset** [@reboot]](evennia.commands.default.system.CmdReset) (cmdset: [AccountCmdSet](evennia.commands.default.cmdset_account.AccountCmdSet), help-category: _System_)
- [**@scripts** [@script]](evennia.commands.default.building.CmdScripts) (cmdset: [CharacterCmdSet](evennia.commands.default.cmdset_character.CharacterCmdSet), help-category: _System_)
- [**@server** [@serverload]](evennia.commands.default.system.CmdServerLoad) (cmdset: [CharacterCmdSet](evennia.commands.default.cmdset_character.CharacterCmdSet), help-category: _System_)
- [**@service** [@services]](evennia.commands.default.system.CmdService) (cmdset: [CharacterCmdSet](evennia.commands.default.cmdset_character.CharacterCmdSet), help-category: _System_)
- [**@set**](evennia.commands.default.building.CmdSetAttribute) (cmdset: [CharacterCmdSet](evennia.commands.default.cmdset_character.CharacterCmdSet), help-category: _Building_)
- [**@sethome**](evennia.commands.default.building.CmdSetHome) (cmdset: [CharacterCmdSet](evennia.commands.default.cmdset_character.CharacterCmdSet), help-category: _Building_)
- [**@shutdown**](evennia.commands.default.system.CmdShutdown) (cmdset: [AccountCmdSet](evennia.commands.default.cmdset_account.AccountCmdSet), help-category: _System_)
- [**@spawn** [@olc]](evennia.commands.default.building.CmdSpawn) (cmdset: [CharacterCmdSet](evennia.commands.default.cmdset_character.CharacterCmdSet), help-category: _Building_)
- [**@tag** [@tags]](evennia.commands.default.building.CmdTag) (cmdset: [CharacterCmdSet](evennia.commands.default.cmdset_character.CharacterCmdSet), help-category: _Building_)
- [**@tasks** [@delays, @task]](evennia.commands.default.system.CmdTasks) (cmdset: [CharacterCmdSet](evennia.commands.default.cmdset_character.CharacterCmdSet), help-category: _System_)
- [**@teleport** [@tel]](evennia.commands.default.building.CmdTeleport) (cmdset: [CharacterCmdSet](evennia.commands.default.cmdset_character.CharacterCmdSet), help-category: _Building_)
- [**@tickers**](evennia.commands.default.system.CmdTickers) (cmdset: [CharacterCmdSet](evennia.commands.default.cmdset_character.CharacterCmdSet), help-category: _System_)
- [**@time** [@uptime]](evennia.commands.default.system.CmdTime) (cmdset: [CharacterCmdSet](evennia.commands.default.cmdset_character.CharacterCmdSet), help-category: _System_)
- [**@tunnel** [@tun]](evennia.commands.default.building.CmdTunnel) (cmdset: [CharacterCmdSet](evennia.commands.default.cmdset_character.CharacterCmdSet), help-category: _Building_)
- [**@typeclass** [@type, @swap, @update, @parent, @typeclasses]](evennia.commands.default.building.CmdTypeclass) (cmdset: [CharacterCmdSet](evennia.commands.default.cmdset_character.CharacterCmdSet), help-category: _Building_)
- [**@wipe**](evennia.commands.default.building.CmdWipe) (cmdset: [CharacterCmdSet](evennia.commands.default.cmdset_character.CharacterCmdSet), help-category: _Building_)
- [**__unloggedin_look_command** [look, l]](evennia.commands.default.unloggedin.CmdUnconnectedLook) (cmdset: [UnloggedinCmdSet](evennia.commands.default.cmdset_unloggedin.UnloggedinCmdSet), help-category: _General_)
- [**about** [version]](evennia.commands.default.system.CmdAbout) (cmdset: [CharacterCmdSet](evennia.commands.default.cmdset_character.CharacterCmdSet), help-category: _System_)
- [**access** [hierarchy, groups]](evennia.commands.default.general.CmdAccess) (cmdset: [CharacterCmdSet](evennia.commands.default.cmdset_character.CharacterCmdSet), help-category: _General_)
- [**accounts** [account, listaccounts]](evennia.commands.default.system.CmdAccounts) (cmdset: [CharacterCmdSet](evennia.commands.default.cmdset_character.CharacterCmdSet), help-category: _System_)
- [**addcom** [aliaschan, chanalias]](evennia.commands.default.comms.CmdAddCom) (cmdset: [AccountCmdSet](evennia.commands.default.cmdset_account.AccountCmdSet), help-category: _Comms_)
- [**alias** [setobjalias]](evennia.commands.default.building.CmdSetObjAlias) (cmdset: [CharacterCmdSet](evennia.commands.default.cmdset_character.CharacterCmdSet), help-category: _Building_)
- [**allcom**](evennia.commands.default.comms.CmdAllCom) (cmdset: [AccountCmdSet](evennia.commands.default.cmdset_account.AccountCmdSet), help-category: _Comms_)
- [**access** [groups, hierarchy]](evennia.commands.default.general.CmdAccess) (cmdset: [CharacterCmdSet](evennia.commands.default.cmdset_character.CharacterCmdSet), help-category: _General_)
- [**batchcode** [batchcodes]](evennia.commands.default.batchprocess.CmdBatchCode) (cmdset: [CharacterCmdSet](evennia.commands.default.cmdset_character.CharacterCmdSet), help-category: _Building_)
- [**batchcommands** [batchcmd, batchcommand]](evennia.commands.default.batchprocess.CmdBatchCommands) (cmdset: [CharacterCmdSet](evennia.commands.default.cmdset_character.CharacterCmdSet), help-category: _Building_)
- [**cboot**](evennia.commands.default.comms.CmdCBoot) (cmdset: [AccountCmdSet](evennia.commands.default.cmdset_account.AccountCmdSet), help-category: _Comms_)
- [**ccreate** [channelcreate]](evennia.commands.default.comms.CmdChannelCreate) (cmdset: [AccountCmdSet](evennia.commands.default.cmdset_account.AccountCmdSet), help-category: _Comms_)
- [**cdesc**](evennia.commands.default.comms.CmdCdesc) (cmdset: [AccountCmdSet](evennia.commands.default.cmdset_account.AccountCmdSet), help-category: _Comms_)
- [**cdestroy**](evennia.commands.default.comms.CmdCdestroy) (cmdset: [AccountCmdSet](evennia.commands.default.cmdset_account.AccountCmdSet), help-category: _Comms_)
- [**channel** [chan, channels]](evennia.commands.default.comms.CmdChannel) (cmdset: [AccountCmdSet](evennia.commands.default.cmdset_account.AccountCmdSet), help-category: _Comms_)
- [**charcreate**](evennia.commands.default.account.CmdCharCreate) (cmdset: [AccountCmdSet](evennia.commands.default.cmdset_account.AccountCmdSet), help-category: _General_)
- [**chardelete**](evennia.commands.default.account.CmdCharDelete) (cmdset: [AccountCmdSet](evennia.commands.default.cmdset_account.AccountCmdSet), help-category: _General_)
- [**clock**](evennia.commands.default.comms.CmdClock) (cmdset: [AccountCmdSet](evennia.commands.default.cmdset_account.AccountCmdSet), help-category: _Comms_)
- [**cmdsets** [listcmsets]](evennia.commands.default.building.CmdListCmdSets) (cmdset: [CharacterCmdSet](evennia.commands.default.cmdset_character.CharacterCmdSet), help-category: _Building_)
- [**color**](evennia.commands.default.account.CmdColorTest) (cmdset: [AccountCmdSet](evennia.commands.default.cmdset_account.AccountCmdSet), help-category: _General_)
- [**connect** [conn, co, con]](evennia.commands.default.unloggedin.CmdUnconnectedConnect) (cmdset: [UnloggedinCmdSet](evennia.commands.default.cmdset_unloggedin.UnloggedinCmdSet), help-category: _General_)
- [**copy**](evennia.commands.default.building.CmdCopy) (cmdset: [CharacterCmdSet](evennia.commands.default.cmdset_character.CharacterCmdSet), help-category: _Building_)
- [**cpattr**](evennia.commands.default.building.CmdCpAttr) (cmdset: [CharacterCmdSet](evennia.commands.default.cmdset_character.CharacterCmdSet), help-category: _Building_)
- [**create**](evennia.commands.default.building.CmdCreate) (cmdset: [CharacterCmdSet](evennia.commands.default.cmdset_character.CharacterCmdSet), help-category: _Building_)
- [**connect** [co, con, conn]](evennia.commands.default.unloggedin.CmdUnconnectedConnect) (cmdset: [UnloggedinCmdSet](evennia.commands.default.cmdset_unloggedin.UnloggedinCmdSet), help-category: _General_)
- [**create** [cre, cr]](evennia.commands.default.unloggedin.CmdUnconnectedCreate) (cmdset: [UnloggedinCmdSet](evennia.commands.default.cmdset_unloggedin.UnloggedinCmdSet), help-category: _General_)
- [**cwho**](evennia.commands.default.comms.CmdCWho) (cmdset: [AccountCmdSet](evennia.commands.default.cmdset_account.AccountCmdSet), help-category: _Comms_)
- [**delcom** [delaliaschan, delchanalias]](evennia.commands.default.comms.CmdDelCom) (cmdset: [AccountCmdSet](evennia.commands.default.cmdset_account.AccountCmdSet), help-category: _Comms_)
- [**desc** [describe]](evennia.commands.default.building.CmdDesc) (cmdset: [CharacterCmdSet](evennia.commands.default.cmdset_character.CharacterCmdSet), help-category: _Building_)
- [**destroy** [del, delete]](evennia.commands.default.building.CmdDestroy) (cmdset: [CharacterCmdSet](evennia.commands.default.cmdset_character.CharacterCmdSet), help-category: _Building_)
- [**dig**](evennia.commands.default.building.CmdDig) (cmdset: [CharacterCmdSet](evennia.commands.default.cmdset_character.CharacterCmdSet), help-category: _Building_)
- [**drop**](evennia.commands.default.general.CmdDrop) (cmdset: [CharacterCmdSet](evennia.commands.default.cmdset_character.CharacterCmdSet), help-category: _General_)
- [**encoding** [encode]](evennia.commands.default.unloggedin.CmdUnconnectedEncoding) (cmdset: [UnloggedinCmdSet](evennia.commands.default.cmdset_unloggedin.UnloggedinCmdSet), help-category: _General_)
- [**examine** [ex, exam]](evennia.commands.default.building.CmdExamine) (cmdset: [AccountCmdSet](evennia.commands.default.cmdset_account.AccountCmdSet), help-category: _Building_)
- [**find** [locate, search]](evennia.commands.default.building.CmdFind) (cmdset: [CharacterCmdSet](evennia.commands.default.cmdset_character.CharacterCmdSet), help-category: _Building_)
- [**get** [grab]](evennia.commands.default.general.CmdGet) (cmdset: [CharacterCmdSet](evennia.commands.default.cmdset_character.CharacterCmdSet), help-category: _General_)
- [**give**](evennia.commands.default.general.CmdGive) (cmdset: [CharacterCmdSet](evennia.commands.default.cmdset_character.CharacterCmdSet), help-category: _General_)
- [**grapevine2chan**](evennia.commands.default.comms.CmdGrapevine2Chan) (cmdset: [AccountCmdSet](evennia.commands.default.cmdset_account.AccountCmdSet), help-category: _Comms_)
- [**help** [?]](evennia.commands.default.help.CmdHelp) (cmdset: [AccountCmdSet](evennia.commands.default.cmdset_account.AccountCmdSet), help-category: _General_)
- [**help** [h, ?]](evennia.commands.default.unloggedin.CmdUnconnectedHelp) (cmdset: [UnloggedinCmdSet](evennia.commands.default.cmdset_unloggedin.UnloggedinCmdSet), help-category: _General_)
- [**help** [?, h]](evennia.commands.default.unloggedin.CmdUnconnectedHelp) (cmdset: [UnloggedinCmdSet](evennia.commands.default.cmdset_unloggedin.UnloggedinCmdSet), help-category: _General_)
- [**home**](evennia.commands.default.general.CmdHome) (cmdset: [CharacterCmdSet](evennia.commands.default.cmdset_character.CharacterCmdSet), help-category: _General_)
- [**ic** [puppet]](evennia.commands.default.account.CmdIC) (cmdset: [AccountCmdSet](evennia.commands.default.cmdset_account.AccountCmdSet), help-category: _General_)
- [**info**](evennia.commands.default.unloggedin.CmdUnconnectedInfo) (cmdset: [UnloggedinCmdSet](evennia.commands.default.cmdset_unloggedin.UnloggedinCmdSet), help-category: _General_)
- [**inventory** [i, inv]](evennia.commands.default.general.CmdInventory) (cmdset: [CharacterCmdSet](evennia.commands.default.cmdset_character.CharacterCmdSet), help-category: _General_)
- [**inventory** [inv, i]](evennia.commands.default.general.CmdInventory) (cmdset: [CharacterCmdSet](evennia.commands.default.cmdset_character.CharacterCmdSet), help-category: _General_)
- [**irc2chan**](evennia.commands.default.comms.CmdIRC2Chan) (cmdset: [AccountCmdSet](evennia.commands.default.cmdset_account.AccountCmdSet), help-category: _Comms_)
- [**ircstatus**](evennia.commands.default.comms.CmdIRCStatus) (cmdset: [AccountCmdSet](evennia.commands.default.cmdset_account.AccountCmdSet), help-category: _Comms_)
- [**link**](evennia.commands.default.building.CmdLink) (cmdset: [CharacterCmdSet](evennia.commands.default.cmdset_character.CharacterCmdSet), help-category: _Building_)
- [**lock** [locks]](evennia.commands.default.building.CmdLock) (cmdset: [CharacterCmdSet](evennia.commands.default.cmdset_character.CharacterCmdSet), help-category: _Building_)
- [**look** [l, ls]](evennia.commands.default.account.CmdOOCLook) (cmdset: [AccountCmdSet](evennia.commands.default.cmdset_account.AccountCmdSet), help-category: _General_)
- [**look** [l, ls]](evennia.commands.default.general.CmdLook) (cmdset: [CharacterCmdSet](evennia.commands.default.cmdset_character.CharacterCmdSet), help-category: _General_)
- [**mvattr**](evennia.commands.default.building.CmdMvAttr) (cmdset: [CharacterCmdSet](evennia.commands.default.cmdset_character.CharacterCmdSet), help-category: _Building_)
- [**name** [rename]](evennia.commands.default.building.CmdName) (cmdset: [CharacterCmdSet](evennia.commands.default.cmdset_character.CharacterCmdSet), help-category: _Building_)
- [**nick** [nickname, nicks]](evennia.commands.default.general.CmdNick) (cmdset: [AccountCmdSet](evennia.commands.default.cmdset_account.AccountCmdSet), help-category: _General_)
- [**objects** [listobjs, stats, db, listobjects]](evennia.commands.default.building.CmdObjects) (cmdset: [CharacterCmdSet](evennia.commands.default.cmdset_character.CharacterCmdSet), help-category: _System_)
- [**ooc** [unpuppet]](evennia.commands.default.account.CmdOOC) (cmdset: [AccountCmdSet](evennia.commands.default.cmdset_account.AccountCmdSet), help-category: _General_)
- [**open**](evennia.commands.default.building.CmdOpen) (cmdset: [CharacterCmdSet](evennia.commands.default.cmdset_character.CharacterCmdSet), help-category: _Building_)
- [**option** [options]](evennia.commands.default.account.CmdOption) (cmdset: [AccountCmdSet](evennia.commands.default.cmdset_account.AccountCmdSet), help-category: _General_)
- [**page** [tell]](evennia.commands.default.comms.CmdPage) (cmdset: [AccountCmdSet](evennia.commands.default.cmdset_account.AccountCmdSet), help-category: _Comms_)
- [**password**](evennia.commands.default.account.CmdPassword) (cmdset: [AccountCmdSet](evennia.commands.default.cmdset_account.AccountCmdSet), help-category: _General_)
- [**pose** [:, emote]](evennia.commands.default.general.CmdPose) (cmdset: [CharacterCmdSet](evennia.commands.default.cmdset_character.CharacterCmdSet), help-category: _General_)
- [**py** [!]](evennia.commands.default.system.CmdPy) (cmdset: [AccountCmdSet](evennia.commands.default.cmdset_account.AccountCmdSet), help-category: _System_)
- [**quell** [unquell]](evennia.commands.default.account.CmdQuell) (cmdset: [AccountCmdSet](evennia.commands.default.cmdset_account.AccountCmdSet), help-category: _General_)
- [**quit**](evennia.commands.default.account.CmdQuit) (cmdset: [AccountCmdSet](evennia.commands.default.cmdset_account.AccountCmdSet), help-category: _General_)
- [**quit** [qu, q]](evennia.commands.default.unloggedin.CmdUnconnectedQuit) (cmdset: [UnloggedinCmdSet](evennia.commands.default.cmdset_unloggedin.UnloggedinCmdSet), help-category: _General_)
- [**reload** [restart]](evennia.commands.default.system.CmdReload) (cmdset: [AccountCmdSet](evennia.commands.default.cmdset_account.AccountCmdSet), help-category: _System_)
- [**reset** [reboot]](evennia.commands.default.system.CmdReset) (cmdset: [AccountCmdSet](evennia.commands.default.cmdset_account.AccountCmdSet), help-category: _System_)
- [**rss2chan**](evennia.commands.default.comms.CmdRSS2Chan) (cmdset: [AccountCmdSet](evennia.commands.default.cmdset_account.AccountCmdSet), help-category: _Comms_)
- [**say** [", ']](evennia.commands.default.general.CmdSay) (cmdset: [CharacterCmdSet](evennia.commands.default.cmdset_character.CharacterCmdSet), help-category: _General_)
- [**screenreader**](evennia.commands.default.unloggedin.CmdUnconnectedScreenreader) (cmdset: [UnloggedinCmdSet](evennia.commands.default.cmdset_unloggedin.UnloggedinCmdSet), help-category: _General_)
- [**scripts** [script]](evennia.commands.default.building.CmdScripts) (cmdset: [CharacterCmdSet](evennia.commands.default.cmdset_character.CharacterCmdSet), help-category: _System_)
- [**server** [serverload, serverprocess]](evennia.commands.default.system.CmdServerLoad) (cmdset: [CharacterCmdSet](evennia.commands.default.cmdset_character.CharacterCmdSet), help-category: _System_)
- [**service** [services]](evennia.commands.default.system.CmdService) (cmdset: [CharacterCmdSet](evennia.commands.default.cmdset_character.CharacterCmdSet), help-category: _System_)
- [**sessions**](evennia.commands.default.account.CmdSessions) (cmdset: [SessionCmdSet](evennia.commands.default.cmdset_session.SessionCmdSet), help-category: _General_)
- [**set**](evennia.commands.default.building.CmdSetAttribute) (cmdset: [CharacterCmdSet](evennia.commands.default.cmdset_character.CharacterCmdSet), help-category: _Building_)
- [**setdesc**](evennia.commands.default.general.CmdSetDesc) (cmdset: [CharacterCmdSet](evennia.commands.default.cmdset_character.CharacterCmdSet), help-category: _General_)
- [**sethelp**](evennia.commands.default.help.CmdSetHelp) (cmdset: [CharacterCmdSet](evennia.commands.default.cmdset_character.CharacterCmdSet), help-category: _Building_)
- [**sethome**](evennia.commands.default.building.CmdSetHome) (cmdset: [CharacterCmdSet](evennia.commands.default.cmdset_character.CharacterCmdSet), help-category: _Building_)
- [**shutdown**](evennia.commands.default.system.CmdShutdown) (cmdset: [AccountCmdSet](evennia.commands.default.cmdset_account.AccountCmdSet), help-category: _System_)
- [**spawn** [olc]](evennia.commands.default.building.CmdSpawn) (cmdset: [CharacterCmdSet](evennia.commands.default.cmdset_character.CharacterCmdSet), help-category: _Building_)
- [**style**](evennia.commands.default.account.CmdStyle) (cmdset: [AccountCmdSet](evennia.commands.default.cmdset_account.AccountCmdSet), help-category: _General_)
- [**tag** [tags]](evennia.commands.default.building.CmdTag) (cmdset: [CharacterCmdSet](evennia.commands.default.cmdset_character.CharacterCmdSet), help-category: _Building_)
- [**tasks** [task, delays]](evennia.commands.default.system.CmdTasks) (cmdset: [CharacterCmdSet](evennia.commands.default.cmdset_character.CharacterCmdSet), help-category: _System_)
- [**tel** [teleport]](evennia.commands.default.building.CmdTeleport) (cmdset: [CharacterCmdSet](evennia.commands.default.cmdset_character.CharacterCmdSet), help-category: _Building_)
- [**tickers**](evennia.commands.default.system.CmdTickers) (cmdset: [CharacterCmdSet](evennia.commands.default.cmdset_character.CharacterCmdSet), help-category: _System_)
- [**time** [uptime]](evennia.commands.default.system.CmdTime) (cmdset: [CharacterCmdSet](evennia.commands.default.cmdset_character.CharacterCmdSet), help-category: _System_)
- [**tunnel** [tun]](evennia.commands.default.building.CmdTunnel) (cmdset: [CharacterCmdSet](evennia.commands.default.cmdset_character.CharacterCmdSet), help-category: _Building_)
- [**typeclass** [swap, typeclasses, parent, type, update]](evennia.commands.default.building.CmdTypeclass) (cmdset: [CharacterCmdSet](evennia.commands.default.cmdset_character.CharacterCmdSet), help-category: _Building_)
- [**unlink**](evennia.commands.default.building.CmdUnLink) (cmdset: [CharacterCmdSet](evennia.commands.default.cmdset_character.CharacterCmdSet), help-category: _Building_)
- [**whisper**](evennia.commands.default.general.CmdWhisper) (cmdset: [CharacterCmdSet](evennia.commands.default.cmdset_character.CharacterCmdSet), help-category: _General_)
- [**who** [doing]](evennia.commands.default.account.CmdWho) (cmdset: [AccountCmdSet](evennia.commands.default.cmdset_account.AccountCmdSet), help-category: _General_)
- [**wipe**](evennia.commands.default.building.CmdWipe) (cmdset: [CharacterCmdSet](evennia.commands.default.cmdset_character.CharacterCmdSet), help-category: _Building_)

View file

@ -28,6 +28,7 @@ evennia.contrib
evennia.contrib.mapbuilder
evennia.contrib.menu_login
evennia.contrib.multidescer
evennia.contrib.mux_comms_cmds
evennia.contrib.puzzles
evennia.contrib.random_string_generator
evennia.contrib.rplanguage

View file

@ -19,7 +19,6 @@ evennia.server
evennia.server.initial_setup
evennia.server.inputfuncs
evennia.server.manager
evennia.server.markup
evennia.server.models
evennia.server.server
evennia.server.serversession

View file

@ -240,6 +240,7 @@ api/evennia.contrib.mail
api/evennia.contrib.mapbuilder
api/evennia.contrib.menu_login
api/evennia.contrib.multidescer
api/evennia.contrib.mux_comms_cmds
api/evennia.contrib.puzzles
api/evennia.contrib.random_string_generator
api/evennia.contrib.rplanguage
@ -321,7 +322,6 @@ api/evennia.server.game_index_client.service
api/evennia.server.initial_setup
api/evennia.server.inputfuncs
api/evennia.server.manager
api/evennia.server.markup
api/evennia.server.models
api/evennia.server.portal
api/evennia.server.portal.amp

View file

@ -18,6 +18,9 @@ from evennia.utils.evtable import EvTable
from evennia.utils.ansi import ANSIString
CMD_IGNORE_PREFIXES = settings.CMD_IGNORE_PREFIXES
class InterruptCommand(Exception):
"""Cleanly interrupt a command."""
@ -97,12 +100,19 @@ def _init_command(cls, **kwargs):
cls.help_category = cls.help_category.lower()
# pre-prepare a help index entry for quicker lookup
# strip the @- etc to allow help to be agnostic
stripped_key = cls.key[1:] if cls.key and cls.key[0] in CMD_IGNORE_PREFIXES else ""
stripped_aliases = (
" ".join(al for al in cls.aliases
if al and al[0] in CMD_IGNORE_PREFIXES for al in cls.aliases)
)
cls.search_index_entry = {
"key": cls.key,
"aliases": " ".join(cls.aliases),
"no_prefix": f"{stripped_key} {stripped_aliases}",
"category": cls.help_category,
"text": cls.__doc__,
"tags": "",
"tags": ""
}

View file

@ -157,7 +157,7 @@ class CmdSetObjAlias(COMMAND_DEFAULT_CLASS):
by everyone.
"""
key = "alias"
key = "@alias"
aliases = "setobjalias"
switch_options = ("category",)
locks = "cmd:perm(setobjalias) or perm(Builder)"
@ -266,7 +266,7 @@ class CmdCopy(ObjManipCommand):
one exact copy of the original object will be created with the name *_copy.
"""
key = "copy"
key = "@copy"
locks = "cmd:perm(copy) or perm(Builder)"
help_category = "Building"
@ -357,7 +357,7 @@ class CmdCpAttr(ObjManipCommand):
If you don't supply a source object, yourself is used.
"""
key = "cpattr"
key = "@cpattr"
switch_options = ("move",)
locks = "cmd:perm(cpattr) or perm(Builder)"
help_category = "Building"
@ -496,7 +496,7 @@ class CmdMvAttr(ObjManipCommand):
object. If you don't supply a source object, yourself is used.
"""
key = "mvattr"
key = "@mvattr"
switch_options = ("copy",)
locks = "cmd:perm(mvattr) or perm(Builder)"
help_category = "Building"
@ -545,7 +545,7 @@ class CmdCreate(ObjManipCommand):
"""
key = "create"
key = "@create"
switch_options = ("drop",)
locks = "cmd:perm(create) or perm(Builder)"
help_category = "Building"
@ -637,8 +637,7 @@ class CmdDesc(COMMAND_DEFAULT_CLASS):
describe the current room.
"""
key = "desc"
aliases = "describe"
key = "@desc"
switch_options = ("edit",)
locks = "cmd:perm(desc) or perm(Builder)"
help_category = "Building"
@ -722,8 +721,8 @@ class CmdDestroy(COMMAND_DEFAULT_CLASS):
You can specify the /force switch to bypass this confirmation.
"""
key = "destroy"
aliases = ["delete", "del"]
key = "@destroy"
aliases = ["@delete", "@del"]
switch_options = ("override", "force")
locks = "cmd:perm(destroy) or perm(Builder)"
help_category = "Building"
@ -864,7 +863,7 @@ class CmdDig(ObjManipCommand):
would be 'north;no;n'.
"""
key = "dig"
key = "@dig"
switch_options = ("teleport",)
locks = "cmd:perm(dig) or perm(Builder)"
help_category = "Building"
@ -1020,8 +1019,8 @@ class CmdTunnel(COMMAND_DEFAULT_CLASS):
For more flexibility and power in creating rooms, use dig.
"""
key = "tunnel"
aliases = ["tun"]
key = "@tunnel"
aliases = ["@tun"]
switch_options = ("oneway", "tel")
locks = "cmd: perm(tunnel) or perm(Builder)"
help_category = "Building"
@ -1114,7 +1113,7 @@ class CmdLink(COMMAND_DEFAULT_CLASS):
currently set destination.
"""
key = "link"
key = "@link"
locks = "cmd:perm(link) or perm(Builder)"
help_category = "Building"
@ -1251,7 +1250,7 @@ class CmdSetHome(CmdLink):
If no location is given, just view the object's home location.
"""
key = "sethome"
key = "@sethome"
locks = "cmd:perm(sethome) or perm(Builder)"
help_category = "Building"
@ -1303,8 +1302,7 @@ class CmdListCmdSets(COMMAND_DEFAULT_CLASS):
to a user. Defaults to yourself.
"""
key = "cmdsets"
aliases = "listcmsets"
key = "@cmdsets"
locks = "cmd:perm(listcmdsets) or perm(Builder)"
help_category = "Building"
@ -1334,8 +1332,8 @@ class CmdName(ObjManipCommand):
"""
key = "name"
aliases = ["rename"]
key = "@name"
aliases = ["@rename"]
locks = "cmd:perm(rename) or perm(Builder)"
help_category = "Building"
@ -1412,7 +1410,7 @@ class CmdOpen(ObjManipCommand):
"""
key = "open"
key = "@open"
locks = "cmd:perm(open) or perm(Builder)"
help_category = "Building"
@ -1614,7 +1612,7 @@ class CmdSetAttribute(ObjManipCommand):
"""
key = "set"
key = "@set"
locks = "cmd:perm(set) or perm(Builder)"
help_category = "Building"
nested_re = re.compile(r"\[.*?\]")
@ -1978,8 +1976,8 @@ class CmdTypeclass(COMMAND_DEFAULT_CLASS):
"""
key = "typeclass"
aliases = ["type", "parent", "swap", "update", "typeclasses"]
key = "@typeclass"
aliases = ["@type", "@parent", "@swap", "@update", "@typeclasses"]
switch_options = ("show", "examine", "update", "reset", "force", "list", "prototype")
locks = "cmd:perm(typeclass) or perm(Builder)"
help_category = "Building"
@ -2035,7 +2033,7 @@ class CmdTypeclass(COMMAND_DEFAULT_CLASS):
caller = self.caller
if "list" in self.switches or self.cmdname == 'typeclasses':
if "list" in self.switches or self.cmdname in ('typeclasses', '@typeclasses'):
tclasses = get_all_typeclasses()
contribs = [key for key in sorted(tclasses) if key.startswith("evennia.contrib")] or [
"<None loaded>"
@ -2135,10 +2133,10 @@ class CmdTypeclass(COMMAND_DEFAULT_CLASS):
caller.msg(string)
return
if self.cmdstring == "swap":
if self.cmdstring in ("swap", "@swap"):
self.switches.append("force")
self.switches.append("reset")
elif self.cmdstring == "update":
elif self.cmdstring in ("update", "@update"):
self.switches.append("force")
self.switches.append("update")
@ -2229,7 +2227,7 @@ class CmdWipe(ObjManipCommand):
matching the given attribute-wildcard search string.
"""
key = "wipe"
key = "@wipe"
locks = "cmd:perm(wipe) or perm(Builder)"
help_category = "Building"
@ -2298,8 +2296,8 @@ class CmdLock(ObjManipCommand):
'get:id(25); delete:perm(Builder)'
"""
key = "lock"
aliases = ["locks"]
key = "@lock"
aliases = ["@locks"]
locks = "cmd: perm(locks) or perm(Builder)"
help_category = "Building"
@ -2419,8 +2417,8 @@ class CmdExamine(ObjManipCommand):
"""
key = "examine"
aliases = ["ex", "exam"]
key = "@examine"
aliases = ["@ex", "@exam"]
locks = "cmd:perm(examine) or perm(Builder)"
help_category = "Building"
arg_regex = r"(/\w+?(\s|$))|\s|$"
@ -2829,8 +2827,8 @@ class CmdFind(COMMAND_DEFAULT_CLASS):
one is given.
"""
key = "find"
aliases = "search, locate"
key = "@find"
aliases = ["@search", "@locate"]
switch_options = ("room", "exit", "char", "exact", "loc", "startswith")
locks = "cmd:perm(find) or perm(Builder)"
help_category = "Building"
@ -3112,8 +3110,8 @@ class CmdScripts(COMMAND_DEFAULT_CLASS):
"""
key = "scripts"
aliases = ["script"]
key = "@scripts"
aliases = ["@script"]
switch_options = ("create", "start", "stop", "pause", "delete")
locks = "cmd:perm(scripts) or perm(Builder)"
help_category = "System"
@ -3255,8 +3253,7 @@ class CmdObjects(COMMAND_DEFAULT_CLASS):
given, <nr> defaults to 10.
"""
key = "objects"
aliases = ["listobjects", "listobjs", "stats", "db"]
key = "@objects"
locks = "cmd:perm(listobjects) or perm(Builder)"
help_category = "System"
@ -3365,8 +3362,8 @@ class CmdTeleport(COMMAND_DEFAULT_CLASS):
"""
key = "tel"
aliases = "teleport"
key = "@teleport"
aliases = "@tel"
switch_options = ("quiet", "intoexit", "tonone", "loc")
rhs_split = ("=", " to ") # Prefer = delimiter, but allow " to " usage.
locks = "cmd:perm(teleport) or perm(Builder)"
@ -3495,8 +3492,8 @@ class CmdTag(COMMAND_DEFAULT_CLASS):
enough to for most grouping schemes.
"""
key = "tag"
aliases = ["tags"]
key = "@tag"
aliases = ["@tags"]
options = ("search", "del")
locks = "cmd:perm(tag) or perm(Builder)"
help_category = "Building"
@ -3682,8 +3679,8 @@ class CmdSpawn(COMMAND_DEFAULT_CLASS):
"""
key = "spawn"
aliases = ["olc"]
key = "@spawn"
aliases = ["@olc"]
switch_options = (
"noloc",
"search",

View file

@ -60,18 +60,18 @@ class AccountCmdSet(CmdSet):
# Comm commands
self.add(comms.CmdChannel())
# self.add(comms.CmdChannels())
self.add(comms.CmdAddCom())
self.add(comms.CmdDelCom())
self.add(comms.CmdAllCom())
self.add(comms.CmdCdestroy())
self.add(comms.CmdChannelCreate())
self.add(comms.CmdClock())
self.add(comms.CmdCBoot())
self.add(comms.CmdCWho())
self.add(comms.CmdCdesc())
self.add(comms.CmdPage())
self.add(comms.CmdIRC2Chan())
self.add(comms.CmdIRCStatus())
self.add(comms.CmdRSS2Chan())
self.add(comms.CmdGrapevine2Chan())
# self.add(comms.CmdChannels())
# self.add(comms.CmdAddCom())
# self.add(comms.CmdDelCom())
# self.add(comms.CmdAllCom())
# self.add(comms.CmdCdestroy())
# self.add(comms.CmdChannelCreate())
# self.add(comms.CmdClock())
# self.add(comms.CmdCBoot())
# self.add(comms.CmdCWho())
# self.add(comms.CmdCdesc())

View file

@ -28,16 +28,6 @@ __all__ = (
"CmdChannel",
"CmdObjectChannel",
"CmdAddCom",
"CmdDelCom",
"CmdAllCom",
"CmdCdestroy",
"CmdCBoot",
"CmdCWho",
"CmdChannelCreate",
"CmdClock",
"CmdCdesc",
"CmdPage",
"CmdIRC2Chan",
@ -217,8 +207,8 @@ class CmdChannel(COMMAND_DEFAULT_CLASS):
ban mychannel1,mychannel2= EvilUser : Was banned for spamming.
"""
key = "channel"
aliases = ["chan", "channels"]
key = "@channel"
aliases = ["@chan", "@channels"]
help_category = "Comms"
# these cmd: lock controls access to the channel command itself
# the admin: lock controls access to /boot/ban/unban switches
@ -1253,488 +1243,6 @@ class CmdObjectChannel(CmdChannel):
account_caller = False
class CmdAddCom(CmdChannel):
"""
Add a channel alias and/or subscribe to a channel
Usage:
addcom [alias=] <channel>
Joins a given channel. If alias is given, this will allow you to
refer to the channel by this alias rather than the full channel
name. Subsequent calls of this command can be used to add multiple
aliases to an already joined channel.
"""
key = "addcom"
aliases = ["aliaschan", "chanalias"]
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 the command"""
caller = self.caller
args = self.args
if not args:
self.msg("Usage: addcom [alias =] channelname.")
return
if self.rhs:
# rhs holds the channelname
channelname = self.rhs
alias = self.lhs
else:
channelname = self.args
alias = None
channel = self.search_channel(channelname)
if not channel:
return
string = ""
if not channel.has_connection(caller):
# we want to connect as well.
success, err = self.sub_to_channel(channel)
if success:
# if this would have returned True, the account is connected
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
if channel.unmute(caller):
self.msg(f"You unmute channel {channel.key}.")
else:
self.msg(f"You are already connected to channel {channel.key}.")
if alias:
# create a nick and add it to the caller.
self.add_alias(channel, alias)
self.msg(f" You can now refer to the channel {channel} with the alias '{alias}'.")
else:
string += " No alias added."
self.msg(string)
class CmdDelCom(CmdChannel):
"""
remove a channel alias and/or unsubscribe from channel
Usage:
delcom <alias or channel>
delcom/all <channel>
If the full channel name is given, unsubscribe from the
channel. If an alias is given, remove the alias but don't
unsubscribe. If the 'all' switch is used, remove all aliases
for that channel.
"""
key = "delcom"
aliases = ["delaliaschan", "delchanalias"]
help_category = "Comms"
locks = "cmd:not perm(channel_banned)"
# this is used by the COMMAND_DEFAULT_CLASS parent
account_caller = True
def func(self):
"""Implementing the command. """
caller = self.caller
if not self.args:
self.msg("Usage: delcom <alias or channel>")
return
ostring = self.args.lower().strip()
channel = self.search_channel(ostring)
if not channel:
return
if not channel.has_connection(caller):
self.msg("You are not listening to that channel.")
return
if ostring == channel.key.lower():
# an exact channel name - unsubscribe
delnicks = "all" in self.switches
# find all nicks linked to this channel and delete them
if delnicks:
aliases = self.get_channel_aliases(channel)
for alias in aliases:
self.remove_alias(alias)
success, err = self.unsub_from_channel(channel)
if success:
wipednicks = " Eventual aliases were removed." if delnicks else ""
self.msg(f"You stop listening to channel '{channel.key}'.{wipednicks}")
else:
self.msg(err)
return
else:
# we are removing a channel nick
self.remove_alias(ostring)
self.msg(f"Any alias '{ostring}' for channel {channel.key} was cleared.")
class CmdAllCom(CmdChannel):
"""
perform admin operations on all channels
Usage:
allcom [on | off | who | destroy]
Allows the user to universally turn off or on all channels they are on, as
well as perform a 'who' for all channels they are on. Destroy deletes all
channels that you control.
Without argument, works like comlist.
"""
key = "allcom"
aliases = [] # important to not inherit parent's aliases
locks = "cmd: not pperm(channel_banned)"
help_category = "Comms"
# this is used by the COMMAND_DEFAULT_CLASS parent
account_caller = True
def func(self):
"""Runs the function"""
caller = self.caller
args = self.args
if not args:
subscribed, available = self.list_channels()
table = self.display_all_channels(subscribed, available)
self.msg(
"\n|wAvailable channels:\n{table}")
return
return
if args == "on":
# get names of all channels available to listen to
# and activate them all
channels = [
chan
for chan in CHANNEL_DEFAULT_TYPECLASS.objects.get_all_channels()
if chan.access(caller, "listen")
]
for channel in channels:
self.execute_cmd("addcom %s" % channel.key)
elif args == "off":
# get names all subscribed channels and disconnect from them all
channels = CHANNEL_DEFAULT_TYPECLASS.objects.get_subscriptions(caller)
for channel in channels:
self.execute_cmd("delcom %s" % channel.key)
elif args == "destroy":
# destroy all channels you control
channels = [
chan
for chan in CHANNEL_DEFAULT_TYPECLASS.objects.get_all_channels()
if chan.access(caller, "control")
]
for channel in channels:
self.execute_cmd("cdestroy %s" % channel.key)
elif args == "who":
# run a who, listing the subscribers on visible channels.
string = "\n|CChannel subscriptions|n"
channels = [
chan
for chan in CHANNEL_DEFAULT_TYPECLASS.objects.get_all_channels()
if chan.access(caller, "listen")
]
if not channels:
string += "No channels."
for channel in channels:
string += "\n|w%s:|n\n %s" % (channel.key, channel.wholist)
self.msg(string.strip())
else:
# wrong input
self.msg("Usage: allcom on | off | who | clear")
class CmdCdestroy(CmdChannel):
"""
destroy a channel you created
Usage:
cdestroy <channel>
Destroys a channel that you control.
"""
key = "cdestroy"
aliases = []
help_category = "Comms"
locks = "cmd: not pperm(channel_banned)"
# this is used by the COMMAND_DEFAULT_CLASS parent
account_caller = True
def func(self):
"""Destroy objects cleanly."""
caller = self.caller
if not self.args:
self.msg("Usage: cdestroy <channelname>")
return
channel = self.search_channel(self.args)
if not channel:
self.msg("Could not find channel %s." % self.args)
return
if not channel.access(caller, "control"):
self.msg("You are not allowed to do that.")
return
channel_key = channel.key
message = f"{channel.key} is being destroyed. Make sure to change your aliases."
self.destroy_channel(channel, message)
self.msg("Channel '%s' was destroyed." % channel_key)
logger.log_sec(
"Channel Deleted: %s (Caller: %s, IP: %s)."
% (channel_key, caller, self.session.address)
)
class CmdCBoot(CmdChannel):
"""
kick an account from a channel you control
Usage:
cboot[/quiet] <channel> = <account> [:reason]
Switch:
quiet - don't notify the channel
Kicks an account or object from a channel you control.
"""
key = "cboot"
aliases = []
switch_options = ("quiet",)
locks = "cmd: not pperm(channel_banned)"
help_category = "Comms"
# this is used by the COMMAND_DEFAULT_CLASS parent
account_caller = True
def func(self):
"""implement the function"""
if not self.args or not self.rhs:
string = "Usage: cboot[/quiet] <channel> = <account> [:reason]"
self.msg(string)
return
channel = self.search_channel(self.lhs)
if not channel:
return
reason = ""
if ":" in self.rhs:
target, reason = self.rhs.rsplit(":", 1)
is_account = target.strip().startswith("*")
searchstring = target.lstrip("*")
else:
is_account = target.strip().startswith("*")
searchstring = self.rhs.lstrip("*")
target = self.caller.search(searchstring, account=is_account)
if not target:
return
if reason:
reason = " (reason: %s)" % reason
if not channel.access(self.caller, "control"):
string = "You don't control this channel."
self.msg(string)
return
success, err = self.boot_user(target, quiet='quiet' in self.switches)
if success:
self.msg(f"Booted {target.key} from {channel.key}")
logger.log_sec(
"Channel Boot: %s (Channel: %s, Reason: %s, Caller: %s, IP: %s)."
% (self.caller, channel, reason, self.caller, self.session.address)
)
else:
self.msg(err)
class CmdCWho(CmdChannel):
"""
show who is listening to a channel
Usage:
cwho <channel>
List who is connected to a given channel you have access to.
"""
key = "cwho"
aliases = []
locks = "cmd: not pperm(channel_banned)"
help_category = "Comms"
# this is used by the COMMAND_DEFAULT_CLASS parent
account_caller = True
def func(self):
"""implement function"""
if not self.args:
string = "Usage: cwho <channel>"
self.msg(string)
return
channel = self.search_channel(self.lhs)
if not channel:
return
if not channel.access(self.caller, "listen"):
string = "You can't access this channel."
self.msg(string)
return
string = "\n|CChannel subscriptions|n"
string += "\n|w%s:|n\n %s" % (channel.key, channel.wholist)
self.msg(string.strip())
class CmdChannelCreate(CmdChannel):
"""
create a new channel
Usage:
ccreate <new channel>[;alias;alias...] = description
Creates a new channel owned by you.
"""
key = "ccreate"
aliases = "channelcreate"
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 the command"""
if not self.args:
self.msg("Usage ccreate <channelname>[;alias;alias..] = description")
return
description = ""
if self.rhs:
description = self.rhs
lhs = self.lhs
channame = lhs
aliases = None
if ";" in lhs:
channame, aliases = lhs.split(";", 1)
aliases = [alias.strip().lower() for alias in aliases.split(";")]
new_chan, err = self.create_channel(channame, description, aliases=aliases)
if new_chan:
self.msg(f"Created channel {new_chan.key} and connected to it.")
else:
self.msg(err)
class CmdClock(CmdChannel):
"""
change channel locks of a channel you control
Usage:
clock <channel> [= <lockstring>]
Changes the lock access restrictions of a channel. If no
lockstring was given, view the current lock definitions.
"""
key = "clock"
aliases = ["clock"]
locks = "cmd:not pperm(channel_banned) and perm(Admin)"
help_category = "Comms"
# this is used by the COMMAND_DEFAULT_CLASS parent
account_caller = True
def func(self):
"""run the function"""
if not self.args:
string = "Usage: clock channel [= lockstring]"
self.msg(string)
return
channel = self.search_channel(self.lhs)
if not channel:
return
if not self.rhs:
# no =, so just view the current locks
self.msg(f"Current locks on {channel.key}\n{channel.locks}")
return
# we want to add/change a lock.
if not channel.access(self.caller, "control"):
string = "You don't control this channel."
self.msg(string)
return
# Try to add the lock
success, err = self.set_lock(channel, self.rhs)
if success:
self.msg(f"Lock(s) applied. Current locks on {channel.key}:\n{channel.locks}")
else:
self.msg(err)
class CmdCdesc(CmdChannel):
"""
describe a channel you control
Usage:
cdesc <channel> = <description>
Changes the description of the channel as shown in
channel lists.
"""
key = "cdesc"
aliases = []
locks = "cmd:not pperm(channel_banned)"
help_category = "Comms"
# this is used by the COMMAND_DEFAULT_CLASS parent
account_caller = True
def func(self):
"""Implement command"""
caller = self.caller
if not self.rhs:
self.msg("Usage: cdesc <channel> = <description>")
return
channel = self.search_channel(self.lhs)
if not channel:
return
# check permissions
if not channel.access(caller, "control"):
self.msg("You cannot admin this channel.")
return
self.set_desc(channel, self.rhs)
self.msg(f"Description of channel '{channel.key}' set to '{self.rhs}'.")
class CmdPage(COMMAND_DEFAULT_CLASS):
"""
send a private message to another account

View file

@ -8,6 +8,8 @@ outside the game in modules given by ``settings.FILE_HELP_ENTRY_MODULES``.
"""
import re
from itertools import chain
from dataclasses import dataclass
from django.conf import settings
from collections import defaultdict
@ -24,6 +26,7 @@ from evennia.utils.utils import (
)
from evennia.help.utils import help_search_with_index, parse_entry_for_subcategories
CMD_IGNORE_PREFIXES = settings.CMD_IGNORE_PREFIXES
COMMAND_DEFAULT_CLASS = class_from_module(settings.COMMAND_DEFAULT_CLASS)
HELP_MORE_ENABLED = settings.HELP_MORE_ENABLED
DEFAULT_HELP_CATEGORY = settings.DEFAULT_HELP_CATEGORY
@ -46,6 +49,7 @@ class HelpCategory:
"key": self.key,
"aliases": "",
"category": self.key,
"no_prefix": "",
"tags": "",
"text": "",
}
@ -403,7 +407,7 @@ class CmdHelp(COMMAND_DEFAULT_CLASS):
key: entry for key, entry in file_help_topics.items()
if self.can_list_topic(entry, caller)}
else:
# query
# query - check the read lock on entries
cmd_help_topics = {
cmd.auto_help_display_key
if hasattr(cmd, "auto_help_display_key") else cmd.key: cmd
@ -437,7 +441,8 @@ class CmdHelp(COMMAND_DEFAULT_CLASS):
search_fields = [
{"field_name": "key", "boost": 10},
{"field_name": "aliases", "boost": 9},
{"field_name": "category", "boost": 8},
{"field_name": "no_prefix", "boost": 8},
{"field_name": "category", "boost": 7},
{"field_name": "tags", "boost": 1}, # tags are not used by default
]
match, suggestions = None, None
@ -479,6 +484,27 @@ class CmdHelp(COMMAND_DEFAULT_CLASS):
self.topic = ""
self.subtopics = []
def strip_cmd_prefix(self, key, all_keys):
"""
Conditional strip of a command prefix, such as @ in @desc. By default
this will be hidden unless there is a duplicate without the prefix
in the full command set (such as @open and open).
Args:
key (str): Command key to analyze.
all_cmds (list): All command-keys (and potentially aliases).
Returns:
str: Potentially modified key to use in help display.
"""
if key and key[0] in CMD_IGNORE_PREFIXES and key[1:] not in all_keys:
# filter out e.g. `@` prefixes from display if there is duplicate
# with the prefix in the set (such as @open/open)
return key[1:]
return key
def func(self):
"""
Run the dynamic help entry creator.
@ -500,7 +526,12 @@ class CmdHelp(COMMAND_DEFAULT_CLASS):
# group by category (cmds are listed separately)
cmd_help_by_category = defaultdict(list)
file_db_help_by_category = defaultdict(list)
# get a collection of all keys + aliases to be able to strip prefixes like @
key_and_aliases = set(chain(*(cmd._keyaliases for cmd in cmd_help_topics.values())))
for key, cmd in cmd_help_topics.items():
key = self.strip_cmd_prefix(key, key_and_aliases)
cmd_help_by_category[cmd.help_category].append(key)
for key, entry in file_db_help_topics.items():
file_db_help_by_category[entry.help_category].append(key)
@ -548,7 +579,7 @@ class CmdHelp(COMMAND_DEFAULT_CLASS):
{"field_name": "text", "boost": 1},
]
for match_query in [query, f"{query}*"]:
for match_query in [query, f"{query}*", f"*{query}"]:
_, suggestions = help_search_with_index(
match_query, entries,
suggestion_maxnum=self.suggestion_maxnum,
@ -559,7 +590,7 @@ class CmdHelp(COMMAND_DEFAULT_CLASS):
help_text += (
"\n... But matches where found within the help "
"texts of the suggestions below.")
break
# break
output = self.format_help_entry(
topic=None, # this will give a no-match style title
@ -652,10 +683,19 @@ class CmdHelp(COMMAND_DEFAULT_CLASS):
# we reached the bottom of the topic tree
help_text = subtopic_map[None]
# get a collection of all keys + aliases to be able to strip prefixes like @
key_and_aliases = set(chain(*(cmd._keyaliases for cmd in cmd_help_topics.values())))
topic = self.strip_cmd_prefix(topic, key_and_aliases)
if subtopics:
aliases = None
else:
aliases = [self.strip_cmd_prefix(alias, key_and_aliases) for alias in aliases]
suggested = [self.strip_cmd_prefix(sugg, key_and_aliases) for sugg in suggested]
output = self.format_help_entry(
topic=topic,
help_text=help_text,
aliases=aliases if not subtopics else None,
aliases=aliases,
subtopics=subtopic_index,
suggested=suggested,
click_topics=clickable_topics

View file

@ -60,8 +60,8 @@ class CmdReload(COMMAND_DEFAULT_CLASS):
reset to purge) and at_reload() hooks will be called.
"""
key = "reload"
aliases = ["restart"]
key = "@reload"
aliases = ["@restart"]
locks = "cmd:perm(reload) or perm(Developer)"
help_category = "System"
@ -98,8 +98,8 @@ class CmdReset(COMMAND_DEFAULT_CLASS):
"""
key = "reset"
aliases = ["reboot"]
key = "@reset"
aliases = ["@reboot"]
locks = "cmd:perm(reload) or perm(Developer)"
help_category = "System"
@ -122,7 +122,7 @@ class CmdShutdown(COMMAND_DEFAULT_CLASS):
Gracefully shut down both Server and Portal.
"""
key = "shutdown"
key = "@shutdown"
locks = "cmd:perm(shutdown) or perm(Developer)"
help_category = "System"
@ -345,8 +345,8 @@ class CmdPy(COMMAND_DEFAULT_CLASS):
"""
key = "py"
aliases = ["!"]
key = "@py"
aliases = ["@!"]
switch_options = ("time", "edit", "clientraw", "noecho")
locks = "cmd:perm(py) or perm(Developer)"
help_category = "System"
@ -427,8 +427,8 @@ class CmdAccounts(COMMAND_DEFAULT_CLASS):
If not given, <nr> defaults to 10.
"""
key = "accounts"
aliases = ["account", "listaccounts"]
key = "@accounts"
aliases = ["@account"]
switch_options = ("delete",)
locks = "cmd:perm(listaccounts) or perm(Admin)"
help_category = "System"
@ -541,8 +541,8 @@ class CmdService(COMMAND_DEFAULT_CLASS):
in the list.
"""
key = "service"
aliases = ["services"]
key = "@service"
aliases = ["@services"]
switch_options = ("list", "start", "stop", "delete")
locks = "cmd:perm(service) or perm(Developer)"
help_category = "System"
@ -642,8 +642,8 @@ class CmdAbout(COMMAND_DEFAULT_CLASS):
Display info about the game engine.
"""
key = "about"
aliases = "version"
key = "@about"
aliases = "@version"
locks = "cmd:all()"
help_category = "System"
@ -690,8 +690,8 @@ class CmdTime(COMMAND_DEFAULT_CLASS):
and the current time stamp.
"""
key = "time"
aliases = "uptime"
key = "@time"
aliases = "@uptime"
locks = "cmd:perm(time) or perm(Player)"
help_category = "System"
@ -758,8 +758,8 @@ class CmdServerLoad(COMMAND_DEFAULT_CLASS):
"""
key = "server"
aliases = ["serverload", "serverprocess"]
key = "@server"
aliases = ["@serverload"]
switch_options = ("mem", "flushmem")
locks = "cmd:perm(list) or perm(Developer)"
help_category = "System"
@ -907,7 +907,7 @@ class CmdTickers(COMMAND_DEFAULT_CLASS):
"""
key = "tickers"
key = "@tickers"
help_category = "System"
locks = "cmd:perm(tickers) or perm(Builder)"
@ -964,8 +964,8 @@ class CmdTasks(COMMAND_DEFAULT_CLASS):
"""
key = "tasks"
aliases = ["delays", "task"]
key = "@tasks"
aliases = ["@delays", "@task"]
switch_options = ("pause", "unpause", "do_task", "call", "remove", "cancel")
locks = "perm(Developer)"
help_category = "System"

View file

@ -993,7 +993,7 @@ class TestBuilding(CommandTest):
self.call(
building.CmdCpAttr(),
"/copy Obj2/test2 = Obj2/test3",
'cpattr: Extra switch "/copy" ignored.|\nCopied Obj2.test2 -> Obj2.test3. '
'@cpattr: Extra switch "/copy" ignored.|\nCopied Obj2.test2 -> Obj2.test3. '
"(value: 'value2')",
)
self.call(building.CmdMvAttr(), "", "Usage: ")
@ -1864,90 +1864,6 @@ class TestBuilding(CommandTest):
)
class TestComms(CommandTest):
def setUp(self):
super(CommandTest, self).setUp()
self.call(
comms.CmdChannelCreate(),
"testchan;test=Test Channel",
"Created channel testchan and connected to it.",
receiver=self.account,
)
def test_toggle_com(self):
self.call(
comms.CmdAddCom(),
"tc = testchan",
"You are already connected to channel testchan.| You can now",
receiver=self.account,
)
self.call(
comms.CmdDelCom(),
"tc",
"Any alias 'tc' for channel testchan was cleared.",
receiver=self.account,
)
def test_all_com(self):
self.call(
comms.CmdAllCom(),
"",
"Available channels:",
receiver=self.account,
)
def test_clock(self):
self.call(
comms.CmdClock(),
"testchan=send:all()",
"Lock(s) applied. Current locks on testchan:",
receiver=self.account,
)
def test_cdesc(self):
self.call(
comms.CmdCdesc(),
"testchan = Test Channel",
"Description of channel 'testchan' set to 'Test Channel'.",
receiver=self.account,
)
def test_cwho(self):
self.call(
comms.CmdCWho(),
"testchan",
"Channel subscriptions\ntestchan:\n TestAccount",
receiver=self.account,
)
def test_page(self):
self.call(
comms.CmdPage(),
"TestAccount2 = Test",
"TestAccount2 is offline. They will see your message if they list their pages later."
"|You paged TestAccount2 with: 'Test'.",
receiver=self.account,
)
def test_cboot(self):
# No one else connected to boot
self.call(
comms.CmdCBoot(),
"",
"Usage: cboot[/quiet] <channel> = <account> [:reason]",
receiver=self.account,
)
def test_cdestroy(self):
self.call(
comms.CmdCdestroy(),
"testchan",
"[testchan] TestAccount: testchan is being destroyed. Make sure to change your aliases."
"|Channel 'testchan' was destroyed.",
receiver=self.account,
)
from evennia.utils.create import create_channel # noqa
class TestCommsChannel(CommandTest):

View file

@ -0,0 +1,545 @@
"""
Legacy Comms-commands
Griatch 2021
In Evennia 1.0, the old Channel commands (originally inspired by MUX) were
replaced by the single `channel` command that performs all these function.
That command is still required to talk on channels. This contrib (extracted
from Evennia 0.9.5) reuses the channel-management of the base Channel command
but breaks out its functionality into separate Commands with MUX-familiar names.
- `allcom` - `channel/all` and `channel`
- `addcom` - `channel/alias`, `channel/sub` and `channel/unmute`
- `delcom` - `channel/unalias`, `alias/unsub` and `channel/mute`
- `cboot` - `channel/boot` (`channel/ban` and `/unban` not supported)
- `cwho` - `channel/who`
- `ccreate` - `channel/create`
- `cdestroy` - `channel/destroy`
- `clock` - `channel/lock`
- `cdesc` - `channel/desc`
Installation:
- Import the `CmdSetLegacyComms` cmdset from this module into `mygame/commands/default_cmdsets.py`
- Add it to the CharacterCmdSet's `at_cmdset_creation` method.
- Reload the server.
Example:
```python
# in mygame/commands/default_cmdsets.py
# ...
from evennia.contrib.legacy_comms import CmdSetLegacyComms # <----
class CharacterCmdSet(default_cmds.CharacterCmdSet):
# ...
def at_cmdset_creation(self):
# ...
self.add(CmdSetLegacyComms) # <----
```
"""
from django.conf import settings
from evennia.commands.cmdset import CmdSet
from evennia.commands.default.comms import CmdChannel
from evennia.utils import logger
CHANNEL_DEFAULT_TYPECLASS = settings.BASE_CHANNEL_TYPECLASS
class CmdAddCom(CmdChannel):
"""
Add a channel alias and/or subscribe to a channel
Usage:
addcom [alias=] <channel>
Joins a given channel. If alias is given, this will allow you to
refer to the channel by this alias rather than the full channel
name. Subsequent calls of this command can be used to add multiple
aliases to an already joined channel.
"""
key = "addcom"
aliases = ["aliaschan", "chanalias"]
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 the command"""
caller = self.caller
args = self.args
if not args:
self.msg("Usage: addcom [alias =] channelname.")
return
if self.rhs:
# rhs holds the channelname
channelname = self.rhs
alias = self.lhs
else:
channelname = self.args
alias = None
channel = self.search_channel(channelname)
if not channel:
return
string = ""
if not channel.has_connection(caller):
# we want to connect as well.
success, err = self.sub_to_channel(channel)
if success:
# if this would have returned True, the account is connected
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
if channel.unmute(caller):
self.msg(f"You unmute channel {channel.key}.")
else:
self.msg(f"You are already connected to channel {channel.key}.")
if alias:
# create a nick and add it to the caller.
self.add_alias(channel, alias)
self.msg(f" You can now refer to the channel {channel} with the alias '{alias}'.")
else:
string += " No alias added."
self.msg(string)
class CmdDelCom(CmdChannel):
"""
remove a channel alias and/or unsubscribe from channel
Usage:
delcom <alias or channel>
delcom/all <channel>
If the full channel name is given, unsubscribe from the
channel. If an alias is given, remove the alias but don't
unsubscribe. If the 'all' switch is used, remove all aliases
for that channel.
"""
key = "delcom"
aliases = ["delaliaschan", "delchanalias"]
help_category = "Comms"
locks = "cmd:not perm(channel_banned)"
# this is used by the COMMAND_DEFAULT_CLASS parent
account_caller = True
def func(self):
"""Implementing the command. """
caller = self.caller
if not self.args:
self.msg("Usage: delcom <alias or channel>")
return
ostring = self.args.lower().strip()
channel = self.search_channel(ostring)
if not channel:
return
if not channel.has_connection(caller):
self.msg("You are not listening to that channel.")
return
if ostring == channel.key.lower():
# an exact channel name - unsubscribe
delnicks = "all" in self.switches
# find all nicks linked to this channel and delete them
if delnicks:
aliases = self.get_channel_aliases(channel)
for alias in aliases:
self.remove_alias(alias)
success, err = self.unsub_from_channel(channel)
if success:
wipednicks = " Eventual aliases were removed." if delnicks else ""
self.msg(f"You stop listening to channel '{channel.key}'.{wipednicks}")
else:
self.msg(err)
return
else:
# we are removing a channel nick
self.remove_alias(ostring)
self.msg(f"Any alias '{ostring}' for channel {channel.key} was cleared.")
class CmdAllCom(CmdChannel):
"""
perform admin operations on all channels
Usage:
allcom [on | off | who | destroy]
Allows the user to universally turn off or on all channels they are on, as
well as perform a 'who' for all channels they are on. Destroy deletes all
channels that you control.
Without argument, works like comlist.
"""
key = "allcom"
aliases = [] # important to not inherit parent's aliases
locks = "cmd: not pperm(channel_banned)"
help_category = "Comms"
# this is used by the COMMAND_DEFAULT_CLASS parent
account_caller = True
def func(self):
"""Runs the function"""
caller = self.caller
args = self.args
if not args:
subscribed, available = self.list_channels()
self.msg(
"\n|wAvailable channels:\n{table}")
return
return
if args == "on":
# get names of all channels available to listen to
# and activate them all
channels = [
chan
for chan in CHANNEL_DEFAULT_TYPECLASS.objects.get_all_channels()
if chan.access(caller, "listen")
]
for channel in channels:
self.execute_cmd("addcom %s" % channel.key)
elif args == "off":
# get names all subscribed channels and disconnect from them all
channels = CHANNEL_DEFAULT_TYPECLASS.objects.get_subscriptions(caller)
for channel in channels:
self.execute_cmd("delcom %s" % channel.key)
elif args == "destroy":
# destroy all channels you control
channels = [
chan
for chan in CHANNEL_DEFAULT_TYPECLASS.objects.get_all_channels()
if chan.access(caller, "control")
]
for channel in channels:
self.execute_cmd("cdestroy %s" % channel.key)
elif args == "who":
# run a who, listing the subscribers on visible channels.
string = "\n|CChannel subscriptions|n"
channels = [
chan
for chan in CHANNEL_DEFAULT_TYPECLASS.objects.get_all_channels()
if chan.access(caller, "listen")
]
if not channels:
string += "No channels."
for channel in channels:
string += "\n|w%s:|n\n %s" % (channel.key, channel.wholist)
self.msg(string.strip())
else:
# wrong input
self.msg("Usage: allcom on | off | who | clear")
class CmdCdestroy(CmdChannel):
"""
destroy a channel you created
Usage:
cdestroy <channel>
Destroys a channel that you control.
"""
key = "cdestroy"
aliases = []
help_category = "Comms"
locks = "cmd: not pperm(channel_banned)"
# this is used by the COMMAND_DEFAULT_CLASS parent
account_caller = True
def func(self):
"""Destroy objects cleanly."""
caller = self.caller
if not self.args:
self.msg("Usage: cdestroy <channelname>")
return
channel = self.search_channel(self.args)
if not channel:
self.msg("Could not find channel %s." % self.args)
return
if not channel.access(caller, "control"):
self.msg("You are not allowed to do that.")
return
channel_key = channel.key
message = f"{channel.key} is being destroyed. Make sure to change your aliases."
self.destroy_channel(channel, message)
self.msg("Channel '%s' was destroyed." % channel_key)
logger.log_sec(
"Channel Deleted: %s (Caller: %s, IP: %s)."
% (channel_key, caller, self.session.address)
)
class CmdCBoot(CmdChannel):
"""
kick an account from a channel you control
Usage:
cboot[/quiet] <channel> = <account> [:reason]
Switch:
quiet - don't notify the channel
Kicks an account or object from a channel you control.
"""
key = "cboot"
aliases = []
switch_options = ("quiet",)
locks = "cmd: not pperm(channel_banned)"
help_category = "Comms"
# this is used by the COMMAND_DEFAULT_CLASS parent
account_caller = True
def func(self):
"""implement the function"""
if not self.args or not self.rhs:
string = "Usage: cboot[/quiet] <channel> = <account> [:reason]"
self.msg(string)
return
channel = self.search_channel(self.lhs)
if not channel:
return
reason = ""
if ":" in self.rhs:
target, reason = self.rhs.rsplit(":", 1)
is_account = target.strip().startswith("*")
searchstring = target.lstrip("*")
else:
is_account = target.strip().startswith("*")
searchstring = self.rhs.lstrip("*")
target = self.caller.search(searchstring, account=is_account)
if not target:
return
if reason:
reason = " (reason: %s)" % reason
if not channel.access(self.caller, "control"):
string = "You don't control this channel."
self.msg(string)
return
success, err = self.boot_user(target, quiet='quiet' in self.switches)
if success:
self.msg(f"Booted {target.key} from {channel.key}")
logger.log_sec(
"Channel Boot: %s (Channel: %s, Reason: %s, Caller: %s, IP: %s)."
% (self.caller, channel, reason, self.caller, self.session.address)
)
else:
self.msg(err)
class CmdCWho(CmdChannel):
"""
show who is listening to a channel
Usage:
cwho <channel>
List who is connected to a given channel you have access to.
"""
key = "cwho"
aliases = []
locks = "cmd: not pperm(channel_banned)"
help_category = "Comms"
# this is used by the COMMAND_DEFAULT_CLASS parent
account_caller = True
def func(self):
"""implement function"""
if not self.args:
string = "Usage: cwho <channel>"
self.msg(string)
return
channel = self.search_channel(self.lhs)
if not channel:
return
if not channel.access(self.caller, "listen"):
string = "You can't access this channel."
self.msg(string)
return
string = "\n|CChannel subscriptions|n"
string += "\n|w%s:|n\n %s" % (channel.key, channel.wholist)
self.msg(string.strip())
class CmdChannelCreate(CmdChannel):
"""
create a new channel
Usage:
ccreate <new channel>[;alias;alias...] = description
Creates a new channel owned by you.
"""
key = "ccreate"
aliases = "channelcreate"
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 the command"""
if not self.args:
self.msg("Usage ccreate <channelname>[;alias;alias..] = description")
return
description = ""
if self.rhs:
description = self.rhs
lhs = self.lhs
channame = lhs
aliases = None
if ";" in lhs:
channame, aliases = lhs.split(";", 1)
aliases = [alias.strip().lower() for alias in aliases.split(";")]
new_chan, err = self.create_channel(channame, description, aliases=aliases)
if new_chan:
self.msg(f"Created channel {new_chan.key} and connected to it.")
else:
self.msg(err)
class CmdClock(CmdChannel):
"""
change channel locks of a channel you control
Usage:
clock <channel> [= <lockstring>]
Changes the lock access restrictions of a channel. If no
lockstring was given, view the current lock definitions.
"""
key = "clock"
aliases = ["clock"]
locks = "cmd:not pperm(channel_banned) and perm(Admin)"
help_category = "Comms"
# this is used by the COMMAND_DEFAULT_CLASS parent
account_caller = True
def func(self):
"""run the function"""
if not self.args:
string = "Usage: clock channel [= lockstring]"
self.msg(string)
return
channel = self.search_channel(self.lhs)
if not channel:
return
if not self.rhs:
# no =, so just view the current locks
self.msg(f"Current locks on {channel.key}\n{channel.locks}")
return
# we want to add/change a lock.
if not channel.access(self.caller, "control"):
string = "You don't control this channel."
self.msg(string)
return
# Try to add the lock
success, err = self.set_lock(channel, self.rhs)
if success:
self.msg(f"Lock(s) applied. Current locks on {channel.key}:\n{channel.locks}")
else:
self.msg(err)
class CmdCdesc(CmdChannel):
"""
describe a channel you control
Usage:
cdesc <channel> = <description>
Changes the description of the channel as shown in
channel lists.
"""
key = "cdesc"
aliases = []
locks = "cmd:not pperm(channel_banned)"
help_category = "Comms"
# this is used by the COMMAND_DEFAULT_CLASS parent
account_caller = True
def func(self):
"""Implement command"""
caller = self.caller
if not self.rhs:
self.msg("Usage: cdesc <channel> = <description>")
return
channel = self.search_channel(self.lhs)
if not channel:
return
# check permissions
if not channel.access(caller, "control"):
self.msg("You cannot admin this channel.")
return
self.set_desc(channel, self.rhs)
self.msg(f"Description of channel '{channel.key}' set to '{self.rhs}'.")
class CmdSetLegacyComms(CmdSet):
def at_cmdset_createion(self):
self.add(CmdAddCom())
self.add(CmdAllCom())
self.add(CmdDelCom())
self.add(CmdCdestroy())
self.add(CmdCBoot())
self.add(CmdCWho())
self.add(CmdChannelCreate())
self.add(CmdClock())
self.add(CmdCdesc())

View file

@ -3355,3 +3355,92 @@ class TestBuildingMenu(CommandTest):
self.assertEqual(self.char1.ndb._building_menu.obj, self.room1)
self.call(CmdNoMatch(building_menu=self.menu), "q")
self.assertEqual(self.exit.key, "in")
from evennia.contrib import mux_comms_cmds as comms # noqa
class TestLegacyMuxComms(CommandTest):
"""
Test the legacy comms contrib.
"""
def setUp(self):
super(CommandTest, self).setUp()
self.call(
comms.CmdChannelCreate(),
"testchan;test=Test Channel",
"Created channel testchan and connected to it.",
receiver=self.account,
)
def test_toggle_com(self):
self.call(
comms.CmdAddCom(),
"tc = testchan",
"You are already connected to channel testchan.| You can now",
receiver=self.account,
)
self.call(
comms.CmdDelCom(),
"tc",
"Any alias 'tc' for channel testchan was cleared.",
receiver=self.account,
)
def test_all_com(self):
self.call(
comms.CmdAllCom(),
"",
"Available channels:",
receiver=self.account,
)
def test_clock(self):
self.call(
comms.CmdClock(),
"testchan=send:all()",
"Lock(s) applied. Current locks on testchan:",
receiver=self.account,
)
def test_cdesc(self):
self.call(
comms.CmdCdesc(),
"testchan = Test Channel",
"Description of channel 'testchan' set to 'Test Channel'.",
receiver=self.account,
)
def test_cwho(self):
self.call(
comms.CmdCWho(),
"testchan",
"Channel subscriptions\ntestchan:\n TestAccount",
receiver=self.account,
)
def test_page(self):
self.call(
comms.CmdPage(),
"TestAccount2 = Test",
"TestAccount2 is offline. They will see your message if they list their pages later."
"|You paged TestAccount2 with: 'Test'.",
receiver=self.account,
)
def test_cboot(self):
# No one else connected to boot
self.call(
comms.CmdCBoot(),
"",
"Usage: cboot[/quiet] <channel> = <account> [:reason]",
receiver=self.account,
)
def test_cdestroy(self):
self.call(
comms.CmdCdestroy(),
"testchan",
"[testchan] TestAccount: testchan is being destroyed. Make sure to change your aliases."
"|Channel 'testchan' was destroyed.",
receiver=self.account,
)

View file

@ -102,6 +102,7 @@ class FileHelpEntry:
"key": self.key,
"aliases": " ".join(self.aliases),
"category": self.help_category,
"no_prefix": "",
"tags": "",
"locks": "",
"text": self.entrytext,

View file

@ -139,6 +139,7 @@ class HelpEntry(SharedMemoryModel):
return {
"key": self.db_key,
"aliases": " ".join(self.aliases.all()),
"no_prefix": "",
"category": self.db_help_category,
"text": self.db_entrytext,
"tags": " ".join(str(tag) for tag in self.tags.all()),

View file

@ -71,7 +71,8 @@ def help_search_with_index(query, candidate_entries, suggestion_maxnum=5, fields
pass
custom_stop_words_filter = stop_word_filter.generate_stop_word_filter(stop_words)
_LUNR_BUILDER_PIPELINE = (trimmer, custom_stop_words_filter, stemmer)
# _LUNR_BUILDER_PIPELINE = (trimmer, custom_stop_words_filter, stemmer)
_LUNR_BUILDER_PIPELINE = (custom_stop_words_filter, stemmer)
indx = [cnd.search_index_entry for cnd in candidate_entries]
mapping = {indx[ix]["key"]: cand for ix, cand in enumerate(candidate_entries)}