diff --git a/CHANGELOG.md b/CHANGELOG.md index c6ddab3..fb1b83e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +# 1.1.4 +* 新增指令`#米游币全部签到` + *为所有存在的stoken进行社区米游币签到 +* 新增指令`#米社全部签到` + *为所有用户进行其余的社区模块签到 +* 新增自动签到默认**00:02**开始执行签到 + *具体时间修改在`./config/config.yaml` # 1.1.3 * 下列功能需要绑定`cookies`来跑,非信任的bot请勿发送cookies * 修正版本说明避免误导 @@ -17,12 +24,6 @@ * 如果出现了安装其中一个包导致另外的包出问题的请群里询问 * 具体获取cookie教程后续会完善 敬情期待~ * 需要完整的cookie内容要包含`login_ticket`跟`login_uid`不然是无法实现米游社签到的 -* 自动签到逻辑目前还在梳理中..... - -# 1.1.1 -* 初步兼容V3版本 -* 版本兼容问题V2报错的话请导入`yaml`包 指令 `cnpm i yaml` -* V3版本请在cmd命令窗口追加`date-format`包 指令`pnpm i date-format` # 1.1.0 * 增加`#图鉴帮助`用于查看帮助命令 diff --git a/apps/index.js b/apps/index.js index 7c2e416..903f02f 100644 --- a/apps/index.js +++ b/apps/index.js @@ -1,4 +1,5 @@ import lodash from "lodash"; +import schedule from "node-schedule"; import { AtlasAlias } from "./xiaoyao_image.js"; @@ -7,8 +8,10 @@ import { help } from "./help.js"; import { - Note,DailyNoteTask, - Note_appoint,pokeNote + Note, + DailyNoteTask, + Note_appoint, + pokeNote } from "./Note.js"; import { rule as adminRule, @@ -21,18 +24,31 @@ import { } from "../components/Changelog.js"; import { rule as signRule, - sign,mysSign,cookiesDocHelp + sign, + mysSign, + cookiesDocHelp, + allMysSign, + allSign } from "./sign.js" export { updateRes, - updateMiaoPlugin,sign, + updateMiaoPlugin, + sign, versionInfo, - Note_appoint,pokeNote,cookiesDocHelp, + Note_appoint, + pokeNote, + cookiesDocHelp, sysCfg, - help,DailyNoteTask, + help, + DailyNoteTask, + allMysSign, + allSign, AtlasAlias, - Note,mysSign + Note, + mysSign }; +import gsCfg from '../model/gsCfg.js'; +const _path = process.cwd(); let rule = { versionInfo: { @@ -68,7 +84,16 @@ lodash.forEach(rule, (r) => { r.prehash = true; r.hashMark = true; }); +task(); +//定时任务 +async function task() { + if (typeof test != "undefined") return; + let set = gsCfg.getfileYaml(`${_path}/plugins/xiaoyao-cvs-plugin/config/`, "config") + schedule.scheduleJob(set.mysBbsTime, () => allMysSign()); + schedule.scheduleJob(set.allSignTime, () => allSign()); +} + export { rule -}; \ No newline at end of file +}; diff --git a/apps/sign.js b/apps/sign.js index 5c819d3..bc93e8d 100644 --- a/apps/sign.js +++ b/apps/sign.js @@ -11,6 +11,7 @@ import { isV3 } from '../components/Changelog.js'; import gsCfg from '../model/gsCfg.js'; +import fs from "fs"; export const rule = { mysSign: { @@ -18,9 +19,17 @@ export const rule = { describe: "米游社米游币签到(理论上会签到全部所以区分开了)" }, sign: { - reg: "^#*(崩坏3|崩坏2|未定事件簿|大别野|崩坏星穹铁道|绝区零)签到$", + reg: "^#*(崩坏3|崩坏2|未定事件簿)签到$", describe: "米社规则签到" }, + allMysSign: { + reg: "^#米游币全部签到$", + describe: "米游币全部签到" + }, + allSign: { + reg: "^#米社全部签到$", + describe: "米社全部签到" + }, cookiesDocHelp: { reg: "^#*(米游社|cookies|米游币)帮助$", describe: "cookies获取帮助" @@ -37,23 +46,30 @@ const RETRY_OPTIONS = { }; export async function sign(e) { - let isck=await cookie(e); - if (!isck) { + let { + skuid + } = await getCookie(e); + if (!skuid) { + e.reply("请先绑定cookie~\n发送【cookie帮助】获取教程") return true; } + START = moment().unix(); let miHoYoApi = new MihoYoApi(e); - let resultMessage=""; + let resultMessage = ""; let msg = e.msg.replace(/#|签到|井|米游社|mys|社区/g, ""); let ForumData = await getDataList(msg); e.reply(`开始尝试${msg}签到预计${msg=='全部'?"60":"5-10"}秒~`) for (let forum of ForumData) { + if (!(["崩坏3", "崩坏2", "未定事件簿"].includes(forum.name))) { + continue; + } resultMessage += `**${forum.name}**\n` try { // 1 BBS Sign let resObj = await promiseRetry((retry, number) => { - Bot.logger.info(`开始签到: [${forum.name}] 尝试次数: ${number}`); - return miHoYoApi.honkai3rdSignTask(msg).catch((e) => { + // Bot.logger.info(`开始签到: [${forum.name}] 尝试次数: ${number}`); + return miHoYoApi.honkai3rdSignTask(forum.name).catch((e) => { Bot.logger.error(`${forum.name} 签到失败: [${e.message}] 尝试次数: ${number}`); return retry(e); }); @@ -64,26 +80,26 @@ export async function sign(e) { Bot.logger.error(`${forum.name} 签到失败 [${e.message}]`); resultMessage += `签到失败: [${e.message}]\n`; } - + await utils.randomSleepAsync(); } - await replyMsg(e,resultMessage); + await replyMsg(e, resultMessage); return true } export async function mysSign(e) { - let isck=await cookie(e); + let isck = await cookie(e); if (!isck) { return true; } - let iscount=""; + let iscount = ""; let miHoYoApi = new MihoYoApi(e); - if(Object.keys((await miHoYoApi.getStoken(e.user_id))).length == 0){ + if (Object.keys((await miHoYoApi.getStoken(e.user_id))).length == 0) { e.reply("未读取到stoken请尝试重新登录获取cookies") return true; } - + START = moment().unix(); - let resultMessage=""; + let resultMessage = ""; // Execute task let msg = e.msg.replace(/#|签到|井|米游社|mys|社区/g, ""); let ForumData = await getDataList(msg); @@ -93,7 +109,7 @@ export async function mysSign(e) { try { // 1 BBS Sign let resObj = await promiseRetry((retry, number) => { - Bot.logger.info(`开始签到: [${forum.name}] 尝试次数: ${number}`); + // Bot.logger.info(`开始签到: [${forum.name}] 尝试次数: ${number}`); return miHoYoApi.forumSign(forum.forumId).catch((e) => { Bot.logger.error(`${forum.name} 签到失败: [${e.message}] 尝试次数: ${number}`); return retry(e); @@ -105,7 +121,6 @@ export async function mysSign(e) { Bot.logger.error(`${forum.name} 签到失败 [${e.message}]`); resultMessage += `签到失败: [${e.message}]\n`; } - await utils.randomSleepAsync(); } for (let forum of ForumData) { @@ -113,7 +128,7 @@ export async function mysSign(e) { try { // 2 BBS list post let resObj = await promiseRetry((retry, number) => { - Bot.logger.info(`读取帖子列表: [${forum.name}] 尝试次数: ${number}`); + // Bot.logger.info(`读取帖子列表: [${forum.name}] 尝试次数: ${number}`); return miHoYoApi.forumPostList(forum.forumId).catch((e) => { Bot.logger.error(`${forum.name} 读取帖子列表失败: [${e.message}] 尝试次数: ${number}`); return retry(e); @@ -126,31 +141,31 @@ export async function mysSign(e) { post = post.post; // 2.1 BBS read post let resObj = await promiseRetry((retry, number) => { - Bot.logger.info(`读取帖子: [${post.subject}] 尝试次数: ${number}`); + // Bot.logger.info(`读取帖子: [${post.subject}] 尝试次数: ${number}`); return miHoYoApi.forumPostDetail(post['post_id']).catch((e) => { Bot.logger.error(`${forum.name} 读取帖子失败: [${e.message}] 尝试次数: ${number}`); return retry(e); }); }, RETRY_OPTIONS); - Bot.logger.info(`${forum.name} [${post.subject}] 读取成功 [${resObj.message}]`); + // Bot.logger.info(`${forum.name} [${post.subject}] 读取成功 [${resObj.message}]`); await utils.randomSleepAsync(); // 2.2 BBS vote post resObj = await promiseRetry((retry, number) => { - Bot.logger.info(`点赞帖子: [${post.subject}] 尝试次数: ${number}`); + // Bot.logger.info(`点赞帖子: [${post.subject}] 尝试次数: ${number}`); return miHoYoApi.forumPostVote(post['post_id']).catch((e) => { Bot.logger.error(`${forum.name} 点赞帖子失败: [${e.message}] 尝试次数: ${number}`); return retry(e); }); }, RETRY_OPTIONS); - Bot.logger.info(`${forum.name} [${post.subject}] 点赞成功 [${resObj.message}]`); + // Bot.logger.info(`${forum.name} [${post.subject}] 点赞成功 [${resObj.message}]`); await utils.randomSleepAsync(); } // 2.3 BBS share post let sharePost = postList[0].post; resObj = await promiseRetry((retry, number) => { - Bot.logger.info(`分享帖子: [${sharePost.subject}] 尝试次数: ${number}`); + // Bot.logger.info(`分享帖子: [${sharePost.subject}] 尝试次数: ${number}`); return miHoYoApi.forumPostShare(sharePost['post_id']).catch((e) => { Bot.logger.error(`${forum.name} 分享帖子失败: [${e.message}] 尝试次数: ${number}`); return retry(e); @@ -163,21 +178,21 @@ export async function mysSign(e) { resultMessage += `读帖点赞分享: 成功\n`; await utils.randomSleepAsync(); } - await replyMsg(e,resultMessage); + await replyMsg(e, resultMessage); return true } -async function replyMsg(e,resultMessage){ +async function replyMsg(e, resultMessage) { const END = moment().unix(); Bot.logger.info(`运行结束, 用时 ${END - START} 秒`); resultMessage += `\n用时 ${END - START} 秒`; e.reply(resultMessage); } -async function getDataList(name){ +async function getDataList(name) { let ForumData = Data.readJSON(`${_path}/plugins/xiaoyao-cvs-plugin/defSet/json`, "mys") - for(let item of ForumData){ - if(item.name==name){ //循环结束未找到的时候返回原数组签到全部 + for (let item of ForumData) { + if (item.name == name) { //循环结束未找到的时候返回原数组签到全部 return [item] } } @@ -185,50 +200,143 @@ async function getDataList(name){ } async function cookie(e) { - let cookie, uid; + let { + cookie, + uid + } = await getCookie(e); let miHoYoApi = new MihoYoApi(e); let skuid; - let cookiesDoc=await getcookiesDoc(); - if (isV3) { - skuid= await gsCfg.getBingCookie(e.user_id); - cookie = skuid.ck; - uid = skuid.item; - } else { - if (NoteCookie[e.user_id]) { - cookie = NoteCookie[e.user_id].cookie; - uid = NoteCookie[e.user_id].uid; - } else if (BotConfig.dailyNote && BotConfig.dailyNote[e.user_id]) { - cookie = BotConfig.dailyNote[e.user_id].cookie; - uid = BotConfig.dailyNote[e.user_id].uid; - } - } - if(!cookie){ - e.reply("cookie失效请重新绑定~【教程】\n"+cookiesDoc) + let cookiesDoc = await getcookiesDoc(); + + if (!cookie) { + e.reply("cookie失效请重新绑定~【教程】\n" + cookiesDoc) return false; } - e.uid = uid; - e.cookie=cookie; - if(Object.keys((await miHoYoApi.getStoken(e.user_id))).length != 0){ + + if (Object.keys((await miHoYoApi.getStoken(e.user_id))).length != 0) { return true; } - if (!cookie.includes("login_ticket")&&(isV3&&!skuid?.login_ticket)) { - e.reply("米游社登录cookie不完整,请前往米游社通行证处重新获取cookie~\ncookies必须包含login_ticket【教程】 "+cookiesDoc) + if (!cookie.includes("login_ticket") && (isV3 && !skuid?.login_ticket)) { + e.reply("米游社登录cookie不完整,请前往米游社通行证处重新获取cookie~\ncookies必须包含login_ticket【教程】 " + cookiesDoc) return false; } let flot = (await miHoYoApi.stoken(cookie, e)); // console.log(flot) - await utils.sleepAsync(1000); //延迟加载防止文件未生成 + await utils.sleepAsync(1000); //延迟加载防止文件未生成 if (!flot) { e.reply("登录失效请重新登录获取cookie发送机器人~") return false; } return true; } -export async function cookiesDocHelp(e){ - let cookiesDoc=await getcookiesDoc() - e.reply("【cookies帮助】"+cookiesDoc+"\ncookies必须包含login_ticket获取后请私发机器人"); +async function getCookie(e) { + let skuid, cookie, uid + if (isV3) { + skuid = await gsCfg.getBingCookie(e.user_id); + cookie = skuid.ck; + uid = skuid.item; + } else { + if (NoteCookie[e.user_id]) { + cookie = NoteCookie[e.user_id].cookie; + uid = NoteCookie[e.user_id].uid; + skuid = NoteCookie[e.user_id]; + } else if (BotConfig.dailyNote && BotConfig.dailyNote[e.user_id]) { + cookie = BotConfig.dailyNote[e.user_id].cookie; + uid = BotConfig.dailyNote[e.user_id].uid; + skuid = BotConfig.NoteCookie[e.user_id]; + } + } + e.uid = uid; + e.cookie = cookie; + return { + cookie, + uid, + skuid + } +} +export async function cookiesDocHelp(e) { + let cookiesDoc = await getcookiesDoc() + e.reply("【cookies帮助】" + cookiesDoc + "\ncookies必须包含login_ticket获取后请私发机器人"); return true } -async function getcookiesDoc(){ - return await gsCfg.getfileYaml(`${_path}/plugins/xiaoyao-cvs-plugin/config/`,"config").cookiesDoc +async function getcookiesDoc() { + return await gsCfg.getfileYaml(`${_path}/plugins/xiaoyao-cvs-plugin/config/`, "config").cookiesDoc +} +//定时米社米币签到任务 +export async function allMysSign() { + Bot.logger.mark(`开始米社签到任务`); + let stoken = await gsCfg.getBingStoken(); + let isPushSign = await gsCfg.getfileYaml(`${_path}/plugins/xiaoyao-cvs-plugin/config/`, "config").isPushSign + //获取需要签到的用户 + for (let data of stoken) { + let user_id = data.qq; + Bot.logger.mark(`正在为qq${user_id}签到`); + let e = { + user_id, + isTask: true + }; + e.cookie = `stuid=${data.stuid};stoken=${data.stoken};ltoken=${data.ltoken};`; + e.msg = "全部" + //已签到不重复执行 + let key = `genshin:mys:signed_bbs:${user_id}`; + if (await redis.get(key)) { + continue; + } + + e.reply = (msg) => { + //关闭签到消息推送 + if (!isPushSign) { + return; + } + + if (msg.includes("签到成功") && (cookie.isSignPush === true || cookie.isSignPush === undefined)) { + // msg = msg.replace("签到成功", "自动签到成功"); + utils.relpyPrivate(user_id, msg + "\n自动签到成功"); + } + }; + + await mysSign(e); + await utils.sleepAsync(10000); + } + Bot.logger.mark(`签到任务完成`); + return true +} + +//定时签到任务 +export async function allSign() { + Bot.logger.mark(`开始米社签到任务`); + let isPushSign = await gsCfg.getfileYaml(`${_path}/plugins/xiaoyao-cvs-plugin/config/`, "config").isAllSign + let userIdList = []; + if (isV3) { + let dir = './data/MysCookie/' + let files = fs.readdirSync(dir).filter(file => file.endsWith('.yaml')) + userIdList = (files.join(",").replace(/.yaml/g, "").split(",")) + } else { + for (let [user_id, cookie] of Object.entries(NoteCookie)) { + userIdList.push(user_id) + } + } + for (let qq of userIdList) { + let user_id = qq; + let e = { + user_id, + qq, + isTask: true + }; + e.msg="全部" + e.reply = (msg) => { + if (!msg.includes("OK")) { + return; + } + if (!isAllSign) { + return; + } + if (msg.includes("签到成功") && (cookie.isSignPush === true || cookie.isSignPush === undefined)) { + utils.relpyPrivate(qq, msg + "\n自动签到成功"); + } + }; + await sign(e); + await utils.sleepAsync(10000); + } + Bot.logger.mark(`签到任务完成`); } diff --git a/config/config.yaml b/config/config.yaml index 4f4fe4f..f889d3e 100644 --- a/config/config.yaml +++ b/config/config.yaml @@ -1,2 +1,10 @@ # cookies教程 -cookiesDoc: docs.qq.com/doc/DV2tDY2ltSFdtbU9z \ No newline at end of file +cookiesDoc: docs.qq.com/doc/DV2tDY2ltSFdtbU9z +# 米币签到成功是否推送 +isPushSign: false +# 米游社米币签到定时任务,Cron表达式,默认00:02开始执行签到 +mysBbsTime: 0 2 0 * * ? +# 签到成功是否推送 +isAllSign: false +# 米游社签到定时任务,Cron表达式,默认00:02开始执行签到 +allSignTime: 0 2 0 * * ? diff --git a/model/gsCfg.js b/model/gsCfg.js index f65ee9f..51641df 100644 --- a/model/gsCfg.js +++ b/model/gsCfg.js @@ -133,7 +133,27 @@ class GsCfg { ckQQ } } + /** 读取所有用户绑定的stoken */ + async getBingStoken() { + let ck = [] + let ckQQ = {} + let dir = `plugins/${plugin}/data/yaml/` + let files = fs.readdirSync(dir).filter(file => file.endsWith('.yaml')) + const readFile = promisify(fs.readFile) + + let promises = [] + + files.forEach((v) => promises.push(readFile(`${dir}${v}`, 'utf8'))) + const res = await Promise.all(promises) + res.forEach((v,index) => { + let tmp = YAML.parse(v) + tmp["qq"]=files[index].split(".")[0]*1 + ck.push(tmp) + + }) + return ck + } getBingCkSingle(userId) { let file = `./data/MysCookie/${userId}.yaml` try { diff --git a/model/mys/mihoyo-api.js b/model/mys/mihoyo-api.js index beb01c5..a37a809 100644 --- a/model/mys/mihoyo-api.js +++ b/model/mys/mihoyo-api.js @@ -23,7 +23,7 @@ const boards = { forumid: 1, key: 'honkai3rd', biz: 'bh3_cn', - actid: 'ea20211026151532', + actid: 'e202207181446311', name: '崩坏3', url: "https://bbs.mihoyo.com/bh3/", getReferer() { @@ -82,30 +82,31 @@ export default class MihoYoApi { constructor(e) { if (e) { this.e = e - this.cookie=e.cookie + this.cookie = e.cookie this.userId = String(e.user_id) this.msgName = e.msg.replace(/#|签到|井|米游社|mys|社区/g, "") + // //初始化配置文件 + let data = this.getStoken(this.e.user_id); + if (data) { + this.cookies = `stuid=${data.stuid};stoken=${data.stoken};ltoken=${data.ltoken};`; + } } Data.createDir("", YamlDataUrl, false); - // //初始化配置文件 - let data = this.getStoken(this.e.user_id); - if(data){ - this.cookies = `stuid=${data.stuid};stoken=${data.stoken};ltoken=${data.ltoken};`; - } + } - getbody() { + getbody(name) { for (let item in boards) { - if (boards[item].name === this.msgName) { + if (boards[item].name === name) { return boards[item] } } } async honkai3rdSignTask(name) { - let kkbody = this.getbody(); + let kkbody = this.getbody(name); try { // 获取账号信息 - const objData= await this.getUserInfo(kkbody) - if(objData.retcode!=200) { + const objData = await this.getUserInfo(kkbody) + if (objData.retcode != 200) { return objData } if (!objData.nickname) { @@ -174,7 +175,7 @@ export default class MihoYoApi { return ""; } - + async forumPostList(forumId) { const url = `https://api-takumi.mihoyo.com/post/api/getForumPostList?forum_id=${forumId}&is_good=false&is_hot=false&page_size=20&sort_type=1`; @@ -332,7 +333,7 @@ export default class MihoYoApi { .getpubHeaders(board)).timeout(10000); let resObj = JSON.parse(res.text); let data = resObj.data - if(resObj.retcode!=0){ + if (resObj.retcode != 0) { return resObj } const game_uid = data?.list?. [0]?.game_uid @@ -341,26 +342,26 @@ export default class MihoYoApi { return { game_uid, region, - nickname,retcode:200 + nickname, + retcode: 200 } } // 游戏签到操作 async postSign(board, game_uid, region) { - let web_api=`https://api-takumi.mihoyo.com` + let web_api = `https://api-takumi.mihoyo.com` let url = - `${web_api}/common/eutheniav2/sign` - if(board.name=="原神"){ - url=`${web_api}/event/bbs_sign_reward/sign` - } - if(board.name=="崩坏2"||board.name=="未定事件簿"){ - url=`${web_api}/event/luna/info?lang=zh-cn` - } - url+=`?region=${region}&act_id=${board.actid}&uid=${game_uid}` - // if(board.name==="崩坏3"){ - // url=`https://webstatic.mihoyo.com/bh3/event/signin-cn/index.html?bbs_presentation_style=fullscreen&bbs_game_role_required=bh3_cn&bbs_auth_required=true&act_id=${board.actid}&utm_source=bbs&utm_medium=mys&utm_campaign=icon` - // } - // console.log(url) - // console.log(this.e) + `${web_api}/event/luna/sign` + if (board.name == "原神") { + url = `${web_api}/event/bbs_sign_reward/sign` + } + if (board.name == "崩坏2" || board.name == "未定事件簿") { + url = `${web_api}/event/luna/info?lang=zh-cn` + } + url += `?region=${region}&act_id=${board.actid}&uid=${game_uid}` + // if (board.name === "崩坏3") { + // url = `${web_api}/event/luna/info?lang=zh-cn®ion=${region}&act_id=${board.actid}&uid=${game_uid}` + // } + // console.log(this.e) let res = await superagent.post(url).set(this.getpubHeaders(board)).timeout(10000); let resObj = JSON.parse(res.text); return resObj diff --git a/model/mys/utils.js b/model/mys/utils.js index 07eb7a1..8fe9892 100644 --- a/model/mys/utils.js +++ b/model/mys/utils.js @@ -21,9 +21,23 @@ export function randomString(length){ } return randomStr; } - + /** + * 发送私聊消息,仅给好友发送 + * @param user_id qq号 + * @param msg 消息 + */ +export async function relpyPrivate (userId, msg) { + userId = Number(userId) + let friend = Bot.fl.get(userId) + if (friend) { + logger.mark(`发送好友消息[${friend.nickname}](${userId})`) + return await Bot.pickUser(userId).sendMsg(msg).catch((err) => { + logger.mark(err) + }) + } +} export default { sleepAsync, randomSleepAsync, - randomString + randomString,relpyPrivate }