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.
@@ -1,4 +1,4 @@
1
- __version__ = '0.3.5'
1
+ __version__ = '0.3.7'
2
2
  __lib_name__ = 'udemy_userAPI' # local name
3
3
  __repo_name__ = 'udemy-userAPI'
4
4
  __autor__ = 'PauloCesar-dev404'
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("Sessão expirada!")
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 parser_chapers(results):
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
- # Primeiro, construímos um dicionário de capítulos
200
- current_chapter = None
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
- chapter_index = dictionary.get('object_index')
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
- 'title_chapter': dictionary.get('title'),
208
- 'videos_in_chapter': []
207
+ 'title': dictionary.get('title'),
208
+ 'chapter_index': chapter_index,
209
+ 'lectures': [] # Lista para armazenar aulas e quizzes
209
210
  }
210
- chapters_dict[f"chapter_{chapter_index}"] = current_chapter
211
- elif _class == 'lecture' and current_chapter is not None:
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
- video_title = dictionary.get('title', None)
215
- if not video_title:
216
- video_title = 'Files'
217
- current_chapter['videos_in_chapter'].append({
218
- 'video_title': video_title,
219
- 'title_lecture': dictionary.get('title'),
220
- 'lecture_id': dictionary.get('id'),
221
- 'asset_id': asset.get('id')
222
- })
223
- return chapters_dict
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
- f"fields[lecture]"
308
- f"=asset,description,download_url,is_free,last_watched_second&fields[asset]=asset_type,length,"
309
- f"media_license_token,course_is_drmed,media_sources,captions,thumbnail_sprite,slides,slide_urls,"
310
- f"download_urls,"
311
- f"external_url&q=0.3108014137011559/?fields[asset]=download_urls")
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(f"Erro ao obter dados de aulas! Código de status: {response.status_code}")
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(f"Erro de conexão: {e}")
345
+ raise UdemyUserApiExceptions(
346
+ f"Erro de conexão: {e}")
329
347
  except requests.Timeout as e:
330
- raise UdemyUserApiExceptions(f"Tempo de requisição excedido: {e}")
348
+ raise UdemyUserApiExceptions(
349
+ f"Tempo de requisição excedido: {e}")
331
350
  except requests.TooManyRedirects as e:
332
- raise UdemyUserApiExceptions(f"Limite de redirecionamentos excedido: {e}")
351
+ raise UdemyUserApiExceptions(
352
+ f"Limite de redirecionamentos excedido: {e}")
333
353
  except requests.HTTPError as e:
334
- raise UdemyUserApiExceptions(f"Erro HTTP: {e}")
354
+ raise UdemyUserApiExceptions(
355
+ f"Erro HTTP: {e}")
335
356
  except Exception as e:
336
- raise UnhandledExceptions(f"Erro ao obter mídias: {e}")
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
@@ -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"Unhandled-ERROR: {e}")
108
+ raise UnhandledExceptions(f"{e}")
109
109
  else:
110
110
  return False
111
111