cwru_directory 0.1.0
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.
- checksums.yaml +7 -0
- data/.gitignore +9 -0
- data/.rspec +2 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +21 -0
- data/README.md +93 -0
- data/Rakefile +2 -0
- data/bin/console +11 -0
- data/bin/setup +7 -0
- data/cwru_directory.gemspec +25 -0
- data/lib/cwru_directory.rb +120 -0
- data/lib/cwru_directory/authentication.rb +18 -0
- data/lib/cwru_directory/config.rb +28 -0
- data/lib/cwru_directory/version.rb +3 -0
- metadata +114 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 7115bc699d6829f6ff8bacb672e7b622c500b73e
|
4
|
+
data.tar.gz: 49a4899de3fa4f29f2480d66d5529be9b88fccd5
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 6d6905486d2e9d90a5f60dbab52a96e38224d9c7189f31b4edbf61551138b4a3f0e6b8d71e9db953793589bce16e1845bc52e30f21d64bffc26508eca054ca74
|
7
|
+
data.tar.gz: fbc6864a947f0f85e65581f8fa87cbd1bd85ab66bc79e42b82735046d37c28581cce889ea9295f05cc58d493604b6a7a19f51392dbdf61cf7b7165b96c911d50
|
data/.gitignore
ADDED
data/.rspec
ADDED
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2015 Andrew Mason
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in
|
13
|
+
all copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
21
|
+
THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,93 @@
|
|
1
|
+
# CWRUDirectory
|
2
|
+
|
3
|
+
Make queries with the Case Western Reserve University [directory listing](https://webapps.case.edu/directory/index.html) in Ruby!
|
4
|
+
|
5
|
+
Inspired by/derived from [the Python implementation](https://github.com/brenns10/caseid).
|
6
|
+
|
7
|
+
## Installation
|
8
|
+
|
9
|
+
Add this line to your application's Gemfile:
|
10
|
+
|
11
|
+
```ruby
|
12
|
+
gem 'cwru_directory'
|
13
|
+
```
|
14
|
+
|
15
|
+
And then execute:
|
16
|
+
|
17
|
+
$ bundle
|
18
|
+
|
19
|
+
Or install it yourself as:
|
20
|
+
|
21
|
+
$ gem install cwru_directory
|
22
|
+
|
23
|
+
## Usage
|
24
|
+
|
25
|
+
### Configuration
|
26
|
+
|
27
|
+
CWRUDirectory currently recognizes the following configuration options
|
28
|
+
(you can set as many other options as you like, they just won't do anything):
|
29
|
+
|
30
|
+
```ruby
|
31
|
+
CWRUDirectory.configure do |config|
|
32
|
+
# case_id and password are used to authenticate with SSO to
|
33
|
+
# be able to access information not available to the public
|
34
|
+
config.case_id = 'abc123'
|
35
|
+
config.password = 'my-password'
|
36
|
+
|
37
|
+
# get_all_info is used to tell CWRUDirectory to actually get
|
38
|
+
# that extra info not available to the public
|
39
|
+
config.get_all_info = true
|
40
|
+
end
|
41
|
+
```
|
42
|
+
|
43
|
+
### Queries
|
44
|
+
|
45
|
+
CWRUDirectory has two ways to query the directory, simple and advanced.
|
46
|
+
Both return a hash, which maps the categories to the sets of results for
|
47
|
+
each category.
|
48
|
+
|
49
|
+
#### The Result hash
|
50
|
+
|
51
|
+
As mentioned above, each element of a result set is a hash, which has the following keys:
|
52
|
+
* `:name`
|
53
|
+
* `:phone_number`
|
54
|
+
* `:email`
|
55
|
+
* `:department`
|
56
|
+
|
57
|
+
If you run this with the `get_all_info` config option set, you will also
|
58
|
+
get some of the following, possibly more:
|
59
|
+
* `"Case Network ID"` - this one is always present (as far as I can tell)
|
60
|
+
* `"Title"`
|
61
|
+
* `"Mail Stop Location Code"` - uhhh. I guess if you need that...
|
62
|
+
|
63
|
+
#### Simple Queries
|
64
|
+
|
65
|
+
Simple queries allow you to search by single search string in a given search mode.
|
66
|
+
|
67
|
+
```ruby
|
68
|
+
CWRUDirectory.simple 'my_search_string'
|
69
|
+
# second argument is the search mode, defaults to :regular,
|
70
|
+
# :phonetic is the only other option the Case directory supports
|
71
|
+
CWRUDirectory.simple 'my_search_string', :phonetic
|
72
|
+
```
|
73
|
+
|
74
|
+
#### Advanced Queries
|
75
|
+
|
76
|
+
You can also make "advanced" queries with many more attributes. The Case directory has the
|
77
|
+
following attributes:
|
78
|
+
* `surname` - last name
|
79
|
+
* `givenname` - first name
|
80
|
+
* `department` - this isn't listed for most entries, so probably won't be that helpful to you
|
81
|
+
* `location` - ??? if you figure out what this actually is, let me know
|
82
|
+
* `category` - one of `'STUDENT', 'FACULTY', 'STAFF', 'EMERITI', 'ALL'`
|
83
|
+
* `search_text` - this is the same as the search text used in the simple queries
|
84
|
+
* `search_method` - same as simple queries
|
85
|
+
|
86
|
+
Just pass in a hash of whichever ones you want to use; the rest will default to empty strings,
|
87
|
+
except for `category` (default is `'ALL'`) and `search_method` (defaults to `:regular`)
|
88
|
+
|
89
|
+
```ruby
|
90
|
+
CWRUDirectory.advanced({surname: 'Mason', givenname: 'Andrew'})
|
91
|
+
```
|
92
|
+
|
93
|
+
That's all for now folks! LDAP probably coming soon.
|
data/Rakefile
ADDED
data/bin/console
ADDED
@@ -0,0 +1,11 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require "bundler/setup"
|
4
|
+
require "cwru_directory"
|
5
|
+
|
6
|
+
# You can add fixtures and/or initialization code here to make experimenting
|
7
|
+
# with your gem easier. You can also use a different console, if you like.
|
8
|
+
|
9
|
+
# (If you use this, don't forget to add pry to your Gemfile!)
|
10
|
+
require "pry"
|
11
|
+
Pry.start
|
data/bin/setup
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'cwru_directory/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "cwru_directory"
|
8
|
+
spec.version = CWRUDirectory::VERSION
|
9
|
+
spec.authors = ["Andrew Mason"]
|
10
|
+
spec.email = ["mason@case.edu"]
|
11
|
+
|
12
|
+
spec.summary = "Gem for making queries with the Case Western Reserve University directory listing"
|
13
|
+
spec.homepage = "https://github.com/ajm188/cwru_directory"
|
14
|
+
spec.license = "MIT"
|
15
|
+
|
16
|
+
spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
17
|
+
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
18
|
+
spec.require_paths = ["lib"]
|
19
|
+
|
20
|
+
spec.add_development_dependency "bundler", "~> 1.8"
|
21
|
+
spec.add_development_dependency "rake", "~> 10.0"
|
22
|
+
spec.add_development_dependency 'pry'
|
23
|
+
|
24
|
+
spec.add_runtime_dependency 'mechanize'
|
25
|
+
end
|
@@ -0,0 +1,120 @@
|
|
1
|
+
require "cwru_directory/version"
|
2
|
+
require 'cwru_directory/config'
|
3
|
+
require 'cwru_directory/authentication'
|
4
|
+
|
5
|
+
require 'mechanize' # Can't just open-uri because the URL does a redirect
|
6
|
+
|
7
|
+
module CWRUDirectory
|
8
|
+
URL = 'https://webapps.case.edu/directory/lookup'
|
9
|
+
@agent ||= Mechanize.new
|
10
|
+
|
11
|
+
class << self
|
12
|
+
# Perform a simple search. Default search method is
|
13
|
+
# regular. Other option is phonetic, which actually seems
|
14
|
+
# to sort of work.
|
15
|
+
#
|
16
|
+
# Returns a hash, which maps each category (see the comments on
|
17
|
+
# the #advanced method) to the list of results for that category.
|
18
|
+
# Each result is itself a hash, with the keys:
|
19
|
+
# * :name
|
20
|
+
# * :phone_number
|
21
|
+
# * :email
|
22
|
+
# * :department
|
23
|
+
def simple(search_text, search_method = :regular)
|
24
|
+
search({search_text: search_text, search_method: search_method})
|
25
|
+
end
|
26
|
+
|
27
|
+
# Perform an advanced search with various params. Ones supported
|
28
|
+
# by the CWRU directory are:
|
29
|
+
# * surname: last name
|
30
|
+
# * givenname: first name
|
31
|
+
# * department: not listed for most entries
|
32
|
+
# * location: ???
|
33
|
+
# * category: one of 'STUDENT', 'FACULTY', 'STAFF', or 'EMERITI'
|
34
|
+
# * search_text: same as the argument to the simple search
|
35
|
+
# * search_method: same as the argument to the simple search
|
36
|
+
#
|
37
|
+
# Returns a hash, exactly like the #simple method (see above)
|
38
|
+
def advanced(params = {})
|
39
|
+
search(params)
|
40
|
+
end
|
41
|
+
|
42
|
+
def search(params)
|
43
|
+
page = @agent.get(URL + '?' + to_query_string(default_search_params.merge(params))).parser
|
44
|
+
rows = page.xpath('//table[@class="dirresults"]/tr')
|
45
|
+
parse_results(rows)
|
46
|
+
end
|
47
|
+
|
48
|
+
def parse_results(rows)
|
49
|
+
header = nil
|
50
|
+
results = {}
|
51
|
+
index = 0
|
52
|
+
while index < rows.length
|
53
|
+
# We need more fine-grained control over the looping
|
54
|
+
# because each result is actually 2 rows in the table,
|
55
|
+
# but header rows are only one row. This is the worst
|
56
|
+
row = rows[index]
|
57
|
+
if row.children[0].get_attribute('class') == 'dirhdr'
|
58
|
+
# This is a new header section.
|
59
|
+
header = row.children[0].children[0].text
|
60
|
+
results[header] = []
|
61
|
+
elsif row.children[0].get_attribute('class') == 'breaker'
|
62
|
+
# This row is just for spacing. Ignore it.
|
63
|
+
index += 1
|
64
|
+
next
|
65
|
+
else
|
66
|
+
# This is a result row. Process it and the next row
|
67
|
+
results[header] << process_result(row, rows[index + 1])
|
68
|
+
index += 1
|
69
|
+
end
|
70
|
+
index += 1
|
71
|
+
end
|
72
|
+
|
73
|
+
if @config.get_all_info
|
74
|
+
authenticate! # we need to be authenticated for this
|
75
|
+
results.values.flatten.each do |result|
|
76
|
+
process_more_info(result, @agent.get(result[:more_info_link])) if result[:more_info_link]
|
77
|
+
end
|
78
|
+
end
|
79
|
+
results
|
80
|
+
end
|
81
|
+
|
82
|
+
def process_result(first_row, second_row)
|
83
|
+
{
|
84
|
+
name: first_row.children[0].text,
|
85
|
+
phone_number: first_row.children[1].text,
|
86
|
+
more_info_link: first_row.children[2].children[0].get_attribute('href'),
|
87
|
+
email: second_row.children[0].text,
|
88
|
+
department: second_row.children[1].text
|
89
|
+
}
|
90
|
+
end
|
91
|
+
|
92
|
+
def process_more_info(result, more_info_page)
|
93
|
+
html = more_info_page.parser
|
94
|
+
# The first row is the person's name and section, so we can skip that.
|
95
|
+
html.xpath('//table[@class="longlisting"]/tr').drop(1).each do |more_info_row|
|
96
|
+
attribute = more_info_row.children[0].text
|
97
|
+
# There is a td of padding between the attribute and the value
|
98
|
+
value = more_info_row.children[2].text
|
99
|
+
|
100
|
+
result[attribute] = value
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
def default_search_params
|
105
|
+
{
|
106
|
+
search_text: '',
|
107
|
+
surname: '',
|
108
|
+
givenname: '',
|
109
|
+
department: '',
|
110
|
+
location: '',
|
111
|
+
category: :all,
|
112
|
+
search_method: :regular
|
113
|
+
}
|
114
|
+
end
|
115
|
+
|
116
|
+
def to_query_string(params)
|
117
|
+
params.map { |k,v| "#{k}=#{v}" }.join('&')
|
118
|
+
end
|
119
|
+
end
|
120
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module CWRUDirectory
|
2
|
+
class << self
|
3
|
+
def authenticate!
|
4
|
+
return if @authenticated
|
5
|
+
# Surely this will return a result, then we can click 'MORE INFO'
|
6
|
+
# which will take us to the Single Sign On
|
7
|
+
page = @agent.get(URL + '?' + to_query_string(default_search_params.merge({surname: 'Mason', givenname: 'Andrew'})))
|
8
|
+
|
9
|
+
# Fill out the SSO form
|
10
|
+
login_page = page.link_with(text: 'MORE INFO').click
|
11
|
+
login_page.form_with(name: nil) do |form|
|
12
|
+
form.field_with(name: 'username').value = @config.case_id
|
13
|
+
form.field_with(name: 'password').value = @config.password
|
14
|
+
end.submit
|
15
|
+
@authenticated = true
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
module CWRUDirectory
|
2
|
+
class Configuration
|
3
|
+
# Method missing gives us an attr_accessor for any attribute
|
4
|
+
# we might need on the configuration object.
|
5
|
+
#
|
6
|
+
# Currently the only config attributes that are used are:
|
7
|
+
# * case_id
|
8
|
+
# * password
|
9
|
+
# * get_all_info
|
10
|
+
def method_missing(meth, *args, &block)
|
11
|
+
meth_string = meth.to_s
|
12
|
+
attr_name = (meth_string.end_with?('=') ? meth_string[0..-2] : meth_string).to_sym
|
13
|
+
|
14
|
+
self.class.class_eval do
|
15
|
+
attr_accessor attr_name
|
16
|
+
end
|
17
|
+
|
18
|
+
self.send(meth, *args, &block)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
class << self
|
23
|
+
def configure(&block)
|
24
|
+
@config ||= Configuration.new
|
25
|
+
yield @config if block_given?
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
metadata
ADDED
@@ -0,0 +1,114 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: cwru_directory
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Andrew Mason
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2015-03-18 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: bundler
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.8'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.8'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rake
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '10.0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '10.0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: pry
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: mechanize
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :runtime
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
69
|
+
description:
|
70
|
+
email:
|
71
|
+
- mason@case.edu
|
72
|
+
executables: []
|
73
|
+
extensions: []
|
74
|
+
extra_rdoc_files: []
|
75
|
+
files:
|
76
|
+
- ".gitignore"
|
77
|
+
- ".rspec"
|
78
|
+
- Gemfile
|
79
|
+
- LICENSE.txt
|
80
|
+
- README.md
|
81
|
+
- Rakefile
|
82
|
+
- bin/console
|
83
|
+
- bin/setup
|
84
|
+
- cwru_directory.gemspec
|
85
|
+
- lib/cwru_directory.rb
|
86
|
+
- lib/cwru_directory/authentication.rb
|
87
|
+
- lib/cwru_directory/config.rb
|
88
|
+
- lib/cwru_directory/version.rb
|
89
|
+
homepage: https://github.com/ajm188/cwru_directory
|
90
|
+
licenses:
|
91
|
+
- MIT
|
92
|
+
metadata: {}
|
93
|
+
post_install_message:
|
94
|
+
rdoc_options: []
|
95
|
+
require_paths:
|
96
|
+
- lib
|
97
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
98
|
+
requirements:
|
99
|
+
- - ">="
|
100
|
+
- !ruby/object:Gem::Version
|
101
|
+
version: '0'
|
102
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
103
|
+
requirements:
|
104
|
+
- - ">="
|
105
|
+
- !ruby/object:Gem::Version
|
106
|
+
version: '0'
|
107
|
+
requirements: []
|
108
|
+
rubyforge_project:
|
109
|
+
rubygems_version: 2.4.5
|
110
|
+
signing_key:
|
111
|
+
specification_version: 4
|
112
|
+
summary: Gem for making queries with the Case Western Reserve University directory
|
113
|
+
listing
|
114
|
+
test_files: []
|