-
Notifications
You must be signed in to change notification settings - Fork 183
/
index.js
190 lines (152 loc) · 5.39 KB
/
index.js
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
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
#!/usr/bin/env node
const cookies = process.env.COOKIE.split('\n').map(s => s.trim())
const games = process.env.GAMES.split('\n').map(s => s.trim())
const discordWebhook = process.env.DISCORD_WEBHOOK
const discordUser = process.env.DISCORD_USER
const msgDelimiter = ':'
const messages = []
const endpoints = {
zzz: 'https://sg-act-nap-api.hoyolab.com/event/luna/zzz/os/sign?act_id=e202406031448091',
gi: 'https://sg-hk4e-api.hoyolab.com/event/sol/sign?act_id=e202102251931481',
hsr: 'https://sg-public-api.hoyolab.com/event/luna/os/sign?act_id=e202303301540311',
hi3: 'https://sg-public-api.hoyolab.com/event/mani/sign?act_id=e202110291205111',
tot: 'https://sg-public-api.hoyolab.com/event/luna/os/sign?act_id=e202202281857121',
}
let hasErrors = false
let latestGames = []
async function run(cookie, games) {
if (!games) {
games = latestGames
} else {
games = games.split(' ')
latestGames = games
}
for (let game of games) {
game = game.toLowerCase()
log('debug', `\n----- CHECKING IN FOR ${game} -----`)
if (!(game in endpoints)) {
log('error', `Game ${game} is invalid. Available games are: zzz, gi, hsr, hi3, and tot`)
continue
}
// begin check in
const endpoint = endpoints[game]
const url = new URL(endpoint)
const actId = url.searchParams.get('act_id')
url.searchParams.set('lang', 'en-us')
const body = JSON.stringify({
lang: 'en-us',
act_id: actId
})
// headers from valid browser request
const headers = new Headers()
headers.set('accept', 'application/json, text/plain, */*')
headers.set('accept-encoding', 'gzip, deflate, br, zstd')
headers.set('accept-language', 'en-US,en;q=0.6')
headers.set('connection', 'keep-alive')
headers.set('origin', 'https://act.hoyolab.com')
headers.set('referrer', 'https://act.hoyolab.com')
headers.set('content-type', 'application.json;charset=UTF-8')
headers.set('cookie', cookie)
headers.set('sec-ch-ua', '"Not/A)Brand";v="8", "Chromium";v="126", "Brave";v="126"')
headers.set('sec-ch-ua-mobile', '?0')
headers.set('sec-ch-ua-platform', '"Linux"')
headers.set('sec-fetch-dest', 'empty')
headers.set('sec-fech-mode', 'cors')
headers.set('sec-fetch-site', 'same-site')
headers.set('sec-gpc', '1')
headers.set("x-rpc-signgame", game)
headers.set('user-agent', 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36')
const res = await fetch(url, { method: 'POST', headers, body })
const json = await res.json()
const code = String(json.retcode)
const successCodes = {
'0': 'Successfully checked in!',
'-5003': 'Already checked in for today',
}
// success responses
if (code in successCodes) {
log('info', game, `${successCodes[code]}`)
continue
}
// error responses
const errorCodes = {
'-100': 'Error not logged in. Your cookie is invalid, try setting up again',
'-10002': 'Error not found. You haven\'t played this game'
}
log('debug', game, `Headers`, Object.fromEntries(res.headers))
log('debug', game, `Response`, json)
if (code in errorCodes) {
log('error', game, `${errorCodes[code]}`)
continue
}
log('error', game, `Error undocumented, report to Issues page if this persists`)
}
}
// custom log function to store messages
function log(type, ...data) {
// log to real console
console[type](...data)
// ignore debug and toggle hasErrors
switch (type) {
case 'debug': return
case 'error': hasErrors = true
}
// check if it's a game specific message, and set it as uppercase for clarity, and add delimiter
if(data[0] in endpoints) {
data[0] = data[0].toUpperCase() + msgDelimiter
}
// serialize data and add to messages
const string = data
.map(value => {
if (typeof value === 'object') {
return JSON.stringify(value, null, 2).replace(/^"|"$/, '')
}
return value
})
.join(' ')
messages.push({ type, string })
}
// must be function to return early
async function discordWebhookSend() {
log('debug', '\n----- DISCORD WEBHOOK -----')
if (!discordWebhook.toLowerCase().trim().startsWith('https://discord.com/api/webhooks/')) {
log('error', 'DISCORD_WEBHOOK is not a Discord webhook URL. Must start with `https://discord.com/api/webhooks/`')
return
}
let discordMsg = ""
if (discordUser) {
discordMsg = `<@${discordUser}>\n`
}
discordMsg += messages.map(msg => `(${msg.type.toUpperCase()}) ${msg.string}`).join('\n')
const res = await fetch(discordWebhook, {
method: 'POST',
headers: {
'content-type': 'application/json'
},
body: JSON.stringify({
content: discordMsg
})
})
if (res.status === 204) {
log('info', 'Successfully sent message to Discord webhook!')
return
}
log('error', 'Error sending message to Discord webhook, please check URL and permissions')
}
if (!cookies || !cookies.length) {
throw new Error('COOKIE environment variable not set!')
}
if (!games || !games.length) {
throw new Error('GAMES environment variable not set!')
}
for (const index in cookies) {
log('info', `-- CHECKING IN FOR ACCOUNT ${Number(index) + 1} --`)
await run(cookies[index], games[index])
}
if (discordWebhook && URL.canParse(discordWebhook)) {
await discordWebhookSend()
}
if (hasErrors) {
console.log('')
throw new Error('Error(s) occured.')
}