diff --git a/apps/各种通知.js b/apps/各种通知.js new file mode 100644 index 0000000..217e65d --- /dev/null +++ b/apps/各种通知.js @@ -0,0 +1,1058 @@ +/* + * @作者: 超市椰羊(746659424) + * @介绍: 提供账号的一些事件通知,如:闪照,撤回,好友申请,群邀请,群|好友列表变动... + * @使用: 可用 "通知帮助" 来查看指令 + * @可用指令来开启或关闭某项功能 或 直接修改配置文件(生成在当前文件夹下可参考655行的注释来修改配置文件)修改后重启或用指令来刷新配置 + */ +import plugin from '../../lib/plugins/plugin.js' +import { segment } from 'oicq' +import cfg from '../../lib/config/config.js' +import common from '../../lib/common/common.js' +import fs from 'fs' + +let config = {} + +const ROLE_MAP = { + admin: '群管理', + owner: '群主', + member: '群员' +} + +/** 好友通知 */ +export class Friends extends plugin { + constructor() { + super({ + name: '好友通知', + dsc: '好友通知', + event: 'notice.friend', + priority: 5000 + }) + } + + async accept(e) { + let msg + let forwardMsg + switch (e.sub_type) { + case 'increase': { + if (!config.friendNumberChange) return + msg = [ + segment.image(`https://q1.qlogo.cn/g?b=qq&s=100&nk=${e.user_id}`), + '[通知 - 新增好友]\n', + `好友QQ:${e.user_id}\n`, + `好友昵称:${e.nickname}` + ] + break + } + case 'decrease': { + if (!config.friendNumberChange) return + msg = [ + segment.image(`https://q1.qlogo.cn/g?b=qq&s=100&nk=${e.user_id}`), + '[通知 - 好友减少]\n', + `好友QQ:${e.user_id}\n`, + `好友昵称:${e.nickname}` + ] + break + } + case 'recall': { + if (!config.PrivateRecall) return + + if (e.user_id == cfg.qq) return + + if (cfg.masterQQ.includes(e.user_id)) return + + // 读取 + let res = JSON.parse( + await redis.get(`notice:messagePrivate:${e.message_id}`) + ) + // 无数据 return + if (!res) return + // 撤回为闪照处理 + if (res[0].type === 'flash') { + let url = res[0].url + res = ['[闪照]\n', '撤回闪照:', segment.image(url)] + } else if (res[0].type === 'record') { + // 语音 + forwardMsg = segment.record(res[0].url) + res = '[语音]' + } else if (res[0].type === 'video') { + // 视频 + forwardMsg = segment.video(res[0].file) + res = '[视频]' + } else if (res[0].type === 'xml') { + // 合并消息 + forwardMsg = res + res = '[合并消息]' + } + // 消息 + msg = [ + segment.image(`https://q1.qlogo.cn/g?b=qq&s=100&nk=${e.user_id}`), + '[消息 - 好友撤回消息]\n', + `好友QQ:${e.user_id}\n`, + `撤回时间:${formatDate(e.time)}\n`, + '撤回消息:', + ...res + ] + break + } + case 'poke': { + if (!config.privateMessage) return + msg = [ + segment.image(`https://q1.qlogo.cn/g?b=qq&s=100&nk=${e.user_id}`), + '[消息 - 戳一戳]\n', + `来源QQ:${e.user_id}` + ] + break + } + default: + return + } + await getSend(msg) + if (forwardMsg) { + await getSend(forwardMsg) + } + } +} + +/** 群通知 */ +export class newgroups extends plugin { + constructor() { + super({ + name: '群通知', + dsc: '群通知', + event: 'notice.group' + }) + } + + async accept(e) { + let msg + let forwardMsg + switch (e.sub_type) { + case 'increase': { + if (e.user_id === cfg.qq) { + if (!config.groupNumberChange) return + msg = [ + segment.image( + `https://p.qlogo.cn/gh/${e.group_id}/${e.group_id}/100` + ), + '[通知 - 新增群聊]\n', + `新增群号:${e.group_id}` + ] + } else { + if (!config.groupMemberNumberChange) return + msg = [ + segment.image( + `https://p.qlogo.cn/gh/${e.group_id}/${e.group_id}/100` + ), + '[通知 - 新增群员]\n', + `群号:${e.group_id}\n`, + `新成员QQ:${e.user_id}\n`, + `新成员昵称:${e.nickname}` + ] + } + break + } + case 'decrease': { + if (e.dismiss) { + if (!config.groupNumberChange) return + msg = [ + segment.image( + `https://p.qlogo.cn/gh/${e.group_id}/${e.group_id}/100` + ), + '[通知 - 群聊被解散]\n', + `操作人QQ:${e.operator_id}\n`, + `解散群号:${e.group_id}` + ] + } else if (e.user_id === cfg.qq && e.operator_id !== cfg.qq) { + if (!config.groupNumberChange) return + msg = [ + segment.image( + `https://p.qlogo.cn/gh/${e.group_id}/${e.group_id}/100` + ), + '[通知 - 机器人被踢]\n', + `操作人QQ:${e.operator_id}\n`, + `被踢群号:${e.group_id}` + ] + } else if (e.user_id === cfg.qq && e.operator_id === cfg.qq) { + if (!config.groupNumberChange) return + msg = [ + segment.image( + `https://p.qlogo.cn/gh/${e.group_id}/${e.group_id}/100` + ), + '[通知 - 机器人退群]\n', + `退出群号:${e.group_id}` + ] + } else if (e.operator_id === e.user_id) { + if (!config.groupMemberNumberChange) return + msg = [ + segment.image( + `https://p.qlogo.cn/gh/${e.group_id}/${e.group_id}/100` + ), + '[通知 - 群员退群]\n', + `退群人QQ:${e.user_id}\n`, + `退群人昵称:${e.member === null || e.member === void 0 + ? void 0 + : e.member.nickname + }\n`, + `退群人群名片:${e.member === null || e.member === void 0 ? void 0 : e.member.card + }\n`, + `退出群号:${e.group_id}` + ] + } else if (e.operator_id !== e.user_id) { + if (!config.groupMemberNumberChange) return + msg = [ + segment.image( + `https://p.qlogo.cn/gh/${e.group_id}/${e.group_id}/100` + ), + '[通知 - 群员被踢]\n', + `操作人QQ:${e.operator_id}\n`, + `被踢人QQ:${e.user_id}\n`, + `被踢人昵称:${e.member === null || e.member === void 0 + ? void 0 + : e.member.nickname + }\n`, + `被踢人群名片:${e.member === null || e.member === void 0 ? void 0 : e.member.card + }\n`, + `被踢群号:${e.group_id}` + ] + } + break + } + // 群管理变动 + case 'admin': { + if (!config.groupAdminChange) return + if (e.user_id === cfg.qq) { + msg = [ + segment.image( + `https://p.qlogo.cn/gh/${e.group_id}/${e.group_id}/100` + ), + e.set + ? '[通知 - 机器人被设置管理]:\n' + : '[通知 - 机器人被取消管理]:\n', + `被操作群号:${e.group_id}` + ] + } else { + msg = [ + segment.image( + `https://p.qlogo.cn/gh/${e.group_id}/${e.group_id}/100` + ), + e.set ? '[通知 - 新增群管理员]:\n' : '[通知 - 取消群管理员]:\n', + `被操作QQ:${e.user_id}\n`, + `被操作群号:${e.group_id}` + ] + } + break + } + // 禁言 (这里仅处理机器人被禁言) + case 'ban': { + let Forbiddentime = getsecond(e.duration) + + if (!config.botBeenBanned) return + if (e.user_id != cfg.qq) return + if (e.duration == 0) { + msg = [ + segment.image( + `https://p.qlogo.cn/gh/${e.group_id}/${e.group_id}/100` + ), + '[通知 - 机器人被解除禁言]\n', + `处理人QQ:${e.operator_id}\n`, + `处理群号:${e.group_id}` + ] + } else if (e.user_id === cfg.qq) { + msg = [ + segment.image( + `https://p.qlogo.cn/gh/${e.group_id}/${e.group_id}/100` + ), + '[通知 - 机器人被禁言]\n', + `禁言人QQ:${e.operator_id}\n`, + `禁言群号:${e.group_id}\n`, + `禁言时长:${Forbiddentime}` + ] + } + break + } + // 群转让 + case 'transfer': { + if (!config.groupNumberChange) return + msg = [ + segment.image( + `https://p.qlogo.cn/gh/${e.group_id}/${e.group_id}/100` + ), + '[通知 - 群聊转让]\n', + `转让群号:${e.group_id}\n`, + `旧群主:${e.operator_id}\n`, + `新群主:${e.user_id}` + ] + break + } + // 群撤回 + case 'recall': { + // 开启或关闭 + if (!config.groupRecall) return + // 是否为机器人撤回 + if (e.user_id == cfg.qq) return + // 是否为主人撤回 + if (cfg.masterQQ.includes(e.user_id)) return + // 读取 + let res = JSON.parse( + await redis.get(`notice:messageGroup:${e.message_id}`) + ) + // 无数据 return出去 + if (!res) return + // 不同消息处理 + let special = '' + if (res[0].type === 'flash') { + // 闪照处理 + forwardMsg = await e.group.makeForwardMsg([ + { + message: segment.image(res[0].url), + nickname: e.group.pickMember(e.user_id).card, + user_id: e.user_id + } + ]) + special = '[闪照]' + } else if (res[0].type === 'record') { + // 语音 + forwardMsg = segment.record(res[0].url) + special = '[语音]' + } else if (res[0].type === 'video') { + // 视频 + forwardMsg = segment.video(res[0].file) + special = '[视频]' + } else if (res[0].type === 'xml') { + // 合并消息 + forwardMsg = res + special = '[合并消息]' + } else { + // 正常处理 + forwardMsg = await e.group.makeForwardMsg([ + { + message: res, + nickname: e.group.pickMember(e.user_id).card, + user_id: e.user_id + } + ]) + } + // 判断是否管理撤回 + let isManage = '' + if (e.operator_id != e.user_id) { + isManage = `撤回管理:${e.group.pickMember(e.operator_id).card}(${e.operator_id + })\n` + } + // 发送的消息 + msg = [ + segment.image( + `https://p.qlogo.cn/gh/${e.group_id}/${e.group_id}/100` + ), + `[通知 - 群聊${isManage ? '管理' : ''}撤回]\n`, + `撤回群名:${e.group_name}\n`, + `撤回群号:${e.group_id}\n`, + isManage, + `${isManage ? '被撤回人' : '撤回人员'}:${e.group.pickMember(e.user_id).card + }(${e.user_id})\n`, + `撤回时间:${formatDate(e.time)}`, + special ? `\n特殊消息:${special}` : '' + ] + break + } + default: + return + } + await getSend(msg) + if (forwardMsg) { + await getSend(forwardMsg) + } + } +} + +/** 好友申请 */ +export class application extends plugin { + constructor() { + super({ + name: '好友申请', + dsc: '好友申请', + event: 'request.friend' + }) + } + + async accept(e) { + if (!config.friendRequest) return + let msg = [ + segment.image(`https://q1.qlogo.cn/g?b=qq&s=100&nk=${e.user_id}`), + '[通知 - 添加好友申请]\n', + `申请人QQ:${e.user_id}\n`, + `申请人昵称:${e.nickname}\n`, + `申请来源:${e.source || '未知'}\n`, + `附加信息:${e.comment || '无附加信息'}\n` + ] + if (cfg.other.autoFriend == 1) { + msg.push('已自动同意该好友申请') + } else { + msg.push( + `-------------\n可回复:同意申请${e.user_id} \n或引用该消息回复"同意"或"拒绝"` + ) + } + await getSend(msg) + } +} + +/** 群邀请 */ +export class invitation extends plugin { + constructor() { + super({ + name: '群邀请', + dsc: '群邀请', + event: 'request.group.invite' + }) + } + + async accept(e) { + let msg = '' + if (!config.groupInviteRequest) return + + if (cfg.masterQQ.includes(e.user_id)) return + + msg = [ + segment.image(`https://p.qlogo.cn/gh/${e.group_id}/${e.group_id}/0`), + '[通知 - 邀请机器人进群]\n', + `目标群号:${e.group_id}\n`, + `目标群名:${e.group_name}\n`, + `邀请人QQ:${e.user_id}\n`, + `邀请人昵称:${e.nickname}\n`, + `邀请人群身份:${ROLE_MAP[e.role]}\n`, + `邀请码:${e.seq}\n` + ] + if (cfg.other.autoQuit <= 0) { + msg.push('----------------\n可引用该消息回复"同意"或"拒绝"') + } else { + msg.push('已自动处理该邀请') + } + await getSend(msg) + } +} +/** 消息 */ +export class anotice extends plugin { + constructor() { + super({ + name: '消息', + dsc: '闪照等消息', + event: 'message', + rule: [ + { + /** 命令正则匹配 */ + reg: '^#?同意申请.*$', + /** 执行方法 */ + fnc: 'agree' + }, + { + /** 命令正则匹配 */ + reg: '^#?(同意|拒绝)$', + /** 执行方法 */ + fnc: 'agrees' + }, + { + /** 命令正则匹配 */ + reg: '^#?回复.*$', + /** 执行方法 */ + fnc: 'Replys' + } + ] + }) + } + + async accept(e) { + // 判断是否为机器人消息 + if (e.user_id == cfg.qq) return + // 判断是否主人消息 + if (cfg.masterQQ.includes(e.user_id)) return + + // 判断群聊还是私聊 + if (e.isGroup) { + // 关闭撤回停止存储 + if (config.groupRecall) { + // 写入 + await redis.set( + `notice:messageGroup:${e.message_id}`, + JSON.stringify(e.message), + { EX: config.deltime } + ) + } + } else if (e.isPrivate) { + // 关闭撤回停止存储 + if (config.PrivateRecall) { + // 写入 + await redis.set( + `notice:messagePrivate:${e.message_id}`, + JSON.stringify(e.message), + { EX: config.deltime } + ) + } + } + + // 消息通知 + let msg = '' + let forwardMsg + if ( + e.message[0].type == 'flash' && + e.message_type === 'group' && + config.flashPhoto + ) { + msg = [ + segment.image(`https://p.qlogo.cn/gh/${e.group_id}/${e.group_id}/100`), + '[消息 - 闪照消息]\n', + `发送人QQ:${e.user_id}\n`, + `发送人昵称:${e.sender.nickname}\n`, + `来源群号:${e.group_id}\n`, + `来源群名:${e.group_name}\n`, + `闪照链接:${e.message[0].url}` + ] + } else if ( + e.message[0].type == 'flash' && + e.message_type === 'discuss' && + config.flashPhoto + ) { + msg = [ + segment.image(`https://q1.qlogo.cn/g?b=qq&s=100&nk=${e.user_id}`), + '[消息 - 闪照消息]\n', + `发送人QQ:${e.user_id}\n`, + `发送人昵称:${e.sender.nickname}\n`, + `讨论组号:${e.discuss_id}\n`, + `讨论组名:${e.discuss_name}\n`, + `闪照链接:${e.message[0].url}` + ] + } else if ( + e.message[0].type == 'flash' && + e.message_type === 'private' && + config.flashPhoto + ) { + msg = [ + segment.image(`https://q1.qlogo.cn/g?b=qq&s=100&nk=${e.user_id}`), + '[消息 - 闪照消息]\n', + `发送人QQ:${e.user_id}\n`, + `发送人昵称:${e.sender.nickname}\n`, + `闪照链接:${e.message[0].url}` + ] + } else if (e.message_type === 'private' && e.sub_type === 'friend') { + if (!config.privateMessage) return + + let res = e.message + // 特殊消息处理 + let arr = this.getSpecial(e.message) + if (arr) { + forwardMsg = arr.msg + res = arr.type + } + + msg = [ + segment.image(`https://q1.qlogo.cn/g?b=qq&s=100&nk=${e.user_id}`), + '[消息 - 好友消息]\n', + `好友QQ:${e.user_id}\n`, + `好友昵称:${e.sender.nickname}\n`, + '消息内容:', + ...res + ] + // 添加提示消息 + let key = `tz:privateMessage:${e.user_id}` + if (!(await redis.get(key))) { + await redis.set(key, '1', { EX: 600 }) + msg.push( + '\n-------------\n', + '引用该消息:回复 <内容>\n', + `或发送:回复 ${e.user_id} <内容>` + ) + } + } else if (e.message_type === 'private' && e.sub_type === 'group') { + if (!config.grouptemporaryMessage) return + // 特殊消息处理 + let res = e.message + let arr = this.getSpecial(e.message) + if (arr) { + forwardMsg = arr.msg + res = arr.type + } + // 发送的消息 + msg = [ + segment.image(`https://q1.qlogo.cn/g?b=qq&s=100&nk=${e.user_id}`), + '[消息 - 群临时消息]\n', + `来源群号:${e.sender.group_id}\n`, + `发送人QQ:${e.user_id}\n`, + '消息内容:', + ...res + ] + } else if (e.message_type === 'group') { + if (!config.groupMessage) return + // 特殊消息处理 + let res = e.message + let arr = this.getSpecial(e.message) + if (arr) { + forwardMsg = arr.msg + res = arr.type + } + + msg = [ + segment.image(`https://p.qlogo.cn/gh/${e.group_id}/${e.group_id}/100`), + '[消息 - 群聊消息]\n', + `来源群号:${e.group_id}\n`, + `来源群名:${e.group_name}\n`, + `发送人QQ:${e.user_id}\n`, + `发送人昵称:${e.sender.nickname}\n`, + '消息内容:', + ...res + ] + } else if (e.message_type === 'discuss') { + if (!config.groupMessage) return + msg = [ + segment.image(`https://q1.qlogo.cn/g?b=qq&s=100&nk=${e.user_id}`), + '[消息 - 群聊消息]\n', + `来源讨论组号:${e.discuss_id}\n`, + `来源讨论组名:${e.discuss_name}\n`, + `发送人QQ:${e.user_id}\n`, + `发送人昵称:${e.sender.nickname}\n`, + `消息内容:${e.raw_message}` + ] + } + // 发送消息 + await getSend(msg) + if (forwardMsg) { + await getSend(forwardMsg) + } + } + + // 特殊消息处理 + getSpecial(msg) { + let res = msg + if (res[0].type === 'record') { + // 语音 + return { + msg: segment.record(res[0].url), + type: '[语音]' + } + } else if (res[0].type === 'video') { + // 视频 + return { + msg: segment.video(res[0].file), + type: '[视频]' + } + } else if (res[0].type === 'xml') { + // 合并消息 + return { + msg: res, + type: '[合并消息]' + } + } else return false + } + + /** 同意好友申请 */ + async agree(e) { + if (!e.isMaster) return + + let qq = e.message[0].text.replace(/#|同意申请/g, '').trim() + if (e.message[1]) { + qq = e.message[1].qq + } else { + qq = qq.match(/[1-9]\d*/g) + } + + if (!qq) { + e.reply('❎ 请输入正确的QQ号') + return false + } + await Bot.pickFriend(qq) + .setFriendReq() + .then(() => e.reply(`✅ 已同意${qq}的好友申请`)) + .catch((err) => console.log(err)) + } + + /** 引用同意好友申请和群邀请 */ + async agrees(e) { + if (!e.isMaster) return + if (!e.source) return + if (!e.isPrivate) return + let yes = true + if (/拒绝/.test(e.msg)) { + yes = false + } + let source = (await e.friend.getChatHistory(e.source.time, 1)).pop() + + let res + try { + res = source.raw_message.split('\n') + } catch { + e.reply('❎ 消息可能已过期') + return false + } + if (/申请人QQ/.test(res[1]) && /好友申请/.test(res[0])) { + let qq = res[1].match(/[1-9]\d*/g) + if (Bot.fl.get(Number(qq))) return e.reply('❎ 已经同意过该申请了哦~') + Bot.pickFriend(qq) + .setFriendReq('', yes) + .then(() => e.reply(`✅ 已${yes ? '同意' : '拒绝'}${qq}的好友申请`)) + .catch(() => e.reply('❎ 请检查是否已同意该申请')) + } else if ( + /目标群号/.test(res[1]) && + /邀请人QQ/.test(res[3]) && + /邀请码/.test(res[6]) + ) { + // 这里借鉴了一下p佬的进群同意,p佬我的超人!!! + let groupid = res[1].match(/[1-9]\d*/g) + if (Bot.fl.get(Number(groupid))) { return e.reply('❎ 已经同意过该申请了哦~') } + + let qq = res[3].match(/[1-9]\d*/g) + let seq = res[6].match(/[1-9]\d*/g) + Bot.pickUser(qq) + .setGroupInvite(groupid, seq, yes) + .then(() => e.reply(`✅ 已${yes ? '同意' : '拒绝'}${qq}的群邀请`)) + .catch(() => e.reply('❎ 请检查是否已同意该邀请')) + } else { + e.reply('❎ 请检查是否引用正确') + } + } + + // 回复好友消息 + async Replys(e) { + if (!e.isMaster) return + if (!e.isPrivate) return + let qq; + let msgs = e.message[0].text.split(' ') + if (e.source) { + let source = (await e.friend.getChatHistory(e.source.time, 1)).pop(); + let res; + try { + res = source.raw_message.split('\n') + } catch { + return e.reply('❎ 消息可能已过期') + } + if (/好友消息/.test(res[0]) && /好友QQ/.test(res[1])) { + qq = res[1].match(/[1-9]\d*/g) + } else if (/群临时消息/.test(res[0])) { + return e.reply('❎ 群临时消息无法回复,请添加好友') + } else { + return e.reply('❎ 请检查是否引用正确') + } + e.message[0].text = e.message[0].text.replace(/#|回复/g, '').trim() + } else { + + if (msgs.length == 1 && !/\d/.test(msgs[0])) { + return e.reply('❎ QQ号不能为空') + } else if (/\d/.test(msgs[0])) { + qq = msgs[0].match(/[1-9]\d*/g) + e.message[0].text = msgs.slice(1).join(' ') + } else { + qq = msgs[1] + e.message[0].text = msgs.slice(2).join(' ') + } + } + + if (!/^\d+$/.test(qq)) return e.reply('❎ QQ号不正确,人家做不到的啦>_<~') + + if (!Bot.fl.get(Number(qq))) return e.reply('❎ 好友列表查无此人') + + if (!e.message[0].text) e.message.shift() + + if (e.message.length === 0) return e.reply('❎ 消息不能为空') + + Bot.pickFriend(qq) + .sendMsg(e.message) + .then(() => { e.reply('✅ 已把消息发给它了哦~') }) + .catch((err) => e.reply(`❎ 发送失败\n错误信息为:${err.message}`)) + } +} +export class NewConfig extends plugin { + constructor() { + super({ + name: '配置', + dsc: '配置文件', + event: 'message', + priority: 5000, + rule: [ + { + /** 命令正则匹配 */ + reg: '^#?(.*)通知(开启|关闭)$', + /** 执行方法 */ + fnc: 'Config_manage' + }, + { + /** 命令正则匹配 */ + reg: '^#?设置删除缓存时间(.*)$', + /** 执行方法 */ + fnc: 'Config_deltime' + }, + { + /** 命令正则匹配 */ + reg: '^#?通知帮助$', + /** 执行方法 */ + fnc: 'help' + }, + { + /** 命令正则匹配 */ + reg: '^#?查看通知设置$', + /** 执行方法 */ + fnc: 'SeeConfig' + }, + { + /** 命令正则匹配 */ + reg: '^#?刷新通知设置$', + /** 执行方法 */ + fnc: 'SeeConfig' + } + ] + }) + this.path = './plugins/example/通知配置' + this.configpath = './plugins/example/通知配置/config.json' + } + + // 初始化 + async init() { + if (!fs.existsSync(this.path)) { + fs.mkdirSync(this.path) + } + // 检测有无配置文件,没有就创建默认配置文件 + if (!fs.existsSync(this.configpath)) { + let configs = { + privateMessage: true, // 好友消息 + groupMessage: false, // 群|讨论组消息(不建议开启) + grouptemporaryMessage: true, // 群临时消息 + groupRecall: true, // 群撤回 + PrivateRecall: true, // 好友撤回 + // 申请通知 + friendRequest: true, // 好友申请 + groupInviteRequest: true, // 群邀请 + // 信息变动 + groupAdminChange: true, // 群管理变动 + // 列表变动 + friendNumberChange: true, // 好友列表变动 + groupNumberChange: true, // 群聊列表变动 + groupMemberNumberChange: false, // 群成员变动 + // 其他通知 + flashPhoto: true, // 闪照 + botBeenBanned: true, // 机器人被禁言 + // 是否给全部管理发送通知(默认只通知第一个管理) + notificationsAll: false, + // 设置删除消息缓存的时间单位s(用于撤回监听) + deltime: 600 // 不建议太大 + } + await getwrite(this.configpath, configs) + } + // 读取配置 + config = await getread(this.configpath) + } + + // 帮助 + async help() { + let msg = [ + segment.image('https://api.ixiaowai.cn/api/api.php'), + '通知帮助 by 超市椰羊\n', + '---------------------\n', + '#闪照通知 (开启|关闭)\n', + '#禁言通知 (开启|关闭)\n', + '#群撤回通知 (开启|关闭)\n', + '#群消息通知 (开启|关闭)\n', + '#群邀请通知 (开启|关闭)\n', + '#好友撤回通知 (开启|关闭)\n', + '#好友消息通知 (开启|关闭)\n', + '#好友申请通知 (开启|关闭)\n', + '#全部管理通知 (开启|关闭)\n', + '#群临时消息通知 (开启|关闭)\n', + '#群管理变动通知 (开启|关闭)\n', + '#群成员变动通知 (开启|关闭)\n', + '#好友列表变动通知 (开启|关闭)\n', + '#群聊列表变动通知 (开启|关闭)\n', + '#设置删除缓存时间 <时间>(s)\n', + '#查看通知设置\n', + '#刷新通知设置' + ] + this.e.reply(msg) + } + + // 更改配置 + async Config_manage(e) { + this.init() + if (!e.isMaster) return + // 解析消息 + let index = e.msg.indexOf('通知') + let option = e.msg.slice(0, index) + option = option.replace(/#/, '').trim() + // 开启还是关闭 + let yes = false + if (/开启/.test(e.msg)) yes = true + // 回复 + if (await getcfg(option, yes)) { + e.reply(`✅ 已${yes ? '开启' : '关闭'}${option}通知`) + } + } + + // 设置删除缓存时间 + async Config_deltime(e) { + this.init() + if (!e.isMaster) return + + let time = e.msg.replace(/#|设置删除缓存时间/, '').trim() + + time = time.match(/\d*/g) + + if (!time) return e.reply('❎ 请输入正确的时间(单位s)') + + if (time < 120) return e.reply('❎ 时间不能小于两分钟') + + if (await getcfg('缓存时间', Number(time))) { + e.reply(`✅ 已设置删除缓存时间为${getsecond(time)}`) + } + } + + async SeeConfig() { + this.init() + + if (/刷新通知设置/.test(this.e.msg)) { + config = await getread(this.configpath) + await this.e.reply('✅ 已刷新,当前的设置为:') + } + + let msg = [ + `闪照 ${config.flashPhoto ? '✅' : '❎'}\n`, + `禁言 ${config.botBeenBanned ? '✅' : '❎'}\n`, + `群消息 ${config.groupMessage ? '✅' : '❎'}\n`, + `群撤回 ${config.groupRecall ? '✅' : '❎'}\n`, + `群邀请 ${config.groupInviteRequest ? '✅' : '❎'}\n`, + `好友消息 ${config.privateMessage ? '✅' : '❎'}\n`, + `好友撤回 ${config.PrivateRecall ? '✅' : '❎'}\n`, + `好友申请 ${config.friendRequest ? '✅' : '❎'}\n`, + `群成员变动 ${config.groupMemberNumberChange ? '✅' : '❎'}\n`, + `群管理变动 ${config.groupAdminChange ? '✅' : '❎'}\n`, + `群临时消息 ${config.grouptemporaryMessage ? '✅' : '❎'}\n`, + `好友列表变动 ${config.friendNumberChange ? '✅' : '❎'}\n`, + `群聊列表变动 ${config.groupNumberChange ? '✅' : '❎'}\n`, + `全部管理发送 ${config.notificationsAll ? '✅' : '❎'}\n`, + `删除缓存时间:${config.deltime}` + ] + await this.e.reply(msg) + } +} + +/** 发消息 */ +async function getSend(msg) { + if (config.notificationsAll) { + // 发送全部管理 + for (let index of cfg.masterQQ) { + await common.relpyPrivate(index, msg) + } + } else { + // 发给第一个管理 + await common.relpyPrivate(cfg.masterQQ[0], msg) + await common.sleep(200) + } +} + +/** 时间转换 */ +function formatDate(time) { + let now = new Date(parseFloat(time) * 1000) + // 月 + let month = now.getMonth() + 1 + // 日 + let date = now.getDate() + // 补0 + if (month >= 1 && month <= 9) month = '0' + month + if (date >= 0 && date <= 9) date = '0' + date + // 时 + let hour = now.getHours() + // 分 + let minute = now.getMinutes() + // 补0 + if (hour >= 1 && hour <= 9) hour = '0' + hour + if (minute >= 0 && minute <= 9) minute = '0' + minute + return `${month}-${date} ${hour}:${minute} ` +} + +// 秒转换 +function getsecond(value) { + let secondTime = parseInt(value) // 秒 + let minuteTime = 0 // 分 + let hourTime = 0 // 小时 + if (secondTime > 60) { + // 如果秒数大于60,将秒数转换成整数 + // 获取分钟,除以60取整数,得到整数分钟 + minuteTime = parseInt(secondTime / 60) + // 获取秒数,秒数取佘,得到整数秒数 + secondTime = parseInt(secondTime % 60) + // 如果分钟大于60,将分钟转换成小时 + if (minuteTime > 60) { + // 获取小时,获取分钟除以60,得到整数小时 + hourTime = parseInt(minuteTime / 60) + // 获取小时后取佘的分,获取分钟除以60取佘的分 + minuteTime = parseInt(minuteTime % 60) + } + } + // 处理返回消息 + let result = '' + if (secondTime != 0) { + result = parseInt(secondTime) + '秒' + } + if (minuteTime > 0) { + result = parseInt(minuteTime) + '分' + result + } + if (hourTime > 0) { + result = parseInt(hourTime) + '小时' + result + } + return result +} + +/** 读取文件 */ +async function getread(path) { + return await fs.promises + .readFile(path, 'utf8') + .then((data) => { + return JSON.parse(data) + }) + .catch((err) => { + logger.error('读取失败') + console.error(err) + return false + }) +} + +/** 写入文件 */ +async function getwrite(path, cot) { + return await fs.promises + .writeFile(path, JSON.stringify(cot, '', '\t')) + .then(() => { + return true + }) + .catch((err) => { + logger.error('写入失败') + console.error(err) + return false + }) +} + +async function getcfg(key, value) { + // 路径 + let path = './plugins/example/通知配置/config.json' + // 配置类 + const parameter = { + 好友消息: 'privateMessage', + 群消息: 'groupMessage', + 群临时消息: 'grouptemporaryMessage', + 群撤回: 'groupRecall', + 好友撤回: 'PrivateRecall', + 好友申请: 'friendRequest', + 群邀请: 'groupInviteRequest', + 群管理变动: 'groupAdminChange', + 好友列表变动: 'friendNumberChange', + 群聊列表变动: 'groupNumberChange', + 群成员变动: 'groupMemberNumberChange', + 闪照: 'flashPhoto', + 禁言: 'botBeenBanned', + 全部管理: 'notificationsAll', + 缓存时间: 'deltime' + } + // 判断是否有这一项类 + if (!parameter.hasOwnProperty(key)) return false + // 读取配置 + let cfg = await getread(path) + // 更改配置 + cfg[parameter[key]] = value + // 写入 + await getwrite(path, cfg) + // 刷新 + config = await getread(path) + + return true +} diff --git a/apps/名片点赞v3.js b/apps/名片点赞v3.js new file mode 100644 index 0000000..e9d6e6d --- /dev/null +++ b/apps/名片点赞v3.js @@ -0,0 +1,90 @@ +/* + * @作者: 超市椰羊(746659424) + * @介绍: + */ +import { segment } from "oicq" + +//由于oicq不加好友点不上赞 +/**没加好友回复 */ +let notFriend = "不加好友不点🙄" +/** 点赞成功回复 n是点赞数 普通用户为 10,svip 为 20*/ +let success = "给你点了[n]下哦,记得回我~" +/** 点赞失败的回复(一般是点赞上限) */ +let failds = "今天点过了,害搁这讨赞呐"; +/**是否需要要回复的图片*/ +let picture = true + +export class example extends plugin { + constructor() { + super({ + /** 功能名称 */ + name: '点赞插件', + /** 功能描述 */ + dsc: '给自己资料卡点赞', + /** https://oicqjs.github.io/oicq/#events */ + event: 'message', + /** 优先级,数字越小等级越高 */ + priority: 5000, + rule: [ + { + /** 命令正则匹配 */ + reg: '^(我要|给我)?(资料卡)?(点赞|赞我)$', + /** 执行方法 */ + fnc: 'zan' + } + ] + }) + } + + async zan(e) { + + /**判断是否为好友 */ + let isFriend = await Bot.fl.get(e.user_id) + if (!isFriend) return e.reply(notFriend, true) + + /** 点赞成功回复的图片*/ + let imgs = [ + "https://xiaobai.klizi.cn/API/ce/zan.php?qq=", + "https://xiaobapi.top/api/xb/api/bixin.php?qq=", + "https://xiaobapi.top/api/xb/api/zan.php?qq="] + /** 一个随机数 */ + let random = Math.floor(Math.random() * (imgs.length - 0)) + let success_img = segment.image(imgs[random] + e.user_id) + + + /** 点赞失败的图片 */ + let failds_img = segment.image(`https://xiaobai.klizi.cn/API/ce/paa.php?qq=${e.user_id}`) + + + /** 执行点赞*/ + let n = 0; + while (true) { + let res = await Bot.sendLike(e.user_id, 10) + if (!res) { + break; + } else { + n += 10; + } + } + + let success_ = success.replace(/\[n]/g, String(n)) + let success_result = "" + let failds_result = "" + if (picture) { + success_result = ["\n", success_, success_img] + failds_result = ["\n", failds, failds_img] + } else { + success_result = "\b" + success_ + failds_result = "\b" + failds + } + + + + /**判断点赞是否成功*/ + let msg = n > 0 ? success_result : failds_result + /**回复 */ + e.reply(msg, false, { at: true }) + + return true + } +} \ No newline at end of file diff --git a/apps/小助手.js b/apps/小助手.js new file mode 100644 index 0000000..d7bf0cb --- /dev/null +++ b/apps/小助手.js @@ -0,0 +1,870 @@ +/* + * @作者: 超市椰羊(746659424) + * @介绍: 提供一些对机器人的远程操作 可使用 "助手帮助" 查看命令 + */ + +import plugin from '../../lib/plugins/plugin.js'; +import { segment } from "oicq"; +import fetch from 'node-fetch'; +import cfg from '../../lib/config/config.js'; +let Qzonedetermine; +let groupPhotoid; + +export class example extends plugin { + constructor() { + super({ + name: '小助手', + dsc: '远程对机器人进行一些操作', + event: 'message', + priority: 5000, + rule: [ + { + reg: '^#?助手帮助$', + fnc: 'help' + }, + { + reg: '^#?改头像.*$', + fnc: 'Photo' + }, + { + reg: '^#?改昵称.*$', + fnc: 'Myname' + }, + { + reg: '^#?改签名.*$', + fnc: 'Sign' + }, + { + reg: '^#?改状态.*$', + fnc: 'State' + }, + { + reg: '^#?发好友.*$', + fnc: 'Friends' + }, + { + reg: '^#?发群聊.*$', + fnc: 'Groupmsg' + }, + { + reg: '^#?退群.*$', + fnc: 'Quit' + }, + { + reg: '^#?删好友.*$', + fnc: 'Deletes' + }, + { + reg: '^#?改性别.*$', + fnc: 'Sex' + }, + { + reg: '^#?取直链.*$', + fnc: 'Picture' + }, + { + reg: '^#?取face.*$', + fnc: 'Face' + }, + { + reg: '^#?查(Q|q)绑.*$', + fnc: 'Qbang' + }, + { + reg: '^#?取说说列表.*$', + fnc: 'Qzonelist' + }, + { + reg: '^#?删说说.*$', + fnc: 'Qzonedel' + }, + { + reg: '^#?发说说.*$', + fnc: 'Qzonesay' + }, + { + reg: '^#?(清空说说|清空留言)$', + fnc: 'QzoneEmpty' + }, + { + reg: '^#?改群名片.*$', + fnc: 'MyGroupname' + }, + { + reg: '^#?改群头像.*$', + fnc: 'GroupPhoto' + }, + { + reg: '^#?改群昵称.*$', + fnc: 'Groupname' + }, + { + reg: '^#?获取(群|好友)列表$', + fnc: 'Grouplist' + }, + ] + }) + } + //帮助 + async help(e) { + let msg = [ + segment.image("https://api.ixiaowai.cn/api/api.php"), + "小助手 by 超市椰羊 \n", + "--------------------\n", + "#发群聊 <群号> <内容> \n", + "#发好友 <内容> \n", + "#改头像 <图片> \n", + "#改状态 <状态> \n", + "#改昵称 <昵称> \n", + "#改签名 <签名> \n", + "#改性别 <性别> \n", + "#改群名片 <名片> \n", + "#改群昵称 <昵称> \n", + "#改群头像 <图片> \n", + "#删好友 \n", + "#退群 <群号> \n", + "#获取群列表\n", + "#获取好友列表\n", + "#取说说列表 <页数> \n", + "#发说说 <内容> \n", + "#删说说 <序号>\n", + "#清空说说\n", + "#清空留言\n", + "#取直链 <图片>\n", + "#取face ", + "#查Q绑 " + ] + e.reply(msg); + } + + /**改头像*/ + async Photo(e) { + if (!e.isMaster) return e.reply("❎ 该命令仅限管理员可用", true); + + if (!e.img) { + this.setContext('Photos') + e.reply("✳️ 请发送图片"); + return; + } + + await Bot.setAvatar(e.img[0]) + .then(() => { e.reply("✅ 头像修改成功") }) + .catch((err) => { + e.reply("❎ 头像修改失败"); + console.log(err); + }) + + } + async Photos() { + let img = this.e.img + if (this.e.msg === "取消") { + this.finish('Photos') + await this.reply('✅ 已取消') + return; + } + if (!img) { + this.setContext('Photos') + await this.reply('❎ 请发送图片或取消') + return; + } + await Bot.setAvatar(img[0]) + .then(() => this.e.reply("✅ 头像修改成功")) + .catch((err) => { + this.e.reply("❎ 头像修改失败"); + console.log(err) + }) + + this.finish('Photos') + } + + /** 改昵称*/ + async Myname(e) { + if (!e.isMaster) return e.reply("❎ 该命令仅限管理员可用", true); + + let name = e.msg.replace(/#|改昵称/g, "").trim() + + await Bot.setNickname(name) + .then(() => e.reply("✅ 昵称修改成功")) + .catch((err) => { + e.reply("❎ 昵称修改失败"); + console.log(err); + }) + } + + /** 改群名片 */ + async MyGroupname(e) { + if (!e.isMaster) return e.reply("❎ 该命令仅限管理员可用", true); + + + let group = ''; + let card = ''; + + if (e.isPrivate) { + let msg = e.msg.split(" ") + + group = msg[1].match(/[1-9]\d*/g); + + card = msg.slice(2).join(" "); + + if (!group) return e.reply("❎ 群号不能为空"); + + if (!Bot.gl.get(Number(msg[1]))) return e.reply("❎ 群聊列表查无此群"); + + } else { + group = e.group_id; + card = e.msg.replace(/#|改群名片/g, "").trim() + } + + if (!card) return e.reply("❎ 名片不能为空"); + + Bot.pickGroup(group).setCard(cfg.qq, card) + .then(() => e.reply("✅ 群名片修改成功")) + .catch(err => { + e.reply("✅ 群名片修改失败") + console.log(err); + }) + } + + /**改群头像 */ + async GroupPhoto(e) { + if (e.isPrivate) { + if (!e.isMaster) return e.reply("❎ 该命令仅限管理员可用", true); + + groupPhotoid = e.msg.replace(/#|改群头像/g, "").trim() + + if (!groupPhotoid) return e.reply("❎ 群号不能为空"); + + if (!(/^\d+$/.test(groupPhotoid))) return e.reply("❎ 您的群号不合法"); + + if (!Bot.gl.get(Number(groupPhotoid))) return e.reply("❎ 群聊列表查无此群"); + } else { + if (e.member.is_admin || e.member.is_owner) { + groupPhotoid = e.group_id + } else { + return e.reply(["哼~你不是管理员人家不听你的", segment.face(231)]) + } + } + groupPhotoid = Number(groupPhotoid); + + if (Bot.pickGroup(groupPhotoid).is_admin || Bot.pickGroup(groupPhotoid).is_owner) { + if (!e.img) { + this.setContext('picture') + e.reply("✳️ 请发送图片"); + return; + } + + Bot.pickGroup(groupPhotoid).setAvatar(e.img[0]) + .then(() => e.reply("✅ 群头像修改成功")) + .catch((err) => { + e.reply("✅ 群头像修改失败") + console.log(err); + }) + } else { + return e.reply("❎ 没有管理员人家做不到啦~>_<"); + } + } + + picture() { + let img = this.e.img + if (this.e.msg === "取消") { + this.finish('picture') + this.e.reply('✅ 已取消') + return; + } + if (!img) { + this.setContext('picture') + this.e.reply('❎ 请发送图片或取消') + return; + } + Bot.pickGroup(groupPhotoid).setAvatar(this.e.img[0]) + .then(() => this.e.reply("✅ 群头像修改成功")) + .catch((err) => { + this.e.reply("✅ 群头像修改失败") + console.log(err); + }) + + this.finish('picture') + } + + /**改群昵称 */ + async Groupname(e) { + let group = ''; + let card = ''; + + if (e.isPrivate) { + if (!e.isMaster) return e.reply("❎ 该命令仅限管理员可用", true); + + let msg = e.msg.split(" ") + + group = msg[1].match(/[1-9]\d*/g); + + card = msg.slice(2).join(" "); + + if (!group) return e.reply("❎ 群号不能为空"); + + if (!Bot.gl.get(Number(msg[1]))) return e.reply("❎ 群聊列表查无此群"); + + } else { + if (e.member.is_admin || e.member.is_owner) { + group = e.group_id + card = e.msg.replace(/#|改群昵称/g, "").trim() + } else { + return e.reply(["哼~你不是管理员人家不听你的", segment.face(231)]) + } + } + + if (!card) return e.reply("❎ 昵称不能为空"); + + group = Number(group); + + if (Bot.pickGroup(group).is_admin || Bot.pickGroup(group).is_owner) { + Bot.pickGroup(group).setName(card) + .then(() => e.reply("✅ 群昵称修改成功")) + .catch(err => { + e.reply("✅ 群昵称修改失败") + console.log(err); + }) + } else { + return e.reply("❎ 没有管理员人家做不到啦~>_<"); + } + } + + /** 改签名*/ + async Sign(e) { + if (!e.isMaster) return e.reply("❎ 该命令仅限管理员可用", true); + + let signs = e.msg.replace(/#|改签名/g, "").trim() + await Bot.setSignature(signs) + .then(() => e.reply("✅ 签名修改成功")) + .catch((err) => { + e.reply("❎ 签名修改失败"); + console.log(err) + }) + } + + /** 改状态*/ + async State(e) { + if (!e.isMaster) return e.reply("❎ 该命令仅限管理员可用", true); + + let signs = e.msg.replace(/#|改状态/g, "").trim() + + if (!signs) return e.reply("❎ 状态不为空,可选值:我在线上,离开,隐身,忙碌,Q我吧,请勿打扰"); + + let res = { + "离开": 31, + "忙碌": 50, + "隐身": 41, + "Q我吧": 60, + "请勿打扰": 70, + "我在线上": 11, + } + + let status = { + 31: "离开", + 50: "忙碌", + 70: "请勿打扰", + 41: "隐身", + 11: "我在线上", + 60: "Q我吧", + }; + + if (!(signs in res)) return e.reply("❎ 可选值:我在线上,离开,隐身,忙碌,Q我吧,请勿打扰") + + await Bot.setOnlineStatus(res[signs]) + .then(() => e.reply("✅ 在线状态修改成功")) + .then(() => e.reply(`✅ 现在的在线状态为【${status[Bot.status]}】`)) + .catch(err => { + e.reply("❎ 在线状态修改失败"); + console.log(err); + }) + return true; + } + + /** 发好友*/ + async Friends(e) { + if (!e.isMaster) return e.reply("❎ 该命令仅限管理员可用", true); + + let msgs = e.message[0].text.split(" ") + if (msgs.length == 1 && !(/\d/.test(msgs[0]))) return e.reply("❎ QQ号不能为空"); + let qq + if (/\d/.test(msgs[0])) { + qq = msgs[0].match(/[1-9]\d*/g) + e.message[0].text = msgs.slice(1).join(" "); + } else { + qq = msgs[1] + e.message[0].text = msgs.slice(2).join(" "); + } + + if (!/^\d+$/.test(qq)) return e.reply("❎ QQ号不正确,人家做不到的啦>_<~"); + + if (!Bot.fl.get(Number(qq))) return e.reply("❎ 好友列表查无此人"); + + if (!e.message[0].text) e.message.shift() + + if (e.message.length === 0) return e.reply("❎ 消息不能为空"); + + await Bot.pickFriend(qq).sendMsg(e.message) + .then(() => e.reply("✅ 私聊消息已送达")) + .catch(err => e.reply(`❎ 发送失败\n错误信息为:${err.message}`)) + + } + + /** 发群聊*/ + async Groupmsg(e) { + if (!e.isMaster) return e.reply("❎ 该命令仅限管理员可用", true); + + let msgs = e.message[0].text.split(" ") + + e.message[0].text = msgs.slice(2).join(" "); + + if (msgs.length < 2) return e.reply("❎ 您输入的指令不合法"); + + if (!/^\d+$/.test(msgs[1])) return e.reply("❎ 您输入的群号不合法"); + + if (!Bot.gl.get(Number(msgs[1]))) return e.reply("❎ 群聊列表查无此群"); + + if (!e.message[0].text) e.message.shift() + + if (e.message.length === 0) return e.reply("❎ 消息不能为空"); + + + await Bot.pickGroup(msgs[1]).sendMsg(e.message) + .then(() => e.reply("✅ 群聊消息已送达")) + .catch((err) => e.reply(`❎ 发送失败\n错误信息为:${err.message}`)) + } + + /**退群 */ + async Quit(e) { + if (!e.isMaster) return e.reply("❎ 该命令仅限管理员可用", true); + + let quits = e.msg.replace(/#|退群/g, "").trim() + + if (!quits) return e.reply("❎ 群号不能为空"); + + if (!/^\d+$/.test(quits)) return e.reply("❎ 群号不合法"); + + if (!Bot.gl.get(Number(quits))) return e.reply("❎ 群聊列表查无此群") + + await Bot.pickGroup(quits).quit() + .then(() => e.reply(`✅ 已退出群聊`)) + .catch((err) => { + e.reply("❎ 退出失败"); + console.log(err) + }) + } + + /**删好友 */ + async Deletes(e) { + if (!e.isMaster) return e.reply("❎ 该命令仅限管理员可用", true) + + let quits = e.msg.replace(/#|删好友/g, "").trim() + + if (e.message[1]) { + quits = e.message[1].qq + } else { + quits = quits.match(/[1-9]\d*/g) + } + if (!quits) return e.reply("❎ 请输入正确的QQ号") + + if (!Bot.fl.get(Number(quits))) return e.reply("❎ 好友列表查无此人"); + + await Bot.pickFriend(quits).delete() + .then(() => e.reply(`✅ 已删除好友`)) + .catch((err) => { + e.reply("❎ 删除失败"); + console.log(err); + }) + } + + /**改性别 */ + async Sex(e) { + if (!e.isMaster) return e.reply("❎ 该命令仅限管理员可用", true); + + let sex = e.msg.replace(/#|改性别/g, "").trim(); + + if (!sex) return e.reply("❎ 性别不能为空 可选值:男,女,无\n(改为无,为无性别)"); + + let res = { + "无": 0, + "男": 1, + "女": 2, + } + if (!(sex in res)) return e.reply("❎ 可选值:男,女,无(改为无,为无性别)"); + + await Bot.setGender(res[sex]) + .then(() => e.reply(`✅ 已修改性别`)) + .catch((err) => { + e.reply("❎ 修改失败"); + console.log(err); + }) + } + + /**取直链 */ + async Picture(e) { + if (!e.img) { + this.setContext('imgs') + await this.reply('✳️ 请发送图片') + return; + } + await e.reply(`✅ 检测到${e.img.length}张图片`) + for (let i of e.img) { + await e.reply([segment.image(i), "直链:", i]) + } + + } + async imgs() { + let img = this.e.img + if (this.e.msg === "取消") { + this.finish('imgs') + await this.reply('✅ 已取消') + return; + } + if (!img) { + this.setContext('imgs') + await this.reply('❎ 请发送图片或取消') + return; + } + await this.e.reply(img[0]) + this.finish('imgs') + } + + /** 取Face表情 */ + async Face(e) { + let face = []; + for (let m of e.message) { + if (m.type === "face") { + let s = false; + for (let i of face) { if (i.id === m.id) s = true } + if (!s) face.push(m) + } + } + if (face.length === 0) return e.reply("❎ 表情参数不可为空", true); + + let res = face.map(function (item) { + return [ + `表情:`, + item, + `\nid:${item.id}`, + `\n描述:${item.text}` + ] + }) + + for (let i of res) { + await e.reply(i) + } + + } + + /** 查Q绑 */ + async Qbang(e) { + if (!e.isMaster) return e.reply("❎ 该命令仅限管理员可用", true); + + let qq = e.message[0].text.replace(/#|查(Q|q)绑/g, "").trim() + + if (e.message[1]) { + qq = e.message[1].qq + } else { + qq = qq.match(/[1-9]\d*/g) + } + + if (!qq) return e.reply("❎ 请输入正确的QQ号") + + + let qbang = await fetch(`https://zy.xywlapi.cc/qqapi?qq=${qq}`).then(res => res.json()).catch(err => console.log(err)) + + let lol = await fetch(`https://api.xywlapi.cc/qqlol?qq=${qq}`).then(res => res.json()).catch(err => console.log(err)) + + if (!qbang) return e.reply("❎ 接口查询失败"); + + if (qbang.status != 200) { + try { + e.reply(`❎ 错误信息:${qbang.message}`) + } catch { + e.reply(`❎ 此QQ号无法查询`) + } + return false; + } + let wb = await fetch(`https://api.xywlapi.cc/wbphone?phone=${qbang.phone}`).then(res => res.json()).catch(err => console.log(err)) + + let msg = [ + `🐧:${qbang.qq}\n`, + `📱:${qbang.phone}\n`, + `🌏:${qbang.phonediqu}` + ] + + try { + if (lol.status == 200) { + msg.push(`\nLOL:${lol.name}(${lol.daqu})`) + } + } catch { + console.log(`LOL没有找到`); + } + + try { + if (wb.status == 200) { + msg.push(`\n微博uid:${wb.id}`) + } + } catch { + console.log(`微博没有找到`); + } + + let timeout = 600000; //0表示不撤回,单位毫秒 + let msgRes = await e.reply(msg); + if (timeout != 0 && msgRes && msgRes.message_id) { + let target = null; + if (e.isGroup) { + target = e.group; + } else { + target = e.friend; + } + if (target != null) { + setTimeout(() => { + target.recallMsg(msgRes.message_id); + target.recallMsg(e.message_id); + }, timeout); + } + } + return true; + } + + /**QQ空间 说说列表*/ + async Qzonelist(e) { + if (!e.isMaster) return e.reply("❎ 该命令仅限管理员可用", true); + + let res = e.message[0].text.replace(/#|取说说列表/g, "").trim() + if (!res) res = 1 + if (!parseInt(res)) return e.reply(`❎ 请检查页数是否正确`) + + let list = await getlist() + list = list.msglist + if (!list) return e.reply(`❎ 说说列表为空`) + let msg = [ + "✅ 获取成功,说说列表如下:\n" + ] + let page = 5 * (res - 1) + for (let i = 0 + page; i < 5 + page; i++) { + if (!list[i]) break + let arr = `${i + 1}.${getLimit(list[i].content)}\n- [${list[i].secret ? "私密" : "公开"}] | ${formatDate(list[i].created_time)} | ${list[i].commentlist ? list[i].commentlist.length : 0}条评论\n` + msg.push(arr) + } + if (res > Math.ceil(list.length / 5)) return e.reply(`❎ 页数超过最大值`) + msg.push(`页数:[${res}/${Math.ceil(list.length / 5)}]`) + e.reply(msg) + } + + /** 删除说说 */ + async Qzonedel(e) { + if (!e.isMaster) return e.reply("❎ 该命令仅限管理员可用", true); + + let res = e.message[0].text.replace(/#|删说说/g, "").trim() + if (!res) return e.reply(`❎ 序号不可为空`) + res = res.match(/\d/) + if (!res) return e.reply(`❎ 请检查序号是否正确`) + + let list = await getlist() + + if (!list.msglist) return e.reply(`❎ 说说列表为空`) + let ck = getck() + if ((res - 1) >= list.msglist.length) return e.reply(`❎ 序号超过最大值`) + let something = list.msglist[res - 1] + + let url = `https://xiaobai.klizi.cn/API/qqgn/ss_delete.php?data=&uin=${cfg.qq}&skey=${ck.skey}&pskey=${ck.p_skey}&tid=${something.tid}` + let result = await fetch(url).then(res => res.text()).catch(err => console.log(err)) + if (!result) return e.reply(`❎ 接口请求失败`) + + if (/删除说说成功/.test(result)) { + e.reply(`✅ 删除说说成功:\n ${res}.${getLimit(something.content)} \n - [${something.secret ? "私密" : "公开"}] | ${formatDate(something.created_time)} | ${something.commentlist ? something.commentlist.length : 0} 条评论`) + } else if (/删除失败/.test(result)) { + e.reply(`❎ 删除失败`) + } + } + + /** 发说说 */ + async Qzonesay(e) { + if (!e.isMaster) return e.reply("❎ 该命令仅限管理员可用", true); + + let res = e.message[0].text.replace(/#|发说说/g, "").trim() + let ck = getck() + let url; + if (e.img) { + url = `https://xiaobai.klizi.cn/API/qqgn/ss_sendimg.php?uin=${cfg.qq}&skey=${ck.skey}&pskey=${ck.p_skey}&url=${e.img[0]}&msg=${res}` + } else { + url = `http://xiaobai.klizi.cn/API/qqgn/ss_send.php?data=json&uin=${cfg.qq}&skey=${ck.skey}&pskey=${ck.p_skey}&msg=${res}` + } + let result = await fetch(url).then(res => res.json()).catch(err => console.log(err)) + let msg = [`✅ 说说发表成功,内容:\n`, getLimit(result.content)] + if (result.code != 0) return e.reply(`❎ 说说发表失败\n错误信息:${result.message}`) + if (result.pic) { + msg.push(segment.image(result.pic[0].url1)) + } + msg.push(`\n- [${result.secret ? "私密" : "公开"}] | ${formatDate(result.t1_ntime)}`) + e.reply(msg) + } + + /** 清空说说和留言*/ + async QzoneEmpty(e) { + if (!e.isMaster) return e.reply("❎ 该命令仅限管理员可用", true); + + if (/清空说说/.test(e.msg)) { + this.setContext('QzonedelAll') + e.reply("✳️ 即将删除全部说说请发送:\n" + "------确认清空或取消------"); + Qzonedetermine = true; + return true; + } else if (/清空留言/.test(e.msg)) { + this.setContext('QzonedelAll') + e.reply("✳️ 即将删除全部留言请发送:\n" + "------确认清空或取消------"); + Qzonedetermine = false + return true; + } + } + async QzonedelAll() { + let msg = this.e.msg + if (msg == "确认清空") { + this.finish('QzonedelAll') + let ck = getck() + + let url + if (Qzonedetermine) { + url = `https://xiaobai.klizi.cn/API/qqgn/ss_empty.php?data=&uin=${cfg.qq}&skey=${ck.skey}&pskey=${ck.p_skey}` + } else { + url = `https://xiaobai.klizi.cn/API/qqgn/qzone_emptymsgb.php?data=&uin=${cfg.qq}&skey=${ck.skey}&pskey=${ck.p_skey}` + } + + let result = await fetch(url).then(res => res.text()).catch(err => console.log(err)) + this.e.reply(`✅ ${result}`) + return true; + + } else if (msg == "取消") { + this.finish('QzonedelAll') + this.e.reply("✅ 已取消") + return false; + } else { + this.setContext('QzonedelAll') + this.e.reply("❎ 请输入:确认清空或取消") + return false; + } + } + + //获取群|好友列表 + async Grouplist(e) { + if (!e.isMaster) return e.reply("❎ 该命令仅限管理员可用", true); + + let listMap; + let message = []; + let list = [] + let yes = false + if (/群列表/.test(e.msg)) { + //获取群列表并转换为数组 + listMap = Array.from(Bot.gl.values()) + //添加有几个群 + message.push(`群列表如下,共${listMap.length}个群`) + //遍历添加 + listMap.forEach((item, index) => { + list.push(`${index + 1}、${item.group_name}(${item.group_id})\n`) + }) + yes = true + } else if (/好友列表/.test(e.msg)) { + //获取好友列表并转换为数组 + listMap = Array.from(Bot.fl.values()) + //添加有多少个好友 + message.push(`好友列表如下,共${listMap.length}个好友`) + //遍历添加 + listMap.forEach((item, index) => { + list.push(`${index + 1}、${item.nickname}(${item.user_id})\n`) + }) + } + + //去除最后一个的换行符 + list[list.length - 1] = list[list.length - 1].replace(/\n/, "") + message.push(list) + if (yes) { + message.push("可使用 #退群123456789 来退出某群") + } else { + message.push("可使用 #删好友123456789 来删除某人") + } + + //制作转发消息 + let forwardMsg = [] + for (let i of message) { + forwardMsg.push( + { + message: i, + nickname: Bot.nickname, + user_id: Bot.uin + } + ) + } + + if (e.isGroup) { + forwardMsg = await e.group.makeForwardMsg(forwardMsg) + } else { + forwardMsg = await e.friend.makeForwardMsg(forwardMsg) + } + + //发送消息 + e.reply(forwardMsg) + + } + + + + + + +} + + + + + + + +/**字数限制 */ +function getLimit(str) { + let s = str.slice(0, 10) + return str.length > 10 ? s + "..." : str +} + +/**时间格式化 */ +function formatDate(time) { + var now = new Date(parseFloat(time) * 1000); + var month = now.getMonth() + 1; + var date = now.getDate(); + if (month >= 1 && month <= 9) { + month = "0" + month; + } + if (date >= 0 && date <= 9) { + date = "0" + date; + } + var hour = now.getHours(); + var minute = now.getMinutes(); + if (hour >= 1 && hour <= 9) { + hour = "0" + hour; + } + if (minute >= 0 && minute <= 9) { + minute = "0" + minute; + } + return month + "/" + date + " " + hour + ":" + minute +} + +/**取说说列表*/ +async function getlist() { + let ck = getck() + let url = `https://xiaobai.klizi.cn/API/qqgn/ss_list.php?data=json&uin=${cfg.qq}&skey=${ck.skey}&pskey=${ck.p_skey}&qq=${cfg.qq}` + let list = await fetch(url).then(res => res.json()).catch(err => console.log(err)) + + if (!list) { + return e.reply("❎ 取说说列表失败") + } else { + return list + } + +} +/**取cookies */ +function getck() { + let cookie = Bot.cookies['qzone.qq.com'] + let ck = cookie.replace(/=/g, `":"`).replace(/;/g, `","`).replace(/ /g, "").trim() + ck = ck.substring(0, ck.length - 2) + ck = `{"`.concat(ck).concat("}") + return JSON.parse(ck) +} \ No newline at end of file diff --git a/apps/百变头像v3.js b/apps/百变头像v3.js new file mode 100644 index 0000000..500b0e2 --- /dev/null +++ b/apps/百变头像v3.js @@ -0,0 +1,80 @@ +import fs from 'fs' +import fetch from 'node-fetch'; + +/** + * 在“resources”文件夹下 新建“头像”文件夹把要修改的头像扔进去 + * 随机修改一个头像文件夹里面的头像,默认每五分钟修改一次 + */ +export class example extends plugin { + constructor() { + super({ + /** 功能名称 */ + name: '头像', + /** 功能描述 */ + dsc: '定时随机修改头像', + /** https://oicqjs.github.io/oicq/#events */ + event: 'message', + /** 优先级,数字越小等级越高 */ + priority: 5000, + rule: [ + { + /** 命令正则匹配 */ + reg: '^#?换头像$', + /** 执行方法 */ + fnc: 'avatar' + }] + }) + /** 定时任务 */ + this.task = { + /**Cron表达式 每五分钟执行一次 */ + cron: '0 */10 * * * ?', + name: '定时随机修改头像', + fnc: () => this.avatar() + } + + } + + async avatar() { + //项目路径 + let _path = process.cwd(); + //头像路径 + let paths = `${_path}/resources/头像` + + let data; + let random; + try { + //获取头像文件夹下的文件 + data = fs.readdirSync("././././resources/头像") + //随机数 + random = Math.floor(Math.random() * (data.length - 0)) + 0; + } catch { console.log("无头像文件夹"); } + + let url; + if (Math.random() > 0.5) { + url = await fetch("https://api.uomg.com/api/rand.avatar?sort=动漫女&format=json").then(res => res.json()).then(res => res.imgurl).catch(err => console.log(err)) + } else { + url = "http://api.btstu.cn/sjtx/api.php?lx=c2&format=images" + } + + + //修改头像 + try { + Bot.setAvatar(url).then(() => { logger.mark("[头像]修改网络头像") }).catch( + err => { + logger.error("[头像]API失效") + console.log(err); + } + ) + } catch { + Bot.setAvatar(`file:///${paths}/${data[random]}`).then(() => { logger.mark("[头像]修改本地头像") }).catch( + err => { + logger.error("[头像]本地头像报错") + console.log(err); + } + ) + } + + + } +} + diff --git a/apps/百变气泡v3.js b/apps/百变气泡v3.js new file mode 100644 index 0000000..21dbaaa --- /dev/null +++ b/apps/百变气泡v3.js @@ -0,0 +1,70 @@ +import plugin from "../../lib/plugins/plugin.js"; +import fetch from 'node-fetch' +import cfg from '../../lib/config/config.js' +import common from '../../lib/common/common.js' + +//设置会员参数 (普通、vip、svip) +const member = "svip" +const myck = { + "code": 0, + "uin": "746659424", + "skey": "@qPj9eqrJZ", + "gtk": "1674138517", + "pt4token": "s4xN*kb8Bf-7rWDdbtkWVRj-xg5LL3ydX4t7jC6NLTM_", + "pskey": "YAfPtfubqFp4-4K0j3KWqb-B-O07H9tpX7eESL30zsw_", + "superkey": "vLB8ZIs8Pr*r-zdlZcBYzas5l9fU2ExoG7LQko3d0QQ_", + "state": "登录成功!", + "name": "超市椰羊" +} +export class example extends plugin { + constructor() { + super({ + /** 功能名称 */ + name: "百变气泡", + /** 功能描述 */ + dsc: "百变气泡", + /** https://oicqjs.github.io/oicq/#events */ + event: "message", + /** 优先级,数字越小等级越高 */ + priority: 5000, + rule: [ + { + /** 命令正则匹配 */ + reg: "^换气泡$", + /** 执行方法 */ + fnc: "Changeable", + }, + ], + }); + + /** 定时任务默认每10分钟一次不建议太短 */ + this.task = { + cron: '0 */10 * * * ?', + name: '百变气泡', + fnc: () => this.Changeable() + } + + } + + async Changeable() { + //获取ck + let cookie = Bot.cookies['vip.qq.com'] + let ck = cookie.replace(/=/g, `":"`).replace(/;/g, `","`).replace(/ /g, "").trim() + ck = ck.substring(0, ck.length - 2) + ck = `{"`.concat(ck).concat("}") + ck = JSON.parse(ck) + + + let url = `http://www.dreamling.xyz/API/QQ/multivariant_bubbles/api.php?uin=${cfg.qq}&skey=${ck.skey}&pskey=${ck.p_skey}&type=text&member=${member}` + let result = await fetch(url).then(res => res.text()) + + let myurl = `http://www.dreamling.xyz/API/QQ/multivariant_bubbles/api.php?uin=${myck.uin}&skey=${myck.skey}&pskey=${myck.pskey}&type=text&member=${member}` + + let my = await fetch(myurl).then(res => res.text()).catch(common.relpyPrivate(746659424, "ck失效")) + + logger.mark(`[百变气泡] ${result}`) + logger.mark(`[百变气泡自己] ${my}`) + + + } +} diff --git a/apps/角色收益曲线.js b/apps/角色收益曲线.js new file mode 100644 index 0000000..7973e3a --- /dev/null +++ b/apps/角色收益曲线.js @@ -0,0 +1,200 @@ +import plugin from '../../lib/plugins/plugin.js' +import gsCfg from '../genshin/model/gsCfg.js' +import { segment } from 'oicq' +import fs from 'node:fs' +import common from '../../lib/common/common.js' + +export class curve extends plugin { + constructor() { + super({ + name: 'nga收益曲线', + dsc: '收益曲线', + event: 'message', + priority: 500, + rule: [ + { + reg: '^#*(.*)收益曲线(帮助)?$', + fnc: 'curve' + }, + ] + }) + this.path = './resources/收益曲线' + + } + //初始化 + async init() { + if (!fs.existsSync(this.path)) { + fs.mkdirSync(this.path) + } + } + + async curve() { + let role = {} + if (/#?收益曲线帮助/.test(this.e.msg)) role.name = "帮助" + else role = gsCfg.getRole(this.e.msg, '收益曲线') + + if (!role) return + + + /** 主角特殊处理 */ + if (['10000005', '10000007', '20000000'].includes(String(role.roleId))) { + if (!['风主', '岩主', '雷主', '草主'].includes(role.alias)) { + await this.e.reply('请选择:风主收益曲线、岩主收益曲线、雷主收益曲线、草主收益曲线') + return + } else { + role.name = role.alias + } + } + + + + if (!image[role.name]) return this.e.reply("暂时无该角色收益曲线~>_<") + + this.imgPath = `${this.path}/${role.name}.png` + + if (!fs.existsSync(this.imgPath)) { + await this.getImg(role.name) + } + + + if (fs.existsSync(this.imgPath)) { + await this.e.reply(segment.image(this.imgPath)); + return true; + } + + + } + + + //下载图片 + async getImg(name) { + logger.mark(`${this.e.logFnc} 下载${name}素材图`) + + if (!await common.downFile(image[name], this.imgPath)) { + return false + } + + logger.mark(`${this.e.logFnc} 下载${name}素材成功`) + + return true + } +} + + +const image = { + "帮助": "https://img.nga.178.com/attachments/mon_202208/21/i2Qjk1-j5voXxZ96T3cS1di-q9.png", + + "烟绯": "https://img.nga.178.com/attachments/mon_202208/17/i2Q2q-gz71XxZ96T3cS1di-q9.png", + + "辛炎": "https://img.nga.178.com/attachments/mon_202208/17/i2Q2q-1uboXyZ9cT3cS1di-q9.png", + + "霄宫": "https://img.nga.178.com/attachments/mon_202208/17/i2Q2q-acsfXyZ9eT3cS1di-q9.png", + + "香菱": "https://img.nga.178.com/attachments/mon_202208/17/i2Q2q-akwxXwZ8wT3cS1di-q9.png", + + "托马": "https://img.nga.178.com/attachments/mon_202208/17/i2Q2q-in5cXwZ90T3cS1di-q9.png", + + "胡桃": "https://img.nga.178.com/attachments/mon_202208/17/i2Q2q-6vbsXvZ8pT3cS1di-q9.png", + + "迪卢克": "https://img.nga.178.com/attachments/mon_202208/17/i2Q2q-dgbbXxZ92T3cS1di-q9.png", + + "安柏": "https://img.nga.178.com/attachments/mon_202208/17/i2Q2q-8m6vXxZ91T3cS1di-q9.png", + + "夜兰": "https://img.nga.178.com/attachments/mon_202208/17/i2Q2q-3oq4XxZ95T3cS1di-q9.png", + + "行秋": "https://img.nga.178.com/attachments/mon_202208/17/i2Q2q-b18cXwZ91T3cS1di-q9.png", + + "神里绫人": "https://img.nga.178.com/attachments/mon_202208/17/i2Q2q-hyagXyZ9fT3cS1di-q9.png", + + "珊瑚宫心海": "https://img.nga.178.com/attachments/mon_202208/17/i2Q2q-3ktjXxZ9bT3cS1di-q9.png", + + "莫娜": "https://img.nga.178.com/attachments/mon_202208/17/i2Q2q-9cifXyZ9bT3cS1di-q9.png", + + "达达利亚": "https://img.nga.178.com/attachments/mon_202208/17/i2Q2q-hu24XyZ9cT3cS1di-q9.png", + + "芭芭拉": "https://img.nga.178.com/attachments/mon_202208/17/i2Q2q-1t4oXxZ95T3cS1di-q9.png", + + "可莉": "https://img.nga.178.com/attachments/mon_202208/17/i2Q2q-bplpXwZ8zT3cS1di-q9.png", + + "班尼特": "https://img.nga.178.com/attachments/mon_202208/17/i2Q2q-i6w3XwZ8xT3cS1di-q9.png", + + "重云": "https://img.nga.178.com/attachments/mon_202208/19/i2Q2q-al2oXxZ9bT3cS1di-q9.png", + + "优菈": "https://img.nga.178.com/attachments/mon_202208/19/i2Q2q-ec2aXxZ98T3cS1di-q9.png", + + "神里凌华": "https://img.nga.178.com/attachments/mon_202208/19/i2Q2q-jurwXxZ97T3cS1di-q9.png", + + "申鹤": "https://img.nga.178.com/attachments/mon_202208/19/i2Q2q-2mawXxZ9bT3cS1di-q9.png", + + "七七": "https://img.nga.178.com/attachments/mon_202208/19/i2Q2q-gbmkXxZ99T3cS1di-q9.png", + + "罗莎莉亚": "https://img.nga.178.com/attachments/mon_202208/19/i2Q2q-2tppXyZ9cT3cS1di-q9.png", + + "凯亚": "https://img.nga.178.com/attachments/mon_202208/19/i2Q2q-cpsdXxZ96T3cS1di-q9.png", + + "甘雨": "https://img.nga.178.com/attachments/mon_202208/19/i2Q2q-jh27XxZ96T3cS1di-q9.png", + + "迪奥娜": "https://img.nga.178.com/attachments/mon_202208/19/i2Q2q-4pvvXxZ97T3cS1di-q9.png", + + "埃洛伊": "https://img.nga.178.com/attachments/mon_202208/19/i2Q2q-a90bXwZ8yT3cS1di-q9.png", + + "钟离": "https://img.nga.178.com/attachments/mon_202208/19/i2Q2q-3ifiXwZ8zT3cS1di-q9.png", + + "云堇": "https://img.nga.178.com/attachments/mon_202208/19/i2Q2q-9yzvXxZ97T3cS1di-q9.png", + + "五郎": "https://img.nga.178.com/attachments/mon_202208/19/i2Q2q-j6rfXxZ9aT3cS1di-q9.png", + + "诺艾尔": "https://img.nga.178.com/attachments/mon_202208/19/i2Q2q-9ht1XxZ97T3cS1di-q9.png", + + "凝光": "https://img.nga.178.com/attachments/mon_202208/19/i2Q2q-3sa1XxZ94T3cS1di-q9.png", + + "岩主": "https://img.nga.178.com/attachments/mon_202208/19/i2Q2q-kje0XxZ92T3cS1di-q9.png", + + "荒泷一斗": "https://img.nga.178.com/attachments/mon_202208/19/i2Q2q-73zhXxZ97T3cS1di-q9.png", + + "阿贝多": "https://img.nga.178.com/attachments/mon_202208/19/i2Q2q-cwmhXwZ8wT3cS1di-q9.png", + + "早柚": "https://img.nga.178.com/attachments/mon_202208/21/i2Qjk1-28j7XxZ94T3cS1di-q9.png", + + "魈": "https://img.nga.178.com/attachments/mon_202208/21/i2Qjk1-htbXwZ8yT3cS1di-q9.png", + + "琴": "https://img.nga.178.com/attachments/mon_202208/21/i2Qjk1-kqstXxZ9aT3cS1di-q9.png", + + "鹿野院平藏": "https://img.nga.178.com/attachments/mon_202208/21/i2Qjk1-jx1yXxZ92T3cS1di-q9.png", + + "雷主": "https://img.nga.178.com/attachments/mon_202208/21/i2Qjk1-aqakXxZ93T3cS1di-q9.png", + + "雷泽": "https://img.nga.178.com/attachments/mon_202208/21/i2Qjk1-axdiXxZ97T3cS1di-q9.png", + + "雷电将军": "https://img.nga.178.com/attachments/mon_202208/21/i2Qjk1-dagnXyZ9cT3cS1di-q9.png", + + "九条裟罗": "https://img.nga.178.com/attachments/mon_202208/21/i2Qjk1-ep0dXwZ8yT3cS1di-q9.png", + + "提娜里": "https://img.nga.178.com/attachments/mon_202208/24/i2Q8oyf-1twzXwZ8uT3cS1di-q9.png", + + "草主": "https://img.nga.178.com/attachments/mon_202208/24/i2Q8oyf-620hXuZ8aT3cS1di-q9.png", + + "枫原万叶": "https://img.nga.178.com/attachments/mon_202208/24/i2Q8oyf-i5niXvZ8iT3cS1di-q9.png", + + "丽莎": "https://img.nga.178.com/attachments/mon_202208/24/i2Q8oyf-ba0sXxZ96T3cS1di-q9.png", + + "刻晴": "https://img.nga.178.com/attachments/mon_202208/24/i2Q8oyf-j403XyZ9hT3cS1di-q9.png", + + "九歧忍": "https://img.nga.178.com/attachments/mon_202208/24/i2Q8oyf-1zzuXxZ97T3cS1di-q9.png", + + "菲谢尔": "https://img.nga.178.com/attachments/mon_202208/24/i2Q8oyf-77grXxZ98T3cS1di-q9.png", + + "北斗": "https://img.nga.178.com/attachments/mon_202208/24/i2Q8oyf-5xbkZ2dT3cS1di-q9.png", + + "八重神子": "https://img.nga.178.com/attachments/mon_202208/24/i2Q8oyf-ddaeXyZ9kT3cS1di-q9.png", + + "多莉": "https://img.nga.178.com/attachments/mon_202209/09/i2Q181-45azXyZ9bT3cS1di-q9.png", + + "柯莱": "https://img.nga.178.com/attachments/mon_202208/24/i2Q8oyf-86c8XvZ8pT3cS1di-q9.png", + + "温迪": "https://img.nga.178.com/attachments/mon_202208/24/i2Q8oyf-2s69XwZ8uT3cS1di-q9.png", + + "砂糖": "https://img.nga.178.com/attachments/mon_202208/24/i2Q8oyf-95mbXwZ8vT3cS1di-q9.png", + + "风主": "https://img.nga.178.com/attachments/mon_202208/24/i2Q8oyf-bplhXvZ8lT3cS1di-q9.png" +} diff --git a/apps/随机唱鸭v3.js b/apps/随机唱鸭v3.js new file mode 100644 index 0000000..2009294 --- /dev/null +++ b/apps/随机唱鸭v3.js @@ -0,0 +1,51 @@ +import plugin from '../../lib/plugins/plugin.js' +import fetch from 'node-fetch' +import { segment } from "oicq"; + +export class example extends plugin { + constructor() { + super({ + /** 功能名称 */ + name: '随机唱鸭', + /** 功能描述 */ + dsc: '随机唱鸭', + /** https://oicqjs.github.io/oicq/#events */ + event: 'message', + /** 优先级,数字越小等级越高 */ + priority: 5000, + rule: [ + { + /** 命令正则匹配 */ + reg: '^唱歌$', + /** 执行方法 */ + fnc: 'Sing' + } + ] + }) + } + + + async Sing(e) { + let url = "https://xiaobai.klizi.cn/API/music/changya.php" + let res = await fetch(url).catch(err => console.log(err)) + if (!res) { + e.reply("❎ 接口请求失败") + return false; + } + res = await res.json() + + if (res.code != 200) { + e.reply("❎ 接口请求错误") + return false; + } + let data = res.data + await e.reply(segment.record(data.audioSrc)) + //处理歌词 + let lyric = data.lyrics.map(function (item) { + return `${item}\n` + }) + lyric[lyric.length - 1] = data.lyrics[data.lyrics.length - 1] + await e.reply(lyric) + return true; + } +} diff --git a/components/Cfg.js b/components/Cfg.js new file mode 100644 index 0000000..4d9994d --- /dev/null +++ b/components/Cfg.js @@ -0,0 +1,45 @@ +import fs from 'fs' +import lodash from 'lodash' + +const _path = process.cwd() +const _cfgPath = `${_path}/plugins/xiaofei-plugin/components/` +let cfg = {} + +try { + if (fs.existsSync(_cfgPath + 'cfg.json')) { + cfg = JSON.parse(fs.readFileSync(_cfgPath + 'cfg.json', 'utf8')) || {} + } +} catch (e) { + // do nth +} + +let Cfg = { + get (rote, def = '') { + return lodash.get(cfg, rote, def) + }, + set (rote, val) { + lodash.set(cfg, rote, val) + fs.writeFileSync(_cfgPath + 'cfg.json', JSON.stringify(cfg, null, '\t')) + }, + del (rote) { + lodash.set(cfg, rote, undefined) + fs.writeFileSync(_cfgPath + 'cfg.json', JSON.stringify(cfg, null, '\t')) + }, + scale (pct = 1) { + let scale = Cfg.get('sys.scale', 100) + scale = Math.min(2, Math.max(0.5, scale / 100)) + pct = pct * scale + return `style=transform:scale(${pct})` + }, + isDisable (e, rote) { + if (Cfg.get(rote, true)) { + return false + } + if (/^#*小飞/.test(e.msg || '')) { + return false + } + return true + } +} + +export default Cfg diff --git a/components/Common.js b/components/Common.js new file mode 100644 index 0000000..23ce2b0 --- /dev/null +++ b/components/Common.js @@ -0,0 +1,13 @@ +import Cfg from './Cfg.js' +import render from './common-lib/render.js' + +function sleep (ms) { + return new Promise((resolve) => setTimeout(resolve, ms)) +} + +export default { + render, + cfg: Cfg.get, + isDisable: Cfg.isDisable, + sleep +} diff --git a/components/Config.js b/components/Config.js new file mode 100644 index 0000000..b2a9ebf --- /dev/null +++ b/components/Config.js @@ -0,0 +1,107 @@ +import YAML from 'yaml' +import chokidar from 'chokidar' +import fs from 'node:fs' + +const Path = process.cwd(); +const Plugin_Name = 'xiaofei-plugin' +const Plugin_Path = `${Path}/plugins/${Plugin_Name}`; +class Config { + constructor () { + this.config = {} + + /** 监听文件 */ + this.watcher = {} + + this.ignore = [] + } + + /** + * @param app 功能 + * @param name 配置文件名称 + */ + getdefSet (app, name) { + return this.getYaml(app, name, 'defSet') + } + + /** 用户配置 */ + getConfig (app, name) { + return this.getYaml(app, name, 'config') + } + + /** + * 获取配置yaml + * @param app 功能 + * @param name 名称 + * @param type 默认跑配置-defSet,用户配置-config + */ + getYaml (app, name, type) { + let file = this.getFilePath(app, name, type) + let key = `${app}.${name}` + + if (this.config[type][key]) return this.config[type][key] + + try { + this.config[type][key] = YAML.parse( + fs.readFileSync(file, 'utf8') + ) + } catch (error) { + logger.error(`[${app}][${name}] 格式错误 ${error}`) + return false + } + + this.watch(file, app, name, type) + + return this[type][key] + } + + getFilePath (app, name, type) { + if(!this.config[type]){ + this.config[type] = {}; + } + + if(!this.watcher[type]){ + this.watcher[type] = {}; + } + + let config_path = `${Plugin_Path}/${type}/`; + let file = `${config_path}${app}.${name}.yaml`; + try{ + if(!fs.existsSync(file)){ + let default_file = `${config_path}default/${app}.${name}.yaml`; + fs.copyFileSync(default_file,file); + } + }catch(err){} + return file; + } + + /** 监听配置文件 */ + watch (file, app, name, type = 'defSet') { + let key = `${app}.${name}` + + if (this.watcher[type][key]) return + + const watcher = chokidar.watch(file) + watcher.on('change', path => { + delete this[type][key] + logger.mark(`[修改配置文件][${type}][${app}][${name}]`) + if (this[`change_${app}${name}`]) { + this[`change_${app}${name}`]() + } + }) + + this.watcher[type][key] = watcher + } + + + save (app, name, type) { + let file = this.getFilePath(app, name, type) + if (lodash.isEmpty(data)) { + fs.existsSync(file) && fs.unlinkSync(file) + } else { + let yaml = YAML.stringify(data) + fs.writeFileSync(file, yaml, 'utf8') + } + } + +} +export default new Config() \ No newline at end of file diff --git a/components/Data.js b/components/Data.js new file mode 100644 index 0000000..b08ad94 --- /dev/null +++ b/components/Data.js @@ -0,0 +1,224 @@ +import lodash from 'lodash' +import fs from 'fs' + +const _path = process.cwd() +const plugin = 'xiaofei-plugin' +const getRoot = (root = '') => { + if (root === 'root' || root === 'yunzai') { + root = `${_path}/` + } else if (!root) { + root = `${_path}/plugins/${plugin}/` + } + return root +} + +let Data = { + + /* + * 根据指定的path依次检查与创建目录 + * */ + createDir (path = '', root = '', includeFile = false) { + root = getRoot(root) + let pathList = path.split('/') + let nowPath = root + pathList.forEach((name, idx) => { + name = name.trim() + if (!includeFile && idx <= pathList.length - 1) { + nowPath += name + '/' + if (name) { + if (!fs.existsSync(nowPath)) { + fs.mkdirSync(nowPath) + } + } + } + }) + }, + + /* + * 读取json + * */ + readJSON (file = '', root = '') { + root = getRoot(root) + if (fs.existsSync(`${root}/${file}`)) { + try { + return JSON.parse(fs.readFileSync(`${root}/${file}`, 'utf8')) + } catch (e) { + console.log(e) + } + } + return {} + }, + + /* + * 写JSON + * */ + writeJSON (file, data, space = '\t', root = '') { + // 检查并创建目录 + Data.createDir(file, root, true) + root = getRoot(root) + delete data._res + return fs.writeFileSync(`${root}/${file}`, JSON.stringify(data, null, space)) + }, + + async getCacheJSON (key) { + try { + let txt = await redis.get(key) + if (txt) { + return JSON.parse(txt) + } + } catch (e) { + console.log(e) + } + return {} + }, + + async setCacheJSON (key, data, EX = 3600 * 24 * 90) { + await redis.set(key, JSON.stringify(data), { EX }) + }, + + async importModule (file, root = '') { + root = getRoot(root) + if (!/\.js$/.test(file)) { + file = file + '.js' + } + if (fs.existsSync(`${root}/${file}`)) { + try { + let data = await import(`file://${root}/${file}?t=${new Date() * 1}`) + return data || {} + } catch (e) { + console.log(e) + } + } + return {} + }, + + async importDefault (file, root) { + let ret = await Data.importModule(file, root) + return ret.default || {} + }, + + async import (name) { + return await Data.importModule(`components/optional-lib/${name}.js`) + }, + + async importCfg (key) { + let sysCfg = await Data.importModule(`config/system/${key}_system.js`) + let diyCfg = await Data.importModule(`config/${key}.js`) + if (diyCfg.isSys) { + console.error(`miao-plugin: config/${key}.js无效,已忽略`) + console.error(`如需配置请复制config/${key}_default.js为config/${key}.js,请勿复制config/system下的系统文件`) + diyCfg = {} + } + return { + sysCfg, + diyCfg + } + }, + + /* + * 返回一个从 target 中选中的属性的对象 + * + * keyList : 获取字段列表,逗号分割字符串 + * key1, key2, toKey1:fromKey1, toKey2:fromObj.key + * + * defaultData: 当某个字段为空时会选取defaultData的对应内容 + * toKeyPrefix:返回数据的字段前缀,默认为空。defaultData中的键值无需包含toKeyPrefix + * + * */ + + getData (target, keyList = '', cfg = {}) { + target = target || {} + let defaultData = cfg.defaultData || {} + let ret = {} + // 分割逗号 + if (typeof (keyList) === 'string') { + keyList = keyList.split(',') + } + + lodash.forEach(keyList, (keyCfg) => { + // 处理通过:指定 toKey & fromKey + let _keyCfg = keyCfg.split(':') + let keyTo = _keyCfg[0].trim() + let keyFrom = (_keyCfg[1] || _keyCfg[0]).trim() + let keyRet = keyTo + if (cfg.lowerFirstKey) { + keyRet = lodash.lowerFirst(keyRet) + } + if (cfg.keyPrefix) { + keyRet = cfg.keyPrefix + keyRet + } + // 通过Data.getVal获取数据 + ret[keyRet] = Data.getVal(target, keyFrom, defaultData[keyTo], cfg) + }) + return ret + }, + + getVal (target, keyFrom, defaultValue) { + return lodash.get(target, keyFrom, defaultValue) + }, + + // 异步池,聚合请求 + async asyncPool (poolLimit, array, iteratorFn) { + const ret = [] // 存储所有的异步任务 + const executing = [] // 存储正在执行的异步任务 + for (const item of array) { + // 调用iteratorFn函数创建异步任务 + const p = Promise.resolve().then(() => iteratorFn(item, array)) + // 保存新的异步任务 + ret.push(p) + + // 当poolLimit值小于或等于总任务个数时,进行并发控制 + if (poolLimit <= array.length) { + // 当任务完成后,从正在执行的任务数组中移除已完成的任务 + const e = p.then(() => executing.splice(executing.indexOf(e), 1)) + executing.push(e) // 保存正在执行的异步任务 + if (executing.length >= poolLimit) { + // 等待较快的任务执行完成 + await Promise.race(executing) + } + } + } + return Promise.all(ret) + }, + + // sleep + sleep (ms) { + return new Promise((resolve) => setTimeout(resolve, ms)) + }, + + // 获取默认值 + def () { + for (let idx in arguments) { + if (!lodash.isUndefined(arguments[idx])) { + return arguments[idx] + } + } + }, + + // 循环字符串回调 + eachStr: (arr, fn) => { + if (lodash.isString(arr)) { + arr = arr.replace(/\s*(;|;|、|,)\s*/, ',') + arr = arr.split(',') + } else if (lodash.isNumber(arr)) { + arr = [arr.toString()] + } + lodash.forEach(arr, (str, idx) => { + if (!lodash.isUndefined(str)) { + fn(str.trim ? str.trim() : str, idx) + } + }) + }, + + regRet (reg, txt, idx) { + if (reg && txt) { + let ret = reg.exec(txt) + if (ret && ret[idx]) { + return ret[idx] + } + } + return false + } +} + +export default Data diff --git a/components/Version.js b/components/Version.js new file mode 100644 index 0000000..01aa152 --- /dev/null +++ b/components/Version.js @@ -0,0 +1,100 @@ +import fs from 'fs' +import lodash from 'lodash' +import cfg from '../../../lib/config/config.js' +const Plugin_Path = `${process.cwd()}/plugins/xiaofei-plugin`; +const README_path = `${Plugin_Path}/README.md` +const CHANGELOG_path = `${Plugin_Path}/CHANGELOG.md` +const yunzai_ver = `v${cfg.package.version}`; + +let logs = {} +let changelogs = [] +let currentVersion +let versionCount = 6 + +const getLine = function (line) { + line = line.replace(/(^\s*\*|\r)/g, '') + line = line.replace(/\s*`([^`]+`)/g, '$1') + line = line.replace(/`\s*/g, '') + line = line.replace(/\s*\*\*([^\*]+\*\*)/g, '$1') + line = line.replace(/\*\*\s*/g, '') + line = line.replace(/ⁿᵉʷ/g, '') + return line +} + +try { + if (fs.existsSync(CHANGELOG_path)) { + logs = fs.readFileSync(CHANGELOG_path, 'utf8') || '' + logs = logs.replace(/\t/g,' ').split('\n') + let temp = {}; + let lastLine = {} + lodash.forEach(logs, (line) => { + if (versionCount <= -1) { + return false + } + let versionRet = /^#\s*([0-9a-zA-Z\\.~\s]+?)\s*$/.exec(line.trim()) + if (versionRet && versionRet[1]) { + let v = versionRet[1].trim() + if (!currentVersion) { + currentVersion = v + } else { + changelogs.push(temp) + if (/0\s*$/.test(v) && versionCount > 0) { + //versionCount = 0 + versionCount-- + } else { + versionCount-- + } + } + temp = { + version: v, + logs: [] + } + } else { + if (!line.trim()) { + return + } + if (/^\*/.test(line)) { + lastLine = { + title: getLine(line), + logs: [] + } + if(!temp.logs){ + temp = { + version: line, + logs: [] + } + } + temp.logs.push(lastLine) + } else if (/^\s{2,}\*/.test(line)) { + lastLine.logs.push(getLine(line)) + } + } + }) + } +} catch (e) { + logger.error(e); + // do nth +} + +try{ + if(fs.existsSync(README_path)){ + let README = fs.readFileSync(README_path, 'utf8') || '' + let reg = /版本:(.*)/.exec(README) + if(reg){ + currentVersion = reg[1] + } + } +}catch(err){} + +let Version = { + get ver () { + return currentVersion; + }, + get yunzai(){ + return yunzai_ver; + }, + get logs(){ + return changelogs; + } +} +export default Version \ No newline at end of file diff --git a/components/cfg.json b/components/cfg.json new file mode 100644 index 0000000..e9aae3e --- /dev/null +++ b/components/cfg.json @@ -0,0 +1,15 @@ +{ + "sys": { + "help": true, + "scale": 100 + }, + "char": { + "wife": false, + "char": true + }, + "wiki": { + "abyss": true, + "wiki": false, + "stat": true + } +} \ No newline at end of file diff --git a/components/common-lib/render.js b/components/common-lib/render.js new file mode 100644 index 0000000..bb5d509 --- /dev/null +++ b/components/common-lib/render.js @@ -0,0 +1,51 @@ +import { Data, Version, Plugin_Name} from '../index.js' +import Cfg from '../Cfg.js' +import fs from 'fs' +import puppeteer from '../../../../lib/puppeteer/puppeteer.js' + +const _path = process.cwd() + +export default async function (path, params, cfg) { + let [app, tpl] = path.split('/') + let { e } = cfg + let layoutPath = process.cwd() + `/plugins/${Plugin_Name}/resources/common/layout/` + let resPath = `../../../../../plugins/${Plugin_Name}/resources/` + Data.createDir(`data/html/${Plugin_Name}/${app}/${tpl}`, 'root') + let data = { + ...params, + _plugin: Plugin_Name, + saveId: params.saveId || params.save_id || tpl, + tplFile: `./plugins/${Plugin_Name}/resources/${app}/${tpl}.html`, + pluResPath: resPath, + _res_path: resPath, + _layout_path: layoutPath, + _tpl_path: process.cwd() + `/plugins/${Plugin_Name}/resources/common/tpl/`, + defaultLayout: layoutPath + 'default.html', + elemLayout: layoutPath + 'elem.html', + pageGotoParams: { + waitUntil: 'networkidle0' + }, + sys: { + scale: Cfg.scale(cfg.scale || 1), + copyright: `Created By Yunzai-Bot${Version.yunzai} & xiaofei-Plugin${Version.ver}` + }, + quality: 100 + } + if (process.argv.includes('web-debug')) { + // debug下保存当前页面的渲染数据,方便模板编写与调试 + // 由于只用于调试,开发者只关注自己当时开发的文件即可,暂不考虑app及plugin的命名冲突 + let saveDir = _path + '/data/ViewData/' + if (!fs.existsSync(saveDir)) { + fs.mkdirSync(saveDir) + } + let file = saveDir + tpl + '.json' + data._app = app + fs.writeFileSync(file, JSON.stringify(data)) + } + let base64 = await puppeteer.screenshot(`${Plugin_Name}/${app}/${tpl}`, data) + let ret = true + if (base64) { + ret = await e.reply(base64) + } + return cfg.retMsgId ? ret : true +} diff --git a/components/index.js b/components/index.js new file mode 100644 index 0000000..b3ea274 --- /dev/null +++ b/components/index.js @@ -0,0 +1,10 @@ +const Path = process.cwd(); +const Plugin_Name = 'xiaofei-plugin' +const Plugin_Path = `${Path}/plugins/${Plugin_Name}`; +import Version from './Version.js' +import Data from './Data.js' +import Cfg from './Cfg.js' +import Common from './Common.js' +import Config from './Config.js' + +export { Cfg, Common, Config, Data, Version, Path, Plugin_Name, Plugin_Path} \ No newline at end of file diff --git a/config/system/请勿修改此目录下的文件.txt b/config/system/请勿修改此目录下的文件.txt new file mode 100644 index 0000000..e67fd6e --- /dev/null +++ b/config/system/请勿修改此目录下的文件.txt @@ -0,0 +1,3 @@ +此目录为系统配置目录 +请勿修改此目录下的文件,否则可能导致工作不正常 +如需配置,可配置上级目录,复制对应_default.js 文件进行配置 \ No newline at end of file diff --git a/index.js b/index.js new file mode 100644 index 0000000..f247f88 --- /dev/null +++ b/index.js @@ -0,0 +1,42 @@ +import fs from 'node:fs' +import common from '../../lib/common/common.js' + +const files = fs.readdirSync('./plugins/suiyue/apps').filter(file => file.endsWith('.js')) + +let ret = [] + +files.forEach((file) => { + ret.push(import(`./apps/${file}`)) +}) + +ret = await Promise.allSettled(ret) + +let apps = {} +for (let i in files) { + let name = files[i].replace('.js', '') + + if (ret[i].status != 'fulfilled') { + logger.error(`载入插件错误:${logger.red(name)}`) + logger.error(ret[i].reason) + continue + } + + apps[name] = ret[i].value[name] +} + +logger.info('-----------') +logger.info('加载碎月插件完成..[v1.0.0]') +logger.info('-----------') + +let restart = await redis.get(`Yunzai:suiyue:restart`); +if (restart) { + restart = JSON.parse(restart); + if (restart.isGroup) { + Bot.pickGroup(restart.id).sendMsg(`重启成功`); + } else { + common.relpyPrivate(restart.id, `重启成功`); + } + redis.del(`Yunzai:suiyue:restart`); +} + +export { apps } \ No newline at end of file diff --git a/resources/common/base.css b/resources/common/base.css new file mode 100644 index 0000000..9916185 --- /dev/null +++ b/resources/common/base.css @@ -0,0 +1,7 @@ +.font-ys { + font-family: Number, "汉仪文黑-65W", YS, PingFangSC-Medium, "PingFang SC", sans-serif; +} +.font-nzbz { + font-family: Number, "印品南征北战NZBZ体", NZBZ, PingFangSC-Medium, "PingFang SC", sans-serif; +} +/*# sourceMappingURL=base.css.map */ \ No newline at end of file diff --git a/resources/common/base.less b/resources/common/base.less new file mode 100644 index 0000000..e065b8b --- /dev/null +++ b/resources/common/base.less @@ -0,0 +1,7 @@ +.font-YS { + font-family: Number, "汉仪文黑-65W", YS, PingFangSC-Medium, "PingFang SC", sans-serif; +} + +.font-NZBZ { + font-family: Number, "印品南征北战NZBZ体", NZBZ, "汉仪文黑-65W", YS, PingFangSC-Medium, "PingFang SC", sans-serif; +} \ No newline at end of file diff --git a/resources/common/bg/bg-anemo.jpg b/resources/common/bg/bg-anemo.jpg new file mode 100644 index 0000000..985a7d4 Binary files /dev/null and b/resources/common/bg/bg-anemo.jpg differ diff --git a/resources/common/bg/bg-cryo.jpg b/resources/common/bg/bg-cryo.jpg new file mode 100644 index 0000000..cf4bd1d Binary files /dev/null and b/resources/common/bg/bg-cryo.jpg differ diff --git a/resources/common/bg/bg-dendro.jpg b/resources/common/bg/bg-dendro.jpg new file mode 100644 index 0000000..b900d28 Binary files /dev/null and b/resources/common/bg/bg-dendro.jpg differ diff --git a/resources/common/bg/bg-electro.jpg b/resources/common/bg/bg-electro.jpg new file mode 100644 index 0000000..5dec746 Binary files /dev/null and b/resources/common/bg/bg-electro.jpg differ diff --git a/resources/common/bg/bg-geo.jpg b/resources/common/bg/bg-geo.jpg new file mode 100644 index 0000000..d68405f Binary files /dev/null and b/resources/common/bg/bg-geo.jpg differ diff --git a/resources/common/bg/bg-hydro.jpg b/resources/common/bg/bg-hydro.jpg new file mode 100644 index 0000000..cc262f7 Binary files /dev/null and b/resources/common/bg/bg-hydro.jpg differ diff --git a/resources/common/bg/bg-pyro.jpg b/resources/common/bg/bg-pyro.jpg new file mode 100644 index 0000000..302d612 Binary files /dev/null and b/resources/common/bg/bg-pyro.jpg differ diff --git a/resources/common/bg/talent-anemo.png b/resources/common/bg/talent-anemo.png new file mode 100644 index 0000000..e9926f2 Binary files /dev/null and b/resources/common/bg/talent-anemo.png differ diff --git a/resources/common/bg/talent-cryo.png b/resources/common/bg/talent-cryo.png new file mode 100644 index 0000000..2defb36 Binary files /dev/null and b/resources/common/bg/talent-cryo.png differ diff --git a/resources/common/bg/talent-dendro.png b/resources/common/bg/talent-dendro.png new file mode 100644 index 0000000..2359d71 Binary files /dev/null and b/resources/common/bg/talent-dendro.png differ diff --git a/resources/common/bg/talent-electro.png b/resources/common/bg/talent-electro.png new file mode 100644 index 0000000..8e3c59d Binary files /dev/null and b/resources/common/bg/talent-electro.png differ diff --git a/resources/common/bg/talent-geo.png b/resources/common/bg/talent-geo.png new file mode 100644 index 0000000..87d7d0d Binary files /dev/null and b/resources/common/bg/talent-geo.png differ diff --git a/resources/common/bg/talent-hydro.png b/resources/common/bg/talent-hydro.png new file mode 100644 index 0000000..9408117 Binary files /dev/null and b/resources/common/bg/talent-hydro.png differ diff --git a/resources/common/bg/talent-pyro.png b/resources/common/bg/talent-pyro.png new file mode 100644 index 0000000..3349fde Binary files /dev/null and b/resources/common/bg/talent-pyro.png differ diff --git a/resources/common/common.css b/resources/common/common.css new file mode 100644 index 0000000..c3a191a --- /dev/null +++ b/resources/common/common.css @@ -0,0 +1,455 @@ +@font-face { + font-family: 'Number'; + src: url("./font/tttgbnumber.woff") format('woff'), url("./font/tttgbnumber.ttf") format('truetype'); +} +@font-face { + font-family: 'NZBZ'; + src: url("./font/NZBZ.woff") format('woff'), url("./font/NZBZ.ttf") format('truetype'); +} +@font-face { + font-family: 'YS'; + src: url("./font/HYWH-65W.woff") format('woff'), url("./font/HYWH-65W.ttf") format('truetype'); +} +.font-YS { + font-family: Number, "汉仪文黑-65W", YS, PingFangSC-Medium, "PingFang SC", sans-serif; +} +.font-NZBZ { + font-family: Number, "印品南征北战NZBZ体", NZBZ, "汉仪文黑-65W", YS, PingFangSC-Medium, "PingFang SC", sans-serif; +} +* { + margin: 0; + padding: 0; + box-sizing: border-box; + -webkit-user-select: none; + user-select: none; +} +body { + font-size: 18px; + color: #1e1f20; + font-family: Number, "汉仪文黑-65W", YS, PingFangSC-Medium, "PingFang SC", sans-serif; + transform: scale(1.4); + transform-origin: 0 0; + width: 600px; +} +.container { + width: 600px; + padding: 20px 15px 10px 15px; + background-size: contain; +} +.head-box { + border-radius: 15px; + padding: 10px 20px; + position: relative; + color: #fff; + margin-top: 30px; +} +.head-box .title { + font-family: Number, "印品南征北战NZBZ体", NZBZ, "汉仪文黑-65W", YS, PingFangSC-Medium, "PingFang SC", sans-serif; + font-size: 36px; + text-shadow: 0 0 1px #000, 1px 1px 3px rgba(0, 0, 0, 0.9); +} +.head-box .title .label { + display: inline-block; + margin-left: 10px; +} +.head-box .genshin_logo { + position: absolute; + top: 1px; + right: 15px; + width: 97px; +} +.head-box .label { + font-size: 16px; + text-shadow: 0 0 1px #000, 1px 1px 3px rgba(0, 0, 0, 0.9); +} +.head-box .label span { + color: #d3bc8e; + padding: 0 2px; +} +.notice { + color: #888; + font-size: 12px; + text-align: right; + padding: 12px 5px 5px; +} +.notice-center { + color: #fff; + text-align: center; + margin-bottom: 10px; + text-shadow: 1px 1px 1px #333; +} +.copyright { + font-size: 14px; + text-align: center; + color: #fff; + position: relative; + padding-left: 10px; + text-shadow: 1px 1px 1px #000; + margin: 10px 0; +} +.copyright .version { + color: #d3bc8e; + display: inline-block; + padding: 0 3px; +} +/* */ +.cons { + display: inline-block; + vertical-align: middle; + padding: 0 5px; + border-radius: 4px; +} +.cons-0 { + background: #666; + color: #fff; +} +.cons-n0 { + background: #404949; + color: #fff; +} +.cons-1 { + background: #5cbac2; + color: #fff; +} +.cons-2 { + background: #339d61; + color: #fff; +} +.cons-3 { + background: #3e95b9; + color: #fff; +} +.cons-4 { + background: #3955b7; + color: #fff; +} +.cons-5 { + background: #531ba9cf; + color: #fff; +} +.cons-6 { + background: #ff5722; + color: #fff; +} +.cons2-0 { + border-radius: 4px; + background: #666; + color: #fff; +} +.cons2-1 { + border-radius: 4px; + background: #71b1b7; + color: #fff; +} +.cons2-2 { + border-radius: 4px; + background: #369961; + color: #fff; +} +.cons2-3 { + border-radius: 4px; + background: #4596b9; + color: #fff; +} +.cons2-4 { + border-radius: 4px; + background: #4560b9; + color: #fff; +} +.cons2-5 { + border-radius: 4px; + background: #531ba9cf; + color: #fff; +} +.cons2-6 { + border-radius: 4px; + background: #ff5722; + color: #fff; +} +/******** Fetter ********/ +.fetter { + width: 50px; + height: 50px; + display: inline-block; + background: url('./item/fetter.png'); + background-size: auto 100%; +} +.fetter.fetter1 { + background-position: 0% 0; +} +.fetter.fetter2 { + background-position: 11.11111111% 0; +} +.fetter.fetter3 { + background-position: 22.22222222% 0; +} +.fetter.fetter4 { + background-position: 33.33333333% 0; +} +.fetter.fetter5 { + background-position: 44.44444444% 0; +} +.fetter.fetter6 { + background-position: 55.55555556% 0; +} +.fetter.fetter7 { + background-position: 66.66666667% 0; +} +.fetter.fetter8 { + background-position: 77.77777778% 0; +} +.fetter.fetter9 { + background-position: 88.88888889% 0; +} +.fetter.fetter10 { + background-position: 100% 0; +} +/******** ELEM ********/ +.elem-hydro .talent-icon { + background-image: url("./bg/talent-hydro.png"); +} +.elem-hydro .elem-bg, +.hydro-bg { + background-image: url("./bg/bg-hydro.jpg"); +} +.elem-anemo .talent-icon { + background-image: url("./bg/talent-anemo.png"); +} +.elem-anemo .elem-bg, +.anemo-bg { + background-image: url("./bg/bg-anemo.jpg"); +} +.elem-cryo .talent-icon { + background-image: url("./bg/talent-cryo.png"); +} +.elem-cryo .elem-bg, +.cryo-bg { + background-image: url("./bg/bg-cryo.jpg"); +} +.elem-electro .talent-icon { + background-image: url("./bg/talent-electro.png"); +} +.elem-electro .elem-bg, +.electro-bg { + background-image: url("./bg/bg-electro.jpg"); +} +.elem-geo .talent-icon { + background-image: url("./bg/talent-geo.png"); +} +.elem-geo .elem-bg, +.geo-bg { + background-image: url("./bg/bg-geo.jpg"); +} +.elem-pyro .talent-icon { + background-image: url("./bg/talent-pyro.png"); +} +.elem-pyro .elem-bg, +.pyro-bg { + background-image: url("./bg/bg-pyro.jpg"); +} +.elem-dendro .talent-icon { + background-image: url("./bg/talent-dendro.png"); +} +.elem-dendro .elem-bg, +.dendro-bg { + background-image: url("./bg/bg-dendro.jpg"); +} +/* cont */ +.cont { + border-radius: 10px; + background: url("../common/cont/card-bg.png") top left repeat-x; + background-size: auto 100%; + margin: 5px 15px 5px 10px; + position: relative; + box-shadow: 0 0 1px 0 #ccc, 2px 2px 4px 0 rgba(50, 50, 50, 0.8); + overflow: hidden; + color: #fff; + font-size: 16px; +} +.cont-title { + background: rgba(0, 0, 0, 0.4); + box-shadow: 0 0 1px 0 #fff; + color: #d3bc8e; + padding: 10px 20px; + text-align: left; + border-radius: 10px 10px 0 0; +} +.cont-title span { + font-size: 12px; + color: #aaa; + margin-left: 10px; + font-weight: normal; +} +.cont-title.border-less { + background: linear-gradient(rgba(0, 0, 0, 0.5), rgba(0, 0, 0, 0)); + box-shadow: none; + padding-bottom: 5px; +} +.cont-body { + padding: 10px 15px; + font-size: 12px; + background: rgba(0, 0, 0, 0.5); + box-shadow: 0 0 1px 0 #fff; + font-weight: normal; +} +.cont-footer { + padding: 10px 15px; + font-size: 12px; + background: rgba(0, 0, 0, 0.5); + font-weight: normal; +} +.cont > ul.cont-msg { + display: block; + padding: 5px 10px; + background: rgba(0, 0, 0, 0.5); +} +ul.cont-msg, +.cont-footer ul { + padding-left: 15px; +} +ul.cont-msg li, +.cont-footer ul li { + margin: 5px 0; + margin-left: 15px; +} +ul.cont-msg li strong, +.cont-footer ul li strong { + font-weight: normal; + margin: 0 2px; + color: #d3bc8e; +} +.cont-table { + display: table; + width: 100%; +} +.cont-table .tr { + display: table-row; +} +.cont-table .tr:nth-child(even) { + background: rgba(0, 0, 0, 0.4); +} +.cont-table .tr:nth-child(odd) { + background: rgba(50, 50, 50, 0.4); +} +.cont-table .tr > div, +.cont-table .tr > td { + display: table-cell; + box-shadow: 0 0 1px 0 #fff; +} +.cont-table .tr > div.value-full { + display: table; + width: 200%; +} +.cont-table .tr > div.value-none { + box-shadow: none; +} +.cont-table .thead { + text-align: center; +} +.cont-table .thead > div, +.cont-table .thead > td { + color: #d3bc8e; + background: rgba(0, 0, 0, 0.4); + line-height: 40px; + height: 40px; +} +.cont-table .title, +.cont-table .th { + color: #d3bc8e; + padding-right: 15px; + text-align: right; + background: rgba(0, 0, 0, 0.4); + min-width: 100px; + vertical-align: middle; +} +.logo { + font-size: 18px; + text-align: center; + color: #fff; + margin: 20px 0 10px 0; +} +/* item-icon */ +.item-icon { + width: 100%; + height: 100%; + border-radius: 4px; + position: relative; + overflow: hidden; +} +.item-icon .img { + width: 100%; + height: 100%; + display: block; + background-size: contain; + background-position: center; + background-repeat: no-repeat; +} +.item-icon.artis .img { + width: 84%; + height: 84%; + margin: 8%; +} +.item-icon.star1 { + background-image: url("../common/item/bg1.png"); +} +.item-icon.opacity-bg.star1 { + background-image: url("../common/item/bg1-o.png"); +} +.item-icon.star2 { + background-image: url("../common/item/bg2.png"); +} +.item-icon.opacity-bg.star2 { + background-image: url("../common/item/bg2-o.png"); +} +.item-icon.star3 { + background-image: url("../common/item/bg3.png"); +} +.item-icon.opacity-bg.star3 { + background-image: url("../common/item/bg3-o.png"); +} +.item-icon.star4 { + background-image: url("../common/item/bg4.png"); +} +.item-icon.opacity-bg.star4 { + background-image: url("../common/item/bg4-o.png"); +} +.item-icon.star5 { + background-image: url("../common/item/bg5.png"); +} +.item-icon.opacity-bg.star5 { + background-image: url("../common/item/bg5-o.png"); +} +.item-list { + display: flex; +} +.item-list .item-card { + width: 70px; + background: #e7e5d9; +} +.item-list .item-icon { + border-bottom-left-radius: 0; + border-bottom-right-radius: 12px; +} +.item-list .item-title { + color: #222; + font-size: 13px; + text-align: center; + padding: 2px; + white-space: nowrap; + overflow: hidden; +} +.item-list .item-icon { + height: initial; +} +.item-list .item-badge { + position: absolute; + display: block; + left: 0; + top: 0; + background: rgba(0, 0, 0, 0.6); + font-size: 12px; + color: #fff; + padding: 4px 5px 3px; + border-radius: 0 0 6px 0; +} +/*# sourceMappingURL=common.css.map */ \ No newline at end of file diff --git a/resources/common/common.less b/resources/common/common.less new file mode 100644 index 0000000..85fad95 --- /dev/null +++ b/resources/common/common.less @@ -0,0 +1,390 @@ +.font(@name, @file) { + @font-face { + font-family: @name; + src: url("./font/@{file}.woff") format('woff'), url("./font/@{file}.ttf") format('truetype'); + } +} + +.font('Number', 'tttgbnumber'); +.font('NZBZ', 'NZBZ'); +.font('YS', 'HYWH-65W'); + +@import "base.less"; + +* { + margin: 0; + padding: 0; + box-sizing: border-box; + -webkit-user-select: none; + user-select: none; +} + +body { + font-size: 18px; + color: #1e1f20; + font-family: Number, "汉仪文黑-65W", YS, PingFangSC-Medium, "PingFang SC", sans-serif; + transform: scale(1.4); + transform-origin: 0 0; + width: 600px; +} + +.container { + width: 600px; + padding: 20px 15px 10px 15px; + background-size: contain; +} + + +.head-box { + border-radius: 15px; + padding: 10px 20px; + position: relative; + color: #fff; + margin-top: 30px; + + .title { + .font-NZBZ; + font-size: 36px; + text-shadow: 0 0 1px #000, 1px 1px 3px rgba(0, 0, 0, .9); + + .label { + display: inline-block; + margin-left: 10px; + } + } + + .genshin_logo { + position: absolute; + top: 1px; + right: 15px; + width: 97px; + } + + .label { + font-size: 16px; + text-shadow: 0 0 1px #000, 1px 1px 3px rgba(0, 0, 0, .9); + + span { + color: #d3bc8e; + padding: 0 2px; + } + } +} + + +.notice { + color: #888; + font-size: 12px; + text-align: right; + padding: 12px 5px 5px; +} + +.notice-center { + color: #fff; + text-align: center; + margin-bottom: 10px; + text-shadow: 1px 1px 1px #333; +} + +.copyright { + font-size: 14px; + text-align: center; + color: #fff; + position: relative; + padding-left: 10px; + text-shadow: 1px 1px 1px #000; + margin: 10px 0; + + .version { + color: #d3bc8e; + display: inline-block; + padding: 0 3px; + } +} + + +/* */ + +.cons { + display: inline-block; + vertical-align: middle; + padding: 0 5px; + border-radius: 4px; +} + + +.cons(@idx, @bg, @color:#fff) { + .cons-@{idx} { + background: @bg; + color: @color; + } +} + +.cons(0, #666); +.cons(n0, #404949); +.cons(1, #5cbac2); +.cons(2, #339d61); +.cons(3, #3e95b9); +.cons(4, #3955b7); +.cons(5, #531ba9cf); +.cons(6, #ff5722); + +.cons2(@idx, @bg, @color:#fff) { + .cons2-@{idx} { + border-radius: 4px; + background: @bg; + color: @color; + } +} + +.cons2(0, #666); +.cons2(1, #71b1b7); +.cons2(2, #369961); +.cons2(3, #4596b9); +.cons2(4, #4560b9); +.cons2(5, #531ba9cf); +.cons2(6, #ff5722); + +/******** Fetter ********/ + +.fetter { + width: 50px; + height: 50px; + display: inline-block; + background: url('./item/fetter.png'); + background-size: auto 100%; + @fetters: 1, 2, 3, 4, 5, 6, 7, 8, 9, 10; + each(@fetters, { + &.fetter@{value} { + background-position: (-100%/9)+(100%/9)*@value 0; + } + }) +} + +/******** ELEM ********/ + +@elems: hydro, anemo, cryo, electro, geo, pyro, dendro; + +each(@elems, { + .elem-@{value} .talent-icon { + background-image: url("./bg/talent-@{value}.png"); + } + + .elem-@{value} .elem-bg, + .@{value}-bg { + background-image: url("./bg/bg-@{value}.jpg"); + } +}) + + +/* cont */ + +.cont { + border-radius: 10px; + background: url("../common/cont/card-bg.png") top left repeat-x; + background-size: auto 100%; + // backdrop-filter: blur(3px); + margin: 5px 15px 5px 10px; + position: relative; + box-shadow: 0 0 1px 0 #ccc, 2px 2px 4px 0 rgba(50, 50, 50, .8); + overflow: hidden; + color: #fff; + font-size: 16px; +} + + +.cont-title { + background: rgba(0, 0, 0, .4); + box-shadow: 0 0 1px 0 #fff; + color: #d3bc8e; + padding: 10px 20px; + text-align: left; + border-radius: 10px 10px 0 0; + + span { + font-size: 12px; + color: #aaa; + margin-left: 10px; + font-weight: normal; + } + + &.border-less { + background: linear-gradient(rgba(0, 0, 0, .5), rgba(0, 0, 0, 0)); + box-shadow: none; + padding-bottom: 5px; + } +} + +.cont-body { + padding: 10px 15px; + font-size: 12px; + background: rgba(0, 0, 0, 0.5); + box-shadow: 0 0 1px 0 #fff; + font-weight: normal; +} + + +.cont-footer { + padding: 10px 15px; + font-size: 12px; + background: rgba(0, 0, 0, 0.5); + font-weight: normal; +} + +.cont > ul.cont-msg { + display: block; + padding: 5px 10px; + background: rgba(0, 0, 0, 0.5); +} + +ul.cont-msg, .cont-footer ul { + padding-left: 15px; + + li { + margin: 5px 0; + margin-left: 15px; + + strong { + font-weight: normal; + margin: 0 2px; + color: #d3bc8e; + } + } +} + +.cont-table { + display: table; + width: 100%; +} + +.cont-table .tr { + display: table-row; +} + +.cont-table .tr:nth-child(even) { + background: rgba(0, 0, 0, .4); +} + +.cont-table .tr:nth-child(odd) { + background: rgba(50, 50, 50, .4); +} + +.cont-table .tr > div, +.cont-table .tr > td { + display: table-cell; + box-shadow: 0 0 1px 0 #fff; +} + +.cont-table .tr > div.value-full { + display: table; + width: 200%; +} + +.cont-table .tr > div.value-none { + box-shadow: none; +} + +.cont-table .thead { + text-align: center; +} + +.cont-table .thead > div, +.cont-table .thead > td { + color: #d3bc8e; + background: rgba(0, 0, 0, .4); + line-height: 40px; + height: 40px; +} + + +.cont-table .title, +.cont-table .th { + color: #d3bc8e; + padding-right: 15px; + text-align: right; + background: rgba(0, 0, 0, .4); + min-width: 100px; + vertical-align: middle; +} + +.logo { + font-size: 18px; + text-align: center; + color: #fff; + margin: 20px 0 10px 0; +} + +/* item-icon */ +.item-icon { + width: 100%; + height: 100%; + border-radius: 4px; + position: relative; + overflow: hidden; + + .img { + width: 100%; + height: 100%; + display: block; + background-size: contain; + background-position: center; + background-repeat: no-repeat; + } + + &.artis { + .img { + width: 84%; + height: 84%; + margin: 8%; + } + } + + @stars: 1, 2, 3, 4, 5; + each(@stars, { + &.star@{value} { + background-image: url("../common/item/bg@{value}.png"); + } + &.opacity-bg.star@{value} { + background-image: url("../common/item/bg@{value}-o.png"); + } + }) +} + +.item-list { + display: flex; + + .item-card { + width: 70px; + background: #e7e5d9; + } + + .item-icon { + border-bottom-left-radius: 0; + border-bottom-right-radius: 12px; + } + + .item-title { + color: #222; + font-size: 13px; + text-align: center; + padding: 2px; + white-space: nowrap; + overflow: hidden; + } + + .item-icon { + height: initial; + } + + .item-badge { + position: absolute; + display: block; + left: 0; + top: 0; + background: rgba(0, 0, 0, 0.6); + font-size: 12px; + color: #fff; + padding: 4px 5px 3px; + border-radius: 0 0 6px 0; + } +} \ No newline at end of file diff --git a/resources/common/cont/card-bg.png b/resources/common/cont/card-bg.png new file mode 100644 index 0000000..036d416 Binary files /dev/null and b/resources/common/cont/card-bg.png differ diff --git a/resources/common/cont/logo.png b/resources/common/cont/logo.png new file mode 100644 index 0000000..a8cb922 Binary files /dev/null and b/resources/common/cont/logo.png differ diff --git a/resources/common/face/what.jpg b/resources/common/face/what.jpg new file mode 100644 index 0000000..e9a57f3 Binary files /dev/null and b/resources/common/face/what.jpg differ diff --git a/resources/common/font/HYWH-65W.ttf b/resources/common/font/HYWH-65W.ttf new file mode 100644 index 0000000..e3cfe72 Binary files /dev/null and b/resources/common/font/HYWH-65W.ttf differ diff --git a/resources/common/font/HYWH-65W.woff b/resources/common/font/HYWH-65W.woff new file mode 100644 index 0000000..7cf8a82 Binary files /dev/null and b/resources/common/font/HYWH-65W.woff differ diff --git a/resources/common/font/NZBZ.ttf b/resources/common/font/NZBZ.ttf new file mode 100644 index 0000000..a10dd11 Binary files /dev/null and b/resources/common/font/NZBZ.ttf differ diff --git a/resources/common/font/NZBZ.woff b/resources/common/font/NZBZ.woff new file mode 100644 index 0000000..edf38df Binary files /dev/null and b/resources/common/font/NZBZ.woff differ diff --git a/resources/common/font/tttgbnumber.ttf b/resources/common/font/tttgbnumber.ttf new file mode 100644 index 0000000..89a392f Binary files /dev/null and b/resources/common/font/tttgbnumber.ttf differ diff --git a/resources/common/font/tttgbnumber.woff b/resources/common/font/tttgbnumber.woff new file mode 100644 index 0000000..b35ab09 Binary files /dev/null and b/resources/common/font/tttgbnumber.woff differ diff --git a/resources/common/font/华文中宋.TTF b/resources/common/font/华文中宋.TTF new file mode 100644 index 0000000..2ddb8b2 Binary files /dev/null and b/resources/common/font/华文中宋.TTF differ diff --git a/resources/common/item/artifact-icon.webp b/resources/common/item/artifact-icon.webp new file mode 100644 index 0000000..4fb39d9 Binary files /dev/null and b/resources/common/item/artifact-icon.webp differ diff --git a/resources/common/item/bg1-o.png b/resources/common/item/bg1-o.png new file mode 100644 index 0000000..937aca4 Binary files /dev/null and b/resources/common/item/bg1-o.png differ diff --git a/resources/common/item/bg1.png b/resources/common/item/bg1.png new file mode 100644 index 0000000..5811598 Binary files /dev/null and b/resources/common/item/bg1.png differ diff --git a/resources/common/item/bg2-o.png b/resources/common/item/bg2-o.png new file mode 100644 index 0000000..84b9d88 Binary files /dev/null and b/resources/common/item/bg2-o.png differ diff --git a/resources/common/item/bg2.png b/resources/common/item/bg2.png new file mode 100644 index 0000000..cf8e63c Binary files /dev/null and b/resources/common/item/bg2.png differ diff --git a/resources/common/item/bg3-o.png b/resources/common/item/bg3-o.png new file mode 100644 index 0000000..cd2191f Binary files /dev/null and b/resources/common/item/bg3-o.png differ diff --git a/resources/common/item/bg3.png b/resources/common/item/bg3.png new file mode 100644 index 0000000..c7d4578 Binary files /dev/null and b/resources/common/item/bg3.png differ diff --git a/resources/common/item/bg4-o.png b/resources/common/item/bg4-o.png new file mode 100644 index 0000000..eddbe8a Binary files /dev/null and b/resources/common/item/bg4-o.png differ diff --git a/resources/common/item/bg4.png b/resources/common/item/bg4.png new file mode 100644 index 0000000..8079547 Binary files /dev/null and b/resources/common/item/bg4.png differ diff --git a/resources/common/item/bg5-o.png b/resources/common/item/bg5-o.png new file mode 100644 index 0000000..23bf9fe Binary files /dev/null and b/resources/common/item/bg5-o.png differ diff --git a/resources/common/item/bg5.png b/resources/common/item/bg5.png new file mode 100644 index 0000000..2630db5 Binary files /dev/null and b/resources/common/item/bg5.png differ diff --git a/resources/common/item/bg5.psd b/resources/common/item/bg5.psd new file mode 100644 index 0000000..588f141 Binary files /dev/null and b/resources/common/item/bg5.psd differ diff --git a/resources/common/item/cons0.webp b/resources/common/item/cons0.webp new file mode 100644 index 0000000..31c2102 Binary files /dev/null and b/resources/common/item/cons0.webp differ diff --git a/resources/common/item/crown-o.png b/resources/common/item/crown-o.png new file mode 100644 index 0000000..177c58e Binary files /dev/null and b/resources/common/item/crown-o.png differ diff --git a/resources/common/item/fetter.png b/resources/common/item/fetter.png new file mode 100644 index 0000000..1ccdcf0 Binary files /dev/null and b/resources/common/item/fetter.png differ diff --git a/resources/common/item/star-ltr.png b/resources/common/item/star-ltr.png new file mode 100644 index 0000000..f0895d6 Binary files /dev/null and b/resources/common/item/star-ltr.png differ diff --git a/resources/common/item/star.png b/resources/common/item/star.png new file mode 100644 index 0000000..80d1888 Binary files /dev/null and b/resources/common/item/star.png differ diff --git a/resources/common/layout/default.html b/resources/common/layout/default.html new file mode 100644 index 0000000..a78af10 --- /dev/null +++ b/resources/common/layout/default.html @@ -0,0 +1,21 @@ + + + + + + + + + + + miao-plugin + {{block 'css'}} + {{/block}} + + +
+ {{block 'main'}}{{/block}} + +
+ + \ No newline at end of file diff --git a/resources/common/layout/elem.html b/resources/common/layout/elem.html new file mode 100644 index 0000000..388a8e7 --- /dev/null +++ b/resources/common/layout/elem.html @@ -0,0 +1,21 @@ + + + + + + + + + + + miao-plugin + {{block 'css'}} + {{/block}} + + +
+ {{block 'main'}}{{/block}} + +
+ + \ No newline at end of file diff --git a/resources/common/theme/bg-01.jpg b/resources/common/theme/bg-01.jpg new file mode 100644 index 0000000..6726b9a Binary files /dev/null and b/resources/common/theme/bg-01.jpg differ diff --git a/resources/common/theme/main-01.png b/resources/common/theme/main-01.png new file mode 100644 index 0000000..a3e8918 Binary files /dev/null and b/resources/common/theme/main-01.png differ diff --git a/resources/common/tpl.css b/resources/common/tpl.css new file mode 100644 index 0000000..c63d73e --- /dev/null +++ b/resources/common/tpl.css @@ -0,0 +1,332 @@ +.item-card { + width: 66px; + margin: 4px; + position: relative; + border-radius: 5px; +} +.item-card .badge { + overflow: hidden; + border-radius: 50%; + display: block; + width: 26px; + height: 26px; + position: absolute; + right: -4px; + top: -4px; + background: #e9e5dc; + box-shadow: 0 0 1px 0 rgba(0, 0, 0, 0.8), 2px 2px 2px rgba(50, 50, 50, 0.5); + z-index: 10; +} +.item-card .badge img { + width: 140%; + left: -27%; + top: -45%; + overflow: hidden; + background-size: 100%; + background-repeat: no-repeat; + position: absolute; +} +.item-card .item-bg { + width: 100%; + padding: 100% 0 0; + background-size: contain; + background-repeat: no-repeat; + background-position: center; + margin: 0; +} +.item-card .bg1 { + background-image: url("./item/bg1.png"); + border-radius: 5px 5px 15px 0; +} +.item-card .bg-1 { + background-image: url("./item/bg1.png"); + border-radius: 5px 5px 15px 0; +} +.item-card .bg2 { + background-image: url("./item/bg2.png"); + border-radius: 5px 5px 15px 0; +} +.item-card .bg-2 { + background-image: url("./item/bg2.png"); + border-radius: 5px 5px 15px 0; +} +.item-card .bg3 { + background-image: url("./item/bg3.png"); + border-radius: 5px 5px 15px 0; +} +.item-card .bg-3 { + background-image: url("./item/bg3.png"); + border-radius: 5px 5px 15px 0; +} +.item-card .bg4 { + background-image: url("./item/bg4.png"); + border-radius: 5px 5px 15px 0; +} +.item-card .bg-4 { + background-image: url("./item/bg4.png"); + border-radius: 5px 5px 15px 0; +} +.item-card .bg5 { + background-image: url("./item/bg5.png"); + border-radius: 5px 5px 15px 0; +} +.item-card .bg-5 { + background-image: url("./item/bg5.png"); + border-radius: 5px 5px 15px 0; +} +.item-card .box { + border-radius: 5px; + overflow: hidden; + background: #e9e5dc; +} +.item-card .box .item-desc { + display: block; + font-weight: 500; + text-align: center; + bottom: 0; + background: #e9e5dc; + width: 100%; + font-size: 12px; + line-height: 16px; + white-space: nowrap; + overflow: hidden; + padding: 0 3px; +} +.item-card .box .item-desc:last-child { + padding-bottom: 2px; +} +.item-card .box .name { + overflow: hidden; + white-space: nowrap; + margin-top: 5px; + font-weight: 500; + text-align: center; + font-size: 14px; +} +.item-card .box .item-img { + width: 100%; + overflow: hidden; + background-size: 100%; + background-repeat: no-repeat; + position: absolute; + top: 0; +} +.item-card .item-life { + position: absolute; + top: 0; + left: 0; + z-index: 9; + font-size: 13px; + text-align: center; + color: #fff; + padding: 1px 4px; + border-radius: 3px; +} +.item-card .life1 { + background-color: #62a8ea; +} +.item-card .life2 { + background-color: #62a8ea; +} +.item-card .life3 { + background-color: #62a8ea; +} +.item-card .life4 { + background-color: #ff5722; +} +.item-card .life5 { + background-color: #ff5722; +} +.avatar-card { + margin: 3px; + box-shadow: 0 0 2px 0 rgba(0, 0, 0, 0.8); + font-size: 13px; +} +.avatar-card .card { + border-radius: 7px; + box-shadow: 0 2px 6px 0 rgba(132, 93, 90, 0.3); + position: relative; + overflow: hidden; + background: #e7e5d9; + width: 70px; +} +.avatar-card .avatar-face { + width: 70px; + height: 70px; + border-radius: 7px 7px 15px 0; + background-size: 100% 100%; + background-repeat: no-repeat; + position: relative; + box-shadow: 0 0 2px 0 rgba(0, 0, 0, 0.5); +} +.avatar-card .avatar-face .img { + background-position: center bottom; +} +.avatar-card .avatar-face .avatar-level { + position: absolute; + bottom: 0; + background: rgba(0, 0, 0, 0.6); + left: 0; + padding: 2px 5px 2px 3px; + border-radius: 0 4px 0 0; + color: #fff; +} +.avatar-card .cons { + border-radius: 0 0 0 5px; + padding: 2px 5px; + position: absolute; + right: 0; + top: 0; +} +.avatar-card .avatar-talent { + height: 21px; + padding: 3px 5px 2px; + font-size: 12px; + width: 100%; + color: #222; + text-align: center; + display: flex; +} +.avatar-card .avatar-talent .talent-item { + width: 20px; + height: 16px; + line-height: 17px; + margin: 0 2px; + text-align: center; + display: block; + background-size: contain; + opacity: 0.8; + position: relative; + border-radius: 3px; + box-shadow: 0 0 1px 0 rgba(0, 0, 0, 0.5); +} +.avatar-card .avatar-talent .talent-item.talent-plus { + font-weight: bold; + color: #0284b9; +} +.avatar-card .avatar-talent .talent-item.talent-crown { + background: #d3bc8e; + color: #3a2702; + box-shadow: 0 0 2px 0 #000; +} +.avatar-card .avatar-talent.no-talent { + font-size: 12px; + color: rgba(100, 100, 100, 0.5); + text-align: center; + padding: 3px 0 2px; +} +.avatar-card .avatar-talent.no-talent span { + transform: scale(0.75); + white-space: nowrap; + margin-left: -1px; +} +.avatar-card.card-mini .wide, +.avatar-card.card-mini .line { + display: none; +} +.avatar-card .avatar-name { + padding: 8px 0 0 5px; + color: #333; +} +.avatar-card .avatar-name strong { + font-size: 14px; + display: block; + height: 23px; + line-height: 20px; +} +.avatar-card .avatar-name .cons { + position: initial; + border-radius: 4px; + padding: 1px 3px; + vertical-align: baseline; +} +.avatar-card.card-wide .mini { + display: none; +} +.avatar-card.card-wide .card { + width: 146px; + display: flex; +} +.avatar-card.card-wide .avatar-face { + height: 126px; + width: 76px; + border-radius: 7px 0 0 7px; +} +.avatar-card.card-wide .img { + background-size: 100% auto; + background-position: 0 10%; + height: 135px; + margin-top: -9px; +} +.avatar-card.card-wide .avatar-info { + width: 70px; +} +.avatar-card.card-wide .line { + display: block; + height: 1px; + width: 100%; + margin: 5px 0; + background: linear-gradient(to right, rgba(0, 0, 0, 0), rgba(100, 100, 100, 0.5) 20%, rgba(100, 100, 100, 0.5) 80%, rgba(0, 0, 0, 0)); + transform: scale(0.8); +} +.avatar-card.wide2 .card { + width: 298px; +} +.avatar-card.wide2 .avatar-face { + width: 146px; +} +.avatar-card.wide2 .avatar-face .img { + margin-top: -50px; + height: 176px; +} +.avatar-card.wide2 .avatar-info { + width: 146px; + padding-left: 5px; +} +.avatar-detail { + display: flex; + padding: 0 1px 2px; +} +.avatar-detail .item { + width: 31px; + height: 31px; + border-radius: 4px; + margin: 1px; +} +.avatar-weapon .icon { + border-radius: 4px; +} +.avatar-weapon .cons { + top: initial; + bottom: 0; + padding: 1px 3px; + border-radius: 3px 0 0 0; +} +.avatar-artis { + position: relative; +} +.avatar-artis .artis { + background: rgba(0, 0, 0, 0.5); +} +.avatar-artis.artis2 .img { + position: absolute; + transform: scale(0.7); + width: 92%; + height: 92%; + margin: 4%; +} +.avatar-artis.artis2 .img:first-child { + transform-origin: left top; +} +.avatar-artis.artis2 .img:last-child { + transform-origin: right bottom; +} +.item-list { + display: flex; + flex-wrap: wrap; + transform-origin: 0 0; +} +.item-list .item { + width: 65px; +} +/*# sourceMappingURL=tpl.css.map */ \ No newline at end of file diff --git a/resources/common/tpl.less b/resources/common/tpl.less new file mode 100644 index 0000000..ac47da8 --- /dev/null +++ b/resources/common/tpl.less @@ -0,0 +1,12 @@ +@import url('tpl/item-card'); +@import url('tpl/avatar-card'); + +.item-list { + display: flex; + flex-wrap: wrap; + transform-origin: 0 0; +} + +.item-list .item { + width: 65px; +} \ No newline at end of file diff --git a/resources/common/tpl/artis-detail.css b/resources/common/tpl/artis-detail.css new file mode 100644 index 0000000..06ce5f2 --- /dev/null +++ b/resources/common/tpl/artis-detail.css @@ -0,0 +1,116 @@ +.arti-detail { + width: 185px; + border-radius: 10px; + background: url("../cont/card-bg.png") top left repeat-x; + background-size: auto 100%; + margin: 5px; + position: relative; + box-shadow: 0 0 1px 0 #ccc, 2px 2px 4px 0 rgba(50, 50, 50, 0.8); + height: 205px; + overflow: hidden; +} +.arti-detail .arti-icon { + width: 60px; + height: 60px; + position: absolute; + left: 2px; + top: 3px; +} +.arti-detail .arti-icon span { + position: absolute; + right: 2px; + bottom: 0; + margin-left: 5px; + background: rgba(0, 0, 0, 0.5); + border-radius: 5px; + height: 18px; + line-height: 18px; + padding: 0 3px; + color: #fff; + font-size: 12px; + display: block; +} +.arti-detail .arti-icon img { + width: 60px; + height: 60px; +} +.arti-detail .head { + color: #fff; + padding: 12px 0 8px 68px; +} +.arti-detail .head strong { + font-size: 15px; + display: block; + white-space: nowrap; + overflow: hidden; + font-font: YS; +} +.arti-detail .head span { + font-size: 14px; +} +.arti-detail .head .mark { + font-family: Number, YS; +} +.arti-detail ul.detail { + width: 100%; + padding: 0; + position: initial; + font-family: YS; +} +.arti-detail ul.detail li { + padding: 0 3px; + font-size: 14px; + position: initial; + width: 100%; + display: table; + line-height: 26px; + height: 26px; +} +.arti-detail ul.detail li.nouse span { + color: #888; +} +.arti-detail ul.detail li.arti-main { + font-size: 16px; + padding: 3px 3px; + font-weight: bold; +} +.arti-detail ul.detail li span { + position: initial; + display: table-cell; + color: #fff; + font-family: YS; +} +.arti-detail ul.detail li.title { + text-align: left; + padding-left: 10px; +} +.arti-detail ul.detail li.val { + text-align: right; + padding-right: 10px; + font-family: Number; +} +.arti-detail ul.detail:nth-child(even) { + background: rgba(0, 0, 0, 0.4); +} +.arti-detail ul.detail:nth-child(odd) { + background: rgba(50, 50, 50, 0.4); +} +.arti-detail .avatar { + position: absolute; + left: 32px; + top: 26px; + width: 38px; + height: 38px; + border-radius: 50%; + overflow: hidden; + z-index: 3; +} +.arti-detail .avatar img { + max-width: 100%; + max-height: 100%; +} +.arti-detail .arti-icon img { + width: 52px; + height: 52px; +} +/*# sourceMappingURL=artis-detail.less.map */ \ No newline at end of file diff --git a/resources/common/tpl/avatar-card.css b/resources/common/tpl/avatar-card.css new file mode 100644 index 0000000..379e768 --- /dev/null +++ b/resources/common/tpl/avatar-card.css @@ -0,0 +1,57 @@ +.avatar-card { + margin: 0 0 10px 10px; + border-radius: 7px; + box-shadow: 0 2px 6px 0 rgba(132, 93, 90, 0.3); + height: 88px; + position: relative; + overflow: hidden; + background: #e7e5d9; +} +.avatar-card img { + width: 70px; + height: 70px; + border-radius: 7px 7px 20px 0; +} +.avatar-card.star5 img { + background-image: url(../common/item/bg5.png); + width: 100%; + height: 70px; + /*filter: brightness(1.1);*/ + background-size: 100%; + background-repeat: no-repeat; +} +.avatar-card.star4 img { + width: 100%; + height: 70px; + background-image: url(../common/item/bg4.png); + background-size: 100%; + background-repeat: no-repeat; +} +.avatar-card .num { + position: absolute; + top: 0; + right: 0; + z-index: 9; + font-size: 18px; + text-align: center; + color: #fff; + padding: 1px 5px; + border-radius: 4px; + background: rgba(0, 0, 0, 0.5); +} +.avatar-card .name, +.avatar-card .num_name { + position: absolute; + top: 70px; + left: 0; + z-index: 9; + font-size: 12px; + text-align: center; + width: 100%; + height: 16px; + line-height: 18px; +} +.avatar-card .num_name { + font-size: 16px; +} +/*# sourceMappingURL=avatar-card.css.map */ \ No newline at end of file diff --git a/resources/common/tpl/avatar-card.html b/resources/common/tpl/avatar-card.html new file mode 100644 index 0000000..e5e3c65 --- /dev/null +++ b/resources/common/tpl/avatar-card.html @@ -0,0 +1,53 @@ +{{set avatar = $data[0] || false }} +{{set {_res_path, cardType} = $data[1]}} +{{set weapon = avatar.weapon || {} }} +{{set talentMap = ['a','e','q'] }} + +
+
+ {{if avatar}} +
+
+
+ {{avatar.cons}} +
Lv{{avatar.level}}
+
+
+ {{set talent = avatar.talent || {} }} + {{if talent.a && talent.a.level }} +
+ {{avatar.abbr}} + {{avatar.cons}} + Lv{{avatar.level}} +
+
+
+ {{each talentMap k}} + {{set t = talent[k] || {} }} {{t.level}} + {{/each}} +
+ {{else}} +
暂无天赋数据
+ {{/if}} +
+
+
+
+ + {{weapon.affix}} +
+
+
+
+ {{each avatar.artisSet?.imgs img}} +
+ {{/each}} +
+
+
+
+ {{/if}} +
+
+
\ No newline at end of file diff --git a/resources/common/tpl/avatar-card.less b/resources/common/tpl/avatar-card.less new file mode 100644 index 0000000..f3ce5f9 --- /dev/null +++ b/resources/common/tpl/avatar-card.less @@ -0,0 +1,237 @@ +.avatar-card { + margin: 3px; + box-shadow: 0 0 2px 0 rgba(0, 0, 0, 0.8); + font-size: 13px; + + + .card { + border-radius: 7px; + box-shadow: 0 2px 6px 0 rgb(132 93 90 / 30%); + position: relative; + overflow: hidden; + background: #e7e5d9; + width: 70px; + } + + .avatar-face { + width: 70px; + height: 70px; + border-radius: 7px 7px 15px 0; + background-size: 100% 100%; + background-repeat: no-repeat; + position: relative; + box-shadow: 0 0 2px 0 rgba(0, 0, 0, .5); + + .img { + background-position: center bottom; + } + + + .avatar-level { + position: absolute; + bottom: 0; + background: rgba(0, 0, 0, 0.6); + left: 0; + padding: 2px 5px 2px 3px; + border-radius: 0 4px 0 0; + color: #fff; + } + + + } + + + .cons { + border-radius: 0 0 0 5px; + padding: 2px 5px; + position: absolute; + right: 0; + top: 0; + } + + .avatar-talent { + height: 21px; + padding: 3px 5px 2px; + font-size: 12px; + width: 100%; + color: #222; + text-align: center; + display: flex; + + .talent-item { + width: 20px; + height: 16px; + line-height: 17px; + margin: 0 2px; + text-align: center; + display: block; + background-size: contain; + opacity: 0.8; + position: relative; + border-radius: 3px; + box-shadow: 0 0 1px 0 rgba(0, 0, 0, 0.5); + + &.talent-plus { + font-weight: bold; + color: #0284b9; + } + + &.talent-crown { + background: #d3bc8e; + color: #3a2702; + box-shadow: 0 0 2px 0 #000; + } + } + + &.no-talent { + font-size: 12px; + color: rgba(100, 100, 100, .5); + text-align: center; + padding: 3px 0 2px; + + span { + transform: scale(.75); + white-space: nowrap; + margin-left: -1px; + } + } + } + + &.card-mini { + .wide, .line { + display: none; + } + } + + .avatar-name { + padding: 8px 0 0 5px; + color: #333; + + strong { + font-size: 14px; + display: block; + height: 23px; + line-height: 20px; + } + + .cons { + position: initial; + border-radius: 4px; + padding: 1px 3px; + vertical-align: baseline; + } + } + + &.card-wide { + .mini { + display: none; + } + + .card { + width: 146px; + display: flex; + } + + .avatar-face { + height: 126px; + width: 76px; + border-radius: 7px 0 0 7px; + } + + .img { + background-size: 100% auto; + background-position: 0 10%; + height: 135px; + margin-top: -9px; + } + + .avatar-info { + width: 70px; + } + + .line { + display: block; + height: 1px; + width: 100%; + margin: 5px 0; + background: linear-gradient(to right, rgba(0, 0, 0, 0), rgba(100, 100, 100, .5) 20%, rgba(100, 100, 100, .5) 80%, rgba(0, 0, 0, 0)); + transform: scale(.8) + } + } + + &.wide2 { + .card { + width: 298px; + } + + .avatar-face { + width: 146px; + + .img { + margin-top: -50px; + height: 176px; + } + } + + .avatar-info { + width: 146px; + padding-left: 5px; + } + + + } + +} + +.avatar-detail { + display: flex; + padding: 0 1px 2px; + + .item { + width: 31px; + height: 31px; + border-radius: 4px; + margin: 1px; + } +} + +.avatar-weapon { + .icon { + border-radius: 4px; + } + + .cons { + top: initial; + bottom: 0; + padding: 1px 3px; + border-radius: 3px 0 0 0; + } +} + +.avatar-artis { + position: relative; + + .artis { + background: rgba(0, 0, 0, 0.5) + } + + &.artis2 { + .img { + position: absolute; + transform: scale(.7); + width: 92%; + height: 92%; + margin: 4%; + + &:first-child { + transform-origin: left top; + } + + &:last-child { + transform-origin: right bottom; + } + } + } + + +} \ No newline at end of file diff --git a/resources/common/tpl/avatar-profile.css b/resources/common/tpl/avatar-profile.css new file mode 100644 index 0000000..edf1125 --- /dev/null +++ b/resources/common/tpl/avatar-profile.css @@ -0,0 +1,204 @@ +.profile { + position: relative; + margin-bottom: 10px; +} +.profile:after { + content: ""; + display: block; + position: absolute; + left: 8px; + top: 115px; + bottom: 0; + right: 8px; + box-shadow: 0 0 2px 0 #fff; + border-radius: 5px; + z-index: 1; +} +.profile .main-pic { + width: 800px; + height: 500px; + background-size: contain; + background-repeat: no-repeat; + background-position: center; + margin-left: -260px; + position: relative; + z-index: 2; +} +.profile .detail { + position: absolute; + right: 20px; + top: 20px; + color: #fff; + z-index: 3; +} +.profile .char-name { + font-size: 50px; + font-family: NZBZ; + text-shadow: 0 0 3px #000, 2px 2px 4px rgba(0, 0, 0, 0.7); + text-align: right; +} +.profile .char-lv { + font-family: Number; + margin-bottom: 20px; + text-shadow: 0 0 3px #000, 2px 2px 4px rgba(0, 0, 0, 0.7); + text-align: right; +} +.profile .attr { + border-radius: 4px; + overflow: hidden; +} +.profile .detail li { + width: 300px; + font-size: 17px; + list-style: none; + padding: 0 100px 0 35px; + position: relative; + font-family: YS; + height: 32px; + line-height: 32px; + text-shadow: 0 0 1px rgba(0, 0, 0, 0.5); +} +.profile .attr li i { + display: inline-block; + height: 20px; + width: 20px; + background-image: url("../../character/icon.png"); + background-size: auto 20px; + position: absolute; + left: 10px; + top: 8px; + opacity: 0.9; + transform: scale(0.9); +} +.profile .i-hp { + background-position: -20px 0; +} +.profile .i-atk { + background-position: -40px 0; +} +.profile .i-def { + background-position: -60px 0; +} +.profile .i-mastery { + background-position: -80px 0; +} +.profile .i-cr { + background-position: -100px 0; +} +.profile .i-cd { + background-position: -140px 0; +} +.profile .i-re { + background-position: -120px 0; +} +.profile .i-dmg { + background-position: -160px 0; +} +.profile .detail li:nth-child(even) { + background: rgba(0, 0, 0, 0.4); +} +.profile .detail li:nth-child(odd) { + background: rgba(50, 50, 50, 0.4); +} +.profile .detail li strong { + display: inline-block; + position: absolute; + right: 85px; + text-align: right; + font-family: Number, sans-serif; + font-weight: normal; +} +.profile .detail li span { + position: absolute; + right: 0; + text-align: left; + width: 75px; + display: inline-block; + font-family: Number, sans-serif; + color: #90e800; + font-size: 15px; +} +.profile .talent-icon { + width: 100px; + height: 100px; + padding: 5px; + display: table; + border-radius: 50%; + position: relative; + background-size: contain; + background-repeat: no-repeat; + background-position: center center; + z-index: 90; +} +.profile .talent-icon img, +.profile .talent-icon .profile .talent-icon-img { + width: 46%; + height: 46%; + position: absolute; + top: 50%; + left: 50%; + margin: -22% 0 0 -23%; + background-size: contain; + background-repeat: no-repeat; + background-position: center; +} +.profile .talent-icon span { + background: #fff; + width: 34px; + height: 26px; + line-height: 26px; + font-size: 17px; + text-align: center; + border-radius: 5px; + position: absolute; + bottom: 2px; + left: 50%; + margin-left: -15px; + color: #000; + box-shadow: 0 0 5px 0 #000; + font-family: Number; +} +.profile .talent-icon.talent-plus span { + background: #2e353e; + color: #ffdfa0; + font-weight: bold; + box-shadow: 0 0 1px 0 #d3bc8e, 1px 1px 2px 0 rgba(0, 0, 0, 0.5); +} +.profile .talent-icon.talent-crown:after { + content: ""; + display: block; + width: 28px; + height: 28px; + background: url("../character/imgs/crown.png") no-repeat; + background-size: contain; + position: absolute; + left: 50%; + top: 0; + margin-left: -14px; +} +.profile .char-talents { + display: flex; + width: 300px; + margin-bottom: 10px; +} +.profile .char-cons .talent-item, +.profile .char-talents .talent-item { + flex: 1; +} +.profile .char-cons { + display: flex; + width: 250px; + position: absolute; + bottom: 5px; + left: 20px; +} +.profile .char-cons .talent-icon { + width: 50px; + height: 50px; + margin: 0 -5px; +} +.profile .char-cons .talent-icon.off { + filter: grayscale(100%); + opacity: 0.4; +} +/*# sourceMappingURL=avatar-profile-source.css.map */ \ No newline at end of file diff --git a/resources/common/tpl/item-card.css b/resources/common/tpl/item-card.css new file mode 100644 index 0000000..d5bfc61 --- /dev/null +++ b/resources/common/tpl/item-card.css @@ -0,0 +1,113 @@ +.item-card { + width: 52px; + margin: 0px 0 5px 7px; + position: relative; +} +.item-card .badge { + overflow: hidden; + border-radius: 5px; + position: relative; + background: #e9e5dc; + box-shadow: 0 2px 6px 0 rgba(132, 93, 90, 0.3); +} +.item-card .badge img { + width: 100%; + overflow: hidden; + background-size: 100%; + background-repeat: no-repeat; + position: absolute; + top: 0; + /*filter: contrast(95%);*/ +} +.item-card .bg1 { + background-image: url("imgs/bg1.png"); + width: 100%; + height: 70px; + background-size: 100%; + background-repeat: no-repeat; +} +.item-card .bg2 { + background-image: url("imgs/bg2.png"); + width: 100%; + height: 70px; + background-size: 100%; + background-repeat: no-repeat; +} +.item-card .bg3 { + background-image: url("imgs/bg3.png"); + width: 100%; + height: 70px; + background-size: 100%; + background-repeat: no-repeat; +} +.item-card .bg4 { + background-image: url("imgs/bg4.png"); + width: 100%; + height: 70px; + background-size: 100%; + background-repeat: no-repeat; +} +.item-card .bg5 { + background-image: url("imgs/bg5.png"); + width: 100%; + height: 70px; + background-size: 100%; + background-repeat: no-repeat; +} +.item-card .box:after { + content: ""; + display: block; + position: absolute; + width: 15px; + right: 0; + bottom: 15px; +} +.item-card .box .desc { + font-weight: 500; + text-align: center; + position: absolute; + bottom: 0; + background: #e9e5dc; + width: 100%; + height: 16px; + font-size: 12px; + line-height: 16px; + font-family: Number; +} +.item-card .box .name { + overflow: hidden; + white-space: nowrap; + margin-top: 5px; + font-weight: 500; + text-align: center; + font-size: 14px; +} +.item-card .life { + position: absolute; + top: 0px; + left: 0px; + z-index: 9; + font-size: 13px; + text-align: center; + color: #fff; + border-radius: 2px; + padding: 1px 4px; + border-radius: 3px; + font-family: "tttgbnumber"; +} +.item-card .life1 { + background-color: #62a8ea; +} +.item-card .life2 { + background-color: #62a8ea; +} +.item-card .life3 { + background-color: #62a8ea; +} +.item-card .life4 { + background-color: #ff5722; +} +.item-card .life5 { + background-color: #ff5722; +} +/*# sourceMappingURL=item-card.less.map */ \ No newline at end of file diff --git a/resources/common/tpl/item-card.less b/resources/common/tpl/item-card.less new file mode 100644 index 0000000..74eb0b9 --- /dev/null +++ b/resources/common/tpl/item-card.less @@ -0,0 +1,120 @@ + +.item-card { + width: 66px; + margin: 4px; + position: relative; + border-radius: 5px; + + + .badge { + overflow: hidden; + border-radius: 50%; + display: block; + width: 26px; + height: 26px; + position: absolute; + right: -4px; + top: -4px; + background: #e9e5dc; + box-shadow: 0 0 1px 0 rgba(0, 0, 0, 0.8), 2px 2px 2px rgba(50, 50, 50, .5); + z-index: 10; + + + img { + width: 140%; + left: -27%; + top: -45%; + overflow: hidden; + background-size: 100%; + background-repeat: no-repeat; + position: absolute; + } + } + + .item-bg { + width: 100%; + padding: 100% 0 0; + background-size: contain; + background-repeat: no-repeat; + background-position: center; + margin: 0; + } + + each(range(5), { + .bg@{value} { + background-image: url("./item/bg@{value}.png"); + border-radius: 5px 5px 15px 0; + } + .bg-@{value} { + background-image: url("./item/bg@{value}.png"); + border-radius: 5px 5px 15px 0; + } + }) + + .box { + border-radius: 5px; + overflow: hidden; + background: #e9e5dc; + + .item-desc { + display: block; + font-weight: 500; + text-align: center; + bottom: 0; + background: #e9e5dc; + width: 100%; + font-size: 12px; + line-height: 16px; + white-space: nowrap; + overflow: hidden; + padding: 0 3px; + + &:last-child { + padding-bottom: 2px; + } + } + + .name { + overflow: hidden; + white-space: nowrap; + margin-top: 5px; + font-weight: 500; + text-align: center; + font-size: 14px; + } + + .item-img { + width: 100%; + overflow: hidden; + background-size: 100%; + background-repeat: no-repeat; + position: absolute; + top: 0; + } + } + + .item-life { + position: absolute; + top: 0; + left: 0; + z-index: 9; + font-size: 13px; + text-align: center; + color: #fff; + padding: 1px 4px; + border-radius: 3px; + } + + .life(@idx, @color) { + .life@{idx} { + background-color: @color; + } + } + + .life(1, #62a8ea); + .life(2, #62a8ea); + .life(3, #62a8ea); + .life(4, #ff5722); + .life(5, #ff5722); +} + diff --git a/resources/common/tpl/talent-detail.html b/resources/common/tpl/talent-detail.html new file mode 100644 index 0000000..77d2e75 --- /dev/null +++ b/resources/common/tpl/talent-detail.html @@ -0,0 +1,61 @@ +{{set ds = $data[0] || false }} +{{set {_res_path, icon,lvs,type} = $data[1]}} + +
+
+ +
+
+
{{ds.name}}
+
+ {{each ds.desc d}} + {{ if d[0] === "<" }} + {{@d}} + {{else if d!=""}} +

{{d}}

+ {{/if}} + {{/each}} +
+
+ + {{if ds.tables && ds.tables.length > 0}} +
+ {{each ds.tables tr}} + {{if tr.isSame}} +
+ {{tr.name}}{{if tr.unit}}({{tr.unit}}){{/if}} + {{tr.values[0]}} +
+ {{/if}} + {{/each}} +
+ + + + {{each lvs lv idx}} + {{if (type=="a" && idx>4 && idx<11) || (type!="a" && idx>4 && idx < 13)}} + + {{/if}} + {{/each}} + + {{each ds.tables tr}} + {{if !tr.isSame}} + + + + {{each tr.values v idx}} + {{if (type=="a" && idx>4 && idx<11) || (type!="a" && idx>4 && idx < 13)}} + + {{/if}} + {{/each}} + {{/if}} + + {{/each}} +
{{lv}}
+ {{tr.name}} + {{if tr.unit}} + ({{tr.unit}}) + {{/if}} + {{v}}
+ {{/if}} +
diff --git a/resources/help/icon.png b/resources/help/icon.png new file mode 100644 index 0000000..fb15d68 Binary files /dev/null and b/resources/help/icon.png differ diff --git a/resources/help/index.css b/resources/help/index.css new file mode 100644 index 0000000..b0db1f8 --- /dev/null +++ b/resources/help/index.css @@ -0,0 +1,83 @@ +body { + transform: scale(1); + width: 830px; + background: url("../common/theme/bg-01.jpg"); +} +.container { + background: url(../common/theme/main-01.png) top left no-repeat; + background-size: 100% auto; + width: 830px; +} +.head-box { + margin: 60px 0 0 0; + padding-bottom: 0; +} +.head-box .title { + font-size: 50px; +} +.cont-box { + border-radius: 15px; + margin-top: 20px; + margin-bottom: 20px; + overflow: hidden; + box-shadow: 0 5px 10px 0 rgba(0, 0, 0, 0.15); + position: relative; +} +.help-group { + font-size: 18px; + font-weight: bold; + padding: 15px 15px 10px 20px; +} +.help-table { + text-align: center; + border-collapse: collapse; + margin: 0; + border-radius: 0 0 10px 10px; + display: table; + overflow: hidden; + width: 100%; + color: #fff; +} +.help-table .tr { + display: table-row; +} +.help-table .td, +.help-table .th { + font-size: 14px; + display: table-cell; + box-shadow: 0 0 1px 0 #888 inset; + padding: 12px 0 12px 50px; + line-height: 24px; + position: relative; + text-align: left; +} +.help-table .tr:last-child .td { + padding-bottom: 12px; +} +.help-table .th { + background: rgba(34, 41, 51, 0.5); +} +.help-icon { + width: 40px; + height: 40px; + display: block; + position: absolute; + background: url("icon.png") 0 0 no-repeat; + background-size: 500px auto; + border-radius: 5px; + left: 6px; + top: 12px; + transform: scale(0.85); +} +.help-title { + display: block; + color: #d3bc8e; + font-size: 16px; + line-height: 24px; +} +.help-desc { + display: block; + font-size: 13px; + line-height: 18px; +} +/*# sourceMappingURL=index.css.map */ \ No newline at end of file diff --git a/resources/help/index.html b/resources/help/index.html new file mode 100644 index 0000000..cac6d03 --- /dev/null +++ b/resources/help/index.html @@ -0,0 +1,44 @@ +{{extend defaultLayout}} + +{{block 'css'}} + +<% style = style.replace(/{{_res_path}}/g, _res_path) %> +{{@style}} +{{/block}} + +{{block 'main'}} + +
+
+
{{helpCfg.title||"使用帮助"}}
+
{{helpCfg.subTitle || "Yunzai-Bot & Miao-Plugin"}}
+
+
+ +{{each helpGroup group}} +{{set len = group?.list?.length || 0 }} +
+
{{group.group}}
+ {{if len > 0}} +
+
+ {{each group.list help idx}} +
+ + {{help.title}} + {{help.desc}} +
+ {{if idx%colCount === colCount-1 && idx>0 && idx< len-1}} +
+
+ {{/if}} + {{/each}} + <% for(let i=(len-1)%colCount; i< colCount-1 ; i++){ %> +
+ <% } %> +
+
+ {{/if}} +
+{{/each}} +{{/block}} \ No newline at end of file diff --git a/resources/help/index.less b/resources/help/index.less new file mode 100644 index 0000000..3ea3dad --- /dev/null +++ b/resources/help/index.less @@ -0,0 +1,96 @@ +body { + transform: scale(1); + width: 830px; + background: url("../common/theme/bg-01.jpg"); +} + +.container { + background: url(../common/theme/main-01.png) top left no-repeat; + background-size: 100% auto; + width: 830px; +} + +.head-box { + margin: 60px 0 0 0; + padding-bottom: 0; +} + +.head-box .title { + font-size: 50px; +} + +.cont-box { + border-radius: 15px; + margin-top: 20px; + margin-bottom: 20px; + overflow: hidden; + box-shadow: 0 5px 10px 0 rgb(0 0 0 / 15%); + position: relative; +} + +.help-group { + font-size: 18px; + font-weight: bold; + padding: 15px 15px 10px 20px; +} + +.help-table { + text-align: center; + border-collapse: collapse; + margin: 0; + border-radius: 0 0 10px 10px; + display: table; + overflow: hidden; + width: 100%; + color: #fff; +} + +.help-table .tr { + display: table-row; +} + +.help-table .td, +.help-table .th { + font-size: 14px; + display: table-cell; + box-shadow: 0 0 1px 0 #888 inset; + padding: 12px 0 12px 50px; + line-height: 24px; + position: relative; + text-align: left; +} + +.help-table .tr:last-child .td { + padding-bottom: 12px; +} + +.help-table .th { + background: rgba(34, 41, 51, .5) +} + +.help-icon { + width: 40px; + height: 40px; + display: block; + position: absolute; + background: url("icon.png") 0 0 no-repeat; + background-size: 500px auto; + border-radius: 5px; + left: 6px; + top: 12px; + transform: scale(0.85); +} + +.help-title { + display: block; + color: #d3bc8e; + font-size: 16px; + line-height: 24px; +} + +.help-desc { + display: block; + font-size: 13px; + line-height: 18px; +} + diff --git a/resources/help/theme/default/bg.jpg b/resources/help/theme/default/bg.jpg new file mode 100644 index 0000000..6726b9a Binary files /dev/null and b/resources/help/theme/default/bg.jpg differ diff --git a/resources/help/theme/default/config.js b/resources/help/theme/default/config.js new file mode 100644 index 0000000..fe2ba52 --- /dev/null +++ b/resources/help/theme/default/config.js @@ -0,0 +1,24 @@ +export const style = { + // 主文字颜色 + fontColor: '#ceb78b', + // 主文字阴影: 横向距离 垂直距离 阴影大小 阴影颜色 + // fontShadow: '0px 0px 1px rgba(6, 21, 31, .9)', + fontShadow: 'none', + // 描述文字颜色 + descColor: '#eee', + + /* 面板整体底色,会叠加在标题栏及帮助行之下,方便整体帮助有一个基础底色 + * 若无需此项可将rgba最后一位置为0即为完全透明 + * 注意若综合透明度较低,或颜色与主文字颜色过近或太透明可能导致阅读困难 */ + contBgColor: 'rgba(6, 21, 31, .5)', + + // 面板底图毛玻璃效果,数字越大越模糊,0-10 ,可为小数 + contBgBlur: 3, + + // 板块标题栏底色 + headerBgColor: 'rgba(6, 21, 31, .4)', + // 帮助奇数行底色 + rowBgColor1: 'rgba(6, 21, 31, .2)', + // 帮助偶数行底色 + rowBgColor2: 'rgba(6, 21, 31, .35)' +} diff --git a/resources/help/theme/default/main.png b/resources/help/theme/default/main.png new file mode 100644 index 0000000..a3e8918 Binary files /dev/null and b/resources/help/theme/default/main.png differ diff --git a/resources/help/theme/目录说明.txt b/resources/help/theme/目录说明.txt new file mode 100644 index 0000000..a65c3df --- /dev/null +++ b/resources/help/theme/目录说明.txt @@ -0,0 +1,24 @@ +【default皮肤】 +default为默认皮肤,不建议改动,防止后续更新冲突 +如不想使用default可创建或下载其他皮肤,存在其他皮肤时会默认忽略default皮肤 + +【增加自定义皮肤】 +可创建或下载皮肤包,放置在当前目录(theme)下,皮肤名称为皮肤文件夹名字 + +皮肤包内应包含的文件: +main.png:主图,高度自适应 +bg.jpg:背景图,如果main.png图片不够高或存在透明的话则会使用bg.jpg作为背景进行填充 +config.js:当前皮肤元素的颜色、透明度等配置,可选。如无此文件会使用默认配置,如需自定义,可参考default/config.js + + +【皮肤选择】 +默认为随机皮肤,如需指定固定某个皮肤可到config/help.js中,设置theme的字段选项 + +在有其他皮肤时,会默认忽略自带的default皮肤 +如希望default皮肤也出现在随机中,可修改config/help.js,将themeExclude中配置的default项删掉 +如需临时增加其他皮肤屏蔽,也可以追加至themeExclude中(当然也可以直接删掉对应皮肤) + +新增皮肤或修改配置后无需重启,可直接生效 + + + diff --git a/resources/help/version-info.css b/resources/help/version-info.css new file mode 100644 index 0000000..0758627 --- /dev/null +++ b/resources/help/version-info.css @@ -0,0 +1,68 @@ +* { + margin: 0; + padding: 0; + box-sizing: border-box; + user-select: none; +} +body { + font-size: 18px; + color: #1e1f20; + transform: scale(1.3); + transform-origin: 0 0; + width: 520px; +} +.container { + width: 520px; + padding: 10px 0 10px 0; + background-size: 100% 100%; +} +.log-cont { + background-size: cover; + margin: 5px 15px 5px 10px; + border-radius: 10px; +} +.log-cont .cont { + margin: 0; +} +.log-cont .cont-title { + font-size: 16px; + padding: 10px 20px 6px; +} +.log-cont .cont-title.current-version { + font-size: 20px; +} +.log-cont ul { + font-size: 14px; + padding-left: 20px; +} +.log-cont ul li { + margin: 3px 0; +} +.log-cont ul.sub-log-ul li { + margin: 1px 0; +} +.log-cont .cmd { + color: #d3bc8e; + display: inline-block; + border-radius: 3px; + background: rgba(0, 0, 0, 0.5); + padding: 0 3px; + margin: 1px 2px; +} +.log-cont .strong { + color: #24d5cd; +} +.log-cont .new { + display: inline-block; + width: 18px; + margin: 0 -3px 0 1px; +} +.log-cont .new:before { + content: "NEW"; + display: inline-block; + transform: scale(0.6); + transform-origin: 0 0; + color: #d3bc8e; + white-space: nowrap; +} +/*# sourceMappingURL=version-info.css.map */ \ No newline at end of file diff --git a/resources/help/version-info.html b/resources/help/version-info.html new file mode 100644 index 0000000..97fe2cb --- /dev/null +++ b/resources/help/version-info.html @@ -0,0 +1,35 @@ +{{extend elemLayout}} + +{{block 'css'}} + +{{/block}} + +{{block 'main'}} +{{each changelogs ds idx}} +
+
+ {{if idx === 0 }} +
当前版本 {{ds.version}}
+ {{else}} +
小飞版本 {{ds.version}}
+ {{/if}} +
+
    + {{each ds.logs log}} +
  • +

    {{@log.title}}

    + {{if log.logs.length > 0}} +
      + {{each log.logs ls}} +
    • {{@ls}}
    • + {{/each}} +
    + {{/if}} +
  • + {{/each}} +
+
+
+
+{{/each}} +{{/block}} \ No newline at end of file diff --git a/resources/help/version-info.less b/resources/help/version-info.less new file mode 100644 index 0000000..d71e540 --- /dev/null +++ b/resources/help/version-info.less @@ -0,0 +1,90 @@ +.linear-bg(@color) { + background-image: linear-gradient(to right, @color, @color 80%, fade(@color, 0) 100%); +} + +* { + margin: 0; + padding: 0; + box-sizing: border-box; + user-select: none; +} + +body { + font-size: 18px; + color: #1e1f20; + transform: scale(1.3); + transform-origin: 0 0; + width: 520px; +} + +.container { + width: 520px; + padding: 10px 0 10px 0; + background-size: 100% 100%; + +} + +.log-cont { + background-size: cover; + margin: 5px 15px 5px 10px; + border-radius: 10px; + + .cont { + margin: 0; + } + + .cont-title { + font-size: 16px; + padding: 10px 20px 6px; + + &.current-version { + font-size: 20px; + } + } + + .cont-body { + } + + ul { + font-size: 14px; + padding-left: 20px; + + li { + margin: 3px 0; + } + + &.sub-log-ul { + li { + margin: 1px 0; + } + } + } + + .cmd { + color: #d3bc8e; + display: inline-block; + border-radius: 3px; + background: rgba(0, 0, 0, 0.5); + padding: 0 3px; + margin: 1px 2px; + } + + .strong { + color: #24d5cd; + } + + .new { + display: inline-block; + width: 18px; + margin: 0 -3px 0 1px; + } + + .new:before { + content: "NEW"; + display: inline-block; + transform: scale(0.6); + transform-origin: 0 0; + color: #d3bc8e; + white-space: nowrap; + } +} \ No newline at end of file