init
This commit is contained in:
@@ -0,0 +1,124 @@
|
||||
"""AcFun 直播录制通知接收插件(供 acfunlive 的「通知推送」功能使用)
|
||||
|
||||
acfunlive 会把开播 / 下播 / 开始录制 / 合并完成等事件以 JSON POST 过来,
|
||||
本插件把它们转成群消息发出去。
|
||||
|
||||
安装:
|
||||
把本文件复制到 Momoko 的 plugins 目录(和 upload_notify.py 放一起),重启 bot。
|
||||
|
||||
acfunlive 侧填写(web UI 的「通知推送地址」):
|
||||
http://127.0.0.1:3000/acfunlive/notify
|
||||
(端口换成你 bot.py 里 nonebot.run(port=...) 的实际端口)
|
||||
|
||||
可选环境变量(写在 bot 的 .env 里):
|
||||
ACFUNLIVE_NOTIFY_GROUP=777163254 # 默认通知群,多个用逗号分隔;补底用,见下
|
||||
ACFUNLIVE_NOTIFY_TOKEN=某个口令 # 填了之后会校验 acfunlive 推送时带的 Bearer 口令
|
||||
|
||||
通知发到哪个群:优先用 acfunlive 推送里带的 group 字段(在 acfunlive 的 web UI
|
||||
「通知群号」里配,改完立即生效,不用重启 bot);没配时才回退到环境变量
|
||||
ACFUNLIVE_NOTIFY_GROUP;两边都没配就只记日志不发送。
|
||||
|
||||
acfunlive 推送的 JSON 字段:
|
||||
event liveOn / liveOff / recordStart / mergeDone / test
|
||||
uid 主播 uid
|
||||
name 主播名字
|
||||
title 直播标题
|
||||
url 直播间地址
|
||||
file 相关文件路径(录制开始时的视频、合并完成时的成片)
|
||||
group 通知群号(acfunlive 页面里配的)
|
||||
text 已经拼好的文本,可以直接发出去
|
||||
time 事件发生的时刻
|
||||
"""
|
||||
|
||||
import os
|
||||
|
||||
from fastapi import FastAPI, Request
|
||||
from nonebot import get_bot, get_driver
|
||||
from nonebot.log import logger
|
||||
|
||||
driver = get_driver()
|
||||
app: FastAPI = driver.server_app
|
||||
|
||||
# 兜底的通知群,多个用逗号分隔;acfunlive 推送里带 group 时以推送的为准
|
||||
GROUPS = [g.strip() for g in os.getenv("ACFUNLIVE_NOTIFY_GROUP", "").split(",") if g.strip()]
|
||||
# 推送口令,留空表示不校验
|
||||
TOKEN = os.getenv("ACFUNLIVE_NOTIFY_TOKEN", "").strip()
|
||||
|
||||
|
||||
def resolve_groups(data: dict) -> list[str]:
|
||||
"""决定这条通知发到哪些群:优先用推送里下发的群号,其次用环境变量"""
|
||||
raw = str(data.get("group") or "").strip()
|
||||
if not raw:
|
||||
return GROUPS
|
||||
return [g.strip() for g in raw.split(",") if g.strip()]
|
||||
|
||||
# 每种事件的前缀,让群里一眼能看出是什么事
|
||||
EVENT_PREFIX = {
|
||||
"liveOn": "🔴 开播",
|
||||
"liveOff": "⚪ 下播",
|
||||
"recordStart": "⏺ 开始录制",
|
||||
"mergeDone": "✅ 合并完成",
|
||||
"test": "🧪 测试通知",
|
||||
}
|
||||
|
||||
|
||||
def build_message(data: dict) -> str:
|
||||
"""把推送内容拼成一条群消息"""
|
||||
event = str(data.get("event", ""))
|
||||
prefix = EVENT_PREFIX.get(event, "📢 " + (event or "通知"))
|
||||
|
||||
# text 是 acfunlive 拼好的正文,优先用它
|
||||
body = str(data.get("text") or "").strip()
|
||||
if not body:
|
||||
parts = []
|
||||
if data.get("name"):
|
||||
parts.append(str(data["name"]))
|
||||
if data.get("title"):
|
||||
parts.append(str(data["title"]))
|
||||
if data.get("url"):
|
||||
parts.append(str(data["url"]))
|
||||
body = "\n".join(parts)
|
||||
|
||||
lines = [prefix]
|
||||
if body:
|
||||
lines.append(body)
|
||||
if data.get("time"):
|
||||
lines.append(str(data["time"]))
|
||||
return "\n".join(lines)
|
||||
|
||||
|
||||
@app.post("/acfunlive/notify")
|
||||
async def acfunlive_notify(data: dict, request: Request):
|
||||
"""接收 acfunlive 推送的直播事件"""
|
||||
if TOKEN:
|
||||
auth = request.headers.get("authorization", "")
|
||||
got = auth[7:].strip() if auth.lower().startswith("bearer ") else auth.strip()
|
||||
if got != TOKEN:
|
||||
logger.warning("AcFun 通知的口令不正确,已忽略")
|
||||
return {"status": "error", "message": "口令不正确"}
|
||||
|
||||
message = build_message(data)
|
||||
groups = resolve_groups(data)
|
||||
logger.info(f"收到 AcFun 通知:{data.get('event')} {data.get('name', '')}")
|
||||
|
||||
if not groups:
|
||||
logger.warning("推送里没有 group,也没有设置 ACFUNLIVE_NOTIFY_GROUP,只记录日志不发送")
|
||||
return {"status": "success", "message": "未配置群号,已忽略"}
|
||||
|
||||
ok, failed = 0, []
|
||||
for group_id in groups:
|
||||
try:
|
||||
bot = get_bot()
|
||||
await bot.send_group_msg(group_id=int(group_id), message=message)
|
||||
ok += 1
|
||||
except Exception as e:
|
||||
failed.append(f"{group_id}: {e}")
|
||||
logger.error(f"向群 {group_id} 发送 AcFun 通知失败:{e}")
|
||||
|
||||
if failed:
|
||||
return {"status": "error", "message": ";".join(failed)}
|
||||
return {"status": "success", "message": f"已发送到 {ok} 个群"}
|
||||
|
||||
|
||||
logger.info("AcFun 直播通知插件加载成功")
|
||||
logger.info(f"HTTP 端点:POST /acfunlive/notify,默认群(推送里带 group 时以推送为准):{GROUPS or '未配置'}")
|
||||
Reference in New Issue
Block a user