migration prep

This commit is contained in:
matnad 2019-02-11 14:40:40 +01:00
parent 640a274146
commit c220b5b590
6 changed files with 165 additions and 15 deletions

45
changelog.md Normal file
View File

@ -0,0 +1,45 @@
# Changelog for Version 2.0
## TL;DR
- Poll creation now interactive
- New prefix: **pm!** (can be customized)
- All commands and roles have been changed, check **pm!help**
## Complete Overhaul
- Voting is no longer done per text, but by using reactions
- Poll creation has been streamlined and is now interactive
- An exhaustive pm!help function
## New features
- Prepare polls in advance and schedule them or activate them on demand
- A quick poll function with default settings
- Multiple Choice as new settings (allow more than one answer)
## Full Private Message and Multi Server Support
- **Every command can be used in private messages with pollmaster**
- This works even if you are in many servers with the bot
- Context sensitive detection of which server(s) are affected
- Promt the user for a server if still ambiguous
## New Look
- Complete visual overhaul for every aspect
- New custom icons
## New Database
- Changed the way all the polls are stored
- Added server specific configurations
## New Prefix
- **pm!** is the new default prefix
- Prefix can be customized for each server
## New roles and permissions
- Users with "Manage Server" permissions can now use all functions regardless of pollmaster specific permissions
- Two new type of roles: *polladmin* and *polluser*
- They can be set with *!polladmin role* and *!polluser role*
- More infos pm!help -> configuration
- The *pollmaster* role is deprecated
## Compability
- Most databases will be preserved and converted to the new format
- If your server lost data, please join the support server or contact the developer

View File

@ -705,10 +705,18 @@ class Poll:
async def to_dict(self): async def to_dict(self):
if self.channel is None:
cid = 0
else:
cid = self.channel.id
if self.author is None:
aid = 0
else:
aid = self.author.id
return { return {
'server_id': str(self.server.id), 'server_id': str(self.server.id),
'channel_id': str(self.channel.id), 'channel_id': str(cid),
'author': str(self.author.id), 'author': str(aid),
'name': self.name, 'name': self.name,
'short': self.short, 'short': self.short,
'anonymous': self.anonymous, 'anonymous': self.anonymous,
@ -827,9 +835,9 @@ class Poll:
return None return None
async def from_dict(self, d): async def from_dict(self, d):
self.server = self.bot.get_server(d['server_id']) self.server = self.bot.get_server(str(d['server_id']))
self.channel = self.bot.get_channel(d['channel_id']) self.channel = self.bot.get_channel(str(d['channel_id']))
self.author = await self.bot.get_user_info(d['author']) self.author = await self.bot.get_user_info(str(d['author']))
self.name = d['name'] self.name = d['name']
self.short = d['short'] self.short = d['short']
self.anonymous = d['anonymous'] self.anonymous = d['anonymous']

View File

@ -215,7 +215,8 @@ class PollControls:
query = self.bot.db.polls.find({'server_id': str(server.id), 'active': False}) query = self.bot.db.polls.find({'server_id': str(server.id), 'active': False})
if query is not None: if query is not None:
polls = [poll async for poll in query] # sort by newest first
polls = [poll async for poll in query.sort('_id', -1)]
else: else:
return return
@ -228,9 +229,9 @@ class PollControls:
# await self.bot.say(embed=await self.embed_list_paginated(polls, item_fct, embed)) # await self.bot.say(embed=await self.embed_list_paginated(polls, item_fct, embed))
# msg = await self.embed_list_paginated(ctx, polls, item_fct, embed, per_page=8) # msg = await self.embed_list_paginated(ctx, polls, item_fct, embed, per_page=8)
pre = await get_server_pre(self.bot, server) pre = await get_server_pre(self.bot, server)
footer_text = '' # f'type {pre}show <label> to display a poll. footer_text = f'type {pre}show <label> to display a poll. '
msg = await embed_list_paginated(self.bot, pre, polls, item_fct, embed, footer_prefix=footer_text, msg = await embed_list_paginated(self.bot, pre, polls, item_fct, embed, footer_prefix=footer_text,
per_page=8) per_page=10)
else: else:
p = await Poll.load_from_db(self.bot, str(server.id), short) p = await Poll.load_from_db(self.bot, str(server.id), short)
if p is not None: if p is not None:
@ -347,10 +348,10 @@ class PollControls:
async def on_reaction_add(self, reaction, user): async def on_reaction_add(self, reaction, user):
if user != self.bot.user: if user != self.bot.user:
try: try:
if reaction.emoji.startswith(('', '')): if isinstance(reaction.emoji, str) and reaction.emoji.startswith(('', '')):
return return
except: except:
print("fail emoji",reaction.emoji) logger.warning("fail emoji "+str(reaction.emoji))
# only look at our polls # only look at our polls
try: try:

View File

@ -1,16 +1,15 @@
import datetime
import os
import traceback import traceback
import logging import logging
import aiohttp import aiohttp
import discord import discord
from discord.ext import commands from discord.ext import commands
from motor.motor_asyncio import AsyncIOMotorClient from motor.motor_asyncio import AsyncIOMotorClient
from essentials.multi_server import get_pre from essentials.multi_server import get_pre
from essentials.settings import SETTINGS from essentials.settings import SETTINGS
from utils.import_old_database import import_old_database
bot_config = { bot_config = {
'command_prefix': get_pre, 'command_prefix': get_pre,
@ -60,12 +59,29 @@ async def on_ready():
db_server_ids = [entry['_id'] async for entry in bot.db.config.find({}, {})] db_server_ids = [entry['_id'] async for entry in bot.db.config.find({}, {})]
for server in bot.servers: for server in bot.servers:
if server.id not in db_server_ids: if server.id not in db_server_ids:
# create new config entry
await bot.db.config.update_one( await bot.db.config.update_one(
{'_id': str(server.id)}, {'_id': str(server.id)},
{'$set': {'prefix': 'pm!', 'admin_role': 'polladmin', 'user_role': 'polluser'}}, {'$set': {'prefix': 'pm!', 'admin_role': 'polladmin', 'user_role': 'polluser'}},
upsert=True upsert=True
) )
#await import_old_database(bot, server)
# text = 'Test Update Notice. Please Ignore.'
text = "Dear Server Admin!\n" \
"After more than a year in the field, today Pollmaster received it's first big update and I am excited to present you the new Version!\n" \
"**TL;DR** A massive overhaul of every function. The new (now customizable) prefix is pm! and you can find the rest of commands with pm!help\n\n" \
"Here are some more highlights:\n" \
"🔹 Voting is no longer done per text, but by using reactions\n" \
"🔹 Creating new polls is now an interactive process instead of command lines\n" \
"🔹 There is now a settings for multiple choice polls\n" \
"🔹 You can use all the commands in a private message with Pollmaster to reduce spam in your channels\n\n" \
"For the full changelog, please visit: "
# embed = discord.Embed(title="Pollmaster updated to version 2!", description=text, color=SETTINGS.color)
# await bot.send_message(server.owner, embed= embed)
@bot.event @bot.event
async def on_command_error(e, ctx): async def on_command_error(e, ctx):
@ -87,6 +103,7 @@ 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

View File

@ -0,0 +1,79 @@
import datetime
import json
import os
import pytz
async def import_old_database(bot, server):
"""try to import the old database"""
try:
clean_server = str(server).replace("/", "")
while clean_server.startswith("."):
clean_server = clean_server[1:]
fn = 'backup/' + clean_server + '.json'
with open(fn, 'r') as infile:
polls = json.load(infile)
for p in polls:
#print(polls[p]['short'])
wr = []
wn = []
for r, n in polls[p]['weights'].items():
wr.append(r)
try:
if n.is_integer():
n = int(n)
except:
pass
wn.append(n)
created = datetime.datetime.strptime(polls[p]['datestarted'], '%d-%m-%Y %H:%M').replace(tzinfo=pytz.utc)
if polls[p]['duration'] == 0:
duration = 0
else:
duration = created + datetime.timedelta(hours=float(polls[p]['duration']))
votes = {}
for u,o in polls[p]['votes'].items():
# get weight
user = server.get_member(u)
weight = 1
if wr.__len__() > 0:
valid_weights = [wn[wr.index(r)] for r in
list(set([n.name for n in user.roles]).intersection(set(wr)))]
if valid_weights.__len__() > 0:
#print(wr, wn)
weight = max(valid_weights)
choices = []
if o in polls[p]['options']:
choices = [polls[p]['options'].index(o)]
votes[u] = {'weight': weight, 'choices': choices}
new_format = {
'server_id': str(server.id),
'channel_id': str(polls[p]['channel']),
'author': str(polls[p]['author']),
'name': polls[p]['name'],
'short': polls[p]['short'],
'anonymous': polls[p]['anonymous'],
'reaction': True,
'multiple_choice': False,
'options_reaction': polls[p]['options'],
'reaction_default': False,
'roles': polls[p]['roles'],
'weights_roles': wr,
'weights_numbers': wn,
'duration': duration,
'duration_tz': 'UTC',
'time_created': created,
'open': polls[p]['open'],
'active': True,
'activation': 0,
'activation_tz': 'UTC',
'votes': votes
}
await bot.db.polls.update_one({'server_id': str(server.id), 'short': polls[p]['short']},
{'$set': new_format}, upsert=True)
#os.remove(fn)
except FileNotFoundError:
pass
except Exception as e:
print(e)

View File

@ -39,6 +39,6 @@ async def embed_list_paginated(bot, pre, items, item_fct, base_embed, footer_pre
if res is None: if res is None:
return return
elif res.reaction.emoji == '' and start > 0: elif res.reaction.emoji == '' and start > 0:
await embed_list_paginated(bot, pre, items, item_fct, base_embed, msg=msg, start=start-per_page, per_page=per_page) await embed_list_paginated(bot, pre, items, item_fct, base_embed, footer_prefix=footer_prefix, msg=msg, start=start-per_page, per_page=per_page)
elif res.reaction.emoji == '' and items.__len__() > start+per_page: elif res.reaction.emoji == '' and items.__len__() > start+per_page:
await embed_list_paginated(bot, pre, items, item_fct, base_embed, msg=msg, start=start+per_page, per_page=per_page) await embed_list_paginated(bot, pre, items, item_fct, base_embed, footer_prefix=footer_prefix, msg=msg, start=start+per_page, per_page=per_page)