wildcard-pair 0.3.1
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 +7 -0
- data/lib/wildcard-pair.rb +5 -0
- data/lib/wildcard-pair/Article.rb +90 -0
- data/lib/wildcard-pair/ArticleCard.rb +84 -0
- data/lib/wildcard-pair/Color.rb +41 -0
- data/lib/wildcard-pair/Media.rb +4 -0
- data/lib/wildcard-pair/Media/Image.rb +46 -0
- data/lib/wildcard-pair/Media/Video.rb +70 -0
- data/lib/wildcard-pair/Offer.rb +102 -0
- data/lib/wildcard-pair/Price.rb +44 -0
- data/lib/wildcard-pair/Product.rb +132 -0
- data/lib/wildcard-pair/ProductCard.rb +117 -0
- data/lib/wildcard-pair/ProductSearchCard.rb +89 -0
- data/lib/wildcard-pair/ProductSearchResult.rb +54 -0
- data/lib/wildcard-pair/Rating.rb +47 -0
- data/lib/wildcard-pair/Review.rb +105 -0
- data/lib/wildcard-pair/ReviewCard.rb +82 -0
- data/lib/wildcard-pair/VideoCard.rb +84 -0
- data/lib/wildcard-pair/hash_mappable.rb +18 -0
- data/lib/wildcard-pair/util/extract_metatags.rb +99 -0
- metadata +124 -0
@@ -0,0 +1,105 @@
|
|
1
|
+
#!/usr/bin/env ruby -wKU
|
2
|
+
|
3
|
+
require 'active_model'
|
4
|
+
require_relative 'hash_mappable.rb'
|
5
|
+
require_relative 'Media.rb'
|
6
|
+
|
7
|
+
module WildcardPair
|
8
|
+
class Review
|
9
|
+
|
10
|
+
include ActiveModel::Validations
|
11
|
+
include ActiveModel::Serializers::JSON
|
12
|
+
include WildcardPair::HashMappable
|
13
|
+
include WildcardPair::Media
|
14
|
+
|
15
|
+
# required fields
|
16
|
+
attr_accessor :title, :html_content
|
17
|
+
# optional fields
|
18
|
+
attr_accessor :publication_date, :abstract_content, :source, :author,
|
19
|
+
:updated_date, :product_name, :app_link_ios,
|
20
|
+
:app_link_android
|
21
|
+
attr_reader :rating, :media
|
22
|
+
|
23
|
+
validates :title, presence: true
|
24
|
+
validates :html_content, presence: true
|
25
|
+
|
26
|
+
validate :validate_media
|
27
|
+
validate :validate_rating
|
28
|
+
|
29
|
+
def metatags=(metatags)
|
30
|
+
if metatags.nil? || !metatags.is_a?(Hash)
|
31
|
+
return
|
32
|
+
end
|
33
|
+
|
34
|
+
#see what you can set based on metatags
|
35
|
+
self.title=metatags['title']
|
36
|
+
self.html_content=metatags['html']
|
37
|
+
self.abstract_content=metatags['description']
|
38
|
+
self.media=Media::Image.new image_url: metatags['image_url']
|
39
|
+
self.app_link_ios=metatags['applink_ios']
|
40
|
+
self.app_link_android=metatags['applink_android']
|
41
|
+
end
|
42
|
+
|
43
|
+
def media=(media)
|
44
|
+
if media.is_a? Video
|
45
|
+
@media = map_hash(media, Media::Video.new)
|
46
|
+
elsif media.is_a? Image
|
47
|
+
@media = map_hash(media, Media::Image.new)
|
48
|
+
elsif media.is_a? Hash
|
49
|
+
if media[:type] == 'video'
|
50
|
+
@media = map_hash(media, Media::Video.new)
|
51
|
+
elsif media[:type] == 'image'
|
52
|
+
@media = map_hash(media, Media::Image.new)
|
53
|
+
else
|
54
|
+
@media = media
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
def validate_media
|
60
|
+
if @media.nil? then return end
|
61
|
+
|
62
|
+
if !@media.is_a? Media or !@media.valid?
|
63
|
+
errors.add(:media, "Media is invalid")
|
64
|
+
return false
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
def rating=(rating)
|
69
|
+
@rating = map_hash(rating, WildcardPair::Rating.new)
|
70
|
+
end
|
71
|
+
|
72
|
+
def initialize(attributes = {})
|
73
|
+
attributes.each do |name, value|
|
74
|
+
send("#{name}=", value)
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
def attributes
|
79
|
+
instance_values
|
80
|
+
end
|
81
|
+
|
82
|
+
def validate_rating
|
83
|
+
if @rating.nil? then return end
|
84
|
+
|
85
|
+
if !@rating.is_a? Rating or !@rating.valid?
|
86
|
+
errors.add(:rating, "Rating is invalid")
|
87
|
+
return false
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
#exclude validation fields in the JSON output
|
92
|
+
def as_json(options={})
|
93
|
+
super(options.merge({:except => [:errors, :validation_context]}))
|
94
|
+
end
|
95
|
+
|
96
|
+
def to_json(options={})
|
97
|
+
if self.valid?
|
98
|
+
super(options)
|
99
|
+
else
|
100
|
+
raise "Video is not valid - please remedy the following errors:" << self.errors.messages.to_s
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
end
|
105
|
+
end
|
@@ -0,0 +1,82 @@
|
|
1
|
+
#!/usr/bin/env ruby -wKU
|
2
|
+
|
3
|
+
require 'active_model'
|
4
|
+
require_relative 'hash_mappable.rb'
|
5
|
+
|
6
|
+
module WildcardPair
|
7
|
+
class ReviewCard
|
8
|
+
private
|
9
|
+
|
10
|
+
attr_accessor :review, :card_type, :pair_version
|
11
|
+
|
12
|
+
public
|
13
|
+
|
14
|
+
include ActiveModel::Validations
|
15
|
+
include ActiveModel::Serializers::JSON
|
16
|
+
include WildcardPair::HashMappable
|
17
|
+
|
18
|
+
attr_accessor :web_url
|
19
|
+
attr_reader :review, :card_type, :pair_version
|
20
|
+
|
21
|
+
validates :web_url, presence: true
|
22
|
+
validate :validate_review
|
23
|
+
|
24
|
+
def initialize(attributes = {})
|
25
|
+
attributes.each do |name, value|
|
26
|
+
send("#{name}=", value)
|
27
|
+
end
|
28
|
+
|
29
|
+
@card_type = 'review'
|
30
|
+
|
31
|
+
if !Gem.loaded_specs['wildcard-pair'].nil?
|
32
|
+
@pair_version = Gem.loaded_specs['wildcard-pair'].version.to_s
|
33
|
+
else
|
34
|
+
@pair_version = "unknown"
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def attributes
|
39
|
+
instance_values
|
40
|
+
end
|
41
|
+
|
42
|
+
def populate_from_metatags(web_url)
|
43
|
+
@web_url=web_url
|
44
|
+
metatags = WildcardPair::ExtractMetaTags.extract(@web_url)
|
45
|
+
|
46
|
+
##now that we've extracted metatags, let's create a Review
|
47
|
+
self.review=WildcardPair::Review.new metatags: metatags
|
48
|
+
end
|
49
|
+
|
50
|
+
def review=(review)
|
51
|
+
@review = map_hash(review, WildcardPair::Review.new)
|
52
|
+
end
|
53
|
+
|
54
|
+
def validate_review
|
55
|
+
if @review.nil? or !@review.is_a? Review
|
56
|
+
errors.add(:review, "A review is required")
|
57
|
+
return
|
58
|
+
end
|
59
|
+
|
60
|
+
if !@review.valid?
|
61
|
+
@review.errors.each do |error, msg|
|
62
|
+
errors["review[%s]" % error] = msg
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
#exclude validation fields in the JSON output
|
68
|
+
def as_json(options={})
|
69
|
+
super(options.merge({:except => [:errors, :validation_context]}))
|
70
|
+
end
|
71
|
+
|
72
|
+
def to_json(options={})
|
73
|
+
if self.valid?
|
74
|
+
super(options)
|
75
|
+
else
|
76
|
+
raise "Review Card is not valid - please remedy the following errors:" << self.errors.messages.to_s
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
@@ -0,0 +1,84 @@
|
|
1
|
+
#!/usr/bin/env ruby -wKU
|
2
|
+
|
3
|
+
require 'active_model'
|
4
|
+
require_relative 'hash_mappable.rb'
|
5
|
+
require_relative 'Media.rb'
|
6
|
+
|
7
|
+
module WildcardPair
|
8
|
+
class VideoCard
|
9
|
+
private
|
10
|
+
|
11
|
+
attr_accessor :media, :card_type, :pair_version
|
12
|
+
|
13
|
+
public
|
14
|
+
|
15
|
+
include ActiveModel::Validations
|
16
|
+
include ActiveModel::Serializers::JSON
|
17
|
+
include WildcardPair::HashMappable
|
18
|
+
include WildcardPair::Media
|
19
|
+
|
20
|
+
attr_accessor :web_url
|
21
|
+
attr_reader :media, :card_type, :pair_version
|
22
|
+
|
23
|
+
validates :web_url, presence: true
|
24
|
+
validate :validate_media
|
25
|
+
|
26
|
+
def initialize(attributes = {})
|
27
|
+
attributes.each do |name, value|
|
28
|
+
send("#{name}=", value)
|
29
|
+
end
|
30
|
+
|
31
|
+
@card_type = 'video'
|
32
|
+
|
33
|
+
if !Gem.loaded_specs['wildcard-pair'].nil?
|
34
|
+
@pair_version = Gem.loaded_specs['wildcard-pair'].version.to_s
|
35
|
+
else
|
36
|
+
@pair_version = "unknown"
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def attributes
|
41
|
+
instance_values
|
42
|
+
end
|
43
|
+
|
44
|
+
def populate_from_metatags(web_url)
|
45
|
+
@web_url=web_url
|
46
|
+
metatags = WildcardPair::ExtractMetaTags.extract(@web_url)
|
47
|
+
|
48
|
+
##now that we've extracted metatags, let's create a Video object with it
|
49
|
+
self.media=WildcardPair::Media::Video.new metatags: metatags
|
50
|
+
end
|
51
|
+
|
52
|
+
def media=(media)
|
53
|
+
@media = map_hash(media, WildcardPair::Media::Video.new)
|
54
|
+
end
|
55
|
+
|
56
|
+
def validate_media
|
57
|
+
if @media.nil? || !@media.is_a?(Video)
|
58
|
+
errors.add(:media, "A video is required")
|
59
|
+
return
|
60
|
+
end
|
61
|
+
|
62
|
+
if !@media.valid?
|
63
|
+
@media.errors.each do |error, msg|
|
64
|
+
errors["media[%s]" % error] = msg = msg
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
#exclude validation fields in the JSON output
|
70
|
+
def as_json(options={})
|
71
|
+
super(options.merge({:except => [:errors, :validation_context]}))
|
72
|
+
end
|
73
|
+
|
74
|
+
def to_json(options={})
|
75
|
+
if self.valid?
|
76
|
+
super(options)
|
77
|
+
else
|
78
|
+
raise "Video Card is not valid - please remedy the following errors:" << self.errors.messages.to_s
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module WildcardPair
|
2
|
+
module HashMappable
|
3
|
+
def map_hash(value, target)
|
4
|
+
if value.is_a? Hash
|
5
|
+
target.attributes = value
|
6
|
+
return target
|
7
|
+
else
|
8
|
+
return value
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
def attributes=(hash)
|
13
|
+
hash.each do |key, value|
|
14
|
+
send("#{key}=", value)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,99 @@
|
|
1
|
+
require 'uri'
|
2
|
+
require 'net/http'
|
3
|
+
require 'nokogiri'
|
4
|
+
|
5
|
+
module WildcardPair
|
6
|
+
module ExtractMetaTags
|
7
|
+
|
8
|
+
def self.get_metatag_key(attribute)
|
9
|
+
|
10
|
+
if attribute.nil?
|
11
|
+
return nil
|
12
|
+
end
|
13
|
+
|
14
|
+
case attribute
|
15
|
+
when "twitter:title", "og:title"
|
16
|
+
return "title"
|
17
|
+
when "twitter:description", "og:description"
|
18
|
+
return "description"
|
19
|
+
when "twitter:image", "twitter:image:src", "og:image"
|
20
|
+
return "image_url"
|
21
|
+
when "og:price:amount", "product:price:amount"
|
22
|
+
return "price"
|
23
|
+
when "twitter:app:url:iphone", "al:ios:url"
|
24
|
+
return "applink_ios"
|
25
|
+
when "twitter:app:url:googleplay", "al:android:url"
|
26
|
+
return "applink_android"
|
27
|
+
when "og:video", "twitter:player"
|
28
|
+
return "video_url"
|
29
|
+
when "og:video:width", "twitter:player:width"
|
30
|
+
return "video_width"
|
31
|
+
when "og:video:height", "twitter:player:height"
|
32
|
+
return "video_height"
|
33
|
+
else
|
34
|
+
return nil
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def self.get_meta_key(meta_element)
|
39
|
+
if !meta_element.is_a?(Hash)
|
40
|
+
return nil
|
41
|
+
end
|
42
|
+
|
43
|
+
if (!meta_element['name'].nil?)
|
44
|
+
return meta_element['name'].value
|
45
|
+
elsif (!meta_element['property'].nil?)
|
46
|
+
return meta_element['property'].value
|
47
|
+
end
|
48
|
+
|
49
|
+
end
|
50
|
+
|
51
|
+
def self.get_meta_value(meta_element)
|
52
|
+
if !meta_element.is_a?(Hash)
|
53
|
+
return nil
|
54
|
+
end
|
55
|
+
|
56
|
+
if (!meta_element['content'].nil?)
|
57
|
+
return meta_element['content'].value
|
58
|
+
elsif (!meta_element['value'].nil?)
|
59
|
+
return meta_element['value'].value
|
60
|
+
end
|
61
|
+
|
62
|
+
end
|
63
|
+
|
64
|
+
private_class_method :get_meta_value, :get_meta_key, :get_metatag_key
|
65
|
+
|
66
|
+
public
|
67
|
+
def self.extract(web_url)
|
68
|
+
begin
|
69
|
+
metatags = Hash.new
|
70
|
+
|
71
|
+
if web_url.is_a?(String) && !web_url.nil? && !web_url.empty?
|
72
|
+
html_content = Net::HTTP.get(URI.parse(web_url))
|
73
|
+
##store html content in metatags hash
|
74
|
+
metatags['html']=html_content
|
75
|
+
doc = Nokogiri::HTML(html_content)
|
76
|
+
|
77
|
+
doc.xpath("//meta").each do |meta|
|
78
|
+
meta_key = get_meta_key(meta.attributes)
|
79
|
+
meta_tag_key = get_metatag_key(meta_key)
|
80
|
+
|
81
|
+
next if meta_tag_key.nil?
|
82
|
+
next if metatags.has_key?(meta_tag_key)
|
83
|
+
|
84
|
+
metatags[meta_tag_key] = get_meta_value(meta.attributes)
|
85
|
+
end
|
86
|
+
|
87
|
+
end
|
88
|
+
|
89
|
+
return metatags
|
90
|
+
|
91
|
+
rescue Exception => e
|
92
|
+
## something bad happened during extraction, lets output message and return empty hash
|
93
|
+
puts e.message
|
94
|
+
return {}
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
end
|
99
|
+
end
|
metadata
ADDED
@@ -0,0 +1,124 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: wildcard-pair
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.3.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Karthik Senthil
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2014-11-12 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: statsd-ruby
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.2'
|
20
|
+
- - ">="
|
21
|
+
- !ruby/object:Gem::Version
|
22
|
+
version: 1.2.1
|
23
|
+
type: :runtime
|
24
|
+
prerelease: false
|
25
|
+
version_requirements: !ruby/object:Gem::Requirement
|
26
|
+
requirements:
|
27
|
+
- - "~>"
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '1.2'
|
30
|
+
- - ">="
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: 1.2.1
|
33
|
+
- !ruby/object:Gem::Dependency
|
34
|
+
name: activemodel
|
35
|
+
requirement: !ruby/object:Gem::Requirement
|
36
|
+
requirements:
|
37
|
+
- - "~>"
|
38
|
+
- !ruby/object:Gem::Version
|
39
|
+
version: '4.1'
|
40
|
+
- - ">="
|
41
|
+
- !ruby/object:Gem::Version
|
42
|
+
version: 4.1.1
|
43
|
+
type: :runtime
|
44
|
+
prerelease: false
|
45
|
+
version_requirements: !ruby/object:Gem::Requirement
|
46
|
+
requirements:
|
47
|
+
- - "~>"
|
48
|
+
- !ruby/object:Gem::Version
|
49
|
+
version: '4.1'
|
50
|
+
- - ">="
|
51
|
+
- !ruby/object:Gem::Version
|
52
|
+
version: 4.1.1
|
53
|
+
- !ruby/object:Gem::Dependency
|
54
|
+
name: nokogiri
|
55
|
+
requirement: !ruby/object:Gem::Requirement
|
56
|
+
requirements:
|
57
|
+
- - "~>"
|
58
|
+
- !ruby/object:Gem::Version
|
59
|
+
version: 1.6.4
|
60
|
+
- - ">="
|
61
|
+
- !ruby/object:Gem::Version
|
62
|
+
version: 1.6.4
|
63
|
+
type: :runtime
|
64
|
+
prerelease: false
|
65
|
+
version_requirements: !ruby/object:Gem::Requirement
|
66
|
+
requirements:
|
67
|
+
- - "~>"
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
version: 1.6.4
|
70
|
+
- - ">="
|
71
|
+
- !ruby/object:Gem::Version
|
72
|
+
version: 1.6.4
|
73
|
+
description: Wildcard Pair SDK to facilitate partners being able to create cards for
|
74
|
+
their content
|
75
|
+
email:
|
76
|
+
- partners@trywildcard.com
|
77
|
+
executables: []
|
78
|
+
extensions: []
|
79
|
+
extra_rdoc_files: []
|
80
|
+
files:
|
81
|
+
- lib/wildcard-pair.rb
|
82
|
+
- lib/wildcard-pair/Article.rb
|
83
|
+
- lib/wildcard-pair/ArticleCard.rb
|
84
|
+
- lib/wildcard-pair/Color.rb
|
85
|
+
- lib/wildcard-pair/Media.rb
|
86
|
+
- lib/wildcard-pair/Media/Image.rb
|
87
|
+
- lib/wildcard-pair/Media/Video.rb
|
88
|
+
- lib/wildcard-pair/Offer.rb
|
89
|
+
- lib/wildcard-pair/Price.rb
|
90
|
+
- lib/wildcard-pair/Product.rb
|
91
|
+
- lib/wildcard-pair/ProductCard.rb
|
92
|
+
- lib/wildcard-pair/ProductSearchCard.rb
|
93
|
+
- lib/wildcard-pair/ProductSearchResult.rb
|
94
|
+
- lib/wildcard-pair/Rating.rb
|
95
|
+
- lib/wildcard-pair/Review.rb
|
96
|
+
- lib/wildcard-pair/ReviewCard.rb
|
97
|
+
- lib/wildcard-pair/VideoCard.rb
|
98
|
+
- lib/wildcard-pair/hash_mappable.rb
|
99
|
+
- lib/wildcard-pair/util/extract_metatags.rb
|
100
|
+
homepage: http://trywildcard.com/dev
|
101
|
+
licenses:
|
102
|
+
- MIT
|
103
|
+
metadata: {}
|
104
|
+
post_install_message:
|
105
|
+
rdoc_options: []
|
106
|
+
require_paths:
|
107
|
+
- lib
|
108
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
109
|
+
requirements:
|
110
|
+
- - ">="
|
111
|
+
- !ruby/object:Gem::Version
|
112
|
+
version: '0'
|
113
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
114
|
+
requirements:
|
115
|
+
- - ">="
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: '0'
|
118
|
+
requirements: []
|
119
|
+
rubyforge_project:
|
120
|
+
rubygems_version: 2.4.3
|
121
|
+
signing_key:
|
122
|
+
specification_version: 4
|
123
|
+
summary: Wildcard Pair Ruby SDK
|
124
|
+
test_files: []
|