@danhachuel/thunderbolt 0.5.85 → 0.5.86

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.
package/README.md CHANGED
@@ -141,7 +141,7 @@ A correcção da integração Nano Banana remove o campo de entrega `inline` rej
141
141
 
142
142
  A página **AI Influencers > Tutorial Meta** apresenta o guia de configuração de uma conta Instagram profissional e das credenciais Meta para automações com n8n, distribuído localmente em `seed/references/guide-instagram.md` e com ligação para a [fonte original no GitHub](https://github.com/gyoridavid/ai_agents_az/blob/main/episode_8/guide-instagram.md). A página **Configurações > Notificações** mantém um histórico persistente de conclusões e falhas, reconcilia estados escritos por componentes locais e disponibiliza um checkbox independente para cada operação mapeada. A subaba **Geral** mantém esse centro local; a subaba **Telegram** permite configurar Bot Token, Chat ID e proxy opcional e envia as mesmas notificações pela Bot API oficial, sem polling ou mensagens recebidas. As notificações novas também aparecem automaticamente como pop-ups no canto inferior direito enquanto o utilizador está noutra página, sem precisar de abrir Notificações; cada aviso é mostrado uma vez por sessão e o histórico continua a controlar o estado de leitura. A página **Configurações > Logs**, colocada imediatamente abaixo de Notificações e acima de Configuração API, apresenta o histórico unificado de tarefas e notificações, com filtro livre por operação, filtros adicionais por operação e estado, e as colunas Operação, Estado, Data, Hora, Registo, Origem, Progresso e Detalhes. A tabela mantém uma barra vertical e, quando a soma das colunas excede a largura disponível, disponibiliza também uma barra de rolagem horizontal na parte inferior para consultar integralmente células longas, sobretudo em **Detalhes**.
143
143
 
144
- A página **Edição > Download Mídia** utiliza a API Python do [yt-dlp](https://github.com/yt-dlp/yt-dlp) para descarregar vídeos e áudio de URLs públicas, com qualidade, contentor, formato de áudio, legendas, metadados, playlists, progresso e histórico local em `storage/downloads/` e `storage/state/media_downloads.json`. Conversão e combinação de streams podem exigir FFmpeg.
144
+ A página **Edição > Download Mídia** utiliza a API Python do [yt-dlp](https://github.com/yt-dlp/yt-dlp) para descarregar vídeos e áudio de URLs públicas, com qualidade, contentor, formato de áudio, legendas, metadados, playlists, progresso e histórico local em `storage/downloads/` e `storage/state/media_downloads.json`. O Thunderbolt instala o pacote Python **Deno** e resolve automaticamente o executável gerido por ele, passando-o ao yt-dlp como runtime `deno:<caminho>`. O pacote `yt-dlp[default]` inclui também os scripts EJS necessários para os desafios JavaScript do YouTube. Se existir um Deno instalado no `PATH`, ele é usado como fallback. Conversão e combinação de streams podem exigir FFmpeg.
145
145
 
146
146
  ## Catálogo comum do Backlog e da Automação
147
147
 
@@ -2,6 +2,7 @@ from __future__ import annotations
2
2
 
3
3
  import hashlib
4
4
  import re
5
+ import shutil
5
6
  import uuid
6
7
  from datetime import datetime, timezone
7
8
  from pathlib import Path
@@ -43,6 +44,22 @@ def _download_root() -> Path:
43
44
  return storage.MEDIA_DOWNLOADS.resolve()
44
45
 
45
46
 
47
+ def _deno_runtime_path() -> str | None:
48
+ """Resolve the project-managed Deno binary, with a PATH fallback."""
49
+ try:
50
+ import deno # type: ignore
51
+
52
+ finder = getattr(deno, "find_deno_bin", None)
53
+ if callable(finder):
54
+ candidate = Path(str(finder())).expanduser()
55
+ if candidate.is_file():
56
+ return str(candidate.resolve())
57
+ except (ImportError, OSError, RuntimeError, TypeError, ValueError):
58
+ pass
59
+ candidate = shutil.which("deno")
60
+ return str(Path(candidate).resolve()) if candidate else None
61
+
62
+
46
63
  def _safe_download_path(value: str | Path) -> Path | None:
47
64
  root = _download_root()
48
65
  candidate = Path(value)
@@ -136,6 +153,10 @@ def build_download_options(
136
153
  "overwrites": False,
137
154
  "paths": {"home": str(root)},
138
155
  }
156
+ deno_path = _deno_runtime_path()
157
+ if deno_path:
158
+ # Equivalent to the CLI argument --js-runtimes deno:<path>.
159
+ options["js_runtimes"] = {"deno": deno_path}
139
160
  if progress_hook is not None:
140
161
  options["progress_hooks"] = [progress_hook]
141
162
  if normalized_mode == "audio":
@@ -183,7 +204,13 @@ def media_download_file(record: dict[str, Any], filename: str) -> Path | None:
183
204
 
184
205
 
185
206
  def dependency_status() -> dict[str, Any]:
186
- return {"yt_dlp": yt_dlp is not None, "ffmpeg_note": "A conversão/combinação de streams pode exigir FFmpeg."}
207
+ deno_path = _deno_runtime_path()
208
+ return {
209
+ "yt_dlp": yt_dlp is not None,
210
+ "deno": bool(deno_path),
211
+ "deno_path": deno_path or "",
212
+ "ffmpeg_note": "A conversão/combinação de streams pode exigir FFmpeg.",
213
+ }
187
214
 
188
215
 
189
216
  def _files_from_info(info: Any, started_at: float) -> list[Path]:
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@danhachuel/thunderbolt",
3
- "version": "0.5.85",
3
+ "version": "0.5.86",
4
4
  "description": "Thunderbolt — interface local para operação de canais faceless e motor MoneyPrinterTurbo",
5
5
  "license": "MIT",
6
6
  "main": "scripts/cli.mjs",
package/requirements.txt CHANGED
@@ -15,7 +15,8 @@ scikit-learn>=1.3,<2
15
15
  mlxtend>=0.23,<1
16
16
  plotly>=5.18,<7
17
17
  seaborn>=0.13,<1
18
- yt-dlp>=2025.1.15,<2027
18
+ yt-dlp[default]>=2025.1.15,<2027
19
+ deno>=2.3,<3
19
20
  youtube-transcript-api>=1.2.0,<2
20
21
  ytmusicapi>=1.12,<2
21
22
  pushtunes>=2.15,<3
@@ -470,7 +470,7 @@ function writeSettings(moneyprinterPath) {
470
470
 
471
471
  function installThunderboltDependencies(python) {
472
472
  if (!existsSync(pythonBin)) run(python.command, [...python.args, "-m", "venv", venvPath]);
473
- installRequirementIfNeeded(join(root, "requirements.txt"), "thunderbolt_requirements_sha256", ["streamlit", "requests", "pandas", "toml", "imageio_ffmpeg", "edge_tts", "google.auth", "google_auth_oauthlib", "googleapiclient", "yt_dlp", "youtube_transcript_api", "huggingface_hub"], "Thunderbolt");
473
+ installRequirementIfNeeded(join(root, "requirements.txt"), "thunderbolt_requirements_sha256", ["streamlit", "requests", "pandas", "toml", "imageio_ffmpeg", "edge_tts", "google.auth", "google_auth_oauthlib", "googleapiclient", "yt_dlp", "deno", "youtube_transcript_api", "huggingface_hub"], "Thunderbolt");
474
474
  }
475
475
 
476
476
  function installMoneyPrinterDependencies(moneyprinterPath) {