Active 0.0.14 → 0.0.17
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.
- data/Rakefile +1 -0
- data/lib/Active.rb +15 -0
- data/lib/services/IActivity.rb +34 -17
- data/lib/services/active_works.rb +5 -4
- data/lib/services/activity.rb +253 -70
- data/lib/services/address.rb +17 -0
- data/lib/services/ats.rb +82 -35
- data/lib/services/gsa.rb +153 -0
- data/lib/services/reg_center.rb +43 -21
- data/lib/services/sanitize.rb +108 -0
- data/lib/services/search.rb +101 -18
- data/lib/services/search.txt +403 -0
- data/lib/services/validators.rb +91 -0
- data/spec/Active_spec.rb +24 -1
- data/spec/activeworks_spec.rb +1 -1
- data/spec/activity_spec.rb +101 -170
- data/spec/ats_spec.rb +9 -3
- data/spec/gsa_spec.rb +123 -0
- data/spec/reg_spec.rb +17 -8
- data/spec/search_memcached_spec.rb +49 -0
- data/spec/search_spec.rb +404 -356
- data/version.txt +1 -1
- metadata +30 -6
data/lib/services/ats.rb
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
require 'digest/sha1'
|
1
2
|
module Active
|
2
3
|
module Services
|
3
4
|
|
@@ -10,15 +11,16 @@ module Active
|
|
10
11
|
# {"destinationID"=>"", "assetId"=>"A9EF9D79-F859-4443-A9BB-91E1833DF2D5", "substitutionUrl"=>"1878023", "city"=>"Antioch", "contactName"=>"City of Antioch", "trackbackurl"=>"http://www.active.com/page/Event_Details.htm?event_id=1878023&assetId=A9EF9D79-F859-4443-A9BB-91E1833DF2D5", "category"=>"Activities", "zip"=>"94531", "userCommentText"=>nil, "location"=>"Multi-use Room (prewett) - Prewett Family Park & Center", "latitude"=>"37.95761", :asset_id=>"A9EF9D79-F859-4443-A9BB-91E1833DF2D5", "searchWeight"=>"1", "country"=>"United States", "participationCriteria"=>"All", "dma"=>"San Francisco - Oakland - San Jose", "isSearchable"=>"true", :asset_name=>"Fitness, Pilates Mat Class (16 Yrs. & Up)", :substitution_url=>"1878023", :asset_type_id=>"EA4E860A-9DCD-4DAA-A7CA-4A77AD194F65", "row"=>"1", "image1"=>"http://www.active.com/images/events/hotrace.gif", "startDate"=>"2010-09-13", "contactPhone"=>"925-779-7070", :asset_type_name=>"Active.com Event Registration", "onlineDonationAvailable"=>"0", "avgUserRating"=>nil, "market"=>"San Francisco - Oakland - San Jose", "assetTypeId"=>"EA4E860A-9DCD-4DAA-A7CA-4A77AD194F65", "assetName"=>"Fitness, Pilates Mat Class (16 Yrs. & Up)", "channel"=>"Not Specified", "seourl"=>"http://www.active.com/not-specified-recware-activities/antioch-ca/fitness-pilates-mat-class-16-yrs-and-up-2010", :xmlns=>"http://api.asset.services.active.com", :url=>"http://www.active.com/page/Event_Details.htm?event_id=1878023", "mediaType"=>"Recware Activities", "startTime"=>"18:15:00", "endTime"=>"18:15:00", "contactEmail"=>"dadams@ci.antioch.ca.us", "eventResults"=>nil, "longitude"=>"-121.7936", "endDate"=>"2010-09-13", "onlineRegistrationAvailable"=>"true", "onlineMembershipAvailable"=>"0", "state"=>"California"}
|
11
12
|
# {"destinationID"=>"", "assetId"=>"D9A22F33-8A14-4175-8D5B-D11578212A98", "substitutionUrl"=>"1847738", "city"=>"Encino", "contactName"=>"Lilliane Ballesteros", "trackbackurl"=>"http://www.active.com/page/Event_Details.htm?event_id=1847738&assetId=D9A22F33-8A14-4175-8D5B-D11578212A98", "category"=>"Activities", "zip"=>"91406", "userCommentText"=>nil, "location"=>"Balboa Park/Lake Balboa", "latitude"=>"34.19933", :asset_id=>"D9A22F33-8A14-4175-8D5B-D11578212A98", "searchWeight"=>"1", "country"=>"United States", "participationCriteria"=>"All", "dma"=>"Los Angeles", "isSearchable"=>"1", :asset_name=>"2nd Annual weSPARK 10K Run & 5K Run Walk", :substitution_url=>"1847738", :asset_type_id=>"EA4E860A-9DCD-4DAA-A7CA-4A77AD194F65", "row"=>"1", "image1"=>"http://www.active.com/images/events/hotrace.gif", "startDate"=>"2010-11-14", "contactPhone"=>"818-906-3022", :asset_type_name=>"Active.com Event Registration", "onlineDonationAvailable"=>"0", "avgUserRating"=>nil, "market"=>"Los Angeles", "assetTypeId"=>"EA4E860A-9DCD-4DAA-A7CA-4A77AD194F65", "assetName"=>"2nd Annual weSPARK 10K Run & 5K Run Walk", "channel"=>["Running", "Walking"], "seourl"=>"http://www.active.com/running/encino-ca/2nd-annual-wespark-10k-run-and-5k-run-walk-2010", :xmlns=>"http://api.asset.services.active.com", :url=>"http://www.active.com/page/Event_Details.htm?event_id=1847738", "mediaType"=>["Event", "Event\\10K", "Event\\5K"], "startTime"=>"8:00:00", "endTime"=>"8:00:00", "contactEmail"=>"lilliane@wespark.org", "eventResults"=>nil, "longitude"=>"-118.4924", "endDate"=>"2010-11-14", "onlineRegistrationAvailable"=>"1", "onlineMembershipAvailable"=>"0", "state"=>"California", "estParticipants"=>"1400", "eventURL"=>"http://www.wespark.org"}
|
12
13
|
|
13
|
-
def initialize(data={})
|
14
|
+
def initialize(data={},preload_metadata=false)
|
14
15
|
# need to hold on to original data
|
15
|
-
@data
|
16
|
-
@asset_id
|
17
|
-
@url
|
18
|
-
@asset_type_id
|
19
|
-
@title
|
16
|
+
@data = data
|
17
|
+
@asset_id = data[:asset_id]
|
18
|
+
@url = data[:url]
|
19
|
+
@asset_type_id = data[:asset_type_id]
|
20
|
+
@title = data[:asset_name] if data[:asset_name]
|
20
21
|
@substitution_url = data[:substitution_url]
|
21
|
-
@metadata_loaded = false
|
22
|
+
# @metadata_loaded = false
|
23
|
+
# load_metadata if preload_metadata
|
22
24
|
end
|
23
25
|
|
24
26
|
def source
|
@@ -27,16 +29,16 @@ module Active
|
|
27
29
|
|
28
30
|
|
29
31
|
def title
|
30
|
-
load_metadata unless @metadata_loaded
|
31
|
-
if @data.has_key?("assetName")
|
32
|
+
# load_metadata unless @metadata_loaded
|
33
|
+
# if @data.has_key?("assetName")
|
32
34
|
@data["assetName"]
|
33
|
-
else
|
34
|
-
|
35
|
-
end
|
35
|
+
# else
|
36
|
+
# @title
|
37
|
+
# end
|
36
38
|
end
|
37
39
|
|
38
40
|
def url
|
39
|
-
load_metadata unless @metadata_loaded
|
41
|
+
# load_metadata unless @metadata_loaded
|
40
42
|
if @data.has_key?("seourl")
|
41
43
|
@data["seourl"]
|
42
44
|
elsif @data.has_key?("trackbackurl")
|
@@ -47,7 +49,7 @@ module Active
|
|
47
49
|
end
|
48
50
|
|
49
51
|
def categories
|
50
|
-
load_metadata unless @metadata_loaded
|
52
|
+
# load_metadata unless @metadata_loaded
|
51
53
|
categories = @data["channel"]
|
52
54
|
if categories.class==String
|
53
55
|
[@data["channel"]]
|
@@ -57,8 +59,8 @@ module Active
|
|
57
59
|
end
|
58
60
|
|
59
61
|
def address
|
60
|
-
load_metadata unless @metadata_loaded
|
61
|
-
@address = {
|
62
|
+
# load_metadata unless @metadata_loaded
|
63
|
+
@address = Hash.new({
|
62
64
|
:name => @data["location"],
|
63
65
|
:address => @data["address"],
|
64
66
|
:city => @data["city"],
|
@@ -67,11 +69,11 @@ module Active
|
|
67
69
|
:lat => @data["latitude"],
|
68
70
|
:lng => @data["longitude"],
|
69
71
|
:country => @data["country"]
|
70
|
-
}
|
72
|
+
})
|
71
73
|
end
|
72
74
|
|
73
75
|
def start_date
|
74
|
-
load_metadata unless @metadata_loaded
|
76
|
+
# load_metadata unless @metadata_loaded
|
75
77
|
if @data.has_key?("startDate")
|
76
78
|
if @data.has_key?("startTime")
|
77
79
|
(DateTime.parse "#{@data["startDate"]} #{@data["startTime"]}")
|
@@ -88,7 +90,7 @@ module Active
|
|
88
90
|
end
|
89
91
|
|
90
92
|
def end_date
|
91
|
-
load_metadata unless @metadata_loaded
|
93
|
+
# load_metadata unless @metadata_loaded
|
92
94
|
if @data.has_key?("endDate")
|
93
95
|
if @data.has_key?("endTime")
|
94
96
|
(DateTime.parse "#{@data["endDate"]} #{@data["endTime"]}")
|
@@ -110,13 +112,27 @@ module Active
|
|
110
112
|
end
|
111
113
|
|
112
114
|
def desc
|
113
|
-
load_metadata unless @metadata_loaded
|
115
|
+
# load_metadata unless @metadata_loaded
|
114
116
|
if @data.has_key?("allText")
|
115
117
|
@data["allText"]
|
116
118
|
elsif @data.has_key?("summary")
|
117
119
|
@data["summary"]
|
118
120
|
end
|
119
121
|
end
|
122
|
+
|
123
|
+
def contact_name
|
124
|
+
# load_metadata unless @metadata_loaded
|
125
|
+
@data["contactName"] if @data.has_key?("contactName")
|
126
|
+
end
|
127
|
+
|
128
|
+
def contact_email
|
129
|
+
# load_metadata unless @metadata_loaded
|
130
|
+
@data["contactEmail"] if @data.has_key?("contactEmail")
|
131
|
+
end
|
132
|
+
|
133
|
+
def substitutionUrl
|
134
|
+
@data[:substitution_url]
|
135
|
+
end
|
120
136
|
|
121
137
|
|
122
138
|
# EXAMPLE
|
@@ -128,42 +144,73 @@ module Active
|
|
128
144
|
|
129
145
|
def self.find_by_id(id)
|
130
146
|
begin
|
131
|
-
|
132
|
-
return
|
147
|
+
|
148
|
+
# return self.get_asset_by_id(id)
|
149
|
+
search_hash = Digest::SHA1.hexdigest("ats_m_#{id}")
|
150
|
+
if Active.CACHE
|
151
|
+
cached_version = Active.CACHE.get(search_hash)
|
152
|
+
return cached_version if cached_version
|
153
|
+
end
|
154
|
+
|
155
|
+
c = Savon::Client.new("http://api.amp.active.com/asset-service/services/AssetService")
|
156
|
+
c.request.headers["Api-Key"] = "6npky9t57235vps5cetm3s7k"
|
157
|
+
r = c.get_asset_metadata! do |soap|
|
158
|
+
soap.namespace = "http://api.asset.services.active.com"
|
159
|
+
soap.body = "<context><userId></userId><applicationId></applicationId></context><assetId>#{id}</assetId>"
|
160
|
+
end
|
161
|
+
ats = ATS.new(r.to_hash[:get_asset_metadata_response][:out])
|
162
|
+
Active.CACHE.set(search_hash, ats) if Active.CACHE
|
163
|
+
return ats
|
164
|
+
|
133
165
|
rescue Savon::SOAPFault => e
|
134
|
-
raise ATSError, "Couldn't find activity with the id of #{id}"
|
166
|
+
raise ATSError, "Couldn't find activity with the id of #{id} error #{e.inspect}"
|
135
167
|
return
|
136
168
|
end
|
137
169
|
end
|
138
170
|
|
171
|
+
# def load_metadata
|
172
|
+
# metadata = ATS.get_asset_metadata(@asset_id)
|
173
|
+
# @data.merge! Hash.from_xml(metadata.to_hash[:get_asset_metadata_response][:out])["importSource"]["asset"]
|
174
|
+
# @metadata_loaded=true
|
175
|
+
# end
|
176
|
+
|
139
177
|
private
|
140
178
|
def self.get_asset_metadata(id)
|
141
|
-
|
179
|
+
search_hash = Digest::SHA1.hexdigest("ats_m_#{id}")
|
180
|
+
if Active.CACHE
|
181
|
+
cached_version = Active.CACHE.get(search_hash)
|
182
|
+
return cached_version if cached_version
|
183
|
+
end
|
184
|
+
|
185
|
+
c = Savon::Client.new("http://api.amp.active.com/asset-service/services/AssetService")
|
142
186
|
c.request.headers["Api-Key"] = "6npky9t57235vps5cetm3s7k"
|
143
|
-
r = c.get_asset_metadata do |soap|
|
187
|
+
r = c.get_asset_metadata! do |soap|
|
144
188
|
soap.namespace = "http://api.asset.services.active.com"
|
145
189
|
soap.body = "<context><userId></userId><applicationId></applicationId></context><assetId>#{id}</assetId>"
|
146
190
|
end
|
147
|
-
|
148
|
-
|
149
|
-
return
|
191
|
+
ats = ATS.new(r.to_hash[:get_asset_metadata_response][:out])
|
192
|
+
Active.CACHE.set(search_hash, ats) if Active.CACHE
|
193
|
+
return ats
|
150
194
|
end
|
151
195
|
|
152
196
|
def self.get_asset_by_id(id)
|
197
|
+
search_hash = Digest::SHA1.hexdigest("ats_#{id}")
|
198
|
+
if Active.CACHE
|
199
|
+
cached_version = Active.CACHE.get(search_hash)
|
200
|
+
return cached_version if cached_version
|
201
|
+
end
|
202
|
+
|
153
203
|
c = Savon::Client.new("http://api.amp.active.com/asset-service/services/AssetService")
|
154
204
|
c.request.headers["Api-Key"] = "6npky9t57235vps5cetm3s7k"
|
155
205
|
r = c.get_asset_by_id! do |soap|
|
156
206
|
soap.namespace = "http://api.asset.services.active.com"
|
157
207
|
soap.body = "<context><userId></userId><applicationId></applicationId></context><assetId>#{id}</assetId>"
|
158
208
|
end
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
def load_metadata
|
163
|
-
metadata = ATS.get_asset_metadata(@asset_id)
|
164
|
-
@data.merge! Hash.from_xml(metadata.to_hash[:get_asset_metadata_response][:out])["importSource"]["asset"]
|
165
|
-
@metadata_loaded=true
|
209
|
+
ats = ATS.new(r.to_hash[:get_asset_by_id_response][:out])
|
210
|
+
Active.CACHE.set(search_hash, ats) if Active.CACHE
|
211
|
+
return ats
|
166
212
|
end
|
213
|
+
|
167
214
|
|
168
215
|
end # end ats
|
169
216
|
end
|
data/lib/services/gsa.rb
ADDED
@@ -0,0 +1,153 @@
|
|
1
|
+
module Active
|
2
|
+
module Services
|
3
|
+
|
4
|
+
class GSAError < StandardError; end
|
5
|
+
|
6
|
+
class GSA < IActivity
|
7
|
+
require 'nokogiri'
|
8
|
+
require 'open-uri'
|
9
|
+
attr_accessor :asset_type_id
|
10
|
+
|
11
|
+
# EXAMPLE Data hash
|
12
|
+
# {"title"=>"Birds of a Feather Run | Ashland, Oregon 97520 | Thursday ...", "language"=>"en", "url"=>"http://www.active.com/running/ashland-or/birds-of-a-feather-run-2010", "escapedUrl"=>"http://www.active.com/running/ashland-or/birds-of-a-feather-run-2010", "meta"=>{"city"=>"Ashland", "assetId"=>["4365AF63-B2AE-4A98-A403-5E30EB6D2D69", "4365af63-b2ae-4a98-a403-5e30eb6d2d69"], "substitutionUrl"=>"1845585", "trackbackurl"=>"http://www.active.com/running/ashland-or/birds-of-a-feather-run-2010", "contactName"=>"Hal Koerner", "eventDate"=>"2010-09-23T00:00:00-07:00", "eventLongitude"=>"-122.5526", "eventId"=>"1845585", "zip"=>"97520", "category"=>"Activities", "latitude"=>"42.12607", "google-site-verification"=>"", "participationCriteria"=>"All", "dma"=>"Medford - Klamath Falls", "country"=>"United States", "sortDate"=>"2000-09-23", "tag"=>["event:10", "Running:10"], "lastModifiedDateTime"=>"2010-09-23 03:04:55.463", "lastModifiedDate"=>"2010-09-23", "startDate"=>"2010-09-23", "contactPhone"=>"541-201-0014", "eventState"=>"Oregon", "splitMediaType"=>"Event", "onlineDonationAvailable"=>"0", "market"=>"Medford - Klamath Falls", "assetName"=>["Birds of a Feather Run", "Birds of a Feather Run"], "seourl"=>"http://www.active.com/running/ashland-or/birds-of-a-feather-run-2010", "assetTypeId"=>"EA4E860A-9DCD-4DAA-A7CA-4A77AD194F65", "channel"=>"Running", "endTime"=>"0:00:00", "mediaType"=>"Event", "startTime"=>"0:00:00", "description"=>"", "longitude"=>"-122.5526", "UpdateDateTime"=>"9/22/2010 11:46:24 AM", "endDate"=>"2010-09-23", "onlineMembershipAvailable"=>"0", "onlineRegistrationAvailable"=>"false", "eventZip"=>"97520", "state"=>"Oregon", "estParticipants"=>"2000", "eventURL"=>"http://sorunners.org/", "eventLatitude"=>"42.12607", "keywords"=>"Event"}, "summary"=>"... Similar Running Events. I Ran for Sudan - Maple Valley First Annual 10K/2Mile Kid's Run/Walk Maple Valley, Washington Sat, Oct 02, 2010; ... "}
|
13
|
+
|
14
|
+
def initialize(json={})
|
15
|
+
# need to hold on to original data
|
16
|
+
@data = HashWithIndifferentAccess.new(json) || HashWithIndifferentAccess.new
|
17
|
+
# self.title = @data['meta']['assetName'] || nil
|
18
|
+
self.title = @data['title'] || nil
|
19
|
+
end
|
20
|
+
|
21
|
+
def source
|
22
|
+
:gsa
|
23
|
+
end
|
24
|
+
|
25
|
+
def title=(value)
|
26
|
+
@title = value
|
27
|
+
if @title
|
28
|
+
@title = @title.split("|")[0].strip if @title.include?("|")
|
29
|
+
@title = @title.gsub(/<\/?[^>]*>/, "")
|
30
|
+
@title = @title.gsub("...", "")
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def url
|
35
|
+
@data["url"]
|
36
|
+
end
|
37
|
+
|
38
|
+
def categories
|
39
|
+
if @data["meta"]["channel"].class==String
|
40
|
+
[@data["meta"]["channel"]]
|
41
|
+
else
|
42
|
+
@data["meta"]["channel"]
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def asset_id
|
47
|
+
return nil unless @data["meta"] and @data["meta"]["assetId"]
|
48
|
+
value = @data["meta"]["assetId"]
|
49
|
+
@asset_id = (value.class==Array) ? value[0] : value
|
50
|
+
end
|
51
|
+
|
52
|
+
def asset_type_id
|
53
|
+
return nil unless @data["meta"] and @data["meta"]["assetTypeId"]
|
54
|
+
@data["meta"]["assetTypeId"]
|
55
|
+
end
|
56
|
+
|
57
|
+
def primary_category
|
58
|
+
categories.first
|
59
|
+
end
|
60
|
+
|
61
|
+
def address
|
62
|
+
@address = HashWithIndifferentAccess.new({
|
63
|
+
:name => @data["meta"]["location"],
|
64
|
+
:address => @data["meta"]["eventAddress"],
|
65
|
+
:city => @data["meta"]["city"],
|
66
|
+
:lat => @data["meta"]["latitude"],
|
67
|
+
:lng => @data["meta"]["longitude"],
|
68
|
+
:country => @data["meta"]["country"]
|
69
|
+
})
|
70
|
+
@address[:state] = @data["meta"]["eventState"] || @data["meta"]["state"]
|
71
|
+
@address[:zip] = @data["meta"]["eventZip"] || @data["meta"]["zip"]
|
72
|
+
@address
|
73
|
+
end
|
74
|
+
|
75
|
+
def start_date
|
76
|
+
if @data.has_key?("meta") and @data["meta"].has_key?("eventDate")
|
77
|
+
DateTime.parse @data["meta"]["eventDate"]
|
78
|
+
else
|
79
|
+
nil
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
def start_time
|
84
|
+
start_date
|
85
|
+
end
|
86
|
+
|
87
|
+
def end_date
|
88
|
+
if @data.has_key?("meta") and @data["meta"].has_key?("endDate")
|
89
|
+
DateTime.parse @data["meta"]["endDate"]
|
90
|
+
else
|
91
|
+
nil
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
def end_time
|
96
|
+
end_date
|
97
|
+
end
|
98
|
+
|
99
|
+
def category
|
100
|
+
primary_category
|
101
|
+
end
|
102
|
+
|
103
|
+
def contact_name
|
104
|
+
if @data["meta"].has_key?("contactName") && !@data["meta"]["contactName"].blank?
|
105
|
+
@data["meta"]["contactName"]
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
def last_modified
|
110
|
+
@data["meta"]["lastModifiedDateTime"] if @data["meta"].has_key?("lastModifiedDateTime")
|
111
|
+
end
|
112
|
+
|
113
|
+
def contact_email
|
114
|
+
if @data["meta"].has_key?("contactEmail") && !@data["meta"]["contactEmail"].blank?
|
115
|
+
@data["meta"]["contactEmail"]
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
def desc
|
120
|
+
if @data["meta"].has_key?("allText") && !@data["meta"]["allText"].blank?
|
121
|
+
@data["meta"]["allText"]
|
122
|
+
elsif @data["meta"].has_key?("summary") && !@data["meta"]["summary"].blank?
|
123
|
+
@data["meta"]["summary"]
|
124
|
+
elsif @data.has_key?("summary") && !@data["summary"].blank?
|
125
|
+
@data["summary"]
|
126
|
+
else
|
127
|
+
""
|
128
|
+
end
|
129
|
+
end
|
130
|
+
# substitutionUrl could be formatted like this
|
131
|
+
# 1. "meta":{"substitutionUrl":"vistarecreation/registrationmain.sdi?source=showAsset.sdi&activity_id=4900"}
|
132
|
+
# 2. "meta":{"substitutionUrl":"4900"}
|
133
|
+
def substitutionUrl
|
134
|
+
if @data["meta"].has_key?("substitutionUrl")
|
135
|
+
if /activity_id=/ =~ @data["meta"]["substitutionUrl"]
|
136
|
+
@data["meta"]["substitutionUrl"].split("activity_id=")[1]
|
137
|
+
else
|
138
|
+
@data["meta"]["substitutionUrl"]
|
139
|
+
end
|
140
|
+
end
|
141
|
+
end
|
142
|
+
# TODO
|
143
|
+
def activeworks_id
|
144
|
+
0
|
145
|
+
end
|
146
|
+
def regcenter_id
|
147
|
+
0
|
148
|
+
end
|
149
|
+
|
150
|
+
|
151
|
+
end
|
152
|
+
end
|
153
|
+
end
|
data/lib/services/reg_center.rb
CHANGED
@@ -6,6 +6,7 @@ module Active
|
|
6
6
|
class RegCenter < IActivity
|
7
7
|
require 'nokogiri'
|
8
8
|
require 'open-uri'
|
9
|
+
require 'digest/sha1'
|
9
10
|
attr_accessor :asset_type_id
|
10
11
|
|
11
12
|
# attr_reader :metadata_loaded
|
@@ -15,15 +16,12 @@ module Active
|
|
15
16
|
# :asset_type_id=>"EA4E860A-9DCD-4DAA-A7CA-4A77AD194F65", :xmlns=>"http://api.asset.services.active.com"}
|
16
17
|
|
17
18
|
def initialize(data={})
|
18
|
-
# need to hold on to original data
|
19
19
|
@data = HashWithIndifferentAccess.new(data) || HashWithIndifferentAccess.new
|
20
|
-
@api_data_loaded = false
|
21
20
|
@asset_type_id = "EA4E860A-9DCD-4DAA-A7CA-4A77AD194F65"
|
22
|
-
get_app_api
|
23
21
|
end
|
24
22
|
|
25
23
|
def source
|
26
|
-
:
|
24
|
+
:primary
|
27
25
|
end
|
28
26
|
|
29
27
|
def title
|
@@ -73,18 +71,18 @@ module Active
|
|
73
71
|
channels.each do |c|
|
74
72
|
return c["channelName"] if c.has_key?("primaryChannel") && c["primaryChannel"]=="true"
|
75
73
|
end
|
74
|
+
nil
|
76
75
|
else
|
77
76
|
#hash
|
78
77
|
return channels["channelName"] if channels.has_key?("primaryChannel") && channels["primaryChannel"]=="true"
|
78
|
+
return nil
|
79
79
|
end
|
80
|
-
#fallback
|
81
|
-
return category
|
82
80
|
end
|
83
81
|
end
|
84
82
|
|
85
83
|
def address
|
86
84
|
if @data.has_key?("event") && @data["event"].has_key?("eventAddress") && !@data["event"]["eventAddress"].blank?
|
87
|
-
@address = {
|
85
|
+
@address = validated_address({
|
88
86
|
:name => @data["event"]["eventLocation"],
|
89
87
|
:address => @data["event"]["eventAddress"],
|
90
88
|
:city => @data["event"]["eventCity"],
|
@@ -93,7 +91,7 @@ module Active
|
|
93
91
|
:lat => @data["event"]["latitude"],
|
94
92
|
:lng => @data["event"]["longitude"],
|
95
93
|
:country => @data["event"]["eventCountry"]
|
96
|
-
}
|
94
|
+
} )
|
97
95
|
end
|
98
96
|
end
|
99
97
|
|
@@ -131,7 +129,9 @@ module Active
|
|
131
129
|
ret +="<div><b>" + eventDetail["eventDetailsName"] + ":</b> " + cleanup_reg_string(eventDetail["eventDetailsValue"]) + "</div>"
|
132
130
|
end
|
133
131
|
end
|
134
|
-
ret
|
132
|
+
return ret
|
133
|
+
elsif @data.has_key?("event") && @data["event"].has_key?("eventDescription")
|
134
|
+
return @data["event"]["eventDescription"]
|
135
135
|
end
|
136
136
|
end
|
137
137
|
|
@@ -139,6 +139,12 @@ module Active
|
|
139
139
|
input.gsub("\r","").gsub("\n","").gsub("\"","""").gsub("\342\200\234","""").gsub("\342\200\235","""")
|
140
140
|
end
|
141
141
|
|
142
|
+
def contact_email
|
143
|
+
if @data.has_key?("event") && @data["event"].has_key?("eventContactEmail")
|
144
|
+
return @data["event"]["eventContactEmail"]
|
145
|
+
end
|
146
|
+
end
|
147
|
+
|
142
148
|
|
143
149
|
# EXAMPLE
|
144
150
|
# lazy load the data for some_crazy_method
|
@@ -148,7 +154,23 @@ module Active
|
|
148
154
|
# end
|
149
155
|
|
150
156
|
def self.find_by_id(id) #local id
|
151
|
-
|
157
|
+
|
158
|
+
search_hash = Digest::SHA1.hexdigest("reg_#{id}")
|
159
|
+
if Active.CACHE
|
160
|
+
cached_version = Active.CACHE.get(search_hash)
|
161
|
+
return cached_version if cached_version
|
162
|
+
end
|
163
|
+
|
164
|
+
begin
|
165
|
+
doc = Nokogiri::XML(open("http://apij.active.com/regcenter/event/#{id}"))
|
166
|
+
reg = RegCenter.new(Hash.from_xml(doc.to_s))
|
167
|
+
Active.CACHE.set(search_hash, reg) if Active.CACHE
|
168
|
+
rescue Exception => e
|
169
|
+
raise RegCenterError, "Couldn't find Reg Center activity with the id of #{id} - #{e.inspect}"
|
170
|
+
return
|
171
|
+
end
|
172
|
+
|
173
|
+
return reg
|
152
174
|
end
|
153
175
|
|
154
176
|
private
|
@@ -182,17 +204,17 @@ module Active
|
|
182
204
|
# @metadata_loaded=true
|
183
205
|
# end
|
184
206
|
|
185
|
-
def get_app_api
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
end
|
207
|
+
# def get_app_api
|
208
|
+
# puts "loading reg center api"
|
209
|
+
# begin
|
210
|
+
# doc = Nokogiri::XML(open("http://apij.active.com/regcenter/event/#{@data[:id]}"))
|
211
|
+
# @data.merge! Hash.from_xml doc.to_s
|
212
|
+
# @api_data_loaded=true
|
213
|
+
# rescue
|
214
|
+
# raise RegCenterError, "Couldn't find Reg Center activity with the id of #{id}"
|
215
|
+
# return
|
216
|
+
# end
|
217
|
+
# end
|
196
218
|
|
197
219
|
end # end ats
|
198
220
|
end
|
@@ -0,0 +1,108 @@
|
|
1
|
+
# http://wonko.com/post/sanitize
|
2
|
+
|
3
|
+
# $Id: sanitize.rb 3 2005-04-05 12:51:14Z dwight $
|
4
|
+
#
|
5
|
+
# Copyright (c) 2005 Dwight Shih
|
6
|
+
# A derived work of the Perl version:
|
7
|
+
# Copyright (c) 2002 Brad Choate, bradchoate.com
|
8
|
+
#
|
9
|
+
# Permission is hereby granted, free of charge, to
|
10
|
+
# any person obtaining a copy of this software and
|
11
|
+
# associated documentation files (the "Software"), to
|
12
|
+
# deal in the Software without restriction, including
|
13
|
+
# without limitation the rights to use, copy, modify,
|
14
|
+
# merge, publish, distribute, sublicense, and/or sell
|
15
|
+
# copies of the Software, and to permit persons to
|
16
|
+
# whom the Software is furnished to do so, subject to
|
17
|
+
# the following conditions:
|
18
|
+
#
|
19
|
+
# The above copyright notice and this permission
|
20
|
+
# notice shall be included in all copies or
|
21
|
+
# substantial portions of the Software.
|
22
|
+
#
|
23
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY
|
24
|
+
# OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
|
25
|
+
# LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
26
|
+
# FITNESS FOR A PARTICULAR PURPOSE AND
|
27
|
+
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
28
|
+
# COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES
|
29
|
+
# OR OTHER LIABILITY, WHETHER IN AN ACTION OF
|
30
|
+
# CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
|
31
|
+
# OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
32
|
+
# OTHER DEALINGS IN THE SOFTWARE.
|
33
|
+
#
|
34
|
+
|
35
|
+
def sanitize( html, okTags='a href, b, br, i, p' )
|
36
|
+
# no closing tag necessary for these
|
37
|
+
soloTags = ["br","hr"]
|
38
|
+
|
39
|
+
# Build hash of allowed tags with allowed attributes
|
40
|
+
tags = okTags.downcase().split(',').collect!{ |s| s.split(' ') }
|
41
|
+
allowed = Hash.new
|
42
|
+
tags.each do |s|
|
43
|
+
key = s.shift
|
44
|
+
allowed[key] = s
|
45
|
+
end
|
46
|
+
|
47
|
+
# Analyze all <> elements
|
48
|
+
stack = Array.new
|
49
|
+
result = html.gsub( /(<.*?>)/m ) do | element |
|
50
|
+
if element =~ /\A<\/(\w+)/ then
|
51
|
+
# </tag>
|
52
|
+
tag = $1.downcase
|
53
|
+
if allowed.include?(tag) && stack.include?(tag) then
|
54
|
+
# If allowed and on the stack
|
55
|
+
# Then pop down the stack
|
56
|
+
top = stack.pop
|
57
|
+
out = "</#{top}>"
|
58
|
+
until top == tag do
|
59
|
+
top = stack.pop
|
60
|
+
out << "</#{top}>"
|
61
|
+
end
|
62
|
+
out
|
63
|
+
end
|
64
|
+
elsif element =~ /\A<(\w+)\s*\/>/
|
65
|
+
# <tag />
|
66
|
+
tag = $1.downcase
|
67
|
+
if allowed.include?(tag) then
|
68
|
+
"<#{tag} />"
|
69
|
+
end
|
70
|
+
elsif element =~ /\A<(\w+)/ then
|
71
|
+
# <tag ...>
|
72
|
+
tag = $1.downcase
|
73
|
+
if allowed.include?(tag) then
|
74
|
+
if ! soloTags.include?(tag) then
|
75
|
+
stack.push(tag)
|
76
|
+
end
|
77
|
+
if allowed[tag].length == 0 then
|
78
|
+
# no allowed attributes
|
79
|
+
"<#{tag}>"
|
80
|
+
else
|
81
|
+
# allowed attributes?
|
82
|
+
out = "<#{tag}"
|
83
|
+
while ( $' =~ /(\w+)=("[^"]+")/ )
|
84
|
+
attr = $1.downcase
|
85
|
+
valu = $2
|
86
|
+
if allowed[tag].include?(attr) then
|
87
|
+
out << " #{attr}=#{valu}"
|
88
|
+
end
|
89
|
+
end
|
90
|
+
out << ">"
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
# eat up unmatched leading >
|
97
|
+
while result.sub!(/\A([^<]*)>/m) { $1 } do end
|
98
|
+
|
99
|
+
# eat up unmatched trailing <
|
100
|
+
while result.sub!(/<([^>]*)\Z/m) { $1 } do end
|
101
|
+
|
102
|
+
# clean up the stack
|
103
|
+
if stack.length > 0 then
|
104
|
+
result << "</#{stack.reverse.join('></')}>"
|
105
|
+
end
|
106
|
+
|
107
|
+
result
|
108
|
+
end
|