船新版本ip-checker油猴脚本

开发背景

一些订阅没有提供ip的归属地,每次都需要自己去对应网址查看,很不方便。索性就搞了一个ip检测工具,也方便C号使用

功能描述

提供ip风险检测(基于scamalytics和ping0),节点切换后,刷新获取当前节点的ip检测信息,展开、收缩的功能。目前功能可能较为简单,后续根据使用情况进行优化。

更新

v1.1 版本

  • 新增复制按钮
  • 新增上下拖动,并记录位置
  • 修改初始化页面时,请求ip检测

v1.2 版本

  • 新增zip展示
  • 优化复制体验,不弹窗
  • 支持点击空白处展开折叠

主要检测信息

  • 公网ip
  • 组织
  • 城市
  • 地区
  • 国家
  • 坐标
  • ISP
  • AS
  • 风险分数
  • 风控值
  • ip类型
  • 原生ip

其中风险分数参考的scamalytics

风控值,ip类型,原生ip参考的是ping0
https://ping0.cc

代码

// ==UserScript==
// @name         ip-checker
// @namespace    http://tampermonkey.net/
// @version      1.2
// @description  显示当前使用的公网IP地址,并带有折叠展开功能和刷新功能,以及IP风险查询功能
// @author       https://linux.do/u/snaily
// @match        http://*/*
// @match        https://*/*
// @grant        GM_xmlhttpRequest
// @grant        GM_setValue
// @grant        GM_getValue
// @connect      api.ipify.org
// @connect      ip-api.com
// @connect      scamalytics.com
// @connect      ping0.cc
// @license      MIT
// ==/UserScript==

(function() {
    'use strict';

    function fetchCurrentIP() {
        console.log('Fetching current IP...');
        const refreshButton = document.getElementById('refreshIpInfo');
        if (refreshButton) {
            refreshButton.disabled = true;
            refreshButton.innerHTML = '正在刷新...';
        }

        GM_xmlhttpRequest({
            method: "GET",
            url: "https://api.ipify.org?format=json",
            onload: function(response) {
                console.log('IP fetched:', response.responseText);
                const ipInfo = JSON.parse(response.responseText);
                fetchIPDetails(ipInfo.ip);
            },
            onerror: function(error) {
                console.log('Error fetching IP:', error);
                if (refreshButton) {
                    refreshButton.disabled = false;
                    refreshButton.innerHTML = '点击刷新IP信息';
                }
            }
        });
    }

    function fetchIPDetails(ip) {
        console.log('Fetching IP details for:', ip);
        GM_xmlhttpRequest({
            method: "GET",
            url: "http://ip-api.com/json/" + ip,
            onload: function(response) {
                console.log('IP details fetched:', response.responseText);
                const ipDetails = JSON.parse(response.responseText);
                fetchIPRisk(ip, ipDetails);
            },
            onerror: function(error) {
                console.log('Error fetching IP details:', error);
                const refreshButton = document.getElementById('refreshIpInfo');
                if (refreshButton) {
                    refreshButton.disabled = false;
                    refreshButton.innerHTML = '点击刷新IP信息';
                }
            }
        });
    }

    function fetchIPRisk(ip, details) {
        console.log('Fetching IP risk for:', ip);
        GM_xmlhttpRequest({
            method: "GET",
            url: `https://scamalytics.com/ip/${ip}`,
            onload: function(response) {
                console.log('IP risk fetched:', response.responseText);
                const riskData = parseIPRisk(response.responseText);
                fetchPing0Risk(ip, details, riskData);
            },
            onerror: function(error) {
                console.log('Error fetching IP risk:', error);
                displayIPDetails(details, null, null);
                const refreshButton = document.getElementById('refreshIpInfo');
                if (refreshButton) {
                    refreshButton.disabled = false;
                    refreshButton.innerHTML = '点击刷新IP信息';
                }
            }
        });
    }

    function parseIPRisk(html) {
        console.log('Parsing IP risk data...');
        const scoreMatch = html.match(/"score":"(.*?)"/);
        const riskMatch = html.match(/"risk":"(.*?)"/);
        if (riskMatch) {
            const riskData = {
                score: scoreMatch[1],
                risk: riskMatch[1]
            };
            console.log('Parsed risk data:', riskData);
            return riskData;
        }
        console.log('Failed to parse risk data.');
        return null;
    }

    function fetchPing0Risk(ip, details, riskData) {
        console.log('Fetching Ping0 risk for:', ip);
        GM_xmlhttpRequest({
            method: "GET",
            url: `https://ping0.cc/ip/${ip}`,
            headers: {
                "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.116 Safari/537.36"
            },
            onload: function(response) {
                console.log('Initial Ping0 response:', response.responseText);
                const windowX = parseWindowX(response.responseText);
                if (windowX) {
                    console.log('Parsed window.x value:', windowX);
                    GM_xmlhttpRequest({
                        method: "GET",
                        url: `https://ping0.cc/ip/${ip}`,
                        headers: {
                            "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.116 Safari/537.36",
                            "Cookie": `jskey=${windowX}`
                        },
                        onload: function(response) {
                            console.log('Final Ping0 response:', response.responseText);
                            const ping0Data = parsePing0Risk(response.responseText);
                            displayIPDetails(details, riskData, ping0Data);
                            const refreshButton = document.getElementById('refreshIpInfo');
                            if (refreshButton) {
                                refreshButton.disabled = false;
                                refreshButton.innerHTML = '点击刷新IP信息';
                            }
                        },
                        onerror: function(error) {
                            console.log('Error fetching final Ping0 risk:', error);
                            displayIPDetails(details, riskData, null);
                            const refreshButton = document.getElementById('refreshIpInfo');
                            if (refreshButton) {
                                refreshButton.disabled = false;
                                refreshButton.innerHTML = '点击刷新IP信息';
                            }
                        }
                    });
                } else {
                    console.log('Failed to retrieve window.x value.');
                    displayIPDetails(details, riskData, null);
                    const refreshButton = document.getElementById('refreshIpInfo');
                    if (refreshButton) {
                        refreshButton.disabled = false;
                        refreshButton.innerHTML = '点击刷新IP信息';
                    }
                }
            },
            onerror: function(error) {
                console.log('Error fetching initial Ping0 page:', error);
                displayIPDetails(details, riskData, null);
                const refreshButton = document.getElementById('refreshIpInfo');
                if (refreshButton) {
                    refreshButton.disabled = false;
                    refreshButton.innerHTML = '点击刷新IP信息';
                }
            }
        });
    }

    function parseWindowX(html) {
        console.log('Parsing window.x value...');
        const match = html.match(/window\.x\s*=\s*'([^']+)'/);
        const windowX = match ? match[1] : null;
        console.log('Parsed window.x:', windowX);
        return windowX;
    }

    function parsePing0Risk(html) {
        console.log('Parsing Ping0 risk data...');
        const parser = new DOMParser();
        const doc = parser.parseFromString(html, 'text/html');

        const riskValue = doc.evaluate('/html/body/div[2]/div[2]/div[1]/div[2]/div[9]/div[2]/span', doc, null, XPathResult.STRING_TYPE, null).stringValue;
        const ipType = doc.evaluate('/html/body/div[2]/div[2]/div[1]/div[2]/div[8]/div[2]/span', doc, null, XPathResult.STRING_TYPE, null).stringValue;
        const nativeIP = doc.evaluate('/html/body/div[2]/div[2]/div[1]/div[2]/div[11]/div[2]/span', doc, null, XPathResult.STRING_TYPE, null).stringValue;

        const ping0Data = {
            riskValue: riskValue.trim(),
            ipType: ipType.trim(),
            nativeIP: nativeIP.trim()
        };
        console.log('Parsed Ping0 data:', ping0Data);
        return ping0Data;
    }

    function createCopyButton(text) {
        const button = document.createElement('button');
        button.innerHTML = '复制';
        button.style.marginLeft = '5px';
        button.style.cursor = 'pointer';
        button.style.backgroundColor = '#007bff';
        button.style.color = '#fff';
        button.style.border = 'none';
        button.style.padding = '2px 5px';
        button.style.borderRadius = '3px';
        button.onclick = () => {
            navigator.clipboard.writeText(text).then(() => {
                alert('复制成功: ' + text);
            }).catch(err => {
                console.error('复制失败: ', err);
            });
        };
        return button;
    }

    function displayIPDetails(details, riskData, ping0Data) {
        console.log('Displaying IP details...');
        var ipElement = document.getElementById('ipInfo');
        if (!ipElement) {
            ipElement = document.createElement('div');
            ipElement.id = 'ipInfo';
            ipElement.style.position = 'fixed';
            ipElement.style.top = GM_getValue('ipInfoTop', '10px');
            ipElement.style.right = '0';
            ipElement.style.backgroundColor = '#fff';
            ipElement.style.padding = '10px';
            ipElement.style.borderRadius = '5px 0 0 5px'; // 仅左侧圆角
            ipElement.style.boxShadow = '0 0 10px rgba(0,0,0,0.5)';
            ipElement.style.textAlign = 'left';
            ipElement.style.zIndex = '9999';
            ipElement.style.color = '#004085'; // 设置深蓝色字体颜色
            ipElement.style.transition = 'right 0.5s'; // 平滑过渡效果
            ipElement.style.width = '300px'; // 指定宽度
            ipElement.style.right = '-300px'; // 默认隐藏在屏幕边缘

            ipElement.innerHTML = `
                <div id="toggleIpInfo" style="position:absolute;left:-20px;top:0;width:20px;height:100%;background-color:#cfe6ff;cursor:pointer;z-index:10000;">
                    <span id="toggleIcon" style="position:absolute;top:50%;left:50%;transform:translate(-50%, -50%);font-size:18px;color:white;">◀</span>
                </div>
                <button id="refreshIpInfo" style="cursor:pointer;background-color:#28a745;color:#fff;border:none;padding:5px 10px;border-radius:5px;width:100%;margin-bottom:10px;">点击刷新IP信息</button>
                <div id="ipDetails" style="display:none;">
                    <div>当前公网IP: ${details.query}<span id="copyButtonContainer"></span></div>
                    <div>组织: ${details.org}</div>
                    <div>城市: ${details.city}</div>
                    <div>地区: ${details.regionName}</div>
                    <div>zip: ${details.zip}</div>
                    <div>国家: ${details.country}</div>
                    <div>坐标: ${details.lon},${details.lat}</div>
                    <div>ISP: ${details.isp}</div>
                    <div>AS: ${details.as}</div>
                    <div>风险分数: ${riskData ? riskData.score : '查询失败'}(${riskData ? riskData.risk : ''})</div>
                    <div>风控值: ${ping0Data ? ping0Data.riskValue : '查询失败'}</div>
                    <div>IP类型: ${ping0Data ? ping0Data.ipType : '查询失败'}</div>
                    <div>原生IP: ${ping0Data ? ping0Data.nativeIP : '查询失败'}</div>
                </div>
            `;

            document.body.appendChild(ipElement);

            // 绑定点击事件
            document.getElementById('toggleIpInfo').addEventListener('click', toggleIpInfo);

            document.getElementById('refreshIpInfo').addEventListener('click', fetchCurrentIP);

            // 初始化变量用于记录拖拽状态
            let isDragging = false;
            let startY = 0;
            let startTop = 0;

            // 鼠标按下事件,在ipElement区域生效
            ipElement.addEventListener('mousedown', function(e) {
                if (e.target.id !== 'refreshIpInfo' && e.target.id !== 'toggleIcon') {
                    isDragging = true;
                    startY = e.clientY;
                    startTop = parseInt(window.getComputedStyle(ipElement).top, 10);
                    ipElement.style.transition = 'none'; // 去除过渡效果以便拖拽时立即反应
                }
            });

            // 鼠标移动事件
            document.addEventListener('mousemove', function(e) {
                if (isDragging) {
                    const moveY = e.clientY - startY;
                    ipElement.style.top = `${startTop + moveY}px`;
                }
            });

            // 鼠标松开事件
            document.addEventListener('mouseup', function() {
                if (isDragging) {
                    isDragging = false;
                    ipElement.style.transition = 'right 0.5s'; // 恢复过渡效果
                    GM_setValue('ipInfoTop', ipElement.style.top); // 记录当前位置
                }
            });

            // 添加复制按钮到 copyButtonContainer
            const copyButtonContainer = document.getElementById('copyButtonContainer');
            copyButtonContainer.appendChild(createCopyButton(details.query));
        } else {
            var ipDetails = document.getElementById('ipDetails');
            ipDetails.innerHTML = `
                    <div>当前公网IP: ${details.query}<span id="copyButtonContainer"></span></div>
                    <div>组织: ${details.org}</div>
                    <div>城市: ${details.city}</div>
                    <div>地区: ${details.regionName}</div>
                    <div>zip: ${details.zip}</div>
                    <div>国家: ${details.country}</div>
                    <div>坐标: ${details.lon},${details.lat}</div>
                    <div>ISP: ${details.isp}</div>
                    <div>AS: ${details.as}</div>
                    <div>风险分数: ${riskData ? riskData.score : '查询失败'}(${riskData ? riskData.risk : ''})</div>
                    <div>风控值: ${ping0Data ? ping0Data.riskValue : '查询失败'}</div>
                    <div>IP类型: ${ping0Data ? ping0Data.ipType : '查询失败'}</div>
                    <div>原生IP: ${ping0Data ? ping0Data.nativeIP : '查询失败'}</div>
            `;

            // 添加复制按钮到 copyButtonContainer
            const copyButtonContainer = document.getElementById('copyButtonContainer');
            copyButtonContainer.appendChild(createCopyButton(details.query));
        }
        // 绑定 ipDetails 的点击事件
        ipDetails.addEventListener('click', toggleIpInfo);
    }

    function toggleIpInfo() {
        var ipDetails = document.getElementById('ipDetails');
        var toggleIcon = document.getElementById('toggleIcon');
        var ipElement = document.getElementById('ipInfo');
        ipElement.style.right = (ipElement.style.right == '0px') ? '-300px' : '0px'; // 切换贴边隐藏
        if (ipDetails.style.display === 'none') {
            ipDetails.style.display = 'block';
            toggleIcon.innerHTML = '▶';
        } else {
            ipDetails.style.display = 'none';
            toggleIcon.innerHTML = '◀';
        }
    }

    function createCopyButton(text) {
        const button = document.createElement('button');
        button.innerHTML = '复制';
        button.style.marginLeft = '5px';
        button.style.cursor = 'pointer';
        button.style.backgroundColor = '#007bff';
        button.style.color = '#fff';
        button.style.border = 'none';
        button.style.padding = '2px 5px';
        button.style.borderRadius = '3px';
        button.onclick = (event) => {
            event.stopPropagation(); // 阻止事件冒泡
            navigator.clipboard.writeText(text).then(() => {
                button.innerHTML = '已复制';
                setTimeout(() => {
                    button.innerHTML = '复制';
                }, 2000);
            }).catch(err => {
                console.error('复制失败: ', err);
            });
        };
        return button;
    }

    // 添加样式表
    const style = document.createElement('style');
    style.innerHTML = `
        #ipInfo button {
            cursor: pointer;
            background-color: #007bff;
            color: #fff;
            border: none;
            padding: 2px 5px;
            border-radius: 3px;
        }
    `;
    document.head.appendChild(style);

    // 初始创建ipElement,但不触发数据获取
    displayIPDetails({}, null, null);

    // fetchCurrentIP(); // 移除自动触发
})();

greasyfork地址

使用教程

初始化页面时自动开始检测ip,检测完毕后,会在右下角提供一个可以展开的按钮,点击展开就可以看到ip检测后的结果,再点击即收缩。
切换节点,点击刷新ip信息按钮,可以获取到当前节点ip信息。

使用截图

v1.0版本
【图1】
image

【图2】
image

v1.1版本
【图3】
image

v1.2版本
【图4】
image

欢迎各位佬友使用脚本给出建议或者对现有的功能接棒优化。最后如果脚本对你有用,给个免费的小红心:heart:

有个问题请教下佬友们,还有哪些参考价值比较高的ip检测网站?

感谢大佬的回答!

批量ip检测见贴:续机场ip批量检测(多线程支持)

76 个赞

Mark!

4 个赞

很快啊

3 个赞

感谢分享

2 个赞

好!

3 个赞

有用的话,佬友们点点赞

3 个赞

马克

2 个赞

出手不凡

2 个赞

嘿嘿,多谢大佬夸奖~~~

1 个赞

mark

1 个赞

好东西,明天试试

1 个赞

可以的,欢迎使用~

4 个赞

感谢分享

1 个赞

不错

2 个赞

mark

1 个赞

mark

1 个赞

ip脚本不错

1 个赞

不错 很方便,就是打开网页有点卡顿

1 个赞


家宽识别成这个,也不知道是optimum逆天还是ping0逆天

1 个赞

收藏!

1 个赞