lonely_coder 0.1.0 → 0.1.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.
data/README.mdown CHANGED
@@ -40,6 +40,12 @@ How does it work?
40
40
  -----------------------------
41
41
  You'll need an OKCupid account (it's free) because most of the site is behind authentication. You can create a new connection to the site.
42
42
 
43
+ Install as a gem
44
+
45
+ gem install lonely_coder
46
+
47
+ Use your account
48
+
43
49
  require 'lonely_coder'
44
50
  okc = OKCupid.new('yourusername', 'yourpassword')
45
51
 
@@ -12,7 +12,7 @@ class OKCupid
12
12
  username: username,
13
13
  password: password
14
14
  })
15
-
15
+
16
16
  @success = browser.page.uri.path == '/home'
17
17
 
18
18
  restore_default_parser(browser)
@@ -35,7 +35,7 @@ class OKCupid
35
35
  # We're only using page uri to determine successful login, so
36
36
  # there's not a lot of value in passing a body string to nokogiri
37
37
  def initialize(uri = nil, response = nil, body = nil, code =nil)
38
- super(uri, response, nil, code)
38
+ super(uri, response, '', code)
39
39
  end
40
40
  end
41
41
  end
@@ -66,7 +66,7 @@ class OKCupid
66
66
  # "v_looks" => 23,
67
67
  # "v_personality" => 25,
68
68
 
69
- # added by us
69
+ # filters
70
70
  'match_limit' => 'match_limit',
71
71
  'order_by' => 'order_by',
72
72
  'location' => 'location'
@@ -22,23 +22,62 @@ class OKCupid
22
22
  end
23
23
 
24
24
  def parse(options)
25
- combine_ages(options)
26
25
  check_for_required_options(options)
27
- remove_match_limit(options)
26
+
27
+ options[:age] = combine_ages(options)
28
+
28
29
 
29
30
  @filters = []
31
+ @parameters = []
32
+
30
33
  options.each do |name,value|
31
-
32
- if OKCupid.const_defined?("#{name.to_s.camelize}Filter")
33
- @filters << OKCupid.const_get("#{name.to_s.camelize}Filter").new(name, value)
34
- else
35
- @filters << Filter.new(name, value)
36
- end
34
+ self.send("add_#{name}_option", value)
35
+ # if OKCupid.const_defined?("#{name.to_s.camelize}Filter")
36
+ # @filters << OKCupid.const_get("#{name.to_s.camelize}Filter").new(name, value)
37
+ # else
38
+ # @filters << Filter.new(name, value)
39
+ # end
37
40
  end
38
41
  end
39
42
 
40
- def remove_match_limit(options)
41
- @match_limit = options.delete(:match_limit)
43
+ def add_order_by_option(value)
44
+ @parameters << OrderByParameter.new(value)
45
+ end
46
+
47
+ def add_last_login_option(value)
48
+ @filters << Filter.new('last_login', value)
49
+ end
50
+
51
+ def add_location_option(value)
52
+ @parameters << LocationParameter.new(value)
53
+ end
54
+
55
+ def add_radius_option(value)
56
+ @filters << RadiusFilter.new('radius', value)
57
+ end
58
+
59
+ def add_require_photo_option(value)
60
+ @filters << RequirePhotoFilter.new('require_photo', value)
61
+ end
62
+
63
+ def add_relationship_status_option(value)
64
+ @filters << Filter.new('relationship_status', value)
65
+ end
66
+
67
+ def add_gentation_option(value)
68
+ @filters << Filter.new('gentation', value)
69
+ end
70
+
71
+ def add_age_option(value)
72
+ @filters << AgeFilter.new('age', value)
73
+ end
74
+
75
+ def add_pagination_option(value)
76
+ @parameters << @pagination = Paginator.new(value)
77
+ end
78
+
79
+ def add_match_limit_option(value)
80
+ # TODO.
42
81
  end
43
82
 
44
83
  def check_for_required_options(options)
@@ -63,6 +102,10 @@ class OKCupid
63
102
  # relationship_status 'single'
64
103
  def defaults
65
104
  {
105
+ :pagination => {
106
+ :page => 1,
107
+ :per_page => 10
108
+ },
66
109
  :match_limit => 80,
67
110
  :min_age => 18,
68
111
  :max_age => 99,
@@ -78,24 +121,87 @@ class OKCupid
78
121
  def results
79
122
  return @results if @results
80
123
 
81
- page = @browser.get(url)
124
+ @browser.pluggable_parser.html = SearchPaginationParser
125
+ page = @browser.get(ajax_url)
126
+
82
127
  @results = page.search('.match_row').collect do |node|
83
128
  OKCupid::Profile.from_search_result(node)
84
129
  end
130
+
131
+ @browser.pluggable_parser.html = Mechanize::Page
132
+
133
+ @results
134
+ end
135
+
136
+ # no idea what the following parameters do. They don't appear to have
137
+ # an effect:
138
+ # sort_type=0
139
+ # fromWhoOnline=0
140
+ # update_prefs=1
141
+ # using_saved_search=0
142
+ # mygender=m
143
+ # no idea what the following parameters do, but without them, the search
144
+ # behaves erratically
145
+ # &timekey=1
146
+ # &custom_search=0
147
+ def magic_params_not_truly_understood
148
+ "timekey=1&custom_search=0"
85
149
  end
86
150
 
87
151
  def load_next_page
88
152
  @browser.pluggable_parser.html = SearchPaginationParser
89
- page = @browser.get("#{url}&low=11&count=10&ajax_load=1")
153
+
154
+ page = @browser.get("#{ajax_url}&#{@pagination.next.to_param}")
155
+
90
156
  @results += page.search('.match_row').collect do |node|
91
157
  OKCupid::Profile.from_search_result(node)
92
158
  end
159
+
93
160
  @browser.pluggable_parser.html = Mechanize::Page
161
+
94
162
  self
95
163
  end
96
164
 
97
165
  def url
98
- '/match?' + filters.compact.to_enum(:each_with_index).map {|filter,index| filter.to_param(index+1)}.join('&')
166
+ "/match?#{filters_as_query}&#{parameters_as_query}&#{magic_params_not_truly_understood}"
167
+ end
168
+
169
+ def ajax_url
170
+ "#{url}&ajax_load=1"
171
+ end
172
+
173
+ def parameters_as_query
174
+ @parameters.collect {|param| param.to_param }.join('&')
175
+ end
176
+
177
+ def filters_as_query
178
+ filters.compact.to_enum(:each_with_index).map {|filter,index| filter.to_param(index+1)}.join('&')
179
+ end
180
+ end
181
+
182
+ # used to create the pagination part of a search url:
183
+ # low=1&count=10&ajax_load=1
184
+ # where low is the start value
185
+ # count is the number of items per page
186
+ class Paginator
187
+ attr_reader :page, :per_page
188
+
189
+ def initialize(options)
190
+ @per_page = options[:per_page]
191
+ @page = options[:page]
192
+ end
193
+
194
+ def low
195
+ @low = ((@page - 1) * @per_page) + 1
196
+ end
197
+
198
+ def next
199
+ @page +=1
200
+ self
201
+ end
202
+
203
+ def to_param
204
+ "low=#{low}&count=#{@per_page}"
99
205
  end
100
206
  end
101
207
 
@@ -137,13 +243,12 @@ class OKCupid
137
243
  end
138
244
  end
139
245
 
140
- class LocationFilter < Filter
141
- def lookup(value)
142
- ''
246
+ class LocationParameter
247
+ def initialize(value)
248
+ @value = value
143
249
  end
144
250
 
145
- def to_param(n)
146
-
251
+ def to_param
147
252
  # to do: 'anywhere' needs to remove the radius filter
148
253
  if @value.is_a?(String)
149
254
  if @value.downcase == 'near me'
@@ -156,24 +261,18 @@ class OKCupid
156
261
  end
157
262
  end
158
263
  end
159
-
160
- class OrderByFilter < Filter
161
- def to_param(n)
264
+
265
+ class OrderByParameter
266
+ def initialize(value)
267
+ @value = value
268
+ @encoded_value = MagicNumbers::OrderBy[value.downcase]
269
+ end
270
+
271
+ def to_param
162
272
  "matchOrderBy=#{@encoded_value}"
163
273
  end
164
274
  end
165
-
166
- # we fake this by paginating results ourselves.
167
- # class MatchLimitFilter < Filter
168
- # def lookup(value)
169
- # 'MATCH'
170
- # end
171
- #
172
- # def to_param(n)
173
- # nil
174
- # end
175
- # end
176
-
275
+
177
276
  class RequirePhotoFilter < Filter
178
277
  def lookup(value)
179
278
  value ? 1 : 0
data/lib/lonely_coder.rb CHANGED
@@ -11,7 +11,7 @@ require 'mechanize'
11
11
 
12
12
  class OKCupid
13
13
  BaseUrl = 'http://www.okcupid.com'
14
- VERSION = '0.1.0'
14
+ VERSION = '0.1.1'
15
15
 
16
16
  def initialize(username=nil, password=nil)
17
17
  @browser = Mechanize.new
@@ -0,0 +1,34 @@
1
+ # -*- encoding: utf-8 -*-
2
+ Gem::Specification.new do |s|
3
+ s.name = "lonely_coder"
4
+ s.version = '0.1.1'
5
+ s.platform = Gem::Platform::RUBY
6
+ s.authors = ["Trek Glowacki"]
7
+ s.email = ["trek.glowacki@gmail.com"]
8
+ s.homepage = "http://github.com/trek/lonely_coder"
9
+ s.summary = %q{A gem for interacting with OKCupid as if it had an API}
10
+ s.description = %q{A gem for interacting with OKCupid as if it had an API.}
11
+
12
+ s.add_dependency 'mechanize', '= 2.0.1'
13
+ s.add_dependency 'activesupport', '>= 3.2.1'
14
+
15
+ s.post_install_message = %q{
16
+
17
+
18
+
19
+ ,d88b.d88b,
20
+ 88888888888
21
+ `Y8888888Y'
22
+ `Y888Y'
23
+ `Y'
24
+
25
+ Good luck out there.
26
+
27
+
28
+ }
29
+
30
+ s.files = `git ls-files`.split("\n")
31
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
32
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
33
+ s.require_paths = ["lib"]
34
+ end