Skip to content
This repository was archived by the owner on Nov 23, 2021. It is now read-only.

additional methods + update functionality #8

Open
wants to merge 11 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion lib/lonely_coder.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,12 @@
# `Y' - trek
#
require 'mechanize'
require 'addressable/uri'
require 'dimensions'

class OKCupid
BaseUrl = 'http://www.okcupid.com'
VERSION = '0.1.5'
VERSION = '0.2.0'

def initialize(username=nil, password=nil)
@browser = Mechanize.new
Expand Down
4 changes: 4 additions & 0 deletions lib/lonely_coder/authentication.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@ def authenticate(username, password)
@authentication = Authentication.new(username, password, @browser)
end

def authenticated?
@authentication.success?
end

class Authentication
def initialize(username, password, browser)
change_to_using_simpler_parser(browser)
Expand Down
190 changes: 165 additions & 25 deletions lib/lonely_coder/profile.rb
Original file line number Diff line number Diff line change
@@ -1,34 +1,51 @@
# encoding: UTF-8

class OKCupid

def profile_for(username)
Profile.by_username(username, @browser)
end

def visitors_for(username, previous_timestamp = 0)
Profile.get_new_visitors(username, previous_timestamp, @browser)
end

def likes_for(username)
Profile.get_new_likes(username, @browser)
end

def update_section(section, text)
Profile.update_profile_section(section, text, @browser)
end

def upload_pic(file, caption)
Profile.upload_picture(file, caption, @browser)
end

class Profile
attr_accessor :username, :match, :friend, :enemy, :location,
:age, :sex, :orientation, :single, :small_avatar_url

# extended profile details
attr_accessor :last_online, :ethnicity, :height, :body_type, :diet, :smokes,
:drinks, :drugs, :religion, :sign, :education, :job, :income,
:offspring, :pets, :speaks, :profile_thumb_urls
attr_accessor :last_online, :ethnicity, :height, :body_type, :diet, :smokes,
:drinks, :drugs, :religion, :sign, :education, :job, :income,
:offspring, :pets, :speaks, :profile_thumb_urls, :essays


# Scraping is never pretty.
def self.from_search_result(html)

username = html.search('span.username').text
age, sex, orientation, single = html.search('p.aso').text.split('/')

percents = html.search('div.percentages')
match = percents.search('p.match .percentage').text.to_i
friend = percents.search('p.friend .percentage').text.to_i
enemy = percents.search('p.enemy .percentage').text.to_i

location = html.search('p.location').text
small_avatar_url = html.search('a.user_image img').attribute('src').value

OKCupid::Profile.new({
username: username,
age: OKCupid.strip(age),
Expand All @@ -42,24 +59,62 @@ def self.from_search_result(html)
small_avatar_url: small_avatar_url
})
end


def Profile.get_new_likes(username, browser)
html = browser.get("http://www.okcupid.com/who-likes-you")
text = html.search('#whosIntoYouUpgrade .title').text
index = text.index(' people')
likes = text[0, index].to_i

return likes
end

def Profile.get_new_visitors(username, previous_timestamp = 1393545600, browser)
html = browser.get("http://www.okcupid.com/visitors")
visitors = html.search(".user_list .user_row_item")

new_visitors = 0
# previous_timestamp = 1393545600

visitors.each { |visitor|
begin
timestamp_script = visitor.search(".timestamp script")
timestamp_search = timestamp_script.text.match(/FancyDate\.add\([^,]+?,\s*(\d+)\s*,/)
timestamp = timestamp_search[1]
timestamp = timestamp.to_i
rescue
next
end
if (timestamp > previous_timestamp)
new_visitors += 1
end
}

return new_visitors
end

def Profile.by_username(username, browser)
html = browser.get("http://www.okcupid.com/profile/#{username}")

percents = html.search('#percentages')
match = percents.search('span.match').text.to_i
friend = percents.search('span.friend').text.to_i
enemy = percents.search('span.enemy').text.to_i

basic = html.search('#aso_loc')
age = basic.search('#ajax_age').text
sex = basic.search('#ajax_gender').text
orientation = basic.search('#ajax_orientation').text
single = basic.search('#ajax_status').text
location = basic.search('#ajax_location').text

profile_thumb_urls = html.search('#profile_thumbs img').collect {|img| img.attribute('src').value}


essays = []
10.times do |i|
essays[i] = html.search('#essay_text_' + i.to_s).text.strip!
end

attributes = {
username: username,
match: match,
Expand All @@ -70,36 +125,120 @@ def Profile.by_username(username, browser)
orientation: orientation,
location: location,
single: single,
profile_thumb_urls: profile_thumb_urls
profile_thumb_urls: profile_thumb_urls,
essays: essays
}

details_div = html.search('#profile_details dl')

details_div.each do |node|
value = OKCupid.strip(node.search('dd').text)
next if value == '—'

attr_name = node.search('dt').text.downcase.gsub(' ','_')
attributes[attr_name] = value
end

self.new(attributes)
end

def Profile.update_profile_section(section, text, browser)
section_titles = [
"My self-summary",
"What I’m doing with my life",
"I’m really good at",
"The first things people usually notice about me",
"Favorite books, movies, shows, music, and food",
"The six things I could never do without",
"I spend a lot of time thinking about",
"On a typical Friday night I am",
"The most private thing I’m willing to admit",
"You should message me if"
]

section_titles_hash = {
:self_summary => 0,
:im_doing => 1,
:good_at => 2,
:first_thing => 3,
:favorites => 4,
:six_things => 5,
:think_about => 6,
:private => 7,
:message_me => 8
}

if section.class == Symbol
section = section_titles_hash[section]
end

profile = browser.get('http://www.okcupid.com/profile')

authcode = profile.body.match(/authcode['"]?\s*:\s*['"]([\w,;]+?)['"]/)[1]

section_response = browser.post('http://www.okcupid.com/profileedit2', {
:authcode => authcode,
:essay_body => text,
:essay_id => section,
:change_summary => "[title:start]#{section_titles[section]}[title:end][add:start]#{text}[add:end]",
:okc_api => 1
})
end

def Profile.upload_picture(file, caption, browser)

file_dimensions = Dimensions.dimensions(file)

profile = browser.get('http://www.okcupid.com/profile')

authcode = profile.body.match(/authcode['"]?\s*:\s*['"]([\w,;]+?)['"]/)[1]
userid = profile.body.match(/userid['"]?\s*:\s*['"]?(\d+)['"]?/)[1]

upload_response = browser.post('http://www.okcupid.com/ajaxuploader', {
'file' => File.new(file)
})

picid = upload_response.body.match(/id'\s*:\s*'(\d+)/)[1]

uri = Addressable::URI.parse('http://www.okcupid.com/photoupload')
uri.query_values = {
:authcode => authcode,
:userid => userid,
:picid => picid,
:width => file_dimensions[0],
:height => file_dimensions[1],
:tn_upper_left_x => 0,
:tn_upper_left_y => 0,
:tn_lower_right_x => file_dimensions[0],
:tn_lower_right_y => file_dimensions[1],

:caption => caption,
:albumid => 0,
:use_new_upload => 1,
:okc_api => 1,
:'picture.add_ajax' => 1,
}

uri.to_s

create_photo = browser.get(uri.to_s)

end

def initialize(attributes)
attributes.each do |attr,val|
self.send("#{attr}=", val)
end
end

def ==(other)
self.username == other.username
end

def eql?(other)
self.username == other.username
end

def hash
if self.username
self.username.hash
Expand All @@ -108,4 +247,5 @@ def hash
end
end
end
end
end

4 changes: 3 additions & 1 deletion lonely_coder.gemspec
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# -*- encoding: utf-8 -*-
Gem::Specification.new do |s|
s.name = "lonely_coder"
s.version = '0.1.5.1'
s.version = '0.2.0.0'
s.platform = Gem::Platform::RUBY
s.authors = ["Trek Glowacki"]
s.email = ["[email protected]"]
Expand All @@ -10,6 +10,8 @@ Gem::Specification.new do |s|
s.description = %q{A gem for interacting with OKCupid as if it had an API.}

s.add_dependency 'mechanize', '= 2.0.1'
s.add_dependency 'addressable', '= 2.3.5'
s.add_dependency 'dimensions', '= 1.3.0'
s.add_dependency 'activesupport', '>= 3.2.1'

s.post_install_message = %q{
Expand Down