2025年10月21日星期二

苦力怕论坛任务脚本

1.购买服务器阿里云:服务器购买地址https://t.aliyun.com/U/Bg6shY若失效,可用地址

1.购买服务器

阿里云:

服务器购买地址

https://t.aliyun.com/U/Bg6shY

若失效,可用地址

https://www.aliyun.com/daily-act/ecs/activity_selection?source=5176.29345612&userCode=49hts92d

腾讯云:

https://curl.qcloud.com/wJpWmSfU

若失效,可用地址

https://cloud.tencent.com/act/cps/redirect?redirect=2446&cps_key=ad201ee2ef3b771157f72ee5464b1fea&from=console

华为云

https://activity.huaweicloud.com/cps.html?fromacct=64b5cf7cc11b4840bb4ed2ea0b2f4468&utm_source=V1g3MDY4NTY=&utm_medium=cps&utm_campaign=201905

2.部署教程

2024年最新青龙面板跑脚本教程(一)持续更新中

3.代码如下

Config:    klp_username:        title: 苦力怕论坛用户名        type: text        default""    klp_password:        title: 苦力怕论坛密码        type: text        passwordtrue==/UserConfig== */const MAX_RETRIES = 3;const RETRY_DELAY = 2000;function showNotification(type, title, details = null) {    let notificationText = '';        if (details) {        for (const [key, value] of Object.entries(details)) {            notificationText += `${key}${value}\n`;        }        // 移除最后一个换行符        notificationText = notificationText.trim();    }        GM_notification({        title`${type === 'success' ? '' : type === 'error' ? '❌' : 'ℹ️'} ${title}`,        text: notificationText,        timeout: type === 'error' ? 0 : 0,        highlight: type === 'error'    });}async function retryWrapper(fn, retries = MAX_RETRIES, delay = RETRY_DELAY) {    for (let i = 0; i < retries; i++) {        try {            return await fn();        } catch (error) {            if (i === retries - 1throw error;            await new Promise(resolve => setTimeout(resolve, delay));        }    }}function fetchAPI(url, method, data = null, headers = {}) {    return new Promise((resolve, reject) => {        const defaultHeaders = {            'Content-Type''application/x-www-form-urlencoded',            'Referer'`https://klpbbs.com/`,            'User-Agent': navigator.userAgent        };                const finalHeaders = {...defaultHeaders, ...headers};                GM_xmlhttpRequest({            method: method,            url: url,            data: data,            headers: finalHeaders,            onload(res) => {                if (res.status >= 200 && res.status < 300) {                    resolve({                        text: res.responseText,                        finalUrl: res.finalUrl,                        status: res.status                    });                } else {                    reject(new Error(`请求失败:${res.status}`));                }            },            onerror(err) => reject(err)        });    });}function getFormhash(html) {    const formhashSources = [        /name="formhash" value="([a-f0-9]+)"/,        /formhash=([a-f0-9]+)/,        /k_misign-sign\.html\?formhash=([a-f0-9]+)/    ];    for (const regex of formhashSources) {        const match = html.match(regex);        if (match) {            return match[1];        }    }        try {        const parser = new DOMParser();        const doc = parser.parseFromString(html, 'text/html');        const formhashInput = doc.querySelector('input[name="formhash"]');        if (formhashInput) {            return formhashInput.value;        }    } catch (e) {        // 忽略解析错误    }        return null;}async function detectVersion() {    try {        const indexUrl = `https://klpbbs.com/`;        const response = await fetchAPI(indexUrl, 'GET');                const isMobile = response.text.includes('comiis_app_block') ||                          response.text.includes('comiis_mh_') ||                         response.text.includes('mobile=2');                const isDesktop = response.text.includes('id="toptb"') ||                           response.text.includes('id="fjump_menu"') ||                          response.text.includes('class="wp"');                if (isMobile) {            return {                type'mobile',                loginUrl`https://klpbbs.com/member.php?mod=logging&action=login&mobile=2`,                signUrl`https://klpbbs.com/k_misign-sign.html?mobile=2`,                creditUrl`https://klpbbs.com/home.php?mod=spacecp&ac=credit&op=base&mobile=2`,                creditLogUrl`https://klpbbs.com/home.php?mod=spacecp&ac=credit&op=log&mobile=2`,                profileUrl`https://klpbbs.com/home.php?mod=space&do=profile&mobile=2`            };        } else if (isDesktop) {            return {                type'desktop',                loginUrl`https://klpbbs.com/member.php?mod=logging&action=login`,                signUrl`https://klpbbs.com/k_misign-sign.html`,                creditUrl`https://klpbbs.com/home.php?mod=spacecp&ac=credit&op=base`,                creditLogUrl`https://klpbbs.com/home.php?mod=spacecp&ac=credit&op=log`,                profileUrl`https://klpbbs.com/home.php?mod=space&do=profile`            };        }                return {            type'desktop',            loginUrl`https://klpbbs.com/member.php?mod=logging&action=login`,            signUrl`https://klpbbs.com/k_misign-sign.html`,            creditUrl`https://klpbbs.com/home.php?mod=spacecp&ac=credit&op=base`,            creditLogUrl`https://klpbbs.com/home.php?mod=spacecp&ac=credit&op=log`,            profileUrl`https://klpbbs.com/home.php?mod=space&do=profile`        };    } catch (error) {        return {            type'desktop',            loginUrl`https://klpbbs.com/member.php?mod=logging&action=login`,            signUrl`https://klpbbs.com/k_misign-sign.html`,            creditUrl`https://klpbbs.com/home.php?mod=spacecp&ac=credit&op=base`,            creditLogUrl`https://klpbbs.com/home.php?mod=spacecp&ac=credit&op=log`,            profileUrl`https://klpbbs.com/home.php?mod=space&do=profile`        };    }}async function checkLoginStatus(versionInfo) {    try {        const { profileUrl } = versionInfo;        const profileRes = await fetchAPI(profileUrl, 'GET');                const isLoggedIn = profileRes.text.includes('退出') ||                           profileRes.text.includes('我的中心') ||                          profileRes.text.includes('个人中心') ||                          profileRes.text.includes('修改头像') ||                          profileRes.text.includes('个人资料');                return isLoggedIn;    } catch (error) {        return false;    }}async function checkSignStatus(versionInfo) {    try {        const { signUrl } = versionInfo;        const signPage = await fetchAPI(signUrl, 'GET');        const html = signPage.text;        // 针对手机版的专门检测        if (versionInfo.type === 'mobile') {            // 手机版未签到:有可点击的签到按钮            const notSignedMobile = (html.includes('id="signresult"') &&                                    html.includes('onclick="ajaxsign();"') &&                                    html.includes('>签到<')) ||                                   (html.includes('class="comiis_btn bg_c f_f"') &&                                    html.includes('>签到<'));                        // 手机版已签到:按钮显示"已签到"且没有onclick事件            const signedMobile = html.includes('>已签到<') &&                                (html.includes('class="comiis_btn bg_b f_c"') ||                                 !html.includes('onclick="ajaxsign();"'));            if (notSignedMobile) {                return false;            } else if (signedMobile) {                return true;            }        }        // 使用DOM解析进行更精确的检测        const parser = new DOMParser();        const doc = parser.parseFromString(html, 'text/html');                // 方法1: 检查签到按钮状态        const signButton = doc.querySelector('input[type="submit"][value*="签到"], button[value*="签到"], a[href*="sign"][onclick*="签到"], .sign-btn, #sign-btn, #signresult, .comiis_btn');                // 方法2: 检查已签到提示        const signedText = doc.querySelector('.signed-text, .sign-success, .qiandao-success, .comiis_btn.bg_b');        // 方法3: 检查按钮文本内容        let buttonText = '';        if (signButton) {            buttonText = signButton.textContent || signButton.value || '';        }        // 逻辑判断优先级:明确迹象 > DOM元素 > 文本匹配        if (signButton && !signButton.disabled &&             (buttonText.includes('签到') && !buttonText.includes('已签到'))) {            return false;        }        if (signedText || (signButton && buttonText.includes('已签到'))) {            return true;        }        // 文本匹配(作为备用方案)        const notSignedIndicators = [            /您今天还没有签到/,            /立即签到/,            /class="signbtn"/,            /id="signbtn"/,            /qiandao.*?button/i        ];        const signedIndicators = [            /您的签到排名/,            /今日已签/,            /签到成功/,            /已签到/,            /class="signed"/,            /id="signed"/,            /今天已经签到/        ];        let notSignedCount = notSignedIndicators.filter(indicator =>             indicator.test(html)).length;        let signedCount = signedIndicators.filter(indicator =>             indicator.test(html)).length;        if (notSignedCount > signedCount) {            return false;        } else if (signedCount > notSignedCount) {            return true;        }        // 如果无法确定状态,保守地返回未签到        GM_setValue('last_sign_page', html);        return false;    } catch (error) {        // 出错时返回未签到        return false;    }}async function klpLogin(username, password, versionInfo) {    try {        const { loginUrl, type } = versionInfo;        let formhash, loginhash, loginParams;                const loginPage = await fetchAPI(loginUrl, 'GET');                formhash = getFormhash(loginPage.text);        if (!formhash) {            throw new Error('获取登录令牌失败');        }                loginParams = new URLSearchParams();        loginParams.append('formhash', formhash);        loginParams.append('username', username);        loginParams.append('password', password);                if (type === 'mobile') {            loginhash = loginPage.text.match(/loginhash=([a-zA-Z0-9]{4,})/)?.[1] || '';            loginParams.append('referer'`https://klpbbs.com/?mobile=2`);            loginParams.append('fastloginfield''username');            loginParams.append('cookietime''31104000');            loginParams.append('questionid''0');            loginParams.append('answer''');            loginParams.append('submit''登录');        } else {            loginParams.append('loginsubmit''true');            loginParams.append('handlekey''login');            loginParams.append('referer'`https://klpbbs.com/`);        }                let loginPostUrl;        if (type === 'mobile') {            loginPostUrl = `https://klpbbs.com/member.php?mod=logging&action=login&loginsubmit=yes&loginhash=${loginhash}&inajax=1`;        } else {            loginPostUrl = `https://klpbbs.com/member.php?mod=logging&action=login&loginsubmit=yes&infloat=yes&handlekey=login&inajax=1`;        }                const loginRes = await fetchAPI(            loginPostUrl,            'POST',            loginParams.toString()        );                const isLoggedIn = await checkLoginStatus(versionInfo);                if (!isLoggedIn) {            if (loginRes.text.includes('密码错误')) throw new Error('登录失败:密码错误');            if (loginRes.text.includes('登录受限')) throw new Error('登录失败:尝试次数过多');            if (loginRes.text.includes('安全提问')) throw new Error('登录失败:需要安全提问');            throw new Error('登录失败:未知错误');        }                return true;    } catch (error) {        throw new Error(`苦力怕论坛登录失败: ${error.message}`);    }}async function klpSignIn(versionInfo) {    try {        const { signUrl, type } = versionInfo;                const isAlreadySigned = await checkSignStatus(versionInfo);        if (isAlreadySigned) {            return 'already';        }                const signPage = await fetchAPI(signUrl, 'GET');        let formhash = getFormhash(signPage.text);                if (!formhash) {            const formhashMatch = signPage.text.match(/k_misign-sign\.html\?formhash=([a-f0-9]+)/);            if (formhashMatch) {                formhash = formhashMatch[1];            } else {                throw new Error('获取签到令牌失败');            }        }        let signPostUrl, signData;                // 手机版和桌面版使用不同的签到参数        if (type === 'mobile') {            // 手机版使用ajax方式签到            signPostUrl = `https://klpbbs.com/plugin.php?id=k_misign:sign&operation=qiandao&format=text&formhash=${formhash}&signsubmit=yes&inajax=1`;            signData = `formhash=${formhash}&signsubmit=yes&inajax=1`;        } else {            // 桌面版            signPostUrl = `${signUrl}&operation=qiandao&format=text`;            signData = `formhash=${formhash}&signsubmit=yes`;        }        const signRes = await fetchAPI(            signPostUrl,            'POST',            signData        );        // 增强的签到成功判断        const successIndicators = [            /签到成功/,            /您的签到排名/,            /已连续签到/,            /已签到/,            /window\.location\.reload/        ];        const failIndicators = [            /签到失败/,            /您今天已经签到/,            /formhash错误/,        ];        const isSuccess = successIndicators.some(indicator => indicator.test(signRes.text));        const isFail = failIndicators.some(indicator => indicator.test(signRes.text));        // 无论响应如何,都重新获取签到页面来确认状态        await new Promise(resolve => setTimeout(resolve, 1000)); // 等待1秒让服务器处理        const finalStatus = await checkSignStatus(versionInfo);                if (finalStatus) {            return 'success';        } else if (isSuccess) {            return 'success';        } else if (isFail || isAlreadySigned) {            return 'already';        } else {            return 'fail';        }    } catch (error) {        throw new Error(`苦力怕论坛签到失败: ${error.message}`);    }}async function klpGetCreditInfo(versionInfo) {    try {        const { creditUrl, creditLogUrl, type } = versionInfo;                const creditHtml = await fetchAPI(creditUrl, 'GET');        const creditAmount = parseCreditAmount(creditHtml.text, type);                const creditLogHtml = await fetchAPI(creditLogUrl, 'GET');        const signInfo = parseCreditLogPage(creditLogHtml.text, type);                return {            creditAmount: creditAmount,            lastSignTime: signInfo.lastSignTime,            lastSignReward: signInfo.lastSignReward        };    } catch (error) {        throw new Error(`获取积分信息失败: ${error.message}`);    }}function parseCreditLogPage(html, type) {    const parser = new DOMParser();    const doc = parser.parseFromString(html, 'text/html');        let lastSignTime = '无记录';    let lastSignReward = '无记录';        if (type === 'desktop') {        const rows = doc.querySelectorAll('table tbody tr');        for (let i = 1; i < rows.length; i++) {            const cells = rows[i].querySelectorAll('td');            if (cells.length >= 4) {                const operation = cells[0].textContent.trim();                                if (operation === '每日签到') {                    const rewardSpan = cells[1].querySelector('.xi1');                    if (rewardSpan) {                        lastSignReward = rewardSpan.textContent.trim();                    }                    lastSignTime = cells[3].textContent.trim();                    break;                }            }        }    } else {        const signRows = doc.querySelectorAll('tr');        for (const row of signRows) {            const cells = row.querySelectorAll('td');            if (cells.length >= 4) {                const operation = cells[0].textContent.trim();                                if (operation === '每日签到') {                    const rewardText = cells[1].textContent.trim();                    const rewardMatch = rewardText.match(/铁粒\s*([+-]\d+)/);                    if (rewardMatch) {                        lastSignReward = rewardMatch[1];                    } else {                        const rewardSpan = cells[1].querySelector('.xi1');                        if (rewardSpan) {                            lastSignReward = rewardSpan.textContent.trim();                        }                    }                                        lastSignTime = cells[3].textContent.trim();                    break;                }            }        }                if (lastSignTime === '无记录') {            const mobileItems = doc.querySelectorAll('li.b_b');            for (const item of mobileItems) {                const operationEl = item.querySelector('span.f_d:not(.y)');                const timeEl = item.querySelector('span.y');                const creditEl = item.querySelector('span.xi1');                                if (operationEl && timeEl && creditEl &&                     (operationEl.textContent.includes('打卡签到') || operationEl.textContent.includes('每日签到'))) {                    lastSignTime = timeEl.textContent.trim();                    lastSignReward = creditEl.textContent.trim();                    break;                }            }        }    }        return {        lastSignTime: lastSignTime,        lastSignReward: lastSignReward    };}function parseCreditAmount(html, type) {    const parser = new DOMParser();    const doc = parser.parseFromString(html, 'text/html');        let creditAmount = '未知';        if (type === 'desktop') {        const creditLi = Array.from(doc.querySelectorAll('ul.creditl li'))            .find(li => li.textContent.includes('铁粒'));        if (creditLi) {            const match = creditLi.textContent.match(/铁粒:\s*(\d+)/);            if (match) creditAmount = match[1];        }    } else {        const creditText = Array.from(doc.querySelectorAll('*'))            .map(el => el.textContent)            .find(text => text.includes('铁粒') && /\d+/.test(text));                if (creditText) {            const match = creditText.match(/铁粒\s*[::]?\s*(\d+)/);            if (match) creditAmount = match[1];        }    }        return creditAmount;}(async function() {    'use strict';    const config = {        klp_usernameGM_getValue("Config.klp_username"''),        klp_passwordGM_getValue("Config.klp_password"'')    };    const results = {        klp: {            loginfalse,            signfalse,            creditInfonull,            version'unknown',            isAlreadyLoggedInfalse,            isAlreadySignedfalse,            errors: []        }    };    if (config.klp_username && config.klp_password) {        try {            const versionInfo = await retryWrapper(() => detectVersion());            results.klp.version = versionInfo.type;                        const isLoggedIn = await checkLoginStatus(versionInfo);            results.klp.isAlreadyLoggedIn = isLoggedIn;                        if (isLoggedIn) {                results.klp.login = true;            } else {                await retryWrapper(() => klpLogin(                    config.klp_username                    config.klp_password,                    versionInfo                ));                results.klp.login = true;            }                        const isSigned = await checkSignStatus(versionInfo);            results.klp.isAlreadySigned = isSigned;                        if (isSigned) {                results.klp.sign = 'already';            } else {                const signResult = await retryWrapper(() => klpSignIn(versionInfo));                results.klp.sign = signResult;                                // 签到后再次检查状态以确保准确性                if (signResult === 'success') {                    const finalCheck = await checkSignStatus(versionInfo);                    if (!finalCheck) {                        results.klp.sign = 'uncertain';                    }                }            }                        const creditInfo = await retryWrapper(() => klpGetCreditInfo(versionInfo));            results.klp.creditInfo = creditInfo;                    } catch (error) {            results.klp.errors.push(error.message);        }    } else {        results.klp.errors.push('苦力怕论坛账号密码配置不完整');    }    const klp = results.klp;    // 错误信息单独通知    if (klp.errors.length > 0) {        showNotification('error''苦力怕论坛签到错误', {错误信息: klp.errors.join('; ')});    }    // 正常状态通知(无论是否有错误都显示)    let statusTitle = '苦力怕论坛签到';    let statusType = 'info';    let details = {};    if (klp.creditInfo) {        if (klp.creditInfo.lastSignTime !== '无记录') {            details[' 签到时间'] = klp.creditInfo.lastSignTime;        }        if (klp.creditInfo.lastSignReward !== '无记录') {            details[' 签到奖励'] = klp.creditInfo.lastSignReward;        }        details[' 铁粒余额'] = klp.creditInfo.creditAmount;    }    if (klp.isAlreadySigned || klp.sign === 'already') {        statusTitle = '苦力怕论坛 - 今日已签到';        statusType = 'info';    } else if (klp.sign === 'success') {        statusTitle = '苦力怕论坛 - 签到成功';        statusType = 'success';    } else if (klp.sign === 'uncertain') {        statusTitle = '苦力怕论坛 - 签到状态不确定';        statusType = 'info';    } else if (klp.errors.length === 0) {        statusTitle = '苦力怕论坛 - 签到失败';        statusType = 'info';    }    // 只在没有错误或者有积分信息时显示状态通知    if (klp.errors.length === 0 || klp.creditInfo) {        showNotification(statusType, statusTitle, details);    }})();

解析

该脚本用于自动登录并签到苦力怕论坛(klpbbs.com),同时获取当天签到奖励和账户积分信息。


功能模块
说明
 自动登录
读取已配置的用户名和密码,模拟网页登录。支持桌面版与手机版页面结构。
 自动签到
登录后自动访问签到接口,自动提交签到请求。
 获取积分
登录后抓取账户的积分页与积分日志,提取"铁粒"余额、签到奖励、签到时间。
 重试机制
网络或请求失败时自动重试,最多3次,每次延迟2秒。
 桌面通知
使用 GM_notification 实时弹出登录/签到/奖励状态提示。
 多端兼容
能自动识别论坛页面是手机端还是桌面端,并选择对应的 URL 路径与表单结构。
 异常检测
能检测"登录失败""已签到""签到失败"等多种情况并反馈具体原因。

主要方法

方法名
主要作用
说明
showNotification(type, title, details)
显示桌面通知
根据不同状态(成功/失败/信息)展示通知内容。
retryWrapper(fn, retries, delay)
封装重试机制
捕获错误后按设定次数重新执行函数。
fetchAPI(url, method, data, headers)
统一网络请求封装
使用 GM_xmlhttpRequest 发送 HTTP 请求,支持跨域访问。
getFormhash(html)
提取 formhash
从网页 HTML 中提取 Discuz 登录/签到所需的 token。
detectVersion()
判断手机版或电脑版
检测页面结构,确定对应登录、签到、积分接口的 URL。
checkLoginStatus(versionInfo)
检查登录状态
判断当前页面是否处于已登录状态。
checkSignStatus(versionInfo)
检查是否已签到
解析签到页 HTML 判断是否已签到。
klpLogin(username, password, versionInfo)
自动登录
使用表单 POST 模拟登录论坛账户。
klpSignIn(versionInfo)
自动签到
访问签到接口并提交签到请求。
klpGetCreditInfo(versionInfo)
获取积分信息
读取积分页和积分日志,提取签到奖励与当前积分。
parseCreditLogPage(html, type)
解析积分日志
提取"每日签到"的时间与奖励。
parseCreditAmount(html, type)
解析积分余额
提取当前账户"铁粒"总额。

执行逻辑

启动脚本   读取配置 (用户名+密码)   detectVersion()  判断手机版/电脑版   checkLoginStatus()  已登录?  否  klpLogin()   checkSignStatus()  已签到?  否  klpSignIn()   klpGetCreditInfo()  获取积分余额/签到时间/奖励   showNotification()  弹出结果通知

执行示例

 签到成功

苦力怕论坛 - 签到成功
 签到时间:2025-10-20
 签到奖励:+20 铁粒
 铁粒余额:5890

 今日已签到

苦力怕论坛 - 今日已签到
 签到时间:2025-10-19
 签到奖励:+18 铁粒
 铁粒余额:5870

 登录失败

苦力怕论坛签到错误
错误信息:登录失败:密码错误



注意

本文部分变量已做脱敏处理,仅用于测试和学习研究,禁止用于商业用途,不能保证其合法性,准确性,完整性和有效性,请根据情况自行判断。技术层面需要提供帮助,可以通过打赏的方式进行探讨。


历史脚本txt文件获取>>
服务器搭建,人工服务咨询>>


没有评论:

发表评论

如何用「Deep Research」搞定GTM增长研究

在AI时代,"Deep Research(深度研究)"模式正在成为增长团队的新秘密武器。 在AI时代, "Deep Research(深度研究)"模式 正在成为增长团队的新秘密武器。过去你可能需要花10小时查资料、比对市场、写方案,如今...