Merge pull request #18 from Matthww/dev

Release 1.0.0
This commit is contained in:
2021-11-06 15:43:31 +01:00
committed by GitHub
17 changed files with 419 additions and 127 deletions
+17
View File
@@ -0,0 +1,17 @@
default_language_version:
python: python3.8
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v4.0.1
hooks:
- id: check-ast
- id: check-case-conflict
- id: check-json
- id: check-merge-conflict
- id: check-yaml
- id: end-of-file-fixer
- id: trailing-whitespace
- repo: https://github.com/asottile/reorder_python_imports
rev: v2.6.0
hooks:
- id: reorder-python-imports
+21 -19
View File
@@ -1,23 +1,24 @@
import asyncio
from aioredis.client import Redis
import discord
from discord import ActivityType
from discord.colour import Color
from discord.ext import commands, tasks
import sys
from signal import SIGINT, SIGTERM
import json import json
from typing import Any, Dict, List, Sequence import sys
from discord import Message from typing import Any
from discord.ext.commands.errors import ( from typing import Dict
ExtensionAlreadyLoaded, from typing import List
ExtensionFailed, from typing import Sequence
ExtensionNotFound,
NoEntryPointError,
)
import lavalink
import aioredis import aioredis
import discord
import lavalink
from aioredis import Redis from aioredis import Redis
from aioredis.client import Redis
from discord import ActivityType
from discord import Message
from discord.colour import Color
from discord.ext import commands
from discord.ext import tasks
from discord.ext.commands.errors import ExtensionAlreadyLoaded
from discord.ext.commands.errors import ExtensionFailed
from discord.ext.commands.errors import ExtensionNotFound
from discord.ext.commands.errors import NoEntryPointError
from context import CustomContext from context import CustomContext
@@ -38,7 +39,6 @@ class ChristmasBot(commands.Bot):
self.initial_cog_names: List[str] = self.config.get("cogs", []) self.initial_cog_names: List[str] = self.config.get("cogs", [])
self.colors: Dict[str, Color] = self.process_colours(config.get("colors", [])) self.colors: Dict[str, Color] = self.process_colours(config.get("colors", []))
self._redis_client: Redis = aioredis.from_url( self._redis_client: Redis = aioredis.from_url(
self.config["redis_url"], encoding="utf-8", decode_responses=True self.config["redis_url"], encoding="utf-8", decode_responses=True
) )
@@ -110,6 +110,9 @@ class ChristmasBot(commands.Bot):
await self.change_presence(activity=activity) await self.change_presence(activity=activity)
config = json.load(open("config.json", "r", encoding="utf-8"))
redis_prefix = config["redis_prefix"]
if __name__ == "__main__": if __name__ == "__main__":
try: try:
import uvloop import uvloop
@@ -119,6 +122,5 @@ if __name__ == "__main__":
except ModuleNotFoundError: except ModuleNotFoundError:
pass pass
config = json.load(open("config.json", "r", encoding="utf-8"))
token = config.pop("token") token = config.pop("token")
ChristmasBot(config).run(token, reconnect=True) ChristmasBot(config).run(token, reconnect=True)
+19 -26
View File
@@ -1,24 +1,25 @@
import datetime
import time
from typing import Optional from typing import Optional
import discord import discord
from discord.ext import tasks, commands
import time
from discord.ext.commands import Context
import humanize import humanize
import datetime
import lavalink import lavalink
from discord.ext import commands
from discord.ext import tasks
from discord.ext.commands import Context
from bot import ChristmasBot from bot import ChristmasBot
from context import CustomContext
from utils.database import AutoJoin
from utils.EmbedGenerator import EmbedGenerator from utils.EmbedGenerator import EmbedGenerator
from utils.classes import BaseCog
from utils.paginator import HelpPaginator from utils.paginator import HelpPaginator
class InformationCog(commands.Cog, name="Information"): class InformationCog(BaseCog, name="Information"):
def __init__(self, bot: ChristmasBot): @commands.command(name="ping", aliases=["pong"])
self.bot = bot
@commands.cooldown(rate=1, per=5, type=commands.BucketType.user) @commands.cooldown(rate=1, per=5, type=commands.BucketType.user)
@commands.command(description="PONG!", aliases=["pong"])
async def ping(self, ctx: Context): async def ping(self, ctx: Context):
"""Test the latency""" """Test the latency"""
avatar = ctx.author.avatar.with_static_format("jpeg") avatar = ctx.author.avatar.with_static_format("jpeg")
@@ -39,24 +40,18 @@ class InformationCog(commands.Cog, name="Information"):
embed.set_footer(text=f"Requested by: {ctx.author}", icon_url=f"{avatar}") embed.set_footer(text=f"Requested by: {ctx.author}", icon_url=f"{avatar}")
await msg.edit(embed=embed) await msg.edit(embed=embed)
@commands.command( @commands.command(name="invite")
name="invite", description="Gets the invite link!", slash_commands=True
)
@commands.cooldown(rate=1, per=5, type=commands.BucketType.user) @commands.cooldown(rate=1, per=5, type=commands.BucketType.user)
async def invite(self, ctx: Context): async def invite(self, ctx: Context):
"""Gets the invite link!""" """Gets the invite link"""
await EmbedGenerator.Message( await EmbedGenerator.Message(
ctx, "Add our bot to your server:", self.bot.invite_link ctx, "Add our bot to your server:", self.bot.invite_link
) )
@commands.command( @commands.command(name="wlinfo")
name="wlinfo",
description="Retrieve various Node/Server/Player information.",
slash_commands=True,
)
@commands.cooldown(rate=1, per=5, type=commands.BucketType.user) @commands.cooldown(rate=1, per=5, type=commands.BucketType.user)
async def wlinfo(self, ctx: Context): async def wlinfo(self, ctx: CustomContext):
"""Retrieve various Node/Server/Player information.""" """Retrieve various node/server/player information"""
player = self.bot.lavalink.player_manager.get(ctx.guild.id) player = self.bot.lavalink.player_manager.get(ctx.guild.id)
node = player.node node = player.node
@@ -77,11 +72,9 @@ class InformationCog(commands.Cog, name="Information"):
f"Server Uptime: `{datetime.timedelta(milliseconds=node.stats.uptime)}`" f"Server Uptime: `{datetime.timedelta(milliseconds=node.stats.uptime)}`"
) )
await ctx.send(fmt) await ctx.send(fmt)
AutoJoin.get_channels()
from utils import database @commands.command(name="help", aliases=["about", "info"])
database.AutoJoin.get_channels()
@commands.command(name="help", aliases=["about", "info"], slash_command=True)
@commands.cooldown(1, 1, commands.BucketType.user) @commands.cooldown(1, 1, commands.BucketType.user)
async def about( async def about(
self, self,
@@ -90,7 +83,7 @@ class InformationCog(commands.Cog, name="Information"):
description="Show help for a command or category" description="Show help for a command or category"
), ),
): ):
"""ChristmasBot command list""" """Retrieve a list of possible commands"""
if command: if command:
entity = self.bot.get_cog(command) or self.bot.get_command(command) entity = self.bot.get_cog(command) or self.bot.get_command(command)
+86 -46
View File
@@ -1,21 +1,27 @@
import asyncio import asyncio
import datetime
import re import re
from typing import Optional from typing import Optional
from aioredis.client import Redis
import discord import discord
from discord.channel import TextChannel from discord.channel import TextChannel
from discord.ext.commands.context import Context from discord.ext.commands.context import Context
from discord.ext.commands.errors import CommandError
import lavalink import lavalink
from discord import Embed
from discord.channel import TextChannel
from discord.ext import commands from discord.ext import commands
from lavalink.models import AudioTrack, DefaultPlayer from discord.ext.commands.context import Context
from lavalink.models import AudioTrack
from lavalink.models import DefaultPlayer
from bot import ChristmasBot from bot import ChristmasBot
from utils.EmbedGenerator import EmbedGenerator from utils.classes import BaseCog
from utils.database import AutoJoin
from context import CustomContext from context import CustomContext
from discord import Embed from utils.database import AutoJoin
from utils.database import Playlist
from utils.exceptions import EmbeddedCommandException
from utils.EmbedGenerator import EmbedGenerator
url_rx = re.compile(r"https?://(?:www\.)?.+") url_rx = re.compile(r"https?://(?:www\.)?.+")
@@ -69,10 +75,7 @@ class LavalinkVoiceClient(discord.VoiceClient):
self.cleanup() self.cleanup()
class Music(commands.Cog): class Music(BaseCog):
def __init__(self, bot: ChristmasBot):
self.bot = bot
@commands.Cog.listener() @commands.Cog.listener()
async def on_ready(self): async def on_ready(self):
if not hasattr( if not hasattr(
@@ -96,7 +99,7 @@ class Music(commands.Cog):
for guild_id, (voicechannel_id, textchannel_id) in redis_result.items(): for guild_id, (voicechannel_id, textchannel_id) in redis_result.items():
player = self.bot.lavalink.player_manager.create(guild_id) player = self.bot.lavalink.player_manager.create(guild_id)
player.store('channel', textchannel_id) player.store("channel", textchannel_id)
voice_channel = await self.bot.fetch_channel(voicechannel_id) voice_channel = await self.bot.fetch_channel(voicechannel_id)
await voice_channel.connect(cls=LavalinkVoiceClient) await voice_channel.connect(cls=LavalinkVoiceClient)
if not player.is_playing: if not player.is_playing:
@@ -109,16 +112,10 @@ class Music(commands.Cog):
await textchannel.send("Automatically joined the voice channel") await textchannel.send("Automatically joined the voice channel")
async def fill_player_queue(self, player: DefaultPlayer, buffer: Optional[int] = 1): async def fill_player_queue(self, player: DefaultPlayer, buffer: Optional[int] = 1):
pipeline = self.bot._redis_client.pipeline() queries = await Playlist.random(self.bot._redis_client, buffer)
for _ in range(buffer):
pipeline.randomkey()
queries = await pipeline.execute()
print(queries)
# Get the results for the query from Lavalink. # Get the results for the query from Lavalink.
for query in queries: for query in queries:
result = await player.node.get_tracks(query) result = await player.node.get_tracks(query)
print(result)
if not result or not result["tracks"]: if not result or not result["tracks"]:
continue continue
@@ -127,6 +124,26 @@ class Music(commands.Cog):
) )
player.add(requester=self.bot.user.id, track=track) player.add(requester=self.bot.user.id, track=track)
async def create_track_embed(self, track: AudioTrack) -> Embed:
embed_color = self.bot.colors["embed"]
embed = discord.Embed(
title=f"Now playing...",
colour=embed_color,
)
embed.description = f"[{track.title}]({track.uri})"
embed.set_thumbnail(
url=f"https://i3.ytimg.com/vi/{track.identifier}/mqdefault.jpg"
)
try:
duration = str(datetime.timedelta(milliseconds=int(track.duration)))
except OverflowError:
duration = "🔴 LIVE"
embed.add_field(name="Duration", value=duration)
embed.add_field(name="Author", value=track.author)
return embed
def cog_unload(self): def cog_unload(self):
"""Cog unload handler. This removes any event hooks that were registered.""" """Cog unload handler. This removes any event hooks that were registered."""
self.bot.lavalink._event_hooks.clear() self.bot.lavalink._event_hooks.clear()
@@ -147,13 +164,15 @@ class Music(commands.Cog):
return guild_check return guild_check
async def cog_command_error(self, ctx, error): async def cog_command_error(self, ctx: CustomContext, error: CommandError):
if isinstance(error, commands.CommandInvokeError): if isinstance(error, commands.CommandInvokeError):
await ctx.send(error.original) await ctx.send(error.original)
# The above handles errors thrown in this cog and shows them to the user. # The above handles errors thrown in this cog and shows them to the user.
# This shouldn't be a problem as the only errors thrown in this cog are from `ensure_voice` # This shouldn't be a problem as the only errors thrown in this cog are from `ensure_voice`
# which contain a reason string, such as "Join a voicechannel" etc. You can modify the above # which contain a reason string, such as "Join a voicechannel" etc. You can modify the above
# if you want to do things differently. # if you want to do things differently.
elif isinstance(error, EmbeddedCommandException):
await error.send(ctx)
async def ensure_voice(self, ctx): async def ensure_voice(self, ctx):
"""This check ensures that the bot and command author are in the same voicechannel.""" """This check ensures that the bot and command author are in the same voicechannel."""
@@ -178,7 +197,14 @@ class Music(commands.Cog):
if not player.is_connected: if not player.is_connected:
if not should_connect: if not should_connect:
raise commands.CommandInvokeError("Not connected.") bot_name = self.bot.config["info"]["name"]
embed = await EmbedGenerator.Message(
ctx,
f"{bot_name} is not connected",
"However you can start playing music using `/connect`",
no_send=True,
)
raise EmbeddedCommandException(embed)
permissions = ctx.author.voice.channel.permissions_for(ctx.me) permissions = ctx.author.voice.channel.permissions_for(ctx.me)
@@ -206,50 +232,56 @@ class Music(commands.Cog):
elif isinstance(event, lavalink.events.TrackStartEvent): elif isinstance(event, lavalink.events.TrackStartEvent):
channel_id = int(event.player.fetch("channel")) channel_id = int(event.player.fetch("channel"))
channel: TextChannel = self.bot.get_channel(channel_id) channel: TextChannel = self.bot.get_channel(channel_id)
embed = await self.create_track_embed(event.player.current)
color = self.bot.colors["embed"]
current_track: AudioTrack = event.player.current
embed = Embed(
title="Now playing:",
description=f"[{current_track.title}]({current_track.uri})",
color=color,
)
await channel.send(embed=embed) await channel.send(embed=embed)
elif isinstance(event, lavalink.events.TrackEndEvent): elif isinstance(event, lavalink.events.TrackEndEvent):
await self.fill_player_queue(event.player, 1) await self.fill_player_queue(event.player, 1)
@commands.command(name="connect", aliases=["p", "play", "join"]) @commands.command(name="connect", aliases=["p", "play", "join"])
async def play(self, ctx: CustomContext): async def play(self, ctx: CustomContext):
"""Starts playing Christmas bangers""" """Start the radio"""
# Get the player for this guild from cache. # Get the player for this guild from cache.
player: DefaultPlayer = self.bot.lavalink.player_manager.get(ctx.guild.id) player = ctx.get_player()
await self.fill_player_queue(player, self.bot.config["queue_buffer_size"]) if player.is_connected:
await ctx.send("Already connected")
return
await self.fill_player_queue(player, self.bot.config["queue_buffer_size"]+1)
if not player.is_playing: if not player.is_playing:
await player.play() await player.play()
await ctx.send("Started playing") await EmbedGenerator.Title(ctx, "*⃣ | Connected.")
return
@commands.command(name="skip", aliases=["next"]) @commands.command(name="skip", aliases=["next"])
async def skip(self, ctx: Context): async def skip(self, ctx: CustomContext):
"""I heard this song way too often""" """Skip the current song"""
player: DefaultPlayer = self.bot.lavalink.player_manager.get(ctx.guild.id) player = ctx.get_player()
await player.skip() await player.skip()
await ctx.send("Skipped current song") await ctx.send("Skipped current song")
@commands.command(name="queue") @commands.command(name="queue")
async def queue(self, ctx: Context): async def queue(self, ctx: CustomContext):
"""Ghetto queue""" """Display the current radio queue"""
player: DefaultPlayer = self.bot.lavalink.player_manager.get(ctx.guild.id) player = ctx.get_player()
await EmbedGenerator.Message(ctx, "Queue:", player.queue) embed_color = self.bot.colors["embed"]
embed = Embed(title="Coming Up...", colour=embed_color)
if len(player.queue) > 0:
embed.description = "\n".join(
f"{index}. [{track.title}]({track.uri})"
for index, track in enumerate(player.queue, 1)
)
else:
embed.description = "We are still determining a playlist"
await ctx.send(embed=embed)
@commands.command(name="disconnect", aliases=["dc", "stop"]) @commands.command(name="disconnect", aliases=["dc", "stop"])
async def disconnect(self, ctx: Context): async def disconnect(self, ctx: CustomContext):
"""Disconnects ChristmasBot""" """Disconnects the radio from the channel"""
player: DefaultPlayer = self.bot.lavalink.player_manager.get(ctx.guild.id) player = ctx.get_player()
if not player.is_connected:
return await EmbedGenerator.Title(ctx, "Not connected.")
if not ctx.author.voice or ( if not ctx.author.voice or (
player.is_connected player.is_connected
@@ -257,7 +289,8 @@ class Music(commands.Cog):
): ):
# Abuse prevention. Users not in voice channels, or not in the same voice channel as the bot # Abuse prevention. Users not in voice channels, or not in the same voice channel as the bot
# may not disconnect the bot. # may not disconnect the bot.
return await EmbedGenerator.Title(ctx, "You're not in my voicechannel!") await EmbedGenerator.Title(ctx, "You're not in my voicechannel!")
return
# Clear the queue to ensure old tracks don't start playing # Clear the queue to ensure old tracks don't start playing
# when someone else queues something. # when someone else queues something.
@@ -268,6 +301,13 @@ class Music(commands.Cog):
await ctx.voice_client.disconnect(force=True) await ctx.voice_client.disconnect(force=True)
await EmbedGenerator.Title(ctx, "*⃣ | Disconnected.") await EmbedGenerator.Title(ctx, "*⃣ | Disconnected.")
@commands.command(name="now")
async def now_playing(self, ctx: CustomContext):
player: DefaultPlayer = self.bot.lavalink.player_manager.get(ctx.guild.id)
track = player.current
embed = await self.create_track_embed(track)
await ctx.send(embed=embed)
def setup(bot: ChristmasBot): def setup(bot: ChristmasBot):
bot.add_cog(Music(bot)) bot.add_cog(Music(bot))
+9 -9
View File
@@ -1,24 +1,24 @@
import discord
from discord.ext import commands
import textwrap
import io
import traceback
import asyncio import asyncio
import io
import textwrap
import time import time
import traceback
from asyncio.subprocess import PIPE from asyncio.subprocess import PIPE
from contextlib import redirect_stdout
from io import BytesIO from io import BytesIO
from platform import python_version from platform import python_version
from contextlib import redirect_stdout
import discord
from discord.ext import commands
from discord.ext.commands.context import Context from discord.ext.commands.context import Context
from bot import ChristmasBot from bot import ChristmasBot
from utils.classes import BaseCog
class OwnerCog(commands.Cog): class OwnerCog(BaseCog):
def __init__(self, bot: ChristmasBot): def __init__(self, bot: ChristmasBot):
self.bot = bot super().__init__(bot)
self._last_result = None self._last_result = None
@staticmethod @staticmethod
+12 -6
View File
@@ -1,18 +1,21 @@
from context import CustomContext
from discord.ext import commands from discord.ext import commands
from utils.EmbedGenerator import EmbedGenerator from utils.EmbedGenerator import EmbedGenerator
from utils.classes import BaseCog
from utils.database import AutoJoin from utils.database import AutoJoin
from bot import ChristmasBot from bot import ChristmasBot
from discord.ext.commands import Context from discord.ext.commands import Context
from bot import ChristmasBot
from context import CustomContext
from utils.database import AutoJoin
from utils.EmbedGenerator import EmbedGenerator
class SettingsCog(commands.Cog, name="Settings"):
def __init__(self, bot: ChristmasBot):
self.bot = bot
class SettingsCog(BaseCog, name="Settings"):
@commands.group(aliases=["aj"], invoke_without_command=True) @commands.group(aliases=["aj"], invoke_without_command=True)
@commands.cooldown(rate=1, per=5, type=commands.BucketType.user) @commands.cooldown(rate=1, per=5, type=commands.BucketType.user)
async def autojoin(self, ctx: CustomContext): async def autojoin(self, ctx: CustomContext):
"""Enable/Disable the bot automatically joining"""
await EmbedGenerator.Message( await EmbedGenerator.Message(
ctx, ctx,
"Autojoin", "Autojoin",
@@ -23,16 +26,19 @@ class SettingsCog(commands.Cog, name="Settings"):
@commands.has_permissions(manage_channels=True) @commands.has_permissions(manage_channels=True)
@commands.cooldown(rate=1, per=5, type=commands.BucketType.user) @commands.cooldown(rate=1, per=5, type=commands.BucketType.user)
async def autojoin_set(self, ctx: CustomContext): async def autojoin_set(self, ctx: CustomContext):
"""Enable the bot automatically joining"""
voicechannel_id = ctx.author.voice.channel.id voicechannel_id = ctx.author.voice.channel.id
textchannel_id = ctx.message.channel.id textchannel_id = ctx.message.channel.id
await AutoJoin.update_channel(ctx.get_redis(), ctx.guild.id, voicechannel_id, textchannel_id) await AutoJoin.update_channel(
ctx.get_redis(), ctx.guild.id, voicechannel_id, textchannel_id
)
await EmbedGenerator.Message(ctx, "Autojoin", "`enabled`") await EmbedGenerator.Message(ctx, "Autojoin", "`enabled`")
@autojoin.command(name="disable") @autojoin.command(name="disable")
@commands.has_permissions(manage_channels=True) @commands.has_permissions(manage_channels=True)
@commands.cooldown(rate=1, per=5, type=commands.BucketType.user) @commands.cooldown(rate=1, per=5, type=commands.BucketType.user)
async def autojoin_del(self, ctx: CustomContext): async def autojoin_del(self, ctx: CustomContext):
vc = ctx.author.voice.channel """Disable the bot automatically joining"""
await AutoJoin.del_channel(ctx.get_redis(), ctx.guild.id) await AutoJoin.del_channel(ctx.get_redis(), ctx.guild.id)
await EmbedGenerator.Message(ctx, "Autojoin", "`disabled`") await EmbedGenerator.Message(ctx, "Autojoin", "`disabled`")
+3 -1
View File
@@ -3,6 +3,7 @@
"owner_ids": [194545408960102400, 190875175460405249], "owner_ids": [194545408960102400, 190875175460405249],
"prefixes": ["ck!"], "prefixes": ["ck!"],
"redis_url": "", "redis_url": "",
"redis_prefix": "",
"lavalink": { "lavalink": {
"host": "", "host": "",
"port": 2333, "port": 2333,
@@ -19,5 +20,6 @@
}, },
"cogs": ["cogs.owner", "cogs.settings", "cogs.information", "cogs.music"], "cogs": ["cogs.owner", "cogs.settings", "cogs.information", "cogs.music"],
"slash_command_guilds": [], "slash_command_guilds": [],
"queue_buffer_size": 5 "queue_buffer_size": 5,
"slash_descriptions": {}
} }
+8
View File
@@ -1,7 +1,15 @@
from aioredis.client import Redis from aioredis.client import Redis
from discord.ext import commands from discord.ext import commands
from discord.ext.commands.errors import CommandInvokeError
from lavalink.models import DefaultPlayer
class CustomContext(commands.Context): class CustomContext(commands.Context):
def get_redis(self) -> Redis: def get_redis(self) -> Redis:
return self.bot._redis_client return self.bot._redis_client
def get_player(self) -> DefaultPlayer:
if hasattr(self.bot, "lavalink"):
return self.bot.lavalink.player_manager.get(self.guild.id)
raise CommandInvokeError("Lavalink is still starting up.")
Generated
+184 -3
View File
@@ -53,6 +53,18 @@ docs = ["furo", "sphinx", "zope.interface", "sphinx-notfound-page"]
tests = ["coverage[toml] (>=5.0.2)", "hypothesis", "pympler", "pytest (>=4.3.0)", "six", "mypy", "pytest-mypy-plugins", "zope.interface"] tests = ["coverage[toml] (>=5.0.2)", "hypothesis", "pympler", "pytest (>=4.3.0)", "six", "mypy", "pytest-mypy-plugins", "zope.interface"]
tests_no_zope = ["coverage[toml] (>=5.0.2)", "hypothesis", "pympler", "pytest (>=4.3.0)", "six", "mypy", "pytest-mypy-plugins"] tests_no_zope = ["coverage[toml] (>=5.0.2)", "hypothesis", "pympler", "pytest (>=4.3.0)", "six", "mypy", "pytest-mypy-plugins"]
[[package]]
name = "backports.entry-points-selectable"
version = "1.1.0"
description = "Compatibility shim providing selectable entry points for older implementations"
category = "dev"
optional = false
python-versions = ">=2.7"
[package.extras]
docs = ["sphinx", "jaraco.packaging (>=8.2)", "rst.linker (>=1.9)"]
testing = ["pytest (>=4.6)", "pytest-flake8", "pytest-cov", "pytest-black (>=0.3.7)", "pytest-mypy", "pytest-checkdocs (>=2.4)", "pytest-enabler (>=1.0.1)"]
[[package]] [[package]]
name = "black" name = "black"
version = "21.9b0" version = "21.9b0"
@@ -91,6 +103,14 @@ python-versions = "*"
[package.dependencies] [package.dependencies]
pycparser = "*" pycparser = "*"
[[package]]
name = "cfgv"
version = "3.3.1"
description = "Validate configuration and produce human readable error messages."
category = "dev"
optional = false
python-versions = ">=3.6.1"
[[package]] [[package]]
name = "chardet" name = "chardet"
version = "3.0.4" version = "3.0.4"
@@ -120,7 +140,7 @@ python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*"
[[package]] [[package]]
name = "discord.py" name = "discord.py"
version = "2.0.0a3661+g96153bb1" version = "2.0.0a3662+gd2adc6c0"
description = "A Python wrapper for the Discord API" description = "A Python wrapper for the Discord API"
category = "main" category = "main"
optional = false optional = false
@@ -141,7 +161,27 @@ voice = ["PyNaCl (>=1.3.0,<1.5)"]
type = "git" type = "git"
url = "https://github.com/iDevision/enhanced-discord.py" url = "https://github.com/iDevision/enhanced-discord.py"
reference = "2.0" reference = "2.0"
resolved_reference = "96153bb177d5a9e0be81f8c05e57d8777f4cd926" resolved_reference = "d2adc6c05fafa761f7b8005ba8469ef4b78c188a"
[[package]]
name = "distlib"
version = "0.3.3"
description = "Distribution utilities"
category = "dev"
optional = false
python-versions = "*"
[[package]]
name = "filelock"
version = "3.3.2"
description = "A platform independent file lock."
category = "dev"
optional = false
python-versions = ">=3.6"
[package.extras]
docs = ["furo (>=2021.8.17b43)", "sphinx (>=4.1)", "sphinx-autodoc-typehints (>=1.12)"]
testing = ["covdefaults (>=1.2.0)", "coverage (>=4)", "pytest (>=4)", "pytest-cov", "pytest-timeout (>=1.4.2)"]
[[package]] [[package]]
name = "humanize" name = "humanize"
@@ -154,6 +194,17 @@ python-versions = ">=3.6"
[package.extras] [package.extras]
tests = ["freezegun", "pytest", "pytest-cov"] tests = ["freezegun", "pytest", "pytest-cov"]
[[package]]
name = "identify"
version = "2.3.4"
description = "File identification library for Python"
category = "dev"
optional = false
python-versions = ">=3.6.1"
[package.extras]
license = ["editdistance-s"]
[[package]] [[package]]
name = "idna" name = "idna"
version = "3.3" version = "3.3"
@@ -193,6 +244,14 @@ category = "dev"
optional = false optional = false
python-versions = "*" python-versions = "*"
[[package]]
name = "nodeenv"
version = "1.6.0"
description = "Node.js virtual environment builder"
category = "dev"
optional = false
python-versions = "*"
[[package]] [[package]]
name = "orjson" name = "orjson"
version = "3.6.4" version = "3.6.4"
@@ -221,6 +280,22 @@ python-versions = ">=3.6"
docs = ["Sphinx (>=4)", "furo (>=2021.7.5b38)", "proselint (>=0.10.2)", "sphinx-autodoc-typehints (>=1.12)"] docs = ["Sphinx (>=4)", "furo (>=2021.7.5b38)", "proselint (>=0.10.2)", "sphinx-autodoc-typehints (>=1.12)"]
test = ["appdirs (==1.4.4)", "pytest (>=6)", "pytest-cov (>=2.7)", "pytest-mock (>=3.6)"] test = ["appdirs (==1.4.4)", "pytest (>=6)", "pytest-cov (>=2.7)", "pytest-mock (>=3.6)"]
[[package]]
name = "pre-commit"
version = "2.15.0"
description = "A framework for managing and maintaining multi-language pre-commit hooks."
category = "dev"
optional = false
python-versions = ">=3.6.1"
[package.dependencies]
cfgv = ">=2.0.0"
identify = ">=1.0.0"
nodeenv = ">=0.11.1"
pyyaml = ">=5.1"
toml = "*"
virtualenv = ">=20.0.8"
[[package]] [[package]]
name = "pycparser" name = "pycparser"
version = "2.20" version = "2.20"
@@ -245,6 +320,14 @@ six = "*"
docs = ["sphinx (>=1.6.5)", "sphinx-rtd-theme"] docs = ["sphinx (>=1.6.5)", "sphinx-rtd-theme"]
tests = ["pytest (>=3.2.1,!=3.3.0)", "hypothesis (>=3.27.0)"] tests = ["pytest (>=3.2.1,!=3.3.0)", "hypothesis (>=3.27.0)"]
[[package]]
name = "pyyaml"
version = "6.0"
description = "YAML parser and emitter for Python"
category = "dev"
optional = false
python-versions = ">=3.6"
[[package]] [[package]]
name = "regex" name = "regex"
version = "2021.10.23" version = "2021.10.23"
@@ -261,6 +344,14 @@ category = "main"
optional = false optional = false
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*" python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*"
[[package]]
name = "toml"
version = "0.10.2"
description = "Python Library for Tom's Obvious, Minimal Language"
category = "dev"
optional = false
python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*"
[[package]] [[package]]
name = "tomli" name = "tomli"
version = "1.2.2" version = "1.2.2"
@@ -290,6 +381,25 @@ dev = ["Cython (>=0.29.24,<0.30.0)", "pytest (>=3.6.0)", "Sphinx (>=4.1.2,<4.2.0
docs = ["Sphinx (>=4.1.2,<4.2.0)", "sphinxcontrib-asyncio (>=0.3.0,<0.4.0)", "sphinx-rtd-theme (>=0.5.2,<0.6.0)"] docs = ["Sphinx (>=4.1.2,<4.2.0)", "sphinxcontrib-asyncio (>=0.3.0,<0.4.0)", "sphinx-rtd-theme (>=0.5.2,<0.6.0)"]
test = ["aiohttp", "flake8 (>=3.9.2,<3.10.0)", "psutil", "pycodestyle (>=2.7.0,<2.8.0)", "pyOpenSSL (>=19.0.0,<19.1.0)", "mypy (>=0.800)"] test = ["aiohttp", "flake8 (>=3.9.2,<3.10.0)", "psutil", "pycodestyle (>=2.7.0,<2.8.0)", "pyOpenSSL (>=19.0.0,<19.1.0)", "mypy (>=0.800)"]
[[package]]
name = "virtualenv"
version = "20.10.0"
description = "Virtual Python Environment builder"
category = "dev"
optional = false
python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.7"
[package.dependencies]
"backports.entry-points-selectable" = ">=1.0.4"
distlib = ">=0.3.1,<1"
filelock = ">=3.2,<4"
platformdirs = ">=2,<3"
six = ">=1.9.0,<2"
[package.extras]
docs = ["proselint (>=0.10.2)", "sphinx (>=3)", "sphinx-argparse (>=0.2.5)", "sphinx-rtd-theme (>=0.4.3)", "towncrier (>=21.3)"]
testing = ["coverage (>=4)", "coverage-enable-subprocess (>=1)", "flaky (>=3)", "pytest (>=4)", "pytest-env (>=0.6.2)", "pytest-freezegun (>=0.4.1)", "pytest-mock (>=2)", "pytest-randomly (>=1)", "pytest-timeout (>=1)", "packaging (>=20.0)"]
[[package]] [[package]]
name = "yarl" name = "yarl"
version = "1.5.1" version = "1.5.1"
@@ -305,7 +415,7 @@ multidict = ">=4.0"
[metadata] [metadata]
lock-version = "1.1" lock-version = "1.1"
python-versions = "^3.8" python-versions = "^3.8"
content-hash = "3e8f3b5171be334aaa606cd70df03f9b0ac49cb2f78b69723ff49233ce9c1cd3" content-hash = "7428479732f5183e24be61ddeee7230bafdd6b76920e2d6d548c6a091e570111"
[metadata.files] [metadata.files]
aiohttp = [ aiohttp = [
@@ -335,6 +445,10 @@ attrs = [
{file = "attrs-21.2.0-py2.py3-none-any.whl", hash = "sha256:149e90d6d8ac20db7a955ad60cf0e6881a3f20d37096140088356da6c716b0b1"}, {file = "attrs-21.2.0-py2.py3-none-any.whl", hash = "sha256:149e90d6d8ac20db7a955ad60cf0e6881a3f20d37096140088356da6c716b0b1"},
{file = "attrs-21.2.0.tar.gz", hash = "sha256:ef6aaac3ca6cd92904cdd0d83f629a15f18053ec84e6432106f7a4d04ae4f5fb"}, {file = "attrs-21.2.0.tar.gz", hash = "sha256:ef6aaac3ca6cd92904cdd0d83f629a15f18053ec84e6432106f7a4d04ae4f5fb"},
] ]
"backports.entry-points-selectable" = [
{file = "backports.entry_points_selectable-1.1.0-py2.py3-none-any.whl", hash = "sha256:a6d9a871cde5e15b4c4a53e3d43ba890cc6861ec1332c9c2428c92f977192acc"},
{file = "backports.entry_points_selectable-1.1.0.tar.gz", hash = "sha256:988468260ec1c196dab6ae1149260e2f5472c9110334e5d51adcb77867361f6a"},
]
black = [ black = [
{file = "black-21.9b0-py3-none-any.whl", hash = "sha256:380f1b5da05e5a1429225676655dddb96f5ae8c75bdf91e53d798871b902a115"}, {file = "black-21.9b0-py3-none-any.whl", hash = "sha256:380f1b5da05e5a1429225676655dddb96f5ae8c75bdf91e53d798871b902a115"},
{file = "black-21.9b0.tar.gz", hash = "sha256:7de4cfc7eb6b710de325712d40125689101d21d25283eed7e9998722cf10eb91"}, {file = "black-21.9b0.tar.gz", hash = "sha256:7de4cfc7eb6b710de325712d40125689101d21d25283eed7e9998722cf10eb91"},
@@ -391,6 +505,10 @@ cffi = [
{file = "cffi-1.15.0-cp39-cp39-win_amd64.whl", hash = "sha256:3773c4d81e6e818df2efbc7dd77325ca0dcb688116050fb2b3011218eda36139"}, {file = "cffi-1.15.0-cp39-cp39-win_amd64.whl", hash = "sha256:3773c4d81e6e818df2efbc7dd77325ca0dcb688116050fb2b3011218eda36139"},
{file = "cffi-1.15.0.tar.gz", hash = "sha256:920f0d66a896c2d99f0adbb391f990a84091179542c205fa53ce5787aff87954"}, {file = "cffi-1.15.0.tar.gz", hash = "sha256:920f0d66a896c2d99f0adbb391f990a84091179542c205fa53ce5787aff87954"},
] ]
cfgv = [
{file = "cfgv-3.3.1-py2.py3-none-any.whl", hash = "sha256:c6a0883f3917a037485059700b9e75da2464e6c27051014ad85ba6aaa5884426"},
{file = "cfgv-3.3.1.tar.gz", hash = "sha256:f5a830efb9ce7a445376bb66ec94c638a9787422f96264c98edc6bdeed8ab736"},
]
chardet = [ chardet = [
{file = "chardet-3.0.4-py2.py3-none-any.whl", hash = "sha256:fc323ffcaeaed0e0a02bf4d117757b98aed530d9ed4531e3e15460124c106691"}, {file = "chardet-3.0.4-py2.py3-none-any.whl", hash = "sha256:fc323ffcaeaed0e0a02bf4d117757b98aed530d9ed4531e3e15460124c106691"},
{file = "chardet-3.0.4.tar.gz", hash = "sha256:84ab92ed1c4d4f16916e05906b6b75a6c0fb5db821cc65e70cbd64a3e2a5eaae"}, {file = "chardet-3.0.4.tar.gz", hash = "sha256:84ab92ed1c4d4f16916e05906b6b75a6c0fb5db821cc65e70cbd64a3e2a5eaae"},
@@ -404,10 +522,22 @@ colorama = [
{file = "colorama-0.4.4.tar.gz", hash = "sha256:5941b2b48a20143d2267e95b1c2a7603ce057ee39fd88e7329b0c292aa16869b"}, {file = "colorama-0.4.4.tar.gz", hash = "sha256:5941b2b48a20143d2267e95b1c2a7603ce057ee39fd88e7329b0c292aa16869b"},
] ]
"discord.py" = [] "discord.py" = []
distlib = [
{file = "distlib-0.3.3-py2.py3-none-any.whl", hash = "sha256:c8b54e8454e5bf6237cc84c20e8264c3e991e824ef27e8f1e81049867d861e31"},
{file = "distlib-0.3.3.zip", hash = "sha256:d982d0751ff6eaaab5e2ec8e691d949ee80eddf01a62eaa96ddb11531fe16b05"},
]
filelock = [
{file = "filelock-3.3.2-py3-none-any.whl", hash = "sha256:bb2a1c717df74c48a2d00ed625e5a66f8572a3a30baacb7657add1d7bac4097b"},
{file = "filelock-3.3.2.tar.gz", hash = "sha256:7afc856f74fa7006a289fd10fa840e1eebd8bbff6bffb69c26c54a0512ea8cf8"},
]
humanize = [ humanize = [
{file = "humanize-3.12.0-py3-none-any.whl", hash = "sha256:4c71c4381f0209715cd993058e717c1b74d58ae2f8c6da7bdb59ab66473b9ab0"}, {file = "humanize-3.12.0-py3-none-any.whl", hash = "sha256:4c71c4381f0209715cd993058e717c1b74d58ae2f8c6da7bdb59ab66473b9ab0"},
{file = "humanize-3.12.0.tar.gz", hash = "sha256:5ec1a66e230a3e31fb3f184aab9436ea13d4e37c168e0ffc345ae5bb57e58be6"}, {file = "humanize-3.12.0.tar.gz", hash = "sha256:5ec1a66e230a3e31fb3f184aab9436ea13d4e37c168e0ffc345ae5bb57e58be6"},
] ]
identify = [
{file = "identify-2.3.4-py2.py3-none-any.whl", hash = "sha256:4de55a93e0ba72bf917c840b3794eb1055a67272a1732351c557c88ec42011b1"},
{file = "identify-2.3.4.tar.gz", hash = "sha256:595283a1c3a078ac5774ad4dc4d1bdd0c1602f60bcf11ae673b64cb2b1945762"},
]
idna = [ idna = [
{file = "idna-3.3-py3-none-any.whl", hash = "sha256:84d9dd047ffa80596e0f246e2eab0b391788b0503584e8945f2368256d2735ff"}, {file = "idna-3.3-py3-none-any.whl", hash = "sha256:84d9dd047ffa80596e0f246e2eab0b391788b0503584e8945f2368256d2735ff"},
{file = "idna-3.3.tar.gz", hash = "sha256:9d643ff0a55b762d5cdb124b8eaa99c66322e2157b69160bc32796e824360e6d"}, {file = "idna-3.3.tar.gz", hash = "sha256:9d643ff0a55b762d5cdb124b8eaa99c66322e2157b69160bc32796e824360e6d"},
@@ -438,6 +568,10 @@ mypy-extensions = [
{file = "mypy_extensions-0.4.3-py2.py3-none-any.whl", hash = "sha256:090fedd75945a69ae91ce1303b5824f428daf5a028d2f6ab8a299250a846f15d"}, {file = "mypy_extensions-0.4.3-py2.py3-none-any.whl", hash = "sha256:090fedd75945a69ae91ce1303b5824f428daf5a028d2f6ab8a299250a846f15d"},
{file = "mypy_extensions-0.4.3.tar.gz", hash = "sha256:2d82818f5bb3e369420cb3c4060a7970edba416647068eb4c5343488a6c604a8"}, {file = "mypy_extensions-0.4.3.tar.gz", hash = "sha256:2d82818f5bb3e369420cb3c4060a7970edba416647068eb4c5343488a6c604a8"},
] ]
nodeenv = [
{file = "nodeenv-1.6.0-py2.py3-none-any.whl", hash = "sha256:621e6b7076565ddcacd2db0294c0381e01fd28945ab36bcf00f41c5daf63bef7"},
{file = "nodeenv-1.6.0.tar.gz", hash = "sha256:3ef13ff90291ba2a4a7a4ff9a979b63ffdd00a464dbe04acf0ea6471517a4c2b"},
]
orjson = [ orjson = [
{file = "orjson-3.6.4-cp310-cp310-macosx_10_7_x86_64.whl", hash = "sha256:fc01a15f3101628fd619158daec79b30d7461149735e73542ca8c13be6b835be"}, {file = "orjson-3.6.4-cp310-cp310-macosx_10_7_x86_64.whl", hash = "sha256:fc01a15f3101628fd619158daec79b30d7461149735e73542ca8c13be6b835be"},
{file = "orjson-3.6.4-cp310-cp310-manylinux_2_24_aarch64.whl", hash = "sha256:48a69fed90f551bf9e9bb7a63e363fed4f67fc7c6e6bfb057054dc78f6721e9e"}, {file = "orjson-3.6.4-cp310-cp310-manylinux_2_24_aarch64.whl", hash = "sha256:48a69fed90f551bf9e9bb7a63e363fed4f67fc7c6e6bfb057054dc78f6721e9e"},
@@ -471,6 +605,10 @@ platformdirs = [
{file = "platformdirs-2.4.0-py3-none-any.whl", hash = "sha256:8868bbe3c3c80d42f20156f22e7131d2fb321f5bc86a2a345375c6481a67021d"}, {file = "platformdirs-2.4.0-py3-none-any.whl", hash = "sha256:8868bbe3c3c80d42f20156f22e7131d2fb321f5bc86a2a345375c6481a67021d"},
{file = "platformdirs-2.4.0.tar.gz", hash = "sha256:367a5e80b3d04d2428ffa76d33f124cf11e8fff2acdaa9b43d545f5c7d661ef2"}, {file = "platformdirs-2.4.0.tar.gz", hash = "sha256:367a5e80b3d04d2428ffa76d33f124cf11e8fff2acdaa9b43d545f5c7d661ef2"},
] ]
pre-commit = [
{file = "pre_commit-2.15.0-py2.py3-none-any.whl", hash = "sha256:a4ed01000afcb484d9eb8d504272e642c4c4099bbad3a6b27e519bd6a3e928a6"},
{file = "pre_commit-2.15.0.tar.gz", hash = "sha256:3c25add78dbdfb6a28a651780d5c311ac40dd17f160eb3954a0c59da40a505a7"},
]
pycparser = [ pycparser = [
{file = "pycparser-2.20-py2.py3-none-any.whl", hash = "sha256:7582ad22678f0fcd81102833f60ef8d0e57288b6b5fb00323d101be910e35705"}, {file = "pycparser-2.20-py2.py3-none-any.whl", hash = "sha256:7582ad22678f0fcd81102833f60ef8d0e57288b6b5fb00323d101be910e35705"},
{file = "pycparser-2.20.tar.gz", hash = "sha256:2d475327684562c3a96cc71adf7dc8c4f0565175cf86b6d7a404ff4c771f15f0"}, {file = "pycparser-2.20.tar.gz", hash = "sha256:2d475327684562c3a96cc71adf7dc8c4f0565175cf86b6d7a404ff4c771f15f0"},
@@ -495,6 +633,41 @@ pynacl = [
{file = "PyNaCl-1.4.0-cp38-cp38-win_amd64.whl", hash = "sha256:7c6092102219f59ff29788860ccb021e80fffd953920c4a8653889c029b2d420"}, {file = "PyNaCl-1.4.0-cp38-cp38-win_amd64.whl", hash = "sha256:7c6092102219f59ff29788860ccb021e80fffd953920c4a8653889c029b2d420"},
{file = "PyNaCl-1.4.0.tar.gz", hash = "sha256:54e9a2c849c742006516ad56a88f5c74bf2ce92c9f67435187c3c5953b346505"}, {file = "PyNaCl-1.4.0.tar.gz", hash = "sha256:54e9a2c849c742006516ad56a88f5c74bf2ce92c9f67435187c3c5953b346505"},
] ]
pyyaml = [
{file = "PyYAML-6.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d4db7c7aef085872ef65a8fd7d6d09a14ae91f691dec3e87ee5ee0539d516f53"},
{file = "PyYAML-6.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9df7ed3b3d2e0ecfe09e14741b857df43adb5a3ddadc919a2d94fbdf78fea53c"},
{file = "PyYAML-6.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:77f396e6ef4c73fdc33a9157446466f1cff553d979bd00ecb64385760c6babdc"},
{file = "PyYAML-6.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a80a78046a72361de73f8f395f1f1e49f956c6be882eed58505a15f3e430962b"},
{file = "PyYAML-6.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:f84fbc98b019fef2ee9a1cb3ce93e3187a6df0b2538a651bfb890254ba9f90b5"},
{file = "PyYAML-6.0-cp310-cp310-win32.whl", hash = "sha256:2cd5df3de48857ed0544b34e2d40e9fac445930039f3cfe4bcc592a1f836d513"},
{file = "PyYAML-6.0-cp310-cp310-win_amd64.whl", hash = "sha256:daf496c58a8c52083df09b80c860005194014c3698698d1a57cbcfa182142a3a"},
{file = "PyYAML-6.0-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:897b80890765f037df3403d22bab41627ca8811ae55e9a722fd0392850ec4d86"},
{file = "PyYAML-6.0-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:50602afada6d6cbfad699b0c7bb50d5ccffa7e46a3d738092afddc1f9758427f"},
{file = "PyYAML-6.0-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:48c346915c114f5fdb3ead70312bd042a953a8ce5c7106d5bfb1a5254e47da92"},
{file = "PyYAML-6.0-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:98c4d36e99714e55cfbaaee6dd5badbc9a1ec339ebfc3b1f52e293aee6bb71a4"},
{file = "PyYAML-6.0-cp36-cp36m-win32.whl", hash = "sha256:0283c35a6a9fbf047493e3a0ce8d79ef5030852c51e9d911a27badfde0605293"},
{file = "PyYAML-6.0-cp36-cp36m-win_amd64.whl", hash = "sha256:07751360502caac1c067a8132d150cf3d61339af5691fe9e87803040dbc5db57"},
{file = "PyYAML-6.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:819b3830a1543db06c4d4b865e70ded25be52a2e0631ccd2f6a47a2822f2fd7c"},
{file = "PyYAML-6.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:473f9edb243cb1935ab5a084eb238d842fb8f404ed2193a915d1784b5a6b5fc0"},
{file = "PyYAML-6.0-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0ce82d761c532fe4ec3f87fc45688bdd3a4c1dc5e0b4a19814b9009a29baefd4"},
{file = "PyYAML-6.0-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:231710d57adfd809ef5d34183b8ed1eeae3f76459c18fb4a0b373ad56bedcdd9"},
{file = "PyYAML-6.0-cp37-cp37m-win32.whl", hash = "sha256:c5687b8d43cf58545ade1fe3e055f70eac7a5a1a0bf42824308d868289a95737"},
{file = "PyYAML-6.0-cp37-cp37m-win_amd64.whl", hash = "sha256:d15a181d1ecd0d4270dc32edb46f7cb7733c7c508857278d3d378d14d606db2d"},
{file = "PyYAML-6.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:0b4624f379dab24d3725ffde76559cff63d9ec94e1736b556dacdfebe5ab6d4b"},
{file = "PyYAML-6.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:213c60cd50106436cc818accf5baa1aba61c0189ff610f64f4a3e8c6726218ba"},
{file = "PyYAML-6.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9fa600030013c4de8165339db93d182b9431076eb98eb40ee068700c9c813e34"},
{file = "PyYAML-6.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:277a0ef2981ca40581a47093e9e2d13b3f1fbbeffae064c1d21bfceba2030287"},
{file = "PyYAML-6.0-cp38-cp38-win32.whl", hash = "sha256:d4eccecf9adf6fbcc6861a38015c2a64f38b9d94838ac1810a9023a0609e1b78"},
{file = "PyYAML-6.0-cp38-cp38-win_amd64.whl", hash = "sha256:1e4747bc279b4f613a09eb64bba2ba602d8a6664c6ce6396a4d0cd413a50ce07"},
{file = "PyYAML-6.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:055d937d65826939cb044fc8c9b08889e8c743fdc6a32b33e2390f66013e449b"},
{file = "PyYAML-6.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:e61ceaab6f49fb8bdfaa0f92c4b57bcfbea54c09277b1b4f7ac376bfb7a7c174"},
{file = "PyYAML-6.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d67d839ede4ed1b28a4e8909735fc992a923cdb84e618544973d7dfc71540803"},
{file = "PyYAML-6.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:cba8c411ef271aa037d7357a2bc8f9ee8b58b9965831d9e51baf703280dc73d3"},
{file = "PyYAML-6.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:40527857252b61eacd1d9af500c3337ba8deb8fc298940291486c465c8b46ec0"},
{file = "PyYAML-6.0-cp39-cp39-win32.whl", hash = "sha256:b5b9eccad747aabaaffbc6064800670f0c297e52c12754eb1d976c57e4f74dcb"},
{file = "PyYAML-6.0-cp39-cp39-win_amd64.whl", hash = "sha256:b3d267842bf12586ba6c734f89d1f5b871df0273157918b0ccefa29deb05c21c"},
{file = "PyYAML-6.0.tar.gz", hash = "sha256:68fb519c14306fec9720a2a5b45bc9f0c8d1b9c72adf45c37baedfcd949c35a2"},
]
regex = [ regex = [
{file = "regex-2021.10.23-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:45b65d6a275a478ac2cbd7fdbf7cc93c1982d613de4574b56fd6972ceadb8395"}, {file = "regex-2021.10.23-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:45b65d6a275a478ac2cbd7fdbf7cc93c1982d613de4574b56fd6972ceadb8395"},
{file = "regex-2021.10.23-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:74d071dbe4b53c602edd87a7476ab23015a991374ddb228d941929ad7c8c922e"}, {file = "regex-2021.10.23-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:74d071dbe4b53c602edd87a7476ab23015a991374ddb228d941929ad7c8c922e"},
@@ -537,6 +710,10 @@ six = [
{file = "six-1.16.0-py2.py3-none-any.whl", hash = "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"}, {file = "six-1.16.0-py2.py3-none-any.whl", hash = "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"},
{file = "six-1.16.0.tar.gz", hash = "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926"}, {file = "six-1.16.0.tar.gz", hash = "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926"},
] ]
toml = [
{file = "toml-0.10.2-py2.py3-none-any.whl", hash = "sha256:806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b"},
{file = "toml-0.10.2.tar.gz", hash = "sha256:b3bda1d108d5dd99f4a20d24d9c348e91c4db7ab1b749200bded2f839ccbe68f"},
]
tomli = [ tomli = [
{file = "tomli-1.2.2-py3-none-any.whl", hash = "sha256:f04066f68f5554911363063a30b108d2b5a5b1a010aa8b6132af78489fe3aade"}, {file = "tomli-1.2.2-py3-none-any.whl", hash = "sha256:f04066f68f5554911363063a30b108d2b5a5b1a010aa8b6132af78489fe3aade"},
{file = "tomli-1.2.2.tar.gz", hash = "sha256:c6ce0015eb38820eaf32b5db832dbc26deb3dd427bd5f6556cf0acac2c214fee"}, {file = "tomli-1.2.2.tar.gz", hash = "sha256:c6ce0015eb38820eaf32b5db832dbc26deb3dd427bd5f6556cf0acac2c214fee"},
@@ -564,6 +741,10 @@ uvloop = [
{file = "uvloop-0.16.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1e5f2e2ff51aefe6c19ee98af12b4ae61f5be456cd24396953244a30880ad861"}, {file = "uvloop-0.16.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1e5f2e2ff51aefe6c19ee98af12b4ae61f5be456cd24396953244a30880ad861"},
{file = "uvloop-0.16.0.tar.gz", hash = "sha256:f74bc20c7b67d1c27c72601c78cf95be99d5c2cdd4514502b4f3eb0933ff1228"}, {file = "uvloop-0.16.0.tar.gz", hash = "sha256:f74bc20c7b67d1c27c72601c78cf95be99d5c2cdd4514502b4f3eb0933ff1228"},
] ]
virtualenv = [
{file = "virtualenv-20.10.0-py2.py3-none-any.whl", hash = "sha256:4b02e52a624336eece99c96e3ab7111f469c24ba226a53ec474e8e787b365814"},
{file = "virtualenv-20.10.0.tar.gz", hash = "sha256:576d05b46eace16a9c348085f7d0dc8ef28713a2cabaa1cf0aea41e8f12c9218"},
]
yarl = [ yarl = [
{file = "yarl-1.5.1-cp35-cp35m-macosx_10_14_x86_64.whl", hash = "sha256:db6db0f45d2c63ddb1a9d18d1b9b22f308e52c83638c26b422d520a815c4b3fb"}, {file = "yarl-1.5.1-cp35-cp35m-macosx_10_14_x86_64.whl", hash = "sha256:db6db0f45d2c63ddb1a9d18d1b9b22f308e52c83638c26b422d520a815c4b3fb"},
{file = "yarl-1.5.1-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:17668ec6722b1b7a3a05cc0167659f6c95b436d25a36c2d52db0eca7d3f72593"}, {file = "yarl-1.5.1-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:17668ec6722b1b7a3a05cc0167659f6c95b436d25a36c2d52db0eca7d3f72593"},
+1
View File
@@ -15,6 +15,7 @@ aioredis = "^2.0.0"
[tool.poetry.dev-dependencies] [tool.poetry.dev-dependencies]
black = {version = "^21.9b0", allow-prereleases = true} black = {version = "^21.9b0", allow-prereleases = true}
pre-commit = "^2.15.0"
[build-system] [build-system]
requires = ["poetry-core>=1.0.0"] requires = ["poetry-core>=1.0.0"]
+10 -6
View File
@@ -1,8 +1,8 @@
from typing import Optional from typing import Optional, Union
import discord import discord
from discord import Embed
from discord.ext.commands import Context from discord.ext.commands import Context
from discord import Embed
class EmbedGenerator: class EmbedGenerator:
@@ -13,7 +13,9 @@ class EmbedGenerator:
return await EmbedGenerator.SendWithFooter(ctx, em, **kwargs) return await EmbedGenerator.SendWithFooter(ctx, em, **kwargs)
@staticmethod @staticmethod
async def Message(ctx: Context, title: str, message: Optional[str] = "", **kwargs): async def Message(
ctx: Context, title: str, message: Optional[str] = "", **kwargs
) -> Embed:
color = ctx.bot.colors["embed"] color = ctx.bot.colors["embed"]
em = Embed(title=title, description=message, color=color) em = Embed(title=title, description=message, color=color)
return await EmbedGenerator.SendWithFooter(ctx, em, **kwargs) return await EmbedGenerator.SendWithFooter(ctx, em, **kwargs)
@@ -21,20 +23,22 @@ class EmbedGenerator:
@staticmethod @staticmethod
async def Image( async def Image(
ctx: Context, title: str, url: str, message: Optional[str] = "", **kwargs ctx: Context, title: str, url: str, message: Optional[str] = "", **kwargs
): ) -> Embed:
color = ctx.bot.colors["embed"] color = ctx.bot.colors["embed"]
em = Embed(title=title, description=message, url=url, color=color) em = Embed(title=title, description=message, url=url, color=color)
em.set_image(url=url) em.set_image(url=url)
return await EmbedGenerator.SendWithFooter(ctx, em, **kwargs) return await EmbedGenerator.SendWithFooter(ctx, em, **kwargs)
@staticmethod @staticmethod
async def Title(ctx: Context, title: str, **kwargs): async def Title(ctx: Context, title: str, **kwargs) -> Embed:
color = ctx.bot.colors["embed"] color = ctx.bot.colors["embed"]
em = Embed(title=title, color=color) em = Embed(title=title, color=color)
return await EmbedGenerator.SendWithFooter(ctx, em, **kwargs) return await EmbedGenerator.SendWithFooter(ctx, em, **kwargs)
@staticmethod @staticmethod
async def SendWithFooter(ctx: Context, em: Embed, **kwargs) -> discord.Message: async def SendWithFooter(
ctx: Context, em: Embed, **kwargs
) -> Union[discord.Message, Embed]:
avatar = ctx.author.avatar.with_static_format("jpeg") avatar = ctx.author.avatar.with_static_format("jpeg")
em.set_footer(text=f"Requested by: {ctx.author}", icon_url=avatar) em.set_footer(text=f"Requested by: {ctx.author}", icon_url=avatar)
if kwargs.get("no_send", False): if kwargs.get("no_send", False):
+13
View File
@@ -0,0 +1,13 @@
from typing import Dict
from discord.ext.commands import Cog
from bot import ChristmasBot
class BaseCog(Cog):
def __init__(self, bot: ChristmasBot) -> None:
self.bot = bot
slash_descriptions: Dict[str, str] = self.bot.config["slash_descriptions"]
for command in self.walk_commands():
if brief := slash_descriptions.get(command.qualified_name):
command.brief = brief
+22 -7
View File
@@ -1,20 +1,35 @@
from typing import Dict
from typing import List
from typing import Optional
from aioredis import Redis from aioredis import Redis
from typing import Sequence
from bot import redis_prefix
class AutoJoin: class AutoJoin:
@staticmethod @staticmethod
async def get_channels(redis: Redis) -> Sequence[tuple]: async def get_channels(redis: Redis) -> Dict[str, str]:
# return all channels # return all channels
channels = await redis.hgetall(name="autojoin") channels = await redis.hgetall(f"{redis_prefix}:autojoin")
return {key: value.split("-") for key, value in channels.items()} return {key: value.split("-") for key, value in channels.items()}
@staticmethod @staticmethod
async def update_channel(redis: Redis, guild_id, voicechannel_id, textchannel_id): async def update_channel(
redis: Redis, guild_id: int, voice_channel_id: int, text_channel_id: int
):
await redis.hset( await redis.hset(
name="autojoin", key=guild_id, value=f"{voicechannel_id}-{textchannel_id}" f"{redis_prefix}:autojoin",
guild_id,
f"{voice_channel_id}-{text_channel_id}",
) )
@staticmethod @staticmethod
async def del_channel(redis: Redis, guild_id): async def del_channel(redis: Redis, guild_id: int):
await redis.hdel("autojoin", guild_id) await redis.hdel(f"{redis_prefix}:autojoin", guild_id)
class Playlist:
@staticmethod
async def random(redis: Redis, amount: Optional[int] = 1) -> List[str]:
return await redis.srandmember(f"{redis_prefix}:playlist", amount)
+11
View File
@@ -0,0 +1,11 @@
from discord.embeds import Embed
from context import CustomContext
from discord.ext.commands import CommandError
class EmbeddedCommandException(CommandError):
def __init__(self, embed: Embed) -> None:
self.embed = embed
async def send(self, ctx: CustomContext):
await ctx.send(embed=self.embed)
-1
View File
@@ -2,7 +2,6 @@
# Modified work Copyright (c) 2017 Perry Fraser # Modified work Copyright (c) 2017 Perry Fraser
# #
# Licensed under the MIT License. https://opensource.org/licenses/MIT # Licensed under the MIT License. https://opensource.org/licenses/MIT
# Stolen line for line from paginator.py in R. Danny's code # Stolen line for line from paginator.py in R. Danny's code
# Added formatting and lots of blocking of inspections # Added formatting and lots of blocking of inspections
import asyncio import asyncio