2019-10-06 23:49:00 +02:00
|
|
|
import json
|
2019-12-30 00:48:11 +01:00
|
|
|
import logging
|
2019-10-06 01:49:30 +02:00
|
|
|
from typing import Union
|
|
|
|
|
|
|
|
import discord
|
2019-09-28 01:39:45 +02:00
|
|
|
from discord.ext import commands
|
2019-10-08 18:54:05 +02:00
|
|
|
from yarl import URL
|
2019-09-28 01:39:45 +02:00
|
|
|
|
|
|
|
from bot import TuxBot
|
2020-01-04 02:46:12 +01:00
|
|
|
from utils import PollModel, ResponsesModel
|
2020-01-12 21:43:05 +01:00
|
|
|
from utils import Texts
|
|
|
|
from utils.functions import emotes as utils_emotes
|
2020-02-04 18:47:11 +01:00
|
|
|
from utils import group_extra
|
2019-09-28 01:39:45 +02:00
|
|
|
|
2019-12-30 00:48:11 +01:00
|
|
|
log = logging.getLogger(__name__)
|
|
|
|
|
2019-09-28 01:39:45 +02:00
|
|
|
|
2020-01-15 00:08:53 +01:00
|
|
|
class Poll(commands.Cog):
|
2019-09-28 01:39:45 +02:00
|
|
|
|
|
|
|
def __init__(self, bot: TuxBot):
|
|
|
|
self.bot = bot
|
2020-01-04 02:46:12 +01:00
|
|
|
self.icon = ":bar_chart:"
|
|
|
|
self.big_icon = "https://emojipedia-us.s3.dualstack.us-west-1.amazonaws.com/thumbs/120/twitter/233/bar-chart_1f4ca.png:"
|
2019-09-28 01:39:45 +02:00
|
|
|
|
2019-12-30 00:48:11 +01:00
|
|
|
def get_poll(self, pld) -> Union[bool, PollModel]:
|
2019-10-06 01:49:30 +02:00
|
|
|
if pld.user_id != self.bot.user.id:
|
2019-10-06 23:49:00 +02:00
|
|
|
poll = self.bot.database.session \
|
2019-12-30 00:48:11 +01:00
|
|
|
.query(PollModel) \
|
|
|
|
.filter(PollModel.message_id == pld.message_id)
|
2019-10-06 01:49:30 +02:00
|
|
|
|
2019-12-16 18:12:10 +01:00
|
|
|
if poll.count() > 0:
|
2019-10-06 23:49:00 +02:00
|
|
|
poll = poll.one()
|
2019-10-26 23:19:47 +02:00
|
|
|
emotes = utils_emotes.get(poll.available_choices)
|
2019-10-06 01:49:30 +02:00
|
|
|
if pld.emoji.name in emotes:
|
|
|
|
return poll
|
|
|
|
|
|
|
|
return False
|
|
|
|
|
|
|
|
async def remove_reaction(self, pld):
|
2019-10-06 23:49:00 +02:00
|
|
|
channel: discord.TextChannel = self.bot.get_channel(pld.channel_id)
|
|
|
|
message: discord.Message = await channel.fetch_message(pld.message_id)
|
2019-10-06 01:49:30 +02:00
|
|
|
user: discord.User = await self.bot.fetch_user(pld.user_id)
|
|
|
|
|
|
|
|
await message.remove_reaction(pld.emoji.name, user)
|
|
|
|
|
2019-10-26 23:19:47 +02:00
|
|
|
@commands.Cog.listener()
|
|
|
|
async def on_raw_reaction_add(self, pld: discord.RawReactionActionEvent):
|
|
|
|
poll = self.get_poll(pld)
|
|
|
|
|
|
|
|
if poll:
|
|
|
|
if poll.is_anonymous:
|
|
|
|
try:
|
|
|
|
await self.remove_reaction(pld)
|
|
|
|
except discord.errors.Forbidden:
|
|
|
|
pass
|
|
|
|
choice = utils_emotes.get_index(pld.emoji.name)
|
|
|
|
|
2019-12-30 00:48:11 +01:00
|
|
|
responses = self.bot.database.session.query(ResponsesModel) \
|
2019-10-26 23:19:47 +02:00
|
|
|
.filter(
|
2019-12-30 00:48:11 +01:00
|
|
|
ResponsesModel.poll_id == poll.id,
|
|
|
|
ResponsesModel.user == pld.user_id,
|
|
|
|
ResponsesModel.choice == choice
|
2019-10-26 23:19:47 +02:00
|
|
|
)
|
|
|
|
|
2019-12-16 23:06:25 +01:00
|
|
|
if responses.count() != 0:
|
|
|
|
response = responses.first()
|
2019-10-26 23:19:47 +02:00
|
|
|
self.bot.database.session.delete(response)
|
2019-12-16 23:06:25 +01:00
|
|
|
self.bot.database.session.commit()
|
2019-10-26 23:19:47 +02:00
|
|
|
else:
|
2019-12-30 00:48:11 +01:00
|
|
|
response = ResponsesModel(
|
2019-10-26 23:19:47 +02:00
|
|
|
user=pld.user_id,
|
|
|
|
poll_id=poll.id,
|
|
|
|
choice=choice
|
|
|
|
)
|
|
|
|
self.bot.database.session.add(response)
|
2019-12-16 23:06:25 +01:00
|
|
|
self.bot.database.session.commit()
|
|
|
|
|
|
|
|
await self.update_poll(poll.id)
|
2019-10-26 23:19:47 +02:00
|
|
|
|
2019-12-29 21:38:59 +01:00
|
|
|
@commands.Cog.listener()
|
2020-01-04 02:46:12 +01:00
|
|
|
async def on_raw_reaction_remove(self,
|
|
|
|
pld: discord.RawReactionActionEvent):
|
2019-12-29 21:38:59 +01:00
|
|
|
poll = self.get_poll(pld)
|
|
|
|
|
|
|
|
if poll:
|
|
|
|
choice = utils_emotes.get_index(pld.emoji.name)
|
|
|
|
|
2019-12-30 00:48:11 +01:00
|
|
|
responses = self.bot.database.session.query(ResponsesModel) \
|
2019-12-29 21:38:59 +01:00
|
|
|
.filter(
|
2019-12-30 00:48:11 +01:00
|
|
|
ResponsesModel.poll_id == poll.id,
|
|
|
|
ResponsesModel.user == pld.user_id,
|
|
|
|
ResponsesModel.choice == choice
|
2019-12-29 21:38:59 +01:00
|
|
|
)
|
|
|
|
|
|
|
|
if responses.count() != 0:
|
|
|
|
response = responses.first()
|
|
|
|
self.bot.database.session.delete(response)
|
|
|
|
self.bot.database.session.commit()
|
|
|
|
await self.update_poll(poll.id)
|
|
|
|
|
2019-12-17 22:41:54 +01:00
|
|
|
###########################################################################
|
2019-10-26 23:19:47 +02:00
|
|
|
|
|
|
|
async def create_poll(self, ctx: commands.Context, poll: str, anonymous):
|
|
|
|
question = (poll.split('|')[0]).strip()
|
|
|
|
responses = [response.strip() for response in poll.split('|')[1:]]
|
|
|
|
emotes = utils_emotes.get(len(responses))
|
|
|
|
|
|
|
|
stmt = await ctx.send(Texts('poll', ctx).get('**Preparation...**'))
|
|
|
|
|
2019-12-30 00:48:11 +01:00
|
|
|
poll_row = PollModel()
|
2019-10-26 23:19:47 +02:00
|
|
|
self.bot.database.session.add(poll_row)
|
|
|
|
self.bot.database.session.flush()
|
|
|
|
|
|
|
|
e = discord.Embed(description=f"**{question}**")
|
|
|
|
e.set_author(
|
2019-12-16 23:06:25 +01:00
|
|
|
name=ctx.author,
|
2019-10-26 23:19:47 +02:00
|
|
|
icon_url="https://cdn.gnous.eu/tuxbot/survey1.png"
|
|
|
|
)
|
|
|
|
for i, response in enumerate(responses):
|
|
|
|
e.add_field(
|
2019-12-29 21:38:59 +01:00
|
|
|
name=f"__{emotes[i]}` - {response.capitalize()}`__",
|
2019-10-26 23:19:47 +02:00
|
|
|
value="**0** vote"
|
|
|
|
)
|
2019-12-16 23:06:25 +01:00
|
|
|
e.set_footer(text=f"ID: #{poll_row.id}")
|
2019-10-26 23:19:47 +02:00
|
|
|
|
|
|
|
poll_row.channel_id = stmt.channel.id
|
|
|
|
poll_row.message_id = stmt.id
|
|
|
|
poll_row.content = e.to_dict()
|
|
|
|
poll_row.is_anonymous = anonymous
|
|
|
|
poll_row.available_choices = len(responses)
|
|
|
|
|
|
|
|
self.bot.database.session.commit()
|
|
|
|
|
|
|
|
await stmt.edit(content='', embed=e)
|
|
|
|
for emote in range(len(responses)):
|
|
|
|
await stmt.add_reaction(emotes[emote])
|
|
|
|
|
2019-10-06 23:49:00 +02:00
|
|
|
async def update_poll(self, poll_id: int):
|
|
|
|
poll = self.bot.database.session \
|
2019-12-30 00:48:11 +01:00
|
|
|
.query(PollModel) \
|
|
|
|
.filter(PollModel.id == poll_id) \
|
2019-10-06 23:49:00 +02:00
|
|
|
.one()
|
|
|
|
channel: discord.TextChannel = self.bot.get_channel(poll.channel_id)
|
|
|
|
message: discord.Message = await channel.fetch_message(poll.message_id)
|
|
|
|
|
2019-10-08 18:54:05 +02:00
|
|
|
chart_base_url = "https://quickchart.io/chart?backgroundColor=white&c="
|
|
|
|
chart_options = {
|
|
|
|
'type': 'pie',
|
|
|
|
'data': {
|
|
|
|
'labels': [],
|
|
|
|
'datasets': [
|
|
|
|
{
|
|
|
|
'data': []
|
|
|
|
}
|
|
|
|
]
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-10-06 23:49:00 +02:00
|
|
|
content = json.loads(poll.content) \
|
|
|
|
if isinstance(poll.content, str) \
|
|
|
|
else poll.content
|
2020-01-04 02:46:12 +01:00
|
|
|
raw_responses = self.bot.database.session \
|
|
|
|
.query(ResponsesModel) \
|
2019-12-30 00:48:11 +01:00
|
|
|
.filter(ResponsesModel.poll_id == poll_id)
|
2019-12-16 23:06:25 +01:00
|
|
|
responses = {}
|
|
|
|
|
|
|
|
for response in raw_responses.all():
|
|
|
|
if responses.get(response.choice):
|
|
|
|
responses[response.choice] += 1
|
|
|
|
else:
|
|
|
|
responses[response.choice] = 1
|
2019-10-06 23:49:00 +02:00
|
|
|
|
|
|
|
for i, field in enumerate(content.get('fields')):
|
2019-12-16 23:06:25 +01:00
|
|
|
responders = responses.get(i, 0)
|
2019-10-08 18:54:05 +02:00
|
|
|
chart_options.get('data') \
|
|
|
|
.get('labels') \
|
|
|
|
.append(field.get('name')[5:].replace('__', ''))
|
|
|
|
chart_options.get('data') \
|
|
|
|
.get('datasets')[0] \
|
|
|
|
.get('data') \
|
|
|
|
.append(responders)
|
|
|
|
|
2019-10-06 23:49:00 +02:00
|
|
|
if responders <= 1:
|
|
|
|
field['value'] = f"**{responders}** vote"
|
|
|
|
else:
|
|
|
|
field['value'] = f"**{responders}** votes"
|
|
|
|
|
|
|
|
e = discord.Embed(description=content.get('description'))
|
|
|
|
e.set_author(
|
|
|
|
name=content.get('author').get('name'),
|
|
|
|
icon_url=content.get('author').get('icon_url')
|
|
|
|
)
|
2019-10-08 18:54:05 +02:00
|
|
|
chart_url = URL(chart_base_url + json.dumps(chart_options))
|
2019-10-09 00:14:43 +02:00
|
|
|
e.set_thumbnail(url=str(chart_url))
|
2019-10-06 23:49:00 +02:00
|
|
|
for field in content.get('fields'):
|
|
|
|
e.add_field(
|
|
|
|
name=field.get('name'),
|
|
|
|
value=field.get('value'),
|
|
|
|
inline=True
|
|
|
|
)
|
|
|
|
e.set_footer(text=content.get('footer').get('text'))
|
|
|
|
|
|
|
|
await message.edit(embed=e)
|
|
|
|
|
|
|
|
poll.content = json.dumps(content)
|
|
|
|
self.bot.database.session.commit()
|
|
|
|
|
2020-02-04 18:47:11 +01:00
|
|
|
@group_extra(name='poll', aliases=['sondage'], category='poll')
|
2019-10-06 01:49:30 +02:00
|
|
|
async def _poll(self, ctx: commands.Context):
|
|
|
|
if ctx.invoked_subcommand is None:
|
2020-01-15 00:08:53 +01:00
|
|
|
await ctx.send_help('poll')
|
2019-10-06 01:49:30 +02:00
|
|
|
|
2020-01-15 00:08:53 +01:00
|
|
|
@_poll.group(name='create', aliases=['new', 'nouveau'])
|
2019-10-06 01:49:30 +02:00
|
|
|
async def _poll_create(self, ctx: commands.Context, *, poll: str):
|
|
|
|
is_anonymous = '--anonyme' in poll
|
|
|
|
poll = poll.replace('--anonyme', '')
|
|
|
|
|
2019-10-26 23:19:47 +02:00
|
|
|
await self.create_poll(ctx, poll, anonymous=is_anonymous)
|
2019-09-28 01:39:45 +02:00
|
|
|
|
|
|
|
|
|
|
|
def setup(bot: TuxBot):
|
2020-01-15 00:08:53 +01:00
|
|
|
bot.add_cog(Poll(bot))
|