udemy-userAPI 0.3.4__py3-none-any.whl → 0.3.6__py3-none-any.whl
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.
- udemy_userAPI/__version__.py +1 -1
- udemy_userAPI/api.py +146 -46
- udemy_userAPI/authenticate.py +8 -4
- udemy_userAPI/bultins.py +128 -51
- udemy_userAPI/sections.py +3 -3
- udemy_userAPI/udemy.py +1 -1
- {udemy_userAPI-0.3.4.dist-info → udemy_userAPI-0.3.6.dist-info}/METADATA +13 -3
- udemy_userAPI-0.3.6.dist-info/RECORD +17 -0
- {udemy_userAPI-0.3.4.dist-info → udemy_userAPI-0.3.6.dist-info}/WHEEL +1 -1
- animation_consoles/__init__.py +0 -1
- animation_consoles/animation.py +0 -64
- ffmpeg_for_python/__config__.py +0 -118
- ffmpeg_for_python/__init__.py +0 -8
- ffmpeg_for_python/__utils.py +0 -78
- ffmpeg_for_python/__version__.py +0 -6
- ffmpeg_for_python/exeptions.py +0 -91
- ffmpeg_for_python/ffmpeg.py +0 -203
- m3u8_analyzer/M3u8Analyzer.py +0 -807
- m3u8_analyzer/__init__.py +0 -7
- m3u8_analyzer/__version__.py +0 -1
- m3u8_analyzer/exeptions.py +0 -82
- udemy_userAPI-0.3.4.dist-info/RECORD +0 -29
- {udemy_userAPI-0.3.4.dist-info → udemy_userAPI-0.3.6.dist-info}/LICENSE +0 -0
- {udemy_userAPI-0.3.4.dist-info → udemy_userAPI-0.3.6.dist-info}/top_level.txt +0 -0
udemy_userAPI/__version__.py
CHANGED
udemy_userAPI/api.py
CHANGED
@@ -66,7 +66,7 @@ def get_pssh(init_url):
|
|
66
66
|
from .authenticate import UdemyAuth
|
67
67
|
auth = UdemyAuth()
|
68
68
|
if not auth.verif_login():
|
69
|
-
raise LoginException("
|
69
|
+
raise LoginException("Sessão expirada!")
|
70
70
|
res = requests.get(init_url, headers=HEADERS_octet_stream)
|
71
71
|
if not res.ok:
|
72
72
|
return
|
@@ -134,7 +134,8 @@ def extract(pssh, license_token):
|
|
134
134
|
from .authenticate import UdemyAuth
|
135
135
|
auth = UdemyAuth()
|
136
136
|
if not auth.verif_login():
|
137
|
-
raise LoginException(
|
137
|
+
raise LoginException(
|
138
|
+
"Sessão expirada!")
|
138
139
|
license_url = (f"https://www.udemy.com/api-2.0/media-license-server/validate-auth-token?drm_type=widevine"
|
139
140
|
f"&auth_token={license_token}")
|
140
141
|
session_id = cdm.open()
|
@@ -163,7 +164,7 @@ def get_mpd_file(mpd_url):
|
|
163
164
|
from .authenticate import UdemyAuth
|
164
165
|
auth = UdemyAuth()
|
165
166
|
if not auth.verif_login():
|
166
|
-
raise LoginException("
|
167
|
+
raise LoginException("Sessão expirada!")
|
167
168
|
try:
|
168
169
|
# Faz a solicitação GET com os cabeçalhos
|
169
170
|
response = requests.get(mpd_url, headers=HEADERS_USER)
|
@@ -184,43 +185,58 @@ def get_mpd_file(mpd_url):
|
|
184
185
|
raise UnhandledExceptions(f"Errro Ao Obter Mídias:{e}")
|
185
186
|
|
186
187
|
|
187
|
-
def
|
188
|
-
"""
|
189
|
-
:param results:
|
190
|
-
:return:
|
191
|
-
"""
|
192
|
-
if not results:
|
193
|
-
raise UdemyUserApiExceptions("Não foi possível obter detalhes do curso!")
|
194
|
-
results = results.get('results', None)
|
188
|
+
def parser_chapters(results) -> list[dict]:
|
195
189
|
if not results:
|
196
190
|
raise UdemyUserApiExceptions("Não foi possível obter detalhes do curso!")
|
197
|
-
chapters_dict = {} # Dicionário para armazenar os capítulos e seus vídeos correspondentes
|
198
191
|
|
199
|
-
|
200
|
-
|
192
|
+
results = results.get('results', [])
|
193
|
+
chapters_dicts = [] # Lista que armazena todos os capítulos
|
194
|
+
current_chapter = None # Capítulo atual
|
195
|
+
|
201
196
|
for dictionary in results:
|
202
197
|
_class = dictionary.get('_class')
|
198
|
+
chapter_index = dictionary.get('object_index')
|
203
199
|
|
200
|
+
# Quando encontrar um novo capítulo
|
204
201
|
if _class == 'chapter':
|
205
|
-
|
202
|
+
if current_chapter: # Se já há um capítulo atual, adicionamos
|
203
|
+
chapters_dicts.append(current_chapter)
|
204
|
+
|
205
|
+
# Inicia um novo capítulo
|
206
206
|
current_chapter = {
|
207
|
-
'
|
208
|
-
'
|
207
|
+
'title': dictionary.get('title'),
|
208
|
+
'chapter_index': chapter_index,
|
209
|
+
'lectures': [] # Lista para armazenar aulas e quizzes
|
209
210
|
}
|
210
|
-
|
211
|
-
|
211
|
+
|
212
|
+
# Se for uma aula, adiciona ao capítulo atual
|
213
|
+
elif _class == 'lecture' and current_chapter:
|
212
214
|
asset = dictionary.get('asset')
|
213
215
|
if asset:
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
'
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
216
|
+
lecture_data = {
|
217
|
+
'asset_type': asset.get('asset_type', ''),
|
218
|
+
'title': dictionary.get('title', 'Files'),
|
219
|
+
'lecture_id': dictionary.get('id', ''),
|
220
|
+
'asset_id': asset.get('id', '')
|
221
|
+
}
|
222
|
+
current_chapter['lectures'].append(lecture_data)
|
223
|
+
|
224
|
+
# Se for um quiz, também adiciona ao capítulo atual
|
225
|
+
elif _class == 'quiz' and current_chapter:
|
226
|
+
quiz_data = {
|
227
|
+
'asset_type': 'quiz',
|
228
|
+
'title': dictionary.get('title', 'Quiz'),
|
229
|
+
'lecture_id': dictionary.get('id', ''),
|
230
|
+
'type': dictionary.get('type', ''),
|
231
|
+
'asset_id': ''
|
232
|
+
}
|
233
|
+
current_chapter['lectures'].append(quiz_data)
|
234
|
+
|
235
|
+
# Adiciona o último capítulo processado
|
236
|
+
if current_chapter:
|
237
|
+
chapters_dicts.append(current_chapter)
|
238
|
+
|
239
|
+
return chapters_dicts
|
224
240
|
|
225
241
|
|
226
242
|
def get_add_files(course_id: int):
|
@@ -240,7 +256,7 @@ def get_add_files(course_id: int):
|
|
240
256
|
from .authenticate import UdemyAuth
|
241
257
|
auth = UdemyAuth()
|
242
258
|
if not auth.verif_login():
|
243
|
-
raise LoginException("
|
259
|
+
raise LoginException("Sessão expirada!")
|
244
260
|
url = (f'https://www.udemy.com/api-2.0/courses/{course_id}/subscriber-curriculum-items/?page_size=2000&fields['
|
245
261
|
f'lecture]=title,object_index,is_published,sort_order,created,asset,supplementary_assets,is_free&fields['
|
246
262
|
f'quiz]=title,object_index,is_published,sort_order,type&fields[practice]=title,object_index,is_published,'
|
@@ -304,15 +320,15 @@ def get_links(course_id: int, id_lecture: int):
|
|
304
320
|
erro ao obter dados das aulas.
|
305
321
|
"""
|
306
322
|
get = (f"https://www.udemy.com/api-2.0/users/me/subscribed-courses/{course_id}/lectures/{id_lecture}/?"
|
307
|
-
|
308
|
-
|
309
|
-
|
310
|
-
|
311
|
-
|
323
|
+
f"fields[lecture]"
|
324
|
+
f"=asset,description,download_url,is_free,last_watched_second&fields[asset]=asset_type,length,"
|
325
|
+
f"media_license_token,course_is_drmed,media_sources,captions,thumbnail_sprite,slides,slide_urls,"
|
326
|
+
f"download_urls,"
|
327
|
+
f"external_url&q=0.3108014137011559/?fields[asset]=download_urls")
|
312
328
|
from .authenticate import UdemyAuth
|
313
329
|
auth = UdemyAuth()
|
314
330
|
if not auth.verif_login():
|
315
|
-
raise LoginException("
|
331
|
+
raise LoginException("Sessão expirada!")
|
316
332
|
try:
|
317
333
|
# Faz a solicitação GET com os cabeçalhos
|
318
334
|
response = requests.get(get, headers=HEADERS_USER)
|
@@ -322,18 +338,96 @@ def get_links(course_id: int, id_lecture: int):
|
|
322
338
|
a = json.loads(response.text)
|
323
339
|
return a
|
324
340
|
else:
|
325
|
-
raise UnhandledExceptions(
|
341
|
+
raise UnhandledExceptions(
|
342
|
+
f"Erro ao obter dados da aula! Código de status: {response.status_code}")
|
326
343
|
|
327
344
|
except requests.ConnectionError as e:
|
328
|
-
raise UdemyUserApiExceptions(
|
345
|
+
raise UdemyUserApiExceptions(
|
346
|
+
f"Erro de conexão: {e}")
|
329
347
|
except requests.Timeout as e:
|
330
|
-
raise UdemyUserApiExceptions(
|
348
|
+
raise UdemyUserApiExceptions(
|
349
|
+
f"Tempo de requisição excedido: {e}")
|
331
350
|
except requests.TooManyRedirects as e:
|
332
|
-
raise UdemyUserApiExceptions(
|
351
|
+
raise UdemyUserApiExceptions(
|
352
|
+
f"Limite de redirecionamentos excedido: {e}")
|
333
353
|
except requests.HTTPError as e:
|
334
|
-
raise UdemyUserApiExceptions(
|
354
|
+
raise UdemyUserApiExceptions(
|
355
|
+
f"Erro HTTP: {e}")
|
335
356
|
except Exception as e:
|
336
|
-
raise UnhandledExceptions(
|
357
|
+
raise UnhandledExceptions(
|
358
|
+
f"Erro ao obter mídias: {e}")
|
359
|
+
|
360
|
+
def get_assessments(course_id: int,lecture_id:int):
|
361
|
+
get = (f'https://www.udemy.com/api-2.0/users/me/subscribed-courses/{course_id}/quizzes/{lecture_id}/?draft='
|
362
|
+
f'false&fields[quiz]=id,type,title,description,object_index,num_assessments,version,duration,'
|
363
|
+
f'is_draft,pass_percent,changelog')
|
364
|
+
from .authenticate import UdemyAuth
|
365
|
+
auth = UdemyAuth()
|
366
|
+
if not auth.verif_login():
|
367
|
+
raise LoginException("Sessão expirada!")
|
368
|
+
try:
|
369
|
+
# Faz a solicitação GET com os cabeçalhos
|
370
|
+
response = requests.get(get, headers=HEADERS_USER)
|
371
|
+
data = []
|
372
|
+
# Exibe o código de status
|
373
|
+
if response.status_code == 200:
|
374
|
+
a = json.loads(response.text)
|
375
|
+
return a
|
376
|
+
else:
|
377
|
+
raise ConnectionError(
|
378
|
+
f"Erro ao obter dados da aula! Código de status: {response.status_code}\n"
|
379
|
+
f"{response.text}"
|
380
|
+
)
|
381
|
+
|
382
|
+
except requests.ConnectionError as e:
|
383
|
+
raise UdemyUserApiExceptions(
|
384
|
+
f"Erro de conexão: {e}")
|
385
|
+
except requests.Timeout as e:
|
386
|
+
raise UdemyUserApiExceptions(
|
387
|
+
f"Tempo de requisição excedido: {e}")
|
388
|
+
except requests.TooManyRedirects as e:
|
389
|
+
raise UdemyUserApiExceptions(
|
390
|
+
f"Limite de redirecionamentos excedido: {e}")
|
391
|
+
except requests.HTTPError as e:
|
392
|
+
raise UdemyUserApiExceptions(
|
393
|
+
f"Erro HTTP: {e}")
|
394
|
+
|
395
|
+
|
396
|
+
def get_quizzes(lecture_id:int):
|
397
|
+
get = (f'https://www.udemy.com/api-2.0/quizzes/{lecture_id}/assessments/?version=1&page_size=1000&fields[assessment]'
|
398
|
+
f'=id,assessment_type,prompt,correct_response,section,question_plain,related_lectures&use_remote_version=true'
|
399
|
+
)
|
400
|
+
from .authenticate import UdemyAuth
|
401
|
+
auth = UdemyAuth()
|
402
|
+
if not auth.verif_login():
|
403
|
+
raise LoginException("Sessão expirada!")
|
404
|
+
try:
|
405
|
+
# Faz a solicitação GET com os cabeçalhos
|
406
|
+
response = requests.get(get, headers=HEADERS_USER)
|
407
|
+
data = []
|
408
|
+
# Exibe o código de status
|
409
|
+
if response.status_code == 200:
|
410
|
+
a = json.loads(response.text)
|
411
|
+
return a
|
412
|
+
else:
|
413
|
+
raise UnhandledExceptions(
|
414
|
+
f"Erro ao obter dados da aula! Código de status: {response.status_code}")
|
415
|
+
|
416
|
+
except requests.ConnectionError as e:
|
417
|
+
raise UdemyUserApiExceptions(
|
418
|
+
f"Erro de conexão: {e}")
|
419
|
+
except requests.Timeout as e:
|
420
|
+
raise UdemyUserApiExceptions(
|
421
|
+
f"Tempo de requisição excedido: {e}")
|
422
|
+
except requests.TooManyRedirects as e:
|
423
|
+
raise UdemyUserApiExceptions(
|
424
|
+
f"Limite de redirecionamentos excedido: {e}")
|
425
|
+
except requests.HTTPError as e:
|
426
|
+
raise UdemyUserApiExceptions(
|
427
|
+
f"Erro HTTP: {e}")
|
428
|
+
except Exception as e:
|
429
|
+
raise UnhandledExceptions(
|
430
|
+
f"Erro ao obter mídias: {e}")
|
337
431
|
|
338
432
|
|
339
433
|
def remove_tag(d: str):
|
@@ -360,7 +454,7 @@ def get_external_liks(course_id: int, id_lecture, asset_id):
|
|
360
454
|
from .authenticate import UdemyAuth
|
361
455
|
auth = UdemyAuth()
|
362
456
|
if not auth.verif_login():
|
363
|
-
raise LoginException("
|
457
|
+
raise LoginException("Sessão expirada!")
|
364
458
|
url = (f'https://www.udemy.com/api-2.0/users/me/subscribed-courses/{course_id}/lectures/{id_lecture}/'
|
365
459
|
f'supplementary-assets/{asset_id}/?fields[asset]=external_url')
|
366
460
|
try:
|
@@ -561,7 +655,7 @@ def lecture_infor(course_id: int, id_lecture: int):
|
|
561
655
|
from .authenticate import UdemyAuth
|
562
656
|
auth = UdemyAuth()
|
563
657
|
if not auth.verif_login():
|
564
|
-
raise LoginException("
|
658
|
+
raise LoginException("Sessão expirada!")
|
565
659
|
edpoint = (f"https://www.udemy.com/api-2.0/users/me/subscribed-courses/{course_id}/lectures/{id_lecture}/?"
|
566
660
|
f"fields[asset]=media_license_token")
|
567
661
|
r = requests.get(edpoint, headers=HEADERS_USER)
|
@@ -592,7 +686,7 @@ def assets_infor(course_id: int, id_lecture: int, assets_id: int):
|
|
592
686
|
from .authenticate import UdemyAuth
|
593
687
|
auth = UdemyAuth()
|
594
688
|
if not auth.verif_login():
|
595
|
-
raise LoginException("
|
689
|
+
raise LoginException("Sessão expirada!")
|
596
690
|
endpoint = (f'https://www.udemy.com/api-2.0/assets/{assets_id}/?fields[asset]=@min,status,delayed_asset_message,'
|
597
691
|
f'processing_errors,body&course_id={course_id}&lecture_id={id_lecture}')
|
598
692
|
r = requests.get(endpoint, headers=HEADERS_USER)
|
@@ -607,6 +701,7 @@ def assets_infor(course_id: int, id_lecture: int, assets_id: int):
|
|
607
701
|
f"{r.text}")
|
608
702
|
|
609
703
|
|
704
|
+
|
610
705
|
def save_html(body, title_lecture):
|
611
706
|
html_content = f"""<!DOCTYPE html>
|
612
707
|
<html lang="en">
|
@@ -621,7 +716,6 @@ def save_html(body, title_lecture):
|
|
621
716
|
|
622
717
|
return html_content
|
623
718
|
|
624
|
-
|
625
719
|
def J(e, t):
|
626
720
|
"""
|
627
721
|
Gera um identificador único baseado na data atual e nas funções X e ee.
|
@@ -689,3 +783,9 @@ def te(e, t):
|
|
689
783
|
s = t[:r]
|
690
784
|
o = ''.join(format(byte, '08b') for byte in s)
|
691
785
|
return o.startswith('0' * e)
|
786
|
+
def is_lecture_in_course(lectures,lecture_id) -> bool:
|
787
|
+
# Verifica se o lecture_id está presente na lista de aulas
|
788
|
+
for lecture in lectures:
|
789
|
+
if lecture.get('lecture_id') == lecture_id:
|
790
|
+
return True
|
791
|
+
return False
|
udemy_userAPI/authenticate.py
CHANGED
@@ -89,7 +89,11 @@ class UdemyAuth:
|
|
89
89
|
return False
|
90
90
|
else:
|
91
91
|
if 'error: 111' in resp.text:
|
92
|
-
raise Upstreamconnecterror(message=
|
92
|
+
raise Upstreamconnecterror(message=
|
93
|
+
'Erro ao se comunicar com o servidor remoto!')
|
94
|
+
elif 'upstream connect error or disconnect/reset before headers. reset reason: connection timeout' in resp.text:
|
95
|
+
raise Upstreamconnecterror(""
|
96
|
+
"Ocorreu uma falha de tempo de resposta!")
|
93
97
|
else:
|
94
98
|
raise LoginException(f"Erro Ao obter login : {resp.text}")
|
95
99
|
except requests.ConnectionError as e:
|
@@ -101,7 +105,7 @@ class UdemyAuth:
|
|
101
105
|
except requests.HTTPError as e:
|
102
106
|
raise UdemyUserApiExceptions(f"Erro HTTP: {e}")
|
103
107
|
except Exception as e:
|
104
|
-
raise UnhandledExceptions(f"
|
108
|
+
raise UnhandledExceptions(f"{e}")
|
105
109
|
else:
|
106
110
|
return False
|
107
111
|
|
@@ -116,7 +120,7 @@ class UdemyAuth:
|
|
116
120
|
"""
|
117
121
|
try:
|
118
122
|
if self.verif_login():
|
119
|
-
raise UserWarning("Atenção, você já possui uma
|
123
|
+
raise UserWarning("Atenção, você já possui uma Sessão válida!")
|
120
124
|
s = cloudscraper.create_scraper()
|
121
125
|
r = s.get(
|
122
126
|
"https://www.udemy.com/join/signup-popup/",
|
@@ -222,7 +226,7 @@ class UdemyAuth:
|
|
222
226
|
from .api import J
|
223
227
|
try:
|
224
228
|
if self.verif_login():
|
225
|
-
raise UserWarning("Atenção, você já possui uma
|
229
|
+
raise UserWarning("Atenção, você já possui uma Sessão válida!")
|
226
230
|
# Inicializa uma sessão com proteção contra Cloudflare
|
227
231
|
session = cloudscraper.create_scraper()
|
228
232
|
|
udemy_userAPI/bultins.py
CHANGED
@@ -1,11 +1,8 @@
|
|
1
|
-
import json
|
2
1
|
from typing import Any
|
3
|
-
import
|
4
|
-
from .api import get_links, remove_tag, parser_chapers, extract_files, HEADERS_USER, assets_infor, get_add_files, \
|
5
|
-
get_files_aule, get_external_liks, extract, get_pssh, organize_streams, get_mpd_file, get_highest_resolution
|
6
|
-
from .sections import get_course_infor
|
7
|
-
from .mpd_analyzer import MPDParser
|
2
|
+
from .api import *
|
8
3
|
from .exeptions import LoginException
|
4
|
+
from .mpd_analyzer import MPDParser
|
5
|
+
from .sections import get_course_infor
|
9
6
|
|
10
7
|
|
11
8
|
class DRM:
|
@@ -76,7 +73,7 @@ class Files:
|
|
76
73
|
from .authenticate import UdemyAuth
|
77
74
|
auth = UdemyAuth()
|
78
75
|
if not auth.verif_login():
|
79
|
-
raise LoginException("
|
76
|
+
raise LoginException("Sessão expirada!")
|
80
77
|
download_urls = []
|
81
78
|
for files in self.__data:
|
82
79
|
lecture_id = files.get('lecture_id', None)
|
@@ -108,6 +105,62 @@ class Files:
|
|
108
105
|
download_urls.append(dt_file)
|
109
106
|
return download_urls
|
110
107
|
|
108
|
+
class Quiz:
|
109
|
+
"""Representa um quiz.
|
110
|
+
"""
|
111
|
+
|
112
|
+
def __init__(self, quiz_data: dict):
|
113
|
+
"""
|
114
|
+
Inicializa uma instância de Quiz.
|
115
|
+
|
116
|
+
Args:
|
117
|
+
quiz_data (dict): Dados do quiz.
|
118
|
+
"""
|
119
|
+
self._data = quiz_data
|
120
|
+
|
121
|
+
@property
|
122
|
+
def id(self) -> int:
|
123
|
+
"""Retorna o ID do quiz."""
|
124
|
+
return self._data.get('id', 0)
|
125
|
+
|
126
|
+
@property
|
127
|
+
def title(self) -> str:
|
128
|
+
"""Retorna o título do quiz."""
|
129
|
+
return self._data.get('title', '')
|
130
|
+
|
131
|
+
@property
|
132
|
+
def type_quiz(self) -> str:
|
133
|
+
"""Retorna o tipo de quiz (exame ou prática)."""
|
134
|
+
return self._data.get('type', '')
|
135
|
+
|
136
|
+
@property
|
137
|
+
def description(self) -> str:
|
138
|
+
"""Retorna a descrição do quiz."""
|
139
|
+
return remove_tag(self._data.get('description', ''))
|
140
|
+
|
141
|
+
@property
|
142
|
+
def duration(self) -> int:
|
143
|
+
"""Retorna a duração do quiz em minutos, se aplicável."""
|
144
|
+
duration: int = self._data.get('duration', 1)
|
145
|
+
if duration > 1:
|
146
|
+
return int(duration / 60)
|
147
|
+
else:
|
148
|
+
return 0
|
149
|
+
|
150
|
+
@property
|
151
|
+
def pass_percent(self) -> int:
|
152
|
+
"""Retorna a porcentagem necessária para passar."""
|
153
|
+
return self._data.get('pass_percent', 0)
|
154
|
+
|
155
|
+
@property
|
156
|
+
def num_assessments(self) -> int:
|
157
|
+
"""Retorna o número de perguntas do quiz."""
|
158
|
+
return self._data.get('num_assessments', 0)
|
159
|
+
|
160
|
+
def content(self) -> dict:
|
161
|
+
"""Obtém o conteúdo do quiz."""
|
162
|
+
htmls = get_quizzes(lecture_id=self.id)
|
163
|
+
return htmls
|
111
164
|
|
112
165
|
class Lecture:
|
113
166
|
"""Cria objetos aula (lecture) do curso e extrai os dados."""
|
@@ -166,8 +219,8 @@ class Lecture:
|
|
166
219
|
"""
|
167
220
|
thumbnail_sprite = self.__asset.get('thumbnail_sprite', {})
|
168
221
|
return {
|
169
|
-
'thumbnail_vtt_url': thumbnail_sprite.get('vtt_url'),
|
170
|
-
'thumbnail_img_url': thumbnail_sprite.get('img_url')
|
222
|
+
'thumbnail_vtt_url': thumbnail_sprite.get('vtt_url',[]),
|
223
|
+
'thumbnail_img_url': thumbnail_sprite.get('img_url',[])
|
171
224
|
}
|
172
225
|
|
173
226
|
@property
|
@@ -178,7 +231,7 @@ class Lecture:
|
|
178
231
|
Returns:
|
179
232
|
str: O tipo de asset.
|
180
233
|
"""
|
181
|
-
return self.__asset.get('asset_type', '
|
234
|
+
return self.__asset.get('asset_type', '') or self.__data.get('_class','').replace('quiz','Quiz')
|
182
235
|
|
183
236
|
@property
|
184
237
|
def get_media_sources(self) -> list:
|
@@ -188,7 +241,7 @@ class Lecture:
|
|
188
241
|
Returns:
|
189
242
|
list: Uma lista contendo as fontes de mídia.
|
190
243
|
"""
|
191
|
-
return self.__asset.get('media_sources')
|
244
|
+
return self.__asset.get('media_sources',[])
|
192
245
|
|
193
246
|
@property
|
194
247
|
def get_captions(self) -> list:
|
@@ -198,7 +251,7 @@ class Lecture:
|
|
198
251
|
Returns:
|
199
252
|
list: Uma lista contendo as legendas.
|
200
253
|
"""
|
201
|
-
return self.__asset.get('captions')
|
254
|
+
return self.__asset.get('captions',[])
|
202
255
|
|
203
256
|
@property
|
204
257
|
def get_external_url(self) -> list:
|
@@ -208,7 +261,7 @@ class Lecture:
|
|
208
261
|
Returns:
|
209
262
|
list: Uma lista contendo os links externos.
|
210
263
|
"""
|
211
|
-
return self.__asset.get('external_url')
|
264
|
+
return self.__asset.get('external_url',[])
|
212
265
|
|
213
266
|
@property
|
214
267
|
def get_media_license_token(self) -> str:
|
@@ -218,7 +271,7 @@ class Lecture:
|
|
218
271
|
Returns:
|
219
272
|
str: O token de acesso à aula.
|
220
273
|
"""
|
221
|
-
return self.__asset.get('media_license_token')
|
274
|
+
return self.__asset.get('media_license_token','')
|
222
275
|
|
223
276
|
def course_is_drmed(self) -> DRM:
|
224
277
|
"""
|
@@ -227,12 +280,19 @@ class Lecture:
|
|
227
280
|
Returns:
|
228
281
|
DRM: O objeto DRM contendo as keys da aula ou None.
|
229
282
|
"""
|
230
|
-
|
231
|
-
d = DRM(license_token=self.get_media_license_token,
|
283
|
+
d = DRM(license_token=self.get_media_license_token,
|
232
284
|
get_media_sources=self.get_media_sources)
|
233
|
-
|
234
|
-
|
235
|
-
|
285
|
+
return d
|
286
|
+
|
287
|
+
def quiz_object(self) ->Quiz:
|
288
|
+
"""se for um quiz ele retorna um objeto Quiz"""
|
289
|
+
if self.get_asset_type.lower() == 'quiz':
|
290
|
+
q =Quiz(get_assessments(lecture_id=self.get_lecture_id,course_id=self.__course_id))
|
291
|
+
return q
|
292
|
+
else:
|
293
|
+
raise UserWarning(
|
294
|
+
'Atenção essa aula não é um Quiz!'
|
295
|
+
)
|
236
296
|
|
237
297
|
@property
|
238
298
|
def get_download_urls(self) -> list:
|
@@ -242,7 +302,7 @@ class Lecture:
|
|
242
302
|
Returns:
|
243
303
|
list: Uma lista contendo as URLs de download.
|
244
304
|
"""
|
245
|
-
return self.__asset.get('download_urls')
|
305
|
+
return self.__asset.get('download_urls',[])
|
246
306
|
|
247
307
|
@property
|
248
308
|
def get_slide_urls(self) -> list:
|
@@ -252,7 +312,7 @@ class Lecture:
|
|
252
312
|
Returns:
|
253
313
|
list: Uma lista contendo as URLs de slides.
|
254
314
|
"""
|
255
|
-
return self.__asset.get('slide_urls')
|
315
|
+
return self.__asset.get('slide_urls',[])
|
256
316
|
|
257
317
|
@property
|
258
318
|
def get_slides(self) -> list:
|
@@ -262,7 +322,7 @@ class Lecture:
|
|
262
322
|
Returns:
|
263
323
|
list: Uma lista contendo os slides.
|
264
324
|
"""
|
265
|
-
return self.__asset.get('slides')
|
325
|
+
return self.__asset.get('slides',[])
|
266
326
|
|
267
327
|
@property
|
268
328
|
def get_articles(self):
|
@@ -272,8 +332,11 @@ class Lecture:
|
|
272
332
|
Returns:
|
273
333
|
Os artigos relacionados à aula.
|
274
334
|
"""
|
275
|
-
|
276
|
-
|
335
|
+
if self.__asset:
|
336
|
+
d = assets_infor(course_id=self.__course_id, id_lecture=self.get_lecture_id, assets_id=self.__asset.get("id"))
|
337
|
+
return d
|
338
|
+
else:
|
339
|
+
return []
|
277
340
|
|
278
341
|
@property
|
279
342
|
def get_resources(self):
|
@@ -283,10 +346,12 @@ class Lecture:
|
|
283
346
|
Returns:
|
284
347
|
Os recursos adicionais relacionados à aula.
|
285
348
|
"""
|
286
|
-
|
287
|
-
|
288
|
-
|
289
|
-
|
349
|
+
if self.__additional_files:
|
350
|
+
files_add = get_files_aule(lecture_id_filter=self.get_lecture_id, data=self.__additional_files)
|
351
|
+
f = Files(files=files_add, id_course=self.__course_id).get_download_url
|
352
|
+
return f
|
353
|
+
else:
|
354
|
+
return []
|
290
355
|
|
291
356
|
class Course:
|
292
357
|
"""Recebe um dicionário com os dados do curso."""
|
@@ -299,8 +364,8 @@ class Course:
|
|
299
364
|
results (dict): Um dicionário contendo os dados do curso.
|
300
365
|
course_id (int): O ID do curso.
|
301
366
|
"""
|
302
|
-
self.__parser_chapers =
|
303
|
-
self.__data = self.__parser_chapers
|
367
|
+
self.__parser_chapers = parser_chapters(results=results)
|
368
|
+
self.__data:list = self.__parser_chapers
|
304
369
|
self.__course_id = course_id
|
305
370
|
self.__results = results
|
306
371
|
self.__additional_files_data = get_add_files(course_id)
|
@@ -375,8 +440,8 @@ class Course:
|
|
375
440
|
int: O número total de lectures no curso.
|
376
441
|
"""
|
377
442
|
total_lectures = 0
|
378
|
-
for chapter in self.__data
|
379
|
-
total_lectures += len(chapter.get('
|
443
|
+
for chapter in self.__data:
|
444
|
+
total_lectures += len(chapter.get('lectures', []))
|
380
445
|
return total_lectures
|
381
446
|
|
382
447
|
@property
|
@@ -398,11 +463,13 @@ class Course:
|
|
398
463
|
list: Uma lista contendo os títulos de vídeos no curso.
|
399
464
|
"""
|
400
465
|
videos = []
|
401
|
-
for chapter in self.__data
|
466
|
+
for chapter in self.__data:
|
402
467
|
for video in chapter.get('videos_in_chapter', []):
|
403
|
-
|
404
|
-
if
|
405
|
-
|
468
|
+
asset_type = video.get('asset_type')
|
469
|
+
if asset_type == 'Video':
|
470
|
+
title = video['title']
|
471
|
+
if title != "Files":
|
472
|
+
videos.append(title)
|
406
473
|
return videos
|
407
474
|
|
408
475
|
@property
|
@@ -410,27 +477,25 @@ class Course:
|
|
410
477
|
"""
|
411
478
|
Obtém uma lista com todas as aulas.
|
412
479
|
|
480
|
+
Args:
|
481
|
+
data (list): Lista de capítulos contendo as aulas.
|
482
|
+
|
413
483
|
Returns:
|
414
484
|
list: Uma lista contendo todas as aulas.
|
415
485
|
"""
|
416
486
|
videos = []
|
417
|
-
|
418
|
-
|
419
|
-
|
420
|
-
for index, video in enumerate(chapter.get('videos_in_chapter', [])):
|
421
|
-
section = f"{chapter.get('title_chapter')}" # Adicionar numeração da seção
|
422
|
-
title = video.get('video_title')
|
423
|
-
id_lecture = video.get('lecture_id')
|
424
|
-
id_asset = video.get('asset_id')
|
487
|
+
|
488
|
+
for chapter in self.__data:
|
489
|
+
for video in chapter.get('lectures', []):
|
425
490
|
dt = {
|
426
|
-
'section':
|
427
|
-
'title': title,
|
428
|
-
'lecture_id':
|
429
|
-
'asset_id':
|
430
|
-
'
|
491
|
+
'section': chapter.get('title', ''),
|
492
|
+
'title': video.get('title', ''),
|
493
|
+
'lecture_id': video.get('lecture_id', ''),
|
494
|
+
'asset_id': video.get('asset_id', ''),
|
495
|
+
'asset_type': video.get('asset_type', '')
|
431
496
|
}
|
432
497
|
videos.append(dt)
|
433
|
-
|
498
|
+
|
434
499
|
return videos
|
435
500
|
|
436
501
|
def get_details_lecture(self, lecture_id: int) -> Lecture:
|
@@ -443,7 +508,19 @@ class Course:
|
|
443
508
|
Returns:
|
444
509
|
Lecture: Um objeto Lecture contendo os detalhes da aula.
|
445
510
|
"""
|
446
|
-
|
511
|
+
type_lecture = ''
|
512
|
+
links= {}
|
513
|
+
if not is_lecture_in_course(lecture_id=lecture_id,lectures=self.get_lectures):
|
514
|
+
raise FileNotFoundError(
|
515
|
+
'Essa aula não existe nesse curso!'
|
516
|
+
)
|
517
|
+
for l in self.get_lectures:
|
518
|
+
if lecture_id == l.get('lecture_id'):
|
519
|
+
type_lecture = l.get('asset_type')
|
520
|
+
if type_lecture.lower() == 'video' or type_lecture.lower() == 'article':
|
521
|
+
links = get_links(course_id=self.__course_id, id_lecture=lecture_id)
|
522
|
+
else:
|
523
|
+
links = get_assessments(course_id=self.__course_id,lecture_id=lecture_id)
|
447
524
|
additional_files = self.__load_assets()
|
448
525
|
lecture = Lecture(data=links, course_id=self.__course_id, additional_files=additional_files)
|
449
526
|
return lecture
|