marmoset 1.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.
- data/bin/marmoset +189 -0
- metadata +115 -0
data/bin/marmoset
ADDED
@@ -0,0 +1,189 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'rubygems'
|
4
|
+
require 'mechanize'
|
5
|
+
require 'highline/import'
|
6
|
+
require 'choice'
|
7
|
+
|
8
|
+
HighLine.track_eof = false
|
9
|
+
|
10
|
+
class MarmosetClient
|
11
|
+
class InvalidLogin < StandardError; end
|
12
|
+
class CourseNotFound < StandardError; end
|
13
|
+
class ProblemNotFound < StandardError; end
|
14
|
+
|
15
|
+
def initialize(opts)
|
16
|
+
@agent = Mechanize.new
|
17
|
+
@course_index_page = nil
|
18
|
+
@course_page = nil
|
19
|
+
@submit_page = nil
|
20
|
+
|
21
|
+
@filename = opts[:filename]
|
22
|
+
@username = opts[:username]
|
23
|
+
@password = opts[:password]
|
24
|
+
@course = opts[:course]
|
25
|
+
@problem = opts[:problem]
|
26
|
+
end
|
27
|
+
|
28
|
+
def login
|
29
|
+
@username ||= ask("Username: ")
|
30
|
+
@password ||= ask("Password: ") {|q| q.echo = '*'}
|
31
|
+
|
32
|
+
say "Logging in ..."
|
33
|
+
|
34
|
+
login_page = @agent.get 'https://marmoset.student.cs.uwaterloo.ca/'
|
35
|
+
form = login_page.forms.first
|
36
|
+
|
37
|
+
form.username = @username
|
38
|
+
form.password = @password
|
39
|
+
|
40
|
+
login_submit_page = @agent.submit form
|
41
|
+
|
42
|
+
if login_submit_page.uri.to_s.include? 'cas.uwaterloo.ca'
|
43
|
+
raise InvalidLogin
|
44
|
+
end
|
45
|
+
|
46
|
+
@course_index_page = @agent.submit login_submit_page.forms.first
|
47
|
+
rescue InvalidLogin
|
48
|
+
say 'Invalid Username/Password'
|
49
|
+
exit
|
50
|
+
end
|
51
|
+
|
52
|
+
def select_course
|
53
|
+
say "Select course ..."
|
54
|
+
login if @course_index_page.nil?
|
55
|
+
|
56
|
+
course_links = @course_index_page.links.find_all do |l|
|
57
|
+
l.href.include? 'course.jsp'
|
58
|
+
end
|
59
|
+
|
60
|
+
if @course.nil?
|
61
|
+
choose do |menu|
|
62
|
+
course_links.each do |course_link|
|
63
|
+
menu.choice(course_link.text.strip) do
|
64
|
+
@course = course_link.text.strip
|
65
|
+
@course_page = course_link.click
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
else
|
70
|
+
course_link = course_links.find do |l|
|
71
|
+
l.text.downcase.include? @course.downcase
|
72
|
+
end
|
73
|
+
raise CourseNotFound if course_link.nil?
|
74
|
+
|
75
|
+
@course_page = course_link.click
|
76
|
+
end
|
77
|
+
rescue CourseNotFound
|
78
|
+
say "Course #{@course} could not be found."
|
79
|
+
options = course_links.collect{|x| x.text.gsub(/\([^\)]+\):/,'').strip}
|
80
|
+
say "Options are: #{options.sort.join(', ')}"
|
81
|
+
exit
|
82
|
+
end
|
83
|
+
|
84
|
+
def select_problem
|
85
|
+
say "Selecting problem ..."
|
86
|
+
select_course if @course_page.nil?
|
87
|
+
|
88
|
+
problem_links = {}
|
89
|
+
|
90
|
+
@course_page.links.find_all{|l| l.href.include? 'submitProject.jsp'}.each do |view_link|
|
91
|
+
index = @course_page.links.find_index{|l| l.href == view_link.href}
|
92
|
+
named_link = @course_page.links[index-2]
|
93
|
+
problem_links[named_link.text] = view_link
|
94
|
+
end
|
95
|
+
|
96
|
+
if @problem.nil?
|
97
|
+
choose do |menu|
|
98
|
+
problem_links.each do |(name,problem_link)|
|
99
|
+
menu.choice(name.strip) do
|
100
|
+
@problem = name
|
101
|
+
@submit_page = problem_page.click
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
105
|
+
else
|
106
|
+
problem_link = problem_links.find{|(prob_name,link)|
|
107
|
+
prob_name.downcase.include? @problem.downcase
|
108
|
+
}
|
109
|
+
raise ProblemNotFound if problem_link.nil?
|
110
|
+
|
111
|
+
problem_link = problem_link[1]
|
112
|
+
@submit_page = problem_link.click
|
113
|
+
end
|
114
|
+
rescue ProblemNotFound
|
115
|
+
say "Problem #{@problem} could not be found in #{@course}"
|
116
|
+
say "Options are: #{problem_links.collect{|x| x[0].strip}.sort.join(', ')}"
|
117
|
+
exit
|
118
|
+
end
|
119
|
+
|
120
|
+
def submit_problem
|
121
|
+
say "Submitting ..."
|
122
|
+
select_problem if @submit_page.nil?
|
123
|
+
|
124
|
+
form = @submit_page.forms.first
|
125
|
+
@submit_page.forms.first.file_uploads.first.file_name = @filename
|
126
|
+
@submit_response_page = @agent.submit(form)
|
127
|
+
say "Assignment submitted succesfully"
|
128
|
+
rescue Mechanize::ResponseCodeError => e
|
129
|
+
say "There was a problem submitting your assignment. Submit manually"
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
PROGRAM_VERSION = 1.0
|
134
|
+
|
135
|
+
Choice.options do
|
136
|
+
option :username do
|
137
|
+
short '-u'
|
138
|
+
long '--username=USERNAME'
|
139
|
+
desc 'Your Quest userid, e.g. jlfwong'
|
140
|
+
default nil
|
141
|
+
end
|
142
|
+
|
143
|
+
option :password do
|
144
|
+
short '-p'
|
145
|
+
long '--password=PASSWORD'
|
146
|
+
desc 'Your Quest password. Will be prompted if not specified'
|
147
|
+
default nil
|
148
|
+
end
|
149
|
+
|
150
|
+
option :course do
|
151
|
+
short '-c'
|
152
|
+
long '--course-code=COURSECODE'
|
153
|
+
desc 'Course ID, e.g. CS241'
|
154
|
+
default nil
|
155
|
+
end
|
156
|
+
|
157
|
+
option :problem do
|
158
|
+
short '-a'
|
159
|
+
long '--assignment-problem=PROB'
|
160
|
+
desc 'Assignment problem name, e.g. A1P4'
|
161
|
+
end
|
162
|
+
|
163
|
+
option :filename, :required => true do
|
164
|
+
short '-f'
|
165
|
+
long '--infile=FILENAME'
|
166
|
+
desc 'The file to submit to marmoset'
|
167
|
+
end
|
168
|
+
|
169
|
+
option :help do
|
170
|
+
long '--help'
|
171
|
+
desc 'Show this message'
|
172
|
+
end
|
173
|
+
|
174
|
+
option :version do
|
175
|
+
short '-v'
|
176
|
+
long '--version'
|
177
|
+
desc 'Show Version'
|
178
|
+
action do
|
179
|
+
puts "#{File.basename(__FILE__)} Marmoset CLI v#{PROGRAM_VERSION}"
|
180
|
+
exit
|
181
|
+
end
|
182
|
+
end
|
183
|
+
end
|
184
|
+
|
185
|
+
client = MarmosetClient.new(Choice.choices)
|
186
|
+
client.login
|
187
|
+
client.select_course
|
188
|
+
client.select_problem
|
189
|
+
client.submit_problem
|
metadata
ADDED
@@ -0,0 +1,115 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: marmoset
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
hash: 21
|
5
|
+
prerelease: false
|
6
|
+
segments:
|
7
|
+
- 1
|
8
|
+
- 0
|
9
|
+
- 1
|
10
|
+
version: 1.0.1
|
11
|
+
platform: ruby
|
12
|
+
authors:
|
13
|
+
- Jamie Wong
|
14
|
+
autorequire:
|
15
|
+
bindir: bin
|
16
|
+
cert_chain: []
|
17
|
+
|
18
|
+
date: 2010-09-21 00:00:00 -04:00
|
19
|
+
default_executable:
|
20
|
+
dependencies:
|
21
|
+
- !ruby/object:Gem::Dependency
|
22
|
+
name: highline
|
23
|
+
prerelease: false
|
24
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ">="
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
hash: 13
|
30
|
+
segments:
|
31
|
+
- 1
|
32
|
+
- 6
|
33
|
+
- 1
|
34
|
+
version: 1.6.1
|
35
|
+
type: :runtime
|
36
|
+
version_requirements: *id001
|
37
|
+
- !ruby/object:Gem::Dependency
|
38
|
+
name: mechanize
|
39
|
+
prerelease: false
|
40
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ">="
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
hash: 23
|
46
|
+
segments:
|
47
|
+
- 1
|
48
|
+
- 0
|
49
|
+
- 0
|
50
|
+
version: 1.0.0
|
51
|
+
type: :runtime
|
52
|
+
version_requirements: *id002
|
53
|
+
- !ruby/object:Gem::Dependency
|
54
|
+
name: choice
|
55
|
+
prerelease: false
|
56
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
57
|
+
none: false
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
hash: 19
|
62
|
+
segments:
|
63
|
+
- 0
|
64
|
+
- 1
|
65
|
+
- 4
|
66
|
+
version: 0.1.4
|
67
|
+
type: :runtime
|
68
|
+
version_requirements: *id003
|
69
|
+
description: A utility using highline, mechanize and choice to submit to UW Marmoset from the command line
|
70
|
+
email:
|
71
|
+
- jamie.lf.wong@gmail.com
|
72
|
+
executables:
|
73
|
+
- marmoset
|
74
|
+
extensions: []
|
75
|
+
|
76
|
+
extra_rdoc_files: []
|
77
|
+
|
78
|
+
files:
|
79
|
+
- bin/marmoset
|
80
|
+
has_rdoc: true
|
81
|
+
homepage: http://github.com/phleet/MarmosetSubmit
|
82
|
+
licenses: []
|
83
|
+
|
84
|
+
post_install_message:
|
85
|
+
rdoc_options: []
|
86
|
+
|
87
|
+
require_paths:
|
88
|
+
- lib
|
89
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
90
|
+
none: false
|
91
|
+
requirements:
|
92
|
+
- - ">="
|
93
|
+
- !ruby/object:Gem::Version
|
94
|
+
hash: 3
|
95
|
+
segments:
|
96
|
+
- 0
|
97
|
+
version: "0"
|
98
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
99
|
+
none: false
|
100
|
+
requirements:
|
101
|
+
- - ">="
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
hash: 3
|
104
|
+
segments:
|
105
|
+
- 0
|
106
|
+
version: "0"
|
107
|
+
requirements: []
|
108
|
+
|
109
|
+
rubyforge_project:
|
110
|
+
rubygems_version: 1.3.7
|
111
|
+
signing_key:
|
112
|
+
specification_version: 3
|
113
|
+
summary: Submit to UW Marmoset from the command line
|
114
|
+
test_files: []
|
115
|
+
|