rakutenusa-blackbook 1.0.12

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 +72 -0
  4. data/VERSION.yml +4 -0
  5. data/lib/blackbook/exporter/base.rb +16 -0
  6. data/lib/blackbook/exporter/vcf.rb +45 -0
  7. data/lib/blackbook/exporter/xml.rb +28 -0
  8. data/lib/blackbook/importer/aol.rb +89 -0
  9. data/lib/blackbook/importer/base.rb +39 -0
  10. data/lib/blackbook/importer/csv.rb +71 -0
  11. data/lib/blackbook/importer/freenet.rb +62 -0
  12. data/lib/blackbook/importer/gmail.rb +74 -0
  13. data/lib/blackbook/importer/gmx.rb +68 -0
  14. data/lib/blackbook/importer/hotmail.rb +128 -0
  15. data/lib/blackbook/importer/page_scraper.rb +86 -0
  16. data/lib/blackbook/importer/web.de.rb +67 -0
  17. data/lib/blackbook/importer/yahoo.rb +63 -0
  18. data/lib/blackbook.rb +82 -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 +127 -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,72 @@
1
+ Blackbook
2
+ http://github.com/purzelrakete/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
+
19
+ Export:
20
+ * Simple hash (default)
21
+ * Vcard
22
+ * XML
23
+
24
+ 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.
25
+
26
+ == SYNOPSIS:
27
+
28
+ # An example of fetching Gmail contacts - by default, returns an array of hashes with :name and :email
29
+ contacts = Blackbook.get :username => 'me@gmail.com', :password => 'whatever'
30
+
31
+ # or returning XML
32
+ contacts = Blackbook.get :username => 'me@gmail.com', :password => 'whatever', :as => :xml
33
+
34
+ # or importing from a CSV file
35
+ contacts = Blackbook.get :csv, :file => #<File:/path/to/file.csv>
36
+
37
+ == REQUIREMENTS:
38
+
39
+ * Mechanize and its dependencies, for interacting with online providers
40
+ * Fastercsv for reading CSV, Mechanize >= 0.7.0 for page scraping
41
+
42
+ == INSTALL:
43
+
44
+ 1. gem sources -a http://gems.github.com
45
+ 2. sudo gem install purzelrakete-blackbook
46
+
47
+ == THANKS:
48
+
49
+ Big thanks to Marton Fabo for figuring out why Mechanize couldn't log in to AOL.
50
+
51
+ == LICENSE:
52
+
53
+ Copyright (c) 2007, Contentfree
54
+
55
+ Permission is hereby granted, free of charge, to any person obtaining
56
+ a copy of this software and associated documentation files (the
57
+ 'Software'), to deal in the Software without restriction, including
58
+ without limitation the rights to use, copy, modify, merge, publish,
59
+ distribute, sublicense, and/or sell copies of the Software, and to
60
+ permit persons to whom the Software is furnished to do so, subject to
61
+ the following conditions:
62
+
63
+ The above copyright notice and this permission notice shall be
64
+ included in all copies or substantial portions of the Software.
65
+
66
+ THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
67
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
68
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
69
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
70
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
71
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
72
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/VERSION.yml ADDED
@@ -0,0 +1,4 @@
1
+ ---
2
+ :major: 1
3
+ :minor: 0
4
+ :patch: 12
@@ -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,89 @@
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
+ raise( Blackbook::BadCredentialsError, "That username and password was not accepted. Please check them and try again." ) if page.body =~ /Invalid Screen Name or Password. Please try again./
31
+
32
+ base_uri = page.body.scan(/^var gSuccessPath = \"(.+)\";/).first.first
33
+ raise( Blackbook::BadCredentialsError, "You do not appear to be signed in." ) unless base_uri
34
+ page = agent.get base_uri
35
+ end
36
+
37
+ ##
38
+ # must login to prepare
39
+
40
+ def prepare
41
+ login
42
+ end
43
+
44
+ ##
45
+ # The url to scrape contacts from has to be put together from the Auth cookie
46
+ # and a known uri that hosts their contact service. An array of hashes with
47
+ # :name and :email keys is returned.
48
+
49
+ def scrape_contacts
50
+ unless auth_cookie = agent.cookies.find{|c| c.name =~ /^Auth/}
51
+ raise( Blackbook::BadCredentialsError, "Must be authenticated to access contacts." )
52
+ end
53
+
54
+ # jump through the hoops of formulating a request to get printable contacts
55
+ uri = agent.current_page.uri.dup
56
+ inputs = agent.current_page.search("//input")
57
+ user = inputs.detect{|i| i['type'] == 'hidden' && i['name'] == 'user'}
58
+ utoken = user['value']
59
+
60
+ path = uri.path.split('/')
61
+ path.pop
62
+ path << 'addresslist-print.aspx'
63
+ uri.path = path.join('/')
64
+ uri.query = "command=all&sort=FirstLastNick&sortDir=Ascending&nameFormat=FirstLastNick&user=#{utoken}"
65
+ page = agent.get uri.to_s
66
+
67
+ # Grab all the contacts
68
+ rows = page.search("table tr")
69
+ name, email = nil, nil
70
+
71
+ results = []
72
+ rows.each do |row|
73
+ new_name = row.search("span[@class='fullName']").inner_text.strip
74
+ if name.blank? || !new_name.blank?
75
+ name = new_name
76
+ end
77
+ next if name.blank?
78
+
79
+ email = row.search("td[@class='sectionContent'] span:last").inner_text.strip
80
+ next if email.blank?
81
+
82
+ results << {:name => name, :email => email}
83
+ name, email = nil, nil
84
+ end
85
+ results
86
+ end
87
+
88
+ Blackbook.register :aol, self
89
+ end
@@ -0,0 +1,39 @@
1
+ #
2
+ # Provides a base template for interface and behavior of contact importers
3
+
4
+ module Blackbook::Importer
5
+ class Base
6
+ attr_accessor :options
7
+
8
+ ##
9
+ # Should return true or false/nil depending on whether the +options+ given
10
+ # can be handled by this importer
11
+
12
+ def =~( options ); end # stub
13
+
14
+ ##
15
+ # Does the work of extracting contacts. Returns an Array of Arrays
16
+ # containing the name and email as the first and second elements. Of
17
+ # course, you can override this behavior to meet the needs of a
18
+ # particular service.
19
+
20
+ def fetch_contacts!; end # stub
21
+
22
+ ##
23
+ # Imports the contacts using the given +options+. Returns an array of
24
+ # hashes in the internal format (a hash with at least :name and :email
25
+ # values).
26
+
27
+ def import(options = {})
28
+ self.options = options
29
+ fetch_contacts!
30
+ end
31
+
32
+ ##
33
+ # Name of the importer service.
34
+
35
+ def service_name
36
+ self.class.name.split("::").last
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,71 @@
1
+ require 'fastercsv'
2
+ require 'ruby-debug'
3
+
4
+ ##
5
+ # Imports contacts from a CSV file
6
+
7
+ class Blackbook::Importer::Csv < Blackbook::Importer::Base
8
+
9
+ DEFAULT_COLUMNS = [:name,:email,:misc]
10
+ DEFAULT_PATTERN = /,/
11
+
12
+ ##
13
+ # Matches this importer to a file that contains CSV values
14
+
15
+ def =~(options)
16
+ options && options[:file].respond_to?(:open) ? true : false
17
+ end
18
+
19
+ ##
20
+ # fetch_contacts! implementation for this importer
21
+
22
+ def fetch_contacts!
23
+ lines = IO.readlines(options[:file].path)
24
+ columns = to_columns(lines.first)
25
+ lines.shift if columns.first == :name
26
+ columns = DEFAULT_COLUMNS.dup unless columns.first == :name
27
+
28
+ contacts = Array.new
29
+ lines.each do |l|
30
+ vals = l.split(pattern)
31
+ next if vals.empty?
32
+ contacts << to_hash(columns, vals)
33
+ end
34
+
35
+ contacts
36
+ end
37
+
38
+ def to_hash(cols, vals) # :nodoc:
39
+ h = Hash.new
40
+ cols.each do |c|
41
+ h[c] = (c == cols.last) ? vals.join(',') : vals.shift
42
+ end
43
+ h
44
+ end
45
+
46
+ def to_columns(line) # :nodoc:
47
+ columns = Array.new
48
+ if line.match(pattern)
49
+ tags = line.split(pattern)
50
+ else
51
+ tags = line.split(DEFAULT_PATTERN)
52
+ end
53
+ # deal with "Name,E-mail..." oddity up front
54
+ if tags.first =~ /^name$/i
55
+ tags.shift
56
+ columns << :name
57
+ if tags.first =~ /^e.?mail/i # E-mail or Email
58
+ tags.shift
59
+ columns << :email
60
+ end
61
+ end
62
+ tags.each{|v| columns << v.strip.to_sym}
63
+ columns
64
+ end
65
+
66
+ def pattern
67
+ @pattern ||= (options[:pattern] || DEFAULT_PATTERN) rescue DEFAULT_PATTERN
68
+ end
69
+
70
+ Blackbook.register(:csv, self)
71
+ end
@@ -0,0 +1,62 @@
1
+ require 'blackbook/importer/page_scraper'
2
+
3
+ class Blackbook::Importer::Freenet < Blackbook::Importer::PageScraper
4
+ LOGIN_URL = "https://office.freenet.de"
5
+ MESSAGES_URL = "/main_overview.html"
6
+
7
+ def =~( options )
8
+ options && options[:username] =~ /@freenet\.de$/i
9
+ end
10
+
11
+ def login
12
+ username, password = options[:username], options[:password]
13
+
14
+ begin
15
+ page = agent.get LOGIN_URL
16
+
17
+ form = page.forms.with.name("loginform").first
18
+ form.username = username.split("@").first
19
+ form.password = password
20
+ page = form.submit
21
+
22
+ if page.body.match(/Fehlgeschlagene Login-Versuche/)
23
+ page = page.forms.with.name("sicherform").submit
24
+ page = agent.get MESSAGES_URL
25
+ end
26
+
27
+ if page.body.match(/Login (erneut )?fehlgeschlagen/) || page.body.match(/Ich bin bereits Mitglied/)
28
+ raise Blackbook::BadCredentialsError.new
29
+ end
30
+ rescue => e
31
+ raise e || Blackbook::BlackbookError.new
32
+ end
33
+ end
34
+
35
+ def prepare
36
+ login
37
+ end
38
+
39
+ def scrape_contacts
40
+ contacts = ["INBOX", "INBOX.sent"].map do |folder|
41
+ page = agent.get "/messages/mail_mailbox.html?mail_folder=#{folder}"
42
+ find_contacts(page)
43
+ end
44
+
45
+ contacts.inject([]) do |memo, contact|
46
+ memo << contact unless memo.include? contact
47
+ memo
48
+ end.flatten
49
+ end
50
+
51
+
52
+ protected
53
+ def find_contacts(page)
54
+ page.search("tr[@id]/td[9]").map do |cell|
55
+ recp, fullname, email = *cell.attributes["title"].match(/"(.*)"<(.*)>/)
56
+
57
+ { :name => fullname, :email => email }
58
+ end
59
+ end
60
+
61
+ Blackbook.register :freenet, self
62
+ end
@@ -0,0 +1,74 @@
1
+ require 'blackbook/importer/page_scraper'
2
+
3
+ ##
4
+ # Imports contacts from GMail
5
+
6
+ class Blackbook::Importer::Gmail < Blackbook::Importer::PageScraper
7
+
8
+ RETRY_THRESHOLD = 5
9
+ ##
10
+ # Matches this importer to an user's name/address
11
+
12
+ def =~(options = {})
13
+ options && options[:username] =~ /@(gmail|googlemail).com$/i ? true : false
14
+ end
15
+
16
+ ##
17
+ # login to gmail
18
+
19
+ def login
20
+ page = agent.get('http://mail.google.com/mail/')
21
+ form = page.forms.first
22
+ form.Email = options[:username]
23
+ form.Passwd = options[:password]
24
+ page = agent.submit(form,form.buttons.first)
25
+
26
+ raise( Blackbook::BadCredentialsError, "That username and password was not accepted. Please check them and try again." ) if page.body =~ /Username and password do not match/
27
+
28
+ if page.search('//meta').first.attributes['content'] =~ /url='?(http.+?)'?$/i
29
+ page = agent.get $1
30
+ end
31
+ end
32
+
33
+ ##
34
+ # prepare this importer
35
+
36
+ def prepare
37
+ login
38
+ end
39
+
40
+ ##
41
+ # scrape gmail contacts for this importer
42
+
43
+ def scrape_contacts
44
+ unless agent.cookies.find{|c| c.name == 'GAUSR' &&
45
+ (c.value.include? "mail:#{options[:username]}")}
46
+ raise( Blackbook::BadCredentialsError, "Must be authenticated to access contacts." )
47
+ end
48
+
49
+ page = agent.get('http://mail.google.com/mail/h/?v=cl&pnl=a')
50
+ title = page.search("//title").inner_text
51
+ if title == 'Redirecting'
52
+ redirect_text = page.search('//meta').first.attributes['content'].inner_text
53
+ url = redirect_text.match(/url='(http.*)'/i)[1]
54
+ page = agent.get(url)
55
+ end
56
+
57
+ contact_rows = page.search("//input[@name='c']/../..")
58
+ contact_rows.collect do |row|
59
+ columns = row/"td"
60
+ email = columns[2].inner_html.gsub( /(\n|&nbsp;)/, '' ) # email
61
+ clean_email = email[/[a-zA-Z0-9._%+-]+@(?:[a-zA-Z0-9-]+\.)+[a-zA-Z]{2,4}/]
62
+
63
+ unless clean_email.empty?
64
+ columns = row/"td"
65
+ {
66
+ :name => ( columns[1] / "b" ).inner_text, # name
67
+ :email => clean_email
68
+ }
69
+ end
70
+ end.compact
71
+ end
72
+
73
+ Blackbook.register(:gmail, self)
74
+ end
@@ -0,0 +1,68 @@
1
+ require 'blackbook/importer/page_scraper'
2
+
3
+ class Blackbook::Importer::GMX < Blackbook::Importer::PageScraper
4
+ LOGIN_URL = "https://www.gmx.net/"
5
+
6
+ def =~( options )
7
+ options && options[:username] =~ /@gmx\.(de|net)$/i
8
+ end
9
+
10
+ def login
11
+ username, password = options[:username], options[:password]
12
+
13
+ begin
14
+ page = agent.get LOGIN_URL
15
+
16
+ form = page.forms.with.name("login").first
17
+ form.id = username
18
+ form.p = password
19
+ page = form.submit
20
+ @next = page
21
+
22
+ if (page.at("div.index") && page.at("div.index").inner_html == "Passwort vergessen?") ||
23
+ page.uri.to_s.match(/login-failed/)
24
+ raise Blackbook::BadCredentialsError.new
25
+ end
26
+ rescue => e
27
+ raise e || Blackbook::BlackbookError.new
28
+ end
29
+ end
30
+
31
+ def prepare
32
+ login
33
+ end
34
+
35
+ def scrape_contacts
36
+ page = @next
37
+
38
+ # Go to E-Mails
39
+ page = page.links.select { |link| link.text =~ /E-Mail/ }.first.click
40
+
41
+ contacts = [/Posteingang/, /Archiv/, /Gesendet/].map do |folder|
42
+ # puts "folder: #{folder}"
43
+ # puts "page title: #{page.title}"
44
+ # puts "page links: #{page.links.select { |link| link.text =~ folder }}"
45
+ page = page.links.select { |link| link.text =~ folder }.first.click
46
+ find_contacts(page)
47
+ end
48
+
49
+ contacts.inject([]) do |memo, contact|
50
+ memo << contact unless memo.include? contact
51
+ memo
52
+ end.flatten
53
+ end
54
+
55
+ protected
56
+
57
+ def find_contacts(page)
58
+ links = page.search("form#MI a").select { |link| link.attributes["title"] =~ /@/ }
59
+ links.map do |link|
60
+ recp = link.attributes["title"].gsub(/\n/, "").split(/\s/)
61
+ email = recp.pop.gsub(/[<>]/, "")
62
+ fullname = recp.join(" ")
63
+
64
+ { :name => fullname, :email => email }
65
+ end
66
+ end
67
+ Blackbook.register :gmx, self
68
+ end