Skip to content

Instantly share code, notes, and snippets.

@robert-carroll
Last active October 3, 2018 22:50
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save robert-carroll/7a767462ef0f00e4b24b19a1236481da to your computer and use it in GitHub Desktop.
Save robert-carroll/7a767462ef0f00e4b24b19a1236481da to your computer and use it in GitHub Desktop.
live events ims format to flat
# https://github.com/instructure/canvas-lms/blob/master/lib/canvas/live_events.rb#L19
# https://canvas.instructure.com/doc/api/file.live_events.html
# this file parses the JSON data
# making best attempts to map JSON data to documented fields
class ParseEvents
# mimic this, https://github.com/instructure/switchman/blob/master/app/models/switchman/shard_internal.rb
def local_id(any_id)
any_id.to_i % 10_000_000_000_000
end
def meta(data)
md = {}
# event fields
md['uuid'] = nil
md['event_type'] = nil
md['event_time'] = nil
# listed metadata fields
md['user_id'] = nil
md['real_user_id'] = nil
md['user_login'] = nil
md['user_agent'] = nil
md['root_account_uuid'] = nil
md['root_account_id'] = nil
md['root_account_lti_guid'] = nil
md['context_type'] = nil
md['context_id'] = nil
md['role'] = nil
md['hostname'] = nil
md['producer'] = nil
md['request_id'] = nil
md['session_id'] = nil
md['user_account_id'] = nil
md['user_sis_id'] = nil
# for events originating as part of an asynchronous job, the following fields may be set
md['job_id'] = nil
md['job_tag'] = nil
# md['root_account_uuid'] = nil
# md['root_account_id'] = nil
# md['root_account_lti_guid']= nil
# event fields
md['uuid'] = data['id'].sub(/^urn:uuid:/, '')
md['event_type'] = data['type']
md['event_time'] = data['eventTime']
# actor
if data.key?('actor') && data['actor'].key?('extensions')
actor = data['actor']['extensions']['com.instructure.canvas']
md['global_user_id'] = actor['entity_id']
md['canvas_user_id'] = local_id(actor['entity_id'])
md['user_login'] = actor['user_login']
md['root_account_id'] = actor['root_account_id']
md['root_account_lti_guid'] = actor['root_account_lti_guid']
md['root_account_uuid'] = actor['root_account_uuid']
end
# membership
if data.key?('membership')
membership = data['membership']
md['role'] = membership['roles'].join(',')
end
# session
if data.key?('session')
session = data['session']
md['session_id'] = session['id'].sub(/^urn:instructure:canvas:session:/, '')
md['session_type'] = session['type']
end
# extensions
if data.key?('extensions')
extensions = data['extensions']['com.instructure.canvas']
md['hostname'] = extensions['hostname']
md['request_id'] = extensions['request_id']
md['user_agent'] = extensions['user_agent']
md['version'] = extensions['version']
end
md
end
def account_notification_created(data)
# puts data
end
def asset_accessed(data)
# https://www.imsglobal.org/sites/default/files/caliper/v1p1/caliper-spec-v1p1/caliper-spec-v1p1.html#navigationEvent
# puts data
# extract metadata
metadata = meta(data)
# body fields
asset_type = data['object']['extensions']['com.instructure.canvas']['asset_type']
asset_id = data['object']['extensions']['com.instructure.canvas']['entity_id']
asset_subtype = data['object']['extensions']['com.instructure.canvas'].key?('asset_subtype') ? data['object']['extensions']['com.instructure.canvas']['asset_subtype'] : nil
begin
return {
'uuid' => metadata['uuid'],
'event_time' => metadata['event_time'],
'global_user_id' => metadata['global_user_id'],
'canvas_user_id' => metadata['canvas_user_id'],
'user_login' => metadata['user_login'],
'roles' => metadata['roles'],
'course_id' => asset_type == 'course' && !asset_id.nil? ? asset_id : nil,
'subtype' => data['object']['name'],
'asset_type' => asset_type,
'asset_id' => asset_id,
'asset_subtype' => asset_subtype,
'request_id' => metadata['request_id'],
'session_id' => metadata['session_id'],
'user_agent' => metadata['user_agent'],
}
rescue => e
puts e
puts data
end
end
def assignment_created(data)
# puts data
end
def assignment_updated(data)
# puts data
end
def attachment_created(data)
# puts data
end
def attachment_deleted(data)
# puts data
end
def attachment_updated(data)
# puts data
end
def content_migration_completed(data)
# puts data
end
def course_created(data)
# puts data
end
def course_updated(data)
# puts data
end
def discussion_entry_created(data)
# 1% of events are missing group and membership
# https://www.imsglobal.org/sites/default/files/caliper/v1p1/caliper-spec-v1p1/caliper-spec-v1p1.html#messageEvent
# these 2 properties are optional in the Caliper docs
# puts data
# extract metadata
metadata = meta(data)
if data.key?('group') && data['group'].key?('id')
course_id = data['group']['id'].sub('urn:instructure:canvas:course:', '')
else course_id = nil
end
if data.key?('membership') && data['membership']['member'].key?('id')
parent_discussion_entry_author_id = data['membership']['member']['id'].sub('urn:instructure:canvas:user:', '')
else parent_discussion_entry_author_id = nil
end
begin
return {
# metadata fields
'uuid' => metadata['uuid'],
'event_time' => metadata['event_time'],
'course_id' => course_id,
# body fields
'discussion_entry_id' => data['object']['id'].sub('urn:instructure:canvas:discussionEntry:', ''),
'parent_discussion_entry_id' => nil,
'parent_discussion_entry_author_id' => parent_discussion_entry_author_id,
'discussion_topic_id' => data['object']['isPartOf']['id'].sub('urn:instructure:canvas:discussion:', ''),
'text' => data['object']['body']
}
rescue => e
puts e
puts data
end
end
def discussion_topic_created(data)
# puts data
# extract metadata
metadata = meta(data)
begin
return {
# metadata fields
'uuid' => metadata['uuid'],
'event_time' => metadata['event_time'],
'course_id' => data.key?('group') ? data['group']['id'].sub('urn:instructure:canvas:course:', '') : nil,
# 'entity_id' => data['group']['extensions']['com.instructure.canvas']['entity_id'],
'instructor_id' => data.key?('membership') ? data['membership']['member']['id'].sub('urn:instructure:canvas:user:', '') : nil,
'discussion_type' => data['object']['type'], # Thread
# body fields
'discussion_topic_id' => data['object']['id'].sub('urn:instructure:canvas:discussion:', ''),
'is_announcement' => data['object']['extensions']['com.instructure.canvas']['is_announcement'],
'title' => data['object']['name'],
'body' => data['object'].key?('body') ? data['object']['body'] : nil # not seen
}
rescue => e
puts e
puts data
end
end
def enrollment_created(data)
# extract metadata
metadata = meta(data)
begin
extensions = data['object']['extensions']['com.instructure.canvas']
return {
# metadata fields
'uuid' => data['id'].sub(/^urn:uuid:/, ''),
# body fields
'enrollment_id' => data['object']['id'].sub(/^.+enrollment:/, ''),
'course_id' => extensions['course_id'].sub('urn:instructure:canvas:course:', ''),
'user_id' => extensions['user_id'].sub('urn:instructure:canvas:user:', ''),
'user_name' => extensions['user_name'],
'type' => extensions['type'],
'created_at' => data['object']['dateCreated'],
'updated_at' => data['object']['dateUpdated'],
'limit_privileges_to_course_section' => extensions['limit_privileges_to_course_section'],
'course_section_id' => extensions['course_section_id'].sub(/^.+section:/, ''),
'associated_user_id' => extensions['associated_user_id'],
'workflow_state' => extensions['workflow_state']
}
rescue => e
puts e
puts data
end
end
def enrollment_state_created(data)
# puts data
end
def enrollment_state_updated(data)
# puts data
end
def enrollment_updated(data)
# puts data
end
def grade_change(data)
# puts data
# extract metadata
metadata = meta(data)
puts metadata
# begin
# return {
# 'submission_id' => data['object']['extensions']['com.instructure.canvas']['entity_id'],
# 'assignment_id' => data['object']['assignable']['id'].sub('urn:instructure:canvas:assignment:', ''),
# 'grade' => data['generated']['extensions']['com.instructure.canvas']['grade'],
# 'old_grade' => nil,
# # wtf "scoreGiven": {"numberStr": "1.0"} "scoreGiven" => 13.125
# # https://www.idatalobal.org/sites/default/files/caliper/v1p1/caliper-spec-v1p1/caliper-spec-v1p1.html#score
# # scoreGiven - decimal - A number with a fractional part denoted by a decimal separator that designates the actual score awarded.
# 'score' => !data['generated']['scoreGiven'].key?('numberStr') ? data['generated']['scoreGiven'] : data['generated']['scoreGiven']['numberStr'],
# 'old_score' => nil,
# 'points_possible' => !data['generated']['maxScore'].key?('numberStr') ? data['generated']['maxScore'] : data['generated']['maxScore']['numberStr'],
# 'old_points_possible' => nil,
# 'grader_id' => data['generated'].key?('scoredBy') ? data['generated']['scoredBy'].sub('urn:instructure:canvas:user:', '') : nil,
# 'user_id' => data['object'].key?('assignee') ? data['object']['assignee']['extensions']['com.instructure.canvas']['sis_id'] : nil,
# 'muted' => nil,
# 'grading_complete' => nil
# }
# rescue => e
# puts e
# puts data
# end
end
def group_category_created(data)
# puts data
end
def group_created(data)
# puts data
end
def group_membership_created(data)
# puts data
end
def group_membership_updated(data)
# puts data
end
def group_updated(data)
# puts data
end
def logged_in(data)
# puts data
# extract metadata
metadata = meta(data)
# body fields
if data['object'].key?('extensions') && data['object']['extensions']['com.instructure.canvas'].key?('redirect_url')
redirect_url = data['object']['extensions']['com.instructure.canvas']['redirect_url']
else redirect_url = nil
end
begin
return {
'uuid' => metadata['uuid'],
'global_user_id' => metadata['global_user_id'],
'canvas_user_id' => metadata['canvas_user_id'],
'user_login' => metadata['user_login'],
'login_at' => metadata['event_time'],
'redirect_url' => redirect_url,
'request_id' => metadata['request_id'],
'session_id' => metadata['session_id'],
'user_agent' => metadata['user_agent'],
}
rescue => e
puts e
puts data
end
end
def logged_out(data)
# puts data
# extract metadata
metadata = meta(data)
begin
return {
'uuid' => metadata['uuid'],
'global_user_id' => metadata['global_user_id'],
'canvas_user_id' => metadata['canvas_user_id'],
'user_login' => metadata['user_login'],
'logout_at' => metadata['event_time'],
'request_id' => metadata['request_id'],
'session_id' => metadata['session_id'],
'user_agent' => metadata['user_agent'],
}
rescue => e
puts e
puts data
end
end
def module_created(data)
# puts data
end
def module_item_created(data)
# puts data
end
def module_item_updated(data)
# puts data
end
def module_updated(data)
# puts data
end
def plagiarism_resubmit(data)
# puts data
end
def quiz_submitted(data)
# puts data
# extract metadata
metadata = meta(data)
# puts metadata
begin
return {
'uuid' => metadata['uuid'],
'global_user_id' => metadata['global_user_id'],
'canvas_user_id' => metadata['canvas_user_id'],
'user_login' => metadata['user_login'],
'submitted_at' => metadata['event_time'],
'request_id' => metadata['request_id'],
'session_id' => metadata['session_id'],
'user_agent' => metadata['user_agent'],
'course_id' => data['group']['extensions']['com.instructure.canvas']['entity_id'],
'quiz_id' => data['object']['assignable']['id'].sub('urn:instructure:canvas:quiz:', ''),
'submission_id' => data['object']['extensions']['com.instructure.canvas']['entity_id']
}
rescue => e
puts e
puts data
end
end
def submission_created(data)
# puts data
# extract metadata
metadata = meta(data)
# puts metadata
if data.key?('object')
obj = data['object']
# type = obj['type']
date_created = obj['dateCreated']
body = !obj['body'].nil? ? obj['body'] : nil
attempt = !obj['count'].nil? ? obj['count'] : nil
end
if data.key?('object') && data['object'].key?('extensions')
subm_ext = data['object']['extensions']['com.instructure.canvas']
submission_id = !subm_ext['entity_id'].nil? ? subm_ext['entity_id'] : nil
submission_type = !subm_ext['submission_type'].nil? ? subm_ext['submission_type'] : nil
submission_url = !subm_ext['url'].nil? ? subm_ext['url'] : nil
end
if data.key?('object') && data['object'].key?('assignable')
assignable = data['object']['assignable']
assignment_id = !assignable['id'].nil? ? assignable['id'].sub('urn:instructure:canvas:assignment:', '') : nil
end
if data.key?('group') && data['group'].key?('extensions')
course_ext = data['group']['extensions']['com.instructure.canvas']
course_id = !course_ext['entity_id'].nil? ? course_ext['entity_id'] : nil
end
return {
# metadata fields
'uuid' => metadata['uuid'],
'roles' => metadata['roles'],
'event_time' => metadata['event_time'],
'request_id' => metadata['request_id'],
'session_id' => metadata['session_id'],
'user_agent' => metadata['user_agent'],
'course_id' => course_id,
# body fields
'submission_id' => submission_id,
'assignment_id' => assignment_id,
'user_id' => metadata['global_user_id'],
'lti_user_id' => nil,
'submitted_at' => date_created,
'updated_at' => nil,
'score' => nil,
'grade' => nil,
'submission_type' => submission_type,
'body' => body,
'url' => submission_url,
'attempt' => attempt,
'lti_assignment_id' => nil,
'group_id' => course_id,
}
end
def submission_updated(data)
# puts data
# extract metadata
metadata = meta(data)
# puts metadata
if data.key?('object')
obj = data['object']
# type = obj['type']
date_created = obj['dateCreated']
body = !obj['body'].nil? ? obj['body'] : nil
attempt = !obj['count'].nil? ? obj['count'] : nil
end
if data.key?('object') && data['object'].key?('extensions')
subm_ext = data['object']['extensions']['com.instructure.canvas']
submission_id = !subm_ext['entity_id'].nil? ? subm_ext['entity_id'] : nil
submission_type = !subm_ext['submission_type'].nil? ? subm_ext['submission_type'] : nil
submission_url = !subm_ext['url'].nil? ? subm_ext['url'] : nil
end
if data.key?('object') && data['object'].key?('assignable')
assignable = data['object']['assignable']
assignment_id = !assignable['id'].nil? ? assignable['id'].sub('urn:instructure:canvas:assignment:', '') : nil
end
if data.key?('group') && data['group'].key?('extensions')
course_ext = data['group']['extensions']['com.instructure.canvas']
course_id = !course_ext['entity_id'].nil? ? course_ext['entity_id'] : nil
end
return {
# metadata fields
'uuid' => metadata['uuid'],
'roles' => metadata['roles'],
'event_time' => metadata['event_time'],
'course_id' => course_id,
# body fields
'submission_id' => submission_id,
'assignment_id' => assignment_id,
'user_id' => metadata['global_user_id'],
'lti_user_id' => nil,
'submitted_at' => date_created,
'updated_at' => nil,
'score' => nil,
'grade' => nil,
'submission_type' => submission_type,
'body' => body,
'url' => submission_url,
'attempt' => attempt,
'lti_assignment_id' => nil,
'group_id' => course_id,
}
end
def syllabus_updated(data)
# puts data
end
def user_account_association_created(data)
# puts data
end
def user_created(data)
# puts data
end
def user_updated(data)
# puts data
end
def wiki_page_created(data)
# puts data
end
def wiki_page_deleted(data)
# puts data
end
def wiki_page_updated(data)
# puts data
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment