2020-02-09 08:52:28 +13:00
|
|
|
from redbot.core.utils.chat_formatting import *
|
|
|
|
from redbot.core import Config, checks, commands, bank
|
|
|
|
from redbot.core.data_manager import cog_data_path
|
|
|
|
import discord
|
|
|
|
|
|
|
|
import aiohttp
|
|
|
|
import PIL
|
|
|
|
import os
|
|
|
|
|
|
|
|
|
|
|
|
class NitroEmoji(commands.Cog):
|
|
|
|
"""
|
|
|
|
Reward nitro boosters with a custom emoji.
|
|
|
|
"""
|
2020-02-09 08:53:01 +13:00
|
|
|
|
2020-02-09 08:52:28 +13:00
|
|
|
def __init__(self, bot):
|
|
|
|
self.bot = bot
|
|
|
|
self.config = Config.get_conf(self, identifier=123859659843, force_registration=True)
|
2020-02-09 08:53:01 +13:00
|
|
|
default_guild = {"channel": None, "disabled": False}
|
|
|
|
default_member = {"emojis": []}
|
2020-02-09 08:52:28 +13:00
|
|
|
self.config.register_guild(**default_guild)
|
|
|
|
self.config.register_member(**default_member)
|
|
|
|
|
|
|
|
async def initialize(self):
|
|
|
|
for member in self.bot.get_all_members():
|
|
|
|
async with self.config.member(member).emojis() as data:
|
|
|
|
to_remove = []
|
|
|
|
for e in data:
|
|
|
|
emoji = self.find_emoji(member.guild, e)
|
|
|
|
# clean removed emojis if bot is down
|
|
|
|
if not emoji:
|
|
|
|
to_remove.append(e)
|
|
|
|
|
|
|
|
for r in to_remove:
|
|
|
|
data.remove(r)
|
|
|
|
|
|
|
|
@staticmethod
|
|
|
|
def get_boosts(member: discord.Member):
|
|
|
|
# this will return number of boosts once api supports it
|
|
|
|
return member.premium_since is not None
|
|
|
|
|
|
|
|
def find_emoji(self, guild, name):
|
|
|
|
emoji = self.bot.get_emoji(name)
|
|
|
|
# find by name:
|
|
|
|
if not emoji:
|
|
|
|
emoji = discord.utils.get(guild.emojis, name=name)
|
|
|
|
return emoji
|
|
|
|
|
|
|
|
async def add_emoji(self, member, name, attachment_or_url, reason=None):
|
|
|
|
path = str(cog_data_path(cog_instance=self))
|
|
|
|
path = os.path.join(path, str(member.id) + name)
|
|
|
|
if isinstance(attachment_or_url, discord.Attachment):
|
|
|
|
await attachment_or_url.save(path)
|
|
|
|
elif isinstance(attachment_or_url, str):
|
|
|
|
async with aiohttp.ClientSession(loop=self.bot.loop) as session:
|
|
|
|
async with session.get(attachment_or_url) as r:
|
|
|
|
if r.status == 200:
|
|
|
|
with open(path, "wb") as f:
|
|
|
|
f.write(await r.read())
|
|
|
|
|
|
|
|
# verify image
|
|
|
|
im = PIL.Image.open(path)
|
|
|
|
im.verify()
|
|
|
|
|
|
|
|
# upload emoji
|
|
|
|
with open(path, "rb") as f:
|
|
|
|
emoji = await member.guild.create_custom_emoji(name=name, image=f.read())
|
|
|
|
|
|
|
|
os.remove(path)
|
|
|
|
|
|
|
|
async with self.config.member(member).emojis() as e:
|
|
|
|
e.append(emoji.id)
|
|
|
|
|
|
|
|
channel = await self.config.guild(member.guild).channel()
|
|
|
|
channel = member.guild.get_channel(channel)
|
|
|
|
if not channel:
|
|
|
|
return
|
|
|
|
|
|
|
|
embed = discord.Embed(title="Custom Emoji Added", colour=member.colour)
|
|
|
|
embed.set_footer(text="User ID:{}".format(member.id))
|
|
|
|
|
|
|
|
embed.set_author(name=str(member), url=emoji.url)
|
|
|
|
embed.set_thumbnail(url=emoji.url)
|
|
|
|
embed.set_author(name=str(member))
|
|
|
|
|
|
|
|
if reason:
|
|
|
|
embed.add_field(name="Reason", value=reason)
|
|
|
|
|
|
|
|
await channel.send(embed=embed)
|
|
|
|
|
|
|
|
async def del_emoji(self, guild, member, emoji=None, reason=None):
|
|
|
|
channel = await self.config.guild(member.guild).channel()
|
|
|
|
channel = member.guild.get_channel(channel)
|
|
|
|
if channel:
|
|
|
|
embed = discord.Embed(title="Custom Emoji Removed", colour=member.colour)
|
|
|
|
embed.set_footer(text="User ID:{}".format(member.id))
|
|
|
|
|
|
|
|
embed.set_author(name=str(member), url=emoji.url)
|
|
|
|
embed.set_thumbnail(url=emoji.url)
|
|
|
|
embed.set_author(name=str(member))
|
|
|
|
|
|
|
|
if reason:
|
|
|
|
embed.add_field(name="Reason", value=reason)
|
|
|
|
|
|
|
|
await channel.send(embed=embed)
|
|
|
|
|
|
|
|
if emoji:
|
|
|
|
await emoji.delete()
|
|
|
|
async with self.config.member(member).emojis() as e:
|
|
|
|
e.remove(emoji.id)
|
|
|
|
|
|
|
|
@commands.group(name="nitroset")
|
|
|
|
@commands.guild_only()
|
|
|
|
@checks.admin()
|
|
|
|
async def nitroset(self, ctx):
|
|
|
|
"""Manage nitro emoji settings."""
|
|
|
|
pass
|
|
|
|
|
|
|
|
@nitroset.command(name="channel")
|
|
|
|
async def nitroset_channel(self, ctx, channel: discord.TextChannel):
|
|
|
|
"""
|
|
|
|
Set the channel to log nitro events.
|
|
|
|
|
|
|
|
Logs boosts, unboosts, and added emojis.
|
|
|
|
"""
|
|
|
|
|
|
|
|
await self.config.guild(ctx.guild).channel.set(channel.id)
|
|
|
|
await ctx.tick()
|
|
|
|
|
|
|
|
@nitroset.command(name="disable")
|
|
|
|
async def nitroset_disable(self, ctx, *, on_off: bool = None):
|
|
|
|
"""
|
|
|
|
Disable users from adding more emojis.
|
|
|
|
|
|
|
|
Users can still remove and list their own emojis.
|
|
|
|
"""
|
|
|
|
if on_off is None:
|
|
|
|
curr = await self.config.guild(ctx.guild).disabled()
|
|
|
|
msg = "enabled" if not curr else "disabled"
|
|
|
|
await ctx.send(f"Nitro emojis is {msg}.")
|
|
|
|
return
|
|
|
|
|
|
|
|
await self.config.guild(ctx.guild).disabled.set(on_off)
|
|
|
|
await ctx.tick()
|
|
|
|
|
|
|
|
@commands.group(name="nitroemoji")
|
|
|
|
@checks.bot_has_permissions(manage_emojis=True)
|
|
|
|
async def nitroemoji(self, ctx):
|
|
|
|
"""
|
|
|
|
Manage your emojis if you boosted the server.
|
|
|
|
"""
|
|
|
|
pass
|
|
|
|
|
|
|
|
@nitroemoji.command(name="add")
|
|
|
|
async def nitroemoji_add(self, ctx, name: str, *, url: str = None):
|
|
|
|
"""
|
|
|
|
Add an emoji to the server, if you boosted.
|
|
|
|
|
|
|
|
Can only add an emoji for every boost you have in the server.
|
|
|
|
"""
|
|
|
|
disabled = await self.config.guild(ctx.guild).disabled()
|
|
|
|
if disabled:
|
|
|
|
await ctx.send("Sorry, adding emojis is currently disabled right now.")
|
|
|
|
return
|
|
|
|
|
|
|
|
curr = await self.config.member(ctx.author).emojis()
|
|
|
|
boosts = self.get_boosts(ctx.author)
|
|
|
|
# TODO: add in checking for multiple emojis once supported
|
|
|
|
if boosts and not curr:
|
|
|
|
try:
|
|
|
|
if url:
|
|
|
|
emoji = await self.add_emoji(ctx.author, name, url)
|
|
|
|
else:
|
|
|
|
emoji = await self.add_emoji(ctx.author, name, ctx.message.attachments[0])
|
|
|
|
await ctx.tick()
|
|
|
|
except discord.errors.HTTPException as e:
|
|
|
|
await ctx.send(e.text)
|
|
|
|
except PIL.UnidentifiedImageError:
|
|
|
|
await ctx.send("That is not a valid picture! Pictures must be in PNG, JPEG, or GIF format.")
|
|
|
|
except:
|
2020-02-09 08:53:01 +13:00
|
|
|
await ctx.send(
|
|
|
|
"Something went wrong, make sure to add a valid picture (PNG, JPG, or GIF) of the right size (256KB) and a valid name."
|
|
|
|
)
|
2020-02-09 08:52:28 +13:00
|
|
|
return
|
|
|
|
elif not boosts:
|
|
|
|
await ctx.send("Sorry, you need to be a nitro booster to add an emoji!")
|
|
|
|
elif curr:
|
|
|
|
await ctx.send("You already have a custom emoji, please delete it first before adding another one.")
|
|
|
|
|
|
|
|
@nitroemoji.command(name="rem")
|
|
|
|
async def nitroemoji_rem(self, ctx, name: str):
|
|
|
|
"""
|
|
|
|
Remove an emoji to the server, if you boosted.
|
|
|
|
"""
|
|
|
|
curr = await self.config.member(ctx.author).emojis()
|
|
|
|
emoji = self.find_emoji(ctx.guild, name)
|
|
|
|
if emoji:
|
|
|
|
if emoji.id in curr:
|
|
|
|
await self.del_emoji(ctx.guild, ctx.author, emoji=emoji, reason="Removed by user.")
|
|
|
|
await ctx.tick()
|
|
|
|
else:
|
|
|
|
await ctx.send("That isn't your custom emoji.")
|
|
|
|
else:
|
|
|
|
await ctx.send(warning("Emoji not found."))
|
|
|
|
|
|
|
|
@nitroemoji.command(name="list")
|
|
|
|
async def nitroemoji_list(self, ctx):
|
|
|
|
"""
|
|
|
|
List your custom emojis in the server
|
|
|
|
"""
|
|
|
|
curr = await self.config.member(ctx.author).emojis()
|
|
|
|
msg = ""
|
|
|
|
if curr:
|
|
|
|
msg += "Current emojis:\n"
|
|
|
|
for emoji in curr:
|
|
|
|
emoji = self.find_emoji(ctx.guild, emoji)
|
|
|
|
if not emoji:
|
|
|
|
continue
|
|
|
|
msg += f"{emoji.url}\n"
|
|
|
|
else:
|
|
|
|
msg += "You have no custom emojis."
|
|
|
|
|
|
|
|
for page in pagify(msg):
|
|
|
|
await ctx.send(page)
|
|
|
|
|
|
|
|
@commands.Cog.listener()
|
|
|
|
async def on_member_update(self, before, after):
|
|
|
|
# check if they stopped boosting
|
|
|
|
if before.premium_since != after.premium_since and after.premium_since is None:
|
|
|
|
emojis = await self.config.member(after).emojis()
|
|
|
|
for emoji in emojis:
|
|
|
|
emoji = self.find_emoji(after.guild, emoji)
|
|
|
|
if not emoji:
|
|
|
|
continue
|
|
|
|
await self.del_emoji(after.guild, after, emoji=emoji, reason="Stopped boosting.")
|
|
|
|
|
|
|
|
@commands.Cog.listener()
|
|
|
|
async def on_guild_emojis_update(self, guild, before, after):
|
|
|
|
b_e = set(before)
|
|
|
|
a_e = set(after)
|
|
|
|
diff = b_e - a_e
|
|
|
|
if diff:
|
|
|
|
for e in diff:
|
|
|
|
for member in guild.premium_subscribers:
|
|
|
|
curr = await self.config.member(member).emojis()
|
|
|
|
if e.id in curr:
|
|
|
|
curr.remove(e.id)
|
|
|
|
await self.config.member(member).emojis.set(curr)
|
|
|
|
await self.del_emoji(guild, member, emoji=e, reason="Manually deleted by admin.")
|
|
|
|
break
|