Active 0.0.42 → 0.1.7

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.
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