import argparse import asyncio import copy import datetime import json import logging import re import shlex import string import traceback import discord import pytz from discord.ext import commands from utils.misc import CustomFormatter from .poll import Poll from utils.paginator import embed_list_paginated from essentials.multi_server import get_server_pre, ask_for_server, ask_for_channel from essentials.settings import SETTINGS from utils.poll_name_generator import generate_word from essentials.exceptions import StopWizard ## A-Z Emojis for Discord AZ_EMOJIS = [(b'\\U0001f1a'.replace(b'a', bytes(hex(224 + (6 + i))[2:], "utf-8"))).decode("unicode-escape") for i in range(26)] class PollControls: def __init__(self, bot): self.bot = bot self.bot.loop.create_task(self.close_polls()) self.ignore_next_removed_reaction = {} # General Methods async def close_polls(self): """This function runs every 60 seconds to schedule prepared polls and close expired polls""" while True: try: query = self.bot.db.polls.find({'active': False, 'activation': {"$not": re.compile("0")}}) if query: for pd in [poll async for poll in query]: p = Poll(self.bot, load=True) await p.from_dict(pd) if not p.server: continue if p.active: await self.bot.send_message(p.channel, 'This poll has been scheduled and is active now!') await p.post_embed(destination=p.channel) query = self.bot.db.polls.find({'open': True, 'duration': {"$not": re.compile("0")}}) if query: for pd in [poll async for poll in query]: p = Poll(self.bot, load=True) await p.from_dict(pd) if not p.server: continue if not p.open: await self.bot.send_message(p.channel, 'This poll has reached the deadline and is closed!') await p.post_embed(destination=p.channel) except AttributeError as ae: #Database not loaded yet logger.warning("Attribute Error in close_polls loop") logger.exception(ae) pass except Exception as ex: #Never break this loop due to an error logger.error("Other Error in close_polls loop") logger.exception(ex) pass await asyncio.sleep(30) def get_lock(self, server_id): if not self.bot.locks.get(str(server_id)): self.bot.locks[server_id] = asyncio.Lock() return self.bot.locks.get(str(server_id)) async def is_admin_or_creator(self, ctx, server, owner_id, error_msg=None): member = server.get_member(ctx.message.author.id) if member.id == owner_id: return True elif member.server_permissions.manage_server: return True else: result = await self.bot.db.config.find_one({'_id': str(server.id)}) if result and result.get('admin_role') in [r.name for r in member.roles]: return True else: if error_msg is not None: await self.bot.send_message(ctx.message.author, error_msg) return False async def say_error(self, ctx, error_text, footer_text=None): embed = discord.Embed(title='', description=error_text, colour=SETTINGS.color) embed.set_author(name='Error', icon_url=SETTINGS.author_icon) if footer_text is not None: embed.set_footer(text=footer_text) await self.bot.say(embed=embed) async def say_embed(self, ctx, say_text='', title='Pollmaster', footer_text=None): embed = discord.Embed(title='', description=say_text, colour=SETTINGS.color) embed.set_author(name=title, icon_url=SETTINGS.author_icon) if footer_text is not None: embed.set_footer(text=footer_text) await self.bot.say(embed=embed) # Commands @commands.command(pass_context=True) async def activate(self, ctx, *, short=None): """Activate a prepared poll. Parameter: