diff --git a/CHANGELOG.md b/CHANGELOG.md index 2aa6af1c86..118a1bbff3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -51,6 +51,8 @@ - New FileHelpStorage system allows adding help entries via external files. - In modules given by `settings.PROTOTYPE_MODULES`, spawner will now first look for a global list `PROTOTYPE_LIST` of dicts before loading all dicts in the module as prototypes. +- New Channel-System using the `channel` command and nicks. Removed the `ChannelHandler` and the + concept of a dynamically created `ChannelCmdSet`. ### Evennia 0.9.5 (2019-2020) diff --git a/docs/source/Components/Channels.md b/docs/source/Components/Channels.md index 8c9b0de6f8..5998880201 100644 --- a/docs/source/Components/Channels.md +++ b/docs/source/Components/Channels.md @@ -170,7 +170,7 @@ The default `help` command has the following `locks` property: locks = "cmd:not perm(channel_banned); admin:all(); manage:all(); changelocks: perm(Admin)" ``` -This is a regular [lockstring](Locks). +This is a regular [lockstring](./Locks). - `cmd: pperm(channel_banned)` - The `cmd` locktype is the standard one used for all Commands. an accessing object failing this will not even know that the command exists. The `pperm()` lockfunc @@ -335,7 +335,7 @@ see the [Channel api docs](api:evennia.comms.comms.DefaultChannel) for details. - `channel_prefix_string` - this property is a string to easily change how the channel is prefixed. It takes the `channelname` format key. Default is `"[{channelname}] "` and produces output like `[public] ...``. -- `subscriptions` - this is the [SubscriptionHandler](`api:evennia.comms.comms.SubscriptionHandler`), which +- `subscriptions` - this is the [SubscriptionHandler](api:evennia.comms.comms#SubscriptionHandler), which has methods `has`, `add`, `remove`, `all`, `clear` and also `online` (to get only actually online channel-members). - `wholist`, `mutelist`, `banlist` are properties that return a list of subscribers, diff --git a/docs/source/Howto/Howto-Overview.md b/docs/source/Howto/Howto-Overview.md index 3741b67683..6c404f7fba 100644 --- a/docs/source/Howto/Howto-Overview.md +++ b/docs/source/Howto/Howto-Overview.md @@ -66,7 +66,6 @@ in mind for your own game, this will give you a good start. ## Howto's - [Giving Exits a default error](./Default-Exit-Errors) -- [Customize Channel output](./Customize-channels) - [Add a command prompt](./Command-Prompt) - [Don't allow spamming commands](./Command-Cooldown) - [Commands that take time](./Command-Duration) diff --git a/docs/source/toc.md b/docs/source/toc.md index 0fd3b361b4..2f721e1866 100644 --- a/docs/source/toc.md +++ b/docs/source/toc.md @@ -91,7 +91,6 @@ - [Howto/Command Duration](Howto/Command-Duration) - [Howto/Command Prompt](Howto/Command-Prompt) - [Howto/Coordinates](Howto/Coordinates) -- [Howto/Customize channels](Howto/Customize-channels) - [Howto/Default Exit Errors](Howto/Default-Exit-Errors) - [Howto/Evennia for Diku Users](Howto/Evennia-for-Diku-Users) - [Howto/Evennia for MUSH Users](Howto/Evennia-for-MUSH-Users) diff --git a/evennia/commands/default/comms.py b/evennia/commands/default/comms.py index d162cec55e..fe56df9334 100644 --- a/evennia/commands/default/comms.py +++ b/evennia/commands/default/comms.py @@ -74,7 +74,7 @@ class CmdChannel(COMMAND_DEFAULT_CLASS): channel/lock channelname = lockstring channel/unlock channelname = lockstring channel/ban channelname (list bans) - channel/ban[/quiet] channelname[, channelname, ...] = subscribername [: logmessage] + channel/ban[/quiet] channelname[, channelname, ...] = subscribername [: reason] channel/unban[/quiet] channelname[, channelname, ...] = subscribername channel/boot[/quiet] channelname[,channelname,...] = subscribername [: reason] @@ -161,15 +161,17 @@ class CmdChannel(COMMAND_DEFAULT_CLASS): channel/unmute channelname Muting silences all output from the channel without actually - un-subscribing. Other channel members will see you are muted in the /who - list. Sending a message to the channel will automatically unmute you. + un-subscribing. Other channel members will see that you are muted in the /who + list. Sending a message to the channel will automatically unmute you. ## create and destroy Usage: channel/create channelname[;alias;alias[:typeclass]] [= description] channel/destroy channelname [= reason] - Creates a new channel (or destroys one you control). + Creates a new channel (or destroys one you control). You will automatically + join the channel you create and everyone will be kicked and loose all aliases + to a destroyed channel. ## lock and unlock @@ -193,28 +195,25 @@ class CmdChannel(COMMAND_DEFAULT_CLASS): ## boot and ban - Usage: channel/ban channelname (list bans) - channel/ban channelname[, channelname, ...] = subscribername [: logmessage] + Usage: + channel/boot[/quiet] channelname[,channelname,...] = subscribername [: reason] + channel/ban channelname[, channelname, ...] = subscribername [: reason] channel/unban channelname[, channelname, ...] = subscribername channel/unban channelname - channel/boot[/quiet] channelname[,channelname,...] = subscribername [: reason] + channel/ban channelname (list bans) - Booting will kick a named subscriber from a channel temporarily. It will - also remove all their aliases. They are still able to re-connect unless - they are also banned. The 'reason' given will be echoed to the user and - channel. + Booting will kick a named subscriber from channel(s) temporarily. The + 'reason' will be passed to the booted user. Unless the /quiet switch is + used, the channel will also be informed of the action. A booted user is + still able to re-connect, but they'll have to set up their aliases again. - Banning will block a given subscriber's ability to connect to a channel. It - will not automatically boot them. The 'logmessage' will be stored on the - channel and shown when you list your bans (so you can remember why they - were banned). - - So to permanently get rid of a user, the way to do so is to first ban them - and then boot them. + Banning will blacklist a user from (re)joining the provided channels. It + will then proceed to boot them from those channels if they were connected. + The 'reason' and `/quiet` works the same as for booting. Example: - ban mychannel1,mychannel2 = EvilUser : Was banned for spamming. - boot mychannel1,mychannel2 = EvilUser : No more spamming! + boot mychannel1 = EvilUser : Kicking you to cool down a bit. + ban mychannel1,mychannel2= EvilUser : Was banned for spamming. """ key = "channel" diff --git a/evennia/comms/migrations/0019_auto_20210514_2032.py b/evennia/comms/migrations/0019_auto_20210514_2032.py new file mode 100644 index 0000000000..76d12af68f --- /dev/null +++ b/evennia/comms/migrations/0019_auto_20210514_2032.py @@ -0,0 +1,41 @@ +# Generated by Django 2.2.16 on 2021-05-14 20:32 + +from django.db import migrations + + +def migrate_channel_aliases(apps, schema_editor): + """ + Note - this migration uses the contemporary ChannelDB rather than + the apps.get_model version. This allows for using all the + helper functionality, but introduces a dependency on current code. So + We catch errors and warn, since this is not something that will be needed + after doing the first migration. + + """ + from evennia.comms.models import ChannelDB + # ChannelDB = apps.get_model("comms", "ChannelDB") + + for channel in ChannelDB.objects.all(): + try: + chan_key = channel.db_key.lower() + channel_aliases = [chan_key] + [alias.lower() for alias in channel.aliases.all()] + for subscriber in channel.subscriptions.all(): + nicktuples = subscriber.nicks.get(category="channel", return_tuple=True, return_list=True) + all_aliases = channel_aliases + [tup[2] for tup in nicktuples if tup[3].lower() == chan_key] + for key_or_alias in all_aliases: + channel.add_user_channel_alias(subscriber, key_or_alias) + except Exception as err: + # we want to continue gracefully here since this is a data-migration from + # an old to a new version and doesn't involve schema changes + print("channel-alias data migration 0019_auto_20210514_2032 skipped: {err}") + + +class Migration(migrations.Migration): + + dependencies = [ + ('comms', '0018_auto_20191025_0831'), + ] + + operations = [ + migrations.RunPython(migrate_channel_aliases) + ] diff --git a/evennia/typeclasses/attributes.py b/evennia/typeclasses/attributes.py index 529e981203..590a727463 100644 --- a/evennia/typeclasses/attributes.py +++ b/evennia/typeclasses/attributes.py @@ -1464,8 +1464,8 @@ class NickHandler(AttributeHandler): shell patterns using the `fnmatch` library and can contain `$N`-markers to indicate the locations of arguments to catch. If `pattern_is_regex=True`, this must instead be a valid regular - expression and the `$N`-markers must be named `argN` matching - groups (see examples). + expression and the `$N`-markers must be named `argN` that matches + numbered regex groups (see examples). replacement (str): The string (or template) to replace `key` with (the "nickname"). This may contain `$N` markers to indicate where to place the argument-matches @@ -1487,7 +1487,7 @@ class NickHandler(AttributeHandler): Example: - pattern (default shell syntax): `"gr $1 at $2"` - - pattern (with pattern_is_regex=True): `r"gr (?P.+?) at (?P.+?)" + - pattern (with pattern_is_regex=True): `r"gr (?P.+?) at (?P.+?)"` - replacement: `"emote With a flourish, $1 grins at $2."` """ diff --git a/evennia/utils/evmenu.py b/evennia/utils/evmenu.py index 528f273e26..289e84de34 100644 --- a/evennia/utils/evmenu.py +++ b/evennia/utils/evmenu.py @@ -1728,8 +1728,8 @@ def ask_yes_no(caller, prompt="Yes or No {options}?", yes_action="Yes", no_actio If a string, this string will be echoed back to the caller. default (str optional): This is what the user will get if they just press the return key without giving any input. One of 'N', 'Y', 'A' or `None` - for no default (an explicit choice must be given). If 'A' is given, - `allow_abort` kwarg is ignored and assumed set. + for no default (an explicit choice must be given). If 'A' (abort) + is given, `allow_abort` kwarg is ignored and assumed set. allow_abort (bool, optional): If set, the 'A(bort)' option is available (a third option meaning neither yes or no but just exits the prompt). session (Session, optional): This allows to specify the @@ -1737,10 +1737,11 @@ def ask_yes_no(caller, prompt="Yes or No {options}?", yes_action="Yes", no_actio is an Account in multisession modes greater than 2. The session is then updated by the command and is available (for example in callbacks) through `caller.ndb._yes_no_question.session`. - *args, **kwargs: These are passed into the callables. + *args: Additional arguments passed on into callables. + **kwargs: Additional keyword args passed on into callables. Raises: - RuntimeError, FooError: If default and allow_abort clashes. + RuntimeError, FooError: If default and `allow_abort` clashes. Example: ::