2021-10-03 16:18:46 +05:30

331 lines
29 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>A Primer to Gateway Intents</title>
<!-- end extra head -->
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
<link rel="stylesheet" type="text/css" href="_static/pygments.css" />
<link rel="stylesheet" type="text/css" href="_static/basic.css" />
<link rel="stylesheet" href="_static/style.css" type="text/css" />
<link rel="stylesheet" href="_static/codeblocks.css" type="text/css" />
<link rel="stylesheet" href="_static/icons.css" type="text/css" />
<script id="documentation_options" data-url_root="./" src="_static/documentation_options.js"></script>
<script data-url_root="./" id="documentation_options" src="_static/documentation_options.js"></script>
<script src="_static/jquery.js"></script>
<script src="_static/underscore.js"></script>
<script src="_static/doctools.js"></script>
<script src="_static/custom.js"></script>
<script src="_static/settings.js"></script>
<script src="_static/copy.js"></script>
<script src="_static/sidebar.js"></script>
<link rel="shortcut icon" href="_static/discord_py_logo.ico"/>
<link rel="index" title="Index" href="genindex.html" />
<link rel="search" title="Search" href="search.html" />
</head>
<body>
<div class="main-grid">
<header class="grid-item">
<nav>
<a href="index.html" class="main-heading">discord.py</a>
<a href="https://github.com/Rapptz/discord.py" title="GitHub"><span class="material-icons custom-icons">github</span></a>
<a href="https://discord.gg/TvqYBrGXEm" title="Discord"><span class="material-icons custom-icons">discord</span></a>
<a href="faq.html" title="FAQ"><span class="material-icons">help_center</span></a>
<a onclick="mobileSearch.open();" title="Search" id="open-search" class="mobile-only"><span class="material-icons">search</span></a>
<a onclick="mobileSearch.close();" title="Close" id="close-search" class="mobile-only" hidden><span class="material-icons">close</span></a>
</nav>
<nav class="mobile-only">
<form role="search" class="search" action="search.html" method="get">
<div class="search-wrapper">
<input type="search" name="q" placeholder="Search documentation" />
<button type="submit">
<span class="material-icons">search</span>
</button>
</div>
</form>
</nav>
</header>
<div class="sub-header grid-item">
<label for="documentation_select">View Documentation For</label>
<select id="documentation_select" onchange="window.location = this.value;">
<option value="#" selected>discord</option>
<option value="ext/commands/index.html" >discord.ext.commands</option>
<option value="ext/tasks/index.html" >discord.ext.tasks</option>
</select>
<form role="search" class="search" action="search.html" method="get">
<div class="search-wrapper">
<input type="search" name="q" placeholder="Search documentation" />
<button type="submit">
<span class="material-icons">search</span>
</button>
</div>
</form>
<a accesskey="S" class="settings" onclick="settingsModal.open();"><span class="material-icons">settings</span></a>
</div>
<aside class="grid-item">
<span id="hamburger-toggle">
<span class="material-icons">menu</span>
</span>
<span id="settings-toggle" class="settings" onclick="settingsModal.open();">
<span class="material-icons">settings</span>
</span>
<div id="sidebar">
<h3><a href="index.html">Table of Contents</a></h3>
<ul>
<li><a class="reference internal" href="#">A Primer to Gateway Intents</a><ul>
<li><a class="reference internal" href="#what-intents-are-needed">What intents are needed?</a></li>
<li><a class="reference internal" href="#privileged-intents">Privileged Intents</a><ul>
<li><a class="reference internal" href="#do-i-need-privileged-intents">Do I need privileged intents?</a><ul>
<li><a class="reference internal" href="#presence-intent">Presence Intent</a></li>
<li><a class="reference internal" href="#member-intent">Member Intent</a></li>
</ul>
</li>
</ul>
</li>
<li><a class="reference internal" href="#member-cache">Member Cache</a></li>
<li><a class="reference internal" href="#retrieving-members">Retrieving Members</a></li>
<li><a class="reference internal" href="#troubleshooting">Troubleshooting</a><ul>
<li><a class="reference internal" href="#where-d-my-members-go">Whered my members go?</a></li>
<li><a class="reference internal" href="#why-does-on-ready-take-so-long-to-fire">Why does <code class="docutils literal notranslate"><span class="pre">on_ready</span></code> take so long to fire?</a></li>
</ul>
</li>
</ul>
</li>
</ul>
</div>
</aside>
<main class="grid-item" role="main">
<div class="versionadded">
<p><span class="versionmodified added">New in version 1.5.</span></p>
</div>
<section id="a-primer-to-gateway-intents">
<span id="intents-primer"></span><h1>A Primer to Gateway Intents<a class="headerlink" href="#a-primer-to-gateway-intents" title="Permalink to this headline"></a></h1>
<p>In version 1.5 comes the introduction of <a class="reference internal" href="api.html#discord.Intents" title="discord.Intents"><code class="xref py py-class docutils literal notranslate"><span class="pre">Intents</span></code></a>. This is a radical change in how bots are written. An intent basically allows a bot to subscribe to specific buckets of events. The events that correspond to each intent is documented in the individual attribute of the <a class="reference internal" href="api.html#discord.Intents" title="discord.Intents"><code class="xref py py-class docutils literal notranslate"><span class="pre">Intents</span></code></a> documentation.</p>
<p>These intents are passed to the constructor of <a class="reference internal" href="api.html#discord.Client" title="discord.Client"><code class="xref py py-class docutils literal notranslate"><span class="pre">Client</span></code></a> or its subclasses (<a class="reference internal" href="api.html#discord.AutoShardedClient" title="discord.AutoShardedClient"><code class="xref py py-class docutils literal notranslate"><span class="pre">AutoShardedClient</span></code></a>, <a class="reference internal" href="ext/commands/api.html#discord.ext.commands.AutoShardedBot" title="discord.ext.commands.AutoShardedBot"><code class="xref py py-class docutils literal notranslate"><span class="pre">AutoShardedBot</span></code></a>, <a class="reference internal" href="ext/commands/api.html#discord.ext.commands.Bot" title="discord.ext.commands.Bot"><code class="xref py py-class docutils literal notranslate"><span class="pre">Bot</span></code></a>) with the <code class="docutils literal notranslate"><span class="pre">intents</span></code> argument.</p>
<p>If intents are not passed, then the library defaults to every intent being enabled except the privileged intents, currently <a class="reference internal" href="api.html#discord.Intents.members" title="discord.Intents.members"><code class="xref py py-attr docutils literal notranslate"><span class="pre">Intents.members</span></code></a> and <a class="reference internal" href="api.html#discord.Intents.presences" title="discord.Intents.presences"><code class="xref py py-attr docutils literal notranslate"><span class="pre">Intents.presences</span></code></a>.</p>
<section id="what-intents-are-needed">
<h2>What intents are needed?<a class="headerlink" href="#what-intents-are-needed" title="Permalink to this headline"></a></h2>
<p>The intents that are necessary for your bot can only be dictated by yourself. Each attribute in the <a class="reference internal" href="api.html#discord.Intents" title="discord.Intents"><code class="xref py py-class docutils literal notranslate"><span class="pre">Intents</span></code></a> class documents what <a class="reference internal" href="api.html#discord-api-events"><span class="std std-ref">events</span></a> it corresponds to and what kind of cache it enables.</p>
<p>For example, if you want a bot that functions without spammy events like presences or typing then we could do the following:</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span> <span class="kn">import</span> <span class="nn">discord</span>
<span class="n">intents</span> <span class="o">=</span> <span class="n">discord</span><span class="o">.</span><span class="n">Intents</span><span class="o">.</span><span class="n">default</span><span class="p">()</span>
<span class="n">intents</span><span class="o">.</span><span class="n">typing</span> <span class="o">=</span> <span class="kc">False</span>
<span class="n">intents</span><span class="o">.</span><span class="n">presences</span> <span class="o">=</span> <span class="kc">False</span>
<span class="c1"># Somewhere else:</span>
<span class="hll"> <span class="c1"># client = discord.Client(intents=intents)</span>
</span> <span class="c1"># or</span>
<span class="hll"> <span class="c1"># from discord.ext import commands</span>
</span><span class="hll"> <span class="c1"># bot = commands.Bot(command_prefix=&#39;!&#39;, intents=intents)</span>
</span></pre></div>
</div>
<p>Note that this doesnt enable <a class="reference internal" href="api.html#discord.Intents.members" title="discord.Intents.members"><code class="xref py py-attr docutils literal notranslate"><span class="pre">Intents.members</span></code></a> since its a privileged intent.</p>
<p>Another example showing a bot that only deals with messages and guild information:</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span> <span class="kn">import</span> <span class="nn">discord</span>
<span class="n">intents</span> <span class="o">=</span> <span class="n">discord</span><span class="o">.</span><span class="n">Intents</span><span class="p">(</span><span class="n">messages</span><span class="o">=</span><span class="kc">True</span><span class="p">,</span> <span class="n">guilds</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span>
<span class="c1"># If you also want reaction events enable the following:</span>
<span class="c1"># intents.reactions = True</span>
<span class="c1"># Somewhere else:</span>
<span class="hll"> <span class="c1"># client = discord.Client(intents=intents)</span>
</span> <span class="c1"># or</span>
<span class="hll"> <span class="c1"># from discord.ext import commands</span>
</span><span class="hll"> <span class="c1"># bot = commands.Bot(command_prefix=&#39;!&#39;, intents=intents)</span>
</span></pre></div>
</div>
</section>
<section id="privileged-intents">
<span id="id1"></span><h2>Privileged Intents<a class="headerlink" href="#privileged-intents" title="Permalink to this headline"></a></h2>
<p>With the API change requiring bot authors to specify intents, some intents were restricted further and require more manual steps. These intents are called <strong>privileged intents</strong>.</p>
<p>A privileged intent is one that requires you to go to the developer portal and manually enable it. To enable privileged intents do the following:</p>
<ol class="arabic">
<li><p>Make sure youre logged on to the <a class="reference external" href="https://discord.com">Discord website</a>.</p></li>
<li><p>Navigate to the <a class="reference external" href="https://discord.com/developers/applications">application page</a>.</p></li>
<li><p>Click on the bot you want to enable privileged intents for.</p></li>
<li><p>Navigate to the bot tab on the left side of the screen.</p>
<blockquote>
<div><img alt="The bot tab in the application page." src="_images/discord_bot_tab.png" />
</div></blockquote>
</li>
<li><p>Scroll down to the “Privileged Gateway Intents” section and enable the ones you want.</p>
<blockquote>
<div><img alt="The privileged gateway intents selector." src="_images/discord_privileged_intents.png" />
</div></blockquote>
</li>
</ol>
<div class="admonition warning">
<p class="admonition-title">Warning</p>
<p>Enabling privileged intents when your bot is in over 100 guilds requires going through <a class="reference external" href="https://support.discord.com/hc/en-us/articles/360040720412">bot verification</a>. If your bot is already verified and you would like to enable a privileged intent you must go through <a class="reference external" href="https://dis.gd/contact">Discord support</a> and talk to them about it.</p>
</div>
<div class="admonition note">
<p class="admonition-title">Note</p>
<p>Even if you enable intents through the developer portal, you still have to enable the intents
through code as well.</p>
</div>
<section id="do-i-need-privileged-intents">
<h3>Do I need privileged intents?<a class="headerlink" href="#do-i-need-privileged-intents" title="Permalink to this headline"></a></h3>
<p>This is a quick checklist to see if you need specific privileged intents.</p>
<section id="presence-intent">
<span id="need-presence-intent"></span><h4>Presence Intent<a class="headerlink" href="#presence-intent" title="Permalink to this headline"></a></h4>
<ul class="simple">
<li><p>Whether you use <a class="reference internal" href="api.html#discord.Member.status" title="discord.Member.status"><code class="xref py py-attr docutils literal notranslate"><span class="pre">Member.status</span></code></a> at all to track member statuses.</p></li>
<li><p>Whether you use <a class="reference internal" href="api.html#discord.Member.activity" title="discord.Member.activity"><code class="xref py py-attr docutils literal notranslate"><span class="pre">Member.activity</span></code></a> or <a class="reference internal" href="api.html#discord.Member.activities" title="discord.Member.activities"><code class="xref py py-attr docutils literal notranslate"><span class="pre">Member.activities</span></code></a> to check members activities.</p></li>
</ul>
</section>
<section id="member-intent">
<span id="need-members-intent"></span><h4>Member Intent<a class="headerlink" href="#member-intent" title="Permalink to this headline"></a></h4>
<ul class="simple">
<li><p>Whether you track member joins or member leaves, corresponds to <a class="reference internal" href="api.html#discord.on_member_join" title="discord.on_member_join"><code class="xref py py-func docutils literal notranslate"><span class="pre">on_member_join()</span></code></a> and <a class="reference internal" href="api.html#discord.on_member_remove" title="discord.on_member_remove"><code class="xref py py-func docutils literal notranslate"><span class="pre">on_member_remove()</span></code></a> events.</p></li>
<li><p>Whether you want to track member updates such as nickname or role changes.</p></li>
<li><p>Whether you want to track user updates such as usernames, avatars, discriminators, etc.</p></li>
<li><p>Whether you want to request the guild member list through <a class="reference internal" href="api.html#discord.Guild.chunk" title="discord.Guild.chunk"><code class="xref py py-meth docutils literal notranslate"><span class="pre">Guild.chunk()</span></code></a> or <a class="reference internal" href="api.html#discord.Guild.fetch_members" title="discord.Guild.fetch_members"><code class="xref py py-meth docutils literal notranslate"><span class="pre">Guild.fetch_members()</span></code></a>.</p></li>
<li><p>Whether you want high accuracy member cache under <a class="reference internal" href="api.html#discord.Guild.members" title="discord.Guild.members"><code class="xref py py-attr docutils literal notranslate"><span class="pre">Guild.members</span></code></a>.</p></li>
</ul>
</section>
</section>
</section>
<section id="member-cache">
<span id="intents-member-cache"></span><h2>Member Cache<a class="headerlink" href="#member-cache" title="Permalink to this headline"></a></h2>
<p>Along with intents, Discord now further restricts the ability to cache members and expects bot authors to cache as little as is necessary. However, to properly maintain a cache the <a class="reference internal" href="api.html#discord.Intents.members" title="discord.Intents.members"><code class="xref py py-attr docutils literal notranslate"><span class="pre">Intents.members</span></code></a> intent is required in order to track the members who left and properly evict them.</p>
<p>To aid with member cache where we dont need members to be cached, the library now has a <a class="reference internal" href="api.html#discord.MemberCacheFlags" title="discord.MemberCacheFlags"><code class="xref py py-class docutils literal notranslate"><span class="pre">MemberCacheFlags</span></code></a> flag to control the member cache. The documentation page for the class goes over the specific policies that are possible.</p>
<p>It should be noted that certain things do not need a member cache since Discord will provide full member information if possible. For example:</p>
<ul class="simple">
<li><p><a class="reference internal" href="api.html#discord.on_message" title="discord.on_message"><code class="xref py py-func docutils literal notranslate"><span class="pre">on_message()</span></code></a> will have <a class="reference internal" href="api.html#discord.Message.author" title="discord.Message.author"><code class="xref py py-attr docutils literal notranslate"><span class="pre">Message.author</span></code></a> be a member even if cache is disabled.</p></li>
<li><p><a class="reference internal" href="api.html#discord.on_voice_state_update" title="discord.on_voice_state_update"><code class="xref py py-func docutils literal notranslate"><span class="pre">on_voice_state_update()</span></code></a> will have the <code class="docutils literal notranslate"><span class="pre">member</span></code> parameter be a member even if cache is disabled.</p></li>
<li><p><a class="reference internal" href="api.html#discord.on_reaction_add" title="discord.on_reaction_add"><code class="xref py py-func docutils literal notranslate"><span class="pre">on_reaction_add()</span></code></a> will have the <code class="docutils literal notranslate"><span class="pre">user</span></code> parameter be a member when in a guild even if cache is disabled.</p></li>
<li><p><a class="reference internal" href="api.html#discord.on_raw_reaction_add" title="discord.on_raw_reaction_add"><code class="xref py py-func docutils literal notranslate"><span class="pre">on_raw_reaction_add()</span></code></a> will have <a class="reference internal" href="api.html#discord.RawReactionActionEvent.member" title="discord.RawReactionActionEvent.member"><code class="xref py py-attr docutils literal notranslate"><span class="pre">RawReactionActionEvent.member</span></code></a> be a member when in a guild even if cache is disabled.</p></li>
<li><p>The reaction add events do not contain additional information when in direct messages. This is a Discord limitation.</p></li>
<li><p>The reaction removal events do not have member information. This is a Discord limitation.</p></li>
</ul>
<p>Other events that take a <a class="reference internal" href="api.html#discord.Member" title="discord.Member"><code class="xref py py-class docutils literal notranslate"><span class="pre">Member</span></code></a> will require the use of the member cache. If absolute accuracy over the member cache is desirable, then it is advisable to have the <a class="reference internal" href="api.html#discord.Intents.members" title="discord.Intents.members"><code class="xref py py-attr docutils literal notranslate"><span class="pre">Intents.members</span></code></a> intent enabled.</p>
</section>
<section id="retrieving-members">
<span id="id2"></span><h2>Retrieving Members<a class="headerlink" href="#retrieving-members" title="Permalink to this headline"></a></h2>
<p>If the cache is disabled or you disable chunking guilds at startup, we might still need a way to load members. The library offers a few ways to do this:</p>
<ul class="simple">
<li><dl class="simple">
<dt><a class="reference internal" href="api.html#discord.Guild.query_members" title="discord.Guild.query_members"><code class="xref py py-meth docutils literal notranslate"><span class="pre">Guild.query_members()</span></code></a></dt><dd><ul>
<li><p>Used to query members by a prefix matching nickname or username.</p></li>
<li><p>This can also be used to query members by their user ID.</p></li>
<li><p>This uses the gateway and not the HTTP.</p></li>
</ul>
</dd>
</dl>
</li>
<li><dl class="simple">
<dt><a class="reference internal" href="api.html#discord.Guild.chunk" title="discord.Guild.chunk"><code class="xref py py-meth docutils literal notranslate"><span class="pre">Guild.chunk()</span></code></a></dt><dd><ul>
<li><p>This can be used to fetch the entire member list through the gateway.</p></li>
</ul>
</dd>
</dl>
</li>
<li><dl class="simple">
<dt><a class="reference internal" href="api.html#discord.Guild.fetch_member" title="discord.Guild.fetch_member"><code class="xref py py-meth docutils literal notranslate"><span class="pre">Guild.fetch_member()</span></code></a></dt><dd><ul>
<li><p>Used to fetch a member by ID through the HTTP API.</p></li>
</ul>
</dd>
</dl>
</li>
<li><dl class="simple">
<dt><a class="reference internal" href="api.html#discord.Guild.fetch_members" title="discord.Guild.fetch_members"><code class="xref py py-meth docutils literal notranslate"><span class="pre">Guild.fetch_members()</span></code></a></dt><dd><ul>
<li><p>used to fetch a large number of members through the HTTP API.</p></li>
</ul>
</dd>
</dl>
</li>
</ul>
<p>It should be noted that the gateway has a strict rate limit of 120 requests per 60 seconds.</p>
</section>
<section id="troubleshooting">
<h2>Troubleshooting<a class="headerlink" href="#troubleshooting" title="Permalink to this headline"></a></h2>
<p>Some common issues relating to the mandatory intent change.</p>
<section id="where-d-my-members-go">
<h3>Whered my members go?<a class="headerlink" href="#where-d-my-members-go" title="Permalink to this headline"></a></h3>
<p>Due to an <a class="reference internal" href="#intents-member-cache"><span class="std std-ref">API change</span></a> Discord is now forcing developers who want member caching to explicitly opt-in to it. This is a Discord mandated change and there is no way to bypass it. In order to get members back you have to explicitly enable the <a class="reference internal" href="#privileged-intents"><span class="std std-ref">members privileged intent</span></a> and change the <a class="reference internal" href="api.html#discord.Intents.members" title="discord.Intents.members"><code class="xref py py-attr docutils literal notranslate"><span class="pre">Intents.members</span></code></a> attribute to true.</p>
<p>For example:</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span> <span class="kn">import</span> <span class="nn">discord</span>
<span class="n">intents</span> <span class="o">=</span> <span class="n">discord</span><span class="o">.</span><span class="n">Intents</span><span class="o">.</span><span class="n">default</span><span class="p">()</span>
<span class="hll"> <span class="n">intents</span><span class="o">.</span><span class="n">members</span> <span class="o">=</span> <span class="kc">True</span>
</span>
<span class="c1"># Somewhere else:</span>
<span class="hll"> <span class="c1"># client = discord.Client(intents=intents)</span>
</span> <span class="c1"># or</span>
<span class="hll"> <span class="c1"># from discord.ext import commands</span>
</span><span class="hll"> <span class="c1"># bot = commands.Bot(command_prefix=&#39;!&#39;, intents=intents)</span>
</span></pre></div>
</div>
</section>
<section id="why-does-on-ready-take-so-long-to-fire">
<h3>Why does <code class="docutils literal notranslate"><span class="pre">on_ready</span></code> take so long to fire?<a class="headerlink" href="#why-does-on-ready-take-so-long-to-fire" title="Permalink to this headline"></a></h3>
<p>As part of the API change regarding intents, Discord also changed how members are loaded in the beginning. Originally the library could request 75 guilds at once and only request members from guilds that have the <a class="reference internal" href="api.html#discord.Guild.large" title="discord.Guild.large"><code class="xref py py-attr docutils literal notranslate"><span class="pre">Guild.large</span></code></a> attribute set to <code class="docutils literal notranslate"><span class="pre">True</span></code>. With the new intent changes, Discord mandates that we can only send 1 guild per request. This causes a 75x slowdown which is further compounded by the fact that <em>all</em> guilds, not just large guilds are being requested.</p>
<p>There are a few solutions to fix this.</p>
<p>The first solution is to request the privileged presences intent along with the privileged members intent and enable both of them. This allows the initial member list to contain online members just like the old gateway. Note that were still limited to 1 guild per request but the number of guilds we request is significantly reduced.</p>
<p>The second solution is to disable member chunking by setting <code class="docutils literal notranslate"><span class="pre">chunk_guilds_at_startup</span></code> to <code class="docutils literal notranslate"><span class="pre">False</span></code> when constructing a client. Then, when chunking for a guild is necessary you can use the various techniques to <a class="reference internal" href="#retrieving-members"><span class="std std-ref">retrieve members</span></a>.</p>
<p>To illustrate the slowdown caused by the API change, take a bot who is in 840 guilds and 95 of these guilds are “large” (over 250 members).</p>
<p>Under the original system this would result in 2 requests to fetch the member list (75 guilds, 20 guilds) roughly taking 60 seconds. With <a class="reference internal" href="api.html#discord.Intents.members" title="discord.Intents.members"><code class="xref py py-attr docutils literal notranslate"><span class="pre">Intents.members</span></code></a> but not <a class="reference internal" href="api.html#discord.Intents.presences" title="discord.Intents.presences"><code class="xref py py-attr docutils literal notranslate"><span class="pre">Intents.presences</span></code></a> this requires 840 requests, with a rate limit of 120 requests per 60 seconds means that due to waiting for the rate limit it totals to around 7 minutes of waiting for the rate limit to fetch all the members. With both <a class="reference internal" href="api.html#discord.Intents.members" title="discord.Intents.members"><code class="xref py py-attr docutils literal notranslate"><span class="pre">Intents.members</span></code></a> and <a class="reference internal" href="api.html#discord.Intents.presences" title="discord.Intents.presences"><code class="xref py py-attr docutils literal notranslate"><span class="pre">Intents.presences</span></code></a> we mostly get the old behaviour so were only required to request for the 95 guilds that are large, this is slightly less than our rate limit so its close to the original timing to fetch the member list.</p>
<p>Unfortunately due to this change being required from Discord there is nothing that the library can do to mitigate this.</p>
<p>If you truly dislike the direction Discord is going with their API, you can contact them via <a class="reference external" href="https://dis.gd/contact">support</a>.</p>
</section>
</section>
</section>
</main>
<footer class="grid-item">
&#169; Copyright 2015-present, Rapptz.
Created using <a href="https://www.sphinx-doc.org/">Sphinx</a> 4.2.0.
</footer>
</div>
<div id="settings" class="modal" onclick="if (event.target == this){ settingsModal.close(); }" hidden>
<div class="modal-content">
<span class="close" onclick="settingsModal.close();" title="Close">
<span class="material-icons">close</span>
</span>
<h1>Settings</h1>
<h2>Font</h2>
<div class="setting">
<h3>Use a serif font:
<label class="toggle"
title="Use a serif font? Your system font will be used, falling back to serif.">
<input type="checkbox" name="useSerifFont" onclick="updateSetting(this);">
<span class="toggle-slider"></span>
</label>
</h3>
</div>
<h2>Theme</h2>
<div class="setting">
<h3>
<label class="toggle" title="Set your theme based on your system preferences">
<input type="radio" name="setTheme" onclick="updateSetting(this);" value="automatic" checked>
</label>
Automatic
</h3>
<h3>
<label class="toggle" title="Set your theme to light theme">
<input type="radio" name="setTheme" onclick="updateSetting(this);" value="light">
</label>
Light
</h3>
<h3>
<label class="toggle" title="Set your theme to dark theme">
<input type="radio" name="setTheme" onclick="updateSetting(this);" value="dark">
</label>
Dark
</h3>
</div>
</div>
</div>
<div id="to-top" onclick="scrollToTop()" hidden>
<span><span class="material-icons">arrow_upward</span> to top</span>
</div>
</body>
</html>