2020-04-10 20:54:46 +02:00
|
|
|
from datetime import datetime
|
|
|
|
|
2020-08-02 14:17:17 +02:00
|
|
|
from discord.abc import GuildChannel
|
2020-04-10 20:37:14 +02:00
|
|
|
from discord.ext import commands
|
2020-08-02 14:17:17 +02:00
|
|
|
from discord import Embed, RawReactionActionEvent, RawMessageDeleteEvent, RawBulkMessageDeleteEvent, TextChannel, Guild
|
2020-07-23 21:42:30 +02:00
|
|
|
from discord.ext.commands import BadArgument
|
2020-04-10 20:37:14 +02:00
|
|
|
|
2020-07-23 21:42:30 +02:00
|
|
|
import db
|
2020-11-05 14:52:03 +01:00
|
|
|
from administrator.check import is_enabled
|
2020-07-23 21:22:47 +02:00
|
|
|
from administrator.logger import logger
|
2020-11-05 14:52:03 +01:00
|
|
|
from administrator.utils import event_is_enabled
|
2020-04-10 20:37:14 +02:00
|
|
|
|
|
|
|
extension_name = "poll"
|
|
|
|
logger = logger.getChild(extension_name)
|
|
|
|
REACTIONS = []
|
|
|
|
for i in range(10):
|
|
|
|
REACTIONS.append(str(i)+"\ufe0f\u20E3")
|
|
|
|
REACTIONS.append("\U0001F51F")
|
|
|
|
|
|
|
|
|
|
|
|
class Poll(commands.Cog):
|
|
|
|
def __init__(self, bot: commands.Bot):
|
|
|
|
self.bot = bot
|
|
|
|
|
2020-07-23 21:34:32 +02:00
|
|
|
def description(self):
|
|
|
|
return "Create poll with a simple command"
|
|
|
|
|
2020-04-10 20:37:14 +02:00
|
|
|
@commands.group("poll", pass_context=True)
|
2020-11-05 14:52:03 +01:00
|
|
|
@is_enabled()
|
2020-04-10 20:37:14 +02:00
|
|
|
@commands.guild_only()
|
|
|
|
async def poll(self, ctx: commands.Context, name: str, *choices):
|
2020-04-10 21:02:06 +02:00
|
|
|
if name == "help":
|
|
|
|
await ctx.invoke(self.poll_help)
|
|
|
|
else:
|
2020-04-10 20:37:14 +02:00
|
|
|
multi = False
|
|
|
|
if choices and choices[0] in ["multi", "m"]:
|
|
|
|
multi = True
|
|
|
|
choices = choices[1:]
|
|
|
|
if len(choices) == 0 or len(choices) > 11:
|
2020-07-23 21:42:30 +02:00
|
|
|
raise BadArgument()
|
2020-04-10 20:37:14 +02:00
|
|
|
else:
|
2020-04-10 20:54:46 +02:00
|
|
|
embed = Embed(title=f"Poll: {name}")
|
|
|
|
embed.set_author(name=str(ctx.author), icon_url=ctx.author.avatar_url)
|
|
|
|
embed.set_footer(text=f"Created: {ctx.message.created_at.strftime('%d/%m/%Y %H:%M')}")
|
2020-04-10 20:37:14 +02:00
|
|
|
for i, choice in enumerate(choices):
|
|
|
|
embed.add_field(name=REACTIONS[i], value=choice, inline=False)
|
|
|
|
message = await ctx.send(embed=embed)
|
|
|
|
reactions = REACTIONS[0:len(choices)] + ["\U0001F5D1"]
|
|
|
|
for reaction in reactions:
|
|
|
|
await message.add_reaction(reaction)
|
2020-07-23 21:42:30 +02:00
|
|
|
s = db.Session()
|
2020-08-02 14:17:17 +02:00
|
|
|
s.add(db.Polls(message.id, ctx.channel.id, ctx.guild.id, ctx.message.author.id, reactions, multi))
|
2020-07-23 21:42:30 +02:00
|
|
|
s.commit()
|
|
|
|
s.close()
|
2020-04-10 20:39:09 +02:00
|
|
|
await ctx.message.delete()
|
2020-04-10 20:37:14 +02:00
|
|
|
|
|
|
|
@poll.group("help", pass_context=True)
|
2020-04-10 21:02:06 +02:00
|
|
|
async def poll_help(self, ctx: commands.Context):
|
2020-07-23 21:30:42 +02:00
|
|
|
embed = Embed(title="Poll help")
|
2020-04-10 21:02:06 +02:00
|
|
|
embed.add_field(name="poll <name> [multi|m] <Choice N°1> <Choice N°2> ... <Choice N°11>",
|
|
|
|
value="Create a poll, the argument multi (or m) after the name allow multiple response\n"
|
|
|
|
"User the \U0001F5D1 to close the poll",
|
|
|
|
inline=False)
|
2020-04-10 20:37:14 +02:00
|
|
|
await ctx.send(embed=embed)
|
|
|
|
|
|
|
|
@commands.Cog.listener()
|
2020-07-23 21:42:30 +02:00
|
|
|
async def on_raw_reaction_add(self, payload: RawReactionActionEvent):
|
2020-11-03 16:26:19 +01:00
|
|
|
if not payload.member:
|
|
|
|
user = await self.bot.fetch_user(payload.user_id)
|
|
|
|
else:
|
|
|
|
user = payload.member
|
2020-11-05 14:52:03 +01:00
|
|
|
|
2020-11-03 16:26:19 +01:00
|
|
|
if not user.bot:
|
2020-07-23 21:42:30 +02:00
|
|
|
s = db.Session()
|
2020-11-05 14:52:03 +01:00
|
|
|
if payload.guild_id and not event_is_enabled(self.qualified_name, payload.guild_id, s):
|
|
|
|
return
|
2020-07-23 21:42:30 +02:00
|
|
|
p = s.query(db.Polls).filter(db.Polls.message == payload.message_id).first()
|
|
|
|
if p:
|
|
|
|
message = await self.bot.get_channel(p.channel).fetch_message(p.message)
|
|
|
|
if str(payload.emoji) not in eval(p.reactions):
|
2020-11-03 16:26:19 +01:00
|
|
|
await message.remove_reaction(payload.emoji, user)
|
2020-07-23 21:42:30 +02:00
|
|
|
elif str(payload.emoji) == "\U0001F5D1":
|
2020-11-03 16:26:19 +01:00
|
|
|
if user.id != p.author:
|
|
|
|
await message.remove_reaction(payload.emoji, user)
|
2020-07-23 21:42:30 +02:00
|
|
|
else:
|
|
|
|
await self.close_poll(s, p)
|
|
|
|
elif not p.multi:
|
|
|
|
f = False
|
|
|
|
for r in message.reactions:
|
|
|
|
if str(r.emoji) != str(payload.emoji):
|
|
|
|
async for u in r.users():
|
2020-11-03 16:26:19 +01:00
|
|
|
if u == user:
|
|
|
|
await r.remove(user)
|
2020-07-23 21:42:30 +02:00
|
|
|
f = True
|
|
|
|
break
|
|
|
|
if f:
|
2020-04-10 20:37:14 +02:00
|
|
|
break
|
2020-07-23 21:42:30 +02:00
|
|
|
s.close()
|
2020-04-10 20:37:14 +02:00
|
|
|
|
2020-07-23 21:42:30 +02:00
|
|
|
async def close_poll(self, session: db.Session, poll: db.Polls):
|
2020-04-10 20:54:46 +02:00
|
|
|
time = datetime.now()
|
2020-07-23 21:42:30 +02:00
|
|
|
message = await self.bot.get_channel(poll.channel).fetch_message(poll.message)
|
2020-04-10 20:41:58 +02:00
|
|
|
reactions = message.reactions
|
|
|
|
await message.clear_reactions()
|
2020-04-10 20:37:14 +02:00
|
|
|
embed = message.embeds[0]
|
|
|
|
for i, f in enumerate(embed.fields):
|
2020-04-10 20:41:58 +02:00
|
|
|
embed.set_field_at(i, name=f"{f.name} - {reactions[i].count-1}", value=f.value, inline=False)
|
2020-04-10 20:54:46 +02:00
|
|
|
embed.set_footer(text=embed.footer.text + "\n" + f"Close: {time.strftime('%d/%m/%Y %H:%M')}")
|
2020-04-10 20:37:14 +02:00
|
|
|
await message.edit(embed=embed)
|
2020-07-23 21:42:30 +02:00
|
|
|
session.delete(poll)
|
|
|
|
session.commit()
|
2020-04-10 20:37:14 +02:00
|
|
|
|
2020-08-02 14:17:17 +02:00
|
|
|
@commands.Cog.listener()
|
|
|
|
async def on_raw_message_delete(self, message: RawMessageDeleteEvent):
|
|
|
|
s = db.Session()
|
|
|
|
p = s.query(db.Polls).filter(db.Polls.message == message.message_id).first()
|
|
|
|
if p:
|
|
|
|
s.delete(p)
|
|
|
|
s.commit()
|
|
|
|
s.close()
|
|
|
|
|
|
|
|
@commands.Cog.listener()
|
|
|
|
async def on_raw_bulk_message_delete(self, messages: RawBulkMessageDeleteEvent):
|
|
|
|
s = db.Session()
|
|
|
|
for p in s.query(db.Polls).filter(db.Polls.message.in_(messages.message_ids)).all():
|
|
|
|
s.delete(p)
|
|
|
|
s.commit()
|
|
|
|
s.close()
|
|
|
|
|
|
|
|
@commands.Cog.listener()
|
|
|
|
async def on_guild_channel_delete(self, channel: GuildChannel):
|
|
|
|
if isinstance(channel, TextChannel):
|
|
|
|
s = db.Session()
|
|
|
|
for p in s.query(db.Polls).filter(db.Polls.channel == channel.id).all():
|
|
|
|
s.delete(p)
|
|
|
|
s.commit()
|
|
|
|
s.close()
|
|
|
|
|
|
|
|
@commands.Cog.listener()
|
|
|
|
async def on_guild_remove(self, guild: Guild):
|
|
|
|
s = db.Session()
|
|
|
|
for p in s.query(db.Polls).filter(db.Polls.guild == guild.id).all():
|
|
|
|
s.delete(p)
|
|
|
|
s.commit()
|
|
|
|
s.close()
|
|
|
|
|
2020-04-10 20:37:14 +02:00
|
|
|
|
|
|
|
def setup(bot):
|
|
|
|
logger.info(f"Loading...")
|
|
|
|
try:
|
|
|
|
bot.add_cog(Poll(bot))
|
|
|
|
except Exception as e:
|
|
|
|
logger.error(f"Error loading: {e}")
|
|
|
|
else:
|
|
|
|
logger.info(f"Load successful")
|
|
|
|
|
|
|
|
|
|
|
|
def teardown(bot):
|
|
|
|
logger.info(f"Unloading...")
|
|
|
|
try:
|
|
|
|
bot.remove_cog("Poll")
|
|
|
|
except Exception as e:
|
|
|
|
logger.error(f"Error unloading: {e}")
|
|
|
|
else:
|
|
|
|
logger.info(f"Unload successful")
|