briancollins-blackbook 1.0.15

Sign up to get free protection for your applications and to get access to all the features.
Files changed (68) hide show
  1. data/CHANGES.markdown +44 -0
  2. data/Manifest.txt +59 -0
  3. data/README.markdown +74 -0
  4. data/VERSION.yml +4 -0
  5. data/lib/blackbook.rb +83 -0
  6. data/lib/blackbook/exporter/base.rb +16 -0
  7. data/lib/blackbook/exporter/vcf.rb +45 -0
  8. data/lib/blackbook/exporter/xml.rb +28 -0
  9. data/lib/blackbook/importer/aol.rb +94 -0
  10. data/lib/blackbook/importer/base.rb +39 -0
  11. data/lib/blackbook/importer/csv.rb +68 -0
  12. data/lib/blackbook/importer/freenet.rb +62 -0
  13. data/lib/blackbook/importer/gmail.rb +73 -0
  14. data/lib/blackbook/importer/gmx.rb +68 -0
  15. data/lib/blackbook/importer/hotmail.rb +128 -0
  16. data/lib/blackbook/importer/page_scraper.rb +52 -0
  17. data/lib/blackbook/importer/web.de.rb +67 -0
  18. data/lib/blackbook/importer/yahoo.rb +73 -0
  19. data/test/config/credentials.yml.example +9 -0
  20. data/test/fixtures/aol_application_page.html +566 -0
  21. data/test/fixtures/aol_bad_login_response_stage_3.html +565 -0
  22. data/test/fixtures/aol_contacts.html +102 -0
  23. data/test/fixtures/aol_login_response_stage_1.html +158 -0
  24. data/test/fixtures/aol_login_response_stage_2.html +559 -0
  25. data/test/fixtures/aol_login_response_stage_3.html +48 -0
  26. data/test/fixtures/aol_login_response_stage_4.html +404 -0
  27. data/test/fixtures/aol_new_contacts.html +431 -0
  28. data/test/fixtures/gmail.csv +3 -0
  29. data/test/fixtures/gmail_bad_login_response_stage_2.html +560 -0
  30. data/test/fixtures/gmail_contacts.html +228 -0
  31. data/test/fixtures/gmail_login_response_stage_1.html +556 -0
  32. data/test/fixtures/gmail_login_response_stage_2.html +1 -0
  33. data/test/fixtures/gmail_login_response_stage_2a.html +1 -0
  34. data/test/fixtures/gmail_login_response_stage_3.html +249 -0
  35. data/test/fixtures/gmail_redirect_body.html +10 -0
  36. data/test/fixtures/hotmail_bad_login_response_stage_2.html +31 -0
  37. data/test/fixtures/hotmail_contacts.html +262 -0
  38. data/test/fixtures/hotmail_login_response_stage_1.html +31 -0
  39. data/test/fixtures/hotmail_login_response_stage_2.html +1 -0
  40. data/test/fixtures/hotmail_login_response_stage_3.html +519 -0
  41. data/test/fixtures/hotmail_scrape_first_page.html +77 -0
  42. data/test/fixtures/hotmail_scrape_response_stage_1.html +90 -0
  43. data/test/fixtures/hotmail_scrape_response_stage_2.html +77 -0
  44. data/test/fixtures/hotmail_scrape_response_stage_3.html +0 -0
  45. data/test/fixtures/yahoo_bad_login_response_stage_2.html +443 -0
  46. data/test/fixtures/yahoo_contacts.csv +3 -0
  47. data/test/fixtures/yahoo_contacts_not_logged_in.html +432 -0
  48. data/test/fixtures/yahoo_contacts_stage_1.html +399 -0
  49. data/test/fixtures/yahoo_login_response_stage_1.html +433 -0
  50. data/test/fixtures/yahoo_login_response_stage_2.html +16 -0
  51. data/test/fixtures/yahoo_no_user_response_stage_2.html +574 -0
  52. data/test/freenet_importer_test.rb +53 -0
  53. data/test/gmx_importer_test.rb +53 -0
  54. data/test/scripts/live_test.rb +25 -0
  55. data/test/test_blackbook.rb +60 -0
  56. data/test/test_blackbook_exporter_base.rb +16 -0
  57. data/test/test_blackbook_exporter_vcf.rb +52 -0
  58. data/test/test_blackbook_exporter_xml.rb +16 -0
  59. data/test/test_blackbook_importer_aol.rb +108 -0
  60. data/test/test_blackbook_importer_base.rb +24 -0
  61. data/test/test_blackbook_importer_csv.rb +60 -0
  62. data/test/test_blackbook_importer_gmail.rb +116 -0
  63. data/test/test_blackbook_importer_hotmail.rb +165 -0
  64. data/test/test_blackbook_importer_page_scraper.rb +51 -0
  65. data/test/test_blackbook_importer_yahoo.rb +137 -0
  66. data/test/test_helper.rb +71 -0
  67. data/test/web.de_importer_test.rb +53 -0
  68. metadata +128 -0
data/CHANGES.markdown ADDED
@@ -0,0 +1,44 @@
1
+ == 1.0.5 / 2008-11-26
2
+
3
+ * moved to github
4
+ * added patch for gmail. emails were coming in with notes.
5
+ * added german stuff to blackbook gem
6
+
7
+ == 1.0.4 / 2008-02-27
8
+
9
+ * 1 minor enhancement
10
+ * fix 1.0.3 dud with AOL issues - Thank you Howard Wong!
11
+
12
+ == 1.0.3 / 2008-02-27
13
+
14
+ * 1 minor enhancement
15
+ * address the change in where AOL contacts are listed
16
+
17
+ == 1.0.2 / 2008-02-20
18
+
19
+ * 1 minor enhancement
20
+ * fixed sign on issue with GMail
21
+
22
+ == 1.0.1 / 2008-02-08
23
+
24
+ * 2 minor enhancement
25
+ * fix edge case sign on issue with GMail
26
+
27
+ == 1.0.0 / 2008-01-30
28
+
29
+ * 2 major enhancements
30
+ * Birthday!
31
+ * Mechanize patch for AOL sign-on! Thanks Mortee!
32
+
33
+ * Importers
34
+ * AOL
35
+ * GMail
36
+ * Hotmail
37
+ * Yahoo!
38
+ * CSV
39
+
40
+ * Exporters
41
+ * Hash
42
+ * XML
43
+ * VCard
44
+
data/Manifest.txt ADDED
@@ -0,0 +1,59 @@
1
+ CHANGES.markdown
2
+ Manifest.txt
3
+ README.markdown
4
+ Rakefile
5
+ debug_blackbook.rb
6
+ init.rb
7
+ lib/blackbook.rb
8
+ lib/blackbook/exporter/base.rb
9
+ lib/blackbook/exporter/vcf.rb
10
+ lib/blackbook/exporter/xml.rb
11
+ lib/blackbook/importer/aol.rb
12
+ lib/blackbook/importer/base.rb
13
+ lib/blackbook/importer/csv.rb
14
+ lib/blackbook/importer/gmail.rb
15
+ lib/blackbook/importer/hotmail.rb
16
+ lib/blackbook/importer/page_scraper.rb
17
+ lib/blackbook/importer/yahoo.rb
18
+ test/fixtures/aol_application_page.html
19
+ test/fixtures/aol_bad_login_response_stage_3.html
20
+ test/fixtures/aol_contacts.html
21
+ test/fixtures/aol_login_response_stage_1.html
22
+ test/fixtures/aol_login_response_stage_2.html
23
+ test/fixtures/aol_login_response_stage_3.html
24
+ test/fixtures/aol_login_response_stage_4.html
25
+ test/fixtures/aol_login_response_stage_5.html
26
+ test/fixtures/aol_new_contacts.html
27
+ test/fixtures/gmail.csv
28
+ test/fixtures/gmail_bad_login_response_stage_2.html
29
+ test/fixtures/gmail_contacts.html
30
+ test/fixtures/gmail_login_response_stage_1.html
31
+ test/fixtures/gmail_login_response_stage_2.html
32
+ test/fixtures/gmail_login_response_stage_2a.html
33
+ test/fixtures/gmail_login_response_stage_3.html
34
+ test/fixtures/hotmail_bad_login_response_stage_2.html
35
+ test/fixtures/hotmail_contacts.html
36
+ test/fixtures/hotmail_login_response_stage_1.html
37
+ test/fixtures/hotmail_login_response_stage_2.html
38
+ test/fixtures/hotmail_login_response_stage_3.html
39
+ test/fixtures/yahoo_bad_login_response_stage_2.html
40
+ test/fixtures/yahoo_contacts.csv
41
+ test/fixtures/yahoo_contacts_not_logged_in.html
42
+ test/fixtures/yahoo_contacts_stage_1.html
43
+ test/fixtures/yahoo_login_response_stage_1.html
44
+ test/fixtures/yahoo_login_response_stage_2.html
45
+ test/scripts/live_test.rb
46
+ test/test_blackbook.rb
47
+ test/test_blackbook_exporter_base.rb
48
+ test/test_blackbook_exporter_vcf.rb
49
+ test/test_blackbook_exporter_xml.rb
50
+ test/test_blackbook_importer_aol.rb
51
+ test/test_blackbook_importer_base.rb
52
+ test/test_blackbook_importer_csv.rb
53
+ test/test_blackbook_importer_gmail.rb
54
+ test/test_blackbook_importer_hotmail.rb
55
+ test/test_blackbook_importer_page_scraper.rb
56
+ test/test_blackbook_importer_yahoo.rb
57
+ test/test_helper.rb
58
+ vendor/plugins/blackbook/lib/autotest/blackbook.rb
59
+ vendor/plugins/blackbook/lib/autotest/discover.rb
data/README.markdown ADDED
@@ -0,0 +1,74 @@
1
+ Blackbook
2
+ http://github.com/cheald/blackbook/tree/master
3
+
4
+ == DESCRIPTION:
5
+
6
+ Blackbook automates the nitty-gritty of importing contacts from various services and files and exporting them as VCard, XML, or simple Hash. Utilize those contacts from services like AOL, GMail, Yahoo Mail, Hotmail or CSV to help your social networking site become GIGANTIC overnight! You'll be able to get big and sell for millions before anyone figures out it's just like every other social network.
7
+
8
+ == FEATURES/PROBLEMS:
9
+
10
+ The current list of supported services and file types:
11
+
12
+ Import:
13
+ * AOL
14
+ * CSV files
15
+ * Gmail
16
+ * Hotmail
17
+ * Yahoo! Mail
18
+ * Freenet
19
+ * GMX
20
+ * Web.de
21
+
22
+ Export:
23
+ * Simple hash (default)
24
+ * Vcard
25
+ * XML
26
+
27
+ If you create an additional importer or exporter - or simply find a bug - please consider submitting it as a patch to the project so the community can all benefit from your hard work and ingenuity.
28
+
29
+ == SYNOPSIS:
30
+
31
+ # An example of fetching Gmail contacts - by default, returns an array of hashes with :name and :email
32
+ contacts = Blackbook.get :username => 'me@gmail.com', :password => 'whatever'
33
+
34
+ # or returning XML
35
+ contacts = Blackbook.get :username => 'me@gmail.com', :password => 'whatever', :as => :xml
36
+
37
+ # or importing from a CSV file
38
+ contacts = Blackbook.get :csv, :file => #<File:/path/to/file.csv>
39
+
40
+ == REQUIREMENTS:
41
+
42
+ * Mechanize >= 0.9.2 and its dependencies, for interacting with online providers
43
+
44
+ == INSTALL:
45
+
46
+ 1. gem sources -a http://gems.github.com
47
+ 2. sudo gem install briancollins-blackbook
48
+
49
+ == THANKS:
50
+
51
+ Big thanks to Marton Fabo for figuring out why Mechanize couldn't log in to AOL.
52
+
53
+ == LICENSE:
54
+
55
+ Copyright (c) 2007, Contentfree
56
+
57
+ Permission is hereby granted, free of charge, to any person obtaining
58
+ a copy of this software and associated documentation files (the
59
+ 'Software'), to deal in the Software without restriction, including
60
+ without limitation the rights to use, copy, modify, merge, publish,
61
+ distribute, sublicense, and/or sell copies of the Software, and to
62
+ permit persons to whom the Software is furnished to do so, subject to
63
+ the following conditions:
64
+
65
+ The above copyright notice and this permission notice shall be
66
+ included in all copies or substantial portions of the Software.
67
+
68
+ THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
69
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
70
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
71
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
72
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
73
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
74
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/VERSION.yml ADDED
@@ -0,0 +1,4 @@
1
+ ---
2
+ :minor: 0
3
+ :patch: 14
4
+ :major: 1
data/lib/blackbook.rb ADDED
@@ -0,0 +1,83 @@
1
+ $:.unshift File.expand_path(File.join(File.dirname(__FILE__)))
2
+ require 'singleton'
3
+ require 'rubygems'
4
+
5
+ class Blackbook
6
+ include ::Singleton
7
+ VERSION = '1.0.5'
8
+
9
+ class BlackbookError < ::StandardError; end
10
+ class BadCredentialsError < BlackbookError; end
11
+ class LegacyAccount < BlackbookError; end
12
+
13
+ attr_accessor :importers
14
+ attr_accessor :exporters
15
+
16
+ def self.get( *args )
17
+ instance.get( *args )
18
+ end
19
+
20
+ def self.register(name, adapter_class)
21
+ case adapter = adapter_class.new
22
+ when Importer::Base
23
+ instance.importers[name.to_sym] = adapter
24
+ when Exporter::Base
25
+ instance.exporters[name.to_sym] = adapter
26
+ else
27
+ raise ArgumentError, "Unknown adapter"
28
+ end
29
+ end
30
+
31
+ # Sends the vcards from the import to whatever is handling the export
32
+ def export( importer, exporter, options )
33
+ exporter.export importer.import( options )
34
+ end
35
+
36
+ # Searches registered importers for one that will handle the given options
37
+ def find_importer( options )
38
+ importers.each{ |key, importer| return importer if importer =~ options }
39
+ nil
40
+ end
41
+
42
+ # Fetches contacts from various services or filetypes. The default is to return an array
43
+ # of hashes - Blackbook's internal format
44
+ #
45
+ # Handles several different calls:
46
+ # get( :username => 'something@gmail.com', :password => 'whatever' )
47
+ # get( :as => :xml, :username => 'something@gmail.com', :password => 'whatever' )
48
+ # get( :csv, :file => #<File:/path/to/file.csv> )
49
+ def get( *args )
50
+ options = args.last.is_a?(Hash) ? args.pop : {}
51
+ to_format = exporters[ options[:as] || :basic ]
52
+ source = (importers[args.first.to_sym] rescue nil) || find_importer(options)
53
+
54
+ raise ArgumentError, "Unknown exporter" unless to_format
55
+ raise ArgumentError, "Unknown source" unless source
56
+
57
+ export source, to_format, options
58
+ end
59
+
60
+ def initialize
61
+ self.importers = {}
62
+ self.exporters = {}
63
+ end
64
+ end
65
+
66
+ # Require all the importers/exporters
67
+ require 'blackbook/importer/base'
68
+ require 'blackbook/exporter/base'
69
+ Dir.glob(File.join(File.dirname(__FILE__), 'blackbook/importer/*.rb')).each {|f| require f }
70
+ Dir.glob(File.join(File.dirname(__FILE__), 'blackbook/exporter/*.rb')).each {|f| require f }
71
+
72
+ class NilClass
73
+ def empty?
74
+ true
75
+ end
76
+ end
77
+
78
+ class Object
79
+ def blank?
80
+ respond_to?(:empty?) ? empty? : !self
81
+ end
82
+ end
83
+
@@ -0,0 +1,16 @@
1
+ ##
2
+ # base class for exporters of contact information
3
+
4
+ module Blackbook::Exporter
5
+
6
+ class Base
7
+ ##
8
+ # Override this to convert +contacts+ (an array of hashes) to something more useful. Here, it
9
+ # just returns Blackbook's internal format
10
+ def export( contacts )
11
+ contacts
12
+ end
13
+
14
+ Blackbook.register :basic, self
15
+ end
16
+ end
@@ -0,0 +1,45 @@
1
+ ##
2
+ # exports contacts in Vcard format
3
+ class Blackbook::Exporter::Vcf < Blackbook::Exporter::Base
4
+
5
+ ##
6
+ # representation of a vcard
7
+
8
+ class Vcard
9
+
10
+ attr_accessor :first, :last, :email
11
+
12
+ ##
13
+ # initialize dynamically sets the attributes passed in as accessible
14
+ # attribute on its object
15
+
16
+ def initialize( attributes = {} )
17
+ attributes.each{ |name,value| self.send("#{name}=", value) rescue next }
18
+ end
19
+
20
+ ##
21
+ # text representation of this vcard
22
+ def to_s
23
+ <<-EOVC
24
+ BEGIN:VCARD
25
+ N:#{last};#{first}
26
+ EMAIL:#{email}
27
+ END:VCARD
28
+ EOVC
29
+ end
30
+ end
31
+
32
+ ##
33
+ # exports contacts as Vcards
34
+
35
+ def export( contacts = [] )
36
+ return if contacts.empty?
37
+
38
+ contacts.uniq.compact.collect do |contact|
39
+ first_name, last_name = contact[:name].split(' ', 2)
40
+ Vcard.new( :first => first_name.to_s, :last => last_name.to_s, :email => contact[:email])
41
+ end
42
+ end
43
+
44
+ Blackbook.register(:vcf, self)
45
+ end
@@ -0,0 +1,28 @@
1
+ require 'rexml/document'
2
+
3
+ ##
4
+ # exports contacts in xml format
5
+
6
+ class Blackbook::Exporter::Xml < Blackbook::Exporter::Base
7
+
8
+ ##
9
+ # contacts are an array of hashes that are contacts and returns xml
10
+
11
+ def export( contacts )
12
+ doc = REXML::Document.new
13
+ doc << REXML::XMLDecl.new
14
+
15
+ root = doc.add_element 'contacts'
16
+ contacts.each do |contact|
17
+ el = root.add_element 'contact'
18
+ name = el.add_element 'name'
19
+ name.text = contact[:name]
20
+
21
+ el.add_element('email').text = contact[:email]
22
+ end
23
+
24
+ doc.to_s
25
+ end
26
+
27
+ Blackbook.register(:xml, self)
28
+ end
@@ -0,0 +1,94 @@
1
+ require 'blackbook/importer/page_scraper'
2
+
3
+ ##
4
+ # Imports contacts from AOL
5
+
6
+ class Blackbook::Importer::Aol < Blackbook::Importer::PageScraper
7
+
8
+ ##
9
+ # Matches this importer to an user's name/address
10
+
11
+ def =~( options )
12
+ options && options[:username] =~ /@(aol|aim)\.com$/i ? true : false
13
+ end
14
+
15
+ ##
16
+ # Login process:
17
+ # - Get mail.aol.com which redirects to a page containing a javascript redirect
18
+ # - Get the URL that the javascript is supposed to redirect you to
19
+ # - Fill out and submit the login form
20
+ # - Get the URL from *another* javascript redirect
21
+
22
+ def login
23
+ page = agent.get( 'http://webmail.aol.com/' )
24
+
25
+ form = page.forms.find{|form| form.name == 'AOLLoginForm'}
26
+ form.loginId = options[:username].split('@').first # Drop the domain
27
+ form.password = options[:password]
28
+ page = agent.submit(form, form.buttons.first)
29
+
30
+ case page.body
31
+ when /Invalid Screen Name or Password. Please try again./
32
+ raise( Blackbook::BadCredentialsError, "That username and password was not accepted. Please check them and try again." )
33
+ when /Terms of Service/
34
+ raise( Blackbook::LegacyAccount, "Your AOL account is not setup for WebMail. Please signup: http://webmail.aol.com")
35
+ end
36
+
37
+ base_uri = page.body.scan(/^var gSuccessPath = \"(.+)\";/).first.first
38
+ raise( Blackbook::BadCredentialsError, "You do not appear to be signed in." ) unless base_uri
39
+ page = agent.get base_uri
40
+ end
41
+
42
+ ##
43
+ # must login to prepare
44
+
45
+ def prepare
46
+ login
47
+ end
48
+
49
+ ##
50
+ # The url to scrape contacts from has to be put together from the Auth cookie
51
+ # and a known uri that hosts their contact service. An array of hashes with
52
+ # :name and :email keys is returned.
53
+
54
+ def scrape_contacts
55
+ unless auth_cookie = agent.cookies.find{|c| c.name =~ /^Auth/}
56
+ raise( Blackbook::BadCredentialsError, "Must be authenticated to access contacts." )
57
+ end
58
+
59
+ # jump through the hoops of formulating a request to get printable contacts
60
+ uri = agent.current_page.uri.dup
61
+ inputs = agent.current_page.search("//input")
62
+ user = inputs.detect{|i| i['type'] == 'hidden' && i['name'] == 'user'}
63
+ utoken = user['value']
64
+
65
+ path = uri.path.split('/')
66
+ path.pop
67
+ path << 'addresslist-print.aspx'
68
+ uri.path = path.join('/')
69
+ uri.query = "command=all&sort=FirstLastNick&sortDir=Ascending&nameFormat=FirstLastNick&user=#{utoken}"
70
+ page = agent.get uri.to_s
71
+
72
+ # Grab all the contacts
73
+ rows = page.search("table tr")
74
+ name, email = nil, nil
75
+
76
+ results = []
77
+ rows.each do |row|
78
+ new_name = row.search("span[@class='fullName']").inner_text.strip
79
+ if name.blank? || !new_name.blank?
80
+ name = new_name
81
+ end
82
+ next if name.blank?
83
+
84
+ email = row.search("td[@class='sectionContent'] span:last").inner_text.strip
85
+ next if email.blank?
86
+
87
+ results << {:name => name, :email => email}
88
+ name, email = nil, nil
89
+ end
90
+ results
91
+ end
92
+
93
+ Blackbook.register :aol, self
94
+ end