udemy-userAPI 0.3.7__py3-none-any.whl → 0.3.9__py3-none-any.whl
Sign up to get free protection for your applications and to get access to all the features.
- animation_consoles/__init__.py +1 -0
- animation_consoles/animation.py +64 -0
- ffmpeg_for_python/__config__.py +118 -0
- ffmpeg_for_python/__init__.py +8 -0
- ffmpeg_for_python/__utils.py +78 -0
- ffmpeg_for_python/__version__.py +6 -0
- ffmpeg_for_python/exeptions.py +91 -0
- ffmpeg_for_python/ffmpeg.py +203 -0
- m3u8_analyzer/M3u8Analyzer.py +807 -0
- m3u8_analyzer/__init__.py +7 -0
- m3u8_analyzer/__version__.py +1 -0
- m3u8_analyzer/exeptions.py +82 -0
- udemy_userAPI/__version__.py +1 -1
- udemy_userAPI/api.py +52 -30
- udemy_userAPI/bultins.py +6 -120
- udemy_userAPI/sections.py +42 -17
- udemy_userAPI/udemy.py +4 -13
- {udemy_userAPI-0.3.7.dist-info → udemy_userAPI-0.3.9.dist-info}/METADATA +2 -2
- udemy_userAPI-0.3.9.dist-info/RECORD +29 -0
- udemy_userAPI-0.3.7.dist-info/RECORD +0 -17
- {udemy_userAPI-0.3.7.dist-info → udemy_userAPI-0.3.9.dist-info}/LICENSE +0 -0
- {udemy_userAPI-0.3.7.dist-info → udemy_userAPI-0.3.9.dist-info}/WHEEL +0 -0
- {udemy_userAPI-0.3.7.dist-info → udemy_userAPI-0.3.9.dist-info}/top_level.txt +0 -0
@@ -0,0 +1 @@
|
|
1
|
+
__version__ = '1.0.4.1'
|
@@ -0,0 +1,82 @@
|
|
1
|
+
class M3u8AnalyzerExceptions(Exception):
|
2
|
+
def __init__(self, message="Erro na análise da playlist M3U8", errors=None):
|
3
|
+
"""
|
4
|
+
Exceção base para erros relacionados à análise de playlists M3U8.
|
5
|
+
|
6
|
+
Args:
|
7
|
+
message (str): Mensagem descritiva do erro. Padrão é "Erro na análise da playlist M3U8".
|
8
|
+
errors (list, optional): Lista de erros adicionais ou detalhes para diagnóstico. Padrão é None.
|
9
|
+
"""
|
10
|
+
super().__init__(message)
|
11
|
+
self.errors = errors
|
12
|
+
|
13
|
+
def __str__(self):
|
14
|
+
"""
|
15
|
+
Retorna a representação em string da exceção.
|
16
|
+
|
17
|
+
Returns:
|
18
|
+
str: Mensagem de erro formatada com detalhes adicionais, se presentes.
|
19
|
+
"""
|
20
|
+
if self.errors:
|
21
|
+
return f"{super().__str__()} | Erros adicionais: {self.errors}"
|
22
|
+
return super().__str__()
|
23
|
+
|
24
|
+
|
25
|
+
class M3u8DownloadError(M3u8AnalyzerExceptions):
|
26
|
+
def __init__(self, message="Erro durante o download da playlist M3U8", errors=None):
|
27
|
+
"""
|
28
|
+
Exceção para erros específicos ocorridos durante o download de uma playlist M3U8.
|
29
|
+
|
30
|
+
Args:
|
31
|
+
message (str): Mensagem descritiva do erro. Padrão é "Erro durante o download da playlist M3U8".
|
32
|
+
errors (list, optional): Lista de erros adicionais ou detalhes para diagnóstico. Padrão é None.
|
33
|
+
"""
|
34
|
+
super().__init__(message, errors)
|
35
|
+
|
36
|
+
|
37
|
+
class M3u8FfmpegDownloadError(M3u8AnalyzerExceptions):
|
38
|
+
def __init__(self, message="Erro durante o download da playlist M3U8 com ffmpeg", errors=None):
|
39
|
+
"""
|
40
|
+
Exceção para erros específicos ocorridos durante o download de uma playlist M3U8 usando ffmpeg.
|
41
|
+
|
42
|
+
Args:
|
43
|
+
message (str): Mensagem descritiva do erro. Padrão é "Erro durante o download da playlist M3U8 com ffmpeg".
|
44
|
+
errors (list, optional): Lista de erros adicionais ou detalhes para diagnóstico. Padrão é None.
|
45
|
+
"""
|
46
|
+
super().__init__(message, errors)
|
47
|
+
|
48
|
+
|
49
|
+
class M3u8NetworkingError(M3u8AnalyzerExceptions):
|
50
|
+
def __init__(self, message="Erro de rede durante o download da playlist M3U8", errors=None):
|
51
|
+
"""
|
52
|
+
Exceção para erros relacionados à rede durante o download de uma playlist M3U8.
|
53
|
+
|
54
|
+
Args:
|
55
|
+
message (str): Mensagem descritiva do erro. Padrão é "Erro de rede durante o download da playlist M3U8".
|
56
|
+
errors (list, optional): Lista de erros adicionais ou detalhes para diagnóstico. Padrão é None.
|
57
|
+
"""
|
58
|
+
super().__init__(message, errors)
|
59
|
+
|
60
|
+
|
61
|
+
class M3u8Error(M3u8AnalyzerExceptions):
|
62
|
+
def __init__(self, message="Erro inesperado na análise de playlist M3U8", errors=None):
|
63
|
+
"""
|
64
|
+
Exceção para erros inesperados que não se encaixam em outras categorias.
|
65
|
+
|
66
|
+
Args:
|
67
|
+
message (str): Mensagem descritiva do erro. Padrão é "Erro inesperado na análise de playlist M3U8".
|
68
|
+
errors (list, optional): Lista de erros adicionais ou detalhes para diagnóstico. Padrão é None.
|
69
|
+
"""
|
70
|
+
super().__init__(message, errors)
|
71
|
+
|
72
|
+
|
73
|
+
class M3u8FileError(M3u8AnalyzerExceptions):
|
74
|
+
def __init__(self, message="Erro ao manipular o arquivo da playlist M3U8", errors=None):
|
75
|
+
"""
|
76
|
+
Exceção para erros ocorridos ao manipular arquivos relacionados a playlists M3U8.
|
77
|
+
|
78
|
+
Args:
|
79
|
+
message (str): Mensagem descritiva do erro. Padrão é "Erro ao manipular o arquivo da playlist M3U8".
|
80
|
+
errors (list, optional): Lista de erros adicionais ou detalhes para diagnóstico. Padrão é None.
|
81
|
+
"""
|
82
|
+
super().__init__(message, errors)
|
udemy_userAPI/__version__.py
CHANGED
udemy_userAPI/api.py
CHANGED
@@ -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
|
-
|
193
|
-
chapters_dicts = [] # Lista
|
207
|
+
items = results.get('results', [])
|
208
|
+
chapters_dicts = [] # Lista de capítulos
|
194
209
|
current_chapter = None # Capítulo atual
|
195
210
|
|
196
|
-
|
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
|
-
|
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
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
'
|
218
|
-
|
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
|
-
'
|
252
|
+
'type': dictionary.get('type', ''),
|
253
|
+
'asset_id': ''
|
221
254
|
}
|
222
|
-
current_chapter['lectures'].append(
|
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
|
-
#
|
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
|
|
udemy_userAPI/bultins.py
CHANGED
@@ -162,115 +162,6 @@ class Quiz:
|
|
162
162
|
htmls = get_quizzes(lecture_id=self.id)
|
163
163
|
return htmls
|
164
164
|
|
165
|
-
|
166
|
-
class Caption:
|
167
|
-
"""Representa uma legenda."""
|
168
|
-
|
169
|
-
def __init__(self, caption: dict):
|
170
|
-
"""
|
171
|
-
Inicializa uma instância de Caption.
|
172
|
-
|
173
|
-
Args:
|
174
|
-
caption (dict): Dados da legenda.
|
175
|
-
"""
|
176
|
-
self._caption = caption
|
177
|
-
|
178
|
-
@property
|
179
|
-
def locale(self) -> str:
|
180
|
-
"""Retorna o idioma."""
|
181
|
-
return self._caption.get('video_label', '')
|
182
|
-
|
183
|
-
@property
|
184
|
-
def status(self) -> str:
|
185
|
-
"""Retorna o status da legenda 1 ou 0"""
|
186
|
-
return self._caption.get('status')
|
187
|
-
|
188
|
-
@property
|
189
|
-
def title(self) -> str:
|
190
|
-
"""Retorna o título da legenda."""
|
191
|
-
return self._caption.get('title', '')
|
192
|
-
|
193
|
-
@property
|
194
|
-
def created(self) -> str:
|
195
|
-
"""Retorna a data de criação da legenda."""
|
196
|
-
return self._caption.get('created', '')
|
197
|
-
|
198
|
-
@property
|
199
|
-
def id(self) -> int:
|
200
|
-
"""Retorna o ID da legenda."""
|
201
|
-
return self._caption.get('id', 0)
|
202
|
-
|
203
|
-
@property
|
204
|
-
def url(self) -> str:
|
205
|
-
"""Retorna a URL da legenda."""
|
206
|
-
return self._caption.get('url', '')
|
207
|
-
|
208
|
-
@property
|
209
|
-
def content(self) -> str:
|
210
|
-
"""Obtém o conteúdo da legenda."""
|
211
|
-
if self.url:
|
212
|
-
r = requests.get(headers=HEADERS_USER, url=self.url)
|
213
|
-
if r.status_code == 200:
|
214
|
-
return r.text
|
215
|
-
else:
|
216
|
-
raise ConnectionError(
|
217
|
-
f'status_code: {r.status_code}, Não foi possível obter o conteúdo da legenda!'
|
218
|
-
)
|
219
|
-
else:
|
220
|
-
raise FileNotFoundError(
|
221
|
-
'Não foi possível obter a URL da legenda!'
|
222
|
-
)
|
223
|
-
|
224
|
-
class Captions:
|
225
|
-
"""Gerencia as legendas de um vídeo."""
|
226
|
-
|
227
|
-
def __init__(self, caption_data: list):
|
228
|
-
"""
|
229
|
-
Inicializa uma instância de Captions.
|
230
|
-
|
231
|
-
Args:
|
232
|
-
caption_data (list): Dados das legendas.
|
233
|
-
"""
|
234
|
-
self._caption_data = caption_data
|
235
|
-
|
236
|
-
def languages(self) -> list[dict]:
|
237
|
-
"""Retorna a lista de idiomas disponíveis na aula."""
|
238
|
-
langs = []
|
239
|
-
for caption in self._caption_data:
|
240
|
-
locale_id = caption.get('locale_id', '')
|
241
|
-
video_label = caption.get('video_label','')
|
242
|
-
if locale_id:
|
243
|
-
langs.append({'locale_id': locale_id,'locale':video_label})
|
244
|
-
return langs
|
245
|
-
|
246
|
-
def get_lang(self, locale_id: str) -> Caption:
|
247
|
-
"""
|
248
|
-
Obtém a legenda para o idioma especificado.
|
249
|
-
|
250
|
-
|
251
|
-
Args:
|
252
|
-
locale_id (str): ID do idioma,pode ser obtido no método -> 'languages'
|
253
|
-
|
254
|
-
Returns:
|
255
|
-
Caption: Objeto Caption.
|
256
|
-
|
257
|
-
Raises:
|
258
|
-
FileNotFoundError: Se o idioma não estiver disponível na aula.
|
259
|
-
"""
|
260
|
-
is_t = False
|
261
|
-
cpt = {}
|
262
|
-
for caption in self._caption_data:
|
263
|
-
if locale_id == caption.get('locale_id'):
|
264
|
-
is_t = True
|
265
|
-
cpt = caption
|
266
|
-
if not is_t:
|
267
|
-
raise FileNotFoundError(
|
268
|
-
'Esse idioma não está disponível nessa aula!'
|
269
|
-
)
|
270
|
-
c = Caption(caption=cpt)
|
271
|
-
return c
|
272
|
-
|
273
|
-
|
274
165
|
class Lecture:
|
275
166
|
"""Cria objetos aula (lecture) do curso e extrai os dados."""
|
276
167
|
|
@@ -353,20 +244,15 @@ class Lecture:
|
|
353
244
|
return self.__asset.get('media_sources',[])
|
354
245
|
|
355
246
|
@property
|
356
|
-
def get_captions(self) ->
|
247
|
+
def get_captions(self) -> list:
|
357
248
|
"""
|
358
249
|
Obtém as legendas.
|
359
250
|
|
360
251
|
Returns:
|
361
|
-
|
252
|
+
list: Uma lista contendo as legendas.
|
362
253
|
"""
|
363
|
-
|
364
|
-
|
365
|
-
return c
|
366
|
-
else:
|
367
|
-
raise FileNotFoundError(
|
368
|
-
'Não foi encontrada legendas nessa aula!'
|
369
|
-
)
|
254
|
+
return self.__asset.get('captions',[])
|
255
|
+
|
370
256
|
@property
|
371
257
|
def get_external_url(self) -> list:
|
372
258
|
"""
|
@@ -602,12 +488,12 @@ class Course:
|
|
602
488
|
'title': video.get('title', ''),
|
603
489
|
'lecture_id': video.get('lecture_id', ''),
|
604
490
|
'asset_id': video.get('asset_id', ''),
|
605
|
-
'asset_type': video.get('asset_type', '')
|
491
|
+
'asset_type': video.get('asset_type', ''),
|
492
|
+
'section_order': chapter.get('chapter_index',1)
|
606
493
|
}
|
607
494
|
videos.append(dt)
|
608
495
|
|
609
496
|
return videos
|
610
|
-
|
611
497
|
def get_details_lecture(self, lecture_id: int) -> Lecture:
|
612
498
|
"""
|
613
499
|
Obtém detalhes de uma aula específica.
|
udemy_userAPI/sections.py
CHANGED
@@ -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,22 +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
|
-
|
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"
|
76
|
-
f"
|
77
|
-
f"
|
78
|
-
f"
|
79
|
-
f"
|
80
|
-
f"
|
81
|
-
f"
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
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}")
|
89
114
|
|
90
115
|
|
91
116
|
def get_course_infor(course_id):
|
udemy_userAPI/udemy.py
CHANGED
@@ -19,6 +19,9 @@ class Udemy:
|
|
19
19
|
LoginException: Se a sessão estiver expirada.
|
20
20
|
"""
|
21
21
|
self.__headers = HEADERS_USER
|
22
|
+
if not verif_login:
|
23
|
+
raise LoginException("Sessão expirada!")
|
24
|
+
|
22
25
|
@staticmethod
|
23
26
|
def my_subscribed_courses_by_plan() -> list[dict]:
|
24
27
|
"""
|
@@ -30,10 +33,6 @@ class Udemy:
|
|
30
33
|
Raises:
|
31
34
|
UdemyUserApiExceptions: Se houver erro ao obter os cursos.
|
32
35
|
"""
|
33
|
-
if not verif_login:
|
34
|
-
raise LoginException(
|
35
|
-
"Nenhuma sessão ativa,primeiro efetue login!")
|
36
|
-
|
37
36
|
try:
|
38
37
|
courses = get_courses_plan(tipe='plan')
|
39
38
|
return courses
|
@@ -51,10 +50,6 @@ class Udemy:
|
|
51
50
|
Raises:
|
52
51
|
UdemyUserApiExceptions: Se houver erro ao obter os cursos.
|
53
52
|
"""
|
54
|
-
if not verif_login:
|
55
|
-
raise LoginException(
|
56
|
-
"Nenhuma sessão ativa,primeiro efetue login!")
|
57
|
-
|
58
53
|
try:
|
59
54
|
# Obtém os cursos
|
60
55
|
courses1 = get_courses_plan(tipe='default') # lista de cursos padrão
|
@@ -77,7 +72,7 @@ class Udemy:
|
|
77
72
|
raise UnhandledExceptions(e)
|
78
73
|
|
79
74
|
@staticmethod
|
80
|
-
def get_details_course(course_id)
|
75
|
+
def get_details_course(course_id):
|
81
76
|
"""
|
82
77
|
Obtém detalhes de um curso através do ID.
|
83
78
|
|
@@ -90,10 +85,6 @@ class Udemy:
|
|
90
85
|
Raises:
|
91
86
|
UnhandledExceptions: Se houver erro ao obter os detalhes do curso.
|
92
87
|
"""
|
93
|
-
if not verif_login:
|
94
|
-
raise LoginException(
|
95
|
-
"Nenhuma sessão ativa,primeiro efetue login!")
|
96
|
-
|
97
88
|
try:
|
98
89
|
d = get_details_courses(course_id)
|
99
90
|
b = Course(course_id=course_id, results=d)
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.2
|
2
2
|
Name: udemy_userAPI
|
3
|
-
Version: 0.3.
|
3
|
+
Version: 0.3.9
|
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
|
-

|
33
33
|

|
34
34
|
[](https://paulocesar-dev404.github.io/me-apoiando-online/)
|
35
35
|
[](https://github.com/PauloCesar-dev404/udemy-userAPI/blob/main/docs/iniciando.md)
|
@@ -0,0 +1,29 @@
|
|
1
|
+
animation_consoles/__init__.py,sha256=5uHhe-PVZ54FHWxbF1sNvNt4fuQf3FtZWVo2Mjo11a8,40
|
2
|
+
animation_consoles/animation.py,sha256=ZreNtdD0HYeqlRx-f1d1twUU4sOFTR7vJ3S6tMQpnHM,2122
|
3
|
+
ffmpeg_for_python/__config__.py,sha256=nCPrYs1NkMnyfyg5ITw9wOar4nUJOxwONrItVpVBVBM,4719
|
4
|
+
ffmpeg_for_python/__init__.py,sha256=-BMtoX8Yof_pnHra2OzoV3faxMubpMvUedMy8TqI8dc,214
|
5
|
+
ffmpeg_for_python/__utils.py,sha256=Qy3J5f4lOIPcSNbTwiawfiHjYPdZ_tq7hafStnnqwA4,3263
|
6
|
+
ffmpeg_for_python/__version__.py,sha256=HLFuN4n_leeJE5twr7yH2AAFyfIcEHzxElLRP1FUKmQ,422
|
7
|
+
ffmpeg_for_python/exeptions.py,sha256=tg-TBdaq_NHxZOCAhkMttzwtJVILPAQPLOKqofe5PPA,3627
|
8
|
+
ffmpeg_for_python/ffmpeg.py,sha256=G2VGHOIhErsqQI4OVlUnIQGmleNCjxyFqzNAMNnoD6I,7920
|
9
|
+
m3u8_analyzer/M3u8Analyzer.py,sha256=aUgxk2jS84MFDNbjlOT8FRiJerFI_jGcKMu9uv1EwcE,36620
|
10
|
+
m3u8_analyzer/__init__.py,sha256=v7CiVqsCq2YH347C-QR1kHPJtXFFdru8qole3E9adCY,217
|
11
|
+
m3u8_analyzer/__version__.py,sha256=YP3yT87ZKrU3eARUUdQ_pg4xAXLGfBXjH4ZgEoZSq1I,25
|
12
|
+
m3u8_analyzer/exeptions.py,sha256=fK6bU3YxNSbfsPmCp4yudUvmwy_g6dj2KwIkH0dW4LI,3672
|
13
|
+
udemy_userAPI/__init__.py,sha256=BPle89xE_CMTKKe_Lw6jioYLgpH-q_Lpho2S-n1PIUA,206
|
14
|
+
udemy_userAPI/__version__.py,sha256=a4LPtetqz-q5GvaAHS-Fgh8_av6e5cuiWN30jTnHd2w,405
|
15
|
+
udemy_userAPI/api.py,sha256=GVvbbs3vFN-rF-qLBwiuHz77sjehwk8HjAI-Dey_A6c,29167
|
16
|
+
udemy_userAPI/authenticate.py,sha256=IJRrCjmhe_x40CrQ2KrOMNP8VvotZf0QMWsrbcLl_rw,14225
|
17
|
+
udemy_userAPI/bultins.py,sha256=8L3FuEE09ySPLVUdyuy2EC7uXppDzr0KpSrNeG5AhRo,18629
|
18
|
+
udemy_userAPI/exeptions.py,sha256=kfnPdZpqYY8nd0gnl6_Vh-MIz-XupmmbRPIuFnyXupk,692
|
19
|
+
udemy_userAPI/sections.py,sha256=Q1PlVt2Bu5MSEP8g11-F_gilJDdhZq50TV1Bo400jcA,6389
|
20
|
+
udemy_userAPI/udemy.py,sha256=SpK0LI4hjO45nZDz5waw-Py-d0uulBb28TVjltyWBxM,2920
|
21
|
+
udemy_userAPI/.cache/.udemy_userAPI,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
22
|
+
udemy_userAPI/mpd_analyzer/__init__.py,sha256=i3JVWyvcFLaj5kPmx8c1PgjsLht7OUIQQClD4yqYbo8,102
|
23
|
+
udemy_userAPI/mpd_analyzer/bin.wvd,sha256=1rAJdCc120hQlX9qe5KUS628eY2ZHYxQSmyhGNefSzo,2956
|
24
|
+
udemy_userAPI/mpd_analyzer/mpd_parser.py,sha256=PgUkHc5x8FTuXFCuYkWPZr9TaO_nsKalb02EFYl_zeA,8926
|
25
|
+
udemy_userAPI-0.3.9.dist-info/LICENSE,sha256=l4jdKYt8gSdDFOGr09vCKnMn_Im55XIcQKqTDEtFfNs,1095
|
26
|
+
udemy_userAPI-0.3.9.dist-info/METADATA,sha256=MvhxygbgYvdBfmsoxVq_wssccc3Ph-MN1T0ArNj-MB4,1655
|
27
|
+
udemy_userAPI-0.3.9.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
|
28
|
+
udemy_userAPI-0.3.9.dist-info/top_level.txt,sha256=ijTINaSDRKhdahY_X7dmSRFTxBIwQErWv9ATCG55mog,14
|
29
|
+
udemy_userAPI-0.3.9.dist-info/RECORD,,
|
@@ -1,17 +0,0 @@
|
|
1
|
-
udemy_userAPI/__init__.py,sha256=BPle89xE_CMTKKe_Lw6jioYLgpH-q_Lpho2S-n1PIUA,206
|
2
|
-
udemy_userAPI/__version__.py,sha256=ZlJ4BqU7L0jruy2h0iTeuMxcPub8qGB7jbO8vbwvXbY,405
|
3
|
-
udemy_userAPI/api.py,sha256=jWWwJBYS9dJDjlozUj4Yi4uc8OCAy5PILqUiRWZMiq8,28153
|
4
|
-
udemy_userAPI/authenticate.py,sha256=IJRrCjmhe_x40CrQ2KrOMNP8VvotZf0QMWsrbcLl_rw,14225
|
5
|
-
udemy_userAPI/bultins.py,sha256=s12tXjbZgyKAnYrEtZxUzuTY-aIINXlm4mpbxR-r4Io,21932
|
6
|
-
udemy_userAPI/exeptions.py,sha256=kfnPdZpqYY8nd0gnl6_Vh-MIz-XupmmbRPIuFnyXupk,692
|
7
|
-
udemy_userAPI/sections.py,sha256=eRjUUlEApwrwlcCs9GWIk580qq1UVFqR5RmOgP6y65E,5424
|
8
|
-
udemy_userAPI/udemy.py,sha256=AAXc24iAtFTyDyVehhFeSx9CyhWMeFWsbYn1J80TgFw,3270
|
9
|
-
udemy_userAPI/.cache/.udemy_userAPI,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
10
|
-
udemy_userAPI/mpd_analyzer/__init__.py,sha256=i3JVWyvcFLaj5kPmx8c1PgjsLht7OUIQQClD4yqYbo8,102
|
11
|
-
udemy_userAPI/mpd_analyzer/bin.wvd,sha256=1rAJdCc120hQlX9qe5KUS628eY2ZHYxQSmyhGNefSzo,2956
|
12
|
-
udemy_userAPI/mpd_analyzer/mpd_parser.py,sha256=PgUkHc5x8FTuXFCuYkWPZr9TaO_nsKalb02EFYl_zeA,8926
|
13
|
-
udemy_userAPI-0.3.7.dist-info/LICENSE,sha256=l4jdKYt8gSdDFOGr09vCKnMn_Im55XIcQKqTDEtFfNs,1095
|
14
|
-
udemy_userAPI-0.3.7.dist-info/METADATA,sha256=B5tTj-p8_9DEWwgarUotK9gTteg6teb_R5oeLg7HznQ,1655
|
15
|
-
udemy_userAPI-0.3.7.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
|
16
|
-
udemy_userAPI-0.3.7.dist-info/top_level.txt,sha256=ijTINaSDRKhdahY_X7dmSRFTxBIwQErWv9ATCG55mog,14
|
17
|
-
udemy_userAPI-0.3.7.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|