-
Notifications
You must be signed in to change notification settings - Fork 27
/
shindanmaker.go
123 lines (115 loc) · 3.6 KB
/
shindanmaker.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
// Package shindanmaker 基于 https://shindanmaker.com 的 API
package shindanmaker
import (
"bytes"
"errors"
"fmt"
"mime/multipart"
"net/http"
"strings"
"time"
xpath "github.com/antchfx/htmlquery"
)
var (
token = ""
cookie = ""
)
// Shindanmaker 基于 https://shindanmaker.com 的 API
// id 是的不同页面的 url 里的数字, 例如 https://shindanmaker.com/a/162207 里的 162207
// name 是要被测定的人的名字, 影响测定结果
func Shindanmaker(id int64, name string) (string, error) {
url := fmt.Sprintf("https://shindanmaker.com/%d", id)
// seed 使每一天的结果都不同
now := time.Now()
seed := fmt.Sprintf("%d%d%d", now.Year(), now.Month(), now.Day())
name += seed
// 刷新 token 和 cookie or 获取shindan_token
shindantoken, err := refresh(url)
if err != nil {
return "", err
}
// 组装参数
client := &http.Client{}
payload := &bytes.Buffer{}
writer := multipart.NewWriter(payload)
_ = writer.WriteField("_token", token)
_ = writer.WriteField("shindanName", name)
_ = writer.WriteField("hiddenName", "名無しのR")
_ = writer.WriteField("type", "name")
_ = writer.WriteField("shindan_token", shindantoken)
_ = writer.Close()
// 发送请求
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Cookie", cookie)
req.Header.Set("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36")
req.Header.Set("Content-Type", writer.FormDataContentType())
resp, err := client.Do(req)
if err != nil {
return "", err
}
defer resp.Body.Close()
// 解析XPATH
doc, err := xpath.Parse(resp.Body)
if err != nil {
return "", err
}
// 取出每个返回的结果
list := xpath.Find(doc, `//*[@id="shindanResult"]`)
if len(list) == 0 {
token = ""
cookie = ""
return "", errors.New("无法查找到结果, 请稍后再试")
}
var output = []string{}
for child := list[0].FirstChild; child != nil; child = child.NextSibling {
text := xpath.InnerText(child)
switch {
case text != "":
output = append(output, text)
case child.Data == "img":
img := child.Attr[1].Val
if strings.Contains(img, "http") {
output = append(output, "[CQ:image,file="+img[strings.Index(img, ",")+1:]+"]")
} else {
output = append(output, "[CQ:image,file=base64://"+img[strings.Index(img, ",")+1:]+"]")
}
default:
output = append(output, "\n")
}
}
return strings.ReplaceAll(strings.Join(output, ""), seed, ""), nil
}
// refresh 刷新 cookie 和 token
func refresh(url string) (string, error) {
client := &http.Client{}
req, _ := http.NewRequest("GET", url, nil)
req.Header.Set("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.110 Safari/537.36")
resp, err := client.Do(req)
if err != nil {
return "", err
}
// 获取 cookie
doc, err := xpath.Parse(resp.Body)
if err != nil {
return "", err
}
if token == "" || cookie == "" {
if temp := resp.Header.Values("Set-Cookie"); len(temp) == 0 {
return "", errors.New("刷新 cookie 时发生错误")
} else if cookie = temp[len(temp)-1]; !strings.Contains(cookie, "_session") {
return "", errors.New("刷新 cookie 时发生错误")
}
// 获取 token
defer resp.Body.Close()
list := xpath.Find(doc, `//*[@id="shindanForm"]/input`)
if len(list) == 0 {
return "", errors.New("刷新 token 时发生错误")
}
token = list[0].Attr[2].Val
}
shindanTokenList := xpath.Find(doc, `//*[@id="shindan_token"]`)
if len(shindanTokenList) == 0 {
return "", errors.New("获取 shindan_token 时发生错误")
}
return shindanTokenList[0].Attr[3].Val, nil
}