From 019ff5bdc5b7011fc5908216cccec0019319b2ad Mon Sep 17 00:00:00 2001 From: nefrace Date: Thu, 13 Apr 2023 11:13:24 +0300 Subject: [PATCH] Triggers, offtop --- filters.go | 7 +++- handlers.go | 95 +++++++++++++++++++++++++++++++++++++++++++++++++++-- states.go | 8 ++++- types.go | 16 +++++++++ 4 files changed, 122 insertions(+), 4 deletions(-) diff --git a/filters.go b/filters.go index da88a5d..34bb820 100644 --- a/filters.go +++ b/filters.go @@ -22,7 +22,12 @@ func karmaTriggers(u *neco.Update) bool { return false } -var docRegex = regexp.MustCompile(`док(ументац[а-я]+|[а-я])? ((п)?о )?(?P@?[\w\d\s]{1,32})`) +func offtopTrigger(u *neco.Update) bool { + text := strings.ToLower(u.Text()) + return strings.Contains(text, "оффтоп") +} + +var docRegex = regexp.MustCompile(`(?i)док(ументац[а-я]+|[а-я])? ((п)?о )?(?P@?[\w\d\s]{1,32})`) func docRequest(u *neco.Update) bool { text := u.Text() diff --git a/handlers.go b/handlers.go index c6ae8a1..431c103 100644 --- a/handlers.go +++ b/handlers.go @@ -1,7 +1,11 @@ package main import ( + "encoding/json" "fmt" + "math/rand" + "net/http" + "net/url" "time" "git.nefrace.ru/nefrace/nechotron" @@ -9,9 +13,68 @@ import ( "github.com/NicoNex/echotron/v3" ) +var docApiURL = "https://docs.godotengine.org/_/api/v2/search/?q=%s&project=godot-ru&version=stable&language=ru" +var docURL = "https://docs.godotengine.org/ru/stable/search.html?q=%s" + +type DocResponse struct { + Count uint `json:"count"` + Next string `json:"next"` + Previous string `json:"previous"` + Results []DocResult `json:"results"` +} + +type DocResult struct { + Title string `json:"title"` + Domain string `json:"domain"` + Path string `json:"path"` + Highlights DocHighlights `json:"highlights"` +} + +type DocHighlights struct { + Title []string `json:"title"` +} + func handleDocRequest(u *nechotron.Update) error { topic := u.Ctx.Value(nechotron.FilteredValue("docTopic")).(string) - return nil + topic_escaped := nechotron.EscapeMd2(topic) + + kb := nechotron.NewInlineKeyboard(). + Row(nechotron.InButtonURL("Поищу сам", fmt.Sprintf(docURL, url.QueryEscape(topic)))). + Row(nechotron.InButtonCallback("Спасибо, не надо", "delete")) + opts := nechotron.NewOptions(). + MarkdownV2(). + ReplyTo(u.MessageID()). + ReplyMarkup(kb.Markup()). + MessageOptions() + + req, err := url.ParseRequestURI(fmt.Sprintf(docApiURL, url.QueryEscape(topic))) + if err != nil { + return err + } + result, err := http.Get(req.String()) + if err != nil { + u.AnswerText(fmt.Sprintf("Извините, по запросу *%s* ничего не найдено.", topic_escaped), opts) + return err + } + defer result.Body.Close() + var response DocResponse + err = json.NewDecoder(result.Body).Decode(&response) + if err != nil { + u.AnswerText(fmt.Sprintf("Извините, по запросу *%s* ничего не найдено.", topic_escaped), opts) + return err + } + textResults := "" + for i, r := range response.Results { + if i > 9 { + break + } + text := nechotron.EscapeMd2(r.Title) + link, _ := url.JoinPath(r.Domain, r.Path) + textResults += fmt.Sprintf("%d\\. [%s](%s)\n", i+1, text, link) + } + text := fmt.Sprintf("Вот что я нашла по запросу *%s*: \n\n%s", topic_escaped, textResults) + _, err = u.AnswerText(text, opts) + return err } func handleKarma(u *nechotron.Update) error { @@ -83,5 +146,33 @@ func handleKarma(u *nechotron.Update) error { _, err = u.AnswerMarkdown( fmt.Sprintf("*%s \\(%d\\)* только что %s карму *%s \\(%d\\)*", mentionFrom, totalFromKarma, changeText, mentionTo, totalToKarma)) return err - +} + +func handleOfftop(u *nechotron.Update) error { + text := "Держите [ссылку на оффтоп](%s)\\!" + offtopLink := "https://t.me/Godot_Engine_Offtop" + offtopAnswers, err := tongo.NewStore[TriggerText](db).GetMany(u.Ctx, tongo.E("trigger", "offtop")) + if err == nil { + if len(offtopAnswers) > 0 { + text = offtopAnswers[rand.Intn(len(offtopAnswers)-1)].Text + } + } + offtopUrl, err := tongo.NewStore[Config](db).GetOne(u.Ctx, tongo.E("name", "offtop_url")) + if err == nil { + offtopLink = offtopUrl.Value.(string) + } + text = fmt.Sprintf(text, offtopLink) + kb := nechotron.NewInlineKeyboard().Row(nechotron.InButtonCallback("Спасибо, не надо", "delete")).Markup() + opts := nechotron.NewOptions(). + MarkdownV2(). + ReplyTo(u.MessageID()). + ReplyMarkup(kb). + MessageOptions() + u.AnswerText(text, opts) + return nil +} + +func handleDeleteCallback(u *nechotron.Update) error { + u.DeleteMessage() + return nil } diff --git a/states.go b/states.go index 84bd8ca..b524299 100644 --- a/states.go +++ b/states.go @@ -6,6 +6,10 @@ import ( var MainState = neco.State{ Fn: func(u *neco.Update) error { + callbackDispatcher := neco.NewDispatcher(). + HandleCallback("delete", handleDeleteCallback) + adminOnly := neco.NewDispatcher(). + HandleFilter(neco.IsUserAdmin, callbackDispatcher.Run) mainCommands := neco.NewDispatcher(). HandleCommand(commandMe, handleMe). HandleCommand(commandHelp, handleHelp). @@ -17,6 +21,8 @@ var MainState = neco.State{ HandleFilter(neco.IsReply, replyDispatcher.Run) docs := neco.NewDispatcher(). HandleFilter(docRequest, handleDocRequest) - return neco.ChainRun(u, mainCommands, replies, docs) + triggers := neco.NewDispatcher(). + HandleFilter(offtopTrigger, handleOfftop) + return neco.ChainRun(u, mainCommands, replies, docs, adminOnly, triggers) }, } diff --git a/types.go b/types.go index 59164d8..0ce3d60 100644 --- a/types.go +++ b/types.go @@ -81,3 +81,19 @@ type Warn struct { } func (Warn) Coll() string { return "warns" } + +type TriggerText struct { + tongo.Item `bson:",inline"` + Trigger string + Text string +} + +func (TriggerText) Coll() string { return "triggers" } + +type Config struct { + tongo.Item `bson:",inline"` + Name string + Value interface{} +} + +func (Config) Coll() string { return "config" }