mirror of
https://github.com/FloatTech/ZeroBot-Plugin.git
synced 2026-02-06 15:20:22 +00:00
feat: 添加 rsshub (#1232)
This commit is contained in:
178
plugin/rsshub/domain/rssHub.go
Normal file
178
plugin/rsshub/domain/rssHub.go
Normal file
@@ -0,0 +1,178 @@
|
||||
package domain
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"net/http"
|
||||
"os"
|
||||
"time"
|
||||
|
||||
"github.com/jinzhu/gorm"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
// RssDomain RssRepo定义
|
||||
type RssDomain struct {
|
||||
storage *repoStorage
|
||||
rssHubClient *RssHubClient
|
||||
}
|
||||
|
||||
// NewRssDomain 新建RssDomain,调用方保证单例模式
|
||||
func NewRssDomain(dbPath string) (*RssDomain, error) {
|
||||
return newRssDomain(dbPath)
|
||||
}
|
||||
|
||||
func newRssDomain(dbPath string) (*RssDomain, error) {
|
||||
if _, err := os.Stat(dbPath); err != nil || os.IsNotExist(err) {
|
||||
// 生成文件
|
||||
f, err := os.Create(dbPath)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer f.Close()
|
||||
}
|
||||
orm, err := gorm.Open("sqlite3", dbPath)
|
||||
if err != nil {
|
||||
logrus.Errorf("[rsshub NewRssDomain] open db error: %v", err)
|
||||
panic(err)
|
||||
}
|
||||
repo := &RssDomain{
|
||||
storage: &repoStorage{orm: orm},
|
||||
rssHubClient: &RssHubClient{Client: http.DefaultClient},
|
||||
}
|
||||
err = repo.storage.initDB()
|
||||
if err != nil {
|
||||
logrus.Errorf("[rsshub NewRssDomain] open db error: %v", err)
|
||||
panic(err)
|
||||
}
|
||||
return repo, nil
|
||||
}
|
||||
|
||||
// Subscribe QQ群订阅Rss频道
|
||||
func (repo *RssDomain) Subscribe(ctx context.Context, gid int64, feedPath string) (
|
||||
rv *RssClientView, isChannelExisted, isSubExisted bool, err error) {
|
||||
// 验证
|
||||
feed, err := repo.rssHubClient.FetchFeed(feedPath)
|
||||
if err != nil {
|
||||
logrus.WithContext(ctx).Errorf("[rsshub Subscribe] add source error: %v", err)
|
||||
return
|
||||
}
|
||||
logrus.WithContext(ctx).Infof("[rsshub Subscribe] try get source success: %v", len(feed.Title))
|
||||
// 新建source结构体
|
||||
rv = convertFeedToRssView(0, feedPath, feed)
|
||||
feedChannel, err := repo.storage.GetSourceByRssHubFeedLink(ctx, feedPath)
|
||||
if err != nil {
|
||||
logrus.WithContext(ctx).Errorf("[rsshub Subscribe] query source by feedPath error: %v", err)
|
||||
return
|
||||
}
|
||||
// 如果已经存在
|
||||
if feedChannel != nil {
|
||||
logrus.WithContext(ctx).Warningf("[rsshub Subscribe] source existed: %v", feedChannel)
|
||||
isChannelExisted = true
|
||||
} else {
|
||||
// 不存在的情况,要把更新时间置空,保证下一次同步时能够更新
|
||||
rv.Source.UpdatedParsed = time.Time{}
|
||||
}
|
||||
// 保存
|
||||
err = repo.storage.UpsertSource(ctx, rv.Source)
|
||||
if err != nil {
|
||||
logrus.WithContext(ctx).Errorf("[rsshub Subscribe] save source error: %v", err)
|
||||
return
|
||||
}
|
||||
logrus.Infof("[rsshub Subscribe] save/update source success %v", rv.Source.ID)
|
||||
// 添加群号到订阅
|
||||
subscribe, err := repo.storage.GetSubscribeByID(ctx, gid, rv.Source.ID)
|
||||
if err != nil {
|
||||
logrus.WithContext(ctx).Errorf("[rsshub Subscribe] query subscribe error: %v", err)
|
||||
return
|
||||
}
|
||||
logrus.WithContext(ctx).Infof("[rsshub Subscribe] query subscribe success: %v", subscribe)
|
||||
// 如果已经存在,直接返回
|
||||
if subscribe != nil {
|
||||
isSubExisted = true
|
||||
logrus.WithContext(ctx).Infof("[rsshub Subscribe] subscribe existed: %v", subscribe)
|
||||
return
|
||||
}
|
||||
// 如果不存在,保存
|
||||
err = repo.storage.CreateSubscribe(ctx, gid, rv.Source.ID)
|
||||
if err != nil {
|
||||
logrus.WithContext(ctx).Errorf("[rsshub Subscribe] save subscribe error: %v", err)
|
||||
return
|
||||
}
|
||||
logrus.WithContext(ctx).Infof("[rsshub Subscribe] success: %v", len(rv.Contents))
|
||||
return
|
||||
}
|
||||
|
||||
// Unsubscribe 群组取消订阅
|
||||
func (repo *RssDomain) Unsubscribe(ctx context.Context, gid int64, feedPath string) (err error) {
|
||||
existedSubscribes, ifExisted, err := repo.storage.GetIfExistedSubscribe(ctx, gid, feedPath)
|
||||
if err != nil {
|
||||
logrus.WithContext(ctx).Errorf("[rsshub Subscribe] query sub by route error: %v", err)
|
||||
return errors.New("数据库错误")
|
||||
}
|
||||
logrus.WithContext(ctx).Infof("[rsshub Subscribe] query source by route success: %v", existedSubscribes)
|
||||
// 如果不存在订阅关系,直接返回
|
||||
if !ifExisted || existedSubscribes == nil {
|
||||
logrus.WithContext(ctx).Infof("[rsshub Subscribe] source existed: %v", ifExisted)
|
||||
return errors.New("频道不存在")
|
||||
}
|
||||
err = repo.storage.DeleteSubscribe(ctx, existedSubscribes.ID)
|
||||
if err != nil {
|
||||
logrus.WithContext(ctx).Errorf("[rsshub Subscribe] delete source error: %v", err)
|
||||
return errors.New("删除失败")
|
||||
}
|
||||
// 查询是否还有群订阅这个频道
|
||||
subscribesNeedsToDel, err := repo.storage.GetSubscribesBySource(ctx, feedPath)
|
||||
if err != nil {
|
||||
logrus.WithContext(ctx).Errorf("[rsshub Subscribe] query source by route error: %v", err)
|
||||
return
|
||||
}
|
||||
// 没有群订阅的时候,把频道删除
|
||||
if len(subscribesNeedsToDel) == 0 {
|
||||
err = repo.storage.DeleteSource(ctx, existedSubscribes.RssSourceID)
|
||||
if err != nil {
|
||||
logrus.WithContext(ctx).Errorf("[rsshub Subscribe] delete source error: %v", err)
|
||||
return errors.New("清除频道信息失败")
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// GetSubscribedChannelsByGroupID 获取群对应的订阅的频道信息
|
||||
func (repo *RssDomain) GetSubscribedChannelsByGroupID(ctx context.Context, gid int64) ([]*RssClientView, error) {
|
||||
channels, err := repo.storage.GetSubscribedChannelsByGroupID(ctx, gid)
|
||||
if err != nil {
|
||||
logrus.WithContext(ctx).Errorf("[rsshub GetSubscribedChannelsByGroupID] GetSubscribedChannelsByGroupID error: %v", err)
|
||||
return nil, err
|
||||
}
|
||||
rv := make([]*RssClientView, len(channels))
|
||||
logrus.WithContext(ctx).Infof("[rsshub GetSubscribedChannelsByGroupID] query subscribe success: %v", len(channels))
|
||||
for i, cn := range channels {
|
||||
rv[i] = &RssClientView{
|
||||
Source: cn,
|
||||
}
|
||||
}
|
||||
return rv, nil
|
||||
}
|
||||
|
||||
// Sync 同步任务,按照群组订阅情况做好map切片
|
||||
func (repo *RssDomain) Sync(ctx context.Context) (groupView map[int64][]*RssClientView, err error) {
|
||||
groupView = make(map[int64][]*RssClientView)
|
||||
// 获取所有Rss频道
|
||||
// 获取所有频道
|
||||
updatedViews, err := repo.syncRss(ctx)
|
||||
if err != nil {
|
||||
logrus.WithContext(ctx).Errorf("[rsshub Sync] sync rss feed error: %v", err)
|
||||
return
|
||||
}
|
||||
logrus.WithContext(ctx).Infof("[rsshub Sync] updated channels: %v", len(updatedViews))
|
||||
subscribes, err := repo.storage.GetSubscribes(ctx)
|
||||
if err != nil {
|
||||
logrus.WithContext(ctx).Errorf("[rsshub Sync] get subscribes error: %v", err)
|
||||
return
|
||||
}
|
||||
for _, subscribe := range subscribes {
|
||||
groupView[subscribe.GroupID] = append(groupView[subscribe.GroupID], updatedViews[subscribe.RssSourceID])
|
||||
}
|
||||
return
|
||||
}
|
||||
Reference in New Issue
Block a user