my_banner 1.0.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/.codeclimate.yml +12 -0
- data/.gitignore +22 -0
- data/.rspec +3 -0
- data/.ruby_version +1 -0
- data/.travis.yml +17 -0
- data/CONTRIBUTING.md +25 -0
- data/CREDITS.md +86 -0
- data/Gemfile +6 -0
- data/Gemfile.lock +128 -0
- data/LICENSE.md +21 -0
- data/README.md +116 -0
- data/Rakefile +8 -0
- data/auth/.gitignore +2 -0
- data/bin/console +8 -0
- data/bin/setup +8 -0
- data/lib/my_banner.rb +32 -0
- data/lib/my_banner/calendar_authorization.rb +16 -0
- data/lib/my_banner/calendar_client.rb +26 -0
- data/lib/my_banner/calendar_service.rb +116 -0
- data/lib/my_banner/drive_authorization.rb +17 -0
- data/lib/my_banner/drive_client.rb +16 -0
- data/lib/my_banner/google_authorization.rb +47 -0
- data/lib/my_banner/schedule.rb +54 -0
- data/lib/my_banner/schedule/tableset.rb +115 -0
- data/lib/my_banner/section.rb +58 -0
- data/lib/my_banner/section/meeting.rb +27 -0
- data/lib/my_banner/spreadsheet_authorization.rb +16 -0
- data/lib/my_banner/spreadsheet_client.rb +16 -0
- data/lib/my_banner/spreadsheet_service.rb +75 -0
- data/lib/my_banner/version.rb +3 -0
- data/lib/tasks/my_banner.rake +120 -0
- data/my_banner.gemspec +36 -0
- data/pages/.gitignore +2 -0
- metadata +234 -0
@@ -0,0 +1,58 @@
|
|
1
|
+
module MyBanner
|
2
|
+
class Section
|
3
|
+
|
4
|
+
attr_accessor :metadata, :course, :section, :title, :instructor, :weekdays, :location, :time_zone, :term_start, :term_end, :start_time, :end_time
|
5
|
+
|
6
|
+
def initialize(metadata={})
|
7
|
+
@metadata = metadata
|
8
|
+
|
9
|
+
@course = metadata.try(:[], :course)
|
10
|
+
@section = metadata.try(:[], :section)
|
11
|
+
@title = metadata.try(:[], :title)
|
12
|
+
|
13
|
+
schedule_info = metadata.try(:[], :scheduled_meeting_times)
|
14
|
+
@instructor = schedule_info.try(:[], :instructors).try(:first)
|
15
|
+
@weekdays = schedule_info.try(:[], :days).try(:each_char).try(:to_a)
|
16
|
+
@location = schedule_info.try(:[], :where)
|
17
|
+
@time_zone = "America/New_York" #todo: lookup or customize
|
18
|
+
|
19
|
+
term_info = schedule_info.try(:[], :date_range) #todo: validate string splits into two-member array
|
20
|
+
@term_start = Date.parse( term_info.try(:split, " - ").try(:first) ) rescue nil
|
21
|
+
@term_end = Date.parse( term_info.try(:split, " - ").try(:last) ) rescue nil
|
22
|
+
|
23
|
+
time_info = schedule_info.try(:[], :time) #todo: validate string splits into two-member array
|
24
|
+
@start_time = time_info.try(:split, " - ").try(:first)
|
25
|
+
@end_time = time_info.try(:split, " - ").try(:last)
|
26
|
+
end
|
27
|
+
|
28
|
+
def abbreviation
|
29
|
+
"#{course}-#{section}" if course && section
|
30
|
+
end
|
31
|
+
alias_method :abbrev, :abbreviation
|
32
|
+
|
33
|
+
# @note does not exclude meetings cancelled due to holidays
|
34
|
+
# @todo cross-reference the "Holidays in the United States" calendar events to make a best guess at which classes to exclude
|
35
|
+
def meetings
|
36
|
+
meeting_dates.map do |date|
|
37
|
+
start_at = DateTime.parse("#{date} #{start_time}")
|
38
|
+
end_at = DateTime.parse("#{date} #{end_time}")
|
39
|
+
Meeting.new(start_at: start_at, end_at: end_at)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
def meeting_dates
|
44
|
+
term_date_range.select { |date| weekday_numbers.include?(date.wday) }
|
45
|
+
end
|
46
|
+
|
47
|
+
def term_date_range
|
48
|
+
term_start..term_end
|
49
|
+
end
|
50
|
+
|
51
|
+
def weekday_numbers
|
52
|
+
weekdays.map { |char| WEEKDAYS_MAP[char.to_sym] }
|
53
|
+
end
|
54
|
+
|
55
|
+
WEEKDAYS_MAP = { M: 1, T: 2, W: 3, R: 4, F: 5, S: 6, N: 0 } # S and N assumed but not yet verified
|
56
|
+
|
57
|
+
end
|
58
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module MyBanner
|
2
|
+
class Section::Meeting
|
3
|
+
|
4
|
+
attr_reader :start_at, :end_at
|
5
|
+
|
6
|
+
def initialize(options={})
|
7
|
+
@start_at = options[:start_at]
|
8
|
+
@end_at = options[:end_at]
|
9
|
+
validate_datetimes
|
10
|
+
end
|
11
|
+
|
12
|
+
def to_s
|
13
|
+
"#{start_at.try(:strftime, '%Y-%m-%d %H:%M')} ... #{end_at.try(:strftime, '%Y-%m-%d %H:%M')}"
|
14
|
+
end
|
15
|
+
|
16
|
+
def to_h
|
17
|
+
{ start_at: start_at, end_at: end_at }
|
18
|
+
end
|
19
|
+
|
20
|
+
private
|
21
|
+
|
22
|
+
def validate_datetimes
|
23
|
+
raise "expecting datetimes" unless start_at && end_at && start_at.is_a?(DateTime) && end_at.is_a?(DateTime)
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
require "google/apis/sheets_v4"
|
2
|
+
|
3
|
+
module MyBanner
|
4
|
+
class SpreadsheetAuthorization < GoogleAuthorization
|
5
|
+
|
6
|
+
AUTH_SCOPE = Google::Apis::SheetsV4::AUTH_SPREADSHEETS #> "https://www.googleapis.com/auth/spreadsheets"
|
7
|
+
|
8
|
+
def initialize(options={})
|
9
|
+
options[:scope] ||= AUTH_SCOPE
|
10
|
+
options[:credentials_filepath] ||= "auth/spreadsheet_credentials.json"
|
11
|
+
options[:token_filepath] ||= "auth/spreadsheet_token.yaml"
|
12
|
+
super(options)
|
13
|
+
end
|
14
|
+
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
require "google/apis/sheets_v4"
|
2
|
+
|
3
|
+
module MyBanner
|
4
|
+
class SpreadsheetClient < Google::Apis::SheetsV4::SheetsService
|
5
|
+
|
6
|
+
# @param authorization [SpreadsheetAuthorization]
|
7
|
+
def initialize(authorization=nil)
|
8
|
+
super()
|
9
|
+
self.client_options.application_name = "MyBanner Spreadsheet Client"
|
10
|
+
self.client_options.application_version = VERSION
|
11
|
+
authorization ||= SpreadsheetAuthorization.new
|
12
|
+
self.authorization = authorization.stored_credentials || authorization.user_provided_credentials
|
13
|
+
end
|
14
|
+
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,75 @@
|
|
1
|
+
|
2
|
+
|
3
|
+
require "google/apis/sheets_v4"
|
4
|
+
|
5
|
+
module MyBanner
|
6
|
+
class SpreadsheetService
|
7
|
+
attr_reader :spreadsheet_title #, :sheet_name #, :sheet_values
|
8
|
+
|
9
|
+
def initialize(spreadsheet_title)
|
10
|
+
@spreadsheet_title = spreadsheet_title
|
11
|
+
#@sheet_name = "roster-todo" # todo: "roster-#{Date.today.to_s}"
|
12
|
+
#@sheet_values = [["email", "registration_number", "net_id"]] + 27.times.map { |i| ["student#{i+1}@todo.edu", i+1, "student#{i+1}"] } # todo: get from roster
|
13
|
+
end
|
14
|
+
|
15
|
+
#def execute
|
16
|
+
# spreadsheet
|
17
|
+
# #update_values
|
18
|
+
#end
|
19
|
+
|
20
|
+
# # @return Google::Apis::SheetsV4::UpdateValuesResponse
|
21
|
+
# def update_values
|
22
|
+
# range = "#{sheet_name}!A1"
|
23
|
+
# vals = Google::Apis::SheetsV4::ValueRange.new(values: sheet_values)
|
24
|
+
# client.update_spreadsheet_value(spreadsheet.spreadsheet_id, range, vals, value_input_option: "RAW")
|
25
|
+
# end
|
26
|
+
|
27
|
+
# @return Google::Apis::SheetsV4::Spreadsheet
|
28
|
+
def spreadsheet
|
29
|
+
@spreadsheet ||= if spreadsheet_file
|
30
|
+
client.get_spreadsheet(spreadsheet_file.id)
|
31
|
+
else
|
32
|
+
client.create_spreadsheet(new_spreadsheet)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def client
|
37
|
+
@client ||= SpreadsheetClient.new
|
38
|
+
end
|
39
|
+
|
40
|
+
def new_spreadsheet
|
41
|
+
#roster_sheet = Google::Apis::SheetsV4::Sheet.new(properties: {title: sheet_name, sheet_type: "GRID"})
|
42
|
+
#new_spreadsheet_attrs = { properties: {title: spreadsheet_title}, sheets: [roster_sheet] }
|
43
|
+
new_spreadsheet_attrs = { properties: { title: spreadsheet_title } }
|
44
|
+
Google::Apis::SheetsV4::Spreadsheet.new(new_spreadsheet_attrs)
|
45
|
+
end
|
46
|
+
|
47
|
+
#
|
48
|
+
# DRIVE FILES
|
49
|
+
#
|
50
|
+
|
51
|
+
# @return Google::Apis::DriveV3::File
|
52
|
+
def spreadsheet_file
|
53
|
+
file_list.files.find { |f| f.name == spreadsheet_title }
|
54
|
+
end
|
55
|
+
|
56
|
+
# @return Google::Apis::DriveV3::FileList
|
57
|
+
def file_list
|
58
|
+
@file_list ||= begin
|
59
|
+
request_options = {q: "mimeType='application/vnd.google-apps.spreadsheet'", order_by: "createdTime desc", page_size: 25}
|
60
|
+
drive_client.list_files(request_options)
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
def drive_client
|
65
|
+
@drive_client ||= DriveClient.new
|
66
|
+
end
|
67
|
+
|
68
|
+
private
|
69
|
+
|
70
|
+
def delete_spreadsheet # DANGER!
|
71
|
+
drive_client.delete_file(spreadsheet.spreadsheet_id)
|
72
|
+
end
|
73
|
+
|
74
|
+
end
|
75
|
+
end
|
@@ -0,0 +1,120 @@
|
|
1
|
+
require_relative "../my_banner"
|
2
|
+
|
3
|
+
# namespace :my_banner do
|
4
|
+
|
5
|
+
task :parse_schedule do
|
6
|
+
page = MyBanner::Schedule.new
|
7
|
+
sections = page.sections
|
8
|
+
puts "-----------------------"
|
9
|
+
puts "SECTIONS: #{sections.count}"
|
10
|
+
puts "-----------------------"
|
11
|
+
sections.each do |section|
|
12
|
+
puts ""
|
13
|
+
puts "#{section.title.upcase}:"
|
14
|
+
puts ""
|
15
|
+
pp section.metadata
|
16
|
+
puts ""
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
# @example bundle exec rake create_calendars
|
21
|
+
task :create_calendars do
|
22
|
+
page = MyBanner::Schedule.new
|
23
|
+
sections = page.sections
|
24
|
+
puts "-----------------------"
|
25
|
+
puts "SECTIONS: #{sections.count}"
|
26
|
+
puts "-----------------------"
|
27
|
+
sections.each do |section|
|
28
|
+
puts "\nSECTION: #{section.abbreviation} (#{section.title})"
|
29
|
+
service = MyBanner::CalendarService.new(section)
|
30
|
+
|
31
|
+
calendar = service.calendar
|
32
|
+
puts "\nCALENDAR: #{calendar.summary} (#{calendar.id})"
|
33
|
+
|
34
|
+
meetings = section.meetings
|
35
|
+
puts "\nMEETINGS: #{meetings.count}"
|
36
|
+
meetings.each do |meeting|
|
37
|
+
puts " + #{meeting.to_s}"
|
38
|
+
end
|
39
|
+
|
40
|
+
events = service.events
|
41
|
+
puts "\nFUTURE EVENTS: #{events.count}"
|
42
|
+
events.each do |event|
|
43
|
+
event_start = event.start.date_time.try(:strftime, "%Y-%m-%d %H:%M") || event.start.date.try(:strftime, "%Y-%m-%d")
|
44
|
+
event_end = event.end.date_time.try(:strftime, "%Y-%m-%d %H:%M") || event.end.date.try(:strftime, "%Y-%m-%d")
|
45
|
+
puts " + #{event_start} ... #{event_end} (#{event.class})"
|
46
|
+
end
|
47
|
+
|
48
|
+
service.execute
|
49
|
+
puts "\n-----------------------"
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
# @example bundle exec rake clear_calendars
|
54
|
+
task :clear_calendars do
|
55
|
+
page = MyBanner::Schedule.new
|
56
|
+
sections = page.sections
|
57
|
+
sections.each do |section|
|
58
|
+
service = MyBanner::CalendarService.new(section)
|
59
|
+
service.send(:delete_events)
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
# @example bundle exec rake create_spreadsheets
|
64
|
+
task :create_spreadsheets do
|
65
|
+
page = MyBanner::Schedule.new
|
66
|
+
sections = page.sections
|
67
|
+
|
68
|
+
puts "-----------------------"
|
69
|
+
puts "SECTIONS: #{sections.count}"
|
70
|
+
puts "-----------------------"
|
71
|
+
|
72
|
+
sections.each do |section|
|
73
|
+
|
74
|
+
puts "\nSECTION: #{section.abbreviation} (#{section.title.upcase})\n"
|
75
|
+
course = section.course
|
76
|
+
start_month = section.term_start.strftime("%Y%m")
|
77
|
+
spreadsheet_title = "Gradebook - #{course} (#{start_month})"
|
78
|
+
|
79
|
+
service = MyBanner::SpreadsheetService.new(spreadsheet_title)
|
80
|
+
spreadsheet = service.spreadsheet
|
81
|
+
puts "SPREADSHEET: #{spreadsheet.properties.title.upcase} (#{spreadsheet.spreadsheet_id})"
|
82
|
+
puts "SHEETS:"
|
83
|
+
spreadsheet.sheets.each do |sheet|
|
84
|
+
grid_props = sheet.properties.grid_properties
|
85
|
+
puts " + #{sheet.properties.title.upcase} (#{grid_props.row_count} rows x #{grid_props.column_count} cols)"
|
86
|
+
end
|
87
|
+
|
88
|
+
#puts "DATA:"
|
89
|
+
#setter_response = service.update_values
|
90
|
+
#getter_response = service.client.get_spreadsheet_values(spreadsheet.spreadsheet_id, setter_response.updated_range)
|
91
|
+
#getter_response.values.each do |row|
|
92
|
+
# puts " #{row.join(" | ")}"
|
93
|
+
#end
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
# @example bundle exec rake delete_spreadsheets
|
98
|
+
task :delete_spreadsheets do
|
99
|
+
page = MyBanner::Schedule.new
|
100
|
+
sections = page.sections
|
101
|
+
|
102
|
+
puts "-----------------------"
|
103
|
+
puts "SECTIONS: #{sections.count}"
|
104
|
+
puts "-----------------------"
|
105
|
+
|
106
|
+
sections.each do |section|
|
107
|
+
puts "\nSECTION: #{section.abbreviation} (#{section.title.upcase})\n"
|
108
|
+
course = section.course
|
109
|
+
start_month = section.term_start.strftime("%Y%m")
|
110
|
+
spreadsheet_title = "Gradebook - #{course} (#{start_month})"
|
111
|
+
service = MyBanner::SpreadsheetService.new(spreadsheet_title)
|
112
|
+
|
113
|
+
spreadsheet = service.spreadsheet
|
114
|
+
puts "SPREADSHEET: #{spreadsheet.properties.title.upcase} (#{spreadsheet.spreadsheet_id})"
|
115
|
+
puts "DELETING..."
|
116
|
+
service.send(:delete_spreadsheet) # temporary, helps to test file creation
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
#end
|
data/my_banner.gemspec
ADDED
@@ -0,0 +1,36 @@
|
|
1
|
+
|
2
|
+
lib = File.expand_path("../lib", __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require "my_banner/version"
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "my_banner"
|
8
|
+
spec.version = MyBanner::VERSION
|
9
|
+
spec.authors = ["MJ Rossetti"]
|
10
|
+
spec.email = ["prof.mj.rossetti@gmail.com", "mjr300@georgetown.edu"]
|
11
|
+
|
12
|
+
spec.summary = "This program processes detailed schedule information from your school's Ellucian Banner information system to generate Google Calendar events and/or Google Sheets gradebook files for each of your scheduled classes."
|
13
|
+
#spec.description = %q{TODO: Write a longer description or delete this line.}
|
14
|
+
spec.homepage = "https://github.com/prof-rossetti/my-banner-rb"
|
15
|
+
spec.license = "MIT"
|
16
|
+
|
17
|
+
spec.files = `git ls-files -z`.split("\x0").reject do |f|
|
18
|
+
f.match(%r{^(test|spec|features)/})
|
19
|
+
end
|
20
|
+
spec.bindir = "exe"
|
21
|
+
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
22
|
+
spec.require_paths = ["lib"]
|
23
|
+
|
24
|
+
spec.add_dependency "activesupport", "~> 5.2"
|
25
|
+
spec.add_dependency "google-api-client", "~> 0.27"
|
26
|
+
spec.add_dependency "nokogiri", '~> 1.9'
|
27
|
+
spec.add_dependency "pry" # really just for development purposes
|
28
|
+
|
29
|
+
spec.add_development_dependency "bundler", "~> 1.16"
|
30
|
+
spec.add_development_dependency "factory_bot", "~> 4.11"
|
31
|
+
spec.add_development_dependency "rake", "~> 10.0"
|
32
|
+
spec.add_development_dependency "rspec", "~> 3.0"
|
33
|
+
spec.add_development_dependency "webmock", "~> 3.4"
|
34
|
+
spec.add_development_dependency "simplecov", "~> 0.16"
|
35
|
+
spec.add_development_dependency "simplecov-console", "~> 0.4"
|
36
|
+
end
|
data/pages/.gitignore
ADDED
metadata
ADDED
@@ -0,0 +1,234 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: my_banner
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- MJ Rossetti
|
8
|
+
autorequire:
|
9
|
+
bindir: exe
|
10
|
+
cert_chain: []
|
11
|
+
date: 2018-12-24 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: activesupport
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '5.2'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '5.2'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: google-api-client
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0.27'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0.27'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: nokogiri
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '1.9'
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '1.9'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: pry
|
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
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: bundler
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - "~>"
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '1.16'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - "~>"
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '1.16'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: factory_bot
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - "~>"
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '4.11'
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - "~>"
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '4.11'
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: rake
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - "~>"
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '10.0'
|
104
|
+
type: :development
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - "~>"
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '10.0'
|
111
|
+
- !ruby/object:Gem::Dependency
|
112
|
+
name: rspec
|
113
|
+
requirement: !ruby/object:Gem::Requirement
|
114
|
+
requirements:
|
115
|
+
- - "~>"
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: '3.0'
|
118
|
+
type: :development
|
119
|
+
prerelease: false
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
requirements:
|
122
|
+
- - "~>"
|
123
|
+
- !ruby/object:Gem::Version
|
124
|
+
version: '3.0'
|
125
|
+
- !ruby/object:Gem::Dependency
|
126
|
+
name: webmock
|
127
|
+
requirement: !ruby/object:Gem::Requirement
|
128
|
+
requirements:
|
129
|
+
- - "~>"
|
130
|
+
- !ruby/object:Gem::Version
|
131
|
+
version: '3.4'
|
132
|
+
type: :development
|
133
|
+
prerelease: false
|
134
|
+
version_requirements: !ruby/object:Gem::Requirement
|
135
|
+
requirements:
|
136
|
+
- - "~>"
|
137
|
+
- !ruby/object:Gem::Version
|
138
|
+
version: '3.4'
|
139
|
+
- !ruby/object:Gem::Dependency
|
140
|
+
name: simplecov
|
141
|
+
requirement: !ruby/object:Gem::Requirement
|
142
|
+
requirements:
|
143
|
+
- - "~>"
|
144
|
+
- !ruby/object:Gem::Version
|
145
|
+
version: '0.16'
|
146
|
+
type: :development
|
147
|
+
prerelease: false
|
148
|
+
version_requirements: !ruby/object:Gem::Requirement
|
149
|
+
requirements:
|
150
|
+
- - "~>"
|
151
|
+
- !ruby/object:Gem::Version
|
152
|
+
version: '0.16'
|
153
|
+
- !ruby/object:Gem::Dependency
|
154
|
+
name: simplecov-console
|
155
|
+
requirement: !ruby/object:Gem::Requirement
|
156
|
+
requirements:
|
157
|
+
- - "~>"
|
158
|
+
- !ruby/object:Gem::Version
|
159
|
+
version: '0.4'
|
160
|
+
type: :development
|
161
|
+
prerelease: false
|
162
|
+
version_requirements: !ruby/object:Gem::Requirement
|
163
|
+
requirements:
|
164
|
+
- - "~>"
|
165
|
+
- !ruby/object:Gem::Version
|
166
|
+
version: '0.4'
|
167
|
+
description:
|
168
|
+
email:
|
169
|
+
- prof.mj.rossetti@gmail.com
|
170
|
+
- mjr300@georgetown.edu
|
171
|
+
executables: []
|
172
|
+
extensions: []
|
173
|
+
extra_rdoc_files: []
|
174
|
+
files:
|
175
|
+
- ".codeclimate.yml"
|
176
|
+
- ".gitignore"
|
177
|
+
- ".rspec"
|
178
|
+
- ".ruby_version"
|
179
|
+
- ".travis.yml"
|
180
|
+
- CONTRIBUTING.md
|
181
|
+
- CREDITS.md
|
182
|
+
- Gemfile
|
183
|
+
- Gemfile.lock
|
184
|
+
- LICENSE.md
|
185
|
+
- README.md
|
186
|
+
- Rakefile
|
187
|
+
- auth/.gitignore
|
188
|
+
- bin/console
|
189
|
+
- bin/setup
|
190
|
+
- lib/my_banner.rb
|
191
|
+
- lib/my_banner/calendar_authorization.rb
|
192
|
+
- lib/my_banner/calendar_client.rb
|
193
|
+
- lib/my_banner/calendar_service.rb
|
194
|
+
- lib/my_banner/drive_authorization.rb
|
195
|
+
- lib/my_banner/drive_client.rb
|
196
|
+
- lib/my_banner/google_authorization.rb
|
197
|
+
- lib/my_banner/schedule.rb
|
198
|
+
- lib/my_banner/schedule/tableset.rb
|
199
|
+
- lib/my_banner/section.rb
|
200
|
+
- lib/my_banner/section/meeting.rb
|
201
|
+
- lib/my_banner/spreadsheet_authorization.rb
|
202
|
+
- lib/my_banner/spreadsheet_client.rb
|
203
|
+
- lib/my_banner/spreadsheet_service.rb
|
204
|
+
- lib/my_banner/version.rb
|
205
|
+
- lib/tasks/my_banner.rake
|
206
|
+
- my_banner.gemspec
|
207
|
+
- pages/.gitignore
|
208
|
+
homepage: https://github.com/prof-rossetti/my-banner-rb
|
209
|
+
licenses:
|
210
|
+
- MIT
|
211
|
+
metadata: {}
|
212
|
+
post_install_message:
|
213
|
+
rdoc_options: []
|
214
|
+
require_paths:
|
215
|
+
- lib
|
216
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
217
|
+
requirements:
|
218
|
+
- - ">="
|
219
|
+
- !ruby/object:Gem::Version
|
220
|
+
version: '0'
|
221
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
222
|
+
requirements:
|
223
|
+
- - ">="
|
224
|
+
- !ruby/object:Gem::Version
|
225
|
+
version: '0'
|
226
|
+
requirements: []
|
227
|
+
rubyforge_project:
|
228
|
+
rubygems_version: 2.7.3
|
229
|
+
signing_key:
|
230
|
+
specification_version: 4
|
231
|
+
summary: This program processes detailed schedule information from your school's Ellucian
|
232
|
+
Banner information system to generate Google Calendar events and/or Google Sheets
|
233
|
+
gradebook files for each of your scheduled classes.
|
234
|
+
test_files: []
|