🎨 删除接口

This commit is contained in:
小锅饭 2025-09-21 11:09:29 +08:00
parent fe9db2d70f
commit ca6bf07075
5 changed files with 31 additions and 101 deletions

View File

@ -13,7 +13,7 @@ import (
// 1. 获取所有频道 // 1. 获取所有频道
// 2. 遍历所有频道,检查频道是否更新 // 2. 遍历所有频道,检查频道是否更新
// 3. 如果更新,获取更新的内容,但是返回的数据 // 3. 如果更新,获取更新的内容,但是返回的数据
func (repo *rssDomain) syncRss(ctx context.Context) (updated map[int64]*RssClientView, err error) { func (repo *RssDomain) syncRss(ctx context.Context) (updated map[int64]*RssClientView, err error) {
updated = make(map[int64]*RssClientView) updated = make(map[int64]*RssClientView)
// 获取所有频道 // 获取所有频道
sources, err := repo.storage.GetSources(ctx) sources, err := repo.storage.GetSources(ctx)
@ -73,7 +73,7 @@ func (repo *rssDomain) syncRss(ctx context.Context) (updated map[int64]*RssClien
} }
// checkSourceNeedUpdate 检查频道是否需要更新 // checkSourceNeedUpdate 检查频道是否需要更新
func (repo *rssDomain) checkSourceNeedUpdate(ctx context.Context, source *RssSource) (needUpdate bool, err error) { func (repo *RssDomain) checkSourceNeedUpdate(ctx context.Context, source *RssSource) (needUpdate bool, err error) {
var sourceInDB *RssSource var sourceInDB *RssSource
sourceInDB, err = repo.storage.GetSourceByRssHubFeedLink(ctx, source.RssHubFeedPath) sourceInDB, err = repo.storage.GetSourceByRssHubFeedLink(ctx, source.RssHubFeedPath)
if err != nil { if err != nil {
@ -92,7 +92,7 @@ func (repo *rssDomain) checkSourceNeedUpdate(ctx context.Context, source *RssSou
} }
// processContentsUpdate 处理内容(s)更新 // processContentsUpdate 处理内容(s)更新
func (repo *rssDomain) processContentsUpdate(ctx context.Context, cv *RssClientView, updateChannelView *RssClientView) error { func (repo *RssDomain) processContentsUpdate(ctx context.Context, cv *RssClientView, updateChannelView *RssClientView) error {
var err error var err error
for _, content := range cv.Contents { for _, content := range cv.Contents {
if content == nil { if content == nil {
@ -115,7 +115,7 @@ func (repo *rssDomain) processContentsUpdate(ctx context.Context, cv *RssClientV
} }
// processContentItemUpdate 处理单个内容更新 // processContentItemUpdate 处理单个内容更新
func (repo *rssDomain) processContentItemUpdate(ctx context.Context, content *RssContent) (existed bool, err error) { func (repo *RssDomain) processContentItemUpdate(ctx context.Context, content *RssContent) (existed bool, err error) {
existed, err = repo.storage.IsContentHashIDExist(ctx, content.HashID) existed, err = repo.storage.IsContentHashIDExist(ctx, content.HashID)
if err != nil { if err != nil {
return return

View File

@ -12,31 +12,17 @@ import (
) )
// RssDomain RssRepo定义 // RssDomain RssRepo定义
type RssDomain interface { type RssDomain struct {
// Subscribe 订阅Rss频道 storage *repoStorage
Subscribe(ctx context.Context, gid int64, route string) (rv *RssClientView, isChannelExisted,
isSubExisted bool, err error)
// Unsubscribe 取消订阅Rss频道
Unsubscribe(ctx context.Context, gid int64, route string) (err error)
// GetSubscribedChannelsByGroupID 获取群组订阅的Rss频道
GetSubscribedChannelsByGroupID(ctx context.Context, gid int64) (rv []*RssClientView, err error)
// Sync 同步Rss频道
// 返回群组-频道推送视图 map[群组]推送内容数组
Sync(ctx context.Context) (groupView map[int64][]*RssClientView, err error)
}
// rssDomain RssRepo定义
type rssDomain struct {
storage RepoStorage
rssHubClient *RssHubClient rssHubClient *RssHubClient
} }
// NewRssDomain 新建RssDomain调用方保证单例模式 // NewRssDomain 新建RssDomain调用方保证单例模式
func NewRssDomain(dbPath string) (RssDomain, error) { func NewRssDomain(dbPath string) (*RssDomain, error) {
return newRssDomain(dbPath) return newRssDomain(dbPath)
} }
func newRssDomain(dbPath string) (*rssDomain, error) { func newRssDomain(dbPath string) (*RssDomain, error) {
if _, err := os.Stat(dbPath); err != nil || os.IsNotExist(err) { if _, err := os.Stat(dbPath); err != nil || os.IsNotExist(err) {
// 生成文件 // 生成文件
f, err := os.Create(dbPath) f, err := os.Create(dbPath)
@ -50,7 +36,7 @@ func newRssDomain(dbPath string) (*rssDomain, error) {
logrus.Errorf("[rsshub NewRssDomain] open db error: %v", err) logrus.Errorf("[rsshub NewRssDomain] open db error: %v", err)
panic(err) panic(err)
} }
repo := &rssDomain{ repo := &RssDomain{
storage: &repoStorage{orm: orm}, storage: &repoStorage{orm: orm},
rssHubClient: &RssHubClient{Client: http.DefaultClient}, rssHubClient: &RssHubClient{Client: http.DefaultClient},
} }
@ -63,7 +49,7 @@ func newRssDomain(dbPath string) (*rssDomain, error) {
} }
// Subscribe QQ群订阅Rss频道 // Subscribe QQ群订阅Rss频道
func (repo *rssDomain) Subscribe(ctx context.Context, gid int64, feedPath string) ( func (repo *RssDomain) Subscribe(ctx context.Context, gid int64, feedPath string) (
rv *RssClientView, isChannelExisted, isSubExisted bool, err error) { rv *RssClientView, isChannelExisted, isSubExisted bool, err error) {
// 验证 // 验证
feed, err := repo.rssHubClient.FetchFeed(feedPath) feed, err := repo.rssHubClient.FetchFeed(feedPath)
@ -118,7 +104,7 @@ func (repo *rssDomain) Subscribe(ctx context.Context, gid int64, feedPath string
} }
// Unsubscribe 群组取消订阅 // Unsubscribe 群组取消订阅
func (repo *rssDomain) Unsubscribe(ctx context.Context, gid int64, feedPath string) (err error) { func (repo *RssDomain) Unsubscribe(ctx context.Context, gid int64, feedPath string) (err error) {
existedSubscribes, ifExisted, err := repo.storage.GetIfExistedSubscribe(ctx, gid, feedPath) existedSubscribes, ifExisted, err := repo.storage.GetIfExistedSubscribe(ctx, gid, feedPath)
if err != nil { if err != nil {
logrus.WithContext(ctx).Errorf("[rsshub Subscribe] query sub by route error: %v", err) logrus.WithContext(ctx).Errorf("[rsshub Subscribe] query sub by route error: %v", err)
@ -153,7 +139,7 @@ func (repo *rssDomain) Unsubscribe(ctx context.Context, gid int64, feedPath stri
} }
// GetSubscribedChannelsByGroupID 获取群对应的订阅的频道信息 // GetSubscribedChannelsByGroupID 获取群对应的订阅的频道信息
func (repo *rssDomain) GetSubscribedChannelsByGroupID(ctx context.Context, gid int64) ([]*RssClientView, error) { func (repo *RssDomain) GetSubscribedChannelsByGroupID(ctx context.Context, gid int64) ([]*RssClientView, error) {
channels, err := repo.storage.GetSubscribedChannelsByGroupID(ctx, gid) channels, err := repo.storage.GetSubscribedChannelsByGroupID(ctx, gid)
if err != nil { if err != nil {
logrus.WithContext(ctx).Errorf("[rsshub GetSubscribedChannelsByGroupID] GetSubscribedChannelsByGroupID error: %v", err) logrus.WithContext(ctx).Errorf("[rsshub GetSubscribedChannelsByGroupID] GetSubscribedChannelsByGroupID error: %v", err)
@ -170,7 +156,7 @@ func (repo *rssDomain) GetSubscribedChannelsByGroupID(ctx context.Context, gid i
} }
// Sync 同步任务按照群组订阅情况做好map切片 // Sync 同步任务按照群组订阅情况做好map切片
func (repo *rssDomain) Sync(ctx context.Context) (groupView map[int64][]*RssClientView, err error) { func (repo *RssDomain) Sync(ctx context.Context) (groupView map[int64][]*RssClientView, err error) {
groupView = make(map[int64][]*RssClientView) groupView = make(map[int64][]*RssClientView)
// 获取所有Rss频道 // 获取所有Rss频道
// 获取所有频道 // 获取所有频道

View File

@ -1,47 +0,0 @@
package domain
import "context"
// RepoContent RSS 推送信息存储接口
type RepoContent interface {
// UpsertContent 添加一条文章
UpsertContent(ctx context.Context, content *RssContent) error
// DeleteSourceContents 删除订阅源的所有文章,返回被删除的文章数
DeleteSourceContents(ctx context.Context, channelID int64) (int64, error)
// IsContentHashIDExist hash id 对应的文章是否已存在
IsContentHashIDExist(ctx context.Context, hashID string) (bool, error)
}
// RepoSource RSS 订阅源存储接口
type RepoSource interface {
// UpsertSource 添加一个订阅源
UpsertSource(ctx context.Context, rfc *RssSource) error
// GetSources 获取所有订阅源信息
GetSources(ctx context.Context) ([]RssSource, error)
// GetSourceByRssHubFeedLink 通过 rssHub 的 feed 链接获取订阅源信息
GetSourceByRssHubFeedLink(ctx context.Context, url string) (*RssSource, error)
// DeleteSource 删除一个订阅源
DeleteSource(ctx context.Context, fID int64) error
}
// RepoSubscribe RSS 订阅存储接口
type RepoSubscribe interface {
// CreateSubscribe 添加一个订阅
CreateSubscribe(ctx context.Context, gid, rssSourceID int64) error
// DeleteSubscribe 删除一个订阅
DeleteSubscribe(ctx context.Context, subscribeID int64) error
// GetSubscribeByID 获取一个订阅
GetSubscribeByID(ctx context.Context, gid int64, subscribeID int64) (*RssSubscribe, error)
// GetSubscribes 获取全部订阅
GetSubscribes(ctx context.Context) ([]*RssSubscribe, error)
}
// RepoMultiQuery 多表查询接口
type RepoMultiQuery interface {
// GetSubscribesBySource 获取一个源对应的所有订阅群组
GetSubscribesBySource(ctx context.Context, feedPath string) ([]*RssSubscribe, error)
// GetIfExistedSubscribe 判断一个群组是否已订阅了一个源
GetIfExistedSubscribe(ctx context.Context, gid int64, feedPath string) (*RssSubscribe, bool, error)
// GetSubscribedChannelsByGroupID 获取该群所有的订阅
GetSubscribedChannelsByGroupID(ctx context.Context, gid int64) ([]*RssSource, error)
}

View File

@ -10,15 +10,6 @@ import (
"github.com/sirupsen/logrus" "github.com/sirupsen/logrus"
) )
// RepoStorage 定义RepoStorage接口
type RepoStorage interface {
RepoContent
RepoSource
RepoSubscribe
RepoMultiQuery
initDB() error
}
// repoStorage db struct for rss // repoStorage db struct for rss
type repoStorage struct { type repoStorage struct {
orm *gorm.DB orm *gorm.DB

View File

@ -18,7 +18,7 @@ import (
// 初始化 repo // 初始化 repo
var ( var (
rssRepo domain.RssDomain rssRepo *domain.RssDomain
initErr error initErr error
regexpForSQL = regexp.MustCompile(`[\^<>\[\]%&\*\(\)\{\}\|\=]|(union\s+select|update\s+|delete\s+|drop\s+|truncate\s+|insert\s+|exec\s+|declare\s+)`) regexpForSQL = regexp.MustCompile(`[\^<>\[\]%&\*\(\)\{\}\|\=]|(union\s+select|update\s+|delete\s+|drop\s+|truncate\s+|insert\s+|exec\s+|declare\s+)`)
) )
@ -28,11 +28,11 @@ var (
engine = control.Register("rsshub", &ctrl.Options[*zero.Ctx]{ engine = control.Register("rsshub", &ctrl.Options[*zero.Ctx]{
// 默认不启动 // 默认不启动
DisableOnDefault: false, DisableOnDefault: false,
Brief: "RssHub订阅姬", Brief: "rsshub订阅姬",
// 详细帮助 // 详细帮助
Help: "RssHub订阅姬desu~ \n" + Help: "rsshub订阅姬desu~ \n" +
"支持的详细订阅列表文档可见:\n" + "支持的详细订阅列表文档可见:\n" +
"https://rsshub.netlify.app/ \n" + "https://rsshub.netlify.app/zh/ \n" +
"- 添加rsshub订阅-/bookfere/weekly \n" + "- 添加rsshub订阅-/bookfere/weekly \n" +
"- 删除rsshub订阅-/bookfere/weekly \n" + "- 删除rsshub订阅-/bookfere/weekly \n" +
"- 查看rsshub订阅列表 \n" + "- 查看rsshub订阅列表 \n" +
@ -43,10 +43,10 @@ var (
// 插件数据存储路径 // 插件数据存储路径
PrivateDataFolder: "rsshub", PrivateDataFolder: "rsshub",
OnEnable: func(ctx *zero.Ctx) { OnEnable: func(ctx *zero.Ctx) {
ctx.SendChain(message.Text("RssHub订阅姬现在启动了哦")) ctx.SendChain(message.Text("rsshub订阅姬现在启动了哦"))
}, },
OnDisable: func(ctx *zero.Ctx) { OnDisable: func(ctx *zero.Ctx) {
ctx.SendChain(message.Text("RssHub订阅姬现在关闭了哦")) ctx.SendChain(message.Text("rsshub订阅姬现在关闭了哦"))
}, },
}).ApplySingle(zbpCtxExt.DefaultSingle) }).ApplySingle(zbpCtxExt.DefaultSingle)
) )
@ -55,7 +55,7 @@ var (
func init() { func init() {
rssRepo, initErr = domain.NewRssDomain(engine.DataFolder() + "rsshub.db") rssRepo, initErr = domain.NewRssDomain(engine.DataFolder() + "rsshub.db")
if initErr != nil { if initErr != nil {
logrus.Errorln("RssHub订阅姬初始化失败", initErr) logrus.Errorln("rsshub订阅姬初始化失败", initErr)
panic(initErr) panic(initErr)
} }
engine.OnFullMatch("rsshub同步", zero.OnlyGroup).SetBlock(true).Handle(func(ctx *zero.Ctx) { engine.OnFullMatch("rsshub同步", zero.OnlyGroup).SetBlock(true).Handle(func(ctx *zero.Ctx) {
@ -80,18 +80,18 @@ func init() {
logrus.Debugf("添加rsshub订阅raw(%s), replaced(%s)", routeStr, input) logrus.Debugf("添加rsshub订阅raw(%s), replaced(%s)", routeStr, input)
rv, _, isSubExisted, err := rssRepo.Subscribe(context.Background(), ctx.Event.GroupID, input) rv, _, isSubExisted, err := rssRepo.Subscribe(context.Background(), ctx.Event.GroupID, input)
if err != nil { if err != nil {
ctx.SendChain(message.Text("RssHub订阅姬添加失败", err.Error())) ctx.SendChain(message.Text("rsshub订阅姬添加失败", err.Error()))
return return
} }
if isSubExisted { if isSubExisted {
ctx.SendChain(message.Text("RssHub订阅姬已存在更新成功")) ctx.SendChain(message.Text("rsshub订阅姬已存在更新成功"))
} else { } else {
ctx.SendChain(message.Text("RssHub订阅姬添加成功\n", rv.Source.Title)) ctx.SendChain(message.Text("rsshub订阅姬添加成功\n", rv.Source.Title))
} }
// 添加成功,发送订阅源快照 // 添加成功,发送订阅源快照
msg, err := newRssDetailsMsg(ctx, rv) msg, err := newRssDetailsMsg(ctx, rv)
if len(msg) == 0 || err != nil { if len(msg) == 0 || err != nil {
ctx.SendPrivateMessage(zero.BotConfig.SuperUsers[0], message.Text("RssHub推送错误", err)) ctx.SendPrivateMessage(zero.BotConfig.SuperUsers[0], message.Text("rsshub推送错误", err))
return return
} }
if id := ctx.Send(msg).ID(); id == 0 { if id := ctx.Send(msg).ID(); id == 0 {
@ -104,21 +104,21 @@ func init() {
logrus.Debugf("删除rsshub订阅raw(%s), replaced(%s)", routeStr, input) logrus.Debugf("删除rsshub订阅raw(%s), replaced(%s)", routeStr, input)
err := rssRepo.Unsubscribe(context.Background(), ctx.Event.GroupID, input) err := rssRepo.Unsubscribe(context.Background(), ctx.Event.GroupID, input)
if err != nil { if err != nil {
ctx.SendChain(message.Text("RssHub订阅姬删除失败 ", err.Error())) ctx.SendChain(message.Text("rsshub订阅姬删除失败 ", err.Error()))
return return
} }
ctx.SendChain(message.Text(fmt.Sprintf("RssHub订阅姬删除%s成功", input))) ctx.SendChain(message.Text(fmt.Sprintf("rsshub订阅姬删除%s成功", input)))
}) })
engine.OnFullMatch("查看rsshub订阅列表", zero.OnlyGroup).SetBlock(true).Handle(func(ctx *zero.Ctx) { engine.OnFullMatch("查看rsshub订阅列表", zero.OnlyGroup).SetBlock(true).Handle(func(ctx *zero.Ctx) {
rv, err := rssRepo.GetSubscribedChannelsByGroupID(context.Background(), ctx.Event.GroupID) rv, err := rssRepo.GetSubscribedChannelsByGroupID(context.Background(), ctx.Event.GroupID)
if err != nil { if err != nil {
ctx.SendChain(message.Text("RssHub订阅姬查询失败 ", err.Error())) ctx.SendChain(message.Text("rsshub订阅姬查询失败 ", err.Error()))
return return
} }
// 添加成功,发送订阅源信息 // 添加成功,发送订阅源信息
msg, err := newRssSourcesMsg(ctx, rv) msg, err := newRssSourcesMsg(ctx, rv)
if err != nil { if err != nil {
ctx.SendChain(message.Text("RssHub订阅姬查询失败 ", err.Error())) ctx.SendChain(message.Text("rsshub订阅姬查询失败 ", err.Error()))
return return
} }
if len(msg) == 0 { if len(msg) == 0 {
@ -132,7 +132,7 @@ func init() {
// sendRssUpdateMsg 发送Rss更新消息 // sendRssUpdateMsg 发送Rss更新消息
func sendRssUpdateMsg(ctx *zero.Ctx, groupToFeedsMap map[int64][]*domain.RssClientView) { func sendRssUpdateMsg(ctx *zero.Ctx, groupToFeedsMap map[int64][]*domain.RssClientView) {
for groupID, views := range groupToFeedsMap { for groupID, views := range groupToFeedsMap {
logrus.Infof("RssHub插件在群 %d 触发推送检查", groupID) logrus.Infof("rsshub插件在群 %d 触发推送检查", groupID)
for _, view := range views { for _, view := range views {
if view == nil || len(view.Contents) == 0 { if view == nil || len(view.Contents) == 0 {
continue continue
@ -142,8 +142,8 @@ func sendRssUpdateMsg(ctx *zero.Ctx, groupToFeedsMap map[int64][]*domain.RssClie
ctx.SendPrivateMessage(zero.BotConfig.SuperUsers[0], message.Text(rssHubPushErrMsg, err)) ctx.SendPrivateMessage(zero.BotConfig.SuperUsers[0], message.Text(rssHubPushErrMsg, err))
continue continue
} }
logrus.Infof("RssHub插件在群 %d 开始推送 %s", groupID, view.Source.Title) logrus.Infof("rsshub插件在群 %d 开始推送 %s", groupID, view.Source.Title)
ctx.SendGroupMessage(groupID, message.Text(fmt.Sprintf("%s\n该RssHub频道下有更新了哦~", view.Source.Title))) ctx.SendGroupMessage(groupID, message.Text(fmt.Sprintf("%s\n该rsshub频道下有更新了哦~", view.Source.Title)))
if res := ctx.SendGroupForwardMessage(groupID, msg); !res.Exists() { if res := ctx.SendGroupForwardMessage(groupID, msg); !res.Exists() {
ctx.SendPrivateMessage(zero.BotConfig.SuperUsers[0], message.Text(rssHubPushErrMsg)) ctx.SendPrivateMessage(zero.BotConfig.SuperUsers[0], message.Text(rssHubPushErrMsg))
} }