udemy-userAPI 0.3.6__tar.gz → 0.3.8__tar.gz

Sign up to get free protection for your applications and to get access to all the features.
Files changed (26) hide show
  1. {udemy_userapi-0.3.6/udemy_userAPI.egg-info → udemy_userapi-0.3.8}/PKG-INFO +2 -2
  2. {udemy_userapi-0.3.6 → udemy_userapi-0.3.8}/README.md +1 -1
  3. {udemy_userapi-0.3.6 → udemy_userapi-0.3.8}/README_PYPI.md +1 -1
  4. udemy_userapi-0.3.8/udemy_userAPI/.cache/.udemy_userAPI +0 -0
  5. {udemy_userapi-0.3.6 → udemy_userapi-0.3.8}/udemy_userAPI/__version__.py +1 -1
  6. {udemy_userapi-0.3.6 → udemy_userapi-0.3.8}/udemy_userAPI/api.py +52 -30
  7. {udemy_userapi-0.3.6 → udemy_userapi-0.3.8}/udemy_userAPI/bultins.py +3 -7
  8. {udemy_userapi-0.3.6 → udemy_userapi-0.3.8}/udemy_userAPI/sections.py +42 -16
  9. {udemy_userapi-0.3.6 → udemy_userapi-0.3.8/udemy_userAPI.egg-info}/PKG-INFO +2 -2
  10. udemy_userapi-0.3.6/udemy_userAPI/.cache/.udemy_userAPI +0 -0
  11. {udemy_userapi-0.3.6 → udemy_userapi-0.3.8}/LICENSE +0 -0
  12. {udemy_userapi-0.3.6 → udemy_userapi-0.3.8}/MANIFEST.in +0 -0
  13. {udemy_userapi-0.3.6 → udemy_userapi-0.3.8}/setup.cfg +0 -0
  14. {udemy_userapi-0.3.6 → udemy_userapi-0.3.8}/setup.py +0 -0
  15. {udemy_userapi-0.3.6 → udemy_userapi-0.3.8}/udemy_userAPI/__init__.py +0 -0
  16. {udemy_userapi-0.3.6 → udemy_userapi-0.3.8}/udemy_userAPI/authenticate.py +0 -0
  17. {udemy_userapi-0.3.6 → udemy_userapi-0.3.8}/udemy_userAPI/exeptions.py +0 -0
  18. {udemy_userapi-0.3.6 → udemy_userapi-0.3.8}/udemy_userAPI/mpd_analyzer/__init__.py +0 -0
  19. {udemy_userapi-0.3.6 → udemy_userapi-0.3.8}/udemy_userAPI/mpd_analyzer/bin.wvd +0 -0
  20. {udemy_userapi-0.3.6 → udemy_userapi-0.3.8}/udemy_userAPI/mpd_analyzer/mpd_parser.py +0 -0
  21. {udemy_userapi-0.3.6 → udemy_userapi-0.3.8}/udemy_userAPI/udemy.py +0 -0
  22. {udemy_userapi-0.3.6 → udemy_userapi-0.3.8}/udemy_userAPI.egg-info/SOURCES.txt +0 -0
  23. {udemy_userapi-0.3.6 → udemy_userapi-0.3.8}/udemy_userAPI.egg-info/dependency_links.txt +0 -0
  24. {udemy_userapi-0.3.6 → udemy_userapi-0.3.8}/udemy_userAPI.egg-info/not-zip-safe +0 -0
  25. {udemy_userapi-0.3.6 → udemy_userapi-0.3.8}/udemy_userAPI.egg-info/requires.txt +0 -0
  26. {udemy_userapi-0.3.6 → udemy_userapi-0.3.8}/udemy_userAPI.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: udemy_userAPI
3
- Version: 0.3.6
3
+ Version: 0.3.8
4
4
  Summary: Obtenha detalhes de cursos que o usuário esteja inscrito da plataforma Udemy,usando o EndPoint de usuário o mesmo que o navegador utiliza para acessar e redenrizar os cursos.
5
5
  Author: PauloCesar-dev404
6
6
  Author-email: paulocesar0073dev404@gmail.com
@@ -29,7 +29,7 @@ Dynamic: summary
29
29
  # udemy-userAPI
30
30
 
31
31
 
32
- ![Versão](https://img.shields.io/badge/version-0.3.6-orange)
32
+ ![Versão](https://img.shields.io/badge/version-0.3.8-orange)
33
33
  ![Licença](https://img.shields.io/badge/license-MIT-orange)
34
34
  [![Sponsor](https://img.shields.io/badge/💲Donate-yellow)](https://paulocesar-dev404.github.io/me-apoiando-online/)
35
35
  [![Sponsor](https://img.shields.io/badge/Documentation-green)](https://github.com/PauloCesar-dev404/udemy-userAPI/blob/main/docs/iniciando.md)
@@ -3,7 +3,7 @@
3
3
 
4
4
 
5
5
 
6
- ![Versão](https://img.shields.io/badge/version-0.3.6-orange)
6
+ ![Versão](https://img.shields.io/badge/version-0.3.8-orange)
7
7
  ![Licença](https://img.shields.io/badge/license-MIT-orange)
8
8
  [![Sponsor](https://img.shields.io/badge/💲Donate-yellow)](https://paulocesar-dev404.github.io/me-apoiando-online/)
9
9
  [![Sponsor](https://img.shields.io/badge/Documentation-green)](https://github.com/PauloCesar-dev404/udemy-userAPI/blob/main/docs/iniciando.md)
@@ -1,7 +1,7 @@
1
1
  # udemy-userAPI
2
2
 
3
3
 
4
- ![Versão](https://img.shields.io/badge/version-0.3.6-orange)
4
+ ![Versão](https://img.shields.io/badge/version-0.3.8-orange)
5
5
  ![Licença](https://img.shields.io/badge/license-MIT-orange)
6
6
  [![Sponsor](https://img.shields.io/badge/💲Donate-yellow)](https://paulocesar-dev404.github.io/me-apoiando-online/)
7
7
  [![Sponsor](https://img.shields.io/badge/Documentation-green)](https://github.com/PauloCesar-dev404/udemy-userAPI/blob/main/docs/iniciando.md)
@@ -1,4 +1,4 @@
1
- __version__ = '0.3.6'
1
+ __version__ = '0.3.8'
2
2
  __lib_name__ = 'udemy_userAPI' # local name
3
3
  __repo_name__ = 'udemy-userAPI'
4
4
  __autor__ = 'PauloCesar-dev404'
@@ -186,53 +186,75 @@ def get_mpd_file(mpd_url):
186
186
 
187
187
 
188
188
  def parser_chapters(results) -> list[dict]:
189
+ """
190
+ Processa os dados do curso e retorna uma lista de capítulos com suas aulas e quizzes.
191
+
192
+ Se os resultados não contiverem capítulos (i.e. apenas aulas ou quizzes), todas as
193
+ aulas/quizzes serão agrupadas em um capítulo padrão.
194
+
195
+ Args:
196
+ results (dict): Dicionário com os resultados do curso, normalmente contendo a chave 'results'.
197
+
198
+ Returns:
199
+ list[dict]: Lista de capítulos, cada um com título, índice (se disponível) e lista de lectures/quizzes.
200
+
201
+ Raises:
202
+ UdemyUserApiExceptions: Se não for possível obter os detalhes do curso.
203
+ """
189
204
  if not results:
190
205
  raise UdemyUserApiExceptions("Não foi possível obter detalhes do curso!")
191
206
 
192
- results = results.get('results', [])
193
- chapters_dicts = [] # Lista que armazena todos os capítulos
207
+ items = results.get('results', [])
208
+ chapters_dicts = [] # Lista de capítulos
194
209
  current_chapter = None # Capítulo atual
195
210
 
196
- for dictionary in results:
211
+ # Nome padrão para o grupo quando não houver capítulos
212
+ default_chapter_title = "CourseFiles"
213
+
214
+ for dictionary in items:
197
215
  _class = dictionary.get('_class')
198
- chapter_index = dictionary.get('object_index')
216
+ chapter_index = dictionary.get('object_index', None)
199
217
 
200
- # Quando encontrar um novo capítulo
201
218
  if _class == 'chapter':
202
- if current_chapter: # Se já há um capítulo atual, adicionamos
219
+ # Se já há um capítulo em andamento, adiciona-o à lista
220
+ if current_chapter:
203
221
  chapters_dicts.append(current_chapter)
204
-
205
222
  # Inicia um novo capítulo
206
223
  current_chapter = {
207
- 'title': dictionary.get('title'),
224
+ 'title': dictionary.get('title', 'Sem Título'),
208
225
  'chapter_index': chapter_index,
209
226
  'lectures': [] # Lista para armazenar aulas e quizzes
210
227
  }
211
-
212
- # Se for uma aula, adiciona ao capítulo atual
213
- elif _class == 'lecture' and current_chapter:
214
- asset = dictionary.get('asset')
215
- if asset:
216
- lecture_data = {
217
- 'asset_type': asset.get('asset_type', ''),
218
- 'title': dictionary.get('title', 'Files'),
228
+ elif _class in ('lecture', 'quiz'):
229
+ # Se não houver um capítulo atual, cria um capítulo padrão
230
+ if current_chapter is None:
231
+ current_chapter = {
232
+ 'title': default_chapter_title,
233
+ 'chapter_index': None,
234
+ 'lectures': []
235
+ }
236
+ # Processa a aula ou quiz
237
+ if _class == 'lecture':
238
+ asset = dictionary.get('asset')
239
+ if asset:
240
+ lecture_data = {
241
+ 'asset_type': asset.get('asset_type', ''),
242
+ 'title': dictionary.get('title', 'Aula'),
243
+ 'lecture_id': dictionary.get('id', ''),
244
+ 'asset_id': asset.get('id', '')
245
+ }
246
+ current_chapter['lectures'].append(lecture_data)
247
+ elif _class == 'quiz':
248
+ quiz_data = {
249
+ 'asset_type': 'quiz',
250
+ 'title': dictionary.get('title', 'Quiz'),
219
251
  'lecture_id': dictionary.get('id', ''),
220
- 'asset_id': asset.get('id', '')
252
+ 'type': dictionary.get('type', ''),
253
+ 'asset_id': ''
221
254
  }
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)
255
+ current_chapter['lectures'].append(quiz_data)
234
256
 
235
- # Adiciona o último capítulo processado
257
+ # Se houver um capítulo em andamento, adiciona-o à lista
236
258
  if current_chapter:
237
259
  chapters_dicts.append(current_chapter)
238
260
 
@@ -475,11 +475,7 @@ class Course:
475
475
  @property
476
476
  def get_lectures(self) -> list:
477
477
  """
478
- Obtém uma lista com todas as aulas.
479
-
480
- Args:
481
- data (list): Lista de capítulos contendo as aulas.
482
-
478
+ Obtém uma lista de dicionários com todas as aulas.
483
479
  Returns:
484
480
  list: Uma lista contendo todas as aulas.
485
481
  """
@@ -492,12 +488,12 @@ class Course:
492
488
  'title': video.get('title', ''),
493
489
  'lecture_id': video.get('lecture_id', ''),
494
490
  'asset_id': video.get('asset_id', ''),
495
- 'asset_type': video.get('asset_type', '')
491
+ 'asset_type': video.get('asset_type', ''),
492
+ 'section_order': chapter.get('chapter_index',1)
496
493
  }
497
494
  videos.append(dt)
498
495
 
499
496
  return videos
500
-
501
497
  def get_details_lecture(self, lecture_id: int) -> Lecture:
502
498
  """
503
499
  Obtém detalhes de uma aula específica.
@@ -53,13 +53,13 @@ def get_courses_plan(tipe: str) -> list:
53
53
 
54
54
  def get_details_courses(course_id):
55
55
  """
56
- Obtém detalhes de um curso específico.
56
+ Obtém detalhes de um curso específico, realizando paginação caso haja múltiplas páginas.
57
57
 
58
58
  Args:
59
59
  course_id (int): ID do curso.
60
60
 
61
61
  Returns:
62
- dict: Dicionário contendo os detalhes do curso.
62
+ dict: Dicionário contendo os detalhes do curso com todos os itens concatenados.
63
63
 
64
64
  Raises:
65
65
  LoginException: Se a sessão estiver expirada.
@@ -70,21 +70,47 @@ def get_details_courses(course_id):
70
70
  auth = UdemyAuth()
71
71
  if not auth.verif_login():
72
72
  raise LoginException("Sessão expirada!")
73
- response = requests.get(
73
+
74
+ # URL base com parâmetros
75
+ base_url = (
74
76
  f"https://www.udemy.com/api-2.0/courses/{course_id}/subscriber-curriculum-items/?"
75
- f"caching_intent=True&fields%5Basset%5D=title%2Cfilename%2Casset_type%2Cstatus%2Ctime_estimation%2"
76
- f"Cis_external&fields%5Bchapter%5D=title%2Cobject_index%2Cis_published%2Csort_order&fields%5Blecture"
77
- f"%5D=title%2Cobject_index%2Cis_published%2Csort_order%2Ccreated%2Casset%2Csupplementary_assets%2"
78
- f"Cis_free&fields%5Bpractice%5D=title%2Cobject_index%2Cis_published%2Csort_order&fields%5Bquiz%5D="
79
- f"title%2Cobject_index%2Cis_published%2Csort_order%2Ctype&pages&page_size=400&fields[lecture]=asset,"
80
- f"description,download_url,is_free,last_watched_second&fields[asset]=asset_type,length,"
81
- f"media_license_token,course_is_drmed,external_url&q=0.3108014137011559",
82
- headers=HEADERS_USER)
83
- if response.status_code == 200:
84
- resposta = json.loads(response.text)
85
- return resposta
86
- else:
87
- raise UdemyUserApiExceptions(f"Erro ao obter detalhes do curso! Código de status: {response.status_code}")
77
+ f"page_size=1000&"
78
+ f"fields[lecture]=title,object_index,is_published,sort_order,created,asset,supplementary_assets,is_free&"
79
+ f"fields[quiz]=title,object_index,is_published,sort_order,type&"
80
+ f"fields[practice]=title,object_index,is_published,sort_order&"
81
+ f"fields[chapter]=title,object_index,is_published,sort_order&"
82
+ f"fields[asset]=title,filename,asset_type,status,time_estimation,is_external&"
83
+ f"caching_intent=True"
84
+ )
85
+
86
+ try:
87
+ response = requests.get(base_url, headers=HEADERS_USER)
88
+ if response.status_code != 200:
89
+ raise UdemyUserApiExceptions(
90
+ f"Erro ao obter detalhes do curso! Código de status: {response.status_code}")
91
+
92
+ data = json.loads(response.text)
93
+ all_results = data.get('results', [])
94
+ next_page = data.get('next', '')
95
+
96
+ # Enquanto houver próxima página, faz requisição e junta os resultados
97
+ while next_page:
98
+ response = requests.get(next_page, headers=HEADERS_USER)
99
+ if response.status_code != 200:
100
+ # Caso ocorra erro na próxima página, pode-se optar por interromper ou registrar o erro.....por enquanto
101
+ # irei parar..mais se por acaso futuramente não der certo mudarei esta implementação!
102
+ # @pauloCesarDev404
103
+ break
104
+ next_data = json.loads(response.text)
105
+ all_results.extend(next_data.get('results', []))
106
+ next_page = next_data.get('next', '')
107
+
108
+ # Atualiza o dicionário final com todos os itens concatenados
109
+ data['results'] = all_results
110
+ return data
111
+
112
+ except Exception as e:
113
+ raise UdemyUserApiExceptions(f"Erro ao obter detalhes do curso! {e}")
88
114
 
89
115
 
90
116
  def get_course_infor(course_id):
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: udemy_userAPI
3
- Version: 0.3.6
3
+ Version: 0.3.8
4
4
  Summary: Obtenha detalhes de cursos que o usuário esteja inscrito da plataforma Udemy,usando o EndPoint de usuário o mesmo que o navegador utiliza para acessar e redenrizar os cursos.
5
5
  Author: PauloCesar-dev404
6
6
  Author-email: paulocesar0073dev404@gmail.com
@@ -29,7 +29,7 @@ Dynamic: summary
29
29
  # udemy-userAPI
30
30
 
31
31
 
32
- ![Versão](https://img.shields.io/badge/version-0.3.6-orange)
32
+ ![Versão](https://img.shields.io/badge/version-0.3.8-orange)
33
33
  ![Licença](https://img.shields.io/badge/license-MIT-orange)
34
34
  [![Sponsor](https://img.shields.io/badge/💲Donate-yellow)](https://paulocesar-dev404.github.io/me-apoiando-online/)
35
35
  [![Sponsor](https://img.shields.io/badge/Documentation-green)](https://github.com/PauloCesar-dev404/udemy-userAPI/blob/main/docs/iniciando.md)
File without changes
File without changes
File without changes
File without changes
File without changes