syncMyMoodle 0.2.0__tar.gz → 0.2.2__tar.gz
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.
- {syncmymoodle-0.2.0/syncMyMoodle.egg-info → syncmymoodle-0.2.2}/PKG-INFO +35 -20
- {syncmymoodle-0.2.0 → syncmymoodle-0.2.2}/README.md +31 -17
- {syncmymoodle-0.2.0 → syncmymoodle-0.2.2}/pyproject.toml +1 -1
- {syncmymoodle-0.2.0 → syncmymoodle-0.2.2}/setup.cfg +2 -2
- {syncmymoodle-0.2.0 → syncmymoodle-0.2.2/syncMyMoodle.egg-info}/PKG-INFO +35 -20
- {syncmymoodle-0.2.0 → syncmymoodle-0.2.2}/syncMyMoodle.egg-info/requires.txt +1 -1
- {syncmymoodle-0.2.0 → syncmymoodle-0.2.2}/syncmymoodle/__main__.py +102 -47
- {syncmymoodle-0.2.0 → syncmymoodle-0.2.2}/LICENSE +0 -0
- {syncmymoodle-0.2.0 → syncmymoodle-0.2.2}/syncMyMoodle.egg-info/SOURCES.txt +0 -0
- {syncmymoodle-0.2.0 → syncmymoodle-0.2.2}/syncMyMoodle.egg-info/dependency_links.txt +0 -0
- {syncmymoodle-0.2.0 → syncmymoodle-0.2.2}/syncMyMoodle.egg-info/top_level.txt +0 -0
- {syncmymoodle-0.2.0 → syncmymoodle-0.2.2}/syncmymoodle/__init__.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
2
|
Name: syncMyMoodle
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.2
|
|
4
4
|
Summary: Synchronization client for RWTH Moodle
|
|
5
5
|
Home-page: https://github.com/Romern/syncMyMoodle
|
|
6
6
|
Author: Nils Kattenbeck
|
|
@@ -20,7 +20,7 @@ Requires-Dist: tqdm>=4.0.0
|
|
|
20
20
|
Provides-Extra: quiz
|
|
21
21
|
Requires-Dist: pdfkit>=0.6.0; extra == "quiz"
|
|
22
22
|
Provides-Extra: keyring
|
|
23
|
-
Requires-Dist:
|
|
23
|
+
Requires-Dist: keyring>=20.0.0; extra == "keyring"
|
|
24
24
|
Provides-Extra: test
|
|
25
25
|
Requires-Dist: black; extra == "test"
|
|
26
26
|
Requires-Dist: isort; extra == "test"
|
|
@@ -28,6 +28,7 @@ Requires-Dist: flake8; extra == "test"
|
|
|
28
28
|
Requires-Dist: flake8-bugbear; extra == "test"
|
|
29
29
|
Requires-Dist: mypy; extra == "test"
|
|
30
30
|
Requires-Dist: types-requests; extra == "test"
|
|
31
|
+
Dynamic: license-file
|
|
31
32
|
|
|
32
33
|
# syncMyMoodle
|
|
33
34
|
|
|
@@ -113,7 +114,7 @@ The following command line arguments are available:
|
|
|
113
114
|
|
|
114
115
|
```bash
|
|
115
116
|
usage: python3 -m syncmymoodle [-h] [--secretservice] [--user USER]
|
|
116
|
-
[--password PASSWORD] [--totp TOTP] [--config CONFIG]
|
|
117
|
+
[--password PASSWORD] [--totp TOTP] [--totpsecret TOTPSECRET] [--config CONFIG]
|
|
117
118
|
[--cookiefile COOKIEFILE] [--courses COURSES]
|
|
118
119
|
[--skipcourses SKIPCOURSES]
|
|
119
120
|
[--semester SEMESTER] [--basedir BASEDIR]
|
|
@@ -125,13 +126,17 @@ in config.json.
|
|
|
125
126
|
|
|
126
127
|
options:
|
|
127
128
|
-h, --help show this help message and exit
|
|
128
|
-
--secretservice use
|
|
129
|
-
|
|
129
|
+
--secretservice use system's secret service integration for storing and
|
|
130
|
+
retrieving account credentials
|
|
131
|
+
--secretservicetotpsecret
|
|
132
|
+
Save TOTP secret in keyring
|
|
130
133
|
--user USER set your RWTH Single Sign-On username
|
|
131
134
|
--password PASSWORD set your RWTH Single Sign-On password
|
|
132
135
|
--totp TOTP set your RWTH Single Sign-On TOTP provider's serial
|
|
133
136
|
number (see
|
|
134
137
|
https://idm.rwth-aachen.de/selfservice/MFATokenManager)
|
|
138
|
+
--totpsecret TOTPSECRET
|
|
139
|
+
(optional) set your RWTH Single Sign-On TOTP provider Secret
|
|
135
140
|
--config CONFIG set your configuration file
|
|
136
141
|
--cookiefile COOKIEFILE
|
|
137
142
|
set the location of a cookie file
|
|
@@ -170,9 +175,11 @@ configuration does:
|
|
|
170
175
|
"user": "", // RWTH SSO username
|
|
171
176
|
"password": "", // RWTH SSO password
|
|
172
177
|
"totp": "", // RWTH SSO TOTP "Serial Number", format: TOTP0000000A, see https://idm.rwth-aachen.de/selfservice/MFATokenManager
|
|
178
|
+
"totpsecret": "", // The TOTP Secret for your TOTP generator (optional)
|
|
173
179
|
"basedir": "./", // The base directory where all your files will be synced to
|
|
174
180
|
"cookie_file": "./session", // The location of the session/cookie file, which can be used instead of a password.
|
|
175
|
-
"use_secret_service": false, // Use the
|
|
181
|
+
"use_secret_service": false, // Use the system keyring (see README), instead of a password.
|
|
182
|
+
"secret_service_store_totp_secret": false, // Store the TOTP secret in the system keyring.
|
|
176
183
|
"no_links": false, // Skip links embedded in pages. Warning: This *will* prevent Onlycast videos from being downloaded.
|
|
177
184
|
"used_modules": { // Disable downloading certain modules.
|
|
178
185
|
"assign": true, // Assignments
|
|
@@ -194,20 +201,27 @@ Command line arguments have a higher priority than configuration files.
|
|
|
194
201
|
You can override any of the options that you have configured in the file
|
|
195
202
|
using command line arguments.
|
|
196
203
|
|
|
197
|
-
|
|
204
|
+
### TOTP
|
|
198
205
|
|
|
199
|
-
|
|
200
|
-
|
|
206
|
+
From the RWTH IDM service you will get a TOTP secret which will be used to
|
|
207
|
+
generate OTP tokens. The serial number of the TOTP, which can be seen in the
|
|
208
|
+
[RWTH IDM Token Manager](https://idm.rwth-aachen.de/selfservice/MFATokenManager),
|
|
209
|
+
has to be provided using the `--totp` option or the JSON entry of the same name.
|
|
210
|
+
It usually has the format `TOTP12345678`.
|
|
201
211
|
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
Linux desktop-oriented distribution, it most probably does!
|
|
212
|
+
The TOTP secret can be specified using the `--totpsecret` option or the JSON
|
|
213
|
+
entry of the same name. It can be found in the `otpauth://` link in the secret
|
|
214
|
+
argument.
|
|
206
215
|
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
your
|
|
216
|
+
## Keyring Integration
|
|
217
|
+
|
|
218
|
+
You are advised to install and use the optional Keyring integration
|
|
219
|
+
to store your password securely if your system supports it, see the
|
|
220
|
+
[projects page](https://github.com/jaraco/keyring) for all supported systems.
|
|
221
|
+
|
|
222
|
+
If you have a compatible keyring installed, you can store your RWTH SSO
|
|
223
|
+
credentials in it and use it with *syncMyMoodle*, which can be particularly
|
|
224
|
+
useful if you do not like storing your passwords in plain text files.
|
|
211
225
|
|
|
212
226
|
To do that, you will have to install *syncMyMoodle* with an extra `keyring`
|
|
213
227
|
argument:
|
|
@@ -218,8 +232,9 @@ pip3 install syncmymoodle[keyring] # when installing from PyPi
|
|
|
218
232
|
pip3 install .[keyring] # when installing manually
|
|
219
233
|
```
|
|
220
234
|
|
|
221
|
-
You will be asked for your password
|
|
222
|
-
time, which you can supply as a parameter or
|
|
235
|
+
You will be asked for your password and TOTP secret when using
|
|
236
|
+
*syncMyMoodle* for the first time, which you can supply as a parameter or
|
|
237
|
+
in the configuration file.
|
|
223
238
|
|
|
224
239
|
If everything went alright, you won't need to enter your password again
|
|
225
240
|
in the future, as it will be obtained automatically and securely from
|
|
@@ -82,7 +82,7 @@ The following command line arguments are available:
|
|
|
82
82
|
|
|
83
83
|
```bash
|
|
84
84
|
usage: python3 -m syncmymoodle [-h] [--secretservice] [--user USER]
|
|
85
|
-
[--password PASSWORD] [--totp TOTP] [--config CONFIG]
|
|
85
|
+
[--password PASSWORD] [--totp TOTP] [--totpsecret TOTPSECRET] [--config CONFIG]
|
|
86
86
|
[--cookiefile COOKIEFILE] [--courses COURSES]
|
|
87
87
|
[--skipcourses SKIPCOURSES]
|
|
88
88
|
[--semester SEMESTER] [--basedir BASEDIR]
|
|
@@ -94,13 +94,17 @@ in config.json.
|
|
|
94
94
|
|
|
95
95
|
options:
|
|
96
96
|
-h, --help show this help message and exit
|
|
97
|
-
--secretservice use
|
|
98
|
-
|
|
97
|
+
--secretservice use system's secret service integration for storing and
|
|
98
|
+
retrieving account credentials
|
|
99
|
+
--secretservicetotpsecret
|
|
100
|
+
Save TOTP secret in keyring
|
|
99
101
|
--user USER set your RWTH Single Sign-On username
|
|
100
102
|
--password PASSWORD set your RWTH Single Sign-On password
|
|
101
103
|
--totp TOTP set your RWTH Single Sign-On TOTP provider's serial
|
|
102
104
|
number (see
|
|
103
105
|
https://idm.rwth-aachen.de/selfservice/MFATokenManager)
|
|
106
|
+
--totpsecret TOTPSECRET
|
|
107
|
+
(optional) set your RWTH Single Sign-On TOTP provider Secret
|
|
104
108
|
--config CONFIG set your configuration file
|
|
105
109
|
--cookiefile COOKIEFILE
|
|
106
110
|
set the location of a cookie file
|
|
@@ -139,9 +143,11 @@ configuration does:
|
|
|
139
143
|
"user": "", // RWTH SSO username
|
|
140
144
|
"password": "", // RWTH SSO password
|
|
141
145
|
"totp": "", // RWTH SSO TOTP "Serial Number", format: TOTP0000000A, see https://idm.rwth-aachen.de/selfservice/MFATokenManager
|
|
146
|
+
"totpsecret": "", // The TOTP Secret for your TOTP generator (optional)
|
|
142
147
|
"basedir": "./", // The base directory where all your files will be synced to
|
|
143
148
|
"cookie_file": "./session", // The location of the session/cookie file, which can be used instead of a password.
|
|
144
|
-
"use_secret_service": false, // Use the
|
|
149
|
+
"use_secret_service": false, // Use the system keyring (see README), instead of a password.
|
|
150
|
+
"secret_service_store_totp_secret": false, // Store the TOTP secret in the system keyring.
|
|
145
151
|
"no_links": false, // Skip links embedded in pages. Warning: This *will* prevent Onlycast videos from being downloaded.
|
|
146
152
|
"used_modules": { // Disable downloading certain modules.
|
|
147
153
|
"assign": true, // Assignments
|
|
@@ -163,20 +169,27 @@ Command line arguments have a higher priority than configuration files.
|
|
|
163
169
|
You can override any of the options that you have configured in the file
|
|
164
170
|
using command line arguments.
|
|
165
171
|
|
|
166
|
-
|
|
172
|
+
### TOTP
|
|
167
173
|
|
|
168
|
-
|
|
169
|
-
|
|
174
|
+
From the RWTH IDM service you will get a TOTP secret which will be used to
|
|
175
|
+
generate OTP tokens. The serial number of the TOTP, which can be seen in the
|
|
176
|
+
[RWTH IDM Token Manager](https://idm.rwth-aachen.de/selfservice/MFATokenManager),
|
|
177
|
+
has to be provided using the `--totp` option or the JSON entry of the same name.
|
|
178
|
+
It usually has the format `TOTP12345678`.
|
|
170
179
|
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
Linux desktop-oriented distribution, it most probably does!
|
|
180
|
+
The TOTP secret can be specified using the `--totpsecret` option or the JSON
|
|
181
|
+
entry of the same name. It can be found in the `otpauth://` link in the secret
|
|
182
|
+
argument.
|
|
175
183
|
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
your
|
|
184
|
+
## Keyring Integration
|
|
185
|
+
|
|
186
|
+
You are advised to install and use the optional Keyring integration
|
|
187
|
+
to store your password securely if your system supports it, see the
|
|
188
|
+
[projects page](https://github.com/jaraco/keyring) for all supported systems.
|
|
189
|
+
|
|
190
|
+
If you have a compatible keyring installed, you can store your RWTH SSO
|
|
191
|
+
credentials in it and use it with *syncMyMoodle*, which can be particularly
|
|
192
|
+
useful if you do not like storing your passwords in plain text files.
|
|
180
193
|
|
|
181
194
|
To do that, you will have to install *syncMyMoodle* with an extra `keyring`
|
|
182
195
|
argument:
|
|
@@ -187,8 +200,9 @@ pip3 install syncmymoodle[keyring] # when installing from PyPi
|
|
|
187
200
|
pip3 install .[keyring] # when installing manually
|
|
188
201
|
```
|
|
189
202
|
|
|
190
|
-
You will be asked for your password
|
|
191
|
-
time, which you can supply as a parameter or
|
|
203
|
+
You will be asked for your password and TOTP secret when using
|
|
204
|
+
*syncMyMoodle* for the first time, which you can supply as a parameter or
|
|
205
|
+
in the configuration file.
|
|
192
206
|
|
|
193
207
|
If everything went alright, you won't need to enter your password again
|
|
194
208
|
in the future, as it will be obtained automatically and securely from
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[metadata]
|
|
2
2
|
name = syncMyMoodle
|
|
3
|
-
version = 0.2.
|
|
3
|
+
version = 0.2.2
|
|
4
4
|
author = Nils Kattenbeck
|
|
5
5
|
author_email = nilskemail+pypi@gmail.com
|
|
6
6
|
description = Synchronization client for RWTH Moodle
|
|
@@ -28,7 +28,7 @@ install_requires =
|
|
|
28
28
|
quiz =
|
|
29
29
|
pdfkit>=0.6.0
|
|
30
30
|
keyring =
|
|
31
|
-
|
|
31
|
+
keyring>=20.0.0
|
|
32
32
|
test =
|
|
33
33
|
black
|
|
34
34
|
isort
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
2
|
Name: syncMyMoodle
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.2
|
|
4
4
|
Summary: Synchronization client for RWTH Moodle
|
|
5
5
|
Home-page: https://github.com/Romern/syncMyMoodle
|
|
6
6
|
Author: Nils Kattenbeck
|
|
@@ -20,7 +20,7 @@ Requires-Dist: tqdm>=4.0.0
|
|
|
20
20
|
Provides-Extra: quiz
|
|
21
21
|
Requires-Dist: pdfkit>=0.6.0; extra == "quiz"
|
|
22
22
|
Provides-Extra: keyring
|
|
23
|
-
Requires-Dist:
|
|
23
|
+
Requires-Dist: keyring>=20.0.0; extra == "keyring"
|
|
24
24
|
Provides-Extra: test
|
|
25
25
|
Requires-Dist: black; extra == "test"
|
|
26
26
|
Requires-Dist: isort; extra == "test"
|
|
@@ -28,6 +28,7 @@ Requires-Dist: flake8; extra == "test"
|
|
|
28
28
|
Requires-Dist: flake8-bugbear; extra == "test"
|
|
29
29
|
Requires-Dist: mypy; extra == "test"
|
|
30
30
|
Requires-Dist: types-requests; extra == "test"
|
|
31
|
+
Dynamic: license-file
|
|
31
32
|
|
|
32
33
|
# syncMyMoodle
|
|
33
34
|
|
|
@@ -113,7 +114,7 @@ The following command line arguments are available:
|
|
|
113
114
|
|
|
114
115
|
```bash
|
|
115
116
|
usage: python3 -m syncmymoodle [-h] [--secretservice] [--user USER]
|
|
116
|
-
[--password PASSWORD] [--totp TOTP] [--config CONFIG]
|
|
117
|
+
[--password PASSWORD] [--totp TOTP] [--totpsecret TOTPSECRET] [--config CONFIG]
|
|
117
118
|
[--cookiefile COOKIEFILE] [--courses COURSES]
|
|
118
119
|
[--skipcourses SKIPCOURSES]
|
|
119
120
|
[--semester SEMESTER] [--basedir BASEDIR]
|
|
@@ -125,13 +126,17 @@ in config.json.
|
|
|
125
126
|
|
|
126
127
|
options:
|
|
127
128
|
-h, --help show this help message and exit
|
|
128
|
-
--secretservice use
|
|
129
|
-
|
|
129
|
+
--secretservice use system's secret service integration for storing and
|
|
130
|
+
retrieving account credentials
|
|
131
|
+
--secretservicetotpsecret
|
|
132
|
+
Save TOTP secret in keyring
|
|
130
133
|
--user USER set your RWTH Single Sign-On username
|
|
131
134
|
--password PASSWORD set your RWTH Single Sign-On password
|
|
132
135
|
--totp TOTP set your RWTH Single Sign-On TOTP provider's serial
|
|
133
136
|
number (see
|
|
134
137
|
https://idm.rwth-aachen.de/selfservice/MFATokenManager)
|
|
138
|
+
--totpsecret TOTPSECRET
|
|
139
|
+
(optional) set your RWTH Single Sign-On TOTP provider Secret
|
|
135
140
|
--config CONFIG set your configuration file
|
|
136
141
|
--cookiefile COOKIEFILE
|
|
137
142
|
set the location of a cookie file
|
|
@@ -170,9 +175,11 @@ configuration does:
|
|
|
170
175
|
"user": "", // RWTH SSO username
|
|
171
176
|
"password": "", // RWTH SSO password
|
|
172
177
|
"totp": "", // RWTH SSO TOTP "Serial Number", format: TOTP0000000A, see https://idm.rwth-aachen.de/selfservice/MFATokenManager
|
|
178
|
+
"totpsecret": "", // The TOTP Secret for your TOTP generator (optional)
|
|
173
179
|
"basedir": "./", // The base directory where all your files will be synced to
|
|
174
180
|
"cookie_file": "./session", // The location of the session/cookie file, which can be used instead of a password.
|
|
175
|
-
"use_secret_service": false, // Use the
|
|
181
|
+
"use_secret_service": false, // Use the system keyring (see README), instead of a password.
|
|
182
|
+
"secret_service_store_totp_secret": false, // Store the TOTP secret in the system keyring.
|
|
176
183
|
"no_links": false, // Skip links embedded in pages. Warning: This *will* prevent Onlycast videos from being downloaded.
|
|
177
184
|
"used_modules": { // Disable downloading certain modules.
|
|
178
185
|
"assign": true, // Assignments
|
|
@@ -194,20 +201,27 @@ Command line arguments have a higher priority than configuration files.
|
|
|
194
201
|
You can override any of the options that you have configured in the file
|
|
195
202
|
using command line arguments.
|
|
196
203
|
|
|
197
|
-
|
|
204
|
+
### TOTP
|
|
198
205
|
|
|
199
|
-
|
|
200
|
-
|
|
206
|
+
From the RWTH IDM service you will get a TOTP secret which will be used to
|
|
207
|
+
generate OTP tokens. The serial number of the TOTP, which can be seen in the
|
|
208
|
+
[RWTH IDM Token Manager](https://idm.rwth-aachen.de/selfservice/MFATokenManager),
|
|
209
|
+
has to be provided using the `--totp` option or the JSON entry of the same name.
|
|
210
|
+
It usually has the format `TOTP12345678`.
|
|
201
211
|
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
Linux desktop-oriented distribution, it most probably does!
|
|
212
|
+
The TOTP secret can be specified using the `--totpsecret` option or the JSON
|
|
213
|
+
entry of the same name. It can be found in the `otpauth://` link in the secret
|
|
214
|
+
argument.
|
|
206
215
|
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
your
|
|
216
|
+
## Keyring Integration
|
|
217
|
+
|
|
218
|
+
You are advised to install and use the optional Keyring integration
|
|
219
|
+
to store your password securely if your system supports it, see the
|
|
220
|
+
[projects page](https://github.com/jaraco/keyring) for all supported systems.
|
|
221
|
+
|
|
222
|
+
If you have a compatible keyring installed, you can store your RWTH SSO
|
|
223
|
+
credentials in it and use it with *syncMyMoodle*, which can be particularly
|
|
224
|
+
useful if you do not like storing your passwords in plain text files.
|
|
211
225
|
|
|
212
226
|
To do that, you will have to install *syncMyMoodle* with an extra `keyring`
|
|
213
227
|
argument:
|
|
@@ -218,8 +232,9 @@ pip3 install syncmymoodle[keyring] # when installing from PyPi
|
|
|
218
232
|
pip3 install .[keyring] # when installing manually
|
|
219
233
|
```
|
|
220
234
|
|
|
221
|
-
You will be asked for your password
|
|
222
|
-
time, which you can supply as a parameter or
|
|
235
|
+
You will be asked for your password and TOTP secret when using
|
|
236
|
+
*syncMyMoodle* for the first time, which you can supply as a parameter or
|
|
237
|
+
in the configuration file.
|
|
223
238
|
|
|
224
239
|
If everything went alright, you won't need to enter your password again
|
|
225
240
|
in the future, as it will be obtained automatically and securely from
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
import base64
|
|
4
4
|
import getpass
|
|
5
5
|
import hashlib
|
|
6
|
+
import hmac
|
|
6
7
|
import http.client
|
|
7
8
|
import json
|
|
8
9
|
import logging
|
|
@@ -10,14 +11,15 @@ import os
|
|
|
10
11
|
import pickle
|
|
11
12
|
import re
|
|
12
13
|
import shutil
|
|
14
|
+
import struct
|
|
13
15
|
import sys
|
|
16
|
+
import time
|
|
14
17
|
import urllib.parse
|
|
15
18
|
from argparse import ArgumentParser
|
|
16
19
|
from contextlib import closing
|
|
17
20
|
from fnmatch import fnmatchcase
|
|
18
21
|
from pathlib import Path
|
|
19
|
-
from
|
|
20
|
-
from typing import TYPE_CHECKING, List
|
|
22
|
+
from typing import List
|
|
21
23
|
|
|
22
24
|
try:
|
|
23
25
|
import pdfkit
|
|
@@ -30,19 +32,35 @@ from bs4 import BeautifulSoup as bs
|
|
|
30
32
|
from tqdm import tqdm
|
|
31
33
|
|
|
32
34
|
try:
|
|
33
|
-
import
|
|
35
|
+
import keyring
|
|
34
36
|
except ImportError:
|
|
35
|
-
|
|
36
|
-
# An ignore hint does not work as it would be marked as superfluous
|
|
37
|
-
# by mypy if secretstorage is installed.
|
|
38
|
-
# Therefore we result to the TYPE_CHECKING constant
|
|
39
|
-
secretstorage = None
|
|
37
|
+
keyring = None
|
|
40
38
|
|
|
41
39
|
YOUTUBE_ID_LENGTH = 11
|
|
42
40
|
|
|
43
41
|
logger = logging.getLogger(__name__)
|
|
44
42
|
|
|
45
43
|
|
|
44
|
+
"""
|
|
45
|
+
To add TOTP functionality without adding external dependencies.
|
|
46
|
+
Code taken from:
|
|
47
|
+
https://github.com/susam/mintotp
|
|
48
|
+
"""
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
def hotp(key, counter, digits=6, digest="sha1"):
|
|
52
|
+
key = base64.b32decode(key.upper() + "=" * ((8 - len(key)) % 8))
|
|
53
|
+
counter = struct.pack(">Q", counter)
|
|
54
|
+
mac = hmac.new(key, counter, digest).digest()
|
|
55
|
+
offset = mac[-1] & 0x0F
|
|
56
|
+
binary = struct.unpack(">L", mac[offset : offset + 4])[0] & 0x7FFFFFFF
|
|
57
|
+
return str(binary)[-digits:].zfill(digits)
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
def totp(key, time_step=30, digits=6, digest="sha1"):
|
|
61
|
+
return hotp(key, int(time.time() / time_step), digits, digest)
|
|
62
|
+
|
|
63
|
+
|
|
46
64
|
class Node:
|
|
47
65
|
def __init__(
|
|
48
66
|
self,
|
|
@@ -209,6 +227,9 @@ class SyncMyMoodle:
|
|
|
209
227
|
pickle.dump(self.session.cookies, f)
|
|
210
228
|
return
|
|
211
229
|
soup = bs(resp.text, features="html.parser")
|
|
230
|
+
if "Wartungsarbeiten" in resp.text:
|
|
231
|
+
logger.critical(soup.find("body").text)
|
|
232
|
+
sys.exit()
|
|
212
233
|
if soup.find("input", {"name": "RelayState"}) is None:
|
|
213
234
|
csrf_token = soup.find("input", {"name": "csrf_token"})["value"]
|
|
214
235
|
login_data = {
|
|
@@ -250,8 +271,12 @@ class SyncMyMoodle:
|
|
|
250
271
|
sys.exit(1)
|
|
251
272
|
|
|
252
273
|
csrf_token = soup.find("input", {"name": "csrf_token"})["value"]
|
|
274
|
+
if not self.config.get("totpsecret"):
|
|
275
|
+
totp_input = input(f"Enter TOTP for generator {self.config['totp']}:\n")
|
|
276
|
+
else:
|
|
277
|
+
totp_input = totp(self.config.get("totpsecret"))
|
|
278
|
+
print(f"Generated TOTP from provided secret: {totp_input}")
|
|
253
279
|
|
|
254
|
-
totp_input = input(f"Enter TOTP for generator {self.config['totp']}:\n")
|
|
255
280
|
totp_login_data = {
|
|
256
281
|
"fudis_otp_input": totp_input,
|
|
257
282
|
"_eventId_proceed": "",
|
|
@@ -260,7 +285,7 @@ class SyncMyMoodle:
|
|
|
260
285
|
|
|
261
286
|
resp4 = self.session.post(resp3.url, data=totp_login_data)
|
|
262
287
|
|
|
263
|
-
sleep(1) # if we go too fast, we might have our connection closed
|
|
288
|
+
time.sleep(1) # if we go too fast, we might have our connection closed
|
|
264
289
|
soup = bs(resp4.text, features="html.parser")
|
|
265
290
|
if soup.find("input", {"name": "RelayState"}) is None:
|
|
266
291
|
logger.critical(
|
|
@@ -936,17 +961,26 @@ class SyncMyMoodle:
|
|
|
936
961
|
episodejson = f"https://engage.streaming.rwth-aachen.de/search/episode.json?id={linkid.groups()[0]}"
|
|
937
962
|
episodejson = json.loads(self.session.get(episodejson).text)
|
|
938
963
|
|
|
939
|
-
tracks
|
|
940
|
-
|
|
964
|
+
# Collect tracks from all mediapackages
|
|
965
|
+
mediapackages = [
|
|
966
|
+
track["mediapackage"]["media"]["track"] for track in episodejson["result"]
|
|
941
967
|
]
|
|
968
|
+
|
|
969
|
+
# TODO, handle multiple mediapackages (videos? could be seperate presenter and screencap)
|
|
970
|
+
tracks = mediapackages[0]
|
|
971
|
+
|
|
972
|
+
# Filter and sort tracks by resolution (width)
|
|
942
973
|
tracks = sorted(
|
|
943
974
|
[
|
|
944
975
|
(t["url"], t["video"]["resolution"])
|
|
945
976
|
for t in tracks
|
|
946
|
-
if t["mimetype"] == "video/mp4"
|
|
977
|
+
if t["mimetype"] == "video/mp4"
|
|
978
|
+
and "transport" not in t
|
|
979
|
+
and "video" in t
|
|
947
980
|
],
|
|
948
|
-
key=
|
|
981
|
+
key=lambda x: int(x[1].split("x")[0]), # Sort by width (e.g., "1920x1080")
|
|
949
982
|
)
|
|
983
|
+
|
|
950
984
|
# only choose mp4s provided with plain https (no transport key), and use the one with the highest resolution (sorted by width) (could also use bitrate)
|
|
951
985
|
finaltrack = tracks[-1]
|
|
952
986
|
|
|
@@ -1118,11 +1152,16 @@ def main():
|
|
|
1118
1152
|
description="Synchronization client for RWTH Moodle. All optional arguments override those in config.json.",
|
|
1119
1153
|
)
|
|
1120
1154
|
|
|
1121
|
-
if
|
|
1155
|
+
if keyring:
|
|
1122
1156
|
parser.add_argument(
|
|
1123
1157
|
"--secretservice",
|
|
1124
1158
|
action="store_true",
|
|
1125
|
-
help="
|
|
1159
|
+
help="Use system's keyring for storing and retrieving account credentials",
|
|
1160
|
+
)
|
|
1161
|
+
parser.add_argument(
|
|
1162
|
+
"--secretservicetotpsecret",
|
|
1163
|
+
action="store_true",
|
|
1164
|
+
help="Save TOTP secret in keyring",
|
|
1126
1165
|
)
|
|
1127
1166
|
|
|
1128
1167
|
parser.add_argument(
|
|
@@ -1136,6 +1175,11 @@ def main():
|
|
|
1136
1175
|
default=None,
|
|
1137
1176
|
help="set your RWTH Single Sign-On TOTP provider's serial number (see https://idm.rwth-aachen.de/selfservice/MFATokenManager)",
|
|
1138
1177
|
)
|
|
1178
|
+
parser.add_argument(
|
|
1179
|
+
"--totpsecret",
|
|
1180
|
+
default=None,
|
|
1181
|
+
help="(optional) set your RWTH Single Sign-On TOTP provider Secret",
|
|
1182
|
+
)
|
|
1139
1183
|
parser.add_argument("--config", default=None, help="set your configuration file")
|
|
1140
1184
|
parser.add_argument(
|
|
1141
1185
|
"--cookiefile", default=None, help="set the location of a cookie file"
|
|
@@ -1206,6 +1250,7 @@ def main():
|
|
|
1206
1250
|
config["user"] = args.user or config.get("user")
|
|
1207
1251
|
config["password"] = args.password or config.get("password")
|
|
1208
1252
|
config["totp"] = args.totp or config.get("totp")
|
|
1253
|
+
config["totpsecret"] = args.totpsecret or config.get("totpsecret")
|
|
1209
1254
|
config["cookie_file"] = args.cookiefile or config.get("cookie_file", "./session")
|
|
1210
1255
|
config["selected_courses"] = (
|
|
1211
1256
|
args.courses.split(",") if args.courses else config.get("selected_courses", [])
|
|
@@ -1217,8 +1262,11 @@ def main():
|
|
|
1217
1262
|
)
|
|
1218
1263
|
config["basedir"] = args.basedir or config.get("basedir", "./")
|
|
1219
1264
|
config["use_secret_service"] = (
|
|
1220
|
-
args.secretservice if
|
|
1265
|
+
args.secretservice if keyring else None
|
|
1221
1266
|
) or config.get("use_secret_service")
|
|
1267
|
+
config["secret_service_store_totp_secret"] = (
|
|
1268
|
+
args.secretservicetotpsecret if keyring else None
|
|
1269
|
+
) or config.get("secret_service_store_totp_secret")
|
|
1222
1270
|
config["skip_courses"] = (
|
|
1223
1271
|
args.skipcourses.split(",")
|
|
1224
1272
|
if args.skipcourses
|
|
@@ -1251,44 +1299,51 @@ def main():
|
|
|
1251
1299
|
"You do not have wkhtmltopdf in your path. Quiz-PDFs are NOT generated"
|
|
1252
1300
|
)
|
|
1253
1301
|
|
|
1254
|
-
if
|
|
1302
|
+
if keyring and config.get("use_secret_service"):
|
|
1255
1303
|
if config.get("password"):
|
|
1256
1304
|
logger.critical("You need to remove your password from your config file!")
|
|
1257
1305
|
sys.exit(1)
|
|
1258
1306
|
|
|
1259
|
-
|
|
1260
|
-
|
|
1261
|
-
|
|
1262
|
-
|
|
1263
|
-
|
|
1264
|
-
|
|
1265
|
-
|
|
1266
|
-
|
|
1267
|
-
|
|
1268
|
-
|
|
1269
|
-
|
|
1270
|
-
|
|
1307
|
+
if config.get("secret_service_store_totp_secret") and config.get("totpsecret"):
|
|
1308
|
+
logger.critical("You need to remove your totpsecret from your config file!")
|
|
1309
|
+
sys.exit(1)
|
|
1310
|
+
|
|
1311
|
+
if not args.user and not config.get("user"):
|
|
1312
|
+
print(
|
|
1313
|
+
"You need to provide your username in the config file or through --user!"
|
|
1314
|
+
)
|
|
1315
|
+
sys.exit(1)
|
|
1316
|
+
|
|
1317
|
+
if (
|
|
1318
|
+
config.get("secretservicetotpsecret")
|
|
1319
|
+
and not args.totp
|
|
1320
|
+
and not config.get("totp")
|
|
1321
|
+
):
|
|
1322
|
+
print(
|
|
1323
|
+
"You need to provide your TOTP provider in the config file or through --totp!"
|
|
1324
|
+
)
|
|
1325
|
+
sys.exit(1)
|
|
1326
|
+
|
|
1327
|
+
config["password"] = keyring.get_password("syncmymoodle", config.get("user"))
|
|
1328
|
+
if config["password"] is None:
|
|
1271
1329
|
if args.password:
|
|
1272
1330
|
password = args.password
|
|
1273
1331
|
else:
|
|
1274
1332
|
password = getpass.getpass("Password:")
|
|
1275
|
-
|
|
1276
|
-
|
|
1277
|
-
|
|
1333
|
+
keyring.set_password("syncmymoodle", config.get("user"), password)
|
|
1334
|
+
config["password"] = password
|
|
1335
|
+
|
|
1336
|
+
if config.get("secret_service_store_totp_secret"):
|
|
1337
|
+
config["totpsecret"] = keyring.get_password(
|
|
1338
|
+
"syncmymoodle", config.get("totp")
|
|
1278
1339
|
)
|
|
1279
|
-
|
|
1280
|
-
|
|
1281
|
-
|
|
1282
|
-
|
|
1283
|
-
|
|
1284
|
-
|
|
1285
|
-
""
|
|
1286
|
-
while item.unlock():
|
|
1287
|
-
print("Please confirm to unlock the password if prompted!")
|
|
1288
|
-
pass
|
|
1289
|
-
if not config.get("user"):
|
|
1290
|
-
config["user"] = item.get_attributes().get("username")
|
|
1291
|
-
config["password"] = item.get_secret().decode("utf-8")
|
|
1340
|
+
if config["totpsecret"] is None:
|
|
1341
|
+
if args.totpsecret:
|
|
1342
|
+
totpsecret = args.totpsecret
|
|
1343
|
+
else:
|
|
1344
|
+
totpsecret = getpass.getpass("TOTP-Secret:")
|
|
1345
|
+
keyring.set_password("syncmymoodle", config.get("totp"), totpsecret)
|
|
1346
|
+
config["totpsecret"] = totpsecret
|
|
1292
1347
|
|
|
1293
1348
|
if not config.get("user") or not config.get("password"):
|
|
1294
1349
|
logger.critical(
|
|
@@ -1298,7 +1353,7 @@ def main():
|
|
|
1298
1353
|
|
|
1299
1354
|
if not config.get("totp"):
|
|
1300
1355
|
logger.critical(
|
|
1301
|
-
"You need to specify your
|
|
1356
|
+
"You need to specify your TOTP generator in the config file or as an argument!"
|
|
1302
1357
|
)
|
|
1303
1358
|
sys.exit(1)
|
|
1304
1359
|
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|