diff --git a/cogs/help.py b/cogs/help.py index eca79be..cb0e6d0 100644 --- a/cogs/help.py +++ b/cogs/help.py @@ -35,7 +35,8 @@ class Help: await self.bot.delete_message(msg) return None else: - await self.bot.remove_reaction(res.reaction.message, res.reaction.emoji, res.user) + if str(res.reaction.message.channel.type) != 'private': + await self.bot.remove_reaction(res.reaction.message, res.reaction.emoji, res.user) return res def get_help_embed(self, page, pre): @@ -90,19 +91,19 @@ class Help: 'type the command or type the command followed by the question to skip that first step.' 'Your Members need the or role to use these commands. More in 🛠 Configuration.', inline=False) - embed.add_field(name='🔹 **Quick Poll:** `!quick ` (optional)', + embed.add_field(name=f'🔹 **Quick Poll:** `{pre}quick ` (optional)', value='If you just need a quick poll, this is the way to go. All you have to specify is the ' 'question and your answers; the rest will be set to default values.', inline=False) - embed.add_field(name='🔹 **All Features:** `!new ` (optional)', + embed.add_field(name=f'🔹 **All Features:** `{pre}new ` (optional)', value='This command gives you full control over your poll. A step by step wizard will guide ' 'you through the process and you can specify options such as Multiple Choice, ' 'Anonymous Voting, Role Restriction, Role Weights and Deadline.', inline=False) - embed.add_field(name='🔹 **Prepare and Schedule:** `!prepare ` (optional)', - value='Similar to `!new`, this gives you all the options. But additionally, the poll will ' + embed.add_field(name=f'🔹 **Prepare and Schedule:** `{pre}prepare ` (optional)', + value=f'Similar to `{pre}new`, this gives you all the options. But additionally, the poll will ' 'be set to \'inactive\'. You can specify if the poll should activate at a certain time ' - 'and/or if you would like to manually `!activate` it. ' + f'and/or if you would like to manually `{pre}activate` it. ' 'Perfect if you are preparing for a team meeting!', inline=False) elif page == '🔍': @@ -110,13 +111,13 @@ class Help: value='All users can display and list polls, with the exception of prepared polls. ' 'Voting is done simply by using the reactions below the poll.', inline=False) - embed.add_field(name='🔹 **Show a Poll:** `!show `', + embed.add_field(name=f'🔹 **Show a Poll:** `{pre}show `', value='This command will refresh and display a poll. The votes in the message will always ' 'be up to date and accurate. The number of reactions can be different for a number ' 'of reasons and you can safely disregard them.', inline=False) - embed.add_field(name='🔹 **List Polls:** `!show <> | open | closed | prepared`', - value='If you just type `!show` without an argument it will default to `!show open`.' + embed.add_field(name=f'🔹 **List Polls:** `{pre}show <> | open | closed | prepared`', + value=f'If you just type `{pre}show` without an argument it will default to `{pre}show open`.' 'These commands will print a list of open, closed or prepared polls that exist on ' 'the server. The first word in bold is the label of the poll and after the colon, ' 'you can read the question. These lists are paginated and you can use the arrow ' @@ -127,24 +128,24 @@ class Help: value='All these commands can only be used by an or by the author of the poll. ' 'Go to 🛠 Configuration for more info on the permissions.', inline=False) - embed.add_field(name='🔹 **Close** `!close `', + embed.add_field(name=f'🔹 **Close** `{pre}close `', value='Polls will close automatically when their deadline is reached. But you can always ' 'close them manually by using this command. A closed poll will lock in the votes so ' 'users can no longer change, add or remove votes. Once closed, you can export a poll.', inline=False) - embed.add_field(name='🔹 **Delete** `!delete `', + embed.add_field(name=f'🔹 **Delete** `{pre}delete `', value='This will *permanently and irreversibly* delete a poll from the database. ' 'Once done, the label is freed up and can be assigned again.', inline=False) - embed.add_field(name='🔹 **Export** `!export `', + embed.add_field(name=f'🔹 **Export** `{pre}export `', value='You can use this command or react with 📎 to a closed poll to generate a report. ' 'The report will then be sent to you in discord via the bot. This utf8-textfile ' '(make sure to open it in an utf8-ready editor) will contain all the infos about the ' 'poll, including a detailed list of participants and their votes (just a list of names ' 'for anonymous polls).', inline=False) - embed.add_field(name='🔹 **Activate** `!activate `', - value='To see how you can prepare inactive polls read the `!prepare` command under Making ' + embed.add_field(name=f'🔹 **Activate** `{pre}activate `', + value=f'To see how you can prepare inactive polls read the `{pre}prepare` command under Making ' 'New Polls. This command is used to manually activate a prepared poll.', inline=False) @@ -152,17 +153,17 @@ class Help: embed.add_field(name='🛠 Configuration', value='To run any of these commands you need the **\"Manage Server\"** permisson.', inline=False) - embed.add_field(name='🔹 **Poll Admins** `!adminrole (optional)`', + embed.add_field(name=f'🔹 **Poll Admins** `{pre}adminrole (optional)`', value='This gives the rights to create polls and to control ALL polls on the server. ' - 'To see the current role for poll admin, run the command without an argument: `!adminrole`\n' + f'To see the current role for poll admin, run the command without an argument: `{pre}adminrole`\n' 'If you want to change the admin role to any other role, use the name of the new role ' - 'as the argument: !adminrole moderators', + f'as the argument: `{pre}adminrole moderators`', inline=False) - embed.add_field(name='🔹 **Poll Users** `!userrole (optional)`', + embed.add_field(name=f'🔹 **Poll Users** `{pre}userrole (optional)`', value='Everything here is identical to the admin role, except that Poll Users can only ' 'control the polls which were created by themselves.', inline=False) - embed.add_field(name='🔹 **Change Prefix** `!prefix `', + embed.add_field(name=f'🔹 **Change Prefix** `{pre}prefix `', value='This will change the bot prefix for your server. If you want to use a trailing ' 'whitespace, use "\w" instead of " " (discord deletes trailing whitespaces).', inline=False) diff --git a/cogs/poll.py b/cogs/poll.py index 6d32b11..a09746f 100644 --- a/cogs/poll.py +++ b/cogs/poll.py @@ -662,8 +662,7 @@ class Poll: if dt.tzinfo is None or dt.tzinfo.utcoffset(dt) is None: dt = dt.astimezone(pytz.utc) - now = datetime.datetime.utcnow().astimezone(pytz.utc) - + now = datetime.datetime.utcnow().replace(tzinfo=pytz.utc) if dt < now: raise DateOutOfRange(dt) return dt diff --git a/cogs/poll_controls.py b/cogs/poll_controls.py index 9ca2ef0..5f8592d 100644 --- a/cogs/poll_controls.py +++ b/cogs/poll_controls.py @@ -20,6 +20,8 @@ class PollControls: 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]: @@ -315,12 +317,17 @@ class PollControls: # Permission Check member = server.get_member(ctx.message.author.id) - result = await self.bot.db.config.find_one({'_id': str(server.id)}) - if result and result.get('admin_role') not in [r.name for r in member.roles] and result.get( - 'user_role') not in [r.name for r in member.roles]: - await self.bot.send_message(ctx.message.author, - 'You don\'t have sufficient rights to start new polls on this server. Please talk to the server admin.') - return + if not member.server_permissions.manage_server: + result = await self.bot.db.config.find_one({'_id': str(server.id)}) + if result and result.get('admin_role') not in [r.name for r in member.roles] and result.get( + 'user_role') not in [r.name for r in member.roles]: + pre = await get_server_pre(self.bot, server) + await self.bot.send_message(ctx.message.author, + 'You don\'t have sufficient rights to start new polls on this server. ' + 'A server administrator has to assign the user or admin role to you. ' + f'To view and set the permissions, an admin can use `{pre}userrole` and ' + f'`{pre}adminrole`') + return ## Create object poll = Poll(self.bot, ctx, server, channel) @@ -339,9 +346,11 @@ class PollControls: # BOT EVENTS (@bot.event) async def on_reaction_add(self, reaction, user): if user != self.bot.user: - - if reaction.emoji.startswith(('⏪', '⏩')): - return + try: + if reaction.emoji.startswith(('⏪', '⏩')): + return + except: + print("fail emoji",reaction.emoji) # only look at our polls try: diff --git a/essentials/multi_server.py b/essentials/multi_server.py index b98cf9c..c6cb007 100644 --- a/essentials/multi_server.py +++ b/essentials/multi_server.py @@ -7,7 +7,7 @@ async def get_pre(bot, message): if str(message.channel.type) == 'private': shared_server_list = await get_servers(bot, message) if shared_server_list.__len__() == 0: - return '!' + return 'pm!!' elif shared_server_list.__len__() == 1: return await get_server_pre(bot, shared_server_list[0]) else: @@ -22,9 +22,9 @@ async def get_server_pre(bot, server): try: result = await bot.db.config.find_one({'_id': str(server.id)}) except AttributeError: - return '!' + return 'pm!' if not result or not result.get('prefix'): - return '!' + return 'pm!!' return result.get('prefix') diff --git a/essentials/settings.py b/essentials/settings.py index 512373e..912f46c 100644 --- a/essentials/settings.py +++ b/essentials/settings.py @@ -6,9 +6,9 @@ from essentials.secrets import SECRETS class Settings: def __init__(self): self.color = discord.Colour(int('7289da', 16)) - self.title_icon = "http://mnadler.ch/img/donat-chart-32.png" - self.author_icon = "http://mnadler.ch/img/donat-chart-32.png" - self.report_icon = "http://mnadler.ch/img/poll-topic-64.png" + self.title_icon = "http://mnadler.ch/img/tag.png" + self.author_icon = "http://mnadler.ch/img/tag.jpg" + self.report_icon = "http://mnadler.ch/img/report.png" self.owner_id = 117687652278468610 self.msg_errors = False self.log_errors = True diff --git a/pollmaster.py b/pollmaster.py index 653c59b..de5eccc 100644 --- a/pollmaster.py +++ b/pollmaster.py @@ -45,6 +45,7 @@ extensions = ['cogs.config','cogs.poll_controls', 'cogs.help', 'cogs.db_api'] for ext in extensions: bot.load_extension(ext) + @bot.event async def on_ready(): bot.owner = await bot.get_user_info(str(SETTINGS.owner_id)) @@ -55,6 +56,16 @@ async def on_ready(): print(bot.db) await bot.change_presence(game=discord.Game(name=f'pm!help')) + # check discord server configs + db_server_ids = [entry['_id'] async for entry in bot.db.config.find({}, {})] + for server in bot.servers: + if server.id not in db_server_ids: + await bot.db.config.update_one( + {'_id': str(server.id)}, + {'$set': {'prefix': 'pm!', 'admin_role': 'polladmin', 'user_role': 'polluser'}}, + upsert=True + ) + @bot.event async def on_command_error(e, ctx): @@ -86,14 +97,18 @@ async def on_command_error(e, ctx): f"\n\tAuthor: <@{ctx.message.author.id}>", timestamp=ctx.message.timestamp ) - await bot.send_message(bot.owner,embed=e) + await bot.send_message(bot.owner, embed=e) + @bot.event async def on_server_join(server): result = await bot.db.config.find_one({'_id': str(server.id)}) if result is None: - await bot.db.config.update_one({'_id': str(server.id)}, - {'$set': {'prefix': 'pm!', 'admin_role': 'polladmin', 'user_role': 'polluser'}}, - upsert=True) + await bot.db.config.update_one( + {'_id': str(server.id)}, + {'$set': {'prefix': 'pm!', 'admin_role': 'polladmin', 'user_role': 'polluser'}}, + upsert=True + ) -bot.run(SETTINGS.bot_token) \ No newline at end of file + +bot.run(SETTINGS.bot_token, reconnect=True) \ No newline at end of file