udemy-userAPI 0.3.7__py3-none-any.whl → 0.3.9__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.
@@ -0,0 +1,7 @@
1
+ # m3u8_analyzer/__init__.py
2
+
3
+ from .M3u8Analyzer import M3u8Analyzer, Wrapper,EncryptSuport
4
+
5
+ __all__ = ['M3u8Analyzer', 'Wrapper','EncryptSuport']
6
+ if __name__ == '__main__':
7
+ raise RuntimeError("no escope!")
@@ -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)
@@ -1,4 +1,4 @@
1
- __version__ = '0.3.7'
1
+ __version__ = '0.3.9'
2
2
  __lib_name__ = 'udemy_userAPI' # local name
3
3
  __repo_name__ = 'udemy-userAPI'
4
4
  __autor__ = 'PauloCesar-dev404'
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
- 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
 
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) -> Captions:
247
+ def get_captions(self) -> list:
357
248
  """
358
249
  Obtém as legendas.
359
250
 
360
251
  Returns:
361
- Captions: Objeto para gerenciar as legendas.
252
+ list: Uma lista contendo as legendas.
362
253
  """
363
- if self.__asset.get('captions',[]):
364
- c = Captions(caption_data=self.__asset.get('captions',[]))
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
- 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(
88
- response.text)
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) ->Course:
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.7
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
- ![Versão](https://img.shields.io/badge/version-0.3.7-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)
@@ -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,,