-
Notifications
You must be signed in to change notification settings - Fork 3
Expand file tree
/
Copy pathCode.gs
More file actions
191 lines (165 loc) · 5.97 KB
/
Code.gs
File metadata and controls
191 lines (165 loc) · 5.97 KB
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
191
const scriptProperties = PropertiesService.getScriptProperties();
/** REPLACE PARAMETERS WITH THE ONES YOU GOT **/
const profiles = {
main: {
'genshin': {
'url': 'https://sg-hk4e-api.hoyoverse.com/common/apicdkey/api/webExchangeCdkey?lang=en&game_biz=hk4e_global&uid=715052227®ion=os_euro'
},
'hsr': {
'url': 'https://sg-hkrpg-api.hoyoverse.com/common/apicdkey/api/webExchangeCdkeyRisk',
'request' : {"game_biz":"hkrpg_global", "uid":"701683615", "region":"prod_official_eur"}
},
'zzz': {
'url': 'https://public-operation-nap.hoyoverse.com/common/apicdkey/api/webExchangeCdkey?lang=en&game_biz=nap_global&uid=1500028068®ion=prod_gf_eu'
}
}
};
const discord_notify = true
/** REMEMBER TO SET THOSE AND COOKIE IN PROJECT SETTINGS > SCRIPT PROPERTIES **/
const myDiscordID = scriptProperties.getProperty('DISCORD_ID')
const discordWebhook = scriptProperties.getProperty('WEBHOOK_URL')
let keepCookieAlive = true
const verbose = false
let first_run = false
let error = false
const cdkeysbygame = fetchJson();
const last_execution = scriptProperties.getProperty('last_execution');
if (last_execution <= 0) {
first_run = true;
}
function fetchJson() {
const jsonUrl = 'https://db.hashblen.com/codes'; // Replace with your JSON endpoint URL
const response = UrlFetchApp.fetch(jsonUrl);
const jsonData = JSON.parse(response.getContentText());
return jsonData;
}
const ALREADY_IN_USE = -2017
const ALREADY_IN_USE_2 = -2018
const EXPIRED = -2001
const INVALID = -2003
const SUCCESSFUL = 0
function sendGetRequestsWithCdkeys(urlDict, profile) {
let results = [];
for (const game in urlDict) {
const fullUrl = urlDict[game].url;
if(!fullUrl) {
continue
}
const cdkeys = cdkeysbygame[game];
cdkeys.forEach(function(cdkeydict) {
if(!first_run && cdkeydict.added_at * 1000 < last_execution && !keepCookieAlive) {
// If code was added before last run of this script, dont try to redeem it again.
return
}
const cookies = scriptProperties.getProperty('COOKIE_' + profile) ?? scriptProperties.getProperty(`COOKIE`); // Replace with your actual cookie token in the script properties!!!
const cdkey = cdkeydict.code;
const isRisk = 'request' in urlDict[game];
const url = isRisk? fullUrl : replaceCdkeyInUrl(fullUrl, cdkey);
let options = {
'method': isRisk? 'post' : 'get',
'headers': {
'Cookie': `${cookies}`,
'Accept': 'application/json, text/plain, */*',
'Accept-Encoding': 'gzip, deflate, br, zstd',
'Connection': 'keep-alive',
'x-rpc-app_version': '2.34.1',
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36',
'x-rpc-client_type': '4',
},
'muteHttpExceptions': true
};
if(isRisk) {
let body = {...urlDict[game].request};
body.cdkey = cdkey;
body.lang = 'en';
options.payload = JSON.stringify(body);
}
try {
const response = UrlFetchApp.fetch(url, options);
keepCookieAlive = false;
const jsonData = JSON.parse(response.getContentText());
const retcode = jsonData.retcode;
if(![ALREADY_IN_USE, ALREADY_IN_USE_2, SUCCESSFUL].includes(retcode)) {
error = true;
}
let resultText = `${game}: ${cdkey}: ${jsonData.message}`;
if(verbose) {
resultText += ` ${response}`;
}
Logger.log(resultText);
if(verbose || ![ALREADY_IN_USE, ALREADY_IN_USE_2].includes(retcode)) {
results.push(resultText); // Store the result in the array
}
} catch (e) {
Logger.log(`${game}: Failed to send request for ${cdkey}: ${e.message}`);
results.push(`$${game}: {cdkey}: Failed to send request`); // Store the error in the array
error = true;
}
Utilities.sleep(5500);
});
}
return results; // Return ARRAY
}
function replaceCdkeyInUrl(url, cdkey) {
// Remove any existing cdkey parameter
let cleanedUrl = url.replace(/cdkey=[^&]*(&)?/, '');
// Ensure no trailing '&' or '?' is left dangling
cleanedUrl = cleanedUrl.replace(/[\?&]$/, '');
// Append the new cdkey parameter
const separator = cleanedUrl.includes('?') ? '&' : '?';
return `${cleanedUrl}${separator}cdkey=${cdkey}`;
}
function first_main() {
Logger.log("Running first_main, only run this the first time or when you had errors for more than a day so that you test old but not expired codes too.")
first_run = true;
main();
}
function main() {
let startExec = Date.now().toString();
const hoyoResp = Object.getOwnPropertyNames(profiles)
.map(name => {
const results = sendGetRequestsWithCdkeys(profiles[name], name);
if (results) {
return results.map(result => `${name}: ${result}`).flat();
}
return [];
})
.flat();
if (discord_notify && discordWebhook && hoyoResp.length > 0) {
sendDiscord(hoyoResp);
}
if (!error) {
scriptProperties.setProperty('last_execution', startExec);
}
}
function discordPing() {
return myDiscordID && error ? `<@${myDiscordID}>, You got errors while processing redemption codes` : 'Redemption codes redeemed successfully';
}
function sendDiscord(data) {
let currentChunk = `${discordPing()}\n`;
for (let i = 0; i < data.length; i++) {
if (currentChunk.length + data[i].length >= 1899) {
postWebhook(currentChunk);
currentChunk = '';
}
currentChunk += `${data[i]}\n`;
}
if (currentChunk) {
postWebhook(currentChunk);
}
}
function postWebhook(data) {
let payload = JSON.stringify({
'username': 'auto-redeem',
'avatar_url': 'https://i.imgur.com/LI1D4hP.png',
'content': data
});
const options = {
method: 'POST',
contentType: 'application/json',
payload: payload,
muteHttpExceptions: true
};
const response = UrlFetchApp.fetch(discordWebhook, options);
Logger.log(`Posted to webhook, returned ${response}`);
}