cwru_directory 0.1.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: 7115bc699d6829f6ff8bacb672e7b622c500b73e
4
+ data.tar.gz: 49a4899de3fa4f29f2480d66d5529be9b88fccd5
5
+ SHA512:
6
+ metadata.gz: 6d6905486d2e9d90a5f60dbab52a96e38224d9c7189f31b4edbf61551138b4a3f0e6b8d71e9db953793589bce16e1845bc52e30f21d64bffc26508eca054ca74
7
+ data.tar.gz: fbc6864a947f0f85e65581f8fa87cbd1bd85ab66bc79e42b82735046d37c28581cce889ea9295f05cc58d493604b6a7a19f51392dbdf61cf7b7165b96c911d50
@@ -0,0 +1,9 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --format documentation
2
+ --color
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in cwru_directory.gemspec
4
+ gemspec
@@ -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.
@@ -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.
@@ -0,0 +1,2 @@
1
+ require "bundler/gem_tasks"
2
+
@@ -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
@@ -0,0 +1,7 @@
1
+ #!/bin/bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+
5
+ bundle install
6
+
7
+ # Do any other automated setup that you need to do here
@@ -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
@@ -0,0 +1,3 @@
1
+ module CWRUDirectory
2
+ VERSION = "0.1.0"
3
+ 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: []