gsr 0.0.1

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.
Files changed (9) hide show
  1. data/.gitignore +18 -0
  2. data/Gemfile +4 -0
  3. data/LICENSE +22 -0
  4. data/README.md +41 -0
  5. data/Rakefile +2 -0
  6. data/gsr.gemspec +19 -0
  7. data/lib/gsr.rb +123 -0
  8. data/lib/gsr/version.rb +5 -0
  9. metadata +68 -0
@@ -0,0 +1,18 @@
1
+ main.rb
2
+ *.gem
3
+ *.rbc
4
+ .bundle
5
+ .config
6
+ .yardoc
7
+ Gemfile.lock
8
+ InstalledFiles
9
+ _yardoc
10
+ coverage
11
+ doc/
12
+ lib/bundler/man
13
+ pkg
14
+ rdoc
15
+ spec/reports
16
+ test/tmp
17
+ test/version_tmp
18
+ tmp
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in gsr.gemspec
4
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2012 Matt Parmett
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,41 @@
1
+ # gsr.rb: A Ruby library for reserving Wharton GSRs #
2
+
3
+ gsr.rb is a simple Ruby library that allows your application to easily book and cancel Wharton Group Study Room (GSR) reservations.
4
+
5
+ ## How to use gsr.rb ##
6
+
7
+ *This section will change as gsr.rb is developed. As such, this section may not be fully accurate, but I will try to keep the instructions as current as possible.*
8
+
9
+ ### Make a reservation ###
10
+
11
+ To reserve a GSR for 60 minutes at noon on 9/18/2012 on the second floor:
12
+
13
+ ```ruby
14
+ require 'gsr.rb'
15
+ concierge = GSR.new(spike_username, spike_password)
16
+ concierge.reserve('floor' => '2', 'start_time' => Time.new(2012, 9, 18, 12, 0, 0), 'duration' => 60)
17
+ ```
18
+
19
+ ```floor``` takes strings ```""```, ```"F"```, ```"G"```, ```"2"```, or ```"3"```. The empty string, to which ```floor``` defaults, means any floor is acceptable.
20
+
21
+ ```start_time``` takes a Time object specifying the desired starting date and time (defaults to ```Time.now```).
22
+
23
+ ```duration``` takes an integer with a value of ```30```, ```60```, or ```90```. If another integer is given, gsr.rb rounds up to the next largest interval. ```duration``` defaults to ```90```.
24
+
25
+ ### Cancel a reservation ###
26
+
27
+ To cancel the reservation closest to the current time (more specific cancellation functionality may be added in the future):
28
+
29
+ ```ruby
30
+ require 'gsr.rb'
31
+ concierge = GSR.new(spike_username, spike_password)
32
+ concierge.cancel
33
+ ```
34
+
35
+ ## Warnings ##
36
+
37
+ Security-wise, this probably isn't the most secure way to handle the spike username and password. The user/pass combo is sent through a form on a secure web page, but no additional encryption/hashing is done on the credentials. Still, if gsr.rb is incorporated into a Heroku app, for example, the spike credentials could be stored securely as environment variables.
38
+
39
+ ## TODO ##
40
+ * More robust cancellation system?
41
+ * Create gem
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env rake
2
+ require "bundler/gem_tasks"
@@ -0,0 +1,19 @@
1
+ # -*- encoding: utf-8 -*-
2
+ require File.expand_path('../lib/gsr/version', __FILE__)
3
+
4
+ Gem::Specification.new do |gem|
5
+ gem.authors = "Matt Parmett"
6
+ gem.email = "parm289@yahoo.com"
7
+ gem.description = %q{Ruby wrapper for the Wharton GSR Reservation System}
8
+ gem.summary = %q{Ruby wrapper for the Wharton GSR Reservation System}
9
+ gem.homepage = ""
10
+
11
+ gem.files = `git ls-files`.split($\)
12
+ gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
13
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
14
+ gem.name = "gsr"
15
+ gem.require_paths = ["lib"]
16
+ gem.version = Gsr::Ruby::VERSION
17
+
18
+ gem.add_dependency "mechanize"
19
+ end
@@ -0,0 +1,123 @@
1
+ require 'mechanize'
2
+ require 'open-uri'
3
+
4
+ #Utility time methods
5
+ class Time
6
+ #Converts start_time from time to formatted string
7
+ def format_start_time()
8
+ #Hour logic
9
+ if self.hour < 0
10
+ raise "Invalid self specified: hour can't be negative"
11
+ elsif self.hour == 0
12
+ hour = 12
13
+ half = "AM"
14
+ elsif self.hour == 12
15
+ hour = 12
16
+ half = "PM"
17
+ elsif self.hour > 12
18
+ hour = self.hour - 12
19
+ half = "PM"
20
+ else # 0 < self.hour < 12
21
+ hour = self.hour
22
+ half = "AM"
23
+ end
24
+
25
+ #Minute logic
26
+ if self.min < 10
27
+ min = "0" + self.min.to_s
28
+ else
29
+ min = self.min.to_s
30
+ end
31
+
32
+ return hour.to_s + ':' + min + " " + half
33
+ end
34
+
35
+ #Converts start_date from date to formatted string
36
+ def format_start_date()
37
+ if Date.valid_date?(self.year, self.month, self.day)
38
+ return self.month.to_s + '/' + self.day.to_s
39
+ else
40
+ raise "Invalid start date specified."
41
+ end
42
+ end
43
+ end
44
+
45
+ # GSR class handles making GSR reservations
46
+ class GSR
47
+ attr_accessor :username, :password, :spike_root_url
48
+
49
+ def initialize(username, password, spike_root_url = "http://spike.wharton.upenn.edu/m/gsr.cfm?logout=true")
50
+ @username = username
51
+ @password = password
52
+ @spike_root_url = spike_root_url
53
+ end
54
+
55
+ # Logs in to spike using mechanize
56
+ def spike_login()
57
+ agent = Mechanize.new
58
+ login = agent.get(self.spike_root_url) #Go to login page
59
+ loginform = agent.page.forms.first #Select login form
60
+ loginform.username = self.username
61
+ loginform.password = self.password
62
+ gsr = agent.submit(loginform, loginform.buttons.first) #Submit form and log in
63
+ return {'agent' => agent, 'gsr' => gsr}
64
+ end
65
+
66
+ #Reserves the GSR
67
+ #requirements is an optional hash with keys:
68
+ #floor (string [F, G, 2, 3]), start_time (Time), duration (integer, minutes [30,60, or 90])
69
+ def reserve(requirements)
70
+ #Check if we have a non-kosher floor and revert to default
71
+ requirements['floor'] = "" if !(requirements['floor'].nil?) and
72
+ !(["", "F", "G", "2", "3"].include? requirements['floor'])
73
+
74
+ #Default args
75
+ default_options = {'floor' => "", 'start_time' => Time.now, 'duration' => 90}
76
+ args = default_options.merge(requirements)
77
+
78
+ #Convert start_date and start_time from date and time to correct form format
79
+ start_time = args['start_time'].format_start_time
80
+ start_date = args['start_time'].format_start_date
81
+
82
+ #Duration logic - round to 30, 60, or 90 (nearest)
83
+ unless requirements['duration'].nil?
84
+ if args['duration'] <= 30
85
+ args['duration'] = 30
86
+ elsif args['duration'] <= 60
87
+ args['duration'] = 60
88
+ else
89
+ args['duration'] = 90
90
+ end
91
+ end
92
+
93
+ agent = spike_login()['agent'] # Mechanize agent at successful login page
94
+ gsr = spike_login()['gsr'] # Mechanize page = successful login page
95
+ gsrform = gsr.form_with(:action => 'https://spike.wharton.upenn.edu/m/gsr.cfm') #Select GSR form
96
+
97
+ #Input GSR info
98
+ gsrform.preferred_floor = args['floor']
99
+ gsrform.start_date = start_date
100
+ gsrform.start_time = start_time
101
+ gsrform.duration = args['duration']
102
+
103
+ #Submit reservation
104
+ submit = agent.submit(gsrform, gsrform.buttons.first)
105
+
106
+ #Check if successful
107
+ raise "Error reserving GSR. Check supplied parameters." if submit.link_with(:text => 'Cancel').nil?
108
+
109
+ end
110
+
111
+ #Cancels most recent GSR reservation
112
+ def cancel()
113
+ agent = spike_login()['agent'] # Mechanize agent at successful login page
114
+ gsr = spike_login()['gsr'] # Mechanize page = successful login page
115
+
116
+ cancel = gsr.link_with(:text => 'Cancel')
117
+ if (cancel.nil?)
118
+ raise "Error: You have no GSR reservation to cancel."
119
+ else
120
+ gsr = cancel.click
121
+ end
122
+ end
123
+ end
@@ -0,0 +1,5 @@
1
+ module Gsr
2
+ module Ruby
3
+ VERSION = "0.0.1"
4
+ end
5
+ end
metadata ADDED
@@ -0,0 +1,68 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: gsr
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Matt Parmett
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-10-27 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: mechanize
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
29
+ version: '0'
30
+ description: Ruby wrapper for the Wharton GSR Reservation System
31
+ email: parm289@yahoo.com
32
+ executables: []
33
+ extensions: []
34
+ extra_rdoc_files: []
35
+ files:
36
+ - .gitignore
37
+ - Gemfile
38
+ - LICENSE
39
+ - README.md
40
+ - Rakefile
41
+ - gsr.gemspec
42
+ - lib/gsr.rb
43
+ - lib/gsr/version.rb
44
+ homepage: ''
45
+ licenses: []
46
+ post_install_message:
47
+ rdoc_options: []
48
+ require_paths:
49
+ - lib
50
+ required_ruby_version: !ruby/object:Gem::Requirement
51
+ none: false
52
+ requirements:
53
+ - - ! '>='
54
+ - !ruby/object:Gem::Version
55
+ version: '0'
56
+ required_rubygems_version: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ! '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ requirements: []
63
+ rubyforge_project:
64
+ rubygems_version: 1.8.23
65
+ signing_key:
66
+ specification_version: 3
67
+ summary: Ruby wrapper for the Wharton GSR Reservation System
68
+ test_files: []