ampersat 0.0.1 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 6232057d580f3bbeb66de8d6149fbd19f1d70c67
4
+ data.tar.gz: 2d3ab791c9798b8b7326f0c20f44bf19c949b052
5
+ SHA512:
6
+ metadata.gz: 93eddae22b005d6f6b6b56b271cec43d81071f68fdc62d4ad886c65c69b79e4c107cfc290d43e830c8bd2b0ab77955e3c9a5a8c7d70e77e33b7bf03eccdb3574
7
+ data.tar.gz: 8c74fd344c52e67a5523d17dd0a35762ca421b107e74946c2bef50d7eb55cb5fe898c67b1785c34de1458ce232171dc4f8142207673010ff59578d718ec97331
@@ -0,0 +1,5 @@
1
+ language: ruby
2
+ rvm:
3
+ - 2.0.0
4
+ - 2.1.0
5
+ - 1.9.3
data/Gemfile CHANGED
@@ -1,4 +1,4 @@
1
- source "http://rubygems.org"
1
+ source 'http://rubygems.org'
2
2
 
3
3
  # Specify your gem's dependencies in ampersat.gemspec
4
4
  gemspec
data/README.md CHANGED
@@ -1,5 +1,7 @@
1
1
  # Calculate Most Common Domains From Email List
2
2
 
3
+ [![Build Status](https://secure.travis-ci.org/garethrees/ampersat.png)](http://travis-ci.org/garethrees/ampersat) [![Code Climate](https://codeclimate.com/github/garethrees/ampersat.png)](https://codeclimate.com/github/garethrees/ampersat)
4
+
3
5
  It's worth checking what email clients your subscribers are using so that you can make sure your emails look good when they view them.
4
6
 
5
7
  This gem looks at your subscribers CSV and lists the domains in order of popularity*.
@@ -10,24 +12,37 @@ This gem looks at your subscribers CSV and lists the domains in order of popular
10
12
 
11
13
  ### Install
12
14
 
13
- gem install ampersat
15
+ `gem install ampersat`
16
+
17
+ ### As CLI
18
+
19
+ ```shell
20
+ $ ampersat domains --file=~/test.csv
21
+ example.com: 2
22
+ example.org: 1
23
+ example.net: 1
24
+ ```
14
25
 
15
26
  ### In irb
16
27
 
17
- $ irb
18
- > require 'ampersat'
19
- => true
20
- > Ampersat.domains("/path/to/csv")
21
- => [["example.com", 2], ["example.org", 1], ["example.net", 1]]
28
+ ```ruby
29
+ $ irb
30
+ > require 'ampersat'
31
+ => true
32
+ > Ampersat.domains('/path/to/csv')
33
+ => [['example.com', 2], ['example.org', 1], ['example.net', 1]]
34
+ ```
22
35
 
23
36
  ### In Your App
24
37
 
25
- domains = Ampersat.domains("/Users/gareth/test.csv")
38
+ ```ruby
39
+ domains = Ampersat.domains('/Users/gareth/test.csv')
26
40
 
27
- domains.each do |domain, count|
28
- puts "#{domain}: #{count}"
29
- end
41
+ domains.each do |domain, count|
42
+ puts "#{domain}: #{count}"
43
+ end
30
44
 
31
- # example.com: 2
32
- # example.org: 1
33
- # example.net: 1
45
+ # example.com: 2
46
+ # example.org: 1
47
+ # example.net: 1
48
+ ```
data/Rakefile CHANGED
@@ -1,5 +1,7 @@
1
1
  require 'bundler/gem_tasks'
2
2
 
3
+ task :default => [:test]
4
+
3
5
  task :test do
4
6
  exec('rspec spec/.')
5
7
  end
@@ -1,24 +1,29 @@
1
1
  # -*- encoding: utf-8 -*-
2
- $:.push File.expand_path("../lib", __FILE__)
3
- require "ampersat/version"
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'ampersat/version'
4
5
 
5
6
  Gem::Specification.new do |s|
6
- s.name = "ampersat"
7
+ s.name = 'ampersat'
7
8
  s.version = Ampersat::VERSION
8
- s.authors = ["Gareth Rees"]
9
- s.email = ["gareth.h.rees@gmail.com"]
10
- s.homepage = "http://github.com/garethrees/ampersat"
11
- s.summary = "Calculates which email domains your subscribers use"
12
- s.description = "Calculates which email domains your subscribers use"
9
+ s.authors = ['Gareth Rees', 'Robert Coleman']
10
+ s.email = ['gareth.h.rees@gmail.com', 'github@robert.net.nz']
11
+ s.homepage = 'http://github.com/garethrees/ampersat'
12
+ s.summary = 'Calculates which email domains your subscribers use'
13
+ s.description = 'Calculates which email domains your subscribers use'
13
14
 
14
15
  s.rubyforge_project = "ampersat"
15
16
 
16
17
  s.files = `git ls-files`.split("\n")
17
18
  s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
18
19
  s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
19
- s.require_paths = ["lib"]
20
+ s.require_paths = ['lib']
20
21
 
21
22
  s.add_development_dependency 'rake'
22
- s.add_development_dependency "rspec", "~> 2.7"
23
-
23
+ s.add_development_dependency 'rspec', '~> 2.7'
24
+ s.add_dependency 'thor', '~> 0.19.1'
25
+ s.add_dependency 'public_suffix', '~> 1.4.4'
26
+ s.add_dependency 'ruby-progressbar', '~> 1.5.1'
27
+ s.add_dependency 'celluloid', '0.15.2'
28
+ s.add_dependency 'celluloid-pmap', '~> 0.1.0'
24
29
  end
@@ -0,0 +1,12 @@
1
+ #!/usr/bin/env ruby
2
+ require 'pathname'
3
+ bin_file = Pathname.new(__FILE__).realpath
4
+ $:.unshift File.expand_path('../../lib', bin_file)
5
+
6
+ Signal.trap('INT') do
7
+ puts "\nSIGINT recieved.. terminated."
8
+ exit 1
9
+ end
10
+
11
+ require 'ampersat/cli'
12
+ Ampersat::CLI.start
@@ -1,21 +1,53 @@
1
- require "ampersat/version"
2
- require "csv"
1
+ require 'csv'
2
+ require 'public_suffix'
3
+ require 'ruby-progressbar'
4
+ require 'resolv'
5
+ require 'celluloid/pmap'
3
6
 
4
7
  module Ampersat
5
8
 
6
- def self.domains(email_list)
9
+ def self.domains(email_list, column=0)
7
10
  domains = Hash.new(0)
8
-
11
+
9
12
  CSV.foreach(email_list) do |row|
10
- domain = Ampersat.find_domain(row.first)
11
- domains[domain] = domains[domain] +1
13
+ domain = Ampersat.find_domain(row[column])
14
+ domains[domain] = domains[domain] + 1
15
+ end
16
+
17
+ domains.sort_by {|key, value| - value}
18
+ end
19
+
20
+ def self.mxs(email_list, column=0)
21
+ mxs = {}
22
+ domains = Ampersat.domains(email_list, column)
23
+ progressbar = ProgressBar.create(format: '%t: %c / %C |%B|', starting_at: 0, total: domains.length)
24
+ domains.pmap(100) do |domain, qty|
25
+ mx = Ampersat.find_mx(domain)
26
+ mxs[mx] ||= {}
27
+ mxs[mx]['domains'] ||= []
28
+ mxs[mx]['domains'] << domain
29
+ mxs[mx]['addresses'] ||= 0
30
+ mxs[mx]['addresses'] = mxs[mx]['addresses'] + qty
31
+ progressbar.increment
12
32
  end
13
33
 
14
- domains.sort_by {|key, value| -value}
34
+ mxs.sort_by {|key, value| - value['addresses'] }
15
35
  end
16
36
 
17
37
  def self.find_domain(email)
18
- email.split('@').last
38
+ email.split('@').last.downcase
39
+ end
40
+
41
+ def self.find_mx(domain)
42
+ @mxs ||= {}
43
+ @mxs[domain] ||= begin
44
+ Resolv::DNS.open(nameserver: '8.8.8.8') do |dns|
45
+ next unless PublicSuffix.valid?(domain)
46
+ response = dns.getresources(domain, Resolv::DNS::Resource::IN::MX)
47
+ next unless response.any?
48
+ response.collect { |r| r.exchange.to_s.downcase }.sort.first
49
+ end
50
+ end
19
51
  end
20
52
 
21
53
  end
@@ -0,0 +1,30 @@
1
+ require 'thor'
2
+ require 'ampersat'
3
+
4
+ module Ampersat
5
+ class CLI < Thor
6
+
7
+ default_task :help
8
+
9
+ desc 'domains </path/to/file.csv>', 'Analyse a CSV, returning domain list'
10
+ method_option :column, type: :numeric, default: 0
11
+ method_option :file, required: true, type: :string
12
+ def domains
13
+ domains = Ampersat.domains(File.expand_path(options[:file]), options[:column])
14
+ domains.each do |domain, count|
15
+ puts "#{ domain }: #{ count }"
16
+ end
17
+ end
18
+
19
+ desc 'mx </path/to/file.csv>', 'Analyse a CSV, returning MX list'
20
+ method_option :column, type: :numeric, default: 0
21
+ method_option :file, required: true, type: :string
22
+ def mx
23
+ mxs = Ampersat.mxs(File.expand_path(options[:file]), options[:column])
24
+ mxs.each do |mx, value|
25
+ puts "#{ mx } - #{ value['addresses'] }: #{ value['domains'].join(', ') }"
26
+ end
27
+ end
28
+
29
+ end
30
+ end
@@ -1,3 +1,3 @@
1
1
  module Ampersat
2
- VERSION = "0.0.1"
2
+ VERSION = '1.0.0'
3
3
  end
@@ -1,30 +1,49 @@
1
1
  # encoding: utf-8
2
- path = File.expand_path(File.dirname(__FILE__) + "/../lib/")
2
+ path = File.expand_path(File.dirname(__FILE__) + '/../lib/')
3
3
  $LOAD_PATH.unshift(path) unless $LOAD_PATH.include?(path)
4
- require "ampersat"
5
-
4
+ require 'ampersat'
6
5
 
7
6
  describe Ampersat do
8
7
 
9
- let(:csv_path) { File.expand_path(File.dirname(__FILE__) + "/support/test.csv") }
10
- let(:email) { "test@example.com" }
11
- let(:multiple_emails) { "jim@example.com, tom@example.com, bob@example.org, james@example.net" }
8
+ let(:csv_path) { File.expand_path(File.dirname(__FILE__) + '/support/test.csv') }
9
+ let(:email) { 'test@example.com' }
10
+ let(:multiple_emails) { 'jim@example.com, tom@example.com, bob@example.org, james@example.net' }
12
11
 
13
- it "should return the sum of each email provider" do
14
- expected_result = [["example.com", 2], ["example.org", 1], ["example.net", 1]]
12
+ it 'should return the sum of each email provider' do
13
+ expected_result = [['example.com', 3], ['example.org', 2], ['example.net', 1]]
15
14
  Ampersat.domains(csv_path).should == expected_result
16
15
  end
17
16
 
18
- it "should return the email providers with the most common first" do
19
- incorrect_result = [["example.org", 1],["example.com", 2], ["example.net", 1]]
17
+ it 'should return the email providers with the most common first' do
18
+ incorrect_result = [['example.org', 2],['example.com', 3], ['example.net', 1]]
20
19
  Ampersat.domains(csv_path).should_not == incorrect_result
21
20
 
22
- expected_result = [["example.com", 2], ["example.org", 1], ["example.net", 1]]
21
+ expected_result = [['example.com', 3], ['example.org', 2], ['example.net', 1]]
23
22
  Ampersat.domains(csv_path).should == expected_result
24
23
  end
25
24
 
26
- it "should find the domain of an email address" do
27
- Ampersat.find_domain(email).should == "example.com"
25
+ it 'should find the domain of an email address' do
26
+ Ampersat.find_domain(email).should == 'example.com'
27
+ end
28
+
29
+ describe 'column' do
30
+ let(:csv_path) { File.expand_path(File.dirname(__FILE__) + '/support/multiple-columns.csv') }
31
+ let(:email) { 'test@example.com' }
32
+ let(:multiple_emails) { 'jim@example.com, tom@example.com, bob@example.org, james@example.net' }
33
+ let(:column) { 1 }
34
+
35
+ it 'should return the sum of each email provider' do
36
+ expected_result = [['example.com', 3], ['example.org', 2], ['example.net', 1]]
37
+ Ampersat.domains(csv_path, column).should == expected_result
38
+ end
39
+
40
+ it 'should return the email providers with the most common first' do
41
+ incorrect_result = [['example.org', 2],['example.com', 3], ['example.net', 1]]
42
+ Ampersat.domains(csv_path, column).should_not == incorrect_result
43
+
44
+ expected_result = [['example.com', 3], ['example.org', 2], ['example.net', 1]]
45
+ Ampersat.domains(csv_path, column).should == expected_result
46
+ end
28
47
  end
29
48
 
30
- end
49
+ end
@@ -0,0 +1,6 @@
1
+ foo,tim@example.com,
2
+ bar,tom@example.com,
3
+ foo,ted@example.com,
4
+ foo,bob@example.org,
5
+ foo,bill@example.org,
6
+ foo,jim@example.net
@@ -1,4 +1,6 @@
1
- jim@example.com,
1
+ tim@example.com,
2
2
  tom@example.com,
3
+ ted@example.com,
3
4
  bob@example.org,
4
- james@example.net
5
+ bill@example.org,
6
+ jim@example.net
metadata CHANGED
@@ -1,79 +1,161 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ampersat
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
5
- prerelease:
4
+ version: 1.0.0
6
5
  platform: ruby
7
6
  authors:
8
7
  - Gareth Rees
8
+ - Robert Coleman
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2011-11-30 00:00:00.000000000Z
12
+ date: 2014-07-22 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rake
16
- requirement: &5275780 !ruby/object:Gem::Requirement
17
- none: false
16
+ requirement: !ruby/object:Gem::Requirement
18
17
  requirements:
19
- - - ! '>='
18
+ - - ">="
20
19
  - !ruby/object:Gem::Version
21
20
  version: '0'
22
21
  type: :development
23
22
  prerelease: false
24
- version_requirements: *5275780
23
+ version_requirements: !ruby/object:Gem::Requirement
24
+ requirements:
25
+ - - ">="
26
+ - !ruby/object:Gem::Version
27
+ version: '0'
25
28
  - !ruby/object:Gem::Dependency
26
29
  name: rspec
27
- requirement: &5275490 !ruby/object:Gem::Requirement
28
- none: false
30
+ requirement: !ruby/object:Gem::Requirement
29
31
  requirements:
30
- - - ~>
32
+ - - "~>"
31
33
  - !ruby/object:Gem::Version
32
34
  version: '2.7'
33
35
  type: :development
34
36
  prerelease: false
35
- version_requirements: *5275490
37
+ version_requirements: !ruby/object:Gem::Requirement
38
+ requirements:
39
+ - - "~>"
40
+ - !ruby/object:Gem::Version
41
+ version: '2.7'
42
+ - !ruby/object:Gem::Dependency
43
+ name: thor
44
+ requirement: !ruby/object:Gem::Requirement
45
+ requirements:
46
+ - - "~>"
47
+ - !ruby/object:Gem::Version
48
+ version: 0.19.1
49
+ type: :runtime
50
+ prerelease: false
51
+ version_requirements: !ruby/object:Gem::Requirement
52
+ requirements:
53
+ - - "~>"
54
+ - !ruby/object:Gem::Version
55
+ version: 0.19.1
56
+ - !ruby/object:Gem::Dependency
57
+ name: public_suffix
58
+ requirement: !ruby/object:Gem::Requirement
59
+ requirements:
60
+ - - "~>"
61
+ - !ruby/object:Gem::Version
62
+ version: 1.4.4
63
+ type: :runtime
64
+ prerelease: false
65
+ version_requirements: !ruby/object:Gem::Requirement
66
+ requirements:
67
+ - - "~>"
68
+ - !ruby/object:Gem::Version
69
+ version: 1.4.4
70
+ - !ruby/object:Gem::Dependency
71
+ name: ruby-progressbar
72
+ requirement: !ruby/object:Gem::Requirement
73
+ requirements:
74
+ - - "~>"
75
+ - !ruby/object:Gem::Version
76
+ version: 1.5.1
77
+ type: :runtime
78
+ prerelease: false
79
+ version_requirements: !ruby/object:Gem::Requirement
80
+ requirements:
81
+ - - "~>"
82
+ - !ruby/object:Gem::Version
83
+ version: 1.5.1
84
+ - !ruby/object:Gem::Dependency
85
+ name: celluloid
86
+ requirement: !ruby/object:Gem::Requirement
87
+ requirements:
88
+ - - '='
89
+ - !ruby/object:Gem::Version
90
+ version: 0.15.2
91
+ type: :runtime
92
+ prerelease: false
93
+ version_requirements: !ruby/object:Gem::Requirement
94
+ requirements:
95
+ - - '='
96
+ - !ruby/object:Gem::Version
97
+ version: 0.15.2
98
+ - !ruby/object:Gem::Dependency
99
+ name: celluloid-pmap
100
+ requirement: !ruby/object:Gem::Requirement
101
+ requirements:
102
+ - - "~>"
103
+ - !ruby/object:Gem::Version
104
+ version: 0.1.0
105
+ type: :runtime
106
+ prerelease: false
107
+ version_requirements: !ruby/object:Gem::Requirement
108
+ requirements:
109
+ - - "~>"
110
+ - !ruby/object:Gem::Version
111
+ version: 0.1.0
36
112
  description: Calculates which email domains your subscribers use
37
113
  email:
38
114
  - gareth.h.rees@gmail.com
39
- executables: []
115
+ - github@robert.net.nz
116
+ executables:
117
+ - ampersat
40
118
  extensions: []
41
119
  extra_rdoc_files: []
42
120
  files:
43
- - .gitignore
44
- - .rspec
121
+ - ".gitignore"
122
+ - ".rspec"
123
+ - ".travis.yml"
45
124
  - Gemfile
46
125
  - README.md
47
126
  - Rakefile
48
127
  - ampersat.gemspec
128
+ - bin/ampersat
49
129
  - lib/ampersat.rb
130
+ - lib/ampersat/cli.rb
50
131
  - lib/ampersat/version.rb
51
132
  - spec/ampersat_spec.rb
133
+ - spec/support/multiple-columns.csv
52
134
  - spec/support/test.csv
53
135
  homepage: http://github.com/garethrees/ampersat
54
136
  licenses: []
137
+ metadata: {}
55
138
  post_install_message:
56
139
  rdoc_options: []
57
140
  require_paths:
58
141
  - lib
59
142
  required_ruby_version: !ruby/object:Gem::Requirement
60
- none: false
61
143
  requirements:
62
- - - ! '>='
144
+ - - ">="
63
145
  - !ruby/object:Gem::Version
64
146
  version: '0'
65
147
  required_rubygems_version: !ruby/object:Gem::Requirement
66
- none: false
67
148
  requirements:
68
- - - ! '>='
149
+ - - ">="
69
150
  - !ruby/object:Gem::Version
70
151
  version: '0'
71
152
  requirements: []
72
153
  rubyforge_project: ampersat
73
- rubygems_version: 1.8.11
154
+ rubygems_version: 2.2.0
74
155
  signing_key:
75
- specification_version: 3
156
+ specification_version: 4
76
157
  summary: Calculates which email domains your subscribers use
77
158
  test_files:
78
159
  - spec/ampersat_spec.rb
160
+ - spec/support/multiple-columns.csv
79
161
  - spec/support/test.csv