github-to-canvas 0.0.56 → 0.1.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,56 +1,160 @@
1
+ require 'byebug'
1
2
  require_relative './github-to-canvas/create_canvas_lesson'
2
3
  require_relative './github-to-canvas/update_canvas_lesson'
4
+ require_relative './github-to-canvas/canvas_dotfile'
5
+ require_relative './github-to-canvas/repository_interface'
3
6
  require_relative './github-to-canvas/repository_converter'
4
7
  require_relative './github-to-canvas/github_interface'
5
8
  require_relative './github-to-canvas/canvas_interface'
6
- require_relative './github-to-canvas/canvas_dotfile'
9
+ require_relative './github-to-canvas/course_creation_interface'
10
+
7
11
  require_relative './github-to-canvas/version'
8
12
 
13
+ require 'yaml'
14
+
9
15
  class GithubToCanvas
10
16
 
11
- def initialize(mode:,
12
- course:nil,
13
- id:nil,
14
- filepath:Dir.pwd,
15
- file_to_convert:'README.md',
16
- branch:'master',
17
- name:File.basename(Dir.getwd),
18
- type:"page",
19
- save_to_github:false,
20
- fis_links:false,
21
- remove_header_and_footer:false,
22
- only_update_content: false,
23
- forkable: false)
24
-
25
- if mode == 'version'
17
+ def initialize(options)
18
+ case options[:mode]
19
+ when 'version'
26
20
  puts VERSION
27
- end
28
-
29
- if mode == 'query'
30
- CanvasInterface.get_course_info(course, id)
31
- end
32
-
33
- if mode == 'remote'
34
- lesson_data = CanvasInterface.get_lesson_info(course, id)
35
- if !lesson_data[1]
36
- puts "No lesson with id #{id} was found in course #{course}."
37
- else
38
- pp lesson_data[0]
39
- puts "\nLesson Type: #{lesson_data[1]}"
40
- end
21
+ when 'query'
22
+ CanvasInterface.get_course_info(options[:course_id], options[:id])
23
+ when 'map'
24
+ CanvasInterface.map_course_info(options[:file_to_convert])
25
+ when 'csv'
26
+ CanvasInterface.csv(options[:file_to_convert])
27
+ when 'canvas_read'
28
+ puts CanvasInterface.read_lesson(options[:filepath])
29
+ when 'github_read'
30
+ markdown = GithubInterface.read_remote(options[:filepath])
31
+ puts RepositoryConverter.convert_to_html(markdown)
32
+ when 'create' # used with a local repo
33
+ html = RepositoryConverter.local_file_conversion(options)
34
+ name = RepositoryInterface.get_name(options[:filepath], html)
35
+ html = RepositoryConverter.adjust_converted_html(options, html)
36
+ response = CanvasInterface.create_lesson(options, name, html)
37
+ RepositoryInterface.local_repo_post_submission(options, response)
38
+ puts "Canvas lesson created. Lesson available at #{response['html_url']}"
39
+ when 'align' # used with a local repo
40
+ html = RepositoryConverter.local_file_conversion(options)
41
+ name = RepositoryInterface.get_name(options[:filepath], html)
42
+ html = RepositoryConverter.adjust_converted_html(options, html)
43
+ CanvasInterface.update_all_related_lessons(options, name, html)
41
44
 
45
+ when 'github_create'
46
+ html = RepositoryConverter.remote_file_conversion(options)
47
+ name = RepositoryInterface.get_name(options[:filepath], html)
48
+ html = RepositoryConverter.adjust_converted_html(options, html)
42
49
 
43
- end
50
+ response = CanvasInterface.create_lesson(options, name, html)
51
+
52
+ puts "Canvas lesson created. Lesson available at #{response['html_url']}"
53
+ when 'github_align'
54
+ html = RepositoryConverter.remote_file_conversion(options)
55
+ name = options[:name] ? options[:name] : RepositoryInterface.get_name(options[:filepath], html)
56
+ html = RepositoryConverter.adjust_converted_html(options, html)
57
+ response = CanvasInterface.update_existing_lesson(options, name, html)
58
+ puts "Canvas lesson updated. Lesson available at #{response['html_url']}"
59
+ when 'build_course'
60
+ course_yaml = YAML.load(File.read(options[:file_to_convert]))
61
+ # Create Course
62
+ created_course_info = CanvasInterface.create_course(course_yaml)
63
+ puts "Course created - #{created_course_info["id"]}"
44
64
 
45
- if mode == 'create'
46
- puts "github-to-canvas will now create a Canvas lesson based on the current repo"
47
- CreateCanvasLesson.new(course, filepath, file_to_convert, branch, name, type, save_to_github, fis_links, remove_header_and_footer, forkable)
48
- end
65
+ course_yaml[:modules].each { |module_info|
66
+ # Create each module
67
+ created_module_info = CanvasInterface.create_module(created_course_info["id"], module_info)
68
+ puts "Module created - #{created_module_info['name']}"
69
+ module_info[:lessons].each { |lesson|
70
+ # Create each lesson
71
+ options[:type] = lesson["type"].downcase
72
+ options[:course_id] = created_course_info["id"]
73
+ options[:filepath] = lesson["repository"]
74
+
75
+ html = RepositoryConverter.remote_file_conversion(options)
76
+ # Add each lesson to it's module
77
+ html = RepositoryConverter.adjust_converted_html(options, html)
78
+ created_lesson_info = CanvasInterface.create_lesson(options, lesson["title"], html)
79
+ lesson = lesson.merge(created_lesson_info)
80
+
81
+ lesson["page_url"] = lesson["url"] if !lesson["page_url"]
82
+
83
+ response = CanvasInterface.add_to_module(created_course_info["id"], created_module_info, lesson)
84
+
85
+ puts "Lesson added to #{created_module_info['name']} - #{lesson['title']}"
86
+ sleep(1)
87
+ }
88
+ }
89
+ when 'add_to_course'
90
+ course_yaml = YAML.load(File.read(options[:file_to_convert]))
49
91
 
50
- if mode == 'align'
51
- puts "github-to-canvas will now align any existing Canvas lessons based on the current repo. NOTE: .canvas file must be present"
52
- UpdateCanvasLesson.new(course, filepath, file_to_convert, branch, name, type, save_to_github, fis_links, remove_header_and_footer, only_update_content, id, forkable)
92
+ course_yaml[:modules].each { |module_info|
93
+ # Create each module
94
+ created_module_info = CanvasInterface.create_module(options[:course_id], module_info)
95
+ puts "Module created - #{created_module_info['name']}"
96
+ module_info[:lessons].each { |lesson|
97
+ # Create each lesson
98
+
99
+ options[:type] = lesson["type"].downcase
100
+ options[:filepath] = lesson["repository"]
101
+ html = RepositoryConverter.remote_file_conversion(options)
102
+ # Add each lesson to it's module
103
+ html = RepositoryConverter.adjust_converted_html(options, html)
104
+ created_lesson_info = CanvasInterface.create_lesson(options, lesson["title"], html)
105
+ lesson = lesson.merge(created_lesson_info)
106
+ response = CanvasInterface.add_to_module(options[:course_id], created_module_info, lesson)
107
+
108
+ puts "Lesson added to #{created_module_info['name']} - #{lesson['title']}"
109
+ sleep(1)
110
+ }
111
+ }
112
+ when 'update_course_lessons'
113
+ course_yaml = YAML.load(File.read(options[:file_to_convert]))
114
+ options[:course_id] = course_yaml[:id]
115
+ course_yaml[:modules].each { |module_info|
116
+ puts "Updating #{module_info[:name]}"
117
+ module_info[:lessons].each { |lesson|
118
+ if lesson["repository"] == ""
119
+ puts "No repository found for #{lesson['title']}"
120
+ next
121
+ end
122
+ options[:id] = lesson['id']
123
+ options[:type] = lesson["type"].downcase
124
+ options[:filepath] = lesson["repository"]
125
+ options[:branch] = 'master'
126
+ html = RepositoryConverter.remote_file_conversion(options)
127
+
128
+ html = RepositoryConverter.adjust_converted_html(options, html)
129
+ created_lesson_info = CanvasInterface.update_existing_lesson(options, lesson["title"], html)
130
+ lesson = lesson.merge(created_lesson_info)
131
+
132
+
133
+ puts "Lesson updated - #{lesson['title']}"
134
+ sleep(1)
135
+ }
136
+ }
137
+ when 'clone_course'
138
+ course_yaml = YAML.load(File.read(options[:file_to_convert]))
139
+ new_dir = "#{course_yaml[:name].downcase.gsub(' ','-')}"
140
+ cmd = "mkdir #{new_dir}"
141
+ `#{cmd}`
142
+ course_yaml[:modules].each { |module_info|
143
+ puts "Cloning #{module_info[:name]}"
144
+ module_info[:lessons].each { |lesson|
145
+ if lesson["repository"] == ""
146
+ puts "No repository found for #{lesson['title']}"
147
+ next
148
+ else
149
+ cmd = "git clone #{lesson['repository']}"
150
+ puts cmd
151
+ GithubInterface.cd_into_and(new_dir, cmd)
152
+ end
153
+ }
154
+ }
155
+ else
156
+ puts VERSION
53
157
  end
54
158
  end
55
-
159
+
56
160
  end
@@ -5,21 +5,21 @@ class CanvasDotfile
5
5
  File.file?(".canvas")
6
6
  end
7
7
 
8
- def self.update_or_create(filepath, response, course, type)
8
+ def self.update_or_create(options, response)
9
9
  if self.exists?
10
- if type == "assignment" || type == "discussion"
11
- canvas_data = self.update_assignment_data(response, course, type)
10
+ if options[:type] == "assignment" || options[:type] == "discussion"
11
+ canvas_data = self.update_assignment_data(response, options[:course_id], options[:type])
12
12
  else
13
- canvas_data = self.update_page_data(response, course, type)
13
+ canvas_data = self.update_page_data(response, options[:course_id], options[:type])
14
14
  end
15
15
  else
16
- if type == "assignment" || type == "discussion"
17
- canvas_data = self.create_assignment_data(response, course, type)
16
+ if options[:type] == "assignment" || options[:type] == "discussion"
17
+ canvas_data = self.create_assignment_data(response, options[:course_id], options[:type])
18
18
  else
19
- canvas_data = self.create_page_data(response, course, type)
19
+ canvas_data = self.create_page_data(response, options[:course_id], options[:type])
20
20
  end
21
21
  end
22
- self.create_canvas_dotfile(filepath, canvas_data)
22
+ self.create_canvas_dotfile(options[:filepath], canvas_data)
23
23
  end
24
24
 
25
25
  def self.create_canvas_dotfile(filepath, canvas_data)
@@ -64,7 +64,7 @@ class CanvasDotfile
64
64
 
65
65
  def self.update_page_data(response, course, type)
66
66
  canvas_data = YAML.load(File.read(".canvas"))
67
- if canvas_data[:lessons].none? { |lesson| lesson[:page_id] == response['page_id'] && lesson[:course_id] == course.to_i && lesson[:canvas_url] == response['html_url']}
67
+ if canvas_data[:lessons].none? { |lesson| lesson[:id] == response['page_id'] && lesson[:course_id] == course.to_i && lesson[:canvas_url] == response['html_url']}
68
68
  lesson_data = {
69
69
  id: response['page_id'],
70
70
  course_id: course.to_i,
@@ -1,7 +1,147 @@
1
+ require 'byebug'
1
2
  require 'json'
2
3
  require 'rest-client'
4
+ require 'yaml'
3
5
  class CanvasInterface
4
6
 
7
+ def self.create_course(course_info)
8
+ # POST /api/v1/accounts/:account_id/courses
9
+ url = "#{ENV['CANVAS_API_PATH']}/accounts/1/courses"
10
+ payload = {
11
+ 'course[name]' => course_info[:name],
12
+ 'course[course_code]' => course_info[:course_code]
13
+ }
14
+ response = RestClient.post(url, payload, self.headers)
15
+ JSON.parse(response)
16
+ end
17
+
18
+ def self.create_module(course_id, module_info)
19
+ # POST /api/v1/courses/:course_id/modules
20
+ url = "#{ENV['CANVAS_API_PATH']}/courses/#{course_id}/modules"
21
+ payload = {
22
+ 'module[name]' => module_info[:name]
23
+ }
24
+ response = RestClient.post(url, payload, headers={
25
+ "Authorization" => "Bearer #{ENV['CANVAS_API_KEY']}"
26
+ })
27
+ JSON.parse(response)
28
+ end
29
+
30
+ def self.create_lesson(options, name, html)
31
+ if options[:type] == 'discussion'
32
+ url = "#{ENV['CANVAS_API_PATH']}/courses/#{options[:course_id]}/#{options[:type]}_topics"
33
+ else
34
+ url = "#{ENV['CANVAS_API_PATH']}/courses/#{options[:course_id]}/#{options[:type]}s"
35
+ end
36
+ payload = self.build_payload(options, name, html)
37
+ begin
38
+ response = RestClient.post(url, payload, self.headers)
39
+ rescue
40
+ puts "Something went wrong while pushing lesson #{options[:id]} to course #{options[:course_id]}"
41
+ abort
42
+ end
43
+ if ![200, 201].include? response.code
44
+ puts "Canvas push failed. #{response.code} status code returned "
45
+ abort
46
+ end
47
+ JSON.parse(response.body)
48
+ end
49
+
50
+ def self.create_quiz(options, quiz_data)
51
+
52
+ end
53
+
54
+ def self.add_to_module(course_id, module_info, lesson_info)
55
+ # POST /api/v1/courses/:course_id/modules/:module_id/items
56
+ url = "#{ENV['CANVAS_API_PATH']}/courses/#{course_id}/modules/#{module_info["id"]}/items"
57
+
58
+ if lesson_info["type"] == "Page"
59
+ payload = {
60
+ 'module_item[title]' => lesson_info["title"],
61
+ 'module_item[type]' => lesson_info["type"],
62
+ 'module_item[indent]' => 0,
63
+ 'module_item[page_url]' => lesson_info["id"],
64
+ 'module_item[completion_requirement][type]' => 'must_view'
65
+ }
66
+ elsif lesson_info["type"] == "Quiz"
67
+ puts "Quiz needs to be added manually - #{lesson_info['title']} - lesson_info["
68
+ else
69
+
70
+ payload = {
71
+ 'module_item[title]' => lesson_info["title"],
72
+ 'module_item[type]' => lesson_info["type"],
73
+ 'module_item[indent]' => 1,
74
+ 'module_item[content_id]' => lesson_info["id"],
75
+ 'module_item[completion_requirement][type]' => 'must_submit'
76
+ }
77
+ end
78
+ begin
79
+ byebug
80
+ response = RestClient.post(url, payload, self.headers)
81
+ rescue
82
+ puts "Something went wrong while adding lesson #{lesson_info["id"]} to module #{module_info["id"]} in course #{course_id}" if lesson_info["type"] == "Assignment"
83
+ puts "Something went wrong while adding lesson #{lesson_info["page_url"]} to module #{module_info["id"]} in course #{course_id}" if lesson_info["type"] == "Page"
84
+ abort
85
+ end
86
+
87
+
88
+ response
89
+
90
+ end
91
+
92
+ def self.update_existing_lesson(options, name, html)
93
+ if options[:type] == "discussion"
94
+ url = "#{ENV['CANVAS_API_PATH']}/courses/#{options[:course_id]}/#{options[:type]}_topics/#{options[:id]}"
95
+ else
96
+ url = "#{ENV['CANVAS_API_PATH']}/courses/#{options[:course_id]}/#{options[:type]}s/#{options[:id]}"
97
+ end
98
+ payload = self.build_payload(options, name, html)
99
+
100
+ begin
101
+ headers = self.headers
102
+ if options[:type] == 'page' || options[:type] == 'Page'
103
+ response = RestClient.get(url, headers)
104
+ lesson_info = JSON.parse(response)
105
+ url = url.sub(/[^\/]+$/, lesson_info["page_id"].to_s)
106
+ end
107
+ response = RestClient.put(url, payload, headers)
108
+ rescue
109
+ puts "Something went wrong while pushing lesson #{options[:id]} to course #{options[:course_id]}"
110
+ puts "Make sure you are working on lessons that are not locked"
111
+ abort
112
+ ""
113
+ end
114
+ JSON.parse(response.body)
115
+ end
116
+
117
+ def self.update_all_related_lessons(options, name, html)
118
+ # Read the local .canvas file if --id <ID> is not used. Otherwise, use provided ID (--course <COURSE> also required)
119
+ if !options[:id]
120
+ canvas_data = CanvasDotfile.read_canvas_data
121
+ response = nil
122
+ canvas_data[:lessons] = canvas_data[:lessons].map { |lesson|
123
+ response = self.update_existing_lesson(lesson, name, html)
124
+ options[:id] = lesson[:id]
125
+ options[:course_id] = lesson[:course_id]
126
+ options[:type] = lesson[:type]
127
+
128
+ }
129
+ RepositoryInterface.local_repo_post_submission(options, response)
130
+ puts "Canvas lesson updated. Lesson available at #{response['html_url']}"
131
+ else
132
+ # If an ID (and course) are provided, they are used instead of the .canvas file
133
+ # Gets the current lesson's type (page or assignment)
134
+
135
+ options[:type] = self.get_lesson_info(options[:course_id], options[:id])[1]
136
+
137
+ # Implements update on Canvas
138
+ response = self.update_existing_lesson(options, name, html)
139
+ RepositoryInterface.local_repo_post_submission(options, response)
140
+ puts "Canvas lesson updated. Lesson available at #{response['html_url']}"
141
+ end
142
+
143
+ end
144
+
5
145
  def self.get_lesson_info(course, id)
6
146
 
7
147
  lesson_types = ["quizzes", "assignments", "pages", "discussion_topics"]
@@ -14,6 +154,7 @@ class CanvasInterface
14
154
  info = ""
15
155
  lesson_type_urls.each do |url|
16
156
  begin
157
+
17
158
  response = RestClient.get(url, headers={
18
159
  "Authorization" => "Bearer #{ENV['CANVAS_API_KEY']}"
19
160
  })
@@ -33,6 +174,7 @@ class CanvasInterface
33
174
  [info, type]
34
175
  end
35
176
 
177
+
36
178
  def self.get_course_info(course, id)
37
179
  if id
38
180
  lesson_data = self.get_lesson_info(course, id)
@@ -41,34 +183,64 @@ class CanvasInterface
41
183
  return
42
184
  end
43
185
 
186
+ url = "#{ENV['CANVAS_API_PATH']}/courses/#{course}"
187
+ response = RestClient.get(url, self.headers)
188
+ course_data = JSON.parse(response)
189
+
190
+ # /api/v1/courses/:course_id/modules
191
+ course_info = {
192
+ name: course_data['name'],
193
+ id: course_data['id'],
194
+ modules: []
195
+ }
196
+
44
197
  begin
45
- results = []
46
198
  index = 1
47
199
 
48
200
  while !!index
49
- url = "#{ENV['CANVAS_API_PATH']}/courses/#{course}/pages?order=asc&sort=title&page=#{index}&per_page=10"
201
+ url = "#{ENV['CANVAS_API_PATH']}/courses/#{course}/modules?page=#{index}&per_page=20"
50
202
  index += 1
51
- response = RestClient.get(url, headers={
52
- "Authorization" => "Bearer #{ENV['CANVAS_API_KEY']}"
53
- })
54
- pages = JSON.parse(response.body)
55
- if ([200, 201].include? response.code) && (!pages.empty?)
56
- results = results + pages
203
+ response = RestClient.get(url, self.headers)
204
+ modules = JSON.parse(response.body)
205
+
206
+ if ([200, 201].include? response.code) && (!modules.empty?)
207
+ course_info[:modules] = course_info[:modules] + modules
57
208
  else
58
209
  index = nil
59
210
  end
60
211
  end
61
- puts ""
62
- puts ""
63
- puts "Info for Course #{course} from #{ENV['CANVAS_API_PATH']}"
64
- puts ""
65
- puts "## Pages ##"
66
- puts "Title : Page ID"
67
- puts ""
68
-
69
- results.each {|result|
70
- puts "#{result['title']} : #{result['page_id']}"
71
- }
212
+
213
+ course_info[:modules] = course_info[:modules].map do |mod|
214
+ new_mod = {
215
+ id: mod['id'],
216
+ name: mod['name'],
217
+ lessons: []
218
+ }
219
+ index = 1
220
+ while !!index
221
+ url = "#{ENV['CANVAS_API_PATH']}/courses/#{course}/modules/#{mod['id']}/items?page=#{index}&per_page=20"
222
+ index += 1
223
+ response = RestClient.get(url, headers={
224
+ "Authorization" => "Bearer #{ENV['CANVAS_API_KEY']}"
225
+ })
226
+ lessons = JSON.parse(response.body)
227
+ lessons = lessons.map do |lesson|
228
+ lesson = lesson.slice("id","title","name","indent","type","html_url","page_url","url","completion_requirement", "published")
229
+ lesson["repository"] = ""
230
+ lesson['id'] = lesson['url'].gsub(/^(.*[\\\/])/,'')
231
+ lesson
232
+ end
233
+ if ([200, 201].include? response.code) && (!lessons.empty?)
234
+ new_mod[:lessons] = new_mod[:lessons] + lessons
235
+ else
236
+ index = nil
237
+ end
238
+
239
+ end
240
+ new_mod
241
+ end
242
+
243
+ puts course_info.to_yaml
72
244
 
73
245
  rescue
74
246
  puts "Something went wrong while getting info about course #{course}"
@@ -76,82 +248,218 @@ class CanvasInterface
76
248
  end
77
249
  end
78
250
 
79
- def self.submit_to_canvas(course_id, type, name, readme)
80
- response = self.push_to_canvas(course_id, type, name, readme)
81
- if ![200, 201].include? response.code
82
- puts "Canvas push failed. #{response.code} status code returned "
83
- abort
84
- end
85
- JSON.parse(response.body)
86
- end
251
+ def self.map_course_info(file_to_convert)
252
+ course_info = YAML.load(File.read("#{Dir.pwd}/#{file_to_convert}"))
253
+ course_info[:modules] = course_info[:modules].map do |mod|
254
+ mod[:lessons] = mod[:lessons].map do |lesson|
87
255
 
88
- def self.push_to_canvas(course_id, type, name, new_readme)
89
- if type == 'discussion'
90
- url = "#{ENV['CANVAS_API_PATH']}/courses/#{course_id}/#{type}_topics"
91
- else
92
- url = "#{ENV['CANVAS_API_PATH']}/courses/#{course_id}/#{type}s"
93
- end
94
- payload = self.build_payload(type, name, new_readme, false)
95
- begin
96
- RestClient.post(url, payload, headers={
97
- "Authorization" => "Bearer #{ENV['CANVAS_API_KEY']}"
98
- })
99
- rescue
100
- puts "Something went wrong while pushing lesson #{id} to course #{course_id}"
101
- abort
256
+ url = lesson["url"]
257
+ response = RestClient.get(url, headers={
258
+ "Authorization" => "Bearer #{ENV['CANVAS_API_KEY']}"
259
+ })
260
+ begin
261
+ lesson_data = JSON.parse(response)
262
+ contents = lesson_data["body"] if lesson["type"] == "Page"
263
+ contents = lesson_data["message"] if lesson["type"] == "Discussion"
264
+ contents = lesson_data["description"] if lesson["type"] == "Assignment" || lesson["type"] == "Quiz"
265
+ if contents.nil?
266
+ repo = ""
267
+ else
268
+ if contents[/data-repo=\"(.*?)"/]
269
+ repo = contents[/data-repo=\"(.*?)"/]
270
+ repo = repo.slice(11..-2)
271
+ elsif contents[/class=\"fis-git-link\" href=\"(.*?)"/]
272
+ repo = contents[/class=\"fis-git-link\" href=\"(.*?)"/]
273
+ repo = repo.slice(27..-2)
274
+ else
275
+ repo = ""
276
+ end
277
+ end
278
+ rescue
279
+ puts 'Error while mapping course info.'
280
+ abort
281
+ end
282
+
283
+ if repo != nil && repo != ""
284
+ if repo.include?('https://github.com/learn-co-curriculum/')
285
+ lesson["repository"] = repo
286
+ else
287
+ lesson["repository"] = "https://github.com/learn-co-curriculum/" + repo
288
+ end
289
+ end
290
+ sleep(1)
291
+ lesson
292
+ end
293
+ mod
102
294
  end
295
+ puts course_info.to_yaml
103
296
  end
104
297
 
105
- def self.update_existing_lesson(course_id, id, type, name, new_readme, only_update_content)
106
- if type == "discussion"
107
- url = "#{ENV['CANVAS_API_PATH']}/courses/#{course_id}/#{type}_topics/#{id}"
108
- else
109
- url = "#{ENV['CANVAS_API_PATH']}/courses/#{course_id}/#{type}s/#{id}"
110
- end
111
- payload = self.build_payload(type, name, new_readme, only_update_content)
112
- begin
113
- RestClient.put(url, payload, headers={
114
- "Authorization" => "Bearer #{ENV['CANVAS_API_KEY']}"
115
- })
116
- rescue
117
- puts "Something went wrong while pushing lesson #{id} to course #{course_id}"
118
- nil
298
+ def self.csv(file_to_convert)
299
+ course_info = YAML.load(File.read("#{Dir.pwd}/#{file_to_convert}"))
300
+ course_info[:modules] = course_info[:modules].map do |mod|
301
+ mod[:lessons] = mod[:lessons].map do |lesson|
302
+
303
+ url = lesson["url"]
304
+ response = RestClient.get(url, headers={
305
+ "Authorization" => "Bearer #{ENV['CANVAS_API_KEY']}"
306
+ })
307
+ begin
308
+ lesson_data = JSON.parse(response)
309
+ contents = lesson_data["body"] if lesson["type"] == "Page"
310
+ contents = lesson_data["message"] if lesson["type"] == "Discussion"
311
+ contents = lesson_data["description"] if lesson["type"] == "Assignment" || lesson["type"] == "Quiz"
312
+ if contents.nil?
313
+ repo = ""
314
+ else
315
+ if contents[/data-repo=\"(.*?)"/]
316
+ repo = contents[/data-repo=\"(.*?)"/]
317
+ repo = repo.slice(11..-2)
318
+ elsif contents[/class=\"fis-git-link\" href=\"(.*?)"/]
319
+ repo = contents[/class=\"fis-git-link\" href=\"(.*?)"/]
320
+ repo = repo.slice(27..-2)
321
+ else
322
+ repo = ""
323
+ end
324
+ end
325
+ rescue
326
+ puts 'Error while mapping course info.'
327
+ abort
328
+ end
329
+
330
+ if repo != nil && repo != ""
331
+ if repo.include?('https://github.com/learn-co-curriculum/')
332
+ lesson["repository"] = repo
333
+ else
334
+ lesson["repository"] = "https://github.com/learn-co-curriculum/" + repo
335
+ end
336
+ end
337
+ sleep(1)
338
+ lesson
339
+ end
340
+ mod
119
341
  end
342
+ byebug
343
+ puts course_info.to_yaml
120
344
  end
121
345
 
122
- def self.build_payload(type, name, new_readme, only_update_content)
123
- if only_update_content
124
- if type == "assignment"
346
+
347
+
348
+
349
+ def self.build_payload(options, name, html)
350
+ if options[:only_update_content]
351
+ if options[:type] == "assignment"
125
352
  payload = {
126
- 'assignment[description]' => new_readme
353
+ 'assignment[description]' => html
127
354
  }
128
- elsif type == "discussion"
355
+ elsif options[:type] == "discussion"
129
356
  payload = {
130
- 'message' => new_readme
357
+ 'message' => html
131
358
  }
132
359
  else
133
360
  payload = {
134
- 'wiki_page[body]' => new_readme
361
+ 'wiki_page[body]' => html
135
362
  }
136
363
  end
137
364
  else
138
- if type == "assignment"
365
+ if options[:type] == "assignment"
139
366
  payload = {
140
367
  'assignment[name]' => name,
141
- 'assignment[description]' => new_readme
368
+ 'assignment[description]' => html,
369
+ 'assignment[submission_types][]' => "online_url",
370
+ 'assignment[grading_type]' => 'pass_fail',
371
+ 'assignment[points_possible]' => 1
142
372
  }
143
- elsif type == "discussion"
373
+ elsif options[:type] == "discussion"
144
374
  payload = {
145
375
  'title' => name,
146
- 'message' => new_readme
376
+ 'message' => html
147
377
  }
148
378
  else
149
379
  payload = {
150
380
  'wiki_page[title]' => name,
151
- 'wiki_page[body]' => new_readme,
381
+ 'wiki_page[body]' => html,
152
382
  'wiki_page[editing_roles]' => "teachers"
153
383
  }
154
384
  end
155
385
  end
156
386
  end
387
+
388
+ def self.read_lesson(url)
389
+ types = ["page", "assignment", "quiz", "discussion"]
390
+ type = types.find {|type| url.match(type)}
391
+ if !url.include?(ENV['CANVAS_API_PATH'])
392
+ url = url.sub(/^.*\/\/.*?\//,"#{ENV['CANVAS_API_PATH']}/")
393
+ end
394
+
395
+ response = RestClient.get(url, headers={
396
+ "Authorization" => "Bearer #{ENV['CANVAS_API_KEY']}"
397
+ })
398
+ lesson_info = JSON.parse(response)
399
+ lesson_info = lesson_info.slice("title",
400
+ "name",
401
+ "description",
402
+ "body",
403
+ "message",
404
+ "shuffle_answers",
405
+ "allowed_attempts",
406
+ "question_count"
407
+ )
408
+ lesson_info["type"] = type.capitalize
409
+ if lesson_info["type"] == "Quiz"
410
+ url = url + "/questions"
411
+ response = RestClient.get(url, headers={
412
+ "Authorization" => "Bearer #{ENV['CANVAS_API_KEY']}"
413
+ })
414
+ lesson_info["questions"] = JSON.parse(response)
415
+ lesson_info["questions"] = lesson_info["questions"].map do |question|
416
+ question.slice("id",
417
+ "position",
418
+ "question_name",
419
+ "question_type",
420
+ "question_text",
421
+ "points_possible",
422
+ "correct_comments_html",
423
+ "incorrect_comments_html",
424
+ "neutral_comments_html",
425
+ "answers"
426
+ )
427
+ end
428
+ end
429
+ lesson_info.to_yaml
430
+ end
431
+
432
+ def self.create_lesson_from_remote(course_id, module_id, lesson_type, raw_url, yaml_file)
433
+ url = "#{ENV['CANVAS_API_PATH']}/courses/#{course_id}/modules/#{module_id}/items"
434
+ if yaml_file
435
+ data = YAML.load(File.read("#{Dir.pwd}/#{yaml_file}"))
436
+ payload = {
437
+ 'module_item[type]' => data["type"],
438
+ 'module_item[title]' => data["title"]
439
+ }
440
+ else
441
+
442
+ end
443
+
444
+
445
+ end
446
+
447
+ def self.headers
448
+ {
449
+ "Authorization" => "Bearer #{ENV['CANVAS_API_KEY']}"
450
+ }
451
+ end
452
+
453
+ # def self.create_quiz_from_remote(course_id, module_id, lesson_type, raw_url)
454
+ # url = "#{ENV['CANVAS_API_PATH']}/courses/#{course_id}/quizzes"
455
+ # payload = {
456
+ # 'quiz[title]' =>
457
+ # }
458
+ # /api/v1/courses/:course_id/quizzes
459
+ # data = YAML.load(File.read("#{Dir.pwd}/#{yaml_file}"))
460
+ # payload = {
461
+ # 'module_item[type]' => data["type"],
462
+ # 'module_item[title]' => data["title"]
463
+ # }
464
+ # end
157
465
  end