mirror of
https://github.com/Cog-Creators/Red-DiscordBot.git
synced 2025-11-06 03:08:55 -05:00
[Trivia] Commands for managing custom trivia lists (#3420)
* Trivia upload * Second push * Black * A bit further * Logic fix * Getting closer * Almost there * Abomination ready for review. Abomination ready for review. * Upload trivia review * Black * Fix debug * Delete a trivia * List cleaned. * Make it nicer * Pass black * Unlink file * Translation * Thanks Jack * Beautify * Black * Fix * Handling empty custom lists * Use existing fileobject. * Black * Test * Change up * Black * Changelog * Typo error * Fix up issues. * Fixes stuff. * Styling * Add reactions * Reactions * Add safe handling of reactions * Style * Fix grammar and remove obsolete code * Timeout * Fix * Requested changes * Styling * Fixes * Typehint * Remove * mistake * Constant * Style * return
This commit is contained in:
parent
eebea59fe3
commit
15e3437001
@ -1,17 +1,19 @@
|
|||||||
"""Module for Trivia cog."""
|
"""Module for Trivia cog."""
|
||||||
|
import asyncio
|
||||||
import math
|
import math
|
||||||
import pathlib
|
import pathlib
|
||||||
from collections import Counter
|
from collections import Counter
|
||||||
from typing import List
|
from typing import List
|
||||||
|
import io
|
||||||
import yaml
|
import yaml
|
||||||
import discord
|
import discord
|
||||||
|
|
||||||
from redbot.core import commands
|
from redbot.core import commands
|
||||||
from redbot.core import Config, checks
|
from redbot.core import Config, checks
|
||||||
from redbot.core.data_manager import cog_data_path
|
from redbot.core.data_manager import cog_data_path
|
||||||
from redbot.core.i18n import Translator, cog_i18n
|
from redbot.core.i18n import Translator, cog_i18n
|
||||||
from redbot.core.utils.chat_formatting import box, pagify, bold
|
from redbot.core.utils.chat_formatting import box, pagify, bold
|
||||||
|
from redbot.core.utils.predicates import MessagePredicate, ReactionPredicate
|
||||||
|
from redbot.core.utils.menus import start_adding_reactions
|
||||||
from redbot.cogs.bank import check_global_setting_admin
|
from redbot.cogs.bank import check_global_setting_admin
|
||||||
from .log import LOG
|
from .log import LOG
|
||||||
from .session import TriviaSession
|
from .session import TriviaSession
|
||||||
@ -183,6 +185,86 @@ class Trivia(commands.Cog):
|
|||||||
else:
|
else:
|
||||||
await ctx.send(_("Done. I will no longer reward the winner with a payout."))
|
await ctx.send(_("Done. I will no longer reward the winner with a payout."))
|
||||||
|
|
||||||
|
@triviaset.group(name="custom")
|
||||||
|
@commands.is_owner()
|
||||||
|
async def triviaset_custom(self, ctx: commands.Context):
|
||||||
|
"""Manage Custom Trivia lists."""
|
||||||
|
pass
|
||||||
|
|
||||||
|
@triviaset_custom.command(name="list")
|
||||||
|
async def custom_trivia_list(self, ctx: commands.Context):
|
||||||
|
"""List uploaded custom trivia."""
|
||||||
|
personal_lists = sorted([p.resolve().stem for p in cog_data_path(self).glob("*.yaml")])
|
||||||
|
no_lists_uploaded = _("No custom Trivia lists uploaded.")
|
||||||
|
|
||||||
|
if not personal_lists:
|
||||||
|
if await ctx.embed_requested():
|
||||||
|
await ctx.send(
|
||||||
|
embed=discord.Embed(
|
||||||
|
colour=await ctx.embed_colour(), description=no_lists_uploaded
|
||||||
|
)
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
await ctx.send(no_lists_uploaded)
|
||||||
|
return
|
||||||
|
|
||||||
|
if await ctx.embed_requested():
|
||||||
|
await ctx.send(
|
||||||
|
embed=discord.Embed(
|
||||||
|
title=_("Uploaded trivia lists"),
|
||||||
|
colour=await ctx.embed_colour(),
|
||||||
|
description=", ".join(sorted(personal_lists)),
|
||||||
|
)
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
msg = box(
|
||||||
|
bold(_("Uploaded trivia lists")) + "\n\n" + ", ".join(sorted(personal_lists))
|
||||||
|
)
|
||||||
|
if len(msg) > 1000:
|
||||||
|
await ctx.author.send(msg)
|
||||||
|
else:
|
||||||
|
await ctx.send(msg)
|
||||||
|
|
||||||
|
@commands.is_owner()
|
||||||
|
@triviaset_custom.command(name="upload", aliases=["add"])
|
||||||
|
async def trivia_upload(self, ctx: commands.Context):
|
||||||
|
"""Upload a trivia file."""
|
||||||
|
if not ctx.message.attachments:
|
||||||
|
await ctx.send(_("Supply a file with next message or type anything to cancel."))
|
||||||
|
try:
|
||||||
|
message = await ctx.bot.wait_for(
|
||||||
|
"message", check=MessagePredicate.same_context(ctx), timeout=30
|
||||||
|
)
|
||||||
|
except asyncio.TimeoutError:
|
||||||
|
await ctx.send(_("You took too long to upload a list."))
|
||||||
|
return
|
||||||
|
if not message.attachments:
|
||||||
|
await ctx.send(_("You have cancelled the upload process."))
|
||||||
|
return
|
||||||
|
parsedfile = message.attachments[0]
|
||||||
|
else:
|
||||||
|
parsedfile = ctx.message.attachments[0]
|
||||||
|
try:
|
||||||
|
await self._save_trivia_list(ctx=ctx, attachment=parsedfile)
|
||||||
|
except yaml.error.MarkedYAMLError as exc:
|
||||||
|
await ctx.send(_("Invalid syntax: ") + str(exc))
|
||||||
|
except yaml.error.YAMLError:
|
||||||
|
await ctx.send(
|
||||||
|
_("There was an error parsing the trivia list. See logs for more info.")
|
||||||
|
)
|
||||||
|
LOG.exception("Custom Trivia file %s failed to upload", parsedfile.filename)
|
||||||
|
|
||||||
|
@commands.is_owner()
|
||||||
|
@triviaset_custom.command(name="delete", aliases=["remove"])
|
||||||
|
async def trivia_delete(self, ctx: commands.Context, name: str):
|
||||||
|
"""Delete a trivia file."""
|
||||||
|
filepath = cog_data_path(self) / f"{name}.yaml"
|
||||||
|
if filepath.exists():
|
||||||
|
filepath.unlink()
|
||||||
|
await ctx.send(_("Trivia {filename} was deleted.").format(filename=filepath.stem))
|
||||||
|
else:
|
||||||
|
await ctx.send(_("Trivia file was not found."))
|
||||||
|
|
||||||
@commands.group(invoke_without_command=True)
|
@commands.group(invoke_without_command=True)
|
||||||
@commands.guild_only()
|
@commands.guild_only()
|
||||||
async def trivia(self, ctx: commands.Context, *categories: str):
|
async def trivia(self, ctx: commands.Context, *categories: str):
|
||||||
@ -525,6 +607,73 @@ class Trivia(commands.Cog):
|
|||||||
else:
|
else:
|
||||||
return dict_
|
return dict_
|
||||||
|
|
||||||
|
async def _save_trivia_list(
|
||||||
|
self, ctx: commands.Context, attachment: discord.Attachment
|
||||||
|
) -> None:
|
||||||
|
"""Checks and saves a trivia list to data folder.
|
||||||
|
|
||||||
|
Parameters
|
||||||
|
----------
|
||||||
|
file : discord.Attachment
|
||||||
|
A discord message attachment.
|
||||||
|
|
||||||
|
Returns
|
||||||
|
-------
|
||||||
|
None
|
||||||
|
"""
|
||||||
|
filename = attachment.filename.rsplit(".", 1)[0]
|
||||||
|
|
||||||
|
# Check if trivia filename exists in core files or if it is a command
|
||||||
|
if filename in self.trivia.all_commands or any(
|
||||||
|
filename == item.stem for item in get_core_lists()
|
||||||
|
):
|
||||||
|
await ctx.send(
|
||||||
|
_(
|
||||||
|
"{filename} is a reserved trivia name and cannot be replaced.\n"
|
||||||
|
"Choose another name."
|
||||||
|
).format(filename=filename)
|
||||||
|
)
|
||||||
|
return
|
||||||
|
|
||||||
|
file = cog_data_path(self) / f"{filename}.yaml"
|
||||||
|
if file.exists():
|
||||||
|
overwrite_message = _("{filename} already exists. Do you wish to overwrite?").format(
|
||||||
|
filename=filename
|
||||||
|
)
|
||||||
|
|
||||||
|
can_react = ctx.channel.permissions_for(ctx.me).add_reactions
|
||||||
|
if not can_react:
|
||||||
|
overwrite_message += " (y/n)"
|
||||||
|
|
||||||
|
overwrite_message_object: discord.Message = await ctx.send(overwrite_message)
|
||||||
|
if can_react:
|
||||||
|
# noinspection PyAsyncCall
|
||||||
|
start_adding_reactions(
|
||||||
|
overwrite_message_object, ReactionPredicate.YES_OR_NO_EMOJIS
|
||||||
|
)
|
||||||
|
pred = ReactionPredicate.yes_or_no(overwrite_message_object, ctx.author)
|
||||||
|
event = "reaction_add"
|
||||||
|
else:
|
||||||
|
pred = MessagePredicate.yes_or_no(ctx=ctx)
|
||||||
|
event = "message"
|
||||||
|
try:
|
||||||
|
await ctx.bot.wait_for(event, check=pred, timeout=30)
|
||||||
|
except asyncio.TimeoutError:
|
||||||
|
await ctx.send(_("You took too long answering."))
|
||||||
|
return
|
||||||
|
|
||||||
|
if pred.result is False:
|
||||||
|
await ctx.send(_("I am not replacing the existing file."))
|
||||||
|
return
|
||||||
|
|
||||||
|
buffer = io.BytesIO(await attachment.read())
|
||||||
|
yaml.safe_load(buffer)
|
||||||
|
buffer.seek(0)
|
||||||
|
|
||||||
|
with file.open("wb") as fp:
|
||||||
|
fp.write(buffer.read())
|
||||||
|
await ctx.send(_("Saved Trivia list as {filename}.").format(filename=filename))
|
||||||
|
|
||||||
def _get_trivia_session(self, channel: discord.TextChannel) -> TriviaSession:
|
def _get_trivia_session(self, channel: discord.TextChannel) -> TriviaSession:
|
||||||
return next(
|
return next(
|
||||||
(session for session in self.trivia_sessions if session.ctx.channel == channel), None
|
(session for session in self.trivia_sessions if session.ctx.channel == channel), None
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user