logo NodeSeekbeta

【年终总结】快来看看你的ns年终总结

做了个啥?

用GPT生成了一个tampermonkey的脚本在鸡腿页面可以实现统计数据

效果

image

tampermonkey代码

// ==UserScript==
// @name         NS Yearly Summary
// @namespace    http://tampermonkey.net/
// @version      2.1
// @description  生成年度总结并展示类似年终报告的页面,包含加入时间等详细信息,以及完整统计数据展示
// @author       KefIe with GPT 4o
// @match        https://www.nodeseek.com/credit
// @grant        GM_xmlhttpRequest
// @grant        GM_addStyle
// @run-at       document-end
// ==/UserScript==

(async function () {
    'use strict';

    // 格式化数据,将原始数组转换为 JSON 对象
    function formatData(rawData) {
        if (!rawData || !rawData.success || !Array.isArray(rawData.data)) {
            throw new Error('数据格式无效');
        }

        // 将数据转换为所需格式
        return rawData.data.map(item => ({
            change: item[0],      // 加/扣分值
            balance: item[1],     // 当前余额
            reason: item[2],      // 操作原因
            timestamp: new Date(item[3]), // 时间戳
        }));
    }

    // 筛选出从 2024-01-01 开始的数据
    function filterData(data) {
        const startDate = new Date('2024-01-01T00:00:00Z');
        return data.filter(item => item.timestamp >= startDate);
    }

    // 生成年度总结
    function generateSummary(allData, filteredData) {
        const summary = {
            joinDate: allData[allData.length - 1]?.timestamp, // 加入时间为最早的记录时间
            totalDays: 0,
            totalGains: 0,
            totalLosses: 0,
            totalEntries: filteredData.length,
            details: {
                "签到收益": { total: 0, count: 0, earliest: null, latest: null },
                "回帖奖励": { total: 0, count: 0 },
                "发帖奖励": { total: 0, count: 0 },
                "被投喂鸡腿": { total: 0, count: 0 },
                "投喂鸡腿": { total: 0, count: 0 },
                "认定为轻度灌水": { total: 0, count: 0 },
                "公开帖子私有化": { total: 0, count: 0 },
                "内板代价": { total: 0, count: 0 },
                "代理相关须发内板": { total: 0, count: 0 },
                "其他": { total: 0, count: 0 }
            },
            maxDeduction: { reason: '', amount: 0 }, // 最大扣分项
            totalDeductions: { total: 0, count: 0 } // 扣分总计
        };

        filteredData.forEach(item => {
            const { change, reason, timestamp } = item;
            if (change > 0) {
                summary.totalGains += change;
                if (reason.includes("签到收益")) {
                    summary.details["签到收益"].total += change;
                    summary.details["签到收益"].count++;
                    if (!summary.details["签到收益"].earliest || timestamp < summary.details["签到收益"].earliest) {
                        summary.details["签到收益"].earliest = timestamp;
                    }
                    if (!summary.details["签到收益"].latest || timestamp > summary.details["签到收益"].latest) {
                        summary.details["签到收益"].latest = timestamp;
                    }
                } else if (reason.includes("回帖奖励")) {
                    summary.details["回帖奖励"].total += change;
                    summary.details["回帖奖励"].count++;
                } else if (reason.includes("发帖奖励")) {
                    summary.details["发帖奖励"].total += change;
                    summary.details["发帖奖励"].count++;
                } else if (reason.includes("被") && reason.includes("投喂鸡腿")) {
                    summary.details["被投喂鸡腿"].total += change;
                    summary.details["被投喂鸡腿"].count++;
                } else {
                    summary.details["其他"].total += change;
                    summary.details["其他"].count++;
                }
            } else {
                const absChange = Math.abs(change);
                summary.totalLosses += absChange;
                summary.totalDeductions.total += absChange;
                summary.totalDeductions.count++;
                if (absChange > summary.maxDeduction.amount) {
                    summary.maxDeduction = { reason, amount: absChange };
                }
                if (reason.includes("轻度灌水")) {
                    summary.details["认定为轻度灌水"].total += absChange;
                    summary.details["认定为轻度灌水"].count++;
                } else if (reason.includes("公开帖子私有化")) {
                    summary.details["公开帖子私有化"].total += absChange;
                    summary.details["公开帖子私有化"].count++;
                } else if (reason.includes("内板代价")) {
                    summary.details["内板代价"].total += absChange;
                    summary.details["内板代价"].count++;
                } else if (reason.includes("代理相关须发内板")) {
                    summary.details["代理相关须发内板"].total += absChange;
                    summary.details["代理相关须发内板"].count++;
                } else if (reason.includes("投喂鸡腿")) {
                    summary.details["投喂鸡腿"].total += absChange;
                    summary.details["投喂鸡腿"].count++;
                } else {
                    summary.details["其他"].total += absChange;
                    summary.details["其他"].count++;
                }
            }
        });

        summary.totalDays = Math.floor((new Date() - summary.joinDate) / (1000 * 60 * 60 * 24));
        return summary;
    }


    // 显示年度总结页面
    function displaySummary(summary) {
        // 清空页面内容
        document.body.innerHTML = '';
        const container = document.createElement('div');
        container.style.fontFamily = 'Arial, sans-serif';
        container.style.margin = '20px';
        container.style.opacity = '0';
        container.style.transition = 'opacity 1s';
        document.body.appendChild(container);

        const sections = [];

        // 第一版:年度总结标题
        sections.push(`<h1 style="text-align: center;">2024 年度总结</h1>`);

        // 第二版:加入时间
        sections.push(
            `<p>您是在 <strong>${summary.joinDate.toLocaleDateString()}</strong> 加入的NS,距离现在已经有 <strong>${summary.totalDays}</strong> 天。</p>`
        );

        // 第三版:总加分、总扣分
        sections.push(
            `<p>今年共计加了 <strong>${summary.totalGains}</strong> 分,扣了 <strong>${summary.totalLosses}</strong> 分,总计 <strong>${summary.totalGains - summary.totalLosses}</strong> 分。</p>`
        );

        // 第四版:签到统计
        const signIn = summary.details["签到收益"];
        if (signIn.count > 0) {
            const avgGain = (signIn.total / signIn.count).toFixed(2);
            const comment = avgGain < 5 ? "明年可能还是拿低保的好" : "你真是个幸运的人";
            sections.push(
                `<p>今年共计签到 <strong>${signIn.count}</strong> 次,
                最早一次签到是在 <strong>${signIn.earliest.toLocaleTimeString()}</strong>,
                最晚一次签到是在 <strong>${signIn.latest.toLocaleTimeString()}</strong>,
                平均每次获得鸡腿 <strong>${avgGain}</strong> 个。${comment}</p>`
            );
        }

        // 第五版:扣分统计
        // 添加扣分统计显示逻辑
        if (summary.totalDeductions.total === 0) {
            // 如果没有扣分记录,显示“你真是个乖宝宝”
            sections.push('<h1 style="text-align: center; color: green;">你真是个乖宝宝</h1>');
        } else {
            // 显示扣分统计
            sections.push('<h2>扣分统计</h2>');
            sections.push(
                `<p>总计扣分 <strong>${summary.totalDeductions.total}</strong> 分,次数 <strong>${summary.totalDeductions.count}</strong>。</p>`
            );

            // 添加每种扣分项的详细统计
            Object.keys(summary.details).forEach(key => {
                if (key.includes("轻度灌水") || key.includes("公开帖子私有化") || key.includes("内板代价") || key.includes("代理相关须发内板")) {
                    const detail = summary.details[key];
                    sections.push(
                        `<p><strong>${key}:</strong> 总计扣分 <strong>${detail.total}</strong> 分,次数 <strong>${detail.count}</strong></p>`
                    );
                }
            });
        }

        // 第六版:投喂统计
        const feeding = summary.details["被投喂鸡腿"];
        if (feeding.count > 0) {
            sections.push(
                `<p>今年你被投喂了 <strong>${feeding.count}</strong> 次,希望明年还能看到你更好的作品。</p>`
            );
        }

        // 第七版:完整统计数据
        sections.push('<h2>完整统计数据</h2>');
        Object.keys(summary.details).forEach(key => {
            const detail = summary.details[key];
            sections.push(
                `<p><strong>${key}:</strong> 总计 <strong>${detail.total}</strong> 分,次数 <strong>${detail.count}</strong></p>`
            );
        });

        // 插入内容
        sections.forEach((section, index) => {
            const sectionElement = document.createElement('div');
            sectionElement.innerHTML = section;
            sectionElement.style.opacity = '0';
            sectionElement.style.transition = 'opacity 1s';
            sectionElement.style.marginBottom = '20px';
            container.appendChild(sectionElement);
            setTimeout(() => {
                sectionElement.style.opacity = '1';
            }, index * 1000); // 每段内容依次淡入
        });

        // 动态淡入效果
        setTimeout(() => {
            container.style.opacity = '1';
        }, 100);
    }

    // 获取 Cookie
    function getCookie() {
        return document.cookie;
    }

    // 封装 GM_xmlhttpRequest 为 Promise
    function gmRequest(options) {
        return new Promise((resolve, reject) => {
            GM_xmlhttpRequest({
                ...options,
                onload: (response) => {
                    if (response.status >= 200 && response.status < 300) {
                        resolve(response);
                    } else {
                        reject(new Error(`HTTP Error: ${response.status}`));
                    }
                },
                onerror: (error) => {
                    reject(error);
                }
            });
        });
    }

    // 动态创建一个按钮并固定在页面中间
    const button = document.createElement('button');
    button.innerText = '开始获取你的ns年终报告';
    button.id = 'centered-button';
    document.body.appendChild(button);

    // 添加样式,让按钮固定在页面中间
    GM_addStyle(`
        #centered-button {
            position: fixed;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            z-index: 10000;
            padding: 15px 30px;
            font-size: 16px;
            cursor: pointer;
            background-color: #007BFF;
            color: white;
            border: none;
            border-radius: 5px;
            box-shadow: 0px 4px 6px rgba(0, 0, 0, 0.1);
        }
        #centered-button:hover {
            background-color: #0056b3;
        }
    `);

    let flag = false; // 防止重复点击

    // 给按钮添加点击事件
    button.addEventListener('click', async () => {
        if (flag) return; // 防止重复执行
        flag = true;

        let allData = []; // 存储所有页面的数据
        const lastPageElement = document.querySelectorAll('.pager-pos');
        let lastPageNum = 1;

        // 获取最后一页页码
        if (lastPageElement.length > 2) {
            lastPageNum = parseInt(
                lastPageElement[lastPageElement.length - 2].href.replace('https://www.nodeseek.com/credit#/p-', '')
            );
        }

        const cookies = getCookie(); // 获取本地 Cookie

        for (let i = 1; i <= lastPageNum; i++) {
            console.log(`正在获取第 ${i}/${lastPageNum} 页的数据`);
            button.innerText = `正在获取第 ${i}/${lastPageNum} 页的数据...`;

            try {
                const response = await gmRequest({
                    method: 'GET',
                    url: `https://www.nodeseek.com/api/account/credit/page-${i}`, // 替换为实际的 API URL
                    headers: {
                        'Content-Type': 'application/json',
                        cookie: cookies,
                    },
                });

                const rawData = JSON.parse(response.responseText);
                const formattedData = formatData(rawData);

                // 合并数据
                allData = [...allData, ...formattedData];
            } catch (error) {
                console.error(`第 ${i} 页请求失败:`, error);
                alert(`第 ${i} 页请求失败,请检查控制台日志!`);
                button.innerText = '点击重新获取'; // 恢复按钮文字
                flag = false;
                return;
            }
        }

        // 筛选出从 2024-01-01 开始的数据
        const filteredData = filterData(allData);
        console.log('筛选后的数据:', filteredData);

        // 生成总结
        const summary = generateSummary(allData, filteredData);
        console.log('年度总结:', summary);

        // 动态展示总结
        displaySummary(summary);

        flag = false; // 重置状态
    });
})();
  • 计划更新
    1.增加更多属性

    各位大佬,你们还有好多奇奇怪怪的加减分项目 能不能分享一下 加速一下更新

    修复bug
    1.投喂鸡腿被计入扣分
    2.页面超过100页,无法获取真实加入时间

    NS论坛官方版本已经发布,效果和数据也更加真实,后续不再更新,感谢论坛支持 xhj006

  • 牛逼了

  • 666 xhj003

  • 您是在 2024/5/17 加入的NS,距离现在已经有 220 天。

    今年共计加了 3289 分,扣了 30 分,总计 3259 分。

    今年共计签到 179 次, 最早一次签到是在 00:16:58, 最晚一次签到是在 12:26:18, 平均每次获得鸡腿 5.08 个。你真是个幸运的人
    扣分统计

    总计扣分 30 分,次数 16。

    认定为轻度灌水: 总计扣分 0 分,次数 0

    公开帖子私有化: 总计扣分 10 分,次数 1

    内板代价: 总计扣分 5 分,次数 1

    代理相关须发内板: 总计扣分 0 分,次数 0

    今年你被投喂了 248 次,希望明年还能看到你更好的作品。
    完整统计数据

    签到收益: 总计 910 分,次数 179

    回帖奖励: 总计 1431 分,次数 1431

    发帖奖励: 总计 620 分,次数 124

    被投喂鸡腿: 总计 248 分,次数 248

    投喂鸡腿: 总计 0 分,次数 0

    认定为轻度灌水: 总计 0 分,次数 0

    公开帖子私有化: 总计 10 分,次数 1

    内板代价: 总计 5 分,次数 1

    代理相关须发内板: 总计 0 分,次数 0

    其他: 总计 95 分,次数 16

  • 今年共计签到 289 次, 最早一次签到是在 10:35:10, 最晚一次签到是在 22:10:36, 平均每次获得鸡腿 4.89 个。明年可能还是拿低保的好

    今年大部分都是随机签到,看来随机签到确实不如固定签到拿的多

  • 这个怎么用呀,需要改自己名字吧

  • 您是在 2024/3/9 加入的NS,距离现在已经有 289 天。
    
    今年共计加了 3376 分,扣了 17 分,总计 3359 分。
    
    今年共计签到 222 次, 最早一次签到是在 23:48:13, 最晚一次签到是在 08:59:24, 平均每次获得鸡腿 5.07 个。你真是个幸运的人
    
    扣分统计
    总计扣分 17 分,次数 4。
    
    认定为轻度灌水: 总计扣分 0 分,次数 0
    
    公开帖子私有化: 总计扣分 10 分,次数 1
    
    内板代价: 总计扣分 0 分,次数 0
    
    代理相关须发内板: 总计扣分 0 分,次数 0
    
    今年你被投喂了 27 次,希望明年还能看到你更好的作品。
    
    完整统计数据
    签到收益: 总计 1125 分,次数 222
    
    回帖奖励: 总计 1369 分,次数 1369
    
    发帖奖励: 总计 765 分,次数 153
    
    被投喂鸡腿: 总计 27 分,次数 27
    
    投喂鸡腿: 总计 0 分,次数 0
    
    认定为轻度灌水: 总计 0 分,次数 0
    
    公开帖子私有化: 总计 10 分,次数 1
    
    内板代价: 总计 0 分,次数 0
    
    代理相关须发内板: 总计 0 分,次数 0
    
    其他: 总计 97 分,次数 4
    
  • 牛逼,挺好的,送你个免费鸡腿

  • @Adger #5 不用,你要在鸡腿页面才会显示

  • @Adm1n #4 哈哈 我用随机 就超出了5

  • 这个好玩,可以有

你好啊,陌生人!

我的朋友,看起来你是新来的,如果想参与到讨论中,点击下面的按钮!

📈用户数目📈

目前论坛共有61578位seeker

🎉欢迎新用户🎉