feat: ts-node

This commit is contained in:
ningmengchongshui 2024-06-08 20:52:49 +08:00
parent 6a5200e734
commit ab46375b3d
14 changed files with 429 additions and 105 deletions

21
.npmrc
View File

@ -1,5 +1,24 @@
#为项目单独设置镜像
registry=https://registry.npmmirror.com
# canvas
canvas_binary_host_mirror=https://ghproxy.com/https://github.com/Automattic/node-canvas/releases/download/
# node-sass
sass_binary_site=https://npmmirror.com/mirrors/node-sass/
# sqlite3
node_sqlite3_binary_host_mirror=https://npmmirror.com/mirrors/sqlite3
canvas_binary_host_mirror=https://npmmirror.com/mirrors/canvas
# TFJS
TFJS_NODE_CDN_STORAGE=https://cdn.npmmirror.com/binaries/
# pup
PUPPETER_DOWNLOAD_BASE_URL=https://npmmirror.com/mirrors/chrome-for-testing
# 不生成lock
package-lock=false
# 改为 npm 依赖安装方式
node-linker=hoisted
# 可耻的提升
shamefully-hoist=true
# 严格的对等依赖关系
strict-peer-dependencies=false
#
sharp_binary_host=https://npmmirror.com/mirrors/sharp
#
sharp_libvips_binary_host=https://npmmirror.com/mirrors/sharp-libvips

2
.prettierignore Normal file
View File

@ -0,0 +1,2 @@
# Node dependencies
node_modules

15
.prettierrc.json Normal file
View File

@ -0,0 +1,15 @@
{
"$schema": "https://json.schemastore.org/prettierrc",
"semi": false,
"tabWidth": 2,
"singleQuote": true,
"printWidth": 80,
"trailingComma": "none",
"useTabs": false,
"proseWrap": "preserve",
"arrowParens": "avoid",
"bracketSpacing": true,
"endOfLine": "auto",
"quoteProps": "consistent",
"vueIndentScriptAndStyle": true
}

127
README.md
View File

@ -1,126 +1,75 @@
# Miao-Yunzai v3
基于乐神版[云崽v3.0](https://gitee.com/le-niao/Yunzai-Bot) 改造
这里是Miao-Yunzai V4 测试仓库,
需要同时安装[miao-plugin](https://github.com/yoimiya-kokomi/miao-plugin.git) 且后续的一些底层改造可能会改变数据结构无法直接迁回原版Yunzai请根据自己需求情况慎重安装
你应该积极使用 V3 ,它仍然是长期支持并维护的版本。
使用[icqq](https://github.com/icqqjs/icqq) 登录防止oicq可能出现的低版本问题
哪怕 V4 后续发布V3仍然接受长期支持并维护。
---
与原版Yunzai-Bot的差异
在功能点未完成测试之前,仓库不会发布任何有关新功能信息。
**【注意】:** 由于是独立新的仓库,【只建议新部署/部署后迁移】不建议原Bot直接换源强更
> 必要环境 Windows/Linux + Chrome/Chromium/Edge
* **一些新特性:** Miao-Yunzai会逐步重构增加新特性与功能可能会有功能与形态上的变化。如期望功能更加稳定可使用此仓库[Yunzai-V3](https://gitee.com/yoimiya-kokomi/Yunzai-Bot)
* **移除了签到功能:** 与原Yunzai独立的仓库去除了较为敏感的签到功能以尝试恢复[Github](https://github.com/yoimiya-kokomi/Miao-Yunzai.git)
环境。附加[Gitee](https://gitee.com/yoimiya-kokomi/Miao-Yunzai.git)
* **默认启用喵版的功能:** 【#角色】【#深渊】【#帮助】等功能默认启用喵版,原版的逻辑会屏蔽,以便于后续逐步精简资源
* **一键迁移 TRSS-Yunzai** 若无法登录QQ可尝试 `node trss` 迁移,迁移后可登录其他协议端 [TRSS-Yunzai](https://gitee.com/TimeRainStarSky/Yunzai)
> 必要环境 18.18.2>Node.js>16.14.0 + Redis>5.0.0
## Miao-Yunzai后续计划
如果你的系统不支持18.18.2版本最低能下载16.14.0版本这是最新的puppeteer版本限制。
先刨坑,但也许会咕咕咕
* 功能与`miao-plugin`部分功能进行整合或升级
* [√] 角色卡片、抽卡分析等使用`miao-plugin`版本
* `miao-plugin`的帮助、设置、版本信息会升至`Miao-Yunzai`,以支持更多场景
* 一些底层会与`miao-plugin`做更深层的联动,以支持一些高级功能
* [√] 星铁底层支持,原神&星铁多UID支持
* 基于面板信息的uid管理及认证
* ck切换感知等
* 逐步实验一些新的特性
* 更完备的plugin基础能力支持
* 第三方 IM / Bot / WebAPI 对接或适配等
项目仅供学习交流使用,严禁用于任何商业用途和非法行为
## 使用方法
> 环境准备: Windows or LinuxNode.js [版本至少v16以上](http://nodejs.cn/download/) [Redis](https://redis.io/docs/getting-started/installation/ )
1.克隆项目并安装miao-plugin
请根据网络情况选择Github安装或Gitee安装
```
# 使用 Github
git clone --depth=1 https://github.com/yoimiya-kokomi/Miao-Yunzai.git
cd Miao-Yunzai
git clone --depth=1 https://github.com/yoimiya-kokomi/miao-plugin.git ./plugins/miao-plugin/
该版本将支持TS、TSX环境提供Miao-Yunzai完全的类型声明及其开发文档。
# 使用Gitee
git clone --depth=1 https://gitee.com/yoimiya-kokomi/Miao-Yunzai.git
cd Miao-Yunzai
git clone --depth=1 https://gitee.com/yoimiya-kokomi/miao-plugin.git ./plugins/miao-plugin/
```
## 新版目录
2.安装[pnpm](https://pnpm.io/zh/installation) ,已安装的可以跳过
- 核心源码
```
# 使用npmjs.org安装
npm install pnpm -g
src/core
# 指定国内源npmmirror.com安装
npm --registry=https://registry.npmmirror.com install pnpm -g
```
- 接口板块
3.安装依赖
src/mts
```
# 直接安装
pnpm install -P
- 工具类
# 如依赖安装缓慢或失败可尝试更换国内npm源后再执行install命令
pnpm config set registry https://registry.npmmirror.com
pnpm install -P
```
src/utils
4.运行(首次运行按提示输入登录)
## 环境补充
```
node app
```
## 常见问题
### puppeteer 相关问题
linux环境其他环境请自行探索
```sh
puppeteer Chromium 启动中...
Error: Failed to launch the browser process!
```
1. 先检查node版本是否大于14 (不大于14请去升级版本)
```sh
node -v
```
2. 如果大于14 则可能是缺失一些库 请安装这些 (点击代码块右上角直接复制,如果报错可以尝试 sudo)
### 依赖库
### Centos
```sh
yum install pango.x86_64 libXcomposite.x86_64 libXcursor.x86_64 libXdamage.x86_64 libXext.x86_64 libXi.x86_64 libXtst.x86_64 cups-libs.x86_64 libXScrnSaver.x86_64 libXrandr.x86_64 GConf2.x86_64 alsa-lib.x86_64 atk.x86_64 gtk3.x86_64 -y
```
### 乱码字体解决办法centos安装不了请换源
- 字体
```sh
yum groupinstall fonts -y
```
### centos7 监听事件错误 "CXXABI_1.3.8" not found 解决办法
下载 [libstdc++.so.6.0.29.zip](https://baiyin1314.lanzouq.com/i8Nr21ig8hyf) 将 **解压缩后** 的文件放在/usr/lib64/中
```
- libstdc
下载 [libstdc++.so.6.0.29.zip](https://baiyin1314.lanzouq.com/i8Nr21ig8hyf)
**解压缩后** 的文件放在/usr/lib64/中
```sh
cd /usr/lib64/
sudo mv libstdc++.so.6 libstdc++.so.6.bak
sudo ln -s libstdc++.so.6.0.29 libstdc++.so.6
```
# Unknown file ".ts"
node >= 20.0.0
```ts
ts-node alemon.config.ts
```
更改为
```ts
node --no-warnings=ExperimentalWarning --loader ts-node/esm alemon.config.ts
```
## 致谢

View File

@ -1,21 +1,15 @@
{
"name": "miao-yunzai",
"version": "3.1.3",
"version": "4.0.0-rc.0",
"author": "Yoimiya-Kokomi, Le-niao",
"description": "QQ group Bot",
"main": "app.js",
"description": "QQ Group Bot",
"main": "src/index.ts",
"type": "module",
"scripts": {
"app": "node .",
"dev": "node . dev",
"login": "node . login",
"web": "node ./lib/tools/web.js",
"test": "node ./lib/tools/test.js",
"start": "pm2 start ./config/pm2/pm2.json",
"stop": "pm2 stop ./config/pm2/pm2.json",
"restart": "pm2 restart ./config/pm2/pm2.json",
"log": "node ./lib/tools/log.js",
"ksr": "node ./lib/tools/ksr.js"
"app": "ts-node app.js",
"dev": "ts-node app.js dev",
"login": "ts-node app.js login",
"format": "prettier --write ."
},
"dependencies": {
"art-template": "^4.13.2",
@ -37,7 +31,11 @@
"redis": "^4.6.13",
"sequelize": "^6.37.1",
"sqlite3": "5.1.6",
"yaml": "^2.4.1"
"yaml": "^2.4.1",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"express": "^4.19.2",
"express-art-template": "^1.0.1"
},
"devDependencies": {
"eslint": "^8.57.0",
@ -45,8 +43,20 @@
"eslint-plugin-import": "^2.29.1",
"eslint-plugin-n": "^16.6.2",
"eslint-plugin-promise": "^6.1.1",
"express": "^4.19.2",
"express-art-template": "^1.0.1"
"@rollup/plugin-alias": "^5.1.0",
"@rollup/plugin-multi-entry": "^6.0.0",
"@rollup/plugin-terser": "^0.4.4",
"@rollup/plugin-typescript": "^11.1.3",
"@types/react-dom": "^18.2.22",
"@types/lodash": "^4.14.200",
"@types/node": "^20.8.5",
"@types/redis": "^4.0.11",
"@types/ws": "^8.5.7",
"nodemon": "^3.0.1",
"rollup": "^4.16.4",
"ts-node": "^10.9.1",
"typescript": "^5.0.4",
"prettier": "^3.0.3"
},
"imports": {
"#miao": "./plugins/miao-plugin/components/index.js",

63
src/core/functional.ts Normal file
View File

@ -0,0 +1,63 @@
import { MessageCallBackType } from './types.js'
import plugin from '../../lib/plugins/plugin.js'
// 插件super默认值
export const PluginSuperDefine = {
name: 'group-app',
dsc: 'group-dsc',
event: 'message',
priority: 9999
}
// 消息
export class Messages {
count = 0
rule: {
reg: RegExp
fnc: string
}[] = []
response(reg: RegExp, fnc: MessageCallBackType) {
this.count++
const propName = `prop_${this.count}`
this[propName] = fnc
this.rule.push({
reg,
fnc: propName
})
}
get ok() {
// eslint-disable-next-line @typescript-eslint/no-this-alias
const App = this
class Children extends plugin {
constructor() {
super({
...PluginSuperDefine,
rule: App.rule
})
for (const key of App.rule) {
if (App[key.fnc] instanceof Function) {
this[key.fnc] = App[key.fnc].bind(App)
}
}
}
}
return Children
}
}
/**
*
*/
export class Events {
count = 0
data: {
[key: string]: typeof plugin
} = {}
use(val: typeof plugin) {
this.count++
this.data[this.count] = val
}
get ok() {
return this.data
}
}

4
src/core/index.ts Normal file
View File

@ -0,0 +1,4 @@
import plugin from '../../lib/plugins/plugin.js'
export { plugin }
export * from './functional.js'
export * from './types.js'

1
src/core/local.js Normal file
View File

@ -0,0 +1 @@
export * from "#miao"

214
src/core/plugin.ts Normal file
View File

@ -0,0 +1,214 @@
import { Common } from './local.js'
import { EventType } from './types.js'
const stateArr = {}
const SymbolTimeout = Symbol('Timeout')
const SymbolResolve = Symbol('Resolve')
export default class plugin {
name = 'your-plugin'
dsc = '无'
rule: {
reg?: RegExp | string
fnc: string
event?: string
log?: boolean
permission?: string
}[] = []
event = 'message'
priority = 9999
task = null
namespace = null
handler = null
e: EventType
/**
* @param name
* @param dsc
* @param handler handler配置
* @param handler.key handler支持的事件key
* @param handler.fn handler的处理func
* @param namespace namespacehandler时建议设置
* @param event message
* @param priority
* @param rule
* @param rule.reg
* @param rule.fnc
* @param rule.event message
* @param rule.log false时不显示执行日志
* @param rule.permission master,owner,admin,all
* @param task
* @param task.name
* @param task.cron cron表达式
* @param task.fnc
* @param task.log false时不显示执行日志
*/
constructor({
name,
dsc,
handler,
namespace,
event,
priority = 5000,
task,
rule
}: {
name?: typeof this.name
dsc?: typeof this.dsc
namespace?: typeof this.namespace
priority?: typeof this.priority
handler?: typeof this.handler
event?: typeof this.event
task?: typeof this.task
rule?: typeof this.rule
}) {
name && (this.name = name)
dsc && (this.dsc = dsc)
event && (this.event = event)
priority && (this.priority = priority)
/** 插件名称 */
this.name = name
/** 插件描述 */
this.dsc = dsc
/** 监听事件默认message https://oicqjs.github.io/oicq/#events */
this.event = event
/** 优先级 */
this.priority = priority
/** 定时任务,可以是数组 */
this.task = {
/** 任务名 */
name: '',
/** 任务方法名 */
fnc: task.fnc || '',
/** 任务cron表达式 */
cron: task.cron || ''
}
/** 命令规则 */
this.rule = rule
if (handler) {
this.handler = handler
this.namespace = namespace || ''
}
}
/**
* @param msg
* @param quote
* @param data.recallMsg 0-1200
* @param data.at at用户
*/
reply(msg = '', quote = false, data = {}) {
if (!this.e?.reply || !msg) return false
return this.e.reply(msg, quote, data)
}
/**
* ******
* tudo
*
* *****
*/
group_id: number
groupId: number
user_id: number
userId: number
/**
*
* @param isGroup
* @returns
*/
conKey(isGroup = false) {
if (isGroup) {
return `${this.name}.${this.group_id || this.groupId || this.e.group_id}`
} else {
return `${this.name}.${this.user_id || this.userId || this.e.user_id}`
}
}
/**
* @param type
* @param isGroup
* @param time
* @param timeout
*/
setContext(
type: string,
isGroup = false,
time = 120,
timeout = '操作超时已取消'
) {
const key = this.conKey(isGroup)
if (!stateArr[key]) stateArr[key] = {}
stateArr[key][type] = this.e
if (time)
stateArr[key][type][SymbolTimeout] = setTimeout(() => {
if (stateArr[key][type]) {
const resolve = stateArr[key][type][SymbolResolve]
delete stateArr[key][type]
resolve ? resolve(false) : this.reply(timeout, true)
}
}, time * 1000)
return stateArr[key][type]
}
/**
*
* @param type
* @param isGroup
* @returns
*/
getContext(type: string, isGroup?: boolean) {
if (type) return stateArr[this.conKey(isGroup)]?.[type]
return stateArr[this.conKey(isGroup)]
}
/**
*
* @param type
* @param isGroup
*/
finish(type:string, isGroup?: boolean) {
const key = this.conKey(isGroup)
if (stateArr[key]?.[type]) {
clearTimeout(stateArr[key][type][SymbolTimeout])
delete stateArr[key][type]
}
}
/**
*
* @param args
* @returns
*/
awaitContext(...args) {
return new Promise(
resolve =>
(this.setContext('resolveContext', ...args)[SymbolResolve] = resolve)
)
}
/**
*
* @param context
*/
resolveContext(context) {
this.finish('resolveContext')
context[SymbolResolve](this.e)
}
/**
*
* @param plugin
* @param tpl
* @param data
* @param cfg
* @returns
*/
async renderImg(plugin, tpl, data, cfg) {
return Common.render(plugin, tpl, data, { ...cfg, e: this.e })
}
}

18
src/core/types.ts Normal file
View File

@ -0,0 +1,18 @@
import { type GroupMessage } from 'icqq'
// 机器人事件类型
export interface EventType extends GroupMessage {
isMaster: boolean
group: {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
recallMsg: (...arg) => any
}
msg: string
// eslint-disable-next-line @typescript-eslint/no-explicit-any
reply: (...arg) => Promise<any>
}
// 函数式回调类型
export type MessageCallBackType = (
e: EventType
) => Promise<boolean | undefined | void>

3
src/index.ts Normal file
View File

@ -0,0 +1,3 @@
export * from './core/index.js'
export * from './mys/index.js'
export * from './utils/index.js'

1
src/mys/index.ts Normal file
View File

@ -0,0 +1 @@
export {}

1
src/utils/index.ts Normal file
View File

@ -0,0 +1 @@
export {}

24
tsconfig.json Normal file
View File

@ -0,0 +1,24 @@
{
"compilerOptions": {
"target": "ESNext",
"module": "ESNext",
"noImplicitAny": false,
"esModuleInterop": true,
"moduleResolution": "node",
"removeComments": true,
"preserveConstEnums": true,
"ignoreDeprecations": "5.0",
"jsx": "react",
"allowJs": false,
"suppressImplicitAnyIndexErrors": true,
"typeRoots": ["node_modules/@types"]
},
"ts-node": {
"esm": true,
"transpileOnly": true,
"experimentalSpecifierResolution": "node"
},
"include": ["plugins", "lib","src"],
"exclude": ["node_modules"]
}