From e1abed776c792f0eb64b60faa4091037dd4b9ec0 Mon Sep 17 00:00:00 2001 From: jerry Date: Sat, 28 Apr 2018 16:20:44 +0800 Subject: [PATCH] initial commit. It works! --- src/cqbot/CQBot.php | 44 +++---- src/cqbot/Framework.php | 161 +++++++++++++++++++++---- src/cqbot/User.php | 5 +- src/cqbot/loader.php | 1 + src/cqbot/mods/Admin.php | 51 +++++--- src/cqbot/mods/ModBase.php | 20 +++- src/cqbot/tasks/TickTask.php | 17 +++ src/cqbot/utils/APIHandler.php | 12 ++ src/cqbot/utils/Buffer.php | 9 +- src/cqbot/utils/CQUtil.php | 146 +++++++++++++--------- src/cqbot/utils/Console.php | 5 - src/cqbot/utils/DataProvider.php | 3 - src/cqbot/utils/ErrorStatus.php | 3 - start.php | 200 ++++++++++++++++++------------- 14 files changed, 445 insertions(+), 232 deletions(-) create mode 100644 src/cqbot/tasks/TickTask.php create mode 100644 src/cqbot/utils/APIHandler.php diff --git a/src/cqbot/CQBot.php b/src/cqbot/CQBot.php index 850cf2f2..b8079710 100755 --- a/src/cqbot/CQBot.php +++ b/src/cqbot/CQBot.php @@ -6,13 +6,6 @@ * Time: 10:43 */ -namespace cqbot; - - -use cqbot\mods\ModBase; -use cqbot\utils\Buffer; -use cqbot\utils\CQUtil; - class CQBot { /** @var Framework */ @@ -41,33 +34,26 @@ class CQBot CQUtil::errorLog("请求执行任务时异常\n" . $e->getMessage()); CQUtil::sendDebugMsg("引起异常的消息:\n" . $it["message"]); } - $msg_arr = explode("&&", $this->replace($it["message"], $it)); - foreach ($msg_arr as $item) { - $msg = trim($item); - $msg = explode(" ", $msg); - $this->checkFunction($msg, $it); - } } } - public function checkFunction($msgCut, $it){ - $cmdList = Buffer::get("commands"); - if (isset($cmdList[$msgCut[0]])) { - Console::debug("Call CQFunction:" . $msgCut[0]); - $temp = $cmdList[$msgCut[0]]; - /** @var ModBase $class */ - $class = new $temp($this, $it); - $class->execute($msgCut); - return true; - } - Console::debug("未找到指令:[" . $msgCut[0] . "]"); - return false; - } - public function callTask($it){ if ($this->data["post_type"] == "message") { - foreach(Buffer::get("mod_task") as $v){ - new $v($this, $this->data); + foreach(Buffer::get("mods") as $v){ + Console::info("Activating module ".$v); + /** @var ModBase $w */ + $w = new $v($this, $this->data); + if($w->call_task === false){ + $msg = trim($this->data["message"]); + $msg = explode(" ", $msg); + $prefix = Buffer::get("cmd_prefix"); + if($prefix != ""){ + if(mb_substr($msg[0],0,mb_strlen($prefix)) == $prefix){ + $msg[0] = mb_substr($msg[0], mb_strlen($prefix)); + } + } + $w->execute($msg); + } } } } diff --git a/src/cqbot/Framework.php b/src/cqbot/Framework.php index 218a91f0..5dd63b11 100755 --- a/src/cqbot/Framework.php +++ b/src/cqbot/Framework.php @@ -6,13 +6,9 @@ * Time: 11:16 */ -namespace cqbot; - -use cqbot\utils\Buffer; -use cqbot\utils\CQUtil; - class Framework { + public static $super_user; private $host = "127.0.0.1"; private $api_port = 10000; private $event_port = 20000; @@ -22,13 +18,14 @@ class Framework public static $obj = null; - private $run_time; + public $run_time; public static $admin_group; public $info_level = 1; /** @var \swoole_http_client $api */ public $api; private $log_file; + public $tick_time; public function __construct(){ } @@ -69,16 +66,17 @@ class Framework return self::$obj; } - public function init(){ + public function init($option = null){ + self::$super_user = ($option !== null ? $option : ""); self::$obj = $this; - Console::put("CQBot Framework starting..."); + Console::info("CQBot Framework starting..."); $this->event = new \swoole_websocket_server($this->host, $this->event_port); Buffer::$log_file = CONFIG_DIR . "log/swoole.log"; - Console::put("Current log file: " . Buffer::$log_file); + Console::info("Current log file: " . Buffer::$log_file); $worker_num = 1; - Console::put("Current worker count: " . $worker_num); + Console::info("Current worker count: " . $worker_num); $dispatch_mode = 2; - Console::put("Current dispatch mode: " . $dispatch_mode); + Console::info("Current dispatch mode: " . $dispatch_mode); $this->checkFiles(); $this->event->set([ "log_file" => Buffer::$log_file, @@ -87,8 +85,13 @@ class Framework ]); $this->event->on('WorkerStart', [$this, 'onWorkerStart']); $this->event->on('message', [$this, 'onEventMessage']); - $this->event->on('open', [$this, 'onConnect']); + //$this->event->on('open', [$this, 'onConnect']); + $this->event->on('open', function ($server, $request){ + Console::put("EVENT connection established", "lightblue"); + }); + $this->event->on("request", [$this, "onRequest"]); $this->event->on('close', function ($serv, $fd){ + Console::info(Console::setColor("EVENT connection closed","red")); //put your connection close method here. }); Buffer::$in_count = new \swoole_atomic(1); @@ -98,7 +101,7 @@ class Framework } public function checkFiles(){ - @mkdir(WORKING_DIR."log/", 0777, true); + @mkdir(CONFIG_DIR."log/", 0777, true); if(!is_file(CONFIG_DIR."log/last_error.log")) file_put_contents(CONFIG_DIR."log/last_error.log", ""); if(!is_file(CONFIG_DIR."log/error_flag")) @@ -115,18 +118,17 @@ class Framework */ public function onWorkerStart(\swoole_server $server, $worker_id){ $this->run_time = time(); - Console::info("Starting worker " . $worker_id); - Console::info("Loading source code..."); + Buffer::set("info_level", $this->info_level);//设置info等级 + Console::info("Starting worker: " . $worker_id); require_once(WORKING_DIR . "src/cqbot/loader.php"); CQUtil::loadAllFiles(); - Buffer::set("info_level", $this->info_level);//设置info等级 foreach (get_included_files() as $file) Console::debug("Loaded " . $file); - echo("\n"); //计时器(ms) $server->tick(1000, [$this, "processTick"]); + //API连接部分 $this->api = new \swoole_http_client($this->host, $this->api_port); $this->api->set(['websocket_mask' => true]); $this->api->on('message', [$this, "onApiMessage"]); @@ -137,18 +139,18 @@ class Framework Console::debug("master_pid = " . $server->master_pid); Console::debug("worker_id = " . $worker_id); - Console::put("\n====================\n"); + Console::put("\n==========STARTUP DONE==========\n"); } public function onUpgrade($cli){ Console::info("Upgraded API websocket"); Buffer::$api = $this->api; Buffer::$event = $this->event; - if ($data = file(CONFIG_DIR . "last_error.log")) { - $last_time = file_get_contents(CONFIG_DIR . "error_flag"); + 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."last_error.log", ""); + file_put_contents(CONFIG_DIR."log/last_error.log", ""); $this->event->shutdown(); return; } @@ -166,4 +168,121 @@ class Framework CQUtil::sendDebugMsg("[CQBot] 成功开启!", 0); } } + + /** + * 回调函数:当HTTP插件发来json包后激活此函数 + * @param swoole_websocket_server $server + * @param $frame + */ + public function onEventMessage($server, $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 (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($this->executeType($req), "gold"))); + } + //传入业务逻辑:CQBot + try { + $c = new CQBot($this); + $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)); + } + } + + /******************* 微信HTTP 响应 ****************** + * @param swoole_http_request $request + * @param swoole_http_response $response + */ + + public function onRequest($request, $response){ + $response->end("Hello world"); + } + + /******************* API 响应 ****************** + * @param swoole_http_client $client + * @param $frame + */ + public function onApiMessage($client, $frame){ + + } + + /***************** 计时器 ****************** + * @param $id + */ + public function processTick($id){ + $this->tick_time = time(); + new TickTask($this, $id); + } + + /** + * 此函数用于解析其他非消息类型事件,显示在log里 + * @param $req + * @return string + */ + public function executeType($req){ + switch($req["post_type"]){ + case "message": + return "消息"; + case "event": + switch($req["event"]){ + case "group_upload": + return "群[".$req["group_id"]."] 文件上传:".$req["file"]["name"]."(".intval($req["file"]["size"] / 1024)."kb)"; + case "group_admin": + switch($req["sub_type"]){ + case "set": + return "群[".$req["group_id"]."] 设置管理员:".$req["user_id"]; + case "unset": + return "群[".$req["group_id"]."] 取消管理员:".$req["user_id"]; + default: + return "unknown_group_admin_type"; + } + case "group_decrease": + switch($req["sub_type"]){ + case "leave": + return "群[".$req["group_id"]."] 成员主动退群:".$req["user_id"]; + case "kick": + return "群[".$req["group_id"]."] 管理员[".$req["operator_id"]."]踢出了:".$req["user_id"]; + case "kick_me": + return "群[".$req["group_id"]."] 本账号被踢出"; + default: + return "unknown_group_decrease_type"; + } + case "group_increase": + return "群[".$req["group_id"]."] ".$req["operator_id"]." 同意 ".$req["user_id"]." 加入了群"; + default: + return "unknown_event"; + } + case "request": + switch($req["request_type"]){ + case "friend": + return "加好友请求:".$req["user_id"].",验证信息:".$req["message"]; + case "group": + switch($req["sub_type"]){ + case "add": + return "加群[".$req["group_id"]."] 请求:".$req["user_id"].",请求信息:".$req["message"]; + case "invite": + return "用户".$req["user_id"]."邀请机器人进入群:".$req["group_id"]; + default: + return "unknown_group_type"; + } + default: + return "unknown_request_type"; + } + default: + return "unknown_post_type"; + } + } } \ No newline at end of file diff --git a/src/cqbot/User.php b/src/cqbot/User.php index 3e8d0d31..2aab59be 100755 --- a/src/cqbot/User.php +++ b/src/cqbot/User.php @@ -6,10 +6,7 @@ * Time: 13:29 */ -namespace cqbot; - -use cqbot\utils\Buffer; -use cqbot\utils\DataProvider as DP; +use DataProvider as DP; class User { diff --git a/src/cqbot/loader.php b/src/cqbot/loader.php index 1fae19a3..983a5670 100755 --- a/src/cqbot/loader.php +++ b/src/cqbot/loader.php @@ -15,6 +15,7 @@ function loadAllClass($dir){ else { if (count($taskFileName) < 2 || $taskFileName[1] != "php") continue; require_once($dir . $m); + Console::debug("Loading PHP file ".$dir.$m); } } } diff --git a/src/cqbot/mods/Admin.php b/src/cqbot/mods/Admin.php index cc6b0b47..a4193b65 100755 --- a/src/cqbot/mods/Admin.php +++ b/src/cqbot/mods/Admin.php @@ -6,36 +6,51 @@ * Time: 14:55 */ -namespace cqbot\mods; - - -use cqbot\CQBot; -use cqbot\utils\CQUtil; - class Admin extends ModBase { protected $cmds; public function __construct(CQBot $main, $data){ - //这里放置你的本模块的新加的指令,写入后系统会自动添加到指令列表 - $cmds = [ - "add-cmd" - ]; - parent::__construct($main, $data, $cmds); + parent::__construct($main, $data); } public function execute($it){ if (!$this->main->isAdmin($this->getUserId())) return false; switch ($it[0]) { - case "add-cmd": - if (count($it) < 3) { - $this->reply("用法:add-cmd 指令 模块名"); - return true; - } - if(!CQUtil::isModExists($it[2])){ - $this->reply("对不起,模块 ".$it[2]." 不存在!"); + case "reload": + $this->reply("正在重新启动..."); + if (file_get_contents("/home/ubuntu/CrazyBotFramework/src/Framework.php") != Buffer::get("res_code")) + $this->reply("检测到改变了Framework文件的内容!如需完全重载,请重启完整进程!"); + CQUtil::reload(); + return true; + case "stop": + $this->reply("正在停止服务器..."); + CQUtil::stop(); + return true; + case "set-prefix": + if(count($it) < 2) return $this->sendDefaultHelp($it[0],["set-prefix","新前缀/空"],"设置新的前缀或设置不需要前缀(不需要前缀输入\"空\"即可)"); + $prefix = $it[1]; + if(mb_strlen($prefix) > 2){ + $this->reply("指令前缀最长为两个字符"); return true; } + Buffer::set("cmd_prefix", $prefix); + $this->reply("成功设置新前缀!\n下次输入指令时需前面带 ".$prefix); + return true; + case "op": + $user = $it[1]; + Buffer::append("su", $user); + $this->reply("added operator $user"); + return true; + case "deop": + $user = $it[1]; + if(Buffer::in_array("su", $user)) Buffer::unsetByValue("su", $user); + $this->reply("removed operator $user"); + return true; + case "test": + $this->reply("Hello world"); + return true; } + return false; } } \ No newline at end of file diff --git a/src/cqbot/mods/ModBase.php b/src/cqbot/mods/ModBase.php index 8acd1d49..d03225b5 100755 --- a/src/cqbot/mods/ModBase.php +++ b/src/cqbot/mods/ModBase.php @@ -6,17 +6,12 @@ * Time: 10:39 */ -namespace cqbot\mods; - - -use cqbot\CQBot; -use cqbot\utils\CQUtil; - abstract class ModBase { protected $main; protected $data; protected $cmds; + public $call_task = false; public function __construct(CQBot $main, $data, $mod_cmd = false){ $this->main = $main; @@ -41,4 +36,17 @@ abstract class ModBase public function getMessageType(){ return $this->data["message_type"]; } public function getCommands(){ return $this->cmds; } + + public function sendDefaultHelp($cmd, $args = [], $help = ""){ + $msg = "「".$cmd."使用帮助」"; + $msg .= "\n用法:".Buffer::get("cmd_prefix").$cmd; + if($args != []){ + $msg .= " ".implode(" ", $args); + } + if($help != ""){ + $msg .= ":".$help; + } + $this->reply($msg); + return true; + } } \ No newline at end of file diff --git a/src/cqbot/tasks/TickTask.php b/src/cqbot/tasks/TickTask.php new file mode 100644 index 00000000..49f65f96 --- /dev/null +++ b/src/cqbot/tasks/TickTask.php @@ -0,0 +1,17 @@ +tick_time - $framework->run_time); + if ($interval % 900 == 0) CQUtil::saveAllFiles();//15分钟存一次数据 + + //这里可以放置你的定时器内执行的功能,自由扩展 + } +} \ No newline at end of file diff --git a/src/cqbot/utils/APIHandler.php b/src/cqbot/utils/APIHandler.php new file mode 100644 index 00000000..95171c1b --- /dev/null +++ b/src/cqbot/utils/APIHandler.php @@ -0,0 +1,12 @@ + $v) { + $serial = serialize($v); + file_put_contents(DP::getUserFolder() . $k . ".dat", $serial); + } + Console::info("Saved files"); } /** @@ -30,15 +47,14 @@ class CQUtil * @param string $head * @param int $send_debug_message */ - public static function errorLog($log, $head = "ERROR", $send_debug_message = 1){ + public static function errorLog($log, $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 { + } else { if ($send_debug_message) self::sendDebugMsg($msg, 0); } @@ -50,7 +66,7 @@ class CQUtil * @param int $need_head * @return null */ - static function sendDebugMsg($msg, $need_head = 1){ + static function sendDebugMsg($msg, $need_head = 1) { if (Framework::$admin_group == "") return null; if ($need_head) $data = CQMsg("[DEBUG] " . date("H:i:s") . ": " . $msg, "group", Framework::$admin_group); @@ -63,11 +79,11 @@ class CQUtil * 检查API端口连接情况 * @return int */ - static function checkAPIConnection(){ + static function checkAPIConnection() { if (Buffer::$api === null) return -1;//在framework链接API之前 if (Buffer::$api->isConnected() === false) { //链接被断开 - Buffer::$api->upgrade('/api/', function ($cli){ + Buffer::$api->upgrade('/api/', function ($cli) { self::sendDebugMsg("API重新链接成功"); self::APIPushDelayMsg(); }); @@ -81,7 +97,7 @@ class CQUtil * @param $data * @return bool */ - static function APIPush($data){ + static function APIPush($data) { if ($data == null || $data == "") { Console::error("EMPTY DATA PUSH"); return false; @@ -104,7 +120,10 @@ class CQUtil return true; } - static function APIPushDelayMsg(){ + /** + * 延迟推送在API连接断开后收到的消息函数 + */ + static function APIPushDelayMsg() { $delay_push_list = Buffer::get("delay_push"); $cur_time = time(); foreach ($delay_push_list as $item) { @@ -121,7 +140,7 @@ class CQUtil * 推迟推送API,用于酷Q重启后的重新连接API * @param $data */ - static function APIPushAfterConnected($data){ + static function APIPushAfterConnected($data) { $delay_push_list = Buffer::get("delay_push"); $delay_push_list[] = ["data" => $data, "time" => time()]; Buffer::set("delay_push", $delay_push_list); @@ -132,8 +151,8 @@ class CQUtil * @param $str * @return null|string|string[] */ - static function unicodeDecode($str){ - return preg_replace_callback('/\\\\u([0-9a-f]{4})/i', function ($matches){ + static function unicodeDecode($str) { + return preg_replace_callback('/\\\\u([0-9a-f]{4})/i', function ($matches) { return mb_convert_encoding(pack("H*", $matches[1]), "UTF-8", "UCS-2BE"); }, $str); @@ -144,7 +163,7 @@ class CQUtil * @param $url * @return mixed */ - static function getHTML($url){ + static function getHTML($url) { $ch = curl_init(); $timeout = 5; curl_setopt($ch, CURLOPT_URL, $url); @@ -163,7 +182,7 @@ class CQUtil * @param string $encoding * @return string */ - static public function getRev($str, $encoding = 'utf-8'){ + static public function getRev($str, $encoding = 'utf-8') { $result = ''; $len = mb_strlen($str); for ($i = $len - 1; $i >= 0; $i--) { @@ -183,7 +202,7 @@ class CQUtil * @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, $name = "CQ开发团队", $send_debug_message = 1) { $mail = new \PHPMailer(true); try { $mail->isSMTP(); @@ -197,8 +216,7 @@ class CQUtil if (is_array($address)) { foreach ($address as $item) $mail->addAddress($item); - } - else { + } else { $mail->addAddress($address); } //Content @@ -224,28 +242,25 @@ class CQUtil * @param $time * @return array */ - static function getRunTime($time){ + static function getRunTime($time) { $time_len = time() - $time; $run_time = []; if (intval($time_len / 86400) > 0) { $run_time[0] = intval($time_len / 86400); $time_len = $time_len % 86400; - } - else { + } else { $run_time[0] = 0; } if (intval($time_len / 3600) > 0) { $run_time[1] = intval($time_len / 3600); $time_len = $time_len % 3600; - } - else { + } else { $run_time[1] = 0; } if (intval($time_len / 60) > 0) { $run_time[2] = intval($time_len / 60); $time_len = $time_len % 60; - } - else { + } else { $run_time[2] = 0; } $run_time[3] = $time_len; @@ -257,7 +272,7 @@ class CQUtil * @param $time * @return string */ - static function getRunTimeFormat($time){ + static function getRunTimeFormat($time) { $time_len = time() - $time; $msg = ""; if (intval($time_len / 86400) > 0) { @@ -282,7 +297,7 @@ class CQUtil * @param $user_id * @return bool */ - static function isGroupAdmin($group, $user_id){ + static function isGroupAdmin($group, $user_id) { $ls = Buffer::get("group_list")[$group]["member"]; $is_admin = false; foreach ($ls as $k => $v) { @@ -303,7 +318,7 @@ class CQUtil * @param $content * @param string $name */ - static function sendErrorEmail($title, $content, $name = "机器人错误提示"){ + static function sendErrorEmail($title, $content, $name = "机器人错误提示") { self::sendEmail(["here your receive email address"], $title, $content, $name, 0); } @@ -313,7 +328,7 @@ class CQUtil * @param bool $real_all * @return array[User] */ - static function getAllUsers($real_all = false): array{ + static function getAllUsers($real_all = false): array { if ($real_all === true) { $dir = scandir(DP::getUserFolder()); unset($dir[0], $dir[1]); @@ -335,7 +350,7 @@ class CQUtil * @param $id * @return User */ - static function getUser($id){ + static function getUser($id) { $d = Buffer::get("user"); if (!isset($d[$id])) { self::initUser($id); @@ -350,7 +365,7 @@ class CQUtil * 初始化用户实例。如果没有此用户的实例数据,会创建 * @param $id */ - static function initUser($id){ + static function initUser($id) { if (file_exists(DP::getUserFolder() . $id . ".dat")) $class = unserialize(file_get_contents(DP::getUserFolder() . $id . ".dat")); else { Console::info("无法找到用户 " . $id . " 的数据,正在创建..."); @@ -365,7 +380,7 @@ class CQUtil * @param $msg * @return bool */ - static function sendGroupMsg($groupId, $msg){ + static function sendGroupMsg($groupId, $msg) { $reply = ["action" => "send_group_msg", "params" => ["group_id" => $groupId, "message" => $msg]]; $reply["echo"] = $reply; $reply["echo"]["time"] = time(); @@ -387,7 +402,7 @@ class CQUtil * @param $msg * @return bool */ - static function sendPrivateMsg($userId, $msg){ + static function sendPrivateMsg($userId, $msg) { $reply = ["action" => "send_private_msg", "params" => ["user_id" => $userId, "message" => $msg]]; $reply["echo"] = $reply; $reply["echo"]["time"] = time(); @@ -404,9 +419,9 @@ class CQUtil } - static function getFriendName($qq){ return Buffer::get("friend_list")[$qq]["nickname"] ?? "unknown"; } + static function getFriendName($qq) { return Buffer::get("friend_list")[$qq]["nickname"] ?? "unknown"; } - static function getGroupName($group){ return Buffer::get("group_list")[$group]["group_name"] ?? "unknown"; } + static function getGroupName($group) { return Buffer::get("group_list")[$group]["group_name"] ?? "unknown"; } /** * 发送其他API,HTTP插件支持的其他API都可以发送。 @@ -414,12 +429,11 @@ class CQUtil * @param $data * @param $echo */ - static function sendAPI($data, $echo){ + static function sendAPI($data, $echo) { if (!is_array($data)) { $api = []; $api["action"] = $data; - } - else { + } else { $api = $data; } $api["echo"] = $echo; @@ -431,7 +445,7 @@ class CQUtil * @param $name * @return bool */ - static function removeCommand($name){ + static function removeCommand($name) { $list = Buffer::get("commands"); if (!isset($list[$name])) return false; unset($list[$name]); @@ -447,8 +461,8 @@ class CQUtil * @param $class * @return bool */ - static function addCommand($name, $class){ - if (!is_file(WORKING_DIR.'src/cqbot/mods/' . $class . '.php')) { + static function addCommand($name, $class) { + if (!is_file(WORKING_DIR . 'src/cqbot/mods/' . $class . '.php')) { return false; } $list = Buffer::get("commands"); @@ -462,15 +476,16 @@ class CQUtil * 获取模块列表的通用方法 * @return array */ - static function getMods(){ - $dir = WORKING_DIR."src/cqbot/mods/"; + static function getMods() { + $dir = WORKING_DIR . "src/cqbot/mods/"; $dirs = scandir($dir); $ls = []; unset($dirs[0], $dirs[1]); - foreach($dirs as $v){ - if($v != "ModBase.php" && (strstr($v,".php") !== false)){ + foreach ($dirs as $v) { + if ($v != "ModBase.php" && (strstr($v, ".php") !== false)) { $name = substr($v, 0, -4); - $ls[]=$name; + $ls[] = $name; + Console::debug("loading mod: " . $name); } } return $ls; @@ -481,8 +496,27 @@ class CQUtil * @param $mod_name * @return bool */ - static function isModExists($mod_name){ + static function isModExists($mod_name) { $ls = self::getMods(); return in_array($mod_name, $ls); } + + /** + * 重启框架,此服务重启为全自动的 + */ + static function reload(){ + Console::info("Reloading server"); + self::saveAllFiles(); + Buffer::$event->reload(); + } + + /** + * 停止运行框架,需要用shell再次开启才能启动 + */ + static function stop(){ + Console::info("Stopping server..."); + self::saveAllFiles(); + Buffer::$api->close(); + Buffer::$event->shutdown(); + } } \ No newline at end of file diff --git a/src/cqbot/utils/Console.php b/src/cqbot/utils/Console.php index 552f720c..0d1b342e 100755 --- a/src/cqbot/utils/Console.php +++ b/src/cqbot/utils/Console.php @@ -6,11 +6,6 @@ * Time: 11:32 */ -namespace cqbot; - - -use cqbot\utils\Buffer; - class Console { static function setColor($string, $color = ""){ diff --git a/src/cqbot/utils/DataProvider.php b/src/cqbot/utils/DataProvider.php index 859bfd2d..defdf409 100755 --- a/src/cqbot/utils/DataProvider.php +++ b/src/cqbot/utils/DataProvider.php @@ -6,9 +6,6 @@ * Time: 12:54 */ -namespace cqbot\utils; - - class DataProvider { /** diff --git a/src/cqbot/utils/ErrorStatus.php b/src/cqbot/utils/ErrorStatus.php index d850932b..0e57eef1 100755 --- a/src/cqbot/utils/ErrorStatus.php +++ b/src/cqbot/utils/ErrorStatus.php @@ -6,9 +6,6 @@ * Time: 11:31 */ -namespace cqbot\utils; - - class ErrorStatus { static $error = [ diff --git a/start.php b/start.php index aac8efdc..8f1398ed 100755 --- a/start.php +++ b/start.php @@ -6,95 +6,127 @@ * Time: 11:13 */ -namespace { +date_default_timezone_set("Asia/Shanghai"); +define("WORKING_DIR", __DIR__ . "/"); +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; + } + } } -namespace cqbot { - date_default_timezone_set("Asia/Shanghai"); - define("WORKING_DIR", __DIR__ . "/"); - 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_port = 10000; +$event_port = 20000; +$admin_group = ""; +$info_level = 1; +$super_user = ""; +//check argv option. +if(count($argv) >= 3){ + echo "detected options.\n"; + //var_dump($argv); + array_shift($argv); + for($i = 0; $i < count($argv); $i++){ + if(substr($argv[$i],0,2) == '--'){ + $option = substr($argv[$i],2); + if(isset($argv[$i+1])){ + switch($option){ + case "host": + $host = $argv[$i+1]; + break; + case "api-port": + $api_port = $argv[$i+1]; + break; + case "event-port": + $event_port = $argv[$i+1]; + break; + case "admin-group": + $admin_group = $argv[$i+1]; + break; + case "info-level": + $info_level = $argv[$i+1]; + break; + case "super-user": + $super_user = $argv[$i+1]; + 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; - } +//loading projects +require(WORKING_DIR . "src/cqbot/Framework.php"); +require(WORKING_DIR . "src/cqbot/utils/Buffer.php"); +require(WORKING_DIR . "src/cqbot/utils/ErrorStatus.php"); +require(WORKING_DIR . "src/cqbot/utils/Console.php"); - //loading projects - require(WORKING_DIR . "src/cqbot/Framework.php"); - require(WORKING_DIR . "src/cqbot/utils/Buffer.php"); - require(WORKING_DIR . "src/cqbot/utils/ErrorStatus.php"); - require(WORKING_DIR . "src/cqbot/utils/Console.php"); - $cqbot = new Framework(); - $cqbot->setHost("127.0.0.1"); - $cqbot->setApiPort("10000"); - $cqbot->setEventPort("20000"); - $cqbot->setAdminGroup(""); - $cqbot->setInfoLevel(1); - $cqbot->init(); - $cqbot->eventServerStart(); -} \ No newline at end of file +$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->eventServerStart(); \ No newline at end of file