203 lines
6.4 KiB
Python
203 lines
6.4 KiB
Python
import logging
|
|
logger = logging.getLogger(__name__)
|
|
|
|
import time
|
|
from datetime import date, datetime, timedelta
|
|
import requests
|
|
from django.db.models import Prefetch
|
|
from django.core.cache import cache
|
|
from django.utils.timezone import now, pytz
|
|
from apiserver.api import models, utils
|
|
from apiserver import secrets
|
|
|
|
DEFAULTS = {
|
|
'last_card_change': time.time(),
|
|
'next_meeting': None,
|
|
'next_clean': None,
|
|
'next_class': None,
|
|
'prev_class': None,
|
|
'member_count': None,
|
|
'paused_count': None,
|
|
'green_count': None,
|
|
'bay_108_temp': None,
|
|
'bay_110_temp': None,
|
|
'minecraft_players': [],
|
|
'card_scans': 0,
|
|
'track': {},
|
|
'alarm': {},
|
|
'sign': '',
|
|
'link': '',
|
|
'autoscan': '',
|
|
}
|
|
|
|
if secrets.MUMBLE:
|
|
DEFAULTS['mumble_users'] = []
|
|
|
|
def changed_card():
|
|
'''
|
|
Called whenever the card list could change, ie. cards added, modified, or
|
|
user status becoming overdue by 3 months
|
|
'''
|
|
cache.set('last_card_change', time.time())
|
|
|
|
def calc_next_events():
|
|
sessions = models.Session.objects
|
|
|
|
# TODO, go by tag?
|
|
member_meeting = sessions.filter(is_cancelled=False, course__in=[317, 413], datetime__gte=now()).first()
|
|
monthly_clean = sessions.filter(is_cancelled=False, course=273, datetime__gte=now()).first()
|
|
next_class = sessions.exclude(course__in=[317, 413, 273]).filter(is_cancelled=False, datetime__gte=now()).order_by('datetime').first()
|
|
prev_class = sessions.exclude(course__in=[317, 413, 273]).filter(is_cancelled=False, datetime__lte=now()).order_by('datetime').last()
|
|
|
|
if member_meeting:
|
|
cache.set('next_meeting', member_meeting.datetime)
|
|
else:
|
|
cache.set('next_meeting', None)
|
|
|
|
if monthly_clean:
|
|
cache.set('next_clean', monthly_clean.datetime)
|
|
else:
|
|
cache.set('next_clean', None)
|
|
|
|
if next_class:
|
|
cache.set('next_class', dict(datetime=next_class.datetime, id=next_class.id, name=next_class.course.name))
|
|
else:
|
|
cache.set('next_class', None)
|
|
|
|
if prev_class:
|
|
cache.set('prev_class', dict(datetime=prev_class.datetime, id=prev_class.id, name=prev_class.course.name))
|
|
else:
|
|
cache.set('prev_class', None)
|
|
|
|
|
|
def calc_member_counts():
|
|
members = models.Member.objects
|
|
not_paused = members.filter(paused_date__isnull=True)
|
|
|
|
num_current = not_paused.filter(status='Current').count()
|
|
num_prepaid = not_paused.filter(status='Prepaid').count()
|
|
num_due = not_paused.filter(status='Due').count()
|
|
num_overdue = not_paused.filter(status='Overdue').count()
|
|
|
|
member_count = num_current + num_prepaid + num_due + num_overdue
|
|
paused_count = members.count() - member_count
|
|
green_count = num_current + num_prepaid
|
|
|
|
six_months_ago = utils.today_alberta_tz() - timedelta(days=183)
|
|
six_month_plus_count = not_paused.filter(application_date__lte=six_months_ago).count()
|
|
|
|
vetted_count = not_paused.filter(vetted_date__isnull=False).count()
|
|
|
|
related_membership_tx = Prefetch(
|
|
'user__transactions',
|
|
queryset=models.Transaction.objects.exclude(
|
|
number_of_membership_months=0,
|
|
).exclude(
|
|
number_of_membership_months__isnull=True,
|
|
),
|
|
)
|
|
|
|
subscriber_count = 0
|
|
for member in not_paused.prefetch_related(related_membership_tx):
|
|
if not member.user.transactions.count():
|
|
continue
|
|
if member.user.transactions.latest('date').paypal_txn_type == 'subscr_payment':
|
|
subscriber_count += 1
|
|
|
|
cache.set('member_count', member_count)
|
|
cache.set('paused_count', paused_count)
|
|
cache.set('green_count', green_count)
|
|
|
|
return dict(
|
|
member_count=member_count,
|
|
green_count=green_count,
|
|
six_month_plus_count=six_month_plus_count,
|
|
vetted_count=vetted_count,
|
|
subscriber_count=subscriber_count,
|
|
)
|
|
|
|
def calc_signup_counts():
|
|
month_beginning = utils.today_alberta_tz().replace(day=1)
|
|
|
|
members = models.Member.objects
|
|
new_members = members.filter(application_date__gte=month_beginning)
|
|
num_new_members = new_members.count()
|
|
|
|
return num_new_members
|
|
|
|
def calc_retain_counts():
|
|
signup_counts = models.StatsSignupCount.objects.all()
|
|
|
|
all_members = models.Member.objects
|
|
active_members = all_members.filter(paused_date__isnull=True)
|
|
vetted_members = all_members.filter(vetted_date__isnull=False)
|
|
|
|
for entry in signup_counts:
|
|
date = entry.month
|
|
active_new_members = active_members.filter(
|
|
application_date__month=date.month, application_date__year=date.year
|
|
)
|
|
vetted_new_members = vetted_members.filter(
|
|
application_date__month=date.month, application_date__year=date.year
|
|
)
|
|
|
|
entry.retain_count = active_new_members.count()
|
|
entry.vetted_count = vetted_new_members.count()
|
|
entry.save()
|
|
|
|
return active_members.count()
|
|
|
|
def check_minecraft_server():
|
|
if secrets.MINECRAFT:
|
|
url = 'https://api.minetools.eu/ping/' + secrets.MINECRAFT
|
|
|
|
try:
|
|
r = requests.get(url, timeout=5)
|
|
r.raise_for_status()
|
|
players = [x['name'] for x in r.json()['players']['sample']]
|
|
cache.set('minecraft_players', players)
|
|
return players
|
|
except BaseException as e:
|
|
logger.error('Problem checking Minecraft: {} - {}'.format(e.__class__.__name__, str(e)))
|
|
|
|
return []
|
|
|
|
def check_mumble_server():
|
|
if secrets.MUMBLE:
|
|
url = secrets.MUMBLE
|
|
|
|
try:
|
|
r = requests.get(url, timeout=5)
|
|
r.raise_for_status()
|
|
users = r.text.split()
|
|
cache.set('mumble_users', users)
|
|
return users
|
|
except BaseException as e:
|
|
logger.error('Problem checking Mumble: {} - {}'.format(e.__class__.__name__, str(e)))
|
|
|
|
return []
|
|
|
|
def calc_card_scans():
|
|
date = utils.today_alberta_tz()
|
|
dt = datetime.combine(date, datetime.min.time())
|
|
midnight = utils.TIMEZONE_CALGARY.localize(dt)
|
|
|
|
cards = models.Card.objects
|
|
count = cards.filter(last_seen__gte=midnight).count()
|
|
|
|
cache.set('card_scans', count)
|
|
|
|
models.StatsSpaceActivity.objects.update_or_create(
|
|
date=date,
|
|
defaults=dict(card_scans=count),
|
|
)
|
|
|
|
def get_progress(request_id):
|
|
return cache.get('request-progress-' + request_id, [])
|
|
|
|
def set_progress(request_id, data):
|
|
logger.info('Progress - ID: %s | Status: %s', request_id, data)
|
|
progress = get_progress(request_id)
|
|
progress.append(data)
|
|
cache.set('request-progress-' + request_id, progress)
|