Skip to content

Commit

Permalink
Merge pull request #35 from LiBa001/v0.2.0
Browse files Browse the repository at this point in the history
V0.2.0
  • Loading branch information
LiBa001 authored May 29, 2021
2 parents 13fd04e + 87fb771 commit 313404e
Show file tree
Hide file tree
Showing 5 changed files with 174 additions and 89 deletions.
2 changes: 1 addition & 1 deletion disputils/__init__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from .pagination import EmbedPaginator, BotEmbedPaginator
from .pagination import EmbedPaginator, BotEmbedPaginator, ControlEmojis
from .confirmation import Confirmation, BotConfirmation
from .multiple_choice import MultipleChoice, BotMultipleChoice
from . import abc
27 changes: 24 additions & 3 deletions disputils/abc.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
from abc import ABC
from discord import Message, Embed
from discord import Message, Embed, TextChannel, errors
from typing import Optional


Expand All @@ -11,6 +11,23 @@ def __init__(self, *args, **kwargs):
self.message: Optional[Message] = None
self.color: hex = kwargs.get("color") or kwargs.get("colour") or 0x000000

async def _publish(self, channel: Optional[TextChannel], **kwargs) -> TextChannel:
if channel is None and self.message is None:
raise TypeError(
"Missing argument. You need to specify a target channel or message."
)

if channel is None:
try:
await self.message.edit(**kwargs)
except errors.NotFound:
self.message = None

if self.message is None:
self.message = await channel.send(**kwargs)

return self.message.channel

async def quit(self, text: str = None):
"""
Quit the dialog.
Expand All @@ -23,9 +40,13 @@ async def quit(self, text: str = None):

if text is None:
await self.message.delete()
self.message = None
else:
await self.message.edit(content=text, embed=None)
await self.message.clear_reactions()
await self.display(text)
try:
await self.message.clear_reactions()
except errors.Forbidden:
pass

async def update(self, text: str, color: hex = None, hide_author: bool = False):
"""
Expand Down
37 changes: 18 additions & 19 deletions disputils/confirmation.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ async def confirm(
user: discord.User,
channel: discord.TextChannel = None,
hide_author: bool = False,
timeout: int = 20,
) -> bool or None:
"""
Run the confirmation.
Expand All @@ -52,6 +53,10 @@ async def confirm(
:param hide_author: Whether or not the ``user`` should be set as embed author.
:type hide_author: bool, optional
:type timeout: int
:param timeout:
Seconds to wait until stopping to listen for user interaction.
:return: True when it's been confirmed, otherwise False. Will return None when a
timeout occurs.
:rtype: :class:`bool`, optional
Expand All @@ -63,39 +68,32 @@ async def confirm(

self._embed = emb

if channel is None and self.message is not None:
channel = self.message.channel
elif channel is None:
raise TypeError("Missing argument. You need to specify a target channel.")

msg = await channel.send(embed=emb)
self.message = msg
await self._publish(channel, embed=emb)
msg = self.message

for emoji in self.emojis:
await msg.add_reaction(emoji)

try:
reaction, user = await self._client.wait_for(
"reaction_add",
check=lambda r, u: (r.message.id == msg.id)
and (u.id == user.id)
and (r.emoji in self.emojis),
timeout=20,
reaction = await self._client.wait_for(
"raw_reaction_add",
check=lambda r: (r.message_id == msg.id)
and (r.user_id == user.id)
and (str(r.emoji) in self.emojis),
timeout=timeout,
)
except asyncio.TimeoutError:
self._confirmed = None
return
else:
self._confirmed = self.emojis[str(reaction.emoji)]
return self._confirmed
finally:
try:
await msg.clear_reactions()
except discord.Forbidden:
pass

confirmed = self.emojis[reaction.emoji]

self._confirmed = confirmed
return confirmed


class BotConfirmation(Confirmation):
def __init__(
Expand All @@ -114,6 +112,7 @@ async def confirm(
user: discord.User = None,
channel: discord.TextChannel = None,
hide_author: bool = False,
timeout: int = 20,
) -> bool or None:

if user is None:
Expand All @@ -122,4 +121,4 @@ async def confirm(
if self.message is None and channel is None:
channel = self._ctx.channel

return await super().confirm(text, user, channel, hide_author=hide_author)
return await super().confirm(text, user, channel, hide_author, timeout)
42 changes: 22 additions & 20 deletions disputils/multiple_choice.py
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,9 @@ async def run(
- message :class:`discord.Message`
- timeout :class:`int` (seconds, default: ``60``),
- closable :class:`bool` (default: ``True``)
- text :class:`str`: Text to appear in the message.
- timeout_msg :class:`str`: Text to appear when dialog times out.
- quit_msg :class:`str`: Text to appear when user quits the dialog.
:return: selected option and used :class:`discord.Message`
:rtype: tuple[:class:`str`, :class:`discord.Message`]
Expand All @@ -134,52 +137,51 @@ async def run(
timeout = kwargs.get("timeout", 60)
closable: bool = kwargs.get("closable", True)

config_embed = self.embed
publish_kwargs = {"embed": self.embed}
if "text" in kwargs:
publish_kwargs["content"] = kwargs["text"]

if channel is not None:
self.message = await channel.send(embed=config_embed)
elif self.message is not None:
await self.message.clear_reactions()
await self.message.edit(content=self.message.content, embed=config_embed)
else:
raise TypeError(
"Missing argument. "
+ "You need to specify either 'channel' or 'message' as a target."
)
await self._publish(channel, **publish_kwargs)

for emoji in self._emojis:
await self.message.add_reaction(emoji)

if closable:
await self.message.add_reaction(self.close_emoji)

def check(r, u):
res = (r.message.id == self.message.id) and u.id != self._client.user.id
def check(r: discord.RawReactionActionEvent):
res = (
r.message_id == self.message.id
) and r.user_id != self._client.user.id

if users is not None:
res = res and (u.id in [_u.id for _u in users])
res = res and (r.user_id in [_u.id for _u in users])

is_valid_emoji = r.emoji in self._emojis
is_valid_emoji = str(r.emoji) in self._emojis
if closable:
is_valid_emoji = is_valid_emoji or r.emoji == self.close_emoji
is_valid_emoji = is_valid_emoji or str(r.emoji) == self.close_emoji

res = res and is_valid_emoji

return res

try:
reaction, user = await self._client.wait_for(
"reaction_add", check=check, timeout=timeout
reaction = await self._client.wait_for(
"raw_reaction_add", check=check, timeout=timeout
)
except asyncio.TimeoutError:
self._choice = None
if "timeout_msg" in kwargs:
await self.quit(kwargs["timeout_msg"])
return None, self.message

if reaction.emoji == self.close_emoji:
if str(reaction.emoji) == self.close_emoji:
self._choice = None
if "quit_msg" in kwargs:
await self.quit(kwargs["quit_msg"])
return None, self.message

index = self._emojis.index(reaction.emoji)
index = self._emojis.index(str(reaction.emoji))
self._choice = self.options[index]

return self._choice, self.message
Expand Down
Loading

0 comments on commit 313404e

Please sign in to comment.