krz/devianter

A DeviantArt guest API library for Go.

clone: git clone https://gitbay.org/krz/devianter.git

v0.2.5: util.go · raw

  1package devianter
  2
  3import (
  4	"encoding/json"
  5	"errors"
  6	"io"
  7	"net/http"
  8	"strings"
  9)
 10
 11// функция для высера ошибки в stderr
 12func try(txt error) {
 13	if txt != nil {
 14		println(txt.Error())
 15	}
 16}
 17
 18// сокращение для вызова щенка и парсинга жсона
 19func ujson(data string, output any) {
 20	input, err := puppy(data)
 21	try(err)
 22	try(json.Unmarshal([]byte(input), output))
 23}
 24
 25/* REQUEST SECTION */
 26// структура для ответа сервера
 27type reqrt struct {
 28	Body    string
 29	Status  int
 30	Cookies []*http.Cookie
 31	Headers http.Header
 32}
 33
 34// функция для совершения запроса
 35var UserAgent string
 36
 37func request(uri string, other ...string) reqrt {
 38	var r reqrt
 39
 40	// создаём новый запрос
 41	cli := &http.Client{}
 42	req, e := http.NewRequest("GET", uri, nil)
 43	try(e)
 44
 45	req.Header.Set("User-Agent", "Mozilla/5.0 (X11; Linux x86_64; rv:123.0) Gecko/20100101 Firefox/123.0.0")
 46
 47	// куки и UA-шник
 48	if UserAgent != "" {
 49		req.Header.Set("User-Agent", UserAgent)
 50	}
 51	if len(other) != 0 {
 52		req.Header.Set("Cookie", other[0])
 53	}
 54
 55	resp, e := cli.Do(req)
 56	try(e)
 57	defer resp.Body.Close()
 58
 59	body, e := io.ReadAll(resp.Body)
 60	try(e)
 61
 62	// заполняем структуру
 63	r.Body = string(body)
 64	r.Cookies = resp.Cookies()
 65	r.Headers = resp.Header
 66	r.Status = resp.StatusCode
 67
 68	return r
 69}
 70
 71/* PUPPY aka DeviantArt API */
 72// получение или обновление токена
 73var cookie string
 74var token string
 75
 76func UpdateCSRF() error {
 77	if cookie == "" {
 78		req := request("https://www.deviantart.com/_puppy")
 79
 80		for _, content := range req.Cookies {
 81			cookie = content.Raw
 82		}
 83	}
 84
 85	req := request("https://www.deviantart.com", cookie)
 86	if req.Status != 200 {
 87		return errors.New(req.Body)
 88	}
 89	token = req.Body[strings.Index(req.Body, "window.__CSRF_TOKEN__ = '")+25 : strings.Index(req.Body, "window.__XHR_LOCAL__")-3]
 90
 91	return nil
 92}
 93
 94func puppy(data string) (string, error) {
 95	var url strings.Builder
 96	url.WriteString("https://www.deviantart.com/_puppy/")
 97	url.WriteString(data)
 98	url.WriteString("&csrf_token=")
 99	url.WriteString(token)
100	url.WriteString("&da_minor_version=20230710")
101
102	body := request(url.String(), cookie)
103
104	// если код ответа не 200, возвращается ошибка
105	if body.Status != 200 {
106		return "", errors.New(body.Body)
107	}
108
109	return body.Body, nil
110}