-
Notifications
You must be signed in to change notification settings - Fork 36
Expand file tree
/
Copy pathexport_course.py
More file actions
92 lines (78 loc) · 3.23 KB
/
export_course.py
File metadata and controls
92 lines (78 loc) · 3.23 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
# Run with Python 3
# Saves all step sources into foldered structure
import os
import json
import re
import requests
import datetime
# Enter parameters below:
# 1. Get your keys at https://stepik.org/oauth2/applications/
# (client type = confidential, authorization grant type = client credentials)
client_id = '...'
client_secret = '...'
api_host = 'https://stepik.org'
course_id = 1
# 2. Get a token
auth = requests.auth.HTTPBasicAuth(client_id, client_secret)
response = requests.post('https://stepik.org/oauth2/token/',
data={'grant_type': 'client_credentials'},
auth=auth)
token = response.json().get('access_token', None)
if not token:
print('Unable to authorize with provided credentials')
exit(1)
# 3. Call API (https://stepik.org/api/docs/) using this token.
def get_valid_filename(s):
return re.sub(r'(?u)[^-\w. ]', '', str(s)).strip()
def fetch_object(obj_class, obj_id):
api_url = '{}/api/{}s/{}'.format(api_host, obj_class, obj_id)
response = requests.get(api_url,
headers={'Authorization': 'Bearer ' + token}).json()
return response['{}s'.format(obj_class)][0]
def fetch_objects(obj_class, obj_ids):
objs = []
# Fetch objects by 30 items,
# so we won't bump into HTTP request length limits
step_size = 30
for i in range(0, len(obj_ids), step_size):
obj_ids_slice = obj_ids[i:i + step_size]
api_url = '{}/api/{}s?{}'.format(api_host, obj_class,
'&'.join('ids[]={}'.format(obj_id)
for obj_id in obj_ids_slice))
response = requests.get(api_url,
headers={'Authorization': 'Bearer ' + token}
).json()
objs += response['{}s'.format(obj_class)]
return objs
course = fetch_object('course', course_id)
sections = fetch_objects('section', course['sections'])
for section in sections:
unit_ids = section['units']
units = fetch_objects('unit', unit_ids)
for unit in units:
lesson_id = unit['lesson']
lesson = fetch_object('lesson', lesson_id)
step_ids = lesson['steps']
steps = fetch_objects('step', step_ids)
for step in steps:
step_source = fetch_object('step-source', step['id'])
path = [
'{} {}'.format(str(course['id']).zfill(2), get_valid_filename(course['title'])),
'{} {}'.format(str(section['position']).zfill(2), get_valid_filename(section['title'])),
'{} {}'.format(str(unit['position']).zfill(2), get_valid_filename(lesson['title'])),
'{}_{}_{}.step'.format(lesson['id'], str(step['position']).zfill(2), step['block']['name'])
]
try:
os.makedirs(os.path.join(os.curdir, *path[:-1]))
except:
pass
filename = os.path.join(os.curdir, *path)
f = open(filename, 'w')
data = {
'block': step_source['block'],
'id': str(step['id']),
'time': datetime.datetime.now().isoformat()
}
f.write(json.dumps(data))
f.close()
print(filename)