2011-10-11 20:55:53 +00:00
|
|
|
#!/usr/bin/ruby1.8
|
2011-08-02 16:44:56 +00:00
|
|
|
# -*- coding: utf-8 -*-
|
|
|
|
|
|
|
|
# Copyright:: Copyright 2011 Google Inc.
|
2011-10-11 20:55:53 +00:00
|
|
|
# License:: Apache 2.0
|
2011-08-02 16:44:56 +00:00
|
|
|
# Original Author:: Bob Aman, Winton Davies, Robert Kaplow
|
|
|
|
# Maintainer:: Robert Kaplow (mailto:rkaplow@google.com)
|
|
|
|
|
|
|
|
require 'rubygems'
|
|
|
|
require 'sinatra'
|
|
|
|
require 'datamapper'
|
|
|
|
require 'google/api_client'
|
|
|
|
require 'yaml'
|
|
|
|
|
2011-10-11 20:55:53 +00:00
|
|
|
enable :sessions
|
2011-08-02 16:44:56 +00:00
|
|
|
|
|
|
|
# Set up our token store
|
|
|
|
DataMapper.setup(:default, 'sqlite::memory:')
|
|
|
|
class TokenPair
|
|
|
|
include DataMapper::Resource
|
|
|
|
|
|
|
|
property :id, Serial
|
2011-10-11 20:55:53 +00:00
|
|
|
property :refresh_token, String, :length => 255
|
|
|
|
property :access_token, String, :length => 255
|
2011-08-02 16:44:56 +00:00
|
|
|
property :expires_in, Integer
|
|
|
|
property :issued_at, Integer
|
|
|
|
|
|
|
|
def update_token!(object)
|
|
|
|
self.refresh_token = object.refresh_token
|
|
|
|
self.access_token = object.access_token
|
|
|
|
self.expires_in = object.expires_in
|
|
|
|
self.issued_at = object.issued_at
|
|
|
|
end
|
|
|
|
|
|
|
|
def to_hash
|
|
|
|
return {
|
|
|
|
:refresh_token => refresh_token,
|
|
|
|
:access_token => access_token,
|
|
|
|
:expires_in => expires_in,
|
|
|
|
:issued_at => Time.at(issued_at)
|
|
|
|
}
|
|
|
|
end
|
|
|
|
end
|
|
|
|
TokenPair.auto_migrate!
|
|
|
|
|
2011-10-11 20:55:53 +00:00
|
|
|
def save_token_pair(session, client)
|
|
|
|
token_pair = if session[:token_id]
|
|
|
|
TokenPair.first_or_create(:id => session[:token_id])
|
|
|
|
else
|
|
|
|
TokenPair.new
|
|
|
|
end
|
|
|
|
token_pair.update_token!(client.authorization)
|
|
|
|
if token_pair.save
|
|
|
|
session[:token_id] = token_pair.id
|
|
|
|
else
|
|
|
|
token_pair.errors.each do |e|
|
|
|
|
raise e
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
# FILL IN THIS SECTION
|
|
|
|
# This is the name of the {bucket}/{object} you are using for the language
|
|
|
|
# file.
|
|
|
|
# ------------------------
|
|
|
|
DATA_OBJECT = "bucket/object"
|
|
|
|
# ------------------------
|
2011-08-02 16:44:56 +00:00
|
|
|
|
2011-10-11 20:55:53 +00:00
|
|
|
before do
|
2011-08-02 16:44:56 +00:00
|
|
|
# FILL IN THIS SECTION
|
2011-10-11 20:55:53 +00:00
|
|
|
# This will work if your yaml file is stored as .google-api.yaml
|
2011-08-02 16:44:56 +00:00
|
|
|
# ------------------------
|
|
|
|
oauth_yaml = YAML.load_file('.google-api.yaml')
|
|
|
|
@client = Google::APIClient.new
|
|
|
|
@client.authorization.client_id = oauth_yaml["client_id"]
|
|
|
|
@client.authorization.client_secret = oauth_yaml["client_secret"]
|
|
|
|
@client.authorization.scope = oauth_yaml["scope"]
|
|
|
|
@client.authorization.refresh_token = oauth_yaml["refresh_token"]
|
|
|
|
@client.authorization.access_token = oauth_yaml["access_token"]
|
|
|
|
# -----------------------
|
|
|
|
|
|
|
|
@client.authorization.redirect_uri = to('/oauth2callback')
|
|
|
|
|
|
|
|
if session[:token_id]
|
|
|
|
# Load the access token here if it's available
|
|
|
|
token_pair = TokenPair.get(session[:token_id])
|
2011-10-11 20:55:53 +00:00
|
|
|
@client.authorization.update_token!(token_pair.to_hash) if token_pair
|
2011-08-02 16:44:56 +00:00
|
|
|
end
|
|
|
|
if @client.authorization.refresh_token && @client.authorization.expired?
|
|
|
|
@client.authorization.fetch_access_token!
|
2011-10-11 20:55:53 +00:00
|
|
|
save_token_pair(session, @client)
|
2011-08-02 16:44:56 +00:00
|
|
|
end
|
|
|
|
|
2011-10-11 20:55:53 +00:00
|
|
|
@prediction = @client.discovered_api('prediction', 'v1.4')
|
2011-08-02 16:44:56 +00:00
|
|
|
unless @client.authorization.access_token || request.path_info =~ /^\/oauth2/
|
|
|
|
redirect to('/oauth2authorize')
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
get '/oauth2authorize' do
|
|
|
|
redirect @client.authorization.authorization_uri.to_s, 303
|
|
|
|
end
|
|
|
|
|
|
|
|
get '/oauth2callback' do
|
|
|
|
@client.authorization.fetch_access_token!
|
2011-10-11 20:55:53 +00:00
|
|
|
save_token_pair(session, @client)
|
2011-08-02 16:44:56 +00:00
|
|
|
redirect to('/')
|
|
|
|
end
|
|
|
|
|
|
|
|
get '/' do
|
2011-10-11 20:55:53 +00:00
|
|
|
erb :index
|
2011-08-02 16:44:56 +00:00
|
|
|
end
|
|
|
|
|
2011-10-11 20:55:53 +00:00
|
|
|
get '/train' do
|
|
|
|
training = @prediction.trainedmodels.insert.request_schema.new
|
|
|
|
training.id = 'language-sample'
|
|
|
|
training.storage_data_location = DATA_OBJECT
|
|
|
|
result = @client.execute(
|
|
|
|
:api_method => @prediction.trainedmodels.insert,
|
|
|
|
:headers => {'Content-Type' => 'application/json'},
|
|
|
|
:body_object => training
|
|
|
|
)
|
2011-10-11 21:00:57 +00:00
|
|
|
|
|
|
|
return [
|
|
|
|
200,
|
|
|
|
[["Content-Type", "application/json"]],
|
|
|
|
::JSON.generate({"status": "success"})
|
|
|
|
]
|
2011-08-02 16:44:56 +00:00
|
|
|
end
|
|
|
|
|
2011-10-11 20:55:53 +00:00
|
|
|
get '/checkStatus' do
|
|
|
|
result = @client.execute(
|
|
|
|
:api_method => @prediction.trainedmodels.get,
|
|
|
|
:parameters => {'id' => 'language-sample'}
|
|
|
|
)
|
|
|
|
|
|
|
|
return [
|
|
|
|
200,
|
|
|
|
[["Content-Type", "application/json"]],
|
2011-10-11 21:00:57 +00:00
|
|
|
assemble_json_body(result)
|
2011-10-11 20:55:53 +00:00
|
|
|
]
|
2011-08-02 16:44:56 +00:00
|
|
|
end
|
|
|
|
|
2011-10-11 20:55:53 +00:00
|
|
|
post '/predict' do
|
|
|
|
input = @prediction.trainedmodels.predict.request_schema.new
|
|
|
|
input.input = {}
|
|
|
|
input.input.csv_instance = [params["input"]]
|
|
|
|
result = @client.execute(
|
|
|
|
:api_method => @prediction.trainedmodels.predict,
|
|
|
|
:parameters => {'id' => 'language-sample'},
|
|
|
|
:headers => {'Content-Type' => 'application/json'},
|
|
|
|
:body_object => input
|
|
|
|
)
|
2011-10-11 21:00:57 +00:00
|
|
|
|
|
|
|
return [
|
|
|
|
200,
|
|
|
|
[["Content-Type", "application/json"]],
|
|
|
|
assemble_json_body(result)
|
|
|
|
]
|
|
|
|
end
|
|
|
|
|
|
|
|
def assemble_json_body(result)
|
|
|
|
# Assemble some JSON our client-side code can work with.
|
2011-10-11 20:55:53 +00:00
|
|
|
json = {}
|
|
|
|
if result.status != 200
|
|
|
|
if result.data["error"]
|
|
|
|
message = result.data["error"]["errors"].first["message"]
|
|
|
|
json["message"] = "#{message} [#{result.status}]"
|
|
|
|
else
|
|
|
|
json["message"] = "Error. [#{result.status}]"
|
|
|
|
end
|
|
|
|
json["response"] = ::JSON.parse(result.body)
|
|
|
|
json["status"] = "error"
|
2011-08-02 16:44:56 +00:00
|
|
|
else
|
2011-10-11 20:55:53 +00:00
|
|
|
json["response"] = ::JSON.parse(result.body)
|
|
|
|
json["status"] = "success"
|
2011-08-02 16:44:56 +00:00
|
|
|
end
|
2011-10-11 21:00:57 +00:00
|
|
|
return ::JSON.generate(json)
|
2011-08-02 16:44:56 +00:00
|
|
|
end
|