mirror of
https://github.com/zhamao-robot/zhamao-framework.git
synced 2026-03-18 13:14:52 +08:00
initial commit. It works!
This commit is contained in:
parent
04b6c2b648
commit
e1abed776c
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -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";
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -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
|
||||
{
|
||||
|
||||
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -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;
|
||||
}
|
||||
}
|
||||
@ -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;
|
||||
}
|
||||
}
|
||||
17
src/cqbot/tasks/TickTask.php
Normal file
17
src/cqbot/tasks/TickTask.php
Normal file
@ -0,0 +1,17 @@
|
||||
<?php
|
||||
/**
|
||||
* Created by PhpStorm.
|
||||
* User: jerry
|
||||
* Date: 2018/4/28
|
||||
* Time: 下午4:00
|
||||
*/
|
||||
|
||||
class TickTask
|
||||
{
|
||||
public function __construct(Framework $framework, $timer_id) {
|
||||
$interval = ($framework->tick_time - $framework->run_time);
|
||||
if ($interval % 900 == 0) CQUtil::saveAllFiles();//15分钟存一次数据
|
||||
|
||||
//这里可以放置你的定时器内执行的功能,自由扩展
|
||||
}
|
||||
}
|
||||
12
src/cqbot/utils/APIHandler.php
Normal file
12
src/cqbot/utils/APIHandler.php
Normal file
@ -0,0 +1,12 @@
|
||||
<?php
|
||||
/**
|
||||
* Created by PhpStorm.
|
||||
* User: jerry
|
||||
* Date: 2018/4/26
|
||||
* Time: 下午1:42
|
||||
*/
|
||||
|
||||
class APIHandler
|
||||
{
|
||||
|
||||
}
|
||||
@ -6,8 +6,6 @@
|
||||
* Time: 11:30
|
||||
*/
|
||||
|
||||
namespace cqbot\utils;
|
||||
|
||||
|
||||
class Buffer
|
||||
{
|
||||
@ -28,7 +26,7 @@ class Buffer
|
||||
/** @var \swoole_atomic $out_count */
|
||||
static $api_id;//API调用ID
|
||||
|
||||
static function get($name){ return self::$data[$name]; }
|
||||
static function get($name){ return self::$data[$name] ?? null; }
|
||||
|
||||
static function set($name, $value){ self::$data[$name] = $value; }
|
||||
|
||||
@ -46,4 +44,9 @@ class Buffer
|
||||
static function isset($name){ return isset(self::$data[$name]); }
|
||||
|
||||
static function array_key_exists($name, $key){ return isset(self::$data[$name][$key]); }
|
||||
|
||||
static function in_array($name, $value){
|
||||
if(!is_array((self::$data[$name] ?? 1))) return false;
|
||||
return in_array($value, self::$data[$name]);
|
||||
}
|
||||
}
|
||||
@ -6,22 +6,39 @@
|
||||
* Time: 10:39
|
||||
*/
|
||||
|
||||
namespace cqbot\utils;
|
||||
|
||||
|
||||
use cqbot\Console;
|
||||
use function cqbot\CQMsg;
|
||||
use cqbot\Framework;
|
||||
use cqbot\User;
|
||||
use cqbot\utils\DataProvider as DP;
|
||||
use DataProvider as DP;
|
||||
|
||||
class CQUtil
|
||||
{
|
||||
public static function loadAllFiles(){
|
||||
public static function loadAllFiles() {
|
||||
Console::debug("loading configs...");
|
||||
Buffer::set("su", DP::getJsonData("su.json"));//超级管理员用户列表
|
||||
Buffer::set("commands", DP::getJsonData("commands.json"));//非实时激活类指令对应模块列表
|
||||
if (count(Buffer::get("su")) < 1 && Framework::$super_user !== "") {
|
||||
Console::info("Added super user");
|
||||
Buffer::set("su", [Framework::$super_user]);
|
||||
}
|
||||
Buffer::set("mods", self::getMods());//加载模块列表
|
||||
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"));
|
||||
}
|
||||
|
||||
//TODO: load all config files to memory
|
||||
public static function saveAllFiles() {
|
||||
Console::info("Saving files...");
|
||||
DP::setJsonData("su.json", Buffer::get("su"));//保存超级管理员的QQ列表
|
||||
|
||||
//保存cmd_prefix(指令前缀)
|
||||
$config = DP::getJsonData("config.json");
|
||||
$config["cmd_prefix"] = Buffer::get("cmd_prefix");
|
||||
DP::setJsonData("config.json", $config);
|
||||
|
||||
//保存用户数据
|
||||
foreach (self::getAllUsers() as $k => $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();
|
||||
}
|
||||
}
|
||||
@ -6,11 +6,6 @@
|
||||
* Time: 11:32
|
||||
*/
|
||||
|
||||
namespace cqbot;
|
||||
|
||||
|
||||
use cqbot\utils\Buffer;
|
||||
|
||||
class Console
|
||||
{
|
||||
static function setColor($string, $color = ""){
|
||||
|
||||
@ -6,9 +6,6 @@
|
||||
* Time: 12:54
|
||||
*/
|
||||
|
||||
namespace cqbot\utils;
|
||||
|
||||
|
||||
class DataProvider
|
||||
{
|
||||
/**
|
||||
|
||||
@ -6,9 +6,6 @@
|
||||
* Time: 11:31
|
||||
*/
|
||||
|
||||
namespace cqbot\utils;
|
||||
|
||||
|
||||
class ErrorStatus
|
||||
{
|
||||
static $error = [
|
||||
|
||||
200
start.php
200
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();
|
||||
}
|
||||
$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();
|
||||
Loading…
x
Reference in New Issue
Block a user