Files
aleesa-webapp-go/internal/monkeyuser/monkeyuser.go
eleksir f2fc168abe Replace prazdnikisegodnyaru with celebratoday, small underhood fixes
- Replace prazdnikisegodnyaru with celebratoday as first is banned in Russia
- Update .golangci.yml rule set
- Megatons of fixes for linter
- Update README.md
2026-02-10 20:05:13 +03:00

130 lines
2.9 KiB
Go

// Package monkeyuser implements client for service www.monkeyusers.com.
package monkeyuser
import (
"aleesa-webapp-go/internal/config"
"bytes"
"context"
"encoding/json"
"errors"
"fmt"
"math/rand/v2"
"strings"
"github.com/carlmjohnson/requests"
"golang.org/x/net/html"
)
type (
// MonkeyUsers описывает структуру json-массива ответа www.monkeyusers.com.
MonkeyUsers []struct {
Title string `json:"title"`
URL string `json:"url"`
}
)
// APIClient клиент сервиса monkeyuser.com.
func APIClient(cfg *config.MyConfig) (string, error) {
var (
ctx = context.Background()
respBody bytes.Buffer
respBytes []byte
body string
userAgent = cfg.UserAgents[rand.IntN(len(cfg.UserAgents))]
baseURL = "https://www.monkeyuser.com"
indexURL = baseURL + "/index.json"
)
err := requests.
URL(indexURL).
UserAgent(userAgent).
ToBytesBuffer(&respBody).
Fetch(ctx)
if err != nil {
return "", fmt.Errorf("unable to GET %s: %w", indexURL, err)
}
// На всякий случай валидируем utf-8.
respBytes = bytes.ToValidUTF8(respBody.Bytes(), []byte{0xef, 0xbf, 0xbd})
var monkeyusers MonkeyUsers
if err := json.Unmarshal(respBytes, &monkeyusers); err != nil {
err = fmt.Errorf("unable to to parse response from %s: %w", indexURL, err)
return "", err
}
amountOfUsers := len(monkeyusers)
if amountOfUsers == 0 {
err = fmt.Errorf("no links found in %s", indexURL)
return "", err
}
ofChoice := rand.IntN(amountOfUsers)
pageURL := fmt.Sprintf("%s%s", baseURL, monkeyusers[ofChoice].URL)
// Делаем второй запрос к серверу.
err = requests.
URL(pageURL).
UserAgent(userAgent).
ToString(&body).
Fetch(ctx)
if err != nil {
return "", fmt.Errorf("unable to GET %s: %w", pageURL, err)
}
// Парсим body ответа от сервера.
doc, err := html.Parse(strings.NewReader(body))
if err != nil {
return "", err
}
var (
hyperlink string
link func(*html.Node)
)
link = func(n *html.Node) {
if n.Type == html.ElementNode && n.Data == "img" {
for _, a_href := range n.Attr { //nolint: revive
// Если у нас class == "lazyload small-image", то после него ключ data-src должен содержать
// искомый relative url.
if a_href.Key == "class" && a_href.Val == "logo" {
continue
}
var v = a_href.Val
if a_href.Key == "src" && v != "/images/logo.png" {
hyperlink = v
break
}
}
}
// traverses the HTML of the webpage from the first child node.
for c := n.FirstChild; c != nil; c = c.NextSibling {
link(c)
}
}
link(doc)
// Возвращаем ссылку на картинку buni comic.
if hyperlink != "" {
return fmt.Sprintf("%s%s", baseURL, hyperlink), nil
}
err = errors.New("no links found on monkeyusers.com")
return "", err
}
/* vim: set ft=go noet ai ts=4 sw=4 sts=4: */