UNPKG

koishi-plugin-jrys-fix

Version:
993 lines (974 loc) 30.3 kB
var __create = Object.create; var __defProp = Object.defineProperty; var __getOwnPropDesc = Object.getOwnPropertyDescriptor; var __getOwnPropNames = Object.getOwnPropertyNames; var __getProtoOf = Object.getPrototypeOf; var __hasOwnProp = Object.prototype.hasOwnProperty; var __name = (target, value) => __defProp(target, "name", { value, configurable: true }); var __export = (target, all) => { for (var name2 in all) __defProp(target, name2, { get: all[name2], enumerable: true }); }; var __copyProps = (to, from, except, desc) => { if (from && typeof from === "object" || typeof from === "function") { for (let key of __getOwnPropNames(from)) if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); } return to; }; var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps( // If the importer is in node compatibility mode or this is not an ESM // file that has been converted to a CommonJS file using a Babel- // compatible transform (i.e. "__esModule" has not been set), then set // "default" to the CommonJS "module.exports" for node compatibility. isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target, mod )); var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); // src/index.ts var src_exports = {}; __export(src_exports, { Config: () => Config, apply: () => apply, inject: () => inject, name: () => name }); module.exports = __toCommonJS(src_exports); var import_koishi = require("koishi"); var import_url = require("url"); var import_fs = __toESM(require("fs")); var import_path = __toESM(require("path")); // src/roll.ts var Jrys = class { static { __name(this, "Jrys"); } constructor() { } seededRandom(seed) { const x = Math.sin(seed) * 1e4; return x - Math.floor(x); } // 获取随机运势,范围默认0-100,同一天中运势相同 async getFortune(uid, maxRange = 100) { const etime = (/* @__PURE__ */ new Date()).setHours(0, 0, 0, 0); let userId = Number(uid); const todaySeed = userId * etime % 1000000001; const todayJrys = Math.floor(this.seededRandom(todaySeed) * maxRange); return todayJrys; } // 抽取四个宜不宜 async getRandomObjects(jsonObject, uid) { if (!Array.isArray(jsonObject) || jsonObject.length < 4) { throw new Error("输入必须是一个包含至少四个对象的数组"); } const seed = await this.getFortune(uid); const randomIndexes = /* @__PURE__ */ new Set(); let counter = 0; while (randomIndexes.size < 4) { const randomIndex = Math.floor(this.seededRandom(seed + counter) * jsonObject.length); randomIndexes.add(randomIndex); counter++; } return Array.from(randomIndexes).map((index) => jsonObject[index]); } async random(min, max, luck = 50) { let rmin = min; let rmax = max; if (max < min) { rmin = max; rmax = min; } const mean = luck / 100; const std = 0.12; let a, b; do { a = Math.random(); b = Math.random(); } while (a == 0 || b == 0); let rand = Math.cos(2 * Math.PI * a) * Math.sqrt(-2 * Math.log(b)); rand = rand * std + mean; if (rand > 1) { rand = 2 - rand; } else if (rand < 0) { rand = -rand; } if (rand > 1) { rand = 1; } else if (rand < 0) { rand = 0; } return Math.round(rand * (rmax - rmin) + rmin); } }; // src/signin.ts var timeGreetings = [ { range: [0, 5], message: "晚安" }, { range: [5, 9], message: "早上好" }, { range: [9, 11], message: "上午好" }, { range: [11, 14], message: "中午好" }, { range: [14, 18], message: "下午好" }, { range: [18, 20], message: "傍晚好" }, { range: [20, 24], message: "晚上好" } ]; var defaultLevelInfo = [ { level: 0, levelExp: 0, levelName: "不知名杂鱼", levelColor: "#838383" }, { level: 1, levelExp: 500, levelName: "荒野漫步者", levelColor: "#838383" }, { level: 2, levelExp: 1e3, levelName: "拓荒者", levelColor: "#838383" }, { level: 3, levelExp: 1500, levelName: "冒险家", levelColor: "#838383" }, { level: 4, levelExp: 2e3, levelName: "传说的冒险家", levelColor: "#000000" }, { level: 5, levelExp: 3e3, levelName: "隐秘收藏家", levelColor: "#000000" }, { level: 6, levelExp: 4e3, levelName: "言灵探索者", levelColor: "#42bc05" }, { level: 7, levelExp: 5e3, levelName: "水系魔法师", levelColor: "#42bc05" }, { level: 8, levelExp: 6e3, levelName: "水系魔导师", levelColor: "#42bc05" }, { level: 9, levelExp: 8e3, levelName: "藏书的魔女", levelColor: "#2003da" }, { level: 10, levelExp: 1e4, levelName: "人形图书馆", levelColor: "#2003da" }, { level: 11, levelExp: 15e3, levelName: "文明归档员", levelColor: "#2003da" }, { level: 12, levelExp: 2e4, levelName: "高塔思索者", levelColor: "#03a4da" }, { level: 13, levelExp: 25e3, levelName: "未知探索者", levelColor: "#03a4da" }, { level: 14, levelExp: 3e4, levelName: "背负真相之人", levelColor: "#9d03da" }, { level: 15, levelExp: 35e3, levelName: "守密人", levelColor: "#9d03da" }, { level: 16, levelExp: 4e4, levelName: "被缚的倒吊者", levelColor: "#9d03da" }, { level: 17, levelExp: 45e3, levelName: "崩毁世界之人", levelColor: "#f10171" }, { level: 18, levelExp: 5e4, levelName: "命运眷顾者", levelColor: "#f10171" }, { level: 19, levelExp: 1e5, levelName: "文明领航员", levelColor: "#c9b86d" }, { level: 20, levelExp: 1e6, levelName: "天选之人", levelColor: "#ffd000" } ]; var defaultFortuneInfo = [ { luck: 0, desc: "走平坦的路但会摔倒的程度" }, { luck: 5, desc: "吃泡面会没有调味包的程度" }, { luck: 15, desc: "上厕所会忘记带纸的程度" }, { luck: 20, desc: "上学/上班路上会堵车的程度" }, { luck: 25, desc: "点外卖很晚才会送到的程度" }, { luck: 30, desc: "点外卖会多给予赠品的程度" }, { luck: 35, desc: "出门能捡到几枚硬币的程度" }, { luck: 40, desc: "踩到香蕉皮不会滑倒的程度" }, { luck: 50, desc: "玩滑梯能流畅滑到底的程度" }, { luck: 60, desc: "晚上走森林不会迷路的程度" }, { luck: 70, desc: "打游戏能够轻松过关的程度" }, { luck: 80, desc: "抽卡能够大成功的程度" }, { luck: 95, desc: "天选之人" } ]; var initDatabase = /* @__PURE__ */ __name((ctx) => { ctx.model.extend("jrys", { id: "integer", name: "string", time: "timestamp", exp: "unsigned", signCount: "unsigned" }); }, "initDatabase"); var Signin = class { static { __name(this, "Signin"); } ctx; cfg; constructor(context, config) { this.ctx = context; this.cfg = config; } // 0:签到成功, 1:已签到 // { "status": 1, "getpoint": signpoint, "signTime": signTime, "allpoint": signpoint, "count": 1 }; // 参数:session, 返回:json async callSignin(uid, userid, luck) { const date = /* @__PURE__ */ new Date(); const roll = new Jrys(); const exp = await roll.random(this.cfg.signExp[0], this.cfg.signExp[1], luck); const coin = await roll.random(this.cfg.signCoin[0], this.cfg.signCoin[1], luck); const userData = await this.ctx.database.get("jrys", { id: uid }); if (userData.length === 0) { let accCount = 1; let accExp = exp; this.ctx.database.create("jrys", { id: uid, name: userid, time: date, exp: accExp, signCount: accCount }); this.ctx.monetary.gain(uid, coin, this.cfg.currency); return { status: 0, getExp: exp, allExp: accExp, getCoin: coin, signTime: date, count: accCount }; } if (userData[0].time.getDate() === date.getDate()) { return { status: 1 }; } else { let accExp = userData[0].exp + exp; let accCount = userData[0].signCount + 1; this.ctx.database.set("jrys", { id: uid }, { name: userid, time: date, exp: accExp, signCount: accCount }); this.ctx.monetary.gain(uid, coin, this.cfg.currency); return { status: 0, getExp: exp, allExp: accExp, getCoin: coin, signTime: date, count: accCount }; } } getLevelInfo(exp, info) { let index = 0; for (let i = 0; i < info.length; i++) { if (exp >= info[i].levelExp) { index++; } else { break; } ; } let nExp; if (index >= info.length) { nExp = "???"; } else { nExp = info[index].levelExp; } index--; return { levelInfo: info[index], nextExp: nExp }; } getFortuneInfo(luck, info) { let index = 0; for (let i = 0; i < info.length; i++) { if (luck >= info[i].luck) { index++; } else { break; } ; } ; index--; return info[index].desc; } getGreeting(hour) { const greeting = timeGreetings.find( (timeGreeting) => hour >= timeGreeting.range[0] && hour < timeGreeting.range[1] ); return greeting ? greeting.message : "你好"; } }; // src/event.ts var defaultEventJson = [ { "name": "看直播", "good": "喜欢的V开歌回啦", "bad": "喜欢的V咕了一整天" }, { "name": "打轴", "good": "一次性过", "bad": "谁说话这么难懂" }, { "name": "剪辑", "good": "灵感爆发", "bad": "一团乱麻" }, { "name": "校对", "good": "变成无情的审轴机器", "bad": "被闪轴闪瞎眼" }, { "name": "浏览Pixiv", "good": "发现符合xp的涩图", "bad": "找不到想要的涩图" }, { "name": "打SC", "good": "享受石油佬的乐趣", "bad": "吃土中" }, { "name": "吃人", "good": "你面前这位有成为神龙的潜质", "bad": "这人会用Aegisub吗?" }, { "name": "背单词", "good": "这次六级肯定过", "bad": "背完50个忘了45个" }, { "name": "翘课", "good": "老师不会点名", "bad": "老师准会抽到你来回答问题" }, { "name": "做作业", "good": "做的每个都对", "bad": "做一个做错一个" }, { "name": "锻炼一下身体", "good": "身体健康, 更加性福", "bad": "能量没消耗多少, 吃得却更多" }, { "name": "浏览成人网站", "good": "重拾对生活的信心", "bad": "你会心神不宁" }, { "name": "修复BUG", "good": "你今天对BUG的嗅觉大大提高", "bad": "新产生的BUG将比修复的更多" }, { "name": "上AB站", "good": "还需要理由吗?", "bad": "满屏兄贵亮瞎你的眼" }, { "name": "打LOL", "good": "你将有如神助", "bad": "你会被虐的很惨" }, { "name": "打DOTA", "good": "天梯5000分不是梦", "bad": "你会遇到猪一样的队友" }, { "name": "打DOTA2", "good": "Godlike", "bad": "不怕神一样的对手,就怕猪一样的队友" }, { "name": "穿女装", "good": "你会得到很多炙热的目光", "bad": "被父母看到" }, { "name": "组模型", "good": "今天的喷漆会很完美", "bad": "精神不集中板件被剪断了" }, { "name": "熬夜", "good": "夜间的效率更高", "bad": "明天有很重要的事" }, { "name": "抚摸猫咪", "good": "才不是特意蹭你的呢", "bad": "死开! 愚蠢的人类" }, { "name": "烹饪", "good": "黑暗料理界就由我来打败", "bad": "难道这就是……仰望星空派?" }, { "name": "告白", "good": "其实我也喜欢你好久了", "bad": "对不起, 你是一个好人" }, { "name": "追新番", "good": "完结之前我绝不会死", "bad": "会被剧透" }, { "name": "日麻", "good": "立直一发自摸!", "bad": "碰喵吃喵杠喵荣喵!" }, { "name": "音游", "good": "FCACFRPR不过如此", "bad": "又双叒叕LOST了..." }, { "name": "向大佬请教", "good": "太棒了,学到许多", "bad": "太棒了,什么都没学到" }, { "name": "早起", "good": "迎接第一缕阳光", "bad": "才4点,再睡一会" }, { "name": "早睡", "good": "第二天精神饱满", "bad": "失眠数羊画圈圈" }, { "name": "入正版游戏", "good": "买了痛三天,不买悔三年", "bad": "emmmm,汇率还是……" }, { "name": "补旧作", "good": "意外地对胃口", "bad": "会踩雷" }, { "name": "晾晒老婆(抱枕套)", "good": "天気も晴れココロも晴れ", "bad": "引发路人围观" }, { "name": "不按攻略打", "good": "居然是HAPPY END", "bad": "碰到BAD END" }, { "name": "观赏CG包", "good": "社保。", "bad": "还不去如看游戏剧情" }, { "name": "研究黄油创作理论", "good": "增进鉴赏水平", "bad": "闲适玩家不需要这些" }, { "name": "暴露性癖", "good": "会引来很多趣味相同的变态", "bad": "四斋蒸鹅心" }, { "name": "施法", "good": "传统手艺精进了", "bad": "房间门关好了吗" }, { "name": "刷新作动态", "good": "喜欢的画师发了新图", "bad": "发现游戏跳票" }, { "name": "回味玩过的作品", "good": "重温感动", "bad": "还是先看看新作" }, { "name": "出门走走", "good": "宅久了要发霉", "bad": "太陽が眩しすぎる" }, { "name": "思考人生", "good": "自己的幸福呢?", "bad": "喵喵……喵?" }, { "name": "撸猫", "good": "啊……好爽", "bad": "家里没有猫的洗洗睡吧" }, { "name": "抽卡", "good": "单抽出货", "bad": "到井前一发出货" }, { "name": "拼乐高", "good": "顺利完工", "bad": "发现少了一块零件" }, { "name": "跳槽", "good": "新工作待遇大幅提升", "bad": "待遇还不如之前的" }, { "name": "和女神聊天", "good": "今天天气不错", "bad": "我去洗澡了,呵呵" }, { "name": "写开源库", "good": "今天北斗七星汇聚,裤子造的又快又好", "bad": "写好会发现github上已经有了更好的" }, { "name": "给测试妹子埋个bug", "good": "下辈子的幸福就靠这个bug了", "bad": "妹子会认为你活和代码一样差" }, { "name": "写单元测试", "good": "写单元测试将减少出错", "bad": "写单元测试会降低你的开发效率" }, { "name": "洗澡", "good": "你几天没洗澡了?", "bad": "会把设计方面的灵感洗掉" }, { "name": "白天上线", "good": "今天白天上线是安全的", "bad": "可能导致灾难性后果" }, { "name": "重构", "good": "代码质量得到提高", "bad": "你很有可能会陷入泥潭" }, { "name": "招人", "good": "你面前这位有成为牛人的潜质", "bad": "这人会写程序吗?" }, { "name": "面试", "good": "面试官今天心情很好", "bad": "面试官不爽,会拿你出气" }, { "name": "申请加薪", "good": "老板今天心情很好", "bad": "公司正在考虑裁员" }, { "name": "提交代码", "good": "遇到冲突的几率是最低的", "bad": "会遇到的一大堆冲突" }, { "name": "代码复审", "good": "发现重要问题的几率大大增加", "bad": "你什么问题都发现不了,白白浪费时间" }, { "name": "晚上上线", "good": "晚上是程序员精神最好的时候", "bad": "你白天已经筋疲力尽了" }, { "name": "乘电梯", "good": "正好赶上打卡截止时间", "bad": "电梯超载" }, { "name": "复读", "good": "有时候,人云亦云也是一种生存方式", "bad": "你的对手是鸽子" }, { "name": "肝爆", "good": "努力使人进步,肝爆让人快乐", "bad": "醒醒,限时活动没了" }, { "name": "氪金", "good": "早买早享受,晚买哭着求", "bad": "第二天就 50% off" }, { "name": "卖弱", "good": "楚楚动人更容易打动群友", "bad": "Boy♂next♂door" }, { "name": "唱脑力", "good": "唱一次提神醒脑,唱两次精神百倍", "bad": "会与复读机一起对群聊造成毁灭性打击" }, { "name": "看手元", "good": "从手元中获得一点音游经验", "bad": "会被大佬闪瞎" }, { "name": "录手元", "good": "音游届的未来新星UP主就是你", "bad": "打完歌才发现忘记开录像" }, { "name": "挑战魔王曲", "good": "一上来就是一个新纪录", "bad": "有这点时间还不如干点别的" }, { "name": "咕咕咕", "good": "一时咕一时爽", "bad": "会被抓起来,被群友强迫穿上女装" }, { "name": "与群友水聊", "good": "扶我起来我还能打字", "bad": "一不小心就被大佬闪瞎" }, { "name": "迫害大佬", "good": "迫害是大佬进步的阶梯", "bad": "亲爱的,你号没了" }, { "name": "算命", "good": "算啥都准", "bad": "诸事不宜" }, { "name": "成为魔法少女", "good": "勇敢的烧酒啊快去拯救世界吧!", "bad": "会掉头" }, { "name": "沟通克苏鲁", "good": "奇怪的知识增加了", "bad": "&▓▓▓◆▓▓▓¥#▓@■.◆" }, { "name": "看新番", "good": "你看的这部新番有成为本季度霸权的可能", "bad": "这周更新的是总集篇" }, { "name": "看旧番", "good": "在宅的道路上又前进了一步", "bad": "被剧情喂屎" }, { "name": "看里番", "good": "传统手艺精进了", "bad": "房间门关好了吗?" }, { "name": "看漫画", "good": "正在追的作品十话连发", "bad": "刷到正在追的作品的腰斩停更通知" }, { "name": "看轻小说", "good": "插画很好舔,孩子很满意", "bad": "买插画送的厕纸有啥好看的" }, { "name": "看本子", "good": "被精准戳中性癖", "bad": "更新的全是你不喜欢的类型" }, { "name": "前往女仆咖啡厅", "good": "感受身心上的治愈", "bad": "虚假的女仆只会让你内心更加空虚" }, { "name": "女装Cosplay", "good": "好评如潮", "bad": "照片传到班级群还被认出来" }, { "name": "修仙", "good": "能突破到下一个境界", "bad": "会在进阶中遭受心魔侵蚀" }, { "name": "渡劫", "good": "万事俱备,只待飞升", "bad": "没能扛过去,寿元终" }, { "name": "在妹子面前吹牛", "good": "改善你矮穷挫的形象", "bad": "会被识破" }, { "name": "发超过10条的状态", "good": "显得你很高产", "bad": "会被人直接拉黑" }, { "name": "在B站上传视频", "good": "播放量爆炸", "bad": "没人看" }, { "name": "搬运视频", "good": "会被硬币砸得很爽", "bad": "不会有人看的" }, { "name": "上微博", "good": "今天的瓜不能错过", "bad": "被智障发言糊一脸" }, { "name": "作死", "good": "节目效果一流", "bad": "吾之旧友弔似汝,如今坟头草丈五" }, { "name": "看老黄历", "good": "反正你已经看了", "bad": "反正你已经看了" }, { "name": "学习一门新技能", "good": "有会成为大神的资质", "bad": "可能会误入歧途" }, { "name": "睡懒觉", "good": "避免内存不足", "bad": "早上很早醒来睡不着了" }, { "name": "睡懒觉", "good": "你今天会更有精神", "bad": "会错过重要的事情" }, { "name": "上课玩手机", "good": "会发现好玩的事情", "bad": "会被老师教训" }, { "name": "抄作业", "good": "没有作业抄的学生生活是罪恶的!", "bad": "老师会认真批改,你懂的……" }, { "name": "学习", "good": "你已经几天(月、年)没学习了?", "bad": "会睡着" }, { "name": "出门带伞", "good": "今天下雨你信不信", "bad": "好运气都被遮住了" }, { "name": "走夜路", "good": "偶尔也要一个人静一静", "bad": "有坏人" }, { "name": "补番", "good": "你会后悔没早点看这部番", "bad": "你会后悔看了这部番" }, { "name": "玩Minecraft", "good": "建筑灵感爆发", "bad": "启动器都会崩溃" }, { "name": "上Steam", "good": "愿望单里全是90%off", "bad": "钱包被G胖洗劫一空" }, { "name": "修图", "good": "原片直出毫无压力", "bad": "Photoshop未响应" }, { "name": "赶稿", "good": "完美守住deadline", "bad": "终究还是超期了" }, { "name": "摸鱼", "good": "摸鱼一时爽,一直摸鱼一直爽", "bad": "被老板当场抓获" }, { "name": "入手新游戏", "good": "你会玩的很开心", "bad": "这游戏明天就99%off" }, { "name": "出门", "good": "今天会是个好天气", "bad": "中途突降暴雨" } ]; // src/index.ts var name = "jrys-fix"; var Config = import_koishi.Schema.object({ imgUrl: import_koishi.Schema.string().role("link").description("随机横图api或者本地路径").required(), signExp: import_koishi.Schema.tuple([Number, Number]).description("签到获得经验范围").default([1, 100]), currency: import_koishi.Schema.string().description("Monetary货币名称").default("coin"), signCoin: import_koishi.Schema.tuple([Number, Number]).description("签到获得货币范围").default([1, 100]), levelSet: import_koishi.Schema.array(import_koishi.Schema.object({ level: import_koishi.Schema.number().description("等级"), levelExp: import_koishi.Schema.number().description("等级最低经验"), levelName: import_koishi.Schema.string().description("等级名称"), levelColor: import_koishi.Schema.string().role("color").description("等级颜色") })).role("table").default(defaultLevelInfo).description("经验等级设置: 升序排列 | 最低等级经验必须为0"), fortuneSet: import_koishi.Schema.array(import_koishi.Schema.object({ luck: import_koishi.Schema.number().description("每级最低运势"), desc: import_koishi.Schema.string().description("运势描述") })).role("table").default(defaultFortuneInfo).description("运势值描述信息: 升序排列 | 运势取值0~100, 最低一级必须为0 | 描述信息最长14个中文字符"), event: import_koishi.Schema.array(import_koishi.Schema.object({ name: import_koishi.Schema.string().description("事件名称"), good: import_koishi.Schema.string().description("好的结局"), bad: import_koishi.Schema.string().description("坏的结局") })).role("table").default([{ name: "网购", good: "买到超值好物", bad: "会被坑" }]).description("自定义黄历事件") }); var inject = { "required": ["database", "puppeteer", "monetary"] }; var logger = new import_koishi.Logger("[JRYS]>> "); function apply(ctx, config) { initDatabase(ctx); const signin = new Signin(ctx, config); const jrys = new Jrys(); let eventJson = []; defaultEventJson.forEach((item) => { eventJson.push(item); }); config.event.forEach((item) => { eventJson.push(item); }); ctx.command("jrys", "今日运势").userFields(["id", "name"]).action(async ({ session }) => { const date = /* @__PURE__ */ new Date(); let name2 = ""; if (session.user.name) { name2 = `@${session.user.name}`; } name2 = name2.length > 13 ? name2.substring(0, 12) + "..." : name2; const luck = await jrys.getFortune(session.user.id); const sign = await signin.callSignin(session.user.id, session.author.id, luck); if (sign.status === 1) { return "今天已经签到过了哦~"; } const month = (date.getMonth() + 1).toString().padStart(2, "0"); const day = date.getDate().toString().padStart(2, "0"); const luckInfo = signin.getFortuneInfo(luck, config.fortuneSet); const [gooddo1, gooddo2, baddo1, baddo2] = await jrys.getRandomObjects(eventJson, session.user.id); const hitokoto = await fetchHitokoto(); const greeting = signin.getGreeting(date.getHours()); const levelinfo = signin.getLevelInfo(sign.allExp, config.levelSet); const percent = typeof levelinfo.nextExp == "string" ? "100.000" : (sign.allExp / levelinfo.nextExp * 100).toFixed(3).toString(); let bgUrl; if (config.imgUrl.match(/http(s)?:\/\/(.*)/gi)) { bgUrl = config.imgUrl; } else { bgUrl = (0, import_url.pathToFileURL)(import_path.default.resolve(__dirname, config.imgUrl + import_koishi.Random.pick(await getFolderImg(config.imgUrl)))).href; } let avatarUrl = session.author.avatar; if (avatarUrl == void 0) { avatarUrl = "avatar.png"; } ; const gooddo = `${gooddo1.name}——${gooddo1.good}<br>${gooddo2.name}——${gooddo2.good}`; const baddo = `${baddo1.name}——${baddo1.bad}<br>${baddo2.name}——${baddo2.bad}`; let page; try { let templateHTML = import_fs.default.readFileSync(import_path.default.resolve(__dirname, "./index/template.txt"), "utf-8"); let pageBody = ` <body id="body"> <div class="container"> <img style="width: 100%;" src="${bgUrl}" alt="Top Image"> <div class="header"> <img class="avatar" src="${avatarUrl}" alt="Avatar"> <div class="dateInfo"> <span class="greeting">${greeting}</span> <span style="color: #666666;">${month}/${day}</span> </div> </div> <div class="hitokoto"> <p>${hitokoto}</p> </div> <div class="content"> <div class="signin"><strong>${name2}</strong> 签到成功!🫧+${sign.getExp} 🪙+${sign.getCoin}</div> <div class="levelInfo"> <span style="color: ${levelinfo.levelInfo.levelColor};">${levelinfo.levelInfo.levelName}</span> <span style="color: #b4b1b1;">${sign.allExp}/${levelinfo.nextExp}</span> </div> <div class="level-bar"> <div class="bar-container"> <div class="progress" style="width: calc(${percent}%);"></div> </div> </div> <div class="fortune"> <span style="font-size: 36px; font-weight: bold;">🍀${luck}</span> <span style="font-size: 28px; color: #838383;">🌠${luckInfo}</span> </div> <hr> <div class="toDo"> <div class="toDoBg" style="background-color: #D4473D;"><span>宜</span></div> <p style="text-shadow: 0px 0px 1px #ffbbbb;">${gooddo}</p> </div> <div class="toDo"> <div class="toDoBg" style="background-color: #000000;"><span>忌</span></div> <p style="text-shadow: 0px 0px 1px #bcdbff;">${baddo}</p> </div> </div> <div class="credit"> 随机生成 请勿迷信 | NyaKoishi © 2024 </div> </div> </body> </html>`; await import_fs.default.writeFileSync(import_path.default.resolve(__dirname, "./index/index.html"), templateHTML + pageBody); page = await ctx.puppeteer.page(); await page.setViewport({ width: 600, height: 1080 * 2 }); await page.goto(`file:///${import_path.default.resolve(__dirname, "./index/index.html")}`); await page.waitForSelector("#body"); const element = await page.$("#body"); let msg; if (element) { const imgBuf = await element.screenshot({ encoding: "binary" }); msg = import_koishi.h.image(imgBuf, "image/png"); } else { msg = "Failed to capture screenshot."; } await page.close(); return import_koishi.h.quote(session.event.message.id) + msg; } catch (err) { logger.error(`[JRYS Error]:\r ` + err); return "哪里出的问题!md跟你爆了"; } }); } __name(apply, "apply"); async function getFolderImg(folder) { let imgfilename = await readFilenames(folder); const filteredArr = imgfilename.filter((filename) => { return /\.(png|jpg|jpeg|ico|svg|webp)$/i.test(filename); }); return filteredArr; } __name(getFolderImg, "getFolderImg"); async function readFilenames(dirPath) { let filenames = []; const files = import_fs.default.readdirSync(dirPath); files.forEach((filename) => { const fullPath = import_path.default.join(dirPath, filename); if (import_fs.default.statSync(fullPath).isDirectory()) { filenames = filenames.concat(readFilenames(fullPath)); } else { filenames.push(filename); } }); return filenames; } __name(readFilenames, "readFilenames"); async function fetchHitokoto() { try { const response = await fetch("https://v1.hitokoto.cn/?c=a&c&b&k"); const { hitokoto: hitokotoText, from: fromText, from_who: fromWhoText } = await response.json(); let hitokoto; if (fromWhoText != null) { hitokoto = `『${hitokotoText}』<br>——&nbsp;${fromWhoText}${fromText}」`; } else { hitokoto = `『${hitokotoText}』<br>——「${fromText}」`; } return hitokoto; } catch (error) { console.error("获取 hitokoto 时出错:", error); return "无法获取 hitokoto"; } } __name(fetchHitokoto, "fetchHitokoto"); // Annotate the CommonJS export names for ESM import in node: 0 && (module.exports = { Config, apply, inject, name });