Hunter view

Send the current website to Hunter

目前為 2022-02-19 提交的版本,檢視 最新版本

您需要先安裝使用者腳本管理器擴展,如 TampermonkeyGreasemonkeyViolentmonkey 之後才能安裝該腳本。

You will need to install an extension such as Tampermonkey to install this script.

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyViolentmonkey 後才能安裝該腳本。

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyUserscripts 後才能安裝該腳本。

你需要先安裝一款使用者腳本管理器擴展,比如 Tampermonkey,才能安裝此腳本

您需要先安裝使用者腳本管理器擴充功能後才能安裝該腳本。

(我已經安裝了使用者腳本管理器,讓我安裝!)

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

(我已經安裝了使用者樣式管理器,讓我安裝!)

// ==UserScript==
// @name         Hunter view
// @namespace    http://tampermonkey.net/
// @version      0.2
// @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","111")
    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;

    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: 20px;">
        <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">协议:</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 style="display: flex;margin-top: 8px;border-top:1px solid #ebebeb;padding-top: 10px;width: 100%;">

        </div>
        <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">xxxxx</a>
              </div>
            </div>
          </div>
        </div>
      </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=20&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 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 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>标题</div>`
            let protocol_innerHTML = `<div>协议</div>`
            let port_innerHTML = `<div>端口</div>`
            let code_innerHTML = `<div>状态码</div>`
            let url_innerHTML = `<div>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'
          }

            const target_location = target_data[0] || {}

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

            org.textContent = target_data[0].as_org || ''

            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'

        }
    });
}