go-dette/handle-docs.go

153 lines
4.6 KiB
Go
Raw Normal View History

2023-06-13 02:22:44 +03:00
package main
import (
"encoding/json"
"fmt"
"log"
"net/http"
"net/url"
"strings"
2023-09-14 01:46:42 +03:00
"time"
2023-06-13 02:22:44 +03:00
"git.nefrace.ru/nefrace/nechotron"
2023-06-15 17:03:57 +03:00
"github.com/NicoNex/echotron/v3"
2023-06-13 02:22:44 +03:00
)
var docApiURL = "https://docs.godotengine.org/_/api/v2/search/?q=%s&project=godot&version=%s&language=en"
2023-06-15 17:03:57 +03:00
var docURL = "https://docs.godotengine.org/en/%s/search.html?q=%s"
2023-09-14 01:46:42 +03:00
var lastDocSearch = time.Now()
2023-06-13 02:22:44 +03:00
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"`
}
2023-09-14 01:46:42 +03:00
func getAndDecode[T any](u string) (*T, error) {
req, err := url.ParseRequestURI(u)
2023-06-13 02:22:44 +03:00
if err != nil {
2023-09-14 01:46:42 +03:00
log.Println("Can't parse url: ", err)
return nil, err
2023-06-13 02:22:44 +03:00
}
result, err := http.Get(req.String())
if err != nil {
2023-09-14 01:46:42 +03:00
log.Println("Can't get http: ", err)
return nil, err
2023-06-13 02:22:44 +03:00
}
defer result.Body.Close()
2023-09-14 01:46:42 +03:00
var response T
2023-06-13 02:22:44 +03:00
err = json.NewDecoder(result.Body).Decode(&response)
if err != nil {
2023-09-14 01:46:42 +03:00
return nil, err
}
return &response, nil
}
func getDocs(topic string, version string) (string, string, error) {
since := time.Since(lastDocSearch)
if since < 20*time.Second {
return "Извините, запросы происходят слишком часто\\.", "", nil
}
lastDocSearch = time.Now()
topic_escaped := nechotron.EscapeMd2(topic)
not_found := fmt.Sprintf("Извините, по запросу *%s* ничего не найдено\\.", topic_escaped)
exactUrl := fmt.Sprintf(docApiURL, url.QueryEscape(topic), version)
looselyUrl := fmt.Sprintf(docApiURL, url.QueryEscape(topic+"*"), version)
workedTopic := topic
response, err := getAndDecode[DocResponse](exactUrl)
if err != nil || len(response.Results) == 0 {
workedTopic = topic + "*"
response, err = getAndDecode[DocResponse](looselyUrl)
if err != nil || len(response.Results) == 0 {
return not_found, "", nil
}
2023-06-13 02:22:44 +03:00
}
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* \\(для версии `%s`\\): \n\n%s", topic_escaped, version, textResults)
2023-09-14 01:46:42 +03:00
return text, workedTopic, nil
2023-06-13 02:22:44 +03:00
}
2023-09-14 01:46:42 +03:00
var doc_variants []string = []string{"4.1", "3.5"}
2023-06-15 17:03:57 +03:00
2023-06-13 02:22:44 +03:00
func handleDocRequest(u *nechotron.Update) error {
topic := u.Ctx.Value(nechotron.FilteredValue("docTopic")).(string)
2023-06-15 17:03:57 +03:00
currentVersion := doc_variants[0]
versionButtons := []echotron.InlineKeyboardButton{}
for _, variant := range doc_variants {
if variant == currentVersion {
continue
}
versionButtons = append(versionButtons, nechotron.InButtonCallback("Для "+variant, fmt.Sprintf("docs:%s:%s", variant, topic)))
}
2023-09-14 01:46:42 +03:00
text, workedTopic, docerr := getDocs(topic, doc_variants[0])
if docerr != nil {
log.Println("Can't get docs: ", docerr)
}
2023-06-13 02:22:44 +03:00
kb := nechotron.NewInlineKeyboard().
2023-06-15 17:03:57 +03:00
Row(versionButtons...).
2023-09-14 01:46:42 +03:00
Row(nechotron.InButtonURL("Поискать самостоятельно", fmt.Sprintf(docURL, currentVersion, url.QueryEscape(workedTopic)))).
2023-06-13 02:22:44 +03:00
Row(nechotron.InButtonCallback("Спасибо, не надо", "delete"))
opts := nechotron.NewOptions().
MarkdownV2().
ReplyTo(u.MessageID()).
ReplyMarkup(kb.Markup()).
MessageOptions()
_, err := u.AnswerText(text, opts)
return err
}
2023-06-15 17:03:57 +03:00
func handleDocCallback(u *nechotron.Update) error {
text := strings.TrimPrefix(u.Callback(), "docs:")
items := strings.Split(text, ":")
version := items[0]
topic := items[1]
versionButtons := []echotron.InlineKeyboardButton{}
for _, variant := range doc_variants {
if variant == version {
continue
}
versionButtons = append(versionButtons, nechotron.InButtonCallback("Для "+variant, fmt.Sprintf("docs:%s:%s", variant, topic)))
}
2023-09-14 01:46:42 +03:00
text, workedTopic, docerr := getDocs(topic, version)
if docerr != nil {
log.Println("Can't get docs: ", docerr)
}
2023-06-13 02:22:44 +03:00
kb := nechotron.NewInlineKeyboard().
2023-06-15 17:03:57 +03:00
Row(versionButtons...).
2023-09-14 01:46:42 +03:00
Row(nechotron.InButtonURL("Поискать самостоятельно", fmt.Sprintf(docURL, version, url.QueryEscape(workedTopic)))).
2023-06-13 02:22:44 +03:00
Row(nechotron.InButtonCallback("Спасибо, не надо", "delete"))
opts := nechotron.NewOptions().
MarkdownV2().
ReplyMarkup(kb.Markup()).
MessageTextOptions()
_, err := u.EditText(text, opts)
2023-09-14 01:46:42 +03:00
if err != nil {
log.Println(err)
log.Println(text)
}
2023-06-13 02:22:44 +03:00
return err
}