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.
@@ -1,4 +1,4 @@
1
- __version__ = '0.3.4'
1
+ __version__ = '0.3.6'
2
2
  __lib_name__ = 'udemy_userAPI' # local name
3
3
  __repo_name__ = 'udemy-userAPI'
4
4
  __autor__ = 'PauloCesar-dev404'
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("Seção expirada!")
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("Seçã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()
@@ -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("Seção expirada!")
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 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):
@@ -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("Seção expirada!")
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
- 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():
315
- raise LoginException("Seção expirada!")
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(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):
@@ -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("Seção expirada!")
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("Seção expirada!")
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("Seção expirada!")
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
@@ -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='Erro no servidor remoto!')
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"Unhandled-ERROR: {e}")
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 seção válida!")
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 seção válida!")
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 requests
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("Seção expirada!")
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', 'Undefined')
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
- try:
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
- return d
234
- except Exception as e:
235
- DeprecationWarning(e)
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
- d = assets_infor(course_id=self.__course_id, id_lecture=self.get_lecture_id, assets_id=self.__asset.get("id"))
276
- return d
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
- files_add = get_files_aule(lecture_id_filter=self.get_lecture_id, data=self.__additional_files)
287
- f = Files(files=files_add, id_course=self.__course_id).get_download_url
288
- return f
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 = parser_chapers(results=results)
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.values():
379
- total_lectures += len(chapter.get('videos_in_chapter', []))
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.values():
466
+ for chapter in self.__data:
402
467
  for video in chapter.get('videos_in_chapter', []):
403
- title = video['video_title']
404
- if title != "Files":
405
- videos.append(title)
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
- section_order = 1 # Iniciar a numeração das seções (capítulos)
418
-
419
- for chapter in self.__data.values():
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': section,
427
- 'title': title,
428
- 'lecture_id': id_lecture,
429
- 'asset_id': id_asset,
430
- 'section_order': section_order
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
- section_order += 1 # Incrementar o número da seção após processar os vídeos do capítulo
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
- links = get_links(course_id=self.__course_id, id_lecture=lecture_id)
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