ZeroBot-Plugin/plugin/rsshub/main.go
2025-10-07 12:39:16 +08:00

153 lines
5.5 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// Package rsshub rss_hub订阅插件
package rsshub
import (
"context"
"fmt"
"regexp"
ctrl "github.com/FloatTech/zbpctrl"
"github.com/FloatTech/zbputils/control"
zbpCtxExt "github.com/FloatTech/zbputils/ctxext"
"github.com/sirupsen/logrus"
zero "github.com/wdvxdr1123/ZeroBot"
"github.com/wdvxdr1123/ZeroBot/message"
"github.com/FloatTech/ZeroBot-Plugin/plugin/rsshub/domain"
)
// 初始化 repo
var (
rssRepo *domain.RssDomain
initErr error
regexpForSQL = regexp.MustCompile(`[\^<>\[\]%&\*\(\)\{\}\|\=]|(union\s+select|update\s+|delete\s+|drop\s+|truncate\s+|insert\s+|exec\s+|declare\s+)`)
)
var (
// 注册插件
engine = control.Register("rsshub", &ctrl.Options[*zero.Ctx]{
// 默认不启动
DisableOnDefault: false,
Brief: "rsshub订阅姬",
// 详细帮助
Help: "rsshub订阅姬desu~ \n" +
"支持的详细订阅列表文档可见:\n" +
"https://rsshub.netlify.app/zh/ \n" +
"- 添加rsshub订阅-/bookfere/weekly \n" +
"- 删除rsshub订阅-/bookfere/weekly \n" +
"- 查看rsshub订阅列表 \n" +
"- rsshub同步 \n" +
"Tips: 定时刷新rsshub订阅信息需要配合job一起使用, 全局只需要设置一个, 无视响应状态推送, 下为例子\n" +
"记录在\"@every 10m\"触发的指令)\n" +
"rsshub同步",
// 插件数据存储路径
PrivateDataFolder: "rsshub",
OnEnable: func(ctx *zero.Ctx) {
ctx.SendChain(message.Text("rsshub订阅姬现在启动了哦"))
},
OnDisable: func(ctx *zero.Ctx) {
ctx.SendChain(message.Text("rsshub订阅姬现在关闭了哦"))
},
}).ApplySingle(zbpCtxExt.DefaultSingle)
)
// init 命令路由
func init() {
rssRepo, initErr = domain.NewRssDomain(engine.DataFolder() + "rsshub.db")
if initErr != nil {
logrus.Errorln("rsshub订阅姬初始化失败", initErr)
panic(initErr)
}
engine.OnFullMatch("rsshub同步", zero.OnlyGroup).SetBlock(true).Handle(func(ctx *zero.Ctx) {
// 群组-频道推送视图 map[群组]推送内容数组
groupToFeedsMap, err := rssRepo.Sync(context.Background())
if err != nil {
logrus.Errorln("rsshub同步失败", err)
ctx.SendPrivateMessage(zero.BotConfig.SuperUsers[0], message.Text("rsshub同步失败", err))
return
}
// 没有更新的[群组-频道推送视图]则不推送
if len(groupToFeedsMap) == 0 {
logrus.Info("rsshub未发现更新")
return
}
sendRssUpdateMsg(ctx, groupToFeedsMap)
})
// 添加订阅
engine.OnPrefix("添加rsshub订阅-", zero.OnlyGroup).SetBlock(true).Handle(func(ctx *zero.Ctx) {
routeStr := ctx.State["args"].(string)
input := regexpForSQL.ReplaceAllString(routeStr, "")
logrus.Debugf("添加rsshub订阅raw(%s), replaced(%s)", routeStr, input)
rv, _, isSubExisted, err := rssRepo.Subscribe(context.Background(), ctx.Event.GroupID, input)
if err != nil {
ctx.SendChain(message.Text("rsshub订阅姬添加失败", err.Error()))
return
}
if isSubExisted {
ctx.SendChain(message.Text("rsshub订阅姬已存在更新成功"))
} else {
ctx.SendChain(message.Text("rsshub订阅姬添加成功\n", rv.Source.Title))
}
// 添加成功,发送订阅源快照
msg, err := newRssDetailsMsg(ctx, rv)
if len(msg) == 0 || err != nil {
ctx.SendPrivateMessage(zero.BotConfig.SuperUsers[0], message.Text("rsshub推送错误", err))
return
}
if id := ctx.Send(msg).ID(); id == 0 {
ctx.SendChain(message.Text("ERROR: 发送订阅源快照失败,可能被风控了"))
}
})
engine.OnPrefix("删除rsshub订阅-", zero.OnlyGroup).SetBlock(true).Handle(func(ctx *zero.Ctx) {
routeStr := ctx.State["args"].(string)
input := regexpForSQL.ReplaceAllString(routeStr, "")
logrus.Debugf("删除rsshub订阅raw(%s), replaced(%s)", routeStr, input)
err := rssRepo.Unsubscribe(context.Background(), ctx.Event.GroupID, input)
if err != nil {
ctx.SendChain(message.Text("rsshub订阅姬删除失败 ", err.Error()))
return
}
ctx.SendChain(message.Text(fmt.Sprintf("rsshub订阅姬删除%s成功", input)))
})
engine.OnFullMatch("查看rsshub订阅列表", zero.OnlyGroup).SetBlock(true).Handle(func(ctx *zero.Ctx) {
rv, err := rssRepo.GetSubscribedChannelsByGroupID(context.Background(), ctx.Event.GroupID)
if err != nil {
ctx.SendChain(message.Text("rsshub订阅姬查询失败 ", err.Error()))
return
}
// 添加成功,发送订阅源信息
msg, err := newRssSourcesMsg(ctx, rv)
if err != nil {
ctx.SendChain(message.Text("rsshub订阅姬查询失败 ", err.Error()))
return
}
if len(msg) == 0 {
ctx.SendChain(message.Text("ん? 没有订阅的频道哦~"))
return
}
ctx.SendChain(msg...)
})
}
// sendRssUpdateMsg 发送Rss更新消息
func sendRssUpdateMsg(ctx *zero.Ctx, groupToFeedsMap map[int64][]*domain.RssClientView) {
for groupID, views := range groupToFeedsMap {
logrus.Infof("rsshub插件在群 %d 触发推送检查", groupID)
for _, view := range views {
if view == nil || len(view.Contents) == 0 {
continue
}
msg, err := newRssDetailsMsg(ctx, view)
if len(msg) == 0 || err != nil {
ctx.SendPrivateMessage(zero.BotConfig.SuperUsers[0], message.Text(rssHubPushErrMsg, err))
continue
}
logrus.Infof("rsshub插件在群 %d 开始推送 %s", groupID, view.Source.Title)
ctx.SendGroupMessage(groupID, message.Text(fmt.Sprintf("%s\n该rsshub频道下有更新了哦~", view.Source.Title)))
if res := ctx.SendGroupForwardMessage(groupID, msg); !res.Exists() {
ctx.SendPrivateMessage(zero.BotConfig.SuperUsers[0], message.Text(rssHubPushErrMsg))
}
}
}
}