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}