Add voting statics to admin panel

This commit is contained in:
Jeremy Zhang 2018-03-19 08:28:09 +00:00
parent bc4ad88372
commit 99afd2aeb7
5 changed files with 218 additions and 3 deletions

View File

@ -1,12 +1,13 @@
from flask import Blueprint, url_for, redirect, session, render_template, abort, request, jsonify
from flask_socketio import emit
from functools import wraps
from titanembeds.database import db, get_administrators_list, Cosmetics, Guilds, UnauthenticatedUsers, UnauthenticatedBans, TitanTokens, TokenTransactions, get_titan_token, set_titan_token, list_disabled_guilds, DisabledGuilds, UserCSS, AuthenticatedUsers
from titanembeds.database import db, get_administrators_list, Cosmetics, Guilds, UnauthenticatedUsers, UnauthenticatedBans, TitanTokens, TokenTransactions, get_titan_token, set_titan_token, list_disabled_guilds, DisabledGuilds, UserCSS, AuthenticatedUsers, DiscordBotsOrgTransactions, GuildMembers
from titanembeds.oauth import generate_guild_icon_url
from titanembeds.utils import get_online_embed_user_keys
import datetime
import json
from sqlalchemy import func
import operator
admin = Blueprint("admin", __name__)
@ -374,3 +375,74 @@ def new_custom_css_post():
db.session.add(css)
db.session.commit()
return jsonify({"id": css.id})
@admin.route("/voting", methods=["GET"])
@is_admin
def voting_get():
datestart = request.args.get("datestart")
timestart = request.args.get("timestart")
dateend = request.args.get("dateend")
timeend = request.args.get("timeend")
if not datestart or not timestart or not dateend or not timeend:
return render_template("admin_voting.html.j2")
start = datetime.datetime.strptime(datestart + " " + timestart, '%d %B, %Y %H:%M%p')
end = datetime.datetime.strptime(dateend + " " + timeend, '%d %B, %Y %H:%M%p')
users = db.session.query(DiscordBotsOrgTransactions).filter(DiscordBotsOrgTransactions.timestamp >= start, DiscordBotsOrgTransactions.timestamp <= end).order_by(DiscordBotsOrgTransactions.timestamp)
all_users = []
for u in users:
uid = u.user_id # Let's fix this OBO error
gmember = db.session.query(GuildMembers).filter(GuildMembers.user_id == uid).first()
if not gmember:
uid = u.user_id + 1
all_users.append({
"id": u.id,
"user_id": uid,
"timestamp": u.timestamp,
"action": u.action,
"referrer": u.referrer
})
overall_votes = {}
for u in all_users:
uid = u["user_id"]
action = u["action"]
if uid not in overall_votes:
overall_votes[uid] = 0
if action == "none":
overall_votes[uid] = overall_votes[uid] - 1
if action == "upvote":
overall_votes[uid] = overall_votes[uid] + 1
sorted_overall_votes = []
for uid, votes in sorted(overall_votes.items(), key=operator.itemgetter(1), reverse=True):
sorted_overall_votes.append(uid)
overall = []
for uid in sorted_overall_votes:
gmember = db.session.query(GuildMembers).filter(GuildMembers.user_id == uid).first()
u = {
"user_id": uid,
"votes": overall_votes[uid]
}
if gmember:
u["discord"] = gmember.username + "#" + str(gmember.discriminator)
overall.append(u)
referrer = {}
for u in all_users:
if not u["referrer"] or u["referrer"] == u["user_id"]:
continue
refer = u["referrer"]
if refer not in referrer:
referrer[refer] = 0
referrer[refer] = referrer[refer] + 1
sorted_referrers = []
for uid, votes in sorted(referrer.items(), key=operator.itemgetter(1), reverse=True):
sorted_referrers.append(uid)
referrals = []
for uid in sorted_referrers:
gmember = db.session.query(GuildMembers).filter(GuildMembers.user_id == uid).first()
u = {
"user_id": uid,
"votes": referrer[uid]
}
if gmember:
u["discord"] = gmember.username + "#" + str(gmember.discriminator)
referrals.append(u)
return render_template("admin_voting.html.j2", overall=overall, referrals=referrals)

View File

@ -503,6 +503,6 @@ def webhook_discordbotsorg_vote():
referrer = int(float(params["referrer"]))
except:
pass
DBLTrans = DiscordBotsOrgTransactions(int(float(user_id)), vote_type, referrer)
DBLTrans = DiscordBotsOrgTransactions(int(user_id), vote_type, referrer)
db.session.add(DBLTrans)
return ('', 204)

View File

@ -0,0 +1,33 @@
(function () {
$('.timepicker').pickatime({
default: 'now', // Set default time: 'now', '1:30AM', '16:30'
fromnow: 0, // set default time to * milliseconds from now (using with default = 'now')
twelvehour: true, // Use AM/PM or 24-hour format
donetext: 'OK', // text for done-button
cleartext: 'Clear', // text for clear-button
canceltext: 'Cancel', // Text for cancel-button
autoclose: true, // automatic close timepicker
ampmclickable: true, // make AM PM clickable
aftershow: function(){} //Function for after opening timepicker
});
$('.datepicker').pickadate({
selectMonths: true, // Creates a dropdown to control month
selectYears: 15, // Creates a dropdown of 15 years to control year,
today: 'Today',
clear: 'Clear',
close: 'Ok',
closeOnSelect: true // Close upon selecting a date,
});
$("#submit").click(function () {
var params = {
datestart: $("#datestart").val(),
timestart: $("#timestart").val(),
dateend: $("#dateend").val(),
timeend: $("#timeend").val()
}
var formatted = $.param( params );
location.assign("/admin/voting?" + formatted);
});
})();

View File

@ -42,6 +42,13 @@
<a class="waves-effect waves-light btn" href="{{ url_for('admin.list_custom_css_get') }}">Manage</a>
</div>
</div>
<div class="col s12">
<div class="card-panel indigo lighten-5 z-depth-3 hoverable black-text">
<h4>Voting Statistics</h4>
<p class="flow-text">Discord Bot List Voting Statics.</p>
<a class="waves-effect waves-light btn" href="{{ url_for('admin.voting_get') }}">Manage</a>
</div>
</div>
<div class="col s12">
<div class="card-panel indigo lighten-5 z-depth-3 hoverable black-text">
<h4>Disabled Servers</h4>

View File

@ -0,0 +1,103 @@
{% extends 'site_layout.html.j2' %}
{% set title="Voting Statistics" %}
{% block content %}
<h1>Viewing Vote Statistics</h1>
<div class="row">
<div class="col s12">
<div class="card-panel indigo lighten-5 z-depth-3 hoverable black-text">
<p class="flow-text">Select Date/Time Range</p>
<table class="bordered striped">
<thead>
<tr>
<th>Start</th>
<th>End</th>
<th>Submit</th>
</tr>
</thead>
<tbody>
<tr>
<td>
<div class="input-field inline">
<input id="datestart" type="text" class="datepicker" palceholder="Start Date">
</div>
<div class="input-field inline">
<input id="timestart" type="text" class="timepicker" palceholder="Start Time">
</div>
</td>
<td>
<div class="input-field inline">
<input id="dateend" type="text" class="datepicker" palceholder="End Date">
</div>
<div class="input-field inline">
<input id="timeend" type="text" class="timepicker" palceholder="End Time">
</div>
</td>
<td>
<a class="waves-effect waves-light btn" id="submit">Submit</a>
</td>
</tr>
</tbody>
</table>
<p>* Timezone will be whatever the server timezone is. Probably UTC.</p>
</div>
</div>
<div class="col s12">
<div class="card-panel indigo lighten-5 z-depth-3 hoverable black-text">
<h3>Best Voters</h3>
<table class="bordered striped">
<thead>
<tr>
<th>Place</th>
<th>User ID</th>
<th>Discord</th>
<th>Votes</th>
</tr>
</thead>
<tbody>
{% for usr in overall %}
<tr>
<td>{{ loop.index }}</td>
<td>{{ usr.user_id }}</td>
<td>{{ usr.discord }}</td>
<td>{{ usr.votes }}</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
<div class="col s12">
<div class="card-panel indigo lighten-5 z-depth-3 hoverable black-text">
<h3>Best Referrers</h3>
<table class="bordered striped">
<thead>
<tr>
<th>Place</th>
<th>User ID</th>
<th>Discord</th>
<th>Referrals Redeemed</th>
</tr>
</thead>
<tbody>
{% for usr in referrals %}
<tr>
<td>{{ loop.index }}</td>
<td>{{ usr.user_id }}</td>
<td>{{ usr.discord }}</td>
<td>{{ usr.votes }}</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
</div>
{% endblock %}
{% block script %}
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.18.1/moment.min.js" integrity="sha256-1hjUhpc44NwiNg8OwMu2QzJXhD8kcj+sJA3aCQZoUjg=" crossorigin="anonymous"></script>
<script type="text/javascript" src="{{ url_for('static', filename='js/admin_voting.js') }}"></script>
{% endblock %}