manhunt 0.1.1 → 0.1.3

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 CHANGED
@@ -5,13 +5,14 @@ begin
5
5
  require 'jeweler'
6
6
  Jeweler::Tasks.new do |gem|
7
7
  gem.name = "manhunt"
8
- gem.summary = %Q{one-line summary of your gem}
9
- gem.description = %Q{ longer description of your gem}
10
- gem.email = "self@richardpenwell.me"
8
+ gem.summary = %Q{Client library for manhunt.net }
9
+ gem.description = %Q{Provides object model to access manhunt.net data}
10
+ gem.email = "almightylinuxgod@me.com"
11
11
  gem.homepage = "http://github.com/penwellr/manhunt"
12
12
  gem.authors = ["Richard Penwell"]
13
13
  gem.add_development_dependency "rspec", ">= 1.2.9"
14
- gem.add_dependency "smartfox"
14
+ gem.add_dependency 'smartfox', '>= 3.1'
15
+ gem.files.exclude 'nbproject/**'
15
16
  # gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
16
17
  end
17
18
  Jeweler::GemcutterTasks.new
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.1.1
1
+ 0.1.3
@@ -0,0 +1,13 @@
1
+ require 'smartfox'
2
+ require 'logger'
3
+ require 'net/http'
4
+
5
+ module Manhunt
6
+ autoload :Folder, 'manhunt/folder'
7
+ autoload :Sessuion, 'manhunt/session'
8
+ autoload :User, 'manhunt/user'
9
+ autoload :Photo, 'manhunt/photo'
10
+ autoload :Message, 'manhunt/message'
11
+
12
+ Logger = Logger.new(STDOUT)
13
+ end
@@ -0,0 +1,60 @@
1
+ class Manhunt::Folder
2
+ attr_reader :name, :count
3
+
4
+ def initialize(session, folder)
5
+ @session = session
6
+ @name = folder
7
+ @messages = {}
8
+ end
9
+
10
+ def messages(page = 1)
11
+ reload(page)
12
+ @messages.values.sort{ |a,b| a.date <=> b.date }.reverse
13
+ end
14
+
15
+ def reload(page)
16
+ url = "/mail/folder/#{@name}/#{page}"
17
+ document = @session.get_document(url)
18
+ @count = ManhuntFolder.parse_message_count(document)
19
+
20
+ @messages = ManhuntFolder.parse_messages(document)
21
+ end
22
+
23
+ def message(id)
24
+ url = "/mail/viewMessage/id/#{id}/folder/#{@name}"
25
+ document = @session.get_document(url)
26
+
27
+ ManhuntMessage.parse_message(document, id)
28
+ end
29
+
30
+ def self.parse_messages(document)
31
+ messages = {}
32
+ message_table = (document/"#msgsListTable")
33
+ format = parse_message_header(message_table/"tr.header")
34
+
35
+ (message_table/"tr").each do |row|
36
+ unless row[:class] == 'header'
37
+ message = ManhuntMessage.parse_header(format, row)
38
+ messages[message.id] = message
39
+ end
40
+ end
41
+
42
+ messages
43
+ end
44
+
45
+ def self.parse_message_header(header_row)
46
+ (header_row/'td').map do |column|
47
+ header = column.inner_text.strip
48
+ if header.empty?
49
+ nil
50
+ else
51
+ header.delete(':').downcase.gsub(' ', '_').to_sym
52
+ end
53
+ end
54
+ end
55
+
56
+ def self.parse_message_count(document)
57
+ count_field = (document / "#msgsShownTxt").inner_text
58
+ (/(\d+)\s+$/.match(count_field))[1].to_i
59
+ end
60
+ end
@@ -0,0 +1,74 @@
1
+ class Manhunt::Message
2
+ include ActiveModel::Serializers::Xml
3
+ include ActiveModel::Serializers::JSON
4
+
5
+ GUID_REGEX = /[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}/
6
+ PROFILE_NAME_REGEX = /setWindow\('profile\/(\w+)','profile'\);/
7
+ USER_ID_REGEX = /modalOpen\('list\/modalAddBuddy',\{buddy:(\d+)\}\);/
8
+
9
+ attr_reader :row, :subject, :from, :format, :state, :id, :body, :from_id, :date, :online
10
+
11
+ def attributes
12
+ { 'subject' => subject, 'from' => from, 'state' => state, 'id' => id, 'body' => body, 'date' => date, 'online' => online }
13
+ end
14
+
15
+ def self.parse_header(format, row)
16
+ ManhuntMessage.new(:header, row, format)
17
+ end
18
+
19
+ def self.parse_message(document, id)
20
+ message = ManhuntMessage.new(:message, document)
21
+ message.instance_eval do
22
+ @id = id
23
+ end
24
+ message
25
+ end
26
+
27
+ def self.compose(session, user_name, user_id, reply_message_id = nil)
28
+ if reply_message_id
29
+ url = "/mail/compose/recipientId/#{user_id}/messageId/#{reply_message_id}/username/#{user_name}"
30
+ end
31
+ compose = session.get_document(url)
32
+
33
+ { :subject => (compose/"#subject").first.attributes['value'], :body => (compose/"#body").first.inner_html, :raw => compose }
34
+ end
35
+
36
+ def initialize(type, document, format = nil)
37
+ @format = format
38
+ @row = document
39
+
40
+ case type
41
+ when :header
42
+ columns = (document/"td")
43
+
44
+ @subject = (document/".subject").inner_text.strip
45
+ @online = (document/".buddyOnline").any?
46
+ @from = columns[@format.index(:from)].inner_text
47
+ @state = :unread
48
+ @state = :read if (document/".messageRead").any?
49
+ @state = :replied if (document/".messageReplied").any?
50
+ @id = GUID_REGEX.match((document/".subject a").first.attributes['href'])[0]
51
+ @date = Time.at((columns[@format.index(:date)]/".LocalTime").first.attributes['gmt_time'].to_i)
52
+ when :message
53
+ @body = (document/"#msgTextDiv").inner_html
54
+ @subject = (document/".headerColored").inner_text.strip
55
+ @from = PROFILE_NAME_REGEX.match((document/"#readRecipProfLink a").first.attributes['onclick'])[1]
56
+ @from_id = USER_ID_REGEX.match((document/"#buddyButton").first.attributes['onclick'])[1]
57
+ end
58
+ end
59
+
60
+ def self.send_message(session, params)
61
+ url = "/mail/send"
62
+
63
+ options = { 'body' => params[:body], 'subject' => params[:subject], 'recipientId' => params[:send_to_id], 'username' => params[:send_to] }
64
+ options['replyMessageId'] = params[:reply_message_id] if params[:reply_message_id]
65
+
66
+
67
+ session.post_nil(url, options)
68
+ end
69
+
70
+ def to_param
71
+ id
72
+ end
73
+
74
+ end
@@ -0,0 +1,18 @@
1
+ class Manhunt::Photo
2
+ attr_reader :photo_id
3
+
4
+ def initialize(user, photo_id)
5
+ @user = user
6
+ @photo_id = photo_id
7
+ end
8
+
9
+ def user_id
10
+ @user.user_id
11
+ end
12
+
13
+ def self.content(session, profile_id, photo_id, size = "med")
14
+ photo_ref = session.post_object('/photo/ajaxGetPhoto', {'profileId' => profile_id, 'photoId' => photo_id, 'photoSize' => size })
15
+
16
+ session.get_binary(photo_ref['url'])
17
+ end
18
+ end
@@ -0,0 +1,184 @@
1
+ require 'net/http'
2
+
3
+ class Manhunt::Session
4
+ LOGIN_PAGE_REGEX = /<form id="login" name="login" method="post" action="\/">/
5
+
6
+ attr_reader :username
7
+ attr_reader :language
8
+
9
+ def initialize(username, password, language = 'en')
10
+ @username = username
11
+ @password = password
12
+ @language = language
13
+ @cookies = { 'MHLogin' => '1', '__utma' => '179992888.1977247352.1264973581.1267729320.1267734788.33',
14
+ '__utmb' => '179992888.15.10.1267734788', '__utmc' => '179992888',
15
+ '__utmz' => '179992888.1264973581.1.1.utmcsr=(direct)|utmccn=(direct)|utmcmd=(none)' }
16
+ end
17
+
18
+ def self.create(options)
19
+ options[:language] ||= 'en'
20
+ session = Manhunt::Session.new(options[:username], options[:password], options[:language])
21
+ session.create
22
+
23
+ return session
24
+ end
25
+
26
+ def create
27
+ @login_options = { 'loginLang' => @language, 'rememberLogin' => false, 'name' => @username, 'pass' => @password, 'skinId' => 'mh', 'canChat' => false }
28
+ login
29
+ end
30
+
31
+ def login
32
+ @login_options ||= { 'loginLang' => @language, 'rememberLogin' => false, 'name' => @username, 'pass' => @password, 'skinId' => 'mh', 'canChat' => false }
33
+ result = post_object('/user/janusLookup', @login_options)
34
+
35
+ @valid = result["handleError"] == 'success'
36
+ end
37
+
38
+ def valid?
39
+ @valid || false
40
+ end
41
+
42
+ def post_object(url, object)
43
+ request_object(url, :post, object)
44
+ end
45
+
46
+ def get_object(url)
47
+ RAILS_DEFAULT_LOGGER.info " \e[1;#{color}mObject Load (0.0s) \e[1;30m#{url}\e[0m"
48
+ request_object(url, :get)
49
+ end
50
+
51
+ def request_object(url, method, object = nil)
52
+ case method
53
+ when :get
54
+ request = Net::HTTP::Get.new(url)
55
+ when :post
56
+ request = Net::HTTP::Post.new(url)
57
+ end
58
+ request['Accept'] = 'application/json, text/javascript, */*'
59
+ request['X-Requested-With'] = 'XMLHttpRequest'
60
+ request.form_data = object if object
61
+ result = prepare_request(request)
62
+ ActiveSupport::JSON.decode(ManhuntSession.pureify_json(result.body))
63
+ end
64
+
65
+ def post_nil(url, object = nil)
66
+ request_nil(url, :post, object)
67
+ end
68
+
69
+ def request_nil(url, method, object = nil)
70
+ RAILS_DEFAULT_LOGGER.info " \e[1;#{color}m#{method.to_s.capitalize} Save (0.0s) \e[1;30m#{url} - #{object.inspect if object}\e[0m"
71
+ case method
72
+ when :get
73
+ request = Net::HTTP::Get.new(url)
74
+ when :post
75
+ request = Net::HTTP::Post.new(url)
76
+ end
77
+ request['Accept'] = 'application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5'
78
+ request['Content-Type'] = 'application/x-www-form-urlencoded' if method == :post
79
+ request.form_data = object if object
80
+ result = prepare_request(request)
81
+ RAILS_DEFAULT_LOGGER.debug "Result => #{result}"
82
+ nil
83
+ end
84
+
85
+
86
+
87
+ def get_document(url)
88
+ RAILS_DEFAULT_LOGGER.info " \e[1;#{color}mDocument Load (0.0s) \e[1;30m#{url}\e[0m"
89
+ request = Net::HTTP::Get.new(url)
90
+ request['Accept'] = 'application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5'
91
+
92
+ result = prepare_request(request)
93
+
94
+ if block_given?
95
+ Hpricot(yield(result.body))
96
+ else
97
+ Hpricot(result.body)
98
+ end
99
+ end
100
+
101
+ def get_binary(url)
102
+ puts " \e[1;#{color}mBinary Load (0.0s) \e[1;30m#{url}\e[0m"
103
+ request = Net::HTTP::Get.new(url)
104
+ request['Accept'] = 'application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5'
105
+
106
+ prepare_request(request)
107
+ end
108
+
109
+ def prepare_request(request)
110
+ request["Cookie"] = @cookies.map{|key, value| "#{key}=#{value}"}.join('; ')
111
+ request["Referer"] = 'http://www.manhunt.net/welcome'
112
+ request["User-Agent"] = 'Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_2; en-us) AppleWebKit/533.1+ (KHTML, like Gecko) Version/4.0.4 Safari/531.21.10'
113
+ request['Accept-Language'] = 'Accept-Language: en-us'
114
+
115
+ result = Net::HTTP.new('www.manhunt.net', 80).start { |http|
116
+ http.request(request)
117
+ }
118
+ if result['Set-Cookie']
119
+ result.get_fields('Set-Cookie').each do |cookie|
120
+ data = cookie.split(';')[0]
121
+ key = data.split('=')[0]
122
+ value = data.split('=')[1]
123
+ @cookies[key] = value
124
+ end
125
+ end
126
+
127
+ if LOGIN_PAGE_REGEX.match(result.body)
128
+ login
129
+ result = Net::HTTP.new('www.manhunt.net', 80).start { |http|
130
+ http.request(request)
131
+ }
132
+ end
133
+
134
+ result
135
+ end
136
+
137
+ def unlock_photos(user)
138
+ parameters = { 'uid' => user.platform_id, 'name' => user.username }
139
+ Rails.logger.info post_object('/list/ajaxAddUnlock', parameters)
140
+ end
141
+
142
+ def folders
143
+ @folders = ['inbox', 'sent', 'saved', 'trash'].map do |name|
144
+ ManhuntFolder.new(self, name)
145
+ end
146
+ end
147
+
148
+ def folder(name)
149
+ ManhuntFolder.new(self, name)
150
+ end
151
+
152
+ def photo_content(profile_id, photo_id, size = "med")
153
+ ManhuntPhoto.content(self, profile_id, photo_id, size)
154
+ end
155
+
156
+ def unread_count
157
+ get_object('/mail/ajaxGetUnreadMessageCount')
158
+ end
159
+
160
+ def user(name)
161
+ Manhunt::User.find(self, name)
162
+ end
163
+
164
+
165
+
166
+ def compose(user, user_id, reply_message_id = nil)
167
+ Manhunt::Message.compose(self, user, user_id, reply_message_id)
168
+ end
169
+
170
+ def send_message(params)
171
+ Manhunt::Message.send_message(self, params)
172
+ end
173
+
174
+ private
175
+ def color
176
+ @@color ||= 36
177
+ @@color = (@@color == 35) ? 36 : 35
178
+ end
179
+
180
+ def self.pureify_json(input)
181
+ replace_input = /^\((.*)\)$/.match(input)
182
+ replace_input ? replace_input[1] : input
183
+ end
184
+ end
@@ -0,0 +1,80 @@
1
+ class Manhunt::User
2
+ attr_reader :user_id, :username, :online, :headline, :photos, :body
3
+ attr_reader :location, :position, :age, :build, :height, :eyes, :ethnicity
4
+ attr_reader :hair, :availability, :hiv, :place, :html, :stats
5
+
6
+ def self.find(session, username)
7
+ uri = "/profile/#{username}"
8
+ document = session.get_document(uri) do |text|
9
+ # This little ugly hack fixes some majorly broken HTML on the site
10
+ text.gsub(", \"med\", \"#largePic\")'; return false;>", ", \"med\", \"#largePic\"); return false;'>")
11
+ end
12
+
13
+ ManhuntUser.parse(session, document)
14
+ end
15
+
16
+ def self.parse(session, document)
17
+ user = ManhuntUser.new(session, document)
18
+ end
19
+
20
+ def id
21
+ user_id
22
+ end
23
+
24
+ def model_name
25
+ "user"
26
+ end
27
+
28
+ def initialize(session, document)
29
+ @session = session
30
+ @username = (document/"#name").inner_text.strip
31
+ @user_id = ManhuntUser.parse_user_id(document)
32
+ @online = (document/".buddyOnline").any?
33
+ @location = (document/"#profileLocation").inner_text.strip
34
+ @body = (document/'#body').inner_text
35
+ @headline = (document/'#headline').inner_text
36
+ @html = document
37
+ @photos = ManhuntUser.parse_photos(self, document/"#pics")
38
+
39
+ parse_stats(document/"#stats")
40
+
41
+
42
+ end
43
+
44
+ def parse_stats(stats_div)
45
+ @stats = {}
46
+ (stats_div/"div").each do |stat|
47
+ title = (stat/"strong").inner_text.strip
48
+ value = (stat/"p").inner_text.strip
49
+
50
+ @stats[title] = value unless title.blank?
51
+ end
52
+
53
+ (stats_div/"label").each do |label|
54
+ title = label.inner_text.strip
55
+ value = label.next_sibling.inner_text.strip
56
+
57
+ @stats[title] = value unless title.blank?
58
+ end
59
+ end
60
+
61
+ def self.parse_photos(user, photo_element)
62
+ (photo_element/'div').map do |photo|
63
+ photo_id = photo[:photoid].to_i
64
+ ManhuntPhoto.new(user, photo_id)
65
+ end
66
+ end
67
+
68
+ def self.parse_user_id(document)
69
+ large_pic = (document/"#largePic").first
70
+ if large_pic
71
+ onclick = large_pic.attributes['onclick']
72
+ match = (/viewProfilePic\(this, (\d+)\); return false;/.match(onclick))
73
+ if match
74
+ return match[1]
75
+ end
76
+ end
77
+
78
+ nil
79
+ end
80
+ end
@@ -0,0 +1,63 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
4
+ # -*- encoding: utf-8 -*-
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = %q{manhunt}
8
+ s.version = "0.1.3"
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
+ s.authors = ["Richard Penwell"]
12
+ s.date = %q{2010-06-16}
13
+ s.description = %q{Provides object model to access manhunt.net data}
14
+ s.email = %q{almightylinuxgod@me.com}
15
+ s.extra_rdoc_files = [
16
+ "LICENSE",
17
+ "README.rdoc"
18
+ ]
19
+ s.files = [
20
+ ".document",
21
+ ".gitignore",
22
+ "LICENSE",
23
+ "README.rdoc",
24
+ "Rakefile",
25
+ "VERSION",
26
+ "lib/manhunt.rb",
27
+ "lib/manhunt/folder.rb",
28
+ "lib/manhunt/message.rb",
29
+ "lib/manhunt/photo.rb",
30
+ "lib/manhunt/session.rb",
31
+ "lib/manhunt/user.rb",
32
+ "manhunt.gemspec",
33
+ "spec/manhunt_spec.rb",
34
+ "spec/spec.opts",
35
+ "spec/spec_helper.rb"
36
+ ]
37
+ s.homepage = %q{http://github.com/penwellr/manhunt}
38
+ s.rdoc_options = ["--charset=UTF-8"]
39
+ s.require_paths = ["lib"]
40
+ s.rubygems_version = %q{1.3.7}
41
+ s.summary = %q{Client library for manhunt.net}
42
+ s.test_files = [
43
+ "spec/manhunt_spec.rb",
44
+ "spec/spec_helper.rb"
45
+ ]
46
+
47
+ if s.respond_to? :specification_version then
48
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
49
+ s.specification_version = 3
50
+
51
+ if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
52
+ s.add_development_dependency(%q<rspec>, [">= 1.2.9"])
53
+ s.add_runtime_dependency(%q<smartfox>, [">= 3.1"])
54
+ else
55
+ s.add_dependency(%q<rspec>, [">= 1.2.9"])
56
+ s.add_dependency(%q<smartfox>, [">= 3.1"])
57
+ end
58
+ else
59
+ s.add_dependency(%q<rspec>, [">= 1.2.9"])
60
+ s.add_dependency(%q<smartfox>, [">= 3.1"])
61
+ end
62
+ end
63
+
metadata CHANGED
@@ -1,12 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: manhunt
3
3
  version: !ruby/object:Gem::Version
4
+ hash: 29
4
5
  prerelease: false
5
6
  segments:
6
7
  - 0
7
8
  - 1
8
- - 1
9
- version: 0.1.1
9
+ - 3
10
+ version: 0.1.3
10
11
  platform: ruby
11
12
  authors:
12
13
  - Richard Penwell
@@ -21,9 +22,11 @@ dependencies:
21
22
  name: rspec
22
23
  prerelease: false
23
24
  requirement: &id001 !ruby/object:Gem::Requirement
25
+ none: false
24
26
  requirements:
25
27
  - - ">="
26
28
  - !ruby/object:Gem::Version
29
+ hash: 13
27
30
  segments:
28
31
  - 1
29
32
  - 2
@@ -35,16 +38,19 @@ dependencies:
35
38
  name: smartfox
36
39
  prerelease: false
37
40
  requirement: &id002 !ruby/object:Gem::Requirement
41
+ none: false
38
42
  requirements:
39
43
  - - ">="
40
44
  - !ruby/object:Gem::Version
45
+ hash: 5
41
46
  segments:
42
- - 0
43
- version: "0"
47
+ - 3
48
+ - 1
49
+ version: "3.1"
44
50
  type: :runtime
45
51
  version_requirements: *id002
46
- description: " longer description of your gem"
47
- email: self@richardpenwell.me
52
+ description: Provides object model to access manhunt.net data
53
+ email: almightylinuxgod@me.com
48
54
  executables: []
49
55
 
50
56
  extensions: []
@@ -60,6 +66,12 @@ files:
60
66
  - Rakefile
61
67
  - VERSION
62
68
  - lib/manhunt.rb
69
+ - lib/manhunt/folder.rb
70
+ - lib/manhunt/message.rb
71
+ - lib/manhunt/photo.rb
72
+ - lib/manhunt/session.rb
73
+ - lib/manhunt/user.rb
74
+ - manhunt.gemspec
63
75
  - spec/manhunt_spec.rb
64
76
  - spec/spec.opts
65
77
  - spec/spec_helper.rb
@@ -73,26 +85,30 @@ rdoc_options:
73
85
  require_paths:
74
86
  - lib
75
87
  required_ruby_version: !ruby/object:Gem::Requirement
88
+ none: false
76
89
  requirements:
77
90
  - - ">="
78
91
  - !ruby/object:Gem::Version
92
+ hash: 3
79
93
  segments:
80
94
  - 0
81
95
  version: "0"
82
96
  required_rubygems_version: !ruby/object:Gem::Requirement
97
+ none: false
83
98
  requirements:
84
99
  - - ">="
85
100
  - !ruby/object:Gem::Version
101
+ hash: 3
86
102
  segments:
87
103
  - 0
88
104
  version: "0"
89
105
  requirements: []
90
106
 
91
107
  rubyforge_project:
92
- rubygems_version: 1.3.6
108
+ rubygems_version: 1.3.7
93
109
  signing_key:
94
110
  specification_version: 3
95
- summary: one-line summary of your gem
111
+ summary: Client library for manhunt.net
96
112
  test_files:
97
113
  - spec/manhunt_spec.rb
98
114
  - spec/spec_helper.rb