Skip to content

Commit

Permalink
Merge pull request #15 from TheXer/udalost
Browse files Browse the repository at this point in the history
Udalost
  • Loading branch information
TheXer authored May 3, 2023
2 parents 0bedf7a + 15794ff commit a4fb157
Show file tree
Hide file tree
Showing 12 changed files with 231 additions and 78 deletions.
24 changes: 10 additions & 14 deletions cogs/error.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,6 @@
from discord.ext import commands


# for finding errors with the code.

class Error(commands.Cog):
"""Basic class for catching errors and sending a message"""

Expand All @@ -19,21 +17,19 @@ def __init__(self, bot):

@commands.Cog.listener()
async def on_command_error(self, ctx: commands.Context, error: commands.CommandError):
if isinstance(error, commands.ExpectedClosingQuoteError):
return await ctx.send(f"Pozor! Chybí tady: {error.close_quote} uvozovka!")

elif isinstance(error, commands.MissingPermissions):
return await ctx.send("Chybí ti požadovaná práva!")
match error:
case commands.ExpectedClosingQuoteError():
return await ctx.send(f"Pozor! Chybí tady: {error} uvozovka!")

elif isinstance(error, commands.CommandNotFound):
pass
case commands.MissingPermissions():
return await ctx.send("Chybí ti požadovaná práva!")

elif isinstance(error, commands.MissingRequiredArgument):
return await ctx.send("Chybí ti povinný argument, zkontroluj si ho znova!")
case commands.CommandNotFound():
pass

else:
self.logger.critical(f"{ctx.message.id}, {ctx.message.content} | {error}")
print(error)
case _:
self.logger.critical(f"{ctx.message.id}, {ctx.message.content} | {error}")
print(error)

@commands.Cog.listener()
async def on_command(self, ctx: commands.Context):
Expand Down
30 changes: 19 additions & 11 deletions cogs/morserovka.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
from discord import Message
import discord
from discord import Message, app_commands
from discord.ext import commands


Expand Down Expand Up @@ -34,24 +35,31 @@ class Morse(commands.Cog):
def __init__(self, bot):
self.bot = bot

@commands.command(aliases=["encrypt"])
async def zasifruj(self, ctx: commands.Context, message: str) -> Message:
await ctx.message.delete()
@app_commands.command(
name="zasifruj",
description="Zašifruj text do morserovky!")
@app_commands.describe(
message="Věta nebo slovo pro zašifrování")
async def zasifruj(self, interaction: discord.Interaction, message: str) -> Message:
try:
cipher = "/".join(self.MORSE_CODE_DICT.get(letter.upper()) for letter in message)
return await ctx.send(cipher)
return await interaction.response.send_message(cipher)
except TypeError:
return await ctx.send("Asi jsi nezadal správný text. Text musí být bez speciálních znaků!")
return await interaction.response.send_message(
"Asi jsi nezadal správný text. Text musí být bez speciálních znaků!")

@commands.command(aliases=["decrypt"])
async def desifruj(self, ctx: commands.Context, message: str) -> Message:
await ctx.message.delete()
@app_commands.command(
name="desifruj",
description="Dešifruj text z morserovky!")
@app_commands.describe(
message="Věta nebo slovo pro dešifrování")
async def desifruj(self, interaction: discord.Interaction, message: str) -> Message:
try:
decipher = ''.join(self.REVERSED_MORSE_CODE_DICT.get(letter) for letter in message.split("/"))
return await ctx.send(decipher)
return await interaction.response.send_message(decipher)
except TypeError:
decipher = ''.join(self.REVERSED_MORSE_CODE_DICT.get(x) for x in message.split("|"))
return await ctx.send(decipher)
return await interaction.response.send_message(decipher)


async def setup(bot):
Expand Down
44 changes: 30 additions & 14 deletions cogs/poll_command.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
import discord
from discord import app_commands
from discord.ext import commands
from loguru import logger

from src.db_folder.databases import PollDatabase, VoteButtonDatabase
from src.jachym import Jachym
Expand All @@ -11,34 +14,38 @@
from src.ui.poll_view import PollView


def error_handling(answer: tuple[str]) -> str:
def error_handling(answer: list[str]) -> str:
if len(answer) > Poll.MAX_OPTIONS:
return f"Zadal jsi příliš mnoho odpovědí, můžeš maximálně {Poll.MAX_OPTIONS}!"
elif len(answer) < Poll.MIN_OPTIONS:
return f"Zadal jsi příliš málo odpovědí, můžeš alespoň {Poll.MIN_OPTIONS}!"


class PollCreate(commands.Cog):
COOLDOWN = 10

def __init__(self, bot: Jachym):
self.bot = bot

@commands.command(aliases=["anketa"])
@commands.cooldown(1, COOLDOWN, commands.BucketType.user)
async def pool(self, ctx: commands.Context, question: str, *answer: str):
await ctx.message.delete()
@app_commands.command(
name="anketa",
description="Anketa pro hlasování. Jsou vidět všichni hlasovatelé.")
@app_commands.describe(
question="Otázka, na kterou potřebuješ vědět odpověď",
answer='Odpovědi, rozděluješ odpovědi uvozovkou ("), maximálně pouze 10 možností')
async def pool(self, interaction: discord.Interaction, question: str, answer: str) -> discord.Message:

await interaction.response.send_message(embed=PollEmbedBase("Dělám na tom, vydrž!"))
message = await interaction.original_response()

message = await ctx.send(embed=PollEmbedBase("Dělám na tom, vydrž!"))
if error_handling(answer):
return await message.edit(embed=PollEmbedBase(error_handling(answer)))
answers = answer.split(sep='"')
if error_handling(answers):
return await message.edit(embed=PollEmbedBase(error_handling(answers)))

poll = Poll(
message_id=message.id,
channel_id=message.channel.id,
question=question,
options=answer,
user_id=ctx.message.author.id
options=answers,
user_id=interaction.user.id
)

embed = PollEmbed(poll)
Expand All @@ -48,14 +55,23 @@ async def pool(self, ctx: commands.Context, question: str, *answer: str):

self.bot.active_discord_polls.add(poll)
await self.bot.set_presence()

await message.edit(embed=embed, view=view)
logger.info(f"Successfully added Pool - {message.id}")
return await message.edit(embed=embed, view=view)

@pool.error
async def pool_error(self, ctx: commands.Context, error):
if isinstance(error, commands.CommandOnCooldown):
await ctx.send(embed=CooldownErrorEmbed(error.retry_after))

@commands.command()
async def anketa(self, ctx):
return await ctx.send(
"Ahoj! Tahle funkce teď už bohužel nebude fungovat :(\n"
"Ale neboj se! Do Jáchyma jsou už teď implementovány slash commands, takže místo vykříčníku teď dej /, "
"kde najdeš všechny funkce co teď Jáchym má! :)\n"
"Ještě jedna maličká věc - já jsem vyvíjený už pomalu třetí rok a můj autor by po mně chtěl, abych Ti poslal odkaz na formulář, kde by rád zpětnou vazbu na mě, jestli odvádím dobrou práci: https://forms.gle/1dFq84Ng39vdkxVQ7\n"
"Moc ti děkuji! A díky, že mě používáš! :)")


async def setup(bot):
await bot.add_cog(PollCreate(bot))
76 changes: 76 additions & 0 deletions cogs/sync_command.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
from typing import Literal, Optional, TYPE_CHECKING

import discord
from discord.ext import commands
from discord.ext.commands import Greedy, Context

if TYPE_CHECKING:
from src.jachym import Jachym


class SyncSlashCommands(commands.Cog):
def __init__(self, bot: "Jachym"):
self.bot = bot

@commands.command()
@commands.guild_only()
@commands.is_owner()
async def sync(
self,
ctx: Context,
guilds: Greedy[discord.Guild],
spec: Optional[Literal["-", "*", "^"]] = None) -> None:
"""
A command to sync all slash commands to servers user requires. Works like this:
!sync
global sync - syncs all slash commands with all guilds
!sync -
sync current guild
!sync *
copies all global app commands to current guild and syncs
!sync ^
clears all commands from the current guild target and syncs (removes guild commands)
!sync id_1 id_2
syncs guilds with id 1 and 2
Args:
ctx: commands.Context
guilds: Greedy[discord.Object]
spec: Optional[Literal]
Returns: Synced slash command
"""

if not guilds:
if spec == "-":
synced = await self.bot.tree.sync(guild=ctx.guild)
elif spec == "*":
self.bot.tree.copy_global_to(guild=ctx.guild)
synced = await self.bot.tree.sync(guild=ctx.guild)
elif spec == "^":
self.bot.tree.clear_commands(guild=ctx.guild)
await self.bot.tree.sync(guild=ctx.guild)
synced = []
else:
synced = await self.bot.tree.sync()

await ctx.send(
f"Synced {len(synced)} commands {'globally' if spec is None else 'to the current guild.'}"
)
return

ret = 0
for guild in guilds:
try:
await self.bot.tree.sync(guild=guild)
except discord.HTTPException:
pass
else:
ret += 1

await ctx.send(f"Synced the tree to {ret}/{len(guilds)}.")


async def setup(bot):
await bot.add_cog(SyncSlashCommands(bot))
27 changes: 17 additions & 10 deletions cogs/utility.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import datetime

from discord import Message
import discord
from discord import Message, app_commands
from discord.ext import commands

from src.ui.embeds import EmbedFromJSON
Expand All @@ -12,18 +13,24 @@ class Utility(commands.Cog):
def __init__(self, bot):
self.bot = bot

@commands.command(pass_context=True, aliases=['help'])
async def pomoc(self, ctx: commands.Context) -> Message:
@app_commands.command(
name="pomoc",
description="Pomocníček, který ti pomůže s různými věcmi.")
async def pomoc(self, interaction: discord.Interaction) -> Message:
embed = EmbedFromJSON().add_fields_from_json("help")
return await ctx.send(embed=embed)
return await interaction.response.send_message(embed=embed, ephemeral=True)

@commands.command(pass_context=True)
async def rozcestnik(self, ctx: commands.Context) -> Message:
@app_commands.command(
name="rozcestnik",
description="Všechny věci, co skaut potřebuje. Odkazy na webové stránky.")
async def rozcestnik(self, interaction: discord.Interaction) -> Message:
embed = EmbedFromJSON().add_fields_from_json("rozcestnik")
return await ctx.send(embed=embed)
return await interaction.response.send_message(embed=embed, ephemeral=True)

@commands.command(pass_context=True)
async def ping(self, ctx: commands.Context) -> Message:
@app_commands.command(
name="ping",
description="Něco trvá dlouho? Koukni se, jestli není vysoká latence")
async def ping(self, interaction: discord.Interaction) -> Message:
ping = round(self.bot.latency * 1000)
if ping < 200:
message = f'🟢 {ping} milisekund.'
Expand All @@ -32,7 +39,7 @@ async def ping(self, ctx: commands.Context) -> Message:
else:
message = f'🔴 {ping} milisekund.'

return await ctx.send(message)
return await interaction.response.send_message(message, ephemeral=True)

@commands.command(pass_context=True, aliases=["smazat"])
@commands.has_permissions(administrator=True)
Expand Down
4 changes: 3 additions & 1 deletion requirements.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
python-dotenv==0.17.1

aiomysql>=0.0.22
aiomysql>=0.0.22
pytest>=7.3.1
loguru>=0.7.0
17 changes: 10 additions & 7 deletions src/db_folder/databases.py
Original file line number Diff line number Diff line change
@@ -1,30 +1,33 @@
from abc import ABC
from typing import Optional, Union, AsyncIterator
from typing import Optional, AsyncIterator, TYPE_CHECKING

import aiomysql
import discord.errors
from discord import Message

from src.ui.poll import Poll

if TYPE_CHECKING:
from ..jachym import Jachym


class Crud(ABC):
def __init__(self, poll: aiomysql.pool.Pool):
self.poll = poll

async def commit_value(self, sql: str, value: tuple):
async def commit_value(self, sql: str, value: tuple) -> None:
async with self.poll.acquire() as conn:
cursor = await conn.cursor()
await cursor.execute(sql, value)
await conn.commit()

async def commit_many_values(self, sql: str, values: list[tuple]):
async def commit_many_values(self, sql: str, values: list[tuple]) -> None:
async with self.poll.acquire() as conn:
cursor = await conn.cursor()
await cursor.executemany(sql, values)
await conn.commit()

async def fetch_all_values(self, sql: str, value: Optional[tuple] = None):
async def fetch_all_values(self, sql: str, value: Optional[tuple] = None) -> list[tuple]:
async with self.poll.acquire() as conn:
cursor = await conn.cursor()
await cursor.execute(sql, value)
Expand All @@ -37,7 +40,7 @@ class PollDatabase(Crud):
def __init__(self, database_poll: aiomysql.pool.Pool):
super().__init__(database_poll)

async def add(self, discord_poll: Poll):
async def add(self, discord_poll: Poll) -> None:
sql = "INSERT INTO `Poll`(message_id, channel_id, question, date_created_at, creator_user) " \
"VALUES (%s, %s, %s, %s, %s)"
values = (
Expand All @@ -50,7 +53,7 @@ async def add(self, discord_poll: Poll):

await self.commit_value(sql, values)

async def remove(self, message_id: int):
async def remove(self, message_id: int) -> None:
sql = "DELETE FROM `Poll` WHERE message_id = %s"
value = (message_id,)

Expand All @@ -70,7 +73,7 @@ async def fetch_all_answers(self, message_id) -> tuple[str, ...]:

return answers

async def fetch_all_polls(self, bot) -> AsyncIterator[Union[Poll, Message]]:
async def fetch_all_polls(self, bot: "Jachym") -> AsyncIterator[Poll | Message]:
sql = "SELECT * FROM `Poll`"
polls = await self.fetch_all_values(sql)

Expand Down
9 changes: 5 additions & 4 deletions src/helpers.py
Original file line number Diff line number Diff line change
@@ -1,16 +1,17 @@
import time
from functools import wraps

from loguru import logger

def timeit(func):

def timeit(func: callable):
@wraps(func)
async def async_wrapper(*args, **kwargs):
print(f"{func.__name__} starting...")
logger.info(f"{func.__name__} starting...")
start = time.time()
result = await func(*args, **kwargs)
duration = time.time() - start
print(f'{func.__name__} took {duration:.2f} seconds')

logger.info(f'{func.__name__} took {duration:.2f} seconds')
return result

return async_wrapper
Loading

0 comments on commit a4fb157

Please sign in to comment.