Compare commits
9 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8f32e427d4 | ||
|
|
3049c49f7a | ||
|
|
14a4f2b8d4 | ||
|
|
6a869574fc | ||
|
|
c581cbacda | ||
|
|
e7fe17a4bc | ||
|
|
b35aaa3b68 | ||
|
|
be83967168 | ||
|
|
064bca1dda |
19
README.md
19
README.md
@@ -1,8 +1,21 @@
|
||||
[English](README-en.md)
|
||||
|
||||
zenfeed:用 AI 赋能 RSS,自动为你筛选、总结、推送重要信息,告别信息过载,重拾阅读掌控感。
|
||||

|
||||
|
||||
开箱即用的公共服务站:https://zenfeed.xyz (集成 Github Trending,V2EX 热榜等常见公开信源)
|
||||
三点:
|
||||
|
||||
**1. AI 版 RSS 阅读器**
|
||||
|
||||
**2. 实时 “新闻” 知识库**
|
||||
|
||||
**3. 帮你时刻关注 “指定事件” 的秘书(如 “关税政策变化”,“xx 股票波动”)**
|
||||
|
||||
开箱即用的公共服务站:https://zenfeed.xyz (集成 Hacker News,Github Trending,V2EX 热榜等常见公开信源)
|
||||
> 总结模型以更新至 Gemini 2.5pro!!
|
||||
|
||||
豆包机器人上架中!
|
||||
|
||||
加入下方👇🏻微信群关注更新
|
||||
|
||||
## 前言
|
||||
|
||||
@@ -142,8 +155,6 @@ $env:API_KEY = "硅基流动apikey"; docker-compose -p zenfeed up -d
|
||||
* 支持 Webhook 通知
|
||||
* 爬虫
|
||||
|
||||
> 进展会第一时间在 [Linux Do](https://linux.do/u/ajd/summary) 更新
|
||||
|
||||
## 有任何问题与反馈,欢迎加群讨论
|
||||
|
||||
<img src="docs/images/wechat.png" alt="Wechat" width="150">
|
||||
|
||||
BIN
docs/images/crad.png
Normal file
BIN
docs/images/crad.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 617 KiB |
@@ -275,7 +275,12 @@ func (r *router) Route(ctx context.Context, result *rule.Result) (groups []*Grou
|
||||
return groups, nil
|
||||
}
|
||||
|
||||
func (r *router) generateSummary(ctx context.Context, prompt string, feeds []*Feed, sourceLabel string) (string, error) {
|
||||
func (r *router) generateSummary(
|
||||
ctx context.Context,
|
||||
prompt string,
|
||||
feeds []*Feed,
|
||||
sourceLabel string,
|
||||
) (string, error) {
|
||||
content := r.parseContentToSummary(feeds, sourceLabel)
|
||||
if content == "" {
|
||||
return "", nil
|
||||
@@ -296,6 +301,7 @@ func (r *router) generateSummary(ctx context.Context, prompt string, feeds []*Fe
|
||||
func (r *router) parseContentToSummary(feeds []*Feed, sourceLabel string) string {
|
||||
if sourceLabel == "" {
|
||||
b := runtimeutil.Must1(json.Marshal(feeds))
|
||||
|
||||
return string(b)
|
||||
}
|
||||
|
||||
|
||||
@@ -208,10 +208,11 @@ func (s *scraper) fillIDs(feeds []*model.Feed) []*model.Feed {
|
||||
for _, feed := range feeds {
|
||||
// We can not use the pub time to join the hash,
|
||||
// because the pub time is dynamic for some sources.
|
||||
//
|
||||
// title may be changed for some sources... so...
|
||||
source := feed.Labels.Get(model.LabelSource)
|
||||
title := feed.Labels.Get(model.LabelTitle)
|
||||
link := feed.Labels.Get(model.LabelLink)
|
||||
feed.ID = hashutil.Sum64s([]string{source, title, link})
|
||||
feed.ID = hashutil.Sum64s([]string{source, link})
|
||||
}
|
||||
|
||||
return feeds
|
||||
|
||||
@@ -22,6 +22,7 @@ import (
|
||||
"reflect"
|
||||
"strconv"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
"time"
|
||||
|
||||
"github.com/benbjohnson/clock"
|
||||
@@ -578,10 +579,14 @@ func (s *storage) blockDependencies() block.Dependencies {
|
||||
}
|
||||
|
||||
func (s *storage) rewrite(ctx context.Context, feeds []*model.Feed) ([]*model.Feed, error) {
|
||||
rewritten := make([]*model.Feed, 0, len(feeds))
|
||||
var wg sync.WaitGroup
|
||||
var errs []error
|
||||
var mu sync.Mutex
|
||||
var (
|
||||
rewritten = make([]*model.Feed, 0, len(feeds))
|
||||
wg sync.WaitGroup
|
||||
mu sync.Mutex
|
||||
errs []error
|
||||
dropped atomic.Int32
|
||||
)
|
||||
|
||||
for _, item := range feeds { // TODO: Limit the concurrency & goroutine number.
|
||||
wg.Add(1)
|
||||
go func(item *model.Feed) {
|
||||
@@ -596,6 +601,7 @@ func (s *storage) rewrite(ctx context.Context, feeds []*model.Feed) ([]*model.Fe
|
||||
}
|
||||
if len(labels) == 0 {
|
||||
log.Debug(ctx, "drop feed", "id", item.ID)
|
||||
dropped.Add(1)
|
||||
|
||||
return // Drop empty labels.
|
||||
}
|
||||
@@ -607,10 +613,12 @@ func (s *storage) rewrite(ctx context.Context, feeds []*model.Feed) ([]*model.Fe
|
||||
}(item)
|
||||
}
|
||||
wg.Wait()
|
||||
if allFailed := len(errs) == len(feeds); allFailed {
|
||||
return nil, errs[0]
|
||||
}
|
||||
if len(errs) > 0 {
|
||||
|
||||
switch len(errs) {
|
||||
case 0:
|
||||
case len(feeds) - int(dropped.Load()):
|
||||
return nil, errs[0] // All failed.
|
||||
default:
|
||||
log.Error(ctx, errors.Wrap(errs[0], "rewrite feeds"), "error_count", len(errs))
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user