Example #1
0
	def GetAccess( self, pebbleToken, createIfRequired ):
		
		if self.CheckPlatformAccess( pebbleToken ):
			return
		
		# Check to see if we already have facebook access
		accessToken = storage.FindPlatformAccessCode( pebbleToken, defines.PLATFORM )
		
		if accessToken:
			response = \
			{
				'status' : "success",
			}
			self.response.status = requests.codes.ok
			self.response.data = jsonToString( response )
			return
		
		# No access code yet, perhaps we've already got an existing auth request on the go?
		authRequest = self.DBGetExistingDeviceAuthCode( pebbleToken )
		
		if authRequest is None and createIfRequired:
			# No existing auth request found for this watch
			logging.debug( "Creating new auth request" )
			
			# Request new code from facebook
			authRequestResponse = net.GetNewDeviceLoginCode()[ 1 ]
			
			# Store new request
			authRequest = self.DBCreateNewDeviceAuthCode( pebbleToken, authRequestResponse )
		elif authRequest:
			# Check status
			self.CheckLoginCodeStatus( pebbleToken, authRequest )
			return
		
		if authRequest:
			logging.debug( "Turning auth request into json response" )
			
			returnData = \
			{
				"status" : "require_auth",
				"url" : authRequest.user_uri,
				"code" : authRequest.user_code,
				"interval" : authRequest.update_interval
			}
			
			self.response.status = requests.codes.ok
			self.response.data = jsonToString( returnData )
			
		else:
			logging.debug( "No auth request - creating json error response" )
			
			returnData = \
			{
				"status" : "no_auth",
				"error" : "No authorisation code found"
			}
			
			self.response.status = requests.codes.bad_request
			self.response.data = jsonToString( returnData )
Example #2
0
def CalcHash( data ):
	if data is None:
		return 0
	if isinstance( data, unicode ):
		logging.debug( "Data is unicode, converting: " + data )
		data = jsonToString( data )
		logging.debug( "Data is json: " + data )
	return zlib.adler32( data )
Example #3
0
	def CheckLoginCodeStatus( self, pebbleToken, authRequest ):
		#todo: Check time since last poll?
		logging.debug( "Checking log in status with facebook" )
		loginCodeStatus = net.GetDeviceLoginCodeStatus( authRequest.auth_code )
		
		if loginCodeStatus[ 0 ] == requests.codes.ok:
			# Create parent object, this does not need to be written to the
			# database as it's only purpose is to contain the pebble token
			watch = storage.CreateWatch( pebbleToken )
			
			accessToken = loginCodeStatus[ 1 ][ 'access_token' ]
			access = storage.CreateAccess( watch, defines.PLATFORM, accessToken )
			
			# store it in the database
			access.put()
			
			# We need to store the facebook user id for when we're told about event changes
			# And also the user's name so that we can display it on the watch as evidence of a successful sign in
			getDataStatus = net.GetCurrentUserData( accessToken )
			
			if( getDataStatus[ 0 ] == requests.codes.ok ):
				
				self.response.status = requests.codes.ok
				
				response = \
				{
					'status' : "success",
					'name' : getDataStatus[ 1 ][ 'name' ]
				}
				
				newSub = storage.CreateFacebookSubscription( getDataStatus[ 1 ][ 'id' ], pebbleToken )
				newSub.put()
				
				# No longer required
				authRequest.delete()
				
			else:
				self.response.status = requests.codes.bad_request
				response = \
				{
					'status' : "failure",
					'message' : "Could not get user details",
				}
			
		else:
			self.response.status = requests.codes.bad_request
			
			response = \
			{
				'status' : "error",
				'message' : status[ 1 ][ 'error' ][ 'message' ],
				'user_code' : authRequest.user_code
			}
		
		self.response.data = jsonToString( response )
Example #4
0
def Process(pebbleToken, events, fbuid):
    # Create parent object, this does not need to be written to the
    # database as it's only purpose is to contain the pebble token
    watch = storage.CreateWatch(pebbleToken)

    for event in events:
        logging.debug("Event '" + event["name"] + "', ID: " + event["id"])

        # We need to associate the key with facebook events
        # ts-fbev-XXXXXXXXXXXXXXXX-YYYYYYYYYYYYYYYYY
        key = "ts-fbev-" + str(fbuid) + "-" + str(event["id"])

        startTime = defines.ISO8601ToDateTime(event["start_time"])

        if "description" in event:
            description = event["description"]
        else:
            description = "No description"

        pin = storage.CreateWatchPin(watch, key, event["name"], description, startTime)
        pin.put()

        # Convert time to UTC
        startTimeUtc = startTime.astimezone(defines.UTC)

        # Construct HTTP put request
        pebbleDateFormat = "%Y-%m-%dT%H:%M:%SZ"
        eventTimeInPebbleFormat = startTimeUtc.strftime(pebbleDateFormat)

        body = {
            "id": key,
            "time": eventTimeInPebbleFormat,
            "layout": {
                "type": "genericPin",
                "title": event["name"],
                "tinyIcon": "system://images/NOTIFICATION_FACEBOOK",
                "body": description,
            },
        }

        headers = {"X-User-Token": pebbleToken, "Content-Type": "application/json"}

        url = "https://timeline-api.getpebble.com/v1/user/pins/" + key
        bodyStr = jsonToString(body)

        response = requests.put(url=url, headers=headers, data=bodyStr)

        logging.debug("Pin URL: " + str(response.url))
        logging.debug("Pin Data: " + bodyStr)
        logging.debug("Pin Headers: " + str(headers))

        logging.debug("Pin response status: " + str(response.status_code))
        logging.debug("Pin response data: " + response.text)
Example #5
0
	def SubscribeBirthdays( self, pebbleToken, action ):
		logging.debug( "SubscribeBirthdays()" )
		
		# update sub data
		fbSubData = storage.FindFacebookSubscriptionByWatchToken( pebbleToken )
		fbSubData.birthdays = action
		fbSubData.put()
		
		response = \
		{
			'status' : "success",
		}
		self.response.status = requests.codes.ok
		self.response.data = jsonToString( response )
Example #6
0
	def CheckPlatformAccess( self, pebbleToken ):
		# Check to see if we already have facebook access
		access = storage.FindPlatformAccessCode( pebbleToken, defines.PLATFORM )
		
		if access:
		
			response = \
			{
				'status' : "success",
			}
			self.response.status = requests.codes.ok
			self.response.data = jsonToString( response )
			return True
		return False
Example #7
0
	def common( self, params, method ):
		
		if method != "delete":
			self.response.set_status( codes.file_not_found )
			return
		
		if 'X-User-Token' not in self.request.headers:
			self.response.set_status( codes.unauthorized )
			return
		
		common.storage.DeleteAllPinsForUser( self.request.headers[ 'X-User-Token' ] )
		
		response = jsonToString( { 'status' : "success" } )
		self.response.set_status( codes.ok )
		self.response.write( response )
		self.response.headers[ "Content-Type" ] = "application/json"
Example #8
0
	def SubscribeEvents( self, pebbleToken, action ):
		logging.debug( "SubscribeEvents()" )
		
		# update sub data
		fbSubData = storage.FindFacebookSubscriptionByWatchToken( pebbleToken )
		fbSubData.events = action
		fbSubData.put()
		
		if action:
			# Grab all the events for the user
			events.Fetch( pebbleToken, fbSubData.key().name() )
		
		response = \
		{
			'status' : "success",
		}
		self.response.status = requests.codes.ok
		self.response.data = jsonToString( response )
Example #9
0
	def common( self, params, method ):
		logging.debug( "Base Handler" )
		
		#Fetch config from derived class
		config = self.GetConfig()
		
		logging.debug( "Params: " + str( params ) )
		if "handler" in params:
			branch = None
			handlerConfig = config[ params[ "handler" ] ]
			if method in handlerConfig:
				methodConfig = handlerConfig[ method ]
			
				if "branch" in params and params[ "branch" ] in methodConfig:
					branch = methodConfig[ params[ "branch" ] ]
				elif "default" in methodConfig:
					branch = methodConfig[ "default" ]
			
			branch = self.ProcessBranch( branch )
			if branch is None:
				return
			
			# Import library
			lib = importlib.import_module( handlerConfig[ "lib" ] )
			
			# Create handler
			handler = lib.Handler( self.app, self.request )
			
			# Call branch
			getattr( handler, branch )( params )
			
			if isinstance( handler.response.data, basestring ):
				data = handler.response.data
			else:
				data = jsonToString( handler.response.data )
			
			self.response.set_status( handler.response.status )
			self.response.write( data )
		else:
			logging.warning( "Invalid handler or method" )
			self.response.set_status( codes.not_found )
Example #10
0
	def Send( self ):
		
		now = datetime.now( common.datetime.UTC )
		timeUntilPin = self.time - now
		
		# Can't have pins more than a year in the future
		if timeUntilPin.days > 364:
			logging.warning( "Ignoring pin with id " + str( self.id ) + " as it's more than a year in the future" )
			return ( codes.bad_request, { "message" : "INVALID_DATE_FUTURE" } )
		
		# Can't have pins more than 2 days in the past
		if timeUntilPin.days < -2:
			logging.warning( "Ignoring pin with id " + str( self.id ) + " as it's more than 2 days in the past" )
			return ( codes.bad_request, { "message" : "INVALID_DATE_PAST" } )
		
		if self.DataMatchesExistingPin():
			logging.info( "Skipping pin with id " + str( self.id ) + " as there have been no changes since the previous time this pin was sent to the server" )
			return ( codes.ok, { "message" : "NO_CHANGE" } )
		
		#Convert the python datetime object into an iso8601-ish format for the pebble api
		pebbleDateFormat = "%Y-%m-%dT%H:%M:%SZ"
		timeInPebbleFormat = self.time.strftime( pebbleDateFormat )
		
		lastUpdated = now.strftime( pebbleDateFormat )
		
		if self.source is not None:
			self.headings.append( "Source" )
			self.paragraphs.append( self.source )
		
		self.headings.append( "Application" )
		self.paragraphs.append( AssemblePinSignature() )
		
		data = \
		{
			'id' 				: self.id,
			'time' 				: timeInPebbleFormat,
			'layout'			: \
			{
				'type'			: "genericPin",
				'title' 		: self.title,
				'tinyIcon'		: self.icon,
				'lastUpdated'	: lastUpdated,
				'headings'		: self.headings,
				'paragraphs'	: self.paragraphs
			}
		}
		
		if self.description is not None:
			data[ "layout" ][ "body" ] = self.description
		
		if self.subtitle is not None:
			data[ "layout" ][ "subtitle" ] = self.subtitle
		
		if self.location is not None:
			data[ "layout" ][ "locationName" ] = self.location
			data[ "layout" ][ "type" ] = "calendarPin"
		
		if self.duration is not None:
			data[ "duration" ] = self.duration
			data[ "layout" ][ "type" ] = "calendarPin"
		
		if len( self.actions ) > 0:
			data[ "actions" ] = self.actions
		
		# Construct the request config
		config = \
		{
			'request' :
			{
				'url' : "https://timeline-api.getpebble.com/v1/user/pins/" + self.id,
				'method' : "PUT",
				
				'headers' :
				{
					'X-User-Token'	: self.pebbleToken,
					'Content-Type'	: "application/json"
				},
				
				'data' : jsonToString( data )
			},
			
			'response' :
			{
				'success' :
				{
					'status' : codes.ok,
					'map' : {}
				},
				
				'failure' :
				{
					'map' :
					{
						'message' : "errorCode"
					}
				}
			}
		}
		
		response = net.MakeRequest( config )
		
		if response[ 0 ] != codes.ok:
			
			if response[ 1 ][ "message" ] == "INVALID_JSON":
				logFunc = logging.error
			else:
				logFunc = logging.warning
			
			logFunc( "Create Pin Failed Response: " + str( response[ 1 ] ) )
			logFunc( "Create Pin Failed Request : " + str( config ) )
		
		return ( response[ 0 ], response[ 1 ] )
Example #11
0
	def post( self ):
		self.response.set_status( codes.not_found )
		self.response.write( jsonToString( { 'status' : "Invalid URL" } ) )
		self.response.headers[ "Content-Type" ] = "application/json"