// ==UserScript==
// @name Auto Mining Notifier
// @namespace http://tampermonkey.net/
// @version 1.5
// @description Tự động kiểm tra và thông báo kết quả khai thác
// @match https://cmangax2.com/*
// @grant GM.xmlHttpRequest
// @grant GM_notification
// @connect api.telegram.org
// @connect cmangax2.com
// ==/UserScript==
(function() {
'use strict';
const priorityItem = {
"pet_heart_bag": "Túi thú tâm",
"add_option": "Tinh Luyện Châu",
"job_exp_3": "Thông Thạo Quyển Lv3",
"job_exp_2": "Thông Thạo Quyển Lv2",
"job_exp_1": "Thông Thạo Quyển Lv1",
"medicinal_exp_1": "Tăng Ích Đan Lv1",
"medicinal_exp_2": "Tăng Ích Đan Lv2",
"medicinal_exp_3": "Tăng Ích Đan Lv3",
"medicinal_exp_4": "Tăng Ích Đan Lv4",
"equipment_upgrade_2": "Trung phẩm Thiên Mộc Thạch",
"egg_super_fragment": "Mảnh trứng thần thú",
"egg_rare": "Trứng hiếm",
"pet_exp_chest" : "Rương thú đan"
};
const priceInMarket = {
"pet_heart_bag": 100,
"add_option": 25,
"job_exp_3": 3,
"job_exp_2": 0.4,
"job_exp_1": 0.1,
"medicinal_exp_1": 1.2,
"medicinal_exp_2": 2.4,
"medicinal_exp_3": 5,
"medicinal_exp_4": 8,
"equipment_upgrade_2": 25,
"egg_super_fragment": 5,
"egg_rare": 35,
"pet_exp_chest": 5
};
const RARE_COLORS = {
4: { name: '🔥 Truyền Thuyết', color: '#ff0000' },
3: { name: '📜 Sử Thi', color: '#c700ff' },
2: { name: '🛡️ Hiếm', color: '#0099ff' },
1: { name: '⚔️ Thường', color: '#666666' },
0: { name: '❌ Không xác định', color: '#000000' }
};
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/your-webhook-url' // Thay thế bằng webhook của bạn
},
MIN_VALUE: 25
};
let lastSentHash = ''; // Lưu trạng thái lần gửi cuối
let isRunning = false; // Cờ kiểm soát quá trình chạy
const calculateValue = (reward) => {
let total = 0;
const validItems = [];
for (const itemKey in reward) {
if (priorityItem[itemKey]) {
const amount = reward[itemKey].amount || 0;
const price = priceInMarket[itemKey] || 0;
if (amount > 0 && price > 0) {
const value = amount * price;
total += value;
validItems.push({ [priorityItem[itemKey]]: amount });
}
}
}
return { total, validItems };
};
const processMiner = async (miner, area, index) => {
try {
const data = JSON.parse(miner.data);
const reward = data.miner?.reward;
//const isProtect = data.miner?.protect === true;
const isProtect = !!data.miner?.protect;
if (!reward || typeof reward !== 'object' || isProtect) return null;
const { total, validItems } = calculateValue(reward);
if (total <= 0) return null;
return {
area: area,
rare: data.rare,
stt: index + 1,
character_id: miner.target,
author: data.miner?.info?.name,
total_value: total,
valid_items: validItems,
isProtect:false
};
} catch (e) {
console.error(`Error processing miner: ${e}`);
return null;
}
};
const processArea = async (area) => {
try {
const response = await fetch(
`https://cmangax2.com/api/score_list?type=battle_mine&area=${area}`
);
const miners = await response.json();
const minersPromises = miners.map((miner, index) =>processMiner(miner, area, index));
const areaResults = await Promise.all(minersPromises);
return areaResults.filter(item => item !== null);
} catch (e) {
console.error(`Error processing area ${area}: ${e}`);
GM_notification(`Lỗi khi xử lý tầng ${area}: ${e.message}`, 'Lỗi');
return [];
}
};
const getHmkLevel = async () => {
const areas = Array.from({ length: 11 }, (_, i) => i + 1);
const areaPromises = areas.map(area => processArea(area));
const allResults = await Promise.all(areaPromises);
return allResults.flat().sort((a, b) => b.total_value - a.total_value);
};
const sendToTelegram = async (message) => {
const token = '8178445381:AAEL5AHPsPcsLYZa5qQvnWPI-3EQI3gMj04';
const chatId = '5709122878';
return new Promise((resolve) => {
GM.xmlHttpRequest({
method: 'POST',
url: `https://api.telegram.org/bot${token}/sendMessage`,
headers: {
'Content-Type': 'application/json'
},
data: JSON.stringify({
chat_id: chatId,
text: message,
parse_mode: 'HTML'
}),
onload: (response) => {
if (response.status !== 200) {
console.error('Lỗi Telegram:', response.responseText);
}
resolve();
},
onerror: (error) => {
console.error('Lỗi kết nối Telegram:', error);
resolve();
}
});
});
};
const sendToDiscord = async (message) => {
return new Promise((resolve) => {
GM.xmlHttpRequest({
method: 'POST',
url: NOTIFICATION_CONFIG.DISCORD.webhookUrl,
headers: {
'Content-Type': 'application/json'
},
data: JSON.stringify({
content: message,
embeds: [{
description: message.replace(/<[^>]+>/g, ''),
color: 0x00ff00
}]
}),
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();
}
});
});
};
const formatForDiscord = (results) => {
return results.map(item => {
const rare = parseInt(item.rare) || 0;
const rareInfo = RARE_COLORS[rare] || RARE_COLORS[0];
return `**#${item.stt}** - Tầng ${item.area}
• Rare: ${rareInfo.name}
• Tác giả: ${item.author || 'Ẩn danh'} id: ${item.character_id}
• Giá trị: ${item.total_value.toFixed(2)}💰
• Vật phẩm: ${item.valid_items.map(i => `${Object.values(i)[0]}x ${Object.keys(i)[0]}`).join(', ')}`
}).join('\n\n');
};
const formatResults = (results) => {
const filtered = results.filter(item => item.total_value >= 25 && item.isProtect === false);
if (filtered.length === 0) return null;
const currentHash = JSON.stringify(filtered);
if (currentHash === lastSentHash) return null;
lastSentHash = currentHash;
const now = new Date();
const options = {
timeZone: 'Asia/Ho_Chi_Minh',
hour12: false,
year: 'numeric',
month: '2-digit',
day: '2-digit',
hour: '2-digit',
minute: '2-digit',
second: '2-digit'
};
const vnTime = new Intl.DateTimeFormat('vi-VN', options)
.format(now)
.replace(/(\d+)\/(\d+)\/(\d+),/, '$1-$2-$3');
let message = `📊 <b>KẾT QUẢ KHAI THÁC MỚI LÚC ${vnTime}</b>\n\n`;
filtered.slice(0, 15).forEach((item, index) => {
const rare = parseInt(item.rare) || 0;
const rareInfo = RARE_COLORS[rare] || RARE_COLORS[0];
message += `🏷 <b>#${index + 1}</b>\n`
+ `┣ Tầng: ${item.area}\n`
+ `┣ Rare: ${rareInfo.name}\n`
+ `┣ Vị ttrí ${item.stt}\n`
+ `┣ Tác giả: ${item.author || 'Ẩn danh'} id: ${item.character_id}\n`
+ `┣ Giá trị: ${item.total_value.toFixed(2)}💰\n`
+ `┗ Vật phẩm: ${item.valid_items.map(i => `${Object.values(i)[0]}x${Object.keys(i)[0]}`).join('\n')}\n\n`;
});
return message;
};
const checkAndNotify = async () => {
if (isRunning) return;
isRunning = true;
try {
const results = await getHmkLevel();
const telegramMessage = formatResults(results);
const discordMessage = formatForDiscord(results.filter(item => item.total_value >= NOTIFICATION_CONFIG.MIN_VALUE));
if (telegramMessage) {
await Promise.all([
sendToTelegram(telegramMessage),
sendToDiscord(discordMessage)
]);
GM_notification('Phát hiện khoáng mới!', 'Thành công');
GM_notification('Đã gửi thông báo đến Telegram & Discord!', 'Thành công');
}
} catch (e) {
GM_notification(`Lỗi hệ thống: ${e.message}`, 'Lỗi');
} finally {
isRunning = false;
}
};
//Kiểm tra định kỳ
setTimeout(function runner() {
checkAndNotify();
setTimeout(runner, 30000);
}, 1000);
//Nút manual check
//const btn = document.createElement('button');
//btn.style = 'position: fixed; bottom: 20px; right: 20px; z-index: 9999; padding: 10px;';
//btn.textContent = 'Kiểm tra ngay';
//btn.onclick = checkAndNotify;
//document.body.appendChild(btn);
})();