finlight Logo

Tuesday, October 20, 2026

用 finlight Webhooks 把新闻推送到 Slack 或 Discord

Kevin Bartsch

用 finlight Webhooks 把新闻推送到 Slack 或 Discord

把新闻送到团队面前最快的方式,就是把它推送到他们已经在盯着的聊天里。借助 finlight 的 webhooks,你 无需轮询:finlight 会在一篇文章匹配你的过滤条件时调用你的接口。本教程将搭建一个小型 Python 接口,用来 验证 webhook 并把它转发到 Slack 或 Discord。

finlight webhooks 如何工作

你在控制台创建一个 webhook,设置它的过滤条件(股票代码、分类等),并把你的 接口 URL 提供给 finlight。当一篇文章匹配时,finlight 会把该文章 POST 到你的接口,并对请求签名,让你 能够确认它确实来自 finlight。每个请求都带有两个请求头:

  • X-Webhook-Signature —— 请求体的 HMAC-SHA256 签名。
  • X-Webhook-Timestamp —— 用于拒绝重放(有 5 分钟的容差窗口)。

官方 SDK 会替你验证这两者。

接口

import os

import requests
from flask import Flask, request
from finlight_client import WebhookService, WebhookVerificationError

app = Flask(__name__)

WEBHOOK_SECRET = os.environ["FINLIGHT_WEBHOOK_SECRET"]
CHAT_WEBHOOK_URL = os.environ["CHAT_WEBHOOK_URL"]


@app.route("/finlight-webhook", methods=["POST"])
def finlight_webhook():
    raw_body = request.get_data(as_text=True)
    signature = request.headers.get("X-Webhook-Signature")
    timestamp = request.headers.get("X-Webhook-Timestamp")

    try:
        article = WebhookService.construct_event(
            raw_body, signature, WEBHOOK_SECRET, timestamp
        )
    except WebhookVerificationError:
        return "", 400

    text = (
        f"*{article.title}*\n"
        f"{article.sentiment} · {article.source}\n"
        f"{article.link}"
    )

    # Slack 的 incoming webhook 需要 {"text": ...}
    requests.post(CHAT_WEBHOOK_URL, json={"text": text})
    return "", 200

WebhookService.construct_event(...) 会校验签名、验证时间戳,并返回一个解析好的 Article。如果有任何 环节失败,它会抛出 WebhookVerificationError,此时你返回 400。

改为发送到 Discord

Discord 的 incoming webhook 使用 content 字段而非 text。替换这一行 post 即可:

requests.post(CHAT_WEBHOOK_URL, json={"content": text})

其余保持不变。

务必验证

验证很重要:没有它,任何发现你 URL 的人都可能往你的频道里发送伪造文章。请始终把原始、未解析的请求体 传给 construct_event(不要先重新序列化),把端点密钥放在环境变量里,并尽快返回,以免让 finlight 等待。

增强版与原始版

finlight 提供增强版 webhook(带情绪和实体)和原始版 webhook(轻量、更快)。当你的告警需要显示情绪或 涉及的公司时用增强版,当你只需要尽快拿到标题时用原始版。

接下来去哪里

获取免费 API 密钥 →