// ==UserScript== // @name Hunter view // @namespace http://tampermonkey.net/ // @version 0.5 // @description Send the current website to Hunter // @author 0cat // @match http://*/* // @match https://*/* // @grant GM_registerMenuCommand // @grant GM_xmlhttpRequest // @grant GM_setValue // @grant GM_getValue // @connect * // @license MIT // @downloadURL https://update.greasyfork.icu/scripts/440243/Hunter%20view.user.js // @updateURL https://update.greasyfork.icu/scripts/440243/Hunter%20view.meta.js // ==/UserScript== GM_registerMenuCommand("Hunter Login", openLoginForm, "l"); GM_registerMenuCommand("Hunter 识别结果", HunterFind, "s"); // 创建自定义输入表单 function openLoginForm() { const body = document.getElementsByTagName('body')[0]; const loginDiv = document.createElement('div'); loginDiv.innerHTML = `

Login to Hunter





`; body.appendChild(loginDiv); document.getElementById('loginSubmit').onclick = function() { const username = document.getElementById('hunterUsername').value; const HunterKey = document.getElementById('hunterKey').value; if (username && HunterKey) { GM_setValue("username", username); GM_setValue("HunterKey", HunterKey); alert("Login successful!"); body.removeChild(loginDiv); // Remove form after login } else { alert("Please fill in both fields."); } }; document.getElementById('loginCancel').onclick = function() { body.removeChild(loginDiv); }; } function HunterFind() { var username = GM_getValue("username"); var HunterKey = GM_getValue("HunterKey"); if (!username || !HunterKey) { console.error("No username or HunterKey found"); return; } const body = document.getElementsByTagName('body')[0]; const div = document.createElement('div'); div.innerHTML = `
隐藏
RDAP_IP_CIDR:
N/A
RDAP_描述:
N/A
地区:
null
运营商和org:
null
ICP:
null
协议:
null
端口:
null
剩余积分:
null
复制
`; body.appendChild(div); // 隐藏/展开功能 const hideBtn = document.getElementById('hideBtn'); const expandBtn = document.getElementById('expandBtn'); const contentDiv = document.getElementById('contentDiv'); hideBtn.onclick = function() { contentDiv.style.display = 'none'; hideBtn.style.display = 'none'; expandBtn.style.display = 'block'; }; expandBtn.onclick = function() { contentDiv.style.display = 'block'; hideBtn.style.display = 'block'; expandBtn.style.display = 'none'; }; var target = window.location.hostname; var isValidIP_reg = /(\d{1,3}\.){3}\d{1,3}/; // 如果是 IP,则执行 RDAP 查询 if (isValidIP_reg.test(target)) { // 发起 RDAP 请求 var rdap_url = `https://rdap.apnic.net/ip/${target}`; GM_xmlhttpRequest({ method: "GET", url: rdap_url, onload: function(xhr) { if (xhr.status !== 200) { console.error("RDAP Request failed, status code:", xhr.status); return; } const rdap_res = JSON.parse(xhr.responseText); // 提取 CIDR 和描述 const handle = rdap_res.handle; const cidr = rdap_res.cidr0_cidrs[0].v4prefix + "/" + rdap_res.cidr0_cidrs[0].length; const description = rdap_res.remarks[0].description[0] || 'N/A'; // 将 CIDR 和描述信息填充到小卡片中 const rdap_cidr_element = document.getElementsByClassName('rdap_cidr')[0]; const rdap_description_element = document.getElementsByClassName('rdap_description')[0]; rdap_cidr_element.textContent = cidr || 'N/A'; rdap_description_element.textContent = description || 'N/A'; }, onerror: function(xhr) { console.error("RDAP Request error:", xhr); } }); } var Hunter_url = "https://hunter.qianxin.com/openApi/search?username=" + username + "&api-key=" + HunterKey + "&page=1&page_size=50&is_web=3&start_time=" + getNewDate("before", 6) + "&end_time=" + getNewDate() + "&search="; var search, url; if (isValidIP_reg.test(target)) { search = btoa('ip=="' + target + '"'); url = Hunter_url + search; } else { search = btoa('domain=="' + target + '"'); url = Hunter_url + search; } if (!url) { console.error("URL generation failed."); return; } // 发起 Hunter 查询请求 try { GM_xmlhttpRequest({ method: "GET", url: url, onload: function(xhr) { if (xhr.status !== 200) { console.error("Hunter Request failed, status code:", xhr.status); return; } const res = JSON.parse(xhr.responseText); const target_data = res.data?.arr || []; if (target_data.length === 0) { return; } // 获取 HTML 元素 const area = document.getElementsByClassName('area')[0]; const org = document.getElementsByClassName('org')[0]; const protocol = document.getElementsByClassName('protocol')[0]; const port = document.getElementsByClassName('port')[0]; const surplus = document.getElementsByClassName('surplus')[0]; const icpnumber = document.getElementsByClassName('icpnumber')[0]; const table_title = document.getElementsByClassName('table_title')[0]; const table_protocol = document.getElementsByClassName('table_protocol')[0]; const table_port = document.getElementsByClassName('table_port')[0]; const table_code = document.getElementsByClassName('table_code')[0]; const table_url = document.getElementsByClassName('table_url')[0]; // 遍历数据并展示到页面 let title_innerHTML = `
标题
`; let protocol_innerHTML = `
协议
`; let port_innerHTML = `
端口
`; let code_innerHTML = `
状态码
`; let url_innerHTML = `
url
`; target_data.forEach(item => { title_innerHTML += `
${item.web_title || 'N/A'}
`; protocol_innerHTML += `
${item.protocol || 'N/A'}
`; code_innerHTML += `
${item.status_code || 'N/A'}
`; url_innerHTML += `
${item.url}
`; port_innerHTML += `
${item.port || 'N/A'}
`; }); table_title.innerHTML = title_innerHTML; table_protocol.innerHTML = protocol_innerHTML; table_code.innerHTML = code_innerHTML; table_port.innerHTML = port_innerHTML; table_url.innerHTML = url_innerHTML; const target_location = target_data[0] || {}; area.textContent = [target_location.country || '', target_location.province || '', target_location.city || ''].filter(item => item).join('-') || 'N/A'; org.textContent = Array.from(new Set(target_data.filter(item => item.as_org).map(item => item.as_org))).join(',') || 'N/A'; icpnumber.textContent = target_data[0].number || 'N/A'; protocol.textContent = Array.from(new Set(target_data.filter(item => item.protocol).map(item => item.protocol))).join(',') || 'N/A'; port.textContent = Array.from(new Set(target_data.filter(item => item.port).map(item => item.port))).join(',') || 'N/A'; surplus.textContent = res.data.rest_quota?.split(':')[1] || 'N/A'; }, onerror: function(xhr) { console.error("Hunter Request error:", xhr); } }); } catch (e) { console.error("Error while sending request:", e); } } function getNewDate(flag, many) { const thirtyDays = [4, 6, 9, 11]; const thirtyOneDays = [1, 3, 5, 7, 8, 10, 12]; const currDate = new Date(); const year = currDate.getFullYear(); let month = currDate.getMonth() + 1; let countDays = 0; let targetDateMilli = 0; let GMTDate = ''; let targetYear = ''; let targetMonth = ''; let targetDate = ''; let dealDate = ''; let hh = currDate.getHours() < 10 ? "0" + currDate.getHours() : currDate.getHours(); let mm = currDate.getMinutes() < 10 ? "0" + currDate.getMinutes() : currDate.getMinutes(); let ss = currDate.getSeconds() < 10 ? "0" + currDate.getSeconds() : currDate.getSeconds(); const isLeapYear = !!((year % 4 == 0 && year % 100 != 0) || year % 400 == 0); for (let i = 0; i < many; i++) { if (flag === 'before') { month = month - 1 <= 0 ? 12 : month - 1; } else { month = month + 1 > 12 ? 1 : month + 1; } thirtyDays.includes(month) ? (countDays += 30) : thirtyOneDays.includes(month) ? (countDays += 31) : isLeapYear ? (countDays += 29) : (countDays += 28); } targetDateMilli = currDate.setDate(currDate.getDate() - (flag === 'before' ? countDays : countDays * -1)); GMTDate = new Date(targetDateMilli); targetYear = GMTDate.getFullYear(); targetMonth = GMTDate.getMonth() + 1; targetDate = GMTDate.getDate(); targetMonth = targetMonth.toString().padStart(2, '0'); targetDate = targetDate.toString().padStart(2, '0'); dealDate = `${targetYear}-${targetMonth}-${targetDate} ${hh}:${mm}:${ss}`; return escape(dealDate); }