Sort event references by categories

This commit is contained in:
Chiggy-Playz 2021-10-03 16:18:46 +05:30
parent 3260ec6643
commit 16b7cdc488
85 changed files with 85331 additions and 571 deletions

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.

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.

Binary file not shown.

View File

@ -0,0 +1,17 @@
<svg style="width: 100%; height: 100%"
xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1036 597.33331" height="597.333" width="1036">
<path d="M498.46 84.248c-1.6 1.665-2.4 3.597-2.4 5.93 0 2.333.8 4.265 2.4 5.863 1.667 1.67 3.6 2.47 5.932 2.47 2.332 0 4.265-.8 5.864-2.46 1.665-1.59 2.465-3.53 2.465-5.86 0-2.33-.8-4.26-2.46-5.93-1.6-1.6-3.53-2.4-5.86-2.4s-4.26.8-5.93 2.4m-9.06 5.93c0-2.33-.8-4.26-2.46-5.93-1.6-1.6-3.53-2.4-5.862-2.4s-4.265.8-5.93 2.4c-1.6 1.67-2.4 3.6-2.4 5.93 0 2.33.8 4.27 2.4 5.86 1.665 1.67 3.598 2.47 5.93 2.47s4.265-.8 5.864-2.46c1.663-1.593 2.463-3.53 2.463-5.86m46.647 0c0-2.333-.8-4.27-2.467-5.93-1.6-1.6-3.53-2.4-5.86-2.4s-4.265.8-5.93 2.4c-1.6 1.665-2.4 3.597-2.4 5.93 0 2.333.8 4.265 2.4 5.863 1.665 1.67 3.598 2.467 5.93 2.467s4.265-.8 5.864-2.468c1.667-1.598 2.467-3.53 2.467-5.86" fill="#e0e0e0"/>
<path d="M2748.2-850.22H155.382c-76.964 0-115.447-48.474-115.447-144.932V-4303.65c0-96.45 38.483-144.93 115.447-144.93H6321.57c76.97 0 115.45 48.48 115.45 144.93v3308.498c0 96.458-38.48 144.933-115.45 144.933H3737.75" fill="none" stroke="#e0e0e0" stroke-width="79.964" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" transform="matrix(.13334 0 0 .13333 0 597.333)"/>
<path d="M4177.05-3798.87v2178.5H998.996v-2178.5c0-133.44 66.474-199.91 199.914-199.91h2778.23c133.44 0 199.91 66.47 199.91 199.91z" fill="none" stroke="#e0e0e0" stroke-width="79.964" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" transform="matrix(.13334 0 0 .13333 0 597.333)"/>
<path d="M6274.1-4181.2v2844.7c0 82.97-36.49 124.45-108.95 124.45H322.307c-72.47 0-108.952-41.48-108.952-124.45v-2844.7c0-82.96 36.483-124.44 108.952-124.44H6165.15c72.46 0 108.95 41.48 108.95 124.44zM449.25-41.084h147.43m182.418 0h339.842m1407.86 0c0-91.458 46.98-151.43 140.94-179.92 23.99-7.497 50.97-12.493 80.46-15.993m0 0c24.49-2.497 51.48-3.997 79.96-3.997h820.63c32.49 0 61.97 2 88.96 5.497M1348.84-41.084H2526.8m221.4-195.913V-850.22m989.55 614.723c26.49 3 49.98 7.996 71.47 14.493 93.96 28.49 140.93 88.462 140.93 179.92m2024.08 0h50.98m-468.28 0h219.89m-1826.67 0h1416.86M3737.75-235.497V-850.22m212.4 809.136H2526.8M3737.75-850.22H2748.2" fill="none" stroke="#e0e0e0" stroke-width="79.964" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" transform="matrix(.13334 0 0 .13333 0 597.333)"/>
<path d="M2126.79-2789.58c-38.13 38.49-57.37 85.01-57.37 139.59 0 54.22 19.24 100.75 57.37 139.23 38.48 38.48 85.01 57.73 139.59 57.73 54.22 0 100.75-19.25 139.23-57.73 38.49-38.48 57.73-85.01 57.73-139.23 0-54.58-19.24-101.1-57.73-139.59-38.48-38.13-85.01-57.37-139.23-57.37-54.58 0-101.11 19.24-139.59 57.37z" fill="none" stroke="#e0e0e0" stroke-width="69.967" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" transform="matrix(.13334 0 0 .13333 0 597.333)"/>
<path d="M2640.7-3448.32c-286.51-11.2-546.09 38.83-778.73 150.43 143.08-106.7 307.5-172.47 493.27-197.66-6.3-14.34-18.9-29.04-38.13-43.73h-62.98c-210.25 36.73-380.62 103.9-511.11 201.16-197.66 325.7-291.76 678.68-281.62 1058.6 142.39 189.97 349.49 279.53 621.31 267.98l122.45-129.44c-148.68-52.82-255.03-123.49-318.7-212 214.1 133.99 465.63 199.41 754.24 196.26" fill="none" stroke="#e0e0e0" stroke-width="69.967" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" transform="matrix(.13334 0 0 .13333 0 597.333)"/>
<path d="M-3149.74-2789.58c-38.13 38.49-57.37 85.01-57.37 139.59 0 54.22 19.24 100.75 57.37 139.23 38.49 38.48 85.01 57.73 139.59 57.73 54.22 0 100.75-19.25 139.23-57.73 38.49-38.48 57.73-85.01 57.73-139.23 0-54.58-19.24-101.1-57.73-139.59-38.48-38.13-85.01-57.37-139.23-57.37-54.58 0-101.1 19.24-139.59 57.37z" fill="none" stroke="#e0e0e0" stroke-width="69.967" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" transform="matrix(-.13334 0 0 .13333 0 597.333)"/>
<path d="M-2635.83-3448.32c-286.51-11.2-546.09 38.83-778.73 150.43 143.08-106.7 307.5-172.47 493.27-197.66-6.3-14.34-18.89-29.04-38.13-43.73h-62.98c-210.25 36.73-380.62 103.9-511.11 201.16-197.66 325.7-291.76 678.68-281.62 1058.6 142.39 189.97 349.49 279.53 621.32 267.98l122.44-129.44c-148.68-52.82-255.03-123.49-318.7-212 214.1 133.99 465.63 199.41 754.24 196.26" fill="none" stroke="#e0e0e0" stroke-width="69.967" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" transform="matrix(-.13334 0 0 .13333 0 597.333)"/>
<path d="M474.47 230.785c-17.793 0-26.655 8.863-26.655 26.654v261.2-23.99H207.912h47.98v-58.9 34.91h143.94-47.98v23.99h95.963v-94.88c-.534-16.73-9.396-25.06-26.656-25.06H186.58c-17.792 0-26.656 8.86-26.656 26.65v163.85c0 17.26 8.33 26.12 25.057 26.65h333.8c16.66-.53 24.99-9.39 24.99-26.65V326.74h-34.65c-16.66.667-24.65-7.33-23.99-23.987h300.28c4.2-7.13 6.27-15.126 6.27-23.99v-21.32c0-17.792-8.86-26.655-26.65-26.655zm-13.327 311.842l23.99 22.588-23.99-22.588" fill="#eadc62"/>
<path d="M777.616 312.677c3.132-3.132 5.73-6.397 7.796-9.928h-300.28c-.665 16.65 7.33 24.65 23.992 23.98h234.572c13.26 0 24.523-4.67 33.92-14.06" fill="#f2edc8"/>
<path d="M3890.68-40.99H1387.32m1971.1-1440.85v-1067.51c0-133.44 66.47-199.91 199.91-199.91h2179.01c133.44 0 199.91 66.47 199.91 199.91v159.93c0 66.47-15.49 126.44-46.98 179.92" fill="none" stroke="#000" stroke-width="79.964" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" transform="matrix(.13334 0 0 .13333 0 597.333)"/>
<path d="M5890.27-2209.5c-15.49 26.48-34.98 50.97-58.47 74.46-70.47 70.47-154.93 105.45-254.39 105.45H4078.1M3358.42-590.243V-770.16m719.68-1259.43h-259.88m-459.8 1259.43v-711.68M3638.3-240.9l-179.92-169.423M4449.93-40.99h-559.25m187.42-1988.6V-240.9c0 129.44-62.48 195.91-187.42 199.91m1007.04 0H4717.8M1559.24-770.16h359.84m4777.83-1259.43l-179.92-179.91m0 0l179.92-179.92M949.022-40.99h438.298M6516.99-2209.5h-626.72m-3971.19 997.54v261.88m0 0v179.92m1079.51-179.92h-359.84m0 0v179.92m-719.67-179.92h719.67m0 179.92h-719.67M1387.32-40.99c-125.44-4-187.91-70.47-187.91-199.91v-1228.94c0-133.44 66.47-199.91 199.9-199.91h1759.2c129.45 0 195.92 62.47 199.91 187.91m-719.67 711.68h719.67" fill="none" stroke="#000" stroke-width="79.964" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" transform="matrix(.13334 0 0 .13333 0 597.333)"/>
<path d="M7716.44-2209.5H7356.6m0 539.75l-179.92-179.92m179.92-899.59l-179.92 179.92" fill="none" stroke="#e0e0e0" stroke-width="99.954" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" transform="matrix(.13334 0 0 .13333 0 597.333)"/>
<path d="M769.485 258.24c-2.332-2.333-5.13-3.467-8.462-3.467s-6.198 1.134-8.53 3.466c-2.333 2.33-3.466 5.19-3.466 8.52s1.133 6.13 3.466 8.46c2.332 2.33 5.198 3.53 8.53 3.53 3.332 0 6.13-1.2 8.462-3.53 2.334-2.34 3.532-5.13 3.532-8.47 0-3.33-1.198-6.2-3.532-8.53"/>
</svg>

After

Width:  |  Height:  |  Size: 6.7 KiB

View File

@ -0,0 +1,17 @@
<svg style="width: 100%; height: 100%"
xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1036 597.33331" height="597.333" width="1036">
<path d="M498.46 84.248c-1.6 1.665-2.4 3.597-2.4 5.93 0 2.333.8 4.265 2.4 5.863 1.667 1.67 3.6 2.47 5.932 2.47 2.332 0 4.265-.8 5.864-2.46 1.665-1.59 2.465-3.53 2.465-5.86 0-2.33-.8-4.26-2.46-5.93-1.6-1.6-3.53-2.4-5.86-2.4s-4.26.8-5.93 2.4m-9.06 5.93c0-2.33-.8-4.26-2.46-5.93-1.6-1.6-3.53-2.4-5.862-2.4s-4.265.8-5.93 2.4c-1.6 1.67-2.4 3.6-2.4 5.93 0 2.33.8 4.27 2.4 5.86 1.665 1.67 3.598 2.47 5.93 2.47s4.265-.8 5.864-2.46c1.663-1.593 2.463-3.53 2.463-5.86m46.647 0c0-2.333-.8-4.27-2.467-5.93-1.6-1.6-3.53-2.4-5.86-2.4s-4.265.8-5.93 2.4c-1.6 1.665-2.4 3.597-2.4 5.93 0 2.333.8 4.265 2.4 5.863 1.665 1.67 3.598 2.467 5.93 2.467s4.265-.8 5.864-2.468c1.667-1.598 2.467-3.53 2.467-5.86" fill="#161616"/>
<path d="M2748.2-850.22H155.382c-76.964 0-115.447-48.474-115.447-144.932V-4303.65c0-96.45 38.483-144.93 115.447-144.93H6321.57c76.97 0 115.45 48.48 115.45 144.93v3308.498c0 96.458-38.48 144.933-115.45 144.933H3737.75" fill="none" stroke="#161616" stroke-width="79.964" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" transform="matrix(.13334 0 0 .13333 0 597.333)"/>
<path d="M4177.05-3798.87v2178.5H998.996v-2178.5c0-133.44 66.474-199.91 199.914-199.91h2778.23c133.44 0 199.91 66.47 199.91 199.91z" fill="none" stroke="#161616" stroke-width="79.964" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" transform="matrix(.13334 0 0 .13333 0 597.333)"/>
<path d="M6274.1-4181.2v2844.7c0 82.97-36.49 124.45-108.95 124.45H322.307c-72.47 0-108.952-41.48-108.952-124.45v-2844.7c0-82.96 36.483-124.44 108.952-124.44H6165.15c72.46 0 108.95 41.48 108.95 124.44zM449.25-41.084h147.43m182.418 0h339.842m1407.86 0c0-91.458 46.98-151.43 140.94-179.92 23.99-7.497 50.97-12.493 80.46-15.993m0 0c24.49-2.497 51.48-3.997 79.96-3.997h820.63c32.49 0 61.97 2 88.96 5.497M1348.84-41.084H2526.8m221.4-195.913V-850.22m989.55 614.723c26.49 3 49.98 7.996 71.47 14.493 93.96 28.49 140.93 88.462 140.93 179.92m2024.08 0h50.98m-468.28 0h219.89m-1826.67 0h1416.86M3737.75-235.497V-850.22m212.4 809.136H2526.8M3737.75-850.22H2748.2" fill="none" stroke="#161616" stroke-width="79.964" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" transform="matrix(.13334 0 0 .13333 0 597.333)"/>
<path d="M2126.79-2789.58c-38.13 38.49-57.37 85.01-57.37 139.59 0 54.22 19.24 100.75 57.37 139.23 38.48 38.48 85.01 57.73 139.59 57.73 54.22 0 100.75-19.25 139.23-57.73 38.49-38.48 57.73-85.01 57.73-139.23 0-54.58-19.24-101.1-57.73-139.59-38.48-38.13-85.01-57.37-139.23-57.37-54.58 0-101.11 19.24-139.59 57.37z" fill="none" stroke="#161616" stroke-width="69.967" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" transform="matrix(.13334 0 0 .13333 0 597.333)"/>
<path d="M2640.7-3448.32c-286.51-11.2-546.09 38.83-778.73 150.43 143.08-106.7 307.5-172.47 493.27-197.66-6.3-14.34-18.9-29.04-38.13-43.73h-62.98c-210.25 36.73-380.62 103.9-511.11 201.16-197.66 325.7-291.76 678.68-281.62 1058.6 142.39 189.97 349.49 279.53 621.31 267.98l122.45-129.44c-148.68-52.82-255.03-123.49-318.7-212 214.1 133.99 465.63 199.41 754.24 196.26" fill="none" stroke="#161616" stroke-width="69.967" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" transform="matrix(.13334 0 0 .13333 0 597.333)"/>
<path d="M-3149.74-2789.58c-38.13 38.49-57.37 85.01-57.37 139.59 0 54.22 19.24 100.75 57.37 139.23 38.49 38.48 85.01 57.73 139.59 57.73 54.22 0 100.75-19.25 139.23-57.73 38.49-38.48 57.73-85.01 57.73-139.23 0-54.58-19.24-101.1-57.73-139.59-38.48-38.13-85.01-57.37-139.23-57.37-54.58 0-101.1 19.24-139.59 57.37z" fill="none" stroke="#161616" stroke-width="69.967" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" transform="matrix(-.13334 0 0 .13333 0 597.333)"/>
<path d="M-2635.83-3448.32c-286.51-11.2-546.09 38.83-778.73 150.43 143.08-106.7 307.5-172.47 493.27-197.66-6.3-14.34-18.89-29.04-38.13-43.73h-62.98c-210.25 36.73-380.62 103.9-511.11 201.16-197.66 325.7-291.76 678.68-281.62 1058.6 142.39 189.97 349.49 279.53 621.32 267.98l122.44-129.44c-148.68-52.82-255.03-123.49-318.7-212 214.1 133.99 465.63 199.41 754.24 196.26" fill="none" stroke="#161616" stroke-width="69.967" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" transform="matrix(-.13334 0 0 .13333 0 597.333)"/>
<path d="M474.47 230.785c-17.793 0-26.655 8.863-26.655 26.654v261.2-23.99H207.912h47.98v-58.9 34.91h143.94-47.98v23.99h95.963v-94.88c-.534-16.73-9.396-25.06-26.656-25.06H186.58c-17.792 0-26.656 8.86-26.656 26.65v163.85c0 17.26 8.33 26.12 25.057 26.65h333.8c16.66-.53 24.99-9.39 24.99-26.65V326.74h-34.65c-16.66.667-24.65-7.33-23.99-23.987h300.28c4.2-7.13 6.27-15.126 6.27-23.99v-21.32c0-17.792-8.86-26.655-26.65-26.655zm-13.327 311.842l23.99 22.588-23.99-22.588" fill="#376fa1"/>
<path d="M777.616 312.677c3.132-3.132 5.73-6.397 7.796-9.928h-300.28c-.665 16.65 7.33 24.65 23.992 23.98h234.572c13.26 0 24.523-4.67 33.92-14.06" fill="#578fc1"/>
<path d="M3890.68-40.99H1387.32m1971.1-1440.85v-1067.51c0-133.44 66.47-199.91 199.91-199.91h2179.01c133.44 0 199.91 66.47 199.91 199.91v159.93c0 66.47-15.49 126.44-46.98 179.92" fill="none" stroke="#000" stroke-width="79.964" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" transform="matrix(.13334 0 0 .13333 0 597.333)"/>
<path d="M5890.27-2209.5c-15.49 26.48-34.98 50.97-58.47 74.46-70.47 70.47-154.93 105.45-254.39 105.45H4078.1M3358.42-590.243V-770.16m719.68-1259.43h-259.88m-459.8 1259.43v-711.68M3638.3-240.9l-179.92-169.423M4449.93-40.99h-559.25m187.42-1988.6V-240.9c0 129.44-62.48 195.91-187.42 199.91m1007.04 0H4717.8M1559.24-770.16h359.84m4777.83-1259.43l-179.92-179.91m0 0l179.92-179.92M949.022-40.99h438.298M6516.99-2209.5h-626.72m-3971.19 997.54v261.88m0 0v179.92m1079.51-179.92h-359.84m0 0v179.92m-719.67-179.92h719.67m0 179.92h-719.67M1387.32-40.99c-125.44-4-187.91-70.47-187.91-199.91v-1228.94c0-133.44 66.47-199.91 199.9-199.91h1759.2c129.45 0 195.92 62.47 199.91 187.91m-719.67 711.68h719.67" fill="none" stroke="#000" stroke-width="79.964" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" transform="matrix(.13334 0 0 .13333 0 597.333)"/>
<path d="M7716.44-2209.5H7356.6m0 539.75l-179.92-179.92m179.92-899.59l-179.92 179.92" fill="none" stroke="#161616" stroke-width="99.954" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" transform="matrix(.13334 0 0 .13333 0 597.333)"/>
<path d="M769.485 258.24c-2.332-2.333-5.13-3.467-8.462-3.467s-6.198 1.134-8.53 3.466c-2.333 2.33-3.466 5.19-3.466 8.52s1.133 6.13 3.466 8.46c2.332 2.33 5.198 3.53 8.53 3.53 3.332 0 6.13-1.2 8.462-3.53 2.334-2.34 3.532-5.13 3.532-8.47 0-3.33-1.198-6.2-3.532-8.53"/>
</svg>

After

Width:  |  Height:  |  Size: 6.6 KiB

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,96 @@
:orphan:
.. _discord-intro:
Creating a Bot Account
========================
In order to work with the library and the Discord API in general, we must first create a Discord Bot account.
Creating a Bot account is a pretty straightforward process.
1. Make sure you're logged on to the `Discord website <https://discord.com>`_.
2. Navigate to the `application page <https://discord.com/developers/applications>`_
3. Click on the "New Application" button.
.. image:: /images/discord_create_app_button.png
:alt: The new application button.
4. Give the application a name and click "Create".
.. image:: /images/discord_create_app_form.png
:alt: The new application form filled in.
5. Create a Bot User by navigating to the "Bot" tab and clicking "Add Bot".
- Click "Yes, do it!" to continue.
.. image:: /images/discord_create_bot_user.png
:alt: The Add Bot button.
6. Make sure that **Public Bot** is ticked if you want others to invite your bot.
- You should also make sure that **Require OAuth2 Code Grant** is unchecked unless you
are developing a service that needs it. If you're unsure, then **leave it unchecked**.
.. image:: /images/discord_bot_user_options.png
:alt: How the Bot User options should look like for most people.
7. Copy the token using the "Copy" button.
- **This is not the Client Secret at the General Information page.**
.. warning::
It should be worth noting that this token is essentially your bot's
password. You should **never** share this with someone else. In doing so,
someone can log in to your bot and do malicious things, such as leaving
servers, ban all members inside a server, or pinging everyone maliciously.
The possibilities are endless, so **do not share this token.**
If you accidentally leaked your token, click the "Regenerate" button as soon
as possible. This revokes your old token and re-generates a new one.
Now you need to use the new token to login.
And that's it. You now have a bot account and you can login with that token.
.. _discord_invite_bot:
Inviting Your Bot
-------------------
So you've made a Bot User but it's not actually in any server.
If you want to invite your bot you must create an invite URL for it.
1. Make sure you're logged on to the `Discord website <https://discord.com>`_.
2. Navigate to the `application page <https://discord.com/developers/applications>`_
3. Click on your bot's page.
4. Go to the "OAuth2" tab.
.. image:: /images/discord_oauth2.png
:alt: How the OAuth2 page should look like.
5. Tick the "bot" checkbox under "scopes".
.. image:: /images/discord_oauth2_scope.png
:alt: The scopes checkbox with "bot" ticked.
6. Tick the permissions required for your bot to function under "Bot Permissions".
- Please be aware of the consequences of requiring your bot to have the "Administrator" permission.
- Bot owners must have 2FA enabled for certain actions and permissions when added in servers that have Server-Wide 2FA enabled. Check the `2FA support page <https://support.discord.com/hc/en-us/articles/219576828-Setting-up-Two-Factor-Authentication>`_ for more information.
.. image:: /images/discord_oauth2_perms.png
:alt: The permission checkboxes with some permissions checked.
7. Now the resulting URL can be used to add your bot to a server. Copy and paste the URL into your browser, choose a server to invite the bot to, and click "Authorize".
.. note::
The person adding the bot needs "Manage Server" permissions to do so.
If you want to generate this URL dynamically at run-time inside your bot and using the
:class:`discord.Permissions` interface, you can use :func:`discord.utils.oauth_url`.

View File

@ -0,0 +1,681 @@
.. currentmodule:: discord
API Reference
===============
The following section outlines the API of discord.py's command extension module.
.. _ext_commands_api_bot:
Bots
------
Bot
~~~~
.. attributetable:: discord.ext.commands.Bot
.. autoclass:: discord.ext.commands.Bot
:members:
:inherited-members:
:exclude-members: after_invoke, before_invoke, check, check_once, command, event, group, listen
.. automethod:: Bot.after_invoke()
:decorator:
.. automethod:: Bot.before_invoke()
:decorator:
.. automethod:: Bot.check()
:decorator:
.. automethod:: Bot.check_once()
:decorator:
.. automethod:: Bot.command(*args, **kwargs)
:decorator:
.. automethod:: Bot.event()
:decorator:
.. automethod:: Bot.group(*args, **kwargs)
:decorator:
.. automethod:: Bot.listen(name=None)
:decorator:
AutoShardedBot
~~~~~~~~~~~~~~~~
.. attributetable:: discord.ext.commands.AutoShardedBot
.. autoclass:: discord.ext.commands.AutoShardedBot
:members:
Prefix Helpers
----------------
.. autofunction:: discord.ext.commands.when_mentioned
.. autofunction:: discord.ext.commands.when_mentioned_or
.. _ext_commands_api_events:
Event Reference
-----------------
These events function similar to :ref:`the regular events <discord-api-events>`, except they
are custom to the command extension module.
.. function:: discord.ext.commands.on_command_error(ctx, error)
An error handler that is called when an error is raised
inside a command either through user input error, check
failure, or an error in your own code.
A default one is provided (:meth:`.Bot.on_command_error`).
:param ctx: The invocation context.
:type ctx: :class:`.Context`
:param error: The error that was raised.
:type error: :class:`.CommandError` derived
.. function:: discord.ext.commands.on_command(ctx)
An event that is called when a command is found and is about to be invoked.
This event is called regardless of whether the command itself succeeds via
error or completes.
:param ctx: The invocation context.
:type ctx: :class:`.Context`
.. function:: discord.ext.commands.on_command_completion(ctx)
An event that is called when a command has completed its invocation.
This event is called only if the command succeeded, i.e. all checks have
passed and the user input it correctly.
:param ctx: The invocation context.
:type ctx: :class:`.Context`
.. _ext_commands_api_command:
Commands
----------
Decorators
~~~~~~~~~~~~
.. autofunction:: discord.ext.commands.command
:decorator:
.. autofunction:: discord.ext.commands.group
:decorator:
Command
~~~~~~~~~
.. attributetable:: discord.ext.commands.Command
.. autoclass:: discord.ext.commands.Command
:members:
:special-members: __call__
:exclude-members: after_invoke, before_invoke, error
.. automethod:: Command.after_invoke()
:decorator:
.. automethod:: Command.before_invoke()
:decorator:
.. automethod:: Command.error()
:decorator:
Group
~~~~~~
.. attributetable:: discord.ext.commands.Group
.. autoclass:: discord.ext.commands.Group
:members:
:inherited-members:
:exclude-members: after_invoke, before_invoke, command, error, group
.. automethod:: Group.after_invoke()
:decorator:
.. automethod:: Group.before_invoke()
:decorator:
.. automethod:: Group.command(*args, **kwargs)
:decorator:
.. automethod:: Group.error()
:decorator:
.. automethod:: Group.group(*args, **kwargs)
:decorator:
GroupMixin
~~~~~~~~~~~
.. attributetable:: discord.ext.commands.GroupMixin
.. autoclass:: discord.ext.commands.GroupMixin
:members:
:exclude-members: command, group
.. automethod:: GroupMixin.command(*args, **kwargs)
:decorator:
.. automethod:: GroupMixin.group(*args, **kwargs)
:decorator:
.. _ext_commands_api_cogs:
Cogs
------
Cog
~~~~
.. attributetable:: discord.ext.commands.Cog
.. autoclass:: discord.ext.commands.Cog
:members:
CogMeta
~~~~~~~~
.. attributetable:: discord.ext.commands.CogMeta
.. autoclass:: discord.ext.commands.CogMeta
:members:
.. _ext_commands_help_command:
Help Commands
---------------
HelpCommand
~~~~~~~~~~~~
.. attributetable:: discord.ext.commands.HelpCommand
.. autoclass:: discord.ext.commands.HelpCommand
:members:
DefaultHelpCommand
~~~~~~~~~~~~~~~~~~~
.. attributetable:: discord.ext.commands.DefaultHelpCommand
.. autoclass:: discord.ext.commands.DefaultHelpCommand
:members:
:exclude-members: send_bot_help, send_cog_help, send_group_help, send_command_help, prepare_help_command
MinimalHelpCommand
~~~~~~~~~~~~~~~~~~~
.. attributetable:: discord.ext.commands.MinimalHelpCommand
.. autoclass:: discord.ext.commands.MinimalHelpCommand
:members:
:exclude-members: send_bot_help, send_cog_help, send_group_help, send_command_help, prepare_help_command
Paginator
~~~~~~~~~~
.. attributetable:: discord.ext.commands.Paginator
.. autoclass:: discord.ext.commands.Paginator
:members:
Enums
------
.. class:: BucketType
:module: discord.ext.commands
Specifies a type of bucket for, e.g. a cooldown.
.. attribute:: default
The default bucket operates on a global basis.
.. attribute:: user
The user bucket operates on a per-user basis.
.. attribute:: guild
The guild bucket operates on a per-guild basis.
.. attribute:: channel
The channel bucket operates on a per-channel basis.
.. attribute:: member
The member bucket operates on a per-member basis.
.. attribute:: category
The category bucket operates on a per-category basis.
.. attribute:: role
The role bucket operates on a per-role basis.
.. versionadded:: 1.3
.. _ext_commands_api_checks:
Checks
-------
.. autofunction:: discord.ext.commands.check(predicate)
:decorator:
.. autofunction:: discord.ext.commands.check_any(*checks)
:decorator:
.. autofunction:: discord.ext.commands.has_role(item)
:decorator:
.. autofunction:: discord.ext.commands.has_permissions(**perms)
:decorator:
.. autofunction:: discord.ext.commands.has_guild_permissions(**perms)
:decorator:
.. autofunction:: discord.ext.commands.has_any_role(*items)
:decorator:
.. autofunction:: discord.ext.commands.bot_has_role(item)
:decorator:
.. autofunction:: discord.ext.commands.bot_has_permissions(**perms)
:decorator:
.. autofunction:: discord.ext.commands.bot_has_guild_permissions(**perms)
:decorator:
.. autofunction:: discord.ext.commands.bot_has_any_role(*items)
:decorator:
.. autofunction:: discord.ext.commands.cooldown(rate, per, type=discord.ext.commands.BucketType.default)
:decorator:
.. autofunction:: discord.ext.commands.dynamic_cooldown(cooldown, type=BucketType.default)
:decorator:
.. autofunction:: discord.ext.commands.max_concurrency(number, per=discord.ext.commands.BucketType.default, *, wait=False)
:decorator:
.. autofunction:: discord.ext.commands.before_invoke(coro)
:decorator:
.. autofunction:: discord.ext.commands.after_invoke(coro)
:decorator:
.. autofunction:: discord.ext.commands.guild_only(,)
:decorator:
.. autofunction:: discord.ext.commands.dm_only(,)
:decorator:
.. autofunction:: discord.ext.commands.is_owner(,)
:decorator:
.. autofunction:: discord.ext.commands.is_nsfw(,)
:decorator:
.. _ext_commands_api_context:
Cooldown
---------
.. attributetable:: discord.ext.commands.Cooldown
.. autoclass:: discord.ext.commands.Cooldown
:members:
Context
--------
.. attributetable:: discord.ext.commands.Context
.. autoclass:: discord.ext.commands.Context
:members:
:inherited-members:
:exclude-members: history, typing
.. automethod:: discord.ext.commands.Context.history
:async-for:
.. automethod:: discord.ext.commands.Context.typing
:async-with:
.. _ext_commands_api_converters:
Converters
------------
.. autoclass:: discord.ext.commands.Converter
:members:
.. autoclass:: discord.ext.commands.ObjectConverter
:members:
.. autoclass:: discord.ext.commands.MemberConverter
:members:
.. autoclass:: discord.ext.commands.UserConverter
:members:
.. autoclass:: discord.ext.commands.MessageConverter
:members:
.. autoclass:: discord.ext.commands.PartialMessageConverter
:members:
.. autoclass:: discord.ext.commands.GuildChannelConverter
:members:
.. autoclass:: discord.ext.commands.TextChannelConverter
:members:
.. autoclass:: discord.ext.commands.VoiceChannelConverter
:members:
.. autoclass:: discord.ext.commands.StoreChannelConverter
:members:
.. autoclass:: discord.ext.commands.StageChannelConverter
:members:
.. autoclass:: discord.ext.commands.CategoryChannelConverter
:members:
.. autoclass:: discord.ext.commands.InviteConverter
:members:
.. autoclass:: discord.ext.commands.GuildConverter
:members:
.. autoclass:: discord.ext.commands.RoleConverter
:members:
.. autoclass:: discord.ext.commands.GameConverter
:members:
.. autoclass:: discord.ext.commands.ColourConverter
:members:
.. autoclass:: discord.ext.commands.EmojiConverter
:members:
.. autoclass:: discord.ext.commands.PartialEmojiConverter
:members:
.. autoclass:: discord.ext.commands.ThreadConverter
:members:
.. autoclass:: discord.ext.commands.GuildStickerConverter
:members:
.. autoclass:: discord.ext.commands.clean_content
:members:
.. autoclass:: discord.ext.commands.Greedy()
.. autofunction:: discord.ext.commands.run_converters
Option
~~~~~~
.. autoclass:: discord.ext.commands.Option
:members:
Flag Converter
~~~~~~~~~~~~~~~
.. autoclass:: discord.ext.commands.FlagConverter
:members:
.. autoclass:: discord.ext.commands.Flag()
:members:
.. autofunction:: discord.ext.commands.flag
.. _ext_commands_api_errors:
Exceptions
-----------
.. autoexception:: discord.ext.commands.CommandError
:members:
.. autoexception:: discord.ext.commands.ConversionError
:members:
.. autoexception:: discord.ext.commands.MissingRequiredArgument
:members:
.. autoexception:: discord.ext.commands.ArgumentParsingError
:members:
.. autoexception:: discord.ext.commands.UnexpectedQuoteError
:members:
.. autoexception:: discord.ext.commands.InvalidEndOfQuotedStringError
:members:
.. autoexception:: discord.ext.commands.ExpectedClosingQuoteError
:members:
.. autoexception:: discord.ext.commands.BadArgument
:members:
.. autoexception:: discord.ext.commands.BadUnionArgument
:members:
.. autoexception:: discord.ext.commands.BadLiteralArgument
:members:
.. autoexception:: discord.ext.commands.PrivateMessageOnly
:members:
.. autoexception:: discord.ext.commands.NoPrivateMessage
:members:
.. autoexception:: discord.ext.commands.CheckFailure
:members:
.. autoexception:: discord.ext.commands.CheckAnyFailure
:members:
.. autoexception:: discord.ext.commands.CommandNotFound
:members:
.. autoexception:: discord.ext.commands.DisabledCommand
:members:
.. autoexception:: discord.ext.commands.CommandInvokeError
:members:
.. autoexception:: discord.ext.commands.TooManyArguments
:members:
.. autoexception:: discord.ext.commands.UserInputError
:members:
.. autoexception:: discord.ext.commands.CommandOnCooldown
:members:
.. autoexception:: discord.ext.commands.MaxConcurrencyReached
:members:
.. autoexception:: discord.ext.commands.NotOwner
:members:
.. autoexception:: discord.ext.commands.MessageNotFound
:members:
.. autoexception:: discord.ext.commands.MemberNotFound
:members:
.. autoexception:: discord.ext.commands.GuildNotFound
:members:
.. autoexception:: discord.ext.commands.UserNotFound
:members:
.. autoexception:: discord.ext.commands.ChannelNotFound
:members:
.. autoexception:: discord.ext.commands.ChannelNotReadable
:members:
.. autoexception:: discord.ext.commands.ThreadNotFound
:members:
.. autoexception:: discord.ext.commands.BadColourArgument
:members:
.. autoexception:: discord.ext.commands.RoleNotFound
:members:
.. autoexception:: discord.ext.commands.BadInviteArgument
:members:
.. autoexception:: discord.ext.commands.EmojiNotFound
:members:
.. autoexception:: discord.ext.commands.PartialEmojiConversionFailure
:members:
.. autoexception:: discord.ext.commands.GuildStickerNotFound
:members:
.. autoexception:: discord.ext.commands.BadBoolArgument
:members:
.. autoexception:: discord.ext.commands.MissingPermissions
:members:
.. autoexception:: discord.ext.commands.BotMissingPermissions
:members:
.. autoexception:: discord.ext.commands.MissingRole
:members:
.. autoexception:: discord.ext.commands.BotMissingRole
:members:
.. autoexception:: discord.ext.commands.MissingAnyRole
:members:
.. autoexception:: discord.ext.commands.BotMissingAnyRole
:members:
.. autoexception:: discord.ext.commands.NSFWChannelRequired
:members:
.. autoexception:: discord.ext.commands.FlagError
:members:
.. autoexception:: discord.ext.commands.BadFlagArgument
:members:
.. autoexception:: discord.ext.commands.MissingFlagArgument
:members:
.. autoexception:: discord.ext.commands.TooManyFlags
:members:
.. autoexception:: discord.ext.commands.MissingRequiredFlag
:members:
.. autoexception:: discord.ext.commands.ExtensionError
:members:
.. autoexception:: discord.ext.commands.ExtensionAlreadyLoaded
:members:
.. autoexception:: discord.ext.commands.ExtensionNotLoaded
:members:
.. autoexception:: discord.ext.commands.NoEntryPointError
:members:
.. autoexception:: discord.ext.commands.ExtensionFailed
:members:
.. autoexception:: discord.ext.commands.ExtensionNotFound
:members:
.. autoexception:: discord.ext.commands.CommandRegistrationError
:members:
Exception Hierarchy
~~~~~~~~~~~~~~~~~~~~~
.. exception_hierarchy::
- :exc:`~.DiscordException`
- :exc:`~.commands.CommandError`
- :exc:`~.commands.ConversionError`
- :exc:`~.commands.UserInputError`
- :exc:`~.commands.MissingRequiredArgument`
- :exc:`~.commands.TooManyArguments`
- :exc:`~.commands.BadArgument`
- :exc:`~.commands.MessageNotFound`
- :exc:`~.commands.MemberNotFound`
- :exc:`~.commands.GuildNotFound`
- :exc:`~.commands.UserNotFound`
- :exc:`~.commands.ChannelNotFound`
- :exc:`~.commands.ChannelNotReadable`
- :exc:`~.commands.BadColourArgument`
- :exc:`~.commands.RoleNotFound`
- :exc:`~.commands.BadInviteArgument`
- :exc:`~.commands.EmojiNotFound`
- :exc:`~.commands.GuildStickerNotFound`
- :exc:`~.commands.PartialEmojiConversionFailure`
- :exc:`~.commands.BadBoolArgument`
- :exc:`~.commands.ThreadNotFound`
- :exc:`~.commands.FlagError`
- :exc:`~.commands.BadFlagArgument`
- :exc:`~.commands.MissingFlagArgument`
- :exc:`~.commands.TooManyFlags`
- :exc:`~.commands.MissingRequiredFlag`
- :exc:`~.commands.BadUnionArgument`
- :exc:`~.commands.BadLiteralArgument`
- :exc:`~.commands.ArgumentParsingError`
- :exc:`~.commands.UnexpectedQuoteError`
- :exc:`~.commands.InvalidEndOfQuotedStringError`
- :exc:`~.commands.ExpectedClosingQuoteError`
- :exc:`~.commands.CommandNotFound`
- :exc:`~.commands.CheckFailure`
- :exc:`~.commands.CheckAnyFailure`
- :exc:`~.commands.PrivateMessageOnly`
- :exc:`~.commands.NoPrivateMessage`
- :exc:`~.commands.NotOwner`
- :exc:`~.commands.MissingPermissions`
- :exc:`~.commands.BotMissingPermissions`
- :exc:`~.commands.MissingRole`
- :exc:`~.commands.BotMissingRole`
- :exc:`~.commands.MissingAnyRole`
- :exc:`~.commands.BotMissingAnyRole`
- :exc:`~.commands.NSFWChannelRequired`
- :exc:`~.commands.DisabledCommand`
- :exc:`~.commands.CommandInvokeError`
- :exc:`~.commands.CommandOnCooldown`
- :exc:`~.commands.MaxConcurrencyReached`
- :exc:`~.commands.ExtensionError`
- :exc:`~.commands.ExtensionAlreadyLoaded`
- :exc:`~.commands.ExtensionNotLoaded`
- :exc:`~.commands.NoEntryPointError`
- :exc:`~.commands.ExtensionFailed`
- :exc:`~.commands.ExtensionNotFound`
- :exc:`~.ClientException`
- :exc:`~.commands.CommandRegistrationError`

View File

@ -0,0 +1,159 @@
.. currentmodule:: discord
.. _ext_commands_cogs:
Cogs
======
There comes a point in your bot's development when you want to organize a collection of commands, listeners, and some state into one class. Cogs allow you to do just that.
The gist:
- Each cog is a Python class that subclasses :class:`.commands.Cog`.
- Every command is marked with the :func:`.commands.command` decorator.
- Every listener is marked with the :meth:`.commands.Cog.listener` decorator.
- Cogs are then registered with the :meth:`.Bot.add_cog` call.
- Cogs are subsequently removed with the :meth:`.Bot.remove_cog` call.
It should be noted that cogs are typically used alongside with :ref:`ext_commands_extensions`.
Quick Example
---------------
This example cog defines a ``Greetings`` category for your commands, with a single :ref:`command <ext_commands_commands>` named ``hello`` as well as a listener to listen to an :ref:`Event <discord-api-events>`.
.. code-block:: python3
class Greetings(commands.Cog):
def __init__(self, bot):
self.bot = bot
self._last_member = None
@commands.Cog.listener()
async def on_member_join(self, member):
channel = member.guild.system_channel
if channel is not None:
await channel.send(f'Welcome {member.mention}.')
@commands.command()
async def hello(self, ctx, *, member: discord.Member = None):
"""Says hello"""
member = member or ctx.author
if self._last_member is None or self._last_member.id != member.id:
await ctx.send(f'Hello {member.name}~')
else:
await ctx.send(f'Hello {member.name}... This feels familiar.')
self._last_member = member
A couple of technical notes to take into consideration:
- All listeners must be explicitly marked via decorator, :meth:`~.commands.Cog.listener`.
- The name of the cog is automatically derived from the class name but can be overridden. See :ref:`ext_commands_cogs_meta_options`.
- All commands must now take a ``self`` parameter to allow usage of instance attributes that can be used to maintain state.
Cog Registration
-------------------
Once you have defined your cogs, you need to tell the bot to register the cogs to be used. We do this via the :meth:`~.commands.Bot.add_cog` method.
.. code-block:: python3
bot.add_cog(Greetings(bot))
This binds the cog to the bot, adding all commands and listeners to the bot automatically.
Note that we reference the cog by name, which we can override through :ref:`ext_commands_cogs_meta_options`. So if we ever want to remove the cog eventually, we would have to do the following.
.. code-block:: python3
bot.remove_cog('Greetings')
Using Cogs
-------------
Just as we remove a cog by its name, we can also retrieve it by its name as well. This allows us to use a cog as an inter-command communication protocol to share data. For example:
.. code-block:: python3
:emphasize-lines: 22,24
class Economy(commands.Cog):
...
async def withdraw_money(self, member, money):
# implementation here
...
async def deposit_money(self, member, money):
# implementation here
...
class Gambling(commands.Cog):
def __init__(self, bot):
self.bot = bot
def coinflip(self):
return random.randint(0, 1)
@commands.command()
async def gamble(self, ctx, money: int):
"""Gambles some money."""
economy = self.bot.get_cog('Economy')
if economy is not None:
await economy.withdraw_money(ctx.author, money)
if self.coinflip() == 1:
await economy.deposit_money(ctx.author, money * 1.5)
.. _ext_commands_cogs_special_methods:
Special Methods
-----------------
As cogs get more complicated and have more commands, there comes a point where we want to customise the behaviour of the entire cog or bot.
They are as follows:
- :meth:`.Cog.cog_unload`
- :meth:`.Cog.cog_check`
- :meth:`.Cog.cog_command_error`
- :meth:`.Cog.cog_before_invoke`
- :meth:`.Cog.cog_after_invoke`
- :meth:`.Cog.bot_check`
- :meth:`.Cog.bot_check_once`
You can visit the reference to get more detail.
.. _ext_commands_cogs_meta_options:
Meta Options
--------------
At the heart of a cog resides a metaclass, :class:`.commands.CogMeta`, which can take various options to customise some of the behaviour. To do this, we pass keyword arguments to the class definition line. For example, to change the cog name we can pass the ``name`` keyword argument as follows:
.. code-block:: python3
class MyCog(commands.Cog, name='My Cog'):
pass
To see more options that you can set, see the documentation of :class:`.commands.CogMeta`.
Inspection
------------
Since cogs ultimately are classes, we have some tools to help us inspect certain properties of the cog.
To get a :class:`list` of commands, we can use :meth:`.Cog.get_commands`. ::
>>> cog = bot.get_cog('Greetings')
>>> commands = cog.get_commands()
>>> print([c.name for c in commands])
If we want to get the subcommands as well, we can use the :meth:`.Cog.walk_commands` generator. ::
>>> print([c.qualified_name for c in cog.walk_commands()])
To do the same with listeners, we can query them with :meth:`.Cog.get_listeners`. This returns a list of tuples -- the first element being the listener name and the second one being the actual function itself. ::
>>> for name, func in cog.get_listeners():
... print(name, '->', func)

View File

@ -0,0 +1,962 @@
.. currentmodule:: discord
.. _ext_commands_commands:
Commands
==========
One of the most appealing aspects of the command extension is how easy it is to define commands and
how you can arbitrarily nest groups and commands to have a rich sub-command system.
Commands are defined by attaching it to a regular Python function. The command is then invoked by the user using a similar
signature to the Python function.
For example, in the given command definition:
.. code-block:: python3
@bot.command()
async def foo(ctx, arg):
await ctx.send(arg)
With the following prefix (``$``), it would be invoked by the user via:
.. code-block:: none
$foo abc
A command must always have at least one parameter, ``ctx``, which is the :class:`.Context` as the first one.
There are two ways of registering a command. The first one is by using :meth:`.Bot.command` decorator,
as seen in the example above. The second is using the :func:`~ext.commands.command` decorator followed by
:meth:`.Bot.add_command` on the instance.
Essentially, these two are equivalent: ::
from discord.ext import commands
bot = commands.Bot(command_prefix='$')
@bot.command()
async def test(ctx):
pass
# or:
@commands.command()
async def test(ctx):
pass
bot.add_command(test)
Since the :meth:`.Bot.command` decorator is shorter and easier to comprehend, it will be the one used throughout the
documentation here.
Any parameter that is accepted by the :class:`.Command` constructor can be passed into the decorator. For example, to change
the name to something other than the function would be as simple as doing this:
.. code-block:: python3
@bot.command(name='list')
async def _list(ctx, arg):
pass
Parameters
------------
Since we define commands by making Python functions, we also define the argument passing behaviour by the function
parameters.
Certain parameter types do different things in the user side and most forms of parameter types are supported.
Positional
++++++++++++
The most basic form of parameter passing is the positional parameter. This is where we pass a parameter as-is:
.. code-block:: python3
@bot.command()
async def test(ctx, arg):
await ctx.send(arg)
On the bot using side, you can provide positional arguments by just passing a regular string:
.. image:: /images/commands/positional1.png
To make use of a word with spaces in between, you should quote it:
.. image:: /images/commands/positional2.png
As a note of warning, if you omit the quotes, you will only get the first word:
.. image:: /images/commands/positional3.png
Since positional arguments are just regular Python arguments, you can have as many as you want:
.. code-block:: python3
@bot.command()
async def test(ctx, arg1, arg2):
await ctx.send(f'You passed {arg1} and {arg2}')
Variable
++++++++++
Sometimes you want users to pass in an undetermined number of parameters. The library supports this
similar to how variable list parameters are done in Python:
.. code-block:: python3
@bot.command()
async def test(ctx, *args):
arguments = ', '.join(args)
await ctx.send(f'{len(args)} arguments: {arguments}')
This allows our user to accept either one or many arguments as they please. This works similar to positional arguments,
so multi-word parameters should be quoted.
For example, on the bot side:
.. image:: /images/commands/variable1.png
If the user wants to input a multi-word argument, they have to quote it like earlier:
.. image:: /images/commands/variable2.png
Do note that similar to the Python function behaviour, a user can technically pass no arguments
at all:
.. image:: /images/commands/variable3.png
Since the ``args`` variable is a :class:`py:tuple`,
you can do anything you would usually do with one.
.. admonition:: Slash Command Only
This functionally is currently not supported by the slash command API, so is turned into
a single ``STRING`` parameter on discord's end which we do our own parsing on.
Keyword-Only Arguments
++++++++++++++++++++++++
When you want to handle parsing of the argument yourself or do not feel like you want to wrap multi-word user input into
quotes, you can ask the library to give you the rest as a single argument. We do this by using a **keyword-only argument**,
seen below:
.. code-block:: python3
@bot.command()
async def test(ctx, *, arg):
await ctx.send(arg)
.. warning::
You can only have one keyword-only argument due to parsing ambiguities.
On the bot side, we do not need to quote input with spaces:
.. image:: /images/commands/keyword1.png
Do keep in mind that wrapping it in quotes leaves it as-is:
.. image:: /images/commands/keyword2.png
By default, the keyword-only arguments are stripped of white space to make it easier to work with. This behaviour can be
toggled by the :attr:`.Command.rest_is_raw` argument in the decorator.
.. _ext_commands_context:
Invocation Context
-------------------
As seen earlier, every command must take at least a single parameter, called the :class:`~ext.commands.Context`.
This parameter gives you access to something called the "invocation context". Essentially all the information you need to
know how the command was executed. It contains a lot of useful information:
- :attr:`.Context.guild` to fetch the :class:`Guild` of the command, if any.
- :attr:`.Context.message` to fetch the :class:`Message` of the command.
- :attr:`.Context.author` to fetch the :class:`Member` or :class:`User` that called the command.
- :meth:`.Context.send` to send a message to the channel the command was used in.
The context implements the :class:`abc.Messageable` interface, so anything you can do on a :class:`abc.Messageable` you
can do on the :class:`~ext.commands.Context`.
.. admonition:: Slash Command Only
:attr:`.Context.message` will be fake if in a slash command, it is not
recommended to access if :attr:`.Context.interaction` is not None as most
methods will error due to the message not actually existing.
Converters
------------
Adding bot arguments with function parameters is only the first step in defining your bot's command interface. To actually
make use of the arguments, we usually want to convert the data into a target type. We call these
:ref:`ext_commands_api_converters`.
Converters come in a few flavours:
- A regular callable object that takes an argument as a sole parameter and returns a different type.
- These range from your own function, to something like :class:`bool` or :class:`int`.
- A custom class that inherits from :class:`~ext.commands.Converter`.
.. _ext_commands_basic_converters:
Basic Converters
++++++++++++++++++
At its core, a basic converter is a callable that takes in an argument and turns it into something else.
For example, if we wanted to add two numbers together, we could request that they are turned into integers
for us by specifying the converter:
.. code-block:: python3
@bot.command()
async def add(ctx, a: int, b: int):
await ctx.send(a + b)
We specify converters by using something called a **function annotation**. This is a Python 3 exclusive feature that was
introduced in :pep:`3107`.
This works with any callable, such as a function that would convert a string to all upper-case:
.. code-block:: python3
def to_upper(argument):
return argument.upper()
@bot.command()
async def up(ctx, *, content: to_upper):
await ctx.send(content)
bool
^^^^^^
Unlike the other basic converters, the :class:`bool` converter is treated slightly different. Instead of casting directly to the :class:`bool` type, which would result in any non-empty argument returning ``True``, it instead evaluates the argument as ``True`` or ``False`` based on its given content:
.. code-block:: python3
if lowered in ('yes', 'y', 'true', 't', '1', 'enable', 'on'):
return True
elif lowered in ('no', 'n', 'false', 'f', '0', 'disable', 'off'):
return False
.. _ext_commands_adv_converters:
Advanced Converters
+++++++++++++++++++++
Sometimes a basic converter doesn't have enough information that we need. For example, sometimes we want to get some
information from the :class:`Message` that called the command or we want to do some asynchronous processing.
For this, the library provides the :class:`~ext.commands.Converter` interface. This allows you to have access to the
:class:`.Context` and have the callable be asynchronous. Defining a custom converter using this interface requires
overriding a single method, :meth:`.Converter.convert`.
An example converter:
.. code-block:: python3
import random
class Slapper(commands.Converter):
async def convert(self, ctx, argument):
to_slap = random.choice(ctx.guild.members)
return f'{ctx.author} slapped {to_slap} because *{argument}*'
@bot.command()
async def slap(ctx, *, reason: Slapper):
await ctx.send(reason)
The converter provided can either be constructed or not. Essentially these two are equivalent:
.. code-block:: python3
@bot.command()
async def slap(ctx, *, reason: Slapper):
await ctx.send(reason)
# is the same as...
@bot.command()
async def slap(ctx, *, reason: Slapper()):
await ctx.send(reason)
Having the possibility of the converter be constructed allows you to set up some state in the converter's ``__init__`` for
fine tuning the converter. An example of this is actually in the library, :class:`~ext.commands.clean_content`.
.. code-block:: python3
@bot.command()
async def clean(ctx, *, content: commands.clean_content):
await ctx.send(content)
# or for fine-tuning
@bot.command()
async def clean(ctx, *, content: commands.clean_content(use_nicknames=False)):
await ctx.send(content)
If a converter fails to convert an argument to its designated target type, the :exc:`.BadArgument` exception must be
raised.
Inline Advanced Converters
+++++++++++++++++++++++++++++
If we don't want to inherit from :class:`~ext.commands.Converter`, we can still provide a converter that has the
advanced functionalities of an advanced converter and save us from specifying two types.
For example, a common idiom would be to have a class and a converter for that class:
.. code-block:: python3
class JoinDistance:
def __init__(self, joined, created):
self.joined = joined
self.created = created
@property
def delta(self):
return self.joined - self.created
class JoinDistanceConverter(commands.MemberConverter):
async def convert(self, ctx, argument):
member = await super().convert(ctx, argument)
return JoinDistance(member.joined_at, member.created_at)
@bot.command()
async def delta(ctx, *, member: JoinDistanceConverter):
is_new = member.delta.days < 100
if is_new:
await ctx.send("Hey you're pretty new!")
else:
await ctx.send("Hm you're not so new.")
This can get tedious, so an inline advanced converter is possible through a :func:`classmethod` inside the type:
.. code-block:: python3
class JoinDistance:
def __init__(self, joined, created):
self.joined = joined
self.created = created
@classmethod
async def convert(cls, ctx, argument):
member = await commands.MemberConverter().convert(ctx, argument)
return cls(member.joined_at, member.created_at)
@property
def delta(self):
return self.joined - self.created
@bot.command()
async def delta(ctx, *, member: JoinDistance):
is_new = member.delta.days < 100
if is_new:
await ctx.send("Hey you're pretty new!")
else:
await ctx.send("Hm you're not so new.")
Discord Converters
++++++++++++++++++++
Working with :ref:`discord_api_models` is a fairly common thing when defining commands, as a result the library makes
working with them easy.
For example, to receive a :class:`Member` you can just pass it as a converter:
.. code-block:: python3
@bot.command()
async def joined(ctx, *, member: discord.Member):
await ctx.send(f'{member} joined on {member.joined_at}')
When this command is executed, it attempts to convert the string given into a :class:`Member` and then passes it as a
parameter for the function. This works by checking if the string is a mention, an ID, a nickname, a username + discriminator,
or just a regular username. The default set of converters have been written to be as easy to use as possible.
A lot of discord models work out of the gate as a parameter:
- :class:`Object` (since v2.0)
- :class:`Member`
- :class:`User`
- :class:`Message` (since v1.1)
- :class:`PartialMessage` (since v1.7)
- :class:`abc.GuildChannel` (since 2.0)
- :class:`TextChannel`
- :class:`VoiceChannel`
- :class:`StageChannel` (since v1.7)
- :class:`StoreChannel` (since v1.7)
- :class:`CategoryChannel`
- :class:`Invite`
- :class:`Guild` (since v1.7)
- :class:`Role`
- :class:`Game`
- :class:`Colour`
- :class:`Emoji`
- :class:`PartialEmoji`
- :class:`Thread` (since v2.0)
Having any of these set as the converter will intelligently convert the argument to the appropriate target type you
specify.
Under the hood, these are implemented by the :ref:`ext_commands_adv_converters` interface. A table of the equivalent
converter is given below:
+--------------------------+-------------------------------------------------+-----------------------------+
| Discord Class | Converter | Supported By Slash Commands |
+--------------------------+-------------------------------------------------+-----------------------------+
| :class:`Object` | :class:`~ext.commands.ObjectConverter` | Not currently |
+--------------------------+-------------------------------------------------+-----------------------------+
| :class:`Member` | :class:`~ext.commands.MemberConverter` | Yes, as type 6 (USER) |
+--------------------------+-------------------------------------------------+-----------------------------+
| :class:`User` | :class:`~ext.commands.UserConverter` | Yes, as type 6 (USER) |
+--------------------------+-------------------------------------------------+-----------------------------+
| :class:`Message` | :class:`~ext.commands.MessageConverter` | Not currently |
+--------------------------+-------------------------------------------------+-----------------------------+
| :class:`PartialMessage` | :class:`~ext.commands.PartialMessageConverter` | Not currently |
+--------------------------+-------------------------------------------------+-----------------------------+
| :class:`.GuildChannel` | :class:`~ext.commands.GuildChannelConverter` | Yes, as type 7 (CHANNEL) |
+--------------------------+-------------------------------------------------+-----------------------------+
| :class:`TextChannel` | :class:`~ext.commands.TextChannelConverter` | Yes, as type 7 (CHANNEL) |
+--------------------------+-------------------------------------------------+-----------------------------+
| :class:`VoiceChannel` | :class:`~ext.commands.VoiceChannelConverter` | Yes, as type 7 (CHANNEL) |
+--------------------------+-------------------------------------------------+-----------------------------+
| :class:`StageChannel` | :class:`~ext.commands.StageChannelConverter` | Yes, as type 7 (CHANNEL) |
+--------------------------+-------------------------------------------------+-----------------------------+
| :class:`StoreChannel` | :class:`~ext.commands.StoreChannelConverter` | Yes, as type 7 (CHANNEL) |
+--------------------------+-------------------------------------------------+-----------------------------+
| :class:`CategoryChannel` | :class:`~ext.commands.CategoryChannelConverter` | Yes, as type 7 (CHANNEL) |
+--------------------------+-------------------------------------------------+-----------------------------+
| :class:`Thread` | :class:`~ext.commands.ThreadConverter` | Yes, as type 7 (CHANNEL) |
+--------------------------+-------------------------------------------------+-----------------------------+
| :class:`Invite` | :class:`~ext.commands.InviteConverter` | Not currently |
+--------------------------+-------------------------------------------------+-----------------------------+
| :class:`Guild` | :class:`~ext.commands.GuildConverter` | Not currently |
+--------------------------+-------------------------------------------------+-----------------------------+
| :class:`Role` | :class:`~ext.commands.RoleConverter` | Yes, as type 8 (ROLE) |
+--------------------------+-------------------------------------------------+-----------------------------+
| :class:`Game` | :class:`~ext.commands.GameConverter` | Not currently |
+--------------------------+-------------------------------------------------+-----------------------------+
| :class:`Colour` | :class:`~ext.commands.ColourConverter` | Not currently |
+--------------------------+-------------------------------------------------+-----------------------------+
| :class:`Emoji` | :class:`~ext.commands.EmojiConverter` | Not currently |
+--------------------------+-------------------------------------------------+-----------------------------+
| :class:`PartialEmoji` | :class:`~ext.commands.PartialEmojiConverter` | Not currently |
+--------------------------+-------------------------------------------------+-----------------------------+
.. admonition:: Slash Command Only
If a slash command is not marked on the table above as supported, it will be sent as type 3 (STRING)
and parsed by normal content parsing, see
`the discord documentation <https://discord.com/developers/docs/interactions/application-commands#application-command-object-application-command-option-type>`_
for all supported types by the API.
By providing the converter it allows us to use them as building blocks for another converter:
.. code-block:: python3
class MemberRoles(commands.MemberConverter):
async def convert(self, ctx, argument):
member = await super().convert(ctx, argument)
return [role.name for role in member.roles[1:]] # Remove everyone role!
@bot.command()
async def roles(ctx, *, member: MemberRoles):
"""Tells you a member's roles."""
await ctx.send('I see the following roles: ' + ', '.join(member))
.. _ext_commands_special_converters:
Special Converters
++++++++++++++++++++
The command extension also has support for certain converters to allow for more advanced and intricate use cases that go
beyond the generic linear parsing. These converters allow you to introduce some more relaxed and dynamic grammar to your
commands in an easy to use manner.
typing.Union
^^^^^^^^^^^^^^
A :data:`typing.Union` is a special type hint that allows for the command to take in any of the specific types instead of
a singular type. For example, given the following:
.. code-block:: python3
import typing
@bot.command()
async def union(ctx, what: typing.Union[discord.TextChannel, discord.Member]):
await ctx.send(what)
The ``what`` parameter would either take a :class:`discord.TextChannel` converter or a :class:`discord.Member` converter.
The way this works is through a left-to-right order. It first attempts to convert the input to a
:class:`discord.TextChannel`, and if it fails it tries to convert it to a :class:`discord.Member`. If all converters fail,
then a special error is raised, :exc:`~ext.commands.BadUnionArgument`.
Note that any valid converter discussed above can be passed in to the argument list of a :data:`typing.Union`.
.. admonition:: Slash Command Only
These are not currently supported by the Discord API and will be sent as type 3 (STRING)
typing.Optional
^^^^^^^^^^^^^^^^^
A :data:`typing.Optional` is a special type hint that allows for "back-referencing" behaviour. If the converter fails to
parse into the specified type, the parser will skip the parameter and then either ``None`` or the specified default will be
passed into the parameter instead. The parser will then continue on to the next parameters and converters, if any.
Consider the following example:
.. code-block:: python3
import typing
@bot.command()
async def bottles(ctx, amount: typing.Optional[int] = 99, *, liquid="beer"):
await ctx.send(f'{amount} bottles of {liquid} on the wall!')
.. image:: /images/commands/optional1.png
In this example, since the argument could not be converted into an ``int``, the default of ``99`` is passed and the parser
resumes handling, which in this case would be to pass it into the ``liquid`` parameter.
.. note::
This converter only works in regular positional parameters, not variable parameters or keyword-only parameters.
typing.Literal
^^^^^^^^^^^^^^^^
A :data:`typing.Literal` is a special type hint that requires the passed parameter to be equal to one of the listed values
after being converted to the same type. For example, given the following:
.. code-block:: python3
from typing import Literal
@bot.command()
async def shop(ctx, buy_sell: Literal['buy', 'sell'], amount: Literal[1, 2], *, item: str):
await ctx.send(f'{buy_sell.capitalize()}ing {amount} {item}(s)!')
The ``buy_sell`` parameter must be either the literal string ``"buy"`` or ``"sell"`` and ``amount`` must convert to the
``int`` ``1`` or ``2``. If ``buy_sell`` or ``amount`` don't match any value, then a special error is raised,
:exc:`~.ext.commands.BadLiteralArgument`. Any literal values can be mixed and matched within the same :data:`typing.Literal` converter.
Note that ``typing.Literal[True]`` and ``typing.Literal[False]`` still follow the :class:`bool` converter rules.
Greedy
^^^^^^^^
The :class:`~ext.commands.Greedy` converter is a generalisation of the :data:`typing.Optional` converter, except applied
to a list of arguments. In simple terms, this means that it tries to convert as much as it can until it can't convert
any further.
Consider the following example:
.. code-block:: python3
@bot.command()
async def slap(ctx, members: commands.Greedy[discord.Member], *, reason='no reason'):
slapped = ", ".join(x.name for x in members)
await ctx.send(f'{slapped} just got slapped for {reason}')
When invoked, it allows for any number of members to be passed in:
.. image:: /images/commands/greedy1.png
The type passed when using this converter depends on the parameter type that it is being attached to:
- Positional parameter types will receive either the default parameter or a :class:`list` of the converted values.
- Variable parameter types will be a :class:`tuple` as usual.
- Keyword-only parameter types will be the same as if :class:`~ext.commands.Greedy` was not passed at all.
:class:`~ext.commands.Greedy` parameters can also be made optional by specifying an optional value.
When mixed with the :data:`typing.Optional` converter you can provide simple and expressive command invocation syntaxes:
.. code-block:: python3
import typing
@bot.command()
async def ban(ctx, members: commands.Greedy[discord.Member],
delete_days: typing.Optional[int] = 0, *,
reason: str):
"""Mass bans members with an optional delete_days parameter"""
for member in members:
await member.ban(delete_message_days=delete_days, reason=reason)
This command can be invoked any of the following ways:
.. code-block:: none
$ban @Member @Member2 spam bot
$ban @Member @Member2 7 spam bot
$ban @Member spam
.. warning::
The usage of :class:`~ext.commands.Greedy` and :data:`typing.Optional` are powerful and useful, however as a
price, they open you up to some parsing ambiguities that might surprise some people.
For example, a signature expecting a :data:`typing.Optional` of a :class:`discord.Member` followed by a
:class:`int` could catch a member named after a number due to the different ways a
:class:`~ext.commands.MemberConverter` decides to fetch members. You should take care to not introduce
unintended parsing ambiguities in your code. One technique would be to clamp down the expected syntaxes
allowed through custom converters or reordering the parameters to minimise clashes.
To help aid with some parsing ambiguities, :class:`str`, ``None``, :data:`typing.Optional` and
:class:`~ext.commands.Greedy` are forbidden as parameters for the :class:`~ext.commands.Greedy` converter.
.. _ext_commands_flag_converter:
FlagConverter
++++++++++++++
.. versionadded:: 2.0
A :class:`~ext.commands.FlagConverter` allows the user to specify user-friendly "flags" using :pep:`526` type annotations
or a syntax more reminiscent of the :mod:`py:dataclasses` module.
For example, the following code:
.. code-block:: python3
from discord.ext import commands
import discord
class BanFlags(commands.FlagConverter):
member: discord.Member
reason: str
days: int = 1
@commands.command()
async def ban(ctx, *, flags: BanFlags):
plural = f'{flags.days} days' if flags.days != 1 else f'{flags.days} day'
await ctx.send(f'Banned {flags.member} for {flags.reason!r} (deleted {plural} worth of messages)')
Allows the user to invoke the command using a simple flag-like syntax:
.. image:: /images/commands/flags1.png
Flags use a syntax that allows the user to not require quotes when passing in values to the flag. The goal of the
flag syntax is to be as user-friendly as possible. This makes flags a good choice for complicated commands that can have
multiple knobs to turn or simulating keyword-only parameters in your external command interface. **It is recommended to use
keyword-only parameters with the flag converter**. This ensures proper parsing and behaviour with quoting.
Internally, the :class:`~ext.commands.FlagConverter` class examines the class to find flags. A flag can either be a
class variable with a type annotation or a class variable that's been assigned the result of the :func:`~ext.commands.flag`
function. These flags are then used to define the interface that your users will use. The annotations correspond to
the converters that the flag arguments must adhere to.
For most use cases, no extra work is required to define flags. However, if customisation is needed to control the flag name
or the default value then the :func:`~ext.commands.flag` function can come in handy:
.. code-block:: python3
from typing import List
class BanFlags(commands.FlagConverter):
members: List[discord.Member] = commands.flag(name='member', default=lambda ctx: [])
This tells the parser that the ``members`` attribute is mapped to a flag named ``member`` and that
the default value is an empty list. For greater customisability, the default can either be a value or a callable
that takes the :class:`~ext.commands.Context` as a sole parameter. This callable can either be a function or a coroutine.
In order to customise the flag syntax we also have a few options that can be passed to the class parameter list:
.. code-block:: python3
# --hello world syntax
class PosixLikeFlags(commands.FlagConverter, delimiter=' ', prefix='--'):
hello: str
# /make food
class WindowsLikeFlags(commands.FlagConverter, prefix='/', delimiter=''):
make: str
# TOPIC: not allowed nsfw: yes Slowmode: 100
class Settings(commands.FlagConverter, case_insensitive=True):
topic: Optional[str]
nsfw: Optional[bool]
slowmode: Optional[int]
.. note::
Despite the similarities in these examples to command like arguments, the syntax and parser is not
a command line parser. The syntax is mainly inspired by Discord's search bar input and as a result
all flags need a corresponding value.
.. admonition:: Slash Command Only
As these are built very similar to slash command options, they are converted into options and parsed
back into flags when the slash command is executed.
The flag converter is similar to regular commands and allows you to use most types of converters
(with the exception of :class:`~ext.commands.Greedy`) as the type annotation. Some extra support is added for specific
annotations as described below.
typing.List
^^^^^^^^^^^^^
If a list is given as a flag annotation it tells the parser that the argument can be passed multiple times.
For example, augmenting the example above:
.. code-block:: python3
from discord.ext import commands
from typing import List
import discord
class BanFlags(commands.FlagConverter):
members: List[discord.Member] = commands.flag(name='member')
reason: str
days: int = 1
@commands.command()
async def ban(ctx, *, flags: BanFlags):
for member in flags.members:
await member.ban(reason=flags.reason, delete_message_days=flags.days)
members = ', '.join(str(member) for member in flags.members)
plural = f'{flags.days} days' if flags.days != 1 else f'{flags.days} day'
await ctx.send(f'Banned {members} for {flags.reason!r} (deleted {plural} worth of messages)')
This is called by repeatedly specifying the flag:
.. image:: /images/commands/flags2.png
typing.Tuple
^^^^^^^^^^^^^
Since the above syntax can be a bit repetitive when specifying a flag many times, the :class:`py:tuple` type annotation
allows for "greedy-like" semantics using a variadic tuple:
.. code-block:: python3
from discord.ext import commands
from typing import Tuple
import discord
class BanFlags(commands.FlagConverter):
members: Tuple[discord.Member, ...]
reason: str
days: int = 1
This allows the previous ``ban`` command to be called like this:
.. image:: /images/commands/flags3.png
The :class:`py:tuple` annotation also allows for parsing of pairs. For example, given the following code:
.. code-block:: python3
# point: 10 11 point: 12 13
class Coordinates(commands.FlagConverter):
point: Tuple[int, int]
.. warning::
Due to potential parsing ambiguities, the parser expects tuple arguments to be quoted
if they require spaces. So if one of the inner types is :class:`str` and the argument requires spaces
then quotes should be used to disambiguate it from the other element of the tuple.
typing.Dict
^^^^^^^^^^^^^
A :class:`dict` annotation is functionally equivalent to ``List[Tuple[K, V]]`` except with the return type
given as a :class:`dict` rather than a :class:`list`.
.. _ext_commands_error_handler:
Error Handling
----------------
When our commands fail to parse we will, by default, receive a noisy error in ``stderr`` of our console that tells us
that an error has happened and has been silently ignored.
In order to handle our errors, we must use something called an error handler. There is a global error handler, called
:func:`.on_command_error` which works like any other event in the :ref:`discord-api-events`. This global error handler is
called for every error reached.
Most of the time however, we want to handle an error local to the command itself. Luckily, commands come with local error
handlers that allow us to do just that. First we decorate an error handler function with :meth:`.Command.error`:
.. code-block:: python3
@bot.command()
async def info(ctx, *, member: discord.Member):
"""Tells you some info about the member."""
msg = f'{member} joined on {member.joined_at} and has {len(member.roles)} roles.'
await ctx.send(msg)
@info.error
async def info_error(ctx, error):
if isinstance(error, commands.BadArgument):
await ctx.send('I could not find that member...')
The first parameter of the error handler is the :class:`.Context` while the second one is an exception that is derived from
:exc:`~ext.commands.CommandError`. A list of errors is found in the :ref:`ext_commands_api_errors` page of the documentation.
Checks
-------
There are cases when we don't want a user to use our commands. They don't have permissions to do so or maybe we blocked
them from using our bot earlier. The commands extension comes with full support for these things in a concept called a
:ref:`ext_commands_api_checks`.
A check is a basic predicate that can take in a :class:`.Context` as its sole parameter. Within it, you have the following
options:
- Return ``True`` to signal that the person can run the command.
- Return ``False`` to signal that the person cannot run the command.
- Raise a :exc:`~ext.commands.CommandError` derived exception to signal the person cannot run the command.
- This allows you to have custom error messages for you to handle in the
:ref:`error handlers <ext_commands_error_handler>`.
To register a check for a command, we would have two ways of doing so. The first is using the :meth:`~ext.commands.check`
decorator. For example:
.. code-block:: python3
async def is_owner(ctx):
return ctx.author.id == 316026178463072268
@bot.command(name='eval')
@commands.check(is_owner)
async def _eval(ctx, *, code):
"""A bad example of an eval command"""
await ctx.send(eval(code))
This would only evaluate the command if the function ``is_owner`` returns ``True``. Sometimes we re-use a check often and
want to split it into its own decorator. To do that we can just add another level of depth:
.. code-block:: python3
def is_owner():
async def predicate(ctx):
return ctx.author.id == 316026178463072268
return commands.check(predicate)
@bot.command(name='eval')
@is_owner()
async def _eval(ctx, *, code):
"""A bad example of an eval command"""
await ctx.send(eval(code))
Since an owner check is so common, the library provides it for you (:func:`~ext.commands.is_owner`):
.. code-block:: python3
@bot.command(name='eval')
@commands.is_owner()
async def _eval(ctx, *, code):
"""A bad example of an eval command"""
await ctx.send(eval(code))
When multiple checks are specified, **all** of them must be ``True``:
.. code-block:: python3
def is_in_guild(guild_id):
async def predicate(ctx):
return ctx.guild and ctx.guild.id == guild_id
return commands.check(predicate)
@bot.command()
@commands.is_owner()
@is_in_guild(41771983423143937)
async def secretguilddata(ctx):
"""super secret stuff"""
await ctx.send('secret stuff')
If any of those checks fail in the example above, then the command will not be run.
When an error happens, the error is propagated to the :ref:`error handlers <ext_commands_error_handler>`. If you do not
raise a custom :exc:`~ext.commands.CommandError` derived exception, then it will get wrapped up into a
:exc:`~ext.commands.CheckFailure` exception as so:
.. code-block:: python3
@bot.command()
@commands.is_owner()
@is_in_guild(41771983423143937)
async def secretguilddata(ctx):
"""super secret stuff"""
await ctx.send('secret stuff')
@secretguilddata.error
async def secretguilddata_error(ctx, error):
if isinstance(error, commands.CheckFailure):
await ctx.send('nothing to see here comrade.')
If you want a more robust error system, you can derive from the exception and raise it instead of returning ``False``:
.. code-block:: python3
class NoPrivateMessages(commands.CheckFailure):
pass
def guild_only():
async def predicate(ctx):
if ctx.guild is None:
raise NoPrivateMessages('Hey no DMs!')
return True
return commands.check(predicate)
@guild_only()
async def test(ctx):
await ctx.send('Hey this is not a DM! Nice.')
@test.error
async def test_error(ctx, error):
if isinstance(error, NoPrivateMessages):
await ctx.send(error)
.. note::
Since having a ``guild_only`` decorator is pretty common, it comes built-in via :func:`~ext.commands.guild_only`.
Global Checks
++++++++++++++
Sometimes we want to apply a check to **every** command, not just certain commands. The library supports this as well
using the global check concept.
Global checks work similarly to regular checks except they are registered with the :meth:`.Bot.check` decorator.
For example, to block all DMs we could do the following:
.. code-block:: python3
@bot.check
async def globally_block_dms(ctx):
return ctx.guild is not None
.. warning::
Be careful on how you write your global checks, as it could also lock you out of your own bot.
.. need a note on global check once here I think

View File

@ -0,0 +1,64 @@
.. currentmodule:: discord
.. _ext_commands_extensions:
Extensions
=============
There comes a time in the bot development when you want to extend the bot functionality at run-time and quickly unload and reload code (also called hot-reloading). The command framework comes with this ability built-in, with a concept called **extensions**.
Primer
--------
An extension at its core is a python file with an entry point called ``setup``. This setup must be a plain Python function (not a coroutine). It takes a single parameter -- the :class:`~.commands.Bot` that loads the extension.
An example extension looks like this:
.. code-block:: python3
:caption: hello.py
:emphasize-lines: 7,8
from discord.ext import commands
@commands.command()
async def hello(ctx):
await ctx.send(f'Hello {ctx.author.display_name}.')
def setup(bot):
bot.add_command(hello)
In this example we define a simple command, and when the extension is loaded this command is added to the bot. Now the final step to this is loading the extension, which we do by calling :meth:`.Bot.load_extension`. To load this extension we call ``bot.load_extension('hello')``.
.. admonition:: Cogs
:class: helpful
Extensions are usually used in conjunction with cogs. To read more about them, check out the documentation, :ref:`ext_commands_cogs`.
.. note::
Extension paths are ultimately similar to the import mechanism. What this means is that if there is a folder, then it must be dot-qualified. For example to load an extension in ``plugins/hello.py`` then we use the string ``plugins.hello``.
Reloading
-----------
When you make a change to the extension and want to reload the references, the library comes with a function to do this for you, :meth:`.Bot.reload_extension`.
.. code-block:: python3
>>> bot.reload_extension('hello')
Once the extension reloads, any changes that we did will be applied. This is useful if we want to add or remove functionality without restarting our bot. If an error occurred during the reloading process, the bot will pretend as if the reload never happened.
Cleaning Up
-------------
Although rare, sometimes an extension needs to clean-up or know when it's being unloaded. For cases like these, there is another entry point named ``teardown`` which is similar to ``setup`` except called when the extension is unloaded.
.. code-block:: python3
:caption: basic_ext.py
def setup(bot):
print('I am being loaded!')
def teardown(bot):
print('I am being unloaded!')

View File

@ -0,0 +1,19 @@
.. _discord_ext_commands:
``discord.ext.commands`` -- Bot commands framework
====================================================
``discord.py`` offers a lower level aspect on interacting with Discord. Often times, the library is used for the creation of
bots. However this task can be daunting and confusing to get correctly the first time. Many times there comes a repetition in
creating a bot command framework that is extensible, flexible, and powerful. For this reason, ``discord.py`` comes with an
extension library that handles this for you.
.. toctree::
:maxdepth: 2
commands
cogs
extensions
slash-commands
api

View File

@ -0,0 +1,23 @@
.. currentmodule:: discord
.. _ext_commands_slash_commands:
Slash Commands
==============
Slash Commands are currently supported in enhanced-discord.py using a system on top of ext.commands.
This system is very simple to use, and can be enabled via :attr:`.Bot.slash_commands` globally,
or only for specific commands via :attr:`.Command.slash_command`.
There is also the parameter ``slash_command_guilds`` which can be passed to either :class:`.Bot` or the command
decorator in order to only upload the commands as guild commands to these specific guild IDs, however this
should only be used for testing or small (<10 guilds) bots.
If you want to add option descriptions to your commands, you should use :class:`.Option`
For troubleshooting, see the :ref:`FAQ <ext_commands_slash_command_troubleshooting>`
.. admonition:: Slash Command Only
For parts of the docs specific to slash commands, look for this box!

View File

@ -0,0 +1,154 @@
.. _discord_ext_tasks:
``discord.ext.tasks`` -- asyncio.Task helpers
====================================================
.. versionadded:: 1.1.0
One of the most common operations when making a bot is having a loop run in the background at a specified interval. This pattern is very common but has a lot of things you need to look out for:
- How do I handle :exc:`asyncio.CancelledError`?
- What do I do if the internet goes out?
- What is the maximum number of seconds I can sleep anyway?
The goal of this discord.py extension is to abstract all these worries away from you.
Recipes
---------
A simple background task in a :class:`~discord.ext.commands.Cog`:
.. code-block:: python3
from discord.ext import tasks, commands
class MyCog(commands.Cog):
def __init__(self):
self.index = 0
self.printer.start()
def cog_unload(self):
self.printer.cancel()
@tasks.loop(seconds=5.0)
async def printer(self):
print(self.index)
self.index += 1
Adding an exception to handle during reconnect:
.. code-block:: python3
import asyncpg
from discord.ext import tasks, commands
class MyCog(commands.Cog):
def __init__(self, bot):
self.bot = bot
self.data = []
self.batch_update.add_exception_type(asyncpg.PostgresConnectionError)
self.batch_update.start()
def cog_unload(self):
self.batch_update.cancel()
@tasks.loop(minutes=5.0)
async def batch_update(self):
async with self.bot.pool.acquire() as con:
# batch update here...
pass
Looping a certain amount of times before exiting:
.. code-block:: python3
from discord.ext import tasks
@tasks.loop(seconds=5.0, count=5)
async def slow_count():
print(slow_count.current_loop)
@slow_count.after_loop
async def after_slow_count():
print('done!')
slow_count.start()
Waiting until the bot is ready before the loop starts:
.. code-block:: python3
from discord.ext import tasks, commands
class MyCog(commands.Cog):
def __init__(self, bot):
self.index = 0
self.bot = bot
self.printer.start()
def cog_unload(self):
self.printer.cancel()
@tasks.loop(seconds=5.0)
async def printer(self):
print(self.index)
self.index += 1
@printer.before_loop
async def before_printer(self):
print('waiting...')
await self.bot.wait_until_ready()
Doing something during cancellation:
.. code-block:: python3
from discord.ext import tasks, commands
import asyncio
class MyCog(commands.Cog):
def __init__(self, bot):
self.bot= bot
self._batch = []
self.lock = asyncio.Lock()
self.bulker.start()
async def do_bulk(self):
# bulk insert data here
...
@tasks.loop(seconds=10.0)
async def bulker(self):
async with self.lock:
await self.do_bulk()
@bulker.after_loop
async def on_bulker_cancel(self):
if self.bulker.is_being_cancelled() and len(self._batch) != 0:
# if we're cancelled and we have some data left...
# let's insert it to our database
await self.do_bulk()
.. _ext_tasks_api:
API Reference
---------------
.. attributetable:: discord.ext.tasks.Loop
.. autoclass:: discord.ext.tasks.Loop()
:members:
:special-members: __call__
:exclude-members: after_loop, before_loop, error
.. automethod:: Loop.after_loop()
:decorator:
.. automethod:: Loop.before_loop()
:decorator:
.. automethod:: Loop.error()
:decorator:
.. autofunction:: discord.ext.tasks.loop

View File

@ -0,0 +1,443 @@
:orphan:
.. currentmodule:: discord
.. _faq:
Frequently Asked Questions
===========================
This is a list of Frequently Asked Questions regarding using ``discord.py`` and its extension modules. Feel free to suggest a
new question or submit one via pull requests.
.. contents:: Questions
:local:
Coroutines
------------
Questions regarding coroutines and asyncio belong here.
What is a coroutine?
~~~~~~~~~~~~~~~~~~~~~~
A |coroutine_link|_ is a function that must be invoked with ``await`` or ``yield from``. When Python encounters an ``await`` it stops
the function's execution at that point and works on other things until it comes back to that point and finishes off its work.
This allows for your program to be doing multiple things at the same time without using threads or complicated
multiprocessing.
**If you forget to await a coroutine then the coroutine will not run. Never forget to await a coroutine.**
Where can I use ``await``\?
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
You can only use ``await`` inside ``async def`` functions and nowhere else.
What does "blocking" mean?
~~~~~~~~~~~~~~~~~~~~~~~~~~~
In asynchronous programming a blocking call is essentially all the parts of the function that are not ``await``. Do not
despair however, because not all forms of blocking are bad! Using blocking calls is inevitable, but you must work to make
sure that you don't excessively block functions. Remember, if you block for too long then your bot will freeze since it has
not stopped the function's execution at that point to do other things.
If logging is enabled, this library will attempt to warn you that blocking is occurring with the message:
``Heartbeat blocked for more than N seconds.``
See :ref:`logging_setup` for details on enabling logging.
A common source of blocking for too long is something like :func:`time.sleep`. Don't do that. Use :func:`asyncio.sleep`
instead. Similar to this example: ::
# bad
time.sleep(10)
# good
await asyncio.sleep(10)
Another common source of blocking for too long is using HTTP requests with the famous module :doc:`req:index`.
While :doc:`req:index` is an amazing module for non-asynchronous programming, it is not a good choice for
:mod:`asyncio` because certain requests can block the event loop too long. Instead, use the :doc:`aiohttp <aio:index>` library which
is installed on the side with this library.
Consider the following example: ::
# bad
r = requests.get('http://aws.random.cat/meow')
if r.status_code == 200:
js = r.json()
await channel.send(js['file'])
# good
async with aiohttp.ClientSession() as session:
async with session.get('http://aws.random.cat/meow') as r:
if r.status == 200:
js = await r.json()
await channel.send(js['file'])
General
---------
General questions regarding library usage belong here.
Where can I find usage examples?
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Example code can be found in the `examples folder <https://github.com/Rapptz/discord.py/tree/master/examples>`_
in the repository.
How do I set the "Playing" status?
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The ``activity`` keyword argument may be passed in the :class:`Client` constructor or :meth:`Client.change_presence`, given an :class:`Activity` object.
The constructor may be used for static activities, while :meth:`Client.change_presence` may be used to update the activity at runtime.
.. warning::
It is highly discouraged to use :meth:`Client.change_presence` or API calls in :func:`on_ready` as this event may be called many times while running, not just once.
There is a high chance of disconnecting if presences are changed right after connecting.
The status type (playing, listening, streaming, watching) can be set using the :class:`ActivityType` enum.
For memory optimisation purposes, some activities are offered in slimmed-down versions:
- :class:`Game`
- :class:`Streaming`
Putting both of these pieces of info together, you get the following: ::
client = discord.Client(activity=discord.Game(name='my game'))
# or, for watching:
activity = discord.Activity(name='my activity', type=discord.ActivityType.watching)
client = discord.Client(activity=activity)
How do I send a message to a specific channel?
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
You must fetch the channel directly and then call the appropriate method. Example: ::
channel = client.get_channel(12324234183172)
await channel.send('hello')
How do I send a DM?
~~~~~~~~~~~~~~~~~~~
Get the :class:`User` or :class:`Member` object and call :meth:`abc.Messageable.send`. For example: ::
user = client.get_user(381870129706958858)
await user.send('👀')
If you are responding to an event, such as :func:`on_message`, you already have the :class:`User` object via :attr:`Message.author`: ::
await message.author.send('👋')
How do I get the ID of a sent message?
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
:meth:`abc.Messageable.send` returns the :class:`Message` that was sent.
The ID of a message can be accessed via :attr:`Message.id`: ::
message = await channel.send('hmm…')
message_id = message.id
How do I upload an image?
~~~~~~~~~~~~~~~~~~~~~~~~~
To upload something to Discord you have to use the :class:`File` object.
A :class:`File` accepts two parameters, the file-like object (or file path) and the filename
to pass to Discord when uploading.
If you want to upload an image it's as simple as: ::
await channel.send(file=discord.File('my_file.png'))
If you have a file-like object you can do as follows: ::
with open('my_file.png', 'rb') as fp:
await channel.send(file=discord.File(fp, 'new_filename.png'))
To upload multiple files, you can use the ``files`` keyword argument instead of ``file``\: ::
my_files = [
discord.File('result.zip'),
discord.File('teaser_graph.png'),
]
await channel.send(files=my_files)
If you want to upload something from a URL, you will have to use an HTTP request using :doc:`aiohttp <aio:index>`
and then pass an :class:`io.BytesIO` instance to :class:`File` like so:
.. code-block:: python3
import io
import aiohttp
async with aiohttp.ClientSession() as session:
async with session.get(my_url) as resp:
if resp.status != 200:
return await channel.send('Could not download file...')
data = io.BytesIO(await resp.read())
await channel.send(file=discord.File(data, 'cool_image.png'))
How can I add a reaction to a message?
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
You use the :meth:`Message.add_reaction` method.
If you want to use unicode emoji, you must pass a valid unicode code point in a string. In your code, you can write this in a few different ways:
- ``'👍'``
- ``'\U0001F44D'``
- ``'\N{THUMBS UP SIGN}'``
Quick example: ::
emoji = '\N{THUMBS UP SIGN}'
# or '\U0001f44d' or '👍'
await message.add_reaction(emoji)
In case you want to use emoji that come from a message, you already get their code points in the content without needing
to do anything special. You **cannot** send ``':thumbsup:'`` style shorthands.
For custom emoji, you should pass an instance of :class:`Emoji`. You can also pass a ``'<:name:id>'`` string, but if you
can use said emoji, you should be able to use :meth:`Client.get_emoji` to get an emoji via ID or use :func:`utils.find`/
:func:`utils.get` on :attr:`Client.emojis` or :attr:`Guild.emojis` collections.
The name and ID of a custom emoji can be found with the client by prefixing ``:custom_emoji:`` with a backslash.
For example, sending the message ``\:python3:`` with the client will result in ``<:python3:232720527448342530>``.
Quick example: ::
# if you have the ID already
emoji = client.get_emoji(310177266011340803)
await message.add_reaction(emoji)
# no ID, do a lookup
emoji = discord.utils.get(guild.emojis, name='LUL')
if emoji:
await message.add_reaction(emoji)
# if you have the name and ID of a custom emoji:
emoji = '<:python3:232720527448342530>'
await message.add_reaction(emoji)
How do I pass a coroutine to the player's "after" function?
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The library's music player launches on a separate thread, ergo it does not execute inside a coroutine.
This does not mean that it is not possible to call a coroutine in the ``after`` parameter. To do so you must pass a callable
that wraps up a couple of aspects.
The first gotcha that you must be aware of is that calling a coroutine is not a thread-safe operation. Since we are
technically in another thread, we must take caution in calling thread-safe operations so things do not bug out. Luckily for
us, :mod:`asyncio` comes with a :func:`asyncio.run_coroutine_threadsafe` function that allows us to call
a coroutine from another thread.
However, this function returns a :class:`~concurrent.futures.Future` and to actually call it we have to fetch its result. Putting all of
this together we can do the following: ::
def my_after(error):
coro = some_channel.send('Song is done!')
fut = asyncio.run_coroutine_threadsafe(coro, client.loop)
try:
fut.result()
except:
# an error happened sending the message
pass
voice.play(discord.FFmpegPCMAudio(url), after=my_after)
How do I run something in the background?
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
`Check the background_task.py example. <https://github.com/Rapptz/discord.py/blob/master/examples/background_task.py>`_
How do I get a specific model?
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
There are multiple ways of doing this. If you have a specific model's ID then you can use
one of the following functions:
- :meth:`Client.get_channel`
- :meth:`Client.get_guild`
- :meth:`Client.get_user`
- :meth:`Client.get_emoji`
- :meth:`Guild.get_member`
- :meth:`Guild.get_channel`
- :meth:`Guild.get_role`
The following use an HTTP request:
- :meth:`abc.Messageable.fetch_message`
- :meth:`Client.fetch_user`
- :meth:`Client.fetch_guilds`
- :meth:`Client.fetch_guild`
- :meth:`Guild.fetch_emoji`
- :meth:`Guild.fetch_emojis`
- :meth:`Guild.fetch_member`
If the functions above do not help you, then use of :func:`utils.find` or :func:`utils.get` would serve some use in finding
specific models.
Quick example: ::
# find a guild by name
guild = discord.utils.get(client.guilds, name='My Server')
# make sure to check if it's found
if guild is not None:
# find a channel by name
channel = discord.utils.get(guild.text_channels, name='cool-channel')
How do I make a web request?
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
To make a request, you should use a non-blocking library.
This library already uses and requires a 3rd party library for making requests, :doc:`aiohttp <aio:index>`.
Quick example: ::
async with aiohttp.ClientSession() as session:
async with session.get('http://aws.random.cat/meow') as r:
if r.status == 200:
js = await r.json()
See `aiohttp's full documentation <http://aiohttp.readthedocs.io/en/stable/>`_ for more information.
How do I use a local image file for an embed image?
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Discord special-cases uploading an image attachment and using it within an embed so that it will not
display separately, but instead in the embed's thumbnail, image, footer or author icon.
To do so, upload the image normally with :meth:`abc.Messageable.send`,
and set the embed's image URL to ``attachment://image.png``,
where ``image.png`` is the filename of the image you will send.
Quick example: ::
file = discord.File("path/to/my/image.png", filename="image.png")
embed = discord.Embed()
embed.set_image(url="attachment://image.png")
await channel.send(file=file, embed=embed)
.. note ::
Due to a Discord limitation, filenames may not include underscores.
Is there an event for audit log entries being created?
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Since Discord does not dispatch this information in the gateway, the library cannot provide this information.
This is currently a Discord limitation.
Commands Extension
-------------------
Questions regarding ``discord.ext.commands`` belong here.
Why does ``on_message`` make my commands stop working?
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Overriding the default provided ``on_message`` forbids any extra commands from running. To fix this, add a
``bot.process_commands(message)`` line at the end of your ``on_message``. For example: ::
@bot.event
async def on_message(message):
# do some extra stuff here
await bot.process_commands(message)
Alternatively, you can place your ``on_message`` logic into a **listener**. In this setup, you should not
manually call ``bot.process_commands()``. This also allows you to do multiple things asynchronously in response
to a message. Example::
@bot.listen('on_message')
async def whatever_you_want_to_call_it(message):
# do stuff here
# do not process commands here
Why do my arguments require quotes?
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
In a simple command defined as: ::
@bot.command()
async def echo(ctx, message: str):
await ctx.send(message)
Calling it via ``?echo a b c`` will only fetch the first argument and disregard the rest. To fix this you should either call
it via ``?echo "a b c"`` or change the signature to have "consume rest" behaviour. Example: ::
@bot.command()
async def echo(ctx, *, message: str):
await ctx.send(message)
This will allow you to use ``?echo a b c`` without needing the quotes.
How do I get the original ``message``\?
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The :class:`~ext.commands.Context` contains an attribute, :attr:`~.Context.message` to get the original
message.
Example: ::
@bot.command()
async def length(ctx):
await ctx.send(f'Your message is {len(ctx.message.content)} characters long.')
How do I make a subcommand?
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Use the :func:`~ext.commands.group` decorator. This will transform the callback into a :class:`~ext.commands.Group` which will allow you to add commands into
the group operating as "subcommands". These groups can be arbitrarily nested as well.
Example: ::
@bot.group()
async def git(ctx):
if ctx.invoked_subcommand is None:
await ctx.send('Invalid git command passed...')
@git.command()
async def push(ctx, remote: str, branch: str):
await ctx.send(f'Pushing to {remote} {branch}')
This could then be used as ``?git push origin master``.
How do I make slash commands?
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
See :doc:`/ext/commands/slash-commands`
My slash commands aren't showing up!
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
.. _ext_commands_slash_command_troubleshooting:
You need to invite your bot with the ``application.commands`` scope on each guild and
you need the :attr:`Permissions.use_slash_commands` permission in order to see slash commands.
.. image:: /images/discord_oauth2_slash_scope.png
:alt: The scopes checkbox with "bot" and "applications.commands" ticked.
Global slash commands (created by not specifying :attr:`~ext.commands.Bot.slash_command_guilds`) will also take up an
hour to refresh on discord's end, so it is recommended to set :attr:`~ext.commands.Bot.slash_command_guilds` for development.
If none of this works, make sure you are actually running enhanced-discord.py by doing ``print(bot.slash_commands)``
My bot won't start after enabling slash commands!
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
This means some of your command metadata is invalid for slash commands.
Make sure your command names and option names are lowercase, and they have to match the regex ``^[\w-]{1,32}$``
If you cannot figure out the problem, you should disable slash commands globally (:attr:`~ext.commands.Bot.slash_commands`\=False)
then go through commands, enabling them specifically with :attr:`~.commands.Command.slash_command`\=True until it
errors, then you can debug the problem with that command specifically.

View File

@ -0,0 +1,76 @@
.. discord.py documentation master file, created by
sphinx-quickstart on Fri Aug 21 05:43:30 2015.
You can adapt this file completely to your liking, but it should at least
contain the root `toctree` directive.
Welcome to discord.py
===========================
.. image:: /images/snake.svg
.. image:: /images/snake_dark.svg
discord.py is a modern, easy to use, feature-rich, and async ready API wrapper
for Discord.
**Features:**
- Modern Pythonic API using ``async``\/``await`` syntax
- Sane rate limit handling that prevents 429s
- Command extension to aid with bot creation
- Easy to use with an object oriented design
- Optimised for both speed and memory
Getting started
-----------------
Is this your first time using the library? This is the place to get started!
- **First steps:** :doc:`intro` | :doc:`quickstart` | :doc:`logging`
- **Working with Discord:** :doc:`discord` | :doc:`intents`
- **Examples:** Many examples are available in the :resource:`repository <examples>`.
Getting help
--------------
If you're having trouble with something, these resources might help.
- Try the :doc:`faq` first, it's got answers to all common questions.
- Ask us and hang out with us in our :resource:`Discord <discord>` server.
- If you're looking for something specific, try the :ref:`index <genindex>` or :ref:`searching <search>`.
- Report bugs in the :resource:`issue tracker <issues>`.
- Ask in our :resource:`GitHub discussions page <discussions>`.
Extensions
------------
These extensions help you during development when it comes to common tasks.
.. toctree::
:maxdepth: 1
ext/commands/index.rst
ext/tasks/index.rst
Manuals
---------
These pages go into great detail about everything the API can do.
.. toctree::
:maxdepth: 1
api
discord.ext.commands API Reference <ext/commands/api.rst>
discord.ext.tasks API Reference <ext/tasks/index.rst>
Meta
------
If you're looking for something related to the project itself, it's here.
.. toctree::
:maxdepth: 1
whats_new
version_guarantees
migrating

View File

@ -0,0 +1,192 @@
:orphan:
.. currentmodule:: discord
.. versionadded:: 1.5
.. _intents_primer:
A Primer to Gateway Intents
=============================
In version 1.5 comes the introduction of :class:`Intents`. 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 :class:`Intents` documentation.
These intents are passed to the constructor of :class:`Client` or its subclasses (:class:`AutoShardedClient`, :class:`~.AutoShardedBot`, :class:`~.Bot`) with the ``intents`` argument.
If intents are not passed, then the library defaults to every intent being enabled except the privileged intents, currently :attr:`Intents.members` and :attr:`Intents.presences`.
What intents are needed?
--------------------------
The intents that are necessary for your bot can only be dictated by yourself. Each attribute in the :class:`Intents` class documents what :ref:`events <discord-api-events>` it corresponds to and what kind of cache it enables.
For example, if you want a bot that functions without spammy events like presences or typing then we could do the following:
.. code-block:: python3
:emphasize-lines: 7,9,10
import discord
intents = discord.Intents.default()
intents.typing = False
intents.presences = False
# Somewhere else:
# client = discord.Client(intents=intents)
# or
# from discord.ext import commands
# bot = commands.Bot(command_prefix='!', intents=intents)
Note that this doesn't enable :attr:`Intents.members` since it's a privileged intent.
Another example showing a bot that only deals with messages and guild information:
.. code-block:: python3
:emphasize-lines: 7,9,10
import discord
intents = discord.Intents(messages=True, guilds=True)
# If you also want reaction events enable the following:
# intents.reactions = True
# Somewhere else:
# client = discord.Client(intents=intents)
# or
# from discord.ext import commands
# bot = commands.Bot(command_prefix='!', intents=intents)
.. _privileged_intents:
Privileged Intents
---------------------
With the API change requiring bot authors to specify intents, some intents were restricted further and require more manual steps. These intents are called **privileged intents**.
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:
1. Make sure you're logged on to the `Discord website <https://discord.com>`_.
2. Navigate to the `application page <https://discord.com/developers/applications>`_.
3. Click on the bot you want to enable privileged intents for.
4. Navigate to the bot tab on the left side of the screen.
.. image:: /images/discord_bot_tab.png
:alt: The bot tab in the application page.
5. Scroll down to the "Privileged Gateway Intents" section and enable the ones you want.
.. image:: /images/discord_privileged_intents.png
:alt: The privileged gateway intents selector.
.. warning::
Enabling privileged intents when your bot is in over 100 guilds requires going through `bot verification <https://support.discord.com/hc/en-us/articles/360040720412>`_. If your bot is already verified and you would like to enable a privileged intent you must go through `Discord support <https://dis.gd/contact>`_ and talk to them about it.
.. note::
Even if you enable intents through the developer portal, you still have to enable the intents
through code as well.
Do I need privileged intents?
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
This is a quick checklist to see if you need specific privileged intents.
.. _need_presence_intent:
Presence Intent
+++++++++++++++++
- Whether you use :attr:`Member.status` at all to track member statuses.
- Whether you use :attr:`Member.activity` or :attr:`Member.activities` to check member's activities.
.. _need_members_intent:
Member Intent
+++++++++++++++
- Whether you track member joins or member leaves, corresponds to :func:`on_member_join` and :func:`on_member_remove` events.
- Whether you want to track member updates such as nickname or role changes.
- Whether you want to track user updates such as usernames, avatars, discriminators, etc.
- Whether you want to request the guild member list through :meth:`Guild.chunk` or :meth:`Guild.fetch_members`.
- Whether you want high accuracy member cache under :attr:`Guild.members`.
.. _intents_member_cache:
Member Cache
-------------
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 :attr:`Intents.members` intent is required in order to track the members who left and properly evict them.
To aid with member cache where we don't need members to be cached, the library now has a :class:`MemberCacheFlags` flag to control the member cache. The documentation page for the class goes over the specific policies that are possible.
It should be noted that certain things do not need a member cache since Discord will provide full member information if possible. For example:
- :func:`on_message` will have :attr:`Message.author` be a member even if cache is disabled.
- :func:`on_voice_state_update` will have the ``member`` parameter be a member even if cache is disabled.
- :func:`on_reaction_add` will have the ``user`` parameter be a member when in a guild even if cache is disabled.
- :func:`on_raw_reaction_add` will have :attr:`RawReactionActionEvent.member` be a member when in a guild even if cache is disabled.
- The reaction add events do not contain additional information when in direct messages. This is a Discord limitation.
- The reaction removal events do not have member information. This is a Discord limitation.
Other events that take a :class:`Member` will require the use of the member cache. If absolute accuracy over the member cache is desirable, then it is advisable to have the :attr:`Intents.members` intent enabled.
.. _retrieving_members:
Retrieving Members
--------------------
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:
- :meth:`Guild.query_members`
- Used to query members by a prefix matching nickname or username.
- This can also be used to query members by their user ID.
- This uses the gateway and not the HTTP.
- :meth:`Guild.chunk`
- This can be used to fetch the entire member list through the gateway.
- :meth:`Guild.fetch_member`
- Used to fetch a member by ID through the HTTP API.
- :meth:`Guild.fetch_members`
- used to fetch a large number of members through the HTTP API.
It should be noted that the gateway has a strict rate limit of 120 requests per 60 seconds.
Troubleshooting
------------------
Some common issues relating to the mandatory intent change.
Where'd my members go?
~~~~~~~~~~~~~~~~~~~~~~~~
Due to an :ref:`API change <intents_member_cache>` 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 :ref:`members privileged intent <privileged_intents>` and change the :attr:`Intents.members` attribute to true.
For example:
.. code-block:: python3
:emphasize-lines: 3,6,8,9
import discord
intents = discord.Intents.default()
intents.members = True
# Somewhere else:
# client = discord.Client(intents=intents)
# or
# from discord.ext import commands
# bot = commands.Bot(command_prefix='!', intents=intents)
Why does ``on_ready`` take so long to fire?
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
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 :attr:`Guild.large` attribute set to ``True``. 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 *all* guilds, not just large guilds are being requested.
There are a few solutions to fix this.
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 we're still limited to 1 guild per request but the number of guilds we request is significantly reduced.
The second solution is to disable member chunking by setting ``chunk_guilds_at_startup`` to ``False`` when constructing a client. Then, when chunking for a guild is necessary you can use the various techniques to :ref:`retrieve members <retrieving_members>`.
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).
Under the original system this would result in 2 requests to fetch the member list (75 guilds, 20 guilds) roughly taking 60 seconds. With :attr:`Intents.members` but not :attr:`Intents.presences` 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 :attr:`Intents.members` and :attr:`Intents.presences` we mostly get the old behaviour so we're only required to request for the 95 guilds that are large, this is slightly less than our rate limit so it's close to the original timing to fetch the member list.
Unfortunately due to this change being required from Discord there is nothing that the library can do to mitigate this.
If you truly dislike the direction Discord is going with their API, you can contact them via `support <https://dis.gd/contact>`_.

View File

@ -0,0 +1,113 @@
:orphan:
.. currentmodule:: discord
.. _intro:
Introduction
==============
This is the documentation for discord.py, a library for Python to aid
in creating applications that utilise the Discord API.
Prerequisites
---------------
discord.py works with Python 3.8 or higher. Support for earlier versions of Python
is not provided. Python 2.7 or lower is not supported. Python 3.7 or lower is not supported.
.. _installing:
Installing
-----------
You can get the library directly from PyPI: ::
python3 -m pip install -U discord.py
If you are using Windows, then the following should be used instead: ::
py -3 -m pip install -U discord.py
To get voice support, you should use ``discord.py[voice]`` instead of ``discord.py``, e.g. ::
python3 -m pip install -U discord.py[voice]
On Linux environments, installing voice requires getting the following dependencies:
- `libffi <https://github.com/libffi/libffi>`_
- `libnacl <https://github.com/saltstack/libnacl>`_
- `python3-dev <https://packages.debian.org/python3-dev>`_
For a Debian-based system, the following command will get these dependencies:
.. code-block:: shell
$ apt install libffi-dev libnacl-dev python3-dev
Remember to check your permissions!
Virtual Environments
~~~~~~~~~~~~~~~~~~~~~
Sometimes you want to keep libraries from polluting system installs or use a different version of
libraries than the ones installed on the system. You might also not have permissions to install libraries system-wide.
For this purpose, the standard library as of Python 3.3 comes with a concept called "Virtual Environment"s to
help maintain these separate versions.
A more in-depth tutorial is found on :doc:`py:tutorial/venv`.
However, for the quick and dirty:
1. Go to your project's working directory:
.. code-block:: shell
$ cd your-bot-source
$ python3 -m venv bot-env
2. Activate the virtual environment:
.. code-block:: shell
$ source bot-env/bin/activate
On Windows you activate it with:
.. code-block:: shell
$ bot-env\Scripts\activate.bat
3. Use pip like usual:
.. code-block:: shell
$ pip install -U discord.py
Congratulations. You now have a virtual environment all set up.
Basic Concepts
---------------
discord.py revolves around the concept of :ref:`events <discord-api-events>`.
An event is something you listen to and then respond to. For example, when a message
happens, you will receive an event about it that you can respond to.
A quick example to showcase how events work:
.. code-block:: python3
import discord
class MyClient(discord.Client):
async def on_ready(self):
print(f'Logged on as {self.user}!')
async def on_message(self, message):
print(f'Message from {messsage.author}: {message.content}')
client = MyClient()
client.run('my token goes here')

View File

@ -0,0 +1,46 @@
:orphan:
.. versionadded:: 0.6.0
.. _logging_setup:
Setting Up Logging
===================
*discord.py* logs errors and debug information via the :mod:`logging` python
module. It is strongly recommended that the logging module is
configured, as no errors or warnings will be output if it is not set up.
Configuration of the ``logging`` module can be as simple as::
import logging
logging.basicConfig(level=logging.INFO)
Placed at the start of the application. This will output the logs from
discord as well as other libraries that use the ``logging`` module
directly to the console.
The optional ``level`` argument specifies what level of events to log
out and can be any of ``CRITICAL``, ``ERROR``, ``WARNING``, ``INFO``, and
``DEBUG`` and if not specified defaults to ``WARNING``.
More advanced setups are possible with the :mod:`logging` module. For
example to write the logs to a file called ``discord.log`` instead of
outputting them to the console the following snippet can be used::
import discord
import logging
logger = logging.getLogger('discord')
logger.setLevel(logging.DEBUG)
handler = logging.FileHandler(filename='discord.log', encoding='utf-8', mode='w')
handler.setFormatter(logging.Formatter('%(asctime)s:%(levelname)s:%(name)s: %(message)s'))
logger.addHandler(handler)
This is recommended, especially at verbose levels such as ``INFO``
and ``DEBUG``, as there are a lot of events logged and it would clog the
stdout of your program.
For more information, check the documentation and tutorial of the
:mod:`logging` module.

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,322 @@
:orphan:
.. currentmodule:: discord
.. _migrating-to-async:
Migrating to v0.10.0
======================
v0.10.0 is one of the biggest breaking changes in the library due to massive
fundamental changes in how the library operates.
The biggest major change is that the library has dropped support to all versions prior to
Python 3.4.2. This was made to support :mod:`asyncio`, in which more detail can be seen
:issue:`in the corresponding issue <50>`. To reiterate this, the implication is that
**python version 2.7 and 3.3 are no longer supported**.
Below are all the other major changes from v0.9.0 to v0.10.0.
Event Registration
--------------------
All events before were registered using :meth:`Client.event`. While this is still
possible, the events must be decorated with ``@asyncio.coroutine``.
Before:
.. code-block:: python3
@client.event
def on_message(message):
pass
After:
.. code-block:: python3
@client.event
@asyncio.coroutine
def on_message(message):
pass
Or in Python 3.5+:
.. code-block:: python3
@client.event
async def on_message(message):
pass
Because there is a lot of typing, a utility decorator (:meth:`Client.async_event`) is provided
for easier registration. For example:
.. code-block:: python3
@client.async_event
def on_message(message):
pass
Be aware however, that this is still a coroutine and your other functions that are coroutines must
be decorated with ``@asyncio.coroutine`` or be ``async def``.
Event Changes
--------------
Some events in v0.9.0 were considered pretty useless due to having no separate states. The main
events that were changed were the ``_update`` events since previously they had no context on what
was changed.
Before:
.. code-block:: python3
def on_channel_update(channel): pass
def on_member_update(member): pass
def on_status(member): pass
def on_server_role_update(role): pass
def on_voice_state_update(member): pass
def on_socket_raw_send(payload, is_binary): pass
After:
.. code-block:: python3
def on_channel_update(before, after): pass
def on_member_update(before, after): pass
def on_server_role_update(before, after): pass
def on_voice_state_update(before, after): pass
def on_socket_raw_send(payload): pass
Note that ``on_status`` was removed. If you want its functionality, use :func:`on_member_update`.
See :ref:`discord-api-events` for more information. Other removed events include ``on_socket_closed``, ``on_socket_receive``, and ``on_socket_opened``.
Coroutines
-----------
The biggest change that the library went through is that almost every function in :class:`Client`
was changed to be a `coroutine <py:library/asyncio-task.html>`_. Functions
that are marked as a coroutine in the documentation must be awaited from or yielded from in order
for the computation to be done. For example...
Before:
.. code-block:: python3
client.send_message(message.channel, 'Hello')
After:
.. code-block:: python3
yield from client.send_message(message.channel, 'Hello')
# or in python 3.5+
await client.send_message(message.channel, 'Hello')
In order for you to ``yield from`` or ``await`` a coroutine then your function must be decorated
with ``@asyncio.coroutine`` or ``async def``.
Iterables
----------
For performance reasons, many of the internal data structures were changed into a dictionary to support faster
lookup. As a consequence, this meant that some lists that were exposed via the API have changed into iterables
and not sequences. In short, this means that certain attributes now only support iteration and not any of the
sequence functions.
The affected attributes are as follows:
- :attr:`Client.servers`
- :attr:`Client.private_channels`
- :attr:`Server.channels`
- :attr:`Server.members`
Some examples of previously valid behaviour that is now invalid
.. code-block:: python3
if client.servers[0].name == "test":
# do something
Since they are no longer :obj:`list`\s, they no longer support indexing or any operation other than iterating.
In order to get the old behaviour you should explicitly cast it to a list.
.. code-block:: python3
servers = list(client.servers)
# work with servers
.. warning::
Due to internal changes of the structure, the order you receive the data in
is not in a guaranteed order.
Enumerations
------------
Due to dropping support for versions lower than Python 3.4.2, the library can now use
:doc:`py:library/enum` in places where it makes sense.
The common places where this was changed was in the server region, member status, and channel type.
Before:
.. code-block:: python3
server.region == 'us-west'
member.status == 'online'
channel.type == 'text'
After:
.. code-block:: python3
server.region == discord.ServerRegion.us_west
member.status = discord.Status.online
channel.type == discord.ChannelType.text
The main reason for this change was to reduce the use of finicky strings in the API as this
could give users a false sense of power. More information can be found in the :ref:`discord-api-enums` page.
Properties
-----------
A lot of function calls that returned constant values were changed into Python properties for ease of use
in format strings.
The following functions were changed into properties:
+----------------------------------------+--------------------------------------+
| Before | After |
+----------------------------------------+--------------------------------------+
| ``User.avatar_url()`` | :attr:`User.avatar_url` |
+----------------------------------------+--------------------------------------+
| ``User.mention()`` | :attr:`User.mention` |
+----------------------------------------+--------------------------------------+
| ``Channel.mention()`` | :attr:`Channel.mention` |
+----------------------------------------+--------------------------------------+
| ``Channel.is_default_channel()`` | :attr:`Channel.is_default` |
+----------------------------------------+--------------------------------------+
| ``Role.is_everyone()`` | :attr:`Role.is_everyone` |
+----------------------------------------+--------------------------------------+
| ``Server.get_default_role()`` | :attr:`Server.default_role` |
+----------------------------------------+--------------------------------------+
| ``Server.icon_url()`` | :attr:`Server.icon_url` |
+----------------------------------------+--------------------------------------+
| ``Server.get_default_channel()`` | :attr:`Server.default_channel` |
+----------------------------------------+--------------------------------------+
| ``Message.get_raw_mentions()`` | :attr:`Message.raw_mentions` |
+----------------------------------------+--------------------------------------+
| ``Message.get_raw_channel_mentions()`` | :attr:`Message.raw_channel_mentions` |
+----------------------------------------+--------------------------------------+
Member Management
-------------------
Functions that involved banning and kicking were changed.
+--------------------------------+--------------------------+
| Before | After |
+--------------------------------+--------------------------+
| ``Client.ban(server, user)`` | ``Client.ban(member)`` |
+--------------------------------+--------------------------+
| ``Client.kick(server, user)`` | ``Client.kick(member)`` |
+--------------------------------+--------------------------+
.. migrating-renames:
Renamed Functions
-------------------
Functions have been renamed.
+------------------------------------+-------------------------------------------+
| Before | After |
+------------------------------------+-------------------------------------------+
| ``Client.set_channel_permissions`` | :meth:`Client.edit_channel_permissions` |
+------------------------------------+-------------------------------------------+
All the :class:`Permissions` related attributes have been renamed and the `can_` prefix has been
dropped. So for example, ``can_manage_messages`` has become ``manage_messages``.
Forced Keyword Arguments
-------------------------
Since 3.0+ of Python, we can now force questions to take in forced keyword arguments. A keyword argument is when you
explicitly specify the name of the variable and assign to it, for example: ``foo(name='test')``. Due to this support,
some functions in the library were changed to force things to take said keyword arguments. This is to reduce errors of
knowing the argument order and the issues that could arise from them.
The following parameters are now exclusively keyword arguments:
- :meth:`Client.send_message`
- ``tts``
- :meth:`Client.logs_from`
- ``before``
- ``after``
- :meth:`Client.edit_channel_permissions`
- ``allow``
- ``deny``
In the documentation you can tell if a function parameter is a forced keyword argument if it is after ``\*,``
in the function signature.
.. _migrating-running:
Running the Client
--------------------
In earlier versions of discord.py, ``client.run()`` was a blocking call to the main thread
that called it. In v0.10.0 it is still a blocking call but it handles the event loop for you.
However, in order to do that you must pass in your credentials to :meth:`Client.run`.
Basically, before:
.. code-block:: python3
client.login('token')
client.run()
After:
.. code-block:: python3
client.run('token')
.. warning::
Like in the older ``Client.run`` function, the newer one must be the one of
the last functions to call. This is because the function is **blocking**. Registering
events or doing anything after :meth:`Client.run` will not execute until the function
returns.
This is a utility function that abstracts the event loop for you. There's no need for
the run call to be blocking and out of your control. Indeed, if you want control of the
event loop then doing so is quite straightforward:
.. code-block:: python3
import discord
import asyncio
client = discord.Client()
@asyncio.coroutine
def main_task():
yield from client.login('token')
yield from client.connect()
loop = asyncio.get_event_loop()
try:
loop.run_until_complete(main_task())
except:
loop.run_until_complete(client.logout())
finally:
loop.close()

View File

@ -0,0 +1,79 @@
:orphan:
.. _quickstart:
.. currentmodule:: discord
Quickstart
============
This page gives a brief introduction to the library. It assumes you have the library installed,
if you don't check the :ref:`installing` portion.
A Minimal Bot
---------------
Let's make a bot that responds to a specific message and walk you through it.
It looks something like this:
.. code-block:: python3
import discord
client = discord.Client()
@client.event
async def on_ready():
print(f'We have logged in as {client.user}')
@client.event
async def on_message(message):
if message.author == client.user:
return
if message.content.startswith('$hello'):
await message.channel.send('Hello!')
client.run('your token here')
Let's name this file ``example_bot.py``. Make sure not to name it ``discord.py`` as that'll conflict
with the library.
There's a lot going on here, so let's walk you through it step by step.
1. The first line just imports the library, if this raises a `ModuleNotFoundError` or `ImportError`
then head on over to :ref:`installing` section to properly install.
2. Next, we create an instance of a :class:`Client`. This client is our connection to Discord.
3. We then use the :meth:`Client.event` decorator to register an event. This library has many events.
Since this library is asynchronous, we do things in a "callback" style manner.
A callback is essentially a function that is called when something happens. In our case,
the :func:`on_ready` event is called when the bot has finished logging in and setting things
up and the :func:`on_message` event is called when the bot has received a message.
4. Since the :func:`on_message` event triggers for *every* message received, we have to make
sure that we ignore messages from ourselves. We do this by checking if the :attr:`Message.author`
is the same as the :attr:`Client.user`.
5. Afterwards, we check if the :class:`Message.content` starts with ``'$hello'``. If it does,
then we send a message in the channel it was used in with ``'Hello!'``. This is a basic way of
handling commands, which can be later automated with the :doc:`./ext/commands/index` framework.
6. Finally, we run the bot with our login token. If you need help getting your token or creating a bot,
look in the :ref:`discord-intro` section.
Now that we've made a bot, we have to *run* the bot. Luckily, this is simple since this is just a
Python script, we can run it directly.
On Windows:
.. code-block:: shell
$ py -3 example_bot.py
On other systems:
.. code-block:: shell
$ python3 example_bot.py
Now you can try playing around with your basic bot.

View File

@ -0,0 +1,30 @@
.. _version_guarantees:
Version Guarantees
=====================
The library follows a `semantic versioning principle <https://semver.org/>`_ which means that the major version is updated every time there is an incompatible API change. However due to the lack of guarantees on the Discord side when it comes to breaking changes along with the fairly dynamic nature of Python it can be hard to discern what can be considered a breaking change and what isn't.
The first thing to keep in mind is that breaking changes only apply to **publicly documented functions and classes**. If it's not listed in the documentation here then it is not part of the public API and is thus bound to change. This includes attributes that start with an underscore or functions without an underscore that are not documented.
.. note::
The examples below are non-exhaustive.
Examples of Breaking Changes
------------------------------
- Changing the default parameter value to something else.
- Renaming a function without an alias to an old function.
- Adding or removing parameters to an event.
Examples of Non-Breaking Changes
----------------------------------
- Adding or removing private underscored attributes.
- Adding an element into the ``__slots__`` of a data class.
- Changing the behaviour of a function to fix a bug.
- Changes in the documentation.
- Modifying the internal HTTP handling.
- Upgrading the dependencies to a new version, major or otherwise.

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,904 @@
/*
* basic.css
* ~~~~~~~~~
*
* Sphinx stylesheet -- basic theme.
*
* :copyright: Copyright 2007-2021 by the Sphinx team, see AUTHORS.
* :license: BSD, see LICENSE for details.
*
*/
/* -- main layout ----------------------------------------------------------- */
div.clearer {
clear: both;
}
div.section::after {
display: block;
content: '';
clear: left;
}
/* -- relbar ---------------------------------------------------------------- */
div.related {
width: 100%;
font-size: 90%;
}
div.related h3 {
display: none;
}
div.related ul {
margin: 0;
padding: 0 0 0 10px;
list-style: none;
}
div.related li {
display: inline;
}
div.related li.right {
float: right;
margin-right: 5px;
}
/* -- sidebar --------------------------------------------------------------- */
div.sphinxsidebarwrapper {
padding: 10px 5px 0 10px;
}
div.sphinxsidebar {
float: left;
width: 230px;
margin-left: -100%;
font-size: 90%;
word-wrap: break-word;
overflow-wrap : break-word;
}
div.sphinxsidebar ul {
list-style: none;
}
div.sphinxsidebar ul ul,
div.sphinxsidebar ul.want-points {
margin-left: 20px;
list-style: square;
}
div.sphinxsidebar ul ul {
margin-top: 0;
margin-bottom: 0;
}
div.sphinxsidebar form {
margin-top: 10px;
}
div.sphinxsidebar input {
border: 1px solid #98dbcc;
font-family: sans-serif;
font-size: 1em;
}
div.sphinxsidebar #searchbox form.search {
overflow: hidden;
}
div.sphinxsidebar #searchbox input[type="text"] {
float: left;
width: 80%;
padding: 0.25em;
box-sizing: border-box;
}
div.sphinxsidebar #searchbox input[type="submit"] {
float: left;
width: 20%;
border-left: none;
padding: 0.25em;
box-sizing: border-box;
}
img {
border: 0;
max-width: 100%;
}
/* -- search page ----------------------------------------------------------- */
ul.search {
margin: 10px 0 0 20px;
padding: 0;
}
ul.search li {
padding: 5px 0 5px 20px;
background-image: url(file.png);
background-repeat: no-repeat;
background-position: 0 7px;
}
ul.search li a {
font-weight: bold;
}
ul.search li p.context {
color: #888;
margin: 2px 0 0 30px;
text-align: left;
}
ul.keywordmatches li.goodmatch a {
font-weight: bold;
}
/* -- index page ------------------------------------------------------------ */
table.contentstable {
width: 90%;
margin-left: auto;
margin-right: auto;
}
table.contentstable p.biglink {
line-height: 150%;
}
a.biglink {
font-size: 1.3em;
}
span.linkdescr {
font-style: italic;
padding-top: 5px;
font-size: 90%;
}
/* -- general index --------------------------------------------------------- */
table.indextable {
width: 100%;
}
table.indextable td {
text-align: left;
vertical-align: top;
}
table.indextable ul {
margin-top: 0;
margin-bottom: 0;
list-style-type: none;
}
table.indextable > tbody > tr > td > ul {
padding-left: 0em;
}
table.indextable tr.pcap {
height: 10px;
}
table.indextable tr.cap {
margin-top: 10px;
background-color: #f2f2f2;
}
img.toggler {
margin-right: 3px;
margin-top: 3px;
cursor: pointer;
}
div.modindex-jumpbox {
border-top: 1px solid #ddd;
border-bottom: 1px solid #ddd;
margin: 1em 0 1em 0;
padding: 0.4em;
}
div.genindex-jumpbox {
border-top: 1px solid #ddd;
border-bottom: 1px solid #ddd;
margin: 1em 0 1em 0;
padding: 0.4em;
}
/* -- domain module index --------------------------------------------------- */
table.modindextable td {
padding: 2px;
border-collapse: collapse;
}
/* -- general body styles --------------------------------------------------- */
div.body {
min-width: 450px;
max-width: 800px;
}
div.body p, div.body dd, div.body li, div.body blockquote {
-moz-hyphens: auto;
-ms-hyphens: auto;
-webkit-hyphens: auto;
hyphens: auto;
}
a.headerlink {
visibility: hidden;
}
a.brackets:before,
span.brackets > a:before{
content: "[";
}
a.brackets:after,
span.brackets > a:after {
content: "]";
}
h1:hover > a.headerlink,
h2:hover > a.headerlink,
h3:hover > a.headerlink,
h4:hover > a.headerlink,
h5:hover > a.headerlink,
h6:hover > a.headerlink,
dt:hover > a.headerlink,
caption:hover > a.headerlink,
p.caption:hover > a.headerlink,
div.code-block-caption:hover > a.headerlink {
visibility: visible;
}
div.body p.caption {
text-align: inherit;
}
div.body td {
text-align: left;
}
.first {
margin-top: 0 !important;
}
p.rubric {
margin-top: 30px;
font-weight: bold;
}
img.align-left, figure.align-left, .figure.align-left, object.align-left {
clear: left;
float: left;
margin-right: 1em;
}
img.align-right, figure.align-right, .figure.align-right, object.align-right {
clear: right;
float: right;
margin-left: 1em;
}
img.align-center, figure.align-center, .figure.align-center, object.align-center {
display: block;
margin-left: auto;
margin-right: auto;
}
img.align-default, figure.align-default, .figure.align-default {
display: block;
margin-left: auto;
margin-right: auto;
}
.align-left {
text-align: left;
}
.align-center {
text-align: center;
}
.align-default {
text-align: center;
}
.align-right {
text-align: right;
}
/* -- sidebars -------------------------------------------------------------- */
div.sidebar,
aside.sidebar {
margin: 0 0 0.5em 1em;
border: 1px solid #ddb;
padding: 7px;
background-color: #ffe;
width: 40%;
float: right;
clear: right;
overflow-x: auto;
}
p.sidebar-title {
font-weight: bold;
}
div.admonition, div.topic, blockquote {
clear: left;
}
/* -- topics ---------------------------------------------------------------- */
div.topic {
border: 1px solid #ccc;
padding: 7px;
margin: 10px 0 10px 0;
}
p.topic-title {
font-size: 1.1em;
font-weight: bold;
margin-top: 10px;
}
/* -- admonitions ----------------------------------------------------------- */
div.admonition {
margin-top: 10px;
margin-bottom: 10px;
padding: 7px;
}
div.admonition dt {
font-weight: bold;
}
p.admonition-title {
margin: 0px 10px 5px 0px;
font-weight: bold;
}
div.body p.centered {
text-align: center;
margin-top: 25px;
}
/* -- content of sidebars/topics/admonitions -------------------------------- */
div.sidebar > :last-child,
aside.sidebar > :last-child,
div.topic > :last-child,
div.admonition > :last-child {
margin-bottom: 0;
}
div.sidebar::after,
aside.sidebar::after,
div.topic::after,
div.admonition::after,
blockquote::after {
display: block;
content: '';
clear: both;
}
/* -- tables ---------------------------------------------------------------- */
table.docutils {
margin-top: 10px;
margin-bottom: 10px;
border: 0;
border-collapse: collapse;
}
table.align-center {
margin-left: auto;
margin-right: auto;
}
table.align-default {
margin-left: auto;
margin-right: auto;
}
table caption span.caption-number {
font-style: italic;
}
table caption span.caption-text {
}
table.docutils td, table.docutils th {
padding: 1px 8px 1px 5px;
border-top: 0;
border-left: 0;
border-right: 0;
border-bottom: 1px solid #aaa;
}
table.footnote td, table.footnote th {
border: 0 !important;
}
th {
text-align: left;
padding-right: 5px;
}
table.citation {
border-left: solid 1px gray;
margin-left: 1px;
}
table.citation td {
border-bottom: none;
}
th > :first-child,
td > :first-child {
margin-top: 0px;
}
th > :last-child,
td > :last-child {
margin-bottom: 0px;
}
/* -- figures --------------------------------------------------------------- */
div.figure, figure {
margin: 0.5em;
padding: 0.5em;
}
div.figure p.caption, figcaption {
padding: 0.3em;
}
div.figure p.caption span.caption-number,
figcaption span.caption-number {
font-style: italic;
}
div.figure p.caption span.caption-text,
figcaption span.caption-text {
}
/* -- field list styles ----------------------------------------------------- */
table.field-list td, table.field-list th {
border: 0 !important;
}
.field-list ul {
margin: 0;
padding-left: 1em;
}
.field-list p {
margin: 0;
}
.field-name {
-moz-hyphens: manual;
-ms-hyphens: manual;
-webkit-hyphens: manual;
hyphens: manual;
}
/* -- hlist styles ---------------------------------------------------------- */
table.hlist {
margin: 1em 0;
}
table.hlist td {
vertical-align: top;
}
/* -- object description styles --------------------------------------------- */
.sig {
font-family: 'Consolas', 'Menlo', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', monospace;
}
.sig-name, code.descname {
background-color: transparent;
font-weight: bold;
}
.sig-name {
font-size: 1.1em;
}
code.descname {
font-size: 1.2em;
}
.sig-prename, code.descclassname {
background-color: transparent;
}
.optional {
font-size: 1.3em;
}
.sig-paren {
font-size: larger;
}
.sig-param.n {
font-style: italic;
}
/* C++ specific styling */
.sig-inline.c-texpr,
.sig-inline.cpp-texpr {
font-family: unset;
}
.sig.c .k, .sig.c .kt,
.sig.cpp .k, .sig.cpp .kt {
color: #0033B3;
}
.sig.c .m,
.sig.cpp .m {
color: #1750EB;
}
.sig.c .s, .sig.c .sc,
.sig.cpp .s, .sig.cpp .sc {
color: #067D17;
}
/* -- other body styles ----------------------------------------------------- */
ol.arabic {
list-style: decimal;
}
ol.loweralpha {
list-style: lower-alpha;
}
ol.upperalpha {
list-style: upper-alpha;
}
ol.lowerroman {
list-style: lower-roman;
}
ol.upperroman {
list-style: upper-roman;
}
:not(li) > ol > li:first-child > :first-child,
:not(li) > ul > li:first-child > :first-child {
margin-top: 0px;
}
:not(li) > ol > li:last-child > :last-child,
:not(li) > ul > li:last-child > :last-child {
margin-bottom: 0px;
}
ol.simple ol p,
ol.simple ul p,
ul.simple ol p,
ul.simple ul p {
margin-top: 0;
}
ol.simple > li:not(:first-child) > p,
ul.simple > li:not(:first-child) > p {
margin-top: 0;
}
ol.simple p,
ul.simple p {
margin-bottom: 0;
}
dl.footnote > dt,
dl.citation > dt {
float: left;
margin-right: 0.5em;
}
dl.footnote > dd,
dl.citation > dd {
margin-bottom: 0em;
}
dl.footnote > dd:after,
dl.citation > dd:after {
content: "";
clear: both;
}
dl.field-list {
display: grid;
grid-template-columns: fit-content(30%) auto;
}
dl.field-list > dt {
font-weight: bold;
word-break: break-word;
padding-left: 0.5em;
padding-right: 5px;
}
dl.field-list > dt:after {
content: ":";
}
dl.field-list > dd {
padding-left: 0.5em;
margin-top: 0em;
margin-left: 0em;
margin-bottom: 0em;
}
dl {
margin-bottom: 15px;
}
dd > :first-child {
margin-top: 0px;
}
dd ul, dd table {
margin-bottom: 10px;
}
dd {
margin-top: 3px;
margin-bottom: 10px;
margin-left: 30px;
}
dl > dd:last-child,
dl > dd:last-child > :last-child {
margin-bottom: 0;
}
dt:target, span.highlighted {
background-color: #fbe54e;
}
rect.highlighted {
fill: #fbe54e;
}
dl.glossary dt {
font-weight: bold;
font-size: 1.1em;
}
.versionmodified {
font-style: italic;
}
.system-message {
background-color: #fda;
padding: 5px;
border: 3px solid red;
}
.footnote:target {
background-color: #ffa;
}
.line-block {
display: block;
margin-top: 1em;
margin-bottom: 1em;
}
.line-block .line-block {
margin-top: 0;
margin-bottom: 0;
margin-left: 1.5em;
}
.guilabel, .menuselection {
font-family: sans-serif;
}
.accelerator {
text-decoration: underline;
}
.classifier {
font-style: oblique;
}
.classifier:before {
font-style: normal;
margin: 0.5em;
content: ":";
}
abbr, acronym {
border-bottom: dotted 1px;
cursor: help;
}
/* -- code displays --------------------------------------------------------- */
pre {
overflow: auto;
overflow-y: hidden; /* fixes display issues on Chrome browsers */
}
pre, div[class*="highlight-"] {
clear: both;
}
span.pre {
-moz-hyphens: none;
-ms-hyphens: none;
-webkit-hyphens: none;
hyphens: none;
}
div[class*="highlight-"] {
margin: 1em 0;
}
td.linenos pre {
border: 0;
background-color: transparent;
color: #aaa;
}
table.highlighttable {
display: block;
}
table.highlighttable tbody {
display: block;
}
table.highlighttable tr {
display: flex;
}
table.highlighttable td {
margin: 0;
padding: 0;
}
table.highlighttable td.linenos {
padding-right: 0.5em;
}
table.highlighttable td.code {
flex: 1;
overflow: hidden;
}
.highlight .hll {
display: block;
}
div.highlight pre,
table.highlighttable pre {
margin: 0;
}
div.code-block-caption + div {
margin-top: 0;
}
div.code-block-caption {
margin-top: 1em;
padding: 2px 5px;
font-size: small;
}
div.code-block-caption code {
background-color: transparent;
}
table.highlighttable td.linenos,
span.linenos,
div.highlight span.gp { /* gp: Generic.Prompt */
user-select: none;
-webkit-user-select: text; /* Safari fallback only */
-webkit-user-select: none; /* Chrome/Safari */
-moz-user-select: none; /* Firefox */
-ms-user-select: none; /* IE10+ */
}
div.code-block-caption span.caption-number {
padding: 0.1em 0.3em;
font-style: italic;
}
div.code-block-caption span.caption-text {
}
div.literal-block-wrapper {
margin: 1em 0;
}
code.xref, a code {
background-color: transparent;
font-weight: bold;
}
h1 code, h2 code, h3 code, h4 code, h5 code, h6 code {
background-color: transparent;
}
.viewcode-link {
float: right;
}
.viewcode-back {
float: right;
font-family: sans-serif;
}
div.viewcode-block:target {
margin: -1px -10px;
padding: 0 10px;
}
/* -- math display ---------------------------------------------------------- */
img.math {
vertical-align: middle;
}
div.body div.math p {
text-align: center;
}
span.eqno {
float: right;
}
span.eqno a.headerlink {
position: absolute;
z-index: 1;
}
div.math:hover a.headerlink {
visibility: visible;
}
/* -- printout stylesheet --------------------------------------------------- */
@media print {
div.document,
div.documentwrapper,
div.bodywrapper {
margin: 0 !important;
width: 100%;
}
div.sphinxsidebar,
div.related,
div.footer,
#top-link {
display: none;
}
}

View File

@ -0,0 +1,143 @@
/* light theme: default */
.highlight .hll { background-color: #ffffcc }
.highlight { background: #f0f0f0; }
.highlight .c { color: #60a0b0; font-style: italic } /* Comment */
.highlight .err { border: 1px solid #FF0000 } /* Error */
.highlight .k { color: #007020; font-weight: bold } /* Keyword */
.highlight .o { color: #666666 } /* Operator */
.highlight .ch { color: #60a0b0; font-style: italic } /* Comment.Hashbang */
.highlight .cm { color: #60a0b0; font-style: italic } /* Comment.Multiline */
.highlight .cp { color: #007020 } /* Comment.Preproc */
.highlight .cpf { color: #60a0b0; font-style: italic } /* Comment.PreprocFile */
.highlight .c1 { color: #60a0b0; font-style: italic } /* Comment.Single */
.highlight .cs { color: #60a0b0; background-color: #fff0f0 } /* Comment.Special */
.highlight .gd { color: #A00000 } /* Generic.Deleted */
.highlight .ge { font-style: italic } /* Generic.Emph */
.highlight .gr { color: #FF0000 } /* Generic.Error */
.highlight .gh { color: #000080; font-weight: bold } /* Generic.Heading */
.highlight .gi { color: #00A000 } /* Generic.Inserted */
.highlight .go { color: #888888 } /* Generic.Output */
.highlight .gp { color: #c65d09; font-weight: bold } /* Generic.Prompt */
.highlight .gs { font-weight: bold } /* Generic.Strong */
.highlight .gu { color: #800080; font-weight: bold } /* Generic.Subheading */
.highlight .gt { color: #0044DD } /* Generic.Traceback */
.highlight .kc { color: #007020; font-weight: bold } /* Keyword.Constant */
.highlight .kd { color: #007020; font-weight: bold } /* Keyword.Declaration */
.highlight .kn { color: #007020; font-weight: bold } /* Keyword.Namespace */
.highlight .kp { color: #007020 } /* Keyword.Pseudo */
.highlight .kr { color: #007020; font-weight: bold } /* Keyword.Reserved */
.highlight .kt { color: #902000 } /* Keyword.Type */
.highlight .m { color: #40a070 } /* Literal.Number */
.highlight .s { color: #4070a0 } /* Literal.String */
.highlight .na { color: #4070a0 } /* Name.Attribute */
.highlight .nb { color: #007020 } /* Name.Builtin */
.highlight .nc { color: #0e84b5; font-weight: bold } /* Name.Class */
.highlight .no { color: #60add5 } /* Name.Constant */
.highlight .nd { color: #555555; font-weight: bold } /* Name.Decorator */
.highlight .ni { color: #d55537; font-weight: bold } /* Name.Entity */
.highlight .ne { color: #007020 } /* Name.Exception */
.highlight .nf { color: #06287e } /* Name.Function */
.highlight .nl { color: #002070; font-weight: bold } /* Name.Label */
.highlight .nn { color: #0e84b5; font-weight: bold } /* Name.Namespace */
.highlight .nt { color: #062873; font-weight: bold } /* Name.Tag */
.highlight .nv { color: #bb60d5 } /* Name.Variable */
.highlight .ow { color: #007020; font-weight: bold } /* Operator.Word */
.highlight .w { color: #bbbbbb } /* Text.Whitespace */
.highlight .mb { color: #40a070 } /* Literal.Number.Bin */
.highlight .mf { color: #40a070 } /* Literal.Number.Float */
.highlight .mh { color: #40a070 } /* Literal.Number.Hex */
.highlight .mi { color: #40a070 } /* Literal.Number.Integer */
.highlight .mo { color: #40a070 } /* Literal.Number.Oct */
.highlight .sa { color: #4070a0 } /* Literal.String.Affix */
.highlight .sb { color: #4070a0 } /* Literal.String.Backtick */
.highlight .sc { color: #4070a0 } /* Literal.String.Char */
.highlight .dl { color: #4070a0 } /* Literal.String.Delimiter */
.highlight .sd { color: #4070a0; font-style: italic } /* Literal.String.Doc */
.highlight .s2 { color: #4070a0 } /* Literal.String.Double */
.highlight .se { color: #4070a0; font-weight: bold } /* Literal.String.Escape */
.highlight .sh { color: #4070a0 } /* Literal.String.Heredoc */
.highlight .si { color: #70a0d0; font-style: italic } /* Literal.String.Interpol */
.highlight .sx { color: #c65d09 } /* Literal.String.Other */
.highlight .sr { color: #235388 } /* Literal.String.Regex */
.highlight .s1 { color: #4070a0 } /* Literal.String.Single */
.highlight .ss { color: #517918 } /* Literal.String.Symbol */
.highlight .bp { color: #007020 } /* Name.Builtin.Pseudo */
.highlight .fm { color: #06287e } /* Name.Function.Magic */
.highlight .vc { color: #bb60d5 } /* Name.Variable.Class */
.highlight .vg { color: #bb60d5 } /* Name.Variable.Global */
.highlight .vi { color: #bb60d5 } /* Name.Variable.Instance */
.highlight .vm { color: #bb60d5 } /* Name.Variable.Magic */
.highlight .il { color: #40a070 } /* Literal.Number.Integer.Long */
/* dark theme: modified "native" */
:root[data-theme="dark"] .highlight pre { background-color: #2a2a2e }
:root[data-theme="dark"] .highlight .hll { background-color: #2a2a2e }
:root[data-theme="dark"] .highlight .c { color: #999999; font-style: italic } /* Comment */
:root[data-theme="dark"] .highlight .err { color: #a61717; background-color: #e3d2d2 } /* Error */
:root[data-theme="dark"] .highlight .g { color: #d0d0d0 } /* Generic */
:root[data-theme="dark"] .highlight .k { color: #6ab825; font-weight: bold } /* Keyword */
:root[data-theme="dark"] .highlight .l { color: #d0d0d0 } /* Literal */
:root[data-theme="dark"] .highlight .n { color: #d0d0d0 } /* Name */
:root[data-theme="dark"] .highlight .o { color: #d0d0d0 } /* Operator */
:root[data-theme="dark"] .highlight .x { color: #d0d0d0 } /* Other */
:root[data-theme="dark"] .highlight .p { color: #d0d0d0 } /* Punctuation */
:root[data-theme="dark"] .highlight .cm { color: #999999; font-style: italic } /* Comment.Multiline */
:root[data-theme="dark"] .highlight .cp { color: #cd2828; font-weight: bold } /* Comment.Preproc */
:root[data-theme="dark"] .highlight .c1 { color: #999999; font-style: italic } /* Comment.Single */
:root[data-theme="dark"] .highlight .cs { color: #e50808; font-weight: bold; background-color: #520000 } /* Comment.Special */
:root[data-theme="dark"] .highlight .gd { color: #d22323 } /* Generic.Deleted */
:root[data-theme="dark"] .highlight .ge { color: #d0d0d0; font-style: italic } /* Generic.Emph */
:root[data-theme="dark"] .highlight .gr { color: #d22323 } /* Generic.Error */
:root[data-theme="dark"] .highlight .gh { color: #ffffff; font-weight: bold } /* Generic.Heading */
:root[data-theme="dark"] .highlight .gi { color: #589819 } /* Generic.Inserted */
:root[data-theme="dark"] .highlight .go { color: #cccccc } /* Generic.Output */
:root[data-theme="dark"] .highlight .gp { color: #aaaaaa } /* Generic.Prompt */
:root[data-theme="dark"] .highlight .gs { color: #d0d0d0; font-weight: bold } /* Generic.Strong */
:root[data-theme="dark"] .highlight .gu { color: #ffffff; text-decoration: underline } /* Generic.Subheading */
:root[data-theme="dark"] .highlight .gt { color: #d22323 } /* Generic.Traceback */
:root[data-theme="dark"] .highlight .kc { color: #6ab825; font-weight: bold } /* Keyword.Constant */
:root[data-theme="dark"] .highlight .kd { color: #6ab825; font-weight: bold } /* Keyword.Declaration */
:root[data-theme="dark"] .highlight .kn { color: #6ab825; font-weight: bold } /* Keyword.Namespace */
:root[data-theme="dark"] .highlight .kp { color: #6ab825 } /* Keyword.Pseudo */
:root[data-theme="dark"] .highlight .kr { color: #6ab825; font-weight: bold } /* Keyword.Reserved */
:root[data-theme="dark"] .highlight .kt { color: #6ab825; font-weight: bold } /* Keyword.Type */
:root[data-theme="dark"] .highlight .ld { color: #d0d0d0 } /* Literal.Date */
:root[data-theme="dark"] .highlight .m { color: #7fb1d7 } /* Literal.Number */
:root[data-theme="dark"] .highlight .s { color: #ed9d13 } /* Literal.String */
:root[data-theme="dark"] .highlight .na { color: #bbbbbb; } /* Name.Attribute */
:root[data-theme="dark"] .highlight .nb { color: #29a5b3; } /* Name.Builtin */
:root[data-theme="dark"] .highlight .nc { color: #6494d8;} /* Name.Class */
:root[data-theme="dark"] .highlight .no { color: #40ffff; } /* Name.Constant */
:root[data-theme="dark"] .highlight .nd { color: #ffa500; } /* Name.Decorator */
:root[data-theme="dark"] .highlight .ni { color: #d0d0d0; } /* Name.Entity */
:root[data-theme="dark"] .highlight .ne { color: #bbbbbb; } /* Name.Exception */
:root[data-theme="dark"] .highlight .nf { color: #6494d8; } /* Name.Function */
:root[data-theme="dark"] .highlight .fm { color: #6494d8; } /* Name.Function.Magic */
:root[data-theme="dark"] .highlight .nl { color: #d0d0d0; } /* Name.Label */
:root[data-theme="dark"] .highlight .nn { color: #6494d8;} /* Name.Namespace */
:root[data-theme="dark"] .highlight .nx { color: #d0d0d0; } /* Name.Other */
:root[data-theme="dark"] .highlight .py { color: #d0d0d0; } /* Name.Property */
:root[data-theme="dark"] .highlight .nt { color: #6ab825; font-weight: bold } /* Name.Tag */
:root[data-theme="dark"] .highlight .nv { color: #40ffff; } /* Name.Variable */
:root[data-theme="dark"] .highlight .ow { color: #6ab825; font-weight: bold } /* Operator.Word */
:root[data-theme="dark"] .highlight .w { color: #666666; } /* Text.Whitespace */
:root[data-theme="dark"] .highlight .mf { color: #7fb1d7; } /* Literal.Number.Float */
:root[data-theme="dark"] .highlight .mh { color: #7fb1d7; } /* Literal.Number.Hex */
:root[data-theme="dark"] .highlight .mi { color: #7fb1d7; } /* Literal.Number.Integer */
:root[data-theme="dark"] .highlight .mo { color: #7fb1d7; } /* Literal.Number.Oct */
:root[data-theme="dark"] .highlight .sb { color: #ed9d13; } /* Literal.String.Backtick */
:root[data-theme="dark"] .highlight .sc { color: #ed9d13; } /* Literal.String.Char */
:root[data-theme="dark"] .highlight .sd { color: #ed9d13; } /* Literal.String.Doc */
:root[data-theme="dark"] .highlight .s2 { color: #ed9d13; } /* Literal.String.Double */
:root[data-theme="dark"] .highlight .se { color: #ed9d13; } /* Literal.String.Escape */
:root[data-theme="dark"] .highlight .sh { color: #ed9d13; } /* Literal.String.Heredoc */
:root[data-theme="dark"] .highlight .si { color: #ed9d13; } /* Literal.String.Interpol */
:root[data-theme="dark"] .highlight .sx { color: #ffa500; } /* Literal.String.Other */
:root[data-theme="dark"] .highlight .sr { color: #ed9d13; } /* Literal.String.Regex */
:root[data-theme="dark"] .highlight .s1 { color: #ed9d13; } /* Literal.String.Single */
:root[data-theme="dark"] .highlight .ss { color: #ed9d13; } /* Literal.String.Symbol */
:root[data-theme="dark"] .highlight .bp { color: #29a5b3; } /* Name.Builtin.Pseudo */
:root[data-theme="dark"] .highlight .vc { color: #40ffff; } /* Name.Variable.Class */
:root[data-theme="dark"] .highlight .vg { color: #40ffff; } /* Name.Variable.Global */
:root[data-theme="dark"] .highlight .vi { color: #40ffff; } /* Name.Variable.Instance */
:root[data-theme="dark"] .highlight .il { color: #7fb1d7; } /* Literal.Number.Integer.Long */

View File

@ -0,0 +1,34 @@
const COPY = "content_copy";
const COPIED = "done";
const copy = async (obj) => {
// <span class="copy"><span class="material-icons">{{text}}</span></span>
await navigator.clipboard.writeText(obj.children[1].innerText).then(
() => {
let icon = obj.children[0].children[0];
icon.textContent = COPIED;
setTimeout(() => (icon.textContent = COPY), 2500);
},
(r) => alert('Could not copy codeblock:\n' + r.toString())
);
};
document.addEventListener("DOMContentLoaded", () => {
let allCodeblocks = document.querySelectorAll("div[class='highlight']");
for (let codeblock of allCodeblocks) {
codeblock.parentNode.className += " relative-copy";
let copyEl = document.createElement("span");
copyEl.addEventListener('click', () => copy(codeblock));
copyEl.className = "copy";
copyEl.setAttribute("aria-label", "Copy Code");
copyEl.setAttribute("title", "Copy Code");
let copyIcon = document.createElement("span");
copyIcon.className = "material-icons";
copyIcon.textContent = COPY;
copyEl.append(copyIcon);
codeblock.prepend(copyEl);
}
});

View File

@ -0,0 +1,97 @@
'use-strict';
let activeModal = null;
let bottomHeightThreshold, sections;
let hamburgerToggle;
let mobileSearch;
let sidebar;
let toTop;
class Modal {
constructor(element) {
this.element = element;
}
close() {
activeModal = null;
this.element.style.display = 'none'
}
open() {
if (activeModal) {
activeModal.close();
}
activeModal = this;
this.element.style.display = 'flex'
}
}
class SearchBar {
constructor() {
this.box = document.querySelector('nav.mobile-only');
this.bar = document.querySelector('nav.mobile-only input[type="search"]');
this.openButton = document.getElementById('open-search');
this.closeButton = document.getElementById('close-search');
}
open() {
this.openButton.hidden = true;
this.closeButton.hidden = false;
this.box.style.top = "100%";
this.bar.focus();
}
close() {
this.openButton.hidden = false;
this.closeButton.hidden = true;
this.box.style.top = "0";
}
}
function scrollToTop() {
window.scrollTo({ top: 0, behavior: 'smooth' });
}
document.addEventListener('DOMContentLoaded', () => {
mobileSearch = new SearchBar();
bottomHeightThreshold = document.documentElement.scrollHeight - 30;
sections = document.querySelectorAll('section');
hamburgerToggle = document.getElementById('hamburger-toggle');
toTop = document.getElementById('to-top');
toTop.hidden = !(window.scrollY > 0);
if (hamburgerToggle) {
hamburgerToggle.addEventListener('click', (e) => {
sidebar.element.classList.toggle('sidebar-toggle');
let button = hamburgerToggle.firstElementChild;
if (button.textContent == 'menu') {
button.textContent = 'close';
}
else {
button.textContent = 'menu';
}
});
}
const tables = document.querySelectorAll('.py-attribute-table[data-move-to-id]');
tables.forEach(table => {
let element = document.getElementById(table.getAttribute('data-move-to-id'));
let parent = element.parentNode;
// insert ourselves after the element
parent.insertBefore(table, element.nextSibling);
});
window.addEventListener('scroll', () => {
toTop.hidden = !(window.scrollY > 0);
});
});
document.addEventListener('keydown', (event) => {
if (event.code == "Escape" && activeModal) {
activeModal.close();
}
});

Binary file not shown.

After

Width:  |  Height:  |  Size: 264 KiB

View File

@ -0,0 +1,323 @@
/*
* doctools.js
* ~~~~~~~~~~~
*
* Sphinx JavaScript utilities for all documentation.
*
* :copyright: Copyright 2007-2021 by the Sphinx team, see AUTHORS.
* :license: BSD, see LICENSE for details.
*
*/
/**
* select a different prefix for underscore
*/
$u = _.noConflict();
/**
* make the code below compatible with browsers without
* an installed firebug like debugger
if (!window.console || !console.firebug) {
var names = ["log", "debug", "info", "warn", "error", "assert", "dir",
"dirxml", "group", "groupEnd", "time", "timeEnd", "count", "trace",
"profile", "profileEnd"];
window.console = {};
for (var i = 0; i < names.length; ++i)
window.console[names[i]] = function() {};
}
*/
/**
* small helper function to urldecode strings
*
* See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/decodeURIComponent#Decoding_query_parameters_from_a_URL
*/
jQuery.urldecode = function(x) {
if (!x) {
return x
}
return decodeURIComponent(x.replace(/\+/g, ' '));
};
/**
* small helper function to urlencode strings
*/
jQuery.urlencode = encodeURIComponent;
/**
* This function returns the parsed url parameters of the
* current request. Multiple values per key are supported,
* it will always return arrays of strings for the value parts.
*/
jQuery.getQueryParameters = function(s) {
if (typeof s === 'undefined')
s = document.location.search;
var parts = s.substr(s.indexOf('?') + 1).split('&');
var result = {};
for (var i = 0; i < parts.length; i++) {
var tmp = parts[i].split('=', 2);
var key = jQuery.urldecode(tmp[0]);
var value = jQuery.urldecode(tmp[1]);
if (key in result)
result[key].push(value);
else
result[key] = [value];
}
return result;
};
/**
* highlight a given string on a jquery object by wrapping it in
* span elements with the given class name.
*/
jQuery.fn.highlightText = function(text, className) {
function highlight(node, addItems) {
if (node.nodeType === 3) {
var val = node.nodeValue;
var pos = val.toLowerCase().indexOf(text);
if (pos >= 0 &&
!jQuery(node.parentNode).hasClass(className) &&
!jQuery(node.parentNode).hasClass("nohighlight")) {
var span;
var isInSVG = jQuery(node).closest("body, svg, foreignObject").is("svg");
if (isInSVG) {
span = document.createElementNS("http://www.w3.org/2000/svg", "tspan");
} else {
span = document.createElement("span");
span.className = className;
}
span.appendChild(document.createTextNode(val.substr(pos, text.length)));
node.parentNode.insertBefore(span, node.parentNode.insertBefore(
document.createTextNode(val.substr(pos + text.length)),
node.nextSibling));
node.nodeValue = val.substr(0, pos);
if (isInSVG) {
var rect = document.createElementNS("http://www.w3.org/2000/svg", "rect");
var bbox = node.parentElement.getBBox();
rect.x.baseVal.value = bbox.x;
rect.y.baseVal.value = bbox.y;
rect.width.baseVal.value = bbox.width;
rect.height.baseVal.value = bbox.height;
rect.setAttribute('class', className);
addItems.push({
"parent": node.parentNode,
"target": rect});
}
}
}
else if (!jQuery(node).is("button, select, textarea")) {
jQuery.each(node.childNodes, function() {
highlight(this, addItems);
});
}
}
var addItems = [];
var result = this.each(function() {
highlight(this, addItems);
});
for (var i = 0; i < addItems.length; ++i) {
jQuery(addItems[i].parent).before(addItems[i].target);
}
return result;
};
/*
* backward compatibility for jQuery.browser
* This will be supported until firefox bug is fixed.
*/
if (!jQuery.browser) {
jQuery.uaMatch = function(ua) {
ua = ua.toLowerCase();
var match = /(chrome)[ \/]([\w.]+)/.exec(ua) ||
/(webkit)[ \/]([\w.]+)/.exec(ua) ||
/(opera)(?:.*version|)[ \/]([\w.]+)/.exec(ua) ||
/(msie) ([\w.]+)/.exec(ua) ||
ua.indexOf("compatible") < 0 && /(mozilla)(?:.*? rv:([\w.]+)|)/.exec(ua) ||
[];
return {
browser: match[ 1 ] || "",
version: match[ 2 ] || "0"
};
};
jQuery.browser = {};
jQuery.browser[jQuery.uaMatch(navigator.userAgent).browser] = true;
}
/**
* Small JavaScript module for the documentation.
*/
var Documentation = {
init : function() {
this.fixFirefoxAnchorBug();
this.highlightSearchWords();
this.initIndexTable();
if (DOCUMENTATION_OPTIONS.NAVIGATION_WITH_KEYS) {
this.initOnKeyListeners();
}
},
/**
* i18n support
*/
TRANSLATIONS : {},
PLURAL_EXPR : function(n) { return n === 1 ? 0 : 1; },
LOCALE : 'unknown',
// gettext and ngettext don't access this so that the functions
// can safely bound to a different name (_ = Documentation.gettext)
gettext : function(string) {
var translated = Documentation.TRANSLATIONS[string];
if (typeof translated === 'undefined')
return string;
return (typeof translated === 'string') ? translated : translated[0];
},
ngettext : function(singular, plural, n) {
var translated = Documentation.TRANSLATIONS[singular];
if (typeof translated === 'undefined')
return (n == 1) ? singular : plural;
return translated[Documentation.PLURALEXPR(n)];
},
addTranslations : function(catalog) {
for (var key in catalog.messages)
this.TRANSLATIONS[key] = catalog.messages[key];
this.PLURAL_EXPR = new Function('n', 'return +(' + catalog.plural_expr + ')');
this.LOCALE = catalog.locale;
},
/**
* add context elements like header anchor links
*/
addContextElements : function() {
$('div[id] > :header:first').each(function() {
$('<a class="headerlink">\u00B6</a>').
attr('href', '#' + this.id).
attr('title', _('Permalink to this headline')).
appendTo(this);
});
$('dt[id]').each(function() {
$('<a class="headerlink">\u00B6</a>').
attr('href', '#' + this.id).
attr('title', _('Permalink to this definition')).
appendTo(this);
});
},
/**
* workaround a firefox stupidity
* see: https://bugzilla.mozilla.org/show_bug.cgi?id=645075
*/
fixFirefoxAnchorBug : function() {
if (document.location.hash && $.browser.mozilla)
window.setTimeout(function() {
document.location.href += '';
}, 10);
},
/**
* highlight the search words provided in the url in the text
*/
highlightSearchWords : function() {
var params = $.getQueryParameters();
var terms = (params.highlight) ? params.highlight[0].split(/\s+/) : [];
if (terms.length) {
var body = $('div.body');
if (!body.length) {
body = $('body');
}
window.setTimeout(function() {
$.each(terms, function() {
body.highlightText(this.toLowerCase(), 'highlighted');
});
}, 10);
$('<p class="highlight-link"><a href="javascript:Documentation.' +
'hideSearchWords()">' + _('Hide Search Matches') + '</a></p>')
.appendTo($('#searchbox'));
}
},
/**
* init the domain index toggle buttons
*/
initIndexTable : function() {
var togglers = $('img.toggler').click(function() {
var src = $(this).attr('src');
var idnum = $(this).attr('id').substr(7);
$('tr.cg-' + idnum).toggle();
if (src.substr(-9) === 'minus.png')
$(this).attr('src', src.substr(0, src.length-9) + 'plus.png');
else
$(this).attr('src', src.substr(0, src.length-8) + 'minus.png');
}).css('display', '');
if (DOCUMENTATION_OPTIONS.COLLAPSE_INDEX) {
togglers.click();
}
},
/**
* helper function to hide the search marks again
*/
hideSearchWords : function() {
$('#searchbox .highlight-link').fadeOut(300);
$('span.highlighted').removeClass('highlighted');
},
/**
* make the url absolute
*/
makeURL : function(relativeURL) {
return DOCUMENTATION_OPTIONS.URL_ROOT + '/' + relativeURL;
},
/**
* get the current relative url
*/
getCurrentURL : function() {
var path = document.location.pathname;
var parts = path.split(/\//);
$.each(DOCUMENTATION_OPTIONS.URL_ROOT.split(/\//), function() {
if (this === '..')
parts.pop();
});
var url = parts.join('/');
return path.substring(url.lastIndexOf('/') + 1, path.length - 1);
},
initOnKeyListeners: function() {
$(document).keydown(function(event) {
var activeElementType = document.activeElement.tagName;
// don't navigate when in search box, textarea, dropdown or button
if (activeElementType !== 'TEXTAREA' && activeElementType !== 'INPUT' && activeElementType !== 'SELECT'
&& activeElementType !== 'BUTTON' && !event.altKey && !event.ctrlKey && !event.metaKey
&& !event.shiftKey) {
switch (event.keyCode) {
case 37: // left
var prevHref = $('link[rel="prev"]').prop('href');
if (prevHref) {
window.location.href = prevHref;
return false;
}
break;
case 39: // right
var nextHref = $('link[rel="next"]').prop('href');
if (nextHref) {
window.location.href = nextHref;
return false;
}
break;
}
}
});
}
};
// quick alias for translations
_ = Documentation.gettext;
$(document).ready(function() {
Documentation.init();
});

View File

@ -0,0 +1,12 @@
var DOCUMENTATION_OPTIONS = {
URL_ROOT: document.getElementById("documentation_options").getAttribute('data-url_root'),
VERSION: '2.0.0a',
LANGUAGE: 'None',
COLLAPSE_INDEX: false,
BUILDER: 'html',
FILE_SUFFIX: '.html',
LINK_SUFFIX: '.html',
HAS_SOURCE: true,
SOURCELINK_SUFFIX: '.txt',
NAVIGATION_WITH_KEYS: false
};

View File

@ -0,0 +1,10 @@
@font-face {
font-family: 'Custom Icons';
font-style: normal;
font-weight: 400;
src: url('icons.woff') format('woff2');
}
.custom-icons {
font-family: 'Custom Icons' !important;
}

Binary file not shown.

10872
docs/Python/html/_static/jquery-3.5.1.js vendored Normal file

File diff suppressed because it is too large Load Diff

2
docs/Python/html/_static/jquery.js vendored Normal file

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,382 @@
/*
* language_data.js
* ~~~~~~~~~~~~~~~~
*
* This script contains the language-specific data used by searchtools.js,
* namely the list of stopwords, stemmer, scorer and splitter.
*
* :copyright: Copyright 2007-2021 by the Sphinx team, see AUTHORS.
* :license: BSD, see LICENSE for details.
*
*/
var stopwords = ["a","and","are","as","at","be","but","by","for","if","in","into","is","it","near","no","not","of","on","or","such","that","the","their","then","there","these","they","this","to","was","will","with"];
/* Non-minified version is copied as a separate JS file, is available */
/**
* Porter Stemmer
*/
var Stemmer = function() {
var step2list = {
ational: 'ate',
tional: 'tion',
enci: 'ence',
anci: 'ance',
izer: 'ize',
bli: 'ble',
alli: 'al',
entli: 'ent',
eli: 'e',
ousli: 'ous',
ization: 'ize',
ation: 'ate',
ator: 'ate',
alism: 'al',
iveness: 'ive',
fulness: 'ful',
ousness: 'ous',
aliti: 'al',
iviti: 'ive',
biliti: 'ble',
logi: 'log'
};
var step3list = {
icate: 'ic',
ative: '',
alize: 'al',
iciti: 'ic',
ical: 'ic',
ful: '',
ness: ''
};
var c = "[^aeiou]"; // consonant
var v = "[aeiouy]"; // vowel
var C = c + "[^aeiouy]*"; // consonant sequence
var V = v + "[aeiou]*"; // vowel sequence
var mgr0 = "^(" + C + ")?" + V + C; // [C]VC... is m>0
var meq1 = "^(" + C + ")?" + V + C + "(" + V + ")?$"; // [C]VC[V] is m=1
var mgr1 = "^(" + C + ")?" + V + C + V + C; // [C]VCVC... is m>1
var s_v = "^(" + C + ")?" + v; // vowel in stem
this.stemWord = function (w) {
var stem;
var suffix;
var firstch;
var origword = w;
if (w.length < 3)
return w;
var re;
var re2;
var re3;
var re4;
firstch = w.substr(0,1);
if (firstch == "y")
w = firstch.toUpperCase() + w.substr(1);
// Step 1a
re = /^(.+?)(ss|i)es$/;
re2 = /^(.+?)([^s])s$/;
if (re.test(w))
w = w.replace(re,"$1$2");
else if (re2.test(w))
w = w.replace(re2,"$1$2");
// Step 1b
re = /^(.+?)eed$/;
re2 = /^(.+?)(ed|ing)$/;
if (re.test(w)) {
var fp = re.exec(w);
re = new RegExp(mgr0);
if (re.test(fp[1])) {
re = /.$/;
w = w.replace(re,"");
}
}
else if (re2.test(w)) {
var fp = re2.exec(w);
stem = fp[1];
re2 = new RegExp(s_v);
if (re2.test(stem)) {
w = stem;
re2 = /(at|bl|iz)$/;
re3 = new RegExp("([^aeiouylsz])\\1$");
re4 = new RegExp("^" + C + v + "[^aeiouwxy]$");
if (re2.test(w))
w = w + "e";
else if (re3.test(w)) {
re = /.$/;
w = w.replace(re,"");
}
else if (re4.test(w))
w = w + "e";
}
}
// Step 1c
re = /^(.+?)y$/;
if (re.test(w)) {
var fp = re.exec(w);
stem = fp[1];
re = new RegExp(s_v);
if (re.test(stem))
w = stem + "i";
}
// Step 2
re = /^(.+?)(ational|tional|enci|anci|izer|bli|alli|entli|eli|ousli|ization|ation|ator|alism|iveness|fulness|ousness|aliti|iviti|biliti|logi)$/;
if (re.test(w)) {
var fp = re.exec(w);
stem = fp[1];
suffix = fp[2];
re = new RegExp(mgr0);
if (re.test(stem))
w = stem + step2list[suffix];
}
// Step 3
re = /^(.+?)(icate|ative|alize|iciti|ical|ful|ness)$/;
if (re.test(w)) {
var fp = re.exec(w);
stem = fp[1];
suffix = fp[2];
re = new RegExp(mgr0);
if (re.test(stem))
w = stem + step3list[suffix];
}
// Step 4
re = /^(.+?)(al|ance|ence|er|ic|able|ible|ant|ement|ment|ent|ou|ism|ate|iti|ous|ive|ize)$/;
re2 = /^(.+?)(s|t)(ion)$/;
if (re.test(w)) {
var fp = re.exec(w);
stem = fp[1];
re = new RegExp(mgr1);
if (re.test(stem))
w = stem;
}
else if (re2.test(w)) {
var fp = re2.exec(w);
stem = fp[1] + fp[2];
re2 = new RegExp(mgr1);
if (re2.test(stem))
w = stem;
}
// Step 5
re = /^(.+?)e$/;
if (re.test(w)) {
var fp = re.exec(w);
stem = fp[1];
re = new RegExp(mgr1);
re2 = new RegExp(meq1);
re3 = new RegExp("^" + C + v + "[^aeiouwxy]$");
if (re.test(stem) || (re2.test(stem) && !(re3.test(stem))))
w = stem;
}
re = /ll$/;
re2 = new RegExp(mgr1);
if (re.test(w) && re2.test(w)) {
re = /.$/;
w = w.replace(re,"");
}
// and turn initial Y back to y
if (firstch == "y")
w = firstch.toLowerCase() + w.substr(1);
return w;
}
}
'use-strict';
let queryBeingDone = null;
let pattern = null;
const escapedRegex = /[-\/\\^$*+?.()|[\]{}]/g;
function escapeRegex(e) {
return e.replace(escapedRegex, '\\$&');
}
// for some reason Sphinx shows some entries twice
// if something has been scored already I'd rather sort it to the bottom
const beenScored = new Set();
function __score(haystack, regex) {
let match = regex.exec(haystack);
if (match == null) {
return Number.MAX_VALUE;
}
let subLength = match[0].length;
let start = match.index;
return (subLength * 1000 + start) / 1000.0;
}
// unused for now
function __cleanNamespaces(query) {
return query.replace(/(discord\.(ext\.)?)?(.+)/, '$3');
}
Scorer = {
// Implement the following function to further tweak the score for each result
// The function takes a result array [filename, title, anchor, descr, score]
// and returns the new score.
score: (result) => {
// only inflate the score of things that are actual API reference things
const [, title, , , score] = result;
if (pattern !== null && title.startsWith('discord.')) {
let _score = __score(title, pattern);
if (_score === Number.MAX_VALUE) {
return score;
}
if (beenScored.has(title)) {
return 0;
}
beenScored.add(title);
let newScore = 100 + queryBeingDone.length - _score;
// console.log(`${title}: ${score} -> ${newScore} (${_score})`);
return newScore;
}
return score;
},
// query matches the full name of an object
objNameMatch: 15,
// or matches in the last dotted part of the object name
objPartialMatch: 11,
// Additive scores depending on the priority of the object
objPrio: {
0: 15, // used to be importantResults
1: 7, // used to be objectResults
2: -5 // used to be unimportantResults
},
// Used when the priority is not in the mapping.
objPrioDefault: 0,
// query found in title
title: 15,
partialTitle: 7,
// query found in terms
term: 5,
partialTerm: 2
};
document.addEventListener('DOMContentLoaded', () => {
const params = new URLSearchParams(window.location.search);
queryBeingDone = params.get('q');
if (queryBeingDone) {
let pattern = Array.from(queryBeingDone).map(escapeRegex).join('.*?');
pattern = new RegExp(pattern, 'i');
}
});
var splitChars = (function() {
var result = {};
var singles = [96, 180, 187, 191, 215, 247, 749, 885, 903, 907, 909, 930, 1014, 1648,
1748, 1809, 2416, 2473, 2481, 2526, 2601, 2609, 2612, 2615, 2653, 2702,
2706, 2729, 2737, 2740, 2857, 2865, 2868, 2910, 2928, 2948, 2961, 2971,
2973, 3085, 3089, 3113, 3124, 3213, 3217, 3241, 3252, 3295, 3341, 3345,
3369, 3506, 3516, 3633, 3715, 3721, 3736, 3744, 3748, 3750, 3756, 3761,
3781, 3912, 4239, 4347, 4681, 4695, 4697, 4745, 4785, 4799, 4801, 4823,
4881, 5760, 5901, 5997, 6313, 7405, 8024, 8026, 8028, 8030, 8117, 8125,
8133, 8181, 8468, 8485, 8487, 8489, 8494, 8527, 11311, 11359, 11687, 11695,
11703, 11711, 11719, 11727, 11735, 12448, 12539, 43010, 43014, 43019, 43587,
43696, 43713, 64286, 64297, 64311, 64317, 64319, 64322, 64325, 65141];
var i, j, start, end;
for (i = 0; i < singles.length; i++) {
result[singles[i]] = true;
}
var ranges = [[0, 47], [58, 64], [91, 94], [123, 169], [171, 177], [182, 184], [706, 709],
[722, 735], [741, 747], [751, 879], [888, 889], [894, 901], [1154, 1161],
[1318, 1328], [1367, 1368], [1370, 1376], [1416, 1487], [1515, 1519], [1523, 1568],
[1611, 1631], [1642, 1645], [1750, 1764], [1767, 1773], [1789, 1790], [1792, 1807],
[1840, 1868], [1958, 1968], [1970, 1983], [2027, 2035], [2038, 2041], [2043, 2047],
[2070, 2073], [2075, 2083], [2085, 2087], [2089, 2307], [2362, 2364], [2366, 2383],
[2385, 2391], [2402, 2405], [2419, 2424], [2432, 2436], [2445, 2446], [2449, 2450],
[2483, 2485], [2490, 2492], [2494, 2509], [2511, 2523], [2530, 2533], [2546, 2547],
[2554, 2564], [2571, 2574], [2577, 2578], [2618, 2648], [2655, 2661], [2672, 2673],
[2677, 2692], [2746, 2748], [2750, 2767], [2769, 2783], [2786, 2789], [2800, 2820],
[2829, 2830], [2833, 2834], [2874, 2876], [2878, 2907], [2914, 2917], [2930, 2946],
[2955, 2957], [2966, 2968], [2976, 2978], [2981, 2983], [2987, 2989], [3002, 3023],
[3025, 3045], [3059, 3076], [3130, 3132], [3134, 3159], [3162, 3167], [3170, 3173],
[3184, 3191], [3199, 3204], [3258, 3260], [3262, 3293], [3298, 3301], [3312, 3332],
[3386, 3388], [3390, 3423], [3426, 3429], [3446, 3449], [3456, 3460], [3479, 3481],
[3518, 3519], [3527, 3584], [3636, 3647], [3655, 3663], [3674, 3712], [3717, 3718],
[3723, 3724], [3726, 3731], [3752, 3753], [3764, 3772], [3774, 3775], [3783, 3791],
[3802, 3803], [3806, 3839], [3841, 3871], [3892, 3903], [3949, 3975], [3980, 4095],
[4139, 4158], [4170, 4175], [4182, 4185], [4190, 4192], [4194, 4196], [4199, 4205],
[4209, 4212], [4226, 4237], [4250, 4255], [4294, 4303], [4349, 4351], [4686, 4687],
[4702, 4703], [4750, 4751], [4790, 4791], [4806, 4807], [4886, 4887], [4955, 4968],
[4989, 4991], [5008, 5023], [5109, 5120], [5741, 5742], [5787, 5791], [5867, 5869],
[5873, 5887], [5906, 5919], [5938, 5951], [5970, 5983], [6001, 6015], [6068, 6102],
[6104, 6107], [6109, 6111], [6122, 6127], [6138, 6159], [6170, 6175], [6264, 6271],
[6315, 6319], [6390, 6399], [6429, 6469], [6510, 6511], [6517, 6527], [6572, 6592],
[6600, 6607], [6619, 6655], [6679, 6687], [6741, 6783], [6794, 6799], [6810, 6822],
[6824, 6916], [6964, 6980], [6988, 6991], [7002, 7042], [7073, 7085], [7098, 7167],
[7204, 7231], [7242, 7244], [7294, 7400], [7410, 7423], [7616, 7679], [7958, 7959],
[7966, 7967], [8006, 8007], [8014, 8015], [8062, 8063], [8127, 8129], [8141, 8143],
[8148, 8149], [8156, 8159], [8173, 8177], [8189, 8303], [8306, 8307], [8314, 8318],
[8330, 8335], [8341, 8449], [8451, 8454], [8456, 8457], [8470, 8472], [8478, 8483],
[8506, 8507], [8512, 8516], [8522, 8525], [8586, 9311], [9372, 9449], [9472, 10101],
[10132, 11263], [11493, 11498], [11503, 11516], [11518, 11519], [11558, 11567],
[11622, 11630], [11632, 11647], [11671, 11679], [11743, 11822], [11824, 12292],
[12296, 12320], [12330, 12336], [12342, 12343], [12349, 12352], [12439, 12444],
[12544, 12548], [12590, 12592], [12687, 12689], [12694, 12703], [12728, 12783],
[12800, 12831], [12842, 12880], [12896, 12927], [12938, 12976], [12992, 13311],
[19894, 19967], [40908, 40959], [42125, 42191], [42238, 42239], [42509, 42511],
[42540, 42559], [42592, 42593], [42607, 42622], [42648, 42655], [42736, 42774],
[42784, 42785], [42889, 42890], [42893, 43002], [43043, 43055], [43062, 43071],
[43124, 43137], [43188, 43215], [43226, 43249], [43256, 43258], [43260, 43263],
[43302, 43311], [43335, 43359], [43389, 43395], [43443, 43470], [43482, 43519],
[43561, 43583], [43596, 43599], [43610, 43615], [43639, 43641], [43643, 43647],
[43698, 43700], [43703, 43704], [43710, 43711], [43715, 43738], [43742, 43967],
[44003, 44015], [44026, 44031], [55204, 55215], [55239, 55242], [55292, 55295],
[57344, 63743], [64046, 64047], [64110, 64111], [64218, 64255], [64263, 64274],
[64280, 64284], [64434, 64466], [64830, 64847], [64912, 64913], [64968, 65007],
[65020, 65135], [65277, 65295], [65306, 65312], [65339, 65344], [65371, 65381],
[65471, 65473], [65480, 65481], [65488, 65489], [65496, 65497]];
for (i = 0; i < ranges.length; i++) {
start = ranges[i][0];
end = ranges[i][1];
for (j = start; j <= end; j++) {
result[j] = true;
}
}
return result;
})();
function splitQuery(query) {
var result = [];
var start = -1;
for (var i = 0; i < query.length; i++) {
if (splitChars[query.charCodeAt(i)]) {
if (start !== -1) {
result.push(query.slice(start, i));
start = -1;
}
} else if (start === -1) {
start = i;
}
}
if (start !== -1) {
result.push(query.slice(start));
}
return result;
}

View File

@ -0,0 +1,69 @@
.highlight .hll { background-color: #ffffcc }
.highlight { background: #f0f0f0; }
.highlight .c { color: #60a0b0; font-style: italic } /* Comment */
.highlight .err { border: 1px solid #FF0000 } /* Error */
.highlight .k { color: #007020; font-weight: bold } /* Keyword */
.highlight .o { color: #666666 } /* Operator */
.highlight .ch { color: #60a0b0; font-style: italic } /* Comment.Hashbang */
.highlight .cm { color: #60a0b0; font-style: italic } /* Comment.Multiline */
.highlight .cp { color: #007020 } /* Comment.Preproc */
.highlight .cpf { color: #60a0b0; font-style: italic } /* Comment.PreprocFile */
.highlight .c1 { color: #60a0b0; font-style: italic } /* Comment.Single */
.highlight .cs { color: #60a0b0; background-color: #fff0f0 } /* Comment.Special */
.highlight .gd { color: #A00000 } /* Generic.Deleted */
.highlight .ge { font-style: italic } /* Generic.Emph */
.highlight .gr { color: #FF0000 } /* Generic.Error */
.highlight .gh { color: #000080; font-weight: bold } /* Generic.Heading */
.highlight .gi { color: #00A000 } /* Generic.Inserted */
.highlight .go { color: #888888 } /* Generic.Output */
.highlight .gp { color: #c65d09; font-weight: bold } /* Generic.Prompt */
.highlight .gs { font-weight: bold } /* Generic.Strong */
.highlight .gu { color: #800080; font-weight: bold } /* Generic.Subheading */
.highlight .gt { color: #0044DD } /* Generic.Traceback */
.highlight .kc { color: #007020; font-weight: bold } /* Keyword.Constant */
.highlight .kd { color: #007020; font-weight: bold } /* Keyword.Declaration */
.highlight .kn { color: #007020; font-weight: bold } /* Keyword.Namespace */
.highlight .kp { color: #007020 } /* Keyword.Pseudo */
.highlight .kr { color: #007020; font-weight: bold } /* Keyword.Reserved */
.highlight .kt { color: #902000 } /* Keyword.Type */
.highlight .m { color: #40a070 } /* Literal.Number */
.highlight .s { color: #4070a0 } /* Literal.String */
.highlight .na { color: #4070a0 } /* Name.Attribute */
.highlight .nb { color: #007020 } /* Name.Builtin */
.highlight .nc { color: #0e84b5; font-weight: bold } /* Name.Class */
.highlight .no { color: #60add5 } /* Name.Constant */
.highlight .nd { color: #555555; font-weight: bold } /* Name.Decorator */
.highlight .ni { color: #d55537; font-weight: bold } /* Name.Entity */
.highlight .ne { color: #007020 } /* Name.Exception */
.highlight .nf { color: #06287e } /* Name.Function */
.highlight .nl { color: #002070; font-weight: bold } /* Name.Label */
.highlight .nn { color: #0e84b5; font-weight: bold } /* Name.Namespace */
.highlight .nt { color: #062873; font-weight: bold } /* Name.Tag */
.highlight .nv { color: #bb60d5 } /* Name.Variable */
.highlight .ow { color: #007020; font-weight: bold } /* Operator.Word */
.highlight .w { color: #bbbbbb } /* Text.Whitespace */
.highlight .mb { color: #40a070 } /* Literal.Number.Bin */
.highlight .mf { color: #40a070 } /* Literal.Number.Float */
.highlight .mh { color: #40a070 } /* Literal.Number.Hex */
.highlight .mi { color: #40a070 } /* Literal.Number.Integer */
.highlight .mo { color: #40a070 } /* Literal.Number.Oct */
.highlight .sa { color: #4070a0 } /* Literal.String.Affix */
.highlight .sb { color: #4070a0 } /* Literal.String.Backtick */
.highlight .sc { color: #4070a0 } /* Literal.String.Char */
.highlight .dl { color: #4070a0 } /* Literal.String.Delimiter */
.highlight .sd { color: #4070a0; font-style: italic } /* Literal.String.Doc */
.highlight .s2 { color: #4070a0 } /* Literal.String.Double */
.highlight .se { color: #4070a0; font-weight: bold } /* Literal.String.Escape */
.highlight .sh { color: #4070a0 } /* Literal.String.Heredoc */
.highlight .si { color: #70a0d0; font-style: italic } /* Literal.String.Interpol */
.highlight .sx { color: #c65d09 } /* Literal.String.Other */
.highlight .sr { color: #235388 } /* Literal.String.Regex */
.highlight .s1 { color: #4070a0 } /* Literal.String.Single */
.highlight .ss { color: #517918 } /* Literal.String.Symbol */
.highlight .bp { color: #007020 } /* Name.Builtin.Pseudo */
.highlight .fm { color: #06287e } /* Name.Function.Magic */
.highlight .vc { color: #bb60d5 } /* Name.Variable.Class */
.highlight .vg { color: #bb60d5 } /* Name.Variable.Global */
.highlight .vi { color: #bb60d5 } /* Name.Variable.Instance */
.highlight .vm { color: #bb60d5 } /* Name.Variable.Magic */
.highlight .il { color: #40a070 } /* Literal.Number.Integer.Long */

View File

@ -0,0 +1,83 @@
'use-strict';
let queryBeingDone = null;
let pattern = null;
const escapedRegex = /[-\/\\^$*+?.()|[\]{}]/g;
function escapeRegex(e) {
return e.replace(escapedRegex, '\\$&');
}
// for some reason Sphinx shows some entries twice
// if something has been scored already I'd rather sort it to the bottom
const beenScored = new Set();
function __score(haystack, regex) {
let match = regex.exec(haystack);
if (match == null) {
return Number.MAX_VALUE;
}
let subLength = match[0].length;
let start = match.index;
return (subLength * 1000 + start) / 1000.0;
}
// unused for now
function __cleanNamespaces(query) {
return query.replace(/(discord\.(ext\.)?)?(.+)/, '$3');
}
Scorer = {
// Implement the following function to further tweak the score for each result
// The function takes a result array [filename, title, anchor, descr, score]
// and returns the new score.
score: (result) => {
// only inflate the score of things that are actual API reference things
const [, title, , , score] = result;
if (pattern !== null && title.startsWith('discord.')) {
let _score = __score(title, pattern);
if (_score === Number.MAX_VALUE) {
return score;
}
if (beenScored.has(title)) {
return 0;
}
beenScored.add(title);
let newScore = 100 + queryBeingDone.length - _score;
// console.log(`${title}: ${score} -> ${newScore} (${_score})`);
return newScore;
}
return score;
},
// query matches the full name of an object
objNameMatch: 15,
// or matches in the last dotted part of the object name
objPartialMatch: 11,
// Additive scores depending on the priority of the object
objPrio: {
0: 15, // used to be importantResults
1: 7, // used to be objectResults
2: -5 // used to be unimportantResults
},
// Used when the priority is not in the mapping.
objPrioDefault: 0,
// query found in title
title: 15,
partialTitle: 7,
// query found in terms
term: 5,
partialTerm: 2
};
document.addEventListener('DOMContentLoaded', () => {
const params = new URLSearchParams(window.location.search);
queryBeingDone = params.get('q');
if (queryBeingDone) {
let pattern = Array.from(queryBeingDone).map(escapeRegex).join('.*?');
pattern = new RegExp(pattern, 'i');
}
});

View File

@ -0,0 +1,528 @@
/*
* searchtools.js
* ~~~~~~~~~~~~~~~~
*
* Sphinx JavaScript utilities for the full-text search.
*
* :copyright: Copyright 2007-2021 by the Sphinx team, see AUTHORS.
* :license: BSD, see LICENSE for details.
*
*/
if (!Scorer) {
/**
* Simple result scoring code.
*/
var Scorer = {
// Implement the following function to further tweak the score for each result
// The function takes a result array [filename, title, anchor, descr, score]
// and returns the new score.
/*
score: function(result) {
return result[4];
},
*/
// query matches the full name of an object
objNameMatch: 11,
// or matches in the last dotted part of the object name
objPartialMatch: 6,
// Additive scores depending on the priority of the object
objPrio: {0: 15, // used to be importantResults
1: 5, // used to be objectResults
2: -5}, // used to be unimportantResults
// Used when the priority is not in the mapping.
objPrioDefault: 0,
// query found in title
title: 15,
partialTitle: 7,
// query found in terms
term: 5,
partialTerm: 2
};
}
if (!splitQuery) {
function splitQuery(query) {
return query.split(/\s+/);
}
}
/**
* Search Module
*/
var Search = {
_index : null,
_queued_query : null,
_pulse_status : -1,
htmlToText : function(htmlString) {
var virtualDocument = document.implementation.createHTMLDocument('virtual');
var htmlElement = $(htmlString, virtualDocument);
htmlElement.find('.headerlink').remove();
docContent = htmlElement.find('[role=main]')[0];
if(docContent === undefined) {
console.warn("Content block not found. Sphinx search tries to obtain it " +
"via '[role=main]'. Could you check your theme or template.");
return "";
}
return docContent.textContent || docContent.innerText;
},
init : function() {
var params = $.getQueryParameters();
if (params.q) {
var query = params.q[0];
$('input[name="q"]')[0].value = query;
this.performSearch(query);
}
},
loadIndex : function(url) {
$.ajax({type: "GET", url: url, data: null,
dataType: "script", cache: true,
complete: function(jqxhr, textstatus) {
if (textstatus != "success") {
document.getElementById("searchindexloader").src = url;
}
}});
},
setIndex : function(index) {
var q;
this._index = index;
if ((q = this._queued_query) !== null) {
this._queued_query = null;
Search.query(q);
}
},
hasIndex : function() {
return this._index !== null;
},
deferQuery : function(query) {
this._queued_query = query;
},
stopPulse : function() {
this._pulse_status = 0;
},
startPulse : function() {
if (this._pulse_status >= 0)
return;
function pulse() {
var i;
Search._pulse_status = (Search._pulse_status + 1) % 4;
var dotString = '';
for (i = 0; i < Search._pulse_status; i++)
dotString += '.';
Search.dots.text(dotString);
if (Search._pulse_status > -1)
window.setTimeout(pulse, 500);
}
pulse();
},
/**
* perform a search for something (or wait until index is loaded)
*/
performSearch : function(query) {
// create the required interface elements
this.out = $('#search-results');
this.title = $('<h2>' + _('Searching') + '</h2>').appendTo(this.out);
this.dots = $('<span></span>').appendTo(this.title);
this.status = $('<p class="search-summary">&nbsp;</p>').appendTo(this.out);
this.output = $('<ul class="search"/>').appendTo(this.out);
$('#search-progress').text(_('Preparing search...'));
this.startPulse();
// index already loaded, the browser was quick!
if (this.hasIndex())
this.query(query);
else
this.deferQuery(query);
},
/**
* execute search (requires search index to be loaded)
*/
query : function(query) {
var i;
// stem the searchterms and add them to the correct list
var stemmer = new Stemmer();
var searchterms = [];
var excluded = [];
var hlterms = [];
var tmp = splitQuery(query);
var objectterms = [];
for (i = 0; i < tmp.length; i++) {
if (tmp[i] !== "") {
objectterms.push(tmp[i].toLowerCase());
}
if ($u.indexOf(stopwords, tmp[i].toLowerCase()) != -1 || tmp[i] === "") {
// skip this "word"
continue;
}
// stem the word
var word = stemmer.stemWord(tmp[i].toLowerCase());
// prevent stemmer from cutting word smaller than two chars
if(word.length < 3 && tmp[i].length >= 3) {
word = tmp[i];
}
var toAppend;
// select the correct list
if (word[0] == '-') {
toAppend = excluded;
word = word.substr(1);
}
else {
toAppend = searchterms;
hlterms.push(tmp[i].toLowerCase());
}
// only add if not already in the list
if (!$u.contains(toAppend, word))
toAppend.push(word);
}
var highlightstring = '?highlight=' + $.urlencode(hlterms.join(" "));
// console.debug('SEARCH: searching for:');
// console.info('required: ', searchterms);
// console.info('excluded: ', excluded);
// prepare search
var terms = this._index.terms;
var titleterms = this._index.titleterms;
// array of [filename, title, anchor, descr, score]
var results = [];
$('#search-progress').empty();
// lookup as object
for (i = 0; i < objectterms.length; i++) {
var others = [].concat(objectterms.slice(0, i),
objectterms.slice(i+1, objectterms.length));
results = results.concat(this.performObjectSearch(objectterms[i], others));
}
// lookup as search terms in fulltext
results = results.concat(this.performTermsSearch(searchterms, excluded, terms, titleterms));
// let the scorer override scores with a custom scoring function
if (Scorer.score) {
for (i = 0; i < results.length; i++)
results[i][4] = Scorer.score(results[i]);
}
// now sort the results by score (in opposite order of appearance, since the
// display function below uses pop() to retrieve items) and then
// alphabetically
results.sort(function(a, b) {
var left = a[4];
var right = b[4];
if (left > right) {
return 1;
} else if (left < right) {
return -1;
} else {
// same score: sort alphabetically
left = a[1].toLowerCase();
right = b[1].toLowerCase();
return (left > right) ? -1 : ((left < right) ? 1 : 0);
}
});
// for debugging
//Search.lastresults = results.slice(); // a copy
//console.info('search results:', Search.lastresults);
// print the results
var resultCount = results.length;
function displayNextItem() {
// results left, load the summary and display it
if (results.length) {
var item = results.pop();
var listItem = $('<li></li>');
var requestUrl = "";
var linkUrl = "";
if (DOCUMENTATION_OPTIONS.BUILDER === 'dirhtml') {
// dirhtml builder
var dirname = item[0] + '/';
if (dirname.match(/\/index\/$/)) {
dirname = dirname.substring(0, dirname.length-6);
} else if (dirname == 'index/') {
dirname = '';
}
requestUrl = DOCUMENTATION_OPTIONS.URL_ROOT + dirname;
linkUrl = requestUrl;
} else {
// normal html builders
requestUrl = DOCUMENTATION_OPTIONS.URL_ROOT + item[0] + DOCUMENTATION_OPTIONS.FILE_SUFFIX;
linkUrl = item[0] + DOCUMENTATION_OPTIONS.LINK_SUFFIX;
}
listItem.append($('<a/>').attr('href',
linkUrl +
highlightstring + item[2]).html(item[1]));
if (item[3]) {
listItem.append($('<span> (' + item[3] + ')</span>'));
Search.output.append(listItem);
setTimeout(function() {
displayNextItem();
}, 5);
} else if (DOCUMENTATION_OPTIONS.HAS_SOURCE) {
$.ajax({url: requestUrl,
dataType: "text",
complete: function(jqxhr, textstatus) {
var data = jqxhr.responseText;
if (data !== '' && data !== undefined) {
var summary = Search.makeSearchSummary(data, searchterms, hlterms);
if (summary) {
listItem.append(summary);
}
}
Search.output.append(listItem);
setTimeout(function() {
displayNextItem();
}, 5);
}});
} else {
// no source available, just display title
Search.output.append(listItem);
setTimeout(function() {
displayNextItem();
}, 5);
}
}
// search finished, update title and status message
else {
Search.stopPulse();
Search.title.text(_('Search Results'));
if (!resultCount)
Search.status.text(_('Your search did not match any documents. Please make sure that all words are spelled correctly and that you\'ve selected enough categories.'));
else
Search.status.text(_('Search finished, found %s page(s) matching the search query.').replace('%s', resultCount));
Search.status.fadeIn(500);
}
}
displayNextItem();
},
/**
* search for object names
*/
performObjectSearch : function(object, otherterms) {
var filenames = this._index.filenames;
var docnames = this._index.docnames;
var objects = this._index.objects;
var objnames = this._index.objnames;
var titles = this._index.titles;
var i;
var results = [];
for (var prefix in objects) {
for (var name in objects[prefix]) {
var fullname = (prefix ? prefix + '.' : '') + name;
var fullnameLower = fullname.toLowerCase()
if (fullnameLower.indexOf(object) > -1) {
var score = 0;
var parts = fullnameLower.split('.');
// check for different match types: exact matches of full name or
// "last name" (i.e. last dotted part)
if (fullnameLower == object || parts[parts.length - 1] == object) {
score += Scorer.objNameMatch;
// matches in last name
} else if (parts[parts.length - 1].indexOf(object) > -1) {
score += Scorer.objPartialMatch;
}
var match = objects[prefix][name];
var objname = objnames[match[1]][2];
var title = titles[match[0]];
// If more than one term searched for, we require other words to be
// found in the name/title/description
if (otherterms.length > 0) {
var haystack = (prefix + ' ' + name + ' ' +
objname + ' ' + title).toLowerCase();
var allfound = true;
for (i = 0; i < otherterms.length; i++) {
if (haystack.indexOf(otherterms[i]) == -1) {
allfound = false;
break;
}
}
if (!allfound) {
continue;
}
}
var descr = objname + _(', in ') + title;
var anchor = match[3];
if (anchor === '')
anchor = fullname;
else if (anchor == '-')
anchor = objnames[match[1]][1] + '-' + fullname;
// add custom score for some objects according to scorer
if (Scorer.objPrio.hasOwnProperty(match[2])) {
score += Scorer.objPrio[match[2]];
} else {
score += Scorer.objPrioDefault;
}
results.push([docnames[match[0]], fullname, '#'+anchor, descr, score, filenames[match[0]]]);
}
}
}
return results;
},
/**
* See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions
*/
escapeRegExp : function(string) {
return string.replace(/[.*+\-?^${}()|[\]\\]/g, '\\$&'); // $& means the whole matched string
},
/**
* search for full-text terms in the index
*/
performTermsSearch : function(searchterms, excluded, terms, titleterms) {
var docnames = this._index.docnames;
var filenames = this._index.filenames;
var titles = this._index.titles;
var i, j, file;
var fileMap = {};
var scoreMap = {};
var results = [];
// perform the search on the required terms
for (i = 0; i < searchterms.length; i++) {
var word = searchterms[i];
var files = [];
var _o = [
{files: terms[word], score: Scorer.term},
{files: titleterms[word], score: Scorer.title}
];
// add support for partial matches
if (word.length > 2) {
var word_regex = this.escapeRegExp(word);
for (var w in terms) {
if (w.match(word_regex) && !terms[word]) {
_o.push({files: terms[w], score: Scorer.partialTerm})
}
}
for (var w in titleterms) {
if (w.match(word_regex) && !titleterms[word]) {
_o.push({files: titleterms[w], score: Scorer.partialTitle})
}
}
}
// no match but word was a required one
if ($u.every(_o, function(o){return o.files === undefined;})) {
break;
}
// found search word in contents
$u.each(_o, function(o) {
var _files = o.files;
if (_files === undefined)
return
if (_files.length === undefined)
_files = [_files];
files = files.concat(_files);
// set score for the word in each file to Scorer.term
for (j = 0; j < _files.length; j++) {
file = _files[j];
if (!(file in scoreMap))
scoreMap[file] = {};
scoreMap[file][word] = o.score;
}
});
// create the mapping
for (j = 0; j < files.length; j++) {
file = files[j];
if (file in fileMap && fileMap[file].indexOf(word) === -1)
fileMap[file].push(word);
else
fileMap[file] = [word];
}
}
// now check if the files don't contain excluded terms
for (file in fileMap) {
var valid = true;
// check if all requirements are matched
var filteredTermCount = // as search terms with length < 3 are discarded: ignore
searchterms.filter(function(term){return term.length > 2}).length
if (
fileMap[file].length != searchterms.length &&
fileMap[file].length != filteredTermCount
) continue;
// ensure that none of the excluded terms is in the search result
for (i = 0; i < excluded.length; i++) {
if (terms[excluded[i]] == file ||
titleterms[excluded[i]] == file ||
$u.contains(terms[excluded[i]] || [], file) ||
$u.contains(titleterms[excluded[i]] || [], file)) {
valid = false;
break;
}
}
// if we have still a valid result we can add it to the result list
if (valid) {
// select one (max) score for the file.
// for better ranking, we should calculate ranking by using words statistics like basic tf-idf...
var score = $u.max($u.map(fileMap[file], function(w){return scoreMap[file][w]}));
results.push([docnames[file], titles[file], '', null, score, filenames[file]]);
}
}
return results;
},
/**
* helper function to return a node containing the
* search summary for a given text. keywords is a list
* of stemmed words, hlwords is the list of normal, unstemmed
* words. the first one is used to find the occurrence, the
* latter for highlighting it.
*/
makeSearchSummary : function(htmlText, keywords, hlwords) {
var text = Search.htmlToText(htmlText);
if (text == "") {
return null;
}
var textLower = text.toLowerCase();
var start = 0;
$.each(keywords, function() {
var i = textLower.indexOf(this.toLowerCase());
if (i > -1)
start = i;
});
start = Math.max(start - 120, 0);
var excerpt = ((start > 0) ? '...' : '') +
$.trim(text.substr(start, 240)) +
((start + 240 - text.length) ? '...' : '');
var rv = $('<p class="context"></p>').text(excerpt);
$.each(hlwords, function() {
rv = rv.highlightText(this, 'highlighted');
});
return rv;
}
};
$(document).ready(function() {
Search.init();
});

View File

@ -0,0 +1,106 @@
'use-strict';
let settingsModal;
class Setting {
constructor(name, defaultValue, setter) {
this.name = name;
this.defaultValue = defaultValue;
this.setValue = setter;
}
setElement() {
throw new TypeError('Abstract methods should be implemented.');
}
load() {
let value = JSON.parse(localStorage.getItem(this.name));
this.value = value === null ? this.defaultValue : value;
try {
this.setValue(this.value);
} catch (error) {
console.error(`Failed to apply setting "${this.name}" With value:`, this.value);
console.error(error);
}
}
update() {
throw new TypeError('Abstract methods should be implemented.');
}
}
class CheckboxSetting extends Setting {
setElement() {
let element = document.querySelector(`input[name=${this.name}]`);
element.checked = this.value;
}
update(element) {
localStorage.setItem(this.name, element.checked);
this.setValue(element.checked);
}
}
class RadioSetting extends Setting {
setElement() {
let element = document.querySelector(`input[name=${this.name}][value=${this.value}]`);
element.checked = true;
}
update(element) {
localStorage.setItem(this.name, `"${element.value}"`);
this.setValue(element.value);
}
}
function getRootAttributeToggle(attributeName, valueName) {
function toggleRootAttribute(set) {
if (set) {
document.documentElement.setAttribute(`data-${attributeName}`, valueName);
} else {
document.documentElement.removeAttribute(`data-${attributeName}`);
}
}
return toggleRootAttribute;
}
function setTheme(value) {
if (value === 'automatic') {
if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) {
document.documentElement.setAttribute('data-theme', 'dark');
} else {
document.documentElement.setAttribute('data-theme', 'light');
}
}
else {
document.documentElement.setAttribute('data-theme', value);
}
}
const settings = [
new CheckboxSetting('useSerifFont', false, getRootAttributeToggle('font', 'serif')),
new RadioSetting('setTheme', 'automatic', setTheme)
]
function updateSetting(element) {
let setting = settings.find((s) => s.name == element.name);
if (setting) {
setting.update(element);
}
}
for (const setting of settings) {
setting.load();
}
document.addEventListener('DOMContentLoaded', () => {
settingsModal = new Modal(document.querySelector('div#settings.modal'));
for (const setting of settings) {
setting.setElement();
}
});

View File

@ -0,0 +1,127 @@
class Sidebar {
constructor(element) {
this.element = element;
this.activeLink = null;
this.element.addEventListener('click', (e) => {
// If we click a navigation, close the hamburger menu
if (e.target.tagName == 'A' && this.element.classList.contains('sidebar-toggle')) {
this.element.classList.remove('sidebar-toggle');
let button = hamburgerToggle.firstElementChild;
button.textContent = 'menu';
// Scroll a little up to actually see the header
// Note: this is generally around ~55px
// A proper solution is getComputedStyle but it can be slow
// Instead let's just rely on this quirk and call it a day
// This has to be done after the browser actually processes
// the section movement
setTimeout(() => window.scrollBy(0, -100), 75);
}
});
}
createCollapsableSections() {
let toc = this.element.querySelector('ul');
if (!toc) {
return
}
let allReferences = toc.querySelectorAll('a.reference.internal:not([href="#"])');
for (let ref of allReferences) {
let next = ref.nextElementSibling;
if (next && next.tagName === "UL") {
let icon = document.createElement('span');
icon.className = 'material-icons collapsible-arrow expanded';
icon.innerText = 'expand_more';
if (next.parentElement.tagName == "LI") {
next.parentElement.classList.add('no-list-style')
}
icon.addEventListener('click', () => {
if (icon.classList.contains('expanded')) {
this.collapseSection(icon);
} else {
this.expandSection(icon);
}
})
ref.classList.add('ref-internal-padding')
ref.parentNode.insertBefore(icon, ref);
}
}
}
resize() {
let rect = this.element.getBoundingClientRect();
this.element.style.height = `calc(100vh - 1em - ${rect.top + document.body.offsetTop}px)`;
}
collapseSection(icon) {
icon.classList.remove('expanded');
icon.classList.add('collapsed');
let children = icon.nextElementSibling.nextElementSibling;
// <arrow><heading>
// --> <square><children>
setTimeout(() => children.style.display = "none", 75)
}
expandSection(icon) {
icon.classList.remove('collapse');
icon.classList.add('expanded');
let children = icon.nextElementSibling.nextElementSibling;
setTimeout(() => children.style.display = "block", 75)
}
setActiveLink(section) {
if (this.activeLink) {
this.activeLink.parentElement.classList.remove('active');
}
if (section) {
this.activeLink = document.querySelector(`#sidebar a[href="#${section.id}"]`);
if (this.activeLink) {
let headingChildren = this.activeLink.parentElement.parentElement;
let heading = headingChildren.previousElementSibling.previousElementSibling;
if (heading && headingChildren.style.display === 'none') {
this.activeLink = heading;
}
this.activeLink.parentElement.classList.add('active');
}
}
}
}
function getCurrentSection() {
let currentSection;
if (window.scrollY + window.innerHeight > bottomHeightThreshold) {
currentSection = sections[sections.length - 1];
}
else {
if (sections) {
sections.forEach(section => {
let rect = section.getBoundingClientRect();
if (rect.top + document.body.offsetTop < 1) {
currentSection = section;
}
});
}
}
return currentSection;
}
document.addEventListener('DOMContentLoaded', () => {
sidebar = new Sidebar(document.getElementById('sidebar'));
sidebar.resize();
sidebar.createCollapsableSections();
window.addEventListener('scroll', () => {
sidebar.setActiveLink(getCurrentSection());
sidebar.resize();
});
});

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

34431
docs/Python/html/api.html Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,234 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Creating a Bot Account</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="#">Creating a Bot Account</a><ul>
<li><a class="reference internal" href="#inviting-your-bot">Inviting Your Bot</a></li>
</ul>
</li>
</ul>
</div>
</aside>
<main class="grid-item" role="main">
<section id="creating-a-bot-account">
<span id="discord-intro"></span><h1>Creating a Bot Account<a class="headerlink" href="#creating-a-bot-account" title="Permalink to this headline"></a></h1>
<p>In order to work with the library and the Discord API in general, we must first create a Discord Bot account.</p>
<p>Creating a Bot account is a pretty straightforward process.</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 “New Application” button.</p>
<blockquote>
<div><img alt="The new application button." src="_images/discord_create_app_button.png" />
</div></blockquote>
</li>
<li><p>Give the application a name and click “Create”.</p>
<blockquote>
<div><img alt="The new application form filled in." src="_images/discord_create_app_form.png" />
</div></blockquote>
</li>
<li><p>Create a Bot User by navigating to the “Bot” tab and clicking “Add Bot”.</p>
<blockquote>
<div><ul class="simple">
<li><p>Click “Yes, do it!” to continue.</p></li>
</ul>
<img alt="The Add Bot button." src="_images/discord_create_bot_user.png" />
</div></blockquote>
</li>
<li><p>Make sure that <strong>Public Bot</strong> is ticked if you want others to invite your bot.</p>
<blockquote>
<div><ul class="simple">
<li><p>You should also make sure that <strong>Require OAuth2 Code Grant</strong> is unchecked unless you
are developing a service that needs it. If youre unsure, then <strong>leave it unchecked</strong>.</p></li>
</ul>
<img alt="How the Bot User options should look like for most people." src="_images/discord_bot_user_options.png" />
</div></blockquote>
</li>
<li><p>Copy the token using the “Copy” button.</p>
<blockquote>
<div><ul class="simple">
<li><p><strong>This is not the Client Secret at the General Information page.</strong></p></li>
</ul>
<div class="admonition warning">
<p class="admonition-title">Warning</p>
<p>It should be worth noting that this token is essentially your bots
password. You should <strong>never</strong> share this with someone else. In doing so,
someone can log in to your bot and do malicious things, such as leaving
servers, ban all members inside a server, or pinging everyone maliciously.</p>
<p>The possibilities are endless, so <strong>do not share this token.</strong></p>
<p>If you accidentally leaked your token, click the “Regenerate” button as soon
as possible. This revokes your old token and re-generates a new one.
Now you need to use the new token to login.</p>
</div>
</div></blockquote>
</li>
</ol>
<p>And thats it. You now have a bot account and you can login with that token.</p>
<section id="inviting-your-bot">
<span id="discord-invite-bot"></span><h2>Inviting Your Bot<a class="headerlink" href="#inviting-your-bot" title="Permalink to this headline"></a></h2>
<p>So youve made a Bot User but its not actually in any server.</p>
<p>If you want to invite your bot you must create an invite URL for it.</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 your bots page.</p></li>
<li><p>Go to the “OAuth2” tab.</p>
<blockquote>
<div><img alt="How the OAuth2 page should look like." src="_images/discord_oauth2.png" />
</div></blockquote>
</li>
<li><p>Tick the “bot” checkbox under “scopes”.</p>
<blockquote>
<div><img alt="The scopes checkbox with &quot;bot&quot; ticked." src="_images/discord_oauth2_scope.png" />
</div></blockquote>
</li>
<li><p>Tick the permissions required for your bot to function under “Bot Permissions”.</p>
<blockquote>
<div><ul class="simple">
<li><p>Please be aware of the consequences of requiring your bot to have the “Administrator” permission.</p></li>
<li><p>Bot owners must have 2FA enabled for certain actions and permissions when added in servers that have Server-Wide 2FA enabled. Check the <a class="reference external" href="https://support.discord.com/hc/en-us/articles/219576828-Setting-up-Two-Factor-Authentication">2FA support page</a> for more information.</p></li>
</ul>
<img alt="The permission checkboxes with some permissions checked." src="_images/discord_oauth2_perms.png" />
</div></blockquote>
</li>
<li><p>Now the resulting URL can be used to add your bot to a server. Copy and paste the URL into your browser, choose a server to invite the bot to, and click “Authorize”.</p></li>
</ol>
<div class="admonition note">
<p class="admonition-title">Note</p>
<p>The person adding the bot needs “Manage Server” permissions to do so.</p>
</div>
<p>If you want to generate this URL dynamically at run-time inside your bot and using the
<a class="reference internal" href="api.html#discord.Permissions" title="discord.Permissions"><code class="xref py py-class docutils literal notranslate"><span class="pre">discord.Permissions</span></code></a> interface, you can use <a class="reference internal" href="api.html#discord.utils.oauth_url" title="discord.utils.oauth_url"><code class="xref py py-func docutils literal notranslate"><span class="pre">discord.utils.oauth_url()</span></code></a>.</p>
</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>

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,282 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Cogs</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" />
<link rel="next" title="Extensions" href="extensions.html" />
<link rel="prev" title="Commands" href="commands.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="../../index.html">discord</option>
<option value="index.html" selected>discord.ext.commands</option>
<option value="../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="#">Cogs</a><ul>
<li><a class="reference internal" href="#quick-example">Quick Example</a></li>
<li><a class="reference internal" href="#cog-registration">Cog Registration</a></li>
<li><a class="reference internal" href="#using-cogs">Using Cogs</a></li>
<li><a class="reference internal" href="#special-methods">Special Methods</a></li>
<li><a class="reference internal" href="#meta-options">Meta Options</a></li>
<li><a class="reference internal" href="#inspection">Inspection</a></li>
</ul>
</li>
</ul>
</div>
</aside>
<main class="grid-item" role="main">
<section id="cogs">
<span id="ext-commands-cogs"></span><h1>Cogs<a class="headerlink" href="#cogs" title="Permalink to this headline"></a></h1>
<p>There comes a point in your bots development when you want to organize a collection of commands, listeners, and some state into one class. Cogs allow you to do just that.</p>
<p>The gist:</p>
<ul class="simple">
<li><p>Each cog is a Python class that subclasses <a class="reference internal" href="api.html#discord.ext.commands.Cog" title="discord.ext.commands.Cog"><code class="xref py py-class docutils literal notranslate"><span class="pre">commands.Cog</span></code></a>.</p></li>
<li><p>Every command is marked with the <a class="reference internal" href="api.html#discord.ext.commands.command" title="discord.ext.commands.command"><code class="xref py py-func docutils literal notranslate"><span class="pre">commands.command()</span></code></a> decorator.</p></li>
<li><p>Every listener is marked with the <a class="reference internal" href="api.html#discord.ext.commands.Cog.listener" title="discord.ext.commands.Cog.listener"><code class="xref py py-meth docutils literal notranslate"><span class="pre">commands.Cog.listener()</span></code></a> decorator.</p></li>
<li><p>Cogs are then registered with the <a class="reference internal" href="api.html#discord.ext.commands.Bot.add_cog" title="discord.ext.commands.Bot.add_cog"><code class="xref py py-meth docutils literal notranslate"><span class="pre">Bot.add_cog()</span></code></a> call.</p></li>
<li><p>Cogs are subsequently removed with the <a class="reference internal" href="api.html#discord.ext.commands.Bot.remove_cog" title="discord.ext.commands.Bot.remove_cog"><code class="xref py py-meth docutils literal notranslate"><span class="pre">Bot.remove_cog()</span></code></a> call.</p></li>
</ul>
<p>It should be noted that cogs are typically used alongside with <a class="reference internal" href="extensions.html#ext-commands-extensions"><span class="std std-ref">Extensions</span></a>.</p>
<section id="quick-example">
<h2>Quick Example<a class="headerlink" href="#quick-example" title="Permalink to this headline"></a></h2>
<p>This example cog defines a <code class="docutils literal notranslate"><span class="pre">Greetings</span></code> category for your commands, with a single <a class="reference internal" href="commands.html#ext-commands-commands"><span class="std std-ref">command</span></a> named <code class="docutils literal notranslate"><span class="pre">hello</span></code> as well as a listener to listen to an <a class="reference internal" href="../../api.html#discord-api-events"><span class="std std-ref">Event</span></a>.</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="k">class</span> <span class="nc">Greetings</span><span class="p">(</span><span class="n">commands</span><span class="o">.</span><span class="n">Cog</span><span class="p">):</span>
<span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">bot</span><span class="p">):</span>
<span class="bp">self</span><span class="o">.</span><span class="n">bot</span> <span class="o">=</span> <span class="n">bot</span>
<span class="bp">self</span><span class="o">.</span><span class="n">_last_member</span> <span class="o">=</span> <span class="kc">None</span>
<span class="nd">@commands</span><span class="o">.</span><span class="n">Cog</span><span class="o">.</span><span class="n">listener</span><span class="p">()</span>
<span class="k">async</span> <span class="k">def</span> <span class="nf">on_member_join</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">member</span><span class="p">):</span>
<span class="n">channel</span> <span class="o">=</span> <span class="n">member</span><span class="o">.</span><span class="n">guild</span><span class="o">.</span><span class="n">system_channel</span>
<span class="k">if</span> <span class="n">channel</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span><span class="p">:</span>
<span class="k">await</span> <span class="n">channel</span><span class="o">.</span><span class="n">send</span><span class="p">(</span><span class="sa">f</span><span class="s1">&#39;Welcome </span><span class="si">{</span><span class="n">member</span><span class="o">.</span><span class="n">mention</span><span class="si">}</span><span class="s1">.&#39;</span><span class="p">)</span>
<span class="nd">@commands</span><span class="o">.</span><span class="n">command</span><span class="p">()</span>
<span class="k">async</span> <span class="k">def</span> <span class="nf">hello</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">ctx</span><span class="p">,</span> <span class="o">*</span><span class="p">,</span> <span class="n">member</span><span class="p">:</span> <span class="n">discord</span><span class="o">.</span><span class="n">Member</span> <span class="o">=</span> <span class="kc">None</span><span class="p">):</span>
<span class="sd">&quot;&quot;&quot;Says hello&quot;&quot;&quot;</span>
<span class="n">member</span> <span class="o">=</span> <span class="n">member</span> <span class="ow">or</span> <span class="n">ctx</span><span class="o">.</span><span class="n">author</span>
<span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">_last_member</span> <span class="ow">is</span> <span class="kc">None</span> <span class="ow">or</span> <span class="bp">self</span><span class="o">.</span><span class="n">_last_member</span><span class="o">.</span><span class="n">id</span> <span class="o">!=</span> <span class="n">member</span><span class="o">.</span><span class="n">id</span><span class="p">:</span>
<span class="k">await</span> <span class="n">ctx</span><span class="o">.</span><span class="n">send</span><span class="p">(</span><span class="sa">f</span><span class="s1">&#39;Hello </span><span class="si">{</span><span class="n">member</span><span class="o">.</span><span class="n">name</span><span class="si">}</span><span class="s1">~&#39;</span><span class="p">)</span>
<span class="k">else</span><span class="p">:</span>
<span class="k">await</span> <span class="n">ctx</span><span class="o">.</span><span class="n">send</span><span class="p">(</span><span class="sa">f</span><span class="s1">&#39;Hello </span><span class="si">{</span><span class="n">member</span><span class="o">.</span><span class="n">name</span><span class="si">}</span><span class="s1">... This feels familiar.&#39;</span><span class="p">)</span>
<span class="bp">self</span><span class="o">.</span><span class="n">_last_member</span> <span class="o">=</span> <span class="n">member</span>
</pre></div>
</div>
<p>A couple of technical notes to take into consideration:</p>
<ul class="simple">
<li><p>All listeners must be explicitly marked via decorator, <a class="reference internal" href="api.html#discord.ext.commands.Cog.listener" title="discord.ext.commands.Cog.listener"><code class="xref py py-meth docutils literal notranslate"><span class="pre">listener()</span></code></a>.</p></li>
<li><p>The name of the cog is automatically derived from the class name but can be overridden. See <a class="reference internal" href="#ext-commands-cogs-meta-options"><span class="std std-ref">Meta Options</span></a>.</p></li>
<li><p>All commands must now take a <code class="docutils literal notranslate"><span class="pre">self</span></code> parameter to allow usage of instance attributes that can be used to maintain state.</p></li>
</ul>
</section>
<section id="cog-registration">
<h2>Cog Registration<a class="headerlink" href="#cog-registration" title="Permalink to this headline"></a></h2>
<p>Once you have defined your cogs, you need to tell the bot to register the cogs to be used. We do this via the <a class="reference internal" href="api.html#discord.ext.commands.Bot.add_cog" title="discord.ext.commands.Bot.add_cog"><code class="xref py py-meth docutils literal notranslate"><span class="pre">add_cog()</span></code></a> method.</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="n">bot</span><span class="o">.</span><span class="n">add_cog</span><span class="p">(</span><span class="n">Greetings</span><span class="p">(</span><span class="n">bot</span><span class="p">))</span>
</pre></div>
</div>
<p>This binds the cog to the bot, adding all commands and listeners to the bot automatically.</p>
<p>Note that we reference the cog by name, which we can override through <a class="reference internal" href="#ext-commands-cogs-meta-options"><span class="std std-ref">Meta Options</span></a>. So if we ever want to remove the cog eventually, we would have to do the following.</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="n">bot</span><span class="o">.</span><span class="n">remove_cog</span><span class="p">(</span><span class="s1">&#39;Greetings&#39;</span><span class="p">)</span>
</pre></div>
</div>
</section>
<section id="using-cogs">
<h2>Using Cogs<a class="headerlink" href="#using-cogs" title="Permalink to this headline"></a></h2>
<p>Just as we remove a cog by its name, we can also retrieve it by its name as well. This allows us to use a cog as an inter-command communication protocol to share data. For example:</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="k">class</span> <span class="nc">Economy</span><span class="p">(</span><span class="n">commands</span><span class="o">.</span><span class="n">Cog</span><span class="p">):</span>
<span class="o">...</span>
<span class="k">async</span> <span class="k">def</span> <span class="nf">withdraw_money</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">member</span><span class="p">,</span> <span class="n">money</span><span class="p">):</span>
<span class="c1"># implementation here</span>
<span class="o">...</span>
<span class="k">async</span> <span class="k">def</span> <span class="nf">deposit_money</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">member</span><span class="p">,</span> <span class="n">money</span><span class="p">):</span>
<span class="c1"># implementation here</span>
<span class="o">...</span>
<span class="k">class</span> <span class="nc">Gambling</span><span class="p">(</span><span class="n">commands</span><span class="o">.</span><span class="n">Cog</span><span class="p">):</span>
<span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">bot</span><span class="p">):</span>
<span class="bp">self</span><span class="o">.</span><span class="n">bot</span> <span class="o">=</span> <span class="n">bot</span>
<span class="k">def</span> <span class="nf">coinflip</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="k">return</span> <span class="n">random</span><span class="o">.</span><span class="n">randint</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">1</span><span class="p">)</span>
<span class="nd">@commands</span><span class="o">.</span><span class="n">command</span><span class="p">()</span>
<span class="k">async</span> <span class="k">def</span> <span class="nf">gamble</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">ctx</span><span class="p">,</span> <span class="n">money</span><span class="p">:</span> <span class="nb">int</span><span class="p">):</span>
<span class="sd">&quot;&quot;&quot;Gambles some money.&quot;&quot;&quot;</span>
<span class="hll"> <span class="n">economy</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">bot</span><span class="o">.</span><span class="n">get_cog</span><span class="p">(</span><span class="s1">&#39;Economy&#39;</span><span class="p">)</span>
</span> <span class="k">if</span> <span class="n">economy</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span><span class="p">:</span>
<span class="hll"> <span class="k">await</span> <span class="n">economy</span><span class="o">.</span><span class="n">withdraw_money</span><span class="p">(</span><span class="n">ctx</span><span class="o">.</span><span class="n">author</span><span class="p">,</span> <span class="n">money</span><span class="p">)</span>
</span> <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">coinflip</span><span class="p">()</span> <span class="o">==</span> <span class="mi">1</span><span class="p">:</span>
<span class="k">await</span> <span class="n">economy</span><span class="o">.</span><span class="n">deposit_money</span><span class="p">(</span><span class="n">ctx</span><span class="o">.</span><span class="n">author</span><span class="p">,</span> <span class="n">money</span> <span class="o">*</span> <span class="mf">1.5</span><span class="p">)</span>
</pre></div>
</div>
</section>
<section id="special-methods">
<span id="ext-commands-cogs-special-methods"></span><h2>Special Methods<a class="headerlink" href="#special-methods" title="Permalink to this headline"></a></h2>
<p>As cogs get more complicated and have more commands, there comes a point where we want to customise the behaviour of the entire cog or bot.</p>
<p>They are as follows:</p>
<ul class="simple">
<li><p><a class="reference internal" href="api.html#discord.ext.commands.Cog.cog_unload" title="discord.ext.commands.Cog.cog_unload"><code class="xref py py-meth docutils literal notranslate"><span class="pre">Cog.cog_unload()</span></code></a></p></li>
<li><p><a class="reference internal" href="api.html#discord.ext.commands.Cog.cog_check" title="discord.ext.commands.Cog.cog_check"><code class="xref py py-meth docutils literal notranslate"><span class="pre">Cog.cog_check()</span></code></a></p></li>
<li><p><a class="reference internal" href="api.html#discord.ext.commands.Cog.cog_command_error" title="discord.ext.commands.Cog.cog_command_error"><code class="xref py py-meth docutils literal notranslate"><span class="pre">Cog.cog_command_error()</span></code></a></p></li>
<li><p><a class="reference internal" href="api.html#discord.ext.commands.Cog.cog_before_invoke" title="discord.ext.commands.Cog.cog_before_invoke"><code class="xref py py-meth docutils literal notranslate"><span class="pre">Cog.cog_before_invoke()</span></code></a></p></li>
<li><p><a class="reference internal" href="api.html#discord.ext.commands.Cog.cog_after_invoke" title="discord.ext.commands.Cog.cog_after_invoke"><code class="xref py py-meth docutils literal notranslate"><span class="pre">Cog.cog_after_invoke()</span></code></a></p></li>
<li><p><a class="reference internal" href="api.html#discord.ext.commands.Cog.bot_check" title="discord.ext.commands.Cog.bot_check"><code class="xref py py-meth docutils literal notranslate"><span class="pre">Cog.bot_check()</span></code></a></p></li>
<li><p><a class="reference internal" href="api.html#discord.ext.commands.Cog.bot_check_once" title="discord.ext.commands.Cog.bot_check_once"><code class="xref py py-meth docutils literal notranslate"><span class="pre">Cog.bot_check_once()</span></code></a></p></li>
</ul>
<p>You can visit the reference to get more detail.</p>
</section>
<section id="meta-options">
<span id="ext-commands-cogs-meta-options"></span><h2>Meta Options<a class="headerlink" href="#meta-options" title="Permalink to this headline"></a></h2>
<p>At the heart of a cog resides a metaclass, <a class="reference internal" href="api.html#discord.ext.commands.CogMeta" title="discord.ext.commands.CogMeta"><code class="xref py py-class docutils literal notranslate"><span class="pre">commands.CogMeta</span></code></a>, which can take various options to customise some of the behaviour. To do this, we pass keyword arguments to the class definition line. For example, to change the cog name we can pass the <code class="docutils literal notranslate"><span class="pre">name</span></code> keyword argument as follows:</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="k">class</span> <span class="nc">MyCog</span><span class="p">(</span><span class="n">commands</span><span class="o">.</span><span class="n">Cog</span><span class="p">,</span> <span class="n">name</span><span class="o">=</span><span class="s1">&#39;My Cog&#39;</span><span class="p">):</span>
<span class="k">pass</span>
</pre></div>
</div>
<p>To see more options that you can set, see the documentation of <a class="reference internal" href="api.html#discord.ext.commands.CogMeta" title="discord.ext.commands.CogMeta"><code class="xref py py-class docutils literal notranslate"><span class="pre">commands.CogMeta</span></code></a>.</p>
</section>
<section id="inspection">
<h2>Inspection<a class="headerlink" href="#inspection" title="Permalink to this headline"></a></h2>
<p>Since cogs ultimately are classes, we have some tools to help us inspect certain properties of the cog.</p>
<p>To get a <a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#list" title="(in Python v3.9)"><code class="xref py py-class docutils literal notranslate"><span class="pre">list</span></code></a> of commands, we can use <a class="reference internal" href="api.html#discord.ext.commands.Cog.get_commands" title="discord.ext.commands.Cog.get_commands"><code class="xref py py-meth docutils literal notranslate"><span class="pre">Cog.get_commands()</span></code></a>.</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">cog</span> <span class="o">=</span> <span class="n">bot</span><span class="o">.</span><span class="n">get_cog</span><span class="p">(</span><span class="s1">&#39;Greetings&#39;</span><span class="p">)</span>
<span class="gp">&gt;&gt;&gt; </span><span class="n">commands</span> <span class="o">=</span> <span class="n">cog</span><span class="o">.</span><span class="n">get_commands</span><span class="p">()</span>
<span class="gp">&gt;&gt;&gt; </span><span class="nb">print</span><span class="p">([</span><span class="n">c</span><span class="o">.</span><span class="n">name</span> <span class="k">for</span> <span class="n">c</span> <span class="ow">in</span> <span class="n">commands</span><span class="p">])</span>
</pre></div>
</div>
<p>If we want to get the subcommands as well, we can use the <a class="reference internal" href="api.html#discord.ext.commands.Cog.walk_commands" title="discord.ext.commands.Cog.walk_commands"><code class="xref py py-meth docutils literal notranslate"><span class="pre">Cog.walk_commands()</span></code></a> generator.</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="nb">print</span><span class="p">([</span><span class="n">c</span><span class="o">.</span><span class="n">qualified_name</span> <span class="k">for</span> <span class="n">c</span> <span class="ow">in</span> <span class="n">cog</span><span class="o">.</span><span class="n">walk_commands</span><span class="p">()])</span>
</pre></div>
</div>
<p>To do the same with listeners, we can query them with <a class="reference internal" href="api.html#discord.ext.commands.Cog.get_listeners" title="discord.ext.commands.Cog.get_listeners"><code class="xref py py-meth docutils literal notranslate"><span class="pre">Cog.get_listeners()</span></code></a>. This returns a list of tuples the first element being the listener name and the second one being the actual function itself.</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="k">for</span> <span class="n">name</span><span class="p">,</span> <span class="n">func</span> <span class="ow">in</span> <span class="n">cog</span><span class="o">.</span><span class="n">get_listeners</span><span class="p">():</span>
<span class="gp">... </span> <span class="nb">print</span><span class="p">(</span><span class="n">name</span><span class="p">,</span> <span class="s1">&#39;-&gt;&#39;</span><span class="p">,</span> <span class="n">func</span><span class="p">)</span>
</pre></div>
</div>
</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>

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,200 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Extensions</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" />
<link rel="next" title="Slash Commands" href="slash-commands.html" />
<link rel="prev" title="Cogs" href="cogs.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="../../index.html">discord</option>
<option value="index.html" selected>discord.ext.commands</option>
<option value="../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="#">Extensions</a><ul>
<li><a class="reference internal" href="#primer">Primer</a></li>
<li><a class="reference internal" href="#reloading">Reloading</a></li>
<li><a class="reference internal" href="#cleaning-up">Cleaning Up</a></li>
</ul>
</li>
</ul>
</div>
</aside>
<main class="grid-item" role="main">
<section id="extensions">
<span id="ext-commands-extensions"></span><h1>Extensions<a class="headerlink" href="#extensions" title="Permalink to this headline"></a></h1>
<p>There comes a time in the bot development when you want to extend the bot functionality at run-time and quickly unload and reload code (also called hot-reloading). The command framework comes with this ability built-in, with a concept called <strong>extensions</strong>.</p>
<section id="primer">
<h2>Primer<a class="headerlink" href="#primer" title="Permalink to this headline"></a></h2>
<p>An extension at its core is a python file with an entry point called <code class="docutils literal notranslate"><span class="pre">setup</span></code>. This setup must be a plain Python function (not a coroutine). It takes a single parameter the <a class="reference internal" href="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> that loads the extension.</p>
<p>An example extension looks like this:</p>
<div class="literal-block-wrapper docutils container" id="id1">
<div class="code-block-caption"><span class="caption-text">hello.py</span><a class="headerlink" href="#id1" title="Permalink to this code"></a></div>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">discord.ext</span> <span class="kn">import</span> <span class="n">commands</span>
<span class="nd">@commands</span><span class="o">.</span><span class="n">command</span><span class="p">()</span>
<span class="k">async</span> <span class="k">def</span> <span class="nf">hello</span><span class="p">(</span><span class="n">ctx</span><span class="p">):</span>
<span class="k">await</span> <span class="n">ctx</span><span class="o">.</span><span class="n">send</span><span class="p">(</span><span class="sa">f</span><span class="s1">&#39;Hello </span><span class="si">{</span><span class="n">ctx</span><span class="o">.</span><span class="n">author</span><span class="o">.</span><span class="n">display_name</span><span class="si">}</span><span class="s1">.&#39;</span><span class="p">)</span>
<span class="hll"><span class="k">def</span> <span class="nf">setup</span><span class="p">(</span><span class="n">bot</span><span class="p">):</span>
</span><span class="hll"> <span class="n">bot</span><span class="o">.</span><span class="n">add_command</span><span class="p">(</span><span class="n">hello</span><span class="p">)</span>
</span></pre></div>
</div>
</div>
<p>In this example we define a simple command, and when the extension is loaded this command is added to the bot. Now the final step to this is loading the extension, which we do by calling <a class="reference internal" href="api.html#discord.ext.commands.Bot.load_extension" title="discord.ext.commands.Bot.load_extension"><code class="xref py py-meth docutils literal notranslate"><span class="pre">Bot.load_extension()</span></code></a>. To load this extension we call <code class="docutils literal notranslate"><span class="pre">bot.load_extension('hello')</span></code>.</p>
<div class="helpful admonition">
<p class="admonition-title">Cogs</p>
<p>Extensions are usually used in conjunction with cogs. To read more about them, check out the documentation, <a class="reference internal" href="cogs.html#ext-commands-cogs"><span class="std std-ref">Cogs</span></a>.</p>
</div>
<div class="admonition note">
<p class="admonition-title">Note</p>
<p>Extension paths are ultimately similar to the import mechanism. What this means is that if there is a folder, then it must be dot-qualified. For example to load an extension in <code class="docutils literal notranslate"><span class="pre">plugins/hello.py</span></code> then we use the string <code class="docutils literal notranslate"><span class="pre">plugins.hello</span></code>.</p>
</div>
</section>
<section id="reloading">
<h2>Reloading<a class="headerlink" href="#reloading" title="Permalink to this headline"></a></h2>
<p>When you make a change to the extension and want to reload the references, the library comes with a function to do this for you, <a class="reference internal" href="api.html#discord.ext.commands.Bot.reload_extension" title="discord.ext.commands.Bot.reload_extension"><code class="xref py py-meth docutils literal notranslate"><span class="pre">Bot.reload_extension()</span></code></a>.</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="gp">&gt;&gt;&gt; </span><span class="n">bot</span><span class="o">.</span><span class="n">reload_extension</span><span class="p">(</span><span class="s1">&#39;hello&#39;</span><span class="p">)</span>
</pre></div>
</div>
<p>Once the extension reloads, any changes that we did will be applied. This is useful if we want to add or remove functionality without restarting our bot. If an error occurred during the reloading process, the bot will pretend as if the reload never happened.</p>
</section>
<section id="cleaning-up">
<h2>Cleaning Up<a class="headerlink" href="#cleaning-up" title="Permalink to this headline"></a></h2>
<p>Although rare, sometimes an extension needs to clean-up or know when its being unloaded. For cases like these, there is another entry point named <code class="docutils literal notranslate"><span class="pre">teardown</span></code> which is similar to <code class="docutils literal notranslate"><span class="pre">setup</span></code> except called when the extension is unloaded.</p>
<div class="literal-block-wrapper docutils container" id="id2">
<div class="code-block-caption"><span class="caption-text">basic_ext.py</span><a class="headerlink" href="#id2" title="Permalink to this code"></a></div>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="k">def</span> <span class="nf">setup</span><span class="p">(</span><span class="n">bot</span><span class="p">):</span>
<span class="nb">print</span><span class="p">(</span><span class="s1">&#39;I am being loaded!&#39;</span><span class="p">)</span>
<span class="k">def</span> <span class="nf">teardown</span><span class="p">(</span><span class="n">bot</span><span class="p">):</span>
<span class="nb">print</span><span class="p">(</span><span class="s1">&#39;I am being unloaded!&#39;</span><span class="p">)</span>
</pre></div>
</div>
</div>
</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>

View File

@ -0,0 +1,184 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>discord.ext.commands Bot commands framework</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" />
<link rel="next" title="Commands" href="commands.html" />
<link rel="prev" title="Welcome to discord.py" href="../../index.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="../../index.html">discord</option>
<option value="#" selected>discord.ext.commands</option>
<option value="../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="settings-toggle" class="settings" onclick="settingsModal.open();">
<span class="material-icons">settings</span>
</span>
<div id="sidebar">
</div>
</aside>
<main class="grid-item" role="main">
<section id="discord-ext-commands-bot-commands-framework">
<span id="discord-ext-commands"></span><h1><code class="docutils literal notranslate"><span class="pre">discord.ext.commands</span></code> Bot commands framework<a class="headerlink" href="#discord-ext-commands-bot-commands-framework" title="Permalink to this headline"></a></h1>
<p><code class="docutils literal notranslate"><span class="pre">discord.py</span></code> offers a lower level aspect on interacting with Discord. Often times, the library is used for the creation of
bots. However this task can be daunting and confusing to get correctly the first time. Many times there comes a repetition in
creating a bot command framework that is extensible, flexible, and powerful. For this reason, <code class="docutils literal notranslate"><span class="pre">discord.py</span></code> comes with an
extension library that handles this for you.</p>
<div class="toctree-wrapper compound">
<ul>
<li class="toctree-l1"><a class="reference internal" href="commands.html">Commands</a><ul>
<li class="toctree-l2"><a class="reference internal" href="commands.html#parameters">Parameters</a></li>
<li class="toctree-l2"><a class="reference internal" href="commands.html#invocation-context">Invocation Context</a></li>
<li class="toctree-l2"><a class="reference internal" href="commands.html#converters">Converters</a></li>
<li class="toctree-l2"><a class="reference internal" href="commands.html#error-handling">Error Handling</a></li>
<li class="toctree-l2"><a class="reference internal" href="commands.html#checks">Checks</a></li>
</ul>
</li>
<li class="toctree-l1"><a class="reference internal" href="cogs.html">Cogs</a><ul>
<li class="toctree-l2"><a class="reference internal" href="cogs.html#quick-example">Quick Example</a></li>
<li class="toctree-l2"><a class="reference internal" href="cogs.html#cog-registration">Cog Registration</a></li>
<li class="toctree-l2"><a class="reference internal" href="cogs.html#using-cogs">Using Cogs</a></li>
<li class="toctree-l2"><a class="reference internal" href="cogs.html#special-methods">Special Methods</a></li>
<li class="toctree-l2"><a class="reference internal" href="cogs.html#meta-options">Meta Options</a></li>
<li class="toctree-l2"><a class="reference internal" href="cogs.html#inspection">Inspection</a></li>
</ul>
</li>
<li class="toctree-l1"><a class="reference internal" href="extensions.html">Extensions</a><ul>
<li class="toctree-l2"><a class="reference internal" href="extensions.html#primer">Primer</a></li>
<li class="toctree-l2"><a class="reference internal" href="extensions.html#reloading">Reloading</a></li>
<li class="toctree-l2"><a class="reference internal" href="extensions.html#cleaning-up">Cleaning Up</a></li>
</ul>
</li>
<li class="toctree-l1"><a class="reference internal" href="slash-commands.html">Slash Commands</a></li>
<li class="toctree-l1"><a class="reference internal" href="api.html">API Reference</a><ul>
<li class="toctree-l2"><a class="reference internal" href="api.html#bots">Bots</a></li>
<li class="toctree-l2"><a class="reference internal" href="api.html#prefix-helpers">Prefix Helpers</a></li>
<li class="toctree-l2"><a class="reference internal" href="api.html#event-reference">Event Reference</a></li>
<li class="toctree-l2"><a class="reference internal" href="api.html#commands">Commands</a></li>
<li class="toctree-l2"><a class="reference internal" href="api.html#cogs">Cogs</a></li>
<li class="toctree-l2"><a class="reference internal" href="api.html#help-commands">Help Commands</a></li>
<li class="toctree-l2"><a class="reference internal" href="api.html#enums">Enums</a></li>
<li class="toctree-l2"><a class="reference internal" href="api.html#checks">Checks</a></li>
<li class="toctree-l2"><a class="reference internal" href="api.html#cooldown">Cooldown</a></li>
<li class="toctree-l2"><a class="reference internal" href="api.html#context">Context</a></li>
<li class="toctree-l2"><a class="reference internal" href="api.html#converters">Converters</a></li>
<li class="toctree-l2"><a class="reference internal" href="api.html#exceptions">Exceptions</a></li>
</ul>
</li>
</ul>
</div>
</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>

View File

@ -0,0 +1,149 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Slash Commands</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" />
<link rel="next" title="API Reference" href="api.html" />
<link rel="prev" title="Extensions" href="extensions.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="../../index.html">discord</option>
<option value="index.html" selected>discord.ext.commands</option>
<option value="../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="settings-toggle" class="settings" onclick="settingsModal.open();">
<span class="material-icons">settings</span>
</span>
<div id="sidebar">
</div>
</aside>
<main class="grid-item" role="main">
<section id="slash-commands">
<span id="ext-commands-slash-commands"></span><h1>Slash Commands<a class="headerlink" href="#slash-commands" title="Permalink to this headline"></a></h1>
<p>Slash Commands are currently supported in enhanced-discord.py using a system on top of ext.commands.</p>
<p>This system is very simple to use, and can be enabled via <a class="reference internal" href="api.html#discord.ext.commands.Bot.slash_commands" title="discord.ext.commands.Bot.slash_commands"><code class="xref py py-attr docutils literal notranslate"><span class="pre">Bot.slash_commands</span></code></a> globally,
or only for specific commands via <a class="reference internal" href="api.html#discord.ext.commands.Command.slash_command" title="discord.ext.commands.Command.slash_command"><code class="xref py py-attr docutils literal notranslate"><span class="pre">Command.slash_command</span></code></a>.</p>
<p>There is also the parameter <code class="docutils literal notranslate"><span class="pre">slash_command_guilds</span></code> which can be passed to either <a class="reference internal" href="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> or the command
decorator in order to only upload the commands as guild commands to these specific guild IDs, however this
should only be used for testing or small (&lt;10 guilds) bots.</p>
<p>If you want to add option descriptions to your commands, you should use <a class="reference internal" href="api.html#discord.ext.commands.Option" title="discord.ext.commands.Option"><code class="xref py py-class docutils literal notranslate"><span class="pre">Option</span></code></a></p>
<p>For troubleshooting, see the <a class="reference internal" href="../../faq.html#ext-commands-slash-command-troubleshooting"><span class="std std-ref">FAQ</span></a></p>
<div class="admonition-slash-command-only admonition">
<p class="admonition-title">Slash Command Only</p>
<p>For parts of the docs specific to slash commands, look for this box!</p>
</div>
</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>

View File

@ -0,0 +1,704 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>discord.ext.tasks asyncio.Task helpers</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" />
<link rel="next" title="API Reference" href="../../api.html" />
<link rel="prev" title="API Reference" href="../commands/api.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="../../index.html">discord</option>
<option value="../commands/index.html" >discord.ext.commands</option>
<option value="#" selected>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="#"><code class="docutils literal notranslate"><span class="pre">discord.ext.tasks</span></code> asyncio.Task helpers</a><ul>
<li><a class="reference internal" href="#recipes">Recipes</a></li>
<li><a class="reference internal" href="#api-reference">API Reference</a></li>
</ul>
</li>
</ul>
</div>
</aside>
<main class="grid-item" role="main">
<section id="discord-ext-tasks-asyncio-task-helpers">
<span id="discord-ext-tasks"></span><h1><code class="docutils literal notranslate"><span class="pre">discord.ext.tasks</span></code> asyncio.Task helpers<a class="headerlink" href="#discord-ext-tasks-asyncio-task-helpers" title="Permalink to this headline"></a></h1>
<div class="versionadded">
<p><span class="versionmodified added">New in version 1.1.0.</span></p>
</div>
<p>One of the most common operations when making a bot is having a loop run in the background at a specified interval. This pattern is very common but has a lot of things you need to look out for:</p>
<ul class="simple">
<li><p>How do I handle <a class="reference external" href="https://docs.python.org/3/library/asyncio-exceptions.html#asyncio.CancelledError" title="(in Python v3.9)"><code class="xref py py-exc docutils literal notranslate"><span class="pre">asyncio.CancelledError</span></code></a>?</p></li>
<li><p>What do I do if the internet goes out?</p></li>
<li><p>What is the maximum number of seconds I can sleep anyway?</p></li>
</ul>
<p>The goal of this discord.py extension is to abstract all these worries away from you.</p>
<section id="recipes">
<h2>Recipes<a class="headerlink" href="#recipes" title="Permalink to this headline"></a></h2>
<p>A simple background task in a <a class="reference internal" href="../commands/api.html#discord.ext.commands.Cog" title="discord.ext.commands.Cog"><code class="xref py py-class docutils literal notranslate"><span class="pre">Cog</span></code></a>:</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">discord.ext</span> <span class="kn">import</span> <span class="n">tasks</span><span class="p">,</span> <span class="n">commands</span>
<span class="k">class</span> <span class="nc">MyCog</span><span class="p">(</span><span class="n">commands</span><span class="o">.</span><span class="n">Cog</span><span class="p">):</span>
<span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="bp">self</span><span class="o">.</span><span class="n">index</span> <span class="o">=</span> <span class="mi">0</span>
<span class="bp">self</span><span class="o">.</span><span class="n">printer</span><span class="o">.</span><span class="n">start</span><span class="p">()</span>
<span class="k">def</span> <span class="nf">cog_unload</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="bp">self</span><span class="o">.</span><span class="n">printer</span><span class="o">.</span><span class="n">cancel</span><span class="p">()</span>
<span class="nd">@tasks</span><span class="o">.</span><span class="n">loop</span><span class="p">(</span><span class="n">seconds</span><span class="o">=</span><span class="mf">5.0</span><span class="p">)</span>
<span class="k">async</span> <span class="k">def</span> <span class="nf">printer</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="nb">print</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">index</span><span class="p">)</span>
<span class="bp">self</span><span class="o">.</span><span class="n">index</span> <span class="o">+=</span> <span class="mi">1</span>
</pre></div>
</div>
<p>Adding an exception to handle during reconnect:</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="kn">import</span> <span class="nn">asyncpg</span>
<span class="kn">from</span> <span class="nn">discord.ext</span> <span class="kn">import</span> <span class="n">tasks</span><span class="p">,</span> <span class="n">commands</span>
<span class="k">class</span> <span class="nc">MyCog</span><span class="p">(</span><span class="n">commands</span><span class="o">.</span><span class="n">Cog</span><span class="p">):</span>
<span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">bot</span><span class="p">):</span>
<span class="bp">self</span><span class="o">.</span><span class="n">bot</span> <span class="o">=</span> <span class="n">bot</span>
<span class="bp">self</span><span class="o">.</span><span class="n">data</span> <span class="o">=</span> <span class="p">[]</span>
<span class="bp">self</span><span class="o">.</span><span class="n">batch_update</span><span class="o">.</span><span class="n">add_exception_type</span><span class="p">(</span><span class="n">asyncpg</span><span class="o">.</span><span class="n">PostgresConnectionError</span><span class="p">)</span>
<span class="bp">self</span><span class="o">.</span><span class="n">batch_update</span><span class="o">.</span><span class="n">start</span><span class="p">()</span>
<span class="k">def</span> <span class="nf">cog_unload</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="bp">self</span><span class="o">.</span><span class="n">batch_update</span><span class="o">.</span><span class="n">cancel</span><span class="p">()</span>
<span class="nd">@tasks</span><span class="o">.</span><span class="n">loop</span><span class="p">(</span><span class="n">minutes</span><span class="o">=</span><span class="mf">5.0</span><span class="p">)</span>
<span class="k">async</span> <span class="k">def</span> <span class="nf">batch_update</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="k">async</span> <span class="k">with</span> <span class="bp">self</span><span class="o">.</span><span class="n">bot</span><span class="o">.</span><span class="n">pool</span><span class="o">.</span><span class="n">acquire</span><span class="p">()</span> <span class="k">as</span> <span class="n">con</span><span class="p">:</span>
<span class="c1"># batch update here...</span>
<span class="k">pass</span>
</pre></div>
</div>
<p>Looping a certain amount of times before exiting:</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">discord.ext</span> <span class="kn">import</span> <span class="n">tasks</span>
<span class="nd">@tasks</span><span class="o">.</span><span class="n">loop</span><span class="p">(</span><span class="n">seconds</span><span class="o">=</span><span class="mf">5.0</span><span class="p">,</span> <span class="n">count</span><span class="o">=</span><span class="mi">5</span><span class="p">)</span>
<span class="k">async</span> <span class="k">def</span> <span class="nf">slow_count</span><span class="p">():</span>
<span class="nb">print</span><span class="p">(</span><span class="n">slow_count</span><span class="o">.</span><span class="n">current_loop</span><span class="p">)</span>
<span class="nd">@slow_count</span><span class="o">.</span><span class="n">after_loop</span>
<span class="k">async</span> <span class="k">def</span> <span class="nf">after_slow_count</span><span class="p">():</span>
<span class="nb">print</span><span class="p">(</span><span class="s1">&#39;done!&#39;</span><span class="p">)</span>
<span class="n">slow_count</span><span class="o">.</span><span class="n">start</span><span class="p">()</span>
</pre></div>
</div>
<p>Waiting until the bot is ready before the loop starts:</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">discord.ext</span> <span class="kn">import</span> <span class="n">tasks</span><span class="p">,</span> <span class="n">commands</span>
<span class="k">class</span> <span class="nc">MyCog</span><span class="p">(</span><span class="n">commands</span><span class="o">.</span><span class="n">Cog</span><span class="p">):</span>
<span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">bot</span><span class="p">):</span>
<span class="bp">self</span><span class="o">.</span><span class="n">index</span> <span class="o">=</span> <span class="mi">0</span>
<span class="bp">self</span><span class="o">.</span><span class="n">bot</span> <span class="o">=</span> <span class="n">bot</span>
<span class="bp">self</span><span class="o">.</span><span class="n">printer</span><span class="o">.</span><span class="n">start</span><span class="p">()</span>
<span class="k">def</span> <span class="nf">cog_unload</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="bp">self</span><span class="o">.</span><span class="n">printer</span><span class="o">.</span><span class="n">cancel</span><span class="p">()</span>
<span class="nd">@tasks</span><span class="o">.</span><span class="n">loop</span><span class="p">(</span><span class="n">seconds</span><span class="o">=</span><span class="mf">5.0</span><span class="p">)</span>
<span class="k">async</span> <span class="k">def</span> <span class="nf">printer</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="nb">print</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">index</span><span class="p">)</span>
<span class="bp">self</span><span class="o">.</span><span class="n">index</span> <span class="o">+=</span> <span class="mi">1</span>
<span class="nd">@printer</span><span class="o">.</span><span class="n">before_loop</span>
<span class="k">async</span> <span class="k">def</span> <span class="nf">before_printer</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="nb">print</span><span class="p">(</span><span class="s1">&#39;waiting...&#39;</span><span class="p">)</span>
<span class="k">await</span> <span class="bp">self</span><span class="o">.</span><span class="n">bot</span><span class="o">.</span><span class="n">wait_until_ready</span><span class="p">()</span>
</pre></div>
</div>
<p>Doing something during cancellation:</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">discord.ext</span> <span class="kn">import</span> <span class="n">tasks</span><span class="p">,</span> <span class="n">commands</span>
<span class="kn">import</span> <span class="nn">asyncio</span>
<span class="k">class</span> <span class="nc">MyCog</span><span class="p">(</span><span class="n">commands</span><span class="o">.</span><span class="n">Cog</span><span class="p">):</span>
<span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">bot</span><span class="p">):</span>
<span class="bp">self</span><span class="o">.</span><span class="n">bot</span><span class="o">=</span> <span class="n">bot</span>
<span class="bp">self</span><span class="o">.</span><span class="n">_batch</span> <span class="o">=</span> <span class="p">[]</span>
<span class="bp">self</span><span class="o">.</span><span class="n">lock</span> <span class="o">=</span> <span class="n">asyncio</span><span class="o">.</span><span class="n">Lock</span><span class="p">()</span>
<span class="bp">self</span><span class="o">.</span><span class="n">bulker</span><span class="o">.</span><span class="n">start</span><span class="p">()</span>
<span class="k">async</span> <span class="k">def</span> <span class="nf">do_bulk</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="c1"># bulk insert data here</span>
<span class="o">...</span>
<span class="nd">@tasks</span><span class="o">.</span><span class="n">loop</span><span class="p">(</span><span class="n">seconds</span><span class="o">=</span><span class="mf">10.0</span><span class="p">)</span>
<span class="k">async</span> <span class="k">def</span> <span class="nf">bulker</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="k">async</span> <span class="k">with</span> <span class="bp">self</span><span class="o">.</span><span class="n">lock</span><span class="p">:</span>
<span class="k">await</span> <span class="bp">self</span><span class="o">.</span><span class="n">do_bulk</span><span class="p">()</span>
<span class="nd">@bulker</span><span class="o">.</span><span class="n">after_loop</span>
<span class="k">async</span> <span class="k">def</span> <span class="nf">on_bulker_cancel</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">bulker</span><span class="o">.</span><span class="n">is_being_cancelled</span><span class="p">()</span> <span class="ow">and</span> <span class="nb">len</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">_batch</span><span class="p">)</span> <span class="o">!=</span> <span class="mi">0</span><span class="p">:</span>
<span class="c1"># if we&#39;re cancelled and we have some data left...</span>
<span class="c1"># let&#39;s insert it to our database</span>
<span class="k">await</span> <span class="bp">self</span><span class="o">.</span><span class="n">do_bulk</span><span class="p">()</span>
</pre></div>
</div>
</section>
<section id="api-reference">
<span id="ext-tasks-api"></span><h2>API Reference<a class="headerlink" href="#api-reference" title="Permalink to this headline"></a></h2>
<div class="py-attribute-table" data-move-to-id="discord.ext.tasks.Loop"><div class="py-attribute-table-column">
<span>
Attributes</span><ul>
<li class="py-attribute-table-entry">
<a class="reference internal" href="#discord.ext.tasks.Loop.current_loop">current_loop</a></li><li class="py-attribute-table-entry">
<a class="reference internal" href="#discord.ext.tasks.Loop.hours">hours</a></li><li class="py-attribute-table-entry">
<a class="reference internal" href="#discord.ext.tasks.Loop.minutes">minutes</a></li><li class="py-attribute-table-entry">
<a class="reference internal" href="#discord.ext.tasks.Loop.next_iteration">next_iteration</a></li><li class="py-attribute-table-entry">
<a class="reference internal" href="#discord.ext.tasks.Loop.seconds">seconds</a></li><li class="py-attribute-table-entry">
<a class="reference internal" href="#discord.ext.tasks.Loop.time">time</a></li></ul>
</div><div class="py-attribute-table-column">
<span>
Methods</span><ul>
<li class="py-attribute-table-entry">
<span class="py-attribute-table-badge" title="coroutine">
async</span><a class="reference internal" href="#discord.ext.tasks.Loop.__call__">__call__</a></li><li class="py-attribute-table-entry">
<span class="py-attribute-table-badge" title="method">
def</span><a class="reference internal" href="#discord.ext.tasks.Loop.add_exception_type">add_exception_type</a></li><li class="py-attribute-table-entry">
<span class="py-attribute-table-badge" title="decorator">
&#64;</span><a class="reference internal" href="#discord.ext.tasks.Loop.after_loop">after_loop</a></li><li class="py-attribute-table-entry">
<span class="py-attribute-table-badge" title="decorator">
&#64;</span><a class="reference internal" href="#discord.ext.tasks.Loop.before_loop">before_loop</a></li><li class="py-attribute-table-entry">
<span class="py-attribute-table-badge" title="method">
def</span><a class="reference internal" href="#discord.ext.tasks.Loop.cancel">cancel</a></li><li class="py-attribute-table-entry">
<span class="py-attribute-table-badge" title="method">
def</span><a class="reference internal" href="#discord.ext.tasks.Loop.change_interval">change_interval</a></li><li class="py-attribute-table-entry">
<span class="py-attribute-table-badge" title="method">
def</span><a class="reference internal" href="#discord.ext.tasks.Loop.clear_exception_types">clear_exception_types</a></li><li class="py-attribute-table-entry">
<span class="py-attribute-table-badge" title="decorator">
&#64;</span><a class="reference internal" href="#discord.ext.tasks.Loop.error">error</a></li><li class="py-attribute-table-entry">
<span class="py-attribute-table-badge" title="method">
def</span><a class="reference internal" href="#discord.ext.tasks.Loop.failed">failed</a></li><li class="py-attribute-table-entry">
<span class="py-attribute-table-badge" title="method">
def</span><a class="reference internal" href="#discord.ext.tasks.Loop.get_task">get_task</a></li><li class="py-attribute-table-entry">
<span class="py-attribute-table-badge" title="method">
def</span><a class="reference internal" href="#discord.ext.tasks.Loop.is_being_cancelled">is_being_cancelled</a></li><li class="py-attribute-table-entry">
<span class="py-attribute-table-badge" title="method">
def</span><a class="reference internal" href="#discord.ext.tasks.Loop.is_running">is_running</a></li><li class="py-attribute-table-entry">
<span class="py-attribute-table-badge" title="method">
def</span><a class="reference internal" href="#discord.ext.tasks.Loop.remove_exception_type">remove_exception_type</a></li><li class="py-attribute-table-entry">
<span class="py-attribute-table-badge" title="method">
def</span><a class="reference internal" href="#discord.ext.tasks.Loop.restart">restart</a></li><li class="py-attribute-table-entry">
<span class="py-attribute-table-badge" title="method">
def</span><a class="reference internal" href="#discord.ext.tasks.Loop.start">start</a></li><li class="py-attribute-table-entry">
<span class="py-attribute-table-badge" title="method">
def</span><a class="reference internal" href="#discord.ext.tasks.Loop.stop">stop</a></li></ul>
</div></div><dl class="py class">
<dt class="sig sig-object py" id="discord.ext.tasks.Loop">
<em class="property"><span class="pre">class</span> </em><span class="sig-prename descclassname"><span class="pre">discord.ext.tasks.</span></span><span class="sig-name descname"><span class="pre">Loop</span></span><a class="headerlink" href="#discord.ext.tasks.Loop" title="Permalink to this definition"></a></dt>
<dd><p>A background task helper that abstracts the loop and reconnection logic for you.</p>
<p>The main interface to create this is through <a class="reference internal" href="#discord.ext.tasks.loop" title="discord.ext.tasks.loop"><code class="xref py py-func docutils literal notranslate"><span class="pre">loop()</span></code></a>.</p>
<dl class="py method">
<dt class="sig sig-object py" id="discord.ext.tasks.Loop.after_loop">
<span class="sig-prename descclassname"><span class="pre">&#64;</span></span><span class="sig-name descname"><span class="pre">after_loop</span></span><a class="headerlink" href="#discord.ext.tasks.Loop.after_loop" title="Permalink to this definition"></a></dt>
<dd><p>A decorator that register a coroutine to be called after the loop finished running.</p>
<p>The coroutine must take no arguments (except <code class="docutils literal notranslate"><span class="pre">self</span></code> in a class context).</p>
<div class="admonition note">
<p class="admonition-title">Note</p>
<p>This coroutine is called even during cancellation. If it is desirable
to tell apart whether something was cancelled or not, check to see
whether <a class="reference internal" href="#discord.ext.tasks.Loop.is_being_cancelled" title="discord.ext.tasks.Loop.is_being_cancelled"><code class="xref py py-meth docutils literal notranslate"><span class="pre">is_being_cancelled()</span></code></a> is <code class="docutils literal notranslate"><span class="pre">True</span></code> or not.</p>
</div>
<dl class="field-list simple">
<dt class="field-odd">Parameters</dt>
<dd class="field-odd"><p><strong>coro</strong> (<a class="reference external" href="https://docs.python.org/3/library/asyncio-task.html#coroutine" title="(in Python v3.9)"><span class="xref std std-ref">coroutine</span></a>) The coroutine to register after the loop finishes.</p>
</dd>
<dt class="field-even">Raises</dt>
<dd class="field-even"><p><a class="reference external" href="https://docs.python.org/3/library/exceptions.html#TypeError" title="(in Python v3.9)"><strong>TypeError</strong></a> The function was not a coroutine.</p>
</dd>
</dl>
</dd></dl>
<dl class="py method">
<dt class="sig sig-object py" id="discord.ext.tasks.Loop.before_loop">
<span class="sig-prename descclassname"><span class="pre">&#64;</span></span><span class="sig-name descname"><span class="pre">before_loop</span></span><a class="headerlink" href="#discord.ext.tasks.Loop.before_loop" title="Permalink to this definition"></a></dt>
<dd><p>A decorator that registers a coroutine to be called before the loop starts running.</p>
<p>This is useful if you want to wait for some bot state before the loop starts,
such as <a class="reference internal" href="../../api.html#discord.Client.wait_until_ready" title="discord.Client.wait_until_ready"><code class="xref py py-meth docutils literal notranslate"><span class="pre">discord.Client.wait_until_ready()</span></code></a>.</p>
<p>The coroutine must take no arguments (except <code class="docutils literal notranslate"><span class="pre">self</span></code> in a class context).</p>
<dl class="field-list simple">
<dt class="field-odd">Parameters</dt>
<dd class="field-odd"><p><strong>coro</strong> (<a class="reference external" href="https://docs.python.org/3/library/asyncio-task.html#coroutine" title="(in Python v3.9)"><span class="xref std std-ref">coroutine</span></a>) The coroutine to register before the loop runs.</p>
</dd>
<dt class="field-even">Raises</dt>
<dd class="field-even"><p><a class="reference external" href="https://docs.python.org/3/library/exceptions.html#TypeError" title="(in Python v3.9)"><strong>TypeError</strong></a> The function was not a coroutine.</p>
</dd>
</dl>
</dd></dl>
<dl class="py method">
<dt class="sig sig-object py" id="discord.ext.tasks.Loop.error">
<span class="sig-prename descclassname"><span class="pre">&#64;</span></span><span class="sig-name descname"><span class="pre">error</span></span><a class="headerlink" href="#discord.ext.tasks.Loop.error" title="Permalink to this definition"></a></dt>
<dd><p>A decorator that registers a coroutine to be called if the task encounters an unhandled exception.</p>
<p>The coroutine must take only one argument the exception raised (except <code class="docutils literal notranslate"><span class="pre">self</span></code> in a class context).</p>
<p>By default this prints to <a class="reference external" href="https://docs.python.org/3/library/sys.html#sys.stderr" title="(in Python v3.9)"><code class="xref py py-data docutils literal notranslate"><span class="pre">sys.stderr</span></code></a> however it could be
overridden to have a different implementation.</p>
<div class="versionadded">
<p><span class="versionmodified added">New in version 1.4.</span></p>
</div>
<dl class="field-list simple">
<dt class="field-odd">Parameters</dt>
<dd class="field-odd"><p><strong>coro</strong> (<a class="reference external" href="https://docs.python.org/3/library/asyncio-task.html#coroutine" title="(in Python v3.9)"><span class="xref std std-ref">coroutine</span></a>) The coroutine to register in the event of an unhandled exception.</p>
</dd>
<dt class="field-even">Raises</dt>
<dd class="field-even"><p><a class="reference external" href="https://docs.python.org/3/library/exceptions.html#TypeError" title="(in Python v3.9)"><strong>TypeError</strong></a> The function was not a coroutine.</p>
</dd>
</dl>
</dd></dl>
<dl class="py property">
<dt class="sig sig-object py" id="discord.ext.tasks.Loop.seconds">
<em class="property"><span class="pre">property</span> </em><span class="sig-name descname"><span class="pre">seconds</span></span><a class="headerlink" href="#discord.ext.tasks.Loop.seconds" title="Permalink to this definition"></a></dt>
<dd><p>Read-only value for the number of seconds
between each iteration. <code class="docutils literal notranslate"><span class="pre">None</span></code> if an explicit <code class="docutils literal notranslate"><span class="pre">time</span></code> value was passed instead.</p>
<div class="versionadded">
<p><span class="versionmodified added">New in version 2.0.</span></p>
</div>
<dl class="field-list simple">
<dt class="field-odd">Type</dt>
<dd class="field-odd"><p>Optional[<a class="reference external" href="https://docs.python.org/3/library/functions.html#float" title="(in Python v3.9)"><code class="xref py py-class docutils literal notranslate"><span class="pre">float</span></code></a>]</p>
</dd>
</dl>
</dd></dl>
<dl class="py property">
<dt class="sig sig-object py" id="discord.ext.tasks.Loop.minutes">
<em class="property"><span class="pre">property</span> </em><span class="sig-name descname"><span class="pre">minutes</span></span><a class="headerlink" href="#discord.ext.tasks.Loop.minutes" title="Permalink to this definition"></a></dt>
<dd><p>Read-only value for the number of minutes
between each iteration. <code class="docutils literal notranslate"><span class="pre">None</span></code> if an explicit <code class="docutils literal notranslate"><span class="pre">time</span></code> value was passed instead.</p>
<div class="versionadded">
<p><span class="versionmodified added">New in version 2.0.</span></p>
</div>
<dl class="field-list simple">
<dt class="field-odd">Type</dt>
<dd class="field-odd"><p>Optional[<a class="reference external" href="https://docs.python.org/3/library/functions.html#float" title="(in Python v3.9)"><code class="xref py py-class docutils literal notranslate"><span class="pre">float</span></code></a>]</p>
</dd>
</dl>
</dd></dl>
<dl class="py property">
<dt class="sig sig-object py" id="discord.ext.tasks.Loop.hours">
<em class="property"><span class="pre">property</span> </em><span class="sig-name descname"><span class="pre">hours</span></span><a class="headerlink" href="#discord.ext.tasks.Loop.hours" title="Permalink to this definition"></a></dt>
<dd><p>Read-only value for the number of hours
between each iteration. <code class="docutils literal notranslate"><span class="pre">None</span></code> if an explicit <code class="docutils literal notranslate"><span class="pre">time</span></code> value was passed instead.</p>
<div class="versionadded">
<p><span class="versionmodified added">New in version 2.0.</span></p>
</div>
<dl class="field-list simple">
<dt class="field-odd">Type</dt>
<dd class="field-odd"><p>Optional[<a class="reference external" href="https://docs.python.org/3/library/functions.html#float" title="(in Python v3.9)"><code class="xref py py-class docutils literal notranslate"><span class="pre">float</span></code></a>]</p>
</dd>
</dl>
</dd></dl>
<dl class="py property">
<dt class="sig sig-object py" id="discord.ext.tasks.Loop.time">
<em class="property"><span class="pre">property</span> </em><span class="sig-name descname"><span class="pre">time</span></span><a class="headerlink" href="#discord.ext.tasks.Loop.time" title="Permalink to this definition"></a></dt>
<dd><p>Read-only list for the exact times this loop runs at.
<code class="docutils literal notranslate"><span class="pre">None</span></code> if relative times were passed instead.</p>
<div class="versionadded">
<p><span class="versionmodified added">New in version 2.0.</span></p>
</div>
<dl class="field-list simple">
<dt class="field-odd">Type</dt>
<dd class="field-odd"><p>Optional[List[<a class="reference external" href="https://docs.python.org/3/library/datetime.html#datetime.time" title="(in Python v3.9)"><code class="xref py py-class docutils literal notranslate"><span class="pre">datetime.time</span></code></a>]]</p>
</dd>
</dl>
</dd></dl>
<dl class="py property">
<dt class="sig sig-object py" id="discord.ext.tasks.Loop.current_loop">
<em class="property"><span class="pre">property</span> </em><span class="sig-name descname"><span class="pre">current_loop</span></span><a class="headerlink" href="#discord.ext.tasks.Loop.current_loop" title="Permalink to this definition"></a></dt>
<dd><p>The current iteration of the loop.</p>
<dl class="field-list simple">
<dt class="field-odd">Type</dt>
<dd class="field-odd"><p><a class="reference external" href="https://docs.python.org/3/library/functions.html#int" title="(in Python v3.9)"><code class="xref py py-class docutils literal notranslate"><span class="pre">int</span></code></a></p>
</dd>
</dl>
</dd></dl>
<dl class="py property">
<dt class="sig sig-object py" id="discord.ext.tasks.Loop.next_iteration">
<em class="property"><span class="pre">property</span> </em><span class="sig-name descname"><span class="pre">next_iteration</span></span><a class="headerlink" href="#discord.ext.tasks.Loop.next_iteration" title="Permalink to this definition"></a></dt>
<dd><p>When the next iteration of the loop will occur.</p>
<div class="versionadded">
<p><span class="versionmodified added">New in version 1.3.</span></p>
</div>
<dl class="field-list simple">
<dt class="field-odd">Type</dt>
<dd class="field-odd"><p>Optional[<a class="reference external" href="https://docs.python.org/3/library/datetime.html#datetime.datetime" title="(in Python v3.9)"><code class="xref py py-class docutils literal notranslate"><span class="pre">datetime.datetime</span></code></a>]</p>
</dd>
</dl>
</dd></dl>
<dl class="py method">
<dt class="sig sig-object py" id="discord.ext.tasks.Loop.__call__">
<em class="property"><span class="pre">await</span> </em><span class="sig-name descname"><span class="pre">__call__</span></span><span class="sig-paren">(</span><em class="sig-param"><span class="o"><span class="pre">*</span></span><span class="n"><span class="pre">args</span></span></em>, <em class="sig-param"><span class="o"><span class="pre">**</span></span><span class="n"><span class="pre">kwargs</span></span></em><span class="sig-paren">)</span><a class="headerlink" href="#discord.ext.tasks.Loop.__call__" title="Permalink to this definition"></a></dt>
<dd><p>This function is a <a class="reference external" href="https://docs.python.org/3/library/asyncio-task.html#coroutine"><em>coroutine</em></a>.</p>
<p>Calls the internal callback that the task holds.</p>
<div class="versionadded">
<p><span class="versionmodified added">New in version 1.6.</span></p>
</div>
<dl class="field-list simple">
<dt class="field-odd">Parameters</dt>
<dd class="field-odd"><ul class="simple">
<li><p><strong>*args</strong> The arguments to use.</p></li>
<li><p><strong>**kwargs</strong> The keyword arguments to use.</p></li>
</ul>
</dd>
</dl>
</dd></dl>
<dl class="py method">
<dt class="sig sig-object py" id="discord.ext.tasks.Loop.start">
<span class="sig-name descname"><span class="pre">start</span></span><span class="sig-paren">(</span><em class="sig-param"><span class="o"><span class="pre">*</span></span><span class="n"><span class="pre">args</span></span></em>, <em class="sig-param"><span class="o"><span class="pre">**</span></span><span class="n"><span class="pre">kwargs</span></span></em><span class="sig-paren">)</span><a class="headerlink" href="#discord.ext.tasks.Loop.start" title="Permalink to this definition"></a></dt>
<dd><p>Starts the internal task in the event loop.</p>
<dl class="field-list simple">
<dt class="field-odd">Parameters</dt>
<dd class="field-odd"><ul class="simple">
<li><p><strong>*args</strong> The arguments to use.</p></li>
<li><p><strong>**kwargs</strong> The keyword arguments to use.</p></li>
</ul>
</dd>
<dt class="field-even">Raises</dt>
<dd class="field-even"><p><a class="reference external" href="https://docs.python.org/3/library/exceptions.html#RuntimeError" title="(in Python v3.9)"><strong>RuntimeError</strong></a> A task has already been launched and is running.</p>
</dd>
<dt class="field-odd">Returns</dt>
<dd class="field-odd"><p>The task that has been created.</p>
</dd>
<dt class="field-even">Return type</dt>
<dd class="field-even"><p><a class="reference external" href="https://docs.python.org/3/library/asyncio-task.html#asyncio.Task" title="(in Python v3.9)"><code class="xref py py-class docutils literal notranslate"><span class="pre">asyncio.Task</span></code></a></p>
</dd>
</dl>
</dd></dl>
<dl class="py method">
<dt class="sig sig-object py" id="discord.ext.tasks.Loop.stop">
<span class="sig-name descname"><span class="pre">stop</span></span><span class="sig-paren">(</span><span class="sig-paren">)</span><a class="headerlink" href="#discord.ext.tasks.Loop.stop" title="Permalink to this definition"></a></dt>
<dd><p>Gracefully stops the task from running.</p>
<p>Unlike <a class="reference internal" href="#discord.ext.tasks.Loop.cancel" title="discord.ext.tasks.Loop.cancel"><code class="xref py py-meth docutils literal notranslate"><span class="pre">cancel()</span></code></a>, this allows the task to finish its
current iteration before gracefully exiting.</p>
<div class="admonition note">
<p class="admonition-title">Note</p>
<p>If the internal function raises an error that can be
handled before finishing then it will retry until
it succeeds.</p>
<p>If this is undesirable, either remove the error handling
before stopping via <a class="reference internal" href="#discord.ext.tasks.Loop.clear_exception_types" title="discord.ext.tasks.Loop.clear_exception_types"><code class="xref py py-meth docutils literal notranslate"><span class="pre">clear_exception_types()</span></code></a> or
use <a class="reference internal" href="#discord.ext.tasks.Loop.cancel" title="discord.ext.tasks.Loop.cancel"><code class="xref py py-meth docutils literal notranslate"><span class="pre">cancel()</span></code></a> instead.</p>
</div>
<div class="versionadded">
<p><span class="versionmodified added">New in version 1.2.</span></p>
</div>
</dd></dl>
<dl class="py method">
<dt class="sig sig-object py" id="discord.ext.tasks.Loop.cancel">
<span class="sig-name descname"><span class="pre">cancel</span></span><span class="sig-paren">(</span><span class="sig-paren">)</span><a class="headerlink" href="#discord.ext.tasks.Loop.cancel" title="Permalink to this definition"></a></dt>
<dd><p>Cancels the internal task, if it is running.</p>
</dd></dl>
<dl class="py method">
<dt class="sig sig-object py" id="discord.ext.tasks.Loop.restart">
<span class="sig-name descname"><span class="pre">restart</span></span><span class="sig-paren">(</span><em class="sig-param"><span class="o"><span class="pre">*</span></span><span class="n"><span class="pre">args</span></span></em>, <em class="sig-param"><span class="o"><span class="pre">**</span></span><span class="n"><span class="pre">kwargs</span></span></em><span class="sig-paren">)</span><a class="headerlink" href="#discord.ext.tasks.Loop.restart" title="Permalink to this definition"></a></dt>
<dd><p>A convenience method to restart the internal task.</p>
<div class="admonition note">
<p class="admonition-title">Note</p>
<p>Due to the way this function works, the task is not
returned like <a class="reference internal" href="#discord.ext.tasks.Loop.start" title="discord.ext.tasks.Loop.start"><code class="xref py py-meth docutils literal notranslate"><span class="pre">start()</span></code></a>.</p>
</div>
<dl class="field-list simple">
<dt class="field-odd">Parameters</dt>
<dd class="field-odd"><ul class="simple">
<li><p><strong>*args</strong> The arguments to use.</p></li>
<li><p><strong>**kwargs</strong> The keyword arguments to use.</p></li>
</ul>
</dd>
</dl>
</dd></dl>
<dl class="py method">
<dt class="sig sig-object py" id="discord.ext.tasks.Loop.add_exception_type">
<span class="sig-name descname"><span class="pre">add_exception_type</span></span><span class="sig-paren">(</span><em class="sig-param"><span class="o"><span class="pre">*</span></span><span class="n"><span class="pre">exceptions</span></span></em><span class="sig-paren">)</span><a class="headerlink" href="#discord.ext.tasks.Loop.add_exception_type" title="Permalink to this definition"></a></dt>
<dd><p>Adds exception types to be handled during the reconnect logic.</p>
<p>By default the exception types handled are those handled by
<a class="reference internal" href="../../api.html#discord.Client.connect" title="discord.Client.connect"><code class="xref py py-meth docutils literal notranslate"><span class="pre">discord.Client.connect()</span></code></a>, which includes a lot of internet disconnection
errors.</p>
<p>This function is useful if youre interacting with a 3rd party library that
raises its own set of exceptions.</p>
<dl class="field-list simple">
<dt class="field-odd">Parameters</dt>
<dd class="field-odd"><p><strong>*exceptions</strong> (Type[<a class="reference external" href="https://docs.python.org/3/library/exceptions.html#BaseException" title="(in Python v3.9)"><code class="xref py py-class docutils literal notranslate"><span class="pre">BaseException</span></code></a>]) An argument list of exception classes to handle.</p>
</dd>
<dt class="field-even">Raises</dt>
<dd class="field-even"><p><a class="reference external" href="https://docs.python.org/3/library/exceptions.html#TypeError" title="(in Python v3.9)"><strong>TypeError</strong></a> An exception passed is either not a class or not inherited from <a class="reference external" href="https://docs.python.org/3/library/exceptions.html#BaseException" title="(in Python v3.9)"><code class="xref py py-class docutils literal notranslate"><span class="pre">BaseException</span></code></a>.</p>
</dd>
</dl>
</dd></dl>
<dl class="py method">
<dt class="sig sig-object py" id="discord.ext.tasks.Loop.clear_exception_types">
<span class="sig-name descname"><span class="pre">clear_exception_types</span></span><span class="sig-paren">(</span><span class="sig-paren">)</span><a class="headerlink" href="#discord.ext.tasks.Loop.clear_exception_types" title="Permalink to this definition"></a></dt>
<dd><p>Removes all exception types that are handled.</p>
<div class="admonition note">
<p class="admonition-title">Note</p>
<p>This operation obviously cannot be undone!</p>
</div>
</dd></dl>
<dl class="py method">
<dt class="sig sig-object py" id="discord.ext.tasks.Loop.remove_exception_type">
<span class="sig-name descname"><span class="pre">remove_exception_type</span></span><span class="sig-paren">(</span><em class="sig-param"><span class="o"><span class="pre">*</span></span><span class="n"><span class="pre">exceptions</span></span></em><span class="sig-paren">)</span><a class="headerlink" href="#discord.ext.tasks.Loop.remove_exception_type" title="Permalink to this definition"></a></dt>
<dd><p>Removes exception types from being handled during the reconnect logic.</p>
<dl class="field-list simple">
<dt class="field-odd">Parameters</dt>
<dd class="field-odd"><p><strong>*exceptions</strong> (Type[<a class="reference external" href="https://docs.python.org/3/library/exceptions.html#BaseException" title="(in Python v3.9)"><code class="xref py py-class docutils literal notranslate"><span class="pre">BaseException</span></code></a>]) An argument list of exception classes to handle.</p>
</dd>
<dt class="field-even">Returns</dt>
<dd class="field-even"><p>Whether all exceptions were successfully removed.</p>
</dd>
<dt class="field-odd">Return type</dt>
<dd class="field-odd"><p><a class="reference external" href="https://docs.python.org/3/library/functions.html#bool" title="(in Python v3.9)"><code class="xref py py-class docutils literal notranslate"><span class="pre">bool</span></code></a></p>
</dd>
</dl>
</dd></dl>
<dl class="py method">
<dt class="sig sig-object py" id="discord.ext.tasks.Loop.get_task">
<span class="sig-name descname"><span class="pre">get_task</span></span><span class="sig-paren">(</span><span class="sig-paren">)</span><a class="headerlink" href="#discord.ext.tasks.Loop.get_task" title="Permalink to this definition"></a></dt>
<dd><p>Optional[<a class="reference external" href="https://docs.python.org/3/library/asyncio-task.html#asyncio.Task" title="(in Python v3.9)"><code class="xref py py-class docutils literal notranslate"><span class="pre">asyncio.Task</span></code></a>]: Fetches the internal task or <code class="docutils literal notranslate"><span class="pre">None</span></code> if there isnt one running.</p>
</dd></dl>
<dl class="py method">
<dt class="sig sig-object py" id="discord.ext.tasks.Loop.is_being_cancelled">
<span class="sig-name descname"><span class="pre">is_being_cancelled</span></span><span class="sig-paren">(</span><span class="sig-paren">)</span><a class="headerlink" href="#discord.ext.tasks.Loop.is_being_cancelled" title="Permalink to this definition"></a></dt>
<dd><p>Whether the task is being cancelled.</p>
</dd></dl>
<dl class="py method">
<dt class="sig sig-object py" id="discord.ext.tasks.Loop.failed">
<span class="sig-name descname"><span class="pre">failed</span></span><span class="sig-paren">(</span><span class="sig-paren">)</span><a class="headerlink" href="#discord.ext.tasks.Loop.failed" title="Permalink to this definition"></a></dt>
<dd><p><a class="reference external" href="https://docs.python.org/3/library/functions.html#bool" title="(in Python v3.9)"><code class="xref py py-class docutils literal notranslate"><span class="pre">bool</span></code></a>: Whether the internal task has failed.</p>
<div class="versionadded">
<p><span class="versionmodified added">New in version 1.2.</span></p>
</div>
</dd></dl>
<dl class="py method">
<dt class="sig sig-object py" id="discord.ext.tasks.Loop.is_running">
<span class="sig-name descname"><span class="pre">is_running</span></span><span class="sig-paren">(</span><span class="sig-paren">)</span><a class="headerlink" href="#discord.ext.tasks.Loop.is_running" title="Permalink to this definition"></a></dt>
<dd><p><a class="reference external" href="https://docs.python.org/3/library/functions.html#bool" title="(in Python v3.9)"><code class="xref py py-class docutils literal notranslate"><span class="pre">bool</span></code></a>: Check if the task is currently running.</p>
<div class="versionadded">
<p><span class="versionmodified added">New in version 1.4.</span></p>
</div>
</dd></dl>
<dl class="py method">
<dt class="sig sig-object py" id="discord.ext.tasks.Loop.change_interval">
<span class="sig-name descname"><span class="pre">change_interval</span></span><span class="sig-paren">(</span><em class="sig-param"><span class="o"><span class="pre">*</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">seconds</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">0</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">minutes</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">0</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">hours</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">0</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">time</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">...</span></span></em><span class="sig-paren">)</span><a class="headerlink" href="#discord.ext.tasks.Loop.change_interval" title="Permalink to this definition"></a></dt>
<dd><p>Changes the interval for the sleep time.</p>
<div class="versionadded">
<p><span class="versionmodified added">New in version 1.2.</span></p>
</div>
<dl class="field-list simple">
<dt class="field-odd">Parameters</dt>
<dd class="field-odd"><ul class="simple">
<li><p><strong>seconds</strong> (<a class="reference external" href="https://docs.python.org/3/library/functions.html#float" title="(in Python v3.9)"><code class="xref py py-class docutils literal notranslate"><span class="pre">float</span></code></a>) The number of seconds between every iteration.</p></li>
<li><p><strong>minutes</strong> (<a class="reference external" href="https://docs.python.org/3/library/functions.html#float" title="(in Python v3.9)"><code class="xref py py-class docutils literal notranslate"><span class="pre">float</span></code></a>) The number of minutes between every iteration.</p></li>
<li><p><strong>hours</strong> (<a class="reference external" href="https://docs.python.org/3/library/functions.html#float" title="(in Python v3.9)"><code class="xref py py-class docutils literal notranslate"><span class="pre">float</span></code></a>) The number of hours between every iteration.</p></li>
<li><p><strong>time</strong> (Union[<a class="reference external" href="https://docs.python.org/3/library/datetime.html#datetime.time" title="(in Python v3.9)"><code class="xref py py-class docutils literal notranslate"><span class="pre">datetime.time</span></code></a>, Sequence[<a class="reference external" href="https://docs.python.org/3/library/datetime.html#datetime.time" title="(in Python v3.9)"><code class="xref py py-class docutils literal notranslate"><span class="pre">datetime.time</span></code></a>]]) <p>The exact times to run this loop at. Either a non-empty list or a single
value of <a class="reference external" href="https://docs.python.org/3/library/datetime.html#datetime.time" title="(in Python v3.9)"><code class="xref py py-class docutils literal notranslate"><span class="pre">datetime.time</span></code></a> should be passed.
This cannot be used in conjunction with the relative time parameters.</p>
<div class="versionadded">
<p><span class="versionmodified added">New in version 2.0.</span></p>
</div>
<div class="admonition note">
<p class="admonition-title">Note</p>
<p>Duplicate times will be ignored, and only run once.</p>
</div>
</p></li>
</ul>
</dd>
<dt class="field-even">Raises</dt>
<dd class="field-even"><ul class="simple">
<li><p><a class="reference external" href="https://docs.python.org/3/library/exceptions.html#ValueError" title="(in Python v3.9)"><strong>ValueError</strong></a> An invalid value was given.</p></li>
<li><p><a class="reference external" href="https://docs.python.org/3/library/exceptions.html#TypeError" title="(in Python v3.9)"><strong>TypeError</strong></a> An invalid value for the <code class="docutils literal notranslate"><span class="pre">time</span></code> parameter was passed, or the
<code class="docutils literal notranslate"><span class="pre">time</span></code> parameter was passed in conjunction with relative time parameters.</p></li>
</ul>
</dd>
</dl>
</dd></dl>
</dd></dl>
<dl class="py function">
<dt class="sig sig-object py" id="discord.ext.tasks.loop">
<span class="sig-prename descclassname"><span class="pre">discord.ext.tasks.</span></span><span class="sig-name descname"><span class="pre">loop</span></span><span class="sig-paren">(</span><em class="sig-param"><span class="o"><span class="pre">*</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">seconds</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">...</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">minutes</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">...</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">hours</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">...</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">time</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">...</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">count</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">None</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">reconnect</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">True</span></span></em>, <em class="sig-param"><span class="n"><span class="pre">loop</span></span><span class="o"><span class="pre">=</span></span><span class="default_value"><span class="pre">...</span></span></em><span class="sig-paren">)</span><a class="headerlink" href="#discord.ext.tasks.loop" title="Permalink to this definition"></a></dt>
<dd><p>A decorator that schedules a task in the background for you with
optional reconnect logic. The decorator returns a <a class="reference internal" href="#discord.ext.tasks.Loop" title="discord.ext.tasks.Loop"><code class="xref py py-class docutils literal notranslate"><span class="pre">Loop</span></code></a>.</p>
<dl class="field-list simple">
<dt class="field-odd">Parameters</dt>
<dd class="field-odd"><ul class="simple">
<li><p><strong>seconds</strong> (<a class="reference external" href="https://docs.python.org/3/library/functions.html#float" title="(in Python v3.9)"><code class="xref py py-class docutils literal notranslate"><span class="pre">float</span></code></a>) The number of seconds between every iteration.</p></li>
<li><p><strong>minutes</strong> (<a class="reference external" href="https://docs.python.org/3/library/functions.html#float" title="(in Python v3.9)"><code class="xref py py-class docutils literal notranslate"><span class="pre">float</span></code></a>) The number of minutes between every iteration.</p></li>
<li><p><strong>hours</strong> (<a class="reference external" href="https://docs.python.org/3/library/functions.html#float" title="(in Python v3.9)"><code class="xref py py-class docutils literal notranslate"><span class="pre">float</span></code></a>) The number of hours between every iteration.</p></li>
<li><p><strong>time</strong> (Union[<a class="reference external" href="https://docs.python.org/3/library/datetime.html#datetime.time" title="(in Python v3.9)"><code class="xref py py-class docutils literal notranslate"><span class="pre">datetime.time</span></code></a>, Sequence[<a class="reference external" href="https://docs.python.org/3/library/datetime.html#datetime.time" title="(in Python v3.9)"><code class="xref py py-class docutils literal notranslate"><span class="pre">datetime.time</span></code></a>]]) <p>The exact times to run this loop at. Either a non-empty list or a single
value of <a class="reference external" href="https://docs.python.org/3/library/datetime.html#datetime.time" title="(in Python v3.9)"><code class="xref py py-class docutils literal notranslate"><span class="pre">datetime.time</span></code></a> should be passed. Timezones are supported.
If no timezone is given for the times, it is assumed to represent UTC time.</p>
<p>This cannot be used in conjunction with the relative time parameters.</p>
<div class="admonition note">
<p class="admonition-title">Note</p>
<p>Duplicate times will be ignored, and only run once.</p>
</div>
<div class="versionadded">
<p><span class="versionmodified added">New in version 2.0.</span></p>
</div>
</p></li>
<li><p><strong>count</strong> (Optional[<a class="reference external" href="https://docs.python.org/3/library/functions.html#int" title="(in Python v3.9)"><code class="xref py py-class docutils literal notranslate"><span class="pre">int</span></code></a>]) The number of loops to do, <code class="docutils literal notranslate"><span class="pre">None</span></code> if it should be an
infinite loop.</p></li>
<li><p><strong>reconnect</strong> (<a class="reference external" href="https://docs.python.org/3/library/functions.html#bool" title="(in Python v3.9)"><code class="xref py py-class docutils literal notranslate"><span class="pre">bool</span></code></a>) Whether to handle errors and restart the task
using an exponential back-off algorithm similar to the
one used in <a class="reference internal" href="../../api.html#discord.Client.connect" title="discord.Client.connect"><code class="xref py py-meth docutils literal notranslate"><span class="pre">discord.Client.connect()</span></code></a>.</p></li>
<li><p><strong>loop</strong> (<a class="reference external" href="https://docs.python.org/3/library/asyncio-eventloop.html#asyncio.AbstractEventLoop" title="(in Python v3.9)"><code class="xref py py-class docutils literal notranslate"><span class="pre">asyncio.AbstractEventLoop</span></code></a>) The loop to use to register the task, if not given
defaults to <a class="reference external" href="https://docs.python.org/3/library/asyncio-eventloop.html#asyncio.get_event_loop" title="(in Python v3.9)"><code class="xref py py-func docutils literal notranslate"><span class="pre">asyncio.get_event_loop()</span></code></a>.</p></li>
</ul>
</dd>
<dt class="field-even">Raises</dt>
<dd class="field-even"><ul class="simple">
<li><p><a class="reference external" href="https://docs.python.org/3/library/exceptions.html#ValueError" title="(in Python v3.9)"><strong>ValueError</strong></a> An invalid value was given.</p></li>
<li><p><a class="reference external" href="https://docs.python.org/3/library/exceptions.html#TypeError" title="(in Python v3.9)"><strong>TypeError</strong></a> The function was not a coroutine, an invalid value for the <code class="docutils literal notranslate"><span class="pre">time</span></code> parameter was passed,
or <code class="docutils literal notranslate"><span class="pre">time</span></code> parameter was passed in conjunction with relative time parameters.</p></li>
</ul>
</dd>
</dl>
</dd></dl>
</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>

601
docs/Python/html/faq.html Normal file
View File

@ -0,0 +1,601 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Frequently Asked Questions</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="#" 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="#">Frequently Asked Questions</a><ul>
<li><a class="reference internal" href="#coroutines">Coroutines</a><ul>
<li><a class="reference internal" href="#what-is-a-coroutine">What is a coroutine?</a></li>
<li><a class="reference internal" href="#where-can-i-use-await">Where can I use <code class="docutils literal notranslate"><span class="pre">await</span></code>?</a></li>
<li><a class="reference internal" href="#what-does-blocking-mean">What does “blocking” mean?</a></li>
</ul>
</li>
<li><a class="reference internal" href="#general">General</a><ul>
<li><a class="reference internal" href="#where-can-i-find-usage-examples">Where can I find usage examples?</a></li>
<li><a class="reference internal" href="#how-do-i-set-the-playing-status">How do I set the “Playing” status?</a></li>
<li><a class="reference internal" href="#how-do-i-send-a-message-to-a-specific-channel">How do I send a message to a specific channel?</a></li>
<li><a class="reference internal" href="#how-do-i-send-a-dm">How do I send a DM?</a></li>
<li><a class="reference internal" href="#how-do-i-get-the-id-of-a-sent-message">How do I get the ID of a sent message?</a></li>
<li><a class="reference internal" href="#how-do-i-upload-an-image">How do I upload an image?</a></li>
<li><a class="reference internal" href="#how-can-i-add-a-reaction-to-a-message">How can I add a reaction to a message?</a></li>
<li><a class="reference internal" href="#how-do-i-pass-a-coroutine-to-the-player-s-after-function">How do I pass a coroutine to the players “after” function?</a></li>
<li><a class="reference internal" href="#how-do-i-run-something-in-the-background">How do I run something in the background?</a></li>
<li><a class="reference internal" href="#how-do-i-get-a-specific-model">How do I get a specific model?</a></li>
<li><a class="reference internal" href="#how-do-i-make-a-web-request">How do I make a web request?</a></li>
<li><a class="reference internal" href="#how-do-i-use-a-local-image-file-for-an-embed-image">How do I use a local image file for an embed image?</a></li>
<li><a class="reference internal" href="#is-there-an-event-for-audit-log-entries-being-created">Is there an event for audit log entries being created?</a></li>
</ul>
</li>
<li><a class="reference internal" href="#commands-extension">Commands Extension</a><ul>
<li><a class="reference internal" href="#why-does-on-message-make-my-commands-stop-working">Why does <code class="docutils literal notranslate"><span class="pre">on_message</span></code> make my commands stop working?</a></li>
<li><a class="reference internal" href="#why-do-my-arguments-require-quotes">Why do my arguments require quotes?</a></li>
<li><a class="reference internal" href="#how-do-i-get-the-original-message">How do I get the original <code class="docutils literal notranslate"><span class="pre">message</span></code>?</a></li>
<li><a class="reference internal" href="#how-do-i-make-a-subcommand">How do I make a subcommand?</a></li>
<li><a class="reference internal" href="#how-do-i-make-slash-commands">How do I make slash commands?</a></li>
<li><a class="reference internal" href="#my-slash-commands-aren-t-showing-up">My slash commands arent showing up!</a></li>
<li><a class="reference internal" href="#my-bot-won-t-start-after-enabling-slash-commands">My bot wont start after enabling slash commands!</a></li>
</ul>
</li>
</ul>
</li>
</ul>
</div>
</aside>
<main class="grid-item" role="main">
<section id="frequently-asked-questions">
<span id="faq"></span><h1>Frequently Asked Questions<a class="headerlink" href="#frequently-asked-questions" title="Permalink to this headline"></a></h1>
<p>This is a list of Frequently Asked Questions regarding using <code class="docutils literal notranslate"><span class="pre">discord.py</span></code> and its extension modules. Feel free to suggest a
new question or submit one via pull requests.</p>
<div class="contents local topic" id="questions">
<p class="topic-title">Questions</p>
<ul class="simple">
<li><p><a class="reference internal" href="#coroutines" id="id1">Coroutines</a></p>
<ul>
<li><p><a class="reference internal" href="#what-is-a-coroutine" id="id2">What is a coroutine?</a></p></li>
<li><p><a class="reference internal" href="#where-can-i-use-await" id="id3">Where can I use <code class="docutils literal notranslate"><span class="pre">await</span></code>?</a></p></li>
<li><p><a class="reference internal" href="#what-does-blocking-mean" id="id4">What does “blocking” mean?</a></p></li>
</ul>
</li>
<li><p><a class="reference internal" href="#general" id="id5">General</a></p>
<ul>
<li><p><a class="reference internal" href="#where-can-i-find-usage-examples" id="id6">Where can I find usage examples?</a></p></li>
<li><p><a class="reference internal" href="#how-do-i-set-the-playing-status" id="id7">How do I set the “Playing” status?</a></p></li>
<li><p><a class="reference internal" href="#how-do-i-send-a-message-to-a-specific-channel" id="id8">How do I send a message to a specific channel?</a></p></li>
<li><p><a class="reference internal" href="#how-do-i-send-a-dm" id="id9">How do I send a DM?</a></p></li>
<li><p><a class="reference internal" href="#how-do-i-get-the-id-of-a-sent-message" id="id10">How do I get the ID of a sent message?</a></p></li>
<li><p><a class="reference internal" href="#how-do-i-upload-an-image" id="id11">How do I upload an image?</a></p></li>
<li><p><a class="reference internal" href="#how-can-i-add-a-reaction-to-a-message" id="id12">How can I add a reaction to a message?</a></p></li>
<li><p><a class="reference internal" href="#how-do-i-pass-a-coroutine-to-the-player-s-after-function" id="id13">How do I pass a coroutine to the players “after” function?</a></p></li>
<li><p><a class="reference internal" href="#how-do-i-run-something-in-the-background" id="id14">How do I run something in the background?</a></p></li>
<li><p><a class="reference internal" href="#how-do-i-get-a-specific-model" id="id15">How do I get a specific model?</a></p></li>
<li><p><a class="reference internal" href="#how-do-i-make-a-web-request" id="id16">How do I make a web request?</a></p></li>
<li><p><a class="reference internal" href="#how-do-i-use-a-local-image-file-for-an-embed-image" id="id17">How do I use a local image file for an embed image?</a></p></li>
<li><p><a class="reference internal" href="#is-there-an-event-for-audit-log-entries-being-created" id="id18">Is there an event for audit log entries being created?</a></p></li>
</ul>
</li>
<li><p><a class="reference internal" href="#commands-extension" id="id19">Commands Extension</a></p>
<ul>
<li><p><a class="reference internal" href="#why-does-on-message-make-my-commands-stop-working" id="id20">Why does <code class="docutils literal notranslate"><span class="pre">on_message</span></code> make my commands stop working?</a></p></li>
<li><p><a class="reference internal" href="#why-do-my-arguments-require-quotes" id="id21">Why do my arguments require quotes?</a></p></li>
<li><p><a class="reference internal" href="#how-do-i-get-the-original-message" id="id22">How do I get the original <code class="docutils literal notranslate"><span class="pre">message</span></code>?</a></p></li>
<li><p><a class="reference internal" href="#how-do-i-make-a-subcommand" id="id23">How do I make a subcommand?</a></p></li>
<li><p><a class="reference internal" href="#how-do-i-make-slash-commands" id="id24">How do I make slash commands?</a></p></li>
<li><p><a class="reference internal" href="#my-slash-commands-aren-t-showing-up" id="id25">My slash commands arent showing up!</a></p></li>
<li><p><a class="reference internal" href="#my-bot-won-t-start-after-enabling-slash-commands" id="id26">My bot wont start after enabling slash commands!</a></p></li>
</ul>
</li>
</ul>
</div>
<section id="coroutines">
<h2><a class="toc-backref" href="#id1">Coroutines</a><a class="headerlink" href="#coroutines" title="Permalink to this headline"></a></h2>
<p>Questions regarding coroutines and asyncio belong here.</p>
<section id="what-is-a-coroutine">
<h3><a class="toc-backref" href="#id2">What is a coroutine?</a><a class="headerlink" href="#what-is-a-coroutine" title="Permalink to this headline"></a></h3>
<p>A <a class="reference external" href="https://docs.python.org/3/library/asyncio-task.html#coroutine"><em>coroutine</em></a> is a function that must be invoked with <code class="docutils literal notranslate"><span class="pre">await</span></code> or <code class="docutils literal notranslate"><span class="pre">yield</span> <span class="pre">from</span></code>. When Python encounters an <code class="docutils literal notranslate"><span class="pre">await</span></code> it stops
the functions execution at that point and works on other things until it comes back to that point and finishes off its work.
This allows for your program to be doing multiple things at the same time without using threads or complicated
multiprocessing.</p>
<p><strong>If you forget to await a coroutine then the coroutine will not run. Never forget to await a coroutine.</strong></p>
</section>
<section id="where-can-i-use-await">
<h3><a class="toc-backref" href="#id3">Where can I use <code class="docutils literal notranslate"><span class="pre">await</span></code>?</a><a class="headerlink" href="#where-can-i-use-await" title="Permalink to this headline"></a></h3>
<p>You can only use <code class="docutils literal notranslate"><span class="pre">await</span></code> inside <code class="docutils literal notranslate"><span class="pre">async</span> <span class="pre">def</span></code> functions and nowhere else.</p>
</section>
<section id="what-does-blocking-mean">
<h3><a class="toc-backref" href="#id4">What does “blocking” mean?</a><a class="headerlink" href="#what-does-blocking-mean" title="Permalink to this headline"></a></h3>
<p>In asynchronous programming a blocking call is essentially all the parts of the function that are not <code class="docutils literal notranslate"><span class="pre">await</span></code>. Do not
despair however, because not all forms of blocking are bad! Using blocking calls is inevitable, but you must work to make
sure that you dont excessively block functions. Remember, if you block for too long then your bot will freeze since it has
not stopped the functions execution at that point to do other things.</p>
<p>If logging is enabled, this library will attempt to warn you that blocking is occurring with the message:
<code class="docutils literal notranslate"><span class="pre">Heartbeat</span> <span class="pre">blocked</span> <span class="pre">for</span> <span class="pre">more</span> <span class="pre">than</span> <span class="pre">N</span> <span class="pre">seconds.</span></code>
See <a class="reference internal" href="logging.html#logging-setup"><span class="std std-ref">Setting Up Logging</span></a> for details on enabling logging.</p>
<p>A common source of blocking for too long is something like <a class="reference external" href="https://docs.python.org/3/library/time.html#time.sleep" title="(in Python v3.9)"><code class="xref py py-func docutils literal notranslate"><span class="pre">time.sleep()</span></code></a>. Dont do that. Use <a class="reference external" href="https://docs.python.org/3/library/asyncio-task.html#asyncio.sleep" title="(in Python v3.9)"><code class="xref py py-func docutils literal notranslate"><span class="pre">asyncio.sleep()</span></code></a>
instead. Similar to this example:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="c1"># bad</span>
<span class="n">time</span><span class="o">.</span><span class="n">sleep</span><span class="p">(</span><span class="mi">10</span><span class="p">)</span>
<span class="c1"># good</span>
<span class="k">await</span> <span class="n">asyncio</span><span class="o">.</span><span class="n">sleep</span><span class="p">(</span><span class="mi">10</span><span class="p">)</span>
</pre></div>
</div>
<p>Another common source of blocking for too long is using HTTP requests with the famous module <a class="reference external" href="https://docs.python-requests.org/en/latest/" title="(in Requests v2.26.0)"><span>Requests: HTTP for Humans™</span></a>.
While <a class="reference external" href="https://docs.python-requests.org/en/latest/" title="(in Requests v2.26.0)"><span>Requests: HTTP for Humans™</span></a> is an amazing module for non-asynchronous programming, it is not a good choice for
<a class="reference external" href="https://docs.python.org/3/library/asyncio.html#module-asyncio" title="(in Python v3.9)"><code class="xref py py-mod docutils literal notranslate"><span class="pre">asyncio</span></code></a> because certain requests can block the event loop too long. Instead, use the <a class="reference external" href="https://docs.aiohttp.org/en/stable/index.html" title="(in aiohttp v3.7)"><span class="xref std std-doc">aiohttp</span></a> library which
is installed on the side with this library.</p>
<p>Consider the following example:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="c1"># bad</span>
<span class="n">r</span> <span class="o">=</span> <span class="n">requests</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s1">&#39;http://aws.random.cat/meow&#39;</span><span class="p">)</span>
<span class="k">if</span> <span class="n">r</span><span class="o">.</span><span class="n">status_code</span> <span class="o">==</span> <span class="mi">200</span><span class="p">:</span>
<span class="n">js</span> <span class="o">=</span> <span class="n">r</span><span class="o">.</span><span class="n">json</span><span class="p">()</span>
<span class="k">await</span> <span class="n">channel</span><span class="o">.</span><span class="n">send</span><span class="p">(</span><span class="n">js</span><span class="p">[</span><span class="s1">&#39;file&#39;</span><span class="p">])</span>
<span class="c1"># good</span>
<span class="k">async</span> <span class="k">with</span> <span class="n">aiohttp</span><span class="o">.</span><span class="n">ClientSession</span><span class="p">()</span> <span class="k">as</span> <span class="n">session</span><span class="p">:</span>
<span class="k">async</span> <span class="k">with</span> <span class="n">session</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s1">&#39;http://aws.random.cat/meow&#39;</span><span class="p">)</span> <span class="k">as</span> <span class="n">r</span><span class="p">:</span>
<span class="k">if</span> <span class="n">r</span><span class="o">.</span><span class="n">status</span> <span class="o">==</span> <span class="mi">200</span><span class="p">:</span>
<span class="n">js</span> <span class="o">=</span> <span class="k">await</span> <span class="n">r</span><span class="o">.</span><span class="n">json</span><span class="p">()</span>
<span class="k">await</span> <span class="n">channel</span><span class="o">.</span><span class="n">send</span><span class="p">(</span><span class="n">js</span><span class="p">[</span><span class="s1">&#39;file&#39;</span><span class="p">])</span>
</pre></div>
</div>
</section>
</section>
<section id="general">
<h2><a class="toc-backref" href="#id5">General</a><a class="headerlink" href="#general" title="Permalink to this headline"></a></h2>
<p>General questions regarding library usage belong here.</p>
<section id="where-can-i-find-usage-examples">
<h3><a class="toc-backref" href="#id6">Where can I find usage examples?</a><a class="headerlink" href="#where-can-i-find-usage-examples" title="Permalink to this headline"></a></h3>
<p>Example code can be found in the <a class="reference external" href="https://github.com/Rapptz/discord.py/tree/master/examples">examples folder</a>
in the repository.</p>
</section>
<section id="how-do-i-set-the-playing-status">
<h3><a class="toc-backref" href="#id7">How do I set the “Playing” status?</a><a class="headerlink" href="#how-do-i-set-the-playing-status" title="Permalink to this headline"></a></h3>
<p>The <code class="docutils literal notranslate"><span class="pre">activity</span></code> keyword argument may be passed in the <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> constructor or <a class="reference internal" href="api.html#discord.Client.change_presence" title="discord.Client.change_presence"><code class="xref py py-meth docutils literal notranslate"><span class="pre">Client.change_presence()</span></code></a>, given an <a class="reference internal" href="api.html#discord.Activity" title="discord.Activity"><code class="xref py py-class docutils literal notranslate"><span class="pre">Activity</span></code></a> object.</p>
<p>The constructor may be used for static activities, while <a class="reference internal" href="api.html#discord.Client.change_presence" title="discord.Client.change_presence"><code class="xref py py-meth docutils literal notranslate"><span class="pre">Client.change_presence()</span></code></a> may be used to update the activity at runtime.</p>
<div class="admonition warning">
<p class="admonition-title">Warning</p>
<p>It is highly discouraged to use <a class="reference internal" href="api.html#discord.Client.change_presence" title="discord.Client.change_presence"><code class="xref py py-meth docutils literal notranslate"><span class="pre">Client.change_presence()</span></code></a> or API calls in <a class="reference internal" href="api.html#discord.on_ready" title="discord.on_ready"><code class="xref py py-func docutils literal notranslate"><span class="pre">on_ready()</span></code></a> as this event may be called many times while running, not just once.</p>
<p>There is a high chance of disconnecting if presences are changed right after connecting.</p>
</div>
<p>The status type (playing, listening, streaming, watching) can be set using the <a class="reference internal" href="api.html#discord.ActivityType" title="discord.ActivityType"><code class="xref py py-class docutils literal notranslate"><span class="pre">ActivityType</span></code></a> enum.
For memory optimisation purposes, some activities are offered in slimmed-down versions:</p>
<ul class="simple">
<li><p><a class="reference internal" href="api.html#discord.Game" title="discord.Game"><code class="xref py py-class docutils literal notranslate"><span class="pre">Game</span></code></a></p></li>
<li><p><a class="reference internal" href="api.html#discord.Streaming" title="discord.Streaming"><code class="xref py py-class docutils literal notranslate"><span class="pre">Streaming</span></code></a></p></li>
</ul>
<p>Putting both of these pieces of info together, you get the following:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">client</span> <span class="o">=</span> <span class="n">discord</span><span class="o">.</span><span class="n">Client</span><span class="p">(</span><span class="n">activity</span><span class="o">=</span><span class="n">discord</span><span class="o">.</span><span class="n">Game</span><span class="p">(</span><span class="n">name</span><span class="o">=</span><span class="s1">&#39;my game&#39;</span><span class="p">))</span>
<span class="c1"># or, for watching:</span>
<span class="n">activity</span> <span class="o">=</span> <span class="n">discord</span><span class="o">.</span><span class="n">Activity</span><span class="p">(</span><span class="n">name</span><span class="o">=</span><span class="s1">&#39;my activity&#39;</span><span class="p">,</span> <span class="nb">type</span><span class="o">=</span><span class="n">discord</span><span class="o">.</span><span class="n">ActivityType</span><span class="o">.</span><span class="n">watching</span><span class="p">)</span>
<span class="n">client</span> <span class="o">=</span> <span class="n">discord</span><span class="o">.</span><span class="n">Client</span><span class="p">(</span><span class="n">activity</span><span class="o">=</span><span class="n">activity</span><span class="p">)</span>
</pre></div>
</div>
</section>
<section id="how-do-i-send-a-message-to-a-specific-channel">
<h3><a class="toc-backref" href="#id8">How do I send a message to a specific channel?</a><a class="headerlink" href="#how-do-i-send-a-message-to-a-specific-channel" title="Permalink to this headline"></a></h3>
<p>You must fetch the channel directly and then call the appropriate method. Example:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">channel</span> <span class="o">=</span> <span class="n">client</span><span class="o">.</span><span class="n">get_channel</span><span class="p">(</span><span class="mi">12324234183172</span><span class="p">)</span>
<span class="k">await</span> <span class="n">channel</span><span class="o">.</span><span class="n">send</span><span class="p">(</span><span class="s1">&#39;hello&#39;</span><span class="p">)</span>
</pre></div>
</div>
</section>
<section id="how-do-i-send-a-dm">
<h3><a class="toc-backref" href="#id9">How do I send a DM?</a><a class="headerlink" href="#how-do-i-send-a-dm" title="Permalink to this headline"></a></h3>
<p>Get the <a class="reference internal" href="api.html#discord.User" title="discord.User"><code class="xref py py-class docutils literal notranslate"><span class="pre">User</span></code></a> or <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> object and call <a class="reference internal" href="api.html#discord.abc.Messageable.send" title="discord.abc.Messageable.send"><code class="xref py py-meth docutils literal notranslate"><span class="pre">abc.Messageable.send()</span></code></a>. For example:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">user</span> <span class="o">=</span> <span class="n">client</span><span class="o">.</span><span class="n">get_user</span><span class="p">(</span><span class="mi">381870129706958858</span><span class="p">)</span>
<span class="k">await</span> <span class="n">user</span><span class="o">.</span><span class="n">send</span><span class="p">(</span><span class="s1">&#39;👀&#39;</span><span class="p">)</span>
</pre></div>
</div>
<p>If you are responding to an event, such as <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>, you already have the <a class="reference internal" href="api.html#discord.User" title="discord.User"><code class="xref py py-class docutils literal notranslate"><span class="pre">User</span></code></a> object via <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>:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">await</span> <span class="n">message</span><span class="o">.</span><span class="n">author</span><span class="o">.</span><span class="n">send</span><span class="p">(</span><span class="s1">&#39;👋&#39;</span><span class="p">)</span>
</pre></div>
</div>
</section>
<section id="how-do-i-get-the-id-of-a-sent-message">
<h3><a class="toc-backref" href="#id10">How do I get the ID of a sent message?</a><a class="headerlink" href="#how-do-i-get-the-id-of-a-sent-message" title="Permalink to this headline"></a></h3>
<p><a class="reference internal" href="api.html#discord.abc.Messageable.send" title="discord.abc.Messageable.send"><code class="xref py py-meth docutils literal notranslate"><span class="pre">abc.Messageable.send()</span></code></a> returns the <a class="reference internal" href="api.html#discord.Message" title="discord.Message"><code class="xref py py-class docutils literal notranslate"><span class="pre">Message</span></code></a> that was sent.
The ID of a message can be accessed via <a class="reference internal" href="api.html#discord.Message.id" title="discord.Message.id"><code class="xref py py-attr docutils literal notranslate"><span class="pre">Message.id</span></code></a>:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">message</span> <span class="o">=</span> <span class="k">await</span> <span class="n">channel</span><span class="o">.</span><span class="n">send</span><span class="p">(</span><span class="s1">&#39;hmm…&#39;</span><span class="p">)</span>
<span class="n">message_id</span> <span class="o">=</span> <span class="n">message</span><span class="o">.</span><span class="n">id</span>
</pre></div>
</div>
</section>
<section id="how-do-i-upload-an-image">
<h3><a class="toc-backref" href="#id11">How do I upload an image?</a><a class="headerlink" href="#how-do-i-upload-an-image" title="Permalink to this headline"></a></h3>
<p>To upload something to Discord you have to use the <a class="reference internal" href="api.html#discord.File" title="discord.File"><code class="xref py py-class docutils literal notranslate"><span class="pre">File</span></code></a> object.</p>
<p>A <a class="reference internal" href="api.html#discord.File" title="discord.File"><code class="xref py py-class docutils literal notranslate"><span class="pre">File</span></code></a> accepts two parameters, the file-like object (or file path) and the filename
to pass to Discord when uploading.</p>
<p>If you want to upload an image its as simple as:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">await</span> <span class="n">channel</span><span class="o">.</span><span class="n">send</span><span class="p">(</span><span class="n">file</span><span class="o">=</span><span class="n">discord</span><span class="o">.</span><span class="n">File</span><span class="p">(</span><span class="s1">&#39;my_file.png&#39;</span><span class="p">))</span>
</pre></div>
</div>
<p>If you have a file-like object you can do as follows:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">with</span> <span class="nb">open</span><span class="p">(</span><span class="s1">&#39;my_file.png&#39;</span><span class="p">,</span> <span class="s1">&#39;rb&#39;</span><span class="p">)</span> <span class="k">as</span> <span class="n">fp</span><span class="p">:</span>
<span class="k">await</span> <span class="n">channel</span><span class="o">.</span><span class="n">send</span><span class="p">(</span><span class="n">file</span><span class="o">=</span><span class="n">discord</span><span class="o">.</span><span class="n">File</span><span class="p">(</span><span class="n">fp</span><span class="p">,</span> <span class="s1">&#39;new_filename.png&#39;</span><span class="p">))</span>
</pre></div>
</div>
<p>To upload multiple files, you can use the <code class="docutils literal notranslate"><span class="pre">files</span></code> keyword argument instead of <code class="docutils literal notranslate"><span class="pre">file</span></code>:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">my_files</span> <span class="o">=</span> <span class="p">[</span>
<span class="n">discord</span><span class="o">.</span><span class="n">File</span><span class="p">(</span><span class="s1">&#39;result.zip&#39;</span><span class="p">),</span>
<span class="n">discord</span><span class="o">.</span><span class="n">File</span><span class="p">(</span><span class="s1">&#39;teaser_graph.png&#39;</span><span class="p">),</span>
<span class="p">]</span>
<span class="k">await</span> <span class="n">channel</span><span class="o">.</span><span class="n">send</span><span class="p">(</span><span class="n">files</span><span class="o">=</span><span class="n">my_files</span><span class="p">)</span>
</pre></div>
</div>
<p>If you want to upload something from a URL, you will have to use an HTTP request using <a class="reference external" href="https://docs.aiohttp.org/en/stable/index.html" title="(in aiohttp v3.7)"><span class="xref std std-doc">aiohttp</span></a>
and then pass an <a class="reference external" href="https://docs.python.org/3/library/io.html#io.BytesIO" title="(in Python v3.9)"><code class="xref py py-class docutils literal notranslate"><span class="pre">io.BytesIO</span></code></a> instance to <a class="reference internal" href="api.html#discord.File" title="discord.File"><code class="xref py py-class docutils literal notranslate"><span class="pre">File</span></code></a> like so:</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="kn">import</span> <span class="nn">io</span>
<span class="kn">import</span> <span class="nn">aiohttp</span>
<span class="k">async</span> <span class="k">with</span> <span class="n">aiohttp</span><span class="o">.</span><span class="n">ClientSession</span><span class="p">()</span> <span class="k">as</span> <span class="n">session</span><span class="p">:</span>
<span class="k">async</span> <span class="k">with</span> <span class="n">session</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">my_url</span><span class="p">)</span> <span class="k">as</span> <span class="n">resp</span><span class="p">:</span>
<span class="k">if</span> <span class="n">resp</span><span class="o">.</span><span class="n">status</span> <span class="o">!=</span> <span class="mi">200</span><span class="p">:</span>
<span class="k">return</span> <span class="k">await</span> <span class="n">channel</span><span class="o">.</span><span class="n">send</span><span class="p">(</span><span class="s1">&#39;Could not download file...&#39;</span><span class="p">)</span>
<span class="n">data</span> <span class="o">=</span> <span class="n">io</span><span class="o">.</span><span class="n">BytesIO</span><span class="p">(</span><span class="k">await</span> <span class="n">resp</span><span class="o">.</span><span class="n">read</span><span class="p">())</span>
<span class="k">await</span> <span class="n">channel</span><span class="o">.</span><span class="n">send</span><span class="p">(</span><span class="n">file</span><span class="o">=</span><span class="n">discord</span><span class="o">.</span><span class="n">File</span><span class="p">(</span><span class="n">data</span><span class="p">,</span> <span class="s1">&#39;cool_image.png&#39;</span><span class="p">))</span>
</pre></div>
</div>
</section>
<section id="how-can-i-add-a-reaction-to-a-message">
<h3><a class="toc-backref" href="#id12">How can I add a reaction to a message?</a><a class="headerlink" href="#how-can-i-add-a-reaction-to-a-message" title="Permalink to this headline"></a></h3>
<p>You use the <a class="reference internal" href="api.html#discord.Message.add_reaction" title="discord.Message.add_reaction"><code class="xref py py-meth docutils literal notranslate"><span class="pre">Message.add_reaction()</span></code></a> method.</p>
<p>If you want to use unicode emoji, you must pass a valid unicode code point in a string. In your code, you can write this in a few different ways:</p>
<ul class="simple">
<li><p><code class="docutils literal notranslate"><span class="pre">'👍'</span></code></p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">'\U0001F44D'</span></code></p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">'\N{THUMBS</span> <span class="pre">UP</span> <span class="pre">SIGN}'</span></code></p></li>
</ul>
<p>Quick example:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">emoji</span> <span class="o">=</span> <span class="s1">&#39;</span><span class="se">\N{THUMBS UP SIGN}</span><span class="s1">&#39;</span>
<span class="c1"># or &#39;\U0001f44d&#39; or &#39;👍&#39;</span>
<span class="k">await</span> <span class="n">message</span><span class="o">.</span><span class="n">add_reaction</span><span class="p">(</span><span class="n">emoji</span><span class="p">)</span>
</pre></div>
</div>
<p>In case you want to use emoji that come from a message, you already get their code points in the content without needing
to do anything special. You <strong>cannot</strong> send <code class="docutils literal notranslate"><span class="pre">':thumbsup:'</span></code> style shorthands.</p>
<p>For custom emoji, you should pass an instance of <a class="reference internal" href="api.html#discord.Emoji" title="discord.Emoji"><code class="xref py py-class docutils literal notranslate"><span class="pre">Emoji</span></code></a>. You can also pass a <code class="docutils literal notranslate"><span class="pre">'&lt;:name:id&gt;'</span></code> string, but if you
can use said emoji, you should be able to use <a class="reference internal" href="api.html#discord.Client.get_emoji" title="discord.Client.get_emoji"><code class="xref py py-meth docutils literal notranslate"><span class="pre">Client.get_emoji()</span></code></a> to get an emoji via ID or use <a class="reference internal" href="api.html#discord.utils.find" title="discord.utils.find"><code class="xref py py-func docutils literal notranslate"><span class="pre">utils.find()</span></code></a>/
<a class="reference internal" href="api.html#discord.utils.get" title="discord.utils.get"><code class="xref py py-func docutils literal notranslate"><span class="pre">utils.get()</span></code></a> on <a class="reference internal" href="api.html#discord.Client.emojis" title="discord.Client.emojis"><code class="xref py py-attr docutils literal notranslate"><span class="pre">Client.emojis</span></code></a> or <a class="reference internal" href="api.html#discord.Guild.emojis" title="discord.Guild.emojis"><code class="xref py py-attr docutils literal notranslate"><span class="pre">Guild.emojis</span></code></a> collections.</p>
<p>The name and ID of a custom emoji can be found with the client by prefixing <code class="docutils literal notranslate"><span class="pre">:custom_emoji:</span></code> with a backslash.
For example, sending the message <code class="docutils literal notranslate"><span class="pre">\:python3:</span></code> with the client will result in <code class="docutils literal notranslate"><span class="pre">&lt;:python3:232720527448342530&gt;</span></code>.</p>
<p>Quick example:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="c1"># if you have the ID already</span>
<span class="n">emoji</span> <span class="o">=</span> <span class="n">client</span><span class="o">.</span><span class="n">get_emoji</span><span class="p">(</span><span class="mi">310177266011340803</span><span class="p">)</span>
<span class="k">await</span> <span class="n">message</span><span class="o">.</span><span class="n">add_reaction</span><span class="p">(</span><span class="n">emoji</span><span class="p">)</span>
<span class="c1"># no ID, do a lookup</span>
<span class="n">emoji</span> <span class="o">=</span> <span class="n">discord</span><span class="o">.</span><span class="n">utils</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">guild</span><span class="o">.</span><span class="n">emojis</span><span class="p">,</span> <span class="n">name</span><span class="o">=</span><span class="s1">&#39;LUL&#39;</span><span class="p">)</span>
<span class="k">if</span> <span class="n">emoji</span><span class="p">:</span>
<span class="k">await</span> <span class="n">message</span><span class="o">.</span><span class="n">add_reaction</span><span class="p">(</span><span class="n">emoji</span><span class="p">)</span>
<span class="c1"># if you have the name and ID of a custom emoji:</span>
<span class="n">emoji</span> <span class="o">=</span> <span class="s1">&#39;&lt;:python3:232720527448342530&gt;&#39;</span>
<span class="k">await</span> <span class="n">message</span><span class="o">.</span><span class="n">add_reaction</span><span class="p">(</span><span class="n">emoji</span><span class="p">)</span>
</pre></div>
</div>
</section>
<section id="how-do-i-pass-a-coroutine-to-the-player-s-after-function">
<h3><a class="toc-backref" href="#id13">How do I pass a coroutine to the players “after” function?</a><a class="headerlink" href="#how-do-i-pass-a-coroutine-to-the-player-s-after-function" title="Permalink to this headline"></a></h3>
<p>The librarys music player launches on a separate thread, ergo it does not execute inside a coroutine.
This does not mean that it is not possible to call a coroutine in the <code class="docutils literal notranslate"><span class="pre">after</span></code> parameter. To do so you must pass a callable
that wraps up a couple of aspects.</p>
<p>The first gotcha that you must be aware of is that calling a coroutine is not a thread-safe operation. Since we are
technically in another thread, we must take caution in calling thread-safe operations so things do not bug out. Luckily for
us, <a class="reference external" href="https://docs.python.org/3/library/asyncio.html#module-asyncio" title="(in Python v3.9)"><code class="xref py py-mod docutils literal notranslate"><span class="pre">asyncio</span></code></a> comes with a <a class="reference external" href="https://docs.python.org/3/library/asyncio-task.html#asyncio.run_coroutine_threadsafe" title="(in Python v3.9)"><code class="xref py py-func docutils literal notranslate"><span class="pre">asyncio.run_coroutine_threadsafe()</span></code></a> function that allows us to call
a coroutine from another thread.</p>
<p>However, this function returns a <a class="reference external" href="https://docs.python.org/3/library/concurrent.futures.html#concurrent.futures.Future" title="(in Python v3.9)"><code class="xref py py-class docutils literal notranslate"><span class="pre">Future</span></code></a> and to actually call it we have to fetch its result. Putting all of
this together we can do the following:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">def</span> <span class="nf">my_after</span><span class="p">(</span><span class="n">error</span><span class="p">):</span>
<span class="n">coro</span> <span class="o">=</span> <span class="n">some_channel</span><span class="o">.</span><span class="n">send</span><span class="p">(</span><span class="s1">&#39;Song is done!&#39;</span><span class="p">)</span>
<span class="n">fut</span> <span class="o">=</span> <span class="n">asyncio</span><span class="o">.</span><span class="n">run_coroutine_threadsafe</span><span class="p">(</span><span class="n">coro</span><span class="p">,</span> <span class="n">client</span><span class="o">.</span><span class="n">loop</span><span class="p">)</span>
<span class="k">try</span><span class="p">:</span>
<span class="n">fut</span><span class="o">.</span><span class="n">result</span><span class="p">()</span>
<span class="k">except</span><span class="p">:</span>
<span class="c1"># an error happened sending the message</span>
<span class="k">pass</span>
<span class="n">voice</span><span class="o">.</span><span class="n">play</span><span class="p">(</span><span class="n">discord</span><span class="o">.</span><span class="n">FFmpegPCMAudio</span><span class="p">(</span><span class="n">url</span><span class="p">),</span> <span class="n">after</span><span class="o">=</span><span class="n">my_after</span><span class="p">)</span>
</pre></div>
</div>
</section>
<section id="how-do-i-run-something-in-the-background">
<h3><a class="toc-backref" href="#id14">How do I run something in the background?</a><a class="headerlink" href="#how-do-i-run-something-in-the-background" title="Permalink to this headline"></a></h3>
<p><a class="reference external" href="https://github.com/Rapptz/discord.py/blob/master/examples/background_task.py">Check the background_task.py example.</a></p>
</section>
<section id="how-do-i-get-a-specific-model">
<h3><a class="toc-backref" href="#id15">How do I get a specific model?</a><a class="headerlink" href="#how-do-i-get-a-specific-model" title="Permalink to this headline"></a></h3>
<p>There are multiple ways of doing this. If you have a specific models ID then you can use
one of the following functions:</p>
<ul class="simple">
<li><p><a class="reference internal" href="api.html#discord.Client.get_channel" title="discord.Client.get_channel"><code class="xref py py-meth docutils literal notranslate"><span class="pre">Client.get_channel()</span></code></a></p></li>
<li><p><a class="reference internal" href="api.html#discord.Client.get_guild" title="discord.Client.get_guild"><code class="xref py py-meth docutils literal notranslate"><span class="pre">Client.get_guild()</span></code></a></p></li>
<li><p><a class="reference internal" href="api.html#discord.Client.get_user" title="discord.Client.get_user"><code class="xref py py-meth docutils literal notranslate"><span class="pre">Client.get_user()</span></code></a></p></li>
<li><p><a class="reference internal" href="api.html#discord.Client.get_emoji" title="discord.Client.get_emoji"><code class="xref py py-meth docutils literal notranslate"><span class="pre">Client.get_emoji()</span></code></a></p></li>
<li><p><a class="reference internal" href="api.html#discord.Guild.get_member" title="discord.Guild.get_member"><code class="xref py py-meth docutils literal notranslate"><span class="pre">Guild.get_member()</span></code></a></p></li>
<li><p><a class="reference internal" href="api.html#discord.Guild.get_channel" title="discord.Guild.get_channel"><code class="xref py py-meth docutils literal notranslate"><span class="pre">Guild.get_channel()</span></code></a></p></li>
<li><p><a class="reference internal" href="api.html#discord.Guild.get_role" title="discord.Guild.get_role"><code class="xref py py-meth docutils literal notranslate"><span class="pre">Guild.get_role()</span></code></a></p></li>
</ul>
<p>The following use an HTTP request:</p>
<ul class="simple">
<li><p><a class="reference internal" href="api.html#discord.abc.Messageable.fetch_message" title="discord.abc.Messageable.fetch_message"><code class="xref py py-meth docutils literal notranslate"><span class="pre">abc.Messageable.fetch_message()</span></code></a></p></li>
<li><p><a class="reference internal" href="api.html#discord.Client.fetch_user" title="discord.Client.fetch_user"><code class="xref py py-meth docutils literal notranslate"><span class="pre">Client.fetch_user()</span></code></a></p></li>
<li><p><a class="reference internal" href="api.html#discord.Client.fetch_guilds" title="discord.Client.fetch_guilds"><code class="xref py py-meth docutils literal notranslate"><span class="pre">Client.fetch_guilds()</span></code></a></p></li>
<li><p><a class="reference internal" href="api.html#discord.Client.fetch_guild" title="discord.Client.fetch_guild"><code class="xref py py-meth docutils literal notranslate"><span class="pre">Client.fetch_guild()</span></code></a></p></li>
<li><p><a class="reference internal" href="api.html#discord.Guild.fetch_emoji" title="discord.Guild.fetch_emoji"><code class="xref py py-meth docutils literal notranslate"><span class="pre">Guild.fetch_emoji()</span></code></a></p></li>
<li><p><a class="reference internal" href="api.html#discord.Guild.fetch_emojis" title="discord.Guild.fetch_emojis"><code class="xref py py-meth docutils literal notranslate"><span class="pre">Guild.fetch_emojis()</span></code></a></p></li>
<li><p><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></p></li>
</ul>
<p>If the functions above do not help you, then use of <a class="reference internal" href="api.html#discord.utils.find" title="discord.utils.find"><code class="xref py py-func docutils literal notranslate"><span class="pre">utils.find()</span></code></a> or <a class="reference internal" href="api.html#discord.utils.get" title="discord.utils.get"><code class="xref py py-func docutils literal notranslate"><span class="pre">utils.get()</span></code></a> would serve some use in finding
specific models.</p>
<p>Quick example:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="c1"># find a guild by name</span>
<span class="n">guild</span> <span class="o">=</span> <span class="n">discord</span><span class="o">.</span><span class="n">utils</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">client</span><span class="o">.</span><span class="n">guilds</span><span class="p">,</span> <span class="n">name</span><span class="o">=</span><span class="s1">&#39;My Server&#39;</span><span class="p">)</span>
<span class="c1"># make sure to check if it&#39;s found</span>
<span class="k">if</span> <span class="n">guild</span> <span class="ow">is</span> <span class="ow">not</span> <span class="kc">None</span><span class="p">:</span>
<span class="c1"># find a channel by name</span>
<span class="n">channel</span> <span class="o">=</span> <span class="n">discord</span><span class="o">.</span><span class="n">utils</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">guild</span><span class="o">.</span><span class="n">text_channels</span><span class="p">,</span> <span class="n">name</span><span class="o">=</span><span class="s1">&#39;cool-channel&#39;</span><span class="p">)</span>
</pre></div>
</div>
</section>
<section id="how-do-i-make-a-web-request">
<h3><a class="toc-backref" href="#id16">How do I make a web request?</a><a class="headerlink" href="#how-do-i-make-a-web-request" title="Permalink to this headline"></a></h3>
<p>To make a request, you should use a non-blocking library.
This library already uses and requires a 3rd party library for making requests, <a class="reference external" href="https://docs.aiohttp.org/en/stable/index.html" title="(in aiohttp v3.7)"><span class="xref std std-doc">aiohttp</span></a>.</p>
<p>Quick example:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="k">async</span> <span class="k">with</span> <span class="n">aiohttp</span><span class="o">.</span><span class="n">ClientSession</span><span class="p">()</span> <span class="k">as</span> <span class="n">session</span><span class="p">:</span>
<span class="k">async</span> <span class="k">with</span> <span class="n">session</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s1">&#39;http://aws.random.cat/meow&#39;</span><span class="p">)</span> <span class="k">as</span> <span class="n">r</span><span class="p">:</span>
<span class="k">if</span> <span class="n">r</span><span class="o">.</span><span class="n">status</span> <span class="o">==</span> <span class="mi">200</span><span class="p">:</span>
<span class="n">js</span> <span class="o">=</span> <span class="k">await</span> <span class="n">r</span><span class="o">.</span><span class="n">json</span><span class="p">()</span>
</pre></div>
</div>
<p>See <a class="reference external" href="http://aiohttp.readthedocs.io/en/stable/">aiohttps full documentation</a> for more information.</p>
</section>
<section id="how-do-i-use-a-local-image-file-for-an-embed-image">
<h3><a class="toc-backref" href="#id17">How do I use a local image file for an embed image?</a><a class="headerlink" href="#how-do-i-use-a-local-image-file-for-an-embed-image" title="Permalink to this headline"></a></h3>
<p>Discord special-cases uploading an image attachment and using it within an embed so that it will not
display separately, but instead in the embeds thumbnail, image, footer or author icon.</p>
<p>To do so, upload the image normally with <a class="reference internal" href="api.html#discord.abc.Messageable.send" title="discord.abc.Messageable.send"><code class="xref py py-meth docutils literal notranslate"><span class="pre">abc.Messageable.send()</span></code></a>,
and set the embeds image URL to <code class="docutils literal notranslate"><span class="pre">attachment://image.png</span></code>,
where <code class="docutils literal notranslate"><span class="pre">image.png</span></code> is the filename of the image you will send.</p>
<p>Quick example:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">file</span> <span class="o">=</span> <span class="n">discord</span><span class="o">.</span><span class="n">File</span><span class="p">(</span><span class="s2">&quot;path/to/my/image.png&quot;</span><span class="p">,</span> <span class="n">filename</span><span class="o">=</span><span class="s2">&quot;image.png&quot;</span><span class="p">)</span>
<span class="n">embed</span> <span class="o">=</span> <span class="n">discord</span><span class="o">.</span><span class="n">Embed</span><span class="p">()</span>
<span class="n">embed</span><span class="o">.</span><span class="n">set_image</span><span class="p">(</span><span class="n">url</span><span class="o">=</span><span class="s2">&quot;attachment://image.png&quot;</span><span class="p">)</span>
<span class="k">await</span> <span class="n">channel</span><span class="o">.</span><span class="n">send</span><span class="p">(</span><span class="n">file</span><span class="o">=</span><span class="n">file</span><span class="p">,</span> <span class="n">embed</span><span class="o">=</span><span class="n">embed</span><span class="p">)</span>
</pre></div>
</div>
<div class="admonition note">
<p class="admonition-title">Note</p>
<p>Due to a Discord limitation, filenames may not include underscores.</p>
</div>
</section>
<section id="is-there-an-event-for-audit-log-entries-being-created">
<h3><a class="toc-backref" href="#id18">Is there an event for audit log entries being created?</a><a class="headerlink" href="#is-there-an-event-for-audit-log-entries-being-created" title="Permalink to this headline"></a></h3>
<p>Since Discord does not dispatch this information in the gateway, the library cannot provide this information.
This is currently a Discord limitation.</p>
</section>
</section>
<section id="commands-extension">
<h2><a class="toc-backref" href="#id19">Commands Extension</a><a class="headerlink" href="#commands-extension" title="Permalink to this headline"></a></h2>
<p>Questions regarding <code class="docutils literal notranslate"><span class="pre">discord.ext.commands</span></code> belong here.</p>
<section id="why-does-on-message-make-my-commands-stop-working">
<h3><a class="toc-backref" href="#id20">Why does <code class="docutils literal notranslate"><span class="pre">on_message</span></code> make my commands stop working?</a><a class="headerlink" href="#why-does-on-message-make-my-commands-stop-working" title="Permalink to this headline"></a></h3>
<p>Overriding the default provided <code class="docutils literal notranslate"><span class="pre">on_message</span></code> forbids any extra commands from running. To fix this, add a
<code class="docutils literal notranslate"><span class="pre">bot.process_commands(message)</span></code> line at the end of your <code class="docutils literal notranslate"><span class="pre">on_message</span></code>. For example:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="nd">@bot</span><span class="o">.</span><span class="n">event</span>
<span class="k">async</span> <span class="k">def</span> <span class="nf">on_message</span><span class="p">(</span><span class="n">message</span><span class="p">):</span>
<span class="c1"># do some extra stuff here</span>
<span class="k">await</span> <span class="n">bot</span><span class="o">.</span><span class="n">process_commands</span><span class="p">(</span><span class="n">message</span><span class="p">)</span>
</pre></div>
</div>
<p>Alternatively, you can place your <code class="docutils literal notranslate"><span class="pre">on_message</span></code> logic into a <strong>listener</strong>. In this setup, you should not
manually call <code class="docutils literal notranslate"><span class="pre">bot.process_commands()</span></code>. This also allows you to do multiple things asynchronously in response
to a message. Example:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="nd">@bot</span><span class="o">.</span><span class="n">listen</span><span class="p">(</span><span class="s1">&#39;on_message&#39;</span><span class="p">)</span>
<span class="k">async</span> <span class="k">def</span> <span class="nf">whatever_you_want_to_call_it</span><span class="p">(</span><span class="n">message</span><span class="p">):</span>
<span class="c1"># do stuff here</span>
<span class="c1"># do not process commands here</span>
</pre></div>
</div>
</section>
<section id="why-do-my-arguments-require-quotes">
<h3><a class="toc-backref" href="#id21">Why do my arguments require quotes?</a><a class="headerlink" href="#why-do-my-arguments-require-quotes" title="Permalink to this headline"></a></h3>
<p>In a simple command defined as:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="nd">@bot</span><span class="o">.</span><span class="n">command</span><span class="p">()</span>
<span class="k">async</span> <span class="k">def</span> <span class="nf">echo</span><span class="p">(</span><span class="n">ctx</span><span class="p">,</span> <span class="n">message</span><span class="p">:</span> <span class="nb">str</span><span class="p">):</span>
<span class="k">await</span> <span class="n">ctx</span><span class="o">.</span><span class="n">send</span><span class="p">(</span><span class="n">message</span><span class="p">)</span>
</pre></div>
</div>
<p>Calling it via <code class="docutils literal notranslate"><span class="pre">?echo</span> <span class="pre">a</span> <span class="pre">b</span> <span class="pre">c</span></code> will only fetch the first argument and disregard the rest. To fix this you should either call
it via <code class="docutils literal notranslate"><span class="pre">?echo</span> <span class="pre">&quot;a</span> <span class="pre">b</span> <span class="pre">c&quot;</span></code> or change the signature to have “consume rest” behaviour. Example:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="nd">@bot</span><span class="o">.</span><span class="n">command</span><span class="p">()</span>
<span class="k">async</span> <span class="k">def</span> <span class="nf">echo</span><span class="p">(</span><span class="n">ctx</span><span class="p">,</span> <span class="o">*</span><span class="p">,</span> <span class="n">message</span><span class="p">:</span> <span class="nb">str</span><span class="p">):</span>
<span class="k">await</span> <span class="n">ctx</span><span class="o">.</span><span class="n">send</span><span class="p">(</span><span class="n">message</span><span class="p">)</span>
</pre></div>
</div>
<p>This will allow you to use <code class="docutils literal notranslate"><span class="pre">?echo</span> <span class="pre">a</span> <span class="pre">b</span> <span class="pre">c</span></code> without needing the quotes.</p>
</section>
<section id="how-do-i-get-the-original-message">
<h3><a class="toc-backref" href="#id22">How do I get the original <code class="docutils literal notranslate"><span class="pre">message</span></code>?</a><a class="headerlink" href="#how-do-i-get-the-original-message" title="Permalink to this headline"></a></h3>
<p>The <a class="reference internal" href="ext/commands/api.html#discord.ext.commands.Context" title="discord.ext.commands.Context"><code class="xref py py-class docutils literal notranslate"><span class="pre">Context</span></code></a> contains an attribute, <a class="reference internal" href="ext/commands/api.html#discord.ext.commands.Context.message" title="discord.ext.commands.Context.message"><code class="xref py py-attr docutils literal notranslate"><span class="pre">message</span></code></a> to get the original
message.</p>
<p>Example:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="nd">@bot</span><span class="o">.</span><span class="n">command</span><span class="p">()</span>
<span class="k">async</span> <span class="k">def</span> <span class="nf">length</span><span class="p">(</span><span class="n">ctx</span><span class="p">):</span>
<span class="k">await</span> <span class="n">ctx</span><span class="o">.</span><span class="n">send</span><span class="p">(</span><span class="sa">f</span><span class="s1">&#39;Your message is </span><span class="si">{</span><span class="nb">len</span><span class="p">(</span><span class="n">ctx</span><span class="o">.</span><span class="n">message</span><span class="o">.</span><span class="n">content</span><span class="p">)</span><span class="si">}</span><span class="s1"> characters long.&#39;</span><span class="p">)</span>
</pre></div>
</div>
</section>
<section id="how-do-i-make-a-subcommand">
<h3><a class="toc-backref" href="#id23">How do I make a subcommand?</a><a class="headerlink" href="#how-do-i-make-a-subcommand" title="Permalink to this headline"></a></h3>
<p>Use the <a class="reference internal" href="ext/commands/api.html#discord.ext.commands.group" title="discord.ext.commands.group"><code class="xref py py-func docutils literal notranslate"><span class="pre">group()</span></code></a> decorator. This will transform the callback into a <a class="reference internal" href="ext/commands/api.html#discord.ext.commands.Group" title="discord.ext.commands.Group"><code class="xref py py-class docutils literal notranslate"><span class="pre">Group</span></code></a> which will allow you to add commands into
the group operating as “subcommands”. These groups can be arbitrarily nested as well.</p>
<p>Example:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="nd">@bot</span><span class="o">.</span><span class="n">group</span><span class="p">()</span>
<span class="k">async</span> <span class="k">def</span> <span class="nf">git</span><span class="p">(</span><span class="n">ctx</span><span class="p">):</span>
<span class="k">if</span> <span class="n">ctx</span><span class="o">.</span><span class="n">invoked_subcommand</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span>
<span class="k">await</span> <span class="n">ctx</span><span class="o">.</span><span class="n">send</span><span class="p">(</span><span class="s1">&#39;Invalid git command passed...&#39;</span><span class="p">)</span>
<span class="nd">@git</span><span class="o">.</span><span class="n">command</span><span class="p">()</span>
<span class="k">async</span> <span class="k">def</span> <span class="nf">push</span><span class="p">(</span><span class="n">ctx</span><span class="p">,</span> <span class="n">remote</span><span class="p">:</span> <span class="nb">str</span><span class="p">,</span> <span class="n">branch</span><span class="p">:</span> <span class="nb">str</span><span class="p">):</span>
<span class="k">await</span> <span class="n">ctx</span><span class="o">.</span><span class="n">send</span><span class="p">(</span><span class="sa">f</span><span class="s1">&#39;Pushing to </span><span class="si">{</span><span class="n">remote</span><span class="si">}</span><span class="s1"> </span><span class="si">{</span><span class="n">branch</span><span class="si">}</span><span class="s1">&#39;</span><span class="p">)</span>
</pre></div>
</div>
<p>This could then be used as <code class="docutils literal notranslate"><span class="pre">?git</span> <span class="pre">push</span> <span class="pre">origin</span> <span class="pre">master</span></code>.</p>
</section>
<section id="how-do-i-make-slash-commands">
<h3><a class="toc-backref" href="#id24">How do I make slash commands?</a><a class="headerlink" href="#how-do-i-make-slash-commands" title="Permalink to this headline"></a></h3>
<p>See <a class="reference internal" href="ext/commands/slash-commands.html"><span class="doc">Slash Commands</span></a></p>
</section>
<section id="my-slash-commands-aren-t-showing-up">
<h3><a class="toc-backref" href="#id25">My slash commands arent showing up!</a><a class="headerlink" href="#my-slash-commands-aren-t-showing-up" title="Permalink to this headline"></a></h3>
<p id="ext-commands-slash-command-troubleshooting">You need to invite your bot with the <code class="docutils literal notranslate"><span class="pre">application.commands</span></code> scope on each guild and
you need the <a class="reference internal" href="api.html#discord.Permissions.use_slash_commands" title="discord.Permissions.use_slash_commands"><code class="xref py py-attr docutils literal notranslate"><span class="pre">Permissions.use_slash_commands</span></code></a> permission in order to see slash commands.</p>
<img alt="The scopes checkbox with &quot;bot&quot; and &quot;applications.commands&quot; ticked." src="images/discord_oauth2_slash_scope.png" />
<p>Global slash commands (created by not specifying <a class="reference internal" href="ext/commands/api.html#discord.ext.commands.Bot.slash_command_guilds" title="discord.ext.commands.Bot.slash_command_guilds"><code class="xref py py-attr docutils literal notranslate"><span class="pre">slash_command_guilds</span></code></a>) will also take up an
hour to refresh on discords end, so it is recommended to set <a class="reference internal" href="ext/commands/api.html#discord.ext.commands.Bot.slash_command_guilds" title="discord.ext.commands.Bot.slash_command_guilds"><code class="xref py py-attr docutils literal notranslate"><span class="pre">slash_command_guilds</span></code></a> for development.</p>
<p>If none of this works, make sure you are actually running enhanced-discord.py by doing <code class="docutils literal notranslate"><span class="pre">print(bot.slash_commands)</span></code></p>
</section>
<section id="my-bot-won-t-start-after-enabling-slash-commands">
<h3><a class="toc-backref" href="#id26">My bot wont start after enabling slash commands!</a><a class="headerlink" href="#my-bot-won-t-start-after-enabling-slash-commands" title="Permalink to this headline"></a></h3>
<p>This means some of your command metadata is invalid for slash commands.
Make sure your command names and option names are lowercase, and they have to match the regex <code class="docutils literal notranslate"><span class="pre">^[\w-]{1,32}$</span></code></p>
<p>If you cannot figure out the problem, you should disable slash commands globally (<a class="reference internal" href="ext/commands/api.html#discord.ext.commands.Bot.slash_commands" title="discord.ext.commands.Bot.slash_commands"><code class="xref py py-attr docutils literal notranslate"><span class="pre">slash_commands</span></code></a>=False)
then go through commands, enabling them specifically with <a class="reference internal" href="ext/commands/api.html#discord.ext.commands.Command.slash_command" title="discord.ext.commands.Command.slash_command"><code class="xref py py-attr docutils literal notranslate"><span class="pre">slash_command</span></code></a>=True until it
errors, then you can debug the problem with that command specifically.</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>

File diff suppressed because it is too large Load Diff

213
docs/Python/html/index.html Normal file
View File

@ -0,0 +1,213 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Welcome to discord.py</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" />
<link rel="next" title="discord.ext.commands Bot commands framework" href="ext/commands/index.html" />
</head>
<body>
<div class="main-grid">
<header class="grid-item">
<nav>
<a href="#" 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="#">Table of Contents</a></h3>
<ul>
<li><a class="reference internal" href="#">Welcome to discord.py</a><ul>
<li><a class="reference internal" href="#getting-started">Getting started</a></li>
<li><a class="reference internal" href="#getting-help">Getting help</a></li>
<li><a class="reference internal" href="#extensions">Extensions</a></li>
<li><a class="reference internal" href="#manuals">Manuals</a></li>
<li><a class="reference internal" href="#meta">Meta</a></li>
</ul>
</li>
</ul>
</div>
</aside>
<main class="grid-item" role="main">
<section id="welcome-to-discord-py">
<h1>Welcome to discord.py<a class="headerlink" href="#welcome-to-discord-py" title="Permalink to this headline"></a></h1>
<img alt="_images/snake.svg" src="_images/snake.svg" /><img alt="_images/snake_dark.svg" src="_images/snake_dark.svg" /><p>discord.py is a modern, easy to use, feature-rich, and async ready API wrapper
for Discord.</p>
<p><strong>Features:</strong></p>
<ul class="simple">
<li><p>Modern Pythonic API using <code class="docutils literal notranslate"><span class="pre">async</span></code>/<code class="docutils literal notranslate"><span class="pre">await</span></code> syntax</p></li>
<li><p>Sane rate limit handling that prevents 429s</p></li>
<li><p>Command extension to aid with bot creation</p></li>
<li><p>Easy to use with an object oriented design</p></li>
<li><p>Optimised for both speed and memory</p></li>
</ul>
<section id="getting-started">
<h2>Getting started<a class="headerlink" href="#getting-started" title="Permalink to this headline"></a></h2>
<p>Is this your first time using the library? This is the place to get started!</p>
<ul class="simple">
<li><p><strong>First steps:</strong> <a class="reference internal" href="intro.html"><span class="doc">Introduction</span></a> | <a class="reference internal" href="quickstart.html"><span class="doc">Quickstart</span></a> | <a class="reference internal" href="logging.html"><span class="doc">Setting Up Logging</span></a></p></li>
<li><p><strong>Working with Discord:</strong> <a class="reference internal" href="discord.html"><span class="doc">Creating a Bot Account</span></a> | <a class="reference internal" href="intents.html"><span class="doc">A Primer to Gateway Intents</span></a></p></li>
<li><p><strong>Examples:</strong> Many examples are available in the <a class="reference external" href="https://github.com/Rapptz/discord.py/tree/master/examples">repository</a>.</p></li>
</ul>
</section>
<section id="getting-help">
<h2>Getting help<a class="headerlink" href="#getting-help" title="Permalink to this headline"></a></h2>
<p>If youre having trouble with something, these resources might help.</p>
<ul class="simple">
<li><p>Try the <a class="reference internal" href="faq.html"><span class="doc">Frequently Asked Questions</span></a> first, its got answers to all common questions.</p></li>
<li><p>Ask us and hang out with us in our <a class="reference external" href="https://discord.gg/TvqYBrGXEm">Discord</a> server.</p></li>
<li><p>If youre looking for something specific, try the <a class="reference internal" href="genindex.html"><span class="std std-ref">index</span></a> or <a class="reference internal" href="search.html"><span class="std std-ref">searching</span></a>.</p></li>
<li><p>Report bugs in the <a class="reference external" href="https://github.com/Rapptz/discord.py/issues">issue tracker</a>.</p></li>
<li><p>Ask in our <a class="reference external" href="https://github.com/Rapptz/discord.py/discussions">GitHub discussions page</a>.</p></li>
</ul>
</section>
<section id="extensions">
<h2>Extensions<a class="headerlink" href="#extensions" title="Permalink to this headline"></a></h2>
<p>These extensions help you during development when it comes to common tasks.</p>
<div class="toctree-wrapper compound">
<ul>
<li class="toctree-l1"><a class="reference internal" href="ext/commands/index.html"><code class="docutils literal notranslate"><span class="pre">discord.ext.commands</span></code> Bot commands framework</a></li>
<li class="toctree-l1"><a class="reference internal" href="ext/tasks/index.html"><code class="docutils literal notranslate"><span class="pre">discord.ext.tasks</span></code> asyncio.Task helpers</a></li>
</ul>
</div>
</section>
<section id="manuals">
<h2>Manuals<a class="headerlink" href="#manuals" title="Permalink to this headline"></a></h2>
<p>These pages go into great detail about everything the API can do.</p>
<div class="toctree-wrapper compound">
<ul>
<li class="toctree-l1"><a class="reference internal" href="api.html">API Reference</a></li>
<li class="toctree-l1"><a class="reference internal" href="ext/commands/api.html">discord.ext.commands API Reference</a></li>
<li class="toctree-l1"><a class="reference internal" href="ext/tasks/index.html">discord.ext.tasks API Reference</a></li>
</ul>
</div>
</section>
<section id="meta">
<h2>Meta<a class="headerlink" href="#meta" title="Permalink to this headline"></a></h2>
<p>If youre looking for something related to the project itself, its here.</p>
<div class="toctree-wrapper compound">
<ul>
<li class="toctree-l1"><a class="reference internal" href="whats_new.html">Changelog</a></li>
<li class="toctree-l1"><a class="reference internal" href="version_guarantees.html">Version Guarantees</a></li>
<li class="toctree-l1"><a class="reference internal" href="migrating.html">Migrating to v1.0</a></li>
</ul>
</div>
</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>

View File

@ -0,0 +1,331 @@
<!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>

242
docs/Python/html/intro.html Normal file
View File

@ -0,0 +1,242 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Introduction</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="#">Introduction</a><ul>
<li><a class="reference internal" href="#prerequisites">Prerequisites</a></li>
<li><a class="reference internal" href="#installing">Installing</a><ul>
<li><a class="reference internal" href="#virtual-environments">Virtual Environments</a></li>
</ul>
</li>
<li><a class="reference internal" href="#basic-concepts">Basic Concepts</a></li>
</ul>
</li>
</ul>
</div>
</aside>
<main class="grid-item" role="main">
<section id="introduction">
<span id="intro"></span><h1>Introduction<a class="headerlink" href="#introduction" title="Permalink to this headline"></a></h1>
<p>This is the documentation for discord.py, a library for Python to aid
in creating applications that utilise the Discord API.</p>
<section id="prerequisites">
<h2>Prerequisites<a class="headerlink" href="#prerequisites" title="Permalink to this headline"></a></h2>
<p>discord.py works with Python 3.8 or higher. Support for earlier versions of Python
is not provided. Python 2.7 or lower is not supported. Python 3.7 or lower is not supported.</p>
</section>
<section id="installing">
<span id="id1"></span><h2>Installing<a class="headerlink" href="#installing" title="Permalink to this headline"></a></h2>
<p>You can get the library directly from PyPI:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">python3</span> <span class="o">-</span><span class="n">m</span> <span class="n">pip</span> <span class="n">install</span> <span class="o">-</span><span class="n">U</span> <span class="n">discord</span><span class="o">.</span><span class="n">py</span>
</pre></div>
</div>
<p>If you are using Windows, then the following should be used instead:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">py</span> <span class="o">-</span><span class="mi">3</span> <span class="o">-</span><span class="n">m</span> <span class="n">pip</span> <span class="n">install</span> <span class="o">-</span><span class="n">U</span> <span class="n">discord</span><span class="o">.</span><span class="n">py</span>
</pre></div>
</div>
<p>To get voice support, you should use <code class="docutils literal notranslate"><span class="pre">discord.py[voice]</span></code> instead of <code class="docutils literal notranslate"><span class="pre">discord.py</span></code>, e.g.</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">python3</span> <span class="o">-</span><span class="n">m</span> <span class="n">pip</span> <span class="n">install</span> <span class="o">-</span><span class="n">U</span> <span class="n">discord</span><span class="o">.</span><span class="n">py</span><span class="p">[</span><span class="n">voice</span><span class="p">]</span>
</pre></div>
</div>
<p>On Linux environments, installing voice requires getting the following dependencies:</p>
<ul class="simple">
<li><p><a class="reference external" href="https://github.com/libffi/libffi">libffi</a></p></li>
<li><p><a class="reference external" href="https://github.com/saltstack/libnacl">libnacl</a></p></li>
<li><p><a class="reference external" href="https://packages.debian.org/python3-dev">python3-dev</a></p></li>
</ul>
<p>For a Debian-based system, the following command will get these dependencies:</p>
<div class="highlight-shell notranslate"><div class="highlight"><pre><span></span>$ apt install libffi-dev libnacl-dev python3-dev
</pre></div>
</div>
<p>Remember to check your permissions!</p>
<section id="virtual-environments">
<h3>Virtual Environments<a class="headerlink" href="#virtual-environments" title="Permalink to this headline"></a></h3>
<p>Sometimes you want to keep libraries from polluting system installs or use a different version of
libraries than the ones installed on the system. You might also not have permissions to install libraries system-wide.
For this purpose, the standard library as of Python 3.3 comes with a concept called “Virtual Environment”s to
help maintain these separate versions.</p>
<p>A more in-depth tutorial is found on <a class="reference external" href="https://docs.python.org/3/tutorial/venv.html" title="(in Python v3.9)"><span>Virtual Environments and Packages</span></a>.</p>
<p>However, for the quick and dirty:</p>
<ol class="arabic">
<li><p>Go to your projects working directory:</p>
<blockquote>
<div><div class="highlight-shell notranslate"><div class="highlight"><pre><span></span>$ <span class="nb">cd</span> your-bot-source
$ python3 -m venv bot-env
</pre></div>
</div>
</div></blockquote>
</li>
<li><p>Activate the virtual environment:</p>
<blockquote>
<div><div class="highlight-shell notranslate"><div class="highlight"><pre><span></span>$ <span class="nb">source</span> bot-env/bin/activate
</pre></div>
</div>
<p>On Windows you activate it with:</p>
<div class="highlight-shell notranslate"><div class="highlight"><pre><span></span>$ bot-env<span class="se">\S</span>cripts<span class="se">\a</span>ctivate.bat
</pre></div>
</div>
</div></blockquote>
</li>
<li><p>Use pip like usual:</p>
<blockquote>
<div><div class="highlight-shell notranslate"><div class="highlight"><pre><span></span>$ pip install -U discord.py
</pre></div>
</div>
</div></blockquote>
</li>
</ol>
<p>Congratulations. You now have a virtual environment all set up.</p>
</section>
</section>
<section id="basic-concepts">
<h2>Basic Concepts<a class="headerlink" href="#basic-concepts" title="Permalink to this headline"></a></h2>
<p>discord.py revolves around the concept of <a class="reference internal" href="api.html#discord-api-events"><span class="std std-ref">events</span></a>.
An event is something you listen to and then respond to. For example, when a message
happens, you will receive an event about it that you can respond to.</p>
<p>A quick example to showcase how events work:</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="kn">import</span> <span class="nn">discord</span>
<span class="k">class</span> <span class="nc">MyClient</span><span class="p">(</span><span class="n">discord</span><span class="o">.</span><span class="n">Client</span><span class="p">):</span>
<span class="k">async</span> <span class="k">def</span> <span class="nf">on_ready</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s1">&#39;Logged on as </span><span class="si">{</span><span class="bp">self</span><span class="o">.</span><span class="n">user</span><span class="si">}</span><span class="s1">!&#39;</span><span class="p">)</span>
<span class="k">async</span> <span class="k">def</span> <span class="nf">on_message</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">message</span><span class="p">):</span>
<span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s1">&#39;Message from </span><span class="si">{</span><span class="n">messsage</span><span class="o">.</span><span class="n">author</span><span class="si">}</span><span class="s1">: </span><span class="si">{</span><span class="n">message</span><span class="o">.</span><span class="n">content</span><span class="si">}</span><span class="s1">&#39;</span><span class="p">)</span>
<span class="n">client</span> <span class="o">=</span> <span class="n">MyClient</span><span class="p">()</span>
<span class="n">client</span><span class="o">.</span><span class="n">run</span><span class="p">(</span><span class="s1">&#39;my token goes here&#39;</span><span class="p">)</span>
</pre></div>
</div>
</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>

View File

@ -0,0 +1,171 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Setting Up Logging</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="settings-toggle" class="settings" onclick="settingsModal.open();">
<span class="material-icons">settings</span>
</span>
<div id="sidebar">
</div>
</aside>
<main class="grid-item" role="main">
<div class="versionadded">
<p><span class="versionmodified added">New in version 0.6.0.</span></p>
</div>
<section id="setting-up-logging">
<span id="logging-setup"></span><h1>Setting Up Logging<a class="headerlink" href="#setting-up-logging" title="Permalink to this headline"></a></h1>
<p><em>discord.py</em> logs errors and debug information via the <a class="reference external" href="https://docs.python.org/3/library/logging.html#module-logging" title="(in Python v3.9)"><code class="xref py py-mod docutils literal notranslate"><span class="pre">logging</span></code></a> python
module. It is strongly recommended that the logging module is
configured, as no errors or warnings will be output if it is not set up.
Configuration of the <code class="docutils literal notranslate"><span class="pre">logging</span></code> module can be as simple as:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="kn">import</span> <span class="nn">logging</span>
<span class="n">logging</span><span class="o">.</span><span class="n">basicConfig</span><span class="p">(</span><span class="n">level</span><span class="o">=</span><span class="n">logging</span><span class="o">.</span><span class="n">INFO</span><span class="p">)</span>
</pre></div>
</div>
<p>Placed at the start of the application. This will output the logs from
discord as well as other libraries that use the <code class="docutils literal notranslate"><span class="pre">logging</span></code> module
directly to the console.</p>
<p>The optional <code class="docutils literal notranslate"><span class="pre">level</span></code> argument specifies what level of events to log
out and can be any of <code class="docutils literal notranslate"><span class="pre">CRITICAL</span></code>, <code class="docutils literal notranslate"><span class="pre">ERROR</span></code>, <code class="docutils literal notranslate"><span class="pre">WARNING</span></code>, <code class="docutils literal notranslate"><span class="pre">INFO</span></code>, and
<code class="docutils literal notranslate"><span class="pre">DEBUG</span></code> and if not specified defaults to <code class="docutils literal notranslate"><span class="pre">WARNING</span></code>.</p>
<p>More advanced setups are possible with the <a class="reference external" href="https://docs.python.org/3/library/logging.html#module-logging" title="(in Python v3.9)"><code class="xref py py-mod docutils literal notranslate"><span class="pre">logging</span></code></a> module. For
example to write the logs to a file called <code class="docutils literal notranslate"><span class="pre">discord.log</span></code> instead of
outputting them to the console the following snippet can be used:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="kn">import</span> <span class="nn">discord</span>
<span class="kn">import</span> <span class="nn">logging</span>
<span class="n">logger</span> <span class="o">=</span> <span class="n">logging</span><span class="o">.</span><span class="n">getLogger</span><span class="p">(</span><span class="s1">&#39;discord&#39;</span><span class="p">)</span>
<span class="n">logger</span><span class="o">.</span><span class="n">setLevel</span><span class="p">(</span><span class="n">logging</span><span class="o">.</span><span class="n">DEBUG</span><span class="p">)</span>
<span class="n">handler</span> <span class="o">=</span> <span class="n">logging</span><span class="o">.</span><span class="n">FileHandler</span><span class="p">(</span><span class="n">filename</span><span class="o">=</span><span class="s1">&#39;discord.log&#39;</span><span class="p">,</span> <span class="n">encoding</span><span class="o">=</span><span class="s1">&#39;utf-8&#39;</span><span class="p">,</span> <span class="n">mode</span><span class="o">=</span><span class="s1">&#39;w&#39;</span><span class="p">)</span>
<span class="n">handler</span><span class="o">.</span><span class="n">setFormatter</span><span class="p">(</span><span class="n">logging</span><span class="o">.</span><span class="n">Formatter</span><span class="p">(</span><span class="s1">&#39;</span><span class="si">%(asctime)s</span><span class="s1">:</span><span class="si">%(levelname)s</span><span class="s1">:</span><span class="si">%(name)s</span><span class="s1">: </span><span class="si">%(message)s</span><span class="s1">&#39;</span><span class="p">))</span>
<span class="n">logger</span><span class="o">.</span><span class="n">addHandler</span><span class="p">(</span><span class="n">handler</span><span class="p">)</span>
</pre></div>
</div>
<p>This is recommended, especially at verbose levels such as <code class="docutils literal notranslate"><span class="pre">INFO</span></code>
and <code class="docutils literal notranslate"><span class="pre">DEBUG</span></code>, as there are a lot of events logged and it would clog the
stdout of your program.</p>
<p>For more information, check the documentation and tutorial of the
<a class="reference external" href="https://docs.python.org/3/library/logging.html#module-logging" title="(in Python v3.9)"><code class="xref py py-mod docutils literal notranslate"><span class="pre">logging</span></code></a> module.</p>
</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>

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,457 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Migrating to v0.10.0</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="#">Migrating to v0.10.0</a><ul>
<li><a class="reference internal" href="#event-registration">Event Registration</a></li>
<li><a class="reference internal" href="#event-changes">Event Changes</a></li>
<li><a class="reference internal" href="#coroutines">Coroutines</a></li>
<li><a class="reference internal" href="#iterables">Iterables</a></li>
<li><a class="reference internal" href="#enumerations">Enumerations</a></li>
<li><a class="reference internal" href="#properties">Properties</a></li>
<li><a class="reference internal" href="#member-management">Member Management</a></li>
<li><a class="reference internal" href="#renamed-functions">Renamed Functions</a></li>
<li><a class="reference internal" href="#forced-keyword-arguments">Forced Keyword Arguments</a></li>
<li><a class="reference internal" href="#running-the-client">Running the Client</a></li>
</ul>
</li>
</ul>
</div>
</aside>
<main class="grid-item" role="main">
<section id="migrating-to-v0-10-0">
<span id="migrating-to-async"></span><h1>Migrating to v0.10.0<a class="headerlink" href="#migrating-to-v0-10-0" title="Permalink to this headline"></a></h1>
<p>v0.10.0 is one of the biggest breaking changes in the library due to massive
fundamental changes in how the library operates.</p>
<p>The biggest major change is that the library has dropped support to all versions prior to
Python 3.4.2. This was made to support <a class="reference external" href="https://docs.python.org/3/library/asyncio.html#module-asyncio" title="(in Python v3.9)"><code class="xref py py-mod docutils literal notranslate"><span class="pre">asyncio</span></code></a>, in which more detail can be seen
<a class="reference external" href="https://github.com/Rapptz/discord.py/issues/50">in the corresponding issue</a>. To reiterate this, the implication is that
<strong>python version 2.7 and 3.3 are no longer supported</strong>.</p>
<p>Below are all the other major changes from v0.9.0 to v0.10.0.</p>
<section id="event-registration">
<h2>Event Registration<a class="headerlink" href="#event-registration" title="Permalink to this headline"></a></h2>
<p>All events before were registered using <a class="reference internal" href="api.html#discord.Client.event" title="discord.Client.event"><code class="xref py py-meth docutils literal notranslate"><span class="pre">Client.event()</span></code></a>. While this is still
possible, the events must be decorated with <code class="docutils literal notranslate"><span class="pre">&#64;asyncio.coroutine</span></code>.</p>
<p>Before:</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="nd">@client</span><span class="o">.</span><span class="n">event</span>
<span class="k">def</span> <span class="nf">on_message</span><span class="p">(</span><span class="n">message</span><span class="p">):</span>
<span class="k">pass</span>
</pre></div>
</div>
<p>After:</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="nd">@client</span><span class="o">.</span><span class="n">event</span>
<span class="nd">@asyncio</span><span class="o">.</span><span class="n">coroutine</span>
<span class="k">def</span> <span class="nf">on_message</span><span class="p">(</span><span class="n">message</span><span class="p">):</span>
<span class="k">pass</span>
</pre></div>
</div>
<p>Or in Python 3.5+:</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="nd">@client</span><span class="o">.</span><span class="n">event</span>
<span class="k">async</span> <span class="k">def</span> <span class="nf">on_message</span><span class="p">(</span><span class="n">message</span><span class="p">):</span>
<span class="k">pass</span>
</pre></div>
</div>
<p>Because there is a lot of typing, a utility decorator (<code class="xref py py-meth docutils literal notranslate"><span class="pre">Client.async_event()</span></code>) is provided
for easier registration. For example:</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="nd">@client</span><span class="o">.</span><span class="n">async_event</span>
<span class="k">def</span> <span class="nf">on_message</span><span class="p">(</span><span class="n">message</span><span class="p">):</span>
<span class="k">pass</span>
</pre></div>
</div>
<p>Be aware however, that this is still a coroutine and your other functions that are coroutines must
be decorated with <code class="docutils literal notranslate"><span class="pre">&#64;asyncio.coroutine</span></code> or be <code class="docutils literal notranslate"><span class="pre">async</span> <span class="pre">def</span></code>.</p>
</section>
<section id="event-changes">
<h2>Event Changes<a class="headerlink" href="#event-changes" title="Permalink to this headline"></a></h2>
<p>Some events in v0.9.0 were considered pretty useless due to having no separate states. The main
events that were changed were the <code class="docutils literal notranslate"><span class="pre">_update</span></code> events since previously they had no context on what
was changed.</p>
<p>Before:</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="k">def</span> <span class="nf">on_channel_update</span><span class="p">(</span><span class="n">channel</span><span class="p">):</span> <span class="k">pass</span>
<span class="k">def</span> <span class="nf">on_member_update</span><span class="p">(</span><span class="n">member</span><span class="p">):</span> <span class="k">pass</span>
<span class="k">def</span> <span class="nf">on_status</span><span class="p">(</span><span class="n">member</span><span class="p">):</span> <span class="k">pass</span>
<span class="k">def</span> <span class="nf">on_server_role_update</span><span class="p">(</span><span class="n">role</span><span class="p">):</span> <span class="k">pass</span>
<span class="k">def</span> <span class="nf">on_voice_state_update</span><span class="p">(</span><span class="n">member</span><span class="p">):</span> <span class="k">pass</span>
<span class="k">def</span> <span class="nf">on_socket_raw_send</span><span class="p">(</span><span class="n">payload</span><span class="p">,</span> <span class="n">is_binary</span><span class="p">):</span> <span class="k">pass</span>
</pre></div>
</div>
<p>After:</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="k">def</span> <span class="nf">on_channel_update</span><span class="p">(</span><span class="n">before</span><span class="p">,</span> <span class="n">after</span><span class="p">):</span> <span class="k">pass</span>
<span class="k">def</span> <span class="nf">on_member_update</span><span class="p">(</span><span class="n">before</span><span class="p">,</span> <span class="n">after</span><span class="p">):</span> <span class="k">pass</span>
<span class="k">def</span> <span class="nf">on_server_role_update</span><span class="p">(</span><span class="n">before</span><span class="p">,</span> <span class="n">after</span><span class="p">):</span> <span class="k">pass</span>
<span class="k">def</span> <span class="nf">on_voice_state_update</span><span class="p">(</span><span class="n">before</span><span class="p">,</span> <span class="n">after</span><span class="p">):</span> <span class="k">pass</span>
<span class="k">def</span> <span class="nf">on_socket_raw_send</span><span class="p">(</span><span class="n">payload</span><span class="p">):</span> <span class="k">pass</span>
</pre></div>
</div>
<p>Note that <code class="docutils literal notranslate"><span class="pre">on_status</span></code> was removed. If you want its functionality, use <a class="reference internal" href="api.html#discord.on_member_update" title="discord.on_member_update"><code class="xref py py-func docutils literal notranslate"><span class="pre">on_member_update()</span></code></a>.
See <a class="reference internal" href="api.html#discord-api-events"><span class="std std-ref">Event Reference</span></a> for more information. Other removed events include <code class="docutils literal notranslate"><span class="pre">on_socket_closed</span></code>, <code class="docutils literal notranslate"><span class="pre">on_socket_receive</span></code>, and <code class="docutils literal notranslate"><span class="pre">on_socket_opened</span></code>.</p>
</section>
<section id="coroutines">
<h2>Coroutines<a class="headerlink" href="#coroutines" title="Permalink to this headline"></a></h2>
<p>The biggest change that the library went through is that almost every function in <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>
was changed to be a <a class="reference external" href="py:library/asyncio-task.html">coroutine</a>. Functions
that are marked as a coroutine in the documentation must be awaited from or yielded from in order
for the computation to be done. For example…</p>
<p>Before:</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="n">client</span><span class="o">.</span><span class="n">send_message</span><span class="p">(</span><span class="n">message</span><span class="o">.</span><span class="n">channel</span><span class="p">,</span> <span class="s1">&#39;Hello&#39;</span><span class="p">)</span>
</pre></div>
</div>
<p>After:</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="k">yield from</span> <span class="n">client</span><span class="o">.</span><span class="n">send_message</span><span class="p">(</span><span class="n">message</span><span class="o">.</span><span class="n">channel</span><span class="p">,</span> <span class="s1">&#39;Hello&#39;</span><span class="p">)</span>
<span class="c1"># or in python 3.5+</span>
<span class="k">await</span> <span class="n">client</span><span class="o">.</span><span class="n">send_message</span><span class="p">(</span><span class="n">message</span><span class="o">.</span><span class="n">channel</span><span class="p">,</span> <span class="s1">&#39;Hello&#39;</span><span class="p">)</span>
</pre></div>
</div>
<p>In order for you to <code class="docutils literal notranslate"><span class="pre">yield</span> <span class="pre">from</span></code> or <code class="docutils literal notranslate"><span class="pre">await</span></code> a coroutine then your function must be decorated
with <code class="docutils literal notranslate"><span class="pre">&#64;asyncio.coroutine</span></code> or <code class="docutils literal notranslate"><span class="pre">async</span> <span class="pre">def</span></code>.</p>
</section>
<section id="iterables">
<h2>Iterables<a class="headerlink" href="#iterables" title="Permalink to this headline"></a></h2>
<p>For performance reasons, many of the internal data structures were changed into a dictionary to support faster
lookup. As a consequence, this meant that some lists that were exposed via the API have changed into iterables
and not sequences. In short, this means that certain attributes now only support iteration and not any of the
sequence functions.</p>
<p>The affected attributes are as follows:</p>
<ul class="simple">
<li><p><code class="xref py py-attr docutils literal notranslate"><span class="pre">Client.servers</span></code></p></li>
<li><p><a class="reference internal" href="api.html#discord.Client.private_channels" title="discord.Client.private_channels"><code class="xref py py-attr docutils literal notranslate"><span class="pre">Client.private_channels</span></code></a></p></li>
<li><p><code class="xref py py-attr docutils literal notranslate"><span class="pre">Server.channels</span></code></p></li>
<li><p><code class="xref py py-attr docutils literal notranslate"><span class="pre">Server.members</span></code></p></li>
</ul>
<p>Some examples of previously valid behaviour that is now invalid</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="k">if</span> <span class="n">client</span><span class="o">.</span><span class="n">servers</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span><span class="o">.</span><span class="n">name</span> <span class="o">==</span> <span class="s2">&quot;test&quot;</span><span class="p">:</span>
<span class="c1"># do something</span>
</pre></div>
</div>
<p>Since they are no longer <a class="reference external" href="https://docs.python.org/3/library/stdtypes.html#list" title="(in Python v3.9)"><code class="xref py py-obj docutils literal notranslate"><span class="pre">list</span></code></a>s, they no longer support indexing or any operation other than iterating.
In order to get the old behaviour you should explicitly cast it to a list.</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="n">servers</span> <span class="o">=</span> <span class="nb">list</span><span class="p">(</span><span class="n">client</span><span class="o">.</span><span class="n">servers</span><span class="p">)</span>
<span class="c1"># work with servers</span>
</pre></div>
</div>
<div class="admonition warning">
<p class="admonition-title">Warning</p>
<p>Due to internal changes of the structure, the order you receive the data in
is not in a guaranteed order.</p>
</div>
</section>
<section id="enumerations">
<h2>Enumerations<a class="headerlink" href="#enumerations" title="Permalink to this headline"></a></h2>
<p>Due to dropping support for versions lower than Python 3.4.2, the library can now use
<a class="reference external" href="https://docs.python.org/3/library/enum.html" title="(in Python v3.9)"><span>enum — Support for enumerations</span></a> in places where it makes sense.</p>
<p>The common places where this was changed was in the server region, member status, and channel type.</p>
<p>Before:</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="n">server</span><span class="o">.</span><span class="n">region</span> <span class="o">==</span> <span class="s1">&#39;us-west&#39;</span>
<span class="n">member</span><span class="o">.</span><span class="n">status</span> <span class="o">==</span> <span class="s1">&#39;online&#39;</span>
<span class="n">channel</span><span class="o">.</span><span class="n">type</span> <span class="o">==</span> <span class="s1">&#39;text&#39;</span>
</pre></div>
</div>
<p>After:</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="n">server</span><span class="o">.</span><span class="n">region</span> <span class="o">==</span> <span class="n">discord</span><span class="o">.</span><span class="n">ServerRegion</span><span class="o">.</span><span class="n">us_west</span>
<span class="n">member</span><span class="o">.</span><span class="n">status</span> <span class="o">=</span> <span class="n">discord</span><span class="o">.</span><span class="n">Status</span><span class="o">.</span><span class="n">online</span>
<span class="n">channel</span><span class="o">.</span><span class="n">type</span> <span class="o">==</span> <span class="n">discord</span><span class="o">.</span><span class="n">ChannelType</span><span class="o">.</span><span class="n">text</span>
</pre></div>
</div>
<p>The main reason for this change was to reduce the use of finicky strings in the API as this
could give users a false sense of power. More information can be found in the <a class="reference internal" href="api.html#discord-api-enums"><span class="std std-ref">Enumerations</span></a> page.</p>
</section>
<section id="properties">
<h2>Properties<a class="headerlink" href="#properties" title="Permalink to this headline"></a></h2>
<p>A lot of function calls that returned constant values were changed into Python properties for ease of use
in format strings.</p>
<p>The following functions were changed into properties:</p>
<div class="table-wrapper"><table class="docutils align-default">
<colgroup>
<col style="width: 51%" />
<col style="width: 49%" />
</colgroup>
<tbody>
<tr class="row-odd"><td><p>Before</p></td>
<td><p>After</p></td>
</tr>
<tr class="row-even"><td><p><code class="docutils literal notranslate"><span class="pre">User.avatar_url()</span></code></p></td>
<td><p><code class="xref py py-attr docutils literal notranslate"><span class="pre">User.avatar_url</span></code></p></td>
</tr>
<tr class="row-odd"><td><p><code class="docutils literal notranslate"><span class="pre">User.mention()</span></code></p></td>
<td><p><a class="reference internal" href="api.html#discord.User.mention" title="discord.User.mention"><code class="xref py py-attr docutils literal notranslate"><span class="pre">User.mention</span></code></a></p></td>
</tr>
<tr class="row-even"><td><p><code class="docutils literal notranslate"><span class="pre">Channel.mention()</span></code></p></td>
<td><p><code class="xref py py-attr docutils literal notranslate"><span class="pre">Channel.mention</span></code></p></td>
</tr>
<tr class="row-odd"><td><p><code class="docutils literal notranslate"><span class="pre">Channel.is_default_channel()</span></code></p></td>
<td><p><code class="xref py py-attr docutils literal notranslate"><span class="pre">Channel.is_default</span></code></p></td>
</tr>
<tr class="row-even"><td><p><code class="docutils literal notranslate"><span class="pre">Role.is_everyone()</span></code></p></td>
<td><p><code class="xref py py-attr docutils literal notranslate"><span class="pre">Role.is_everyone</span></code></p></td>
</tr>
<tr class="row-odd"><td><p><code class="docutils literal notranslate"><span class="pre">Server.get_default_role()</span></code></p></td>
<td><p><code class="xref py py-attr docutils literal notranslate"><span class="pre">Server.default_role</span></code></p></td>
</tr>
<tr class="row-even"><td><p><code class="docutils literal notranslate"><span class="pre">Server.icon_url()</span></code></p></td>
<td><p><code class="xref py py-attr docutils literal notranslate"><span class="pre">Server.icon_url</span></code></p></td>
</tr>
<tr class="row-odd"><td><p><code class="docutils literal notranslate"><span class="pre">Server.get_default_channel()</span></code></p></td>
<td><p><code class="xref py py-attr docutils literal notranslate"><span class="pre">Server.default_channel</span></code></p></td>
</tr>
<tr class="row-even"><td><p><code class="docutils literal notranslate"><span class="pre">Message.get_raw_mentions()</span></code></p></td>
<td><p><a class="reference internal" href="api.html#discord.Message.raw_mentions" title="discord.Message.raw_mentions"><code class="xref py py-attr docutils literal notranslate"><span class="pre">Message.raw_mentions</span></code></a></p></td>
</tr>
<tr class="row-odd"><td><p><code class="docutils literal notranslate"><span class="pre">Message.get_raw_channel_mentions()</span></code></p></td>
<td><p><a class="reference internal" href="api.html#discord.Message.raw_channel_mentions" title="discord.Message.raw_channel_mentions"><code class="xref py py-attr docutils literal notranslate"><span class="pre">Message.raw_channel_mentions</span></code></a></p></td>
</tr>
</tbody>
</table>
</div></section>
<section id="member-management">
<h2>Member Management<a class="headerlink" href="#member-management" title="Permalink to this headline"></a></h2>
<p>Functions that involved banning and kicking were changed.</p>
<div class="table-wrapper"><table class="docutils align-default">
<colgroup>
<col style="width: 55%" />
<col style="width: 45%" />
</colgroup>
<tbody>
<tr class="row-odd"><td><p>Before</p></td>
<td><p>After</p></td>
</tr>
<tr class="row-even"><td><p><code class="docutils literal notranslate"><span class="pre">Client.ban(server,</span> <span class="pre">user)</span></code></p></td>
<td><p><code class="docutils literal notranslate"><span class="pre">Client.ban(member)</span></code></p></td>
</tr>
<tr class="row-odd"><td><p><code class="docutils literal notranslate"><span class="pre">Client.kick(server,</span> <span class="pre">user)</span></code></p></td>
<td><p><code class="docutils literal notranslate"><span class="pre">Client.kick(member)</span></code></p></td>
</tr>
</tbody>
</table>
</div></section>
<section id="renamed-functions">
<h2>Renamed Functions<a class="headerlink" href="#renamed-functions" title="Permalink to this headline"></a></h2>
<p>Functions have been renamed.</p>
<div class="table-wrapper"><table class="docutils align-default">
<colgroup>
<col style="width: 46%" />
<col style="width: 54%" />
</colgroup>
<tbody>
<tr class="row-odd"><td><p>Before</p></td>
<td><p>After</p></td>
</tr>
<tr class="row-even"><td><p><code class="docutils literal notranslate"><span class="pre">Client.set_channel_permissions</span></code></p></td>
<td><p><code class="xref py py-meth docutils literal notranslate"><span class="pre">Client.edit_channel_permissions()</span></code></p></td>
</tr>
</tbody>
</table>
</div><p>All the <a class="reference internal" href="api.html#discord.Permissions" title="discord.Permissions"><code class="xref py py-class docutils literal notranslate"><span class="pre">Permissions</span></code></a> related attributes have been renamed and the <cite>can_</cite> prefix has been
dropped. So for example, <code class="docutils literal notranslate"><span class="pre">can_manage_messages</span></code> has become <code class="docutils literal notranslate"><span class="pre">manage_messages</span></code>.</p>
</section>
<section id="forced-keyword-arguments">
<h2>Forced Keyword Arguments<a class="headerlink" href="#forced-keyword-arguments" title="Permalink to this headline"></a></h2>
<p>Since 3.0+ of Python, we can now force questions to take in forced keyword arguments. A keyword argument is when you
explicitly specify the name of the variable and assign to it, for example: <code class="docutils literal notranslate"><span class="pre">foo(name='test')</span></code>. Due to this support,
some functions in the library were changed to force things to take said keyword arguments. This is to reduce errors of
knowing the argument order and the issues that could arise from them.</p>
<p>The following parameters are now exclusively keyword arguments:</p>
<ul class="simple">
<li><dl class="simple">
<dt><code class="xref py py-meth docutils literal notranslate"><span class="pre">Client.send_message()</span></code></dt><dd><ul>
<li><p><code class="docutils literal notranslate"><span class="pre">tts</span></code></p></li>
</ul>
</dd>
</dl>
</li>
<li><dl class="simple">
<dt><code class="xref py py-meth docutils literal notranslate"><span class="pre">Client.logs_from()</span></code></dt><dd><ul>
<li><p><code class="docutils literal notranslate"><span class="pre">before</span></code></p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">after</span></code></p></li>
</ul>
</dd>
</dl>
</li>
<li><dl class="simple">
<dt><code class="xref py py-meth docutils literal notranslate"><span class="pre">Client.edit_channel_permissions()</span></code></dt><dd><ul>
<li><p><code class="docutils literal notranslate"><span class="pre">allow</span></code></p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">deny</span></code></p></li>
</ul>
</dd>
</dl>
</li>
</ul>
<p>In the documentation you can tell if a function parameter is a forced keyword argument if it is after <code class="docutils literal notranslate"><span class="pre">\*,</span></code>
in the function signature.</p>
</section>
<section id="running-the-client">
<span id="migrating-running"></span><h2>Running the Client<a class="headerlink" href="#running-the-client" title="Permalink to this headline"></a></h2>
<p>In earlier versions of discord.py, <code class="docutils literal notranslate"><span class="pre">client.run()</span></code> was a blocking call to the main thread
that called it. In v0.10.0 it is still a blocking call but it handles the event loop for you.
However, in order to do that you must pass in your credentials to <a class="reference internal" href="api.html#discord.Client.run" title="discord.Client.run"><code class="xref py py-meth docutils literal notranslate"><span class="pre">Client.run()</span></code></a>.</p>
<p>Basically, before:</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="n">client</span><span class="o">.</span><span class="n">login</span><span class="p">(</span><span class="s1">&#39;token&#39;</span><span class="p">)</span>
<span class="n">client</span><span class="o">.</span><span class="n">run</span><span class="p">()</span>
</pre></div>
</div>
<p>After:</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="n">client</span><span class="o">.</span><span class="n">run</span><span class="p">(</span><span class="s1">&#39;token&#39;</span><span class="p">)</span>
</pre></div>
</div>
<div class="admonition warning">
<p class="admonition-title">Warning</p>
<p>Like in the older <code class="docutils literal notranslate"><span class="pre">Client.run</span></code> function, the newer one must be the one of
the last functions to call. This is because the function is <strong>blocking</strong>. Registering
events or doing anything after <a class="reference internal" href="api.html#discord.Client.run" title="discord.Client.run"><code class="xref py py-meth docutils literal notranslate"><span class="pre">Client.run()</span></code></a> will not execute until the function
returns.</p>
</div>
<p>This is a utility function that abstracts the event loop for you. Theres no need for
the run call to be blocking and out of your control. Indeed, if you want control of the
event loop then doing so is quite straightforward:</p>
<div class="highlight-python3 notranslate"><div class="highlight"><pre><span></span><span class="kn">import</span> <span class="nn">discord</span>
<span class="kn">import</span> <span class="nn">asyncio</span>
<span class="n">client</span> <span class="o">=</span> <span class="n">discord</span><span class="o">.</span><span class="n">Client</span><span class="p">()</span>
<span class="nd">@asyncio</span><span class="o">.</span><span class="n">coroutine</span>
<span class="k">def</span> <span class="nf">main_task</span><span class="p">():</span>
<span class="k">yield from</span> <span class="n">client</span><span class="o">.</span><span class="n">login</span><span class="p">(</span><span class="s1">&#39;token&#39;</span><span class="p">)</span>
<span class="k">yield from</span> <span class="n">client</span><span class="o">.</span><span class="n">connect</span><span class="p">()</span>
<span class="n">loop</span> <span class="o">=</span> <span class="n">asyncio</span><span class="o">.</span><span class="n">get_event_loop</span><span class="p">()</span>
<span class="k">try</span><span class="p">:</span>
<span class="n">loop</span><span class="o">.</span><span class="n">run_until_complete</span><span class="p">(</span><span class="n">main_task</span><span class="p">())</span>
<span class="k">except</span><span class="p">:</span>
<span class="n">loop</span><span class="o">.</span><span class="n">run_until_complete</span><span class="p">(</span><span class="n">client</span><span class="o">.</span><span class="n">logout</span><span class="p">())</span>
<span class="k">finally</span><span class="p">:</span>
<span class="n">loop</span><span class="o">.</span><span class="n">close</span><span class="p">()</span>
</pre></div>
</div>
</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>

Binary file not shown.

View File

@ -0,0 +1,205 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Quickstart</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="#">Quickstart</a><ul>
<li><a class="reference internal" href="#a-minimal-bot">A Minimal Bot</a></li>
</ul>
</li>
</ul>
</div>
</aside>
<main class="grid-item" role="main">
<section id="quickstart">
<span id="id1"></span><h1>Quickstart<a class="headerlink" href="#quickstart" title="Permalink to this headline"></a></h1>
<p>This page gives a brief introduction to the library. It assumes you have the library installed,
if you dont check the <a class="reference internal" href="intro.html#installing"><span class="std std-ref">Installing</span></a> portion.</p>
<section id="a-minimal-bot">
<h2>A Minimal Bot<a class="headerlink" href="#a-minimal-bot" title="Permalink to this headline"></a></h2>
<p>Lets make a bot that responds to a specific message and walk you through it.</p>
<p>It looks something like this:</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">client</span> <span class="o">=</span> <span class="n">discord</span><span class="o">.</span><span class="n">Client</span><span class="p">()</span>
<span class="nd">@client</span><span class="o">.</span><span class="n">event</span>
<span class="k">async</span> <span class="k">def</span> <span class="nf">on_ready</span><span class="p">():</span>
<span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s1">&#39;We have logged in as </span><span class="si">{</span><span class="n">client</span><span class="o">.</span><span class="n">user</span><span class="si">}</span><span class="s1">&#39;</span><span class="p">)</span>
<span class="nd">@client</span><span class="o">.</span><span class="n">event</span>
<span class="k">async</span> <span class="k">def</span> <span class="nf">on_message</span><span class="p">(</span><span class="n">message</span><span class="p">):</span>
<span class="k">if</span> <span class="n">message</span><span class="o">.</span><span class="n">author</span> <span class="o">==</span> <span class="n">client</span><span class="o">.</span><span class="n">user</span><span class="p">:</span>
<span class="k">return</span>
<span class="k">if</span> <span class="n">message</span><span class="o">.</span><span class="n">content</span><span class="o">.</span><span class="n">startswith</span><span class="p">(</span><span class="s1">&#39;$hello&#39;</span><span class="p">):</span>
<span class="k">await</span> <span class="n">message</span><span class="o">.</span><span class="n">channel</span><span class="o">.</span><span class="n">send</span><span class="p">(</span><span class="s1">&#39;Hello!&#39;</span><span class="p">)</span>
<span class="n">client</span><span class="o">.</span><span class="n">run</span><span class="p">(</span><span class="s1">&#39;your token here&#39;</span><span class="p">)</span>
</pre></div>
</div>
<p>Lets name this file <code class="docutils literal notranslate"><span class="pre">example_bot.py</span></code>. Make sure not to name it <code class="docutils literal notranslate"><span class="pre">discord.py</span></code> as thatll conflict
with the library.</p>
<p>Theres a lot going on here, so lets walk you through it step by step.</p>
<ol class="arabic">
<li><p>The first line just imports the library, if this raises a <cite>ModuleNotFoundError</cite> or <cite>ImportError</cite>
then head on over to <a class="reference internal" href="intro.html#installing"><span class="std std-ref">Installing</span></a> section to properly install.</p></li>
<li><p>Next, we create an instance of a <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>. This client is our connection to Discord.</p></li>
<li><p>We then use the <a class="reference internal" href="api.html#discord.Client.event" title="discord.Client.event"><code class="xref py py-meth docutils literal notranslate"><span class="pre">Client.event()</span></code></a> decorator to register an event. This library has many events.
Since this library is asynchronous, we do things in a “callback” style manner.</p>
<p>A callback is essentially a function that is called when something happens. In our case,
the <a class="reference internal" href="api.html#discord.on_ready" title="discord.on_ready"><code class="xref py py-func docutils literal notranslate"><span class="pre">on_ready()</span></code></a> event is called when the bot has finished logging in and setting things
up and the <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> event is called when the bot has received a message.</p>
</li>
<li><p>Since the <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> event triggers for <em>every</em> message received, we have to make
sure that we ignore messages from ourselves. We do this by checking if the <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>
is the same as the <a class="reference internal" href="api.html#discord.Client.user" title="discord.Client.user"><code class="xref py py-attr docutils literal notranslate"><span class="pre">Client.user</span></code></a>.</p></li>
<li><p>Afterwards, we check if the <a class="reference internal" href="api.html#discord.Message.content" title="discord.Message.content"><code class="xref py py-class docutils literal notranslate"><span class="pre">Message.content</span></code></a> starts with <code class="docutils literal notranslate"><span class="pre">'$hello'</span></code>. If it does,
then we send a message in the channel it was used in with <code class="docutils literal notranslate"><span class="pre">'Hello!'</span></code>. This is a basic way of
handling commands, which can be later automated with the <a class="reference internal" href="ext/commands/index.html"><span class="doc">discord.ext.commands Bot commands framework</span></a> framework.</p></li>
<li><p>Finally, we run the bot with our login token. If you need help getting your token or creating a bot,
look in the <a class="reference internal" href="discord.html#discord-intro"><span class="std std-ref">Creating a Bot Account</span></a> section.</p></li>
</ol>
<p>Now that weve made a bot, we have to <em>run</em> the bot. Luckily, this is simple since this is just a
Python script, we can run it directly.</p>
<p>On Windows:</p>
<div class="highlight-shell notranslate"><div class="highlight"><pre><span></span>$ py -3 example_bot.py
</pre></div>
</div>
<p>On other systems:</p>
<div class="highlight-shell notranslate"><div class="highlight"><pre><span></span>$ python3 example_bot.py
</pre></div>
</div>
<p>Now you can try playing around with your basic bot.</p>
</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>

View File

@ -0,0 +1,167 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Search</title>
<script src="searchindex.js" defer></script>
<!-- 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>
<script src="_static/searchtools.js"></script>
<script src="_static/language_data.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="#" />
</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="#" 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="#" 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="settings-toggle" class="settings" onclick="settingsModal.open();">
<span class="material-icons">settings</span>
</span>
<div id="sidebar">
</div>
</aside>
<main class="grid-item" role="main">
<h1 id="search-documentation">Search</h1>
<noscript>
<div class="admonition warning">
<p>
Please activate JavaScript to enable the search
functionality.
</p>
</div>
</noscript>
<p>
Searching for multiple words only shows matches that contain
all words.
</p>
<form action="" method="get">
<input type="text" name="q" aria-labelledby="search-documentation" value="" autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false"/>
<input type="submit" value="search" />
<span id="search-progress" style="padding-left: 10px"></span>
</form>
<div id="search-results">
</div>
</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>

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,174 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Version Guarantees</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" />
<link rel="next" title="Migrating to v1.0" href="migrating.html" />
<link rel="prev" title="Changelog" href="whats_new.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="#">Version Guarantees</a><ul>
<li><a class="reference internal" href="#examples-of-breaking-changes">Examples of Breaking Changes</a></li>
<li><a class="reference internal" href="#examples-of-non-breaking-changes">Examples of Non-Breaking Changes</a></li>
</ul>
</li>
</ul>
</div>
</aside>
<main class="grid-item" role="main">
<section id="version-guarantees">
<span id="id1"></span><h1>Version Guarantees<a class="headerlink" href="#version-guarantees" title="Permalink to this headline"></a></h1>
<p>The library follows a <a class="reference external" href="https://semver.org/">semantic versioning principle</a> which means that the major version is updated every time there is an incompatible API change. However due to the lack of guarantees on the Discord side when it comes to breaking changes along with the fairly dynamic nature of Python it can be hard to discern what can be considered a breaking change and what isnt.</p>
<p>The first thing to keep in mind is that breaking changes only apply to <strong>publicly documented functions and classes</strong>. If its not listed in the documentation here then it is not part of the public API and is thus bound to change. This includes attributes that start with an underscore or functions without an underscore that are not documented.</p>
<div class="admonition note">
<p class="admonition-title">Note</p>
<p>The examples below are non-exhaustive.</p>
</div>
<section id="examples-of-breaking-changes">
<h2>Examples of Breaking Changes<a class="headerlink" href="#examples-of-breaking-changes" title="Permalink to this headline"></a></h2>
<ul class="simple">
<li><p>Changing the default parameter value to something else.</p></li>
<li><p>Renaming a function without an alias to an old function.</p></li>
<li><p>Adding or removing parameters to an event.</p></li>
</ul>
</section>
<section id="examples-of-non-breaking-changes">
<h2>Examples of Non-Breaking Changes<a class="headerlink" href="#examples-of-non-breaking-changes" title="Permalink to this headline"></a></h2>
<ul class="simple">
<li><p>Adding or removing private underscored attributes.</p></li>
<li><p>Adding an element into the <code class="docutils literal notranslate"><span class="pre">__slots__</span></code> of a data class.</p></li>
<li><p>Changing the behaviour of a function to fix a bug.</p></li>
<li><p>Changes in the documentation.</p></li>
<li><p>Modifying the internal HTTP handling.</p></li>
<li><p>Upgrading the dependencies to a new version, major or otherwise.</p></li>
</ul>
</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>

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff