Active 0.0.42 → 0.1.7

Sign up to get free protection for your applications and to get access to all the features.
Files changed (54) hide show
  1. data/.gitignore +6 -0
  2. data/.irbrc +21 -0
  3. data/.rspec +1 -0
  4. data/.rvmrc +2 -0
  5. data/Active.gemspec +28 -29
  6. data/Gemfile +4 -0
  7. data/History.txt +5 -2
  8. data/{README.txt → README.md} +4 -20
  9. data/Rakefile +11 -17
  10. data/lib/Active.rb +11 -79
  11. data/lib/active/activity.rb +7 -0
  12. data/lib/active/article.rb +7 -0
  13. data/lib/active/asset.rb +205 -0
  14. data/lib/active/errors.rb +9 -0
  15. data/lib/active/query.rb +225 -0
  16. data/lib/active/result.rb +7 -0
  17. data/lib/active/results.rb +6 -0
  18. data/lib/active/training.rb +7 -0
  19. data/lib/active/version.rb +3 -0
  20. data/lib/ext/hash_extensions.rb +8 -0
  21. data/spec/asset_spec.rb +47 -0
  22. data/spec/search_spec.rb +383 -432
  23. data/spec/spec_helper.rb +23 -2
  24. metadata +113 -116
  25. data/bin/Active +0 -7
  26. data/lib/.DS_Store +0 -0
  27. data/lib/services/.DS_Store +0 -0
  28. data/lib/services/IActivity.rb +0 -39
  29. data/lib/services/_ats.rb +0 -215
  30. data/lib/services/active_works.rb +0 -167
  31. data/lib/services/activity.rb +0 -512
  32. data/lib/services/address.rb +0 -17
  33. data/lib/services/ats.rb +0 -229
  34. data/lib/services/dto/user.rb +0 -9
  35. data/lib/services/gsa.rb +0 -205
  36. data/lib/services/reg_center.rb +0 -270
  37. data/lib/services/sanitize.rb +0 -108
  38. data/lib/services/search.rb +0 -494
  39. data/lib/services/validators.rb +0 -124
  40. data/rspec-tm +0 -1
  41. data/rvmrc +0 -1
  42. data/spec/.DS_Store +0 -0
  43. data/spec/Active_spec.rb +0 -28
  44. data/spec/activeworks_spec.rb +0 -60
  45. data/spec/activity_spec.rb +0 -421
  46. data/spec/ats_spec.rb +0 -106
  47. data/spec/benchmark/search_bench.rb +0 -55
  48. data/spec/custom_matchers_spec.rb +0 -27
  49. data/spec/gsa_spec.rb +0 -210
  50. data/spec/reg_spec.rb +0 -173
  51. data/spec/search_memcached_spec.rb +0 -42
  52. data/spec/validators_spec.rb +0 -19
  53. data/test/test_Active.rb +0 -0
  54. data/version.txt +0 -1
@@ -1,270 +0,0 @@
1
- module Active
2
- module Services
3
-
4
- class RegCenterError < StandardError; end
5
-
6
- class RegCenter < IActivity
7
- require 'nokogiri'
8
- require 'open-uri'
9
- require 'digest/sha1'
10
- attr_accessor :asset_type_id
11
-
12
- # attr_reader :metadata_loaded
13
- # EXAMPLE Data hash
14
- # {:asset_id=>"A9EF9D79-F859-4443-A9BB-91E1833DF2D5", :substitution_url=>"1878023", :asset_type_name=>"Active.com Event Registration",
15
- # :asset_name=>"Fitness, Pilates Mat Class (16 Yrs. &amp; Up)", :url=>"http://www.active.com/page/Event_Details.htm?event_id=1878023",
16
- # :asset_type_id=>"EA4E860A-9DCD-4DAA-A7CA-4A77AD194F65", :xmlns=>"http://api.asset.services.active.com"}
17
-
18
- def initialize(data={})
19
- @data = HashWithIndifferentAccess.new(data) || HashWithIndifferentAccess.new
20
- @asset_type_id = "EA4E860A-9DCD-4DAA-A7CA-4A77AD194F65"
21
- end
22
-
23
- def source
24
- :reg_center
25
- end
26
-
27
- def title
28
- if @data.has_key?("event") && @data["event"].has_key?("eventName")
29
- cleanup_reg_string(@data["event"]["eventName"])
30
- end
31
- end
32
-
33
- def event_image_url
34
- if @data.has_key?("event") && @data["event"].has_key?("eventImageUrl")
35
- @data["event"]["eventImageUrl"]
36
- end
37
- end
38
-
39
- def url
40
- if @data.has_key?("event") && @data["event"].has_key?("eventDetailsPageUrl")
41
- @data["event"]["eventDetailsPageUrl"]
42
- elsif @data.has_key?("event") && @data["event"].has_key?("registrationUrl")
43
- @data["event"]["registrationUrl"]
44
- elsif @data.has_key?("event") && @data["event"].has_key?("eventContactUrl")
45
- @data["event"]["eventContactUrl"]
46
- end
47
- end
48
-
49
- def registration_url
50
- if @data.has_key?("event") && @data["event"].has_key?("registrationUrl")
51
- @data["event"]["registrationUrl"]
52
- else
53
- ""
54
- end
55
- end
56
-
57
- def event_url
58
- @data[:event][:eventUrl]
59
- end
60
-
61
- def categories
62
- if @data.has_key?("event") && @data["event"].has_key?("channels") && @data["event"]["channels"]!=nil && @data["event"]["channels"].has_key?("channel") && @data["event"]["channels"]["channel"]!=nil
63
- channels = @data["event"]["channels"]["channel"]
64
- if channels.class==Array
65
- @data["event"]["channels"]["channel"].collect {|e| e["channelName"]}
66
- else
67
- #hash
68
- [channels["channelName"]]
69
- end
70
- end
71
- end
72
-
73
- def asset_id
74
- if @data.has_key?("event") && @data["event"].has_key?("assetID")
75
- @data["event"]["assetID"]
76
- end
77
- end
78
-
79
- def primary_category
80
- if @data["event"]["channels"]["channel"]!=nil
81
- channels = @data["event"]["channels"]["channel"]
82
- if channels.class==Array
83
- channels.each do |c|
84
- return c["channelName"] if c.has_key?("primaryChannel") && c["primaryChannel"]=="true"
85
- end
86
- nil
87
- else
88
- #hash
89
- return channels["channelName"] if channels.has_key?("primaryChannel") && channels["primaryChannel"]=="true"
90
- return nil
91
- end
92
- end
93
- end
94
-
95
- def address
96
- @address = validated_address({
97
- :name => @data["event"]["eventLocation"],
98
- :address => @data["event"]["eventAddress"],
99
- :city => @data["event"]["eventCity"],
100
- :state => @data["event"]["eventState"],
101
- :zip => @data["event"]["eventZip"],
102
- :lat => @data["event"]["latitude"],
103
- :lng => @data["event"]["longitude"],
104
- :country => @data["event"]["eventCountry"]
105
- } )
106
- end
107
-
108
- def start_date
109
- DateTime.parse @data["event"]["eventDate"] if @data.has_key?("event") && @data["event"].has_key?("eventDate")
110
- end
111
-
112
- def start_time
113
- start_date
114
- end
115
-
116
- def end_time
117
- nil
118
- end
119
-
120
- def end_date
121
- nil
122
- end
123
- # The date and time that registration closes
124
- def registration_close_date
125
- DateTime.parse(@data["event"]["eventCloseDate"])
126
- end
127
-
128
- def category
129
- primary_category
130
- end
131
-
132
- def user
133
- email = contact_email
134
- u = User.new
135
- u.email = email if Validators.email(email)
136
- # u.first_name = @data["meta"]["contactName"] || nil
137
- # u.phone = @data["meta"]["contactPhone"] || nil
138
- u
139
- end
140
-
141
- def desc_old
142
- if @data.has_key?("event") && @data["event"].has_key?("briefDescription")
143
- ret = @data["event"]["briefDescription"]
144
- if @data["event"].has_key?("eventDetails") && @data["event"]["eventDetails"] != nil && @data["event"]["eventDetails"].has_key?("eventDetail")
145
- eventDetail = @data["event"]["eventDetails"]["eventDetail"]
146
- if eventDetail.class == Array
147
- @data["event"]["eventDetails"]["eventDetail"].each do |detail|
148
- ret +="<div><b>" + detail["eventDetailsName"] + ":</b> " + cleanup_reg_string(detail["eventDetailsValue"]) + "</div>"
149
- end
150
- else
151
- #hash
152
- ret +="<div><b>" + eventDetail["eventDetailsName"] + ":</b> " + cleanup_reg_string(eventDetail["eventDetailsValue"]) + "</div>"
153
- end
154
- end
155
- return ret
156
- elsif @data.has_key?("event") && @data["event"].has_key?("eventDescription")
157
- return @data["event"]["eventDescription"]
158
- end
159
- end
160
-
161
- def desc(length = :full)
162
- if length == :full
163
- @data["event"]["eventDescription"]
164
- else
165
- @data["event"]["briefDescription"]
166
- end
167
- end
168
-
169
- # Content should be a array of hashes.
170
- # [ {:title => "briefDescription", :type => "html", :content => "..." }]
171
- #
172
- # It should contain everything in briefDescription description and eventDetails.
173
- # It should just be one big happy
174
- #
175
- # TODO: Need to order this by detail[:eventDetailsOrder]
176
- # TODO: Add the other description blocks to this
177
- def content
178
- if @data["event"] and @data["event"]["eventDetails"]
179
-
180
- if @data["event"]["eventDetails"]["eventDetail"].class == Array
181
- return @data["event"]["eventDetails"]["eventDetail"].collect { |obj| {:title => obj[:eventDetailsName], :content => obj[:eventDetailsValue]} }
182
- else
183
- return [{:title => @data["event"]["eventDetails"]["eventDetail"]["eventDetailsName"],:content => @data["event"]["eventDetails"]["eventDetail"]["eventDetailsValue"]}]
184
- end
185
-
186
- else
187
- return []
188
- end
189
- end
190
-
191
- def cleanup_reg_string(input)
192
- input.gsub("\r","").gsub("\n","").gsub("\"","""").gsub("\342\200\234","""").gsub("\342\200\235","""")
193
- end
194
-
195
- def contact_email
196
- if @data.has_key?("event") && @data["event"].has_key?("eventContactEmail")
197
- return @data["event"]["eventContactEmail"]
198
- end
199
- end
200
-
201
-
202
- # EXAMPLE
203
- # lazy load the data for some_crazy_method
204
- # def some_crazy
205
- # return @some_crazy unless @some_crazy.nil?
206
- # @some_crazy = @data[:some_crazy_method_from_ats].split replace twist bla bla bla
207
- # end
208
- # local id
209
- def self.find_by_id(id)
210
- begin
211
- doc = Nokogiri::XML(open("http://apij.active.com/regcenter/event/#{id}"))
212
- puts "////////<br/>"
213
- puts doc.to_s
214
- puts "////////<br/>"
215
- reg = RegCenter.new(Hash.from_xml(doc.to_s))
216
- rescue Exception => e
217
- raise RegCenterError, "Couldn't find Reg Center activity with the id of #{id} - #{e.inspect}"
218
- return nil
219
- end
220
- reg
221
- end
222
-
223
-
224
- def self.get_asset_metadata(id)
225
- c = Savon::Client.new("http://api.amp.active.com/asset-service/services/AssetService?wsdl")
226
- c.request.headers["Api-Key"] = "6npky9t57235vps5cetm3s7k"
227
- r = c.get_asset_metadata do |soap|
228
- soap.namespace = "http://api.asset.services.active.com"
229
- soap.body = "<context><userId></userId><applicationId></applicationId></context><assetId>#{id}</assetId>"
230
- end
231
- puts "==========="
232
- puts r.to_hash[:get_asset_metadata_response][:out].inspect
233
- return r
234
- end
235
-
236
-
237
- private
238
- # def self.get_asset_by_id(id)
239
- # puts "loading ATS"
240
- # c = Savon::Client.new("http://api.amp.active.com/asset-service/services/AssetService")
241
- # c.request.headers["Api-Key"] = "6npky9t57235vps5cetm3s7k"
242
- # r = c.get_asset_by_id! do |soap|
243
- # soap.namespace = "http://api.asset.services.active.com"
244
- # soap.body = "<context><userId></userId><applicationId></applicationId></context><assetId>#{id}</assetId>"
245
- # end
246
- # return r
247
- # end
248
- #
249
- # def load_metadata
250
- # puts "loading ATS metadata"
251
- # metadata = ATS.get_asset_metadata(@asset_id)
252
- # @data.merge! Hash.from_xml(metadata.to_hash[:get_asset_metadata_response][:out])["importSource"]["asset"]
253
- # @metadata_loaded=true
254
- # end
255
-
256
- # def get_app_api
257
- # puts "loading reg center api"
258
- # begin
259
- # doc = Nokogiri::XML(open("http://apij.active.com/regcenter/event/#{@data[:id]}"))
260
- # @data.merge! Hash.from_xml doc.to_s
261
- # @api_data_loaded=true
262
- # rescue
263
- # raise RegCenterError, "Couldn't find Reg Center activity with the id of #{id}"
264
- # return
265
- # end
266
- # end
267
-
268
- end # end ats
269
- end
270
- end
@@ -1,108 +0,0 @@
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
@@ -1,494 +0,0 @@
1
- require 'net/http'
2
- require 'json'
3
- require 'cgi'
4
- require 'mysql'
5
- require 'active_record'
6
- require 'digest/md5'
7
-
8
- module Active
9
- module Services
10
-
11
- # we should remove this class and just replace with symbols
12
- class Sort
13
- def self.DATE_ASC
14
- "date_asc"
15
- end
16
- def self.DATE_DESC
17
- "date_desc"
18
- end
19
- def self.RELEVANCE
20
- "relevance"
21
- end
22
- end
23
-
24
- # we should remove this class and just replace with symbols
25
- class Facet
26
- def self.ACTIVITIES
27
- "activities"
28
- end
29
- end
30
-
31
- class Search
32
- attr_accessor :api_key, :start_date, :end_date, :location, :channels, :split_media_type, :keywords, :search, :radius, :limit, :sort, :page, :offset, :latitude, :longitude,
33
- :asset_type_id, :url,
34
- :view, :facet, :sort, :num_results, :asset_ids, :dma, :city, :state, :country, :bounding_box
35
-
36
- attr_reader :results, :endIndex, :pageSize, :searchTime, :numberOfResults, :end_point, :meta
37
-
38
- SEARCH_URL = "http://search.active.com"
39
- DEFAULT_TIMEOUT = 60
40
-
41
- def initialize(data={})
42
- self.asset_type_id = data[:asset_type_id]
43
- self.url = data[:url]
44
- self.api_key = data[:api_key] || ""
45
- self.location = data[:location]
46
- self.zips = data[:zips] || []
47
- self.channels = data[:channels] || []
48
- self.split_media_type = data[:split_media_type] || []
49
- self.keywords = data[:keywords] || []
50
- self.radius = data[:radius] || nil
51
- self.limit = data[:limit] || "10"
52
- self.sort = data[:sort] || Sort.DATE_ASC
53
- self.page = data[:page] || "1"
54
- self.offset = data[:offset] || "0"
55
- self.view = data[:view] || "json"
56
- self.facet = data[:facet] || Facet.ACTIVITIES
57
- self.num_results = data[:num_results] || "10"
58
- self.search = data[:search] || ""
59
- self.start_date = data[:start_date] || "today"
60
- self.end_date = data[:end_date] || "+"
61
- self.asset_ids = data[:asset_ids] || []
62
- self.asset_id = data[:asset_id] || ""
63
- self.latitude = data[:latitude]
64
- self.longitude = data[:longitude]
65
- self.dma = data[:dma]
66
- self.city = data[:city]
67
- self.state = data[:state]
68
- self.country = data[:country]
69
- self.bounding_box = data[:bounding_box]
70
- end
71
-
72
- # Example
73
- # Search.search( {:zips => "92121, 92078, 92114"} )
74
- # or
75
- # Search.new( {:zips => [92121, 92078, 92114]} )
76
- def zips=(value)
77
- if value.class == String
78
- @zips = value.split(",").each { |k| k.strip! }
79
- else
80
- @zips = value
81
- end
82
- end
83
-
84
- def zips
85
- @zips
86
- end
87
-
88
- def location=(value)
89
- return if value.nil?
90
- @location = CGI.escape(value)
91
- end
92
-
93
- def keywords=(value)
94
- if value.class == String
95
- @keywords = value.gsub(",", " ").split(" ").each { |k| k.strip! }
96
- else
97
- @keywords = value
98
- end
99
- end
100
-
101
- def channels=(value)
102
- if value.class == String
103
- @channels = value.split(",").each { |k| k.strip! }
104
- else
105
- @channels = value
106
- end
107
- end
108
-
109
- def asset_ids=(value)
110
- @asset_ids = value
111
- end
112
-
113
- def bounding_box=(value)
114
- return if value==nil
115
- value = HashWithIndifferentAccess.new(value)
116
- if value.has_key?("sw") && value.has_key?("ne")
117
- @bounding_box=value
118
- else
119
- raise "bounding_box must be hash with keys sw and ne"
120
- end
121
- end
122
-
123
- def asset_id=(value)
124
- return if value.empty?
125
- @asset_ids<<value
126
- end
127
-
128
- def end_point
129
- meta_data = ""
130
- loc_str = ""
131
- # CHANNELS
132
- channel_keys = []
133
- @channels.each do |c|
134
- c = c.to_sym
135
- if Categories.CHANNELS.include?(c)
136
- channel_keys << Categories.CHANNELS[c]
137
- else
138
- puts "/////////// Channel key not found [#{c}]"
139
- end
140
- end
141
- meta_data += channel_keys.collect { |channel| "meta:channel=#{Search.double_encode_channel(channel)}" }.join("+OR+")
142
- # SPLIT MEDIA TYPE
143
- if split_media_type
144
- meta_data += "+AND+" unless meta_data == ""
145
- meta_data += split_media_type.collect { |type| "meta:splitMediaType=#{Search.double_encode_channel(type)}" }.join("+OR+")
146
- end
147
- # ASSET TYPE ID
148
- if asset_type_id
149
- meta_data += "+AND+" unless meta_data == ""
150
- meta_data += "meta:assetTypeId=#{Search.double_encode_channel(asset_type_id)}"
151
- end
152
- # url
153
- if url
154
- meta_data += "+AND+" unless meta_data == ""
155
- # url.gsub!(/\-/,"%252D")
156
- url.gsub!(/\//,"%2F")
157
- # URI.escape(url, Regexp.new("[^#{URI::PATTERN::UNRESERVED}]"))
158
- meta_data += "site:#{url}"
159
- # meta_data += "site:#{Search.double_encode_channel(url)}"
160
- end
161
- # ASSET IDS
162
- unless asset_ids.empty?
163
- meta_data += "+AND+" unless meta_data == ""
164
- temp_ids = []
165
- asset_ids.each do |id|
166
- temp_ids << "meta:" + CGI.escape("assetId=#{id.gsub("-","%2d")}")
167
- end
168
- meta_data += temp_ids.join("+OR+")
169
- end
170
- # LOCATION
171
- # 1 Look for :city, :state, :country
172
- # 2 Look for zip codes
173
- # 3 Look for lat lng
174
- # 4 Look for a formatted string "San Diego, CA, US"
175
- # 5 Look for a dma
176
- if @city or @state or @country
177
- if @city
178
- meta_data += "+AND+" unless meta_data == ""
179
- meta_data += "meta:city=#{Search.double_encode_channel(@city)}"
180
- end
181
- if @state
182
- meta_data += "+AND+" unless meta_data == ""
183
- meta_data += "meta:state=#{Search.double_encode_channel(@state)}"
184
- end
185
- elsif !@zips.empty?
186
- loc_str = @zips.join(",")
187
- elsif @latitude and @longitude
188
- loc_str = "#{@latitude};#{@longitude}"
189
- elsif @dma
190
- meta_data += "+AND+" unless meta_data == ""
191
- meta_data += "meta:dma=#{Search.double_encode_channel(@dma)}"
192
- else
193
- loc_str = @location
194
- end
195
-
196
- # BOUNDING BOX
197
- unless @bounding_box.nil?
198
- #The values in the GSA metadata are shifted to prevent negative values. This was done b/c lat/long
199
- # are searched as a number range and the GSA doesn't allow negative values in number ranges.
200
- # We shift latitude values by 90 and longitude values by 180.
201
- if @bounding_box[:sw].class==String
202
- #String :bounding_box => { :sw => "37.695141,-123.013657", :ne => "37.832371,-122.356979"}
203
- latitude1 = @bounding_box[:sw].split(",").first.to_f+90
204
- latitude2 = @bounding_box[:ne].split(",").first.to_f+90
205
- longitude1 = @bounding_box[:sw].split(",").last.to_f+180
206
- longitude2 = @bounding_box[:ne].split(",").last.to_f+180
207
- else
208
- #hash query[:bounding_box] = { :sw => [123, 10], :ne => [222,10] }
209
- latitude1 = @bounding_box[:sw].first.to_f+90
210
- latitude2 = @bounding_box[:ne].first.to_f+90
211
- longitude1 = @bounding_box[:sw].last.to_f+180
212
- longitude2 = @bounding_box[:ne].last.to_f+180
213
- end
214
- meta_data += "+AND+" unless meta_data == ""
215
- meta_data += "meta:latitudeShifted:#{latitude1}..#{latitude2}+AND+meta:longitudeShifted:#{longitude1}..#{longitude2}"
216
- end
217
-
218
- # AND DATE
219
- if @start_date.class == Date
220
- @start_date = URI.escape(@start_date.strftime("%m/%d/%Y")).gsub(/\//,"%2F")
221
- end
222
- if @end_date.class == Date
223
- @end_date = URI.escape(@end_date.strftime("%m/%d/%Y")).gsub(/\//,"%2F")
224
- end
225
- meta_data += "+AND+" unless meta_data == ""
226
- meta_data += "meta:startDate:daterange:#{@start_date}..#{@end_date}"
227
-
228
- # url = "#{SEARCH_URL}/search?api_key=#{@api_key}&num=#{@num_results}&page=#{@page}&l=#{loc_str}&f=#{@facet}&v=#{@view}&r=#{@radius}&s=#{@sort}&k=#{@keywords.join("+")}&m=#{meta_data}"
229
- urla = ["#{SEARCH_URL}/search?api_key=#{@api_key}"]
230
- urla << "num=#{@num_results}" if @num_results
231
- urla << "page=#{@page}" if @page
232
- urla << "l=#{loc_str}" unless loc_str.nil? or loc_str.empty?
233
- urla << "f=#{@facet}" if @facet
234
- urla << "v=#{@view}" if @view
235
- urla << "r=#{@radius}" if @radius
236
- urla << "s=#{@sort}" if @sort
237
- urla << "k=#{@keywords.join("+")}" if @keywords and !@keywords.empty?
238
- urla << "m=#{meta_data}" if meta_data
239
-
240
- return urla.join("&")
241
- end
242
-
243
- # TODO the seach method should not raise an error.
244
- def search
245
- searchurl = URI.parse(end_point)
246
- req = Net::HTTP::Get.new(searchurl.path)
247
- http = Net::HTTP.new(searchurl.host, searchurl.port)
248
- http.read_timeout = DEFAULT_TIMEOUT
249
-
250
- puts "Active Search [GET] #{"#{searchurl.path}?#{searchurl.query}"}"
251
- res = http.start { |http|
252
- http.get("#{searchurl.path}?#{searchurl.query}")
253
- }
254
-
255
- if (200..307).include?(res.code.to_i)
256
- begin
257
- parsed_json = JSON.parse(res.body)
258
- @endIndex = parsed_json["endIndex"]
259
- @pageSize = parsed_json["pageSize"]
260
- @searchTime = parsed_json["searchTime"]
261
- # GSA will only return 1000 events but will give us a number larger then 1000.
262
- @numberOfResults = (parsed_json["numberOfResults"] <= 1000) ? parsed_json["numberOfResults"] : 1000
263
- @results = parsed_json['_results'].collect { |a| Activity.new(GSA.new(a)) }
264
-
265
- begin
266
- Active.CACHE.set( Digest::MD5.hexdigest(end_point), self) if Active.CACHE
267
- rescue Exception => e
268
- end
269
-
270
- rescue JSON::ParserError => e
271
- raise RuntimeError, "JSON::ParserError json=#{res.body}"
272
- @endIndex = 0
273
- @pageSize = 0
274
- @searchTime = 0
275
- @numberOfResults = 0
276
- @results = []
277
- end
278
-
279
- else
280
- raise RuntimeError, "Active Search responded with a #{res.code} for your query."
281
- end
282
- end
283
-
284
- # examples
285
- #
286
- #
287
- # = Keywords =
288
- # Keywords can be set like this
289
- # Search.new({:keywords => "Dog,Cat,Cow"})
290
- # Search.new({:keywords => %w(Dog Cat Cow)})
291
- # Search.new({:keywords => ["Dog","Cat","Cow"]})
292
- #
293
- # = Channels and MediaType =
294
- # Search.new({:channels => [:running], :split_media_type => ["5k"]})
295
- # for a list of channels and splitMediaTypes please see http://developer.active.com/docs/Activecom_Search_API_Reference
296
- #
297
- # = Location =
298
- # The location will be set in this order and will override other values. For example is you set a zip code and a location only the zip will be used.
299
- #
300
- # 1 Look for zip codes
301
- # Search.search( {:zips => "92121, 92078, 92114"} )
302
- # Search.search( {:zips => %w(92121, 92078, 92114)} )
303
- # Search.search( {:zips => [92121, 92078, 92114]} )
304
- #
305
- # 2 Look for lat lng
306
- # Search.search( {:latitude=>"37.785895", :longitude=>"-122.40638"} )
307
- #
308
- # 3 Look for a formatted string "San Diego, CA, US"
309
- # Search.search( {:location = "San Diego, CA, US"} )
310
- #
311
- # 4 Look for a DMA
312
- # Search.new({:dma=>"San Francisco - Oakland - San Jose"})
313
- #
314
- # = How to look at the results =
315
- #
316
- #
317
- # http://developer.active.com/docs/Activecom_Search_API_Reference
318
- # returns an array of results and query info
319
- def self.search(data=nil)
320
- search = Search.new(data)
321
- search_hash = Digest::MD5.hexdigest(search.end_point)
322
- puts "search_hash #{search_hash}"
323
- cache = Search.return_cached(search_hash)
324
- if cache != nil
325
- return cache
326
- else
327
- search.search
328
- return search
329
- end
330
- end
331
-
332
- def self.return_cached key
333
- if Active.CACHE
334
- begin
335
- cached_version = Active.CACHE.get(key)
336
- rescue Exception => e
337
- return nil
338
- end
339
-
340
-
341
-
342
- if cached_version
343
- puts "Active Search [CACHE] #{key}"
344
- return cached_version
345
- end
346
- end
347
- nil
348
- end
349
-
350
-
351
- def []
352
- @results
353
- end
354
-
355
- private
356
- def self.double_encode_channel str
357
- str = URI.escape(str, Regexp.new("[^#{URI::PATTERN::UNRESERVED}]"))
358
- str = URI.escape(str, Regexp.new("[^#{URI::PATTERN::UNRESERVED}]"))
359
- str.gsub!(/\-/,"%252D")
360
- str
361
- end
362
- end
363
-
364
- # TODO move to a reflection service
365
- class Categories
366
- def self.CHANNELS
367
- {
368
- :active_lifestyle => '',
369
- :fitness => 'Fitness',
370
- :body_building => 'Fitness\Body Building',
371
- :boxing => 'Fitness\Boxing',
372
- :weight_lifting => 'Fitness\Weight Lifting',
373
- :gear => 'Gear',
374
- :lifestyle_vehicles => 'Lifestyle Vehicles',
375
- :mind_mody => 'Mind & Body',
376
- :meditation => 'Mind & Body\Meditation',
377
- :pilates => 'Mind & Body\Pilates',
378
- :yoga => 'Mind & Body\Yoga',
379
- :nutrition => 'Nutrition',
380
- :travel => 'Travel',
381
- :women => 'Women',
382
- :other => 'Other',
383
- :corporate => 'Corporate',
384
- :not_specified => 'Not Specified',
385
- :unknown => 'Unknown',
386
- :special_interest => 'Special+Interest',
387
- :giving => 'Giving',
388
- :parks_recreation => 'Parks & Recreation',
389
- :gear => 'Parks & Recreation\Gear',
390
- :mind_body => 'Parks & Recreation\Mind & Body',
391
- :travel => 'Parks & Recreation\Travel',
392
- :vehicles => 'Parks & Recreation\Vehicles',
393
- :women => 'Parks & Recreation\Women',
394
- :reunions => 'Reunions',
395
- :sports => 'Sports',
396
- :action_sports => 'Action Sports',
397
- :auto_racing => 'Action Sports\Auto Racing',
398
- :bmx => 'Action Sports\BMX',
399
- :dirt_bike_racing => 'Action Sports\Dirt Bike Racing',
400
- :motocross => 'Action Sports\Motocross',
401
- :motorcycle_racing => 'Action Sports\Motorcycle Racing',
402
- :skateboarding => 'Action Sports\Skateboarding',
403
- :skydiving => 'Action Sports\Skydiving',
404
- :surfing => 'Action Sports\Surfing',
405
- :wake_kite_boarding => 'Action Sports\Wake/Kite Boarding',
406
- :water_skiing => 'Action Sports\Water Skiing',
407
- :wind_surfing => 'Action Sports\Wind Surfing',
408
- :baseball => 'Baseball',
409
- :little_league_baseball => 'Baseball\Little League Baseball',
410
- :tee_ball => 'Baseball\Tee Ball',
411
- :basketball => 'Basketball',
412
- :cheerleading => 'Cheerleading',
413
- :cycling => 'Cycling',
414
- :field_hockey => 'Field Hockey',
415
- :football => 'Football',
416
- :flag_football => 'Football\Flag Football',
417
- :football_au => 'Football\Football-AU',
418
- :golf => 'Golf',
419
- :ice_hockey => 'Ice Hockey',
420
- :lacrosse => 'Lacrosse',
421
- :more_sports => 'More Sports',
422
- :adventure_racing => 'More Sports\Adventure Racing',
423
- :archery => 'More Sports\Archery',
424
- :badminton => 'More Sports\Badminton',
425
- :billiards => 'More Sports\Billiards',
426
- :bowling => 'More Sports\Bowling',
427
- :cricket => 'More Sports\Cricket',
428
- :croquet => 'More Sports\Croquet',
429
- :curling => 'More Sports\Curling',
430
- :dance => 'More Sports\Dance',
431
- :disc_sports => 'More Sports\Disc Sports',
432
- :dodgeball => 'More Sports\Dodgeball',
433
- :duathlon => 'More Sports\Duathlon',
434
- :equestrian => 'More Sports\Equestrian',
435
- :fencing => 'More Sports\Fencing',
436
- :figure_skating => 'More Sports\Figure Skating',
437
- :gymnastics => 'More Sports\Gymnastics',
438
- :inline_hockey => 'More Sports\Inline Hockey',
439
- :inline_skating => 'More Sports\Inline Skating',
440
- :kickball => 'More Sports\Kickball',
441
- :martial_arts => 'More Sports\Martial Arts',
442
- :paintball => 'More Sports\Paintball',
443
- :polo => 'More Sports\Polo',
444
- :racquetball => 'More Sports\Racquetball',
445
- :rowing => 'More Sports\Rowing',
446
- :rugby => 'More Sports\Rugby',
447
- :scouting => 'More Sports\Scouting',
448
- :scuba_diving => 'More Sports\Scuba Diving',
449
- :skating => 'More Sports\Skating',
450
- :squash => 'More Sports\Squash',
451
- :ultimate_frisbee => 'More Sports\Ultimate Frisbee',
452
- :water_polo => 'More Sports\Water Polo',
453
- :mountain_biking => 'Mountain Biking',
454
- :outdoors => 'Outdoors',
455
- :canoeing => 'Outdoors\Canoeing',
456
- :climbing => 'Outdoors\Climbing',
457
- :hiking => 'Outdoors\Hiking',
458
- :kayaking => 'Outdoors\Kayaking',
459
- :orienteering => 'Outdoors\Orienteering',
460
- :outrigging => 'Outdoors\Outrigging',
461
- :rafting => 'Outdoors\Rafting',
462
- :racquetball => 'Racquetball',
463
- :rugby => 'Rugby',
464
- :running => 'Running',
465
- :cross_country => 'Running\Cross Country',
466
- :marathon_running => 'Running\Marathon Running',
467
- :track_field => 'Running\Track & Field',
468
- :trail_running => 'Running\Trail Running',
469
- :sailing => 'Sailing',
470
- :snow_sports => 'Snow Sports',
471
- :skiing => 'Snow Sports\Skiing',
472
- :snowboarding => 'Snow Sports\Snowboarding',
473
- :snowshoeing => 'Snow Sports\Snowshoeing',
474
- :soccer => 'Soccer',
475
- :softball => 'Softball',
476
- :softball_dixie => 'Softball\Softball-Dixie',
477
- :softball_fast_pitch => 'Softball\Softball-Fast Pitch',
478
- :softball_slow_pitch => 'Softball\Softball-Slow Pitch',
479
- :squash => 'Squash',
480
- :swimming => 'Swimming',
481
- :diving => 'Swimming\Diving',
482
- :tennis => 'Tennis',
483
- :other_tennis => 'Tennis\Other Tennis',
484
- :usta => 'Tennis\USTA',
485
- :triathlon => 'Triathlon',
486
- :volleyball => 'Volleyball',
487
- :walking => 'Walking',
488
- :wrestling => 'Wrestling'
489
- }
490
- end
491
- end
492
-
493
- end
494
- end