live_paper 0.0.8 → 0.0.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/Rakefile +8 -0
- data/lib/live_paper.rb +24 -113
- data/lib/live_paper/base_object.rb +82 -0
- data/lib/live_paper/http_client.rb +80 -0
- data/lib/live_paper/image.rb +32 -0
- data/lib/live_paper/link.rb +46 -0
- data/lib/live_paper/payoff.rb +78 -0
- data/lib/live_paper/qr_trigger.rb +44 -0
- data/lib/live_paper/short_trigger.rb +37 -0
- data/lib/live_paper/version.rb +1 -1
- data/lib/live_paper/wm_trigger.rb +52 -0
- data/live_paper.gemspec +3 -1
- data/spec/live_paper/base_object_spec.rb +200 -0
- data/spec/live_paper/http_client_spec.rb +182 -0
- data/spec/live_paper/link_spec.rb +183 -0
- data/spec/live_paper/payoff_spec.rb +220 -0
- data/spec/live_paper/trigger_spec.rb +134 -0
- data/spec/live_paper_session_spec.rb +16 -0
- data/spec/spec_helper.rb +6 -0
- data/spec/spec_helpers/lpp_client.rb +75 -0
- metadata +55 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e0be6ece34f4d51cf32f7ea78ffaae9d6c8543b3
|
4
|
+
data.tar.gz: b3838914f2bbaca46a1af9d87d259612186849f0
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4956d0c6516a9f2778e2e84c2958a4ebc50b981fa9fce39dd2260b8ef00b07016834d13b43f14858c2f72a3ba516501c6058baca22fa50f8564d2b3310291346
|
7
|
+
data.tar.gz: bde0081f9039ec48fb5354cee3fdf5c062967a7f2cd3ca85bd5fab44ea7cda3067e3b68f99305895c4256c1e36e413159983159b7692713f6ec8dbf805545aa8
|
data/Rakefile
CHANGED
@@ -1,2 +1,10 @@
|
|
1
|
+
require 'rspec/core/rake_task'
|
1
2
|
require "bundler/gem_tasks"
|
2
3
|
|
4
|
+
# Default directory to look in is `/specs`
|
5
|
+
# Run with `rake spec`
|
6
|
+
RSpec::Core::RakeTask.new(:spec) do |task|
|
7
|
+
task.rspec_opts = ['--color', '--format', 'documentation']
|
8
|
+
end
|
9
|
+
|
10
|
+
task :default => :spec
|
data/lib/live_paper.rb
CHANGED
@@ -1,6 +1,15 @@
|
|
1
|
+
require "live_paper/base_object"
|
2
|
+
require "live_paper/http_client"
|
3
|
+
require "live_paper/image"
|
4
|
+
require "live_paper/link"
|
5
|
+
require "live_paper/payoff"
|
6
|
+
require "live_paper/wm_trigger"
|
7
|
+
require "live_paper/qr_trigger"
|
8
|
+
require "live_paper/short_trigger"
|
1
9
|
require "live_paper/version"
|
2
10
|
require 'base64'
|
3
11
|
require 'rest-client'
|
12
|
+
require 'json'
|
4
13
|
|
5
14
|
module LivePaper
|
6
15
|
|
@@ -12,7 +21,8 @@ module LivePaper
|
|
12
21
|
|
13
22
|
class LivePaperSession
|
14
23
|
def initialize(auth)
|
15
|
-
|
24
|
+
#todo: tdd, verify hash
|
25
|
+
$lpp_basic_auth = Base64.strict_encode64("#{auth[:id]}:#{auth[:secret]}")
|
16
26
|
end
|
17
27
|
|
18
28
|
def smart_link(dest, image=nil)
|
@@ -32,129 +42,30 @@ module LivePaper
|
|
32
42
|
end
|
33
43
|
|
34
44
|
def shorten(dest)
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
trig["link"].select { |item| item["rel"] == "shortURL" }.first["href"]
|
45
|
+
t=ShortTrigger.create(name: 'short trigger')
|
46
|
+
p=Payoff.create(name: 'name', type: Payoff::TYPE[:WEB], url: dest)
|
47
|
+
Link.create(payoff_id: p.id, trigger_id: t.id, name: "link")
|
48
|
+
t.short_url
|
41
49
|
end
|
42
50
|
|
43
51
|
def qr_bytes(dest)
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
img_loc = trig["link"].select { |item| item["rel"] == "image" }.first["href"]
|
50
|
-
resp = RestClient.get(img_loc, {Authorization: api_headers[:Authorization], Accept: 'image/png'})
|
51
|
-
resp.body
|
52
|
+
t=QrTrigger.create(name: 'QR code trigger')
|
53
|
+
p=Payoff.create(name: 'name', type: Payoff::TYPE[:WEB], url: dest)
|
54
|
+
Link.create(payoff_id: p.id, trigger_id: t.id, name: "link")
|
55
|
+
t.download_qrcode
|
52
56
|
end
|
53
57
|
|
54
58
|
def watermark_bytes(dest, image_url)
|
55
|
-
image =
|
59
|
+
image = Image.upload image_url
|
56
60
|
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
img_loc = trig["link"].select { |item| item["rel"] == "image" }.first["href"]
|
62
|
-
resp = RestClient.get(img_loc, Authorization: api_headers[:Authorization])
|
63
|
-
resp.body
|
61
|
+
t=WmTrigger.create(name: 'watermark', watermark: {strength: 10, resolution: 75, imageURL: image})
|
62
|
+
p=Payoff.create(name: 'name', type: Payoff::TYPE[:WEB], url: dest)
|
63
|
+
Link.create(payoff_id: p.id, trigger_id: t.id, name: "link")
|
64
|
+
t.download_watermark
|
64
65
|
rescue Exception => e
|
65
66
|
puts "Exception!"
|
66
67
|
puts e.response
|
67
68
|
end
|
68
69
|
|
69
|
-
private
|
70
|
-
def upload_image(img)
|
71
|
-
uri='https://storage.livepaperapi.com/objects/v1/files'
|
72
|
-
# return the original img uri if it is LPP storage
|
73
|
-
if img.include? uri
|
74
|
-
return img
|
75
|
-
end
|
76
|
-
begin
|
77
|
-
src_image = RestClient.get(img, Accept: 'image/jpg')
|
78
|
-
response = RestClient.post uri,
|
79
|
-
src_image.body,
|
80
|
-
Authorization: api_headers[:Authorization],
|
81
|
-
content_type: 'image/jpg'
|
82
|
-
response.headers[:location]
|
83
|
-
rescue Exception => e
|
84
|
-
puts "Exception! ******\n#{e}"
|
85
|
-
img
|
86
|
-
end
|
87
|
-
end
|
88
|
-
|
89
|
-
def trigger(type="shorturl", options={})
|
90
|
-
body = {
|
91
|
-
trigger: {
|
92
|
-
name: "trigger",
|
93
|
-
type: type,
|
94
|
-
expiryDate: Time.now + (365 * 24 * 60 * 60)
|
95
|
-
}.merge(options)
|
96
|
-
}
|
97
|
-
create_resource('trigger', body)
|
98
|
-
end
|
99
|
-
|
100
|
-
def url_payoff(dest)
|
101
|
-
body = {
|
102
|
-
payoff: {
|
103
|
-
name: "payoff",
|
104
|
-
URL: dest
|
105
|
-
}
|
106
|
-
}
|
107
|
-
create_resource('payoff', body)
|
108
|
-
end
|
109
|
-
|
110
|
-
def link(trigger, payoff)
|
111
|
-
body = {
|
112
|
-
link: {
|
113
|
-
name: "link",
|
114
|
-
payoffId: payoff["id"],
|
115
|
-
triggerId: trigger["id"]
|
116
|
-
}
|
117
|
-
}
|
118
|
-
create_resource('link', body)
|
119
|
-
end
|
120
|
-
|
121
|
-
def authorize(auth)
|
122
|
-
uri = "#{LP_API_HOST}/auth/token"
|
123
|
-
body = "grant_type=client_credentials&scope=all"
|
124
|
-
|
125
|
-
basic_auth = Base64.strict_encode64("#{auth[:id]}:#{auth[:secret]}")
|
126
|
-
|
127
|
-
begin
|
128
|
-
response = RestClient.post uri, body,
|
129
|
-
:content_type => 'application/x-www-form-urlencoded',
|
130
|
-
Accept: 'application/json',
|
131
|
-
Authorization: "Basic #{basic_auth}"
|
132
|
-
rescue Exception => e
|
133
|
-
puts "Exception!"
|
134
|
-
puts e.response
|
135
|
-
end
|
136
|
-
|
137
|
-
body = JSON.parse(response.body)
|
138
|
-
@token=body["accessToken"]
|
139
|
-
end
|
140
|
-
|
141
|
-
def api_headers
|
142
|
-
{Authorization: "Bearer #{@token}",
|
143
|
-
content_type: 'application/json',
|
144
|
-
Accept: 'application/json'
|
145
|
-
}
|
146
|
-
end
|
147
|
-
|
148
|
-
def create_resource(resource, body)
|
149
|
-
uri= "https://www.livepaperapi.com/api/v1/#{resource}s"
|
150
|
-
response = RestClient.post uri, body.to_json, api_headers
|
151
|
-
JSON.parse(response.body)[resource]
|
152
|
-
rescue Exception => e
|
153
|
-
puts "Exception!"
|
154
|
-
puts e.response
|
155
|
-
nil
|
156
|
-
end
|
157
|
-
|
158
70
|
end
|
159
|
-
|
160
71
|
end
|
@@ -0,0 +1,82 @@
|
|
1
|
+
require_relative 'http_client'
|
2
|
+
require 'json'
|
3
|
+
|
4
|
+
module LivePaper
|
5
|
+
class BaseObject
|
6
|
+
extend HttpClient
|
7
|
+
attr_accessor :id, :name, :date_created, :date_modified
|
8
|
+
|
9
|
+
def assign_attributes(data)
|
10
|
+
data.each do |key, value|
|
11
|
+
method = "#{underscore key.to_s}="
|
12
|
+
public_send(method, value) if respond_to?(method)
|
13
|
+
end unless data.empty?
|
14
|
+
end
|
15
|
+
|
16
|
+
def initialize(data={})
|
17
|
+
assign_attributes data
|
18
|
+
end
|
19
|
+
|
20
|
+
def self.create(data)
|
21
|
+
self.new(data).save
|
22
|
+
end
|
23
|
+
|
24
|
+
def save
|
25
|
+
validate_attributes!
|
26
|
+
BaseObject.request_handling_auth(self.class.api_url, 'POST') do |request|
|
27
|
+
response = BaseObject.send_request(request, 'application/json', create_body.to_json)
|
28
|
+
parse(response.body)
|
29
|
+
end unless present? @id
|
30
|
+
self
|
31
|
+
end
|
32
|
+
|
33
|
+
def self.find(id)
|
34
|
+
request_handling_auth("#{api_url}/#{id}", 'GET') do |request|
|
35
|
+
response = send_request(request, 'application/json')
|
36
|
+
parse response.body
|
37
|
+
end rescue nil
|
38
|
+
end
|
39
|
+
|
40
|
+
def self.parse(data)
|
41
|
+
self.new().parse(data)
|
42
|
+
end
|
43
|
+
|
44
|
+
def parse(data)
|
45
|
+
raise NotImplementedError
|
46
|
+
end
|
47
|
+
|
48
|
+
def self.api_url
|
49
|
+
raise NotImplementedError
|
50
|
+
end
|
51
|
+
|
52
|
+
protected
|
53
|
+
def all_present?(array)
|
54
|
+
array.all? { |e| present? e } rescue false
|
55
|
+
end
|
56
|
+
|
57
|
+
def all_keys_present?(hash, keys)
|
58
|
+
keys.all? { |e| present? hash[e] } rescue false
|
59
|
+
end
|
60
|
+
|
61
|
+
def present?(obj)
|
62
|
+
!(obj.respond_to?(:empty?) ? obj.empty? : !obj)
|
63
|
+
end
|
64
|
+
|
65
|
+
def underscore(camel_cased_word)
|
66
|
+
camel_cased_word.gsub(/::/, '/').
|
67
|
+
gsub(/([A-Z]+)([A-Z][a-z])/, '\1_\2').
|
68
|
+
gsub(/([a-z\d])([A-Z])/, '\1_\2').
|
69
|
+
tr("-", "_").
|
70
|
+
downcase
|
71
|
+
end
|
72
|
+
|
73
|
+
private
|
74
|
+
def validate_attributes!
|
75
|
+
raise NotImplementedError
|
76
|
+
end
|
77
|
+
|
78
|
+
def create_body
|
79
|
+
raise NotImplementedError
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
@@ -0,0 +1,80 @@
|
|
1
|
+
require 'open-uri'
|
2
|
+
require 'net/https'
|
3
|
+
|
4
|
+
class NotAuthenticatedError < Exception
|
5
|
+
end
|
6
|
+
|
7
|
+
module LivePaper
|
8
|
+
module HttpClient
|
9
|
+
LP_API_HOST="https://www.livepaperapi.com"
|
10
|
+
AUTH_URL = "#{LP_API_HOST}/auth/token"
|
11
|
+
|
12
|
+
def send_request(request, content_type = nil, body = nil)
|
13
|
+
request['Content-type'] = content_type if content_type
|
14
|
+
request.body = body if body
|
15
|
+
response = @http.request(request)
|
16
|
+
check_response(response)
|
17
|
+
response
|
18
|
+
end
|
19
|
+
|
20
|
+
def check_response(response)
|
21
|
+
status = response.code.to_i
|
22
|
+
raise NotAuthenticatedError.new("Unauthorized") if status == 401
|
23
|
+
unless Array(200..201).include?(status)
|
24
|
+
raise "Request failed with code #{status}"
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def request_handling_auth(url, method)
|
29
|
+
tries = 0
|
30
|
+
begin
|
31
|
+
request_access_token unless @access_token
|
32
|
+
request = http_request(url, method)
|
33
|
+
request['Authorization'] = "Bearer #{@access_token}"
|
34
|
+
yield request
|
35
|
+
rescue NotAuthenticatedError => e
|
36
|
+
tries += 1
|
37
|
+
if tries < 3
|
38
|
+
@access_token = nil
|
39
|
+
retry
|
40
|
+
else
|
41
|
+
raise e
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def request_access_token
|
47
|
+
request = http_request(AUTH_URL, 'POST')
|
48
|
+
request['Authorization'] = "Basic #{$lpp_basic_auth}"
|
49
|
+
request['Content-Type'] = 'application/x-www-form-urlencoded'
|
50
|
+
request.body = 'grant_type=client_credentials&scope=all'
|
51
|
+
response = @http.request(request)
|
52
|
+
parsed = JSON.parse(response.body)
|
53
|
+
@access_token = parsed['accessToken']
|
54
|
+
end
|
55
|
+
|
56
|
+
def http_request(url, method)
|
57
|
+
uri = URI.parse(url)
|
58
|
+
set_http uri
|
59
|
+
|
60
|
+
case method.to_s.upcase
|
61
|
+
when 'POST'
|
62
|
+
Net::HTTP::Post.new(uri.request_uri)
|
63
|
+
when 'GET'
|
64
|
+
Net::HTTP::Get.new(uri.request_uri)
|
65
|
+
else
|
66
|
+
raise "Method '#{method}' not supported."
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
private
|
71
|
+
def set_http(uri)
|
72
|
+
http_params = [uri.host, uri.port]
|
73
|
+
http_params.concat ENV['HTTP_PROXY'].gsub('http://', '').split(':') unless ENV['HTTP_PROXY'].to_s.empty?
|
74
|
+
|
75
|
+
@http = Net::HTTP.new(*http_params)
|
76
|
+
@http.use_ssl = true
|
77
|
+
@http.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
require_relative 'base_object'
|
2
|
+
require 'rest-client'
|
3
|
+
|
4
|
+
module LivePaper
|
5
|
+
class Image
|
6
|
+
extend HttpClient
|
7
|
+
|
8
|
+
attr_accessor :url
|
9
|
+
|
10
|
+
API_URL = 'https://storage.livepaperapi.com/objects/v1/files'
|
11
|
+
|
12
|
+
def self.upload(img)
|
13
|
+
# return the original img uri if it is LivePaper storage
|
14
|
+
if img.include? API_URL
|
15
|
+
return img
|
16
|
+
end
|
17
|
+
begin
|
18
|
+
src_image = RestClient.get(img, Accept: 'image/jpg')
|
19
|
+
request_access_token unless @access_token
|
20
|
+
response = RestClient.post API_URL,
|
21
|
+
src_image.body,
|
22
|
+
Authorization: "Bearer #{@access_token}",
|
23
|
+
content_type: 'image/jpg'
|
24
|
+
response.headers[:location]
|
25
|
+
rescue Exception => e
|
26
|
+
puts "Exception! ******\n#{e}"
|
27
|
+
img
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
require_relative 'base_object'
|
2
|
+
|
3
|
+
module LivePaper
|
4
|
+
class Link < BaseObject
|
5
|
+
attr_accessor :payoff_id, :trigger_id, :analytics
|
6
|
+
|
7
|
+
def parse(data)
|
8
|
+
data = JSON.parse(data, symbolize_names: true)[:link]
|
9
|
+
assign_attributes data
|
10
|
+
@analytics = get_link_for data, 'analytics'
|
11
|
+
self
|
12
|
+
end
|
13
|
+
|
14
|
+
def payoff
|
15
|
+
@payoff ||= LivePaper::Payoff.find @payoff_id
|
16
|
+
end
|
17
|
+
|
18
|
+
def trigger
|
19
|
+
#todo: need to get the right object created here!!!
|
20
|
+
@trigger ||= LivePaper::WmTrigger.find @trigger_id
|
21
|
+
end
|
22
|
+
|
23
|
+
def self.api_url
|
24
|
+
"#{LP_API_HOST}/api/v1/links"
|
25
|
+
end
|
26
|
+
|
27
|
+
private
|
28
|
+
def validate_attributes!
|
29
|
+
raise ArgumentError, 'Required Attributes needed: name, payoff_id and trigger_id.' unless all_present? [@name, @payoff_id, @trigger_id]
|
30
|
+
end
|
31
|
+
|
32
|
+
def create_body
|
33
|
+
{
|
34
|
+
link: {
|
35
|
+
name: @name,
|
36
|
+
triggerId: @trigger_id,
|
37
|
+
payoffId: @payoff_id
|
38
|
+
}
|
39
|
+
}
|
40
|
+
end
|
41
|
+
|
42
|
+
def get_link_for(data, rel)
|
43
|
+
data[:link].find { |obj| obj[:rel] == rel }[:href] rescue ''
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,78 @@
|
|
1
|
+
require_relative 'base_object'
|
2
|
+
|
3
|
+
module LivePaper
|
4
|
+
class Payoff < BaseObject
|
5
|
+
attr_accessor :type, :url, :data_type, :data
|
6
|
+
|
7
|
+
TYPE = {
|
8
|
+
WEB: 'WEB_PAYOFF',
|
9
|
+
RICH: 'RICH_PAYOFF'
|
10
|
+
}
|
11
|
+
|
12
|
+
def parse(data)
|
13
|
+
data = JSON.parse(data, symbolize_names: true)[:payoff]
|
14
|
+
assign_attributes(data)
|
15
|
+
send(present?(data[:richPayoff]) ? :parse_richpayoff : :parse_webpayoff, data)
|
16
|
+
self
|
17
|
+
end
|
18
|
+
|
19
|
+
def self.api_url
|
20
|
+
"#{LP_API_HOST}/api/v1/payoffs"
|
21
|
+
end
|
22
|
+
|
23
|
+
private
|
24
|
+
def validate_attributes!
|
25
|
+
raise ArgumentError, 'Required Attributes needed: name, type, url.' unless all_present? [@name, @type, @url]
|
26
|
+
raise ArgumentError, 'Required Attributes needed: data_type, data.' if @type == TYPE[:RICH] and !all_present? [@data_type, @data]
|
27
|
+
end
|
28
|
+
|
29
|
+
def parse_richpayoff(data)
|
30
|
+
data = data[:richPayoff]
|
31
|
+
|
32
|
+
@type = TYPE[:RICH]
|
33
|
+
@url = data[:public][:url]
|
34
|
+
@data_type = data[:private][:'content-type']
|
35
|
+
@data = JSON.parse(Base64.decode64(data[:private][:data]), symbolize_names: true) rescue nil
|
36
|
+
end
|
37
|
+
|
38
|
+
def parse_webpayoff(data)
|
39
|
+
@type = TYPE[:WEB]
|
40
|
+
@url = data[:URL]
|
41
|
+
end
|
42
|
+
|
43
|
+
def create_body
|
44
|
+
{
|
45
|
+
payoff: case @type
|
46
|
+
when TYPE[:WEB]
|
47
|
+
create_webpayoff_body
|
48
|
+
when TYPE[:RICH]
|
49
|
+
create_richpayoff_body
|
50
|
+
else
|
51
|
+
raise ArgumentError, 'Type unknown.'
|
52
|
+
end
|
53
|
+
}
|
54
|
+
end
|
55
|
+
|
56
|
+
def create_webpayoff_body
|
57
|
+
{
|
58
|
+
name: @name,
|
59
|
+
URL: @url
|
60
|
+
}
|
61
|
+
end
|
62
|
+
|
63
|
+
def create_richpayoff_body
|
64
|
+
{
|
65
|
+
name: @name,
|
66
|
+
richPayoff: {
|
67
|
+
version: 1,
|
68
|
+
private: {
|
69
|
+
:'content-type' => @data_type,
|
70
|
+
:data => @data
|
71
|
+
},
|
72
|
+
public: {url: @url}
|
73
|
+
}
|
74
|
+
}
|
75
|
+
end
|
76
|
+
|
77
|
+
end
|
78
|
+
end
|