udemy-userAPI 0.3.5__py3-none-any.whl → 0.3.7__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 +139 -39
- udemy_userAPI/authenticate.py +1 -1
- udemy_userAPI/bultins.py +243 -56
- udemy_userAPI/sections.py +2 -1
- udemy_userAPI/udemy.py +13 -4
- {udemy_userAPI-0.3.5.dist-info → udemy_userAPI-0.3.7.dist-info}/METADATA +13 -3
- udemy_userAPI-0.3.7.dist-info/RECORD +17 -0
- {udemy_userAPI-0.3.5.dist-info → udemy_userAPI-0.3.7.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.5.dist-info/RECORD +0 -29
- {udemy_userAPI-0.3.5.dist-info → udemy_userAPI-0.3.7.dist-info}/LICENSE +0 -0
- {udemy_userAPI-0.3.5.dist-info → udemy_userAPI-0.3.7.dist-info}/top_level.txt +0 -0
udemy_userAPI/__version__.py
CHANGED
udemy_userAPI/api.py
CHANGED
@@ -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()
|
@@ -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):
|
@@ -304,11 +320,11 @@ 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():
|
@@ -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):
|
@@ -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
@@ -105,7 +105,7 @@ class UdemyAuth:
|
|
105
105
|
except requests.HTTPError as e:
|
106
106
|
raise UdemyUserApiExceptions(f"Erro HTTP: {e}")
|
107
107
|
except Exception as e:
|
108
|
-
raise UnhandledExceptions(f"
|
108
|
+
raise UnhandledExceptions(f"{e}")
|
109
109
|
else:
|
110
110
|
return False
|
111
111
|
|