<h1>Channels<aclass="headerlink"href="#channels"title="Permalink to this headline">¶</a></h1>
<p>In a multiplayer game, players often need other means of in-game communication
than moving to the same room and use <codeclass="docutils literal notranslate"><spanclass="pre">say</span></code> or <codeclass="docutils literal notranslate"><spanclass="pre">emote</span></code>.</p>
<p><em>Channels</em> allows Evennia’s to act as a fancy chat program. When a player is
connected to a channel, sending a message to it will automatically distribute
it to every other subscriber.</p>
<p>Channels can be used both for chats between <aclass="reference internal"href="Accounts.html"><spanclass="doc std std-doc">Accounts</span></a> and between
<aclass="reference internal"href="Objects.html"><spanclass="doc std std-doc">Objects</span></a> (usually Characters). Chats could be both OOC
(out-of-character) or IC (in-charcter) in nature. Some examples:</p>
<ulclass="simple">
<li><p>A support channel for contacting staff (OOC)</p></li>
<li><p>A general chat for discussing anything and foster community (OOC)</p></li>
<li><p>Admin channel for private staff discussions (OOC)</p></li>
<li><p>Private guild channels for planning and organization (IC/OOC depending on game)</p></li>
<p>In the default command set, channels are all handled via the mighty <aclass="reference internal"href="../api/evennia.commands.default.comms.html#evennia.commands.default.comms.CmdChannel"title="evennia.commands.default.comms.CmdChannel"><spanclass="xref myst py py-class">channel command</span></a>, <codeclass="docutils literal notranslate"><spanclass="pre">channel</span></code> (or <codeclass="docutils literal notranslate"><spanclass="pre">chan</span></code>). By default, this command will assume all entities dealing with channels are <codeclass="docutils literal notranslate"><spanclass="pre">Accounts</span></code>.</p>
<div><p>What happens when aliasing is that a <aclass="reference internal"href="Nicks.html"><spanclass="doc std std-doc">nick</span></a> is created that maps your
alias + argument onto calling the <codeclass="docutils literal notranslate"><spanclass="pre">channel</span></code> command. So when you enter <codeclass="docutils literal notranslate"><spanclass="pre">foo</span><spanclass="pre">hello</span></code>,
what the server sees is actually <codeclass="docutils literal notranslate"><spanclass="pre">channel</span><spanclass="pre">foo</span><spanclass="pre">=</span><spanclass="pre">hello</span></code>. The system is also
clever enough to know that whenever you search for channels, your channel-nicks
should also be considered so as to convert your input to an existing channel name.</p>
</div></blockquote>
<p>You can check if you missed channel conversations by viewing the channel’s
scrollback with</p>
<divclass="highlight-none notranslate"><divclass="highlight"><pre><span></span>channel/history public
</pre></div>
</div>
<p>This retrieves the last 20 lines of text (also from a time when you were
offline). You can step further back by specifying how many lines back to start:</p>
<divclass="highlight-none notranslate"><divclass="highlight"><pre><span></span>channel/history public = 30
</pre></div>
</div>
<p>This again retrieve 20 lines, but starting 30 lines back (so you’ll get lines
30-50 counting backwards).</p>
</section>
<sectionid="channel-administration">
<h3>Channel administration<aclass="headerlink"href="#channel-administration"title="Permalink to this headline">¶</a></h3>
<p>Each dict is fed as <codeclass="docutils literal notranslate"><spanclass="pre">**channeldict</span></code> into the <aclass="reference internal"href="../api/evennia.utils.create.html#evennia.utils.create.create_channel"title="evennia.utils.create.create_channel"><spanclass="xref myst py py-func">create_channel</span></a> function, and thus supports all the same keywords.</p>
<p>Evennia also has two system-related channels:</p>
<ulclass="simple">
<li><p><codeclass="docutils literal notranslate"><spanclass="pre">CHANNEL_MUDINFO</span></code> is a dict describing the “MudInfo” channel. This is assumed to exist and is a place for Evennia to echo important server information. The idea is that server admins and staff can subscribe to this channel to stay in the loop.</p></li>
<li><p><codeclass="docutils literal notranslate"><spanclass="pre">CHANNEL_CONECTINFO</span></code> is not defined by default. It will receive connect/disconnect-messages and could be visible also for regular players. If not given, connection-info will just be logged quietly.</p></li>
</ul>
</section>
<sectionid="managing-channels-in-game">
<h4>Managing channels in-game<aclass="headerlink"href="#managing-channels-in-game"title="Permalink to this headline">¶</a></h4>
<p>To create/destroy a new channel on the fly you can do</p>
<p>Aliases are optional but can be good for obvious shortcuts everyone may want to
use. The description is used in channel-listings. You will automatically join a
channel you created and will be controlling it. You can also use <codeclass="docutils literal notranslate"><spanclass="pre">channel/desc</span></code> to
<p>Banning adds the user to the channels blacklist. This means they will not be
able to <em>rejoin</em> if you boot them. You will need to run <codeclass="docutils literal notranslate"><spanclass="pre">channel/boot</span></code> to
<p>See the <aclass="reference internal"href="../api/evennia.commands.default.comms.html#evennia.commands.default.comms.CmdChannel"title="evennia.commands.default.comms.CmdChannel"><spanclass="xref myst py py-class">Channel command</span></a> api docs (and in-game help) for more details.</p>
<li><p><codeclass="docutils literal notranslate"><spanclass="pre">listen</span></code> - who may listen to the channel. Users without this access will not
even be able to join the channel and it will not appear in listings for them.</p></li>
<li><p><codeclass="docutils literal notranslate"><spanclass="pre">send</span></code> - who may send to the channel.</p></li>
<li><p><codeclass="docutils literal notranslate"><spanclass="pre">control</span></code> - this is assigned to you automatically when you create the channel. With
control over the channel you can edit it, boot users and do other management tasks.</p></li>
<p>By default everyone can use the channel command (<aclass="reference internal"href="../api/evennia.commands.default.comms.html#evennia.commands.default.comms.CmdChannel"title="evennia.commands.default.comms.CmdChannel"><spanclass="xref myst py py-class">evennia.commands.default.comms.CmdChannel</span></a>) to create channels and will then control the channels they created (to boot/ban people etc). If you as a developer does not want regular players to do this (perhaps you want only staff to be able to spawn new channels), you can override the <codeclass="docutils literal notranslate"><spanclass="pre">channel</span></code> command and change its <codeclass="docutils literal notranslate"><spanclass="pre">locks</span></code> property.</p>
<p>The default <codeclass="docutils literal notranslate"><spanclass="pre">help</span></code> command has the following <codeclass="docutils literal notranslate"><spanclass="pre">locks</span></code> property:</p>
<p>This is a regular <aclass="reference internal"href="Locks.html"><spanclass="doc std std-doc">lockstring</span></a>.</p>
<ulclass="simple">
<li><p><codeclass="docutils literal notranslate"><spanclass="pre">cmd:</span><spanclass="pre">pperm(channel_banned)</span></code> - The <codeclass="docutils literal notranslate"><spanclass="pre">cmd</span></code> locktype is the standard one used for all Commands.
an accessing object failing this will not even know that the command exists. The <codeclass="docutils literal notranslate"><spanclass="pre">pperm()</span></code> lockfunc
checks an on-account [Permission](Building Permissions) ‘channel_banned’ - and the <codeclass="docutils literal notranslate"><spanclass="pre">not</span></code> means
that if they <em>have</em> that ‘permission’ they are cut off from using the <codeclass="docutils literal notranslate"><spanclass="pre">channel</span></code> command. You usually
don’t need to change this lock.</p></li>
<li><p><codeclass="docutils literal notranslate"><spanclass="pre">admin:all()</span></code> - this is a lock checked in the <codeclass="docutils literal notranslate"><spanclass="pre">channel</span></code> command itself. It controls access to the
<codeclass="docutils literal notranslate"><spanclass="pre">/boot</span></code>, <codeclass="docutils literal notranslate"><spanclass="pre">/ban</span></code> and <codeclass="docutils literal notranslate"><spanclass="pre">/unban</span></code> switches (by default letting everyone use them).</p></li>
<li><p><codeclass="docutils literal notranslate"><spanclass="pre">manage:all()</span></code> - this controls access to the <codeclass="docutils literal notranslate"><spanclass="pre">/create</span></code>, <codeclass="docutils literal notranslate"><spanclass="pre">/destroy</span></code>, <codeclass="docutils literal notranslate"><spanclass="pre">/desc</span></code> switches.</p></li>
<li><p><codeclass="docutils literal notranslate"><spanclass="pre">changelocks:</span><spanclass="pre">perm(Admin)</span></code> - this controls access to the <codeclass="docutils literal notranslate"><spanclass="pre">/lock</span></code> and <codeclass="docutils literal notranslate"><spanclass="pre">/unlock</span></code> switches. By
default this is something only [Admins](Building Permissions) can change.</p></li>
</ul>
<blockquote>
<div><p>Note - while <codeclass="docutils literal notranslate"><spanclass="pre">admin:all()</span></code> and <codeclass="docutils literal notranslate"><spanclass="pre">manage:all()</span></code> will let everyone use these switches, users
will still only be able to admin or destroy channels they actually control!</p>
</div></blockquote>
<p>If you only want (say) Builders and higher to be able to create and admin
channels you could override the <codeclass="docutils literal notranslate"><spanclass="pre">help</span></code> command and change the lockstring to:</p>
<divclass="highlight-python notranslate"><divclass="highlight"><pre><span></span><spanclass="c1"># in for example mygame/commands/commands.py</span>
<spanclass="n">locks</span><spanclass="o">=</span><spanclass="s2">"cmd: not pperm(channel_banned);admin:perm(Builder);manage:perm(Builder);changelocks:perm(Admin)"</span>
<h3>Allowing Characters to use Channels<aclass="headerlink"href="#allowing-characters-to-use-channels"title="Permalink to this headline">¶</a></h3>
<p>The default <codeclass="docutils literal notranslate"><spanclass="pre">channel</span></code> command (<aclass="reference internal"href="../api/evennia.commands.default.comms.html#evennia.commands.default.comms.CmdChannel"title="evennia.commands.default.comms.CmdChannel"><spanclass="xref myst py py-class">evennia.commands.default.comms.CmdChannel</span></a>) sits in the <codeclass="docutils literal notranslate"><spanclass="pre">Account</span></code><aclass="reference internal"href="Command-Sets.html"><spanclass="doc std std-doc">command set</span></a>. It is set up such that it will always operate on <codeclass="docutils literal notranslate"><spanclass="pre">Accounts</span></code>, even if you were to add it to the <codeclass="docutils literal notranslate"><spanclass="pre">CharacterCmdSet</span></code>.</p>
<p>It’s a one-line change to make this command accept non-account callers. But for convenience we provide a version for Characters/Objects. Just import <aclass="reference internal"href="../api/evennia.commands.default.comms.html#evennia.commands.default.comms.CmdObjectChannel"title="evennia.commands.default.comms.CmdObjectChannel"><spanclass="xref myst py py-class">evennia.commands.default.comms.CmdObjectChannel</span></a> and inherit from that instead.</p>
<h3>Customizing channel output and behavior<aclass="headerlink"href="#customizing-channel-output-and-behavior"title="Permalink to this headline">¶</a></h3>
<p>When distributing a message, the channel will call a series of hooks on itself
and (more importantly) on each recipient. So you can customize things a lot by
just modifying hooks on your normal Object/Account typeclasses.</p>
<p>Internally, the message is sent with
<codeclass="docutils literal notranslate"><spanclass="pre">channel.msg(message,</span><spanclass="pre">senders=sender,</span><spanclass="pre">bypass_mute=False,</span><spanclass="pre">**kwargs)</span></code>, where
<codeclass="docutils literal notranslate"><spanclass="pre">bypass_mute=True</span></code> means the message ignores muting (good for alerts or if you
delete the channel etc) and <codeclass="docutils literal notranslate"><spanclass="pre">**kwargs</span></code> are any extra info you may want to pass
to the hooks. The <codeclass="docutils literal notranslate"><spanclass="pre">senders</span></code> (it’s always only one in the default implementation
but could in principle be multiple) and <codeclass="docutils literal notranslate"><spanclass="pre">bypass_mute</span></code> are part of the <codeclass="docutils literal notranslate"><spanclass="pre">kwargs</span></code>
<p>Note that <codeclass="docutils literal notranslate"><spanclass="pre">Accounts</span></code> and <codeclass="docutils literal notranslate"><spanclass="pre">Objects</span></code> both have their have separate sets of hooks.
<h3>Channel class<aclass="headerlink"href="#channel-class"title="Permalink to this headline">¶</a></h3>
<p>Channels are <aclass="reference internal"href="Typeclasses.html"><spanclass="doc std std-doc">Typeclassed</span></a> entities. This means they are persistent in the database, can have <aclass="reference internal"href="Attributes.html"><spanclass="doc std std-doc">attributes</span></a> and <aclass="reference internal"href="Tags.html"><spanclass="doc std std-doc">Tags</span></a> and can be easily extended.</p>
<p>To change which channel typeclass Evennia uses for default commands, change <codeclass="docutils literal notranslate"><spanclass="pre">settings.BASE_CHANNEL_TYPECLASS</span></code>. The base command class is <aclass="reference internal"href="../api/evennia.comms.comms.html#evennia.comms.comms.DefaultChannel"title="evennia.comms.comms.DefaultChannel"><spanclass="xref myst py py-class"><codeclass="docutils literal notranslate"><spanclass="pre">evennia.comms.comms.DefaultChannel</span></code></span></a>. There is an empty child class in <codeclass="docutils literal notranslate"><spanclass="pre">mygame/typeclasses/channels.py</span></code>, same as for other typelass-bases.</p>
<spanclass="c1"># view subscriptions (the SubscriptionHandler handles all subs under the hood)</span>
<spanclass="n">channel</span><spanclass="o">.</span><spanclass="n">subscriptions</span><spanclass="o">.</span><spanclass="n">has</span><spanclass="p">(</span><spanclass="n">me</span><spanclass="p">)</span><spanclass="c1"># check we subbed</span>
<spanclass="n">channel</span><spanclass="o">.</span><spanclass="n">subscriptions</span><spanclass="o">.</span><spanclass="n">all</span><spanclass="p">()</span><spanclass="c1"># get all subs</span>
<spanclass="n">channel</span><spanclass="o">.</span><spanclass="n">subscriptions</span><spanclass="o">.</span><spanclass="n">online</span><spanclass="p">()</span><spanclass="c1"># get only subs currently online</span>
<p>The channel has many more hooks, both hooks shared with all typeclasses as well as special ones related to muting/banning etc. See the channel class for
<p>The channel messages are not stored in the database. A channel is instead always logged to a regular text log-file <codeclass="docutils literal notranslate"><spanclass="pre">mygame/server/logs/channel_<channelname>.log</span></code>. This is where <codeclass="docutils literal notranslate"><spanclass="pre">channels/history</span><spanclass="pre">channelname</span></code> gets its data from. A channel’s log will rotate when it grows too big, which thus also automatically limits the max amount of history a user can view with
<p>The log file name is set on the channel class as the <codeclass="docutils literal notranslate"><spanclass="pre">log_file</span></code> property. This
is a string that takes the formatting token <codeclass="docutils literal notranslate"><spanclass="pre">{channelname}</span></code> to be replaced with
the (lower-case) name of the channel. By default the log is written to in the
<h3>Properties on Channels<aclass="headerlink"href="#properties-on-channels"title="Permalink to this headline">¶</a></h3>
<p>Channels have all the standard properties of a Typeclassed entity (<codeclass="docutils literal notranslate"><spanclass="pre">key</span></code>,
<codeclass="docutils literal notranslate"><spanclass="pre">aliases</span></code>, <codeclass="docutils literal notranslate"><spanclass="pre">attributes</span></code>, <codeclass="docutils literal notranslate"><spanclass="pre">tags</span></code>, <codeclass="docutils literal notranslate"><spanclass="pre">locks</span></code> etc). This is not an exhaustive list;
see the <aclass="reference internal"href="../api/evennia.comms.comms.html#evennia.comms.comms.DefaultChannel"title="evennia.comms.comms.DefaultChannel"><spanclass="xref myst py py-class">Channel api docs</span></a> for details.</p>
<ulclass="simple">
<li><p><codeclass="docutils literal notranslate"><spanclass="pre">send_to_online_only</span></code> - this class boolean defaults to <codeclass="docutils literal notranslate"><spanclass="pre">True</span></code> and is a
sensible optimization since people offline people will not see the message anyway.</p></li>
<li><p><codeclass="docutils literal notranslate"><spanclass="pre">log_file</span></code> - this is a string that determines the name of the channel log file. Default
is <codeclass="docutils literal notranslate"><spanclass="pre">"channel_{channelname}.log"</span></code>. The log file will appear in <codeclass="docutils literal notranslate"><spanclass="pre">settings.LOG_DIR</span></code> (usually
<codeclass="docutils literal notranslate"><spanclass="pre">mygame/server/logs/</span></code>). You should usually not change this.</p></li>
<li><p><codeclass="docutils literal notranslate"><spanclass="pre">channel_prefix_string</span></code> - this property is a string to easily change how
the channel is prefixed. It takes the <codeclass="docutils literal notranslate"><spanclass="pre">channelname</span></code> format key. Default is <codeclass="docutils literal notranslate"><spanclass="pre">"[{channelname}]</span><spanclass="pre">"</span></code>
and produces output like <codeclass="docutils literal notranslate"><spanclass="pre">[public]</span><spanclass="pre">...</span></code>.</p></li>
<li><p><codeclass="docutils literal notranslate"><spanclass="pre">subscriptions</span></code> - this is the <aclass="reference internal"href="../api/evennia.comms.models.html#evennia.comms.models.SubscriptionHandler"title="evennia.comms.models.SubscriptionHandler"><spanclass="xref myst py py-class">SubscriptionHandler</span></a>, which
has methods <codeclass="docutils literal notranslate"><spanclass="pre">has</span></code>, <codeclass="docutils literal notranslate"><spanclass="pre">add</span></code>, <codeclass="docutils literal notranslate"><spanclass="pre">remove</span></code>, <codeclass="docutils literal notranslate"><spanclass="pre">all</span></code>, <codeclass="docutils literal notranslate"><spanclass="pre">clear</span></code> and also <codeclass="docutils literal notranslate"><spanclass="pre">online</span></code> (to get
only actually online channel-members).</p></li>
<li><p><codeclass="docutils literal notranslate"><spanclass="pre">wholist</span></code>, <codeclass="docutils literal notranslate"><spanclass="pre">mutelist</span></code>, <codeclass="docutils literal notranslate"><spanclass="pre">banlist</span></code> are properties that return a list of subscribers,
as well as who are currently muted or banned.</p></li>
<li><p><codeclass="docutils literal notranslate"><spanclass="pre">channel_msg_nick_pattern</span></code> - this is a regex pattern for performing the in-place nick
replacement (detect that <codeclass="docutils literal notranslate"><spanclass="pre">channelalias</span><spanclass="pre"><msg</span></code> means that you want to send a message to a channel).
This pattern accepts an <codeclass="docutils literal notranslate"><spanclass="pre">{alias}</span></code> formatting marker. Don’t mess with this unless you really
want to change how channels work.</p></li>
<li><p><codeclass="docutils literal notranslate"><spanclass="pre">channel_msg_nick_replacement</span></code> - this is a string on the [nick replacement</p></li>
<li><p>form](./Nicks.md). It accepts the <codeclass="docutils literal notranslate"><spanclass="pre">{channelname}</span></code> formatting tag. This is strongly tied to the
<codeclass="docutils literal notranslate"><spanclass="pre">channel</span></code> command and is by default <codeclass="docutils literal notranslate"><spanclass="pre">channel</span><spanclass="pre">{channelname}</span><spanclass="pre">=</span><spanclass="pre">$1</span></code>.</p></li>
<li><p><codeclass="docutils literal notranslate"><spanclass="pre">at_pre_channel_msg(message,</span><spanclass="pre">**kwargs)</span></code> - called before sending a message, to
modify it. Not used by default.</p></li>
<li><p><codeclass="docutils literal notranslate"><spanclass="pre">msg(message,</span><spanclass="pre">senders=...,</span><spanclass="pre">bypass_mute=False,</span><spanclass="pre">**kwargs)</span></code> - send the message onto
the channel. The <codeclass="docutils literal notranslate"><spanclass="pre">**kwargs</span></code> are passed on into the other call hooks (also on the recipient).</p></li>
<li><p><codeclass="docutils literal notranslate"><spanclass="pre">at_post_channel_msg(message,</span><spanclass="pre">**kwargs)</span></code> - by default this is used to store the message
to the log file.</p></li>
<li><p><codeclass="docutils literal notranslate"><spanclass="pre">channel_prefix(message)</span></code> - this is called to allow the channel to prefix. This is called
by the object/account when they build the message, so if wanting something else one can
also just remove that call.</p></li>
<li><p>every channel message. By default it just returns <codeclass="docutils literal notranslate"><spanclass="pre">channel_prefix_string</span></code>.</p></li>
<li><p><codeclass="docutils literal notranslate"><spanclass="pre">has_connection(subscriber)</span></code> - shortcut to check if an entity subscribes to
this channel.</p></li>
<li><p><codeclass="docutils literal notranslate"><spanclass="pre">mute/unmute(subscriber)</span></code> - this mutes the channel for this user.</p></li>
<li><p><codeclass="docutils literal notranslate"><spanclass="pre">ban/unban(subscriber)</span></code> - adds/remove user from banlist.</p></li>
<li><p><codeclass="docutils literal notranslate"><spanclass="pre">connect/disconnect(subscriber)</span></code> - adds/removes a subscriber.</p></li>
<li><p><codeclass="docutils literal notranslate"><spanclass="pre">add_user_channel_alias(user,</span><spanclass="pre">alias,</span><spanclass="pre">**kwargs)</span></code> - sets up a user-nick for this channel. This is
what maps e.g. <codeclass="docutils literal notranslate"><spanclass="pre">alias</span><spanclass="pre"><msg></span></code> to <codeclass="docutils literal notranslate"><spanclass="pre">channel</span><spanclass="pre">channelname</span><spanclass="pre">=</span><spanclass="pre"><msg></span></code>.</p></li>
<li><p><codeclass="docutils literal notranslate"><spanclass="pre">remove_user_channel_alias(user,</span><spanclass="pre">alias,</span><spanclass="pre">**kwargs)</span></code> - remove an alias. Note that this is
a class-method that will happily remove found channel-aliases from the user linked to <em>any</em>
channel, not only from the channel the method is called on.</p></li>
<li><p><codeclass="docutils literal notranslate"><spanclass="pre">pre_join_channel(subscriber)</span></code> - if this returns <codeclass="docutils literal notranslate"><spanclass="pre">False</span></code>, connection will be refused.</p></li>
<li><p><codeclass="docutils literal notranslate"><spanclass="pre">post_join_channel(subscriber)</span></code> - by default this sets up a users’ channel-nicks/aliases.</p></li>
<li><p><codeclass="docutils literal notranslate"><spanclass="pre">pre_leave_channel(subscriber)</span></code> - if this returns <codeclass="docutils literal notranslate"><spanclass="pre">False</span></code>, the user is not allowed to leave.</p></li>
<li><p><codeclass="docutils literal notranslate"><spanclass="pre">post_leave_channel(subscriber)</span></code> - this will clean up any channel aliases/nicks of the user.</p></li>
<li><p><codeclass="docutils literal notranslate"><spanclass="pre">delete</span></code> the standard typeclass-delete mechanism will also automatically un-subscribe all
subscribers (and thus wipe all their aliases).</p></li>