Skip to content

Commit

Permalink
signon / signoff
Browse files Browse the repository at this point in the history
  • Loading branch information
tpetr committed Feb 13, 2011
1 parent 94950d4 commit 3408859
Show file tree
Hide file tree
Showing 13 changed files with 170 additions and 26 deletions.
23 changes: 8 additions & 15 deletions muxlist/account/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,18 +7,8 @@
from muxlist.mix.models import Group, _get_redis

from time import time
from math import floor

def user_heartbeat(user_id):
r = _get_redis()
last_update = r.get('online_last')
now = floor(time()) / 60
r.sadd('online_' % now, user_id)

if now != last_update:
r.expire('online_' % now, 60)

User.heartbeat = lambda self: return send_heartbeat(self.id)
import settings

class UserProfile(models.Model):
user = models.OneToOneField(User)
Expand All @@ -31,10 +21,13 @@ def __unicode__(self):
def create_userprofile(sender, instance, created, **kwargs):
if created:
UserProfile.objects.create(user=instance)
g = Group.objects.get(name='test')
g.collaborators.add(instance)
g.save()
if NEW_USER_NOTIFICATIONS:
try:
g = Group.objects.get(name='test')
g.collaborators.add(instance)
g.save()
except Group.DoesNotExist:
pass
if settings.NEW_USER_NOTIFICATION:
send_new_user_email(instance)

models.signals.post_save.connect(create_userprofile, sender=User)
Expand Down
74 changes: 74 additions & 0 deletions muxlist/account/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,79 @@
from django.core.mail import send_mail
from settings import ADMINS

import time, redis
import settings

def _get_redis():
return redis.Redis(host='localhost', port=6379, db=0)

def user_online_group(user, group, now=None, r=None):
now = now or (int(time.time()) / 60)
r = r or _get_redis()

for i in xrange(now, now - settings.USER_IDLE_TIME, -1):
if r.sismember('%i_online_%i' % (group.id, i), user.id):
return True

return False

def set_user_online_global(user, now=None, r=None):
now = now or (int(time.time()) / 60)
r = r or _get_redis()

global_online_now = 'online_%i' % now

preexist = r.exists(global_online_now)

r.sadd(global_online_now, user.id)

if not preexist:
r.expire(global_online_now, 300)

def set_user_online_group(user, group, now=None, r=None):
now = now or (int(time.time()) / 60)
r = r or _get_redis()

group_online_now = '%i_online_%i' % (group.id, now)
user_groups = 'user_%i_groups' % user.id

r.sadd(user_groups, group.id)

preexist = r.exists(group_online_now)
r.sadd(group_online_now, user.id)

if not preexist:
r.expire(group_online_now, 300)

def set_user_offline(user, r=None):
r = r or _get_redis()

now = int(time.time()) / 60

online = False
groups = []

# remove from online
for i in xrange(now, now-settings.USER_IDLE_TIME, -1):
if r.srem('online_%i' % i, user.id):
online = True

# if user was online
if online:
# for each group it was in, remove from online
for group_id in r.smembers('user_%i_groups' % user.id):
group_id = int(group_id)
online = False
for i in xrange(now, now-settings.USER_IDLE_TIME, -1):
if r.srem('%i_online_%i' % (group_id, i), user.id):
online = True
# if removed, add to list
if online: groups.append(group_id)

r.delete('user_%i_groups' % user.id)

return groups


def send_new_user_email(user):
return send_mail("[muxlist] New user: %s" % user.username, render_to_string('email/new_user.html', {'user': user}), '[email protected]', [a[1] for a in ADMINS])
10 changes: 10 additions & 0 deletions muxlist/comet/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,3 +28,13 @@ def send_queue_update(count, group):
conn = _get_stomp()
msg = json.dumps([{'type': 'queue_count', 'value': count},])
conn.send(msg, destination='/group/%s' % group.id)

def send_user_join(user, group):
conn = _get_stomp()
msg = json.dumps([{'type': 'user_join', 'value': user.username}])
conn.send(msg, destination='/group/%i' % group.id)

def send_user_leave(user, group):
conn = _get_stomp()
msg = json.dumps([{'type': 'user_leave', 'value': user.username}])
conn.send(msg, destination='/group/%i' % group.id)
22 changes: 19 additions & 3 deletions muxlist/comet/views.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,24 @@
from django.http import HttpResponse, Http404
from django.shortcuts import get_object_or_404

def heartbeat(request):
if not request.is_authenticated(): raise Http404
from muxlist.mix.models import Group, _get_redis
import json, time

request.user.heartbeat()
from muxlist.comet.utils import send_user_leave
from muxlist.account.utils import set_user_offline

import settings

class LightweightGroup(object):
def __init__(self, group_id):
self.id = group_id

def disconnect(request):
if not request.user.is_authenticated(): raise Http404

user = request.user

for group_id in set_user_offline(user):
send_user_leave(user, LightweightGroup(int(group_id)))

return HttpResponse()
22 changes: 19 additions & 3 deletions muxlist/mix/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@
from django.contrib.auth.models import User
from mix.utils import dequeue_track
import redis, time
from math import floor

from muxlist.music.models import Track
from muxlist.account.utils import set_user_online_global, set_user_online_group, user_online_group

from muxlist.comet import utils as comet_utils
from django.conf import settings
Expand All @@ -28,6 +28,23 @@ def get_absolute_url(self):
def __unicode__(self):
return self.name

def user_heartbeat(self, user):
r = _get_redis()
now = int(time.time()) / 60

if not user_online_group(user, self, now, r):
comet_utils.send_user_join(user, self)

set_user_online_global(user, now, r)
set_user_online_group(user, self, now, r)

def get_users_online(self):
r = _get_redis()

now = int(time.time()) / 60

return User.objects.filter(id__in=r.sunion(['%i_online_%i' % (self.id, i) for i in xrange(now-settings.USER_IDLE_TIME+1, now+1)]))

def enqueue_track(self, track, user):
r = _get_redis()

Expand All @@ -45,7 +62,6 @@ def enqueue_track(self, track, user):

# send queue update if next song not pushed
if self.check_for_next_track()[0] == None:
print "send_queue_update()"
comet_utils.send_queue_update(count, self)

# return queue count
Expand Down Expand Up @@ -98,7 +114,7 @@ def next_track(self, r=None):
if track_id == None: return None, None, None

# record what time the track started
started_at = floor(time.time()) + 1 # add a second for RTT and crap
started_at = int(time.time()) + 1 # add a second for RTT and crap

# set the track as current
r.set('%s_current' % self.id, track_id)
Expand Down
1 change: 1 addition & 0 deletions muxlist/mix/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,6 @@
(r'^(?P<group_name>.*)/next/$', 'next_track'),
(r'^(?P<group_name>.*)/force-next/$', 'next_track_force'),
(r'^(?P<group_name>.*)/current/$', 'current_track'),
(r'^(?P<group_name>.*)/heartbeat/$', 'heartbeat'),
(r'^(?P<group_name>.*)/$', 'index'),
)
18 changes: 18 additions & 0 deletions muxlist/mix/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,15 @@
from muxlist.music.signals import track_uploaded
from django.dispatch import receiver

def heartbeat(request, group_name):
if not request.user.is_authenticated(): raise Http404

group = get_object_or_404(Group, name=group_name)

group.user_heartbeat(request.user)

return HttpResponse(json.dumps([u.username for u in group.get_users_online()]))

@receiver(track_uploaded, sender=None)
def tu(sender, **kwargs):
group_name = 'test'
Expand All @@ -28,6 +37,8 @@ def next_track(request, group_name):
# get group
group = get_object_or_404(Group, name=group_name)

group.user_heartbeat(request.user)

# check for next track
if group.check_for_next_track()[0] == None: return HttpResponse(status=402)

Expand All @@ -39,6 +50,9 @@ def next_track_force(request, group_name):

# TODO: check for some kind of creds

# user heartbeat
group.user_heartbeat(request.user)

# next track!
return HttpResponse(group.next_track())

Expand All @@ -50,6 +64,8 @@ def current_track(request, group_name):
if not (group.is_public or (request.user.is_authenticated() and request.user in group.collaborators.all())):
return HttpResponse(status=401)

group.user_heartbeat(request.user)

# get current track
track, user, started_at = group.get_current_track()

Expand Down Expand Up @@ -84,6 +100,8 @@ def add_message(request, group_name):
if not (group.is_public or (request.user.is_authenticated() and request.user in group.collaborators.all())):
return HttpResponse(status=401)

group.user_heartbeat(request.user)

# send chat
comet_utils.send_chat(request.POST['msg'], request.user, group)

Expand Down
5 changes: 0 additions & 5 deletions muxlist/music/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,11 +54,6 @@ def __json__(self):
class TrackLocation(models.Model):
url = models.URLField(max_length=512, verify_exists=False)
track = models.ForeignKey(Track, related_name='locations')
queue = 'track'

@staticmethod
def perform(id):
print "perform!"

def get_url(self):
if self.url.startswith('http://muxlist.s3.amazonaws.com/'):
Expand Down
8 changes: 8 additions & 0 deletions muxlist/music/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@

from boto.s3.connection import S3Connection, Key

import hashlib

def _get_s3_connection():
return S3Connection('1GDBYBN31QAR4P85HQG2', 'rcU7fQs/fOys/lQIJcNPZ65bk7kpyGJb5POommIV')

Expand All @@ -14,6 +16,12 @@ def upload_to_s3(fp, name):
k.set_contents_from_file(fp)
return 'http://muxlist.s3.amazonaws.com/%s' % name

def calculate_md5(fp):
fp.seek(0)
md5 = hashlib.md5()
for chunk in f.chunks():
md5.update(chunk)
return md5.hexdigest()

def get_track_data_from_url(url):
request = urllib2.Request(url)
Expand Down
1 change: 1 addition & 0 deletions muxlist/music/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ def begin_slice(request):
if request.method == 'POST':
form = SliceUploadForm(data=request.POST, files=request.FILES)
if form.is_valid():
form.cleaned_data['group'].user_heartbeat(request.user)
begin_hash = hashlib.md5(form.cleaned_data['file'].read(100)).hexdigest()
try:
tl = TrackLocation.objects.get(begin_hash=begin_hash, size=request.META['HTTP_X_FILE_SIZE'])
Expand Down
5 changes: 5 additions & 0 deletions muxlist/settings/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@

NEW_USER_NOTIFICATION = False

USER_IDLE_TIME = 5

MANAGERS = ADMINS

DATABASES = {
Expand Down Expand Up @@ -88,9 +90,12 @@
'muxlist.music',
'muxlist.mix',
'muxlist.account',
'muxlist.comet',
'registration',
)

AUTH_PROFILE_MODULE = 'account.UserProfile'
ACCOUNT_ACTIVATION_DAYS = 7

LOGIN_URL = '/account/login'

Expand Down
1 change: 1 addition & 0 deletions muxlist/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,4 +24,5 @@
(r'^admin/', include(admin.site.urls)),
(r'^account/', include('muxlist.account.urls')),
(r'^restq/', include('muxlist.restq.urls')),
(r'^comet/', include('muxlist.comet.urls')),
)
6 changes: 6 additions & 0 deletions templates/mix/group.html
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
stomp = new STOMPClient();
stomp.onconnectedframe = function () {
$("<li><i>thundercats are go</i></li>").appendTo('#stream');
$(window).unload(function () { $.post('/comet/disconnect/'); })
stomp.subscribe('/group/{{ group.id }}');
// why??
setTimeout("comet_ready()", 100)
Expand Down Expand Up @@ -69,6 +70,11 @@
stream_scroll();
} else if (data.type == 'queue_count') {
$('#queue_count').html(data.value)
} else if (data.type == 'user_join') {
console.log(data)
$('<li><b>' + data.value + '</b> joined</li>').appendTo('#stream');
} else if (data.type == 'user_leave') {
$('<li><b>' + data.value + '</b> left</li>').appendTo('#stream');
}
}
}
Expand Down

0 comments on commit 3408859

Please sign in to comment.