@danhachuel/thunderbolt 0.4.95 → 0.4.97

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/app/main.py CHANGED
@@ -7134,6 +7134,7 @@ def _render_media_provider_card(settings: dict[str, Any], cards: list[dict[str,
7134
7134
  card_form = nullcontext() if embedded else st.form(f"media_card_form_{card_id}")
7135
7135
  with card_form:
7136
7136
  key_col, model_col = st.columns(2)
7137
+ refresh_clicked = False
7137
7138
  with key_col:
7138
7139
  api_key = str(card.get("api_key") or "")
7139
7140
  if definition.requires_api_key:
@@ -7159,9 +7160,15 @@ def _render_media_provider_card(settings: dict[str, Any], cards: list[dict[str,
7159
7160
  key=f"media_card_{card_id}_model_select",
7160
7161
  )
7161
7162
  model = "" if selected_model == "__select_model__" else selected_model
7162
- base_url = st.text_input("Base URL", value=str(card.get("base_url") or definition.default_base_url), key=f"media_card_{card_id}_base_url")
7163
+ if definition.code == "canva":
7164
+ refresh_clicked = st.form_submit_button("Consultar Modelos", use_container_width=True, key=f"media_card_{card_id}_refresh")
7165
+ if definition.code == "canva":
7166
+ base_url = definition.default_base_url
7167
+ st.text_input("Base URL", value=base_url, disabled=True, key=f"media_card_{card_id}_base_url_display")
7168
+ else:
7169
+ base_url = st.text_input("Base URL", value=str(card.get("base_url") or definition.default_base_url), key=f"media_card_{card_id}_base_url")
7163
7170
  extra_values: dict[str, str] = {}
7164
- if definition.extra_fields:
7171
+ if definition.extra_fields and definition.code != "canva":
7165
7172
  extra_cols = st.columns(len(definition.extra_fields))
7166
7173
  for extra_col, field_name in zip(extra_cols, definition.extra_fields):
7167
7174
  with extra_col:
@@ -7170,17 +7177,38 @@ def _render_media_provider_card(settings: dict[str, Any], cards: list[dict[str,
7170
7177
  supports_image = True
7171
7178
  supports_video = False
7172
7179
  st.caption("Canva Connect é usado exclusivamente para thumbnails no Pool de Imagem. Não é provider de vídeo.")
7173
- redirect_uri = str(card.get("redirect_uri") or "").strip()
7174
- if not redirect_uri:
7175
- st.info("Defina o Redirect URI no Developer Portal Canva e repita-o neste card antes de autorizar.")
7176
- elif str(card.get("client_id") or "").strip() and str(card.get("client_secret") or "").strip():
7177
- if st.button("Autorizar Canva", key=f"media_card_{card_id}_authorize"):
7180
+ credential_cols = st.columns(3)
7181
+ with credential_cols[0]:
7182
+ client_id = st.text_input("Client Id", value=str(card.get("client_id") or ""), key=f"media_card_{card_id}_client_id")
7183
+ with credential_cols[1]:
7184
+ client_secret = st.text_input("Client Secret", value=str(card.get("client_secret") or ""), type="password", key=f"media_card_{card_id}_client_secret")
7185
+ with credential_cols[2]:
7186
+ redirect_uri = st.text_input("Redirect Uri", value=str(card.get("redirect_uri") or ""), key=f"media_card_{card_id}_redirect_uri")
7187
+ extra_values.update({"client_id": client_id.strip(), "client_secret": client_secret.strip(), "redirect_uri": redirect_uri.strip()})
7188
+ oauth_token = card.get("oauth_token") if isinstance(card.get("oauth_token"), dict) else {}
7189
+ has_credentials = bool(client_id.strip() and client_secret.strip() and redirect_uri.strip())
7190
+ is_authorized = bool(oauth_token.get("access_token"))
7191
+ oauth_state = "Autorizado" if is_authorized else ("Não Autorizado" if has_credentials else "⚠️ Incompleto")
7192
+ st.markdown(f"**Estado OAuth:** `{oauth_state}`")
7193
+ if not has_credentials:
7194
+ st.info("Preencha Client Id, Client Secret e Redirect Uri para iniciar a autorização.")
7195
+ else:
7196
+ authorize_clicked = st.form_submit_button("Iniciar autorização", use_container_width=True, key=f"media_card_{card_id}_authorize") if embedded else st.button("Iniciar autorização", key=f"media_card_{card_id}_authorize")
7197
+ if authorize_clicked:
7178
7198
  verifier, challenge = create_pkce_pair()
7179
7199
  state = create_state()
7180
7200
  st.session_state[f"canva_verifier_{card_id}"] = verifier
7181
7201
  st.session_state[f"canva_state_{card_id}"] = state
7182
- st.link_button("Abrir autorização Canva", authorization_url(str(card.get("client_id")), redirect_uri, "design:content:read design:content:write", state, challenge), use_container_width=True)
7183
- st.caption("Estado OAuth: autorizado" if (card.get("oauth_token") or {}).get("access_token") else "Estado OAuth: não autorizado")
7202
+ st.session_state[f"canva_authorization_url_{card_id}"] = authorization_url(client_id, redirect_uri, "design:content:read design:content:write", state, challenge)
7203
+ authorization_link = str(st.session_state.get(f"canva_authorization_url_{card_id}") or "")
7204
+ if authorization_link:
7205
+ st.markdown(f"[Abrir autorização Canva]({authorization_link})")
7206
+ with st.expander("Opções de exportação e dimensões", expanded=False):
7207
+ export_quality = st.selectbox("Export Quality", ["High", "Medium", "Low"], index=["high", "medium", "low"].index(str(card.get("export_quality") or "medium").lower()), key=f"media_card_{card_id}_export_quality")
7208
+ export_format = st.selectbox("Export Format", ["PNG", "JPG", "PDF"], index=["png", "jpg", "pdf"].index(str(card.get("export_format") or "png").lower()), key=f"media_card_{card_id}_export_format")
7209
+ dimensions = st.selectbox("Thumbnail Width / Height", ["1280 x 720", "1792 x 1024"], index=1 if str(card.get("thumbnail_width")) == "1792" or str(card.get("thumbnail_height")) == "1024" else 0, key=f"media_card_{card_id}_dimensions")
7210
+ selected_width, selected_height = dimensions.replace(" ", "").split("x", 1)
7211
+ extra_values.update({"export_quality": export_quality.lower(), "export_format": export_format.lower(), "thumbnail_width": selected_width, "thumbnail_height": selected_height})
7184
7212
  status_cols = st.columns(4)
7185
7213
  with status_cols[0]:
7186
7214
  enabled = st.checkbox("Provider activo", value=bool(card.get("enabled", True)), key=f"media_card_{card_id}_enabled")
@@ -7192,7 +7220,8 @@ def _render_media_provider_card(settings: dict[str, Any], cards: list[dict[str,
7192
7220
  priority = st.number_input("Prioridade", min_value=0, max_value=999, value=int(card.get("priority", index)), step=1, key=f"media_card_{card_id}_priority")
7193
7221
  action_cols = st.columns(4)
7194
7222
  with action_cols[0]:
7195
- refresh_clicked = st.form_submit_button("Consultar Modelos", use_container_width=True, key=f"media_card_{card_id}_refresh")
7223
+ if definition.code != "canva":
7224
+ refresh_clicked = st.form_submit_button("Consultar Modelos", use_container_width=True, key=f"media_card_{card_id}_refresh")
7196
7225
  with action_cols[1]:
7197
7226
  test_clicked = st.form_submit_button("Testar Chamada API", use_container_width=True, key=f"media_card_{card_id}_test")
7198
7227
  with action_cols[2]:
@@ -219,6 +219,18 @@ def normalize_media_card(card: Any, index: int = 0) -> dict[str, Any]:
219
219
  for field in definition.extra_fields:
220
220
  result[field] = str(source.get(field) or "").strip()
221
221
  if provider == "canva":
222
+ quality = str(source.get("export_quality") or "medium").strip().lower()
223
+ result["export_quality"] = {"regular": "medium", "default": "medium"}.get(quality, quality if quality in {"high", "medium", "low"} else "medium")
224
+ export_format = str(source.get("export_format") or "png").strip().lower()
225
+ result["export_format"] = export_format if export_format in {"png", "jpg", "pdf"} else "png"
226
+ raw_width = str(source.get("thumbnail_width") or "").strip().lower().replace("×", "x").replace(" ", "")
227
+ raw_height = str(source.get("thumbnail_height") or "").strip().lower().replace("×", "x").replace(" ", "")
228
+ combined = raw_width if "x" in raw_width else raw_height
229
+ if "x" in combined:
230
+ left, right = combined.split("x", 1)
231
+ raw_width, raw_height = left, right
232
+ result["thumbnail_width"] = raw_width if raw_width in {"1280", "1792"} else "1280"
233
+ result["thumbnail_height"] = raw_height if raw_height in {"720", "1024"} else ("1024" if result["thumbnail_width"] == "1792" else "720")
222
234
  result["oauth_token"] = dict(source.get("oauth_token") or {}) if isinstance(source.get("oauth_token"), Mapping) else {}
223
235
  if provider == "nano_banana":
224
236
  result["aspect_ratio"] = str(source.get("aspect_ratio") or INTERNAL_IMAGE_ASPECT_RATIO).strip()
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@danhachuel/thunderbolt",
3
- "version": "0.4.95",
3
+ "version": "0.4.97",
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",