fix: 补充类型

This commit is contained in:
ningmengchongshui 2024-06-09 20:02:18 +08:00
parent 9da3312f43
commit c7e3b94161
14 changed files with 369 additions and 257 deletions

View File

@ -1,6 +1,8 @@
import YAML from 'yaml'
import fs from 'node:fs'
import chokidar from 'chokidar'
import { join } from 'node:path'
import { CONFIG_DEFAULT_PATH, CONFIG_INIT_PATH } from './system.js'
/**
* ********
@ -13,17 +15,17 @@ class Cfg {
/** 监听文件 */
watcher = { config: {}, defSet: {} }
constructor () {
constructor() {
this.initCfg()
}
/**
*
*/
initCfg () {
let path = 'config/config/'
let pathDef = 'config/default_config/'
initCfg() {
const path = CONFIG_INIT_PATH
const pathDef = CONFIG_DEFAULT_PATH
const files = fs.readdirSync(pathDef).filter(file => file.endsWith('.yaml'))
for (let file of files) {
if (!fs.existsSync(`${path}${file}`)) {
@ -37,45 +39,45 @@ class Cfg {
/**
* qq号
*/
get qq () {
get qq() {
return Number(this.getConfig('qq').qq)
}
/**
*
*/
get pwd () {
get pwd() {
return this.getConfig('qq').pwd
}
/**
* icqq配置
*/
get bot () {
get bot() {
let bot = this.getConfig('bot')
let defbot = this.getdefSet('bot')
bot = { ...defbot, ...bot }
bot.platform = this.getConfig('qq').platform
/** 设置data目录防止pm2运行时目录不对 */
bot.data_dir = process.cwd() + '/data/icqq/' + this.qq || ''
if (!bot.ffmpeg_path) delete bot.ffmpeg_path
if (!bot.ffprobe_path) delete bot.ffprobe_path
return bot
const Config = { ...defbot, ...bot }
Config.platform = this.getConfig('qq').platform
/**
* data目录pm2运行时目录不对
*/
Config.data_dir = join(process.cwd(), `/data/icqq/${this.qq}`)
if (!Config.ffmpeg_path) delete Config.ffmpeg_path
if (!Config.ffprobe_path) delete Config.ffprobe_path
return Config
}
/**
*
*/
get other () {
get other() {
return this.getConfig('other')
}
/**
*
*/
get redis () {
get redis() {
return this.getConfig('redis')
}
@ -96,25 +98,29 @@ class Cfg {
/**
* qq
*/
get masterQQ () {
let masterQQ = this.getConfig('other').masterQQ || []
get masterQQ() {
const masterQQ = this.getConfig('other')?.masterQQ || []
if (Array.isArray(masterQQ)) {
masterQQ.forEach(qq => { qq = String(qq) })
return masterQQ.forEach(qq => { qq = String(qq) })
} else {
masterQQ = [String(masterQQ)]
return [String(masterQQ)]
}
return masterQQ
}
_package = null
/**
* package.json
*/
get package () {
get package() {
if (this._package) return this._package
this._package = JSON.parse(fs.readFileSync('package.json', 'utf8'))
return this._package
try {
const data = fs.readFileSync('package.json', 'utf8')
this._package = JSON.parse(data)
return this._package
} catch {
return {}
}
}
/**
@ -122,9 +128,9 @@ class Cfg {
* @param groupId
* @returns
*/
getGroup (groupId = '') {
let config = this.getConfig('group')
let defCfg = this.getdefSet('group')
getGroup(groupId = '') {
const config = this.getConfig('group')
const defCfg = this.getdefSet('group')
if (config[groupId]) {
return { ...defCfg.default, ...config.default, ...config[groupId] }
}
@ -135,9 +141,9 @@ class Cfg {
* other配置
* @returns
*/
getOther () {
let def = this.getdefSet('other')
let config = this.getConfig('other')
getOther() {
const def = this.getdefSet('other')
const config = this.getConfig('other')
return { ...def, ...config }
}
@ -145,27 +151,27 @@ class Cfg {
* notice配置
* @returns
*/
getNotice () {
let def = this.getdefSet('notice')
let config = this.getConfig('notice')
getNotice() {
const def = this.getdefSet('notice')
const config = this.getConfig('notice')
return { ...def, ...config }
}
/**
*
*
* @param name
* @returns
*/
getdefSet (name) {
getdefSet(name: string) {
return this.getYaml('default_config', name)
}
/**
*
*
* @param name
* @returns
*/
getConfig (name) {
getConfig(name: string) {
return this.getYaml('config', name)
}
@ -174,7 +180,7 @@ class Cfg {
* @param type -defSet-config
* @param name
*/
getYaml (type, name) {
getYaml(type, name) {
let file = `config/${type}/${name}.yaml`
let key = `${type}.${name}`
if (this.config[key]) return this.config[key]
@ -195,13 +201,11 @@ class Cfg {
* @param type
* @returns
*/
watch (file, name, type = 'default_config') {
let key = `${type}.${name}`
watch(file:string, name:string, type = 'default_config') {
const key = `${type}.${name}`
if (this.watcher[key]) return
const watcher = chokidar.watch(file)
watcher.on('change', path => {
watcher.on('change', () => {
delete this.config[key]
if (typeof Bot == 'undefined') return
logger.mark(`[修改配置文件][${type}][${name}]`)
@ -209,7 +213,6 @@ class Cfg {
this[`change_${name}`]()
}
})
this.watcher[key] = watcher
}
@ -217,21 +220,19 @@ class Cfg {
*
* @returns
*/
change_qq () {
change_qq() {
if (process.argv.includes('login') || !this.qq) return
logger.info('修改机器人QQ或密码请手动重启')
}
/**
*
*
*/
async change_bot () {
/** 修改日志等级 */
let log = await import('./log.js')
async change_bot() {
const log = await import('./log.js')
log.default()
}
}
/**
@ -239,4 +240,4 @@ class Cfg {
*
* ***
*/
export default new Cfg()
export default new Cfg()

View File

@ -1,100 +1,170 @@
import fs, { promises } from "node:fs"
import yaml from "yaml"
import { BOT_NAME } from "./system.js"
import createQQ from "./qq.js"
import setLog from "./log.js"
import redisInit from "./redis.js"
import { checkRun } from "./check.js"
import fs from "node:fs"
import yaml from "yaml"
/** 设置标题 */
process.title = "Miao-Yunzai"
import { join } from "node:path"
/**
*
*/
async function UpdateTitle() {
// 添加一些多余的标题内容
let title = "Miao-Yunzai"
let qq = await fs.promises.readFile("./config/config/qq.yaml", 'utf-8').then(yaml.parse).catch(() => null)
export async function UpdateTitle() {
/**
*
*/
let title = BOT_NAME
//
const qq = await promises.readFile("./config/config/qq.yaml", 'utf-8').then(yaml.parse).catch(() => null)
/**
*
*/
if (qq) {
title += `@${qq.qq || ""}`
switch (qq.platform) {
case 1:
case 1:{
title += " 安卓手机"
break
case 2:
}
case 2:{
title += " aPad"
break
case 3:
}
case 3:{
title += " 安卓手表"
break
case 4:
}
case 4:{
title += " MacOS"
break
case 5:
}
case 5:{
title += " iPad"
break
case 6:
}
case 6:{
title += " Tim"
break
default:
}
default:{
break
}
}
}
/** 设置标题 */
/**
*
*/
process.title = title
}
/** 设置时区 */
/**
*
*/
export async function checkInit() {
/**
* node_modules
*/
if (!fs.existsSync(join(process.cwd(), "./node_modules"))) {
console.log("未安装依赖。。。。")
console.log("请先运行命令pnpm install -P 安装依赖")
process.exit()
}
/**
* node_modules/icqq
*/
if(!fs.existsSync(join(process.cwd(), "./node_modules/icqq"))){
console.log("未安装icqq。。。。")
console.log("请先运行命令pnpm install -P 安装依赖")
process.exit()
}
/**
* qq.yaml
*/
await createQQ()
/**
*
*/
setLog()
/**
*
*/
logger.mark(`${BOT_NAME} 启动中...`)
/**
*
*/
await redisInit()
/**
*
*/
await checkRun()
/**
*
*/
await UpdateTitle()
}
/**
*
*/
process.title = BOT_NAME
/**
*
*/
process.env.TZ = "Asia/Shanghai"
/**
*
*/
process.on("SIGHUP", () => process.exit())
/** 捕获未处理的错误 */
/**
*
*/
process.on("uncaughtException", error => {
if (typeof logger == "undefined") console.log(error)
else logger.error(error)
})
/** 捕获未处理的Promise错误 */
process.on("unhandledRejection", (error, promise) => {
/**
* Promise错误
*/
process.on("unhandledRejection", (error) => {
if (typeof logger == "undefined") console.log(error)
else logger.error(error)
})
/** 退出事件 */
process.on("exit", async code => {
if (typeof redis != "undefined" && typeof test == "undefined")
/**
* 退
*/
process.on("exit", async () => {
if (typeof redis != "undefined") {
await redis.save()
if (typeof logger == "undefined")
console.log("Miao-Yunzai 已停止运行")
else
logger.mark(logger.magenta("Miao-Yunzai 已停止运行"))
}
if (typeof logger == "undefined") {
console.log(`${BOT_NAME} 已停止运行`)
}
else {
logger.mark(logger.magenta(`${BOT_NAME} 已停止运行`))
}
})
await checkInit()
/**
*
*
*/
async function checkInit() {
/** 检查node_modules */
if (!fs.existsSync("./node_modules") || !fs.existsSync("./node_modules/icqq")) {
console.log("请先运行命令pnpm install -P 安装依赖")
process.exit()
}
/** 检查qq.yaml */
await createQQ()
/** 日志设置 */
setLog()
logger.mark("Miao-Yunzai 启动中...")
await redisInit()
await checkRun()
//** 更新标题 */
await UpdateTitle()
}
await checkInit()

View File

@ -1,8 +1,9 @@
import fs from 'fs'
import inquirer from 'inquirer'
import chalk from 'chalk'
import { BOT_NAME, CONFIG_DEFAULT_PATH, CONFIG_INIT_PATH } from './system.js'
import cfg from './config.js'
import { sleep } from '../utils/common.js'
import chalk from 'chalk'
/**
* qq配置文件 `config/bot/qq.yaml`
@ -20,11 +21,10 @@ export default async function createQQ() {
return
}
/**
*
*/
console.log(`欢迎使用${chalk.green('Miao-Yunzai v' + cfg.package.version)}\n请按提示输入完成QQ配置`)
console.log(`欢迎使用${chalk.green(`${BOT_NAME} v` + cfg.package.version)}\n请按提示输入完成QQ配置`)
/**
@ -99,8 +99,11 @@ export default async function createQQ() {
/**
*
*/
let file = './config/config/'
let fileDef = './config/default_config/'
const file = `./${CONFIG_INIT_PATH}`
const fileDef = `./${CONFIG_DEFAULT_PATH}`
let qq = fs.readFileSync(`${fileDef}qq.yaml`, 'utf8')
@ -136,4 +139,4 @@ export default async function createQQ() {
*
*/
await sleep(2000)
}
}

8
src/config/system.ts Normal file
View File

@ -0,0 +1,8 @@
// 机器人名称
export const BOT_NAME = 'Miao-Yunzai'
// 生成式配置
export const CONFIG_INIT_PATH = 'config/config/'
// 默认配置
export const CONFIG_DEFAULT_PATH = 'config/default_config/'
// redis root
export const REDIS_ROOT_KEY = 'Yz:cache:'

126
src/core/common.ts Normal file
View File

@ -0,0 +1,126 @@
/**
* ************
* bot处理core
* ************
*/
/**
*
* @param userId qq号
* @param msg
* @param uin bot发送Bot
*/
export async function relpyPrivate(userId, msg, uin = Bot.uin) {
userId = Number(userId)
let friend = Bot.fl.get(userId)
if (friend) {
logger.mark(`发送好友消息[${friend.nickname}](${userId})`)
return await Bot[uin]
.pickUser(userId)
.sendMsg(msg)
.catch(err => {
logger.mark(err)
})
}
}
/**
*
* @param e
* @param msg
* @param dec
* @param msgsscr
*/
export async function makeForwardMsg(
e: any,
msg: any[] | string = [],
dec: string = '',
msgsscr = false
) {
// 不是数组
if (!Array.isArray(msg)) msg = [msg]
//
let name = msgsscr ? e.sender.card || e.user_id : Bot.nickname
//
const Id = msgsscr ? e.user_id : Bot.uin
// 是群聊
if (e.isGroup) {
try {
const Info = await e.bot.getGroupMemberInfo(e.group_id, Id)
name = Info.card || Info.nickname
} catch (err) {
console.error(err)
}
}
let forwardMsg:
| {
user_id: number
nickname: string
message: any
}[]
| {
data: any
} = []
/**
*
*/
for (const message of msg) {
if (!message) continue
forwardMsg.push({
user_id: Id,
nickname: name,
message: message
})
}
/**
*
*/
try {
/**
*
*/
if (e?.group?.makeForwardMsg) {
// ?
forwardMsg = await e.group.makeForwardMsg(forwardMsg)
} else if (e?.friend?.makeForwardMsg) {
// ?
forwardMsg = await e.friend.makeForwardMsg(forwardMsg)
} else {
//
return msg.join('\n')
}
/**
*
*/
if (dec) {
/**
*
*/
if (typeof forwardMsg.data === 'object') {
const 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>`)
}
}
} catch (err) {
console.error(err)
}
return forwardMsg
}

View File

@ -1,6 +1,7 @@
import EventListener from '../listener/listener.js'
import fetch from 'node-fetch'
import cfg from '../../config/config.js'
import { BOT_NAME } from '../../config/system.js'
/**
* 线
@ -25,7 +26,7 @@ export default class offlineEvent extends EventListener {
async execute (e) {
logger.mark('掉线了')
let config = cfg.getConfig('notice')
let title = `Miao-Yunzai(${Bot.nickname})已离线,请关注`
let title = `${BOT_NAME}(${Bot.nickname})已离线,请关注`
if (config.iyuu) {
await fetch(`https://iyuu.cn/${config.iyuu}.send?text=${title}&desp=${e.message}`)
}

View File

@ -1,6 +1,7 @@
import EventListener from '../listener/listener.js'
import cfg from '../../config/config.js'
import { relpyPrivate } from '../../utils/common.js'
import { relpyPrivate } from '../../core/common.js'
import { BOT_NAME } from '../../config/system.js'
/**
* 线
@ -27,7 +28,7 @@ export default class onlineEvent extends EventListener {
*/
async execute(e) {
logger.mark('----^_^----')
logger.mark(logger.green(`Miao-Yunzai 上线成功 版本v${cfg.package.version}`))
logger.mark(logger.green(`${BOT_NAME} 上线成功 版本v${cfg.package.version}`))
logger.mark(logger.green('https://github.com/yoimiya-kokomi/Miao-Yunzai'))
// logger.mark('-----------')
/** 加载插件 */
@ -48,7 +49,7 @@ export default class onlineEvent extends EventListener {
if (await redis.get(key)) return
let msg = `欢迎使用【Miao-Yunzai v${cfg.package.version}\n【#帮助】查看指令说明\n【#状态】查看运行状态\n【#日志】查看运行日志\n【#更新】拉取 Github 更新\n【#全部更新】更新全部插件\n【#更新日志】查看更新日志\n【#重启】重新启动\n【#配置ck】配置公共查询 Cookie`
let msg = `欢迎使用【${BOT_NAME} v${cfg.package.version}\n【#帮助】查看指令说明\n【#状态】查看运行状态\n【#日志】查看运行日志\n【#更新】拉取 Github 更新\n【#全部更新】更新全部插件\n【#更新日志】查看更新日志\n【#重启】重新启动\n【#配置ck】配置公共查询 Cookie`
redis.set(key, '1', { EX: cfg.bot.online_msg_exp })

View File

@ -1,11 +1,14 @@
import moment from 'moment'
import BaseModel from './BaseModel.js'
import MysUtil from './MysUtil.js'
import { REDIS_ROOT_KEY } from '../config/system.js'
//
const servs = ['mys', 'hoyolab']
// 超时时间不必精确直接定24小时即可
const EX = 3600 * 24
const redisKeyRoot = 'Yz:cache:'
//
const redisKeyRoot = REDIS_ROOT_KEY
/**
* ************

View File

@ -62,7 +62,7 @@ export default class MysUser extends BaseModel {
constructor(ltuid) {
super()
if (!ltuid) {
return false
return
}
// 检查实例缓存
let self = this._getThis('mys', ltuid)
@ -520,7 +520,7 @@ export default class MysUser extends BaseModel {
* ck数据
* @param data
*/
setCkData(data = {}) {
setCkData(data: { ck: string; type: string; device: string; uids?: any }) {
this.ck = data.ck || this.ck || ''
this.type = data.type || this.type || 'mys'
this.device = data.device || this.device || MysUtil.getDeviceGuid()

View File

@ -425,15 +425,13 @@ export default class NoteUser extends BaseModel {
return await this.delMysUser(ltuid)
}
mysUsers = []
_map = null
/**
*
* @param mysUser
*/
async delMysUser(mysUser = '') {
async delMysUser(mysUser: any = '') {
let ltuid = mysUser.ltuid || mysUser
if (ltuid && this.mysUsers[ltuid]) {
let mys = this.mysUsers[ltuid]
@ -484,7 +482,7 @@ export default class NoteUser extends BaseModel {
// TODO: 若checkRet中返回了不同的uid进行CK保存更新
// 失效
let mysUser = await MysUser.create(ck)
if (mysUser) {
if (mysUser && checkRet) {
let status = checkRet.status
if (status === 0 || status === 1) {
// status为1时无法查询天赋但仍可查询角色保留CK

View File

@ -16,7 +16,7 @@ export default class apiTool {
* @param {} server
* @param {? type(bool or string)} isSr
*/
constructor(uid: string | null, server, isSr: boolean = false) {
constructor(uid: string | null, server: string, isSr: boolean = false) {
uid && (this.uid = uid)
typeof isSr != 'undefined' && (this.uid = uid)
server && (this.server = server)

View File

@ -261,6 +261,10 @@ class GsCfg {
}
}
nameID = new Map()
sr_nameID = new Map()
/**
*
* @returns
@ -270,6 +274,7 @@ class GsCfg {
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')
@ -303,7 +308,7 @@ class GsCfg {
* @param isSr
* @returns
*/
_roleNameToID(keyword, isSr) {
_roleNameToID(keyword, isSr?: boolean) {
if (isSr) this.isSr = isSr
if (!isNaN(keyword)) keyword = Number(keyword)
this._getAbbr()

View File

@ -3,8 +3,28 @@ import fetch from 'node-fetch'
import cfg from '../config/config.js'
import apiTool from './apiTool.js'
let HttpsProxyAgent = ''
let HttpsProxyAgent = null
/**
*
*/
export default class MysApi {
uid = null
cookie = null
isSr = null
server = null
apiTool = null
/**
* 5
*/
cacheCd = 300
/**
*
*/
_device = null
option = null
/**
* @param uid uid
* @param cookie cookie
@ -278,17 +298,14 @@ export default class MysApi {
let proxyAddress = cfg.bot.proxyAddress
if (!proxyAddress) return null
if (proxyAddress === 'http://0.0.0.0:0') return null
if (!/os_|official/.test(this.server)) return null
if (HttpsProxyAgent === '') {
HttpsProxyAgent = await import('https-proxy-agent').catch(err => {
//
if (HttpsProxyAgent == null) {
const data = await import('https-proxy-agent').catch(err => {
logger.error(err)
})
HttpsProxyAgent = HttpsProxyAgent
? HttpsProxyAgent.HttpsProxyAgent
: undefined
HttpsProxyAgent = data ? data.HttpsProxyAgent : undefined
}
if (HttpsProxyAgent) {

View File

@ -4,26 +4,6 @@ import fetch from 'node-fetch'
import fs from 'node:fs'
import path from 'node:path'
/**
*
* @param userId qq号
* @param msg
* @param uin bot发送Bot
*/
export async function relpyPrivate(userId, msg, uin = Bot.uin) {
userId = Number(userId)
let friend = Bot.fl.get(userId)
if (friend) {
logger.mark(`发送好友消息[${friend.nickname}](${userId})`)
return await Bot[uin]
.pickUser(userId)
.sendMsg(msg)
.catch(err => {
logger.mark(err)
})
}
}
/**
*
* @param ms
@ -67,104 +47,3 @@ export function mkdirs(dirname: string) {
}
}
}
/**
*
* @param e
* @param msg
* @param dec
* @param msgsscr
*/
export async function makeForwardMsg(
e: any,
msg: any[] | string = [],
dec: string = '',
msgsscr = false
) {
// 不是数组
if (!Array.isArray(msg)) msg = [msg]
//
let name = msgsscr ? e.sender.card || e.user_id : Bot.nickname
//
const Id = msgsscr ? e.user_id : Bot.uin
// 是群聊
if (e.isGroup) {
try {
const Info = await e.bot.getGroupMemberInfo(e.group_id, Id)
name = Info.card || Info.nickname
} catch (err) {
console.error(err)
}
}
let forwardMsg:
| {
user_id: number
nickname: string
message: any
}[]
| {
data: any
} = []
/**
*
*/
for (const message of msg) {
if (!message) continue
forwardMsg.push({
user_id: Id,
nickname: name,
message: message
})
}
/**
*
*/
try {
/**
*
*/
if (e?.group?.makeForwardMsg) {
// ?
forwardMsg = await e.group.makeForwardMsg(forwardMsg)
} else if (e?.friend?.makeForwardMsg) {
// ?
forwardMsg = await e.friend.makeForwardMsg(forwardMsg)
} else {
//
return msg.join('\n')
}
/**
*
*/
if (dec) {
/**
*
*/
if (typeof forwardMsg.data === 'object') {
const 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>`)
}
}
} catch (err) {
console.error(err)
}
return forwardMsg
}