udemy-userAPI 0.3.10__py3-none-any.whl → 0.3.11__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.
@@ -1,4 +1,4 @@
1
- __version__ = '0.3.10'
1
+ __version__ = '0.3.11'
2
2
  __lib_name__ = 'udemy_userAPI' # local name
3
3
  __repo_name__ = 'udemy-userAPI'
4
4
  __autor__ = 'PauloCesar-dev404'
@@ -208,7 +208,7 @@ class UdemyAuth:
208
208
  with open(self.__file_path, 'wb') as f:
209
209
  f.write(b'')
210
210
 
211
- def login_passwordless(self, email: str, locale: str = 'pt-BR'):
211
+ def login_passwordless(self, email: str, locale: str = 'pt-BR', otp_callback=None):
212
212
  """
213
213
  Realiza login na Udemy usando autenticação de dois fatores (2FA).
214
214
 
@@ -219,6 +219,7 @@ class UdemyAuth:
219
219
  Args:
220
220
  email (str): Email do usuário.
221
221
  locale (str): Localização do usuário (recomendado para receber mensagens no idioma local).
222
+ otp_callback (callable, opcional): Função para obter o código OTP (se None, usa input padrão).
222
223
 
223
224
  Raises:
224
225
  LoginException: Em caso de falha no processo de login.
@@ -227,23 +228,16 @@ class UdemyAuth:
227
228
  try:
228
229
  if self.verif_login():
229
230
  raise UserWarning("Atenção, você já possui uma Sessão válida!")
230
- # Inicializa uma sessão com proteção contra Cloudflare
231
- session = cloudscraper.create_scraper()
232
231
 
233
- # Requisita a página de inscrição para obter o token CSRF
232
+ session = cloudscraper.create_scraper()
234
233
  signup_url = "https://www.udemy.com/join/signup-popup/"
235
234
  headers = {"User-Agent": "okhttp/4.9.2 UdemyAndroid 8.9.2(499) (phone)"}
236
235
  response = session.get(signup_url, headers=headers)
237
-
238
- # Obtém o token CSRF dos cookies retornados
239
236
  csrf_token = response.cookies.get("csrftoken")
240
237
  if not csrf_token:
241
238
  raise LoginException("Não foi possível obter o token CSRF.")
242
239
 
243
- # Prepara os dados do login
244
240
  data = {"email": email, "fullname": ""}
245
-
246
- # Atualiza os cookies e cabeçalhos da sessão
247
241
  session.cookies.update(response.cookies)
248
242
  session.headers.update({
249
243
  "User-Agent": "okhttp/4.9.2 UdemyAndroid 8.9.2(499) (phone)",
@@ -261,17 +255,20 @@ class UdemyAuth:
261
255
  "Cache-Control": "no-cache",
262
256
  })
263
257
 
264
- # Faz a requisição para iniciar o login
265
258
  login_url = "https://www.udemy.com/api-2.0/auth/code-generation/login/4.0/"
266
259
  response = session.post(login_url, data=data, allow_redirects=False)
260
+
267
261
  if 'error_message' in response.text:
268
262
  erro_data: dict = response.json()
269
263
  error_message = erro_data.get('error_message', {})
270
264
  raise LoginException(error_message)
265
+
271
266
  for attempt in range(3):
272
- # Solicita o código OTP ao usuário
273
- otp = input("Digite o código de 6 dígitos enviado ao seu e-mail: ")
274
- # Realiza o login com o código OTP
267
+ # Obtém o código OTP via callback ou terminal
268
+ if otp_callback and callable(otp_callback):
269
+ otp = otp_callback()
270
+ else:
271
+ otp = input("Digite o código de 6 dígitos enviado ao seu e-mail: ")
275
272
  otp_login_url = "https://www.udemy.com/api-2.0/auth/udemy-passwordless/login/4.0/"
276
273
  otp_data = {
277
274
  "email": email,
@@ -280,33 +277,36 @@ class UdemyAuth:
280
277
  "subscribeToEmails": "false",
281
278
  "upow": J(email, 'login')
282
279
  }
280
+
283
281
  session.headers.update({
284
282
  "Referer": f"https://www.udemy.com/join/passwordless-auth/?locale={locale}&next="
285
283
  f"https%3A%2F%2Fwww.udemy.com%2Fmobile%2Fipad%2F&response_type=html"
286
284
  })
285
+
287
286
  response = session.post(otp_login_url, otp_data, allow_redirects=False)
288
- # Verifica se o login foi bem-sucedido
287
+
289
288
  if response.status_code == 200:
290
289
  self._save_cookies(session.cookies)
290
+ break # Sai do loop se o login for bem-sucedido
291
291
  else:
292
292
  if 'error_message' in response.text:
293
293
  erro_data: dict = response.json()
294
294
  error_message = erro_data.get('error_message', {})
295
295
  error_code = erro_data.get('error_code', {})
296
+
296
297
  if error_code == '1538':
297
298
  raise LoginException(error_message)
298
299
  elif error_code == '2550':
299
- print(error_message)
300
- continue
300
+ ### codigo errado....
301
+ raise LoginException(error_message)
301
302
  elif error_code == '1330':
302
303
  raise LoginException(error_message)
303
304
  elif error_code == '1149':
304
- raise LoginException(f"Erro interno ao enviar os dados veja os detalhes: '{error_message}'")
305
+ raise LoginException(
306
+ f"Erro interno ao enviar os dados, veja os detalhes: '{error_message}'")
307
+
305
308
  raise LoginException(response.text)
306
- break
309
+
307
310
  except Exception as e:
308
- if DEBUG:
309
- error_details = traceback.format_exc()
310
- else:
311
- error_details = str(e)
311
+ error_details = traceback.format_exc() if DEBUG else str(e)
312
312
  raise LoginException(error_details)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: udemy_userAPI
3
- Version: 0.3.10
3
+ Version: 0.3.11
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.8-orange)
32
+ ![Versão](https://img.shields.io/badge/version-0.3.11-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,17 @@
1
+ udemy_userAPI/__init__.py,sha256=BPle89xE_CMTKKe_Lw6jioYLgpH-q_Lpho2S-n1PIUA,206
2
+ udemy_userAPI/__version__.py,sha256=H_ODVq4mKyiFkG5i7lWTBSW7IGZEXM6ygiPLRFT_VtA,406
3
+ udemy_userAPI/api.py,sha256=GVvbbs3vFN-rF-qLBwiuHz77sjehwk8HjAI-Dey_A6c,29167
4
+ udemy_userAPI/authenticate.py,sha256=lKh4_UMT4zapnUzUSgM0HZoyZYX84w0MMZAaGvCMZQ4,14086
5
+ udemy_userAPI/bultins.py,sha256=LZlyOjSGte6B6gNn7cjl6L2Q2T_CyXIqqfkOUzt4CV4,21996
6
+ udemy_userAPI/exeptions.py,sha256=kfnPdZpqYY8nd0gnl6_Vh-MIz-XupmmbRPIuFnyXupk,692
7
+ udemy_userAPI/sections.py,sha256=Q1PlVt2Bu5MSEP8g11-F_gilJDdhZq50TV1Bo400jcA,6389
8
+ udemy_userAPI/udemy.py,sha256=SpK0LI4hjO45nZDz5waw-Py-d0uulBb28TVjltyWBxM,2920
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.11.dist-info/LICENSE,sha256=l4jdKYt8gSdDFOGr09vCKnMn_Im55XIcQKqTDEtFfNs,1095
14
+ udemy_userAPI-0.3.11.dist-info/METADATA,sha256=HEgb5dgPW0dIQPdd2BHd4moLOuA1_y_8PWm1CapcxMY,1657
15
+ udemy_userAPI-0.3.11.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
16
+ udemy_userAPI-0.3.11.dist-info/top_level.txt,sha256=ijTINaSDRKhdahY_X7dmSRFTxBIwQErWv9ATCG55mog,14
17
+ udemy_userAPI-0.3.11.dist-info/RECORD,,
@@ -1 +0,0 @@
1
- from .animation import AnimationConsole
@@ -1,64 +0,0 @@
1
- import sys
2
- import time
3
- import threading
4
- from colorama import init, Fore, Style
5
-
6
- # Inicializa o suporte a cores no Windows
7
- init(autoreset=True)
8
-
9
-
10
- class AnimationConsole:
11
- def __init__(self, text="Loading", color=Fore.GREEN, color_frame=Fore.BLUE):
12
- """
13
- Cria uma animação de loading com uma mensagem colorida no console.
14
- :param text: Texto inicial da mensagem de loading.
15
- :param color: Cor do texto, usando Fore do colorama.
16
- """
17
- self._color_frame = color_frame
18
- self._text = text
19
- self._color = color
20
- self._running = False
21
- self._animation_thread = None
22
- self._frames = ["-", "\\", "|", "/"]
23
- self._index = 0
24
-
25
- def start(self):
26
- """
27
- Inicia a animação no console.
28
- """
29
- if self._running:
30
- return # Previne múltiplas execuções
31
- self._running = True
32
- self._animation_thread = threading.Thread(target=self._animate, daemon=True)
33
- self._animation_thread.start()
34
-
35
- def stop(self):
36
- """
37
- Para a animação no console.
38
- """
39
- self._running = False
40
- if self._animation_thread:
41
- self._animation_thread.join()
42
- sys.stdout.write("\r" + " " * (len(self._text) + 20) + "\r") # Limpa a linha
43
-
44
- def update_message(self, new_text, new_color=None):
45
- """
46
- Atualiza a mensagem exibida junto à animação.
47
- :param new_text: Novo texto a ser exibido.
48
- :param new_color: Nova cor para o texto (opcional).
49
- """
50
- self._text = new_text
51
- if new_color:
52
- self._color = new_color
53
-
54
- def _animate(self):
55
- """
56
- Animação interna do console.
57
- """
58
- while self._running:
59
- frame = self._frames[self._index]
60
- self._index = (self._index + 1) % len(self._frames)
61
- sys.stdout.write(
62
- f"\r{self._color}{self._text}{Style.RESET_ALL} {self._color_frame}{frame}{Style.RESET_ALL}")
63
- sys.stdout.flush()
64
- time.sleep(0.1)
@@ -1,118 +0,0 @@
1
- import sys
2
- import os
3
- import requests
4
- import zipfile
5
- import shutil
6
- import stat
7
- from .exeptions import *
8
- from .__utils import URL_PLATAFOMR, system
9
-
10
- lib_name = os.path.dirname(__file__)
11
- URL_BASE_REPO = "https://raw.githubusercontent.com/PauloCesar-dev404/binarios/main/"
12
-
13
-
14
- class Configurate:
15
- """Configura variáveis de ambiente no ambiente virtual ou globalmente."""
16
-
17
- def __init__(self):
18
- self.VERSION = self.__read_version
19
- self.FFMPEG_URL = os.getenv('FFMPEG_URL')
20
- self.FFMPEG_BINARY = os.getenv('FFMPEG_BINARY')
21
- PATH = os.path.join(lib_name, 'ffmpeg-bin')
22
- os.makedirs(PATH, exist_ok=True)
23
- dirpath = PATH
24
- self.INSTALL_DIR = os.getenv('INSTALL_DIR', dirpath)
25
- self.configure()
26
-
27
- def configure(self):
28
- """Configura as variáveis de ambiente com base no sistema operacional."""
29
- if not self.FFMPEG_URL or not self.FFMPEG_BINARY:
30
- platform_name = system
31
- if platform_name == 'Windows':
32
- self.FFMPEG_URL = URL_PLATAFOMR
33
- self.FFMPEG_BINARY = 'ffmpeg.exe'
34
- elif platform_name == 'Linux':
35
- self.FFMPEG_URL = URL_PLATAFOMR
36
- self.FFMPEG_BINARY = 'ffmpeg'
37
- else:
38
- raise DeprecationWarning(f"Arquitetura '{platform_name}' ainda não suportada...\n\n"
39
- f"Versão atual da lib: {self.VERSION}")
40
- os.environ['FFMPEG_URL'] = self.FFMPEG_URL
41
- os.environ['FFMPEG_BINARY'] = self.FFMPEG_BINARY
42
-
43
- if not os.getenv('INSTALL_DIR'):
44
- os.environ['INSTALL_DIR'] = self.INSTALL_DIR
45
-
46
- @property
47
- def __read_version(self):
48
- """Lê a versão do arquivo __version__.py."""
49
- version_file = os.path.join(os.path.dirname(os.path.abspath(__file__)).split('.')[0], '__version__.py')
50
- if os.path.isfile(version_file):
51
- with open(version_file, 'r') as file:
52
- version_line = file.readline().strip()
53
- if version_line.startswith('__version__'):
54
- return version_line.split('=')[1].strip().strip("'")
55
- return 'Unknown Version'
56
-
57
- def __download_file(self, url: str, local_filename: str):
58
- """Baixa um arquivo do URL para o caminho local especificado."""
59
- try:
60
- response = requests.get(url, stream=True)
61
- response.raise_for_status()
62
- total_length = int(response.headers.get('content-length', 0))
63
-
64
- with open(local_filename, 'wb') as f:
65
- start_time = time.time()
66
- downloaded = 0
67
-
68
- for data in response.iter_content(chunk_size=4096):
69
- downloaded += len(data)
70
- f.write(data)
71
-
72
- elapsed_time = time.time() - start_time
73
- elapsed_time = max(elapsed_time, 0.001)
74
- speed_kbps = (downloaded / 1024) / elapsed_time
75
- percent_done = (downloaded / total_length) * 100
76
-
77
-
78
- except requests.RequestException as e:
79
- raise Exception(f"Erro durante o download: {e}")
80
-
81
- def __extract_zip(self, zip_path: str, extract_to: str):
82
- """Descompacta o arquivo ZIP no diretório especificado."""
83
- try:
84
- with zipfile.ZipFile(zip_path, 'r') as zip_ref:
85
- zip_ref.extractall(extract_to)
86
- except zipfile.BadZipFile as e:
87
- sys.stderr.write(f"Erro ao descompactar o arquivo: {e}\n")
88
- raise
89
- finally:
90
- os.remove(zip_path)
91
-
92
- def remove_file(self, file_path: str):
93
- """Remove o arquivo ou diretório especificado."""
94
- if os.path.exists(file_path):
95
- try:
96
- shutil.rmtree(file_path, onerror=self.handle_remove_readonly)
97
- except Exception as e:
98
- print(f"Erro ao remover {file_path}: {e}")
99
- raise
100
-
101
- def install_bins(self):
102
- """Instala o ffmpeg baixando e descompactando o binário apropriado."""
103
- zip_path = os.path.join(self.INSTALL_DIR, "ffmpeg.zip")
104
- os.makedirs(self.INSTALL_DIR, exist_ok=True)
105
- self.__download_file(self.FFMPEG_URL, zip_path)
106
- self.__extract_zip(zip_path, self.INSTALL_DIR)
107
- self.remove_file(zip_path)
108
- os.environ["PATH"] += os.pathsep + self.INSTALL_DIR
109
- return
110
-
111
- def handle_remove_readonly(self, func, path, exc_info):
112
- """Callback para lidar com arquivos somente leitura."""
113
- os.chmod(path, stat.S_IWRITE)
114
- func(path)
115
-
116
-
117
- if __name__ == "__main__":
118
- FFmpegExceptions("erro de runtime...")
@@ -1,8 +0,0 @@
1
- # ffmpeg-and-python/__init__.py
2
-
3
- from .ffmpeg import FFmpeg
4
- from .exeptions import FFmpegExceptions
5
-
6
- __all__ = ['FFmpeg', 'FFmpegExceptions']
7
- if __name__ == '__main__':
8
- raise RuntimeError("no escope!")
@@ -1,78 +0,0 @@
1
- import platform
2
- import os
3
-
4
- URL_PLATAFOMR = ''
5
-
6
-
7
- def get_processor_info():
8
- system = platform.system()
9
- architecture = platform.architecture()[0]
10
- processor = ''
11
- if system == "Windows":
12
- processor = platform.processor()
13
- elif system in ["Linux", "Darwin"]: # Darwin é o nome do sistema para macOS
14
- try:
15
- if system == "Linux":
16
- # Obtém informações detalhadas do processador no Linux
17
- with open("/proc/cpuinfo") as f:
18
- cpuinfo = f.read()
19
- if "model name" in cpuinfo:
20
- processor = cpuinfo.split("model name")[1].split(":")[1].split("\n")[0].strip()
21
- else:
22
- processor = "Unknown"
23
- elif system == "Darwin":
24
- # Obtém informações detalhadas do processador no macOS
25
- processor = os.popen("sysctl -n machdep.cpu.brand_string").read().strip()
26
- except FileNotFoundError:
27
- processor = "Unknown"
28
- d = (f"System: {system} "
29
- f"Architecture: {architecture} "
30
- f"Processor: {processor} ")
31
- return d
32
-
33
-
34
- # Processa a informação do processador e limpa a string
35
- data = (get_processor_info().replace('Architecture:', '').replace('System:', '').
36
- replace('Processor:', '').strip().split())
37
-
38
- # Remove entradas vazias e limpa espaços em branco
39
- cleaned_data = [item.strip() for item in data if item.strip()]
40
-
41
- # Garantindo que há pelo menos três elementos
42
- if len(cleaned_data) >= 2:
43
- system = cleaned_data[0]
44
- architecture = cleaned_data[1]
45
- processor = ' '.join(cleaned_data[2:]) # Junta o restante como o processador
46
-
47
- URL_BASE_REPO = "https://raw.githubusercontent.com/PauloCesar-dev404/binarios/main/"
48
- # Mapeamento para Linux
49
- linux_mapping = {
50
- "x86_64": "amd64",
51
- "i686": "i686",
52
- "arm64": "arm64",
53
- "armhf": "armhf",
54
- "armel": "armel"
55
- }
56
- # Formata a URL com base no sistema e arquitetura
57
- if system == "Linux" and ('intel' in processor.lower() or 'amd' in processor.lower()):
58
- url = f"{URL_BASE_REPO}linux/ffmpeg-7.0.2-{linux_mapping.get('x86_64')}.zip"
59
- elif system == "Linux" and 'i686' in architecture.lower():
60
- url = f"{URL_BASE_REPO}linux/ffmpeg-7.0.2-{linux_mapping.get('i686')}.zip"
61
- elif system == "Linux" and 'arm64' in architecture.lower():
62
- url = f"{URL_BASE_REPO}linux/ffmpeg-7.0.2-{linux_mapping.get('arm64')}.zip"
63
- elif system == "Linux" and 'armhf' in architecture.lower():
64
- url = f"{URL_BASE_REPO}linux/ffmpeg-7.0.2-{linux_mapping.get('armhf')}.zip"
65
- elif system == "Linux" and 'armel' in architecture.lower():
66
- url = f"{URL_BASE_REPO}linux/ffmpeg-7.0.2-{linux_mapping.get('armel')}.zip"
67
- elif system == "Windows" and architecture == '64bit':
68
- url = f"{URL_BASE_REPO}windows/win-ffmpeg-7.0.2-full-amd64-intel64.zip"
69
- else:
70
- url = f"Unsupported system or architecture"
71
-
72
- URL_PLATAFOMR = url
73
-
74
- else:
75
- raise DeprecationWarning("Não foi possível obter seu sistema ....consulte o desenvolvedor!")
76
-
77
- if __name__ == '__main__':
78
- raise RuntimeError("este é uma função interna!")
@@ -1,6 +0,0 @@
1
- __version__ = '0.3.5'
2
- __lib_name__ = 'ffmpeg_for_python'
3
- __autor__ = 'PauloCesar-dev404'
4
- __repo__ = 'https://github.com/PauloCesar-dev404/ffmpeg-for-python'
5
- __lib__ = f'https://raw.githubusercontent.com/PauloCesar-dev404/ffmpeg-for-python/main/{__lib_name__}-{__version__}-py3-none-any.whl'
6
- __source__ = f'https://raw.githubusercontent.com/PauloCesar-dev404/ffmpeg-for-python/main/{__lib_name__}-{__version__}.tar.gz'
@@ -1,91 +0,0 @@
1
- import time
2
-
3
- INPUT_ERROR = [
4
- 'Error opening input: No such file or directory',
5
- 'Error opening input: Permission denied',
6
- 'Error opening input: Invalid argument',
7
- 'Error opening input: Protocol not found',
8
- 'Error opening input: Unsupported protocol',
9
- 'Error opening input: File format not recognized',
10
- 'Error opening input: Could not open file',
11
- 'Error opening input: Invalid data found when processing input',
12
- 'Error opening input: Input stream is empty',
13
- 'Error opening input: Cannot open file for reading',
14
- 'Error opening input: File is too short',
15
- 'Error opening input: End of file while parsing input',
16
- 'Error opening input: Codec not found',
17
- 'Error opening input: No decoder for codec',
18
- 'Error opening input: Stream not found',
19
- 'Error opening input: Stream codec not found',
20
- 'Error opening input: Stream index out of range',
21
- 'Error opening input: Invalid timestamp',
22
- 'Error opening input: Corrupt file',
23
- 'Error opening input: Unsupported codec',
24
- 'Error opening input: Failed to initialize filter',
25
- 'Error opening input: Error while opening codec',
26
- 'Error opening input: Device not found',
27
- 'Error opening input: Device or resource busy',
28
- 'Error opening input: Invalid option',
29
- 'Error opening input: Unable to seek',
30
- 'Error opening input: Input format not found'
31
- ]
32
- OUTPUT_ERROR = [
33
- 'Error opening output file: No such file or directory',
34
- 'Error opening output file: Permission denied',
35
- 'Error opening output file: Invalid argument',
36
- 'Error opening output file: Unsupported protocol',
37
- 'Error opening output file: Protocol not found',
38
- 'Error opening output file: File format not recognized',
39
- 'Error opening output file: Could not open file for writing',
40
- 'Error opening output file: Disk full or quota exceeded',
41
- 'Error opening output file: Cannot create file',
42
- 'Error opening output file: Invalid data found when processing output',
43
- 'Error opening output file: Output stream not found',
44
- 'Error opening output file: Cannot write to file',
45
- 'Error opening output file: File already exists',
46
- 'Error opening output file: Unsupported codec',
47
- 'Error opening output file: Codec not found',
48
- 'Error opening output file: Cannot open codec for writing',
49
- 'Error opening output file: Failed to initialize filter',
50
- 'Error opening output file: Invalid option',
51
- 'Error opening output file: Invalid timestamp',
52
- 'Error opening output file: Corrupt file',
53
- 'Error opening output file: Device or resource busy',
54
- 'Error opening output file: Cannot seek',
55
- 'Error opening output file: Stream index out of range',
56
- 'Error opening output file: Stream codec not found'
57
- ]
58
- ERROS = []
59
- for er in INPUT_ERROR:
60
- ERROS.append(er)
61
- for er in OUTPUT_ERROR:
62
- ERROS.append(er)
63
-
64
-
65
- class FFmpegExceptions(Exception):
66
- def __init__(self, message: str):
67
- super().__init__(message)
68
-
69
- def __str__(self):
70
- """
71
- Retorna a representação em string da exceção.
72
-
73
- Returns:
74
- str: Mensagem de erro formatada com detalhes adicionais, se presentes.
75
- """
76
-
77
- return super().__str__()
78
-
79
-
80
- def wraper_erros(line: str):
81
- """Verifica se a linha de saida do ffmpeg está no dict de erros e retorna sua categoria"""
82
-
83
- if "Error" in line:
84
- erro = line.split('Error')[1]
85
- return erro.strip()
86
- elif 'already exists. Overwrite? [y/N]' in line:
87
- erro = line.split('File')[1]
88
- return erro.strip()
89
-
90
-
91
-