udemy-userAPI 0.2.4__py3-none-any.whl → 0.2.6__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/authenticate.py +113 -24
- udemy_userAPI/bultins.py +20 -12
- udemy_userAPI/udemy.py +7 -8
- {udemy_userAPI-0.2.4.dist-info → udemy_userAPI-0.2.6.dist-info}/METADATA +2 -2
- udemy_userAPI-0.2.6.dist-info/RECORD +29 -0
- udemy_userAPI-0.2.4.dist-info/RECORD +0 -17
- {udemy_userAPI-0.2.4.dist-info → udemy_userAPI-0.2.6.dist-info}/LICENSE +0 -0
- {udemy_userAPI-0.2.4.dist-info → udemy_userAPI-0.2.6.dist-info}/WHEEL +0 -0
- {udemy_userAPI-0.2.4.dist-info → udemy_userAPI-0.2.6.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/authenticate.py
CHANGED
@@ -1,15 +1,19 @@
|
|
1
1
|
import json
|
2
2
|
import os
|
3
3
|
import pickle
|
4
|
+
import traceback
|
5
|
+
from datetime import datetime
|
4
6
|
import requests
|
5
7
|
from .exeptions import UnhandledExceptions, UdemyUserApiExceptions, LoginException
|
6
8
|
import cloudscraper
|
7
9
|
|
10
|
+
DEBUG = False
|
11
|
+
|
8
12
|
|
9
13
|
class UdemyAuth:
|
10
14
|
def __init__(self):
|
11
15
|
"""Autenticação na plataforma udemy de maneira segura, atencao ao limite de logins,recomendo que apos logar
|
12
|
-
nao use
|
16
|
+
nao use novamente o metodo login use apenas o verifcador de login para evitar bloqueios temporários..."""
|
13
17
|
self.__cookie_dict = {}
|
14
18
|
# Diretório do arquivo atual
|
15
19
|
current_directory = os.path.dirname(__file__)
|
@@ -23,14 +27,6 @@ class UdemyAuth:
|
|
23
27
|
file_name = '.udemy_userAPI' # Nome do arquivo
|
24
28
|
self.__file_path = os.path.join(self.__user_dir, file_name)
|
25
29
|
|
26
|
-
def __make_cookies(self, client_id: str, access_token: str, csrf_token: str):
|
27
|
-
self.__cookie_dict = {
|
28
|
-
'client_id': client_id,
|
29
|
-
'access_token': access_token,
|
30
|
-
'csrf_token': csrf_token
|
31
|
-
}
|
32
|
-
|
33
|
-
@property
|
34
30
|
def verif_login(self):
|
35
31
|
"""verificar se o usuario estar logado."""
|
36
32
|
|
@@ -43,6 +39,9 @@ class UdemyAuth:
|
|
43
39
|
cookies_str = "; ".join([f"{key}={value}" for key, value in cookies_dict.items()])
|
44
40
|
return cookies_str
|
45
41
|
except Exception as e:
|
42
|
+
if DEBUG:
|
43
|
+
e = traceback.format_exc()
|
44
|
+
raise LoginException(e)
|
46
45
|
return False
|
47
46
|
|
48
47
|
log = verif_config()
|
@@ -70,7 +69,7 @@ class UdemyAuth:
|
|
70
69
|
resp = requests.get(url=url, headers=headers)
|
71
70
|
if resp.status_code == 200:
|
72
71
|
convert = json.loads(resp.text)
|
73
|
-
isLoggedIn = convert.get('header', {}).get('isLoggedIn',False)
|
72
|
+
isLoggedIn = convert.get('header', {}).get('isLoggedIn', False)
|
74
73
|
if isLoggedIn:
|
75
74
|
if isLoggedIn == True:
|
76
75
|
return True
|
@@ -143,8 +142,7 @@ class UdemyAuth:
|
|
143
142
|
|
144
143
|
# Verifica a resposta para determinar se o login foi bem-sucedido
|
145
144
|
if "returnUrl" in r.text:
|
146
|
-
self.
|
147
|
-
self.__save_cookies(s.cookies)
|
145
|
+
self._save_cookies(s.cookies)
|
148
146
|
else:
|
149
147
|
login_error = r.json().get("error", {}).get("data", {}).get("formErrors", [])[0]
|
150
148
|
if login_error[0] == "Y":
|
@@ -153,34 +151,125 @@ class UdemyAuth:
|
|
153
151
|
raise LoginException("Email ou senha incorretos")
|
154
152
|
else:
|
155
153
|
raise UnhandledExceptions(login_error)
|
156
|
-
|
157
|
-
return s
|
158
154
|
except Exception as e:
|
159
|
-
|
155
|
+
if DEBUG:
|
156
|
+
e = traceback.format_exc()
|
157
|
+
raise LoginException(e)
|
160
158
|
|
161
|
-
def
|
159
|
+
def _save_cookies(self, cookies):
|
162
160
|
try:
|
163
161
|
with open(fr'{self.__file_path}', 'wb') as f:
|
164
162
|
pickle.dump(cookies, f)
|
165
163
|
except Exception as e:
|
166
|
-
LoginException(e)
|
164
|
+
raise LoginException(e)
|
167
165
|
|
168
166
|
@property
|
169
167
|
def load_cookies(self) -> str:
|
170
|
-
"""
|
168
|
+
"""Carrega cookies e retorna-os em uma string formatada"""
|
171
169
|
try:
|
172
|
-
file = os.path.join(
|
173
|
-
if os.path.exists(file):
|
174
|
-
with open(
|
170
|
+
file = os.path.join(self.__file_path)
|
171
|
+
if os.path.exists(file) and os.path.getsize(file) > 0: # Verifica se o arquivo existe e não está vazio
|
172
|
+
with open(file, 'rb') as f:
|
175
173
|
cookies = pickle.load(f)
|
174
|
+
# Converte cookies em formato de string
|
176
175
|
cookies_dict = {cookie.name: cookie.value for cookie in cookies}
|
177
176
|
cookies_str = "; ".join([f"{key}={value}" for key, value in cookies_dict.items()])
|
178
177
|
return cookies_str
|
179
178
|
else:
|
180
|
-
return
|
179
|
+
return "" # Retorna uma string vazia se o arquivo não existir ou estiver vazio
|
180
|
+
except (EOFError, pickle.UnpicklingError): # Trata arquivos vazios ou corrompidos
|
181
|
+
return "" # Retorna uma string vazia
|
181
182
|
except Exception as e:
|
182
|
-
|
183
|
+
if DEBUG:
|
184
|
+
e = traceback.format_exc()
|
185
|
+
raise LoginException(f"Erro ao carregar cookies: {e}")
|
183
186
|
|
184
187
|
def remove_cookies(self):
|
188
|
+
"""remove os cookies salvos"""
|
185
189
|
if os.path.exists(self.__file_path):
|
186
|
-
|
190
|
+
with open(self.__file_path, 'wb') as f:
|
191
|
+
f.write(b'')
|
192
|
+
|
193
|
+
def login_passwordless(self, email: str, locale: str = 'pt-BR'):
|
194
|
+
"""
|
195
|
+
Realiza login na Udemy usando autenticação de dois fatores (2FA).
|
196
|
+
|
197
|
+
Este método utiliza o fluxo de autenticação OAuth da Udemy para enviar um
|
198
|
+
código de verificação por e-mail ao usuário. Após inserir o código recebido,
|
199
|
+
o login é concluído.
|
200
|
+
|
201
|
+
:param email: Email do usuário.
|
202
|
+
:param locale: Localização do usuário (recomendado para receber mensagens no idioma local).
|
203
|
+
:raises LoginException: Em caso de falha no processo de login.
|
204
|
+
"""
|
205
|
+
try:
|
206
|
+
# Inicializa uma sessão com proteção contra Cloudflare
|
207
|
+
session = cloudscraper.create_scraper()
|
208
|
+
|
209
|
+
# Requisita a página de inscrição para obter o token CSRF
|
210
|
+
signup_url = "https://www.udemy.com/join/signup-popup/"
|
211
|
+
headers = {"User-Agent": "okhttp/4.9.2 UdemyAndroid 8.9.2(499) (phone)"}
|
212
|
+
response = session.get(signup_url, headers=headers)
|
213
|
+
|
214
|
+
# Obtém o token CSRF dos cookies retornados
|
215
|
+
csrf_token = response.cookies.get("csrftoken")
|
216
|
+
if not csrf_token:
|
217
|
+
raise LoginException("Não foi possível obter o token CSRF.")
|
218
|
+
|
219
|
+
# Prepara os dados do login
|
220
|
+
data = {"email": email, "fullname": ""}
|
221
|
+
|
222
|
+
# Atualiza os cookies e cabeçalhos da sessão
|
223
|
+
session.cookies.update(response.cookies)
|
224
|
+
session.headers.update({
|
225
|
+
"User-Agent": "okhttp/4.9.2 UdemyAndroid 8.9.2(499) (phone)",
|
226
|
+
"Accept": "application/json, text/plain, */*",
|
227
|
+
"Accept-Language": locale,
|
228
|
+
"Referer": f"https://www.udemy.com/join/passwordless-auth/?locale={locale.replace('-', '_')}&next="
|
229
|
+
f"https%3A%2F%2Fwww.udemy.com%2Fmobile%2Fipad%2F&response_type=html",
|
230
|
+
"Origin": "https://www.udemy.com",
|
231
|
+
"DNT": "1",
|
232
|
+
"Connection": "keep-alive",
|
233
|
+
"Sec-Fetch-Dest": "empty",
|
234
|
+
"Sec-Fetch-Mode": "cors",
|
235
|
+
"Sec-Fetch-Site": "same-origin",
|
236
|
+
"Pragma": "no-cache",
|
237
|
+
"Cache-Control": "no-cache",
|
238
|
+
})
|
239
|
+
|
240
|
+
# Faz a requisição para iniciar o login
|
241
|
+
login_url = "https://www.udemy.com/api-2.0/auth/code-generation/login/4.0/"
|
242
|
+
response = session.post(login_url, data=data, allow_redirects=False)
|
243
|
+
if 'error_message' in response.text:
|
244
|
+
raise LoginException(f"Erro no login inicial: {response.text}")
|
245
|
+
|
246
|
+
# Solicita o código OTP ao usuário
|
247
|
+
otp = input("Digite o código de 6 dígitos enviado ao seu e-mail: ")
|
248
|
+
upow = datetime.now().strftime("%Y-%m-%d")
|
249
|
+
# Realiza o login com o código OTP
|
250
|
+
otp_login_url = "https://www.udemy.com/api-2.0/auth/udemy-passwordless/login/4.0/"
|
251
|
+
otp_data = {
|
252
|
+
"email": email,
|
253
|
+
"fullname": "",
|
254
|
+
"otp": otp,
|
255
|
+
"subscribeToEmails": "false",
|
256
|
+
"upow": f"{upow}XBY",
|
257
|
+
}
|
258
|
+
session.headers.update({
|
259
|
+
"Referer": f"https://www.udemy.com/join/passwordless-auth/?locale={locale}&next="
|
260
|
+
f"https%3A%2F%2Fwww.udemy.com%2Fmobile%2Fipad%2F&response_type=html"
|
261
|
+
})
|
262
|
+
response = session.post(otp_login_url, otp_data, allow_redirects=False)
|
263
|
+
|
264
|
+
if response.status_code == 200:
|
265
|
+
self._save_cookies(session.cookies)
|
266
|
+
else:
|
267
|
+
raise LoginException(f"Falha no login OTP: {response.text}")
|
268
|
+
except Exception as e:
|
269
|
+
if DEBUG:
|
270
|
+
error_details = traceback.format_exc()
|
271
|
+
else:
|
272
|
+
error_details = str(e)
|
273
|
+
raise LoginException(error_details)
|
274
|
+
|
275
|
+
|
udemy_userAPI/bultins.py
CHANGED
@@ -10,9 +10,10 @@ from .mpd_analyzer import MPDParser
|
|
10
10
|
class DRM:
|
11
11
|
def __init__(self, license_token: str, get_media_sources: list):
|
12
12
|
self.__mpd_content = None
|
13
|
-
self.__dash_url = organize_streams(streams=get_media_sources).get('dash')
|
14
13
|
self.__token = license_token
|
15
|
-
self.
|
14
|
+
self.__dash_url = organize_streams(streams=get_media_sources).get('dash', {})
|
15
|
+
if not license_token or not get_media_sources or not self.__dash_url:
|
16
|
+
return
|
16
17
|
|
17
18
|
def get_key_for_lesson(self):
|
18
19
|
"""get keys for lesson"""
|
@@ -28,6 +29,12 @@ class DRM:
|
|
28
29
|
keys = extract(pssh=pssh, license_token=self.__token)
|
29
30
|
if keys:
|
30
31
|
return keys
|
32
|
+
else:
|
33
|
+
return None
|
34
|
+
else:
|
35
|
+
return None
|
36
|
+
else:
|
37
|
+
return None
|
31
38
|
|
32
39
|
|
33
40
|
class Files:
|
@@ -44,11 +51,13 @@ class Files:
|
|
44
51
|
lecture_id = files.get('lecture_id', None)
|
45
52
|
asset_id = files.get('asset_id', None)
|
46
53
|
title = files.get("title", None)
|
47
|
-
lecture_title = files.get('lecture_title')
|
48
|
-
external_link = files.get('ExternalLink')
|
54
|
+
lecture_title = files.get('lecture_title', None)
|
55
|
+
external_link = files.get('ExternalLink', None)
|
49
56
|
if external_link:
|
50
57
|
lnk = get_external_liks(course_id=self.__id_course, id_lecture=lecture_id, asset_id=asset_id)
|
51
|
-
dt_file = {'title-file': title,
|
58
|
+
dt_file = {'title-file': title,
|
59
|
+
'lecture_title': lecture_title,
|
60
|
+
'lecture_id': lecture_id,
|
52
61
|
'external_link': external_link,
|
53
62
|
'data-file': lnk.get('external_url', None)}
|
54
63
|
return dt_file
|
@@ -59,8 +68,9 @@ class Files:
|
|
59
68
|
headers=HEADERS_USER)
|
60
69
|
if resp.status_code == 200:
|
61
70
|
da = json.loads(resp.text)
|
62
|
-
|
63
|
-
|
71
|
+
dt_file = {'title-file': title,
|
72
|
+
'lecture_title': lecture_title,
|
73
|
+
'lecture_id': lecture_id,
|
64
74
|
'external_link': external_link,
|
65
75
|
'data-file': da['download_urls']}
|
66
76
|
download_urls.append(dt_file)
|
@@ -128,12 +138,10 @@ class Lecture:
|
|
128
138
|
def course_is_drmed(self) -> DRM:
|
129
139
|
"""verifica se a aula possui DRM se sim retorna as keys da aula...
|
130
140
|
retorna 'kid:key' or None"""
|
131
|
-
if self.__asset.get('course_is_drmed'):
|
141
|
+
if self.__asset.get('course_is_drmed', {}):
|
132
142
|
d = DRM(license_token=self.get_media_license_token,
|
133
143
|
get_media_sources=self.get_media_sources)
|
134
144
|
return d
|
135
|
-
else:
|
136
|
-
return self.__asset.get('course_is_drmed')
|
137
145
|
|
138
146
|
@property
|
139
147
|
def get_download_urls(self) -> list:
|
@@ -267,8 +275,8 @@ class Course:
|
|
267
275
|
for item in self.__additional_files_data.get('results', []):
|
268
276
|
# Check if the item is a lecture with supplementary assets
|
269
277
|
if item.get('_class') == 'lecture':
|
270
|
-
id = item.get('id')
|
271
|
-
title = item.get('title')
|
278
|
+
id = item.get('id', {})
|
279
|
+
title = item.get('title', {})
|
272
280
|
assets = item.get('supplementary_assets', [])
|
273
281
|
for asset in assets:
|
274
282
|
supplementary_assets.append({
|
udemy_userAPI/udemy.py
CHANGED
@@ -12,24 +12,23 @@ class Udemy:
|
|
12
12
|
"""wrapper para api de usuario da plataforma udemy"""
|
13
13
|
|
14
14
|
def __init__(self):
|
15
|
-
"""
|
16
|
-
cookies de seção.
|
17
|
-
"""
|
18
15
|
self.__headers = HEADERS_USER
|
19
16
|
if verif_login is None:
|
20
17
|
raise LoginException("User Not Logged!")
|
21
18
|
|
22
|
-
@
|
23
|
-
def my_subscribed_courses_by_plan(
|
24
|
-
"""obtém os cursos que o usuário esatá inscrito, obtidos atraves de planos(assinatura)
|
19
|
+
@staticmethod
|
20
|
+
def my_subscribed_courses_by_plan() -> list[dict]:
|
21
|
+
"""obtém os cursos que o usuário esatá inscrito, obtidos atraves de planos(assinatura)
|
22
|
+
:return:
|
23
|
+
"""
|
25
24
|
try:
|
26
25
|
courses = get_courses_plan(tipe='plan')
|
27
26
|
return courses
|
28
27
|
except UdemyUserApiExceptions as e:
|
29
28
|
UnhandledExceptions(e)
|
30
29
|
|
31
|
-
@
|
32
|
-
def my_subscribed_courses(
|
30
|
+
@staticmethod
|
31
|
+
def my_subscribed_courses() -> list[dict]:
|
33
32
|
"""Obtém os cursos que o usuário está inscrito, excluindo listas vazias ou nulas"""
|
34
33
|
try:
|
35
34
|
# Obtém os cursos
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: udemy_userAPI
|
3
|
-
Version: 0.2.
|
3
|
+
Version: 0.2.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
|
@@ -19,7 +19,7 @@ Requires-Dist: pywidevine
|
|
19
19
|
# udemy-userAPI
|
20
20
|
|
21
21
|
|
22
|
-

|
23
23
|

|
24
24
|
[](https://apoia.se/paulocesar-dev404)
|
25
25
|
[](https://github.com/PauloCesar-dev404/udemy-userAPI/wiki)
|
@@ -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=rzNgClR2jOV4dqJpZ-J9iW5J_qFV_BiiYOYrBzRWseQ,405
|
15
|
+
udemy_userAPI/api.py,sha256=dpwFtXewQmKwgG1IvzDFYZoEHNTwZbLIuv4WKgbqjOg,18817
|
16
|
+
udemy_userAPI/authenticate.py,sha256=ywAM-85c0UnpoTc-eiEysYIEOY5r4SytbngwuV86wgY,12292
|
17
|
+
udemy_userAPI/bultins.py,sha256=_-CM8Y-EuOEyg3kbNI2LKUONdCn2d1El1AmoNqFo0EU,12426
|
18
|
+
udemy_userAPI/exeptions.py,sha256=nuZoAt4i-ctrW8zx9LZtejrngpFXDHOVE5cEXM4RtrY,508
|
19
|
+
udemy_userAPI/sections.py,sha256=zPyDhvTIQCL0nbf7OJZG28Kax_iooILQ_hywUwvHoL8,4043
|
20
|
+
udemy_userAPI/udemy.py,sha256=KMWMmid0zC9pUCULjLSAOK0P7yvCOtdShXpT6Q-fhro,2127
|
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=_vw1feJXDjw5fQLOmA5-H3UklX_30Pbl__HtDUqvp3c,17283
|
25
|
+
udemy_userAPI-0.2.6.dist-info/LICENSE,sha256=l4jdKYt8gSdDFOGr09vCKnMn_Im55XIcQKqTDEtFfNs,1095
|
26
|
+
udemy_userAPI-0.2.6.dist-info/METADATA,sha256=klDgLa9mjUKStI8BUjgEWHA8azJKyDut_bJvHpoLWz8,1394
|
27
|
+
udemy_userAPI-0.2.6.dist-info/WHEEL,sha256=PZUExdf71Ui_so67QXpySuHtCi3-J3wvF4ORK6k_S8U,91
|
28
|
+
udemy_userAPI-0.2.6.dist-info/top_level.txt,sha256=ijTINaSDRKhdahY_X7dmSRFTxBIwQErWv9ATCG55mog,14
|
29
|
+
udemy_userAPI-0.2.6.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=yRNB4bHSJhN7ugz9iJp6x2b-P_k3yGzI60MkeoyisfQ,405
|
3
|
-
udemy_userAPI/api.py,sha256=dpwFtXewQmKwgG1IvzDFYZoEHNTwZbLIuv4WKgbqjOg,18817
|
4
|
-
udemy_userAPI/authenticate.py,sha256=JWqDHgcBh7pnRrHOL_RP3Lx32txrdCtS4biUsHq49LE,7950
|
5
|
-
udemy_userAPI/bultins.py,sha256=XCXMe_5qKig_q5vbSFXBtx1vM87pE3UvEMKyUy6JCRo,12202
|
6
|
-
udemy_userAPI/exeptions.py,sha256=nuZoAt4i-ctrW8zx9LZtejrngpFXDHOVE5cEXM4RtrY,508
|
7
|
-
udemy_userAPI/sections.py,sha256=zPyDhvTIQCL0nbf7OJZG28Kax_iooILQ_hywUwvHoL8,4043
|
8
|
-
udemy_userAPI/udemy.py,sha256=ceaXVTbQhSYkHnPIpYWUVtT6IT6jBvzYO_k4B7EFyj8,2154
|
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=_vw1feJXDjw5fQLOmA5-H3UklX_30Pbl__HtDUqvp3c,17283
|
13
|
-
udemy_userAPI-0.2.4.dist-info/LICENSE,sha256=l4jdKYt8gSdDFOGr09vCKnMn_Im55XIcQKqTDEtFfNs,1095
|
14
|
-
udemy_userAPI-0.2.4.dist-info/METADATA,sha256=IWt_ESRHpa9rDwcg3Kgsm3KlE7pvY1NyDCHdBZEaE3s,1394
|
15
|
-
udemy_userAPI-0.2.4.dist-info/WHEEL,sha256=PZUExdf71Ui_so67QXpySuHtCi3-J3wvF4ORK6k_S8U,91
|
16
|
-
udemy_userAPI-0.2.4.dist-info/top_level.txt,sha256=ijTINaSDRKhdahY_X7dmSRFTxBIwQErWv9ATCG55mog,14
|
17
|
-
udemy_userAPI-0.2.4.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|