126 lines
2.3 KiB
Go
126 lines
2.3 KiB
Go
|
package app
|
||
|
|
||
|
import (
|
||
|
"bytes"
|
||
|
"context"
|
||
|
"os"
|
||
|
"text/template"
|
||
|
"time"
|
||
|
|
||
|
tgbotapi "github.com/go-telegram-bot-api/telegram-bot-api/v5"
|
||
|
"github.com/mmcdole/gofeed"
|
||
|
"gitrepo.ru/neonxp/rss2world/templates"
|
||
|
)
|
||
|
|
||
|
type App struct {
|
||
|
config *Config
|
||
|
telegram *tgbotapi.BotAPI
|
||
|
templates *template.Template
|
||
|
}
|
||
|
|
||
|
func New(cfg *Config) (*App, error) {
|
||
|
bot, err := tgbotapi.NewBotAPI(cfg.Telegram.BotToken)
|
||
|
if err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
|
||
|
tpl, err := template.ParseFS(templates.Templates, "*.gotmpl")
|
||
|
if err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
|
||
|
return &App{
|
||
|
config: cfg,
|
||
|
telegram: bot,
|
||
|
templates: tpl,
|
||
|
}, nil
|
||
|
}
|
||
|
|
||
|
func (a *App) Run(ctx context.Context) error {
|
||
|
ticker := time.NewTicker(a.config.RSS.CheckInterval)
|
||
|
for {
|
||
|
select {
|
||
|
case <-ctx.Done():
|
||
|
return nil
|
||
|
case <-ticker.C:
|
||
|
if err := a.iteration(); err != nil {
|
||
|
return err
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func (a *App) iteration() error {
|
||
|
|
||
|
seq, err := a.readSeqFile()
|
||
|
if os.IsNotExist(err) {
|
||
|
seq = ""
|
||
|
err = nil
|
||
|
}
|
||
|
if err != nil {
|
||
|
return err
|
||
|
}
|
||
|
|
||
|
items, err := a.findNewItems(seq)
|
||
|
if err != nil || len(items) == 0 {
|
||
|
return err
|
||
|
}
|
||
|
|
||
|
for i := len(items) - 1; i >= 0; i-- {
|
||
|
if err := a.processItem(items[i]); err != nil {
|
||
|
return err
|
||
|
}
|
||
|
if err := a.writeSeqFile(items[i].GUID); err != nil {
|
||
|
return err
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
func (a *App) processItem(item *gofeed.Item) error {
|
||
|
buf := bytes.NewBufferString("")
|
||
|
if err := a.templates.ExecuteTemplate(buf, "telegram", item); err != nil {
|
||
|
return err
|
||
|
}
|
||
|
for _, group := range a.config.Telegram.TargetGroups {
|
||
|
msg := tgbotapi.NewMessage(group, buf.String())
|
||
|
msg.ParseMode = tgbotapi.ModeHTML
|
||
|
if _, err := a.telegram.Send(msg); err != nil {
|
||
|
return err
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
func (a *App) readSeqFile() (string, error) {
|
||
|
seqVal, err := os.ReadFile(a.config.RSS.SeqFile)
|
||
|
if err != nil {
|
||
|
return "", err
|
||
|
}
|
||
|
|
||
|
return string(seqVal), nil
|
||
|
}
|
||
|
|
||
|
func (a *App) writeSeqFile(seqVal string) error {
|
||
|
return os.WriteFile(a.config.RSS.SeqFile, []byte(seqVal), 0644)
|
||
|
}
|
||
|
|
||
|
func (a *App) findNewItems(from string) ([]*gofeed.Item, error) {
|
||
|
fp := gofeed.NewParser()
|
||
|
feed, err := fp.ParseURL(a.config.RSS.URL)
|
||
|
if err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
out := make([]*gofeed.Item, 0, len(feed.Items))
|
||
|
for _, item := range feed.Items {
|
||
|
if item.GUID == from {
|
||
|
break
|
||
|
}
|
||
|
out = append(out, item)
|
||
|
}
|
||
|
|
||
|
return out, nil
|
||
|
}
|