mirror of
https://github.com/zhamao-robot/zhamao-framework.git
synced 2026-03-17 20:54:52 +08:00
Finished single websocket framework. It works.
完成了全反向websocket框架,全面支持多机器人
This commit is contained in:
parent
ab6408e0eb
commit
2de4337600
@ -101,5 +101,6 @@ $ php start.php</pre>
|
||||
获得过:<br>
|
||||
计算机应用能力大赛二等奖<br>
|
||||
溢达全国创意大赛一等奖<br>
|
||||
未来可能会拿到全国计算机设计大赛的奖
|
||||
</p>
|
||||
如有任何问题可以随时戳死作者哦
|
||||
|
||||
@ -19,24 +19,27 @@ class CQBot
|
||||
|
||||
public $starttime;
|
||||
public $endtime;
|
||||
public $current_id;
|
||||
|
||||
public function __construct(Framework $framework){
|
||||
public function __construct(Framework $framework, $package) {
|
||||
$this->starttime = microtime(true);
|
||||
$this->framework = $framework;
|
||||
}
|
||||
|
||||
public function execute($it){
|
||||
$this->data = $it;
|
||||
if ($it["post_type"] == "message") {
|
||||
$this->data = $package;
|
||||
$this->current_id = $this->data["self_id"];
|
||||
if ($package["post_type"] == "message") {
|
||||
try {
|
||||
$this->callTask($it);
|
||||
$this->callTask($package);
|
||||
} catch (\Exception $e) {
|
||||
CQUtil::errorLog("请求执行任务时异常\n" . $e->getMessage());
|
||||
CQUtil::sendDebugMsg("引起异常的消息:\n" . $it["message"]);
|
||||
CQUtil::errorLog("请求执行任务时异常\n" . $e->getMessage(), $this->current_id);
|
||||
CQUtil::sendDebugMsg("引起异常的消息:\n" . $package["message"], $this->current_id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function execute($it) {
|
||||
|
||||
}
|
||||
|
||||
public function callTask($it){
|
||||
if ($this->data["post_type"] == "message") {
|
||||
foreach(Buffer::get("mods") as $v){
|
||||
@ -69,7 +72,8 @@ class CQBot
|
||||
break;
|
||||
case "discuss":
|
||||
$reply = json_encode(["action" => "send_discuss_msg", "params" => ["discuss_id" => $this->data["discuss_id"], "message" => $msg]]);
|
||||
if (CQUtil::APIPush($reply)) {
|
||||
$connect = CQUtil::getApiConnectionByQQ($this->current_id);
|
||||
if (CQUtil::sendAPI($connect->fd, $reply, ["send_discuss_msg"])) {
|
||||
$out_count = Buffer::$out_count->get();
|
||||
if (Buffer::$data["info_level"] == 2) {
|
||||
Console::put("************API PUSHED***********");
|
||||
@ -88,12 +92,12 @@ class CQBot
|
||||
|
||||
public function sendGroupMsg($groupId, $msg){
|
||||
$this->function_called = true;
|
||||
CQUtil::sendGroupMsg($groupId, $msg);
|
||||
CQUtil::sendGroupMsg($groupId, $msg, $this->current_id);
|
||||
}
|
||||
|
||||
public function sendPrivateMsg($userId, $msg){
|
||||
$this->function_called = true;
|
||||
CQUtil::sendPrivateMsg($userId, $msg);
|
||||
CQUtil::sendPrivateMsg($userId, $msg, $this->current_id);
|
||||
}
|
||||
|
||||
public function isAdmin($user){
|
||||
|
||||
@ -42,14 +42,15 @@ class Framework
|
||||
|
||||
public function setInfoLevel($level){ $this->info_level = $level; }
|
||||
|
||||
public function setSuperUser($option) { self::$super_user = $option; }
|
||||
|
||||
public function eventServerStart(){ $this->event->start(); }
|
||||
|
||||
public static function getInstance(){ return self::$obj; }
|
||||
|
||||
public function init($option = []){
|
||||
public function init() {
|
||||
$this->selfCheck();
|
||||
$this->checkFiles();
|
||||
self::$super_user = $option;
|
||||
Console::info("CQBot Framework starting...");
|
||||
$this->event = new \swoole_websocket_server($this->host, $this->event_port);
|
||||
|
||||
@ -96,16 +97,11 @@ class Framework
|
||||
self::$obj = $this;
|
||||
$this->run_time = time();
|
||||
Buffer::set("info_level", $this->info_level);//设置info等级
|
||||
Buffer::$event = $server;
|
||||
require_once(WORKING_DIR . "src/cqbot/loader.php");
|
||||
new WorkerStartEvent($server, $worker_id);
|
||||
}
|
||||
|
||||
/**
|
||||
* 回调函数:API连接升级为WebSocket时候调用,可用于成功和酷Qhttp建立连接的检测依据
|
||||
* @param $cli
|
||||
*/
|
||||
public function onUpgrade($cli){ new ApiUpgradeEvent($cli); }
|
||||
|
||||
/**
|
||||
* 回调函数:有客户端或HTTP插件反向客户端连接时调用
|
||||
* @param swoole_websocket_server $server
|
||||
@ -113,7 +109,13 @@ class Framework
|
||||
*/
|
||||
public function onEventOpen(\swoole_websocket_server $server, \swoole_http_request $request){ new WSOpenEvent($server, $request); }
|
||||
|
||||
/**
|
||||
* 回调函数:断开连接时候回调的函数
|
||||
* @param swoole_server $server
|
||||
* @param int $fd
|
||||
*/
|
||||
public function onEventClose(\swoole_server $server, int $fd) { new WSCloseEvent($server, $fd); }
|
||||
|
||||
/**
|
||||
* 回调函数:当HTTP插件发来json包后激活此函数
|
||||
* @param swoole_websocket_server $server
|
||||
@ -130,13 +132,6 @@ class Framework
|
||||
*/
|
||||
public function onRequest($request, $response){ new HTTPEvent($request, $response); }
|
||||
|
||||
/**
|
||||
* 回调函数:API响应函数,用于发送api请求后返回的状态包的检查,比如rescode = 200
|
||||
* @param swoole_http_client $client
|
||||
* @param $frame
|
||||
*/
|
||||
public function onApiMessage($client, $frame){ new ApiMessageEvent($client, $frame); }
|
||||
|
||||
/**
|
||||
* 回调函数:异步计时器,一秒执行一次。请勿在此使用过多的阻塞方法
|
||||
* @param $id
|
||||
|
||||
@ -1,15 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Created by PhpStorm.
|
||||
* User: jerry
|
||||
* Date: 2018/5/26
|
||||
* Time: 下午4:01
|
||||
*/
|
||||
|
||||
class ApiMessageEvent extends Event
|
||||
{
|
||||
public function __construct(swoole_http_client $client, swoole_websocket_frame $frame) {
|
||||
$res = json_decode($frame->data, true);
|
||||
if (isset($res["echo"])) APIHandler::execute($res["echo"], $res);
|
||||
}
|
||||
}
|
||||
@ -1,55 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Created by PhpStorm.
|
||||
* User: jerry
|
||||
* Date: 2018/5/26
|
||||
* Time: 下午3:54
|
||||
*/
|
||||
|
||||
class ApiUpgradeEvent extends Event
|
||||
{
|
||||
public function __construct(swoole_http_client $cli) {
|
||||
Console::info("Upgraded API websocket");
|
||||
if(!$this->getFramework()->api->isConnected()) {
|
||||
echo "API connection lost.\nI will try next time after 30 second.\n";
|
||||
|
||||
//这里本来该用异步计时器的,但是我太懒了,直接睡30秒先。
|
||||
//需要改用异步计时器的话,告诉我我会改的233333。
|
||||
sleep(30);
|
||||
$this->getFramework()->api = new \swoole_http_client($this->getFramework()->host, $this->getFramework()->api_port);
|
||||
$this->getFramework()->api->set(['websocket_mask' => true]);
|
||||
$this->getFramework()->api->on('message', [$this->getFramework(), "onApiMessage"]);
|
||||
$this->getFramework()->api->on("close", function ($cli){
|
||||
Console::info(Console::setColor("API connection closed", "red"));
|
||||
});
|
||||
$this->getFramework()->api->upgrade('/api/', [$this->getFramework(), "onUpgrade"]);
|
||||
return;
|
||||
}
|
||||
Buffer::$api = $this->getFramework()->api;
|
||||
Buffer::$event = $this->getFramework()->event;
|
||||
if ($data = file(CONFIG_DIR . "log/last_error.log")) {
|
||||
$last_time = file_get_contents(CONFIG_DIR . "log/error_flag");
|
||||
if (time() - $last_time < 2) {
|
||||
CQUtil::sendDebugMsg("检测到重复引起异常,停止服务器", 0);
|
||||
file_put_contents(CONFIG_DIR."log/last_error.log", "");
|
||||
$this->getFramework()->event->shutdown();
|
||||
return;
|
||||
}
|
||||
CQUtil::sendDebugMsg("检测到异常", 0);
|
||||
$msg = "";
|
||||
foreach ($data as $e) {
|
||||
$msg = $msg . $e . "\n";
|
||||
}
|
||||
CQUtil::sendDebugMsg($msg, 0);
|
||||
CQUtil::sendDebugMsg("[CQBot] 成功开启!", 0);
|
||||
file_put_contents(CONFIG_DIR . "error_flag", time());
|
||||
file_put_contents(CONFIG_DIR . "last_error.log", "");
|
||||
}
|
||||
else {
|
||||
CQUtil::sendDebugMsg("[CQBot] 成功开启!", 0);
|
||||
}
|
||||
CQUtil::sendAPI("_get_friend_list", ["get_friend_list"]);
|
||||
CQUtil::sendAPI("get_group_list", ["get_group_list"]);
|
||||
CQUtil::sendAPI("get_version_info", ["get_version_info"]);
|
||||
}
|
||||
}
|
||||
@ -9,6 +9,11 @@
|
||||
class WSCloseEvent extends Event
|
||||
{
|
||||
public function __construct(swoole_server $server, int $fd) {
|
||||
|
||||
$connect = CQUtil::getConnection($fd);
|
||||
if ($connect->getPair() !== null) {
|
||||
$connect->getPair()->setPair(null);
|
||||
$connect->setPair(null);
|
||||
}
|
||||
unset(Buffer::$connect[$fd]);
|
||||
}
|
||||
}
|
||||
@ -9,30 +9,68 @@
|
||||
class WSMessageEvent extends Event
|
||||
{
|
||||
public function __construct(swoole_websocket_server $server, swoole_websocket_frame $frame) {
|
||||
$in_count = Buffer::$in_count->get();
|
||||
Buffer::$in_count->add(1);
|
||||
$req = json_decode($frame->data, true);
|
||||
if (Buffer::$data["info_level"] == 2) {
|
||||
Console::put("************EVENT RECEIVED***********");
|
||||
Console::put("msg_id = " . $in_count);
|
||||
Console::put("worker_id = " . $server->worker_id);
|
||||
if (isset($req["echo"])) if (APIHandler::execute($req["echo"], $req)) return;
|
||||
if (isset($req["echo"]["type"]) && $req["echo"]["type"] === "handshake") {
|
||||
$fd_id = $frame->fd;
|
||||
$connect = CQUtil::getConnection($fd_id);
|
||||
$connect->setQQ($req["user_id"]);
|
||||
$connect->setType(1);
|
||||
$connect->findSub();
|
||||
if ($data = file(CONFIG_DIR . "log/last_error.log")) {
|
||||
$last_time = file_get_contents(CONFIG_DIR . "log/error_flag");
|
||||
if (time() - $last_time < 2) {
|
||||
CQUtil::sendDebugMsg("检测到重复引起异常,停止服务器", $req["user_id"], 0);
|
||||
file_put_contents(CONFIG_DIR . "log/last_error.log", "");
|
||||
$this->getFramework()->event->shutdown();
|
||||
return;
|
||||
}
|
||||
CQUtil::sendDebugMsg("检测到异常", $req["user_id"], 0);
|
||||
$msg = "";
|
||||
foreach ($data as $e) {
|
||||
$msg = $msg . $e . "\n";
|
||||
}
|
||||
CQUtil::sendDebugMsg($msg, $req["user_id"], 0);
|
||||
CQUtil::sendDebugMsg("[CQBot] 成功开启!", $req["user_id"], 0);
|
||||
file_put_contents(CONFIG_DIR . "error_flag", time());
|
||||
file_put_contents(CONFIG_DIR . "last_error.log", "");
|
||||
} else {
|
||||
CQUtil::sendDebugMsg("[CQBot] 成功开启!", $req["user_id"], 0);
|
||||
}
|
||||
CQUtil::sendAPI($frame->fd, "_get_friend_list", ["get_friend_list"]);
|
||||
CQUtil::sendAPI($frame->fd, "get_group_list", ["get_group_list"]);
|
||||
CQUtil::sendAPI($frame->fd, "get_version_info", ["get_version_info"]);
|
||||
return;
|
||||
}
|
||||
if (Buffer::$data["info_level"] >= 1) {
|
||||
$type = $req["post_type"] == "message" ? ($req["message_type"] == "group" ? "GROUP_MSG:" . $req["group_id"] : ($req["message_type"] == "private" ? "PRIVATE_MSG" : "DISCUSS_MSG:" . $req["discuss_id"])) : strtoupper($req["post_type"]);
|
||||
Console::put(Console::setColor(date("H:i:s"), "green") . Console::setColor(" [$in_count]" . $type, "lightlightblue") . Console::setColor(" " . $req["user_id"], "yellow") . Console::setColor(" > ", "gray") . ($req["post_type"] == "message" ? $req["message"] : Console::setColor(CQUtil::executeType($req), "gold")));
|
||||
}
|
||||
//传入业务逻辑:CQBot
|
||||
try {
|
||||
$c = new CQBot($this->getFramework());
|
||||
$c->execute($req);
|
||||
$c->endtime = microtime(true);
|
||||
$value = $c->endtime - $c->starttime;
|
||||
Console::debug("Using time: ".$value);
|
||||
if(Buffer::get("time_send") === true)
|
||||
CQUtil::sendDebugMsg("Using time: ".$value);
|
||||
} catch (Exception $e) {
|
||||
CQUtil::errorlog("处理消息时异常,消息处理中断\n" . $e->getMessage() . "\n" . $e->getTraceAsString());
|
||||
CQUtil::sendDebugMsg("引起异常的消息:\n" . var_export($req, true));
|
||||
$connect = CQUtil::getConnection($frame->fd);
|
||||
switch ($connect->getType()) {
|
||||
case 0:
|
||||
$connect->setQQ($req["self_id"]);
|
||||
$connect->findSub();
|
||||
$in_count = Buffer::$in_count->get();
|
||||
Buffer::$in_count->add(1);
|
||||
if (Buffer::$data["info_level"] == 2) {
|
||||
Console::put("************EVENT RECEIVED***********");
|
||||
Console::put("msg_id = " . $in_count);
|
||||
Console::put("worker_id = " . $server->worker_id);
|
||||
}
|
||||
if (Buffer::$data["info_level"] >= 1) {
|
||||
$type = $req["post_type"] == "message" ? ($req["message_type"] == "group" ? "GROUP_MSG:" . $req["group_id"] : ($req["message_type"] == "private" ? "PRIVATE_MSG" : "DISCUSS_MSG:" . $req["discuss_id"])) : strtoupper($req["post_type"]);
|
||||
Console::put(Console::setColor(date("H:i:s"), "green") . Console::setColor(" [$in_count]" . $type, "lightlightblue") . Console::setColor(" " . $req["user_id"], "yellow") . Console::setColor(" > ", "gray") . ($req["post_type"] == "message" ? $req["message"] : Console::setColor(CQUtil::executeType($req), "gold")));
|
||||
}
|
||||
//传入业务逻辑:CQBot
|
||||
try {
|
||||
$c = new CQBot($this->getFramework(), $req);
|
||||
$c->endtime = microtime(true);
|
||||
$value = $c->endtime - $c->starttime;
|
||||
Console::debug("Using time: " . $value);
|
||||
if (Buffer::get("time_send") === true)
|
||||
CQUtil::sendDebugMsg("Using time: " . $value, $req["self_id"]);
|
||||
} catch (Exception $e) {
|
||||
CQUtil::errorlog("处理消息时异常,消息处理中断\n" . $e->getMessage() . "\n" . $e->getTraceAsString(), $req["self_id"]);
|
||||
CQUtil::sendDebugMsg("引起异常的消息:\n" . var_export($req, true), $req['self_id']);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@ -8,5 +8,8 @@
|
||||
|
||||
class WSOpenEvent extends Event
|
||||
{
|
||||
public function __construct(swoole_websocket_server $server, swoole_http_request $request) { }
|
||||
public function __construct(swoole_websocket_server $server, swoole_http_request $request) {
|
||||
$fd = $request->fd;
|
||||
CQUtil::getConnection($fd);
|
||||
}
|
||||
}
|
||||
@ -20,15 +20,6 @@ class WorkerStartEvent extends Event
|
||||
$this->getFramework()->scheduler = new Scheduler($this->getFramework());
|
||||
$server->tick(1000, [$this->getFramework(), "processTick"]);
|
||||
|
||||
//API连接部分
|
||||
$this->getFramework()->api = new \swoole_http_client($this->getFramework()->host, $this->getFramework()->api_port);
|
||||
$this->getFramework()->api->set(['websocket_mask' => true]);
|
||||
$this->getFramework()->api->on('message', [$this->getFramework(), "onApiMessage"]);
|
||||
$this->getFramework()->api->on("close", function ($cli){
|
||||
Console::info(Console::setColor("API connection closed", "red"));
|
||||
});
|
||||
$this->getFramework()->api->upgrade('/api/', [$this->getFramework(), "onUpgrade"]);
|
||||
|
||||
Console::debug("master_pid = " . $server->master_pid);
|
||||
Console::debug("worker_id = " . $worker_id);
|
||||
Console::put("\n==========STARTUP DONE==========\n");
|
||||
|
||||
@ -10,10 +10,12 @@ class Group
|
||||
{
|
||||
private $group_id;
|
||||
private $group_name;
|
||||
private $self_id;
|
||||
//private $prefix;
|
||||
private $members = [];
|
||||
|
||||
public function __construct($group_id, $info) {
|
||||
public function __construct($group_id, $info, $self_id) {
|
||||
$this->self_id = $self_id;
|
||||
$this->group_id = $group_id;
|
||||
$this->group_name = $info["group_name"];
|
||||
//$this->prefix = $info["prefix"];
|
||||
@ -82,9 +84,17 @@ class Group
|
||||
* @param bool $with_members
|
||||
*/
|
||||
public function updateData($with_members = false) {
|
||||
CQUtil::sendAPI(["action" => "get_group_list"], ["update_group_info", $this->getGroupId()]);
|
||||
$connection = CQUtil::getApiConnectionByQQ($this->getSelfId());
|
||||
CQUtil::sendAPI($connection->fd, ["action" => "get_group_list"], ["update_group_info", $this->getGroupId()]);
|
||||
if ($with_members) {
|
||||
CQUtil::sendAPI(["action" => "get_group_member_list", "params" => ["group_id" => $this->getGroupId()]], ["update_group_member_list", strval($this->getGroupId())]);
|
||||
CQUtil::sendAPI($connection->fd, ["action" => "get_group_member_list", "params" => ["group_id" => $this->getGroupId()]], ["update_group_member_list", strval($this->getGroupId())]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function getSelfId() {
|
||||
return $this->self_id;
|
||||
}
|
||||
}
|
||||
@ -65,7 +65,7 @@ class GroupMember extends User
|
||||
* 返回用户是不是群管理员
|
||||
* @return bool
|
||||
*/
|
||||
public function isAdmin(){
|
||||
public function isAdmin() {
|
||||
return in_array($this->getRole(), ["owner", "admin"]);
|
||||
}
|
||||
|
||||
@ -82,7 +82,7 @@ class GroupMember extends User
|
||||
"card" => $card
|
||||
]
|
||||
];
|
||||
CQUtil::sendAPI($data, []);
|
||||
CQUtil::sendAPI(CQUtil::getApiConnectionByQQ($this->getGroup()->getSelfId())->fd, $data, []);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -123,9 +123,9 @@ class GroupMember extends User
|
||||
/**
|
||||
* 更新群组成员信息
|
||||
*/
|
||||
public function updateData(){
|
||||
public function updateData() {
|
||||
$user_id = $this->getId();
|
||||
CQUtil::sendAPI([
|
||||
CQUtil::sendAPI(CQUtil::getApiConnectionByQQ($this->getGroup()->getSelfId())->fd, [
|
||||
"action" => "get_group_member_info",
|
||||
"params" => [
|
||||
"group_id" => $this->getGroup()->getGroupId(),
|
||||
|
||||
148
src/cqbot/item/WSConnection.php
Normal file
148
src/cqbot/item/WSConnection.php
Normal file
@ -0,0 +1,148 @@
|
||||
<?php
|
||||
/**
|
||||
* Created by PhpStorm.
|
||||
* User: jerry
|
||||
* Date: 2018/6/13
|
||||
* Time: 8:10 PM
|
||||
*/
|
||||
|
||||
class WSConnection
|
||||
{
|
||||
public $fd;
|
||||
|
||||
/**
|
||||
* 0 = event连接
|
||||
* 1 = api连接
|
||||
* 默认为event连接,如果可以收到返回的get_status则标记为1
|
||||
* @var int
|
||||
*/
|
||||
protected $type = 0;
|
||||
|
||||
protected $server;
|
||||
|
||||
/** @var WSConnection */
|
||||
protected $pair = null;
|
||||
|
||||
protected $qq = "";
|
||||
|
||||
public function __construct(swoole_websocket_server $server, $fd) {
|
||||
$this->server = $server;
|
||||
$this->fd = $fd;
|
||||
$this->manageType();
|
||||
}
|
||||
|
||||
/**
|
||||
* 返回swoole server
|
||||
* @return swoole_websocket_server
|
||||
*/
|
||||
public function getServer() {
|
||||
return $this->server;
|
||||
}
|
||||
|
||||
/**
|
||||
* 返回本连接是什么类型的
|
||||
* @return int
|
||||
*/
|
||||
public function getType() {
|
||||
return $this->type;
|
||||
}
|
||||
|
||||
/**
|
||||
* 用来确认此连接是API还是event
|
||||
* 如果此fd连接是event,则不会返回任何信息,关于QQ的匹配,则会在接收入第一条消息后设置
|
||||
* 如果此连接是api,则此操作后,HTTP API会返回登录号的号码,如果返回了则标记此连接为api并记录这个api连接属于的QQ号
|
||||
*/
|
||||
private function manageType() {
|
||||
$this->server->push($this->fd, '{"action":"get_login_info","echo":{"type":"handshake"}}');
|
||||
}
|
||||
|
||||
/**
|
||||
* 返回此连接相关联的event连接,使用前需初始化完成
|
||||
* @return $this|null|WSConnection
|
||||
*/
|
||||
public function getEventConnection() {
|
||||
switch ($this->type) {
|
||||
case 0:
|
||||
return $this;
|
||||
case 1:
|
||||
return $this->pair;
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 返回此链接相关联的api连接,使用前需初始化完成
|
||||
* @return $this|null|WSConnection
|
||||
*/
|
||||
public function getApiConnection() {
|
||||
switch ($this->type) {
|
||||
case 0:
|
||||
return $this->pair;
|
||||
case 1:
|
||||
return $this;
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查此连接对应的QQ,此部分较为复杂,先留着
|
||||
* @param $qq
|
||||
*/
|
||||
public function manageQQ($qq) {
|
||||
//TODO
|
||||
}
|
||||
|
||||
/**
|
||||
* 返回此连接属于的QQ号
|
||||
* @return string
|
||||
*/
|
||||
public function getQQ() {
|
||||
return $this->qq;
|
||||
}
|
||||
|
||||
/**
|
||||
* 返回关联连接(experiment)
|
||||
* @return WSConnection
|
||||
*/
|
||||
public function getPair() {
|
||||
return $this->pair;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置关联连接
|
||||
* @param WSConnection $pair
|
||||
*/
|
||||
public function setPair(WSConnection $pair) {
|
||||
$this->pair = $pair;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $qq
|
||||
*/
|
||||
public function setQQ($qq) {
|
||||
$this->qq = $qq;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $type
|
||||
*/
|
||||
public function setType(int $type) {
|
||||
$this->type = $type;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public function findSub() {
|
||||
if ($this->qq != "") {
|
||||
foreach (CQUtil::getConnections() as $fd => $cn) {
|
||||
if ($cn->getQQ() == $this->qq && $cn->getType() != $this->getType()) {
|
||||
$this->setPair($cn);
|
||||
$cn->setPair($this);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -9,14 +9,14 @@
|
||||
class APIHandler
|
||||
{
|
||||
static function execute($cmd, $res = null) {
|
||||
if (!isset($cmd[0])) return;
|
||||
switch ($cmd[0]) {
|
||||
if (!isset($cmd["type"])) return false;
|
||||
switch ($cmd["type"]) {
|
||||
case "set_friend_add_request":
|
||||
$id = $cmd[1];
|
||||
$id = $cmd["params"][0];
|
||||
$msg = "Hi~你好!";
|
||||
$msg .= "\n第一次见面请多关照!";
|
||||
CQUtil::sendPrivateMsg($id, $msg);
|
||||
break;
|
||||
CQUtil::sendPrivateMsg($id, $msg, $cmd["self_id"]);
|
||||
return true;
|
||||
case "get_friend_list":
|
||||
$friend = $res["data"][0]["friends"];
|
||||
$list = [];
|
||||
@ -25,9 +25,9 @@ class APIHandler
|
||||
}
|
||||
Buffer::set("friend_list", $list);
|
||||
Console::put(Console::setColor("已读取" . count(Buffer::get("friend_list")) . "个好友", "blue"));
|
||||
break;
|
||||
return true;
|
||||
case "update_group_member_list":
|
||||
$group_id = $cmd[1];
|
||||
$group_id = $cmd["params"][0];
|
||||
$info_data = $res["data"];
|
||||
Console::info(Console::setColor("Updating group $group_id members, it will take several minutes.", "yellow"));
|
||||
foreach ($info_data as $k => $v) {
|
||||
@ -35,11 +35,11 @@ class APIHandler
|
||||
CQUtil::getGroup($group_id)->setMember($v["user_id"], $s);
|
||||
$s->updateData();
|
||||
}
|
||||
break;
|
||||
return true;
|
||||
case "update_group_member_info":
|
||||
$info_data = $res["data"];
|
||||
$group = $cmd[1];
|
||||
$user = $cmd[2];
|
||||
$group = $cmd["params"][0];
|
||||
$user = $cmd["params"][1];
|
||||
$g = CQUtil::getGroup($group);
|
||||
$member = $g->getMember($user);
|
||||
$member->setAttribute($info_data);
|
||||
@ -48,43 +48,44 @@ class APIHandler
|
||||
$member->setLastSentTime($info_data["last_sent_time"]);
|
||||
$member->setRole($info_data["role"]);
|
||||
Console::info("Updated group member information: " . $group . ":" . $user);
|
||||
break;
|
||||
return true;
|
||||
case "update_group_info":
|
||||
$group = $res["data"];
|
||||
$current = $cmd[1];
|
||||
$current = $cmd["params"][0];
|
||||
$list = [];
|
||||
foreach ($group as $k => $v) {
|
||||
$list[$v["group_id"]] = $group[$k];
|
||||
}
|
||||
if (!isset($list[$current]) && Buffer::array_key_exists("groups", $current)) {
|
||||
Buffer::unset("groups", $current);
|
||||
break;
|
||||
return true;
|
||||
}
|
||||
$g = CQUtil::getGroup($current);
|
||||
$g->setGroupName($list[$current]["group_name"]);
|
||||
$g->setPrefix($list[$current]["prefix"]);
|
||||
break;
|
||||
return true;
|
||||
case "get_group_member_list":
|
||||
$group_data = $res["data"];
|
||||
$ls = Buffer::get("group_list");
|
||||
$group_id = $cmd[1];
|
||||
$group_id = $cmd["params"][0];
|
||||
$ls[$group_id]["member"] = $group_data;
|
||||
$group = new Group($group_id, $ls[$group_id]);
|
||||
$group = new Group($group_id, $ls[$group_id], $cmd["self_id"]);
|
||||
//TODO: 添加获取API时多账号对群的实例化的支持
|
||||
Buffer::appendKey("groups", $group_id, $group);
|
||||
break;
|
||||
return true;
|
||||
case "get_group_list":
|
||||
$group = $res["data"];
|
||||
$list = [];
|
||||
foreach ($group as $k => $v) {
|
||||
$list[$v["group_id"]] = $group[$k];
|
||||
CQUtil::sendAPI(["action" => "get_group_member_list", "params" => ["group_id" => $v["group_id"]]], ["get_group_member_list", $v["group_id"]]);
|
||||
CQUtil::sendAPI(CQUtil::getApiConnectionByQQ($cmd["self_id"])->fd, ["action" => "get_group_member_list", "params" => ["group_id" => $v["group_id"]]], ["get_group_member_list", $v["group_id"]]);
|
||||
}
|
||||
Buffer::set("group_list", $list);
|
||||
Console::put(Console::setColor("已读取" . count(Buffer::get("group_list")) . "个群", "blue"));
|
||||
break;
|
||||
return true;
|
||||
case "get_version_info":
|
||||
Buffer::set("version_info", $res["data"]);
|
||||
break;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@ -25,6 +25,8 @@ class Buffer
|
||||
static $out_count;//发送消息数量
|
||||
/** @var \swoole_atomic $out_count */
|
||||
static $api_id;//API调用ID
|
||||
/** @var WSConnection[] */
|
||||
static $connect = [];
|
||||
|
||||
static function get($name){ return self::$data[$name] ?? null; }
|
||||
|
||||
|
||||
@ -18,7 +18,7 @@ class CQUtil
|
||||
Buffer::set("user", []);//清空用户列表
|
||||
Buffer::set("time_send", false);//发送Timing数据到管理群
|
||||
Buffer::set("cmd_prefix", DP::getJsonData("config.json")["cmd_prefix"] ?? "");//设置指令的前缀符号
|
||||
Buffer::set("res_code", file_get_contents(WORKING_DIR."src/cqbot/Framework.php"));
|
||||
Buffer::set("res_code", file_get_contents(WORKING_DIR . "src/cqbot/Framework.php"));
|
||||
}
|
||||
|
||||
public static function saveAllFiles() {
|
||||
@ -41,65 +41,48 @@ class CQUtil
|
||||
/**
|
||||
* 生成报错日志
|
||||
* @param $log
|
||||
* @param $self_id
|
||||
* @param string $head
|
||||
* @param int $send_debug_message
|
||||
*/
|
||||
public static function errorLog($log, $head = "ERROR", $send_debug_message = 1) {
|
||||
public static function errorLog($log, $self_id, $head = "ERROR", $send_debug_message = 1) {
|
||||
Console::error($log, ($head === "ERROR") ? null : "[" . $head . "] ");
|
||||
$time = date("Y-m-d H:i:s");
|
||||
$msg = "[$head @ $time]: $log\n";
|
||||
file_put_contents(DP::getDataFolder() . "log_error.txt", $msg, FILE_APPEND);
|
||||
if (self::checkAPIConnection() === -1) {
|
||||
file_put_contents(DP::getDataFolder() . "last_error.log", $msg, FILE_APPEND);
|
||||
} else {
|
||||
if ($send_debug_message)
|
||||
self::sendDebugMsg($msg, 0);
|
||||
}
|
||||
if ($send_debug_message)
|
||||
self::sendDebugMsg($msg, $self_id);
|
||||
}
|
||||
|
||||
/**
|
||||
* 发送调试信息到管理群(需先设置管理群号)
|
||||
* @param $msg
|
||||
* @param $self_id
|
||||
* @param int $need_head
|
||||
* @return null
|
||||
*/
|
||||
static function sendDebugMsg($msg, $need_head = 1) {
|
||||
if (Framework::$admin_group == "") return null;
|
||||
static function sendDebugMsg($msg, $self_id, $need_head = 1) {
|
||||
if (Framework::$admin_group[$self_id] == "") return null;
|
||||
if ($need_head)
|
||||
$data = CQMsg("[DEBUG] " . date("H:i:s") . ": " . $msg, "group", Framework::$admin_group);
|
||||
else
|
||||
$data = CQMsg($msg, "group", Framework::$admin_group);
|
||||
return self::APIPush($data);
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查API端口连接情况
|
||||
* @return int
|
||||
*/
|
||||
static function checkAPIConnection() {
|
||||
if (Buffer::$api === null) return -1;//在framework链接API之前
|
||||
if (Buffer::$api->isConnected() === false) {
|
||||
//链接被断开
|
||||
Buffer::$api->upgrade('/api/', function ($cli) {
|
||||
self::sendDebugMsg("API重新链接成功");
|
||||
self::APIPushDelayMsg();
|
||||
});
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
$connect = CQUtil::getApiConnectionByQQ($self_id);
|
||||
return self::sendAPI($connect->fd, $data, ["send_debug_msg"]);
|
||||
}
|
||||
|
||||
/**
|
||||
* 推送API,给API端口
|
||||
* @param $fd
|
||||
* @param $data
|
||||
* @return bool
|
||||
*/
|
||||
static function APIPush($data) {
|
||||
static function APIPush($fd, $data) {
|
||||
if ($data == null || $data == "") {
|
||||
Console::error("EMPTY DATA PUSH");
|
||||
return false;
|
||||
}
|
||||
if (self::checkAPIConnection() === -1) {
|
||||
/*if (self::checkAPIConnection() === -1) {
|
||||
//忽略掉framework链接API之前的消息
|
||||
self::errorlog("API推送失败,未发送的消息: \n" . $data, "API ERROR", 0);
|
||||
return false;
|
||||
@ -107,20 +90,21 @@ class CQUtil
|
||||
if (self::checkAPIConnection() === 0) {
|
||||
self::APIPushAfterConnected($data);
|
||||
return true;
|
||||
}
|
||||
if (Buffer::$api->push($data) === false) {
|
||||
}*/
|
||||
if (Buffer::$event->push($fd, $data) === false) {
|
||||
$data = self::unicodeDecode($data);
|
||||
self::errorlog("API推送失败,未发送的消息: \n" . $data, "API ERROR", 0);
|
||||
self::sendErrorEmail("API推送失败", "未成功推送的消息:<br>$data<br>请检查酷q是否开启及网络链接情况<br>在此期间,机器人会中断所有消息处理<br>请及时处理");
|
||||
$connect = self::getConnection($fd);
|
||||
self::errorlog("API推送失败,未发送的消息: \n" . $data, $connect->getQQ(), "API ERROR", 0);
|
||||
self::sendErrorEmail("API推送失败", "未成功推送的消息:<br>$data<br>请检查酷q是否开启及网络链接情况<br>在此期间,机器人会中断所有消息处理<br>请及时处理", $connect->getQQ());
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 延迟推送在API连接断开后收到的消息函数
|
||||
* 延迟推送在API连接断开后收到的消息函数//待定
|
||||
*/
|
||||
static function APIPushDelayMsg() {
|
||||
/*static function APIPushDelayMsg() {
|
||||
$delay_push_list = Buffer::get("delay_push");
|
||||
$cur_time = time();
|
||||
foreach ($delay_push_list as $item) {
|
||||
@ -131,10 +115,10 @@ class CQUtil
|
||||
}
|
||||
}
|
||||
Buffer::set("delay_push", []);
|
||||
}
|
||||
}*/
|
||||
|
||||
/**
|
||||
* 推迟推送API,用于酷Q重启后的重新连接API
|
||||
* 推迟推送API,用于酷Q重启后的重新连接API//待定
|
||||
* @param $data
|
||||
*/
|
||||
static function APIPushAfterConnected($data) {
|
||||
@ -195,11 +179,12 @@ class CQUtil
|
||||
* @param $address
|
||||
* @param $title
|
||||
* @param $content
|
||||
* @param $self_id
|
||||
* @param string $name
|
||||
* @param int $send_debug_message
|
||||
* @return bool|string
|
||||
*/
|
||||
static function sendEmail($address, $title, $content, $name = "CQ开发团队", $send_debug_message = 1) {
|
||||
static function sendEmail($address, $title, $content, $self_id, $name = "CQ开发团队", $send_debug_message = 1) {
|
||||
$mail = new \PHPMailer(true);
|
||||
try {
|
||||
$mail->isSMTP();
|
||||
@ -228,12 +213,64 @@ class CQUtil
|
||||
unset($mail);
|
||||
return true;
|
||||
} catch (\Exception $e) {
|
||||
self::errorLog("发送邮件错误!错误信息:" . $info = $mail->ErrorInfo, "ERROR", $send_debug_message);
|
||||
self::errorLog("发送邮件错误!错误信息:" . $info = $mail->ErrorInfo, $self_id, "ERROR", $send_debug_message);
|
||||
unset($mail);
|
||||
return $info;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 返回所有api、event连接
|
||||
* @param string $type
|
||||
* @return WSConnection[]
|
||||
*/
|
||||
static function getConnections($type = "all") {
|
||||
switch ($type) {
|
||||
case "all":
|
||||
return Buffer::$connect;
|
||||
case "event":
|
||||
$ls = [];
|
||||
foreach (Buffer::$connect as $fd => $connection) {
|
||||
if ($connection->getType() === 0) {
|
||||
$ls[$fd] = $connection;
|
||||
}
|
||||
}
|
||||
return $ls;
|
||||
case "api":
|
||||
$ls = [];
|
||||
foreach (Buffer::$connect as $fd => $connection) {
|
||||
if ($connection->getType() === 1) {
|
||||
$ls[$fd] = $connection;
|
||||
}
|
||||
}
|
||||
return $ls;
|
||||
default:
|
||||
Console::error("寻找连接时链接类型传入错误!");
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $fd
|
||||
* @return WSConnection
|
||||
*/
|
||||
static function getConnection($fd) {
|
||||
if (!isset(Buffer::$connect[$fd])) {
|
||||
$s = new WSConnection(Buffer::$event, $fd);
|
||||
Buffer::$connect[$fd] = $s;
|
||||
}
|
||||
return Buffer::$connect[$fd];
|
||||
}
|
||||
|
||||
static function getApiConnectionByQQ($qq) {
|
||||
foreach (self::getConnections() as $fd => $c) {
|
||||
if ($c->getType() === 1 && $c->getQQ() == $qq) {
|
||||
return $c;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取运行时间
|
||||
* @param $time
|
||||
@ -313,10 +350,11 @@ class CQUtil
|
||||
* 此功能基于sendMail,请看上方sendMail函数的介绍
|
||||
* @param $title
|
||||
* @param $content
|
||||
* @param $self_id
|
||||
* @param string $name
|
||||
*/
|
||||
static function sendErrorEmail($title, $content, $name = "机器人错误提示") {
|
||||
self::sendEmail(["here your receive email address"], $title, $content, $name, 0);
|
||||
static function sendErrorEmail($title, $content, $self_id, $name = "机器人错误提示") {
|
||||
self::sendEmail(["here your receive email address"], $title, $content, $self_id, $name, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -375,14 +413,22 @@ class CQUtil
|
||||
* 发送群组消息,含控制台推出
|
||||
* @param $groupId
|
||||
* @param $msg
|
||||
* @param string $self_id
|
||||
* @return bool
|
||||
*/
|
||||
static function sendGroupMsg($groupId, $msg) {
|
||||
static function sendGroupMsg($groupId, $msg, $self_id) {
|
||||
$reply = ["action" => "send_group_msg", "params" => ["group_id" => $groupId, "message" => $msg]];
|
||||
$reply["echo"] = $reply;
|
||||
$reply["echo"]["time"] = time();
|
||||
$reply = json_encode($reply);
|
||||
if (self::APIPush($reply)) {
|
||||
$connections = CQUtil::getApiConnectionByQQ($self_id);
|
||||
if ($connections === null) {
|
||||
Console::error("未找到qq号:" . $self_id . "的API连接");
|
||||
return false;
|
||||
} else {
|
||||
$api_fd = $connections->fd;
|
||||
}
|
||||
if (self::sendAPI($api_fd, $reply, ["send_group_msg"])) {
|
||||
if (Buffer::$data["info_level"] == 1) {
|
||||
$out_count = Buffer::$out_count->get();
|
||||
Console::put(Console::setColor(date("H:i:s "), "lightpurple") . Console::setColor("[{$out_count}]GROUP", "blue") . Console::setColor(" " . $groupId, "yellow") . Console::setColor(" > ", "gray") . $msg);
|
||||
@ -397,14 +443,22 @@ class CQUtil
|
||||
* 发送私聊消息
|
||||
* @param $userId
|
||||
* @param $msg
|
||||
* @param $self_id
|
||||
* @return bool
|
||||
*/
|
||||
static function sendPrivateMsg($userId, $msg) {
|
||||
static function sendPrivateMsg($userId, $msg, $self_id) {
|
||||
$reply = ["action" => "send_private_msg", "params" => ["user_id" => $userId, "message" => $msg]];
|
||||
$reply["echo"] = $reply;
|
||||
$reply["echo"]["time"] = time();
|
||||
$reply = json_encode($reply);
|
||||
if (self::APIPush($reply)) {
|
||||
$connections = CQUtil::getApiConnectionByQQ($self_id);
|
||||
if ($connections === null) {
|
||||
Console::error("未找到qq号:" . $self_id . "的API连接");
|
||||
return false;
|
||||
} else {
|
||||
$api_fd = $connections->fd;
|
||||
}
|
||||
if (self::sendAPI($api_fd, $reply, ["send_private_msg"])) {
|
||||
if (Buffer::$data["info_level"] == 1) {
|
||||
$out_count = Buffer::$out_count->get();
|
||||
Console::put(Console::setColor(date("H:i:s "), "lightpurple") . Console::setColor("[{$out_count}]PRIVATE", "blue") . Console::setColor(" " . $userId, "yellow") . Console::setColor(" > ", "gray") . $msg);
|
||||
@ -423,50 +477,26 @@ class CQUtil
|
||||
/**
|
||||
* 发送其他API,HTTP插件支持的其他API都可以发送。
|
||||
* echo是返回内容,可以在APIHandler.php里面解析
|
||||
* @param $fd
|
||||
* @param $data
|
||||
* @param $echo
|
||||
* @return bool
|
||||
*/
|
||||
static function sendAPI($data, $echo) {
|
||||
static function sendAPI($fd, $data, $echo) {
|
||||
if (!is_array($data)) {
|
||||
$api = [];
|
||||
$api["action"] = $data;
|
||||
} else {
|
||||
$api = $data;
|
||||
}
|
||||
$rw = $echo;
|
||||
$echo = [
|
||||
"self_id" => self::getConnection($fd)->getQQ(),
|
||||
"type" => array_shift($rw),
|
||||
"params" => $rw
|
||||
];
|
||||
$api["echo"] = $echo;
|
||||
self::APIPush(json_encode($api));
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除一个和模块相关联的指令
|
||||
* @param $name
|
||||
* @return bool
|
||||
*/
|
||||
static function removeCommand($name) {
|
||||
$list = Buffer::get("commands");
|
||||
if (!isset($list[$name])) return false;
|
||||
unset($list[$name]);
|
||||
Buffer::set("commands", $list);
|
||||
DP::setJsonData("commands.json", $list);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加一个指令给非callTask方式激活的模块。
|
||||
* 注意:如果给callTask方式激活的模块添加指令,则在使用对应功能时会回复多次同样的内容
|
||||
* @param $name
|
||||
* @param $class
|
||||
* @return bool
|
||||
*/
|
||||
static function addCommand($name, $class) {
|
||||
if (!is_file(WORKING_DIR . 'src/cqbot/mods/' . $class . '.php')) {
|
||||
return false;
|
||||
}
|
||||
$list = Buffer::get("commands");
|
||||
$list[$name] = $class;
|
||||
DP::setJsonData("commands.json", $list);
|
||||
Buffer::set("commands", $list);
|
||||
return true;
|
||||
return self::APIPush($fd, json_encode($api));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -501,7 +531,7 @@ class CQUtil
|
||||
/**
|
||||
* 重启框架,此服务重启为全自动的
|
||||
*/
|
||||
static function reload(){
|
||||
static function reload() {
|
||||
Console::info("Reloading server");
|
||||
self::saveAllFiles();
|
||||
Buffer::$event->reload();
|
||||
@ -510,7 +540,7 @@ class CQUtil
|
||||
/**
|
||||
* 停止运行框架,需要用shell再次开启才能启动
|
||||
*/
|
||||
static function stop(){
|
||||
static function stop() {
|
||||
Console::info("Stopping server...");
|
||||
self::saveAllFiles();
|
||||
Buffer::$api->close();
|
||||
@ -610,7 +640,7 @@ class CQUtil
|
||||
* @param $group_id
|
||||
* @return Group|null
|
||||
*/
|
||||
static function getGroup($group_id){
|
||||
static function getGroup($group_id) {
|
||||
$d = Buffer::get("groups");
|
||||
return $d[$group_id] ?? null;
|
||||
}
|
||||
|
||||
219
start.php
219
start.php
@ -1,204 +1,11 @@
|
||||
<?php
|
||||
/**
|
||||
* Created by PhpStorm.
|
||||
* User: jerry
|
||||
* Date: 2018/3/29
|
||||
* Time: 11:13
|
||||
*/
|
||||
|
||||
date_default_timezone_set("Asia/Shanghai");
|
||||
|
||||
//工作目录设置
|
||||
define("WORKING_DIR", __DIR__ . "/");
|
||||
echo "工作目录:".WORKING_DIR."\n";
|
||||
define("CONFIG_DIR", WORKING_DIR . "config/");
|
||||
define("USER_DIR", WORKING_DIR . "users");
|
||||
|
||||
//启动时间
|
||||
define("START_TIME", time());
|
||||
@mkdir(CONFIG_DIR, 0777, true);
|
||||
@mkdir(USER_DIR, 0777, true);
|
||||
register_shutdown_function('handleFatal');
|
||||
function handleFatal() {
|
||||
$error = error_get_last();
|
||||
if (isset($error['type'])) {
|
||||
switch ($error['type']) {
|
||||
case E_ERROR :
|
||||
case E_PARSE :
|
||||
case E_CORE_ERROR :
|
||||
case E_COMPILE_ERROR :
|
||||
$time = date('Y-m-d H:i:s', time());
|
||||
$message = $error['message'];
|
||||
$file = $error['file'];
|
||||
$line = $error['line'];
|
||||
$log = "[$time] $message ($file:$line)\nStack trace:\n";
|
||||
$trace = debug_backtrace();
|
||||
foreach ($trace as $i => $t) {
|
||||
if (!isset($t['file'])) {
|
||||
$t['file'] = 'unknown';
|
||||
}
|
||||
if (!isset($t['line'])) {
|
||||
$t['line'] = 0;
|
||||
}
|
||||
if (!isset($t['function'])) {
|
||||
$t['function'] = 'unknown';
|
||||
}
|
||||
$log .= "#$i {$t['file']}({$t['line']}): ";
|
||||
if (isset($t['object']) and is_object($t['object'])) {
|
||||
$log .= get_class($t['object']) . '->';
|
||||
}
|
||||
$log .= "{$t['function']}()\n";
|
||||
}
|
||||
|
||||
file_put_contents(CONFIG_DIR . "last_error.log", $log);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function CQMsg($msg, $type, $id) {
|
||||
if ($type === "group") {
|
||||
$reply = ["action" => "send_group_msg", "params" => ["group_id" => $id, "message" => $msg]];
|
||||
$reply["echo"] = $reply;
|
||||
$reply["echo"]["time"] = time();
|
||||
$reply = json_encode($reply);
|
||||
} else if ($type === "private") {
|
||||
$reply = ["action" => "send_private_msg", "params" => ["user_id" => $id, "message" => $msg]];
|
||||
$reply["echo"] = $reply;
|
||||
$reply["echo"]["time"] = time();
|
||||
$reply = json_encode($reply);
|
||||
} else if ($type === "discuss") {
|
||||
$reply = ["action" => "send_discuss_msg", "params" => ["discuss_id" => $id, "message" => $msg]];
|
||||
$reply["echo"] = $reply;
|
||||
$reply["echo"]["time"] = time();
|
||||
$reply = json_encode($reply);
|
||||
} else {
|
||||
$reply = false;
|
||||
}
|
||||
return $reply;
|
||||
}
|
||||
|
||||
|
||||
|
||||
$host = "0.0.0.0";
|
||||
$api_host = "127.0.0.1";
|
||||
$api_port = 10000;
|
||||
$event_port = 20000;
|
||||
$admin_group = "";
|
||||
$info_level = 1;
|
||||
$super_user = [];
|
||||
|
||||
if (!file_exists(CONFIG_DIR . "config.json")) {
|
||||
file_put_contents(CONFIG_DIR . "config.json", json_encode([]));
|
||||
}
|
||||
$json = json_decode(file_get_contents(CONFIG_DIR . "config.json"), true);
|
||||
if (!isset($json["host"])) {
|
||||
echo "请输入你要监听的Event IP(默认0.0.0.0) :";
|
||||
$r = strtolower(trim(fgets(STDIN)));
|
||||
if ($r == "") {
|
||||
echo "监听地址:0.0.0.0(默认)\n";
|
||||
$json["host"] = $host;
|
||||
} else {
|
||||
$host = $r;
|
||||
echo "监听地址:" . $r . "\n";
|
||||
$json["host"] = $host;
|
||||
}
|
||||
} else {
|
||||
$host = $json["host"];
|
||||
}
|
||||
if (!isset($json["event_port"])) {
|
||||
a3:
|
||||
echo "请输入你要监听的Event端口(默认20000) :";
|
||||
$r = strtolower(trim(fgets(STDIN)));
|
||||
if ($r == "") {
|
||||
echo "监听地址:20000(默认)\n";
|
||||
$json["event_port"] = $event_port;
|
||||
} else {
|
||||
if (!is_numeric($r)) {
|
||||
echo "输入错误!请输入数字!(1-65535)\n";
|
||||
goto a3;
|
||||
}
|
||||
$event_port = $r;
|
||||
echo "监听地址:" . $r . "\n";
|
||||
$json["event_port"] = $event_port;
|
||||
}
|
||||
} else {
|
||||
$event_port = $json["event_port"];
|
||||
}
|
||||
if (!isset($json["api_host"])) {
|
||||
echo "请输入你要连接的api server IP(默认127.0.0.1) :";
|
||||
$r = strtolower(trim(fgets(STDIN)));
|
||||
if ($r == "") {
|
||||
echo "API地址:127.0.0.1(默认)\n";
|
||||
$json["api_host"] = $api_host;
|
||||
} else {
|
||||
$api_host = $r;
|
||||
echo "监听地址:" . $r . "\n";
|
||||
$json["api_host"] = $api_host;
|
||||
}
|
||||
} else {
|
||||
$api_host = $json["api_host"];
|
||||
}
|
||||
if (!isset($json["api_port"])) {
|
||||
a2:
|
||||
echo "请输入你要监听的API端口(默认10000) :";
|
||||
$r = strtolower(trim(fgets(STDIN)));
|
||||
if ($r == "") {
|
||||
echo "监听地址:10000(默认)\n";
|
||||
$json["api_port"] = $api_port;
|
||||
} else {
|
||||
if (!is_numeric($r)) {
|
||||
echo "输入错误!请输入数字!(1-65535)\n";
|
||||
goto a2;
|
||||
}
|
||||
$api_port = $r;
|
||||
echo "监听地址:" . $r . "\n";
|
||||
$json["api_port"] = $api_port;
|
||||
}
|
||||
} else {
|
||||
$api_port = $json["api_port"];
|
||||
}
|
||||
if (!isset($json["admin_group"])) {
|
||||
a4:
|
||||
echo "请输入你要设置的管理员群:";
|
||||
$r = strtolower(trim(fgets(STDIN)));
|
||||
if ($r == "") {
|
||||
echo "检测到你没有设置管理员群,本次跳过\n";
|
||||
} else {
|
||||
if (!is_numeric($r)) {
|
||||
echo "输入错误!请输入数字群号!\n";
|
||||
goto a4;
|
||||
}
|
||||
$admin_group = $r;
|
||||
echo "管理群:" . $r . "\n";
|
||||
$json["admin_group"] = $admin_group;
|
||||
}
|
||||
} else {
|
||||
$admin_group = $json["admin_group"];
|
||||
}
|
||||
|
||||
if (!isset($json["super_user"])) {
|
||||
a5:
|
||||
echo "请输入你要设置的高级管理员:";
|
||||
$r = strtolower(trim(fgets(STDIN)));
|
||||
if ($r == "") {
|
||||
echo "检测到你没有设置高级管理员,本次跳过\n";
|
||||
} else {
|
||||
if (!is_numeric($r)) {
|
||||
echo "输入错误!请输入数字QQ号!\n";
|
||||
goto a5;
|
||||
}
|
||||
$super_user[] = $r;
|
||||
echo "管理员:" . $r . "\n";
|
||||
$json["super_user"][] = $r;
|
||||
}
|
||||
} else {
|
||||
$super_user = $json["super_user"];
|
||||
}
|
||||
|
||||
file_put_contents(CONFIG_DIR."config.json", json_encode($json, 128 | 256));
|
||||
require("tools.php");
|
||||
|
||||
//loading projects
|
||||
require(WORKING_DIR . "src/cqbot/Framework.php");
|
||||
@ -206,11 +13,23 @@ require(WORKING_DIR . "src/cqbot/utils/Buffer.php");
|
||||
require(WORKING_DIR . "src/cqbot/utils/ErrorStatus.php");
|
||||
require(WORKING_DIR . "src/cqbot/utils/Console.php");
|
||||
|
||||
//初始参数设置:host、端口、多个机器人号对应的admin_group、事件等级、多个机器人号对应的超级管理员
|
||||
$properties["host"] = "0.0.0.0";
|
||||
$properties["port"] = 20000;
|
||||
$properties["admin_group"] = [];
|
||||
$properties["info_level"] = 1;
|
||||
$properties["super_user"] = [];
|
||||
|
||||
$json = json_decode(file_get_contents(CONFIG_DIR . "config.json"), true);
|
||||
|
||||
if (!isset($json["host"]) || !isset($json["port"])) setupWizard($json, $properties);
|
||||
|
||||
//initializing framework
|
||||
$cqbot = new Framework();
|
||||
$cqbot->setHost($host);
|
||||
$cqbot->setApiPort($api_port);
|
||||
$cqbot->setEventPort($event_port);
|
||||
$cqbot->setAdminGroup($admin_group);
|
||||
$cqbot->setInfoLevel($info_level);
|
||||
$cqbot->init($super_user);
|
||||
$cqbot->setHost($properties["host"]);
|
||||
$cqbot->setEventPort($properties["port"]);
|
||||
$cqbot->setAdminGroup($properties["admin_group"]);
|
||||
$cqbot->setInfoLevel($properties["info_level"]);
|
||||
$cqbot->setSuperUser($properties["super_user"]);
|
||||
$cqbot->init();
|
||||
$cqbot->eventServerStart();
|
||||
183
tools.php
Normal file
183
tools.php
Normal file
@ -0,0 +1,183 @@
|
||||
<?php
|
||||
/**
|
||||
* Created by PhpStorm.
|
||||
* User: jerry
|
||||
* Date: 2018/6/14
|
||||
* Time: 11:04 AM
|
||||
*/
|
||||
|
||||
date_default_timezone_set("Asia/Shanghai");
|
||||
|
||||
//启动时间
|
||||
define("START_TIME", time());
|
||||
@mkdir(CONFIG_DIR, 0777, true);
|
||||
@mkdir(USER_DIR, 0777, true);
|
||||
register_shutdown_function('handleFatal');
|
||||
|
||||
if (!file_exists(CONFIG_DIR . "config.json")) file_put_contents(CONFIG_DIR . "config.json", json_encode([]));
|
||||
|
||||
function handleFatal() {
|
||||
$error = error_get_last();
|
||||
if (isset($error['type'])) {
|
||||
switch ($error['type']) {
|
||||
case E_ERROR :
|
||||
case E_PARSE :
|
||||
case E_CORE_ERROR :
|
||||
case E_COMPILE_ERROR :
|
||||
$time = date('Y-m-d H:i:s', time());
|
||||
$message = $error['message'];
|
||||
$file = $error['file'];
|
||||
$line = $error['line'];
|
||||
$log = "[$time] $message ($file:$line)\nStack trace:\n";
|
||||
$trace = debug_backtrace();
|
||||
foreach ($trace as $i => $t) {
|
||||
if (!isset($t['file'])) {
|
||||
$t['file'] = 'unknown';
|
||||
}
|
||||
if (!isset($t['line'])) {
|
||||
$t['line'] = 0;
|
||||
}
|
||||
if (!isset($t['function'])) {
|
||||
$t['function'] = 'unknown';
|
||||
}
|
||||
$log .= "#$i {$t['file']}({$t['line']}): ";
|
||||
if (isset($t['object']) and is_object($t['object'])) {
|
||||
$log .= get_class($t['object']) . '->';
|
||||
}
|
||||
$log .= "{$t['function']}()\n";
|
||||
}
|
||||
|
||||
file_put_contents(CONFIG_DIR . "last_error.log", $log);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function CQMsg($msg, $type, $id) {
|
||||
if ($type === "group") {
|
||||
$reply = ["action" => "send_group_msg", "params" => ["group_id" => $id, "message" => $msg]];
|
||||
$reply["echo"] = $reply;
|
||||
$reply["echo"]["time"] = time();
|
||||
$reply = json_encode($reply);
|
||||
} else if ($type === "private") {
|
||||
$reply = ["action" => "send_private_msg", "params" => ["user_id" => $id, "message" => $msg]];
|
||||
$reply["echo"] = $reply;
|
||||
$reply["echo"]["time"] = time();
|
||||
$reply = json_encode($reply);
|
||||
} else if ($type === "discuss") {
|
||||
$reply = ["action" => "send_discuss_msg", "params" => ["discuss_id" => $id, "message" => $msg]];
|
||||
$reply["echo"] = $reply;
|
||||
$reply["echo"]["time"] = time();
|
||||
$reply = json_encode($reply);
|
||||
} else {
|
||||
$reply = false;
|
||||
}
|
||||
return $reply;
|
||||
}
|
||||
|
||||
function printHelp() {
|
||||
echo color("{gold}=====CQBot-swoole=====");
|
||||
echo color("{gold}* 首次使用设置 *");
|
||||
echo color("[{green}?{r}] {lightlightblue}查看此列表");
|
||||
echo color("[{green}1{r}] {yellow}设置监听地址");
|
||||
echo color("[{green}2{r}] {yellow}设置监听端口");
|
||||
echo color("[{green}3{r}] {yellow}设置管理群");
|
||||
echo color("[{green}4{r}] {yellow}设置管理员");
|
||||
echo color("[{green}5{r}] {lightlightblue}开始运行");
|
||||
}
|
||||
|
||||
function setupWizard(&$json, &$properties) {
|
||||
printHelp();
|
||||
while (true) {
|
||||
echo color("> ", "");
|
||||
$id = trim(fgets(STDIN));
|
||||
switch ($id) {
|
||||
case "1":
|
||||
echo color("请输入监听地址(默认0.0.0.0):", "");
|
||||
$host = trim(fgets(STDIN));
|
||||
if ($host == "") {
|
||||
$properties["host"] = "0.0.0.0";
|
||||
echo color("{gray}已设置地址:0.0.0.0(默认)");
|
||||
} else {
|
||||
$properties["host"] = $host;
|
||||
echo color("{gray}已设置地址:" . $host);
|
||||
}
|
||||
break;
|
||||
case "2":
|
||||
echo color("请输入监听端口(默认20000):", "");
|
||||
$host = trim(fgets(STDIN));
|
||||
if ($host == "") {
|
||||
$properties["port"] = 20000;
|
||||
echo color("{gray}已设置端口:20000(默认)");
|
||||
} else {
|
||||
$properties["port"] = $host;
|
||||
echo color("{gray}已设置端口:" . $host);
|
||||
}
|
||||
break;
|
||||
case "3":
|
||||
echo color("请输入机器人QQ号:", "");
|
||||
$self_id = trim(fgets(STDIN));
|
||||
if ($self_id == "") {
|
||||
echo color("{red}请勿输入空数据!");
|
||||
break;
|
||||
}
|
||||
echo color("请输入本机器人QQ的管理群(机器人必须已经在群内):", "");
|
||||
$group = trim(fgets(STDIN));
|
||||
if ($group == "") {
|
||||
echo color("{red}请勿输入空数据!");
|
||||
break;
|
||||
}
|
||||
$properties["admin_group"][$self_id][] = $group;
|
||||
echo color("{gray}已设置机器人" . $self_id . "的管理群:" . $group);
|
||||
break;
|
||||
case "4":
|
||||
echo color("请输入机器人QQ号:", "");
|
||||
$self_id = trim(fgets(STDIN));
|
||||
if ($self_id == "") {
|
||||
echo color("{red}请勿输入空数据!");
|
||||
break;
|
||||
}
|
||||
echo color("请输入本机器人QQ的管理员QQ:", "");
|
||||
$group = trim(fgets(STDIN));
|
||||
if ($group == "") {
|
||||
echo color("{red}请勿输入空数据!");
|
||||
break;
|
||||
}
|
||||
$properties["super_user"][$self_id][] = $group;
|
||||
echo color("{gray}已设置机器人" . $self_id . "的管理员:" . $group);
|
||||
break;
|
||||
case "5":
|
||||
break 2;
|
||||
case "?":
|
||||
case "?":
|
||||
printHelp();
|
||||
break;
|
||||
default:
|
||||
echo color("{red}请输入正确的编号进行操作!\n在设置监听端口和监听地址后可开始运行服务器");
|
||||
break;
|
||||
}
|
||||
}
|
||||
$json["host"] = $properties["host"];
|
||||
$json["port"] = $properties["port"];
|
||||
$json["admin_group"] = $properties["admin_group"];
|
||||
$json["super_user"] = $properties["super_user"];
|
||||
$json["info_level"] = $properties["info_level"];
|
||||
file_put_contents(CONFIG_DIR . "config.json", json_encode($json, 128 | 256));
|
||||
}
|
||||
|
||||
function color($str, $end = "\n") {
|
||||
$str = str_replace("{red}", "\e[38;5;203m", $str);
|
||||
$str = str_replace("{green}", "\e[38;5;83m", $str);
|
||||
$str = str_replace("{yellow}", "\e[38;5;227m", $str);
|
||||
$str = str_replace("{lightpurple}", "\e[38;5;207m", $str);
|
||||
$str = str_replace("{lightblue}", "\e[38;5;87m", $str);
|
||||
$str = str_replace("{gold}", "\e[38;5;214m", $str);
|
||||
$str = str_replace("{gray}", "\e[38;5;59m", $str);
|
||||
$str = str_replace("{pink}", "\e[38;5;207m", $str);
|
||||
$str = str_replace("{lightlightblue}", "\e[38;5;63m", $str);
|
||||
$str = str_replace("{r}", "\e[m", $str);
|
||||
$str .= "\e[m" . $end;
|
||||
return $str;
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user