Class: Picobrew::Api

Inherits:
Object
  • Object
show all
Includes:
HTTParty
Defined in:
lib/picobrew/api.rb

Constant Summary collapse

HOST =
'picobrew.com'

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(username, password, cookies = nil) ⇒ Api

Returns a new instance of Api.



17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
# File 'lib/picobrew/api.rb', line 17

def initialize(username, password, cookies = nil)
	@username = username
	@password = password
	@http = Net::HTTP.new(HOST, 443)
	@http.use_ssl = true
	@http.verify_mode = OpenSSL::SSL::VERIFY_NONE
       @cached_sessions = []

	log "Created Picobrew object for #{username}"
       if !cookies.nil?
           log "Using provided cookies instead of logging in"
           @cookies = cookie_from_hash(cookies)
       else
           ()
       end
end

Instance Attribute Details

#cookiesObject (readonly)

debug_output



15
16
17
# File 'lib/picobrew/api.rb', line 15

def cookies
  @cookies
end

Instance Method Details

#cache_sessionsObject



199
200
201
202
203
# File 'lib/picobrew/api.rb', line 199

def cache_sessions()
    log "Caching sesions"
    @cached_sessions = get_all_sessions()
    @cached_at = Time.now
end

#check_active(session_id) ⇒ Object

don’t really understand this one, not sure if id is required



218
219
220
221
222
223
224
225
226
227
# File 'lib/picobrew/api.rb', line 218

def check_active(session_id)
    log "Check if session is active: #{session_id}"
    begin
        options = options({:body => {'option' => 'checkActive', 'sessionId' => session_id}})
        response = self.class.post('/JSONAPI/Zymatic/ZymaticSession.cshtml', options)
        response.body
    rescue Exception => e
        log "Error: #{e}"
    end
end


264
265
266
267
268
# File 'lib/picobrew/api.rb', line 264

def cookie_from_hash(hsh)
    cookie_hash = CookieHash.new
    cookie_hash.add_cookies(hsh)
    cookie_hash
end

#find_session(session_guid) ⇒ Object



192
193
194
195
196
197
# File 'lib/picobrew/api.rb', line 192

def find_session(session_guid)
       log "Looking up short session id for #{session_guid}"
       # quick and dirty cache expiration
       cache_sessions if @cached_sessions.empty? || @cached_at.to_i + 5 * 60 < Time.now.to_i
       return @cached_sessions.find {|session| session['GUID'] == session_guid}
end

#get_active_sessionObject



205
206
207
208
209
210
211
212
213
214
215
# File 'lib/picobrew/api.rb', line 205

def get_active_session()
       log "Get Active Session"
       begin
       	options = options({:body => {'option' => 'getZymaticsForUser', 'getActiveSession' => 'true'}})
       	response = self.class.post('/JSONAPI/Zymatic/ZymaticSession.cshtml', options)
		# TOOD: return json
           response.body
       rescue Exception => e
       	log "Error: #{e}"
       end
end

#get_all_recipesObject



55
56
57
58
59
60
61
62
63
64
# File 'lib/picobrew/api.rb', line 55

def get_all_recipes()
	log "Get All Recipes"
       begin
       	options = options({:body => {'option' => 'getAllRecipesForUser'}})
       	response = self.class.post('/JSONAPI/Zymatic/ZymaticRecipe.cshtml', options)
       	body = JSON.parse(response.body)
       rescue Exception => e
       	log "Error: #{e}"
       end
end

#get_all_sessionsObject



137
138
139
140
141
142
143
144
145
146
# File 'lib/picobrew/api.rb', line 137

def get_all_sessions()
    log "Get All Sessions"
    begin
        options = options({:body => {'option' => 'getAllSessionsForUser'}})
        response = self.class.post('/JSONAPI/Zymatic/ZymaticSession.cshtml', options)
        body = JSON.parse(response.body)
    rescue Exception => e
        log "Error: #{e}"
    end
end

#get_recipe(recipe_id) ⇒ Object



66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
# File 'lib/picobrew/api.rb', line 66

def get_recipe(recipe_id)
    log "Scrape Recipe #{recipe_id}"
    begin
        options = options({})
        response = self.class.get("/Members/Recipes/ParseRecipe.cshtml?id=#{recipe_id}", options)
        page = Nokogiri::HTML(response.body)
        recipe = {'specs' => {}}
        page.css('#user-specs-table tr').each do |element|
            recipe['specs'][element.css('td')[0].text] = element.css('td')[1].text
        end
        page.css('#editForm input').each do |element|
            if is_json? element['value']
                recipe[element['name']] = JSON.parse(element['value'])
            else
                recipe[element['name']] = element['value']
            end
        end
        recipe
    rescue Exception => e
        log "Error: #{e}"
    end
end

#get_recipe_control_program(recipe_id) ⇒ Object



89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
# File 'lib/picobrew/api.rb', line 89

def get_recipe_control_program(recipe_id)
    log "Scrape Recipe Advanced Editor"
    begin
        options = options({})
        response = self.class.get("/members/recipes/editctlprogram?id=#{recipe_id}", options)
        page = Nokogiri::HTML(response.body)
        program = {'steps' => []}
        page.css('#stepTable tr').each do |row|
            next if row.at_css('input').nil?

            step = {
                'index' => row.at_css('input')['data-index'].to_i,
                'name' => row.at_css('input[name*=Name]')['value'],
                'location' => row.at_css('select option[@selected=selected]').text,
                'targetTemp' => row.at_css('input[name*=Temp]')['value'].to_i,
                'time' => row.at_css('input[name*=Time]')['value'].to_i,
                'drain' => row.at_css('input[name*=Drain]')['value'].to_i
            }

            program['steps'].push(step) if !step['name'].nil?
        end
        program
    rescue Exception => e
        log "Error: #{e}"
    end
end

#get_recipe_control_programs(user_id, machine_id) ⇒ Object

API used by Zymatic hardware Does not require auth, but require user id and machine id Move this to a separate class?



232
233
234
235
236
237
238
239
240
# File 'lib/picobrew/api.rb', line 232

def get_recipe_control_programs(user_id, machine_id)
    log "Get Recipe Control Programs"
    begin
        response = self.class.get("/API/SyncUser?user=#{user_id}&machine=#{machine_id}")
        response.body
    rescue Exception => e
        log "Error: #{e}"
    end
end

#get_recipe_id_for_session_id(session_guid) ⇒ Object



182
183
184
185
# File 'lib/picobrew/api.rb', line 182

def get_recipe_id_for_session_id(session_guid)
	session = find_session(session_guid)
	return session['RecipeGUID'] if !session.nil?
end

#get_session_log(session_id) ⇒ Object



148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
# File 'lib/picobrew/api.rb', line 148

def get_session_log(session_id)
	log "Get Session Log for #{session_id}"
       # the sessions list contains references for guids, but the log api
       # wants a *different* id, so need to lookup one from the other
       if session_id.length > 6
           session_id = get_short_session_id_for_guid(session_id)
           raise Exception "No short session id for guid" if session_id.nil?
           log "Get Session Log for #{session_id}"
       end
	begin
		options = options({:body => {'option' => 'getSessionLogs', 'sessionID' => session_id}})
		response = self.class.post('/JSONAPI/Zymatic/ZymaticSession.cshtml', options)
		body = JSON.parse(response.body)
	rescue Exception => e
		log "Error: #{e}"
	end
end

#get_session_notes(session_id) ⇒ Object



166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
# File 'lib/picobrew/api.rb', line 166

def get_session_notes(session_id)
    log "Get Session Notes for #{session_id}"
    if session_id.length > 6
        session_id = get_short_session_id_for_guid(session_id)
        raise Exception, "No short session id for guid" if session_id.nil?
        log "Get Session Notes for #{session_id}"
    end
    begin
        options = options({ :body => {'option' => 'getSessionNotes', 'sessionID' => session_id} })
        response = self.class.post('/JSONAPI/Zymatic/ZymaticSession.cshtml', options)
        body = JSON.parse(response.body)
    rescue Exception => e
        log "Error: #{e}"
    end
end

#get_sessions_for_recipe(recipe_id) ⇒ Object



116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
# File 'lib/picobrew/api.rb', line 116

def get_sessions_for_recipe(recipe_id)
    log "Get Sessions for Recipe #{recipe_id}"
    begin
        options = options({})
        response = self.class.get("/Members/Logs/brewingsessions.cshtml?id=#{recipe_id}", options)
        page = Nokogiri::HTML(response.body)
        sessions = []
        page.css('#BrewingSessions tbody tr').each do |row|
            sessions.push({
                'name' => row.css('td.name').text,
                'id' => row.css('td.name a')[0]['href'].gsub(/.*id=/, ''),
                'date' => row.css('td.date').text,
                'notes' => row.css('td')[3].text
            } )
        end
        sessions
    rescue Exception => e
        log "Error: #{e}"
    end
end

#get_short_session_id_for_guid(session_guid) ⇒ Object



187
188
189
190
# File 'lib/picobrew/api.rb', line 187

def get_short_session_id_for_guid(session_guid)
		session = find_session(session_guid)
    return session['ID'] if !session.nil?
end

#is_json?(json) ⇒ Boolean

Returns:

  • (Boolean)


242
243
244
245
246
247
248
249
# File 'lib/picobrew/api.rb', line 242

def is_json?(json)
    begin
        JSON.parse(json)
        return true
    rescue JSON::ParserError
        return false
    end
end

#log(msg) ⇒ Object



270
271
272
# File 'lib/picobrew/api.rb', line 270

def log(msg)
	# puts msg
end

#logged_in?Boolean

Returns:

  • (Boolean)


51
52
53
# File 'lib/picobrew/api.rb', line 51

def logged_in?()
	!@cookies.nil?
end

#loginObject



34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
# File 'lib/picobrew/api.rb', line 34

def ()
	log "Logging in"
	begin
           options = {
               :body => {'username' => @username, 'Password' => @password},
               :headers => {'Content-Type' => 'application/x-www-form-urlencoded; charset=UTF-8'},
               :follow_redirects => false
           }
        response = self.class.post('/account/loginAjax.cshtml', options)
           raise "No Set-Cookie in response" if response.get_fields('Set-Cookie').nil?
        @cookies = parse_cookie(response)
       rescue Exception => e
           raise "Authentication error: #{e}"
       end
       log "logged in"
end

#options(params) ⇒ Object



251
252
253
254
255
256
# File 'lib/picobrew/api.rb', line 251

def options(params)
    { :headers => {
        'Content-Type' => 'application/x-www-form-urlencoded',
        'Cookie' => @cookies.to_cookie_string }
    }.merge params
end


258
259
260
261
262
# File 'lib/picobrew/api.rb', line 258

def parse_cookie(resp)
    cookie_hash = CookieHash.new
    resp.get_fields('Set-Cookie').each { |c| cookie_hash.add_cookies(c) }
    cookie_hash
end