feat(commands|Polls>propose): feat poll proposition + acceptation

This commit is contained in:
Romain J 2021-01-22 10:22:39 +01:00
parent 37bbf0368e
commit 1fb3e035bd
13 changed files with 294 additions and 116 deletions

View file

@ -16,6 +16,9 @@ update:
update_soft: update_soft:
$(VENV)/bin/pip install --upgrade . $(VENV)/bin/pip install --upgrade .
dev: reformat update_soft
tuxbot dev
# Blackify code # Blackify code
reformat: reformat:
$(PYTHON) -m black `git ls-files "*.py"` --line-length=79 && $(PYTHON) -m pylint tuxbot $(PYTHON) -m black `git ls-files "*.py"` --line-length=79 && $(PYTHON) -m pylint tuxbot

View file

@ -8,7 +8,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: Tuxbot-bot\n" "Project-Id-Version: Tuxbot-bot\n"
"Report-Msgid-Bugs-To: rick@gnous.eu\n" "Report-Msgid-Bugs-To: rick@gnous.eu\n"
"POT-Creation-Date: 2021-01-20 17:24+0100\n" "POT-Creation-Date: 2021-01-22 10:16+0100\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n" "Language-Team: LANGUAGE <LL@li.org>\n"

View file

@ -8,7 +8,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: Tuxbot-bot\n" "Project-Id-Version: Tuxbot-bot\n"
"Report-Msgid-Bugs-To: rick@gnous.eu\n" "Report-Msgid-Bugs-To: rick@gnous.eu\n"
"POT-Creation-Date: 2021-01-20 17:24+0100\n" "POT-Creation-Date: 2021-01-22 10:16+0100\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n" "Language-Team: LANGUAGE <LL@li.org>\n"
@ -36,14 +36,14 @@ msgstr ""
msgid "The alias `{alias}` for the command `{command}` was successfully created" msgid "The alias `{alias}` for the command `{command}` was successfully created"
msgstr "" msgstr ""
#: tuxbot/cogs/Custom/functions/converters.py:14 #: tuxbot/cogs/Custom/functions/converters.py:15
msgid "Alias must be like `[command] | [alias]`" msgid "Alias must be like `[command] | [alias]`"
msgstr "" msgstr ""
#: tuxbot/cogs/Custom/functions/converters.py:23 #: tuxbot/cogs/Custom/functions/converters.py:24
msgid "Unknown command" msgid "Unknown command"
msgstr "" msgstr ""
#: tuxbot/cogs/Custom/functions/converters.py:26 #: tuxbot/cogs/Custom/functions/converters.py:27
msgid "Command already exists" msgid "Command already exists"
msgstr "" msgstr ""

View file

@ -42,12 +42,12 @@ class PollConverter(commands.Converter):
poll = await Poll.get_or_none(id=int(poll_id)) poll = await Poll.get_or_none(id=int(poll_id))
if poll.channel_id != ctx.channel.id:
raise InvalidChannel(_("Please provide a message in this channel"))
if poll is None: if poll is None:
raise BadPoll(_("Unable to find this poll")) raise BadPoll(_("Unable to find this poll"))
if poll.channel_id != ctx.channel.id:
raise InvalidChannel(_("Please provide a message in this channel"))
return poll return poll

View file

@ -0,0 +1,133 @@
import json
from os.path import dirname
import discord
from tuxbot.cogs import Polls
from tuxbot.core.i18n import Translator
from tuxbot.core.utils.functions.utils import upper_first
from . import emotes as utils_emotes
from .exceptions import InvalidChannel, BadPoll, TooLongProposition
from ..models import Response, Poll, Suggest
_ = Translator("Polls", dirname(__file__))
async def _poll_reaction_add(
self: Polls, pld: discord.RawReactionActionEvent, poll: Poll
):
if poll.is_anonymous:
try:
await self.remove_reaction(pld)
except discord.errors.Forbidden:
pass
choice = utils_emotes.get_index(pld.emoji.name)
response = await Response.get_or_none(
user_id=pld.user_id, choice=choice, poll__id=poll.id
)
if response is not None:
await poll.choices.remove(response)
await response.delete()
else:
res = await Response.create(
user_id=pld.user_id, poll=poll, choice=choice
)
await poll.choices.add(res)
await self.update_poll(poll)
async def _suggest_reaction_add(
self: Polls, pld: discord.RawReactionActionEvent, suggest: Suggest
):
poll = await suggest.poll
if (
poll.author_id == pld.user_id
or (await self.bot.is_owner(discord.Object(pld.user_id)))
or (
(channel := await self.bot.fetch_channel(pld.channel_id))
.permissions_for(await channel.guild.fetch_member(pld.user_id))
.administrator
)
):
if pld.emoji.name == utils_emotes.check[0]:
poll.available_choices += 1
emote = utils_emotes.emotes[poll.available_choices - 1]
content = (
json.loads(poll.content)
if isinstance(poll.content, str)
else poll.content
)
content["fields"].append(
{
"name": f"__{emote} - {upper_first(suggest.proposition)}__",
"value": "**0** vote",
}
)
await poll.save()
channel: discord.TextChannel = await self.bot.fetch_channel(
poll.channel_id
)
message = await channel.fetch_message(poll.message_id)
await message.add_reaction(emote)
await self.update_poll(poll)
channel: discord.TextChannel = await self.bot.fetch_channel(
suggest.channel_id
)
message = await channel.fetch_message(suggest.message_id)
await message.delete()
await suggest.delete()
else:
try:
await self.remove_reaction(pld)
except discord.errors.Forbidden:
pass
async def cog_command_error(self: Polls, ctx, error):
if isinstance(error, (InvalidChannel, BadPoll, TooLongProposition)):
await ctx.send(_(str(error), ctx, self.bot.config))
async def on_raw_reaction_add(
self: Polls, pld: discord.RawReactionActionEvent
):
poll = await self.get_poll(pld)
if poll:
await _poll_reaction_add(self, pld, poll)
elif suggest := await self.get_suggest(pld):
await _suggest_reaction_add(self, pld, suggest)
async def on_raw_reaction_remove(self, pld: discord.RawReactionActionEvent):
poll = await self.get_poll(pld)
if poll:
choice = utils_emotes.get_index(pld.emoji.name)
response = await Response.get_or_none(
user_id=pld.user_id, choice=choice, poll__id=poll.id
)
if response is not None:
await poll.choices.remove(response)
await response.delete()
await self.update_poll(poll)

View file

@ -18,32 +18,40 @@ msgstr ""
"Content-Transfer-Encoding: 8bit\n" "Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n"
#: tuxbot/cogs/Polls/polls.py:92 #: tuxbot/cogs/Polls/polls.py:55 tuxbot/cogs/Polls/polls.py:176
msgid "**Preparation**" msgid "**Preparation**"
msgstr "" msgstr ""
#: tuxbot/cogs/Polls/polls.py:221 #: tuxbot/cogs/Polls/polls.py:204
#, python-brace-format #, python-brace-format
msgid "Proposed addition for survey #{id}" msgid "Proposed addition for poll #{id}"
msgstr "" msgstr ""
#: tuxbot/cogs/Polls/polls.py:226 #: tuxbot/cogs/Polls/polls.py:209
msgid "Poll"
msgstr ""
#: tuxbot/cogs/Polls/polls.py:211
msgid "here"
msgstr ""
#: tuxbot/cogs/Polls/polls.py:215
#, python-brace-format #, python-brace-format
msgid "Requested by {author}" msgid "Requested by {author}"
msgstr "" msgstr ""
#: tuxbot/cogs/Polls/functions/converters.py:20 #: tuxbot/cogs/Polls/functions/converters.py:21
#: tuxbot/cogs/Polls/functions/converters.py:45 #: tuxbot/cogs/Polls/functions/converters.py:49
msgid "Please provide a message in this channel" msgid "Please provide a message in this channel"
msgstr "" msgstr ""
#: tuxbot/cogs/Polls/functions/converters.py:29 #: tuxbot/cogs/Polls/functions/converters.py:30
#: tuxbot/cogs/Polls/functions/converters.py:35 #: tuxbot/cogs/Polls/functions/converters.py:36
#: tuxbot/cogs/Polls/functions/converters.py:40 #: tuxbot/cogs/Polls/functions/converters.py:41
#: tuxbot/cogs/Polls/functions/converters.py:48 #: tuxbot/cogs/Polls/functions/converters.py:46
msgid "Unable to find this poll" msgid "Unable to find this poll"
msgstr "" msgstr ""
#: tuxbot/cogs/Polls/functions/converters.py:57 #: tuxbot/cogs/Polls/functions/converters.py:58
msgid "Your proposal must be smaller than 30" msgid "Your proposal must be smaller than 30"
msgstr "" msgstr ""

View file

@ -18,32 +18,41 @@ msgstr ""
"Content-Transfer-Encoding: 8bit\n" "Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n > 1);\n" "Plural-Forms: nplurals=2; plural=(n > 1);\n"
#: tuxbot/cogs/Polls/polls.py:92 #: tuxbot/cogs/Polls/polls.py:55 tuxbot/cogs/Polls/polls.py:176
msgid "**Preparation**" msgid "**Preparation**"
msgstr "**Préparation**" msgstr "**Préparation**"
#: tuxbot/cogs/Polls/polls.py:221 #: tuxbot/cogs/Polls/polls.py:204
#, python-brace-format #, python-brace-format
msgid "Proposed addition for poll #{id}" msgid "Proposed addition for poll #{id}"
msgstr "Proposition d'ajout pour le sondage #{id}" msgstr "Proposition d'ajout pour le sondage #{id}"
#: tuxbot/cogs/Polls/polls.py:226 #: tuxbot/cogs/Polls/polls.py:209
msgid "Poll"
msgstr "Sondage"
#: tuxbot/cogs/Polls/polls.py:211
msgid "here"
msgstr "ici"
#: tuxbot/cogs/Polls/polls.py:215
#, python-brace-format #, python-brace-format
msgid "Requested by {author}" msgid "Requested by {author}"
msgstr "Demandé par {author}" msgstr "Demandée par {author}"
#: tuxbot/cogs/Polls/functions/converters.py:20 #: tuxbot/cogs/Polls/functions/converters.py:21
#: tuxbot/cogs/Polls/functions/converters.py:45 #: tuxbot/cogs/Polls/functions/converters.py:49
msgid "Please provide a message in this channel" msgid "Please provide a message in this channel"
msgstr "Veuillez fournir un message dans ce salon" msgstr "Veuillez fournir un message dans ce salon"
#: tuxbot/cogs/Polls/functions/converters.py:29 #: tuxbot/cogs/Polls/functions/converters.py:30
#: tuxbot/cogs/Polls/functions/converters.py:35 #: tuxbot/cogs/Polls/functions/converters.py:36
#: tuxbot/cogs/Polls/functions/converters.py:40 #: tuxbot/cogs/Polls/functions/converters.py:41
#: tuxbot/cogs/Polls/functions/converters.py:48 #: tuxbot/cogs/Polls/functions/converters.py:46
msgid "Unable to find this poll" msgid "Unable to find this poll"
msgstr "Impossible de trouver ce sondage" msgstr "Impossible de trouver ce sondage"
#: tuxbot/cogs/Polls/functions/converters.py:57 #: tuxbot/cogs/Polls/functions/converters.py:58
msgid "Your proposal must be smaller than 30" msgid "Your proposal must be smaller than 30"
msgstr "Votre proposition doit être inférieure à 30" msgstr "Votre proposition doit être inférieure à 30"

View file

@ -8,7 +8,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: Tuxbot-bot\n" "Project-Id-Version: Tuxbot-bot\n"
"Report-Msgid-Bugs-To: rick@gnous.eu\n" "Report-Msgid-Bugs-To: rick@gnous.eu\n"
"POT-Creation-Date: 2021-01-20 17:24+0100\n" "POT-Creation-Date: 2021-01-22 10:16+0100\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n" "Language-Team: LANGUAGE <LL@li.org>\n"
@ -17,32 +17,40 @@ msgstr ""
"Content-Type: text/plain; charset=CHARSET\n" "Content-Type: text/plain; charset=CHARSET\n"
"Content-Transfer-Encoding: 8bit\n" "Content-Transfer-Encoding: 8bit\n"
#: tuxbot/cogs/Polls/polls.py:92 #: tuxbot/cogs/Polls/polls.py:55 tuxbot/cogs/Polls/polls.py:176
msgid "**Preparation**" msgid "**Preparation**"
msgstr "" msgstr ""
#: tuxbot/cogs/Polls/polls.py:221 #: tuxbot/cogs/Polls/polls.py:204
#, python-brace-format #, python-brace-format
msgid "Proposed addition for poll #{id}" msgid "Proposed addition for poll #{id}"
msgstr "" msgstr ""
#: tuxbot/cogs/Polls/polls.py:226 #: tuxbot/cogs/Polls/polls.py:209
msgid "Poll"
msgstr ""
#: tuxbot/cogs/Polls/polls.py:211
msgid "here"
msgstr ""
#: tuxbot/cogs/Polls/polls.py:215
#, python-brace-format #, python-brace-format
msgid "Requested by {author}" msgid "Requested by {author}"
msgstr "" msgstr ""
#: tuxbot/cogs/Polls/functions/converters.py:20 #: tuxbot/cogs/Polls/functions/converters.py:21
#: tuxbot/cogs/Polls/functions/converters.py:45 #: tuxbot/cogs/Polls/functions/converters.py:49
msgid "Please provide a message in this channel" msgid "Please provide a message in this channel"
msgstr "" msgstr ""
#: tuxbot/cogs/Polls/functions/converters.py:29 #: tuxbot/cogs/Polls/functions/converters.py:30
#: tuxbot/cogs/Polls/functions/converters.py:35 #: tuxbot/cogs/Polls/functions/converters.py:36
#: tuxbot/cogs/Polls/functions/converters.py:40 #: tuxbot/cogs/Polls/functions/converters.py:41
#: tuxbot/cogs/Polls/functions/converters.py:48 #: tuxbot/cogs/Polls/functions/converters.py:46
msgid "Unable to find this poll" msgid "Unable to find this poll"
msgstr "" msgstr ""
#: tuxbot/cogs/Polls/functions/converters.py:57 #: tuxbot/cogs/Polls/functions/converters.py:58
msgid "Your proposal must be smaller than 30" msgid "Your proposal must be smaller than 30"
msgstr "" msgstr ""

View file

@ -5,7 +5,9 @@ from tortoise import fields
class Suggest(tortoise.Model): class Suggest(tortoise.Model):
suggest_id = fields.BigIntField(pk=True) suggest_id = fields.BigIntField(pk=True)
poll = fields.ForeignKeyField("models.Poll") poll = fields.ForeignKeyField("models.Poll")
user_id = fields.BigIntField() channel_id = fields.BigIntField()
message_id = fields.BigIntField()
author_id = fields.BigIntField()
proposition = fields.CharField(max_length=30) proposition = fields.CharField(max_length=30)
@ -15,7 +17,7 @@ class Suggest(tortoise.Model):
def __str__(self): def __str__(self):
return ( return (
f"<suggest_id poll={self.poll} " f"<suggest_id poll={self.poll} "
f"user_id={self.user_id} " f"author_id={self.author_id} "
f"proposition={self.proposition}>" f"proposition={self.proposition}>"
) )

View file

@ -7,14 +7,14 @@ from discord.ext import commands
from yarl import URL from yarl import URL
from tuxbot.core.utils.functions.extra import ContextPlus, group_extra from tuxbot.core.utils.functions.extra import ContextPlus, group_extra
from tuxbot.core.utils.functions.utils import upper_first
from tuxbot.core.bot import Tux from tuxbot.core.bot import Tux
from tuxbot.core.i18n import ( from tuxbot.core.i18n import (
Translator, Translator,
) )
from .functions import emotes as utils_emotes from .functions import emotes as utils_emotes, listeners
from .functions.converters import NewPropositionConvertor, PollConverter from .functions.converters import NewPropositionConvertor, PollConverter
from .functions.exceptions import InvalidChannel, BadPoll, TooLongProposition from .models import Poll
from .models import Poll, Response
from .models.suggests import Suggest from .models.suggests import Suggest
log = logging.getLogger("tuxbot.cogs.Polls") log = logging.getLogger("tuxbot.cogs.Polls")
@ -26,54 +26,17 @@ class Polls(commands.Cog, name="Polls"):
self.bot = bot self.bot = bot
async def cog_command_error(self, ctx, error): async def cog_command_error(self, ctx, error):
if isinstance(error, (InvalidChannel, BadPoll, TooLongProposition)): await listeners.cog_command_error(self, ctx, error)
await ctx.send(_(str(error), ctx, self.bot.config))
@commands.Cog.listener() @commands.Cog.listener()
async def on_raw_reaction_add(self, pld: discord.RawReactionActionEvent): async def on_raw_reaction_add(self, pld: discord.RawReactionActionEvent):
poll = await self.get_poll(pld) await listeners.on_raw_reaction_add(self, pld)
if poll:
if poll.is_anonymous:
try:
await self.remove_reaction(pld)
except discord.errors.Forbidden:
pass
choice = utils_emotes.get_index(pld.emoji.name)
response = await Response.get_or_none(
user_id=pld.user_id, choice=choice, poll__id=poll.id
)
if response is not None:
await poll.choices.remove(response)
await response.delete()
else:
res = await Response.create(
user_id=pld.user_id, poll=poll, choice=choice
)
await poll.choices.add(res)
await self.update_poll(poll)
@commands.Cog.listener() @commands.Cog.listener()
async def on_raw_reaction_remove( async def on_raw_reaction_remove(
self, pld: discord.RawReactionActionEvent self, pld: discord.RawReactionActionEvent
): ):
poll = await self.get_poll(pld) await listeners.on_raw_reaction_remove(self, pld)
if poll:
choice = utils_emotes.get_index(pld.emoji.name)
response = await Response.get_or_none(
user_id=pld.user_id, choice=choice, poll__id=poll.id
)
if response is not None:
await poll.choices.remove(response)
await response.delete()
await self.update_poll(poll)
# ========================================================================= # =========================================================================
# ========================================================================= # =========================================================================
@ -113,7 +76,7 @@ class Polls(commands.Cog, name="Polls"):
) )
for i, answer in enumerate(answers): for i, answer in enumerate(answers):
e.add_field( e.add_field(
name=f"__{emotes[i]} - {answer.capitalize()}__", name=f"__{emotes[i]} - {upper_first(answer)}__",
value="**0** vote", value="**0** vote",
) )
e.set_footer(text=f"ID: #{poll_row.id}") e.set_footer(text=f"ID: #{poll_row.id}")
@ -205,21 +168,49 @@ class Polls(commands.Cog, name="Polls"):
await message.remove_reaction(pld.emoji.name, user) await message.remove_reaction(pld.emoji.name, user)
async def propose_new( async def created_suggest(
self, ctx: ContextPlus, poll: PollConverter, new: str self, ctx: ContextPlus, poll: PollConverter, new: str
): ):
await Suggest.create(poll=poll, user_id=ctx.author.id, proposition=new) stmt = await ctx.send(
_(
"**Preparation**",
ctx,
self.bot.config,
)
)
suggest_row = await Suggest()
suggest_row.channel_id = ctx.channel.id
suggest_row.message_id = stmt.id
suggest_row.author_id = ctx.author.id
if isinstance(poll, Poll): if isinstance(poll, Poll):
# pylint: disable=pointless-string-statement # pylint: disable=pointless-string-statement
"""Just to change type for PyCharm""" """Just to change type for PyCharm"""
suggest_row.poll = poll
suggest_row.proposition = new
await suggest_row.save()
poll_channel: discord.TextChannel = await self.bot.fetch_channel(
poll.channel_id
)
poll_message = await poll_channel.fetch_message(poll.message_id)
e = discord.Embed( e = discord.Embed(
title=_( title=_(
"Proposed addition for poll #{id}", ctx, self.bot.config "Proposed addition for poll #{id}", ctx, self.bot.config
).format(id=poll.id), ).format(id=poll.id),
description=new, description=new,
) )
e.add_field(
name=_("Poll", ctx, self.bot.config),
value="[{}]({})".format(
_("here", ctx, self.bot.config), poll_message.jump_url
),
)
e.set_footer( e.set_footer(
text=_("Requested by {author}", ctx, self.bot.config).format( text=_("Requested by {author}", ctx, self.bot.config).format(
author=ctx.author.name author=ctx.author.name
@ -227,10 +218,21 @@ class Polls(commands.Cog, name="Polls"):
icon_url=ctx.author.avatar_url_as(format="png"), icon_url=ctx.author.avatar_url_as(format="png"),
) )
message = await ctx.send(embed=e) await stmt.edit(content="", embed=e)
for emote in utils_emotes.check: for emote in utils_emotes.check:
await message.add_reaction(emote) await stmt.add_reaction(emote)
async def get_suggest(
self, pld: discord.RawReactionActionEvent
) -> Union[bool, Suggest]:
if pld.user_id != self.bot.user.id:
suggest = await Suggest.get_or_none(message_id=pld.message_id)
if suggest is not None and pld.emoji.name in utils_emotes.check:
return suggest
return False
# ========================================================================= # =========================================================================
# ========================================================================= # =========================================================================
@ -242,13 +244,13 @@ class Polls(commands.Cog, name="Polls"):
@_poll.command(name="create", aliases=["new", "nouveau"]) @_poll.command(name="create", aliases=["new", "nouveau"])
async def _poll_create(self, ctx: ContextPlus, *, poll: str): async def _poll_create(self, ctx: ContextPlus, *, poll: str):
args: list = poll.lower().split() args: list = poll.split()
is_anonymous = False is_anonymous = False
if "--anonymous" in args: if "--anonymous" in map(str.lower, args):
is_anonymous = True is_anonymous = True
args.remove("--anonymous") args.remove("--anonymous")
elif "--anonyme" in args: elif "--anonyme" in map(str.lower, args):
is_anonymous = True is_anonymous = True
args.remove("--anonyme") args.remove("--anonyme")
@ -257,14 +259,14 @@ class Polls(commands.Cog, name="Polls"):
delimiters = [i for i, val in enumerate(args) if val == "|"] delimiters = [i for i, val in enumerate(args) if val == "|"]
question = " ".join(args[: delimiters[0]]).capitalize() question = upper_first(" ".join(args[: delimiters[0]]))
answers = [] answers = []
for i in range(len(delimiters) - 1): for i in range(len(delimiters) - 1):
start = delimiters[i] + 1 start = delimiters[i] + 1
end = delimiters[i + 1] end = delimiters[i + 1]
answers.append(" ".join(args[start:end]).capitalize()) answers.append(upper_first(" ".join(args[start:end])))
await self.create_poll(ctx, question, answers, anonymous=is_anonymous) await self.create_poll(ctx, question, answers, anonymous=is_anonymous)
@ -276,4 +278,4 @@ class Polls(commands.Cog, name="Polls"):
*, *,
new: NewPropositionConvertor, new: NewPropositionConvertor,
): ):
await self.propose_new(ctx, poll, str(new)) await self.created_suggest(ctx, poll, str(new))

View file

@ -8,7 +8,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: Tuxbot-bot\n" "Project-Id-Version: Tuxbot-bot\n"
"Report-Msgid-Bugs-To: rick@gnous.eu\n" "Report-Msgid-Bugs-To: rick@gnous.eu\n"
"POT-Creation-Date: 2021-01-20 17:24+0100\n" "POT-Creation-Date: 2021-01-22 10:16+0100\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n" "Language-Team: LANGUAGE <LL@li.org>\n"
@ -55,62 +55,62 @@ msgstr ""
msgid "class" msgid "class"
msgstr "" msgstr ""
#: tuxbot/cogs/Utils/utils.py:100 #: tuxbot/cogs/Utils/utils.py:101
msgid "functions" msgid "functions"
msgstr "" msgstr ""
#: tuxbot/cogs/Utils/utils.py:102 #: tuxbot/cogs/Utils/utils.py:104
msgid "coroutines" msgid "coroutines"
msgstr "" msgstr ""
#: tuxbot/cogs/Utils/utils.py:104 #: tuxbot/cogs/Utils/utils.py:107
msgid "comments" msgid "comments"
msgstr "" msgstr ""
#: tuxbot/cogs/Utils/utils.py:109 #: tuxbot/cogs/Utils/utils.py:113
msgid "__Latest changes__" msgid "__Latest changes__"
msgstr "" msgstr ""
#: tuxbot/cogs/Utils/utils.py:115 #: tuxbot/cogs/Utils/utils.py:119
msgid "__:link: Links__" msgid "__:link: Links__"
msgstr "" msgstr ""
#: tuxbot/cogs/Utils/utils.py:120 #: tuxbot/cogs/Utils/utils.py:124
msgid "| [Invite]" msgid "| [Invite]"
msgstr "" msgstr ""
#: tuxbot/cogs/Utils/utils.py:135 #: tuxbot/cogs/Utils/utils.py:139
msgid "Contributors" msgid "Contributors"
msgstr "" msgstr ""
#: tuxbot/cogs/Utils/utils.py:191 #: tuxbot/cogs/Utils/utils.py:195
msgid "Invite" msgid "Invite"
msgstr "" msgstr ""
#: tuxbot/cogs/Utils/utils.py:195 #: tuxbot/cogs/Utils/utils.py:199
msgid "Minimal" msgid "Minimal"
msgstr "" msgstr ""
#: tuxbot/cogs/Utils/utils.py:197 #: tuxbot/cogs/Utils/utils.py:201
msgid "The minimum permissions include the strict requirements for the proper functioning of all basics commands.\n" msgid "The minimum permissions include the strict requirements for the proper functioning of all basics commands.\n"
msgstr "" msgstr ""
#: tuxbot/cogs/Utils/utils.py:202 tuxbot/cogs/Utils/utils.py:214 #: tuxbot/cogs/Utils/utils.py:206 tuxbot/cogs/Utils/utils.py:218
msgid "[Add!]" msgid "[Add!]"
msgstr "" msgstr ""
#: tuxbot/cogs/Utils/utils.py:207 #: tuxbot/cogs/Utils/utils.py:211
msgid "Admin" msgid "Admin"
msgstr "" msgstr ""
#: tuxbot/cogs/Utils/utils.py:209 #: tuxbot/cogs/Utils/utils.py:213
msgid "All minimal permissions + extra permissions for admin commands such as kick and ban\n" msgid "All minimal permissions + extra permissions for admin commands such as kick and ban\n"
msgstr "" msgstr ""
#: tuxbot/cogs/Utils/utils.py:237 #: tuxbot/cogs/Utils/utils.py:241
msgid "Unable to find `{}`" msgid "Unable to find `{}`"
msgstr "" msgstr ""
#: tuxbot/cogs/Utils/utils.py:245 #: tuxbot/cogs/Utils/utils.py:249
msgid "Unable to fetch lines for `{}`" msgid "Unable to fetch lines for `{}`"
msgstr "" msgstr ""

View file

@ -36,7 +36,7 @@ def is_mod():
def is_admin(): def is_admin():
"""Is the user Admin ?""" """Is the user Admin ? as @check"""
async def pred(ctx): async def pred(ctx):
if await ctx.bot.is_owner(ctx.author): if await ctx.bot.is_owner(ctx.author):
@ -49,6 +49,17 @@ def is_admin():
return commands.check(pred) return commands.check(pred)
async def is_user_admin(ctx):
"""Is the user Admin ? as function"""
if await ctx.bot.is_owner(ctx.author):
return True
permissions: discord.Permissions = ctx.channel.permissions_for(ctx.author)
return permissions.administrator
async def check_permissions(ctx: ContextPlus, **perms: Dict[str, bool]): async def check_permissions(ctx: ContextPlus, **perms: Dict[str, bool]):
"""Does a user have any perms ? """Does a user have any perms ?

View file

@ -0,0 +1,2 @@
def upper_first(string: str) -> str:
return "".join(string[0].upper() + string[1:])