diff options
Diffstat (limited to 'app')
-rw-r--r-- | app/app.go | 125 | ||||
-rw-r--r-- | app/config.go | 25 |
2 files changed, 150 insertions, 0 deletions
diff --git a/app/app.go b/app/app.go new file mode 100644 index 0000000..1ea0ee8 --- /dev/null +++ b/app/app.go @@ -0,0 +1,125 @@ +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 +} diff --git a/app/config.go b/app/config.go new file mode 100644 index 0000000..66531aa --- /dev/null +++ b/app/config.go @@ -0,0 +1,25 @@ +package app + +import ( + "gitrepo.ru/neonxp/rss2world/internal/rss" + "gitrepo.ru/neonxp/rss2world/internal/telegram" + + "github.com/caarlos0/env/v11" +) + +type Config struct { + RSS *rss.Config + Telegram *telegram.Config +} + +func NewConfig() (*Config, error) { + cfg := &Config{RSS: &rss.Config{}, Telegram: &telegram.Config{}} + if err := env.Parse(cfg.RSS); err != nil { + return nil, err + } + if err := env.Parse(cfg.Telegram); err != nil { + return nil, err + } + + return cfg, nil +} |