Skip to content

Instantly share code, notes, and snippets.

@Jeiel0rbit
Created August 15, 2025 13:33
Show Gist options
  • Select an option

  • Save Jeiel0rbit/f099fca9dd2b1c2cd0231715d5269dd0 to your computer and use it in GitHub Desktop.

Select an option

Save Jeiel0rbit/f099fca9dd2b1c2cd0231715d5269dd0 to your computer and use it in GitHub Desktop.
API TabNews + Gemini AI
# -*- coding: utf-8 -*-
import requests
import json
from datetime import datetime, timedelta, timezone
# --- CONFIGURAÇÕES ---
# URL da API do TabNews através do proxy para evitar bloqueio do Cloudflare
PROXY_URL = "https://corsproxy.io/?url="
# A estratégia 'relevant' é mais adequada para obter os posts com mais tabcoins
TARGET_URL = "https://www.tabnews.com.br/api/v1/contents/NewsletterOficial?strategy=relevant"
TABNEWS_API_URL = f"{PROXY_URL}{TARGET_URL}"
# URL da API do Gemini com o modelo atualizado
GEMINI_API_URL = "https://generativelanguage.googleapis.com/v1beta/models/gemini-2.0-flash-lite:generateContent"
# Chave da API do Gemini.
GEMINI_API_KEY = ""
# Cabeçalho personalizado para a requisição.
HEADERS = {
"User-Agent": "sou pessoa legítima apenas para meu projeto Square News"
}
# Instruções (prompt) para a formatação do texto pela API do Gemini
GEMINI_PROMPT_TEMPLATE = """
Formate as manchetes abaixo para Discord no seguinte padrão:
- Um cabeçalho no início com `:newspaper: **[hora] — [Square News](link)**`. Use um link genérico para o Square News.
- Cada manchete no formato:
**[TÍTULO EM MAIÚSCULO]** — [texto da notícia]
- Palavras e valores importantes em **negrito**.
- Termos conceituais ou estrangeiros em *itálico*.
- Nenhuma numeração, apenas blocos de texto.
- Links sempre embutidos no título geral, não nas manchetes individuais.
- Não adicionar comentários, apenas formatar o texto.
Exemplo de como deve ficar a saída:
:newspaper: **11h — [Square News](https://is.gd/Square_News)**
**CHIPS CEREBRAIS** — A Merge Labs, nova startup de implantes cerebrais apoiada por Sam Altman, entra no mercado avaliada em **US$ 850 milhões**, competindo com a Neuralink de Elon Musk.
**MUNDO AFORA** — Reddit bloqueia bots do Internet Archive por raspagem de IA. Do Kwon, fundador da Luna e TerraUSD, se declara culpado de fraude. Bitcoin bate novo recorde.
Agora, formate as seguintes manchetes:
[cole as manchetes aqui]
"""
def fetch_tabnews_articles():
"""
Busca os artigos da API do TabNews através de um proxy.
Returns:
list: Uma lista de dicionários de artigos, ou None em caso de erro.
"""
print("Buscando notícias no TabNews via proxy...")
try:
response = requests.get(TABNEWS_API_URL, headers=HEADERS)
response.raise_for_status()
return response.json()
except requests.exceptions.RequestException as e:
print(f"Erro ao buscar notícias do TabNews: {e}")
if e.response is not None:
print(f"Status Code: {e.response.status_code}")
print(f"Resposta do servidor: {e.response.text}")
return None
def select_weekly_top_articles(articles, days=7, limit=7):
"""
Seleciona os 'limit' artigos mais relevantes dos últimos 'days' dias.
A relevância é baseada no número de 'tabcoins'.
Args:
articles (list): A lista de artigos para filtrar.
days (int): O número de dias no passado para considerar.
limit (int): O número máximo de artigos a retornar.
Returns:
list: Uma lista com os artigos mais relevantes da semana.
"""
print(f"Selecionando os {limit} artigos mais relevantes dos últimos {days} dias...")
weekly_articles = []
if not articles:
return []
now = datetime.now(timezone.utc)
time_threshold = now - timedelta(days=days)
# 1. Filtra todos os artigos publicados na última semana
for article in articles:
published_at_str = article.get("published_at")
if not published_at_str:
continue
try:
published_at = datetime.fromisoformat(published_at_str.replace('Z', '+00:00'))
if published_at >= time_threshold:
weekly_articles.append(article)
except ValueError:
print(f"Aviso: Não foi possível analisar a data: {published_at_str}")
# 2. Ordena os artigos da semana por relevância (mais tabcoins)
weekly_articles.sort(key=lambda x: x.get('tabcoins', 0), reverse=True)
# 3. Pega os 'limit' melhores artigos
top_articles = weekly_articles[:limit]
# 4. Formata a lista para o Gemini
final_list = []
for article in top_articles:
title = article.get("title")
source_url = article.get("source_url")
if title and source_url:
final_list.append({
"title": title,
"source_url": source_url
})
print(f"Selecionados {len(final_list)} artigos mais relevantes da semana.")
return final_list
def format_with_gemini(articles):
"""
Envia os artigos para a API do Gemini para formatação.
Args:
articles (list): A lista de artigos a serem formatados.
Returns:
str: O texto formatado, ou None em caso de erro.
"""
if not articles:
print("Nenhuma notícia para formatar.")
return None
print("Formatando notícias com a API do Gemini...")
headlines_str = ""
for article in articles:
headlines_str += f"Título: {article['title']}\nFonte: {article['source_url']}\n\n"
full_prompt = GEMINI_PROMPT_TEMPLATE.replace("[cole as manchetes aqui]", headlines_str.strip())
payload = {
"contents": [{
"parts": [{"text": full_prompt}]
}]
}
try:
api_url_with_key = f"{GEMINI_API_URL}?key={GEMINI_API_KEY}"
response = requests.post(
api_url_with_key,
headers={"Content-Type": "application/json"},
data=json.dumps(payload)
)
response.raise_for_status()
result = response.json()
if (result.get("candidates") and
result["candidates"][0].get("content") and
result["candidates"][0]["content"].get("parts")):
return result["candidates"][0]["content"]["parts"][0].get("text")
else:
print("Erro: Resposta da API do Gemini em formato inesperado.")
print(result)
return None
except requests.exceptions.RequestException as e:
print(f"Erro ao chamar a API do Gemini: {e}")
if e.response is not None:
print(f"Resposta do servidor: {e.response.text}")
return None
def main():
"""
Função principal que orquestra a execução do script.
"""
all_articles = fetch_tabnews_articles()
if all_articles:
top_articles = select_weekly_top_articles(all_articles, days=7, limit=7)
if top_articles:
formatted_news = format_with_gemini(top_articles)
if formatted_news:
print("\n--- Notícias Formatadas para o Discord ---\n")
print(formatted_news)
else:
print("\nFalha ao formatar as notícias.")
else:
print("\nNenhum artigo relevante encontrado na última semana.")
if __name__ == "__main__":
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment