udemy-userAPI 0.3.7__py3-none-any.whl → 0.3.8__py3-none-any.whl

Sign up to get free protection for your applications and to get access to all the features.
@@ -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)
Binary file
@@ -1,4 +1,4 @@
1
- __version__ = '0.3.7'
1
+ __version__ = '0.3.8'
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.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.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=uwv2sjxdkP_iinuyfXK3i0Hngd7zXHyOfaCoAUNr_PY,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=J6Wp1IjPAoO8TksV4CfLUmt-7c6hcn6y1y3HnETvoFc,4139
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.8.dist-info/LICENSE,sha256=l4jdKYt8gSdDFOGr09vCKnMn_Im55XIcQKqTDEtFfNs,1095
26
+ udemy_userAPI-0.3.8.dist-info/METADATA,sha256=YbJ2lhBvhSeQHQy5R8sdaGoav2fc0NEUG2VWWPSpZyc,1655
27
+ udemy_userAPI-0.3.8.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
28
+ udemy_userAPI-0.3.8.dist-info/top_level.txt,sha256=ijTINaSDRKhdahY_X7dmSRFTxBIwQErWv9ATCG55mog,14
29
+ udemy_userAPI-0.3.8.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,,