mirror of
https://github.com/babalae/bettergi-scripts-list.git
synced 2026-03-15 03:23:22 +08:00
250 lines
9.4 KiB
JavaScript
250 lines
9.4 KiB
JavaScript
let username = settings.username || "default";
|
||
let use_bgi_code_source = settings.use_bgi_code_source || false;
|
||
|
||
async function* getCodeFromFile() {
|
||
const content = file.readTextSync("codes.txt");
|
||
const codes = content.split("\n");
|
||
|
||
|
||
for (let i = 0; i < codes.length; i++) {
|
||
const line = codes[i].trim();
|
||
if (!line) continue;
|
||
|
||
// 找到最后一个英文逗号
|
||
const lastCommaIndex = line.lastIndexOf(',');
|
||
let code, deadline;
|
||
if (lastCommaIndex === -1) {
|
||
// 没有逗号,则整个当作code
|
||
code = line;
|
||
deadline = '';
|
||
} else {
|
||
code = line.slice(0, lastCommaIndex).trim();
|
||
deadline = line.slice(lastCommaIndex + 1).trim();
|
||
}
|
||
|
||
if (!code) continue;
|
||
yield [code, deadline];
|
||
}
|
||
}
|
||
|
||
const BGI_CODE_UPDATETIME_URL = "https://cnb.cool/bettergi/genshin-redeem-code/-/git/raw/main/update_time.txt"
|
||
const BGI_CODE_LIST_URL = "https://cnb.cool/bettergi/genshin-redeem-code/-/git/raw/main/codes.json"
|
||
async function* getCodeFromBGI() {
|
||
// const updateTimeResp = await fetch(BGI_CODE_UPDATETIME_URL);
|
||
// if (!updateTimeResp.ok) {
|
||
// log.error(`获取BGI兑换码更新时间失败: ${updateTimeResp.status} ${updateTimeResp.statusText}`);
|
||
// return;
|
||
// }
|
||
// const updateTime = (await updateTimeResp.text()).trim(); // YYYYMMDD
|
||
// const updateTimeDate = new Date(`${updateTime.slice(0, 4)}-${updateTime.slice(4, 6)}-${updateTime.slice(6, 8)}`);
|
||
|
||
const listResp = await http.request('GET', BGI_CODE_LIST_URL, null, null);
|
||
log.debug(`BGI兑换码列表请求返回: ${JSON.stringify(listResp)}`);
|
||
if (listResp.status_code != 200) {
|
||
log.error(`获取BGI兑换码列表失败: 服务器返回状态${listResp.status} ${listResp.statusText}`);
|
||
return;
|
||
}
|
||
const fixed = listResp.body
|
||
.replace(/,\s*]/g, ']')
|
||
.replace(/,\s*}/g, '}');
|
||
|
||
const listJson = JSON.parse(fixed);
|
||
if (!Array.isArray(listJson)) {
|
||
log.error(`BGI兑换码列表格式错误`);
|
||
return;
|
||
}
|
||
const codeTitles = listJson.map(item => item.title);
|
||
log.info(`BGI兑换码列表获取成功,共 ${codeTitles.length} 组兑换码: ${codeTitles.join(", ")}`);
|
||
|
||
for (const item of listJson) {
|
||
const valid = item.valid.trim(); // YYYY-MM-DD
|
||
const validDate = new Date(valid);
|
||
for (const code of item.codes) {
|
||
if (!code) continue;
|
||
// 有效期格式不明,暂时先不返回
|
||
yield [code, null];
|
||
}
|
||
}
|
||
}
|
||
|
||
async function* getCodeList() {
|
||
if (!use_bgi_code_source) {
|
||
yield *getCodeFromFile();
|
||
} else {
|
||
yield *getCodeFromBGI();
|
||
}
|
||
}
|
||
|
||
async function openCodeUI() {
|
||
keyPress("ESCAPE");
|
||
await sleep(2000);
|
||
|
||
const settingsRo = RecognitionObject.TemplateMatch(file.readImageMatSync("assets/settings.png"));
|
||
const ro1 = captureGameRegion();
|
||
const settingsRes = ro1.find(settingsRo);
|
||
ro1.dispose();
|
||
if (settingsRes.isExist()) settingsRes.click();
|
||
await sleep(2000);
|
||
|
||
const accountRo = RecognitionObject.TemplateMatch(file.readImageMatSync("assets/account.png"));
|
||
const ro2 = captureGameRegion();
|
||
const accountRes = ro2.find(accountRo);
|
||
ro2.dispose();
|
||
if (accountRes.isExist()) accountRes.click();
|
||
await sleep(500);
|
||
|
||
const goToRedeemRo = RecognitionObject.TemplateMatch(file.readImageMatSync("assets/go_to_redeem.png"));
|
||
const ro3 = captureGameRegion();
|
||
const goToRedeemRes = ro3.find(goToRedeemRo);
|
||
ro3.dispose();
|
||
if (goToRedeemRes.isExist()) goToRedeemRes.click();
|
||
await sleep(500);
|
||
}
|
||
|
||
(async function () {
|
||
setGameMetrics(1920, 1080, 1);
|
||
|
||
// 1. 返回主界面
|
||
await genshin.returnMainUi();
|
||
await sleep(1000);
|
||
|
||
// 2. 检验设置用户名
|
||
function getUsername() {
|
||
username = username.trim();
|
||
// 只允许 中文 / 英文 / 数字,长度 1~20
|
||
if (!username || !/^[\u4e00-\u9fa5A-Za-z0-9]{1,20}$/.test(username)) {
|
||
log.error(`用户名${username}违规,暂时使用默认用户名,请查看readme后修改`)
|
||
username = "default";
|
||
}
|
||
return username;
|
||
}
|
||
|
||
username = getUsername();
|
||
const recordPath = `record/record_${username}.txt`;
|
||
|
||
// 3. 读取已兑换记录
|
||
let redeemedCodes = new Set();
|
||
try {
|
||
const recordContent = file.readTextSync(recordPath);
|
||
if (recordContent) {
|
||
redeemedCodes = new Set(recordContent.split("\n").map(l => l.trim()).filter(Boolean));
|
||
}
|
||
} catch (e) {
|
||
log.warn(`未找到 ${recordPath},稍后会自动创建`);
|
||
}
|
||
|
||
// 4-5. 读取 code 并打开兑换界面进行兑换
|
||
try {
|
||
let count = 0;
|
||
let uiOpened = false;
|
||
|
||
for await (const [code, deadline] of getCodeList()) {
|
||
// 跳过已兑换的
|
||
if (redeemedCodes.has(code)) {
|
||
count++;
|
||
continue;
|
||
}
|
||
|
||
// 时间检查
|
||
const now = new Date();
|
||
const currentTime = now.getFullYear() + '.' + String(now.getMonth() + 1).padStart(2, '0') + '.' + String(now.getDate()).padStart(2, '0') + ' ' + String(now.getHours()).padStart(2, '0') + ':' + String(now.getMinutes()).padStart(2, '0') + ':' + String(now.getSeconds()).padStart(2, '0');
|
||
if (currentTime > deadline) {
|
||
log.info(`兑换码【${code}】已超过截止时间,跳过`);
|
||
continue;
|
||
}
|
||
|
||
// 打开兑换界面
|
||
if (!uiOpened) {
|
||
await openCodeUI();
|
||
uiOpened = true;
|
||
}
|
||
|
||
// 输入兑换码
|
||
const inputCodeRo = RecognitionObject.TemplateMatch(file.readImageMatSync("assets/input_code.png"));
|
||
const ro4 = captureGameRegion();
|
||
const inputCodeRes = ro4.find(inputCodeRo);
|
||
ro4.dispose();
|
||
if (inputCodeRes.isExist()) inputCodeRes.click();
|
||
await sleep(300);
|
||
|
||
await inputText(code);
|
||
await sleep(500);
|
||
|
||
// 点击兑换按钮
|
||
const redeemRo = RecognitionObject.TemplateMatch(file.readImageMatSync("assets/redeem.png"));
|
||
const ro5 = captureGameRegion();
|
||
const redeemRes = ro5.find(redeemRo);
|
||
ro5.dispose();
|
||
if (redeemRes.isExist()) redeemRes.click();
|
||
await sleep(1500);
|
||
|
||
// 检测各种状态
|
||
const ro6 = captureGameRegion();
|
||
const invalidRes = ro6.find(RecognitionObject.TemplateMatch(file.readImageMatSync("assets/invalid.png")));
|
||
ro6.dispose();
|
||
if (invalidRes.isExist()) log.info(`兑换码【${code}】无效`);
|
||
|
||
const ro7 = captureGameRegion();
|
||
const usedRes = ro7.find(RecognitionObject.TemplateMatch(file.readImageMatSync("assets/used.png")));
|
||
ro7.dispose();
|
||
if (usedRes.isExist()) {
|
||
// 写入记录
|
||
const writeOk = file.writeTextSync(recordPath, code + "\n", true);
|
||
if (writeOk) {
|
||
log.info(`兑换码【${code}】已使用`);
|
||
redeemedCodes.add(code);
|
||
}
|
||
}
|
||
|
||
const ro8 = captureGameRegion();
|
||
const expiredRes = ro8.find(RecognitionObject.TemplateMatch(file.readImageMatSync("assets/expired.png")));
|
||
ro8.dispose();
|
||
if (expiredRes.isExist()) {
|
||
// 写入记录
|
||
const writeOk = file.writeTextSync(recordPath, code + "\n", true);
|
||
if (writeOk) {
|
||
log.info(`兑换码【${code}】已过期`);
|
||
redeemedCodes.add(code);
|
||
}
|
||
}
|
||
|
||
const ro9 = captureGameRegion();
|
||
const notopenRes = ro9.find(RecognitionObject.TemplateMatch(file.readImageMatSync("assets/not_open.png")));
|
||
ro9.dispose();
|
||
if (notopenRes.isExist()) log.info(`兑换码【${code}】未开启`);
|
||
|
||
const ro10 = captureGameRegion();
|
||
const confirmRes = ro10.find(RecognitionObject.TemplateMatch(file.readImageMatSync("assets/confirm.png")));
|
||
ro10.dispose();
|
||
if (confirmRes.isExist()) {
|
||
log.info(`兑换码【${code}】成功兑换`);
|
||
confirmRes.click();
|
||
|
||
// 写入记录
|
||
const writeOk = file.writeTextSync(recordPath, code + "\n", true);
|
||
if (writeOk) {
|
||
log.info(`已记录兑换码【${code}】到 ${recordPath}`);
|
||
redeemedCodes.add(code);
|
||
}
|
||
}
|
||
|
||
// 清除输入
|
||
const ro11 = captureGameRegion();
|
||
const clearRes = ro11.find(RecognitionObject.TemplateMatch(file.readImageMatSync("assets/clear.png")));
|
||
ro11.dispose();
|
||
if (clearRes.isExist()) clearRes.click();
|
||
|
||
await sleep(4000);
|
||
}
|
||
if (count > 0) {
|
||
log.info(`检测到${count}个兑换码已兑换过,跳过`);
|
||
}
|
||
} catch (error) {
|
||
log.error(`读取兑换码文件失败: ${error}`);
|
||
}
|
||
|
||
// 6. 返回主界面
|
||
await genshin.returnMainUi();
|
||
|
||
})();
|