mypage_tools 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 22802225cc96365c393cd16775b504bf8e49d37c
4
+ data.tar.gz: 3d585f0cc41fcee1a98a27c6d4b7c87b17e96c61
5
+ SHA512:
6
+ metadata.gz: 756f3a6075e5d983063c5a4b9c15ba85061dd075450e09c29fc8c109e2833e973d6545d7875ecfa3d539cd31f3c260b8342ce241953bde8b7416f12fa4a12477
7
+ data.tar.gz: ff404bc6df53c0d386efd83d7a8681bce39beca95488dba96174eaa107c6d5a01211722ed95bb189aa8db0f49103e0bd06e513b15fc721c1586d5d66af16c702
data/.gitignore ADDED
@@ -0,0 +1,17 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in mypage_tools.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2014 Brown Mike
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.
data/README.md ADDED
@@ -0,0 +1,42 @@
1
+ # MypageTools
2
+
3
+ A work in progress. Very primitive right now.
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ gem 'mypage_tools'
10
+
11
+ And then execute:
12
+
13
+ $ bundle
14
+
15
+ Or install it yourself as:
16
+
17
+ $ gem install mypage_tools
18
+
19
+ ## Requirements
20
+
21
+ For now you need [PhantomJS](http://phantomjs.org) and [Ruby 2.0](http://www.ruby-lang.org/en/downloads/) or greater installed.
22
+
23
+ If you have [Homebrew](http://brew.sh) installed you can just
24
+
25
+ $ brew install phantomjs
26
+
27
+ ## Usage
28
+
29
+ $ mypage
30
+
31
+ ## TODO:
32
+ + Automagically handle PhantomJS dependency
33
+ + Output to one .ics file starting from the first day you don't have a schedule for
34
+ + Write tests! :-X
35
+
36
+ ## Contributing
37
+
38
+ 1. Fork it
39
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
40
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
41
+ 4. Push to the branch (`git push origin my-new-feature`)
42
+ 5. Create new Pull Request
data/Rakefile ADDED
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
data/bin/mypage ADDED
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "mypage_tools"
4
+
5
+ MypageTools::CLI.parse_options
@@ -0,0 +1,25 @@
1
+ # Voodoo to make Capybara do what I want.
2
+ # Ripped off nearly wholesale from a random blog after hours of Googling.
3
+ module CapybaraWithPhantomJs
4
+ include Capybara::DSL
5
+
6
+ def new_session
7
+ Capybara.register_driver :poltergeist do |app|
8
+ Capybara::Poltergeist::Driver.new(app)
9
+ end
10
+
11
+ Capybara.configure do |config|
12
+ config.run_server = false # Aparrently I have to do this if I'm not locally testing
13
+ config.default_driver = :poltergeist
14
+ config.default_selector = :xpath
15
+ config.ignore_hidden_elements = true
16
+ config.app_host = "https://mypage.apple.com"
17
+ end
18
+
19
+ @session = Capybara::Session.new(:poltergeist)
20
+
21
+ @session.driver.headers = { "User-Agent" => "Mozilla/5.0 (Macintosh; Intel Mac OS X" }
22
+
23
+ @session
24
+ end
25
+ end
@@ -0,0 +1,48 @@
1
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
2
+ # #
3
+ # USELESS COMMENT BOX BY: #
4
+ # #
5
+ # ___ ___ _ _ #
6
+ # | \ / | o | | / /____ #
7
+ # | |\ \/ /| | _ | |/ // __ \ #
8
+ # | | \__/ | || || (/ ____\ #
9
+ # | | | || || |\ \ \___ #
10
+ # |_| |_||_||_| \_\_____\ #
11
+ # ____ #
12
+ # | \ #
13
+ # | - ) _____ ___ __ __ __ #
14
+ # | __/ | ___\ / _ \\ \ __ / // \ #
15
+ # | \ | | | | | |\ \ / \ / /| /\ | #
16
+ # | - )| | | |_| | \ \/ /\ \/ / | | | | #
17
+ # |____/ |_| \ ___ / \__/ \__/ |_| |_| #
18
+ # #
19
+ # #
20
+ # TODO: Compare gathered data to existing .ics files #
21
+ # and inform of any changes to schedule #
22
+ # #
23
+ # TODO: Add ability to automagically import to #
24
+ # Calendar application #
25
+ # #
26
+ # TODO: GUI? Bah. Probably not. #
27
+ # #
28
+ # TODO: Check timecard against schedule for possible #
29
+ # missing punches? #
30
+ # #
31
+ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
32
+
33
+ require "capybara/dsl"
34
+ require "capybara/poltergeist"
35
+ require "icalendar"
36
+ require "io/console"
37
+ require "active_support/core_ext"
38
+ require "mypage_tools/version"
39
+ require "capybara_with_phantom_js"
40
+ require "mypage_tools/shift"
41
+ require "mypage_tools/weekly_schedule"
42
+ require "mypage_tools/schedule_scraper"
43
+ require "mypage_tools/schedule_page"
44
+ require "mypage_tools/cli"
45
+
46
+ module MypageTools
47
+ SCHEDULE_DIR = File.join(Dir.home, "myPage Schedule")
48
+ end
@@ -0,0 +1,56 @@
1
+ module MypageTools
2
+ class CLI
3
+ def self.parse_options args=ARGV
4
+ case args[0]
5
+ when "schedule"
6
+ schedule
7
+ when "help"
8
+ self.help
9
+ else
10
+ puts "\nUnkown Argument\n"
11
+ self.help
12
+ end
13
+ end
14
+
15
+ def self.schedule
16
+ print `clear`
17
+ puts "In order to get your work schedule you need to provide your login and password for myPage."
18
+ print "Login: "
19
+ ARGV.clear
20
+ login = gets.chomp
21
+ password = get_password
22
+ puts "\n"
23
+ scrape_session = ScheduleScraper.new login, password
24
+ scrape_session.schedule_page
25
+ while scrape_session.schedule_available?
26
+ scrape_session.generate_schedule
27
+ scrape_session.next_week
28
+ break if scrape_session.no_schedule_available? # Loop not breaking w/out this line. Need to investigate.
29
+ end
30
+ puts "\nNo further schedules available."
31
+ print `open #{Dir.home}/myPage\\ Schedule`
32
+ end
33
+
34
+ def self.help # hahaha
35
+ puts ""
36
+ puts "The only implemented feature currently is getting your schedule"
37
+ puts ""
38
+ puts "USAGE:"
39
+ puts "\tmypage schedule"
40
+ puts ""
41
+ end
42
+
43
+ private
44
+ if STDIN.respond_to?(:noecho)
45
+ def self.get_password
46
+ print "Password: "
47
+ STDIN.noecho(&:gets).chomp
48
+ end
49
+ else
50
+ # Legacy support for Ruby < 1.9
51
+ def self.get_password
52
+ `read -s -p "Password: " password; echo $password`.chomp
53
+ end
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,74 @@
1
+ module MypageTools
2
+ class SchedulePage
3
+ # Expects the myPage schedule page as a Nokogiri HTML object
4
+ def initialize page
5
+ @page = page
6
+ end
7
+
8
+ # Return string containing the date the week begins, i.e. "Sep 14, 2013"
9
+ # Matches from the raw_schedule_text using a regex
10
+ # http://rubular.com/r/OjRZ0q6cko
11
+ def week_begins
12
+ unless @week_begins
13
+ @week_begins = raw_schedule_text.scan(/\w+\s\d{1,2},\s\d{4}/)[0]
14
+ end
15
+ @week_begins
16
+ end
17
+
18
+ # Gross & Ugly.
19
+ # Returns an array where every item is a Shift object
20
+ def shift_array
21
+ unless @shift_array
22
+ @shift_array = []
23
+ days_of_week = %w[Saturday Sunday Monday Tuesday Wednesday Thursday Friday]
24
+
25
+ # Establishing variable scope
26
+ current_day = nil
27
+ current_date = nil
28
+ index_counter = 0
29
+ shift = nil
30
+
31
+ # Finds a day then creates shifts for that day from each following pair of times
32
+ raw_schedule_array.each do |item|
33
+ if days_of_week.member?(item)
34
+ current_day = item
35
+ # Figure out the date of the shift based on the day of the week & start date of the week
36
+ current_date = Date.parse(week_begins) + days_of_week.index(item)
37
+ index_counter = 0
38
+ elsif index_counter == 0
39
+ shift = Shift.new
40
+ shift.day_of_week = current_day
41
+ shift.date = current_date
42
+ shift.start = item
43
+ index_counter += 1
44
+ elsif index_counter == 1
45
+ shift.stop = item
46
+ index_counter = 0
47
+ @shift_array << shift
48
+ end
49
+ end
50
+ end
51
+ @shift_array
52
+ end
53
+
54
+ private
55
+ # Returns a string with all the necessary information to extract that week's schedule
56
+ def raw_schedule_text
57
+ unless @raw_schedule_text
58
+ xpath_to_schedule = "//div[@id = 'contentTimecard']/div/table/tbody/tr/td/table/tbody"
59
+ @raw_schedule_text = @page.search(xpath_to_schedule).text
60
+ end
61
+ @raw_schedule_text
62
+ end
63
+
64
+ # Data structure for schedule: [Day, Start, End, Day, Start, End, (Start), (End), etc...]
65
+ # Matched from the raw_schedule_text with a regex
66
+ # http://rubular.com/r/xOOFBOKFMM
67
+ def raw_schedule_array
68
+ unless @raw_schedule_array
69
+ @raw_schedule_array = raw_schedule_text.scan /[SMTWF]\w{2,5}day|\d{1,2}:\d{2}[A|P]M/
70
+ end
71
+ @raw_schedule_array
72
+ end
73
+ end
74
+ end
@@ -0,0 +1,103 @@
1
+ module MypageTools
2
+ class ScheduleScraper
3
+ include CapybaraWithPhantomJs
4
+
5
+ def initialize username, password
6
+ @username = username
7
+ @password = password
8
+ end
9
+
10
+ def schedule_page
11
+ unless @schedule_page
12
+ new_session
13
+ visit "/"
14
+ wait_for(:wait_message => "Loading Login Page") { page.has_content? "Account Name" }
15
+ login
16
+ click_link "myTime"
17
+ wait_for(:wait_message => "Loading Timecard") { page.has_content? "Current Timecard" }
18
+ click_link "Schedule"
19
+ wait_for(:wait_message => "Checking for available schedule") { schedule_available? }
20
+ @schedule_page = SchedulePage.new(Nokogiri::HTML.parse(page.html))
21
+ end
22
+ @schedule_page
23
+ end
24
+
25
+ def schedule_available?
26
+ page.has_text? /Schedule\sbegins\s\w+\s\d{1,2},\s\d{4}/
27
+ end
28
+
29
+ def no_schedule_available?
30
+ page.has_text? "Schedule is not available for the selected week"
31
+ end
32
+
33
+ def generate_schedule
34
+ schedule = WeeklySchedule.new @schedule_page.week_begins, @schedule_page.shift_array
35
+ schedule.to_ics
36
+ end
37
+
38
+ def next_week
39
+ next_week_begins_date = Date.parse(@schedule_page.week_begins) + 7
40
+ if date_in_current_month? next_week_begins_date
41
+ click_calendar_day(next_week_begins_date)
42
+ @schedule_page = SchedulePage.new(Nokogiri::HTML.parse(page.html))
43
+ else
44
+ click_next_month next_week_begins_date
45
+ click_calendar_day(next_week_begins_date)
46
+ @schedule_page = SchedulePage.new(Nokogiri::HTML.parse(page.html))
47
+ end
48
+ end
49
+
50
+ private
51
+ def login
52
+ fill_in "appleId", with: @username
53
+ fill_in "accountPassword", with: @password
54
+ click_on "submitButton2"
55
+ wait_for(:wait_message => "Logging in") { page.has_button? "Sign Out" }
56
+ end
57
+
58
+ def date_in_current_month? date
59
+ Date.parse(@schedule_page.week_begins).month == date.month
60
+ end
61
+
62
+ def click_calendar_day date
63
+ day_number = date.day.to_s
64
+ within("//div[@id = 'calendar-#{date.year}-#{date.month - 1}']") do
65
+ # BUG FIX -> capybara finding multiple elements, use regex to exact match date
66
+ find("//td[@class = 'weekend']", text: /\A#{day_number}\z/).click
67
+ end
68
+ wait_for(:wait_message => "Loading next week") do
69
+ page.has_content?("Schedule begins #{date.strftime("%b %d, %Y")}") || no_schedule_available?
70
+ end
71
+ end
72
+
73
+ # Clicks on the little arrow on the calendar to load the next month
74
+ def click_next_month date
75
+ find("//img[@id = 'right' and @class = 'arrow']").click
76
+ wait_for { page.has_content? "#{date.strftime("%B %Y")}" }
77
+ end
78
+
79
+ # Helper method to allow waiting for a specific thing on the page to load
80
+ # Times out after 10 seconds (1+2+3+4)
81
+ # Expects a block that returns a boolean value
82
+ def wait_for options={}
83
+ options.reverse_merge!({fail_message: "Request Timed Out"})
84
+ wait_message = options[:wait_message]
85
+ latency = 0
86
+ print "\n" << wait_message << "..." if wait_message
87
+ while latency < 6
88
+ latency.times { print "." } if wait_message
89
+ sleep latency
90
+ if yield
91
+ print "\n" if wait_message
92
+ return true
93
+ end
94
+ latency += 1
95
+ end
96
+ abort format_failure(options[:fail_message])
97
+ end
98
+
99
+ def format_failure message
100
+ "\n" + ("#" * message.length) + "\n\n#{message}\n\n" + ("#" * message.length) + "\n\n"
101
+ end
102
+ end
103
+ end
@@ -0,0 +1,40 @@
1
+ module MypageTools
2
+ # Data structure to represent a single shift on a single day
3
+ class Shift
4
+ include Icalendar
5
+ attr_accessor :day_of_week, :date, :start, :stop
6
+
7
+ def initialize day_of_week=nil, date=nil, start=nil, stop=nil
8
+ @day_of_week = day_of_week
9
+ @date = date
10
+ @start = start
11
+ @stop = stop
12
+ end
13
+
14
+ def date
15
+ @date.strftime("%b %d, %Y")
16
+ end
17
+
18
+ def start
19
+ Time.parse(@start).strftime("%H:%M")
20
+ end
21
+
22
+ def stop
23
+ Time.parse(@stop).strftime("%H:%M")
24
+ end
25
+
26
+ def not_scheduled?
27
+ @start == "00:00AM" && @stop == "00:00AM"
28
+ end
29
+
30
+ def to_ical_event
31
+ event = Event.new
32
+ event.start = DateTime.parse(self.date + " " + self.start + " PST")
33
+ event.end = DateTime.parse(self.date + " " + self.stop + " PST")
34
+ event.description = "Work at Apple"
35
+ event.summary = "Work (Apple)"
36
+ event.location = "Apple Store University Village, 2656 Northeast University Village Street, Seattle, WA, US"
37
+ event
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,3 @@
1
+ module MypageTools
2
+ VERSION = "0.0.2"
3
+ end
@@ -0,0 +1,27 @@
1
+ module MypageTools
2
+ # Data structure to represent 1 week's Shifts
3
+ class WeeklySchedule
4
+ include Icalendar
5
+ attr_reader :week_begins
6
+
7
+ def initialize week_begins, shift_array
8
+ @week_begins = week_begins
9
+ @shift_array = shift_array
10
+ end
11
+
12
+ def to_ics
13
+ cal = Calendar.new
14
+ @shift_array.each do |shift|
15
+ cal.add_event shift.to_ical_event unless shift.not_scheduled?
16
+ end
17
+ cal.publish
18
+ cal_string = cal.to_ical
19
+
20
+ # TODO: Extract this elsewhere
21
+ FileUtils.mkdir(SCHEDULE_DIR) unless File.directory?(SCHEDULE_DIR)
22
+ file_name = File.join(SCHEDULE_DIR, "Schedule from #{@week_begins}.ics")
23
+ File.open(file_name, "w") { |io| io.write cal_string }
24
+ print "\nSaving schedule to:\n#{file_name}\n"
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,29 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'mypage_tools/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "mypage_tools"
8
+ spec.version = MypageTools::VERSION
9
+ spec.authors = ["Brown Mike"]
10
+ spec.email = ["thebrownmike@me.com"]
11
+ spec.description = %q{myPage tools for Apple Retail employees}
12
+ spec.summary = %q{myPage tools for Apple Retail employees}
13
+ spec.homepage = "https://www.github.com/brownmike/mypage_tools"
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files`.split($/)
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_runtime_dependency "capybara", "~> 2.2.1"
22
+ spec.add_runtime_dependency "poltergeist", "~> 1.5.0"
23
+ spec.add_runtime_dependency "icalendar", "~> 1.5.0"
24
+ spec.add_runtime_dependency "active_support", "~> 3.0.0"
25
+ spec.add_runtime_dependency "i18n"
26
+
27
+ spec.add_development_dependency "bundler", "~> 1.3"
28
+ spec.add_development_dependency "rake"
29
+ end
metadata ADDED
@@ -0,0 +1,158 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: mypage_tools
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.2
5
+ platform: ruby
6
+ authors:
7
+ - Brown Mike
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-02-06 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: capybara
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: 2.2.1
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: 2.2.1
27
+ - !ruby/object:Gem::Dependency
28
+ name: poltergeist
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: 1.5.0
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: 1.5.0
41
+ - !ruby/object:Gem::Dependency
42
+ name: icalendar
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: 1.5.0
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: 1.5.0
55
+ - !ruby/object:Gem::Dependency
56
+ name: active_support
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: 3.0.0
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: 3.0.0
69
+ - !ruby/object:Gem::Dependency
70
+ name: i18n
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :runtime
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: bundler
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - "~>"
88
+ - !ruby/object:Gem::Version
89
+ version: '1.3'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - "~>"
95
+ - !ruby/object:Gem::Version
96
+ version: '1.3'
97
+ - !ruby/object:Gem::Dependency
98
+ name: rake
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ">="
102
+ - !ruby/object:Gem::Version
103
+ version: '0'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ">="
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
111
+ description: myPage tools for Apple Retail employees
112
+ email:
113
+ - thebrownmike@me.com
114
+ executables:
115
+ - mypage
116
+ extensions: []
117
+ extra_rdoc_files: []
118
+ files:
119
+ - ".gitignore"
120
+ - Gemfile
121
+ - LICENSE.txt
122
+ - README.md
123
+ - Rakefile
124
+ - bin/mypage
125
+ - lib/capybara_with_phantom_js.rb
126
+ - lib/mypage_tools.rb
127
+ - lib/mypage_tools/cli.rb
128
+ - lib/mypage_tools/schedule_page.rb
129
+ - lib/mypage_tools/schedule_scraper.rb
130
+ - lib/mypage_tools/shift.rb
131
+ - lib/mypage_tools/version.rb
132
+ - lib/mypage_tools/weekly_schedule.rb
133
+ - mypage_tools.gemspec
134
+ homepage: https://www.github.com/brownmike/mypage_tools
135
+ licenses:
136
+ - MIT
137
+ metadata: {}
138
+ post_install_message:
139
+ rdoc_options: []
140
+ require_paths:
141
+ - lib
142
+ required_ruby_version: !ruby/object:Gem::Requirement
143
+ requirements:
144
+ - - ">="
145
+ - !ruby/object:Gem::Version
146
+ version: '0'
147
+ required_rubygems_version: !ruby/object:Gem::Requirement
148
+ requirements:
149
+ - - ">="
150
+ - !ruby/object:Gem::Version
151
+ version: '0'
152
+ requirements: []
153
+ rubyforge_project:
154
+ rubygems_version: 2.0.3
155
+ signing_key:
156
+ specification_version: 4
157
+ summary: myPage tools for Apple Retail employees
158
+ test_files: []