udemy-userAPI 0.1.5__tar.gz → 0.1.6__tar.gz

Sign up to get free protection for your applications and to get access to all the features.
Files changed (21) hide show
  1. {udemy_userapi-0.1.5/udemy_userAPI.egg-info → udemy_userapi-0.1.6}/PKG-INFO +2 -2
  2. {udemy_userapi-0.1.5 → udemy_userapi-0.1.6}/README.md +1 -1
  3. {udemy_userapi-0.1.5 → udemy_userapi-0.1.6}/README_PYPI.md +1 -1
  4. {udemy_userapi-0.1.5 → udemy_userapi-0.1.6}/udemy_userAPI/__version__.py +1 -1
  5. {udemy_userapi-0.1.5 → udemy_userapi-0.1.6}/udemy_userAPI/api.py +37 -3
  6. {udemy_userapi-0.1.5 → udemy_userapi-0.1.6}/udemy_userAPI/authenticate.py +16 -9
  7. {udemy_userapi-0.1.5 → udemy_userapi-0.1.6}/udemy_userAPI/bultins.py +23 -10
  8. {udemy_userapi-0.1.5 → udemy_userapi-0.1.6}/udemy_userAPI/udemy.py +18 -3
  9. {udemy_userapi-0.1.5 → udemy_userapi-0.1.6/udemy_userAPI.egg-info}/PKG-INFO +2 -2
  10. {udemy_userapi-0.1.5 → udemy_userapi-0.1.6}/LICENSE +0 -0
  11. {udemy_userapi-0.1.5 → udemy_userapi-0.1.6}/MANIFEST.in +0 -0
  12. {udemy_userapi-0.1.5 → udemy_userapi-0.1.6}/setup.cfg +0 -0
  13. {udemy_userapi-0.1.5 → udemy_userapi-0.1.6}/setup.py +0 -0
  14. {udemy_userapi-0.1.5 → udemy_userapi-0.1.6}/udemy_userAPI/__init__.py +0 -0
  15. {udemy_userapi-0.1.5 → udemy_userapi-0.1.6}/udemy_userAPI/exeptions.py +0 -0
  16. {udemy_userapi-0.1.5 → udemy_userapi-0.1.6}/udemy_userAPI/sections.py +0 -0
  17. {udemy_userapi-0.1.5 → udemy_userapi-0.1.6}/udemy_userAPI.egg-info/SOURCES.txt +0 -0
  18. {udemy_userapi-0.1.5 → udemy_userapi-0.1.6}/udemy_userAPI.egg-info/dependency_links.txt +0 -0
  19. {udemy_userapi-0.1.5 → udemy_userapi-0.1.6}/udemy_userAPI.egg-info/not-zip-safe +0 -0
  20. {udemy_userapi-0.1.5 → udemy_userapi-0.1.6}/udemy_userAPI.egg-info/requires.txt +0 -0
  21. {udemy_userapi-0.1.5 → udemy_userapi-0.1.6}/udemy_userAPI.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: udemy_userAPI
3
- Version: 0.1.5
3
+ Version: 0.1.6
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
@@ -18,7 +18,7 @@ Requires-Dist: cloudscraper
18
18
  # udemy-userAPI
19
19
 
20
20
 
21
- ![Versão](https://img.shields.io/badge/version-0.1.5-orange)
21
+ ![Versão](https://img.shields.io/badge/version-0.1.6-orange)
22
22
  ![Licença](https://img.shields.io/badge/license-MIT-orange)
23
23
  [![Sponsor](https://img.shields.io/badge/💲Donate-yellow)](https://apoia.se/paulocesar-dev404)
24
24
  [![Sponsor](https://img.shields.io/badge/Documentation-green)](https://github.com/PauloCesar-dev404/udemy-userAPI/wiki)
@@ -2,7 +2,7 @@
2
2
  <img src="assets/udemy_userAPI-logo.png" alt="udemy_userAPI-logo" width="200"/>
3
3
 
4
4
 
5
- ![Versão](https://img.shields.io/badge/version-0.1.5-orange)
5
+ ![Versão](https://img.shields.io/badge/version-0.1.6-orange)
6
6
  ![Licença](https://img.shields.io/badge/license-MIT-orange)
7
7
  [![Sponsor](https://img.shields.io/badge/💲Donate-yellow)](https://apoia.se/paulocesar-dev404)
8
8
  [![Sponsor](https://img.shields.io/badge/Documentation-green)](https://github.com/PauloCesar-dev404/udemy-userAPI/wiki)
@@ -1,7 +1,7 @@
1
1
  # udemy-userAPI
2
2
 
3
3
 
4
- ![Versão](https://img.shields.io/badge/version-0.1.5-orange)
4
+ ![Versão](https://img.shields.io/badge/version-0.1.6-orange)
5
5
  ![Licença](https://img.shields.io/badge/license-MIT-orange)
6
6
  [![Sponsor](https://img.shields.io/badge/💲Donate-yellow)](https://apoia.se/paulocesar-dev404)
7
7
  [![Sponsor](https://img.shields.io/badge/Documentation-green)](https://github.com/PauloCesar-dev404/udemy-userAPI/wiki)
@@ -1,4 +1,4 @@
1
- __version__ = '0.1.5'
1
+ __version__ = '0.1.6'
2
2
  __lib_name__ = 'udemy_userAPI' # local name
3
3
  __repo_name__ = 'udemy-userAPI'
4
4
  __autor__ = 'PauloCesar-dev404'
@@ -67,14 +67,14 @@ def parser_chapers(results):
67
67
  elif _class == 'lecture' and current_chapter is not None:
68
68
  asset = dictionary.get('asset')
69
69
  if asset:
70
- video_title = asset.get('title', None)
70
+ video_title = dictionary.get('title', None)
71
71
  if not video_title:
72
72
  video_title = 'Files'
73
73
  current_chapter['videos_in_chapter'].append({
74
74
  'video_title': video_title,
75
75
  'title_lecture': dictionary.get('title'),
76
- 'id_lecture': dictionary.get('id'),
77
- 'id_asset': asset.get('id')
76
+ 'lecture_id': dictionary.get('id'),
77
+ 'asset_id': asset.get('id')
78
78
  })
79
79
 
80
80
  return chapters_dict
@@ -257,3 +257,37 @@ def format_size(byte_size):
257
257
  return f"{byte_size / TB:.2f} TB"
258
258
  except Exception as e:
259
259
  return byte_size
260
+
261
+
262
+ def lecture_infor(course_id: int, id_lecture: int):
263
+ edpoint = (f"https://www.udemy.com/api-2.0/users/me/subscribed-courses/{course_id}/lectures/{id_lecture}/?"
264
+ f"fields[asset]=media_license_token&q=0.06925737374647678")
265
+ r = requests.get(edpoint, headers=HEADERS_USER)
266
+ if r.status_code == 200:
267
+ return json.loads(r.text)
268
+
269
+
270
+ def assets_infor(course_id: int, id_lecture: int, assets_id: int):
271
+ endpoint = (f'https://www.udemy.com/api-2.0/assets/{assets_id}/?fields[asset]=@min,status,delayed_asset_message,'
272
+ f'processing_errors,body&course_id={course_id}&lecture_id={id_lecture}')
273
+ r = requests.get(endpoint, headers=HEADERS_USER)
274
+ if r.status_code == 200:
275
+ dt = json.loads(r.text)
276
+ body = dt.get("body")
277
+ title = lecture_infor(course_id=course_id, id_lecture=id_lecture).get("title")
278
+ return save_html(body, title_lecture=title)
279
+
280
+
281
+ def save_html(body, title_lecture):
282
+ html_content = f"""<!DOCTYPE html>
283
+ <html lang="en">
284
+ <head>
285
+ <meta charset="UTF-8">
286
+ <title>{title_lecture}</title>
287
+ </head>
288
+ <body>
289
+ {body}
290
+ </body>
291
+ </html>"""
292
+
293
+ return html_content
@@ -11,9 +11,17 @@ class UdemyAuth:
11
11
  """Autenticação na plataforma udemy de maneira segura, atencao ao limite de logins,recomendo que apos logar
12
12
  nao use novamnete o metodo login use apenas o verifcador de login para evitar bloqueios temporários..."""
13
13
  self.__cookie_dict = {}
14
- dir_out = '.udemy_userAPI'
15
- os.makedirs(os.path.join(os.path.expanduser('~'), dir_out), exist_ok=True)
16
- self.__user_dir = os.path.join(os.path.expanduser('~'), dir_out)
14
+ # Diretório do arquivo atual
15
+ current_directory = os.path.dirname(__file__)
16
+ # dir cache
17
+ cache = '.cache'
18
+ cache_dir = os.path.join(current_directory, cache)
19
+ os.makedirs(cache_dir, exist_ok=True)
20
+ # Cria o diretório completo para a API do usuário
21
+ self.__user_dir = os.path.join(cache_dir)
22
+ # Cria o caminho completo para um arquivo específico
23
+ file_name = '.udemy_userAPI' # Nome do arquivo
24
+ self.__file_path = os.path.join(self.__user_dir, file_name)
17
25
 
18
26
  def __make_cookies(self, client_id: str, access_token: str, csrf_token: str):
19
27
  self.__cookie_dict = {
@@ -29,7 +37,7 @@ class UdemyAuth:
29
37
  def verif_config():
30
38
  # Verificar se o arquivo .userLogin existe e carregar cookies se existir
31
39
  try:
32
- with open(fr'{self.__user_dir}\.Udemy_userLogin', 'rb') as f:
40
+ with open(fr'{self.__file_path}', 'rb') as f:
33
41
  cookies = pickle.load(f)
34
42
  cookies_dict = {cookie.name: cookie.value for cookie in cookies}
35
43
  cookies_str = "; ".join([f"{key}={value}" for key, value in cookies_dict.items()])
@@ -144,19 +152,18 @@ class UdemyAuth:
144
152
  return s
145
153
 
146
154
  def __save_cookies(self, cookies):
147
- with open(fr'{self.__user_dir}\.Udemy_userLogin', 'wb') as f:
155
+ with open(fr'{self.__file_path}', 'wb') as f:
148
156
  pickle.dump(cookies, f)
149
157
 
150
158
  @property
151
159
  def load_cookies(self) -> str:
152
160
  """carrega cookies e retorna-os em uma string formatada"""
153
- file = os.path.join(fr'{self.__user_dir}\.Udemy_userLogin')
161
+ file = os.path.join(fr'{self.__file_path}')
154
162
  if os.path.exists(file):
155
- with open(fr'{self.__user_dir}\.Udemy_userLogin', 'rb') as f:
163
+ with open(fr'{self.__file_path}', 'rb') as f:
156
164
  cookies = pickle.load(f)
157
165
  cookies_dict = {cookie.name: cookie.value for cookie in cookies}
158
166
  cookies_str = "; ".join([f"{key}={value}" for key, value in cookies_dict.items()])
159
167
  return cookies_str
160
168
  else:
161
- raise LoginException()
162
-
169
+ return 'None'
@@ -1,8 +1,7 @@
1
1
  import requests
2
2
  import json
3
3
  from .sections import get_course_infor
4
- from .api import get_links, remove_tag, parser_chapers, extract_files, HEADERS_USER
5
-
4
+ from .api import get_links, remove_tag, parser_chapers, extract_files, HEADERS_USER, assets_infor
6
5
 
7
6
 
8
7
  class Files:
@@ -32,7 +31,8 @@ class Files:
32
31
  class Lecture:
33
32
  """CRIAR objetos aula(lecture) do curso e extrair os dados.."""
34
33
 
35
- def __init__(self, data: dict):
34
+ def __init__(self, data: dict, course_id: int):
35
+ self.__course_id = course_id
36
36
  self.__data = data
37
37
  self.__asset = self.__data.get("asset")
38
38
 
@@ -105,6 +105,11 @@ class Lecture:
105
105
  """obtem slides se tiver.."""
106
106
  return self.__asset.get('slides')
107
107
 
108
+ @property
109
+ def get_articles(self):
110
+ d = assets_infor(course_id=self.__course_id, id_lecture=self.get_lecture_id, assets_id=self.__asset.get("id"))
111
+ return d
112
+
108
113
 
109
114
  class Course:
110
115
  """receb um dict com os dados do curso"""
@@ -172,21 +177,29 @@ class Course:
172
177
 
173
178
  @property
174
179
  def get_lectures(self) -> list:
175
- """Obtém uma lista com todos as aulas"""
180
+ """Obtém uma lista com todas as aulas."""
176
181
  videos = []
177
182
  for chapter in self.__data.values():
178
- for video in chapter.get('videos_in_chapter', []):
179
- title = video['video_title']
180
- id_lecture = video['id_lecture']
181
- id_asset = video['id_asset']
182
- dt = {"title": title, 'id_lecture': id_lecture, 'id_asset': id_asset}
183
+ for index, video in enumerate(chapter.get('videos_in_chapter', [])): # Corrigido o loop
184
+ section = chapter.get('title_chapter')
185
+ title = video.get('video_title')
186
+ id_lecture = video.get('lecture_id')
187
+ id_asset = video.get('asset_id')
188
+ section_order = index + 1 # Adiciona 1 para começar a numeração em 1
189
+ dt = {
190
+ 'section': section,
191
+ 'title': title,
192
+ 'lecture_id': id_lecture,
193
+ 'asset_id': id_asset,
194
+ 'section_order': section_order
195
+ }
183
196
  videos.append(dt)
184
197
  return videos
185
198
 
186
199
  def get_details_lecture(self, lecture_id: int) -> Lecture:
187
200
  """obter detalhes de uma aula específica, irá retornar o objeto Lecture"""
188
201
  links = get_links(course_id=self.__course_id, id_lecture=lecture_id)
189
- lecture = Lecture(data=links)
202
+ lecture = Lecture(data=links, course_id=self.__course_id)
190
203
  return lecture
191
204
 
192
205
  @property
@@ -30,10 +30,25 @@ class Udemy:
30
30
 
31
31
  @property
32
32
  def my_subscribed_courses(self) -> list[dict]:
33
- """obtém os cursos que o usuário esatá inscrito"""
33
+ """Obtém os cursos que o usuário está inscrito, excluindo listas vazias ou nulas"""
34
34
  try:
35
- courses = get_courses_plan(tipe='default')
36
- return courses
35
+ # Obtém os cursos
36
+ courses1 = get_courses_plan(tipe='default') # lista de cursos padrão
37
+ courses2 = get_courses_plan(tipe='plan') # lista de cursos de um plano
38
+
39
+ # Cria uma lista vazia para armazenar os cursos válidos
40
+ all_courses = []
41
+
42
+ # Adiciona a lista somente se não estiver vazia ou nula
43
+ if courses1:
44
+ for i in courses1:
45
+ all_courses.extend(i)
46
+ if courses2:
47
+ for i in courses2:
48
+ all_courses.extend(i)
49
+
50
+ return all_courses
51
+
37
52
  except UdemyUserApiExceptions as e:
38
53
  UnhandledExceptions(e)
39
54
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: udemy_userAPI
3
- Version: 0.1.5
3
+ Version: 0.1.6
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
@@ -18,7 +18,7 @@ Requires-Dist: cloudscraper
18
18
  # udemy-userAPI
19
19
 
20
20
 
21
- ![Versão](https://img.shields.io/badge/version-0.1.5-orange)
21
+ ![Versão](https://img.shields.io/badge/version-0.1.6-orange)
22
22
  ![Licença](https://img.shields.io/badge/license-MIT-orange)
23
23
  [![Sponsor](https://img.shields.io/badge/💲Donate-yellow)](https://apoia.se/paulocesar-dev404)
24
24
  [![Sponsor](https://img.shields.io/badge/Documentation-green)](https://github.com/PauloCesar-dev404/udemy-userAPI/wiki)
File without changes
File without changes
File without changes
File without changes