mirror of
https://github.com/brandons209/Red-bot-Cogs.git
synced 2024-05-02 19:43:37 +12:00
add in feature to edit role icons for personal roles if the server allows it
This commit is contained in:
parent
ee3eb24a0b
commit
8ceaa0ddee
49
personalroles/discord_new_features.py
Normal file
49
personalroles/discord_new_features.py
Normal file
|
@ -0,0 +1,49 @@
|
|||
# NOTE: this file contains backports or unintroduced features of next versions of dpy (as for 1.7.3)
|
||||
# TODO: nuke this file when Red is changed its version to support required features
|
||||
# from @fixator10
|
||||
from discord import Role
|
||||
from discord.http import Route
|
||||
from discord.utils import _bytes_to_base64_data
|
||||
|
||||
|
||||
async def edit_role_icon(bot, role: Role, reason=None, **fields):
|
||||
"""|coro|
|
||||
|
||||
Changes specified role's icon
|
||||
|
||||
Parameters
|
||||
-----------
|
||||
role: :class:`discord.Role`
|
||||
A role to edit
|
||||
icon: :class:`bytes`
|
||||
A :term:`py:bytes-like object` representing the image to upload.
|
||||
unicode_emoji: :class:`str`
|
||||
A unicode emoji to set
|
||||
reason: Optional[:class:`str`]
|
||||
The reason for editing this role. Shows up on the audit log.
|
||||
|
||||
Raises
|
||||
-------
|
||||
Forbidden
|
||||
You do not have permissions to change the role.
|
||||
HTTPException
|
||||
Editing the role failed.
|
||||
InvalidArgument
|
||||
Wrong image format passed for ``icon``.
|
||||
:param bot:
|
||||
"""
|
||||
if "unicode_emoji" in fields:
|
||||
fields["icon"] = None
|
||||
else:
|
||||
try:
|
||||
icon_bytes = fields["icon"]
|
||||
except KeyError:
|
||||
pass
|
||||
else:
|
||||
if icon_bytes is not None:
|
||||
fields["icon"] = _bytes_to_base64_data(icon_bytes)
|
||||
else:
|
||||
fields["icon"] = None
|
||||
|
||||
r = Route("PATCH", "/guilds/{guild_id}/roles/{role_id}", guild_id=role.guild.id, role_id=role.id)
|
||||
await bot.http.request(r, json=fields, reason=reason)
|
|
@ -1,4 +1,6 @@
|
|||
from textwrap import shorten
|
||||
from asyncio import TimeoutError as AsyncTimeoutError
|
||||
from typing import Union
|
||||
|
||||
import discord
|
||||
from redbot.core import checks
|
||||
|
@ -8,10 +10,13 @@ from redbot.core.i18n import Translator, cog_i18n
|
|||
from redbot.core.utils import chat_formatting as chat
|
||||
from redbot.core.utils.menus import menu, DEFAULT_CONTROLS
|
||||
from redbot.core.utils.mod import get_audit_reason
|
||||
from redbot.core.utils.predicates import ReactionPredicate
|
||||
from tabulate import tabulate
|
||||
from typing import Literal
|
||||
import asyncio
|
||||
|
||||
from .discord_new_features import edit_role_icon
|
||||
|
||||
_ = Translator("PersonalRoles", __file__)
|
||||
|
||||
|
||||
|
@ -23,11 +28,16 @@ async def has_assigned_role(ctx):
|
|||
return len(user_roles) > 0 or ctx.guild.get_role(await ctx.cog.config.member(ctx.author).role())
|
||||
|
||||
|
||||
async def role_icons_feature(ctx):
|
||||
"""Check for ROLE_ICONS feature"""
|
||||
return "ROLE_ICONS" in ctx.guild.features
|
||||
|
||||
|
||||
@cog_i18n(_)
|
||||
class PersonalRoles(commands.Cog):
|
||||
"""Assign and edit personal roles"""
|
||||
|
||||
__version__ = "2.0.4"
|
||||
__version__ = "2.2.0"
|
||||
|
||||
# noinspection PyMissingConstructor
|
||||
def __init__(self, bot: commands.Bot):
|
||||
|
@ -249,6 +259,7 @@ class PersonalRoles(commands.Cog):
|
|||
@myrole.command(aliases=["color"])
|
||||
@commands.guild_only()
|
||||
@commands.check(has_assigned_role)
|
||||
@commands.bot_has_permissions(manage_roles=True)
|
||||
async def colour(self, ctx, *, colour: discord.Colour = discord.Colour.default()):
|
||||
"""Change color of personal role"""
|
||||
|
||||
|
@ -287,6 +298,7 @@ class PersonalRoles(commands.Cog):
|
|||
@myrole.command()
|
||||
@commands.guild_only()
|
||||
@commands.check(has_assigned_role)
|
||||
@commands.bot_has_permissions(manage_roles=True)
|
||||
async def name(self, ctx, *, name: str):
|
||||
"""Change name of personal role
|
||||
You can't use blacklisted names
|
||||
|
@ -356,6 +368,136 @@ class PersonalRoles(commands.Cog):
|
|||
else:
|
||||
await ctx.send(chat.warning("You already have a personal role!"))
|
||||
|
||||
@myrole.group()
|
||||
@commands.check(has_assigned_role)
|
||||
@commands.check(role_icons_feature)
|
||||
@commands.bot_has_permissions(manage_roles=True)
|
||||
async def icon(self, ctx):
|
||||
"""Change icon of personal role"""
|
||||
pass
|
||||
|
||||
@icon.command(name="emoji")
|
||||
@commands.cooldown(1, 30, commands.BucketType.user)
|
||||
async def icon_emoji(self, ctx, *, emoji: Union[discord.Emoji, discord.PartialEmoji] = None):
|
||||
"""Change icon of personal role using emoji"""
|
||||
role = await self.config.member(ctx.author).role()
|
||||
role = ctx.guild.get_role(role)
|
||||
if not emoji:
|
||||
if ctx.channel.permissions_for(ctx.author).add_reactions:
|
||||
m = await ctx.send(_("React to this message with your emoji"))
|
||||
try:
|
||||
reaction = await ctx.bot.wait_for(
|
||||
"reaction_add",
|
||||
check=ReactionPredicate.same_context(message=m, user=ctx.author),
|
||||
timeout=30,
|
||||
)
|
||||
emoji = reaction[0].emoji
|
||||
except AsyncTimeoutError:
|
||||
return
|
||||
finally:
|
||||
await m.delete(delay=0)
|
||||
else:
|
||||
await ctx.send_help()
|
||||
return
|
||||
try:
|
||||
if isinstance(emoji, discord.Emoji):
|
||||
await edit_role_icon(
|
||||
self.bot,
|
||||
role,
|
||||
icon=await emoji.url_as(format="png").read(),
|
||||
reason=get_audit_reason(ctx.author, _("Personal Role")),
|
||||
)
|
||||
elif isinstance(emoji, discord.PartialEmoji):
|
||||
if emoji.is_custom_emoji():
|
||||
await edit_role_icon(
|
||||
self.bot,
|
||||
role,
|
||||
icon=await emoji.url_as(format="png").read(),
|
||||
reason=get_audit_reason(ctx.author, _("Personal Role")),
|
||||
)
|
||||
else:
|
||||
# unicode emoji
|
||||
await edit_role_icon(
|
||||
self.bot,
|
||||
role,
|
||||
unicode_emoji=emoji.name,
|
||||
reason=get_audit_reason(ctx.author, _("Personal Role")),
|
||||
)
|
||||
else:
|
||||
await edit_role_icon(
|
||||
self.bot,
|
||||
role,
|
||||
unicode_emoji=emoji,
|
||||
reason=get_audit_reason(ctx.author, _("Personal Role")),
|
||||
)
|
||||
except discord.Forbidden:
|
||||
ctx.command.reset_cooldown(ctx)
|
||||
await ctx.send(chat.error(_("Unable to edit role.\nRole must be lower than my top role")))
|
||||
except discord.InvalidArgument:
|
||||
await ctx.send(chat.error(_("This image type is unsupported, or link is incorrect")))
|
||||
except discord.HTTPException as e:
|
||||
ctx.command.reset_cooldown(ctx)
|
||||
await ctx.send(chat.error(_("Unable to edit role: {}").format(e)))
|
||||
else:
|
||||
await ctx.send(_("Changed icon of {user}'s personal role").format(user=ctx.message.author.name))
|
||||
|
||||
@icon.command(name="image", aliases=["url"])
|
||||
@commands.cooldown(1, 30, commands.BucketType.user)
|
||||
async def icon_image(self, ctx, *, url: str = None):
|
||||
"""Change icon of personal role by using image"""
|
||||
role = await self.config.member(ctx.author).role()
|
||||
role = ctx.guild.get_role(role)
|
||||
if not (ctx.message.attachments or url):
|
||||
raise commands.BadArgument
|
||||
if ctx.message.attachments:
|
||||
image = await ctx.message.attachments[0].read()
|
||||
else:
|
||||
try:
|
||||
async with ctx.cog.session.get(url, raise_for_status=True) as resp:
|
||||
image = await resp.read()
|
||||
except aiohttp.ClientResponseError as e:
|
||||
await ctx.send(chat.error(_("Unable to get image: {}").format(e.message)))
|
||||
return
|
||||
try:
|
||||
await edit_role_icon(
|
||||
self.bot,
|
||||
role,
|
||||
icon=image,
|
||||
reason=get_audit_reason(ctx.author, _("Personal Role")),
|
||||
)
|
||||
except discord.Forbidden:
|
||||
ctx.command.reset_cooldown(ctx)
|
||||
await ctx.send(chat.error(_("Unable to edit role.\nRole must be lower than my top role")))
|
||||
except discord.InvalidArgument:
|
||||
await ctx.send(chat.error(_("This image type is unsupported, or link is incorrect")))
|
||||
except discord.HTTPException as e:
|
||||
ctx.command.reset_cooldown(ctx)
|
||||
await ctx.send(chat.error(_("Unable to edit role: {}").format(e)))
|
||||
else:
|
||||
await ctx.send(_("Changed icon of {user}'s personal role").format(user=ctx.message.author.name))
|
||||
|
||||
@icon.command(name="reset", aliases=["remove"])
|
||||
@commands.cooldown(1, 30, commands.BucketType.user)
|
||||
async def icon_reset(self, ctx):
|
||||
"""Remove icon of personal role"""
|
||||
role = await self.config.member(ctx.author).role()
|
||||
role = ctx.guild.get_role(role)
|
||||
try:
|
||||
await edit_role_icon(
|
||||
self.bot,
|
||||
role,
|
||||
icon=None,
|
||||
unicode_emoji=None,
|
||||
reason=get_audit_reason(ctx.author, _("Personal Role")),
|
||||
)
|
||||
await ctx.send(_("Removed icon of {user}'s personal role").format(user=ctx.message.author.name))
|
||||
except discord.Forbidden:
|
||||
ctx.command.reset_cooldown(ctx)
|
||||
await ctx.send(chat.error(_("Unable to edit role.\nRole must be lower than my top role")))
|
||||
except discord.HTTPException as e:
|
||||
ctx.command.reset_cooldown(ctx)
|
||||
await ctx.send(chat.error(_("Unable to edit role: {}").format(e)))
|
||||
|
||||
### Helper methods
|
||||
@staticmethod
|
||||
def role_from_string(guild: discord.Guild, role_name: str):
|
||||
|
|
Loading…
Reference in a new issue