gman 4.0.0 → 4.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/{lib → config}/domains.txt +0 -0
- data/lib/gman.rb +5 -194
- data/lib/gman/country_codes.rb +40 -0
- data/lib/gman/locality.rb +28 -0
- metadata +24 -26
- data/CONTRIBUTING.md +0 -22
- data/Gemfile +0 -6
- data/README.md +0 -68
- data/lib/gman/version.rb +0 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 581df932b6e1afe6a5ed61c5116abee789b3da65
|
4
|
+
data.tar.gz: b7bb194063df9af7d3b3a3d83b287c94d9076170
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 59cefe32f4435eb85a7d8621206314328bd9804c9a63eeef6bcf68125ae6bcd4f5ed1fc237b1925d9e198ee1ae4332a3f0d381d91761bb6a438cdf5e781f6e56
|
7
|
+
data.tar.gz: 899fe3d0dc4c9d5cfd75ab55bf64e08220cdf112140e9cb573c0009517ef3e6689a31fe5587b9209e7d26538cab88d946e58b183ec0de0495384cbebf13a3977
|
data/{lib → config}/domains.txt
RENAMED
File without changes
|
data/lib/gman.rb
CHANGED
@@ -1,114 +1,11 @@
|
|
1
|
-
require '
|
2
|
-
require 'yaml'
|
1
|
+
require 'naughty_or_nice'
|
3
2
|
require 'swot'
|
4
|
-
require "addressable/uri"
|
5
3
|
require 'iso_country_codes'
|
6
|
-
require_relative
|
7
|
-
|
8
|
-
class Gman
|
9
|
-
|
10
|
-
# Source: http://bit.ly/1n2X9iv
|
11
|
-
EMAIL_REGEX = %r{
|
12
|
-
^
|
13
|
-
(
|
14
|
-
[\w\!\#\$\%\&\'\*\+\-\/\=\?\^\`\{\|\}\~]+
|
15
|
-
\.
|
16
|
-
)
|
17
|
-
*
|
18
|
-
[\w\!\#\$\%\&\'\*\+\-\/\=\?\^\`\{\|\}\~]+
|
19
|
-
@
|
20
|
-
(
|
21
|
-
(
|
22
|
-
(
|
23
|
-
(
|
24
|
-
(
|
25
|
-
[a-z0-9]{1}
|
26
|
-
[a-z0-9\-]{0,62}
|
27
|
-
[a-z0-9]{1}
|
28
|
-
)
|
29
|
-
|
|
30
|
-
[a-z]
|
31
|
-
)
|
32
|
-
\.
|
33
|
-
)+
|
34
|
-
[a-z]{2,6}
|
35
|
-
)
|
36
|
-
|
|
37
|
-
(
|
38
|
-
\d{1,3}
|
39
|
-
\.
|
40
|
-
){3}
|
41
|
-
\d{1,3}
|
42
|
-
(
|
43
|
-
\:\d{1,5}
|
44
|
-
)?
|
45
|
-
)
|
46
|
-
$
|
47
|
-
}xi
|
48
|
-
|
49
|
-
# Second level .us domains for states and locality
|
50
|
-
# See http://en.wikipedia.org/wiki/.us
|
51
|
-
#
|
52
|
-
# Examples:
|
53
|
-
# * foo.state.il.us
|
54
|
-
# * ci.foo.il.us
|
55
|
-
#
|
56
|
-
# Not:
|
57
|
-
# * state.foo.il.us
|
58
|
-
# * foo.ci.il.us
|
59
|
-
# * k12.il.us
|
60
|
-
# * ci.foo.zx.us
|
61
|
-
LOCALITY_REGEX = %r{
|
62
|
-
(
|
63
|
-
(state|dst|cog)
|
64
|
-
|
|
65
|
-
(ci|town|vil|co)\.[a-z-]+
|
66
|
-
)
|
67
|
-
\.(ak|al|ar|az|ca|co|ct|dc|de|fl|ga|hi|ia|id|il|in|ks|ky|la|ma|md|me|mi|mn|mo|ms|mt|nc|nd|ne|nh|nj|nm|nv|ny|oh|ok|or|pa|ri|sc|sd|tn|tx|um|ut|va|vt|wa|wi|wv|wy)
|
68
|
-
\.us
|
69
|
-
}x
|
70
|
-
|
71
|
-
# Map last part of TLD to alpha2 country code
|
72
|
-
ALPHA2_MAP = {
|
73
|
-
:ac => 'sh',
|
74
|
-
:uk => 'gb',
|
75
|
-
:su => 'ru',
|
76
|
-
:tp => 'tl',
|
77
|
-
:yu => 'rs',
|
78
|
-
:gov => "us",
|
79
|
-
:mil => "us",
|
80
|
-
:org => "us",
|
81
|
-
:com => "us",
|
82
|
-
:net => "us",
|
83
|
-
:edu => "us",
|
84
|
-
:travel => "us",
|
85
|
-
:info => "us"
|
86
|
-
}
|
4
|
+
require_relative 'gman/country_codes'
|
5
|
+
require_relative 'gman/locality'
|
87
6
|
|
7
|
+
class Gman < NaughtyOrNice
|
88
8
|
class << self
|
89
|
-
|
90
|
-
attr_writer :list
|
91
|
-
|
92
|
-
# Normalizes and checks if a given string represents a government domain
|
93
|
-
# Possible strings to test:
|
94
|
-
# ".gov"
|
95
|
-
# "foo.gov"
|
96
|
-
# "foo@bar.gov"
|
97
|
-
# "foo.gov.uk"
|
98
|
-
# "http://foo.bar.gov"
|
99
|
-
#
|
100
|
-
# Returns boolean true if a government domain
|
101
|
-
def valid?(text)
|
102
|
-
Gman.new(text).valid?
|
103
|
-
end
|
104
|
-
|
105
|
-
# Is the given string in the form of a valid email address?
|
106
|
-
#
|
107
|
-
# Returns true if email, otherwise false
|
108
|
-
def email?(text)
|
109
|
-
Gman.new(text).email?
|
110
|
-
end
|
111
|
-
|
112
9
|
# returns an instance of our custom public suffix list
|
113
10
|
# list behaves like PublicSuffix::List but is limited to our whitelisted domains
|
114
11
|
def list
|
@@ -117,46 +14,10 @@ class Gman
|
|
117
14
|
|
118
15
|
# Returns the absolute path to the domain list
|
119
16
|
def list_path
|
120
|
-
File.join(File.dirname(__FILE__), "domains.txt")
|
17
|
+
File.join(File.dirname(__FILE__), "../config/domains.txt")
|
121
18
|
end
|
122
19
|
end
|
123
20
|
|
124
|
-
# Creates a new Gman instance
|
125
|
-
#
|
126
|
-
# text - the input string to check for governmentiness
|
127
|
-
def initialize(text)
|
128
|
-
@text = text.to_s.downcase.strip
|
129
|
-
end
|
130
|
-
|
131
|
-
# Parse the domain from the input string
|
132
|
-
#
|
133
|
-
# Can handle urls, domains, or emails
|
134
|
-
#
|
135
|
-
# Returns the domain string
|
136
|
-
def domain
|
137
|
-
@domain ||= begin
|
138
|
-
return nil if @text.empty?
|
139
|
-
|
140
|
-
uri = Addressable::URI.parse(@text)
|
141
|
-
|
142
|
-
if uri.host # valid https?://* URI
|
143
|
-
uri.host
|
144
|
-
elsif email?
|
145
|
-
@text.match(/@([\w\.\-]+)\Z/i)[1]
|
146
|
-
else # url sans http://
|
147
|
-
begin
|
148
|
-
uri = Addressable::URI.parse("http://#{@text}")
|
149
|
-
# properly parse http://foo edge cases
|
150
|
-
# see https://github.com/sporkmonger/addressable/issues/145
|
151
|
-
uri.host if uri.host =~ /\./
|
152
|
-
rescue Addressable::URI::InvalidURIError
|
153
|
-
nil
|
154
|
-
end
|
155
|
-
end
|
156
|
-
end
|
157
|
-
end
|
158
|
-
alias_method :to_s, :domain
|
159
|
-
|
160
21
|
# Checks if the input string represents a government domain
|
161
22
|
#
|
162
23
|
# Returns boolean true if a government domain
|
@@ -177,54 +38,4 @@ class Gman
|
|
177
38
|
# also allow for explicit matches to domain list
|
178
39
|
Gman.list.rules.any? { |rule| rule.value == domain }
|
179
40
|
end
|
180
|
-
|
181
|
-
# Is the input text in the form of a valid email address?
|
182
|
-
#
|
183
|
-
# Returns true if email, otherwise false
|
184
|
-
def email?
|
185
|
-
!!(@text =~ EMAIL_REGEX)
|
186
|
-
end
|
187
|
-
|
188
|
-
# Is this domain a .us state or locality?
|
189
|
-
def locality?
|
190
|
-
!!(domain =~ LOCALITY_REGEX)
|
191
|
-
end
|
192
|
-
|
193
|
-
# Helper function to return the public suffix domain object
|
194
|
-
#
|
195
|
-
# Supports all domain strings (URLs, emails)
|
196
|
-
#
|
197
|
-
# Returns the domain object or nil, but no errors, never an error
|
198
|
-
def domain_parts
|
199
|
-
PublicSuffix.parse domain
|
200
|
-
rescue PublicSuffix::DomainInvalid
|
201
|
-
nil
|
202
|
-
end
|
203
|
-
|
204
|
-
# Returns the two character alpha county code represented by the domain
|
205
|
-
#
|
206
|
-
# e.g., United States = US, United Kingdom = GB
|
207
|
-
def alpha2
|
208
|
-
alpha2 = domain_parts.tld.split('.').last
|
209
|
-
if ALPHA2_MAP[alpha2.to_sym]
|
210
|
-
ALPHA2_MAP[alpha2.to_sym]
|
211
|
-
else
|
212
|
-
alpha2
|
213
|
-
end
|
214
|
-
end
|
215
|
-
|
216
|
-
# Returns the ISO Country represented by the domain
|
217
|
-
#
|
218
|
-
# Example Usage:
|
219
|
-
# Gman.new("foo.gov").country.name => "United States"
|
220
|
-
# Gman.new("foo.gov").country.currency => "USD"
|
221
|
-
def country
|
222
|
-
@country ||= IsoCountryCodes.find(alpha2)
|
223
|
-
end
|
224
|
-
|
225
|
-
# Console output
|
226
|
-
def inspect
|
227
|
-
"#<Gman domain=\"#{domain}\" valid=#{valid?}>"
|
228
|
-
end
|
229
|
-
|
230
41
|
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
class Gman < NaughtyOrNice
|
2
|
+
|
3
|
+
# Map last part of TLD to alpha2 country code
|
4
|
+
ALPHA2_MAP = {
|
5
|
+
:ac => 'sh',
|
6
|
+
:uk => 'gb',
|
7
|
+
:su => 'ru',
|
8
|
+
:tp => 'tl',
|
9
|
+
:yu => 'rs',
|
10
|
+
:gov => "us",
|
11
|
+
:mil => "us",
|
12
|
+
:org => "us",
|
13
|
+
:com => "us",
|
14
|
+
:net => "us",
|
15
|
+
:edu => "us",
|
16
|
+
:travel => "us",
|
17
|
+
:info => "us"
|
18
|
+
}
|
19
|
+
|
20
|
+
# Returns the two character alpha county code represented by the domain
|
21
|
+
#
|
22
|
+
# e.g., United States = US, United Kingdom = GB
|
23
|
+
def alpha2
|
24
|
+
alpha2 = domain_parts.tld.split('.').last
|
25
|
+
if ALPHA2_MAP[alpha2.to_sym]
|
26
|
+
ALPHA2_MAP[alpha2.to_sym]
|
27
|
+
else
|
28
|
+
alpha2
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
# Returns the ISO Country represented by the domain
|
33
|
+
#
|
34
|
+
# Example Usage:
|
35
|
+
# Gman.new("foo.gov").country.name => "United States"
|
36
|
+
# Gman.new("foo.gov").country.currency => "USD"
|
37
|
+
def country
|
38
|
+
@country ||= IsoCountryCodes.find(alpha2)
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
class Gman < NaughtyOrNice
|
2
|
+
|
3
|
+
LOCALITY_REGEX = %r{
|
4
|
+
(
|
5
|
+
(state|dst|cog)
|
6
|
+
|
|
7
|
+
(ci|town|vil|co)\.[a-z-]+
|
8
|
+
)
|
9
|
+
\.(ak|al|ar|az|ca|co|ct|dc|de|fl|ga|hi|ia|id|il|in|ks|ky|la|ma|md|me|mi|mn|mo|ms|mt|nc|nd|ne|nh|nj|nm|nv|ny|oh|ok|or|pa|ri|sc|sd|tn|tx|um|ut|va|vt|wa|wi|wv|wy)
|
10
|
+
\.us
|
11
|
+
}x
|
12
|
+
|
13
|
+
# Second level .us domains for states and locality
|
14
|
+
# See http://en.wikipedia.org/wiki/.us
|
15
|
+
#
|
16
|
+
# Examples:
|
17
|
+
# * foo.state.il.us
|
18
|
+
# * ci.foo.il.us
|
19
|
+
#
|
20
|
+
# Not:
|
21
|
+
# * state.foo.il.us
|
22
|
+
# * foo.ci.il.us
|
23
|
+
# * k12.il.us
|
24
|
+
# * ci.foo.zx.us
|
25
|
+
def locality?
|
26
|
+
!!(domain =~ LOCALITY_REGEX)
|
27
|
+
end
|
28
|
+
end
|
metadata
CHANGED
@@ -1,73 +1,73 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: gman
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 4.
|
4
|
+
version: 4.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ben Balter
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-09-
|
11
|
+
date: 2014-09-19 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
|
-
name:
|
14
|
+
name: swot
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
17
|
- - "~>"
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version:
|
19
|
+
version: 0.3.1
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
24
|
- - "~>"
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version:
|
26
|
+
version: 0.3.1
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
|
-
name:
|
28
|
+
name: iso_country_codes
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
31
|
- - "~>"
|
32
32
|
- !ruby/object:Gem::Version
|
33
|
-
version: 0.
|
33
|
+
version: '0.4'
|
34
34
|
type: :runtime
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
38
|
- - "~>"
|
39
39
|
- !ruby/object:Gem::Version
|
40
|
-
version: 0.
|
40
|
+
version: '0.4'
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
|
-
name:
|
42
|
+
name: naughty_or_nice
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
44
44
|
requirements:
|
45
45
|
- - "~>"
|
46
46
|
- !ruby/object:Gem::Version
|
47
|
-
version:
|
47
|
+
version: 0.0.2
|
48
48
|
type: :runtime
|
49
49
|
prerelease: false
|
50
50
|
version_requirements: !ruby/object:Gem::Requirement
|
51
51
|
requirements:
|
52
52
|
- - "~>"
|
53
53
|
- !ruby/object:Gem::Version
|
54
|
-
version:
|
54
|
+
version: 0.0.2
|
55
55
|
- !ruby/object:Gem::Dependency
|
56
|
-
name:
|
56
|
+
name: rake
|
57
57
|
requirement: !ruby/object:Gem::Requirement
|
58
58
|
requirements:
|
59
|
-
- - "
|
59
|
+
- - ">="
|
60
60
|
- !ruby/object:Gem::Version
|
61
|
-
version: '0
|
62
|
-
type: :
|
61
|
+
version: '0'
|
62
|
+
type: :development
|
63
63
|
prerelease: false
|
64
64
|
version_requirements: !ruby/object:Gem::Requirement
|
65
65
|
requirements:
|
66
|
-
- - "
|
66
|
+
- - ">="
|
67
67
|
- !ruby/object:Gem::Version
|
68
|
-
version: '0
|
68
|
+
version: '0'
|
69
69
|
- !ruby/object:Gem::Dependency
|
70
|
-
name:
|
70
|
+
name: shoulda
|
71
71
|
requirement: !ruby/object:Gem::Requirement
|
72
72
|
requirements:
|
73
73
|
- - ">="
|
@@ -81,7 +81,7 @@ dependencies:
|
|
81
81
|
- !ruby/object:Gem::Version
|
82
82
|
version: '0'
|
83
83
|
- !ruby/object:Gem::Dependency
|
84
|
-
name:
|
84
|
+
name: rdoc
|
85
85
|
requirement: !ruby/object:Gem::Requirement
|
86
86
|
requirements:
|
87
87
|
- - ">="
|
@@ -95,7 +95,7 @@ dependencies:
|
|
95
95
|
- !ruby/object:Gem::Version
|
96
96
|
version: '0'
|
97
97
|
- !ruby/object:Gem::Dependency
|
98
|
-
name:
|
98
|
+
name: bundler
|
99
99
|
requirement: !ruby/object:Gem::Requirement
|
100
100
|
requirements:
|
101
101
|
- - ">="
|
@@ -109,7 +109,7 @@ dependencies:
|
|
109
109
|
- !ruby/object:Gem::Version
|
110
110
|
version: '0'
|
111
111
|
- !ruby/object:Gem::Dependency
|
112
|
-
name:
|
112
|
+
name: pry
|
113
113
|
requirement: !ruby/object:Gem::Requirement
|
114
114
|
requirements:
|
115
115
|
- - ">="
|
@@ -130,14 +130,12 @@ executables:
|
|
130
130
|
extensions: []
|
131
131
|
extra_rdoc_files: []
|
132
132
|
files:
|
133
|
-
- CONTRIBUTING.md
|
134
|
-
- Gemfile
|
135
133
|
- LICENSE
|
136
|
-
- README.md
|
137
134
|
- bin/gman_filter
|
138
|
-
-
|
135
|
+
- config/domains.txt
|
139
136
|
- lib/gman.rb
|
140
|
-
- lib/gman/
|
137
|
+
- lib/gman/country_codes.rb
|
138
|
+
- lib/gman/locality.rb
|
141
139
|
homepage: https://github.com/benbalter/gman
|
142
140
|
licenses:
|
143
141
|
- MIT
|
data/CONTRIBUTING.md
DELETED
@@ -1,22 +0,0 @@
|
|
1
|
-
# Contributing to Gman
|
2
|
-
|
3
|
-
## How to contribute
|
4
|
-
|
5
|
-
1. Fork the project
|
6
|
-
2. Create a descriptive branch
|
7
|
-
3. Make your change
|
8
|
-
4. Submit a pull request
|
9
|
-
|
10
|
-
## Code
|
11
|
-
|
12
|
-
Open an issue, or submit a pull request
|
13
|
-
|
14
|
-
## Domains
|
15
|
-
|
16
|
-
Domains live in `./lib/domains.txt` as a list of TLDs and SLD+TLDs.
|
17
|
-
|
18
|
-
Right now, the only valid government top level domains (TLDs), represent the US government and are `.gov`, and `.mil`.
|
19
|
-
|
20
|
-
Secondary domains (e.g., `gov.uk`, or `mil.au`) detect non-US government entities.
|
21
|
-
|
22
|
-
To add or remove a domain from the list of known government domains, simply edit the `domains.txt` file.
|
data/Gemfile
DELETED
data/README.md
DELETED
@@ -1,68 +0,0 @@
|
|
1
|
-
# Gman Gem
|
2
|
-
|
3
|
-
[![Build Status](https://travis-ci.org/benbalter/gman.png)](https://travis-ci.org/benbalter/gman) [![Gem Version](https://badge.fury.io/rb/gman.png)](http://badge.fury.io/rb/gman)
|
4
|
-
|
5
|
-
A ruby gem to check if the owner of a given email address or website is working for THE MAN (a.k.a verifies government domains). It does this by leveraging the power of the [Public Suffix List](http://publicsuffix.org/), and the associated [Ruby Gem](https://github.com/weppos/publicsuffix-ruby).
|
6
|
-
|
7
|
-
You could theoretically [use regex](https://gist.github.com/benbalter/6147066), but either you'll get a bunch of false positives, or your regex will be insanely complicated. `gov.uk`, may be valid, for example, but `gov.fr` is not (it's `gouv.fr`, for what it's worth).
|
8
|
-
|
9
|
-
The solution? Use Public Suffix to verify that it's a valid public domain, then maintain [a crowd-sourced sub-list of known global government and military domains](https://github.com/benbalter/gman/blob/master/lib/domains.txt). It should cover all US and international, government and military domains for both email and website verification.
|
10
|
-
|
11
|
-
See a domains that's missing or one that shouldn't be there? [We'd love you to contribute](CONTRIBUTING.md).
|
12
|
-
|
13
|
-
## Installation
|
14
|
-
|
15
|
-
Gman is a Ruby gem, so you'll need a little Ruby-fu to get it working. Simply
|
16
|
-
|
17
|
-
`gem install gman`
|
18
|
-
|
19
|
-
Or add this to your `Gemfile` before doing a `bundle install`:
|
20
|
-
|
21
|
-
`gem 'gman'`
|
22
|
-
|
23
|
-
## Usage
|
24
|
-
|
25
|
-
### In general
|
26
|
-
|
27
|
-
### Verify email addresses
|
28
|
-
|
29
|
-
```ruby
|
30
|
-
Gman.valid? "foo@bar.gov" #=> true
|
31
|
-
Gman.valid? "foo@bar.com" #=> false
|
32
|
-
```
|
33
|
-
|
34
|
-
### Verify domain
|
35
|
-
|
36
|
-
```ruby
|
37
|
-
Gman.valid? "http://foo.bar.gov" #=> true
|
38
|
-
Gman.valid? "foo.bar.gov" #=> true
|
39
|
-
Gman.valid? "foo.gov" #=> true
|
40
|
-
Gman.valid? "foo.biz" #=> false
|
41
|
-
```
|
42
|
-
|
43
|
-
### Get the ISO Country Code information represented by a government domain
|
44
|
-
|
45
|
-
```ruby
|
46
|
-
domain = Gman.new "whitehouse.gov" #=> #<Gman domain="whitehouse.gov" valid=true>
|
47
|
-
domain.country.name #=> "United States"
|
48
|
-
domain.country.alpha2 #=> "US"
|
49
|
-
domain.country.alpha3 #=> "USA"
|
50
|
-
domain.country.currency #=> "USD"
|
51
|
-
domain.conutry.calling_code #=> "+1"
|
52
|
-
```
|
53
|
-
|
54
|
-
### Command line
|
55
|
-
|
56
|
-
Filters newline-separated email addresses from stdin. Example usage:
|
57
|
-
|
58
|
-
```
|
59
|
-
$ gman_filter < path/to/list/of/addresses.txt
|
60
|
-
```
|
61
|
-
|
62
|
-
## Contributing
|
63
|
-
|
64
|
-
Contributions welcome! Please see [the contribution guidelines](CONTRIBUTING.md) for code contributions or for details on how to add, update, or delete government domains.
|
65
|
-
|
66
|
-
## Credits
|
67
|
-
|
68
|
-
Heavily inspired by [swot](https://github.com/leereilly/swot). Thanks [@leereilly](https://github.com/leereilly)!
|
data/lib/gman/version.rb
DELETED