Skip to content

Instantly share code, notes, and snippets.

@ryanlovett
Created August 18, 2017 20:47
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 ryanlovett/ef7ce2611fa4ae8e16517ccc57a222b8 to your computer and use it in GitHub Desktop.
Save ryanlovett/ef7ce2611fa4ae8e16517ccc57a222b8 to your computer and use it in GitHub Desktop.
Get the official campus emails for students in a Berkeley course
#!/usr/bin/python
# Example usage:
# $0 -H headers.json -s compsci -c c8
# $0 -H headers.json -s stat -c c100
import sys
import os
import json
import requests
import argparse
def get_descriptors(uri, params, headers):
'''Get SIS descriptor IDs.'''
r = requests.get(uri, params=params, headers=headers)
data = r.json()
return data['apiResponse']['response']['fieldValues']
def extract_lecture_codes(sections):
return list(
map(lambda x: x['code'],
filter(lambda x: ' LEC ' in x['description'], sections)
)
)
def get_enrollments(uri, params, headers):
if args.verbose:
print("get_enrollments: {} {}".format(uri, params))
r = requests.get(uri, params=params, headers=headers)
if r.status_code == 404:
if args.debug: print('No more enrollments')
# there is no more data
return []
data = r.json()
# Return if there is no response (e.g. 404)
if 'response' not in data['apiResponse']:
if args.debug: print('404 No response')
print('404 No response')
return[]
# Return if the UID has no enrollments
if 'classSectionEnrollments' not in data['apiResponse']['response']:
if args.debug: print('No enrollments')
print('No enrollments')
return []
enrollments = \
data['apiResponse']['response']['classSectionEnrollments']
params['page-number'] += 1
enrollments += get_enrollments(uri, params, headers)
if args.debug: print('enrollments batch: {}'.format(len(enrollments)))
return enrollments
def enrollment_emails(enrollments):
'''Extract unique student emails from enrollments.'''
emails = set()
for e in enrollments:
for identifier in e['student']['identifiers']:
for email in e['student']['emails']:
if email['type']['code'] == 'CAMP':
emails.add(email['emailAddress'])
break
return emails
## MAIN
# there's an api for this too
TERM_FALL_2016 = 2168
TERM_SPRING_2017 = 2172
TERM_SUMMER_2017 = 2178
TERM_FALL_2017 = 2178
SUBJECT_AREA = 'STAT'
# Headers file contains requests json. Example:
# { "Accept": "application/json",
# "app_id": "YOUR_SIS_APP_ID",
# "app_key": "YOUR_SIS_APP_KEY" }
HEADERS_FILE = 'fetch-enrollments.json'
parser = argparse.ArgumentParser(description="Print enrolled students' email addresses.")
parser.add_argument('-t', dest='term_id', type=int, default=TERM_FALL_2017,
help='SIS Term ID (default=%(default)s)')
parser.add_argument('-s', dest='sa_filter', default=SUBJECT_AREA,
help='subject area filter (default=%(default)s)')
parser.add_argument('-c', dest='course', default='',
help='Course number, e.g. c8, 133, 135')
parser.add_argument('-H', dest='headers_file', default=HEADERS_FILE,
help='JSON file containing requests headers')
parser.add_argument('-v', dest='verbose', action='store_true', help='Be verbose.')
parser.add_argument('-d', dest='debug', action='store_true', help='Debug.')
args = parser.parse_args()
## main
# api secrets
headers = json.loads(open(args.headers_file).read())
enrollments_uri = "https://apis.berkeley.edu/sis/v2/enrollments"
descriptors_uri = enrollments_uri + '/terms/{}/classes/sections/descriptors'
sections_uri = enrollments_uri + "/terms/{}/classes/sections/{}"
params = {
"subject-area-code": args.sa_filter,
"catalog-number": args.course,
}
# Retrieve the "section IDs" associated with the course.
# This gets both lecture and sections.
uri = descriptors_uri.format(args.term_id)
sections = get_descriptors(uri, params, headers)
# We only care about the lecture.
lecture_codes = extract_lecture_codes(sections)
# Get the enrollments
params['page-number'] = 1
params['page-size'] = 100
enrollments = []
for lecture_code in lecture_codes:
uri = sections_uri.format(args.term_id, lecture_code)
enrollments += get_enrollments(uri, params, headers)
# Get the emails
emails = enrollment_emails(enrollments)
print('\n'.join(e for e in emails))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment