mirror of
https://github.com/brandons209/Red-bot-Cogs.git
synced 2024-05-17 10:53:39 +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 textwrap import shorten
|
||||||
|
from asyncio import TimeoutError as AsyncTimeoutError
|
||||||
|
from typing import Union
|
||||||
|
|
||||||
import discord
|
import discord
|
||||||
from redbot.core import checks
|
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 import chat_formatting as chat
|
||||||
from redbot.core.utils.menus import menu, DEFAULT_CONTROLS
|
from redbot.core.utils.menus import menu, DEFAULT_CONTROLS
|
||||||
from redbot.core.utils.mod import get_audit_reason
|
from redbot.core.utils.mod import get_audit_reason
|
||||||
|
from redbot.core.utils.predicates import ReactionPredicate
|
||||||
from tabulate import tabulate
|
from tabulate import tabulate
|
||||||
from typing import Literal
|
from typing import Literal
|
||||||
import asyncio
|
import asyncio
|
||||||
|
|
||||||
|
from .discord_new_features import edit_role_icon
|
||||||
|
|
||||||
_ = Translator("PersonalRoles", __file__)
|
_ = 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())
|
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(_)
|
@cog_i18n(_)
|
||||||
class PersonalRoles(commands.Cog):
|
class PersonalRoles(commands.Cog):
|
||||||
"""Assign and edit personal roles"""
|
"""Assign and edit personal roles"""
|
||||||
|
|
||||||
__version__ = "2.0.4"
|
__version__ = "2.2.0"
|
||||||
|
|
||||||
# noinspection PyMissingConstructor
|
# noinspection PyMissingConstructor
|
||||||
def __init__(self, bot: commands.Bot):
|
def __init__(self, bot: commands.Bot):
|
||||||
|
@ -249,6 +259,7 @@ class PersonalRoles(commands.Cog):
|
||||||
@myrole.command(aliases=["color"])
|
@myrole.command(aliases=["color"])
|
||||||
@commands.guild_only()
|
@commands.guild_only()
|
||||||
@commands.check(has_assigned_role)
|
@commands.check(has_assigned_role)
|
||||||
|
@commands.bot_has_permissions(manage_roles=True)
|
||||||
async def colour(self, ctx, *, colour: discord.Colour = discord.Colour.default()):
|
async def colour(self, ctx, *, colour: discord.Colour = discord.Colour.default()):
|
||||||
"""Change color of personal role"""
|
"""Change color of personal role"""
|
||||||
|
|
||||||
|
@ -287,6 +298,7 @@ class PersonalRoles(commands.Cog):
|
||||||
@myrole.command()
|
@myrole.command()
|
||||||
@commands.guild_only()
|
@commands.guild_only()
|
||||||
@commands.check(has_assigned_role)
|
@commands.check(has_assigned_role)
|
||||||
|
@commands.bot_has_permissions(manage_roles=True)
|
||||||
async def name(self, ctx, *, name: str):
|
async def name(self, ctx, *, name: str):
|
||||||
"""Change name of personal role
|
"""Change name of personal role
|
||||||
You can't use blacklisted names
|
You can't use blacklisted names
|
||||||
|
@ -356,6 +368,136 @@ class PersonalRoles(commands.Cog):
|
||||||
else:
|
else:
|
||||||
await ctx.send(chat.warning("You already have a personal role!"))
|
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
|
### Helper methods
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def role_from_string(guild: discord.Guild, role_name: str):
|
def role_from_string(guild: discord.Guild, role_name: str):
|
||||||
|
|
Loading…
Reference in a new issue