This commit is contained in:
touchscale 2023-08-06 00:46:07 +08:00
commit 65ea249513
26 changed files with 1264 additions and 880 deletions

View File

@ -22,5 +22,7 @@ online_msg: true
# 上线推送通知的冷却时间
online_msg_exp: 86400
# 签名API地址
# 签名API地址(如:http://127.0.0.1:8080/sign?key=114514)
sign_api_addr:
# 传入的QQ版本(如:8.9.63、8.9.68)
ver:

View File

@ -15,6 +15,7 @@ export default class Yunzai extends Client {
/** 加载icqq事件监听 */
await ListenerLoader.load(bot)
await bot.login(cfg.qq, cfg.pwd)
bot[bot.uin] = bot
return bot
}
}

View File

@ -9,7 +9,7 @@ import path from 'node:path'
* @param user_id qq号
* @param msg 消息
*/
async function relpyPrivate (userId, msg) {
async function relpyPrivate(userId, msg) {
userId = Number(userId)
let friend = Bot.fl.get(userId)
@ -25,7 +25,7 @@ async function relpyPrivate (userId, msg) {
* 休眠函数
* @param ms 毫秒
*/
function sleep (ms) {
function sleep(ms) {
return new Promise((resolve) => setTimeout(resolve, ms))
}
@ -34,7 +34,7 @@ function sleep (ms) {
* @param fileUrl 下载地址
* @param savePath 保存路径
*/
async function downFile (fileUrl, savePath, param = {}) {
async function downFile(fileUrl, savePath, param = {}) {
try {
mkdirs(path.dirname(savePath))
logger.debug(`[下载文件] ${fileUrl}`)
@ -48,7 +48,7 @@ async function downFile (fileUrl, savePath, param = {}) {
}
}
function mkdirs (dirname) {
function mkdirs(dirname) {
if (fs.existsSync(dirname)) {
return true
} else {
@ -61,19 +61,20 @@ function mkdirs (dirname) {
/**
* 制作转发消息
* @param e icqq消息e
* @param e 消息事件
* @param msg 消息数组
* @param dec 转发描述
* @param msgsscr 转发信息是否为Bot
* @param msgsscr 转发信息是否伪装
*/
async function makeForwardMsg (e, msg = [], dec = '', msgsscr = false) {
// 是频道直接返回 join
if (e.isGuild) return msg.join('\n')
async function makeForwardMsg(e, msg = [], dec = '', msgsscr = false) {
if (!Array.isArray(msg)) msg = [msg]
let name = msgsscr ? e.sender.card || e.user_id : Bot.nickname
let id = msgsscr ? e.user_id : Bot.uin
let name = msgsscr ? this.e.sender.card || this.e.user_id : Bot.nickname
let id = msgsscr ? this.e.user_id : Bot.uin
if (e.isGroup) {
let info = await e.bot.getGroupMemberInfo(e.group_id, e.bot.uin)
let info = await e.bot.getGroupMemberInfo(e.group_id, id)
name = info.card || info.nickname
}
let userInfo = {
@ -82,28 +83,37 @@ async function makeForwardMsg (e, msg = [], dec = '', msgsscr = false) {
}
let forwardMsg = []
msg.forEach(msg => {
for (const message of msg){
if(!message) continue
forwardMsg.push({
...userInfo,
message: msg
message: message
})
})
}
/** 制作转发内容 */
if (e.isGroup) {
if (e?.group?.makeForwardMsg) {
forwardMsg = await e.group.makeForwardMsg(forwardMsg)
} else if (e.friend) {
} else if (e?.friend?.makeForwardMsg) {
forwardMsg = await e.friend.makeForwardMsg(forwardMsg)
} else {
return false
return msg.join('\n')
}
if (dec) {
/** 处理描述 */
forwardMsg.data = forwardMsg.data
.replace(/\n/g, '')
.replace(/<title color="#777777" size="26">(.+?)<\/title>/g, '___')
.replace(/___+/, `<title color="#777777" size="26">${dec}</title>`)
if (typeof (forwardMsg.data) === 'object') {
let detail = forwardMsg.data?.meta?.detail
if (detail) {
detail.news = [{ text: dec }]
}
} else {
forwardMsg.data = forwardMsg.data
.replace(/\n/g, '')
.replace(/<title color="#777777" size="26">(.+?)<\/title>/g, '___')
.replace(/___+/, `<title color="#777777" size="26">${dec}</title>`)
}
}
return forwardMsg

View File

@ -21,7 +21,7 @@
"chalk": "^5.2.0",
"chokidar": "^3.5.3",
"https-proxy-agent": "5.0.1",
"icqq": "^0.4.11",
"icqq": "^0.4.12",
"image-size": "^1.0.2",
"inquirer": "^8.2.5",
"lodash": "^4.17.21",

View File

@ -1,11 +1,12 @@
import plugin from '../../../lib/plugins/plugin.js'
import common from '../../../lib/common/common.js'
import fs from 'node:fs'
import gsCfg from '../model/gsCfg.js'
import YAML from 'yaml'
import lodash from 'lodash'
export class abbrSet extends plugin {
constructor (e) {
constructor(e) {
super({
name: '别名设置',
dsc: '角色别名设置',
@ -13,24 +14,24 @@ export class abbrSet extends plugin {
priority: 600,
rule: [
{
reg: '^#(设置|配置)(.*)(别名|昵称)$',
reg: '^#(星铁)?(设置|配置)(.*)(别名|昵称)$',
fnc: 'abbr'
},
{
reg: '^#删除(别名|昵称)(.*)$',
reg: '^#(星铁)?删除(别名|昵称)(.*)$',
fnc: 'delAbbr'
},
{
reg: '^#(.*)(别名|昵称)$',
reg: '^#(星铁)?(.*)(别名|昵称)$',
fnc: 'abbrList'
}
]
})
this.isSr = false
this.file = './plugins/genshin/config/role.name.yaml'
}
async init () {
async init() {
if (!fs.existsSync(this.file)) {
fs.writeFileSync(this.file, `神里绫华:
- 龟龟
@ -38,17 +39,18 @@ export class abbrSet extends plugin {
}
}
async abbr () {
async abbr() {
if (!await this.checkAuth()) return
let role = gsCfg.getRole(this.e.msg, '#|设置|配置|别名|昵称')
let role = gsCfg.getRole(this.e.msg, '#|星铁|设置|配置|别名|昵称', this.e.isSr)
if (!role) return false
this.e.role = role
this.isSr = this.e.isSr
this.setContext('setAbbr')
await this.reply(`请发送${role.alias}别名,多个用空格隔开`)
}
async checkAuth () {
async checkAuth() {
if (!this.e.isGroup && !this.e.isMaster) {
await this.reply('禁止私聊设置角色别名')
return false
@ -76,7 +78,7 @@ export class abbrSet extends plugin {
return true
}
async setAbbr () {
async setAbbr() {
if (!this.e.msg || this.e.at || this.e.img) {
await this.reply('设置错误:请发送正确内容')
return
@ -96,10 +98,10 @@ export class abbrSet extends plugin {
let ret = []
for (let name of setName) {
name = name.replace(/#|设置|配置|别名|昵称/g, '')
name = name.replace(/#|星铁|设置|配置|别名|昵称/g, '')
if (!name) continue
/** 重复添加 */
if (nameArr[role.name].includes(name) || gsCfg.roleNameToID(name)) {
if (nameArr[role.name].includes(name) || gsCfg.roleNameToID(name, this.isSr)) {
continue
}
@ -113,19 +115,18 @@ export class abbrSet extends plugin {
this.save(nameArr)
gsCfg.nameID = false
gsCfg[this.isSr ? 'sr_nameID' : 'nameID'] = false
await this.reply(`设置别名成功:${ret.join('、')}`)
}
save (data) {
save(data) {
data = YAML.stringify(data)
fs.writeFileSync(this.file, data)
}
async delAbbr () {
let role = gsCfg.getRole(this.e.msg, '#|删除|别名|昵称')
async delAbbr() {
let role = gsCfg.getRole(this.e.msg, '#|星铁|删除|别名|昵称', this.e.isSr)
if (!role) return false
let nameArr = gsCfg.getConfig('role', 'name')
@ -145,12 +146,12 @@ export class abbrSet extends plugin {
await this.reply(`设置${role.name}别名成功:${role.alias}`)
}
async abbrList () {
let role = gsCfg.getRole(this.e.msg, '#|别名|昵称')
async abbrList() {
let role = gsCfg.getRole(this.e.msg, '#|星铁|别名|昵称', this.e.isSr)
if (!role) return false
let name = gsCfg.getdefSet('role', 'name')[role.roleId]
let name = gsCfg.getdefSet('role', this.e.isSr ? 'sr_name' : 'name')[role.roleId]
let nameUser = gsCfg.getConfig('role', 'name')[role.name] ?? []
let list = lodash.uniq([...name, ...nameUser])
@ -158,51 +159,13 @@ export class abbrSet extends plugin {
let msg = []
for (let i in list) {
let num = Number(i) + 1
msg.push(`${num}.${list[i]}\n`)
msg.push(`${num}.${list[i]}`)
}
let title = `${role.name}别名,${list.length}`
msg = await this.makeForwardMsg(this.e.bot.uin, title, msg)
msg = await common.makeForwardMsg(this.e, [title, msg.join("\n")], title)
await this.e.reply(msg)
}
async makeForwardMsg (qq, title, msg) {
let nickname = this.e.bot.nickname
if (this.e.isGroup) {
let info = await this.e.bot.getGroupMemberInfo(this.e.group_id, qq)
nickname = info.card ?? info.nickname
}
let userInfo = {
user_id: this.e.bot.uin,
nickname
}
let forwardMsg = [
{
...userInfo,
message: title
},
{
...userInfo,
message: msg
}
]
/** 制作转发内容 */
if (this.e.isGroup) {
forwardMsg = await this.e.group.makeForwardMsg(forwardMsg)
} else {
forwardMsg = await this.e.friend.makeForwardMsg(forwardMsg)
}
/** 处理描述 */
forwardMsg.data = forwardMsg.data
.replace(/\n/g, '')
.replace(/<title color="#777777" size="26">(.+?)<\/title>/g, '___')
.replace(/___+/, `<title color="#777777" size="26">${title}</title>`)
return forwardMsg
}
}

View File

@ -5,7 +5,7 @@ import puppeteer from '../../../lib/puppeteer/puppeteer.js'
import gsCfg from '../model/gsCfg.js'
export class calculator extends plugin {
constructor () {
constructor() {
super({
name: '养成计算',
dsc: '角色养成材料计算器',
@ -13,47 +13,48 @@ export class calculator extends plugin {
priority: 700,
rule: [
{
reg: '^#*(.*)(养成|计算)([0-9]|,|| )*$',
reg: '^#*(星铁)?(.*)(养成|计算)([0-9]|,|| )*$',
fnc: 'Calculator'
},
{
reg: '^#*角色(养成|计算|养成计算)$',
reg: '^#*(星铁)?角色(养成|计算|养成计算)$',
fnc: 'calculatorHelp'
},
{
reg: '^#*尘歌壶模数(养成|计算|养成计算)$',
fnc: 'blueprintHelp'
},
{
reg: '^#*尘歌壶(模数|养成|养成计算)(\\d{10,15})$',
fnc: 'Blueprint'
},
{
reg: '^#*尘歌壶模数(养成|计算|养成计算)$',
fnc: 'blueprintHelp'
},
{
reg: '^#*尘歌壶(模数|养成|养成计算)(\\d{10,15})$',
fnc: 'Blueprint'
},
]
})
this._path = process.cwd().replace(/\\/g, '/')
}
async blueprintHelp (e) {
async blueprintHelp(e) {
let msg = '#尘歌壶模数\n指令#尘歌壶模数\n示例#尘歌壶模数123456\n参数为模数id(10-15位数字)'
await e.reply(msg)
return true
}
async calculatorHelp (e) {
let msg = '#角色养成计算\n指令#刻晴养成\n示例#刻晴养成81 90 9 9 9\n参数为角色、武器、技能等级'
async calculatorHelp(e) {
let msg = `角色养成计算\n指令:${e.isSr ? '*克拉拉养成\n示例*克拉拉养成75 80 6 9 9 9\n参数为角色、武器、普攻、战技、终结技、天赋' : '#刻晴养成\n示例#刻晴养成81 90 9 9 9\n参数为角色、武器、技能等级'}`
await e.reply(msg)
return true
}
async Blueprint(){
let role = this.e.msg.replace(/#/,'').match(/\d+/g);
let data = await new Blueprint(this.e).get(role)
if (!data) return
/** 生成图片 */
let img = await puppeteer.screenshot('Blueprint', data)
if (img) await this.reply(img)
async Blueprint() {
let role = this.e.msg.replace(/#/, '').match(/\d+/g);
let data = await new Blueprint(this.e).get(role)
if (!data) return
/** 生成图片 */
let img = await puppeteer.screenshot('Blueprint', data)
if (img) await this.reply(img)
}
/** #刻晴养成 */
async Calculator () {
let role = gsCfg.getRole(this.e.msg, '#||养成|计算|[0-9]|,|| ')
async Calculator() {
let role = gsCfg.getRole(this.e.msg, '#||星铁|养成|计算|[0-9]|,|| ', this.e.isSr)
if (!role) return false
if ([10000005, 10000007, 20000000].includes(Number(role.roleId))) {
@ -65,7 +66,18 @@ export class calculator extends plugin {
if (!data) return
/** 生成图片 */
let img = await puppeteer.screenshot('Calculator', data)
let url = this.srHead('calculator', data)
let img = await puppeteer.screenshot(url, data)
if (img) await this.reply(img)
}
srHead = (url, data) => {
let name = url
if (this.e.isSr) {
name = `StarRail/${url}`
data.pluResPath = `${this._path}/plugins/genshin/resources/StarRail/`
data.tplFile = `./plugins/genshin/resources/StarRail/html/${url}/${url}.html`
data.headStyle = `<style> .head_box { background: url(${this._path}/plugins/genshin/resources/StarRail/img/worldcard/星穹列车.png) #fff; background-position-x: -10px; background-repeat: no-repeat; background-size: 540px; background-position-y: -100px; </style>`
}
return name
}
}

View File

@ -1,6 +1,5 @@
import plugin from '../../../lib/plugins/plugin.js'
import MysNews from '../model/mysNews.js'
import MysSrNews from '../model/mysSrNews.js'
import fs from 'node:fs'
import lodash from 'lodash'
import gsCfg from '../model/gsCfg.js'
@ -8,7 +7,7 @@ import YAML from 'yaml'
gsCfg.cpCfg('mys', 'pushNews')
export class mysNews extends plugin {
constructor (e) {
constructor(e) {
super({
name: '米游社公告',
dsc: '#公告 #资讯 #活动',
@ -16,26 +15,13 @@ export class mysNews extends plugin {
priority: 700,
rule: [
{
reg: '^(#*官方(公告|资讯|活动)|#*原神(公告|资讯|活动)|#公告|#资讯|#活动)[0-9]*$',
reg: '^#*(官方|星铁|原神|崩坏三|崩三|绝区零|崩坏二|崩二|崩坏学园二|未定|未定事件簿)?(公告|资讯|活动)[0-9]*$',
fnc: 'news'
},
{
reg: '^(#米游社|#mys)(.*)',
fnc: 'mysSearch'
},
{
reg: '^(#*铁道(公告|资讯|活动)|#*星铁(公告|资讯|活动)|#星穹公告|#星穹资讯|#星穹活动)[0-9]*$',
fnc: 'srNews'
},
{
reg: '^#*(开启|关闭)(铁道|星铁|星穹)(公告|资讯)推送$',
fnc: 'srSetPush'
},
{
reg: '^#推送(铁道|星铁|星穹)(公告|资讯)$',
permission: 'master',
fnc: 'srMysNewsTask'
},
{
reg: '(.*)(bbs.mihoyo.com|miyoushe.com)/ys(.*)/article(.*)',
fnc: 'mysUrl'
@ -45,85 +31,66 @@ export class mysNews extends plugin {
fnc: 'ysEstimate'
},
{
reg: '^#*(开启|关闭)(公告|资讯)推送$',
reg: '^#*(星铁|原神|崩坏三|崩三|绝区零|崩坏二|崩二|崩坏学园二|未定|未定事件簿)?(开启|关闭)(公告|资讯)推送$',
fnc: 'setPush'
},
{
reg: '^#推送(公告|资讯)$',
reg: '^#(星铁|原神|崩坏三|崩三|绝区零|崩坏二|崩二|崩坏学园二|未定|未定事件簿)?推送(公告|资讯)$',
permission: 'master',
fnc: 'mysNewsTask'
}
]
})
this.file = './plugins/genshin/config/mys.pushNews.yaml'
/** 定时任务 */
this.task = [
{
cron: gsCfg.getConfig('mys', 'pushNews').pushTime,
name: '米游社公告推送任务',
fnc: () => this.mysNewsTask(),
log: false
},
{
cron: gsCfg.getConfig('mys', 'pushNews').pushTime,
name: '崩坏星穹铁道公告推送任务',
fnc: () => this.srMysNewsTask(),
log: false
}
]
this.task = {
cron: gsCfg.getConfig('mys', 'pushNews').pushTime,
name: '米游社公告推送任务',
fnc: () => this.mysNewsTask(),
log: false
}
}
async init () {
async init() {
if (fs.existsSync(this.file)) return
fs.copyFileSync('./plugins/genshin/defSet/mys/pushNews.yaml', this.file)
}
async news () {
let data = await new MysNews(this.e).getNews()
async news() {
let gids = this.gids()
let data = await new MysNews(this.e).getNews(gids)
if (!data) return
await this.reply(data)
}
async srNews () {
let data = await new MysSrNews(this.e).getNews()
if (!data) return
await this.reply(data)
}
async mysNewsTask () {
async mysNewsTask() {
let mysNews = new MysNews(this.e)
await mysNews.mysNewsTask()
}
async srMysNewsTask () {
let mysNews = new MysSrNews(this.e)
await mysNews.mysNewsTask()
}
async mysSearch () {
async mysSearch() {
if (/签到/g.test(this.e.msg)) return false
let data = await new MysNews(this.e).mysSearch()
if (!data) return
await this.reply(data)
}
async mysUrl () {
async mysUrl() {
let data = await new MysNews(this.e).mysUrl()
if (!data) return
await this.reply(data)
}
async ysEstimate () {
async ysEstimate() {
let data = await new MysNews(this.e).ysEstimate()
if (!data) return
await this.reply(data)
}
async srSetPush () {
async setPush() {
if (!this.e.isGroup) {
await this.reply('推送请在群聊中设置')
return
@ -134,25 +101,31 @@ export class mysNews extends plugin {
}
let cfg = gsCfg.getConfig('mys', 'pushNews')
let gids = this.gids()
let type = 'srannounceGroup'
let game = gids == 1 ? 'bbb' : gids == 2 ? 'gs' : gids == 3 ? 'bb' : gids == 4 ? 'wd' : gids == 6 ? 'sr' : 'zzz'
let type = `${game}announceGroup`
let typeName = '公告'
if (this.e.msg.includes('资讯')) {
type = 'srinfoGroup'
type = `${game}infoGroup`
typeName = '资讯'
}
let model
let msg = `崩坏星穹铁道${typeName}推送已`
let name = await new MysNews(this.e).game(gids)
let msg = `${name}${typeName}推送已`
if (!Array.isArray(cfg[type][this.e.self_id]))
cfg[type][this.e.self_id] = []
if (this.e.msg.includes('开启')) {
model = '开启'
cfg[type].push(this.e.group_id)
cfg[type] = lodash.uniq(cfg[type])
cfg[type][this.e.self_id].push(this.e.group_id)
cfg[type][this.e.self_id] = lodash.uniq(cfg[type][this.e.self_id])
msg += `${model}\n如有最新${typeName}将自动推送至此`
} else {
model = '关闭'
msg += `${model}`
cfg[type] = lodash.difference(cfg[type], [this.e.group_id])
cfg[type][this.e.self_id] = lodash.difference(cfg[type][this.e.self_id], [this.e.group_id])
}
let yaml = YAML.stringify(cfg)
@ -162,42 +135,26 @@ export class mysNews extends plugin {
await this.reply(msg)
}
async setPush () {
if (!this.e.isGroup) {
await this.reply('推送请在群聊中设置')
return
gids() {
let msg = this.e.msg.replace(/[#公告资讯活动开启关闭推送]/g, '');
switch (msg) {
case '崩坏三':
case '崩三':
return 1
case '原神':
return 2
case '崩坏学园二':
case '崩坏二':
case '崩二':
return 3
case '未定事件簿':
case '未定':
return 4
case '星铁':
return 6
case '绝区零':
return 8
}
if (!this.e.member?.is_admin && !this.e.isMaster) {
await this.reply('暂无权限,只有管理员才能操作', true)
return true
}
let cfg = gsCfg.getConfig('mys', 'pushNews')
let type = 'announceGroup'
let typeName = '公告'
if (this.e.msg.includes('资讯')) {
type = 'infoGroup'
typeName = '资讯'
}
let model
let msg = `原神${typeName}推送已`
if (this.e.msg.includes('开启')) {
model = '开启'
cfg[type].push(this.e.group_id)
cfg[type] = lodash.uniq(cfg[type])
msg += `${model}\n如有最新${typeName}将自动推送至此`
} else {
model = '关闭'
msg += `${model}`
cfg[type] = lodash.difference(cfg[type], [this.e.group_id])
}
let yaml = YAML.stringify(cfg)
fs.writeFileSync(this.file, yaml, 'utf8')
logger.mark(`${this.e.logFnc} ${model}${typeName}推送:${this.e.group_id}`)
await this.reply(msg)
return 2
}
}

View File

@ -3,9 +3,9 @@
- 罗莎莉亚
- 烟绯
up5:
- 珊瑚宫心海
up5_2:
- 流浪者
up5_2:
- 珊瑚宫心海
weapon5:
- 不灭月华
- 图莱杜拉的回忆
@ -15,7 +15,7 @@
- 钟剑
- 匣里灭辰
- 西风猎弓
endTime: "2023-08-15 18:00:00"
endTime: "2023-08-11 18:00:00"
- up4:
- 米卡
- 雷泽

View File

@ -1,18 +1,50 @@
# 米游社公共推送定时任务,修改需要重启
pushTime: 0 0/5 * * * ?
# 最多同时推送条数
maxNum: 1
#公共推送群
announceGroup: []
# 包含关键字不推送
banWord:
gs: 冒险助力礼包|纪行|预下载|脚本外挂|集中反馈|已开奖|云·原神|魔神任务|传说任务|线下赛|晋级赛|战绩更新|海选赛|邀请赛|积分赛|战绩工具|交流平台|首日赛|线上赛|社区内容|个人专访|全民赛|决赛|总决赛|半决赛|淘汰赛|作品展示|同人|大别野
sr: 预下载|脚本外挂|集中反馈|已开奖|问题说明|意见反馈|账号封禁|工具|直播预告|获奖名单|大别野
wd: 大别野|已开奖
bb: 已开奖|大别野
bbb: 封禁名单|大别野|马克兔速报|预下载
zzz: 作品展示|已开奖|大别野
#资讯推送群
infoGroup: []
#原神公告推送群
gsannounceGroup: {}
#原神资讯推送群
gsinfoGroup: {}
#崩坏星穹铁道公告推送群
srannounceGroup: []
srannounceGroup: {}
#崩坏星穹铁道资讯推送群
srinfoGroup: []
srinfoGroup: {}
#绝区零公告推送群
zzzannounceGroup: {}
#绝区零资讯推送群
zzzinfoGroup: {}
#未定事件簿公告推送群
wdannounceGroup: {}
#未定事件簿资讯推送群
wdinfoGroup: {}
#崩坏3公告推送群
bbbannounceGroup: {}
#崩坏3资讯推送群
bbbinfoGroup: {}
#崩坏学园2公告推送群
bbannounceGroup: {}
#崩坏学园2资讯推送群
bbinfoGroup: {}

View File

@ -1,13 +1,13 @@
- from: '2023-07-25 18:00:00'
to: '2023-08-15 14:59:59'
five:
- 珊瑚宫心海
- 流浪者
- 珊瑚宫心海
four:
- 珐露珊
- 罗莎莉亚
- 烟绯
name: 浮岳虹珠|余火变相
name: 余火变相|浮岳虹珠
- from: '2023-07-05 06:00:00'
to: '2023-07-25 17:59:59'
five:

View File

@ -0,0 +1,149 @@
1001:
- 三月七
- 三月
- 看板娘
- 三七
- 三祁
- 纠缠之缘
- March7th
- 37
1002:
- 单恒
- 单垣
- 丹垣
- 丹桁
- 冷面小青龙
- DanHeng
- 丹恒
1003:
- 姬子
- 机子
- 寄子
- Himeko
1004:
- 瓦尔特
- 杨叔
- 老杨
- Welt
1005:
- 卡芙卡
1006:
- 银狼
- 音浪
- 银浪
- 隐狼
- 淫狼
- 骇兔
- 鸭子
- 小鸭
- 小鸭鸭
- yinlang
- YinLang
1008:
- 阿兰
- 阿兰
- Alan
- 阿郎
- 阿蓝
- Arlan
1009:
- 艾丝妲
- 爱思达
- 爱丝妲
- 爱思妲
- 爱丝达
- 艾思达
- 艾思妲
- 艾丝达
- 富婆
- Asta
1013:
- 黑塔
- 人偶
- 转圈圈
- Herta
1101:
- 布洛妮娅
- 布诺妮亚
- 布洛妮亚
- 布诺妮娅
- 布洛尼亚
- 鸭鸭
- 大鸭鸭
- Bronya
1102:
- 希儿
- 希尔
- Seele
1103:
- 希露瓦
- 希录瓦
- Serval
1104:
- 杰帕德
- 杰哥
- Gepard
1105:
- 娜塔莎
- 那塔莎
- 那塔沙
- 娜塔沙
- Natasha
- 渡鸦
1106:
- 佩拉
- 配拉
- 佩啦
- 冰砂糖
- Pela
1107:
- 克拉拉
- 可拉拉
- 史瓦罗
- Clara
1108:
- 桑博
- Sampo
1109:
- 虎克
- 胡克
- Hook
1201:
- 青雀
- 青却
- 卿雀
- Qingque
1202:
- 停云
- 停运
- 听云
- Tingyun
1203:
- 罗刹
1204:
- 景元
- JingYuan
1205:
-
1206:
- 素裳
- 李素裳
- Sushang
1207:
- 驭空
1209:
- 彦卿
- 言情
- 彦情
- 彦青
- 言卿
- 燕青
- Yanqing
1211:
- 白露
- 龙女
- 小龙女
- 白鹭
- 白鹿
- 白麓
- Bailu

View File

@ -18,7 +18,7 @@ export default class base {
* @param pluResPath 插件资源路径
*/
get screenData() {
let headImg = '优菈'
let headImg = '珊瑚宫心海'
return {
saveId: this.userId,

View File

@ -5,13 +5,13 @@ import lodash from 'lodash'
import gsCfg from './gsCfg.js'
export default class Calculator extends base {
constructor (e) {
constructor(e) {
super(e)
this.model = 'calculator'
this.checkMsg = '设置角色、武器、技能等级有误\n指令#刻晴养成\n示例#刻晴养成81 90 9 9 9\n参数为角色、武器、技能等级'
this.checkMsg = `设置角色、武器、技能等级有误\n指令:${e.isSr ? '*克拉拉养成\n示例*克拉拉养成75 80 6 9 9 9\n参数为角色、武器、普攻、战技、终结技、天赋' : '#刻晴养成\n示例#刻晴养成81 90 9 9 9\n参数为角色、武器、技能等级'}`
}
async get (role) {
async get(role) {
this.role = role
/** 获取绑定uid */
let uid = await MysInfo.getUid(this.e)
@ -26,8 +26,18 @@ export default class Calculator extends base {
this.mysApi = new MysApi(uid, ck.ck, { log: true })
let seed_id = lodash.sample('abcdefghijklmnopqrstuvwxyz0123456789', 16).replace(/,/g, '')
let device_fp = await MysInfo.get(this.e, 'getFp', {
seed_id
})
this.headers = {
'x-rpc-device_fp': device_fp?.data?.device_fp
}
/** 获取角色数据 */
let character = await this.mysApi.getData('character')
let character = await MysInfo.get(this.e, this.e.isSr ? 'avatarInfo' : 'character', {
headers: this.headers,
})
if (!character || character.retcode !== 0) return false
character = character.data
@ -35,7 +45,7 @@ export default class Calculator extends base {
await this.getSet()
/** 获取计算角色 */
this.dataCharacter = character.avatars.find((item) => item.id == role.roleId)
this.dataCharacter = character[this.e.isSr ? 'avatar_list' : 'avatars'].find((item) => item.id == role.roleId)
/** 获取计算参数 */
let body = await this.getBody()
@ -56,34 +66,35 @@ export default class Calculator extends base {
}
}
async getSet () {
let defSetSkill = '90,90,10,10,10'.split(',')
async getSet() {
let defSetSkill = this.e.isSr ? '80,80,6,10,10,10'.split(',') : '90,90,10,10,10'.split(',')
let set = this.e.msg.replace(/#||养成|计算/g, '').trim()
let set = this.e.msg.replace(/#||星铁|养成|计算/g, '').trim()
set = set.replace(/| /g, ',')
set = set.replace(this.role.alias, '')
let setSkill = []
let length = this.e.isSr ? 6 : 5
if (set) {
setSkill = set.split(',')
setSkill = lodash.compact(setSkill)
for (let i = 0; i <= 4; i++) {
for (let i = 0; i < length; i++) {
if (!setSkill[i]) setSkill[i] = defSetSkill[i]
}
} else {
setSkill = defSetSkill
}
if (setSkill.length != 5) {
let reMsg = this.checkMsg.replace(/刻晴/g, this.role.alias)
if (setSkill.length != length) {
let reMsg = this.checkMsg.replace(/刻晴|克拉拉/g, this.role.alias)
await this.e.reply(reMsg)
return false
}
/** 检查参数 */
let check = [90, 90, 10, 10, 10]
let check = this.e.isSr ? [80, 80, 6, 10, 10, 10] : [90, 90, 10, 10, 10]
for (const key in check) {
if (check[key] < Number(setSkill[key])) {
setSkill[key] = check[key]
@ -93,21 +104,37 @@ export default class Calculator extends base {
this.setSkill = setSkill
}
async getBody () {
async getBody() {
// 技能
let skillList = []
if (this.dataCharacter) {
/** 角色存在获取技能数据 */
let detail = await this.mysApi.getData('detail', { avatar_id: this.role.roleId })
let data = this.e.isSr ? { avatar_id: this.role.roleId, tab_from: 'TabOwned' } : { avatar_id: this.role.roleId }
let detail = await MysInfo.get(this.e, 'detail', {
headers: this.headers,
...data
})
if (!detail || detail.retcode !== 0) return false
skillList = detail.data.skill_list
skillList = detail.data.skill_list || detail.data.skills
} else {
/** 尚未拥有的角色 */
skillList = await this.getSkillId(this.role.roleId)
if (this.e.isSr) {
let detail = await MysInfo.get(this.e, 'detail', {
headers: this.headers,
avatar_id: this.role.roleId,
tab_from: 'TabAll'
})
if (!detail || detail.retcode !== 0) return false
this.avatar = detail.data.avatar
skillList = detail.data.skills
} else {
skillList = await this.getSkillId(this.role.roleId)
}
if (!skillList) {
this.e.reply('暂无角色数据,请稍后再试')
this.e.reply('暂无角色数据,请稍后再试\n星铁角色养成请使用*开头')
return false
}
@ -116,57 +143,96 @@ export default class Calculator extends base {
this.dataCharacter = {
level: 1,
name: this.role.name,
icon: `${this.screenData.pluResPath}img/role/${this.role.name}.png`,
rarity: four.includes(Number(this.role.roleId)) ? 4 : 5
icon: this.e.isSr ? this.avatar.icon_url : `${this.screenData.pluResPath}img/role/${this.role.name}.png`,
rarity: this.e.isSr ? this.avatar.rarity : four.includes(Number(this.role.roleId)) ? 4 : 5
}
}
skillList = skillList.filter((item) => item.max_level != 1)
/** 拼接计算参数 */
let body = {
avatar_id: Number(this.role.roleId),
avatar_level_current: Number(this.dataCharacter.level),
avatar_level_target: Number(this.setSkill[0]),
skill_list: [
{
id: Number(skillList[0].group_id),
level_current: Number(skillList[0].level_current),
level_target: Number(this.setSkill[2])
let body
if (this.e.isSr) {
body = {
game: 'hkrpg',
avatar: {
item_id: Number(this.role.roleId),
cur_level: Number(this.dataCharacter.level),
target_level: Number(this.setSkill[0]),
},
{
id: Number(skillList[1].group_id),
level_current: Number(skillList[1].level_current),
level_target: Number(this.setSkill[3])
},
{
id: Number(skillList[2].group_id),
level_current: Number(skillList[2].level_current),
level_target: Number(this.setSkill[4])
skill_list: []
}
for (let data of skillList) {
let skill = {
item_id: data.point_id,
cur_level: data.cur_level,
target_level: data.target_level
}
]
if (Number(this.setSkill[0]) >= data.min_level_limit) body.skill_list.push(skill)
}
} else {
skillList = skillList.filter((item) => item.max_level != 1)
body = {
avatar_id: Number(this.role.roleId),
avatar_level_current: Number(this.dataCharacter.level),
avatar_level_target: Number(this.setSkill[0]),
skill_list: [
{
id: Number(skillList[0].group_id),
level_current: Number(skillList[0].level_current),
level_target: Number(this.setSkill[2])
},
{
id: Number(skillList[1].group_id),
level_current: Number(skillList[1].level_current),
level_target: Number(this.setSkill[3])
},
{
id: Number(skillList[2].group_id),
level_current: Number(skillList[2].level_current),
level_target: Number(this.setSkill[4])
}
]
}
}
if (this.mysApi.getServer().startsWith('os')) {
body.lang = "zh-cn"
}
if (this.dataCharacter.weapon) {
if (Number(this.dataCharacter.weapon.rarity) < 3) {
this.setSkill[1] = 70
if (this.e.isSr) {
if (this.dataCharacter.equip) {
body.equipment = {
item_id: Number(this.dataCharacter.equip.id),
cur_level: Number(this.dataCharacter.equip.level),
target_level: Number(this.setSkill[1])
}
}
body.weapon = {
id: Number(this.dataCharacter.weapon.id),
level_current: Number(this.dataCharacter.weapon.level),
level_target: Number(this.setSkill[1])
} else {
if (this.dataCharacter.weapon) {
if (Number(this.dataCharacter.weapon.rarity) < 3) {
this.setSkill[1] = 70
}
body.weapon = {
id: Number(this.dataCharacter.weapon.id),
level_current: Number(this.dataCharacter.weapon.level),
level_target: Number(this.setSkill[1])
}
}
}
skillList = skillList.filter((item) => item.max_level != 1)
this.skillList = skillList
return body
}
async getSkillId (roleId) {
let avatarSkill = await this.mysApi.getData('avatarSkill', { avatar_id: roleId })
async getSkillId(roleId) {
let avatarSkill = await MysInfo.get(this.e, 'avatarSkill', {
headers: this.headers,
avatar_id: roleId
})
if (!avatarSkill || avatarSkill.retcode !== 0) return false
avatarSkill = avatarSkill.data
avatarSkill.list.forEach((item) => {
@ -176,20 +242,20 @@ export default class Calculator extends base {
return avatarSkill.list
}
async computes (body) {
let computes = await this.mysApi.getData('compute', body)
async computes(body) {
let computes = await MysInfo.get(this.e, 'compute', body)
if (!computes || computes.retcode !== 0) return false
computes = computes.data
let formart = (num) => {
return num > 10000 ? (num / 10000).toFixed(1) + ' w' : num
}
if (this.e.isSr) delete computes.coin_id
for (let i in computes) {
for (let j in computes[i]) {
computes[i][j].num = formart(computes[i][j].num)
if (computes[i][j].name.includes('「')) {
if (computes[i][j][this.e.isSr ? 'item_name' : 'name'].includes('「')) {
computes[i][j].isTalent = true
}
}

View File

@ -64,11 +64,6 @@ export default class GachaLog extends base {
MakeMsg.push(tmpMsg)
MakeMsg.push(`抽卡记录更新完成,您还可回复\n【#${this?.e?.isSr?'星铁光锥':'武器'}记录】统计${this?.e?.isSr?'星铁光锥':'武器'}池数据\n【#${this?.e?.isSr?'星铁':''}角色统计】按卡池统计数据\n【#导出记录】导出记录数据`)
let Msg = await common.makeForwardMsg(this.e, MakeMsg, tmpMsg)
Msg.data=Msg.data
.replace(/\n/g, '')
.replace(/<title color="#777777" size="26">(.+?)<\/title>/g, '___')
.replace(/___+/, `<title color="#777777" size="26">${tmpMsg}</title>`)
await this.e.reply(Msg)
this.isLogUrl = true

View File

@ -9,7 +9,8 @@ import MysUser from './mys/MysUser.js'
/** 配置文件 */
class GsCfg {
constructor () {
constructor() {
this.isSr = false
/** 默认设置 */
this.defSetPath = './plugins/genshin/defSet/'
this.defSet = {}
@ -24,7 +25,7 @@ class GsCfg {
this.ignore = ['mys.pubCk', 'gacha.set', 'bot.help', 'role.name']
}
get element () {
get element() {
return { ...this.getdefSet('element', 'role'), ...this.getdefSet('element', 'weapon') }
}
@ -32,12 +33,12 @@ class GsCfg {
* @param app 功能
* @param name 配置文件名称
*/
getdefSet (app, name) {
getdefSet(app, name) {
return this.getYaml(app, name, 'defSet')
}
/** 用户配置 */
getConfig (app, name) {
getConfig(app, name) {
if (this.ignore.includes(`${app}.${name}`)) {
return this.getYaml(app, name, 'config')
}
@ -51,7 +52,7 @@ class GsCfg {
* @param name 名称
* @param type 默认跑配置-defSet用户配置-config
*/
getYaml (app, name, type) {
getYaml(app, name, type) {
let file = this.getFilePath(app, name, type)
let key = `${app}.${name}`
@ -71,13 +72,13 @@ class GsCfg {
return this[type][key]
}
getFilePath (app, name, type) {
getFilePath(app, name, type) {
if (type == 'defSet') return `${this.defSetPath}${app}/${name}.yaml`
else return `${this.configPath}${app}.${name}.yaml`
}
/** 监听配置文件 */
watch (file, app, name, type = 'defSet') {
watch(file, app, name, type = 'defSet') {
let key = `${app}.${name}`
if (this.watcher[type][key]) return
@ -95,7 +96,7 @@ class GsCfg {
}
/** 读取所有用户绑定的ck */
async getBingCk (game = 'gs') {
async getBingCk(game = 'gs') {
let ck = {}
let ckQQ = {}
let noteCk = {}
@ -121,20 +122,20 @@ class GsCfg {
}
/** 获取qq号绑定ck */
getBingCkSingle (userId) {
getBingCkSingle(userId) {
console.log('gsCfg.getBingCkSingle() 即将废弃')
return {}
}
saveBingCk (userId, data) {
saveBingCk(userId, data) {
console.log('gsCfg.saveBingCk() 即将废弃')
}
/**
* 原神角色id转换角色名字
*/
roleIdToName (id) {
let name = this.getdefSet('role', 'name')
roleIdToName(id) {
let name = this.getdefSet('role', this.isSr ? 'sr_name' : 'name')
if (name[id]) {
return name[id][0]
}
@ -145,7 +146,7 @@ class GsCfg {
/**
* 原神武器id转换成武器名字
*/
getWeaponDataByWeaponHash (hash) {
getWeaponDataByWeaponHash(hash) {
let data = this.getdefSet('weapon', 'data')
let weaponData = {}
weaponData.name = data.Name[hash]
@ -155,20 +156,22 @@ class GsCfg {
}
/** 原神角色别名转id */
roleNameToID (keyword) {
roleNameToID(keyword, isSr) {
if (isSr) this.isSr = isSr
if (!isNaN(keyword)) keyword = Number(keyword)
this.getAbbr()
let roelId = this.nameID.get(String(keyword))
let roelId = this[this.isSr ? 'sr_nameID' : 'nameID'].get(String(keyword))
return roelId || false
}
/** 获取角色别名 */
getAbbr () {
if (this.nameID) return
getAbbr() {
if (this[this.isSr ? 'sr_nameID' : 'nameID']) return
this.nameID = new Map()
this.sr_nameID = new Map()
let nameArr = this.getdefSet('role', 'name')
let sr_nameArr = this.getdefSet('role', 'sr_name')
let nameArrUser = this.getConfig('role', 'name')
let nameID = {}
@ -180,6 +183,13 @@ class GsCfg {
}
}
for (let i in sr_nameArr) {
nameID[sr_nameArr[i][0]] = i
for (let abbr of sr_nameArr[i]) {
this.sr_nameID.set(String(abbr), i)
}
}
for (let i in nameArrUser) {
for (let abbr of nameArrUser[i]) {
this.nameID.set(String(abbr), nameID[i])
@ -188,8 +198,8 @@ class GsCfg {
}
/** 返回所有别名,包括用户自定义的 */
getAllAbbr () {
let nameArr = this.getdefSet('role', 'name')
getAllAbbr() {
let nameArr = this.getdefSet('role', this.isSr ? 'sr_name' : 'name')
let nameArrUser = this.getConfig('role', 'name')
for (let i in nameArrUser) {
@ -205,7 +215,7 @@ class GsCfg {
* @param name 名称
* @param isWeapon 是否武器
*/
shortName (name, isWeapon = false) {
shortName(name, isWeapon = false) {
let other = {}
if (isWeapon) {
other = this.getdefSet('weapon', 'other')
@ -216,12 +226,12 @@ class GsCfg {
}
/** 公共配置ck文件修改hook */
async change_myspubCk () {
async change_myspubCk() {
await MysInfo.initCache()
await MysInfo.initPubCk()
}
getGachaSet (groupId = '') {
getGachaSet(groupId = '') {
let config = this.getYaml('gacha', 'set', 'config')
let def = config.default
if (config[groupId]) {
@ -230,7 +240,7 @@ class GsCfg {
return def
}
getMsgUid (msg) {
getMsgUid(msg) {
let ret = /[1|2|5-9][0-9]{8}/g.exec(msg)
if (!ret) return false
return ret[0]
@ -245,12 +255,13 @@ class GsCfg {
* @return alias 当前别名
* @return uid 游戏uid
*/
getRole (msg, filterMsg = '') {
getRole(msg, filterMsg = '', isSr = false) {
let alias = msg.replace(/#|老婆|老公|[1|2|5-9][0-9]{8}/g, '').trim()
if (filterMsg) {
alias = alias.replace(new RegExp(filterMsg, 'g'), '').trim()
}
this.isSr = isSr
/** 判断是否命中别名 */
let roleId = this.roleNameToID(alias)
if (!roleId) return false
@ -265,7 +276,7 @@ class GsCfg {
}
}
cpCfg (app, name) {
cpCfg(app, name) {
if (!fs.existsSync('./plugins/genshin/config')) {
fs.mkdirSync('./plugins/genshin/config')
}
@ -279,7 +290,7 @@ class GsCfg {
/**
* 根据角色名获取对应的元素类型
*/
getElementByRoleName (roleName) {
getElementByRoleName(roleName) {
let element = this.getdefSet('element', 'role')
if (element[roleName]) {
return element[roleName]
@ -289,7 +300,7 @@ class GsCfg {
/**
* 根据技能id获取对应的技能数据,角色名用于命座加成的技能等级
*/
getSkillDataByskillId (skillId, roleName) {
getSkillDataByskillId(skillId, roleName) {
let skillMap = this.getdefSet('skill', 'data')
let skillData = {}
if (skillMap.Name[skillId]) {
@ -304,7 +315,7 @@ class GsCfg {
return skillData
}
fightPropIdToName (propId) {
fightPropIdToName(propId) {
let propMap = this.getdefSet('prop', 'prop')
if (propMap[propId]) {
return propMap[propId]
@ -312,7 +323,7 @@ class GsCfg {
return ''
}
getRoleTalentByTalentId (talentId) {
getRoleTalentByTalentId(talentId) {
let talentMap = this.getdefSet('role', 'talent')
let talent = {}
if (talentMap.Name[talentId]) {

View File

@ -173,6 +173,17 @@ export default class apiTool {
dailyNote: {
url: `${hostRecord}game_record/app/hkrpg/api/note`,
query: `role_id=${this.uid}&server=${this.server}`
},
/** 养成计算器 */
compute: {
url: `${host}event/rpgcalc/compute?`,
query:`game=hkrpg`,
body: data
},
/** 详情 */
detail: {
url: `${host}event/rpgcalc/avatar/detail`,
query: `game=hkrpg&lang=zh-cn&item_id=${data.avatar_id}&tab_from=${data.tab_from}&change_target_level=0&uid=${this.uid}&region=${this.server}`
}
}
}

View File

@ -25,7 +25,7 @@ export default class MysInfo {
}
// ck对应MysUser对象
this.ckUser = null
this.auth = ['dailyNote', 'bbs_sign_info', 'bbs_sign_home', 'bbs_sign', 'ys_ledger', 'compute', 'avatarSkill', 'detail', 'blueprint', 'UserGame', 'getFp', 'deckList', 'avatar_cardList', 'action_cardList']
this.auth = ['dailyNote', 'bbs_sign_info', 'bbs_sign_home', 'bbs_sign', 'ys_ledger', 'compute', 'avatarSkill', 'detail', 'blueprint', 'UserGame', 'deckList', 'avatar_cardList', 'action_cardList', 'avatarInfo']
}
static async init(e, api) {
@ -177,7 +177,7 @@ export default class MysInfo {
}
for (let i in res) {
res[i] = await mysInfo.checkCode(res[i], res[i].api)
res[i] = await mysInfo.checkCode(res[i], res[i].api, mysApi)
if (res[i]?.retcode === 0) continue
@ -185,7 +185,7 @@ export default class MysInfo {
}
} else {
res = await mysApi.getData(api, data)
res = await mysInfo.checkCode(res, api)
res = await mysInfo.checkCode(res, api, mysApi)
}
return res
@ -335,7 +335,7 @@ export default class MysInfo {
return this.ckUser?.ck
}
async checkCode(res, type) {
async checkCode(res, type, mysApi = {}) {
if (!res) {
this.e.reply('米游社接口请求失败,暂时无法查询')
return false

View File

@ -5,16 +5,15 @@ import puppeteer from '../../../lib/puppeteer/puppeteer.js'
import common from '../../../lib/common/common.js'
import gsCfg from '../model/gsCfg.js'
const _path = process.cwd()
let emoticon
export default class MysNews extends base {
constructor (e) {
constructor(e) {
super(e)
this.model = 'mysNews'
}
async getNews () {
async getNews(gid) {
let type = 1
let typeName = '公告'
if (this.e.msg.includes('资讯')) {
@ -26,7 +25,7 @@ export default class MysNews extends base {
typeName = '活动'
}
const res = await this.postData('getNewsList', { gids: 2, page_size: 20, type })
const res = await this.postData('getNewsList', { gids: gid, page_size: 20, type })
if (!res) return
const data = res.data.list
@ -34,7 +33,7 @@ export default class MysNews extends base {
return true
}
const page = this.e.msg.replace(/#||官方|原神|公告|资讯|活动/g, '').trim() || 1
const page = this.e.msg.replace(/#||官方|星铁|原神|崩坏三|崩三|绝区零|崩坏二|崩二|崩坏学园二|未定|未定事件簿|公告|资讯|活动/g, '').trim() || 1
if (page > data.length) {
await this.e.reply('目前只查前20条最新的公告请输入1-20之间的整数。')
return true
@ -42,22 +41,22 @@ export default class MysNews extends base {
const postId = data[page - 1].post.post_id
const param = await this.newsDetail(postId)
const param = await this.newsDetail(postId, gid)
const img = await this.render(param)
return await this.replyMsg(img, `原神${typeName}${param.data.post.subject}`)
let game = this.game()
return this.replyMsg(img, `${game}${typeName}${param.data.post.subject}`)
}
async render (param) {
return await puppeteer.screenshots(this.model, param)
render(param) {
return puppeteer.screenshots(this.model, param)
}
async newsDetail (postId) {
const res = await this.postData('getPostFull', { gids: 2, read: 1, post_id: postId })
async newsDetail(postId, gid) {
const res = await this.postData('getPostFull', { gids: gid, read: 1, post_id: postId })
if (!res) return
const data = await this.detalData(res.data.post)
const data = await this.detalData(res.data.post, gid)
return {
...this.screenData,
@ -67,15 +66,15 @@ export default class MysNews extends base {
}
}
postApi (type, data) {
let host = 'https://bbs-api-static.mihoyo.com/'
postApi(type, data) {
let host = 'https://bbs-api.miyoushe.com/'
let param = []
lodash.forEach(data, (v, i) => param.push(`${i}=${v}`))
param = param.join('&')
switch (type) {
// 搜索
case 'searchPosts':
host = 'https://bbs-api.mihoyo.com/post/wapi/searchPosts?'
host = 'https://bbs-api.miyoushe.com/post/wapi/searchPosts?'
break
// 帖子详情
case 'getPostFull':
@ -92,10 +91,10 @@ export default class MysNews extends base {
return host + param
}
async postData (type, data) {
async postData(type, data) {
const url = this.postApi(type, data)
const headers = {
Referer: 'https://bbs.mihoyo.com/',
Referer: 'https://www.miyoushe.com',
'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/104.0.0.0 Safari/537.36'
}
let response
@ -114,7 +113,7 @@ export default class MysNews extends base {
return res
}
async detalData (data) {
async detalData(data, gid) {
let json
try {
json = JSON.parse(data.post.content)
@ -134,7 +133,7 @@ export default class MysNews extends base {
}
if (!emoticon) {
emoticon = await this.mysEmoticon()
emoticon = await this.mysEmoticon(gid)
}
data.post.content = data.post.content.replace(/_\([^)]*\)/g, function (t, e) {
@ -161,10 +160,10 @@ export default class MysNews extends base {
return data
}
async mysEmoticon () {
async mysEmoticon(gid) {
const emp = new Map()
const res = await this.postData('emoticon', { gids: 2 })
const res = await this.postData('emoticon', { gids: gid })
if (res.retcode != 0) {
return emp
@ -181,7 +180,7 @@ export default class MysNews extends base {
return emp
}
async mysSearch () {
async mysSearch() {
let msg = this.e.msg
msg = msg.replace(/#|米游社|mys/g, '')
@ -211,10 +210,10 @@ export default class MysNews extends base {
const img = await this.render(param)
return await this.replyMsg(img, `${param.data.post.subject}`)
return this.replyMsg(img, `${param.data.post.subject}`)
}
async mysUrl () {
async mysUrl() {
let msg = this.e.msg
let postId = /[0-9]+/g.exec(msg)[0]
@ -224,10 +223,10 @@ export default class MysNews extends base {
const img = await this.render(param)
return await this.replyMsg(img, `${param.data.post.subject}`)
return this.replyMsg(img, `${param.data.post.subject}`)
}
async ysEstimate () {
async ysEstimate() {
let msg = '版本原石盘点'
let res = await this.postData('searchPosts', { gids: 2, size: 20, keyword: msg })
if (res?.data?.posts.length <= 0) {
@ -255,86 +254,85 @@ export default class MysNews extends base {
img.push(segment.image(param.data.post.images[0] + '?x-oss-process=image//resize,s_600/quality,q_80/auto-orient,0/interlace,1/format,jpg'))
}
return await this.replyMsg(img, `${param.data.post.subject}`)
return this.replyMsg(img, `${param.data.post.subject}`)
}
async replyMsg (img, titile) {
replyMsg(img, title = '') {
if (!img || img.length <= 0) return false
if (img.length == 1) {
return img[0]
if (title) img.unshift(title)
return img
} else {
let msg = [titile, ...img]
return await common.makeForwardMsg(this.e, msg, titile).catch((err) => {
logger.error(err)
})
return common.makeForwardMsg(this.e, img, title)
}
}
async mysNewsTask (type = 1) {
async mysNewsTask() {
let cfg = gsCfg.getConfig('mys', 'pushNews')
// 推送2小时内的公告资讯
let interval = 7200
// 最多同时推送两条
this.maxNum = cfg.maxNum
// 包含关键字不推送
let banWord = /冒险助力礼包|纪行|预下载|脚本外挂|集中反馈|已开奖|云·原神|魔神任务|传说任务说明/g
let anno = await this.postData('getNewsList', { gids: 2, page_size: 10, type: 1 })
let info = await this.postData('getNewsList', { gids: 2, page_size: 10, type: 3 })
for (let gid of [1, 2, 3, 4, 6, 8]) {
let type = gid == 1 ? 'bbb' : gid == 2 ? 'gs' : gid == 3 ? 'bb' : gid == 4 ? 'wd' : gid == 6 ? 'sr' : 'zzz'
let news = []
if (anno) anno.data.list.forEach(v => { news.push({ ...v, typeName: '公告', post_id: v.post.post_id }) })
if (info) info.data.list.forEach(v => { news.push({ ...v, typeName: '资讯', post_id: v.post.post_id }) })
if (news.length <= 0) return
news = lodash.orderBy(news, ['post_id'], ['asc'])
let now = Date.now() / 1000
this.key = 'Yz:genshin:mys:newPush:'
this.e.isGroup = true
this.pushGroup = []
for (let val of news) {
if (Number(now - val.post.created_at) > interval) {
continue
let news = []
if (!lodash.isEmpty(cfg[`${type}announceGroup`])) {
let anno = await this.postData('getNewsList', { gids: gid, page_size: 10, type: 1 })
if (anno) anno.data.list.forEach(v => { news.push({ ...v, typeName: '公告', post_id: v.post.post_id }) })
}
if (new RegExp(banWord).test(val.post.subject)) {
continue
if (!lodash.isEmpty(cfg[`${type}infoGroup`])) {
let info = await this.postData('getNewsList', { gids: gid, page_size: 10, type: 3 })
if (info) info.data.list.forEach(v => { news.push({ ...v, typeName: '资讯', post_id: v.post.post_id }) })
}
if (val.typeName == '公告') {
for (let groupId of cfg.announceGroup) {
await this.sendNews(groupId, val.typeName, val.post.post_id)
}
}
if (val.typeName == '资讯') {
for (let groupId of cfg.infoGroup) {
await this.sendNews(groupId, val.typeName, val.post.post_id)
}
if (news.length <= 0) continue
news = lodash.orderBy(news, ['post_id'], ['asc'])
let now = Date.now() / 1000
this.key = `Yz:${type}:mys:newPush:`
this.e.isGroup = true
this.pushGroup = []
for (let val of news) {
if (Number(now - val.post.created_at) > interval)
continue
if (cfg.banWord[type] && new RegExp(cfg.banWord[type]).test(val.post.subject))
continue
if (val.typeName == '公告')
for (let botId in cfg[`${type}announceGroup`])
for (let groupId of cfg[`${type}announceGroup`][botId])
await this.sendNews(botId, groupId, val.typeName, val.post.post_id, gid)
if (val.typeName == '资讯')
for (let botId in cfg[`${type}infoGroup`])
for (let groupId of cfg[`${type}infoGroup`][botId])
await this.sendNews(botId, groupId, val.typeName, val.post.post_id, gid)
}
}
}
async sendNews (groupId, typeName, postId) {
async sendNews(botId, groupId, typeName, postId, gid) {
if (!this.pushGroup[groupId]) this.pushGroup[groupId] = 0
if (this.pushGroup[groupId] >= this.maxNum) return
let sended = await redis.get(`${this.key}${groupId}:${postId}`)
let sended = await redis.get(`${this.key}${botId}:${groupId}:${postId}`)
if (sended) return
// TODO: 暂时处理,后续待更好的解决方案 定时任务无法获取e.bot
this.e.bot = Bot
let game = this.game(gid)
// 判断是否存在群关系
if (!this.e.bot.gl.get(Number(groupId))) {
logger.mark(`[米游社${typeName}推送] 群${groupId}未关联`)
this.e.group = Bot[botId]?.pickGroup(groupId)
if (!this.e.group) {
logger.mark(`[米游社${game}${typeName}推送] 群${botId}:${groupId}未关联`)
return
}
if (!this[postId]) {
const param = await this.newsDetail(postId)
const param = await this.newsDetail(postId, gid)
logger.mark(`[米游社${typeName}推送] ${param.data.post.subject}`)
logger.mark(`[米游社${game}${typeName}推送] ${param.data.post.subject}`)
this[postId] = {
img: await this.render(param),
@ -343,20 +341,28 @@ export default class MysNews extends base {
}
this.pushGroup[groupId]++
this.e.group = this.e.bot.pickGroup(Number(groupId))
this.e.group_id = Number(groupId)
let tmp = await this.replyMsg(this[postId].img, `原神${typeName}推送:${this[postId].title}`)
await common.sleep(1000)
if (!tmp) return
if (tmp?.type != 'xml') {
tmp = [`原神${typeName}推送\n`, tmp]
}
await redis.set(`${this.key}${groupId}:${postId}`, '1', { EX: 3600 * 10 })
await redis.set(`${this.key}${botId}:${groupId}:${postId}`, '1', { EX: 3600 * 10 })
// 随机延迟10-90秒
await common.sleep(lodash.random(10, 90) * 1000)
await this.e.group.sendMsg(tmp)
await common.sleep(lodash.random(10000, 90000))
const msg = await this.replyMsg(this[postId].img, `${game}${typeName}推送:${this[postId].title}`)
return this.e.group.sendMsg(msg)
}
}
game(gid) {
switch (gid) {
case 1:
return '崩坏三'
case 2:
return '原神'
case 3:
return '崩坏二'
case 4:
return '未定事件簿'
case 6:
return '崩坏星穹铁道'
case 8:
return '绝区零'
}
return ''
}
}

View File

@ -1,284 +0,0 @@
import base from './base.js'
import fetch from 'node-fetch'
import lodash from 'lodash'
import puppeteer from '../../../lib/puppeteer/puppeteer.js'
import common from '../../../lib/common/common.js'
import gsCfg from '../model/gsCfg.js'
let emoticon
export default class MysSrNews extends base {
constructor (e) {
super(e)
this.model = 'mysNews'
}
async getNews () {
let type = 1
let typeName = '公告'
if (this.e.msg.includes('资讯')) {
type = '3'
typeName = '资讯'
}
if (this.e.msg.includes('活动')) {
type = '2'
typeName = '活动'
}
const res = await this.postData('getNewsList', { gids: 6, page_size: 20, type })
if (!res) return
const data = res.data.list
if (data.length == 0) {
return true
}
const page = this.e.msg.replace(/#||星铁|星穹|铁道|公告|资讯|活动/g, '').trim() || 1
if (page > data.length) {
await this.e.reply('目前只查前20条最新的公告请输入1-20之间的整数。')
return true
}
const postId = data[page - 1].post.post_id
const param = await this.newsDetail(postId)
const img = await this.render(param)
return await this.replyMsg(img, `崩坏星穹铁道${typeName}${param.data.post.subject}`)
}
async render (param) {
return await puppeteer.screenshots(this.model, param)
}
async newsDetail (postId) {
const res = await this.postData('getPostFull', { gids: 6, read: 1, post_id: postId })
if (!res) return
const data = await this.detalData(res.data.post)
return {
...this.screenData,
saveId: postId,
dataConent: data.post.content,
data
}
}
postApi (type, data) {
let host = 'https://bbs-api-static.mihoyo.com/'
let param = []
lodash.forEach(data, (v, i) => param.push(`${i}=${v}`))
param = param.join('&')
switch (type) {
// 搜索
case 'searchPosts':
host = 'https://bbs-api.mihoyo.com/post/wapi/searchPosts?'
break
// 帖子详情
case 'getPostFull':
host += 'post/wapi/getPostFull?'
break
// 公告列表
case 'getNewsList':
host += 'post/wapi/getNewsList?'
break
case 'emoticon':
host += 'misc/api/emoticon_set?'
break
}
return host + param
}
async postData (type, data) {
const url = this.postApi(type, data)
const headers = {
Referer: 'https://bbs.mihoyo.com/',
'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/104.0.0.0 Safari/537.36'
}
let response
try {
response = await fetch(url, { method: 'get', headers })
} catch (error) {
logger.error(error.toString())
return false
}
if (!response.ok) {
logger.error(`[米游社接口错误][${type}] ${response.status} ${response.statusText}`)
return false
}
const res = await response.json()
return res
}
async detalData (data) {
let json
try {
json = JSON.parse(data.post.content)
} catch (error) {
}
if (typeof json == 'object') {
if (json.imgs && json.imgs.length > 0) {
for (const val of json.imgs) {
data.post.content = ` <div class="ql-image-box"><img src="${val}?x-oss-process=image//resize,s_600/quality,q_80/auto-orient,0/interlace,1/format,png"></div>`
}
}
} else {
for (const img of data.post.images) {
data.post.content = data.post.content.replace(img, img + '?x-oss-process=image//resize,s_600/quality,q_80/auto-orient,0/interlace,1/format,jpg')
}
if (!emoticon) {
emoticon = await this.mysEmoticon()
}
data.post.content = data.post.content.replace(/_\([^)]*\)/g, function (t, e) {
t = t.replace(/_\(|\)/g, '')
if (emoticon.has(t)) {
return `<img class="emoticon-image" src="${emoticon.get(t)}"/>`
} else {
return ''
}
})
const arrEntities = { lt: '<', gt: '>', nbsp: ' ', amp: '&', quot: '"' }
data.post.content = data.post.content.replace(/&(lt|gt|nbsp|amp|quot);/ig, function (all, t) {
return arrEntities[t]
})
}
data.post.created_time = new Date(data.post.created_at * 1000).toLocaleString()
for (const i in data.stat) {
data.stat[i] = data.stat[i] > 10000 ? (data.stat[i] / 10000).toFixed(2) + '万' : data.stat[i]
}
return data
}
async mysEmoticon () {
const emp = new Map()
const res = await this.postData('emoticon', { gids: 6 })
if (res.retcode != 0) {
return emp
}
for (const val of res.data.list) {
if (!val.icon) continue
for (const list of val.list) {
if (!list.icon) continue
emp.set(list.name, list.icon)
}
}
return emp
}
async replyMsg (img, titile) {
if (!img || img.length <= 0) return false
if (img.length == 1) {
return img[0]
} else {
let msg = [titile, ...img]
return await common.makeForwardMsg(this.e, msg, titile).catch((err) => {
logger.error(err)
})
}
}
async mysNewsTask (type = 1) {
let cfg = gsCfg.getConfig('mys', 'pushNews')
// 推送2小时内的公告资讯
let interval = 7200
// 最多同时推送两条
this.maxNum = cfg.maxNum
// 包含关键字不推送
let banWord = /冒险助力礼包|纪行|预下载|脚本外挂|集中反馈|已开奖|云·原神|魔神任务|传说任务说明/g
let anno = await this.postData('getNewsList', { gids: 6, page_size: 10, type: 1 })
let info = await this.postData('getNewsList', { gids: 6, page_size: 10, type: 3 })
let news = []
if (anno) anno.data.list.forEach(v => { news.push({ ...v, typeName: '公告', post_id: v.post.post_id }) })
if (info) info.data.list.forEach(v => { news.push({ ...v, typeName: '资讯', post_id: v.post.post_id }) })
if (news.length <= 0) return
news = lodash.orderBy(news, ['post_id'], ['asc'])
let now = Date.now() / 1000
this.key = 'Yz:genshin:mys:newPush:'
this.e.isGroup = true
this.pushGroup = []
for (let val of news) {
if (Number(now - val.post.created_at) > interval) {
continue
}
if (new RegExp(banWord).test(val.post.subject)) {
continue
}
if (val.typeName == '公告') {
for (let groupId of cfg.srannounceGroup) {
await this.sendNews(groupId, val.typeName, val.post.post_id)
}
}
if (val.typeName == '资讯') {
for (let groupId of cfg.srinfoGroup) {
await this.sendNews(groupId, val.typeName, val.post.post_id)
}
}
}
}
async sendNews (groupId, typeName, postId) {
if (!this.pushGroup[groupId]) this.pushGroup[groupId] = 0
if (this.pushGroup[groupId] >= this.maxNum) return
let sended = await redis.get(`${this.key}${groupId}:${postId}`)
if (sended) return
// TODO: 暂时处理,后续待更好的解决方案 定时任务无法获取e.bot
this.e.bot = Bot
// 判断是否存在群关系
if (!this.e.bot.gl.get(Number(groupId))) {
logger.mark(`[崩坏星穹铁道${typeName}推送] 群${groupId}未关联`)
return
}
if (!this[postId]) {
const param = await this.newsDetail(postId)
logger.mark(`[崩坏星穹铁道${typeName}推送] ${param.data.post.subject}`)
this[postId] = {
img: await this.render(param),
title: param.data.post.subject
}
}
this.pushGroup[groupId]++
this.e.group = Bot.pickGroup(Number(groupId))
this.e.group_id = Number(groupId)
let tmp = await this.replyMsg(this[postId].img, `崩坏星穹铁道${typeName}推送:${this[postId].title}`)
await common.sleep(1000)
if (!tmp) return
if (tmp?.type != 'xml') {
tmp = [`崩坏星穹铁道${typeName}推送\n`, tmp]
}
redis.set(`${this.key}${groupId}:${postId}`, '1', { EX: 3600 * 10 })
// 随机延迟10-90秒
await common.sleep(lodash.random(10, 90) * 1000)
await this.e.group.sendMsg(tmp)
}
}

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,135 @@
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="content-type" content="text/html;charset=utf-8" />
<link rel="shortcut icon" href="#" />
<link rel="stylesheet" type="text/css" href="{{pluResPath}}html/calculator/calculator.css" />
</head>
<body>
<div class="container" id="container">
<div class="info_box">
<div class="uidRight">
<span>UID : {{uid}}</span>
</div>
<div class="topLeft">
<span>角色养成计算</span>
</div>
</div>
<div class="head_box">
<div class="item">
<div class="role_box">
{{ if dataCharacter.rank>0}}
<span class="life life{{dataCharacter.rank}}">
{{dataCharacter.rank}}命</span>
{{/if}}
<div class="bg{{dataCharacter.rarity}}">
<img class="role_img" src="{{dataCharacter.icon}}" onerror="whenError(this)" />
</div>
</div>
<div class="role_name">
{{dataCharacter.name}}
<div class="role_LV">Lv.{{dataCharacter.level}} <span class="jt"></span> Lv.{{setSkill[0]}}</div>
</div>
{{ if dataCharacter.equip}}
<div class="weapon_box">
<div class="weapon_bg{{dataCharacter.equip.rarity}}">
<img class="weapon_img" src="{{dataCharacter.equip.icon}}" onerror="whenError(this)" />
</div>
</div>
<div class="weapon_name">
{{dataCharacter.equip.name}}
<div class="weapon_LV">Lv.{{dataCharacter.equip.level}} <span class="jt"></span>
Lv.{{setSkill[1]}}
</div>
</div>
{{/if}}
</div>
{{each skillList skill i}}
<div class="skill">
<div class="skillimg">
<img class="skillimgC" src="{{skill.item_url}}" />
</div>
<div class="skillname">
{{ if skill.anchor=="Point01"}}普通攻击{{else if skill.anchor=="Point02"}}战技{{else if skill.anchor=="Point03"}}终结技{{else}}天赋{{/if}}
<div class="skillLv">Lv.{{skill.max_level}}</div>
</div>
<div class="skillRight">
<div class="skillNow"> {{skill.cur_level}} </div>
<div class="skillJt"><span class="jt"></span></div>
<div class="skillNow"> {{setSkill[i+2]}} </div>
</div>
</div>
{{/each}}
</div>
{{if computes.avatar_consume.length + computes.skill_consume.length + computes.equipment_consume.length > 0}}
<div class="data_box">
{{if computes.avatar_consume.length > 0}}
<div class="role_top">
<div class="role_top_name">{{dataCharacter.name}}</div>
<div class="role_top_LV">Lv.{{dataCharacter.level}} <span class="jt"></span> Lv.{{setSkill[0]}}</div>
</div>
<div class="role_separate_line">角色消耗</div>
<div class="cailiao_box">
{{each computes.avatar_consume avatar_consume}}
<div
class="cailiao_item {{if computes.avatar_consume.length>2 && avatar_consume.item_name == `信用点`}}long{{/if}}">
<div class="cailiao_img">
<img class="cailiao_item_img" src="{{avatar_consume.item_url}}" />
</div>
<div class="cailiao_item_title">{{avatar_consume.item_name}} x {{avatar_consume.num}}</div>
</div>
{{/each}}
</div>
{{/if}}
{{if computes.skill_consume.length > 0}}
<div class="role_separate_line">行迹消耗</div>
<div class="cailiao_box">
{{each computes.skill_consume skill_consume}}
<div class="cailiao_item {{if skill_consume.item_name == `信用点`}}long{{/if}}">
<div class="cailiao_img">
<img class="cailiao_item_img" src="{{skill_consume.item_url}}" />
</div>
<div class="cailiao_item_title {{if skill_consume.isTalent}}isTalent{{/if}}">
{{skill_consume.item_name}} x {{skill_consume.num}}</div>
</div>
{{/each}}
</div>
{{/if}}
{{if computes.equipment_consume.length > 0}}
<div class="role_top">
<div class="role_top_name">{{dataCharacter.equip.name}}</div>
<div class="role_top_LV">Lv.{{dataCharacter.equip.level}} <span class="jt"></span>
Lv.{{setSkill[1]}}</div>
</div>
<div class="role_separate"></div>
<div class="cailiao_box">
{{each computes.equipment_consume equipment_consume}}
<div class="cailiao_item">
<div class="cailiao_img">
<img class="cailiao_item_img" src="{{equipment_consume.item_url}}" />
</div>
<div class="cailiao_item_title">{{equipment_consume.item_name}} x {{equipment_consume.num}}</div>
</div>
{{/each}}
</div>
{{/if}}
</div>
{{else}}
<div class="data_box">
<div class="biye">毕业了,下一位 </div>
</div>
{{/if}}
</div>
</body>
<script type="text/javascript"></script>
</html>

Binary file not shown.

After

Width:  |  Height:  |  Size: 53 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 211 KiB

View File

@ -1,10 +1,11 @@
import plugin from '../../lib/plugins/plugin.js'
import common from '../../lib/common/common.js'
import fs from 'node:fs'
import lodash from 'lodash'
import moment from 'moment'
export class sendLog extends plugin {
constructor () {
constructor() {
super({
name: '发送日志',
dsc: '发送最近100条运行日志',
@ -25,7 +26,7 @@ export class sendLog extends plugin {
this.errFile = './logs/error.log'
}
async sendLog () {
async sendLog() {
let lineNum = this.e.msg.match(/\d+/g)
if (lineNum) {
this.lineNum = lineNum[0]
@ -48,13 +49,14 @@ export class sendLog extends plugin {
this.reply(`暂无相关日志:${type}`)
return
}
let title = `最近${log.length}${type}日志`
let forwardMsg = await this.makeForwardMsg(`最近${log.length}${type}日志`, log)
let forwardMsg = await common.makeForwardMsg(this.e, [title, log.join("")], title)
await this.reply(forwardMsg)
}
getLog (logFile) {
getLog(logFile) {
let log = fs.readFileSync(logFile, { encoding: 'utf-8' })
log = log.split('\n')
@ -78,42 +80,4 @@ export class sendLog extends plugin {
return tmp
}
async makeForwardMsg (title, msg) {
let nickname = this.e.bot.nickname
if (this.e.isGroup) {
let info = await this.e.bot.getGroupMemberInfo(this.e.group_id, this.e.bot.uin)
nickname = info.card ?? info.nickname
}
let userInfo = {
user_id: this.e.bot.uin,
nickname
}
let forwardMsg = [
{
...userInfo,
message: title
},
{
...userInfo,
message: msg
}
]
/** 制作转发内容 */
if (this.e.isGroup) {
forwardMsg = await this.e.group.makeForwardMsg(forwardMsg)
} else {
forwardMsg = await this.e.friend.makeForwardMsg(forwardMsg)
}
/** 处理描述 */
forwardMsg.data = forwardMsg.data
.replace(/\n/g, '')
.replace(/<title color="#777777" size="26">(.+?)<\/title>/g, '___')
.replace(/___+/, `<title color="#777777" size="26">${title}</title>`)
return forwardMsg
}
}

View File

@ -11,7 +11,7 @@ const { exec, execSync } = require('child_process')
let uping = false
export class update extends plugin {
constructor () {
constructor() {
super({
name: '更新',
dsc: '#更新 #强制更新',
@ -37,7 +37,7 @@ export class update extends plugin {
this.typeName = 'Miao-Yunzai'
}
async update () {
async update() {
if (!this.e.isMaster) return false
if (uping) {
await this.reply('已有命令更新中..请勿重复操作')
@ -64,7 +64,7 @@ export class update extends plugin {
}
}
async checkGit () {
async checkGit() {
let ret = await execSync('git --version', { encoding: 'utf-8' })
if (!ret || !ret.includes('git version')) {
await this.reply('请先安装git')
@ -74,21 +74,19 @@ export class update extends plugin {
return true
}
getPlugin (plugin = '') {
getPlugin(plugin = '') {
if (!plugin) {
plugin = this.e.msg.replace(/#|更新|强制/g, '')
if (!plugin) return ''
}
let path = `./plugins/${plugin}/.git`
if (!fs.existsSync(path)) return false
if (!fs.existsSync(`plugins/${plugin}/.git`)) return false
this.typeName = plugin
return plugin
}
async execSync (cmd) {
async execSync(cmd) {
return new Promise((resolve, reject) => {
exec(cmd, { windowsHide: true }, (error, stdout, stderr) => {
resolve({ error, stdout, stderr })
@ -96,7 +94,7 @@ export class update extends plugin {
})
}
async runUpdate (plugin = '') {
async runUpdate(plugin = '') {
this.isNowUp = false
let cm = 'git pull --no-rebase'
@ -104,17 +102,15 @@ export class update extends plugin {
let type = '更新'
if (this.e.msg.includes('强制')) {
type = '强制更新'
cm = `git fetch --all && git reset --hard && ${cm}`
cm = `git reset --hard && git pull --rebase --allow-unrelated-histories`
}
if (plugin) {
if (this.e.msg.includes('强制')) {
type = '强制更新'
cm = `git -C ./plugins/${plugin}/ fetch --all && git -C ./plugins/${plugin}/ reset --hard && git -C ./plugins/${plugin}/ pull`
}else{
cm = `git -C ./plugins/${plugin}/ pull --no-rebase`
}
}
if (type == '强制更新')
cm = `cd "plugins/${plugin}" && git reset --hard && git pull --rebase --allow-unrelated-histories`
else
cm = `cd "plugins/${plugin}" && git pull --no-rebase`
}
this.oldCommitId = await this.getcommitId(plugin)
@ -147,10 +143,10 @@ export class update extends plugin {
return true
}
async getcommitId (plugin = '') {
async getcommitId(plugin = '') {
let cm = 'git rev-parse --short HEAD'
if (plugin) {
cm = `git -C ./plugins/${plugin}/ rev-parse --short HEAD`
cm = `cd "plugins/${plugin}" && git rev-parse --short HEAD`
}
let commitId = await execSync(cm, { encoding: 'utf-8' })
@ -159,10 +155,10 @@ export class update extends plugin {
return commitId
}
async getTime (plugin = '') {
let cm = 'git log -1 --oneline --pretty=format:"%cd" --date=format:"%m-%d %H:%M"'
async getTime(plugin = '') {
let cm = 'git log -1 --pretty=format:"%cd" --date=format:"%F %T"'
if (plugin) {
cm = `cd ./plugins/${plugin}/ && git log -1 --oneline --pretty=format:"%cd" --date=format:"%m-%d %H:%M"`
cm = `cd "plugins/${plugin}" && git log -1 --pretty=format:"%cd" --date=format:"%F %T"`
}
let time = ''
@ -177,7 +173,7 @@ export class update extends plugin {
return time
}
async gitErr (err, stdout) {
async gitErr(err, stdout) {
let msg = '更新失败!'
let errMsg = err.toString()
stdout = stdout.toString()
@ -207,7 +203,7 @@ export class update extends plugin {
await this.reply([errMsg, stdout])
}
async updateAll () {
async updateAll() {
let dirs = fs.readdirSync('./plugins/')
await this.runUpdate()
@ -225,14 +221,14 @@ export class update extends plugin {
}
}
restart () {
restart() {
new Restart(this.e).restart()
}
async getLog (plugin = '') {
let cm = 'git log -20 --oneline --pretty=format:"%h||[%cd] %s" --date=format:"%m-%d %H:%M"'
async getLog(plugin = '') {
let cm = 'git log -20 --pretty=format:"%h||[%cd] %s" --date=format:"%F %T"'
if (plugin) {
cm = `cd ./plugins/${plugin}/ && ${cm}`
cm = `cd "plugins/${plugin}" && ${cm}`
}
let logAll
@ -259,59 +255,14 @@ export class update extends plugin {
if (log.length <= 0) return ''
let end = ''
let title = `${plugin || 'Miao-Yunzai'}更新日志,共${line}`
log = await this.makeForwardMsg(`${plugin || 'Miao-Yunzai'}更新日志,共${line}`, log, end)
log = await common.makeForwardMsg(this.e, [title, log], title)
return log
}
async makeForwardMsg (title, msg, end) {
let nickname = this.e.bot.nickname
if (this.e.isGroup) {
let info = await this.e.bot.getGroupMemberInfo(this.e.group_id, this.e.bot.uin)
nickname = info.card ?? info.nickname
}
let userInfo = {
user_id: this.e.bot.uin,
nickname
}
let forwardMsg = [
{
...userInfo,
message: title
},
{
...userInfo,
message: msg
}
]
if (end) {
forwardMsg.push({
...userInfo,
message: end
})
}
/** 制作转发内容 */
if (this.e.isGroup) {
forwardMsg = await this.e.group.makeForwardMsg(forwardMsg)
} else {
forwardMsg = await this.e.friend.makeForwardMsg(forwardMsg)
}
/** 处理描述 */
forwardMsg.data = forwardMsg.data
.replace(/\n/g, '')
.replace(/<title color="#777777" size="26">(.+?)<\/title>/g, '___')
.replace(/___+/, `<title color="#777777" size="26">${title}</title>`)
return forwardMsg
}
async updateLog () {
async updateLog() {
let log = await this.getLog()
await this.reply(log)
}

View File

@ -1,9 +1,8 @@
import cfg from '../../lib/config/config.js'
import plugin from '../../lib/plugins/plugin.js'
import common from '../../lib/common/common.js'
import fs from 'node:fs'
import lodash from 'lodash'
import { segment } from 'icqq'
import { pipeline } from 'stream'
import { promisify } from 'util'
import fetch from 'node-fetch'
@ -12,7 +11,7 @@ import moment from 'moment'
let textArr = {}
export class add extends plugin {
constructor () {
constructor() {
super({
name: '添加表情',
dsc: '添加表情,文字等',
@ -45,7 +44,7 @@ export class add extends plugin {
this.isGlobal = false
}
async init () {
async init() {
if (!fs.existsSync(this.path)) {
fs.mkdirSync(this.path)
}
@ -54,7 +53,7 @@ export class add extends plugin {
}
}
async accept () {
async accept() {
/** 处理消息 */
if (this.e.atBot && this.e.msg && this.e?.msg.includes('添加') && !this.e?.msg.includes('#')) {
this.e.msg = '#' + this.e.msg
@ -62,12 +61,12 @@ export class add extends plugin {
}
/** 群号key */
get grpKey () {
get grpKey() {
return `Yz:group_id:${this.e.user_id}`
}
/** #添加 */
async add () {
async add() {
this.isGlobal = this.e?.msg.includes("全局");
await this.getGroupId()
@ -95,14 +94,13 @@ export class add extends plugin {
}
/** 获取群号 */
async getGroupId () {
async getGroupId() {
/** 添加全局表情存入到机器人qq文件中 */
if (this.isGlobal) {
this.group_id = this.e.bot.uin;
return this.e.bot.uin;
}
if (this.e.isGroup) {
this.group_id = this.e.group_id
redis.setEx(this.grpKey, 3600 * 24 * 30, String(this.group_id))
@ -119,7 +117,7 @@ export class add extends plugin {
return false
}
checkAuth () {
checkAuth() {
if (this.e.isMaster) return true
let groupCfg = cfg.getGroup(this.group_id)
@ -148,7 +146,7 @@ export class add extends plugin {
return true
}
checkKeyWord () {
checkKeyWord() {
if (this.e.img && this.e.img.length > 1) {
this.e.reply('添加错误:只能发送一个表情当关键词')
return false
@ -171,7 +169,7 @@ export class add extends plugin {
}
/** 单独添加 */
async singleAdd () {
async singleAdd() {
if (this.e.message.length != 2) return false
let msg = lodash.keyBy(this.e.message, 'type')
if (!this.e.msg || !msg.image) return false
@ -194,7 +192,7 @@ export class add extends plugin {
}
/** 获取添加关键词 */
getKeyWord () {
getKeyWord() {
this.e.isGlobal = this.e.msg.includes("全局");
this.keyWord = this.e.toString()
@ -214,7 +212,7 @@ export class add extends plugin {
}
/** 过滤别名 */
trimAlias (msg) {
trimAlias(msg) {
let groupCfg = cfg.getGroup(this.group_id)
let alias = groupCfg.botAlias
if (!Array.isArray(alias)) {
@ -230,7 +228,7 @@ export class add extends plugin {
}
/** 添加内容 */
async addContext () {
async addContext() {
this.isGlobal = this.e.isGlobal || this.getContext()?.addContext?.isGlobal;
await this.getGroupId()
/** 关键词 */
@ -287,7 +285,7 @@ export class add extends plugin {
}
/** 添加成功回复消息 */
getRetMsg () {
getRetMsg() {
let retMsg = this.getContext()
let msg = ''
if (retMsg?.addContext?.message) {
@ -316,7 +314,7 @@ export class add extends plugin {
return lodash.compact(msg)
}
saveJson () {
saveJson() {
let obj = {}
for (let [k, v] of textArr[this.group_id]) {
obj[k] = v
@ -324,7 +322,7 @@ export class add extends plugin {
fs.writeFileSync(`${this.path}${this.group_id}.json`, JSON.stringify(obj, '', '\t'))
}
saveGlobalJson() {
let obj = {};
for (let [k, v] of textArr[this.e.bot.uin]) {
@ -337,7 +335,7 @@ export class add extends plugin {
);
}
async saveImg (url, keyWord) {
async saveImg(url, keyWord) {
let groupCfg = cfg.getGroup(this.group_id)
let savePath = `${this.facePath}${this.group_id}/`
@ -375,9 +373,9 @@ export class add extends plugin {
return savePath
}
async getText () {
async getText() {
if (!this.e.message) return false
this.isGlobal = false
await this.getGroupId()
@ -385,7 +383,7 @@ export class add extends plugin {
if (!this.group_id) return false
this.initTextArr()
this.initGlobalTextArr()
let keyWord = this.e.toString()
@ -410,7 +408,7 @@ export class add extends plugin {
if (lodash.isEmpty(msg) && lodash.isEmpty(globalMsg)) return false
msg = [...msg, ...globalMsg]
if (num >= 0 && num < msg.length) {
msg = msg[num]
} else {
@ -446,7 +444,7 @@ export class add extends plugin {
return true
}
expiredMsg (keyWord, num) {
expiredMsg(keyWord, num) {
logger.mark(`[发送表情]${this.e.logText} ${keyWord} 表情已过期失效`)
let arr = textArr[this.group_id].get(keyWord)
@ -462,7 +460,7 @@ export class add extends plugin {
}
/** 初始化已添加内容 */
initTextArr () {
initTextArr() {
if (textArr[this.group_id]) return
textArr[this.group_id] = new Map()
@ -510,7 +508,7 @@ export class add extends plugin {
fs.mkdirSync(facePath)
}
}
/** 初始化全局已添加内容 */
initGlobalTextArr() {
if (textArr[this.e.bot.uin]) return;
@ -568,7 +566,7 @@ export class add extends plugin {
}
}
async del () {
async del() {
this.isGlobal = this.e?.msg.includes("全局");
await this.getGroupId()
if (!this.group_id) return false
@ -652,14 +650,14 @@ export class add extends plugin {
img = item[0]
}
if (img.local) {
fs.unlink(img.local, () => {})
fs.unlink(img.local, () => { })
}
})
this.saveJson()
}
async list () {
async list() {
this.isGlobal = this.e?.msg.includes("全局");
let page = 1
@ -727,9 +725,8 @@ export class add extends plugin {
num++
}
let end = ''
if (type == 'list' && count > 100) {
end = `更多内容请翻页查看\n如:#表情列表${Number(page) + 1}`
msg.push(`更多内容请翻页查看\n如:#表情列表${Number(page) + 1}`)
}
let title = `表情列表,第${page}页,共${count}`
@ -737,63 +734,19 @@ export class add extends plugin {
title = `表情${search}${count}`
}
let forwardMsg = await this.makeForwardMsg(this.e.bot.uin, title, msg, end)
let forwardMsg = await common.makeForwardMsg(this.e, [title, msg], title)
this.e.reply(forwardMsg)
}
async makeForwardMsg (qq, title, msg, end = '') {
let nickname = this.e.bot.nickname
if (this.e.isGroup) {
let info = await this.e.bot.getGroupMemberInfo(this.e.group_id, qq)
nickname = info.card ?? info.nickname
}
let userInfo = {
user_id: this.e.bot.uin,
nickname
}
let forwardMsg = [
{
...userInfo,
message: title
}
]
let msgArr = lodash.chunk(msg, 40)
msgArr.forEach(v => {
v[v.length - 1] = lodash.trim(v[v.length - 1], '\n')
forwardMsg.push({ ...userInfo, message: v })
})
if (end) {
forwardMsg.push({ ...userInfo, message: end })
}
/** 制作转发内容 */
if (this.e.isGroup) {
forwardMsg = await this.e.group.makeForwardMsg(forwardMsg)
} else {
forwardMsg = await this.e.friend.makeForwardMsg(forwardMsg)
}
/** 处理描述 */
forwardMsg.data = forwardMsg.data
.replace(/\n/g, '')
.replace(/<title color="#777777" size="26">(.+?)<\/title>/g, '___')
.replace(/___+/, `<title color="#777777" size="26">${title}</title>`)
return forwardMsg
}
/** 分页 */
pagination (pageNo, pageSize, array) {
pagination(pageNo, pageSize, array) {
let offset = (pageNo - 1) * pageSize
return offset + pageSize >= array.length ? array.slice(offset, array.length) : array.slice(offset, offset + pageSize)
}
/** 关键词转换成可发送消息 */
async keyWordTran (msg) {
async keyWordTran(msg) {
/** 图片 */
if (msg.includes('{image')) {
let tmp = msg.split('{image')
@ -825,4 +778,4 @@ export class add extends plugin {
return msg
}
}
}