summaryrefslogtreecommitdiff
path: root/app
diff options
context:
space:
mode:
authorAlexander NeonXP Kiryukhin <i@neonxp.ru>2024-06-27 02:20:00 +0300
committerAlexander NeonXP Kiryukhin <i@neonxp.ru>2024-06-27 02:20:00 +0300
commit12ef16cbeef97b58a5e660230eaa84ceb80afdbc (patch)
treea4ca8b8a5ed07b8406467f1919e2d76fd44c7952 /app
first commit
Diffstat (limited to 'app')
-rw-r--r--app/app.go125
-rw-r--r--app/config.go25
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
+}