Hunter view

Send the current website to Hunter

当前为 2022-07-05 提交的版本,查看 最新版本

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Greasemonkey 油猴子Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Userscripts ,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展后才能安装此脚本。

(我已经安装了用户脚本管理器,让我安装!)

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

(我已经安装了用户样式管理器,让我安装!)

// ==UserScript==
// @name         Hunter view
// @namespace    http://tampermonkey.net/
// @version      0.4.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
// ==/UserScript==

GM_registerMenuCommand ("Hunter Login",Login, "l");
GM_registerMenuCommand ("Hunter 识别结果",HunterFind, "s");

function Login(){
    var username=prompt("Please enter Hunter Username","")
    var HunterKey=prompt("Please enter Hunter Key","")
    if(HunterKey== null || HunterKey== "" || username== null || username== ""){
        alert("未登录")
        return;
    }
    GM_setValue("username",username);
    GM_setValue("HunterKey",HunterKey);
}

function getNewDate(flag, many) {

    const thirtyDays = [4, 6, 9, 11] // 30天的月份
    const thirtyOneDays = [1, 3, 5, 7, 8, 10, 12] // 31天的月份
    const currDate = new Date() // 今天日期
    const year = currDate.getFullYear()
    let month = currDate.getMonth() + 1
    let targetDateMilli = 0
    let GMTDate = '' // 中国标准时间
    let targetYear = '' // 年
    let targetMonth = '' // 月
    let targetDate = '' // 日
    let dealTargetDays = '' // 目标日期
    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();//秒

    let dealDate='' //YYYY-MM-DD HH:MM:SS
    const isLeapYear =
        !!((year % 4 == 0 && year % 100 != 0) || year % 400 == 0) // 是否是闰年
    // console.log(isLeapYear, "isLeapYear");
    let countDays = 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')
    dealTargetDays = `${targetYear}-${targetMonth}-${targetDate}`
    dealDate = dealTargetDays+ " " + hh + ":" + mm + ":" + ss;
    dealDate = escape(dealDate)

    return dealDate
}

function HunterFind(){
  const body = document.getElementsByTagName('body')[0]
const div = document.createElement('div')
div.innerHTML = `<div style="font-size:14px;color:rgba(0,0,0,0.65);box-shadow: 0 2px 12px 0 rgba(0,0,0,0.1) ;background-color: #fff;border-radius: 5px;border: 1px solid #ebebeb;right:20px;top:20px;position: fixed;z-index: 1000000">
      <div style="display: flex;justify-content: flex-end;margin-right: 8px;">
        <div style="color:rgb(24, 36, 127);cursor: pointer;margin-left: 8px;margin-top: 4px;font-size: 12px;margin-bottom: 4px;display: none" class="icon-xiajiantou">Hunter展开</div>
        <div style="cursor: pointer;font-size: 12px;margin-top: 2px;color:rgb(96, 98, 102);" class="icon-xiajiantou-copy">隐藏</div>
      </div>
      <div class="plugs_content" style="padding-bottom: 10px;">
        <div style="margin-left: 4px;border-radius: 2px;display: inline-block;padding: 8px;padding-right: 40px;">
          <div style="margin-bottom: 4px;display: flex">
            <div style="margin-right: 6px;white-space: nowrap">地区:</div>
            <div class="area" style="word-wrap:break-word;word-break:normal;overflow: hidden;">null</div>
          </div>
          <div style="margin-bottom: 4px;display: flex">
            <div style="margin-right: 6px;white-space: nowrap">运营商和org:</div>
            <div class="org" style="word-wrap:break-word;word-break:normal;overflow: hidden;">null</div>
          </div>
          <div style="margin-bottom: 4px;display: flex">
            <div style="margin-right: 6px;white-space: nowrap">ICP:</div>
            <div class="icpnumber" style="word-wrap:break-word;word-break:normal;overflow: hidden;">null</div>
          </div>
          <div style="margin-bottom: 4px;display: flex">
            <div style="margin-right: 6px;white-space: nowrap">协议:</div>
            <div class="protocol" style="word-wrap:break-word;word-break:normal;overflow: hidden;">null</div>
          </div>
          <div style="margin-bottom: 4px;display: flex">
            <div style="margin-right: 6px;white-space: nowrap">端口:</div>
            <div class="port">null</div>
          </div>
          <div style="margin-bottom: 4px;display: flex">
            <div style="margin-right: 6px;white-space: nowrap">剩余积分:</div>
            <div class="surplus">null</div>
          </div>
        </div>
      <div class="copy-text-data" style="cursor: pointer;display: flex;margin-top: 8px;border-top:1px solid #ebebeb;justify-content: flex-end;padding-right: 4px;">
            复制
      </div>
        <ul class="demo1" style="width: 100%;max-height: 350px;max-width: 600px; overflow: auto;">
        <div style="display: flex;margin-top: 8px;">
          <div style="padding: 0 10px;">
            <div class="table_title">
              null
            </div>
          </div>
          <div style="padding: 0 10px;">
            <div class="table_protocol">
              null
            </div>
          </div>
          <div style="padding: 0 10px;">
            <div class="table_port">
              null
            </div>
          </div>
          <div style="padding: 0 10px;">
            <div class="table_code">
              null
            </div>
          </div>
          <div style="padding: 0 10px;">
            <div class="table_url">
              <div>
                <a href="" class="url1" style="color: #1890ff;text-decoration: none">url</a>
              </div>
            </div>
          </div>
        </div>
        </ul>
      </div>
    </div>`
body.appendChild(div)
    var username = GM_getValue("username");
    var HunterKey = GM_getValue("HunterKey");
    var url
    var search
    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 target = window.location.hostname // 获取域名或者ip
    var isValidIP_reg=/(\d{1,3}\.){3}\d{1,3}/ //判断是否是ip还是domain
    var messaage = {}
    messaage.type = 2
    messaage.message = target
    const msg = JSON.stringify(messaage)
    if (isValidIP_reg.test(target))
    {
        search = btoa('ip=="'+target+'"')
        url = Hunter_url+search
    }
    else
    {
        search = btoa('domain=="'+target+'"')
        url = Hunter_url+search
    }
    GM_xmlhttpRequest({
        url:url,
        method :"GET",
        data:msg,
        onload:function(xhr){
            const res = JSON.parse(xhr.responseText)

            const top_icon = document.getElementsByClassName('icon-xiajiantou-copy')[0]
            const bottom_icon = document.getElementsByClassName('icon-xiajiantou')[0]
            const content = document.getElementsByClassName('plugs_content')[0]
            const copy = document.getElementsByClassName('copy-text-data')[0]

            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 = `<div style='white-space: nowrap'>标题</div>`
            let protocol_innerHTML = `<div style='white-space: nowrap'>协议</div>`
            let port_innerHTML = `<div style='white-space: nowrap'>端口</div>`
            let code_innerHTML = `<div style='white-space: nowrap'>状态码</div>`
            let url_innerHTML = `<div style='white-space: nowrap'>url</div>`

            const data = res.data || {}

            const target_data = data.arr || []

            target_data.forEach(item=>{
                title_innerHTML = title_innerHTML + `<div style="white-space: nowrap;height: 20px">${item.web_title}</div>`
                protocol_innerHTML = protocol_innerHTML + `<div style="white-space: nowrap;height: 20px">${item.protocol}</div>`
                code_innerHTML = code_innerHTML + `<div style="white-space: nowrap;height: 20px">${item.status_code}</div>`
                url_innerHTML = url_innerHTML + `<div style="white-space: nowrap;height: 20px"><a href="${item.url}" target='_blank' style="color: #1890ff;text-decoration: none">${item.url}</a></div>`
                port_innerHTML = port_innerHTML + `<div style="white-space: nowrap;height: 20px">${item.port}</div>`
            })

            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

            top_icon.onclick = ()=>{
              content.style.display = 'none'
              top_icon.style.display = 'none'
              bottom_icon.style.display = 'block'
          }

            bottom_icon.onclick = ()=>{
              content.style.display = 'block'
              top_icon.style.display = 'block'
              bottom_icon.style.display = 'none'
          }
            copy.onclick = ()=>{
                const target = target_data.map((item)=>{
                    const copy_target_data = item.web_title + '  ' + item.protocol + '  ' + item.port + '  ' + item.status_code + '  ' + item.url + '\r\n'
                    return copy_target_data
                })
                const input = document.createElement('textarea')
                document.body.appendChild(input)
                input.value = target.join('')
                input.select()
                document.execCommand("copy")
                document.body.removeChild(textarea)
          }


            const target_location = target_data[0] || {}

            area.textContent = [target_location.country || '',target_location.province || '',target_location.city || ''].filter(item=>item).join('-') || ''

            org.textContent = Array.from(new Set(target_data.filter(item=>item.as_org).map(item=>item.as_org))).join(',')

            icpnumber.textContent = target_data[0].number || ''


            protocol.textContent = Array.from(new Set(target_data.filter(item=>item.protocol).map(item=>item.protocol))).join(',')

            port.textContent = Array.from(new Set(target_data.filter(item=>item.port).map(item=>item.port))).join(',')

            surplus.textContent = data.rest_quota.split(':')[1] || ''


            port.style.wordWrap = 'break-word'
            port.style.wordBreak = 'normal'
            port.style.overflow = 'hidden'
            port.style.width = '350px'

            protocol.style.wordWrap = 'break-word'
            protocol.style.wordBreak = 'normal'
            protocol.style.overflow = 'hidden'
            protocol.style.width = '350px'

            area.style.wordWrap = 'break-word'
            area.style.wordBreak = 'normal'
            area.style.overflow = 'hidden'
            area.style.width = '350px'

            org.style.wordWrap = 'break-word'
            org.style.wordBreak = 'normal'
            org.style.overflow = 'hidden'
            org.style.width = '350px'

        }
    });
}