summaryrefslogtreecommitdiff
path: root/cmd/bot/main.go
diff options
context:
space:
mode:
Diffstat (limited to 'cmd/bot/main.go')
-rw-r--r--cmd/bot/main.go156
1 files changed, 156 insertions, 0 deletions
diff --git a/cmd/bot/main.go b/cmd/bot/main.go
new file mode 100644
index 0000000..99e1424
--- /dev/null
+++ b/cmd/bot/main.go
@@ -0,0 +1,156 @@
+package main
+
+import (
+ "fmt"
+ "log"
+ "os"
+ "os/exec"
+ "strings"
+ "time"
+
+ "go.etcd.io/bbolt"
+ tele "gopkg.in/telebot.v3"
+ "gopkg.in/telebot.v3/middleware"
+
+ "go.neonxp.dev/bot/pkg/bash"
+ "go.neonxp.dev/bot/pkg/geo"
+ "go.neonxp.dev/bot/pkg/weather"
+)
+
+var (
+ rplGeoSearch = &tele.ReplyMarkup{}
+ btnShops = rplGeoSearch.Data("Магазины и супермаркеты", "shops")
+ btnFarma = rplGeoSearch.Data("Аптеки", "farma")
+)
+
+func main() {
+ pref := tele.Settings{
+ Token: os.Getenv("TOKEN"),
+ Poller: &tele.LongPoller{Timeout: 10 * time.Second},
+ }
+ rplGeoSearch.Inline(rplGeoSearch.Row(btnShops, btnFarma))
+ db, err := bbolt.Open("db/my.db", 0o600, nil)
+ if err != nil {
+ log.Fatal(err)
+ }
+ defer db.Close()
+
+ b, err := tele.NewBot(pref)
+ if err != nil {
+ log.Fatal(err)
+ return
+ }
+ b.Use(middleware.AutoRespond())
+ b.Use(func(next tele.HandlerFunc) tele.HandlerFunc {
+ return tele.HandlerFunc(func(ctx tele.Context) error {
+ if ctx.Message() != nil {
+ log.Printf("F:%s L:%s N:%s ID:%d: %s", ctx.Sender().FirstName, ctx.Sender().LastName, ctx.Sender().Username, ctx.Sender().ID, ctx.Message().Text)
+ }
+ return next(ctx)
+ })
+ })
+
+ b.Handle("/help", func(ctx tele.Context) error {
+ return ctx.Send(helpText, tele.ModeMarkdown)
+ })
+
+ b.Handle("/weather", func(ctx tele.Context) error {
+ city := ctx.Message().Payload
+ if city == "" {
+ city = "Казань"
+ }
+ weather, err := weather.Get(city)
+ if err != nil {
+ return err
+ }
+ return ctx.Send(weather)
+ })
+ b.Handle("/weatherfull", func(ctx tele.Context) error {
+ city := ctx.Message().Payload
+ if city == "" {
+ city = "Казань"
+ }
+ return ctx.Send(&tele.Photo{
+ File: tele.FromURL(fmt.Sprintf("https://wttr.in/%s.png?2p&lang=ru", city)),
+ })
+ })
+ b.Handle("/bash", func(ctx tele.Context) error {
+ q, err := bash.Get()
+ if err != nil {
+ return err
+ }
+ return ctx.Send(fmt.Sprintf("[#%d](https://xn--80abh7bk0c.xn--p1ai/quote/%d) • _%s_\n\n%s", q.Num, q.Num, q.Date, q.Body), tele.ModeMarkdown)
+ })
+ b.Handle("/info", func(ctx tele.Context) error {
+ cmd := exec.Command("neofetch", "--stdout")
+ stdout, err := cmd.Output()
+ if err != nil {
+ return err
+ }
+
+ return ctx.Send(string(stdout))
+ })
+ b.Handle(tele.OnLocation, func(ctx tele.Context) error {
+ return ctx.Send("Выберите категорию:", &tele.SendOptions{
+ ReplyTo: ctx.Message(),
+ ReplyMarkup: rplGeoSearch,
+ })
+ })
+ b.Handle(&btnFarma, func(ctx tele.Context) error {
+ return geoSearch(ctx, "farma")
+ })
+ b.Handle(&btnShops, func(ctx tele.Context) error {
+ return geoSearch(ctx, "shops")
+ })
+
+ b.Handle(tele.OnQuery, func(ctx tele.Context) error {
+ city := ctx.Data()
+ if len(city) < 3 {
+ return ctx.Answer(&tele.QueryResponse{})
+ }
+ weather, err := weather.Get(city)
+ if err != nil {
+ return err
+ }
+ return ctx.Answer(&tele.QueryResponse{
+ Results: tele.Results{
+ &tele.PhotoResult{
+ ResultBase: tele.ResultBase{
+ ID: city,
+ },
+ Title: weather,
+ URL: fmt.Sprintf("https://wttr.in/%s.png?2p&lang=ru", city),
+ ThumbURL: "https://neonxp.dev/img/weather.png",
+ },
+ },
+ CacheTime: 1800,
+ })
+ })
+
+ b.Handle(tele.OnInlineResult, func(ctx tele.Context) error {
+ city := ctx.InlineResult().ResultID
+ return ctx.Send(&tele.Photo{
+ File: tele.FromURL(fmt.Sprintf("https://wttr.in/%s.png?2p&lang=ru", city)),
+ })
+ })
+
+ b.Start()
+}
+
+func geoSearch(ctx tele.Context, search string) error {
+ msg := ctx.Message()
+ if msg.ReplyTo == nil || msg.ReplyTo.Location == nil {
+ return fmt.Errorf("no location: %v", msg)
+ }
+ points, err := geo.Search(float64(msg.ReplyTo.Location.Lat), float64(msg.ReplyTo.Location.Lng), search)
+ if err != nil {
+ return err
+ }
+ results := make([]string, 0, len(points))
+ for i, p := range points {
+ results = append(results, fmt.Sprintf(
+ `%d. <a href="https://openstreetmap.ru/#mmap=19/%f/%f">%s</a>`, i+1, p.Lat, p.Lon, p.Name,
+ ))
+ }
+ return ctx.Send("<b>Результаты в радиусе километра:</b>\n\n"+strings.Join(results, "\n"), tele.ModeHTML)
+}