Source

vk-online / status.py

#!/usr/bin/python
# -*- coding: utf-8 -*-

import md5
import logging
import time
import datetime
from webapp2 import RequestHandler, WSGIApplication


from google.appengine.ext import db
from google.appengine.api import taskqueue
from google.appengine.api import mail

import vkontakte

######################
# Enter your user_id #
# and app secrets    #
######################

USER_ID = 
APP_ID = 
APP_SECRET = 
EMAIL = 

def get_status(user_id=5594):
	vk = vkontakte.API(APP_ID, APP_SECRET)
	profiles = vk.getProfiles(uids='%d' % user_id, fields='education, online')
	pavel = profiles[0]
	return pavel['online']


class Status(db.Model):
	user_id = db.IntegerProperty(required=True)
	time = db.DateTimeProperty(auto_now_add=True)
	online = db.IntegerProperty()

class StatusHour(db.Model):
	user_id = db.IntegerProperty()
	time = db.DateTimeProperty()
	online = db.IntegerProperty(default=0)

log = logging.getLogger('task')

###############
##   Tasks   ##
###############

date_format = '%y-%m-%d-%H'

def _notify(user_id):
	msg = ''' Пользователь в сети http://vkontakte.ru/id%d

	--
	VK-online
	''' % user_id

	mail.send_mail(EMAIL, EMAIL, 'VK-online notify', msg)

class GetStatus(RequestHandler):
	def get(self):
		user_id = USER_ID
		online = get_status(user_id)
		log.info('Online: %d' , online)

		if online > 0:
			timeParam = datetime.datetime.now().strftime(date_format)
			try:
				taskqueue.add(url='/task/status/hour', name='aggregate-hour-'+timeParam, params={'time': timeParam})
			except taskqueue.TaskAlreadyExistsError:
				pass

			# if status changed
			prev = Status.all().filter('user_id', user_id).order('-time').fetch(1)[0]
			if prev.online == 0:
				_notify(user_id)

		status = Status(user_id=user_id, online=online)
		status.put()


	def post(self):
		self.get()


def get_key(user_id, time_str):
	'Create key for StatusHour'
	m = md5.new(str(user_id)+time_str)
	return m.hexdigest()

class GetStatusHour(RequestHandler):
	""" Aggregate online status by hour """

	def get(self):
		user_id = USER_ID
		timeParam = self.request.get('time')
		
		update = True
		if timeParam == '':
			update = False
			timeParam = datetime.datetime.now().strftime(date_format)
			log.info('Aggregate '+timeParam)
		
		key = get_key(user_id, timeParam)
		st = StatusHour.get_or_insert(key)

		if st.user_id is None: # create new
			st.user_id = user_id
			st.time = datetime.datetime.strptime(timeParam, date_format)
			st.put()

		if update: # status changed
			st.online = 1
			st.put()

	def post(self):
		self.get()	


#########################
##        Graph        ##
#########################

import jinja2
import os

jinja_environment = jinja2.Environment(
    loader=jinja2.FileSystemLoader(os.path.dirname(__file__)))

class GraphStatus(RequestHandler):
	def get(self):
		user_id = USER_ID
		statuses = Status.all()\
			.filter('user_id', user_id)\
			.order('-time').fetch(1000)
		
		def byDate(st):
			return st.time

		statuses = sorted(statuses, key=byDate)
		for status in statuses:
			status.timestamp = int(status.time.strftime('%s'))*1000

		template_values = {
			'user_id': user_id,
			'statuses': statuses
		}
		template = jinja_environment.get_template('index.html')
		self.response.out.write(template.render(template_values))



class GraphStatusHour(RequestHandler):
	def get(self):
		user_id = USER_ID
		statuses = StatusHour.all()\
			.filter('user_id', user_id)\
			.order('-time').fetch(1000)
		
		def byDate(st):
			return st.time

		statuses = sorted(statuses, key=byDate)
		for status in statuses:
			status.timestamp = int(status.time.strftime('%s'))*1000

		template_values = {
			'user_id': user_id,
			'statuses': statuses
		}
		template = jinja_environment.get_template('index.html')
		self.response.out.write(template.render(template_values))


app = WSGIApplication([('/task/status', GetStatus),
					   ('/task/status/hour', GetStatusHour),
					   ('/minute', GraphStatus),
					   ('/', GraphStatusHour),
							  ],
                              debug=True)