Compare commits

...

8 Commits

  1. 81
      app/models.py
  2. 4
      app/teamspeak.py
  3. 89
      app/templates/hero_random.html
  4. 1
      app/templates/layout.html
  5. 9
      app/templates/private_profile.html
  6. 19
      app/templates/profile.html
  7. 18
      app/views.py
  8. 34
      migrations/versions/50e77b6e7331_.py
  9. 5
      requirements.txt
  10. 14
      run.py

81
app/models.py

@ -1,6 +1,5 @@
import simplejson as json import simplejson as json
from datetime import datetime
from random import choice
from datetime import datetime, timedelta
from flask.ext.sqlalchemy import SQLAlchemy from flask.ext.sqlalchemy import SQLAlchemy
from sqlalchemy.ext.mutable import Mutable from sqlalchemy.ext.mutable import Mutable
@ -69,16 +68,14 @@ class User(db.Model):
nickname = db.Column(db.String(80)) nickname = db.Column(db.String(80))
avatar = db.Column(db.String(255)) avatar = db.Column(db.String(255))
admin = db.Column(db.Boolean)
bio_text = db.Column(db.String(4096)) bio_text = db.Column(db.String(4096))
created = db.Column(db.DateTime) created = db.Column(db.DateTime)
last_seen = db.Column(db.DateTime) last_seen = db.Column(db.DateTime)
twitch = db.Column(db.String(60)) twitch = db.Column(db.String(60))
hitbox = db.Column(db.String(60)) hitbox = db.Column(db.String(60))
random_heroes = db.Column(MutableDict.as_mutable(Json))
az_completions = db.Column(db.Integer)
admin = db.Column(db.Boolean)
public = db.Column(db.Boolean) public = db.Column(db.Boolean)
logo = db.Column(db.Boolean) logo = db.Column(db.Boolean)
@ -89,7 +86,8 @@ class User(db.Model):
ts3_starttime = db.Column(db.DateTime) ts3_starttime = db.Column(db.DateTime)
ts3_endtime = db.Column(db.DateTime) ts3_endtime = db.Column(db.DateTime)
ts3_rewardtime = db.Column(db.DateTime) ts3_rewardtime = db.Column(db.DateTime)
ts3_connections = db.Column(MutableDict.as_mutable(Json))
ts3_stretch_award_time = db.Column(db.DateTime)
ts3_longest_stretch = db.Column(db.Interval)
last_post_reward = db.Column(db.Integer) last_post_reward = db.Column(db.Integer)
winrate_data = db.Column(MutableDict.as_mutable(Json)) winrate_data = db.Column(MutableDict.as_mutable(Json))
@ -114,10 +112,9 @@ class User(db.Model):
def __init__(self, steam_id): def __init__(self, steam_id):
self.steam_id = steam_id self.steam_id = steam_id
self.random_heroes = {'current':None, 'completed':[]}
self.az_completions = 0 self.az_completions = 0
self.ts3_connections = {'list':[]}
self.ts3_rewardtime = datetime.utcnow() self.ts3_rewardtime = datetime.utcnow()
self.ts3_longest_stretch = timedelta()
self.created = datetime.utcnow() self.created = datetime.utcnow()
self.last_seen = datetime.utcnow() self.last_seen = datetime.utcnow()
self.bio_text = None self.bio_text = None
@ -127,64 +124,33 @@ class User(db.Model):
self.admin = False self.admin = False
self.public = True self.public = True
self.biglogo = True self.biglogo = True
@property
def random_hero(self):
if not self.random_heroes['current']:
heroes = []
for (tavern_name, tavern) in parse_valve_heropedia():
heroes.extend([complete_hero_data('name', entry['name']) for entry in tavern if entry['name'] not in self.random_heroes['completed']])
if heroes:
self.random_heroes['current'] = choice(heroes)
self.random_heroes = self.random_heroes
db.session.commit()
return self.random_heroes['current']
@random_hero.setter
def random_hero(self, herodata):
self.random_heroes['current'] = herodata
self.random_heroes = self.random_heroes
db.session.commit()
@property
def random_completed(self):
return self.random_heroes['completed']
def random_success(self):
self.random_heroes['completed'].append(self.random_heroes['current']['name'])
if len(API_DATA['result']['heroes']) - len(self.random_heroes['completed']) <= 0:
self.az_completions = self.az_completions + 1
del self.random_heroes['completed'][:]
self.random_heroes['current'] = None
self.random_heroes = self.random_heroes
db.session.commit()
return self.random_hero
def random_skip(self):
self.random_heroes['current'] = None
self.random_heroes = self.random_heroes
db.session.commit()
return self.random_hero
def update_connection(self, reward_threshold=30): def update_connection(self, reward_threshold=30):
now = datetime.utcnow() now = datetime.utcnow()
self.ts3_starttime = self.ts3_starttime or now self.ts3_starttime = self.ts3_starttime or now
self.ts3_endtime = now self.ts3_endtime = now
# Add general TS3 points here # Add general TS3 points here
if self.ts3_endtime and self.ts3_rewardtime:
delta = (self.ts3_endtime - self.ts3_rewardtime)
duration = (delta.seconds % 3600) // 60
if duration > reward_threshold:
self.ts3_rewardtime = datetime.utcnow()
self.points_from_ts3 += 1
else:
self.ts3_rewardtime = datetime.utcnow()
delta = (self.ts3_endtime - self.ts3_rewardtime)
duration = (delta.seconds % 3600) // 60
if duration > reward_threshold:
self.ts3_rewardtime = datetime.utcnow()
self.points_from_ts3 += 1
# Update last_seen for web profile
self.last_seen = datetime.utcnow() self.last_seen = datetime.utcnow()
db.session.commit(); db.session.commit();
def finalize_connection(self): def finalize_connection(self):
self.ts3_connections['list'].append({'starttime': self.ts3_starttime, 'endtime': self.ts3_endtime})
self.ts3_startime = None
# Check for longest!
if self.ts3_endtime and self.ts3_starttime:
current_stretch = self.ts3_endtime - self.ts3_starttime
if current_stretch > self.ts3_longest_stretch:
self.ts3_longest_stretch = current_stretch
self.ts3_stretch_award_time = datetime.utcnow()
# Reset values
self.ts3_starttime = None
self.ts3_endtime = None self.ts3_endtime = None
db.session.commit(); db.session.commit();
@ -193,6 +159,7 @@ class User(db.Model):
posts = board.Users.select().where(board.Users.id == int(self.forum_id))[0].posts posts = board.Users.select().where(board.Users.id == int(self.forum_id))[0].posts
if self.last_post_reward: if self.last_post_reward:
num_points = (posts - self.last_post_reward) / reward_threshold num_points = (posts - self.last_post_reward) / reward_threshold
print("Old: {0}, New: {1}, ({0} - {1}) / {2}, {3}, {4}".format(self.last_post_reward, posts, reward_threshold, num_points, self.nickname))
if num_points > 0: if num_points > 0:
self.points_from_forum += num_points self.points_from_forum += num_points
self.last_post_reward += num_points * reward_threshold self.last_post_reward += num_points * reward_threshold
@ -308,7 +275,7 @@ class Event(db.Model):
@property @property
def expired(self): def expired(self):
current_time = datetime.utcnow() current_time = datetime.utcnow()
return self.end_time < curent_time
return self.end_time < current_time
def add_participant(self, user): def add_participant(self, user):
entry = self.participants.setdefault(user, {'start_time': datetime.utcnow() }) entry = self.participants.setdefault(user, {'start_time': datetime.utcnow() })

4
app/teamspeak.py

@ -348,6 +348,7 @@ def award_idle_ts3_points(server):
for channel in list_response.data: for channel in list_response.data:
if exempt_check(channel['cid']): if exempt_check(channel['cid']):
exempt_cids.append(channel['cid']) exempt_cids.append(channel['cid'])
# Get list of clients # Get list of clients
clientlist = server.clientlist() clientlist = server.clientlist()
for clid, client in clientlist.iteritems(): for clid, client in clientlist.iteritems():
@ -366,6 +367,7 @@ def award_idle_ts3_points(server):
active_users.add(doob) active_users.add(doob)
except KeyError: except KeyError:
pass pass
doobs = set(models.User.query.filter(models.User.ts3_starttime != None).all()) doobs = set(models.User.query.filter(models.User.ts3_starttime != None).all())
for doob in doobs.intersection(active_users):
for doob in doobs.difference(active_users):
doob.finalize_connection() doob.finalize_connection()

89
app/templates/hero_random.html

@ -1,89 +0,0 @@
{% extends "layout.html" %}
{% block head %}
<link rel="stylesheet" href="{{ url_for('static', filename='css/heropedia.css') }}" >
{% endblock %}
{% block title %} A-Z Challenge: {{ user.nickname }}{% endblock %}
{% block content %}
{% set taverns = heropedia() %}
<h2 class="uk-text-center">{{ user.nickname }}'s A-Z Challenge</h2>
<hr />
<div class="uk-grid">
<div class="uk-width-large-1-3 uk-width-medium-1-1 uk-panel uk-text-center uk-margin-bottom">
<h3 class="uk-panel-title">Current Hero</h3>
<h4 class="uk-text-bold uk-margin-remove">{{ user.random_hero['localized_name'] }}</h4>
<img src="{{ url_for('static', filename=hero_image_large(user.random_hero)) }}" class="dn-hero-icon" />
<p>
<span id="heroes_completed">Heroes Completed: {{ user.random_heroes.completed | length }}</span><br/>
<span id="heroes_left">Heroes Left: {{ total_hero_pool() - user.random_heroes.completed|length }}</span>
</span>
</p>
{% if g.user and g.user.steam_id == user.steam_id %}
<form action="{{ url_for('user_random_hero', userid=g.user.id) }}" method="post" id="random_form" class="uk-margin">
<input type="checkbox" name="completed" id="completed_checkbox" style="display:none;">
<input type="checkbox" name="skip" id="skip_checkbox" style="display:none;">
<a class="uk-button uk-button-success" id="completed_button">Completed!</a>
<a class="uk-button uk-button-primary" id="skip_button">Skip</a>
</form>
{% endif %}
</div>
<div class="uk-width-large-2-3 uk-width-medium-1-1 uk-panel uk-text-center uk-margin">
{% if user.az_completions > 0 %}
<div class="uk-badge uk-panel-badge uk-badge-notification uk-badge-success">x{{ user.az_completions }}</div>
{% endif %}
<h3 class="uk-panel-title">Completed</h3>
{% for hero in user.random_heroes.completed %}
<img src="{{ url_for('static', filename=hero_image_small(hero)) }}" class="dn-hero-icon" />
{% endfor %}
<br/><br/>
<br/><br/>
</div>
<div class="uk-width-large-2-3 uk-width-medium-1-1 uk-container-center">
<ul class="uk-tab" data-uk-tab="{connect:'#taverns'}">
<li class="uk-active"><a href="">Strength</a></li>
<li><a href="">Agility</a></li>
<li><a href="">Intelligence</a></li>
</ul>
<ul id="taverns" class="uk-switcher uk-margin">
<li><div class="uk-panel tavern">
<label id="tavernStrength">Strength</label>
{% for hero in taverns[0][1] + taverns[3][1] %}
<img class="{{hero['name'] in user.random_completed and 'filterUnmatchedHero' or 'filterMatchedHero' }}" id="{{ hero['name'] }}" src="{{ url_for('static', filename=hero_image_small(hero)) }}" />
{% endfor %}
</div></li>
<li><div class="uk-panel tavern">
<label id="tavernAgility">Agility</label>
{% for hero in taverns[1][1] + taverns[4][1] %}
<img class="{{hero['name'] in user.random_completed and 'filterUnmatchedHero' or 'filterMatchedHero' }}" id="{{ hero['name'] }}" src="{{ url_for('static', filename=hero_image_small(hero)) }}" />
{% endfor %}
</div> </li>
<li><div class="uk-panel tavern">
<label id="tavernIntelligence">Intelligence</label>
{% for hero in taverns[2][1] + taverns[5][1] %}
<img class="{{hero['name'] in user.random_completed and 'filterUnmatchedHero' or 'filterMatchedHero' }}" id="{{ hero['name'] }}" src="{{ url_for('static', filename=hero_image_small(hero)) }}" />
{% endfor %}
</div> </li>
</ul>
</div>
</div>
{% endblock %}
{% if g.user and g.user.id == user.id %}
{% block pagescripts %}
<script>
$(document).ready(function() {
$('#completed_button').click( function() {
$('#completed_checkbox').attr('checked', true);
$('#random_form').submit();
});
$('#skip_button').click( function() {
$('#skip_checkbox').attr('checked', true);
$('#random_form').submit();
});
});
</script>
{% endblock %}
{% endif %}

1
app/templates/layout.html

@ -35,7 +35,6 @@
<div class="uk-dropdown uk-dropdown-navbar"> <div class="uk-dropdown uk-dropdown-navbar">
<ul class="uk-nav uk-nav-navbar"> <ul class="uk-nav uk-nav-navbar">
<li><a href="{{ url_for('user_profile', userid=g.user.id) }}">Profile</a></li> <li><a href="{{ url_for('user_profile', userid=g.user.id) }}">Profile</a></li>
<li><a href="{{ url_for('user_random_hero', userid=g.user.id) }}">A-Z Challenge</a></li>
<li><a href="http://board.dotanoobs.com/?page=lastposts">Latest Posts</a></li> <li><a href="http://board.dotanoobs.com/?page=lastposts">Latest Posts</a></li>
{% if g.user.admin %} {% if g.user.admin %}
<li><a href="{{ url_for('event_edit') }}">Add Event</a></li> <li><a href="{{ url_for('event_edit') }}">Add Event</a></li>

9
app/templates/private_profile.html

@ -15,16 +15,7 @@
</div> </div>
<!-- Side bar --> <!-- Side bar -->
<div class="uk-width-large-1-3 uk-width-medium-1-1 uk-panel uk-panel-box uk-panel-box-secondary"> <div class="uk-width-large-1-3 uk-width-medium-1-1 uk-panel uk-panel-box uk-panel-box-secondary">
<div class="uk-container-center uk-text-center">
<span class="uk-text-bold">Current Hero</span><br/>
<span>{{ user.random_hero['localized_name'] }}</span><br/>
<a href={{ url_for('user_random_hero', userid=user.id) }}>
<img src="{{ url_for('static', filename=hero_image_large(user.random_hero)) }}" class="dn-hero-icon" /><br/>
<span>View A-Z Progress</span>
</a>
</div>
<ul class="uk-list uk-list-space uk-list-striped uk-text-center"> <ul class="uk-list uk-list-space uk-list-striped uk-text-center">
<li>Completed <span id='rands'>{{ user.random_heroes.completed | length }}</span> heroes in A-Z</li>
<li>Has <span id='points_total'>0</span> doobs points</li> <li>Has <span id='points_total'>0</span> doobs points</li>
<li>Last seen at <span class='date'> {{ user.last_seen | js_datetime }}</span></li> <li>Last seen at <span class='date'> {{ user.last_seen | js_datetime }}</span></li>
<li>Doob since <span class='date'> {{ user.created | js_datetime }}</span></li> <li>Doob since <span class='date'> {{ user.created | js_datetime }}</span></li>

19
app/templates/profile.html

@ -45,19 +45,6 @@
<!-- Side bar --> <!-- Side bar -->
<div class="uk-width-large-1-3 uk-width-medium-1-1 uk-panel"> <div class="uk-width-large-1-3 uk-width-medium-1-1 uk-panel">
{% if user.public %} {% if user.public %}
<div class="uk-container-center uk-text-center">
<span class="uk-text-bold">Current Hero</span><br/>
<span class="uk-text-success uk-text-bold">
{{ user.random_hero['localized_name'] }}
({{ user.random_heroes.completed | length + 1 }}
/
{{ total_hero_pool() - user.random_heroes.completed|length }})
</span><br/>
<a href={{ url_for('user_random_hero', userid=user.id) }}>
<img src="{{ url_for('static', filename=hero_image_large(user.random_hero)) }}" class="dn-hero-icon" /><br/>
<span>View A-Z Progress</span>
</a>
</div>
<table class="uk-table uk-table-hover uk-table-condensed"> <table class="uk-table uk-table-hover uk-table-condensed">
<caption>{{ user.nickname }}</caption> <caption>{{ user.nickname }}</caption>
<tbody class="uk-text-small"> <tbody class="uk-text-small">
@ -83,12 +70,6 @@
</tr> </tr>
</tbody> </tbody>
</table> </table>
{% if not user.winrate_data['data'] %}
<h3 class="uk-text-warning">No data compiled, check back tomorrow!</h3>
<button class="uk-button uk-button-success uk-align-center" data-uk-modal="{target: '#winrate_modal'}" disabled>View Winrate</button>
{% else %}
<button class="uk-button uk-button-success uk-align-center" data-uk-modal="{target: '#winrate_modal'}">View Winrate</button>
{% endif %}
{% endif %} {% endif %}
</div> </div>
</div> </div>

18
app/views.py

@ -56,7 +56,7 @@ def create_or_login(resp):
match = app.config['STEAM_ID_RE'].search(resp.identity_url) match = app.config['STEAM_ID_RE'].search(resp.identity_url)
g.user = User.get_or_create(match.group(1)) g.user = User.get_or_create(match.group(1))
steamdata = get_steam_userinfo(g.user.steam_id) steamdata = get_steam_userinfo(g.user.steam_id)
g.user.nickname = steamdata['personaname']
g.user.nickname = steamdata['personaname'].encode('utf-8', 'replace')
g.user.avatar = steamdata['avatar'] g.user.avatar = steamdata['avatar']
db.session.commit() db.session.commit()
session['user_id'] = g.user.id session['user_id'] = g.user.id
@ -80,28 +80,12 @@ def teamspeak():
def friends(): def friends():
return render_template('friends.html') return render_template('friends.html')
# Stream pages
@app.route('/shaneomad')
def twitch_shaneomad():
return render_template('potatr.html', twitch_id=app.config.TWITCH_CLIENT_ID)
# User profile page # User profile page
@app.route('/user/<int:userid>') @app.route('/user/<int:userid>')
def user_profile(userid): def user_profile(userid):
user = User.query.filter_by(id=userid).first_or_404() user = User.query.filter_by(id=userid).first_or_404()
return render_template('profile.html', user=user) return render_template('profile.html', user=user)
# User random a-z challenge progress page
@app.route('/user/<int:userid>/random', methods=['POST', 'GET'])
def user_random_hero(userid):
user = User.query.filter_by(id=userid).first_or_404()
if request.method == 'POST':
if request.form.get('skip', False):
user.random_skip()
elif request.form.get('completed', False):
user.random_success()
return render_template('hero_random.html', user=user)
# User settings page # User settings page
@app.route('/settings', methods=['POST', 'GET']) @app.route('/settings', methods=['POST', 'GET'])
@login_required @login_required

34
migrations/versions/50e77b6e7331_.py

@ -0,0 +1,34 @@
"""empty message
Revision ID: 50e77b6e7331
Revises: 9e520de441f
Create Date: 2014-11-17 13:21:23.705195
"""
# revision identifiers, used by Alembic.
revision = '50e77b6e7331'
down_revision = '9e520de441f'
from alembic import op
import sqlalchemy as sa
from sqlalchemy.dialects import mysql
def upgrade():
### commands auto generated by Alembic - please adjust! ###
op.add_column('user', sa.Column('ts3_longest_stretch', sa.Interval(), nullable=True))
op.add_column('user', sa.Column('ts3_stretch_award_time', sa.DateTime(), nullable=True))
op.drop_column('user', u'random_heroes')
op.drop_column('user', u'ts3_connections')
op.drop_column('user', u'az_completions')
### end Alembic commands ###
def downgrade():
### commands auto generated by Alembic - please adjust! ###
op.add_column('user', sa.Column(u'az_completions', mysql.INTEGER(display_width=11), autoincrement=False, nullable=True))
op.add_column('user', sa.Column(u'ts3_connections', mysql.TEXT(), nullable=True))
op.add_column('user', sa.Column(u'random_heroes', mysql.TEXT(), nullable=True))
op.drop_column('user', 'ts3_stretch_award_time')
op.drop_column('user', 'ts3_longest_stretch')
### end Alembic commands ###

5
requirements.txt

@ -9,7 +9,7 @@ Flask-WTF==0.9.4
Jinja2==2.7.1 Jinja2==2.7.1
Mako==1.0.0 Mako==1.0.0
MarkupSafe==0.18 MarkupSafe==0.18
MySQL-python==1.2.4
MySQL-python==1.2.5
Pygments==1.6 Pygments==1.6
SQLAlchemy==0.8.4 SQLAlchemy==0.8.4
WTForms==1.0.5 WTForms==1.0.5
@ -24,13 +24,12 @@ ipdb==0.8
ipython==2.1.0 ipython==2.1.0
itsdangerous==0.23 itsdangerous==0.23
nose==1.3.3 nose==1.3.3
numpy==1.8.1
peewee==2.1.6 peewee==2.1.6
pyparsing==2.0.2 pyparsing==2.0.2
python-crontab==1.8.1 python-crontab==1.8.1
python-dateutil==2.2 python-dateutil==2.2
python-openid==2.2.5 python-openid==2.2.5
python-ts3==0.1
#python-ts3==0.1
pytz==2014.4 pytz==2014.4
requests==2.1.0 requests==2.1.0
simplejson==3.3.1 simplejson==3.3.1

14
run.py

@ -57,7 +57,15 @@ def install_cronjobs():
print "Problem installing cronjobs: {}".format(e) print "Problem installing cronjobs: {}".format(e)
else: else:
cron.write() cron.write()
print "Cron jobs written succesfully"
print "Cron jobs written successfully"
@manager.command
def delete_cronjobs():
from os import path
from crontab import CronTab
cron = CronTab(user=True)
cron.remove_all(comment='DOOBSAUTO')
print "Existing cronjobs deleted successfully"
@manager.command @manager.command
def admin(name): def admin(name):
@ -96,6 +104,10 @@ def ts3_process_events():
tsServer = createTeamspeakInstance() tsServer = createTeamspeakInstance()
process_ts3_events(tsServer) process_ts3_events(tsServer)
@manager.command
def forum_award_points():
for user in models.User.query.filter(models.User.forum_id != None).all():
user.update_forum_posts()
if __name__ == '__main__': if __name__ == '__main__':
manager.run() manager.run()
Loading…
Cancel
Save