DotaNoobs main site.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

284 lines
11 KiB

import simplejson as json
from datetime import datetime
from flask.ext.sqlalchemy import SQLAlchemy
from sqlalchemy.ext.mutable import Mutable
import board
from app import db, app
from utils import parse_valve_heropedia, complete_hero_data, API_DATA
# Model independant get_or_create
def get_or_create_instance(session, model, **kwargs):
instance = session.query(model).filter_by(**kwargs).first()
if instance:
return instance
instance = model(**kwargs)
return instance
# Get a little of that Mongoness back
class Json(db.TypeDecorator):
impl = db.Text
def process_bind_param(self, value, dialect):
if value is not None:
value = json.dumps(value)
return value
def process_result_value(self, value, dialect):
if value is not None:
value = json.loads(value)
except ValueError:
return {}
return value
# Mongoness factor - phase 2
class MutableDict(Mutable, dict):
def coerce(cls, key, value):
if not isinstance(value, MutableDict):
if isinstance(value, dict):
return MutableDict(value)
return Mutable.coerce(key,value)
return value
def __delitem__(self, key):
dict.__delitem__(self, key)
def __setitem__(self, key, value):
dict.__setitem__(self, key, value)
def __getstate__(self):
return dict(self)
def __setstate__(self, state):
class User(db.Model):
id = db.Column(db.Integer, primary_key=True)
steam_id = db.Column(db.String(40), unique=True)
forum_id = db.Column(db.Integer)
teamspeak_id = db.Column(db.String(200), unique=True)
nickname = db.Column(db.String(80))
avatar = db.Column(db.String(255))
bio_text = db.Column(db.String(4096))
created = db.Column(db.DateTime)
last_seen = db.Column(db.DateTime)
twitch = db.Column(db.String(60))
hitbox = db.Column(db.String(60))
admin = db.Column(db.Boolean)
public = db.Column(db.Boolean)
logo = db.Column(db.Boolean)
points_from_events = db.Column(db.Integer)
points_from_ts3 = db.Column(db.Integer)
points_from_forum = db.Column(db.Integer)
ts3_starttime = db.Column(db.DateTime)
ts3_endtime = db.Column(db.DateTime)
ts3_rewardtime = db.Column(db.DateTime)
ts3_connections = db.Column(MutableDict.as_mutable(Json))
last_post_reward = db.Column(db.Integer)
winrate_data = db.Column(MutableDict.as_mutable(Json))
def get_or_create(self, steam_id):
return get_or_create_instance(db.session, User, steam_id=steam_id)
def get_streaming_users(self):
twitch_streams = []
hitbox_streams = []
for user in User.query.all():
if user.points_from_events + user.points_from_ts3 + user.points_from_forum < 5: continue
if user.twitch:
if user.hitbox:
return {'twitch': twitch_streams, 'hitbox': hitbox_streams}
def __init__(self, steam_id):
self.steam_id = steam_id
self.az_completions = 0
self.ts3_connections = {'list':[]}
self.ts3_rewardtime = datetime.utcnow()
self.created = datetime.utcnow()
self.last_seen = datetime.utcnow()
self.bio_text = None
self.points_from_events = 0
self.points_from_ts3 = 0
self.points_from_forum = 0
self.admin = False
self.public = True
self.biglogo = True
def update_connection(self, reward_threshold=30):
now = datetime.utcnow()
self.ts3_starttime = self.ts3_starttime or now
self.ts3_endtime = now
# 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
self.ts3_rewardtime = datetime.utcnow()
self.last_seen = datetime.utcnow()
def finalize_connection(self):
self.ts3_connections['list'].append({'starttime': self.ts3_starttime, 'endtime': self.ts3_endtime})
self.ts3_startime = None
self.ts3_endtime = None
def update_forum_posts(self, reward_threshold=5):
if self.forum_id:
posts = == int(self.forum_id))[0].posts
if self.last_post_reward:
num_points = (posts - self.last_post_reward) / reward_threshold
if num_points > 0:
self.points_from_forum += num_points
self.last_post_reward += num_points * reward_threshold
# Initialize if this is the first reward
self.last_post_reward = posts
def is_active(self):
return self.ts3_starttime and True or False
def __repr__(self):
return '<User {}>'.format(
class TeamspeakData(db.Model):
id = db.Column(db.Integer, primary_key=True)
time = db.Column(db.DateTime())
clients = db.Column(Json())
def __init__(self, clientlist):
self.time = datetime.utcnow()
self.clients = clientlist
class Event(db.Model):
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(200))
desc = db.Column(db.String(4096))
type = db.Column(db.String(20))
start_time = db.Column(db.DateTime)
end_time = db.Column(db.DateTime)
points = db.Column(db.Integer)
reward_threshold = db.Column(db.Integer)
total_subchans = db.Column(db.Integer)
channels = db.Column(MutableDict.as_mutable(Json))
participants = db.Column(MutableDict.as_mutable(Json))
def __init__(self, id):
self.channels = {'event_cid':None, 'cids':[]}
def get_or_create(self, event_id):
return get_or_create_instance(db.session, Event, id=event_id)
def cids(self):
return self.channels['cids']
def event_cid(self):
return self.channels['event_cid']
def channel_ids(self):
cids = self.channels['cids']
if self.channels['event_cid']:
return cids
def create_channels(self):
import ts3
server = ts3.TS3Server(app.config['TS3_HOST'], app.config['TS3_PORT'])
server.login(app.config['TS3_USERNAME'], app.config['TS3_PASSWORD'])
# Create the parent channel
if not self.event_cid:
# Find the LFG channel and place this one after
response = server.send_command('channelfind', keys={'pattern': 'Looking for Group'})
if response.is_successful:
cid =[0]['cid']
response = server.send_command('channelcreate', keys={'channel_name''utf-8'), 'channel_flag_semi_permanent':'1', 'channel_order':cid})
if response.is_successful:
self.channels['event_cid'] =[0]['cid']
# Create the subchannels
if not self.cids:
cids = []
keys = {'channel_name':'Event Room #{}'.format(len(self.cids) + 1), 'channel_flag_semi_permanent':'1', 'cpid':self.event_cid.encode('utf-8')}
response = server.send_command('channelcreate', keys=keys)
if response.is_successful:
parent_cid =[0]['cid']
raise UserWarning("channelcreate failed")
response = server.send_command('channelcreate', keys={'channel_name':'Radiant Team', 'channel_flag_semi_permanent':'1', 'cpid':parent_cid})
if response.is_successful:
response = server.send_command('channelcreate', keys={'channel_name':'Dire Team', 'channel_flag_semi_permanent':'1', 'cpid':parent_cid})
if response.is_successful:
response = server.send_command('channelcreate', keys={'channel_name':'Spectators', 'channel_flag_semi_permanent':'1', 'cpid':parent_cid})
if response.is_successful:
self.channels['cids'] = cids
def remove_channels(self):
import ts3
server = ts3.TS3Server(app.config['TS3_HOST'], app.config['TS3_PORT'])
server.login(app.config['TS3_USERNAME'], app.config['TS3_PASSWORD'])
response = server.send_command('channeldelete', keys={'cid':self.event_cid.encode('utf-8'), 'force':'1'})
if response.is_successful:
self.channels = {'event_cid': None, 'cids':[]}
def active(self):
current_time = datetime.utcnow()
return self.start_time < current_time and current_time < self.end_time
def expired(self):
current_time = datetime.utcnow()
return self.end_time < curent_time
def add_participant(self, user):
entry = self.participants.setdefault(user, {'start_time': datetime.utcnow() })
entry['end_time'] = datetime.utcnow()
if 'points' not in entry and (entry['end_time'] - entry['start_time']) > self.reward_threshold:
user.points_from_events += self.points
entry['points'] = self.points
def participants(self):
return tuple(self.participants)
def __repr__(self):
return '<Event {}>'.format(