1
Fork 0
mirror of https://github.com/RYGhub/royalnet.git synced 2024-11-23 19:44:20 +00:00

Merge branch 'master' into web

This commit is contained in:
Steffo 2019-06-02 19:32:28 +02:00 committed by GitHub
commit e593fe9a6e
40 changed files with 487 additions and 103 deletions

1
.gitignore vendored
View file

@ -10,3 +10,4 @@ royalnet.egg-info/
.pytest_cache/
dist/
build/
venv/

View file

@ -1,7 +1,7 @@
# `royalnet` **alpha**
# `royalnet` [![PyPI](https://img.shields.io/pypi/v/royalnet.svg)](https://pypi.org/project/royalnet/)
The fifth rewrite of [Royalnet](https://github.com/Steffo99/royalnet/)!
The fifth rewrite of the Royal Network!
It includes a lot of miscellaneous useful stuff.
It has a lot of submodules, many of which may be used in other bots.
[Documentation available here.](https://steffo99.github.io/royalnet/html/)
[Documentation available here](https://royal-games.github.io/royalnet/html/index.html).

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View file

@ -340,17 +340,41 @@
<dl class="method">
<dt id="royalnet.audio.YtdlFile._stop_download">
<code class="descname">_stop_download</code><span class="sig-paren">(</span><span class="sig-paren">)</span><a class="headerlink" href="#royalnet.audio.YtdlFile._stop_download" title="Permalink to this definition"></a></dt>
<dd></dd></dl>
<dd><p>I have no clue of what this does, or why is it here. Possibly remove it?</p>
<dl class="field-list simple">
<dt class="field-odd">Raises</dt>
<dd class="field-odd"><p><strong>InterruptDownload</strong> …uhhh, always?</p>
</dd>
</dl>
</dd></dl>
<dl class="staticmethod">
<dt id="royalnet.audio.YtdlFile.create_from_url">
<em class="property">static </em><code class="descname">create_from_url</code><span class="sig-paren">(</span><em>url</em>, <em>outtmpl='%(title)s-%(id)s.%(ext)s'</em>, <em>**ytdl_args</em><span class="sig-paren">)</span> &#x2192; List[royalnet.audio.youtubedl.YtdlFile]<a class="headerlink" href="#royalnet.audio.YtdlFile.create_from_url" title="Permalink to this definition"></a></dt>
<dd></dd></dl>
<dd><p>Download the videos at the specified url.</p>
<dl class="field-list simple">
<dt class="field-odd">Parameters</dt>
<dd class="field-odd"><ul class="simple">
<li><p><strong>url</strong> The url to download the videos from.</p></li>
<li><p><strong>outtmpl</strong> The filename that the downloaded videos are going to have. The name can be formatted according to the <a class="reference external" href="https://github.com/ytdl-org/youtube-dl/blob/master/README.md#output-template">outtmpl documentation</a>.</p></li>
<li><p><strong>ytdl_args</strong> Other arguments to be passed to the YoutubeDL object.</p></li>
</ul>
</dd>
<dt class="field-even">Returns</dt>
<dd class="field-even"><p>A <a class="reference external" href="https://docs.python.org/3.7/library/stdtypes.html#list" title="(in Python v3.7)"><code class="xref py py-class docutils literal notranslate"><span class="pre">list</span></code></a> of YtdlFiles.</p>
</dd>
</dl>
</dd></dl>
<dl class="method">
<dt id="royalnet.audio.YtdlFile.delete_video_file">
<code class="descname">delete_video_file</code><span class="sig-paren">(</span><span class="sig-paren">)</span><a class="headerlink" href="#royalnet.audio.YtdlFile.delete_video_file" title="Permalink to this definition"></a></dt>
<dd></dd></dl>
<dd><p>Delete the file located at <code class="docutils literal notranslate"><span class="pre">self.video_filename</span></code>.</p>
<div class="admonition note">
<p class="admonition-title">Note</p>
<p>No checks are done when deleting, so it may try to delete a non-existing file and raise an exception or do some other weird stuff with weird filenames.</p>
</div>
</dd></dl>
<dl class="attribute">
<dt id="royalnet.audio.YtdlFile.ytdl_args">
@ -383,6 +407,11 @@
<code class="descname">download</code><span class="sig-paren">(</span><em>outtmpl='%(title)s-%(id)s.%(ext)s'</em>, <em>**ytdl_args</em><span class="sig-paren">)</span> &#x2192; royalnet.audio.youtubedl.YtdlFile<a class="headerlink" href="#royalnet.audio.YtdlInfo.download" title="Permalink to this definition"></a></dt>
<dd></dd></dl>
<dl class="method">
<dt id="royalnet.audio.YtdlInfo.to_discord_embed">
<code class="descname">to_discord_embed</code><span class="sig-paren">(</span><span class="sig-paren">)</span> &#x2192; discord.embeds.Embed<a class="headerlink" href="#royalnet.audio.YtdlInfo.to_discord_embed" title="Permalink to this definition"></a></dt>
<dd></dd></dl>
</dd></dl>
<dl class="class">
@ -460,7 +489,7 @@ The name of the downloaded and PCM-converted audio file.</p>
<dl class="class">
<dt id="royalnet.audio.RoyalPCMAudio">
<em class="property">class </em><code class="descclassname">royalnet.audio.</code><code class="descname">RoyalPCMAudio</code><span class="sig-paren">(</span><em>rpf: royalnet.audio.royalpcmfile.RoyalPCMFile</em><span class="sig-paren">)</span><a class="headerlink" href="#royalnet.audio.RoyalPCMAudio" title="Permalink to this definition"></a></dt>
<dd><p>A discord-compatible <a class="reference external" href="https://discordpy.readthedocs.io/en/latest/api.html#discord.AudioSource" title="(in discord.py v1.2.0a)"><code class="xref py py-class docutils literal notranslate"><span class="pre">discord.AudioSource</span></code></a> that keeps data in a file instead of in memory.</p>
<dd><p>A <a class="reference external" href="https://discordpy.readthedocs.io/en/latest/api.html#discord.AudioSource" title="(in discord.py v1.2.0a)"><code class="xref py py-class docutils literal notranslate"><span class="pre">discord.AudioSource</span></code></a> that keeps data in a file instead of in memory.</p>
<dl class="method">
<dt id="royalnet.audio.RoyalPCMAudio.__init__">
<code class="descname">__init__</code><span class="sig-paren">(</span><em>rpf: royalnet.audio.royalpcmfile.RoyalPCMFile</em><span class="sig-paren">)</span><a class="headerlink" href="#royalnet.audio.RoyalPCMAudio.__init__" title="Permalink to this definition"></a></dt>
@ -511,29 +540,19 @@ The name of the downloaded and PCM-converted audio file.</p>
<dl class="method">
<dt id="royalnet.audio.RoyalPCMAudio.is_opus">
<code class="descname">is_opus</code><span class="sig-paren">(</span><span class="sig-paren">)</span><a class="headerlink" href="#royalnet.audio.RoyalPCMAudio.is_opus" title="Permalink to this definition"></a></dt>
<dd><p>Checks if the audio source is already encoded in Opus.</p>
<p>Defaults to <code class="docutils literal notranslate"><span class="pre">False</span></code>.</p>
<dd><p>This audio file isnt Opus-encoded, but PCM-encoded.</p>
<dl class="field-list simple">
<dt class="field-odd">Returns</dt>
<dd class="field-odd"><p><code class="docutils literal notranslate"><span class="pre">False</span></code>.</p>
</dd>
</dl>
</dd></dl>
<dl class="method">
<dt id="royalnet.audio.RoyalPCMAudio.read">
<code class="descname">read</code><span class="sig-paren">(</span><span class="sig-paren">)</span><a class="headerlink" href="#royalnet.audio.RoyalPCMAudio.read" title="Permalink to this definition"></a></dt>
<dd><p>Reads 20ms worth of audio.</p>
<p>Subclasses must implement this.</p>
<p>If the audio is complete, then returning an empty
<span class="xref std std-term">py:bytes-like object</span> to signal this is the way to do so.</p>
<p>If <a class="reference internal" href="#royalnet.audio.RoyalPCMAudio.is_opus" title="royalnet.audio.RoyalPCMAudio.is_opus"><code class="xref py py-meth docutils literal notranslate"><span class="pre">is_opus()</span></code></a> method returns <code class="docutils literal notranslate"><span class="pre">True</span></code>, then it must return
20ms worth of Opus encoded audio. Otherwise, it must be 20ms
worth of 16-bit 48KHz stereo PCM, which is about 3,840 bytes
per frame (20ms worth of audio).</p>
<dl class="field-list simple">
<dt class="field-odd">Returns</dt>
<dd class="field-odd"><p>A bytes like object that represents the PCM or Opus data.</p>
</dd>
<dt class="field-even">Return type</dt>
<dd class="field-even"><p><a class="reference external" href="https://docs.python.org/3.7/library/stdtypes.html#bytes" title="(in Python v3.7)"><code class="xref py py-class docutils literal notranslate"><span class="pre">bytes</span></code></a></p>
</dd>
</dl>
<p>If the audio is complete, then returning an empty <a class="reference external" href="https://docs.python.org/3.7/library/stdtypes.html#bytes" title="(in Python v3.7)"><code class="xref py py-class docutils literal notranslate"><span class="pre">bytes</span></code></a>-like object to signal this is the way to do so.</p>
</dd></dl>
</dd></dl>

View file

@ -188,7 +188,8 @@
<dl class="attribute">
<dt id="royalnet.bots.TelegramBot.botfather_command_string">
<code class="descname">botfather_command_string</code><a class="headerlink" href="#royalnet.bots.TelegramBot.botfather_command_string" title="Permalink to this definition"></a></dt>
<dd></dd></dl>
<dd><p>Generate a string to be pasted in the “Edit Commands” BotFather prompt.</p>
</dd></dl>
<dl class="attribute">
<dt id="royalnet.bots.TelegramBot.interface_name">

View file

@ -158,7 +158,8 @@
<h1>royalnet.commands<a class="headerlink" href="#royalnet-commands" title="Permalink to this headline"></a></h1>
<div class="toctree-wrapper compound">
</div>
<span class="target" id="module-royalnet.commands"></span><p>Commands that can be used in bots. These probably wont suit your needs, as they are tailored for the bots of the <a class="reference external" href="https://ryg.steffo.eu">Royal Games</a> gaming community, but you can check them for reference.</p>
<span class="target" id="module-royalnet.commands"></span><p>Commands that can be used in bots.</p>
<p>These probably wont suit your needs, as they are tailored for the bots of the <a class="reference external" href="https://ryg.steffo.eu">Royal Games</a> gaming community, but they may be useful to develop new ones.</p>
<dl class="class">
<dt id="royalnet.commands.NullCommand">
<em class="property">class </em><code class="descclassname">royalnet.commands.</code><code class="descname">NullCommand</code><a class="headerlink" href="#royalnet.commands.NullCommand" title="Permalink to this definition"></a></dt>

View file

@ -261,7 +261,7 @@
<dl class="attribute">
<dt id="royalnet.database.tables.Telegram.royal">
<code class="descname">royal</code><em class="property"> = &lt;RelationshipProperty at 0x7a5f588; no key&gt;</em><a class="headerlink" href="#royalnet.database.tables.Telegram.royal" title="Permalink to this definition"></a></dt>
<code class="descname">royal</code><em class="property"> = &lt;RelationshipProperty at 0x7f81332fcbc8; no key&gt;</em><a class="headerlink" href="#royalnet.database.tables.Telegram.royal" title="Permalink to this definition"></a></dt>
<dd></dd></dl>
<dl class="attribute">
@ -291,7 +291,7 @@
<dl class="attribute">
<dt id="royalnet.database.tables.Diario.creator">
<code class="descname">creator</code><em class="property"> = &lt;RelationshipProperty at 0x7a5f150; no key&gt;</em><a class="headerlink" href="#royalnet.database.tables.Diario.creator" title="Permalink to this definition"></a></dt>
<code class="descname">creator</code><em class="property"> = &lt;RelationshipProperty at 0x7f81333176c8; no key&gt;</em><a class="headerlink" href="#royalnet.database.tables.Diario.creator" title="Permalink to this definition"></a></dt>
<dd></dd></dl>
<dl class="attribute">
@ -316,7 +316,7 @@
<dl class="attribute">
<dt id="royalnet.database.tables.Diario.quoted_account">
<code class="descname">quoted_account</code><em class="property"> = &lt;RelationshipProperty at 0x7a5fa98; no key&gt;</em><a class="headerlink" href="#royalnet.database.tables.Diario.quoted_account" title="Permalink to this definition"></a></dt>
<code class="descname">quoted_account</code><em class="property"> = &lt;RelationshipProperty at 0x7f8133317948; no key&gt;</em><a class="headerlink" href="#royalnet.database.tables.Diario.quoted_account" title="Permalink to this definition"></a></dt>
<dd></dd></dl>
<dl class="attribute">
@ -351,7 +351,7 @@
<dl class="attribute">
<dt id="royalnet.database.tables.Alias.royal">
<code class="descname">royal</code><em class="property"> = &lt;RelationshipProperty at 0x7a5f738; no key&gt;</em><a class="headerlink" href="#royalnet.database.tables.Alias.royal" title="Permalink to this definition"></a></dt>
<code class="descname">royal</code><em class="property"> = &lt;RelationshipProperty at 0x7f8133317ec8; no key&gt;</em><a class="headerlink" href="#royalnet.database.tables.Alias.royal" title="Permalink to this definition"></a></dt>
<dd></dd></dl>
<dl class="attribute">
@ -366,7 +366,7 @@
<em class="property">class </em><code class="descclassname">royalnet.database.tables.</code><code class="descname">ActiveKvGroup</code><a class="headerlink" href="#royalnet.database.tables.ActiveKvGroup" title="Permalink to this definition"></a></dt>
<dd><dl class="attribute">
<dt id="royalnet.database.tables.ActiveKvGroup.group">
<code class="descname">group</code><em class="property"> = &lt;RelationshipProperty at 0x7a5f738; no key&gt;</em><a class="headerlink" href="#royalnet.database.tables.ActiveKvGroup.group" title="Permalink to this definition"></a></dt>
<code class="descname">group</code><em class="property"> = &lt;RelationshipProperty at 0x7f8133317a48; no key&gt;</em><a class="headerlink" href="#royalnet.database.tables.ActiveKvGroup.group" title="Permalink to this definition"></a></dt>
<dd></dd></dl>
<dl class="attribute">
@ -376,7 +376,7 @@
<dl class="attribute">
<dt id="royalnet.database.tables.ActiveKvGroup.royal">
<code class="descname">royal</code><em class="property"> = &lt;RelationshipProperty at 0x7a5fc48; no key&gt;</em><a class="headerlink" href="#royalnet.database.tables.ActiveKvGroup.royal" title="Permalink to this definition"></a></dt>
<code class="descname">royal</code><em class="property"> = &lt;RelationshipProperty at 0x7f81333171c8; no key&gt;</em><a class="headerlink" href="#royalnet.database.tables.ActiveKvGroup.royal" title="Permalink to this definition"></a></dt>
<dd></dd></dl>
<dl class="attribute">
@ -391,7 +391,7 @@
<em class="property">class </em><code class="descclassname">royalnet.database.tables.</code><code class="descname">Keyvalue</code><a class="headerlink" href="#royalnet.database.tables.Keyvalue" title="Permalink to this definition"></a></dt>
<dd><dl class="attribute">
<dt id="royalnet.database.tables.Keyvalue.group">
<code class="descname">group</code><em class="property"> = &lt;RelationshipProperty at 0x7a5f978; no key&gt;</em><a class="headerlink" href="#royalnet.database.tables.Keyvalue.group" title="Permalink to this definition"></a></dt>
<code class="descname">group</code><em class="property"> = &lt;RelationshipProperty at 0x7f81333173c8; no key&gt;</em><a class="headerlink" href="#royalnet.database.tables.Keyvalue.group" title="Permalink to this definition"></a></dt>
<dd></dd></dl>
<dl class="attribute">
@ -446,7 +446,7 @@
<dl class="attribute">
<dt id="royalnet.database.tables.Discord.royal">
<code class="descname">royal</code><em class="property"> = &lt;RelationshipProperty at 0x7a5fae0; no key&gt;</em><a class="headerlink" href="#royalnet.database.tables.Discord.royal" title="Permalink to this definition"></a></dt>
<code class="descname">royal</code><em class="property"> = &lt;RelationshipProperty at 0x7f8133317948; no key&gt;</em><a class="headerlink" href="#royalnet.database.tables.Discord.royal" title="Permalink to this definition"></a></dt>
<dd></dd></dl>
<dl class="attribute">

View file

@ -267,7 +267,7 @@
</li>
<li><a href="database.html#royalnet.database.Alchemy">Alchemy (class in royalnet.database)</a>
</li>
<li><a href="utils.html#royalnet.utils.Call.alchemy">alchemy (royalnet.utils.Call attribute)</a>
<li><a href="utils.html#royalnet.utils.Call.alchemy">alchemy (royalnet.utils.Call attribute)</a>, <a href="utils.html#royalnet.utils.Call.alchemy">[1]</a>
</li>
</ul></td>
<td style="width: 33%; vertical-align: top;"><ul>
@ -313,11 +313,11 @@
</li>
<li><a href="utils.html#royalnet.utils.Command">Command (class in royalnet.utils)</a>
</li>
<li><a href="utils.html#royalnet.utils.Command.command_description">command_description (royalnet.utils.Command attribute)</a>
<li><a href="utils.html#royalnet.utils.Command.command_description">command_description (royalnet.utils.Command attribute)</a>, <a href="utils.html#royalnet.utils.Command.command_description">[1]</a>
</li>
<li><a href="utils.html#royalnet.utils.Command.command_name">command_name (royalnet.utils.Command attribute)</a>
<li><a href="utils.html#royalnet.utils.Command.command_name">command_name (royalnet.utils.Command attribute)</a>, <a href="utils.html#royalnet.utils.Command.command_name">[1]</a>
</li>
<li><a href="utils.html#royalnet.utils.Command.command_syntax">command_syntax (royalnet.utils.Command attribute)</a>
<li><a href="utils.html#royalnet.utils.Command.command_syntax">command_syntax (royalnet.utils.Command attribute)</a>, <a href="utils.html#royalnet.utils.Command.command_syntax">[1]</a>
</li>
<li><a href="utils.html#royalnet.utils.CommandArgs">CommandArgs (class in royalnet.utils)</a>
</li>
@ -476,14 +476,14 @@
</li>
<li><a href="bots.html#royalnet.bots.TelegramBot.interface_name">(royalnet.bots.TelegramBot attribute)</a>
</li>
<li><a href="utils.html#royalnet.utils.Call.interface_name">(royalnet.utils.Call attribute)</a>
<li><a href="utils.html#royalnet.utils.Call.interface_name">(royalnet.utils.Call attribute)</a>, <a href="utils.html#royalnet.utils.Call.interface_name">[1]</a>
</li>
</ul></li>
</ul></td>
<td style="width: 33%; vertical-align: top;"><ul>
<li><a href="utils.html#royalnet.utils.Call.interface_obj">interface_obj (royalnet.utils.Call attribute)</a>
<li><a href="utils.html#royalnet.utils.Call.interface_obj">interface_obj (royalnet.utils.Call attribute)</a>, <a href="utils.html#royalnet.utils.Call.interface_obj">[1]</a>
</li>
<li><a href="utils.html#royalnet.utils.Call.interface_prefix">interface_prefix (royalnet.utils.Call attribute)</a>
<li><a href="utils.html#royalnet.utils.Call.interface_prefix">interface_prefix (royalnet.utils.Call attribute)</a>, <a href="utils.html#royalnet.utils.Call.interface_prefix">[1]</a>
</li>
<li><a href="error.html#royalnet.error.InvalidConfigError">InvalidConfigError</a>
</li>
@ -559,7 +559,7 @@
</li>
<li><a href="utils.html#royalnet.utils.Command.network_handler_dict">network_handler_dict() (royalnet.utils.Command class method)</a>
</li>
<li><a href="utils.html#royalnet.utils.Command.network_handlers">network_handlers (royalnet.utils.Command attribute)</a>
<li><a href="utils.html#royalnet.utils.Command.network_handlers">network_handlers (royalnet.utils.Command attribute)</a>, <a href="utils.html#royalnet.utils.Command.network_handlers">[1]</a>
</li>
<li><a href="network.html#royalnet.network.NetworkError">NetworkError</a>
</li>
@ -659,7 +659,7 @@
</li>
<li><a href="network.html#royalnet.network.RoyalnetLink.request">request() (royalnet.network.RoyalnetLink method)</a>
</li>
<li><a href="utils.html#royalnet.utils.Command.require_alchemy_tables">require_alchemy_tables (royalnet.utils.Command attribute)</a>
<li><a href="utils.html#royalnet.utils.Command.require_alchemy_tables">require_alchemy_tables (royalnet.utils.Command attribute)</a>, <a href="utils.html#royalnet.utils.Command.require_alchemy_tables">[1]</a>
</li>
<li><a href="network.html#royalnet.network.Response">Response (class in royalnet.network)</a>
</li>
@ -801,6 +801,8 @@
<li><a href="network.html#royalnet.network.Response.to_dict">(royalnet.network.Response method)</a>
</li>
</ul></li>
<li><a href="audio.html#royalnet.audio.YtdlInfo.to_discord_embed">to_discord_embed() (royalnet.audio.YtdlInfo method)</a>
</li>
<li><a href="network.html#royalnet.network.Package.to_json_bytes">to_json_bytes() (royalnet.network.Package method)</a>
</li>
<li><a href="network.html#royalnet.network.Package.to_json_string">to_json_string() (royalnet.network.Package method)</a>
@ -865,9 +867,11 @@
<li><a href="audio.html#royalnet.audio.YtdlFile.ytdl_args">(royalnet.audio.YtdlFile attribute)</a>
</li>
</ul></li>
<li><a href="audio.html#royalnet.audio.RoyalPCMFile.ytdl_filename">ytdl_filename (royalnet.audio.RoyalPCMFile attribute)</a>
</li>
</ul></td>
<td style="width: 33%; vertical-align: top;"><ul>
<li><a href="audio.html#royalnet.audio.RoyalPCMFile.ytdl_filename">ytdl_filename (royalnet.audio.RoyalPCMFile attribute)</a>
<li><a href="utils.html#royalnet.utils.ytdldateformat">ytdldateformat() (in module royalnet.utils)</a>
</li>
<li><a href="audio.html#royalnet.audio.YtdlFile">YtdlFile (class in royalnet.audio)</a>
</li>

View file

@ -158,10 +158,10 @@
<h1>royalnet.network<a class="headerlink" href="#royalnet-network" title="Permalink to this headline"></a></h1>
<div class="toctree-wrapper compound">
</div>
<span class="target" id="module-royalnet.network"></span><p>Royalnet realated classes.</p>
<span class="target" id="module-royalnet.network"></span><p>Royalnet (websocket) related classes.</p>
<dl class="class">
<dt id="royalnet.network.RoyalnetLink">
<em class="property">class </em><code class="descclassname">royalnet.network.</code><code class="descname">RoyalnetLink</code><span class="sig-paren">(</span><em>master_uri: str</em>, <em>secret: str</em>, <em>link_type: str</em>, <em>request_handler</em>, <em>*</em>, <em>loop: asyncio.events.AbstractEventLoop = &lt;_WindowsSelectorEventLoop running=False closed=False debug=False&gt;</em><span class="sig-paren">)</span><a class="headerlink" href="#royalnet.network.RoyalnetLink" title="Permalink to this definition"></a></dt>
<em class="property">class </em><code class="descclassname">royalnet.network.</code><code class="descname">RoyalnetLink</code><span class="sig-paren">(</span><em>master_uri: str</em>, <em>secret: str</em>, <em>link_type: str</em>, <em>request_handler</em>, <em>*</em>, <em>loop: asyncio.events.AbstractEventLoop = &lt;_UnixSelectorEventLoop running=False closed=False debug=False&gt;</em><span class="sig-paren">)</span><a class="headerlink" href="#royalnet.network.RoyalnetLink" title="Permalink to this definition"></a></dt>
<dd><dl class="method">
<dt id="royalnet.network.RoyalnetLink.connect">
<code class="descname">connect</code><span class="sig-paren">(</span><span class="sig-paren">)</span><a class="headerlink" href="#royalnet.network.RoyalnetLink.connect" title="Permalink to this definition"></a></dt>
@ -295,7 +295,7 @@ Contains info about the source and the destination.</p>
<dl class="class">
<dt id="royalnet.network.RoyalnetServer">
<em class="property">class </em><code class="descclassname">royalnet.network.</code><code class="descname">RoyalnetServer</code><span class="sig-paren">(</span><em>address: str</em>, <em>port: int</em>, <em>required_secret: str</em>, <em>*</em>, <em>loop: asyncio.events.AbstractEventLoop = &lt;_WindowsSelectorEventLoop running=False closed=False debug=False&gt;</em><span class="sig-paren">)</span><a class="headerlink" href="#royalnet.network.RoyalnetServer" title="Permalink to this definition"></a></dt>
<em class="property">class </em><code class="descclassname">royalnet.network.</code><code class="descname">RoyalnetServer</code><span class="sig-paren">(</span><em>address: str</em>, <em>port: int</em>, <em>required_secret: str</em>, <em>*</em>, <em>loop: asyncio.events.AbstractEventLoop = &lt;_UnixSelectorEventLoop running=False closed=False debug=False&gt;</em><span class="sig-paren">)</span><a class="headerlink" href="#royalnet.network.RoyalnetServer" title="Permalink to this definition"></a></dt>
<dd><dl class="method">
<dt id="royalnet.network.RoyalnetServer.find_client">
<code class="descname">find_client</code><span class="sig-paren">(</span><em>*</em>, <em>nid: str = None</em>, <em>link_type: str = None</em><span class="sig-paren">)</span> &#x2192; List[royalnet.network.royalnetserver.ConnectedClient]<a class="headerlink" href="#royalnet.network.RoyalnetServer.find_client" title="Permalink to this definition"></a></dt>

Binary file not shown.

File diff suppressed because one or more lines are too long

View file

@ -173,6 +173,30 @@
<dt id="royalnet.utils.Call">
<em class="property">class </em><code class="descclassname">royalnet.utils.</code><code class="descname">Call</code><span class="sig-paren">(</span><em>channel, command: Type[royalnet.utils.command.Command], command_args: List[str] = None, **kwargs</em><span class="sig-paren">)</span><a class="headerlink" href="#royalnet.utils.Call" title="Permalink to this definition"></a></dt>
<dd><p>A command call. An abstract class, sub-bots should create a new call class from this.</p>
<dl class="attribute">
<dt id="royalnet.utils.Call.interface_name">
<code class="descname">interface_name</code><a class="headerlink" href="#royalnet.utils.Call.interface_name" title="Permalink to this definition"></a></dt>
<dd><p>The name of the interface that is calling the command. For example, <code class="docutils literal notranslate"><span class="pre">telegram</span></code>, or <code class="docutils literal notranslate"><span class="pre">discord</span></code>.</p>
</dd></dl>
<dl class="attribute">
<dt id="royalnet.utils.Call.interface_obj">
<code class="descname">interface_obj</code><a class="headerlink" href="#royalnet.utils.Call.interface_obj" title="Permalink to this definition"></a></dt>
<dd><p>The main object of the interface that is calling the command. For example, the <a class="reference internal" href="bots.html#royalnet.bots.TelegramBot" title="royalnet.bots.TelegramBot"><code class="xref py py-class docutils literal notranslate"><span class="pre">royalnet.bots.TelegramBot</span></code></a> object.</p>
</dd></dl>
<dl class="attribute">
<dt id="royalnet.utils.Call.interface_prefix">
<code class="descname">interface_prefix</code><a class="headerlink" href="#royalnet.utils.Call.interface_prefix" title="Permalink to this definition"></a></dt>
<dd><p>The command prefix used by the interface. For example, <code class="docutils literal notranslate"><span class="pre">/</span></code>, or <code class="docutils literal notranslate"><span class="pre">!</span></code>.</p>
</dd></dl>
<dl class="attribute">
<dt id="royalnet.utils.Call.alchemy">
<code class="descname">alchemy</code><a class="headerlink" href="#royalnet.utils.Call.alchemy" title="Permalink to this definition"></a></dt>
<dd><p>The <a class="reference internal" href="database.html#royalnet.database.Alchemy" title="royalnet.database.Alchemy"><code class="xref py py-class docutils literal notranslate"><span class="pre">royalnet.database.Alchemy</span></code></a> object associated to this interface. May be None if the interface is not connected to any database.</p>
</dd></dl>
<dl class="method">
<dt id="royalnet.utils.Call.__init__">
<code class="descname">__init__</code><span class="sig-paren">(</span><em>channel, command: Type[royalnet.utils.command.Command], command_args: List[str] = None, **kwargs</em><span class="sig-paren">)</span><a class="headerlink" href="#royalnet.utils.Call.__init__" title="Permalink to this definition"></a></dt>
@ -196,8 +220,8 @@
</dd></dl>
<dl class="attribute">
<dt id="royalnet.utils.Call.alchemy">
<code class="descname">alchemy</code><em class="property"> = NotImplemented</em><a class="headerlink" href="#royalnet.utils.Call.alchemy" title="Permalink to this definition"></a></dt>
<dt>
<code class="descname">alchemy</code><em class="property"> = NotImplemented</em></dt>
<dd></dd></dl>
<dl class="method">
@ -216,18 +240,18 @@ That probably means, the database row identifying the user.</p>
</dd></dl>
<dl class="attribute">
<dt id="royalnet.utils.Call.interface_name">
<code class="descname">interface_name</code><em class="property"> = NotImplemented</em><a class="headerlink" href="#royalnet.utils.Call.interface_name" title="Permalink to this definition"></a></dt>
<dt>
<code class="descname">interface_name</code><em class="property"> = NotImplemented</em></dt>
<dd></dd></dl>
<dl class="attribute">
<dt id="royalnet.utils.Call.interface_obj">
<code class="descname">interface_obj</code><em class="property"> = NotImplemented</em><a class="headerlink" href="#royalnet.utils.Call.interface_obj" title="Permalink to this definition"></a></dt>
<dt>
<code class="descname">interface_obj</code><em class="property"> = NotImplemented</em></dt>
<dd></dd></dl>
<dl class="attribute">
<dt id="royalnet.utils.Call.interface_prefix">
<code class="descname">interface_prefix</code><em class="property"> = NotImplemented</em><a class="headerlink" href="#royalnet.utils.Call.interface_prefix" title="Permalink to this definition"></a></dt>
<dt>
<code class="descname">interface_prefix</code><em class="property"> = NotImplemented</em></dt>
<dd></dd></dl>
<dl class="method">
@ -238,7 +262,7 @@ That probably means, the database row identifying the user.</p>
<dt class="field-odd">Parameters</dt>
<dd class="field-odd"><ul class="simple">
<li><p><strong>message</strong> The data to be sent. Must be <a class="reference external" href="https://docs.python.org/3.7/library/pickle.html#module-pickle" title="(in Python v3.7)"><code class="xref py py-mod docutils literal notranslate"><span class="pre">pickle</span></code></a>-able.</p></li>
<li><p><strong>destination</strong> </p></li>
<li><p><strong>destination</strong> The destination of the request, either in UUID format or node name.</p></li>
</ul>
</dd>
</dl>
@ -272,20 +296,50 @@ That probably means, the database row identifying the user.</p>
<dl class="class">
<dt id="royalnet.utils.Command">
<em class="property">class </em><code class="descclassname">royalnet.utils.</code><code class="descname">Command</code><a class="headerlink" href="#royalnet.utils.Command" title="Permalink to this definition"></a></dt>
<dd><p>A generic command, called from any source.</p>
<dl class="attribute">
<dt id="royalnet.utils.Command.command_description">
<code class="descname">command_description</code><em class="property"> = NotImplemented</em><a class="headerlink" href="#royalnet.utils.Command.command_description" title="Permalink to this definition"></a></dt>
<dd></dd></dl>
<dd><p>The base class from which all commands should inherit.</p>
<dl class="attribute">
<dt id="royalnet.utils.Command.command_name">
<code class="descname">command_name</code><em class="property"> = NotImplemented</em><a class="headerlink" href="#royalnet.utils.Command.command_name" title="Permalink to this definition"></a></dt>
<dd></dd></dl>
<code class="descname">command_name</code><a class="headerlink" href="#royalnet.utils.Command.command_name" title="Permalink to this definition"></a></dt>
<dd><p>The name of the command. To have <code class="docutils literal notranslate"><span class="pre">/example</span></code> on Telegram, the name should be <code class="docutils literal notranslate"><span class="pre">example</span></code>.</p>
</dd></dl>
<dl class="attribute">
<dt id="royalnet.utils.Command.command_description">
<code class="descname">command_description</code><a class="headerlink" href="#royalnet.utils.Command.command_description" title="Permalink to this definition"></a></dt>
<dd><p>A small description of the command, to be displayed when the command is being autocompleted.</p>
</dd></dl>
<dl class="attribute">
<dt id="royalnet.utils.Command.command_syntax">
<code class="descname">command_syntax</code><em class="property"> = NotImplemented</em><a class="headerlink" href="#royalnet.utils.Command.command_syntax" title="Permalink to this definition"></a></dt>
<code class="descname">command_syntax</code><a class="headerlink" href="#royalnet.utils.Command.command_syntax" title="Permalink to this definition"></a></dt>
<dd><p>The syntax of the command, to be displayed when a <a class="reference internal" href="error.html#royalnet.error.InvalidInputError" title="royalnet.error.InvalidInputError"><code class="xref py py-exc docutils literal notranslate"><span class="pre">royalnet.error.InvalidInputError</span></code></a> is raised, in the format <code class="docutils literal notranslate"><span class="pre">(required_arg)</span> <span class="pre">[optional_arg]</span></code>.</p>
</dd></dl>
<dl class="attribute">
<dt id="royalnet.utils.Command.require_alchemy_tables">
<code class="descname">require_alchemy_tables</code><a class="headerlink" href="#royalnet.utils.Command.require_alchemy_tables" title="Permalink to this definition"></a></dt>
<dd><p>A set of <a class="reference internal" href="database.html#module-royalnet.database" title="royalnet.database"><code class="xref py py-class docutils literal notranslate"><span class="pre">royalnet.database</span></code></a> tables, that must exist for this command to work.</p>
</dd></dl>
<dl class="attribute">
<dt id="royalnet.utils.Command.network_handlers">
<code class="descname">network_handlers</code><a class="headerlink" href="#royalnet.utils.Command.network_handlers" title="Permalink to this definition"></a></dt>
<dd><p>A list of :py:class:<a href="#id1"><span class="problematic" id="id2">`</span></a>classyalnet.utils.NetworkHandler`s that must exist for this command to work.</p>
</dd></dl>
<dl class="attribute">
<dt>
<code class="descname">command_description</code><em class="property"> = NotImplemented</em></dt>
<dd></dd></dl>
<dl class="attribute">
<dt>
<code class="descname">command_name</code><em class="property"> = NotImplemented</em></dt>
<dd></dd></dl>
<dl class="attribute">
<dt>
<code class="descname">command_syntax</code><em class="property"> = NotImplemented</em></dt>
<dd></dd></dl>
<dl class="classmethod">
@ -299,13 +353,13 @@ That probably means, the database row identifying the user.</p>
<dd></dd></dl>
<dl class="attribute">
<dt id="royalnet.utils.Command.network_handlers">
<code class="descname">network_handlers</code><em class="property"> = {}</em><a class="headerlink" href="#royalnet.utils.Command.network_handlers" title="Permalink to this definition"></a></dt>
<dt>
<code class="descname">network_handlers</code><em class="property"> = {}</em></dt>
<dd></dd></dl>
<dl class="attribute">
<dt id="royalnet.utils.Command.require_alchemy_tables">
<code class="descname">require_alchemy_tables</code><em class="property"> = {}</em><a class="headerlink" href="#royalnet.utils.Command.require_alchemy_tables" title="Permalink to this definition"></a></dt>
<dt>
<code class="descname">require_alchemy_tables</code><em class="property"> = {}</em></dt>
<dd></dd></dl>
</dd></dl>
@ -329,8 +383,20 @@ That probably means, the database row identifying the user.</p>
<dl class="function">
<dt id="royalnet.utils.cdj">
<code class="descclassname">royalnet.utils.</code><code class="descname">cdj</code><span class="sig-paren">(</span><em>class_</em><span class="sig-paren">)</span> &#x2192; dict<a class="headerlink" href="#royalnet.utils.cdj" title="Permalink to this definition"></a></dt>
<code class="descclassname">royalnet.utils.</code><code class="descname">cdj</code><span class="sig-paren">(</span><em>class_: Any</em><span class="sig-paren">)</span> &#x2192; dict<a class="headerlink" href="#royalnet.utils.cdj" title="Permalink to this definition"></a></dt>
<dd><p>Return a dict of the class attributes without the <code class="docutils literal notranslate"><span class="pre">__module__</span></code>, <code class="docutils literal notranslate"><span class="pre">__dict__</span></code>, <code class="docutils literal notranslate"><span class="pre">__weakref__</span></code> and <code class="docutils literal notranslate"><span class="pre">__doc__</span></code> keys, to be used while generating dynamically SQLAlchemy declarative table classes.</p>
<dl class="field-list simple">
<dt class="field-odd">Parameters</dt>
<dd class="field-odd"><p><strong>class</strong> The object that you want to dict-ify.</p>
</dd>
<dt class="field-even">Returns</dt>
<dd class="field-even"><p>The class dict.</p>
</dd>
</dl>
<div class="admonition warning">
<p class="admonition-title">Warning</p>
<p>You cant dict-ify classes with <code class="docutils literal notranslate"><span class="pre">__slots__</span></code>!</p>
</div>
</dd></dl>
<dl class="function">
@ -346,7 +412,7 @@ That probably means, the database row identifying the user.</p>
<dl class="function">
<dt id="royalnet.utils.plusformat">
<code class="descclassname">royalnet.utils.</code><code class="descname">plusformat</code><span class="sig-paren">(</span><em>i: int</em><span class="sig-paren">)</span> &#x2192; str<a class="headerlink" href="#royalnet.utils.plusformat" title="Permalink to this definition"></a></dt>
<dd><p>Convert an <a class="reference external" href="https://docs.python.org/3.7/library/functions.html#int" title="(in Python v3.7)"><code class="xref py py-class docutils literal notranslate"><span class="pre">int</span></code></a> to a <a class="reference external" href="https://docs.python.org/3.7/library/stdtypes.html#str" title="(in Python v3.7)"><code class="xref py py-class docutils literal notranslate"><span class="pre">str</span></code></a>, adding a <code class="docutils literal notranslate"><span class="pre">+</span></code> if they are greater than 0.</p>
<dd><p>Convert an <a class="reference external" href="https://docs.python.org/3.7/library/functions.html#int" title="(in Python v3.7)"><code class="xref py py-class docutils literal notranslate"><span class="pre">int</span></code></a> to a <a class="reference external" href="https://docs.python.org/3.7/library/stdtypes.html#str" title="(in Python v3.7)"><code class="xref py py-class docutils literal notranslate"><span class="pre">str</span></code></a>, prepending a <code class="docutils literal notranslate"><span class="pre">+</span></code> if its greater than 0.</p>
<dl class="field-list simple">
<dt class="field-odd">Parameters</dt>
<dd class="field-odd"><p><strong>i</strong> the <a class="reference external" href="https://docs.python.org/3.7/library/functions.html#int" title="(in Python v3.7)"><code class="xref py py-class docutils literal notranslate"><span class="pre">int</span></code></a> to convert.</p>
@ -360,14 +426,14 @@ That probably means, the database row identifying the user.</p>
<dl class="class">
<dt id="royalnet.utils.CommandArgs">
<em class="property">class </em><code class="descclassname">royalnet.utils.</code><code class="descname">CommandArgs</code><a class="headerlink" href="#royalnet.utils.CommandArgs" title="Permalink to this definition"></a></dt>
<dd><p>The arguments of a command.</p>
<dd><p>An interface to access the arguments of a command with ease.</p>
<dl class="method">
<dt id="royalnet.utils.CommandArgs.__getitem__">
<code class="descname">__getitem__</code><span class="sig-paren">(</span><em>item</em><span class="sig-paren">)</span><a class="headerlink" href="#royalnet.utils.CommandArgs.__getitem__" title="Permalink to this definition"></a></dt>
<dd><p>Arguments can be accessed with an array notation, such as <code class="docutils literal notranslate"><span class="pre">args[0]</span></code>.</p>
<dl class="field-list simple">
<dt class="field-odd">Raises</dt>
<dd class="field-odd"><p><a class="reference internal" href="error.html#royalnet.error.InvalidInputError" title="royalnet.error.InvalidInputError"><strong>InvalidInputError</strong></a> </p>
<dd class="field-odd"><p><a class="reference internal" href="error.html#royalnet.error.InvalidInputError" title="royalnet.error.InvalidInputError"><strong>royalnet.error.InvalidInputError</strong></a> if the requested argument does not exist.</p>
</dd>
</dl>
</dd></dl>
@ -381,7 +447,7 @@ That probably means, the database row identifying the user.</p>
<dd class="field-odd"><p><strong>require_at_least</strong> the minimum amount of arguments required, will raise <a class="reference internal" href="error.html#royalnet.error.InvalidInputError" title="royalnet.error.InvalidInputError"><code class="xref py py-exc docutils literal notranslate"><span class="pre">royalnet.error.InvalidInputError</span></code></a> if the requirement is not fullfilled.</p>
</dd>
<dt class="field-even">Raises</dt>
<dd class="field-even"><p><a class="reference internal" href="error.html#royalnet.error.InvalidInputError" title="royalnet.error.InvalidInputError"><strong>royalnet.error.InvalidInputError</strong></a> </p>
<dd class="field-even"><p><a class="reference internal" href="error.html#royalnet.error.InvalidInputError" title="royalnet.error.InvalidInputError"><strong>royalnet.error.InvalidInputError</strong></a> if there are less than <code class="docutils literal notranslate"><span class="pre">require_at_least</span></code> arguments.</p>
</dd>
<dt class="field-odd">Returns</dt>
<dd class="field-odd"><p>The space-joined string.</p>
@ -397,8 +463,11 @@ That probably means, the database row identifying the user.</p>
<dt class="field-odd">Parameters</dt>
<dd class="field-odd"><p><strong>pattern</strong> The regex pattern to be passed to <a class="reference external" href="https://docs.python.org/3.7/library/re.html#re.match" title="(in Python v3.7)"><code class="xref py py-func docutils literal notranslate"><span class="pre">re.match()</span></code></a>.</p>
</dd>
<dt class="field-even">Returns</dt>
<dd class="field-even"><p>The matched groups, as returned by <code class="xref py py-func docutils literal notranslate"><span class="pre">re.Match.groups()</span></code>.</p>
<dt class="field-even">Raises</dt>
<dd class="field-even"><p><a class="reference internal" href="error.html#royalnet.error.InvalidInputError" title="royalnet.error.InvalidInputError"><strong>royalnet.error.InvalidInputError</strong></a> if the pattern doesnt match.</p>
</dd>
<dt class="field-odd">Returns</dt>
<dd class="field-odd"><p>The matched groups, as returned by <code class="xref py py-func docutils literal notranslate"><span class="pre">re.Match.groups()</span></code>.</p>
</dd>
</dl>
</dd></dl>
@ -454,7 +523,7 @@ That probably means, the database row identifying the user.</p>
<dl class="function">
<dt>
<code class="descclassname">royalnet.utils.</code><code class="descname">plusformat</code><span class="sig-paren">(</span><em>i: int</em><span class="sig-paren">)</span> &#x2192; str</dt>
<dd><p>Convert an <a class="reference external" href="https://docs.python.org/3.7/library/functions.html#int" title="(in Python v3.7)"><code class="xref py py-class docutils literal notranslate"><span class="pre">int</span></code></a> to a <a class="reference external" href="https://docs.python.org/3.7/library/stdtypes.html#str" title="(in Python v3.7)"><code class="xref py py-class docutils literal notranslate"><span class="pre">str</span></code></a>, adding a <code class="docutils literal notranslate"><span class="pre">+</span></code> if they are greater than 0.</p>
<dd><p>Convert an <a class="reference external" href="https://docs.python.org/3.7/library/functions.html#int" title="(in Python v3.7)"><code class="xref py py-class docutils literal notranslate"><span class="pre">int</span></code></a> to a <a class="reference external" href="https://docs.python.org/3.7/library/stdtypes.html#str" title="(in Python v3.7)"><code class="xref py py-class docutils literal notranslate"><span class="pre">str</span></code></a>, prepending a <code class="docutils literal notranslate"><span class="pre">+</span></code> if its greater than 0.</p>
<dl class="field-list simple">
<dt class="field-odd">Parameters</dt>
<dd class="field-odd"><p><strong>i</strong> the <a class="reference external" href="https://docs.python.org/3.7/library/functions.html#int" title="(in Python v3.7)"><code class="xref py py-class docutils literal notranslate"><span class="pre">int</span></code></a> to convert.</p>
@ -469,6 +538,31 @@ That probably means, the database row identifying the user.</p>
<dt id="royalnet.utils.fileformat">
<code class="descclassname">royalnet.utils.</code><code class="descname">fileformat</code><span class="sig-paren">(</span><em>string: str</em><span class="sig-paren">)</span> &#x2192; str<a class="headerlink" href="#royalnet.utils.fileformat" title="Permalink to this definition"></a></dt>
<dd><p>Ensure a string can be used as a filename by replacing all non-word characters with underscores.</p>
<dl class="field-list simple">
<dt class="field-odd">Parameters</dt>
<dd class="field-odd"><p><strong>string</strong> the input string.</p>
</dd>
<dt class="field-even">Returns</dt>
<dd class="field-even"><p>A valid filename string.</p>
</dd>
</dl>
</dd></dl>
<dl class="function">
<dt id="royalnet.utils.ytdldateformat">
<code class="descclassname">royalnet.utils.</code><code class="descname">ytdldateformat</code><span class="sig-paren">(</span><em>string: Optional[str], separator: str = '-'</em><span class="sig-paren">)</span> &#x2192; str<a class="headerlink" href="#royalnet.utils.ytdldateformat" title="Permalink to this definition"></a></dt>
<dd><p>Convert the weird date string returned by <code class="docutils literal notranslate"><span class="pre">youtube-dl</span></code> into the <code class="docutils literal notranslate"><span class="pre">YYYY-MM-DD</span></code> format.</p>
<dl class="field-list simple">
<dt class="field-odd">Parameters</dt>
<dd class="field-odd"><ul class="simple">
<li><p><strong>string</strong> the input string, in the <code class="docutils literal notranslate"><span class="pre">YYYYMMDD</span></code> format.</p></li>
<li><p><strong>separator</strong> the string to add between the years, the months and the days. Defaults to <code class="docutils literal notranslate"><span class="pre">-</span></code>.</p></li>
</ul>
</dd>
<dt class="field-even">Returns</dt>
<dd class="field-even"><p>The resulting string, in the format <code class="docutils literal notranslate"><span class="pre">YYYY-MM-DD</span></code> format.</p>
</dd>
</dl>
</dd></dl>
</div>

View file

@ -1,5 +1,5 @@
from . import audio, bots, commands, database, network, utils, error
version = "5.0a11"
version = "5.0a12"
__all__ = ["audio", "bots", "commands", "database", "network", "utils", "error"]

View file

@ -47,6 +47,18 @@ class PlayMode:
"""Delete all :py:class:`royalnet.audio.RoyalPCMAudio` contained inside this PlayMode."""
raise NotImplementedError()
def queue_preview(self) -> typing.List[RoyalPCMAudio]:
"""Display all the videos in the PlayMode as a list, if possible.
To be used with `queue` commands, for example.
Raises:
NotImplementedError: If a preview can't be generated.
Returns:
A list of videos contained in the queue."""
raise NotImplementedError()
class Playlist(PlayMode):
"""A video list. :py:class:`royalnet.audio.RoyalPCMAudio` played are removed from the list."""
@ -80,9 +92,13 @@ class Playlist(PlayMode):
self.list.append(item)
def delete(self) -> None:
if self.now_playing is not None:
self.now_playing.delete()
while self.list:
self.list.pop(0).delete()
self.now_playing.delete()
def queue_preview(self) -> typing.List[RoyalPCMAudio]:
return self.list
class Pool(PlayMode):
@ -125,3 +141,8 @@ class Pool(PlayMode):
item.delete()
self.pool = None
self._pool_copy = None
def queue_preview(self) -> typing.List[RoyalPCMAudio]:
preview_pool = self.pool.copy()
random.shuffle(preview_pool)
return preview_pool

View file

@ -5,7 +5,7 @@ from .royalpcmfile import RoyalPCMFile
class RoyalPCMAudio(AudioSource):
"""A discord-compatible :py:class:`discord.AudioSource` that keeps data in a file instead of in memory."""
"""A :py:class:`discord.AudioSource` that keeps data in a file instead of in memory."""
def __init__(self, rpf: "RoyalPCMFile"):
"""Create a :py:class:`discord.audio.RoyalPCMAudio` from a :py:class:`royalnet.audio.RoyalPCMFile`.
@ -41,9 +41,16 @@ class RoyalPCMAudio(AudioSource):
return [RoyalPCMAudio(rpf) for rpf in rpf_list]
def is_opus(self):
"""This audio file isn't Opus-encoded, but PCM-encoded.
Returns:
``False``."""
return False
def read(self):
"""Reads 20ms worth of audio.
If the audio is complete, then returning an empty :py:class:`bytes`-like object to signal this is the way to do so."""
data: bytes = self._file.read(OpusEncoder.FRAME_SIZE)
# If the file was externally closed, it means it was deleted
if self._file.closed:

View file

@ -48,14 +48,30 @@ class YtdlFile:
@staticmethod
def create_from_url(url, outtmpl="%(title)s-%(id)s.%(ext)s", **ytdl_args) -> typing.List["YtdlFile"]:
"""Download the videos at the specified url.
Parameters:
url: The url to download the videos from.
outtmpl: The filename that the downloaded videos are going to have. The name can be formatted according to the `outtmpl documentation <https://github.com/ytdl-org/youtube-dl/blob/master/README.md#output-template>`_.
ytdl_args: Other arguments to be passed to the YoutubeDL object.
Returns:
A :py:class:`list` of YtdlFiles."""
info_list = YtdlInfo.create_from_url(url)
return [info.download(outtmpl, **ytdl_args) for info in info_list]
def _stop_download(self):
"""I have no clue of what this does, or why is it here. Possibly remove it?
Raises:
InterruptDownload: ...uhhh, always?"""
raise InterruptDownload()
def delete_video_file(self):
# TODO: _might_ be unsafe, test this
"""Delete the file located at ``self.video_filename``.
Note:
No checks are done when deleting, so it may try to delete a non-existing file and raise an exception or do some other weird stuff with weird filenames."""
os.remove(self.video_filename)
@ -150,9 +166,9 @@ class YtdlInfo:
embed.set_thumbnail(
url=self.thumbnail)
embed.set_author(name=self.uploader, url=self.uploader_url)
embed.set_footer(text="Fonte: youtube-dl", icon_url="https://i.imgur.com/TSvSRYn.png")
embed.set_footer(text="Source: youtube-dl", icon_url="https://i.imgur.com/TSvSRYn.png")
embed.add_field(name="Duration", value=str(self.duration), inline=True)
embed.add_field(name="Published on", value=str(self.upload_date), inline=True)
embed.add_field(name="Published on", value=self.upload_date.strftime("%d %b %Y"), inline=True)
return embed
def __repr__(self):

View file

@ -130,6 +130,7 @@ class TelegramBot(GenericBot):
@property
def botfather_command_string(self) -> str:
"""Generate a string to be pasted in the "Edit Commands" BotFather prompt."""
string = ""
for command_key in self.commands:
command = self.commands[command_key]

View file

@ -1,4 +1,6 @@
"""Commands that can be used in bots. These probably won't suit your needs, as they are tailored for the bots of the `Royal Games <https://ryg.steffo.eu>`_ gaming community, but you can check them for reference."""
"""Commands that can be used in bots.
These probably won't suit your needs, as they are tailored for the bots of the Royal Games gaming community, but they may be useful to develop new ones."""
from .null import NullCommand
from .ping import PingCommand
@ -23,9 +25,12 @@ from .playmode import PlaymodeCommand
from .videochannel import VideochannelCommand
from .missing import MissingCommand
from .cv import CvCommand
from .pause import PauseCommand
from .queue import QueueCommand
__all__ = ["NullCommand", "PingCommand", "ShipCommand", "SmecdsCommand", "CiaoruoziCommand", "ColorCommand",
"SyncCommand", "DiarioCommand", "RageCommand", "DateparserCommand", "AuthorCommand", "ReminderCommand",
"KvactiveCommand", "KvCommand", "KvrollCommand", "VideoinfoCommand", "SummonCommand", "PlayCommand",
"SkipCommand", "PlaymodeCommand", "VideochannelCommand", "MissingCommand", "CvCommand"]
"SkipCommand", "PlaymodeCommand", "VideochannelCommand", "MissingCommand", "CvCommand", "PauseCommand",
"QueueCommand"]

View file

@ -0,0 +1,53 @@
import typing
import discord
from ..network import Request, ResponseSuccess
from ..utils import Command, Call, NetworkHandler
from ..error import TooManyFoundError, NoneFoundError
if typing.TYPE_CHECKING:
from ..bots import DiscordBot
class PauseNH(NetworkHandler):
message_type = "music_pause"
# noinspection PyProtectedMember
@classmethod
async def discord(cls, bot: "DiscordBot", data: dict):
# Find the matching guild
if data["guild_name"]:
guild = bot.client.find_guild_by_name(data["guild_name"])
else:
if len(bot.music_data) == 0:
raise NoneFoundError("No voice clients active")
if len(bot.music_data) > 1:
raise TooManyFoundError("Multiple guilds found")
guild = list(bot.music_data)[0]
# Set the currently playing source as ended
voice_client: discord.VoiceClient = bot.client.find_voice_client_by_guild(guild)
if not (voice_client.is_playing() or voice_client.is_paused()):
raise NoneFoundError("Nothing to pause")
# Toggle pause
resume = voice_client._player.is_paused()
if resume:
voice_client._player.resume()
else:
voice_client._player.pause()
return ResponseSuccess({"resume": resume})
class PauseCommand(Command):
command_name = "pause"
command_description = "Mette in pausa o riprende la riproduzione della canzone attuale."
command_syntax = "[ [guild] ]"
network_handlers = [PauseNH]
@classmethod
async def common(cls, call: Call):
guild, = call.args.match(r"(?:\[(.+)])?")
response = await call.net_request(Request("music_pause", {"guild_name": guild}), "discord")
if response["resume"]:
await call.reply(f"▶️ Riproduzione ripresa.")
else:
await call.reply(f"⏸ Riproduzione messa in pausa.")

View file

@ -0,0 +1,76 @@
import typing
import pickle
from ..network import Request, ResponseSuccess
from ..utils import Command, Call, NetworkHandler, numberemojiformat
from ..error import TooManyFoundError, NoneFoundError
if typing.TYPE_CHECKING:
from ..bots import DiscordBot
class QueueNH(NetworkHandler):
message_type = "music_queue"
@classmethod
async def discord(cls, bot: "DiscordBot", data: dict):
# Find the matching guild
if data["guild_name"]:
guild = bot.client.find_guild_by_name(data["guild_name"])
else:
if len(bot.music_data) == 0:
raise NoneFoundError("No voice clients active")
if len(bot.music_data) > 1:
raise TooManyFoundError("Multiple guilds found")
guild = list(bot.music_data)[0]
# Check if the guild has a PlayMode
playmode = bot.music_data.get(guild)
if not playmode:
return ResponseSuccess({
"type": None
})
try:
queue = playmode.queue_preview()
except NotImplementedError:
return ResponseSuccess({
"type": playmode.__class__.__name__
})
return ResponseSuccess({
"type": playmode.__class__.__name__,
"queue":
{
"strings": [str(element.rpf.info) for element in queue],
"pickled_embeds": str(pickle.dumps([element.rpf.info.to_discord_embed() for element in queue]))
}
})
class QueueCommand(Command):
command_name = "queue"
command_description = "Visualizza un'anteprima della coda di riproduzione attuale."
command_syntax = "[ [guild] ]"
network_handlers = [QueueNH]
@classmethod
async def common(cls, call: Call):
guild, = call.args.match(r"(?:\[(.+)])?")
data = await call.net_request(Request("music_queue", {"guild_name": guild}), "discord")
if data["type"] is None:
await call.reply(" Non c'è nessuna coda di riproduzione attiva al momento.")
return
elif "queue" not in data:
await call.reply(f" La coda di riproduzione attuale ([c]{data['type']}[/c]) non permette l'anteprima.")
return
if data["type"] == "Playlist":
message = f" Questa [c]Playlist[/c] contiene {len(data['queue'])} elementi, e i prossimi saranno:\n"
elif data["type"] == "Pool":
message = f" Questo [c]Pool[/c] contiene {len(data['queue'])} elementi, tra cui:\n"
else:
message = f" Il PlayMode attuale, [c]{data['type']}[/c], contiene {len(data['queue'])} elementi:\n"
if call.interface_name == "discord":
await call.reply(message)
for embed in pickle.loads(eval(data["queue"]["pickled_embeds"]))[:5]:
await call.channel.send(embed=embed)
else:
message += numberemojiformat(data["queue"]["strings"][:10])
await call.reply(message)

View file

@ -23,7 +23,7 @@ class SkipNH(NetworkHandler):
guild = list(bot.music_data)[0]
# Set the currently playing source as ended
voice_client: discord.VoiceClient = bot.client.find_voice_client_by_guild(guild)
if not voice_client.is_playing():
if not (voice_client.is_playing() or voice_client.is_paused()):
raise NoneFoundError("Nothing to skip")
# noinspection PyProtectedMember
voice_client._player.stop()

View file

@ -1,4 +1,4 @@
"""Royalnet realated classes."""
"""Royalnet (websocket) related classes."""
from .request import Request
from .response import Response, ResponseSuccess, ResponseError
from .package import Package

View file

@ -20,7 +20,7 @@ log.setLevel(logging.WARNING)
commands = [PingCommand, ShipCommand, SmecdsCommand, ColorCommand, CiaoruoziCommand, DebugCreateCommand, SyncCommand,
AuthorCommand, DiarioCommand, RageCommand, DateparserCommand, ReminderCommand, KvactiveCommand, KvCommand,
KvrollCommand, VideoinfoCommand, SummonCommand, PlayCommand, SkipCommand, PlaymodeCommand,
VideochannelCommand, CvCommand]
VideochannelCommand, CvCommand, PauseCommand, QueueCommand]
address, port = "127.0.0.1", 1234

View file

@ -9,7 +9,7 @@ from .safeformat import safeformat
from .classdictjanitor import cdj
from .sleepuntil import sleep_until
from .networkhandler import NetworkHandler
from .formatters import andformat, plusformat, fileformat, ytdldateformat
from .formatters import andformat, plusformat, fileformat, ytdldateformat, numberemojiformat
__all__ = ["asyncify", "Call", "Command", "safeformat", "cdj", "sleep_until", "plusformat", "CommandArgs",
"NetworkHandler", "andformat", "plusformat", "fileformat", "ytdldateformat"]
"NetworkHandler", "andformat", "plusformat", "fileformat", "ytdldateformat", "numberemojiformat"]

View file

@ -10,7 +10,13 @@ loop = asyncio.get_event_loop()
class Call:
"""A command call. An abstract class, sub-bots should create a new call class from this."""
"""A command call. An abstract class, sub-bots should create a new call class from this.
Attributes:
interface_name: The name of the interface that is calling the command. For example, ``telegram``, or ``discord``.
interface_obj: The main object of the interface that is calling the command. For example, the :py:class:`royalnet.bots.TelegramBot` object.
interface_prefix: The command prefix used by the interface. For example, ``/``, or ``!``.
alchemy: The :py:class:`royalnet.database.Alchemy` object associated to this interface. May be None if the interface is not connected to any database."""
# These parameters / methods should be overridden
interface_name = NotImplemented
@ -30,7 +36,7 @@ class Call:
Parameters:
message: The data to be sent. Must be :py:mod:`pickle`-able.
destination: """
destination: The destination of the request, either in UUID format or node name."""
raise NotImplementedError()
async def get_author(self, error_if_none=False):

View file

@ -1,5 +1,16 @@
def cdj(class_) -> dict:
"""Return a dict of the class attributes without the ``__module__``, ``__dict__``, ``__weakref__`` and ``__doc__`` keys, to be used while generating dynamically SQLAlchemy declarative table classes."""
import typing
def cdj(class_: typing.Any) -> dict:
"""Return a dict of the class attributes without the ``__module__``, ``__dict__``, ``__weakref__`` and ``__doc__`` keys, to be used while generating dynamically SQLAlchemy declarative table classes.
Parameters:
class_: The object that you want to dict-ify.
Returns:
The class dict.
Warning:
You can't dict-ify classes with ``__slots__``!"""
d = dict(class_.__dict__)
del d["__module__"]
del d["__dict__"]

View file

@ -6,7 +6,14 @@ if typing.TYPE_CHECKING:
class Command:
"""A generic command, called from any source."""
"""The base class from which all commands should inherit.
Attributes:
command_name: The name of the command. To have ``/example`` on Telegram, the name should be ``example``.
command_description: A small description of the command, to be displayed when the command is being autocompleted.
command_syntax: The syntax of the command, to be displayed when a :py:exc:`royalnet.error.InvalidInputError` is raised, in the format ``(required_arg) [optional_arg]``.
require_alchemy_tables: A set of :py:class:`royalnet.database` tables, that must exist for this command to work.
network_handlers: A list of :py:class:`classyalnet.utils.NetworkHandler`s that must exist for this command to work."""
command_name: str = NotImplemented
command_description: str = NotImplemented

View file

@ -4,13 +4,13 @@ from royalnet.error import InvalidInputError
class CommandArgs(list):
"""The arguments of a command."""
"""An interface to access the arguments of a command with ease."""
def __getitem__(self, item):
"""Arguments can be accessed with an array notation, such as ``args[0]``.
Raises:
:py:exc:`InvalidInputError` if the requested argument does not exist."""
royalnet.error.InvalidInputError: if the requested argument does not exist."""
if isinstance(item, int):
try:
return super().__getitem__(item)
@ -30,7 +30,7 @@ class CommandArgs(list):
require_at_least: the minimum amount of arguments required, will raise :py:exc:`royalnet.error.InvalidInputError` if the requirement is not fullfilled.
Raises:
:py:exc:`royalnet.error.InvalidInputError` if the ``require_at_least`` requirement is not fullfilled.
royalnet.error.InvalidInputError: if there are less than ``require_at_least`` arguments.
Returns:
The space-joined string."""
@ -44,6 +44,9 @@ class CommandArgs(list):
Parameters:
pattern: The regex pattern to be passed to :py:func:`re.match`.
Raises:
royalnet.error.InvalidInputError: if the pattern doesn't match.
Returns:
The matched groups, as returned by :py:func:`re.Match.groups`."""
text = self.joined()

View file

@ -1,4 +1,8 @@
def discord_escape(string: str) -> str:
"""Escape a string to be sent through Discord, and format it using RoyalCode.
Warning:
Currently escapes everything, even items in code blocks."""
return string.replace("*", "\\*") \
.replace("_", "\\_") \
.replace("`", "\\`") \
@ -15,6 +19,10 @@ def discord_escape(string: str) -> str:
def telegram_escape(string: str) -> str:
"""Escape a string to be sent through Telegram, and format it using RoyalCode.
Warning:
Currently escapes everything, even items in code blocks."""
return string.replace("<", "&lt;") \
.replace(">", "&gt;") \
.replace("[b]", "<b>") \

View file

@ -23,7 +23,7 @@ def andformat(l: typing.List[str], middle=", ", final=" and ") -> str:
def plusformat(i: int) -> str:
"""Convert an :py:class:`int` to a :py:class:`str`, adding a ``+`` if they are greater than 0.
"""Convert an :py:class:`int` to a :py:class:`str`, prepending a ``+`` if it's greater than 0.
Parameters:
i: the :py:class:`int` to convert.
@ -36,11 +36,37 @@ def plusformat(i: int) -> str:
def fileformat(string: str) -> str:
"""Ensure a string can be used as a filename by replacing all non-word characters with underscores."""
"""Ensure a string can be used as a filename by replacing all non-word characters with underscores.
Parameters:
string: the input string.
Returns:
A valid filename string."""
return re.sub(r"\W", "_", string)
def ytdldateformat(string: typing.Optional[str], separator: str = "-") -> str:
"""Convert the weird date string returned by ``youtube-dl`` into the ``YYYY-MM-DD`` format.
Parameters:
string: the input string, in the ``YYYYMMDD`` format.
separator: the string to add between the years, the months and the days. Defaults to ``-``.
Returns:
The resulting string, in the format ``YYYY-MM-DD`` format."""
if string is None:
return ""
return f"{string[0:4]}-{string[4:6]}-{string[6:8]}"
return f"{string[0:4]}{separator}{string[4:6]}{separator}{string[6:8]}"
def numberemojiformat(l: typing.List[str]) -> str:
number_emojis = ["1", "2", "3", "4", "5", "6", "7", "8", "9", "🔟"]
extra_emoji = "*️⃣"
result = ""
for index, element in enumerate(l):
try:
result += f"{number_emojis[index]} {element}\n"
except IndexError:
result += f"{extra_emoji} {element}\n"
return result

View file

@ -0,0 +1,11 @@
import flask as f
from .. import Royalprint
bp = Royalprint("helloworld", __name__, url_prefix="/helloworld")
@bp.route("/")
def helloworld():
return "Hello world!"

View file

@ -0,0 +1,13 @@
import flask as f
from .. import Royalprint
from ...database.tables import Royal
bp = Royalprint("testing", __name__, url_prefix="/testing", required_tables={Royal})
@bp.route("/listroyals")
def listroyals():
from ..alchemyhandler import alchemy, alchemy_session
royals = alchemy_session.query(alchemy.Royal).all()
return f'<body><script type="text/plain" style="display: block;">{repr(royals)}</script></body>'