issue #2
This commit is contained in:
parent
b64ecd0133
commit
bba439f9b9
@ -1090,6 +1090,10 @@ class Poll:
|
|||||||
else:
|
else:
|
||||||
if [choice] == self.votes[user.id]['choices']:
|
if [choice] == self.votes[user.id]['choices']:
|
||||||
already_voted = True
|
already_voted = True
|
||||||
|
if self.anonymous:
|
||||||
|
# undo anonymous vote
|
||||||
|
await self.unvote(user, option, message)
|
||||||
|
return
|
||||||
else:
|
else:
|
||||||
self.votes[user.id]['choices'] = [choice]
|
self.votes[user.id]['choices'] = [choice]
|
||||||
else:
|
else:
|
||||||
@ -1102,7 +1106,7 @@ class Poll:
|
|||||||
if not already_voted:
|
if not already_voted:
|
||||||
# edit message if there is a real change
|
# edit message if there is a real change
|
||||||
await self.bot.edit_message(message, embed=await self.generate_embed())
|
await self.bot.edit_message(message, embed=await self.generate_embed())
|
||||||
pass
|
|
||||||
|
|
||||||
async def unvote(self, user, option, message):
|
async def unvote(self, user, option, message):
|
||||||
if not await self.is_open():
|
if not await self.is_open():
|
||||||
|
|||||||
@ -1,4 +1,5 @@
|
|||||||
import copy
|
import copy
|
||||||
|
import json
|
||||||
import logging
|
import logging
|
||||||
import discord
|
import discord
|
||||||
|
|
||||||
@ -91,7 +92,7 @@ class PollControls:
|
|||||||
return
|
return
|
||||||
if short is None:
|
if short is None:
|
||||||
pre = await get_server_pre(self.bot, ctx.message.server)
|
pre = await get_server_pre(self.bot, ctx.message.server)
|
||||||
error = f'Please specify the label of a poll after the close command. \n' \
|
error = f'Please specify the label of a poll after the delete command. \n' \
|
||||||
f'`{pre}close <poll_label>`'
|
f'`{pre}close <poll_label>`'
|
||||||
await self.say_error(ctx, error)
|
await self.say_error(ctx, error)
|
||||||
else:
|
else:
|
||||||
@ -341,100 +342,147 @@ class PollControls:
|
|||||||
return poll
|
return poll
|
||||||
|
|
||||||
# BOT EVENTS (@bot.event)
|
# BOT EVENTS (@bot.event)
|
||||||
async def on_reaction_add(self, reaction, user):
|
async def on_socket_raw_receive(self, raw_msg):
|
||||||
if user != self.bot.user:
|
if not isinstance(raw_msg, str):
|
||||||
try:
|
return
|
||||||
if isinstance(reaction.emoji, str) and reaction.emoji.startswith(('⏪', '⏩')):
|
msg = json.loads(raw_msg)
|
||||||
return
|
type = msg.get("t")
|
||||||
except:
|
data = msg.get("d")
|
||||||
logger.warning("fail emoji "+str(reaction.emoji))
|
if not data:
|
||||||
|
return
|
||||||
|
emoji = data.get("emoji")
|
||||||
|
user_id = data.get("user_id")
|
||||||
|
message_id = data.get("message_id")
|
||||||
|
if type == "MESSAGE_REACTION_ADD":
|
||||||
|
await self.do_on_reaction_add(data)
|
||||||
|
elif type == "MESSAGE_REACTION_REMOVE":
|
||||||
|
await self.do_on_reaction_remove(data)
|
||||||
|
|
||||||
# only look at our polls
|
async def do_on_reaction_remove(self, data):
|
||||||
try:
|
# get emoji symbol
|
||||||
short = reaction.message.embeds[0]['author']['name'][3:]
|
emoji = data.get('emoji')
|
||||||
if not reaction.message.embeds[0]['author']['name'].startswith('>> ') or not short:
|
if emoji:
|
||||||
return
|
emoji = emoji.get('name')
|
||||||
except IndexError:
|
if not emoji:
|
||||||
return
|
|
||||||
|
|
||||||
# create message object for the reaction
|
|
||||||
user_msg = copy.deepcopy(reaction.message)
|
|
||||||
user_msg.author = user
|
|
||||||
|
|
||||||
server = await ask_for_server(self.bot, user_msg, short)
|
|
||||||
if str(user_msg.channel.type) == 'private':
|
|
||||||
user = server.get_member(user.id)
|
|
||||||
user_msg.author = user
|
|
||||||
|
|
||||||
# fetch poll
|
|
||||||
p = await Poll.load_from_db(self.bot, server.id, short)
|
|
||||||
if p is None:
|
|
||||||
return
|
|
||||||
|
|
||||||
# export
|
|
||||||
if (reaction.emoji == '📎'):
|
|
||||||
# sending file
|
|
||||||
file = await p.export()
|
|
||||||
if file is not None:
|
|
||||||
await self.bot.send_file(
|
|
||||||
user,
|
|
||||||
file,
|
|
||||||
content='Sending you the requested export of "{}".'.format(p.short)
|
|
||||||
)
|
|
||||||
return
|
|
||||||
|
|
||||||
# no rights, terminate function
|
|
||||||
if not await p.has_required_role(user):
|
|
||||||
await self.bot.remove_reaction(reaction.message, reaction.emoji, user)
|
|
||||||
await self.bot.send_message(user, f'You are not allowed to vote in this poll. Only users with '
|
|
||||||
f'at least one of these roles can vote:\n{", ".join(p.roles)}')
|
|
||||||
return
|
|
||||||
|
|
||||||
# order here is crucial since we can't determine if a reaction was removed by the bot or user
|
|
||||||
# update database with vote
|
|
||||||
await p.vote(user, reaction.emoji, reaction.message)
|
|
||||||
|
|
||||||
# check if we need to remove reactions (this will trigger on_reaction_remove)
|
|
||||||
if str(reaction.message.channel.type) != 'private':
|
|
||||||
if p.anonymous:
|
|
||||||
# immediately remove reaction
|
|
||||||
await self.bot.remove_reaction(reaction.message, reaction.emoji, user)
|
|
||||||
elif not p.multiple_choice:
|
|
||||||
# remove all other reactions
|
|
||||||
for r in reaction.message.reactions:
|
|
||||||
if r != reaction:
|
|
||||||
await self.bot.remove_reaction(reaction.message, r.emoji, user)
|
|
||||||
|
|
||||||
async def on_reaction_remove(self, reaction, user):
|
|
||||||
if reaction.emoji.startswith(('⏪', '⏩')):
|
|
||||||
return
|
return
|
||||||
|
|
||||||
# only look at our polls
|
# check if we can find a poll label
|
||||||
try:
|
message_id = data.get('message_id')
|
||||||
short = reaction.message.embeds[0]['author']['name'][3:]
|
channel_id = data.get('channel_id')
|
||||||
if not reaction.message.embeds[0]['author']['name'].startswith('>> ') or not short:
|
user_id = data.get('user_id')
|
||||||
return
|
channel = self.bot.get_channel(channel_id)
|
||||||
except IndexError:
|
user = await self.bot.get_user_info(user_id) # only do this once
|
||||||
|
if not channel:
|
||||||
|
# discord rapidly closes dm channels by desing
|
||||||
|
# put private channels back into the bots cache and try again
|
||||||
|
await self.bot.start_private_message(user)
|
||||||
|
channel = self.bot.get_channel(channel_id)
|
||||||
|
message = await self.bot.get_message(channel=channel, id=message_id)
|
||||||
|
label = None
|
||||||
|
if message and message.embeds:
|
||||||
|
embed = message.embeds[0]
|
||||||
|
label_object = embed.get('author')
|
||||||
|
if label_object:
|
||||||
|
label_full = label_object.get('name')
|
||||||
|
if label_full and label_full.startswith('>> '):
|
||||||
|
label = label_full[3:]
|
||||||
|
if not label:
|
||||||
return
|
return
|
||||||
|
|
||||||
# create message object for the reaction
|
|
||||||
user_msg = copy.deepcopy(reaction.message)
|
|
||||||
user_msg.author = user
|
|
||||||
|
|
||||||
server = await ask_for_server(self.bot, user_msg, short)
|
|
||||||
if str(user_msg.channel.type) == 'private':
|
|
||||||
user = server.get_member(user.id)
|
|
||||||
user_msg.author = user
|
|
||||||
|
|
||||||
# fetch poll
|
# fetch poll
|
||||||
p = await Poll.load_from_db(self.bot, server.id, short)
|
# create message object for the reaction sender, to get correct server
|
||||||
if p is None:
|
user_msg = copy.deepcopy(message)
|
||||||
|
user_msg.author = user
|
||||||
|
server = await ask_for_server(self.bot, user_msg, label)
|
||||||
|
p = await Poll.load_from_db(self.bot, server.id, label)
|
||||||
|
if not isinstance(p, Poll):
|
||||||
return
|
return
|
||||||
|
|
||||||
if not p.anonymous:
|
if not p.anonymous:
|
||||||
# for anonymous polls we can't unvote because we need to hide reactions
|
# for anonymous polls we can't unvote because we need to hide reactions
|
||||||
await p.unvote(user, reaction.emoji, reaction.message)
|
member = server.get_member(user_id)
|
||||||
|
await p.unvote(member, emoji, message)
|
||||||
|
|
||||||
|
|
||||||
|
async def do_on_reaction_add(self, data):
|
||||||
|
# dont look at bot's own reactions
|
||||||
|
user_id = data.get('user_id')
|
||||||
|
if user_id == self.bot.user.id:
|
||||||
|
return
|
||||||
|
|
||||||
|
# get emoji symbol
|
||||||
|
emoji = data.get('emoji')
|
||||||
|
if emoji:
|
||||||
|
emoji = emoji.get('name')
|
||||||
|
if not emoji:
|
||||||
|
return
|
||||||
|
|
||||||
|
# check if we can find a poll label
|
||||||
|
message_id = data.get('message_id')
|
||||||
|
channel_id = data.get('channel_id')
|
||||||
|
channel = self.bot.get_channel(channel_id)
|
||||||
|
user = await self.bot.get_user_info(user_id) # only do this once
|
||||||
|
if not channel:
|
||||||
|
# discord rapidly closes dm channels by desing
|
||||||
|
# put private channels back into the bots cache and try again
|
||||||
|
await self.bot.start_private_message(user)
|
||||||
|
channel = self.bot.get_channel(channel_id)
|
||||||
|
message = await self.bot.get_message(channel=channel, id=message_id)
|
||||||
|
label = None
|
||||||
|
if message and message.embeds:
|
||||||
|
embed = message.embeds[0]
|
||||||
|
label_object = embed.get('author')
|
||||||
|
if label_object:
|
||||||
|
label_full = label_object.get('name')
|
||||||
|
if label_full and label_full.startswith('>> '):
|
||||||
|
label = label_full[3:]
|
||||||
|
if not label:
|
||||||
|
return
|
||||||
|
|
||||||
|
# fetch poll
|
||||||
|
# create message object for the reaction sender, to get correct server
|
||||||
|
user_msg = copy.deepcopy(message)
|
||||||
|
user_msg.author = user
|
||||||
|
server = await ask_for_server(self.bot, user_msg, label)
|
||||||
|
p = await Poll.load_from_db(self.bot, server.id, label)
|
||||||
|
if not isinstance(p, Poll):
|
||||||
|
return
|
||||||
|
|
||||||
|
# export
|
||||||
|
if emoji == '📎':
|
||||||
|
# sending file
|
||||||
|
file = await p.export()
|
||||||
|
if file is not None:
|
||||||
|
await self.bot.send_file(
|
||||||
|
user,
|
||||||
|
file,
|
||||||
|
content='Sending you the requested export of "{}".'.format(p.short)
|
||||||
|
)
|
||||||
|
return
|
||||||
|
|
||||||
|
# no rights, terminate function
|
||||||
|
member = server.get_member(user_id)
|
||||||
|
if not await p.has_required_role(member):
|
||||||
|
await self.bot.remove_reaction(message, emoji, user)
|
||||||
|
await self.bot.send_message(user, f'You are not allowed to vote in this poll. Only users with '
|
||||||
|
f'at least one of these roles can vote:\n{", ".join(p.roles)}')
|
||||||
|
return
|
||||||
|
|
||||||
|
# order here is crucial since we can't determine if a reaction was removed by the bot or user
|
||||||
|
# update database with vote
|
||||||
|
await p.vote(member, emoji, message)
|
||||||
|
#
|
||||||
|
# check if we need to remove reactions (this will trigger on_reaction_remove)
|
||||||
|
if str(channel.type) != 'private':
|
||||||
|
if p.anonymous:
|
||||||
|
# immediately remove reaction and to be safe, remove all reactions
|
||||||
|
await self.bot.remove_reaction(message, emoji, user)
|
||||||
|
elif not p.multiple_choice:
|
||||||
|
# remove all other reactions
|
||||||
|
for r in message.reactions:
|
||||||
|
if r.emoji and r.emoji != emoji:
|
||||||
|
await self.bot.remove_reaction(message, r.emoji, user)
|
||||||
|
|
||||||
def setup(bot):
|
def setup(bot):
|
||||||
global logger
|
global logger
|
||||||
logger = logging.getLogger('bot')
|
logger = logging.getLogger('bot')
|
||||||
|
|||||||
@ -15,7 +15,8 @@ bot_config = {
|
|||||||
'pm_help': False,
|
'pm_help': False,
|
||||||
'status': discord.Status.online,
|
'status': discord.Status.online,
|
||||||
'owner_id': SETTINGS.owner_id,
|
'owner_id': SETTINGS.owner_id,
|
||||||
'fetch_offline_members': False
|
'fetch_offline_members': False,
|
||||||
|
'max_messages': 200000
|
||||||
}
|
}
|
||||||
|
|
||||||
bot = commands.Bot(**bot_config)
|
bot = commands.Bot(**bot_config)
|
||||||
@ -96,7 +97,6 @@ async def on_command_error(e, ctx):
|
|||||||
|
|
||||||
# log error
|
# log error
|
||||||
logger.error(f'{type(e).__name__}: {e}\n{"".join(traceback.format_tb(e.__traceback__))}')
|
logger.error(f'{type(e).__name__}: {e}\n{"".join(traceback.format_tb(e.__traceback__))}')
|
||||||
# raise(e)
|
|
||||||
|
|
||||||
if SETTINGS.msg_errors:
|
if SETTINGS.msg_errors:
|
||||||
# send discord message for unexpected errors
|
# send discord message for unexpected errors
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user