krz/devianter

A DeviantArt guest API library for Go.

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

v0.2.0: util.go · raw

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