summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDmitry Ilvokhin <d@ilvokhin.com>2025-03-08 22:26:47 +0000
committerDmitry Ilvokhin <d@ilvokhin.com>2025-03-08 22:26:47 +0000
commit5c2b8ff9b7a6c239424f54f3a818b1916253955d (patch)
treefa1fa63a0e2c3757d6290c45821952f8a894eebd
parent5688f1493026eb4cf96f1abd6d961a5801f1dd26 (diff)
downloadflatbot-5c2b8ff9b7a6c239424f54f3a818b1916253955d.tar.gz
flatbot-5c2b8ff9b7a6c239424f54f3a818b1916253955d.tar.bz2
flatbot-5c2b8ff9b7a6c239424f54f3a818b1916253955d.zip
Manage options with CLI flags
-rw-r--r--flatbot.go103
-rw-r--r--sent.go3
2 files changed, 91 insertions, 15 deletions
diff --git a/flatbot.go b/flatbot.go
index ef10854..0a0e751 100644
--- a/flatbot.go
+++ b/flatbot.go
@@ -1,46 +1,119 @@
package main
import (
+ "flag"
"fmt"
"io"
"log"
"net/http"
"os"
+ "time"
)
+var (
+ apiToken = flag.String("api-token",
+ os.Getenv("FLATBOT_TELEGRAM_BOT_API_TOKEN"),
+ "Telegram Bot API token")
+ chatID = flag.String("chat-id",
+ os.Getenv("FLATBOT_TELEGRAM_CHAT_ID"),
+ "Telegram chat id where to send notification messages")
+ state = flag.String("state", "/tmp/flatbot-sent.json",
+ "Filename to save and load already sent flats")
+ interval = flag.Duration("frequency", 5*time.Minute,
+ "Frequency interval to fetch new data")
+ once = flag.Bool("once", false, "Run fetch and message loop only once")
+ dryRun = flag.Bool("dry-run", false,
+ "Run entire flow, but print new flats to stdout instead of "+
+ "sending them to Telegram")
+)
+
+func usage() {
+ fmt.Fprintf(os.Stderr,
+ "usage: flatbot [-api-token token] [-chat-id id] "+
+ "[-state file] [-interval duration] [-once] [-send] "+
+ "URL...\n")
+ flag.PrintDefaults()
+ os.Exit(2)
+}
+
func main() {
- url := "http://localhost:8000/2025-02-19-isle-of-dogs.html"
- body, err := fetch(url)
+ flag.Usage = usage
+ flag.Parse()
+ if !*dryRun {
+ if len(*apiToken) == 0 {
+ fmt.Fprintf(os.Stderr,
+ "Going to send messages to Telegram, "+
+ "but no API token was provided\n")
+ os.Exit(1)
+ }
+ if len(*chatID) == 0 {
+ fmt.Fprintf(os.Stderr,
+ "Going to send messages to Telegram, "+
+ "but no chat id was provided\n")
+ os.Exit(1)
+ }
+ }
+ if flag.NArg() == 0 {
+ usage()
+ os.Exit(1)
+ }
+
+ for {
+ err := loopOnce()
+ if err != nil {
+ log.Fatal(err)
+ }
+ if *once {
+ break
+ }
+ log.Printf("Going to sleep for %v", *interval)
+ time.Sleep(*interval)
+ }
+}
+
+func loopOnce() error {
+ sent, err := readSent(*state)
if err != nil {
- log.Fatal(err)
+ return err
}
- fetched, err := parse(body)
+ for _, url := range flag.Args() {
+ sent, err = doOneURL(url, sent)
+ if err != nil {
+ log.Print(err)
+ continue
+ }
+ }
+ // TODO: trim sent file here?
+ return writeSent(sent, *state)
+}
+
+func doOneURL(url string, sent []flat) ([]flat, error) {
+ body, err := fetch(url)
if err != nil {
- log.Fatal(err)
+ return sent, err
}
- sent, err := readSent("sent/sent.json")
+ fetched, err := parse(body)
if err != nil {
- log.Fatal(err)
+ return sent, err
}
newFlats := removeAlreadySent(fetched, sent)
m := messenger{
- Token: os.Getenv("FLATBOT_TELEGRAM_BOT_API_TOKEN"),
- ChatID: os.Getenv("FLATBOT_TELEGRAM_CHANNEL_ID"),
+ Token: *apiToken,
+ ChatID: *chatID,
}
for _, f := range newFlats {
- if false {
+ if !*dryRun {
err = m.Send(f)
if err != nil {
- // TODO: what to do with it?
log.Print(err)
+ continue
}
}
+ log.Printf("Should have been sent to chat: %v, %v",
+ f.Price, f.URL())
sent = append(sent, f)
}
- // Remove flats from sent that are no longer in the search response to
- // prevent indefinite grow of sent file.
- sent = removeDelisted(sent, fetched)
- writeSent(sent, "/tmp/sent.json")
+ return sent, nil
}
func fetch(url string) ([]byte, error) {
diff --git a/sent.go b/sent.go
index 0c72e6b..f21b791 100644
--- a/sent.go
+++ b/sent.go
@@ -54,6 +54,9 @@ func removeDelisted(sent []flat, allFlats []flat) []flat {
}
func writeSent(sent []flat, filename string) error {
+ if !slices.IsSortedFunc(sent, compareID) {
+ slices.SortFunc(sent, compareID)
+ }
jsonData, err := json.Marshal(sent)
if err != nil {
return err