// ==UserScript==
// @name Auto Claim Battle Mine Reward
// @namespace http://tampermonkey.net/
// @version 1.4
// @description Tự động nhận phần thưởng Battle Mine
// @author Optimized by KeshiNguyen
// @match *://*/*
// @run-at document-idle
// @grant GM.xmlHttpRequest
// @grant GM_notification
// @connect discord.com
// ==/UserScript==
(function() {
'use strict';
const isGameDomain = () => {
return /cmangax\d+\.com|cnovel/.test(location.hostname);
};
if (!isGameDomain()) return;
// ======= GIỮ TAB KHÔNG BỊ TREO =======
const keepTabAwake = () => {
const iframe = document.createElement('iframe');
iframe.style.display = 'none';
document.body.appendChild(iframe);
setInterval(() => {
window.focus();
document.dispatchEvent(new MouseEvent('mousemove'));
}, 20000);
};
const waitForGameKeys = (timeout = 5000) => {
return new Promise((resolve, reject) => {
const start = Date.now();
const check = () => {
const scripts = document.getElementsByTagName('script');
for (const script of scripts) {
const player_id = script.textContent.match(/my_character\s*=\s*['"]?(\d+)['"]?/);
const token_character = script.textContent.match(/token_character\s*=\s*['"]?([a-zA-Z0-9]+)['"]?/);
if (player_id && token_character) {
return resolve({
player_id: parseInt(player_id[1], 10),
token_character: token_character[1]
});
}
}
if (Date.now() - start > timeout) {
return reject("Không tìm thấy thông tin player/token trong thời gian cho phép.");
}
setTimeout(check, 200); // Retry sau 200ms
};
check();
});
};
// ======= QUẢN LÝ TIMEOUT VÀ INTERVAL =======
let intervals = [];
let timeouts = [];
let baseUrl = location.hostname;
let last_mine_id = localStorage.getItem("cmanga_last_mine_id") || "";
let last_state = "";
const RARE = {
1: "Thường",
2: "Hiếm",
3: "Sử thi",
4: "Truyền thuyết"
}
const clearAll = () => {
intervals.forEach(clearInterval);
timeouts.forEach(clearTimeout);
intervals = [];
timeouts = [];
};
const NOTIFICATION_CONFIG = {
TELEGRAM: {
token: 'Thay bằng token bằng cách tìm botfather rồi nhập /mybots rồi chọn token',
chatId: 'Thay bằng chat id bằng cách tìm userinfo rồi start là xong'
},
DISCORD: {
webhookUrl: 'https://discord.com/api/webhooks/1374401953374666864/sXgxVbDOPQDBK29JFfNqmBRs_K8ZRSxY5t-EQ9W7TAbzx6QWJKWmyp0ukbGVmMYwfqc6'
},
MIN_VALUE: 25
};
const formatForDiscord = (result, now) => {
if (!result) return null;
let embed = {
title: 'Thông báo khai thác mới',
color: 0x00ff00,
timestamp: new Date().toISOString()
};
if (result?.type === "miner") {
const current_state = `mining_${result?.score_id}`;
if (current_state === last_state) return null;
last_state = current_state;
embed.description = `📊 **NGỒI KHOÁNG LÚC ${now.toLocaleString('vi-VN')}**\n\n` +
`Vị trí::: Tầng ${result?.area} loại ${result?.rare} score_id: ${result?.score_id}`;
}
else if (result?.type === "is_kicked") {
const current_state = `is_kicked`;
if (current_state === last_state) return null;
last_state = current_state;
embed.description = `📊 **BỊ TẤN CÔNG KHOÁNG LÚC ${now.toLocaleString('vi-VN')}**\n\n` +
`Bị tấn công bởi ${result?.attacker ? `${result?.attacker} với id ${result?.id}` : 'ẩn danh'}`;
}
else {
return null;
}
return embed;
};
const sendViaFetch = async (message) => {
//const formattedMessage = formatForDiscord(message, new Date());
try {
const response = await fetch(NOTIFICATION_CONFIG.DISCORD.webhookUrl, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
content: '📢 Thông báo khai thác mới (via fetch)',
embeds: [{
title: 'Chi tiết kết quả',
description: message,
color: 0x00ff00,
timestamp: new Date().toISOString()
}]
})
});
if (!response.ok) {
console.error('Lỗi Discord (fetch):', await response.text());
}
} catch (error) {
console.error('Lỗi fetch khi gửi thông báo:', error);
}
};
const sendToDiscord = async (message) => {
try {
const embed = formatForDiscord(message, new Date());
if (!embed) return;
const payload = {
embeds: [embed]
};
// Kiểm tra môi trường
if (typeof GM === 'undefined') {
console.warn('GM không khả dụng, sử dụng fetch API');
return await sendViaFetch(message);
}
if (!GM.xmlHttpRequest) {
console.warn('GM.xmlHttpRequest không khả dụng, sử dụng fetch API');
return await sendViaFetch(message);
}
return new Promise((resolve) => {
GM.xmlHttpRequest({
method: 'POST',
url: NOTIFICATION_CONFIG.DISCORD.webhookUrl,
headers: {
'Content-Type': 'application/json'
},
data: JSON.stringify(payload),
onload: (response) => {
if (response.status < 200 || response.status >= 300) {
console.error('Lỗi Discord:', response.responseText);
}
resolve();
},
onerror: (error) => {
console.error('Lỗi kết nối Discord:', error);
resolve();
}
});
});
} catch (error) {
console.error('Lỗi khi gửi thông báo:', error);
}
};
// ======= PHẦN CHÍNH NHẬN THƯỞNG =======
function startAutoClaim() {
const SCORE_URL = `/api/score_list?type=battle_mine_target&target=${window.my_character}`;
const CLAIM_URL = `/assets/ajax/character_activity.php`;
const ENERGY_URL = `/api/character_energy_mine?character=${window.my_character}`;
const CHARACTER_ACTIVITY_URL = `/assets/ajax/character_activity.php`;
const OTHER_URL = `/api/get_data_by_id?table=game_character&data=other&id=${window.my_character}&v=${Date.now()}`;
async function fetchScore() {
try {
const res = await fetch(SCORE_URL);
console.log(SCORE_URL);
const json = await res.json();
return json.length > 0 ? json[0] : null;
} catch (err) {
console.error('[x] Lỗi fetchScore:', err);
return null;
}
}
const sendRequest = async (url, action) => {
return new Promise((resolve, reject) => {
GM.xmlHttpRequest({
method: "POST",
url: url.toString(),
headers: {
"Content-Type": "application/x-www-form-urlencoded",
"X-Requested-With": "XMLHttpRequest"
},
data: `action=${action}`,
onload: function(response) {
const responseText = response.responseText;
if (/alertify\.error/.test(responseText)) {
console.error("❌ Lỗi khi đăng ký hoạt động");
return resolve({
success: false,
message: `Fail when sign activity with action ${action}`
});
} else if (/alertify\.success/.test(responseText)) {
console.log("✅ Response:", responseText);
return resolve({
success: true,
message: `Sign activity with action ${action} successfully`,
data: responseText
});
}
},
onerror: function(err) {
console.error("❌ Lỗi mạng khi gửi request:", err);
return reject({
success: false,
message: `Network error: ${err}`
});
}
});
});
};
async function attack(mine_id) {
if (!mine_id) {
console.warn('[!] mine_id rỗng khi cố gắng tấn công. Bỏ qua.');
return false;
}
try {
const attack_res = await sendRequest(CHARACTER_ACTIVITY_URL, `battle_mine_challenge&mine_id=${mine_id}&target=public`);
if (!attack_res.success) {
console.error(`[x] Attack failed: ${attack_res.message}`);
console.log('Response attack:::', attack_res);
return false;
}
return true;
} catch (e) {
console.error("Lỗi trong quá trình khiêu chiến:", e);
return false;
}
}
async function claimReward() {
try {
const res = await fetch(CLAIM_URL, {
method: 'POST',
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
body: new URLSearchParams({
action: 'battle_mine_take_reward',
target: 'public'
})
});
const result = await res.json();
console.log('[✓] Nhận thưởng:', result);
clearAll();
timeouts.push(setTimeout(checkAndClaimReward, 60000)); // Check lại sau 1 phút
} catch (err) {
console.error('[x] Lỗi claimReward:', err);
}
}
async function checkAndClaimReward() {
try {
let score_res = await fetchScore();
let message = "";
if (!score_res) {
console.log('[!] Đã bị sút khỏi hmk');
const other = await fetch(OTHER_URL);
const other_json = await other.json();
let other_data = JSON.parse(other_json.other);
let battle_mine_info = other_data?.battle_mine?.war?.info;
message = { id: battle_mine_info?.id, attacker: battle_mine_info?.name, type: "is_kicked" };
if (message) {
await sendToDiscord(message);
console.log("Đã gửi tới discord")
}
const energy_res = await fetch(ENERGY_URL);
const json = await energy_res.json();
console.log(json);
const energy = json.current;
console.log("current energy:::", energy);
console.log("last_mine_id:::", last_mine_id);
if (parseInt(energy) > 8) {
const attack_res = await attack(last_mine_id);
console.log("attack_res", attack_res);
if (attack_res) {
score_res = await fetchScore();
}
}
}
if (!score_res) {
// Nếu không có score_res, chờ 1 phút rồi chạy lại
timeouts.push(setTimeout(checkAndClaimReward, 60000));
return;
}
let data = JSON.parse(score_res.data);
console.log("data:::", data);
last_mine_id = score_res.id_score;
localStorage.setItem('cmanga_last_mine_id', last_mine_id);
console.log("id_score:::", last_mine_id);
let miner = data?.miner
console.log(`[i] Thời gian hiện tại: ${miner.times} phút`);
message = { type: 'miner', rare: RARE[data?.rare] , area: data?.area, score_id: score_res?.id_score };
if (message) {
await sendToDiscord(message);
console.log("Đã gửi tới discord")
}
if (miner.times >= 60) {
await claimReward();
} else {
const waitMinutes = 60 - miner.times;
const waitMs = waitMinutes * 60000;
console.log(`[~] Đợi ${waitMinutes} phút`);
timeouts.push(setTimeout(checkAndClaimReward, waitMs));
timeouts.push(setTimeout(checkAndClaimReward, 60000));
}
} catch (err) {
console.error('[x] Lỗi checkAndClaim:', err);
}
}
checkAndClaimReward();
}
// Khởi động script khi trang tải xong
window.addEventListener('load', async () => {
try {
const { player_id, token_character } = await waitForGameKeys();
window.my_character = player_id;
window.token_character = token_character;
keepTabAwake();
startAutoClaim();
} catch (error) {
console.error('Lỗi khi khởi động script:', error);
}
});
})();