mirror of
https://github.com/zhamao-robot/zhamao-framework.git
synced 2026-07-20 23:25:35 +08:00
Compare commits
28 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3f286c057b | ||
|
|
a94746b9fb | ||
|
|
f726be554a | ||
|
|
ac54459ec8 | ||
|
|
b4cef11a55 | ||
|
|
169a751e0f | ||
|
|
e1983d6dd8 | ||
|
|
52f01446b5 | ||
|
|
fa699ac5e0 | ||
|
|
0e952c39f5 | ||
|
|
16b885da54 | ||
|
|
7e35596f9b | ||
|
|
3c41d17802 | ||
|
|
4ba5e3fc57 | ||
|
|
920680ee3d | ||
|
|
c632977ca1 | ||
|
|
94834c6625 | ||
|
|
e3ffeec782 | ||
|
|
438a204751 | ||
|
|
b0331f6346 | ||
|
|
0cbb81788e | ||
|
|
7173da9ad2 | ||
|
|
302e2c60da | ||
|
|
87e637f759 | ||
|
|
1d2aaf3c99 | ||
|
|
676527205f | ||
|
|
b560246efb | ||
|
|
c1f720a0b3 |
30
README.md
30
README.md
@@ -2,14 +2,14 @@
|
|||||||
|
|
||||||
[]()
|
[]()
|
||||||
[](https://github.com/zhamao-robot/zhamao-framework/blob/master/LICENSE)
|
[](https://github.com/zhamao-robot/zhamao-framework/blob/master/LICENSE)
|
||||||
[]()
|
[]()
|
||||||
|
|
||||||
[](https://github.com/zhamao-robot/zhamao-framework/search?q=goto)
|
[](https://github.com/zhamao-robot/zhamao-framework/search?q=stupid)
|
||||||
[](https://github.com/zhamao-robot/zhamao-framework/search?q=TODO)
|
[](https://github.com/zhamao-robot/zhamao-framework/search?q=TODO)
|
||||||
|
|
||||||
一个异步、多平台兼容的 **聊天机器人** 框架。
|
一个异步、多平台兼容的 **聊天机器人** 框架。
|
||||||
|
|
||||||
<img src="./resources/images/logo.png" height = "200" alt="炸毛框架" align=center/>
|
<img src="https://avatars0.githubusercontent.com/u/48620312" height = "200" alt="炸毛框架" align=center/>
|
||||||
|
|
||||||
## 简介
|
## 简介
|
||||||
zhamao-framework 是一个基于 酷Q 的 PHP Swoole 的机器人框架,它会对 QQ 机器人收到的消息进行解析处理,并以模块化的形式进行开发,来完成机器人的自然语言对话等功能。
|
zhamao-framework 是一个基于 酷Q 的 PHP Swoole 的机器人框架,它会对 QQ 机器人收到的消息进行解析处理,并以模块化的形式进行开发,来完成机器人的自然语言对话等功能。
|
||||||
@@ -18,6 +18,9 @@ zhamao-framework 是一个基于 酷Q 的 PHP Swoole 的机器人框架,它会
|
|||||||
|
|
||||||
除了起到解析消息的作用,炸毛框架 还提供了完整的 WebSocket + HTTP 服务器,你还能用此框架构建出高性能的 API 接口服务器。
|
除了起到解析消息的作用,炸毛框架 还提供了完整的 WebSocket + HTTP 服务器,你还能用此框架构建出高性能的 API 接口服务器。
|
||||||
|
|
||||||
|
## 开始
|
||||||
|
你可以使用 GitHub 的 `Use This Template` 功能快速将本项目克隆到你的公开或私有仓库,也可以从 `release` 中下载本项目的最新版本到本地私有开发。
|
||||||
|
|
||||||
## 文档
|
## 文档
|
||||||
本项目文档正在努力编写中。
|
本项目文档正在努力编写中。
|
||||||
|
|
||||||
@@ -32,15 +35,32 @@ Pages:[https://framework.zhamao.xin/](https://framework.zhamao.xin/)
|
|||||||
- 常驻内存,全局缓存变量随处使用
|
- 常驻内存,全局缓存变量随处使用
|
||||||
- 自带 MySQL 查询器、数据库连接池等数据库连接方案
|
- 自带 MySQL 查询器、数据库连接池等数据库连接方案
|
||||||
- 自带 HTTP 服务器、WebSocket 服务器可复用,可以构建属于自己的 HTTP API 接口
|
- 自带 HTTP 服务器、WebSocket 服务器可复用,可以构建属于自己的 HTTP API 接口
|
||||||
|
- 静态文件服务器
|
||||||
|
|
||||||
## 炸毛特色模块
|
## 炸毛特色模块
|
||||||
|
|
||||||
| 模块名称 | 说明 | 模块地址 |
|
| 模块名称 | 说明 | 模块地址 |
|
||||||
| ------------------ | -------------------------------- | ------------------------------------------------------------ |
|
| ------------------ | -------------------------------- | ------------------------------------------------------------ |
|
||||||
| 微信公众号兼容模块 | 为框架提供微信公众号订阅号兼容层 | [zhamao-wechat-patch](https://github.com/zhamao-robot/zhamao-wechat-patch) |
|
| 微信公众号兼容模块 | 为框架提供微信公众号订阅号兼容层 | [zhamao-wechat-patch](https://github.com/zhamao-robot/zhamao-wechat-patch) |
|
||||||
|
| 通用模块 | 图片上传和下载模块 | [zhamao-general-tools](https://github.com/zhamao-robot/zhamao-general-tools) |
|
||||||
|
|
||||||
|
## 计划开发内容
|
||||||
|
- [ ] WebSocket测试脚本(客户端)
|
||||||
|
- [X] Session 和中间层管理模块
|
||||||
|
- [ ] 支持本地和远程两种方式的定时器(计划任务)
|
||||||
|
- [X] 常驻服务脚本
|
||||||
|
- [ ] 一些常用的通用 API 例如经济(用户积分、亲密度等)的模块
|
||||||
|
- [ ] 图灵机器人/腾讯AI 聊天模块
|
||||||
|
- [ ] 分词模块(可能会放弃计划,因为目前好用的分词都是其他语言的)
|
||||||
|
- [ ] HTTP 过滤器、Auth 模块、完整的 MVC 兼容(可能会放弃计划,因为框架主打机器人开发)
|
||||||
|
- [ ] Redis 连接池或开箱即用的相应功能内置
|
||||||
|
- [ ] 2.0 版本抛弃 `ModBase` 继承结构,完全使用上下文代替
|
||||||
|
- [X] 更好的 Logger,稳定和漂亮的控制台输出
|
||||||
|
- [ ] 日志服务
|
||||||
|
- [ ] 模块支持 Phar 打包(可能会比较靠后支持)
|
||||||
|
- [ ] 兼容面向过程的模块编写方案(可能会比较靠后支持)
|
||||||
|
- [ ] 完整的单元测试(如果有需求则尽快开发)
|
||||||
|
- [X] 静态文件服务器
|
||||||
|
|
||||||
## 从 cqbot-swoole 升级
|
## 从 cqbot-swoole 升级
|
||||||
目前新的框架采用了全新的注解机制,所以旧版的框架上写的模块到新框架需要重新编写。当然为了减少工作量,新的框架也最大限度地保留了旧版框架编写的风格,一般情况下根据新版框架的文档仅需修改少量地方即可完成重写。
|
目前新的框架采用了全新的注解机制,所以旧版的框架上写的模块到新框架需要重新编写。当然为了减少工作量,新的框架也最大限度地保留了旧版框架编写的风格,一般情况下根据新版框架的文档仅需修改少量地方即可完成重写。
|
||||||
|
|||||||
13
SECURITY.md
Normal file
13
SECURITY.md
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
# Security Policy
|
||||||
|
|
||||||
|
## Supported Versions
|
||||||
|
|
||||||
|
| Version | Supported |
|
||||||
|
| ------- | ------------------ |
|
||||||
|
| 1.2 | :white_check_mark: |
|
||||||
|
| 1.1.x | :x: |
|
||||||
|
| 1.0.x | :x: |
|
||||||
|
|
||||||
|
## Reporting a Vulnerability
|
||||||
|
|
||||||
|
If you find a bug which is safety related, you should post a new issue named **Security Issue**, and I will check it as soon as possible.
|
||||||
@@ -37,8 +37,15 @@ switch ($argv[1] ?? '') {
|
|||||||
}
|
}
|
||||||
$loader = new FrameworkLoader($argv);
|
$loader = new FrameworkLoader($argv);
|
||||||
break;
|
break;
|
||||||
|
case '--help':
|
||||||
|
case '-h':
|
||||||
|
echo "\nUsage: ".$argv[0]." [OPTION]\n";
|
||||||
|
echo "\nzhamao-framework start script, provides several startup arguments.";
|
||||||
|
echo "\n\n -h, --help\t\tShow this help menu";
|
||||||
|
echo "\n framework, server\tstart main framework, this is default option\n\n";
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
echo "Unknown option \"{$argv[1]}\"!\n";
|
echo "Unknown option \"{$argv[1]}\"!\n\"--help\" for more information\n";
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
26
bin/systemd
Normal file
26
bin/systemd
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
#!/usr/bin/env php
|
||||||
|
<?php /** @since 1.2 */
|
||||||
|
switch ($argv[1] ?? '') {
|
||||||
|
case '--generate':
|
||||||
|
generate();
|
||||||
|
break;
|
||||||
|
case '--help':
|
||||||
|
case '-h':
|
||||||
|
default:
|
||||||
|
echo "\nUsage: " . $argv[0] . " [OPTION]\n";
|
||||||
|
echo "\nzhamao-framework systemd generator.";
|
||||||
|
echo "\n\n -h, --help\t\tShow this help menu";
|
||||||
|
echo "\n --generate\tGenerate a systemd service file\n\n";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
function generate() {
|
||||||
|
$s = "[Unit]\nDescription=zhamao-framework Daemon\nAfter=rc-local.service\n\n[Service]\nType=simple";
|
||||||
|
$s .= "\nUser=" . exec("whoami");
|
||||||
|
$s .= "\nGroup=" . exec("groups | awk '{print $1}'");
|
||||||
|
$s .= "\nWorkingDirectory=" . getcwd();
|
||||||
|
$s .= "\nExecStart=" . getcwd() . "/bin/start server --disable-console-input";
|
||||||
|
$s .= "\nRestart=always\n\n[Install]\nWantedBy=multi-user.target\n";
|
||||||
|
file_put_contents(getcwd() . "/resources/zhamao.service", $s);
|
||||||
|
echo "File successfully generated. Path: " . getcwd() . "/resources/zhamao.service\n";
|
||||||
|
}
|
||||||
@@ -3,7 +3,7 @@
|
|||||||
"description": "high-performance intelligent assistant",
|
"description": "high-performance intelligent assistant",
|
||||||
"minimum-stability": "stable",
|
"minimum-stability": "stable",
|
||||||
"license": "proprietary",
|
"license": "proprietary",
|
||||||
"version": "1.0",
|
"version": "1.2.0",
|
||||||
"authors": [
|
"authors": [
|
||||||
{
|
{
|
||||||
"name": "whale",
|
"name": "whale",
|
||||||
@@ -18,10 +18,11 @@
|
|||||||
"swoole/ide-helper": "@dev",
|
"swoole/ide-helper": "@dev",
|
||||||
"ext-mbstring": "*",
|
"ext-mbstring": "*",
|
||||||
"swlib/saber": "^1.0",
|
"swlib/saber": "^1.0",
|
||||||
"doctrine/annotations": "^1.8",
|
"doctrine/annotations": "<1.10.2",
|
||||||
"ext-json": "*",
|
"ext-json": "*",
|
||||||
"ext-posix": "*",
|
"ext-posix": "*",
|
||||||
"ext-ctype": "*"
|
"ext-ctype": "*",
|
||||||
|
"ext-pcntl": "*"
|
||||||
},
|
},
|
||||||
"repositories": {
|
"repositories": {
|
||||||
"packagist": {
|
"packagist": {
|
||||||
|
|||||||
141
config/file_header.json
Normal file
141
config/file_header.json
Normal file
@@ -0,0 +1,141 @@
|
|||||||
|
{
|
||||||
|
"ai": "application/postscript",
|
||||||
|
"aif": "audio/x-aiff",
|
||||||
|
"aifc": "audio/x-aiff",
|
||||||
|
"aiff": "audio/x-aiff",
|
||||||
|
"asc": "text/plain",
|
||||||
|
"au": "audio/basic",
|
||||||
|
"avi": "video/x-msvideo",
|
||||||
|
"bcpio": "application/x-bcpio",
|
||||||
|
"bin": "application/octet-stream",
|
||||||
|
"bmp": "image/bmp",
|
||||||
|
"cdf": "application/x-netcdf",
|
||||||
|
"class": "application/octet-stream",
|
||||||
|
"cpio": "application/x-cpio",
|
||||||
|
"cpt": "application/mac-compactpro",
|
||||||
|
"csh": "application/x-csh",
|
||||||
|
"css": "text/css",
|
||||||
|
"dcr": "application/x-director",
|
||||||
|
"dir": "application/x-director",
|
||||||
|
"djv": "image/vnd.djvu",
|
||||||
|
"djvu": "image/vnd.djvu",
|
||||||
|
"dll": "application/octet-stream",
|
||||||
|
"dms": "application/octet-stream",
|
||||||
|
"doc": "application/msword",
|
||||||
|
"dvi": "application/x-dvi",
|
||||||
|
"dxr": "application/x-director",
|
||||||
|
"eps": "application/postscript",
|
||||||
|
"etx": "text/x-setext",
|
||||||
|
"exe": "application/octet-stream",
|
||||||
|
"ez": "application/andrew-inset",
|
||||||
|
"gif": "image/gif",
|
||||||
|
"gtar": "application/x-gtar",
|
||||||
|
"hdf": "application/x-hdf",
|
||||||
|
"hqx": "application/mac-binhex40",
|
||||||
|
"htm": "text/html",
|
||||||
|
"html": "text/html",
|
||||||
|
"ice": "x-conference/x-cooltalk",
|
||||||
|
"ief": "image/ief",
|
||||||
|
"iges": "model/iges",
|
||||||
|
"igs": "model/iges",
|
||||||
|
"jpe": "image/jpeg",
|
||||||
|
"jpeg": "image/jpeg",
|
||||||
|
"jpg": "image/jpeg",
|
||||||
|
"js": "application/x-javascript",
|
||||||
|
"kar": "audio/midi",
|
||||||
|
"latex": "application/x-latex",
|
||||||
|
"lha": "application/octet-stream",
|
||||||
|
"lzh": "application/octet-stream",
|
||||||
|
"m3u": "audio/x-mpegurl",
|
||||||
|
"man": "application/x-troff-man",
|
||||||
|
"me": "application/x-troff-me",
|
||||||
|
"mesh": "model/mesh",
|
||||||
|
"mid": "audio/midi",
|
||||||
|
"midi": "audio/midi",
|
||||||
|
"mif": "application/vnd.mif",
|
||||||
|
"mov": "video/quicktime",
|
||||||
|
"movie": "video/x-sgi-movie",
|
||||||
|
"mp2": "audio/mpeg",
|
||||||
|
"mp3": "audio/mpeg",
|
||||||
|
"mpe": "video/mpeg",
|
||||||
|
"mpeg": "video/mpeg",
|
||||||
|
"mpg": "video/mpeg",
|
||||||
|
"mpga": "audio/mpeg",
|
||||||
|
"ms": "application/x-troff-ms",
|
||||||
|
"msh": "model/mesh",
|
||||||
|
"mxu": "video/vnd.mpegurl",
|
||||||
|
"nc": "application/x-netcdf",
|
||||||
|
"oda": "application/oda",
|
||||||
|
"pbm": "image/x-portable-bitmap",
|
||||||
|
"pdb": "chemical/x-pdb",
|
||||||
|
"pdf": "application/pdf",
|
||||||
|
"pgm": "image/x-portable-graymap",
|
||||||
|
"pgn": "application/x-chess-pgn",
|
||||||
|
"png": "image/png",
|
||||||
|
"pnm": "image/x-portable-anymap",
|
||||||
|
"ppm": "image/x-portable-pixmap",
|
||||||
|
"ppt": "application/vnd.ms-powerpoint",
|
||||||
|
"ps": "application/postscript",
|
||||||
|
"qt": "video/quicktime",
|
||||||
|
"ra": "audio/x-realaudio",
|
||||||
|
"ram": "audio/x-pn-realaudio",
|
||||||
|
"ras": "image/x-cmu-raster",
|
||||||
|
"rgb": "image/x-rgb",
|
||||||
|
"rm": "audio/x-pn-realaudio",
|
||||||
|
"roff": "application/x-troff",
|
||||||
|
"rpm": "audio/x-pn-realaudio-plugin",
|
||||||
|
"rtf": "text/rtf",
|
||||||
|
"rtx": "text/richtext",
|
||||||
|
"sgm": "text/sgml",
|
||||||
|
"sgml": "text/sgml",
|
||||||
|
"sh": "application/x-sh",
|
||||||
|
"shar": "application/x-shar",
|
||||||
|
"silo": "model/mesh",
|
||||||
|
"sit": "application/x-stuffit",
|
||||||
|
"skd": "application/x-koan",
|
||||||
|
"skm": "application/x-koan",
|
||||||
|
"skp": "application/x-koan",
|
||||||
|
"skt": "application/x-koan",
|
||||||
|
"smi": "application/smil",
|
||||||
|
"smil": "application/smil",
|
||||||
|
"snd": "audio/basic",
|
||||||
|
"so": "application/octet-stream",
|
||||||
|
"spl": "application/x-futuresplash",
|
||||||
|
"src": "application/x-wais-source",
|
||||||
|
"sv4cpio": "application/x-sv4cpio",
|
||||||
|
"sv4crc": "application/x-sv4crc",
|
||||||
|
"swf": "application/x-shockwave-flash",
|
||||||
|
"t": "application/x-troff",
|
||||||
|
"tar": "application/x-tar",
|
||||||
|
"tcl": "application/x-tcl",
|
||||||
|
"tex": "application/x-tex",
|
||||||
|
"texi": "application/x-texinfo",
|
||||||
|
"texinfo": "application/x-texinfo",
|
||||||
|
"tif": "image/tiff",
|
||||||
|
"tiff": "image/tiff",
|
||||||
|
"tr": "application/x-troff",
|
||||||
|
"tsv": "text/tab-separated-values",
|
||||||
|
"txt": "text/plain",
|
||||||
|
"ustar": "application/x-ustar",
|
||||||
|
"vcd": "application/x-cdlink",
|
||||||
|
"vrml": "model/vrml",
|
||||||
|
"wav": "audio/x-wav",
|
||||||
|
"wbmp": "image/vnd.wap.wbmp",
|
||||||
|
"wbxml": "application/vnd.wap.wbxml",
|
||||||
|
"wml": "text/vnd.wap.wml",
|
||||||
|
"wmlc": "application/vnd.wap.wmlc",
|
||||||
|
"wmls": "text/vnd.wap.wmlscript",
|
||||||
|
"wmlsc": "application/vnd.wap.wmlscriptc",
|
||||||
|
"wrl": "model/vrml",
|
||||||
|
"xbm": "image/x-xbitmap",
|
||||||
|
"xht": "application/xhtml+xml",
|
||||||
|
"xhtml": "application/xhtml+xml",
|
||||||
|
"xls": "application/vnd.ms-excel",
|
||||||
|
"xml": "text/xml",
|
||||||
|
"xpm": "image/x-xpixmap",
|
||||||
|
"xsl": "text/xml",
|
||||||
|
"xwd": "image/x-xwindowdump",
|
||||||
|
"xyz": "chemical/x-xyz",
|
||||||
|
"zip": "application/zip",
|
||||||
|
"": "application/octet-stream"
|
||||||
|
}
|
||||||
@@ -58,10 +58,22 @@ $config['init_atomics'] = [
|
|||||||
'out_count' => 0, //消息发送(调用send_*_msg的统计数量)
|
'out_count' => 0, //消息发送(调用send_*_msg的统计数量)
|
||||||
'reload_time' => 0, //调用reload功能统计数量
|
'reload_time' => 0, //调用reload功能统计数量
|
||||||
'wait_msg_id' => 0, //协程挂起id自增
|
'wait_msg_id' => 0, //协程挂起id自增
|
||||||
'info_level' => 0, //终端显示的log等级
|
'info_level' => 2, //终端显示的log等级
|
||||||
];
|
];
|
||||||
|
|
||||||
/** 自动保存的缓存保存时间(秒) */
|
/** 自动保存的缓存保存时间(秒) */
|
||||||
$config['auto_save_interval'] = 900;
|
$config['auto_save_interval'] = 900;
|
||||||
|
|
||||||
return $config;
|
/** 上下文接口类 implemented from ContextInterface */
|
||||||
|
$config['context_class'] = \ZM\Context\Context::class;
|
||||||
|
|
||||||
|
/** 静态文件访问 */
|
||||||
|
$config['static_file_server'] = [
|
||||||
|
'status' => false,
|
||||||
|
'document_root' => WORKING_DIR . '/resources/html',
|
||||||
|
'document_index' => [
|
||||||
|
'index.html'
|
||||||
|
]
|
||||||
|
];
|
||||||
|
|
||||||
|
return $config;
|
||||||
|
|||||||
10
resources/html/static.html
Normal file
10
resources/html/static.html
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<title>This is example</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<h1>Hello zhamao!</h1>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
@@ -14,8 +14,7 @@ use Exception;
|
|||||||
|
|
||||||
class Console
|
class Console
|
||||||
{
|
{
|
||||||
static function setColor($string, $color = "")
|
static function setColor($string, $color = "") {
|
||||||
{
|
|
||||||
switch ($color) {
|
switch ($color) {
|
||||||
case "red":
|
case "red":
|
||||||
return "\x1b[38;5;203m" . $string . "\x1b[m";
|
return "\x1b[38;5;203m" . $string . "\x1b[m";
|
||||||
@@ -25,6 +24,7 @@ class Console
|
|||||||
return "\x1b[38;5;227m" . $string . "\x1b[m";
|
return "\x1b[38;5;227m" . $string . "\x1b[m";
|
||||||
case "blue":
|
case "blue":
|
||||||
return "\033[34m" . $string . "\033[0m";
|
return "\033[34m" . $string . "\033[0m";
|
||||||
|
case "pink": // I really don't know what stupid color it is.
|
||||||
case "lightpurple":
|
case "lightpurple":
|
||||||
return "\x1b[38;5;207m" . $string . "\x1b[m";
|
return "\x1b[38;5;207m" . $string . "\x1b[m";
|
||||||
case "lightblue":
|
case "lightblue":
|
||||||
@@ -33,8 +33,6 @@ class Console
|
|||||||
return "\x1b[38;5;214m" . $string . "\x1b[m";
|
return "\x1b[38;5;214m" . $string . "\x1b[m";
|
||||||
case "gray":
|
case "gray":
|
||||||
return "\x1b[38;5;59m" . $string . "\x1b[m";
|
return "\x1b[38;5;59m" . $string . "\x1b[m";
|
||||||
case "pink":
|
|
||||||
return "\x1b[38;5;207m" . $string . "\x1b[m";
|
|
||||||
case "lightlightblue":
|
case "lightlightblue":
|
||||||
return "\x1b[38;5;63m" . $string . "\x1b[m";
|
return "\x1b[38;5;63m" . $string . "\x1b[m";
|
||||||
default:
|
default:
|
||||||
@@ -42,9 +40,8 @@ class Console
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static function error($obj, $head = null)
|
static function error($obj, $head = null) {
|
||||||
{
|
if ($head === null) $head = date("[H:i:s] ") . "[E] ";
|
||||||
if ($head === null) $head = date("[H:i:s ") . "ERROR] ";
|
|
||||||
if (ZMBuf::$info_level !== null && in_array(ZMBuf::$info_level->get(), [1, 2])) {
|
if (ZMBuf::$info_level !== null && in_array(ZMBuf::$info_level->get(), [1, 2])) {
|
||||||
$trace = debug_backtrace()[1] ?? ['file' => '', 'function' => ''];
|
$trace = debug_backtrace()[1] ?? ['file' => '', 'function' => ''];
|
||||||
$trace = "[" . basename($trace["file"], ".php") . ":" . $trace["function"] . "] ";
|
$trace = "[" . basename($trace["file"], ".php") . ":" . $trace["function"] . "] ";
|
||||||
@@ -58,90 +55,80 @@ class Console
|
|||||||
echo(self::setColor($head . ($trace ?? "") . $obj, "red") . "\n");
|
echo(self::setColor($head . ($trace ?? "") . $obj, "red") . "\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
static function warning($obj, $head = null)
|
static function warning($obj, $head = null) {
|
||||||
{
|
if ($head === null) $head = date("[H:i:s]") . " [W] ";
|
||||||
if ($head === null) $head = date("[H:i:s") . " WARN] ";
|
|
||||||
if (ZMBuf::$info_level !== null && in_array(ZMBuf::$info_level->get(), [1, 2])) {
|
if (ZMBuf::$info_level !== null && in_array(ZMBuf::$info_level->get(), [1, 2])) {
|
||||||
$trace = debug_backtrace()[1] ?? ['file' => '', 'function' => ''];
|
$trace = debug_backtrace()[1] ?? ['file' => '', 'function' => ''];
|
||||||
$trace = "[" . basename($trace["file"], ".php") . ":" . $trace["function"] . "] ";
|
$trace = "[" . basename($trace["file"], ".php") . ":" . $trace["function"] . "] ";
|
||||||
}
|
}
|
||||||
if (!is_string($obj)) {
|
if(ZMBuf::$atomics["info_level"]->get() >= 1) {
|
||||||
if (isset($trace)) {
|
if (!is_string($obj)) {
|
||||||
var_dump($obj);
|
if (isset($trace)) {
|
||||||
return;
|
var_dump($obj);
|
||||||
} else $obj = "{Object}";
|
return;
|
||||||
|
} else $obj = "{Object}";
|
||||||
|
}
|
||||||
|
echo(self::setColor($head . ($trace ?? "") . $obj, "yellow") . "\n");
|
||||||
}
|
}
|
||||||
echo(self::setColor($head . ($trace ?? "") . $obj, "yellow") . "\n");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static function info($obj, $head = null)
|
static function info($obj, $head = null) {
|
||||||
{
|
if ($head === null) $head = date("[H:i:s] ") . "[I] ";
|
||||||
if ($head === null) $head = date("[H:i:s ") . "INFO] ";
|
|
||||||
if (ZMBuf::$info_level !== null && in_array(ZMBuf::$info_level->get(), [1, 2])) {
|
if (ZMBuf::$info_level !== null && in_array(ZMBuf::$info_level->get(), [1, 2])) {
|
||||||
$trace = debug_backtrace()[1] ?? ['file' => '', 'function' => ''];
|
$trace = debug_backtrace()[1] ?? ['file' => '', 'function' => ''];
|
||||||
$trace = "[" . basename($trace["file"], ".php") . ":" . $trace["function"] . "] ";
|
$trace = "[" . basename($trace["file"], ".php") . ":" . $trace["function"] . "] ";
|
||||||
}
|
}
|
||||||
if (!is_string($obj)) {
|
if(ZMBuf::$atomics["info_level"]->get() >= 2) {
|
||||||
if (isset($trace)) {
|
if (!is_string($obj)) {
|
||||||
var_dump($obj);
|
if (isset($trace)) {
|
||||||
return;
|
var_dump($obj);
|
||||||
} else $obj = "{Object}";
|
return;
|
||||||
|
} else $obj = "{Object}";
|
||||||
|
}
|
||||||
|
echo(self::setColor($head . ($trace ?? "") . $obj, "lightblue") . "\n");
|
||||||
}
|
}
|
||||||
echo(self::setColor($head . ($trace ?? "") . $obj, "lightblue") . "\n");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static function log($obj, $color = "")
|
static function success($obj, $head = null) {
|
||||||
{
|
if ($head === null) $head = date("[H:i:s] ") . "[S] ";
|
||||||
|
if (ZMBuf::$info_level !== null && in_array(ZMBuf::$info_level->get(), [1, 2])) {
|
||||||
|
$trace = debug_backtrace()[1] ?? ['file' => '', 'function' => ''];
|
||||||
|
$trace = "[" . basename($trace["file"], ".php") . ":" . $trace["function"] . "] ";
|
||||||
|
}
|
||||||
|
if(ZMBuf::$atomics["info_level"]->get() >= 2) {
|
||||||
|
if (!is_string($obj)) {
|
||||||
|
if (isset($trace)) {
|
||||||
|
var_dump($obj);
|
||||||
|
return;
|
||||||
|
} else $obj = "{Object}";
|
||||||
|
}
|
||||||
|
echo(self::setColor($head . ($trace ?? "") . $obj, "green") . "\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static function verbose($obj, $head = null) {
|
||||||
|
if($head === null) $head = date("[H:i:s] ") . "[V] ";
|
||||||
|
if(ZMBuf::$atomics["info_level"]->get() >= 3) {
|
||||||
|
if (!is_string($obj)) {
|
||||||
|
if (isset($trace)) {
|
||||||
|
var_dump($obj);
|
||||||
|
return;
|
||||||
|
} else $obj = "{Object}";
|
||||||
|
}
|
||||||
|
echo(self::setColor($head . ($trace ?? "") . $obj, "blue") . "\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static function debug($obj) {
|
||||||
|
debug($obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
static function log($obj, $color = "") {
|
||||||
if (!is_string($obj)) var_dump($obj);
|
if (!is_string($obj)) var_dump($obj);
|
||||||
else echo(self::setColor($obj, $color) . "\n");
|
else echo(self::setColor($obj, $color) . "\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
static function msg($obj, $self_id = "")
|
static function stackTrace() {
|
||||||
{
|
|
||||||
if (ZMBuf::$info_level !== null && ZMBuf::$info_level->get() == 3) {
|
|
||||||
if (!isset($obj["post_type"])) {
|
|
||||||
switch ($obj["action"]) {
|
|
||||||
case "send_private_msg":
|
|
||||||
$msg = Console::setColor(date("H:i:s ") . "[" . (ZMBuf::globals("robot_alias")[$self_id] ?? "Null") . "] ", "lightlightblue");
|
|
||||||
$msg .= Console::setColor("私聊↑(" . $obj["params"]["user_id"] . ")", "lightlightblue");
|
|
||||||
$msg .= Console::setColor(" > ", "gray");
|
|
||||||
$msg .= $obj["params"]["message"];
|
|
||||||
Console::log($msg);
|
|
||||||
break;
|
|
||||||
case "send_group_msg":
|
|
||||||
//TODO: 写新的控制台消息(API消息处理)
|
|
||||||
Console::log(Console::setColor("[" . date("H:i:s") . " GROUP:" . $obj["params"]["group_id"] . "] ", "blue") . Console::setColor($obj["params"]["user_id"] ?? "", "yellow") . Console::setColor(" > ", "gray") . ($obj["params"]["message"] ?? ""));
|
|
||||||
break;
|
|
||||||
case "send_discuss_msg":
|
|
||||||
Console::log(Console::setColor("[" . date("H:i:s") . " DISCUSS:" . $obj["params"]["discuss_id"] . "] ", "blue") . Console::setColor($obj["params"]["user_id"] ?? "", "yellow") . Console::setColor(" > ", "gray") . ($obj["params"]["message"] ?? ""));
|
|
||||||
break;
|
|
||||||
case "send_msg":
|
|
||||||
$obj["action"] = "send_" . $obj["message_type"] . "_msg";
|
|
||||||
self::msg($obj);
|
|
||||||
break;
|
|
||||||
case "send_wechat_msg":
|
|
||||||
Console::log(Console::setColor("[" . date("H:i:s") . " WECHAT] ", "blue") . Console::setColor($obj["params"]["user_id"] ?? "", "yellow") . Console::setColor(" > ", "gray") . ($obj["params"]["message"] ?? ""));
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if ($obj["post_type"] == "message") {
|
|
||||||
switch ($obj["message_type"]) {
|
|
||||||
case "group":
|
|
||||||
//
|
|
||||||
//TODO: 写新的控制台消息(event处理)
|
|
||||||
case "private":
|
|
||||||
case "discuss":
|
|
||||||
case "wechat":
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static function stackTrace()
|
|
||||||
{
|
|
||||||
$log = "Stack trace:\n";
|
$log = "Stack trace:\n";
|
||||||
$trace = debug_backtrace();
|
$trace = debug_backtrace();
|
||||||
//array_shift($trace);
|
//array_shift($trace);
|
||||||
@@ -165,8 +152,7 @@ class Console
|
|||||||
echo $log;
|
echo $log;
|
||||||
}
|
}
|
||||||
|
|
||||||
static function listenConsole()
|
static function listenConsole() {
|
||||||
{
|
|
||||||
if (in_array('--disable-console-input', FrameworkLoader::$argv)) {
|
if (in_array('--disable-console-input', FrameworkLoader::$argv)) {
|
||||||
self::info("ConsoleCommand disabled.");
|
self::info("ConsoleCommand disabled.");
|
||||||
return;
|
return;
|
||||||
@@ -183,10 +169,18 @@ class Console
|
|||||||
* @param string $cmd
|
* @param string $cmd
|
||||||
* @return bool
|
* @return bool
|
||||||
*/
|
*/
|
||||||
private static function executeCommand(string $cmd)
|
private static function executeCommand(string $cmd) {
|
||||||
{
|
|
||||||
$it = explodeMsg($cmd);
|
$it = explodeMsg($cmd);
|
||||||
switch ($it[0] ?? '') {
|
switch ($it[0] ?? '') {
|
||||||
|
case 'logtest':
|
||||||
|
Console::log(date("[H:i:s]"). " [L] This is normal msg. (0)");
|
||||||
|
Console::error("This is error msg. (0)");
|
||||||
|
Console::warning("This is warning msg. (1)");
|
||||||
|
Console::info("This is info msg. (2)");
|
||||||
|
Console::success("This is success msg. (2)");
|
||||||
|
Console::verbose("This is verbose msg. (3)");
|
||||||
|
Console::debug("This is debug msg. (4)");
|
||||||
|
return true;
|
||||||
case 'call':
|
case 'call':
|
||||||
$class_name = $it[1];
|
$class_name = $it[1];
|
||||||
$function_name = $it[2];
|
$function_name = $it[2];
|
||||||
@@ -203,6 +197,9 @@ class Console
|
|||||||
case 'echo':
|
case 'echo':
|
||||||
Console::info($it[1]);
|
Console::info($it[1]);
|
||||||
return true;
|
return true;
|
||||||
|
case 'color':
|
||||||
|
Console::log($it[2], $it[1]);
|
||||||
|
return true;
|
||||||
case 'stop':
|
case 'stop':
|
||||||
ZMUtil::stop();
|
ZMUtil::stop();
|
||||||
return false;
|
return false;
|
||||||
@@ -218,9 +215,8 @@ class Console
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function withSleep(string $string, int $int)
|
public static function withSleep(string $string, int $int) {
|
||||||
{
|
|
||||||
self::info($string);
|
self::info($string);
|
||||||
sleep($int);
|
sleep($int);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,10 @@
|
|||||||
|
|
||||||
namespace Framework;
|
namespace Framework;
|
||||||
|
|
||||||
|
use Co;
|
||||||
|
use Swoole\Http\Request;
|
||||||
|
use Swoole\Runtime;
|
||||||
|
use Swoole\WebSocket\Frame;
|
||||||
use ZM\Event\EventHandler;
|
use ZM\Event\EventHandler;
|
||||||
use Exception;
|
use Exception;
|
||||||
use Swoole\WebSocket\Server;
|
use Swoole\WebSocket\Server;
|
||||||
@@ -31,13 +35,15 @@ class FrameworkLoader
|
|||||||
/** @var Server */
|
/** @var Server */
|
||||||
private $server;
|
private $server;
|
||||||
|
|
||||||
public function __construct($args = []) {
|
public function __construct($args = [])
|
||||||
|
{
|
||||||
if (self::$instance !== null) die("Cannot run two FrameworkLoader in one process!");
|
if (self::$instance !== null) die("Cannot run two FrameworkLoader in one process!");
|
||||||
self::$instance = $this;
|
self::$instance = $this;
|
||||||
self::$argv = $args;
|
self::$argv = $args;
|
||||||
|
|
||||||
chdir(__DIR__ . '/../..');
|
chdir(__DIR__ . '/../..');
|
||||||
define('WORKING_DIR', getcwd());
|
define('WORKING_DIR', getcwd());
|
||||||
|
Runtime::enableCoroutine();
|
||||||
$this->requireGlobalFunctions();
|
$this->requireGlobalFunctions();
|
||||||
$this->registerAutoloader('classLoader');
|
$this->registerAutoloader('classLoader');
|
||||||
self::$settings = new GlobalConfig();
|
self::$settings = new GlobalConfig();
|
||||||
@@ -50,17 +56,45 @@ class FrameworkLoader
|
|||||||
try {
|
try {
|
||||||
$this->server = new Server(self::$settings->get("host"), self::$settings->get("port"));
|
$this->server = new Server(self::$settings->get("host"), self::$settings->get("port"));
|
||||||
if (in_array("--remote-shell", $args)) RemoteShell::listen($this->server, "127.0.0.1");
|
if (in_array("--remote-shell", $args)) RemoteShell::listen($this->server, "127.0.0.1");
|
||||||
$this->server->set(self::$settings->get("swoole"));
|
$settings = self::$settings->get("swoole");
|
||||||
|
if (in_array("--daemon", $args)) {
|
||||||
|
$settings["daemonize"] = 1;
|
||||||
|
Console::log("已启用守护进程,输出重定向到 " . $settings["log_file"]);
|
||||||
|
self::$argv[] = "--disable-console-input";
|
||||||
|
}
|
||||||
|
$this->server->set($settings);
|
||||||
$this->server->on("WorkerStart", [$this, "onWorkerStart"]);
|
$this->server->on("WorkerStart", [$this, "onWorkerStart"]);
|
||||||
$this->server->on("message", function ($server, $frame) { EventHandler::callSwooleEvent("message", $server, $frame); });
|
$this->server->on("message", function ($server, Frame $frame) {
|
||||||
|
Console::debug("Calling Swoole \"message\" event from fd=" . $frame->fd);
|
||||||
|
EventHandler::callSwooleEvent("message", $server, $frame);
|
||||||
|
});
|
||||||
$this->server->on("request", function ($request, $response) {
|
$this->server->on("request", function ($request, $response) {
|
||||||
$response = new Response($response);
|
$response = new Response($response);
|
||||||
|
Console::debug("Receiving Http request event, cid=" . Co::getCid());
|
||||||
EventHandler::callSwooleEvent("request", $request, $response);
|
EventHandler::callSwooleEvent("request", $request, $response);
|
||||||
});
|
});
|
||||||
$this->server->on("open", function ($server, $request) { EventHandler::callSwooleEvent("open", $server, $request); });
|
$this->server->on("open", function ($server, Request $request) {
|
||||||
$this->server->on("close", function ($server, $fd) { EventHandler::callSwooleEvent("close", $server, $fd); });
|
Console::debug("Calling Swoole \"open\" event from fd=" . $request->fd);
|
||||||
|
EventHandler::callSwooleEvent("open", $server, $request);
|
||||||
|
});
|
||||||
|
$this->server->on("close", function ($server, $fd) {
|
||||||
|
Console::debug("Calling Swoole \"close\" event from fd=" . $fd);
|
||||||
|
EventHandler::callSwooleEvent("close", $server, $fd);
|
||||||
|
});
|
||||||
ZMBuf::initAtomic();
|
ZMBuf::initAtomic();
|
||||||
Console::info("host: ".self::$settings->get("host").", port: ".self::$settings->get("port"));
|
if (in_array("--log-error", $args)) ZMBuf::$atomics["info_level"]->set(0);
|
||||||
|
if (in_array("--log-warning", $args)) ZMBuf::$atomics["info_level"]->set(1);
|
||||||
|
if (in_array("--log-info", $args)) ZMBuf::$atomics["info_level"]->set(2);
|
||||||
|
if (in_array("--log-verbose", $args)) ZMBuf::$atomics["info_level"]->set(3);
|
||||||
|
if (in_array("--log-debug", $args)) ZMBuf::$atomics["info_level"]->set(4);
|
||||||
|
Console::log(
|
||||||
|
"host: " . self::$settings->get("host") .
|
||||||
|
", port: " . self::$settings->get("port") .
|
||||||
|
", log_level: " . ZMBuf::$atomics["info_level"]->get() .
|
||||||
|
", version: " . json_decode(file_get_contents(WORKING_DIR . "/composer.json"), true)["version"]
|
||||||
|
);
|
||||||
|
global $motd;
|
||||||
|
echo $motd . PHP_EOL;
|
||||||
$this->server->start();
|
$this->server->start();
|
||||||
} catch (Exception $e) {
|
} catch (Exception $e) {
|
||||||
Console::error("Framework初始化出现错误,请检查!");
|
Console::error("Framework初始化出现错误,请检查!");
|
||||||
@@ -69,15 +103,18 @@ class FrameworkLoader
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private function requireGlobalFunctions() {
|
private function requireGlobalFunctions()
|
||||||
|
{
|
||||||
require __DIR__ . '/global_functions.php';
|
require __DIR__ . '/global_functions.php';
|
||||||
}
|
}
|
||||||
|
|
||||||
private function registerAutoloader(string $string) {
|
private function registerAutoloader(string $string)
|
||||||
|
{
|
||||||
if (!spl_autoload_register($string)) die("Failed to register autoloader named \"$string\" !");
|
if (!spl_autoload_register($string)) die("Failed to register autoloader named \"$string\" !");
|
||||||
}
|
}
|
||||||
|
|
||||||
private function defineProperties() {
|
private function defineProperties()
|
||||||
|
{
|
||||||
define("ZM_START_TIME", microtime(true));
|
define("ZM_START_TIME", microtime(true));
|
||||||
define("ZM_DATA", self::$settings->get("zm_data"));
|
define("ZM_DATA", self::$settings->get("zm_data"));
|
||||||
define("CONFIG_DIR", self::$settings->get("config_dir"));
|
define("CONFIG_DIR", self::$settings->get("config_dir"));
|
||||||
@@ -91,7 +128,8 @@ class FrameworkLoader
|
|||||||
define("ZM_MATCH_SECOND", 3);
|
define("ZM_MATCH_SECOND", 3);
|
||||||
}
|
}
|
||||||
|
|
||||||
private function selfCheck() {
|
private function selfCheck()
|
||||||
|
{
|
||||||
if (!extension_loaded("swoole")) die("Can not find swoole extension.\n");
|
if (!extension_loaded("swoole")) die("Can not find swoole extension.\n");
|
||||||
//if (!extension_loaded("gd")) die("Can not find gd extension.\n");
|
//if (!extension_loaded("gd")) die("Can not find gd extension.\n");
|
||||||
if (!extension_loaded("sockets")) die("Can not find sockets extension.\n");
|
if (!extension_loaded("sockets")) die("Can not find sockets extension.\n");
|
||||||
@@ -103,9 +141,21 @@ class FrameworkLoader
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function onWorkerStart(\Swoole\Server $server, $worker_id) {
|
public function onWorkerStart(\Swoole\Server $server, $worker_id)
|
||||||
|
{
|
||||||
self::$instance = $this;
|
self::$instance = $this;
|
||||||
self::$run_time = microtime(true);
|
self::$run_time = microtime(true);
|
||||||
EventHandler::callSwooleEvent("WorkerStart", $server, $worker_id);
|
EventHandler::callSwooleEvent("WorkerStart", $server, $worker_id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
global $motd;
|
||||||
|
$motd = <<<EOL
|
||||||
|
______
|
||||||
|
|__ / |__ __ _ _ __ ___ __ _ ___
|
||||||
|
/ /| '_ \ / _` | '_ ` _ \ / _` |/ _ \
|
||||||
|
/ /_| | | | (_| | | | | | | (_| | (_) |
|
||||||
|
/____|_| |_|\__,_|_| |_| |_|\__,_|\___/
|
||||||
|
|
||||||
|
EOL;
|
||||||
|
|
||||||
|
|||||||
@@ -18,8 +18,7 @@ class GlobalConfig
|
|||||||
public $success = false;
|
public $success = false;
|
||||||
|
|
||||||
public function __construct() {
|
public function __construct() {
|
||||||
/** @noinspection PhpIncludeInspection */
|
include_once WORKING_DIR . '/config/global.php';
|
||||||
include_once WORKING_DIR.'/config/global.php';
|
|
||||||
global $config;
|
global $config;
|
||||||
$this->success = true;
|
$this->success = true;
|
||||||
$this->config = $config;
|
$this->config = $config;
|
||||||
@@ -30,4 +29,8 @@ class GlobalConfig
|
|||||||
if ($r === null) return null;
|
if ($r === null) return null;
|
||||||
return $r;
|
return $r;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
public function getAll() {
|
||||||
|
return $this->config;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,10 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
|
|
||||||
namespace Framework;
|
|
||||||
|
|
||||||
|
|
||||||
class InfoLevel
|
|
||||||
{
|
|
||||||
const INFO = 0;
|
|
||||||
}
|
|
||||||
@@ -1,18 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
|
|
||||||
namespace Framework;
|
|
||||||
|
|
||||||
|
|
||||||
use Swoole\Coroutine\System;
|
|
||||||
|
|
||||||
class Logger
|
|
||||||
{
|
|
||||||
private static function getTimeFormat($type = "I") {
|
|
||||||
return "[" . date("Y-m-d H:i:s") . "]\t[" . $type . "]\t";
|
|
||||||
}
|
|
||||||
|
|
||||||
public static function writeSwooleLog($log) {
|
|
||||||
System::writeFile(CRASH_DIR . "swoole_error.log", "\n" . self::getTimeFormat() . $log, FILE_APPEND);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -11,7 +11,6 @@ namespace Framework;
|
|||||||
use Swoole\Atomic;
|
use Swoole\Atomic;
|
||||||
use swoole_atomic;
|
use swoole_atomic;
|
||||||
use ZM\connection\WSConnection;
|
use ZM\connection\WSConnection;
|
||||||
use ZM\Utils\Scheduler;
|
|
||||||
use ZM\Utils\SQLPool;
|
use ZM\Utils\SQLPool;
|
||||||
|
|
||||||
class ZMBuf
|
class ZMBuf
|
||||||
@@ -22,8 +21,7 @@ class ZMBuf
|
|||||||
/** @var WSConnection[] */
|
/** @var WSConnection[] */
|
||||||
static $connect = [];//储存连接实例的数组
|
static $connect = [];//储存连接实例的数组
|
||||||
//Scheduler计划任务连接实例,只可以在单worker_num时使用
|
//Scheduler计划任务连接实例,只可以在单worker_num时使用
|
||||||
/** @var Scheduler|null */
|
static $scheduler = null; //This is stupid warning...
|
||||||
static $scheduler = null;
|
|
||||||
|
|
||||||
//Swoole SQL连接池,多进程下每个进程一个连接池
|
//Swoole SQL连接池,多进程下每个进程一个连接池
|
||||||
/** @var SQLPool */
|
/** @var SQLPool */
|
||||||
@@ -52,6 +50,7 @@ class ZMBuf
|
|||||||
public static $req_mapping = [];
|
public static $req_mapping = [];
|
||||||
public static $config = [];
|
public static $config = [];
|
||||||
public static $context = [];
|
public static $context = [];
|
||||||
|
public static $instance = [];
|
||||||
|
|
||||||
static function get($name, $default = null) {
|
static function get($name, $default = null) {
|
||||||
return self::$cache[$name] ?? $default;
|
return self::$cache[$name] ?? $default;
|
||||||
@@ -99,13 +98,14 @@ class ZMBuf
|
|||||||
}
|
}
|
||||||
|
|
||||||
static function config($config_name) {
|
static function config($config_name) {
|
||||||
return self::$config ?? null;
|
return self::$config[$config_name] ?? null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function resetCache() {
|
public static function resetCache() {
|
||||||
self::$cache = [];
|
self::$cache = [];
|
||||||
self::$connect = [];
|
self::$connect = [];
|
||||||
self::$time_nlp = null;
|
self::$time_nlp = null;
|
||||||
|
self::$instance = [];
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
|
use Framework\Console;
|
||||||
use Framework\ZMBuf;
|
use Framework\ZMBuf;
|
||||||
use ZM\Utils\Context;
|
use ZM\Context\ContextInterface;
|
||||||
|
|
||||||
function classLoader($p) {
|
function classLoader($p) {
|
||||||
$filepath = getClassPath($p);
|
$filepath = getClassPath($p);
|
||||||
@@ -11,7 +12,7 @@ function classLoader($p) {
|
|||||||
try {
|
try {
|
||||||
require_once $filepath;
|
require_once $filepath;
|
||||||
} catch (Exception $e) {
|
} catch (Exception $e) {
|
||||||
echo "Error when finding class: ".$p.PHP_EOL;
|
echo "Error when finding class: " . $p . PHP_EOL;
|
||||||
die;
|
die;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -148,18 +149,33 @@ function matchArgs($pattern, $context) {
|
|||||||
} else return false;
|
} else return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
function set_coroutine_params($array){
|
function set_coroutine_params($array) {
|
||||||
$cid = Co::getCid();
|
$cid = Co::getCid();
|
||||||
if($cid == -1) die("Cannot set coroutine params at none coroutine mode.");
|
if ($cid == -1) die("Cannot set coroutine params at none coroutine mode.");
|
||||||
ZMBuf::$context[$cid] = $array;
|
ZMBuf::$context[$cid] = $array;
|
||||||
foreach(ZMBuf::$context as $c => $v) {
|
foreach (ZMBuf::$context as $c => $v) {
|
||||||
if(!Co::exists($c)) unset(ZMBuf::$context[$c]);
|
if (!Co::exists($c)) unset(ZMBuf::$context[$c]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function context(){
|
/**
|
||||||
|
* @return ContextInterface|null
|
||||||
|
*/
|
||||||
|
function context() {
|
||||||
$cid = Co::getCid();
|
$cid = Co::getCid();
|
||||||
if(isset(ZMBuf::$context[$cid])) {
|
$c_class = ZMBuf::globals("context_class");
|
||||||
return new Context(ZMBuf::$context[$cid], $cid);
|
if (isset(ZMBuf::$context[$cid])) {
|
||||||
} else return null;
|
return new $c_class(ZMBuf::$context[$cid], $cid);
|
||||||
|
} else {
|
||||||
|
while (($pcid = Co::getPcid($cid)) !== -1) {
|
||||||
|
if (isset(ZMBuf::$context[$cid])) return new $c_class(ZMBuf::$context[$cid], $cid);
|
||||||
|
else $cid = $pcid;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function debug($msg) {
|
||||||
|
if (ZMBuf::$atomics["info_level"]->get() >= 4)
|
||||||
|
Console::log(date("[H:i:s] ") . "[D] " . $msg, 'gray');
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,10 +15,12 @@ use ZM\ModBase;
|
|||||||
/**
|
/**
|
||||||
* Class Hello
|
* Class Hello
|
||||||
* @package Module\Example
|
* @package Module\Example
|
||||||
|
* @since 1.0
|
||||||
*/
|
*/
|
||||||
class Hello extends ModBase
|
class Hello extends ModBase
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
|
* 在机器人连接后向终端输出信息
|
||||||
* @SwooleEventAt("open",rule="connectType:qq")
|
* @SwooleEventAt("open",rule="connectType:qq")
|
||||||
* @param $conn
|
* @param $conn
|
||||||
*/
|
*/
|
||||||
@@ -26,6 +28,7 @@ class Hello extends ModBase
|
|||||||
Console::info("机器人 ".$conn->getQQ()." 已连接!");
|
Console::info("机器人 ".$conn->getQQ()." 已连接!");
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
|
* 向机器人发送"你好",即可回复这句话
|
||||||
* @CQCommand("你好")
|
* @CQCommand("你好")
|
||||||
*/
|
*/
|
||||||
public function hello(){
|
public function hello(){
|
||||||
@@ -33,14 +36,16 @@ class Hello extends ModBase
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @RequestMapping("/test/ping")
|
* 中间件测试的一个示例函数
|
||||||
|
* @RequestMapping("/httpTimer")
|
||||||
* @Middleware("timer")
|
* @Middleware("timer")
|
||||||
*/
|
*/
|
||||||
public function pong(){
|
public function timer(){
|
||||||
return "pong";
|
return "This page is used as testing TimerMiddleware! Do not use it in production.";
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* 框架会默认关闭未知的WebSocket链接,因为这个绑定的事件,你可以根据你自己的需求进行修改
|
||||||
* @SwooleEventAt(type="open",rule="connectType:unknown")
|
* @SwooleEventAt(type="open",rule="connectType:unknown")
|
||||||
*/
|
*/
|
||||||
public function closeUnknownConn(){
|
public function closeUnknownConn(){
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ class CQ
|
|||||||
if (is_numeric($qq) || $qq === "all") {
|
if (is_numeric($qq) || $qq === "all") {
|
||||||
return "[CQ:at,qq=" . $qq . "]";
|
return "[CQ:at,qq=" . $qq . "]";
|
||||||
}
|
}
|
||||||
Console::error("传入的QQ号码($qq)错误!");
|
Console::warning("传入的QQ号码($qq)错误!");
|
||||||
return " ";
|
return " ";
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -31,7 +31,7 @@ class CQ
|
|||||||
if (is_numeric($id)) {
|
if (is_numeric($id)) {
|
||||||
return "[CQ:face,id=" . $id . "]";
|
return "[CQ:face,id=" . $id . "]";
|
||||||
}
|
}
|
||||||
Console::error("传入的face id($id)错误!");
|
Console::warning("传入的face id($id)错误!");
|
||||||
return " ";
|
return " ";
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -44,7 +44,7 @@ class CQ
|
|||||||
if (is_numeric($id)) {
|
if (is_numeric($id)) {
|
||||||
return "[CQ:emoji,id=" . $id . "]";
|
return "[CQ:emoji,id=" . $id . "]";
|
||||||
}
|
}
|
||||||
Console::error("传入的emoji id($id)错误!");
|
Console::warning("传入的emoji id($id)错误!");
|
||||||
return " ";
|
return " ";
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -66,7 +66,7 @@ class CQ
|
|||||||
if (is_numeric($id)) {
|
if (is_numeric($id)) {
|
||||||
return "[CQ:sface,id=" . $id . "]";
|
return "[CQ:sface,id=" . $id . "]";
|
||||||
}
|
}
|
||||||
Console::error("传入的sface id($id)错误!");
|
Console::warning("传入的sface id($id)错误!");
|
||||||
return " ";
|
return " ";
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -151,7 +151,7 @@ class CQ
|
|||||||
return "[CQ:music,type=$type,id=$id_or_url]";
|
return "[CQ:music,type=$type,id=$id_or_url]";
|
||||||
case "custom":
|
case "custom":
|
||||||
if ($title === null || $audio === null) {
|
if ($title === null || $audio === null) {
|
||||||
Console::error("传入CQ码实例的标题和音频链接不能为空!");
|
Console::warning("传入CQ码实例的标题和音频链接不能为空!");
|
||||||
return " ";
|
return " ";
|
||||||
}
|
}
|
||||||
if ($content === null) $c = "";
|
if ($content === null) $c = "";
|
||||||
@@ -160,7 +160,7 @@ class CQ
|
|||||||
else $i = ",image=" . $image;
|
else $i = ",image=" . $image;
|
||||||
return "[CQ:music,type=custom,url=" . $id_or_url . ",audio=" . $audio . ",title=" . $title . $c . $i . "]";
|
return "[CQ:music,type=custom,url=" . $id_or_url . ",audio=" . $audio . ",title=" . $title . $c . $i . "]";
|
||||||
default:
|
default:
|
||||||
Console::error("传入的music type($type)错误!");
|
Console::warning("传入的music type($type)错误!");
|
||||||
return " ";
|
return " ";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -217,4 +217,4 @@ class CQ
|
|||||||
}
|
}
|
||||||
return $msg;
|
return $msg;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ use Framework\ZMBuf;
|
|||||||
use ZM\Connection\ConnectionManager;
|
use ZM\Connection\ConnectionManager;
|
||||||
use ZM\Connection\CQConnection;
|
use ZM\Connection\CQConnection;
|
||||||
use ZM\Connection\WSConnection;
|
use ZM\Connection\WSConnection;
|
||||||
|
use ZM\Utils\ZMRobot;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @method static send_private_msg($self_id, $params, $function = null)
|
* @method static send_private_msg($self_id, $params, $function = null)
|
||||||
@@ -68,19 +69,26 @@ use ZM\Connection\WSConnection;
|
|||||||
*/
|
*/
|
||||||
class CQAPI
|
class CQAPI
|
||||||
{
|
{
|
||||||
public static function quick_reply(WSConnection $conn, $data, $msg, $yield = null) {
|
public static function quick_reply(CQConnection $conn, $data, $msg, $yield = null) {
|
||||||
switch ($data["message_type"]) {
|
switch ($data["message_type"]) {
|
||||||
case "group":
|
case "group":
|
||||||
return self::send_group_msg($conn, ["group_id" => $data["group_id"], "message" => $msg], $yield);
|
return (new ZMRobot($conn))->setCallback($yield)->sendGroupMsg($data["group_id"], $msg);
|
||||||
case "private":
|
case "private":
|
||||||
return self::send_private_msg($conn, ["user_id" => $data["user_id"], "message" => $msg], $yield);
|
return (new ZMRobot($conn))->setCallback($yield)->sendPrivateMsg($data["user_id"], $msg);
|
||||||
case "discuss":
|
case "discuss":
|
||||||
return self::send_discuss_msg($conn, ["discuss_id" => $data["discuss_id"], "message" => $msg], $yield);
|
return (new ZMRobot($conn))->setCallback($yield)->sendDiscussMsg($data["discuss_id"], $msg);
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param $name
|
||||||
|
* @param $arg
|
||||||
|
* @return bool
|
||||||
|
* @deprecated
|
||||||
|
*/
|
||||||
public static function __callStatic($name, $arg) {
|
public static function __callStatic($name, $arg) {
|
||||||
|
trigger_error("This dynamic CQAPI calling method will be removed after 2.0 version.", E_USER_DEPRECATED);
|
||||||
$all = self::getSupportedAPIs();
|
$all = self::getSupportedAPIs();
|
||||||
$find = null;
|
$find = null;
|
||||||
if (in_array($name, $all)) $find = $name;
|
if (in_array($name, $all)) $find = $name;
|
||||||
@@ -93,12 +101,12 @@ class CQAPI
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ($find === null) {
|
if ($find === null) {
|
||||||
Console::error("Unknown API " . $name);
|
Console::warning("Unknown API " . $name);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
$reply = ["action" => $find];
|
$reply = ["action" => $find];
|
||||||
if (!is_array($arg[1])) {
|
if (!is_array($arg[1])) {
|
||||||
Console::error("Error when parsing params. Please make sure your params is an array.");
|
Console::warning("Error when parsing params. Please make sure your params is an array.");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if ($arg[1] != []) {
|
if ($arg[1] != []) {
|
||||||
@@ -107,7 +115,7 @@ class CQAPI
|
|||||||
if (!($arg[0] instanceof CQConnection)) {
|
if (!($arg[0] instanceof CQConnection)) {
|
||||||
$robot = ConnectionManager::getByType("qq", ["self_id" => $arg[0]]);
|
$robot = ConnectionManager::getByType("qq", ["self_id" => $arg[0]]);
|
||||||
if ($robot == []) {
|
if ($robot == []) {
|
||||||
Console::error("发送错误,机器人连接不存在!");
|
Console::warning("发送错误,机器人连接不存在!");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
$arg[0] = $robot[0];
|
$arg[0] = $robot[0];
|
||||||
@@ -195,7 +203,7 @@ class CQAPI
|
|||||||
* @param |null $function
|
* @param |null $function
|
||||||
* @return bool
|
* @return bool
|
||||||
*/
|
*/
|
||||||
private static function processAPI($connection, $reply, $function = null) {
|
public static function processAPI($connection, $reply, $function = null) {
|
||||||
$api_id = ZMBuf::$atomics["wait_msg_id"]->get();
|
$api_id = ZMBuf::$atomics["wait_msg_id"]->get();
|
||||||
$reply["echo"] = $api_id;
|
$reply["echo"] = $api_id;
|
||||||
ZMBuf::$atomics["wait_msg_id"]->add(1);
|
ZMBuf::$atomics["wait_msg_id"]->add(1);
|
||||||
@@ -222,7 +230,7 @@ class CQAPI
|
|||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
if ($connection->push(json_encode($reply))) {
|
if ($connection->push(json_encode($reply))) {
|
||||||
Console::msg($reply, $connection->getQQ());
|
//Console::msg($reply, $connection->getQQ());
|
||||||
ZMBuf::$atomics["out_count"]->add(1);
|
ZMBuf::$atomics["out_count"]->add(1);
|
||||||
if ($function === true) {
|
if ($function === true) {
|
||||||
Co::suspend();
|
Co::suspend();
|
||||||
@@ -232,6 +240,7 @@ class CQAPI
|
|||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
|
Console::warning("CQAPI send failed, websocket push error.");
|
||||||
$response = [
|
$response = [
|
||||||
"status" => "failed",
|
"status" => "failed",
|
||||||
"retcode" => 999,
|
"retcode" => 999,
|
||||||
@@ -246,4 +255,4 @@ class CQAPI
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,33 +3,23 @@
|
|||||||
|
|
||||||
namespace ZM\Annotation;
|
namespace ZM\Annotation;
|
||||||
|
|
||||||
use Doctrine\Common\Annotations\AnnotationException;
|
use Doctrine\Common\Annotations\{AnnotationException, AnnotationReader};
|
||||||
use Doctrine\Common\Annotations\AnnotationReader;
|
use Framework\{Console, ZMBuf};
|
||||||
use Framework\Console;
|
|
||||||
use Framework\ZMBuf;
|
|
||||||
use ReflectionClass;
|
use ReflectionClass;
|
||||||
use ReflectionException;
|
use ReflectionException;
|
||||||
use ReflectionMethod;
|
use ReflectionMethod;
|
||||||
use ZM\Annotation\CQ\{CQAfter, CQBefore, CQCommand, CQMessage, CQMetaEvent, CQNotice, CQRequest};
|
use ZM\Annotation\CQ\{CQAfter, CQBefore, CQCommand, CQMessage, CQMetaEvent, CQNotice, CQRequest};
|
||||||
use ZM\Annotation\Http\After;
|
use ZM\Annotation\Http\{After, Before, Controller, HandleException, Middleware, MiddlewareClass, RequestMapping};
|
||||||
use ZM\Annotation\Http\Before;
|
use Swoole\Timer;
|
||||||
use ZM\Annotation\Http\Controller;
|
|
||||||
use ZM\Annotation\Http\HandleException;
|
|
||||||
use ZM\Annotation\Http\Middleware;
|
|
||||||
use ZM\Annotation\Http\MiddlewareClass;
|
|
||||||
use ZM\Annotation\Http\RequestMapping;
|
|
||||||
use ZM\Annotation\Interfaces\CustomAnnotation;
|
use ZM\Annotation\Interfaces\CustomAnnotation;
|
||||||
use ZM\Annotation\Interfaces\Level;
|
use ZM\Annotation\Interfaces\Level;
|
||||||
use ZM\Annotation\Module\Closed;
|
use ZM\Annotation\Module\{Closed, InitBuffer, SaveBuffer};
|
||||||
use ZM\Annotation\Module\InitBuffer;
|
use ZM\Annotation\Swoole\{OnStart, OnTick, SwooleEventAfter, SwooleEventAt};
|
||||||
use ZM\Annotation\Module\SaveBuffer;
|
|
||||||
use ZM\Annotation\Swoole\OnStart;
|
|
||||||
use ZM\Annotation\Swoole\SwooleEventAfter;
|
|
||||||
use ZM\Annotation\Swoole\SwooleEventAt;
|
|
||||||
use ZM\Annotation\Interfaces\Rule;
|
use ZM\Annotation\Interfaces\Rule;
|
||||||
use ZM\Connection\WSConnection;
|
use ZM\Connection\WSConnection;
|
||||||
use ZM\Http\MiddlewareInterface;
|
use ZM\Http\MiddlewareInterface;
|
||||||
use ZM\Utils\DataProvider;
|
use ZM\Utils\DataProvider;
|
||||||
|
use ZM\Utils\ZMUtil;
|
||||||
|
|
||||||
class AnnotationParser
|
class AnnotationParser
|
||||||
{
|
{
|
||||||
@@ -52,17 +42,20 @@ class AnnotationParser
|
|||||||
$class_prefix = '';
|
$class_prefix = '';
|
||||||
$methods = $reflection_class->getMethods(ReflectionMethod::IS_PUBLIC);
|
$methods = $reflection_class->getMethods(ReflectionMethod::IS_PUBLIC);
|
||||||
$class_annotations = $reader->getClassAnnotations($reflection_class);
|
$class_annotations = $reader->getClassAnnotations($reflection_class);
|
||||||
|
$middleware_addon = null;
|
||||||
foreach ($class_annotations as $vs) {
|
foreach ($class_annotations as $vs) {
|
||||||
if ($vs instanceof Closed) {
|
if ($vs instanceof Closed) {
|
||||||
continue 2;
|
continue 2;
|
||||||
} elseif ($vs instanceof Controller) {
|
} elseif ($vs instanceof Controller) {
|
||||||
|
Console::debug("找到 Controller 中间件: ".$vs->class);
|
||||||
$class_prefix = $vs->prefix;
|
$class_prefix = $vs->prefix;
|
||||||
} elseif ($vs instanceof SaveBuffer) {
|
} elseif ($vs instanceof SaveBuffer) {
|
||||||
|
Console::debug("注册自动保存的缓存变量: ".$vs->buf_name." (Dir:".$vs->sub_folder.")");
|
||||||
DataProvider::addSaveBuffer($vs->buf_name, $vs->sub_folder);
|
DataProvider::addSaveBuffer($vs->buf_name, $vs->sub_folder);
|
||||||
} elseif ($vs instanceof InitBuffer) {
|
} elseif ($vs instanceof InitBuffer) {
|
||||||
ZMBuf::set($vs->buf_name, []);
|
ZMBuf::set($vs->buf_name, []);
|
||||||
} elseif ($vs instanceof MiddlewareClass) {
|
} elseif ($vs instanceof MiddlewareClass) {
|
||||||
Console::info("正在注册中间件 ".$vs->class);
|
Console::verbose("正在注册中间件 " . $vs->class);
|
||||||
$result = [
|
$result = [
|
||||||
"class" => "\\" . $reflection_class->getName()
|
"class" => "\\" . $reflection_class->getName()
|
||||||
];
|
];
|
||||||
@@ -87,6 +80,8 @@ class AnnotationParser
|
|||||||
}
|
}
|
||||||
ZMBuf::$events[MiddlewareClass::class][$result["name"]] = $result;
|
ZMBuf::$events[MiddlewareClass::class][$result["name"]] = $result;
|
||||||
continue 2;
|
continue 2;
|
||||||
|
} elseif ($vs instanceof Middleware) {
|
||||||
|
$middleware_addon = $vs;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
foreach ($methods as $vs) {
|
foreach ($methods as $vs) {
|
||||||
@@ -102,14 +97,16 @@ class AnnotationParser
|
|||||||
elseif ($vss instanceof CQRequest) ZMBuf::$events[CQRequest::class][] = $vss;
|
elseif ($vss instanceof CQRequest) ZMBuf::$events[CQRequest::class][] = $vss;
|
||||||
elseif ($vss instanceof CQMetaEvent) ZMBuf::$events[CQMetaEvent::class][] = $vss;
|
elseif ($vss instanceof CQMetaEvent) ZMBuf::$events[CQMetaEvent::class][] = $vss;
|
||||||
elseif ($vss instanceof CQCommand) ZMBuf::$events[CQCommand::class][] = $vss;
|
elseif ($vss instanceof CQCommand) ZMBuf::$events[CQCommand::class][] = $vss;
|
||||||
elseif ($vss instanceof RequestMapping) self::registerRequestMapping($vss, $vs, $reflection_class, $class_prefix);
|
elseif ($vss instanceof RequestMapping) {
|
||||||
elseif ($vss instanceof CustomAnnotation) ZMBuf::$events[get_class($vss)][] = $vss;
|
self::registerRequestMapping($vss, $vs, $reflection_class, $class_prefix);
|
||||||
|
if ($middleware_addon !== null)
|
||||||
|
ZMBuf::$events[MiddlewareInterface::class][$vss->class][$vss->method] = $middleware_addon->middleware;
|
||||||
|
} elseif ($vss instanceof CustomAnnotation) ZMBuf::$events[get_class($vss)][] = $vss;
|
||||||
elseif ($vss instanceof CQBefore) ZMBuf::$events[CQBefore::class][$vss->cq_event][] = $vss;
|
elseif ($vss instanceof CQBefore) ZMBuf::$events[CQBefore::class][$vss->cq_event][] = $vss;
|
||||||
elseif ($vss instanceof CQAfter) ZMBuf::$events[CQAfter::class][$vss->cq_event][] = $vss;
|
elseif ($vss instanceof CQAfter) ZMBuf::$events[CQAfter::class][$vss->cq_event][] = $vss;
|
||||||
elseif ($vss instanceof OnStart) ZMBuf::$events[OnStart::class][] = $vss;
|
elseif ($vss instanceof OnStart) ZMBuf::$events[OnStart::class][] = $vss;
|
||||||
elseif ($vss instanceof Middleware) {
|
elseif ($vss instanceof Middleware) ZMBuf::$events[MiddlewareInterface::class][$vss->class][$vss->method] = $vss->middleware;
|
||||||
ZMBuf::$events[MiddlewareInterface::class][$vss->class][$vss->method] = $vss->middleware;
|
elseif ($vss instanceof OnTick) self::addTimerTick($vss);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -131,6 +128,10 @@ class AnnotationParser
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (ZMBuf::isset("timer_count")) {
|
||||||
|
Console::info("Added " . ZMBuf::get("timer_count") . " timer(s)!");
|
||||||
|
ZMBuf::unsetCache("timer_count");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static function getRuleCallback($rule_str) {
|
private static function getRuleCallback($rule_str) {
|
||||||
@@ -240,9 +241,9 @@ class AnnotationParser
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ($prefix_exp == [] && $route_exp == []) {
|
if ($prefix_exp == [] && $route_exp == []) {
|
||||||
$array[$uid - 1]['method'] = $method->getName();
|
$array[0]['method'] = $method->getName();
|
||||||
$array[$uid - 1]['class'] = $class->getName();
|
$array[0]['class'] = $class->getName();
|
||||||
$array[$uid - 1]['request_method'] = $vss->request_method;
|
$array[0]['request_method'] = $vss->request_method;
|
||||||
ZMBuf::$req_mapping = $array;
|
ZMBuf::$req_mapping = $array;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -314,4 +315,9 @@ class AnnotationParser
|
|||||||
$tree[] = &$items[$item['id']];
|
$tree[] = &$items[$item['id']];
|
||||||
return $tree;
|
return $tree;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static function addTimerTick(?OnTick $vss) {
|
||||||
|
ZMBuf::set("timer_count", ZMBuf::get("timer_count", 0) + 1);
|
||||||
|
Timer::tick($vss->tick_ms, [ZMUtil::getModInstance($vss->class), $vss->method]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ use ZM\Annotation\AnnotationBase;
|
|||||||
* Class Middleware
|
* Class Middleware
|
||||||
* @package ZM\Annotation\Http
|
* @package ZM\Annotation\Http
|
||||||
* @Annotation
|
* @Annotation
|
||||||
* @Target("METHOD")
|
* @Target("ALL")
|
||||||
*/
|
*/
|
||||||
class Middleware extends AnnotationBase
|
class Middleware extends AnnotationBase
|
||||||
{
|
{
|
||||||
@@ -21,4 +21,4 @@ class Middleware extends AnnotationBase
|
|||||||
* @Required()
|
* @Required()
|
||||||
*/
|
*/
|
||||||
public $middleware;
|
public $middleware;
|
||||||
}
|
}
|
||||||
|
|||||||
25
src/ZM/Annotation/Swoole/OnTick.php
Normal file
25
src/ZM/Annotation/Swoole/OnTick.php
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
|
||||||
|
namespace ZM\Annotation\Swoole;
|
||||||
|
|
||||||
|
|
||||||
|
use Doctrine\Common\Annotations\Annotation\Required;
|
||||||
|
use Doctrine\Common\Annotations\Annotation\Target;
|
||||||
|
use ZM\Annotation\AnnotationBase;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class OnTick
|
||||||
|
* @package ZM\Annotation\Swoole
|
||||||
|
* @Annotation
|
||||||
|
* @Target("METHOD")
|
||||||
|
* @since 1.2
|
||||||
|
*/
|
||||||
|
class OnTick extends AnnotationBase
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var int
|
||||||
|
* @Required()
|
||||||
|
*/
|
||||||
|
public $tick_ms;
|
||||||
|
}
|
||||||
@@ -11,7 +11,7 @@ class ConnectionManager
|
|||||||
/**
|
/**
|
||||||
* 通过server的fd获取WSConnection实例化对象
|
* 通过server的fd获取WSConnection实例化对象
|
||||||
* @param int $fd
|
* @param int $fd
|
||||||
* @return WSConnection
|
* @return WSConnection|CQConnection|ProxyConnection
|
||||||
*/
|
*/
|
||||||
public static function get(int $fd) {
|
public static function get(int $fd) {
|
||||||
foreach (ZMBuf::$connect as $v) {
|
foreach (ZMBuf::$connect as $v) {
|
||||||
@@ -23,7 +23,7 @@ class ConnectionManager
|
|||||||
/**
|
/**
|
||||||
* @param string $type
|
* @param string $type
|
||||||
* @param array $option
|
* @param array $option
|
||||||
* @return WSConnection[]
|
* @return WSConnection[]|CQConnection[]
|
||||||
*/
|
*/
|
||||||
public static function getByType(string $type, $option = []) {
|
public static function getByType(string $type, $option = []) {
|
||||||
$conn = [];
|
$conn = [];
|
||||||
@@ -70,4 +70,4 @@ class ConnectionManager
|
|||||||
$classes = getAllClasses(WORKING_DIR . "/src/Custom/Connection/", "Custom\\Connection");
|
$classes = getAllClasses(WORKING_DIR . "/src/Custom/Connection/", "Custom\\Connection");
|
||||||
ZMBuf::$custom_connection_class = $classes;
|
ZMBuf::$custom_connection_class = $classes;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,7 +5,6 @@ namespace ZM\Connection;
|
|||||||
|
|
||||||
|
|
||||||
use Framework\Console;
|
use Framework\Console;
|
||||||
use Framework\Logger;
|
|
||||||
use swoole_websocket_server;
|
use swoole_websocket_server;
|
||||||
|
|
||||||
abstract class WSConnection
|
abstract class WSConnection
|
||||||
@@ -43,10 +42,10 @@ abstract class WSConnection
|
|||||||
}
|
}
|
||||||
if ($this->server->push($this->fd, $data) === false) {
|
if ($this->server->push($this->fd, $data) === false) {
|
||||||
$data = unicode_decode($data);
|
$data = unicode_decode($data);
|
||||||
if ($push_error_record) Logger::writeSwooleLog("API push failed. Data: " . $data);
|
if ($push_error_record) Console::warning("API push failed. Data: " . $data);
|
||||||
Console::error("websocket数据未成功推送,长度:" . strlen($data));
|
Console::warning("websocket数据未成功推送,长度:" . strlen($data));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,15 +1,18 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
|
|
||||||
namespace ZM\Utils;
|
namespace ZM\Context;
|
||||||
|
|
||||||
|
|
||||||
use Swoole\Http\Request;
|
use Swoole\Http\Request;
|
||||||
use Swoole\WebSocket\Frame;
|
use Swoole\WebSocket\Frame;
|
||||||
use swoole_server;
|
use swoole_server;
|
||||||
|
use ZM\Connection\ConnectionManager;
|
||||||
|
use ZM\Connection\CQConnection;
|
||||||
use ZM\Http\Response;
|
use ZM\Http\Response;
|
||||||
|
use ZM\Utils\ZMRobot;
|
||||||
|
|
||||||
class Context
|
class Context implements ContextInterface
|
||||||
{
|
{
|
||||||
private $server = null;
|
private $server = null;
|
||||||
private $frame = null;
|
private $frame = null;
|
||||||
@@ -18,12 +21,12 @@ class Context
|
|||||||
private $response = null;
|
private $response = null;
|
||||||
private $cid;
|
private $cid;
|
||||||
|
|
||||||
public function __construct($param0, $cid) {
|
public function __construct($param, $cid) {
|
||||||
if (isset($param0["server"])) $this->server = $param0["server"];
|
if (isset($param["server"])) $this->server = $param["server"];
|
||||||
if (isset($param0["frame"])) $this->frame = $param0["frame"];
|
if (isset($param["frame"])) $this->frame = $param["frame"];
|
||||||
if (isset($param0["data"])) $this->data = $param0["data"];
|
if (isset($param["data"])) $this->data = $param["data"];
|
||||||
if (isset($param0["request"])) $this->request = $param0["request"];
|
if (isset($param["request"])) $this->request = $param["request"];
|
||||||
if (isset($param0["response"])) $this->response = $param0["response"];
|
if (isset($param["response"])) $this->response = $param["response"];
|
||||||
$this->cid = $cid;
|
$this->cid = $cid;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -68,4 +71,12 @@ class Context
|
|||||||
public function getCid() {
|
public function getCid() {
|
||||||
return $this->cid;
|
return $this->cid;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return ZMRobot|null
|
||||||
|
*/
|
||||||
|
public function getRobot() {
|
||||||
|
$conn = ConnectionManager::get($this->getFrame()->fd);
|
||||||
|
return $conn instanceof CQConnection ? new ZMRobot($conn) : null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
37
src/ZM/Context/ContextInterface.php
Normal file
37
src/ZM/Context/ContextInterface.php
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
|
||||||
|
namespace ZM\Context;
|
||||||
|
|
||||||
|
|
||||||
|
use Swoole\Http\Request;
|
||||||
|
use Swoole\WebSocket\Frame;
|
||||||
|
use Swoole\WebSocket\Server;
|
||||||
|
use ZM\Http\Response;
|
||||||
|
use ZM\Utils\ZMRobot;
|
||||||
|
|
||||||
|
interface ContextInterface
|
||||||
|
{
|
||||||
|
public function __construct($param, $cid);
|
||||||
|
|
||||||
|
/** @return Server */
|
||||||
|
public function getServer();
|
||||||
|
|
||||||
|
/** @return Frame */
|
||||||
|
public function getFrame();
|
||||||
|
|
||||||
|
/** @return mixed */
|
||||||
|
public function getData();
|
||||||
|
|
||||||
|
/** @return int */
|
||||||
|
public function getCid();
|
||||||
|
|
||||||
|
/** @return Response */
|
||||||
|
public function getResponse();
|
||||||
|
|
||||||
|
/** @return Request */
|
||||||
|
public function getRequest();
|
||||||
|
|
||||||
|
/** @return ZMRobot */
|
||||||
|
public function getRobot();
|
||||||
|
}
|
||||||
@@ -14,6 +14,9 @@ class DB
|
|||||||
{
|
{
|
||||||
private static $table_list = [];
|
private static $table_list = [];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @throws DbException
|
||||||
|
*/
|
||||||
public static function initTableList() {
|
public static function initTableList() {
|
||||||
$result = self::rawQuery("select TABLE_NAME from INFORMATION_SCHEMA.TABLES where TABLE_SCHEMA='" . ZMBuf::globals("sql_config")["sql_database"] . "';", []);
|
$result = self::rawQuery("select TABLE_NAME from INFORMATION_SCHEMA.TABLES where TABLE_SCHEMA='" . ZMBuf::globals("sql_config")["sql_database"] . "';", []);
|
||||||
foreach ($result as $v) {
|
foreach ($result as $v) {
|
||||||
@@ -40,10 +43,19 @@ class DB
|
|||||||
return Table::getTableInstance($table_name);
|
return Table::getTableInstance($table_name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param $line
|
||||||
|
* @throws DbException
|
||||||
|
*/
|
||||||
public static function statement($line) {
|
public static function statement($line) {
|
||||||
self::rawQuery($line, []);
|
self::rawQuery($line, []);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param $line
|
||||||
|
* @return bool
|
||||||
|
* @throws DbException
|
||||||
|
*/
|
||||||
public static function unprepared($line) {
|
public static function unprepared($line) {
|
||||||
if (ZMBuf::get("sql_log") === true) {
|
if (ZMBuf::get("sql_log") === true) {
|
||||||
$starttime = microtime(true);
|
$starttime = microtime(true);
|
||||||
@@ -64,12 +76,18 @@ class DB
|
|||||||
"] " . $line . " (Error:" . $e->getMessage() . ")\n";
|
"] " . $line . " (Error:" . $e->getMessage() . ")\n";
|
||||||
Coroutine::writeFile(CRASH_DIR . "sql.log", $log, FILE_APPEND);
|
Coroutine::writeFile(CRASH_DIR . "sql.log", $log, FILE_APPEND);
|
||||||
}
|
}
|
||||||
Console::error($e->getMessage());
|
Console::warning($e->getMessage());
|
||||||
return false;
|
throw $e;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function rawQuery(string $line, $params) {
|
/**
|
||||||
|
* @param string $line
|
||||||
|
* @param array $params
|
||||||
|
* @return mixed
|
||||||
|
* @throws DbException
|
||||||
|
*/
|
||||||
|
public static function rawQuery(string $line, $params = []) {
|
||||||
if (ZMBuf::get("sql_log") === true) {
|
if (ZMBuf::get("sql_log") === true) {
|
||||||
$starttime = microtime(true);
|
$starttime = microtime(true);
|
||||||
}
|
}
|
||||||
@@ -113,8 +131,12 @@ class DB
|
|||||||
"] " . $line . " " . json_encode($params, JSON_UNESCAPED_UNICODE) . " (Error:" . $e->getMessage() . ")\n";
|
"] " . $line . " " . json_encode($params, JSON_UNESCAPED_UNICODE) . " (Error:" . $e->getMessage() . ")\n";
|
||||||
Coroutine::writeFile(CRASH_DIR . "sql.log", $log, FILE_APPEND);
|
Coroutine::writeFile(CRASH_DIR . "sql.log", $log, FILE_APPEND);
|
||||||
}
|
}
|
||||||
Console::error($e->getMessage());
|
Console::warning($e->getMessage());
|
||||||
return false;
|
throw $e;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
public static function isTableExists($table) {
|
||||||
|
return in_array($table, self::$table_list);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -4,6 +4,8 @@
|
|||||||
namespace ZM\DB;
|
namespace ZM\DB;
|
||||||
|
|
||||||
|
|
||||||
|
use ZM\Exception\DbException;
|
||||||
|
|
||||||
class DeleteBody
|
class DeleteBody
|
||||||
{
|
{
|
||||||
use WhereBody;
|
use WhereBody;
|
||||||
@@ -21,8 +23,12 @@ class DeleteBody
|
|||||||
$this->table = $table;
|
$this->table = $table;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return mixed
|
||||||
|
* @throws DbException
|
||||||
|
*/
|
||||||
public function save() {
|
public function save() {
|
||||||
list($sql, $param) = $this->getWhereSQL();
|
list($sql, $param) = $this->getWhereSQL();
|
||||||
return DB::rawQuery("DELETE FROM " . $this->table->getTableName() . " WHERE " . $sql, $param);
|
return DB::rawQuery("DELETE FROM " . $this->table->getTableName() . " WHERE " . $sql, $param);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +4,8 @@
|
|||||||
namespace ZM\DB;
|
namespace ZM\DB;
|
||||||
|
|
||||||
|
|
||||||
|
use ZM\Exception\DbException;
|
||||||
|
|
||||||
class InsertBody
|
class InsertBody
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
@@ -22,7 +24,10 @@ class InsertBody
|
|||||||
$this->row = $row;
|
$this->row = $row;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @throws DbException
|
||||||
|
*/
|
||||||
public function save() {
|
public function save() {
|
||||||
DB::rawQuery('INSERT INTO ' . $this->table->getTableName() . ' VALUES ('.implode(',', array_fill(0, 5, '?')).')', $this->row);
|
DB::rawQuery('INSERT INTO ' . $this->table->getTableName() . ' VALUES ('.implode(',', array_fill(0, count($this->row), '?')).')', $this->row);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ namespace ZM\DB;
|
|||||||
|
|
||||||
|
|
||||||
use Framework\Console;
|
use Framework\Console;
|
||||||
|
use ZM\Exception\DbException;
|
||||||
|
|
||||||
class SelectBody
|
class SelectBody
|
||||||
{
|
{
|
||||||
@@ -23,8 +24,16 @@ class SelectBody
|
|||||||
$this->select_thing = $select_thing;
|
$this->select_thing = $select_thing;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return null
|
||||||
|
* @throws DbException
|
||||||
|
*/
|
||||||
public function get() { return $this->fetchAll(); }
|
public function get() { return $this->fetchAll(); }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return null
|
||||||
|
* @throws DbException
|
||||||
|
*/
|
||||||
public function fetchAll() {
|
public function fetchAll() {
|
||||||
if ($this->table->isCacheEnabled()) {
|
if ($this->table->isCacheEnabled()) {
|
||||||
$rr = md5(implode(",", $this->select_thing) . serialize($this->where_thing));
|
$rr = md5(implode(",", $this->select_thing) . serialize($this->where_thing));
|
||||||
@@ -40,16 +49,30 @@ class SelectBody
|
|||||||
return $this->getResult();
|
return $this->getResult();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return mixed|null
|
||||||
|
* @throws DbException
|
||||||
|
*/
|
||||||
public function fetchFirst() {
|
public function fetchFirst() {
|
||||||
return $this->fetchAll()[0] ?? null;
|
return $this->fetchAll()[0] ?? null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function value() {
|
/**
|
||||||
|
* @param null $key
|
||||||
|
* @return mixed|null
|
||||||
|
* @throws DbException
|
||||||
|
*/
|
||||||
|
public function value($key = null) {
|
||||||
$r = $this->fetchFirst();
|
$r = $this->fetchFirst();
|
||||||
if ($r === null) return null;
|
if ($r === null) return null;
|
||||||
return current($r);
|
if ($key === null)
|
||||||
|
return current($r);
|
||||||
|
else return $r[$key] ?? null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @throws DbException
|
||||||
|
*/
|
||||||
public function execute() {
|
public function execute() {
|
||||||
$str = $this->queryPrepare();
|
$str = $this->queryPrepare();
|
||||||
$this->result = DB::rawQuery($str[0], $str[1]);
|
$this->result = DB::rawQuery($str[0], $str[1]);
|
||||||
@@ -85,4 +108,4 @@ class SelectBody
|
|||||||
}
|
}
|
||||||
return [$msg, $array ?? []];
|
return [$msg, $array ?? []];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ use Framework\Console;
|
|||||||
use Framework\ZMBuf;
|
use Framework\ZMBuf;
|
||||||
use ZM\Event\Swoole\{MessageEvent, RequestEvent, WorkerStartEvent, WSCloseEvent, WSOpenEvent};
|
use ZM\Event\Swoole\{MessageEvent, RequestEvent, WorkerStartEvent, WSCloseEvent, WSOpenEvent};
|
||||||
use ZM\Http\Response;
|
use ZM\Http\Response;
|
||||||
|
use ZM\Utils\DataProvider;
|
||||||
use ZM\Utils\ZMUtil;
|
use ZM\Utils\ZMUtil;
|
||||||
|
|
||||||
class EventHandler
|
class EventHandler
|
||||||
@@ -21,15 +22,22 @@ class EventHandler
|
|||||||
switch ($event_name) {
|
switch ($event_name) {
|
||||||
case "workerstart":
|
case "workerstart":
|
||||||
try {
|
try {
|
||||||
|
register_shutdown_function(function () {
|
||||||
|
$error = error_get_last();
|
||||||
|
if ($error["type"] != 0) {
|
||||||
|
Console::error("Internal fatal error: " . $error["message"] . " at " . $error["file"] . "({$error["line"]})");
|
||||||
|
}
|
||||||
|
DataProvider::saveBuffer();
|
||||||
|
ZMBuf::$server->shutdown();
|
||||||
|
});
|
||||||
(new WorkerStartEvent($param0, $param1))->onActivate()->onAfter();
|
(new WorkerStartEvent($param0, $param1))->onActivate()->onAfter();
|
||||||
Console::log("\n=== Worker #" . $param0->worker_id . " 已启动 ===\n", "gold");
|
Console::log("\n=== Worker #" . $param0->worker_id . " 已启动 ===\n", "gold");
|
||||||
} catch (Exception $e) {
|
} catch (Exception $e) {
|
||||||
Console::error("Worker加载出错!停止服务!");
|
Console::error("Worker加载出错!停止服务!");
|
||||||
Console::error($e->getMessage() . "\n" . $e->getTraceAsString());
|
Console::error($e->getMessage() . "\n" . $e->getTraceAsString());
|
||||||
|
|
||||||
ZMUtil::stop();
|
ZMUtil::stop();
|
||||||
return;
|
return;
|
||||||
} catch(Error $e) {
|
} catch (Error $e) {
|
||||||
var_export($e);
|
var_export($e);
|
||||||
ZMUtil::stop();
|
ZMUtil::stop();
|
||||||
}
|
}
|
||||||
@@ -43,6 +51,9 @@ class EventHandler
|
|||||||
} catch (Exception $e) {
|
} catch (Exception $e) {
|
||||||
/** @var Response $param1 */
|
/** @var Response $param1 */
|
||||||
$param1->status(500);
|
$param1->status(500);
|
||||||
|
Console::info($param0->server["remote_addr"] . ":" . $param0->server["remote_port"] .
|
||||||
|
" [" . $param1->getStatusCode() . "] " . $param0->server["request_uri"]
|
||||||
|
);
|
||||||
if (!$param1->isEnd()) $param1->end("Internal server error: " . $e->getMessage());
|
if (!$param1->isEnd()) $param1->end("Internal server error: " . $e->getMessage());
|
||||||
Console::error("Internal server error (500), caused by uncaught exception.");
|
Console::error("Internal server error (500), caused by uncaught exception.");
|
||||||
Console::log($e->getTraceAsString(), "gray");
|
Console::log($e->getTraceAsString(), "gray");
|
||||||
|
|||||||
@@ -39,17 +39,19 @@ class MessageEvent implements SwooleEvent
|
|||||||
*/
|
*/
|
||||||
public function onActivate() {
|
public function onActivate() {
|
||||||
ZMUtil::checkWait();
|
ZMUtil::checkWait();
|
||||||
|
$conn = ConnectionManager::get($this->frame->fd);
|
||||||
|
set_coroutine_params(["server" => $this->server, "frame" => $this->frame, "connection" => $conn]);
|
||||||
try {
|
try {
|
||||||
if (ConnectionManager::get($this->frame->fd)->getType() == "qq") {
|
if ($conn->getType() == "qq") {
|
||||||
$data = json_decode($this->frame->data, true);
|
$data = json_decode($this->frame->data, true);
|
||||||
if (isset($data["post_type"])) {
|
if (isset($data["post_type"])) {
|
||||||
|
set_coroutine_params(["data" => $data, "connection" => $conn]);
|
||||||
EventHandler::callCQEvent($data, ConnectionManager::get($this->frame->fd), 0);
|
EventHandler::callCQEvent($data, ConnectionManager::get($this->frame->fd), 0);
|
||||||
} else
|
} else
|
||||||
EventHandler::callCQResponse($data);
|
EventHandler::callCQResponse($data);
|
||||||
}
|
}
|
||||||
foreach (ZMBuf::$events[SwooleEventAt::class] ?? [] as $v) {
|
foreach (ZMBuf::$events[SwooleEventAt::class] ?? [] as $v) {
|
||||||
if (strtolower($v->type) == "message" && $this->parseSwooleRule($v)) {
|
if (strtolower($v->type) == "message" && $this->parseSwooleRule($v)) {
|
||||||
$conn = ConnectionManager::get($this->frame->fd);
|
|
||||||
$c = $v->class;
|
$c = $v->class;
|
||||||
/** @var ModBase $class */
|
/** @var ModBase $class */
|
||||||
$class = new $c(["server" => $this->server, "frame" => $this->frame, "connection" => $conn], ModHandleType::SWOOLE_MESSAGE);
|
$class = new $c(["server" => $this->server, "frame" => $this->frame, "connection" => $conn], ModHandleType::SWOOLE_MESSAGE);
|
||||||
@@ -58,7 +60,7 @@ class MessageEvent implements SwooleEvent
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (Exception $e) {
|
} catch (Exception $e) {
|
||||||
Console::error("出现错误: " . $e->getMessage());
|
Console::warning("Websocket message event exception: " . $e->getMessage());
|
||||||
}
|
}
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
@@ -91,4 +93,4 @@ class MessageEvent implements SwooleEvent
|
|||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ namespace ZM\Event\Swoole;
|
|||||||
use Closure;
|
use Closure;
|
||||||
use Doctrine\Common\Annotations\AnnotationException;
|
use Doctrine\Common\Annotations\AnnotationException;
|
||||||
use Exception;
|
use Exception;
|
||||||
|
use Framework\Console;
|
||||||
use Framework\ZMBuf;
|
use Framework\ZMBuf;
|
||||||
use Swoole\Http\Request;
|
use Swoole\Http\Request;
|
||||||
use ZM\Annotation\Http\MiddlewareClass;
|
use ZM\Annotation\Http\MiddlewareClass;
|
||||||
@@ -63,9 +64,6 @@ class RequestEvent implements SwooleEvent
|
|||||||
} elseif ($node["son"][0]["name"] == $r) {
|
} elseif ($node["son"][0]["name"] == $r) {
|
||||||
$node = $node["son"][0];
|
$node = $node["son"][0];
|
||||||
continue;
|
continue;
|
||||||
} else {
|
|
||||||
$this->responseStatus(404);
|
|
||||||
return $this;
|
|
||||||
}
|
}
|
||||||
} elseif ($cnt >= 1) {
|
} elseif ($cnt >= 1) {
|
||||||
if (isset($node["param_route"])) {
|
if (isset($node["param_route"])) {
|
||||||
@@ -84,7 +82,40 @@ class RequestEvent implements SwooleEvent
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
$this->responseStatus(404);
|
|
||||||
|
if (ZMBuf::globals("static_file_server")["status"]) {
|
||||||
|
$base_dir = ZMBuf::globals("static_file_server")["document_root"];
|
||||||
|
$base_index = ZMBuf::globals("static_file_server")["document_index"];
|
||||||
|
$uri = $this->request->server["request_uri"];
|
||||||
|
$path = realpath($base_dir . urldecode($uri));
|
||||||
|
if ($path !== false) {
|
||||||
|
if (is_dir($path)) $path = $path . '/';
|
||||||
|
$work = realpath(WORKING_DIR) . '/';
|
||||||
|
if (strpos($path, $work) !== 0) {
|
||||||
|
$this->responseStatus(403);
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
if (is_dir($path)) {
|
||||||
|
foreach ($base_index as $vp) {
|
||||||
|
if (is_file($path . $vp)) {
|
||||||
|
Console::info("[200] " . $uri . " (static)");
|
||||||
|
$exp = strtolower(pathinfo($path . $vp)['extension'] ?? "unknown");
|
||||||
|
$this->response->setHeader("Content-Type", ZMBuf::config("file_header")[$exp] ?? "application/octet-stream");
|
||||||
|
$this->response->end(file_get_contents($path . $vp));
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} elseif (is_file($path)) {
|
||||||
|
Console::info("[200] " . $uri . " (static)");
|
||||||
|
$exp = strtolower(pathinfo($path)['extension'] ?? "unknown");
|
||||||
|
$this->response->setHeader("Content-Type", ZMBuf::config("file_header")[$exp] ?? "application/octet-stream");
|
||||||
|
$this->response->end(file_get_contents($path));
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$this->response->status(404);
|
||||||
|
$this->response->end(ZMUtil::getHttpCodePage(404));
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -94,7 +125,7 @@ class RequestEvent implements SwooleEvent
|
|||||||
$c_name = $node["class"];
|
$c_name = $node["class"];
|
||||||
if (isset(ZMBuf::$events[MiddlewareInterface::class][$c_name][$node["method"]])) {
|
if (isset(ZMBuf::$events[MiddlewareInterface::class][$c_name][$node["method"]])) {
|
||||||
$middleware = ZMBuf::$events[MiddlewareInterface::class][$c_name][$node["method"]];
|
$middleware = ZMBuf::$events[MiddlewareInterface::class][$c_name][$node["method"]];
|
||||||
if(!isset(ZMBuf::$events[MiddlewareClass::class][$middleware])) throw new AnnotationException("Annotation parse error: Unknown MiddlewareClass named \"{$middleware}\"!");
|
if (!isset(ZMBuf::$events[MiddlewareClass::class][$middleware])) throw new AnnotationException("Annotation parse error: Unknown MiddlewareClass named \"{$middleware}\"!");
|
||||||
$middleware = ZMBuf::$events[MiddlewareClass::class][$middleware];
|
$middleware = ZMBuf::$events[MiddlewareClass::class][$middleware];
|
||||||
$before = $middleware["class"];
|
$before = $middleware["class"];
|
||||||
$r = new $before();
|
$r = new $before();
|
||||||
@@ -112,8 +143,8 @@ class RequestEvent implements SwooleEvent
|
|||||||
if (!$this->response->isEnd()) goto eventCall;
|
if (!$this->response->isEnd()) goto eventCall;
|
||||||
} catch (Exception $e) {
|
} catch (Exception $e) {
|
||||||
if (!isset($middleware["exceptions"])) throw $e;
|
if (!isset($middleware["exceptions"])) throw $e;
|
||||||
foreach($middleware["exceptions"] as $name => $method) {
|
foreach ($middleware["exceptions"] as $name => $method) {
|
||||||
if($e instanceof $name) {
|
if ($e instanceof $name) {
|
||||||
call_user_func([$r, $method], $e, $this->request, $this->response, $params);
|
call_user_func([$r, $method], $e, $this->request, $this->response, $params);
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -30,6 +30,7 @@ class WSCloseEvent implements SwooleEvent
|
|||||||
public function onActivate() {
|
public function onActivate() {
|
||||||
ZMUtil::checkWait();
|
ZMUtil::checkWait();
|
||||||
ConnectionManager::close($this->fd);
|
ConnectionManager::close($this->fd);
|
||||||
|
set_coroutine_params(["server" => $this->server, "fd" => $this->fd]);
|
||||||
foreach(ZMBuf::$events[SwooleEventAt::class] ?? [] as $v) {
|
foreach(ZMBuf::$events[SwooleEventAt::class] ?? [] as $v) {
|
||||||
if(strtolower($v->type) == "close" && $this->parseSwooleRule($v)) {
|
if(strtolower($v->type) == "close" && $this->parseSwooleRule($v)) {
|
||||||
$c = $v->class;
|
$c = $v->class;
|
||||||
@@ -60,4 +61,4 @@ class WSCloseEvent implements SwooleEvent
|
|||||||
private function parseSwooleRule($v) {
|
private function parseSwooleRule($v) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -55,6 +55,7 @@ class WSOpenEvent implements SwooleEvent
|
|||||||
$this->conn = new $type_conn($this->server, $this->request->fd);
|
$this->conn = new $type_conn($this->server, $this->request->fd);
|
||||||
}
|
}
|
||||||
ZMBuf::$connect[$this->request->fd] = $this->conn;
|
ZMBuf::$connect[$this->request->fd] = $this->conn;
|
||||||
|
set_coroutine_params(["server" => $this->server, "request" => $this->request, "connection" => $this->conn]);
|
||||||
foreach (ZMBuf::$events[SwooleEventAt::class] ?? [] as $v) {
|
foreach (ZMBuf::$events[SwooleEventAt::class] ?? [] as $v) {
|
||||||
if (strtolower($v->type) == "open" && $this->parseSwooleRule($v) === true) {
|
if (strtolower($v->type) == "open" && $this->parseSwooleRule($v) === true) {
|
||||||
$c = $v->class;
|
$c = $v->class;
|
||||||
@@ -90,4 +91,4 @@ class WSOpenEvent implements SwooleEvent
|
|||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,23 +6,28 @@ namespace ZM\Event\Swoole;
|
|||||||
|
|
||||||
use Co;
|
use Co;
|
||||||
use Doctrine\Common\Annotations\AnnotationException;
|
use Doctrine\Common\Annotations\AnnotationException;
|
||||||
|
use Exception;
|
||||||
use ReflectionException;
|
use ReflectionException;
|
||||||
use Swoole\Coroutine;
|
use Swoole\Coroutine;
|
||||||
|
use Swoole\Process;
|
||||||
use Swoole\Timer;
|
use Swoole\Timer;
|
||||||
use ZM\Annotation\AnnotationBase;
|
use ZM\Annotation\AnnotationBase;
|
||||||
use ZM\Annotation\AnnotationParser;
|
use ZM\Annotation\AnnotationParser;
|
||||||
use ZM\Annotation\Swoole\OnStart;
|
use ZM\Annotation\Swoole\OnStart;
|
||||||
use ZM\Annotation\Swoole\SwooleEventAfter;
|
use ZM\Annotation\Swoole\SwooleEventAfter;
|
||||||
use ZM\Connection\ConnectionManager;
|
use ZM\Connection\ConnectionManager;
|
||||||
|
use ZM\Context\ContextInterface;
|
||||||
use ZM\DB\DB;
|
use ZM\DB\DB;
|
||||||
use Framework\Console;
|
use Framework\Console;
|
||||||
use Framework\GlobalConfig;
|
use Framework\GlobalConfig;
|
||||||
use Framework\ZMBuf;
|
use Framework\ZMBuf;
|
||||||
use Swoole\Server;
|
use Swoole\Server;
|
||||||
|
use ZM\Exception\DbException;
|
||||||
use ZM\ModBase;
|
use ZM\ModBase;
|
||||||
use ZM\ModHandleType;
|
use ZM\ModHandleType;
|
||||||
use ZM\Utils\DataProvider;
|
use ZM\Utils\DataProvider;
|
||||||
use ZM\Utils\SQLPool;
|
use ZM\Utils\SQLPool;
|
||||||
|
use ZM\Utils\ZMUtil;
|
||||||
|
|
||||||
class WorkerStartEvent implements SwooleEvent
|
class WorkerStartEvent implements SwooleEvent
|
||||||
{
|
{
|
||||||
@@ -41,9 +46,14 @@ class WorkerStartEvent implements SwooleEvent
|
|||||||
* @return WorkerStartEvent
|
* @return WorkerStartEvent
|
||||||
* @throws AnnotationException
|
* @throws AnnotationException
|
||||||
* @throws ReflectionException
|
* @throws ReflectionException
|
||||||
|
* @throws DbException
|
||||||
*/
|
*/
|
||||||
public function onActivate(): WorkerStartEvent {
|
public function onActivate(): WorkerStartEvent {
|
||||||
Console::info("Worker启动中");
|
Console::info("Worker启动中");
|
||||||
|
Process::signal(SIGINT, function (){
|
||||||
|
Console::warning("Server interrupted by keyboard.");
|
||||||
|
ZMUtil::stop(true);
|
||||||
|
});
|
||||||
ZMBuf::resetCache(); //清空变量缓存
|
ZMBuf::resetCache(); //清空变量缓存
|
||||||
ZMBuf::set("wait_start", []); //添加队列,在workerStart运行完成前先让其他协程等待执行
|
ZMBuf::set("wait_start", []); //添加队列,在workerStart运行完成前先让其他协程等待执行
|
||||||
$this->resetConnections();//释放所有与framework的连接
|
$this->resetConnections();//释放所有与framework的连接
|
||||||
@@ -58,11 +68,11 @@ class WorkerStartEvent implements SwooleEvent
|
|||||||
$name = explode(".", $v);
|
$name = explode(".", $v);
|
||||||
if (($prefix = end($name)) == "json") {
|
if (($prefix = end($name)) == "json") {
|
||||||
ZMBuf::$config[$name[0]] = json_decode(Co::readFile(WORKING_DIR . '/config/' . $v), true);
|
ZMBuf::$config[$name[0]] = json_decode(Co::readFile(WORKING_DIR . '/config/' . $v), true);
|
||||||
Console::info("已读取配置文件(json):" . $prefix);
|
Console::info("已读取配置文件:" . $v);
|
||||||
} elseif ($prefix == "php") {
|
} elseif ($prefix == "php") {
|
||||||
ZMBuf::$config[$name[0]] = include_once WORKING_DIR . '/config/' . $v;
|
ZMBuf::$config[$name[0]] = include_once WORKING_DIR . '/config/' . $v;
|
||||||
if (is_array(ZMBuf::$config[$name[0]]))
|
if (is_array(ZMBuf::$config[$name[0]]))
|
||||||
Console::info("已读取配置文件(php):" . $prefix);
|
Console::info("已读取配置文件:" . $v);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (ZMBuf::globals("sql_config")["sql_host"] != "") {
|
if (ZMBuf::globals("sql_config")["sql_host"] != "") {
|
||||||
@@ -94,6 +104,7 @@ class WorkerStartEvent implements SwooleEvent
|
|||||||
$class = new $class_name(["server" => $this->server, "worker_id" => $this->worker_id], ModHandleType::SWOOLE_WORKER_START);
|
$class = new $class_name(["server" => $this->server, "worker_id" => $this->worker_id], ModHandleType::SWOOLE_WORKER_START);
|
||||||
call_user_func_array([$class, $v->method], []);
|
call_user_func_array([$class, $v->method], []);
|
||||||
}
|
}
|
||||||
|
set_coroutine_params(["server" => $this->server, "worker_id" => $this->worker_id]);
|
||||||
foreach (ZMBuf::$events[SwooleEventAfter::class] ?? [] as $v) {
|
foreach (ZMBuf::$events[SwooleEventAfter::class] ?? [] as $v) {
|
||||||
/** @var AnnotationBase $v */
|
/** @var AnnotationBase $v */
|
||||||
if (strtolower($v->type) == "workerstart") {
|
if (strtolower($v->type) == "workerstart") {
|
||||||
@@ -120,6 +131,7 @@ class WorkerStartEvent implements SwooleEvent
|
|||||||
/**
|
/**
|
||||||
* @throws AnnotationException
|
* @throws AnnotationException
|
||||||
* @throws ReflectionException
|
* @throws ReflectionException
|
||||||
|
* @throws Exception
|
||||||
*/
|
*/
|
||||||
private function loadAllClass() {
|
private function loadAllClass() {
|
||||||
//加载phar包
|
//加载phar包
|
||||||
@@ -148,6 +160,7 @@ class WorkerStartEvent implements SwooleEvent
|
|||||||
//加载自定义的全局函数
|
//加载自定义的全局函数
|
||||||
if(file_exists(WORKING_DIR."/src/Custom/global_function.php"))
|
if(file_exists(WORKING_DIR."/src/Custom/global_function.php"))
|
||||||
require_once WORKING_DIR."/src/Custom/global_function.php";
|
require_once WORKING_DIR."/src/Custom/global_function.php";
|
||||||
|
$this->afterCheck();
|
||||||
}
|
}
|
||||||
|
|
||||||
private function setAutosaveTimer($globals) {
|
private function setAutosaveTimer($globals) {
|
||||||
@@ -156,4 +169,14 @@ class WorkerStartEvent implements SwooleEvent
|
|||||||
DataProvider::saveBuffer();
|
DataProvider::saveBuffer();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
/**
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
private function afterCheck() {
|
||||||
|
$context_class = ZMBuf::globals("context_class");
|
||||||
|
if(!is_a($context_class, ContextInterface::class, true)) {
|
||||||
|
throw new Exception("Context class must implemented from ContextInterface!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
20
src/ZM/Exception/RobotNotFoundException.php
Normal file
20
src/ZM/Exception/RobotNotFoundException.php
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
|
||||||
|
namespace ZM\Exception;
|
||||||
|
|
||||||
|
|
||||||
|
use Exception;
|
||||||
|
use Throwable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class RobotNotFoundException
|
||||||
|
* @package ZM\Exception
|
||||||
|
* @since 1.2
|
||||||
|
*/
|
||||||
|
class RobotNotFoundException extends Exception
|
||||||
|
{
|
||||||
|
public function __construct($message = "", $code = 0, Throwable $previous = null) {
|
||||||
|
parent::__construct($message, $code, $previous);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -21,6 +21,7 @@ class Response
|
|||||||
*/
|
*/
|
||||||
private $response;
|
private $response;
|
||||||
private $is_end = false;
|
private $is_end = false;
|
||||||
|
private $status_code;
|
||||||
|
|
||||||
public function __construct(\Swoole\Http\Response $response) {
|
public function __construct(\Swoole\Http\Response $response) {
|
||||||
$this->response = $response;
|
$this->response = $response;
|
||||||
@@ -90,9 +91,14 @@ class Response
|
|||||||
* @return mixed
|
* @return mixed
|
||||||
*/
|
*/
|
||||||
public function status($http_code, $reason = null) {
|
public function status($http_code, $reason = null) {
|
||||||
|
$this->status_code = $http_code;
|
||||||
return $this->response->status($http_code, $reason);
|
return $this->response->status($http_code, $reason);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function getStatusCode() {
|
||||||
|
return $this->status_code ?? 200;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param $http_code
|
* @param $http_code
|
||||||
* @param $reason
|
* @param $reason
|
||||||
|
|||||||
@@ -10,46 +10,55 @@ use Framework\ZMBuf;
|
|||||||
|
|
||||||
class DataProvider
|
class DataProvider
|
||||||
{
|
{
|
||||||
const HEADER_TYPE = '{"ai":"application/postscript","aif":"audio/x-aiff","aifc":"audio/x-aiff","aiff":"audio/x-aiff","asc":"text/plain","au":"audio/basic","avi":"video/x-msvideo","bcpio":"application/x-bcpio","bin":"application/octet-stream","bmp":"image/bmp","cdf":"application/x-netcdf","class":"application/octet-stream","cpio":"application/x-cpio","cpt":"application/mac-compactpro","csh":"application/x-csh","css":"text/css","dcr":"application/x-director","dir":"application/x-director","djv":"image/vnd.djvu","djvu":"image/vnd.djvu","dll":"application/octet-stream","dms":"application/octet-stream","doc":"application/msword","dvi":"application/x-dvi","dxr":"application/x-director","eps":"application/postscript","etx":"text/x-setext","exe":"application/octet-stream","ez":"application/andrew-inset","gif":"image/gif","gtar":"application/x-gtar","hdf":"application/x-hdf","hqx":"application/mac-binhex40","htm":"text/html","html":"text/html","ice":"x-conference/x-cooltalk","ief":"image/ief","iges":"model/iges","igs":"model/iges","jpe":"image/jpeg","jpeg":"image/jpeg","jpg":"image/jpeg","js":"application/x-javascript","kar":"audio/midi","latex":"application/x-latex","lha":"application/octet-stream","lzh":"application/octet-stream","m3u":"audio/x-mpegurl","man":"application/x-troff-man","me":"application/x-troff-me","mesh":"model/mesh","mid":"audio/midi","midi":"audio/midi","mif":"application/vnd.mif","mov":"video/quicktime","movie":"video/x-sgi-movie","mp2":"audio/mpeg","mp3":"audio/mpeg","mpe":"video/mpeg","mpeg":"video/mpeg","mpg":"video/mpeg","mpga":"audio/mpeg","ms":"application/x-troff-ms","msh":"model/mesh","mxu":"video/vnd.mpegurl","nc":"application/x-netcdf","oda":"application/oda","pbm":"image/x-portable-bitmap","pdb":"chemical/x-pdb","pdf":"application/pdf","pgm":"image/x-portable-graymap","pgn":"application/x-chess-pgn","png":"image/png","pnm":"image/x-portable-anymap","ppm":"image/x-portable-pixmap","ppt":"application/vnd.ms-powerpoint","ps":"application/postscript","qt":"video/quicktime","ra":"audio/x-realaudio","ram":"audio/x-pn-realaudio","ras":"image/x-cmu-raster","rgb":"image/x-rgb","rm":"audio/x-pn-realaudio","roff":"application/x-troff","rpm":"audio/x-pn-realaudio-plugin","rtf":"text/rtf","rtx":"text/richtext","sgm":"text/sgml","sgml":"text/sgml","sh":"application/x-sh","shar":"application/x-shar","silo":"model/mesh","sit":"application/x-stuffit","skd":"application/x-koan","skm":"application/x-koan","skp":"application/x-koan","skt":"application/x-koan","smi":"application/smil","smil":"application/smil","snd":"audio/basic","so":"application/octet-stream","spl":"application/x-futuresplash","src":"application/x-wais-source","sv4cpio":"application/x-sv4cpio","sv4crc":"application/x-sv4crc","swf":"application/x-shockwave-flash","t":"application/x-troff","tar":"application/x-tar","tcl":"application/x-tcl","tex":"application/x-tex","texi":"application/x-texinfo","texinfo":"application/x-texinfo","tif":"image/tiff","tiff":"image/tiff","tr":"application/x-troff","tsv":"text/tab-separated-values","txt":"text/plain","ustar":"application/x-ustar","vcd":"application/x-cdlink","vrml":"model/vrml","wav":"audio/x-wav","wbmp":"image/vnd.wap.wbmp","wbxml":"application/vnd.wap.wbxml","wml":"text/vnd.wap.wml","wmlc":"application/vnd.wap.wmlc","wmls":"text/vnd.wap.wmlscript","wmlsc":"application/vnd.wap.wmlscriptc","wrl":"model/vrml","xbm":"image/x-xbitmap","xht":"application/xhtml+xml","xhtml":"application/xhtml+xml","xls":"application/vnd.ms-excel","xml":"text/xml","xpm":"image/x-xpixmap","xsl":"text/xml","xwd":"image/x-xwindowdump","xyz":"chemical/x-xyz","zip":"application/zip"}';
|
|
||||||
public static $buffer_list = [];
|
public static $buffer_list = [];
|
||||||
|
|
||||||
public static function getResourceFolder() {
|
public static function getResourceFolder()
|
||||||
|
{
|
||||||
return WORKING_DIR . '/resources/';
|
return WORKING_DIR . '/resources/';
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function getDataConfig(){
|
public static function getDataConfig()
|
||||||
|
{
|
||||||
return CONFIG_DIR;
|
return CONFIG_DIR;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function addSaveBuffer($buf_name, $sub_folder = null) {
|
public static function addSaveBuffer($buf_name, $sub_folder = null)
|
||||||
|
{
|
||||||
$name = ($sub_folder ?? "") . "/" . $buf_name . ".json";
|
$name = ($sub_folder ?? "") . "/" . $buf_name . ".json";
|
||||||
self::$buffer_list[$buf_name] = $name;
|
self::$buffer_list[$buf_name] = $name;
|
||||||
ZMBuf::set($buf_name, self::getJsonData($name));
|
ZMBuf::set($buf_name, self::getJsonData($name));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function saveBuffer() {
|
public static function saveBuffer()
|
||||||
$head = Console::setColor(date("[H:i:s ") . "INFO] Saving buffer......", "lightblue");
|
{
|
||||||
echo $head;
|
$head = Console::setColor(date("[H:i:s] ") . "[V] Saving buffer......", "blue");
|
||||||
foreach(self::$buffer_list as $k => $v) {
|
if (ZMBuf::$atomics["info_level"]->get() >= 3)
|
||||||
|
echo $head;
|
||||||
|
foreach (self::$buffer_list as $k => $v) {
|
||||||
self::setJsonData($v, ZMBuf::get($k));
|
self::setJsonData($v, ZMBuf::get($k));
|
||||||
}
|
}
|
||||||
echo Console::setColor("saved", "lightblue").PHP_EOL;
|
if (ZMBuf::$atomics["info_level"]->get() >= 3)
|
||||||
|
echo Console::setColor("saved", "blue") . PHP_EOL;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function getFrameworkLink(){
|
public static function getFrameworkLink()
|
||||||
|
{
|
||||||
return ZMBuf::globals("http_reverse_link");
|
return ZMBuf::globals("http_reverse_link");
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function getJsonData(string $string) {
|
public static function getJsonData(string $string)
|
||||||
if(!file_exists(self::getDataConfig().$string)) return [];
|
{
|
||||||
return json_decode(Co::readFile(self::getDataConfig().$string), true);
|
if (!file_exists(self::getDataConfig() . $string)) return [];
|
||||||
|
return json_decode(Co::readFile(self::getDataConfig() . $string), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static function setJsonData($filename, array $args) {
|
private static function setJsonData($filename, array $args)
|
||||||
|
{
|
||||||
Co::writeFile(self::getDataConfig() . $filename, json_encode($args, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT | JSON_BIGINT_AS_STRING));
|
Co::writeFile(self::getDataConfig() . $filename, json_encode($args, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT | JSON_BIGINT_AS_STRING));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function getDataFolder() {
|
public static function getDataFolder()
|
||||||
|
{
|
||||||
return ZM_DATA;
|
return ZM_DATA;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
412
src/ZM/Utils/ZMRobot.php
Normal file
412
src/ZM/Utils/ZMRobot.php
Normal file
@@ -0,0 +1,412 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
|
||||||
|
namespace ZM\Utils;
|
||||||
|
|
||||||
|
use ZM\API\CQAPI;
|
||||||
|
use ZM\Connection\ConnectionManager;
|
||||||
|
use ZM\Connection\CQConnection;
|
||||||
|
use ZM\Exception\RobotNotFoundException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class ZMRobot
|
||||||
|
* @package ZM\Utils
|
||||||
|
* @since 1.2
|
||||||
|
*/
|
||||||
|
class ZMRobot
|
||||||
|
{
|
||||||
|
const API_ASYNC = 1;
|
||||||
|
const API_NORMAL = 0;
|
||||||
|
const API_RATE_LIMITED = 2;
|
||||||
|
|
||||||
|
private $connection;
|
||||||
|
|
||||||
|
private $callback = null;
|
||||||
|
private $prefix = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param $robot_id
|
||||||
|
* @return ZMRobot
|
||||||
|
* @throws RobotNotFoundException
|
||||||
|
*/
|
||||||
|
public static function get($robot_id) {
|
||||||
|
$r = ConnectionManager::getByType("qq", ["self_id" => $robot_id]);
|
||||||
|
if ($r == []) throw new RobotNotFoundException("机器人 " . $robot_id . " 未连接到框架!");
|
||||||
|
return new ZMRobot($r[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @throws RobotNotFoundException
|
||||||
|
* @return ZMRobot
|
||||||
|
*/
|
||||||
|
public static function getRandom() {
|
||||||
|
$r = ConnectionManager::getByType("qq");
|
||||||
|
if($r == []) throw new RobotNotFoundException("没有任何机器人连接到框架!");
|
||||||
|
return new ZMRobot($r[array_rand($r)]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function __construct(CQConnection $connection) {
|
||||||
|
$this->connection = $connection;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setCallback($callback = true) {
|
||||||
|
$this->callback = $callback;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setPrefix($prefix = self::API_NORMAL) {
|
||||||
|
$this->prefix = $prefix;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function sendPrivateMsg($user_id, $message, $auto_escape = false) {
|
||||||
|
return CQAPI::processAPI($this->connection, [
|
||||||
|
'action' => $this->getActionName(__FUNCTION__),
|
||||||
|
'params' => [
|
||||||
|
'user_id' => $user_id,
|
||||||
|
'message' => $message,
|
||||||
|
'auto_escape' => $auto_escape
|
||||||
|
]
|
||||||
|
], $this->callback);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function sendGroupMsg($group_id, $message, $auto_escape = false) {
|
||||||
|
return CQAPI::processAPI($this->connection, [
|
||||||
|
'action' => $this->getActionName(__FUNCTION__),
|
||||||
|
'params' => [
|
||||||
|
'group_id' => $group_id,
|
||||||
|
'message' => $message,
|
||||||
|
'auto_escape' => $auto_escape
|
||||||
|
]
|
||||||
|
], $this->callback);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function sendDiscussMsg($discuss_id, $message, $auto_escape = false) {
|
||||||
|
return CQAPI::processAPI($this->connection, [
|
||||||
|
'action' => $this->getActionName(__FUNCTION__),
|
||||||
|
'params' => [
|
||||||
|
'discuss_id' => $discuss_id,
|
||||||
|
'message' => $message,
|
||||||
|
'auto_escape' => $auto_escape
|
||||||
|
]
|
||||||
|
], $this->callback);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function sendMsg($message_type, $target_id, $message, $auto_escape = false) {
|
||||||
|
return CQAPI::processAPI($this->connection, [
|
||||||
|
'action' => $this->getActionName(__FUNCTION__),
|
||||||
|
'params' => [
|
||||||
|
'message_type' => $message_type,
|
||||||
|
($message_type == 'private' ? 'user' : $message_type) . '_id' => $target_id,
|
||||||
|
'message' => $message,
|
||||||
|
'auto_escape' => $auto_escape
|
||||||
|
]
|
||||||
|
], $this->callback);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function deleteMsg($message_id) {
|
||||||
|
return CQAPI::processAPI($this->connection, [
|
||||||
|
'action' => $this->getActionName(__FUNCTION__),
|
||||||
|
'params' => [
|
||||||
|
'message_id' => $message_id
|
||||||
|
]
|
||||||
|
], $this->callback);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function sendLike($user_id, $times = 1) {
|
||||||
|
return CQAPI::processAPI($this->connection, [
|
||||||
|
'action' => $this->getActionName(__FUNCTION__),
|
||||||
|
'params' => [
|
||||||
|
'user_id' => $user_id,
|
||||||
|
'times' => $times
|
||||||
|
]
|
||||||
|
], $this->callback);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setGroupKick($group_id, $user_id, $reject_add_request = false) {
|
||||||
|
return CQAPI::processAPI($this->connection, [
|
||||||
|
'action' => $this->getActionName(__FUNCTION__),
|
||||||
|
'params' => [
|
||||||
|
'group_id' => $group_id,
|
||||||
|
'user_id' => $user_id,
|
||||||
|
'reject_add_request' => $reject_add_request
|
||||||
|
]
|
||||||
|
], $this->callback);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setGroupBan($group_id, $user_id, $duration = 1800) {
|
||||||
|
return CQAPI::processAPI($this->connection, [
|
||||||
|
'action' => $this->getActionName(__FUNCTION__),
|
||||||
|
'params' => [
|
||||||
|
'group_id' => $group_id,
|
||||||
|
'user_id' => $user_id,
|
||||||
|
'duration' => $duration
|
||||||
|
]
|
||||||
|
], $this->callback);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setGroupAnonymousBan($group_id, $anonymous_or_flag, $duration = 1800) {
|
||||||
|
return CQAPI::processAPI($this->connection, [
|
||||||
|
'action' => $this->getActionName(__FUNCTION__),
|
||||||
|
'params' => [
|
||||||
|
'group_id' => $group_id,
|
||||||
|
(is_string($anonymous_or_flag) ? 'flag' : 'anonymous') => $anonymous_or_flag,
|
||||||
|
'duration' => $duration
|
||||||
|
]
|
||||||
|
], $this->callback);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setGroupWholeBan($group_id, $enable = true) {
|
||||||
|
return CQAPI::processAPI($this->connection, [
|
||||||
|
'action' => $this->getActionName(__FUNCTION__),
|
||||||
|
'params' => [
|
||||||
|
'group_id' => $group_id,
|
||||||
|
'enable' => $enable
|
||||||
|
]
|
||||||
|
], $this->callback);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setGroupAdmin($group_id, $user_id, $enable = true) {
|
||||||
|
return CQAPI::processAPI($this->connection, [
|
||||||
|
'action' => $this->getActionName(__FUNCTION__),
|
||||||
|
'params' => [
|
||||||
|
'group_id' => $group_id,
|
||||||
|
'user_id' => $user_id,
|
||||||
|
'enable' => $enable
|
||||||
|
]
|
||||||
|
], $this->callback);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setGroupAnonymous($group_id, $enable = true) {
|
||||||
|
return CQAPI::processAPI($this->connection, [
|
||||||
|
'action' => $this->getActionName(__FUNCTION__),
|
||||||
|
'params' => [
|
||||||
|
'group_id' => $group_id,
|
||||||
|
'enable' => $enable
|
||||||
|
]
|
||||||
|
], $this->callback);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setGroupCard($group_id, $user_id, $card = "") {
|
||||||
|
return CQAPI::processAPI($this->connection, [
|
||||||
|
'action' => $this->getActionName(__FUNCTION__),
|
||||||
|
'params' => [
|
||||||
|
'group_id' => $group_id,
|
||||||
|
'user_id' => $user_id,
|
||||||
|
'card' => $card
|
||||||
|
]
|
||||||
|
], $this->callback);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setGroupLeave($group_id, $is_dismiss = false) {
|
||||||
|
return CQAPI::processAPI($this->connection, [
|
||||||
|
'action' => $this->getActionName(__FUNCTION__),
|
||||||
|
'params' => [
|
||||||
|
'group_id' => $group_id,
|
||||||
|
'is_dismiss' => $is_dismiss
|
||||||
|
]
|
||||||
|
], $this->callback);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setGroupSpecialTitle($group_id, $user_id, $special_title = "", $duration = -1) {
|
||||||
|
return CQAPI::processAPI($this->connection, [
|
||||||
|
'action' => $this->getActionName(__FUNCTION__),
|
||||||
|
'params' => [
|
||||||
|
'group_id' => $group_id,
|
||||||
|
'user_id' => $user_id,
|
||||||
|
'special_title' => $special_title,
|
||||||
|
'duration' => $duration
|
||||||
|
]
|
||||||
|
], $this->callback);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setDiscussLeave($discuss_id) {
|
||||||
|
return CQAPI::processAPI($this->connection, [
|
||||||
|
'action' => $this->getActionName(__FUNCTION__),
|
||||||
|
'params' => [
|
||||||
|
'discuss_id' => $discuss_id
|
||||||
|
]
|
||||||
|
], $this->callback);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setFriendAddRequest($flag, $approve = true, $remark = "") {
|
||||||
|
return CQAPI::processAPI($this->connection, [
|
||||||
|
'action' => $this->getActionName(__FUNCTION__),
|
||||||
|
'params' => [
|
||||||
|
'flag' => $flag,
|
||||||
|
'approve' => $approve,
|
||||||
|
'remark' => $remark
|
||||||
|
]
|
||||||
|
], $this->callback);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setGroupAddRequest($flag, $sub_type, $approve = true, $reason = "") {
|
||||||
|
return CQAPI::processAPI($this->connection, [
|
||||||
|
'action' => $this->getActionName(__FUNCTION__),
|
||||||
|
'params' => [
|
||||||
|
'flag' => $flag,
|
||||||
|
'sub_type' => $sub_type,
|
||||||
|
'approve' => $approve,
|
||||||
|
'reason' => $reason
|
||||||
|
]
|
||||||
|
], $this->callback);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getLoginInfo() {
|
||||||
|
return CQAPI::processAPI($this->connection, ['action' => $this->getActionName(__FUNCTION__)], $this->callback);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getStrangerInfo($user_id, $no_cache = false) {
|
||||||
|
return CQAPI::processAPI($this->connection, [
|
||||||
|
'action' => $this->getActionName(__FUNCTION__),
|
||||||
|
'params' => [
|
||||||
|
'user_id' => $user_id,
|
||||||
|
'no_cache' => $no_cache
|
||||||
|
]
|
||||||
|
], $this->callback);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getFriendList() {
|
||||||
|
return CQAPI::processAPI($this->connection, [
|
||||||
|
'action' => $this->getActionName(__FUNCTION__)
|
||||||
|
], $this->callback);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getGroupList() {
|
||||||
|
return CQAPI::processAPI($this->connection, [
|
||||||
|
'action' => $this->getActionName(__FUNCTION__)
|
||||||
|
], $this->callback);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getGroupInfo($group_id, $no_cache = false) {
|
||||||
|
return CQAPI::processAPI($this->connection, [
|
||||||
|
'action' => $this->getActionName(__FUNCTION__),
|
||||||
|
'params' => [
|
||||||
|
'group_id' => $group_id,
|
||||||
|
'no_cache' => $no_cache
|
||||||
|
]
|
||||||
|
], $this->callback);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getGroupMemberInfo($group_id, $user_id, $no_cache = false) {
|
||||||
|
return CQAPI::processAPI($this->connection, [
|
||||||
|
'action' => $this->getActionName(__FUNCTION__),
|
||||||
|
'params' => [
|
||||||
|
'group_id' => $group_id,
|
||||||
|
'user_id' => $user_id,
|
||||||
|
'no_cache' => $no_cache
|
||||||
|
]
|
||||||
|
], $this->callback);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getGroupMemberList($group_id) {
|
||||||
|
return CQAPI::processAPI($this->connection, [
|
||||||
|
'action' => $this->getActionName(__FUNCTION__),
|
||||||
|
'params' => [
|
||||||
|
'group_id' => $group_id
|
||||||
|
]
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getCookies($domain = "") {
|
||||||
|
return CQAPI::processAPI($this->connection, [
|
||||||
|
'action' => $this->getActionName(__FUNCTION__),
|
||||||
|
'params' => [
|
||||||
|
'domain' => $domain
|
||||||
|
]
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getCsrfToken() {
|
||||||
|
return CQAPI::processAPI($this->connection, [
|
||||||
|
'action' => $this->getActionName(__FUNCTION__)
|
||||||
|
], $this->callback);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getCredentials($domain = "") {
|
||||||
|
return CQAPI::processAPI($this->connection, [
|
||||||
|
'action' => $this->getActionName(__FUNCTION__),
|
||||||
|
'params' => [
|
||||||
|
'domain' => $domain
|
||||||
|
]
|
||||||
|
], $this->callback);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getRecord($file, $out_format, $full_path = false) {
|
||||||
|
return CQAPI::processAPI($this->connection, [
|
||||||
|
'action' => $this->getActionName(__FUNCTION__),
|
||||||
|
'params' => [
|
||||||
|
'file' => $file,
|
||||||
|
'out_format' => $out_format,
|
||||||
|
'full_path' => $full_path
|
||||||
|
]
|
||||||
|
], $this->callback);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getImage($file) {
|
||||||
|
return CQAPI::processAPI($this->connection, [
|
||||||
|
'action' => $this->getActionName(__FUNCTION__),
|
||||||
|
'params' => [
|
||||||
|
'file' => $file
|
||||||
|
]
|
||||||
|
], $this->callback);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function canSendImage() {
|
||||||
|
return CQAPI::processAPI($this->connection, [
|
||||||
|
'action' => $this->getActionName(__FUNCTION__)
|
||||||
|
], $this->callback);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function canSendRecord() {
|
||||||
|
return CQAPI::processAPI($this->connection, [
|
||||||
|
'action' => $this->getActionName(__FUNCTION__)
|
||||||
|
], $this->callback);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getStatus() {
|
||||||
|
return CQAPI::processAPI($this->connection, [
|
||||||
|
'action' => $this->getActionName(__FUNCTION__)
|
||||||
|
], $this->callback);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getVersionInfo() {
|
||||||
|
return CQAPI::processAPI($this->connection, [
|
||||||
|
'action' => $this->getActionName(__FUNCTION__)
|
||||||
|
], $this->callback);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setRestartPlugin($delay = 0) {
|
||||||
|
return CQAPI::processAPI($this->connection, [
|
||||||
|
'action' => $this->getActionName(__FUNCTION__),
|
||||||
|
'params' => [
|
||||||
|
'delay' => $delay
|
||||||
|
]
|
||||||
|
], $this->callback);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function cleanDataDir($data_dir) {
|
||||||
|
return CQAPI::processAPI($this->connection, [
|
||||||
|
'action' => $this->getActionName(__FUNCTION__),
|
||||||
|
'params' => [
|
||||||
|
'data_dir' => $data_dir
|
||||||
|
]
|
||||||
|
], $this->callback);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function cleanPluginLog() {
|
||||||
|
return CQAPI::processAPI($this->connection, [
|
||||||
|
'action' => $this->getActionName(__FUNCTION__)
|
||||||
|
], $this->callback);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getExperimentAPI() {
|
||||||
|
return new ZMRobotExperiment($this->connection, $this->callback, $this->prefix);
|
||||||
|
}
|
||||||
|
|
||||||
|
private function getActionName(string $method) {
|
||||||
|
$prefix = ($this->prefix == self::API_ASYNC ? '_async' : ($this->prefix == self::API_RATE_LIMITED ? '_rate_limited' : ''));
|
||||||
|
$func_name = strtolower(preg_replace('/(?<=[a-z])([A-Z])/', '_$1', $method));
|
||||||
|
return $prefix . $func_name;
|
||||||
|
}
|
||||||
|
}
|
||||||
104
src/ZM/Utils/ZMRobotExperiment.php
Normal file
104
src/ZM/Utils/ZMRobotExperiment.php
Normal file
@@ -0,0 +1,104 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
|
||||||
|
namespace ZM\Utils;
|
||||||
|
|
||||||
|
|
||||||
|
use ZM\API\CQAPI;
|
||||||
|
use ZM\Connection\CQConnection;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class ZMRobotExperiment
|
||||||
|
* @package ZM\Utils
|
||||||
|
* @since 1.2
|
||||||
|
*/
|
||||||
|
class ZMRobotExperiment
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var CQConnection
|
||||||
|
*/
|
||||||
|
private $connection;
|
||||||
|
|
||||||
|
private $callback = null;
|
||||||
|
private $prefix = 0;
|
||||||
|
|
||||||
|
public function __construct(CQConnection $connection, $callback, $prefix) {
|
||||||
|
$this->connection = $connection;
|
||||||
|
$this->callback = $callback;
|
||||||
|
$this->prefix = $prefix;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setCallback($callback = true) {
|
||||||
|
$this->callback = $callback;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setPrefix($prefix = ZMRobot::API_NORMAL) {
|
||||||
|
$this->prefix = $prefix;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getFriendList($flat = false) {
|
||||||
|
return CQAPI::processAPI($this->connection, [
|
||||||
|
'action' => '_' . $this->getActionName(__FUNCTION__),
|
||||||
|
'params' => [
|
||||||
|
'flat' => $flat
|
||||||
|
]
|
||||||
|
], $this->callback);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getGroupInfo($group_id) {
|
||||||
|
return CQAPI::processAPI($this->connection, [
|
||||||
|
'action' => '_' . $this->getActionName(__FUNCTION__),
|
||||||
|
'params' => [
|
||||||
|
'group_id' => $group_id
|
||||||
|
]
|
||||||
|
], $this->callback);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getVipInfo($user_id) {
|
||||||
|
return CQAPI::processAPI($this->connection, [
|
||||||
|
'action' => '_' . $this->getActionName(__FUNCTION__),
|
||||||
|
'params' => [
|
||||||
|
'user_id' => $user_id
|
||||||
|
]
|
||||||
|
], $this->callback);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getGroupNotice($group_id) {
|
||||||
|
return CQAPI::processAPI($this->connection, [
|
||||||
|
'action' => '_' . $this->getActionName(__FUNCTION__),
|
||||||
|
'params' => [
|
||||||
|
'group_id' => $group_id
|
||||||
|
]
|
||||||
|
], $this->callback);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function sendGroupNotice($group_id, $title, $content) {
|
||||||
|
return CQAPI::processAPI($this->connection, [
|
||||||
|
'action' => '_' . $this->getActionName(__FUNCTION__),
|
||||||
|
'params' => [
|
||||||
|
'group_id' => $group_id,
|
||||||
|
'title' => $title,
|
||||||
|
'content' => $content
|
||||||
|
]
|
||||||
|
], $this->callback);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setRestart($clean_log = false, $clean_cache = false, $clean_event = false) {
|
||||||
|
return CQAPI::processAPI($this->connection, [
|
||||||
|
'action' => '_' . $this->getActionName(__FUNCTION__),
|
||||||
|
'params' => [
|
||||||
|
'clean_log' => $clean_log,
|
||||||
|
'clean_cache' => $clean_cache,
|
||||||
|
'clean_event' => $clean_event
|
||||||
|
]
|
||||||
|
], $this->callback);
|
||||||
|
}
|
||||||
|
|
||||||
|
private function getActionName(string $method) {
|
||||||
|
$prefix = ($this->prefix == ZMRobot::API_ASYNC ? '_async' : ($this->prefix == ZMRobot::API_RATE_LIMITED ? '_rate_limited' : ''));
|
||||||
|
$func_name = strtolower(preg_replace('/(?<=[a-z])([A-Z])/', '_$1', $method));
|
||||||
|
return $prefix . $func_name;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -14,25 +14,26 @@ class ZMUtil
|
|||||||
* 检查workerStart是否运行结束
|
* 检查workerStart是否运行结束
|
||||||
*/
|
*/
|
||||||
public static function checkWait() {
|
public static function checkWait() {
|
||||||
if(ZMBuf::isset("wait_start")) {
|
if (ZMBuf::isset("wait_start")) {
|
||||||
ZMBuf::append("wait_start", Co::getCid());
|
ZMBuf::append("wait_start", Co::getCid());
|
||||||
Co::suspend();
|
Co::suspend();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function stop() {
|
public static function stop($without_shutdown = false) {
|
||||||
Console::info(Console::setColor("Stopping server...", "red"));
|
Console::info(Console::setColor("Stopping server...", "red"));
|
||||||
foreach (ZMBuf::$server->connections as $v) {
|
foreach (ZMBuf::$server->connections as $v) {
|
||||||
ZMBuf::$server->close($v);
|
ZMBuf::$server->close($v);
|
||||||
}
|
}
|
||||||
DataProvider::saveBuffer();
|
DataProvider::saveBuffer();
|
||||||
ZMBuf::$server->shutdown();
|
if (!$without_shutdown)
|
||||||
|
ZMBuf::$server->shutdown();
|
||||||
ZMBuf::$server->stop();
|
ZMBuf::$server->stop();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function getHttpCodePage(int $http_code) {
|
public static function getHttpCodePage(int $http_code) {
|
||||||
if(isset(ZMBuf::globals("http_default_code_page")[$http_code])) {
|
if (isset(ZMBuf::globals("http_default_code_page")[$http_code])) {
|
||||||
return Co::readFile(DataProvider::getResourceFolder()."html/".ZMBuf::globals("http_default_code_page")[$http_code]);
|
return Co::readFile(DataProvider::getResourceFolder() . "html/" . ZMBuf::globals("http_default_code_page")[$http_code]);
|
||||||
} else return null;
|
} else return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -68,4 +69,13 @@ class ZMUtil
|
|||||||
}
|
}
|
||||||
return ["type" => $type, "params" => $array, "start" => $start, "end" => $end];
|
return ["type" => $type, "params" => $array, "start" => $start, "end" => $end];
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
public static function getModInstance($class) {
|
||||||
|
if (!isset(ZMBuf::$instance[$class])) {
|
||||||
|
ZMBuf::$instance[$class] = new $class();
|
||||||
|
return ZMBuf::$instance[$class];
|
||||||
|
} else {
|
||||||
|
return ZMBuf::$instance[$class];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user