mirror of
https://github.com/zhamao-robot/zhamao-framework.git
synced 2026-03-17 20:54:52 +08:00
First version commit.
It is TODO status.
This commit is contained in:
parent
09bfa9f33f
commit
04b6c2b648
8
.gitignore
vendored
Executable file
8
.gitignore
vendored
Executable file
@ -0,0 +1,8 @@
|
||||
# Created by .ignore support plugin (hsz.mobi)
|
||||
### Example user template template
|
||||
### Example user template
|
||||
|
||||
# IntelliJ project files
|
||||
.idea
|
||||
out
|
||||
gen
|
||||
161
src/cqbot/CQBot.php
Executable file
161
src/cqbot/CQBot.php
Executable file
@ -0,0 +1,161 @@
|
||||
<?php
|
||||
/**
|
||||
* Created by PhpStorm.
|
||||
* User: jerry
|
||||
* Date: 2018/4/12
|
||||
* Time: 10:43
|
||||
*/
|
||||
|
||||
namespace cqbot;
|
||||
|
||||
|
||||
use cqbot\mods\ModBase;
|
||||
use cqbot\utils\Buffer;
|
||||
use cqbot\utils\CQUtil;
|
||||
|
||||
class CQBot
|
||||
{
|
||||
/** @var Framework */
|
||||
public $framework;
|
||||
|
||||
//传入数据
|
||||
public $data = null;
|
||||
|
||||
//检测有没有回复过消息
|
||||
private $function_called = false;
|
||||
|
||||
public $starttime;
|
||||
public $endtime;
|
||||
|
||||
public function __construct(Framework $framework){
|
||||
$this->starttime = microtime(true);
|
||||
$this->framework = $framework;
|
||||
}
|
||||
|
||||
public function execute($it){
|
||||
$this->data = $it;
|
||||
if ($it["post_type"] == "message") {
|
||||
try {
|
||||
$this->callTask($it);
|
||||
} catch (\Exception $e) {
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function reply($msg){
|
||||
$this->function_called = true;
|
||||
switch ($this->data["message_type"]) {
|
||||
case "group":
|
||||
$this->sendGroupMsg($this->data["group_id"], $msg);
|
||||
break;
|
||||
case "private":
|
||||
$this->sendPrivateMsg($this->data["user_id"], $msg);
|
||||
break;
|
||||
case "discuss":
|
||||
$reply = json_encode(["action" => "send_discuss_msg", "params" => ["discuss_id" => $this->data["discuss_id"], "message" => $msg]]);
|
||||
if (CQUtil::APIPush($reply)) {
|
||||
$out_count = Buffer::$out_count->get();
|
||||
if (Buffer::$data["info_level"] == 2) {
|
||||
Console::put("************API PUSHED***********");
|
||||
}
|
||||
if (Buffer::$data["info_level"] >= 1) {
|
||||
Console::put(Console::setColor(date("H:i:s "), "lightpurple") . Console::setColor("[$out_count]REPLY", "blue") . Console::setColor(" > ", "gray") . json_decode($reply, true)['params']["message"]);
|
||||
}
|
||||
Buffer::$out_count->add(1);
|
||||
}
|
||||
break;
|
||||
case "wechat":
|
||||
//TODO: add wechat account support in the future
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public function sendGroupMsg($groupId, $msg){
|
||||
$this->function_called = true;
|
||||
CQUtil::sendGroupMsg($groupId, $msg);
|
||||
}
|
||||
|
||||
public function sendPrivateMsg($userId, $msg){
|
||||
$this->function_called = true;
|
||||
CQUtil::sendPrivateMsg($userId, $msg);
|
||||
}
|
||||
|
||||
public function isAdmin($user){
|
||||
if (in_array($user, Buffer::get("su"))) return true;
|
||||
else return false;
|
||||
}
|
||||
|
||||
public function replace($msg, $dat){
|
||||
$msg = str_replace("{at}", '[CQ:at,qq=' . $dat["user_id"] . ']', $msg);
|
||||
$msg = str_replace("{and}", '&', $msg);
|
||||
while (strpos($msg, '{') !== false && strpos($msg, '}') !== false) {
|
||||
if (strpos($msg, '{') > strpos($msg, '}')) return $msg;
|
||||
$start = strpos($msg, '{');
|
||||
$end = strpos($msg, '}');
|
||||
$sub = explode("=", substr($msg, $start + 1, $end - $start - 1));
|
||||
switch ($sub[0]) {
|
||||
case "at":
|
||||
$qq = $sub[1];
|
||||
$msg = str_replace(substr($msg, $start, $end - $start + 1), '[CQ:at,qq=' . $qq . ']', $msg);
|
||||
break;
|
||||
case "image":
|
||||
case "record":
|
||||
$pictFile = $sub[1];
|
||||
$msg = str_replace(substr($msg, $start, $end - $start + 1), '[CQ:' . $sub[0] . ',file=' . $pictFile . ']', $msg);
|
||||
break;
|
||||
case "dice":
|
||||
$file = $sub[1];
|
||||
$msg = str_replace(substr($msg, $start, $end - $start + 1), '[CQ:dice,type=' . $file . ']', $msg);
|
||||
break;
|
||||
case "shake":
|
||||
$msg = str_replace(substr($msg, $start, $end - $start + 1), '[CQ:shake]', $msg);
|
||||
break;
|
||||
case "music":
|
||||
$id = $sub[1];
|
||||
$msg = str_replace(substr($msg, $start, $end - $start + 1), '[CQ:music,type=163,id=' . $id . ']', $msg);
|
||||
break;
|
||||
case "internet":
|
||||
array_shift($sub);
|
||||
$id = implode("=", $sub);
|
||||
if (substr($id, 0, 7) != "http://") $id = "http://" . $id;
|
||||
$is = file_get_contents($id, false, NULL, 0, 1024);
|
||||
if ($is == false) $is = "[请求时发生了错误] 如有疑问,请联系管理员";
|
||||
$msg = str_replace(substr($msg, $start, $end - $start + 1), $is, $msg);
|
||||
break 2;
|
||||
default:
|
||||
break 2;
|
||||
}
|
||||
}
|
||||
return $msg;
|
||||
}
|
||||
}
|
||||
169
src/cqbot/Framework.php
Executable file
169
src/cqbot/Framework.php
Executable file
@ -0,0 +1,169 @@
|
||||
<?php
|
||||
/**
|
||||
* Created by PhpStorm.
|
||||
* User: jerry
|
||||
* Date: 2018/3/29
|
||||
* Time: 11:16
|
||||
*/
|
||||
|
||||
namespace cqbot;
|
||||
|
||||
use cqbot\utils\Buffer;
|
||||
use cqbot\utils\CQUtil;
|
||||
|
||||
class Framework
|
||||
{
|
||||
private $host = "127.0.0.1";
|
||||
private $api_port = 10000;
|
||||
private $event_port = 20000;
|
||||
|
||||
/** @var \swoole_websocket_server $event */
|
||||
public $event;
|
||||
|
||||
public static $obj = null;
|
||||
|
||||
private $run_time;
|
||||
public static $admin_group;
|
||||
public $info_level = 1;
|
||||
|
||||
/** @var \swoole_http_client $api */
|
||||
public $api;
|
||||
private $log_file;
|
||||
|
||||
public function __construct(){ }
|
||||
|
||||
/**
|
||||
* @param string $host
|
||||
* @return $this
|
||||
*/
|
||||
public function setHost($host = ""){
|
||||
$this->host = $host;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function setApiPort($port = 10000){
|
||||
$this->api_port = $port;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function setEventPort($port = 20000){
|
||||
$this->event_port = $port;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function setAdminGroup($group){
|
||||
self::$admin_group = $group;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function setInfoLevel($level){
|
||||
$this->info_level = $level;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function eventServerStart(){
|
||||
$this->event->start();
|
||||
}
|
||||
|
||||
public static function getInstance(){
|
||||
return self::$obj;
|
||||
}
|
||||
|
||||
public function init(){
|
||||
self::$obj = $this;
|
||||
Console::put("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);
|
||||
$worker_num = 1;
|
||||
Console::put("Current worker count: " . $worker_num);
|
||||
$dispatch_mode = 2;
|
||||
Console::put("Current dispatch mode: " . $dispatch_mode);
|
||||
$this->checkFiles();
|
||||
$this->event->set([
|
||||
"log_file" => Buffer::$log_file,
|
||||
"worker_num" => 1,
|
||||
"dispatch_mode" => 2
|
||||
]);
|
||||
$this->event->on('WorkerStart', [$this, 'onWorkerStart']);
|
||||
$this->event->on('message', [$this, 'onEventMessage']);
|
||||
$this->event->on('open', [$this, 'onConnect']);
|
||||
$this->event->on('close', function ($serv, $fd){
|
||||
//put your connection close method here.
|
||||
});
|
||||
Buffer::$in_count = new \swoole_atomic(1);
|
||||
Buffer::$out_count = new \swoole_atomic(1);
|
||||
Buffer::$api_id = new \swoole_atomic(1);
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function checkFiles(){
|
||||
@mkdir(WORKING_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"))
|
||||
file_put_contents(CONFIG_DIR."log/error_flag", time());
|
||||
}
|
||||
|
||||
/* Callback function down here */
|
||||
|
||||
/**
|
||||
* This is async function in EventLoop
|
||||
* When it reload, it will run this function again.
|
||||
* @param \swoole_server $server
|
||||
* @param $worker_id
|
||||
*/
|
||||
public function onWorkerStart(\swoole_server $server, $worker_id){
|
||||
$this->run_time = time();
|
||||
Console::info("Starting worker " . $worker_id);
|
||||
Console::info("Loading source code...");
|
||||
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"]);
|
||||
|
||||
$this->api = new \swoole_http_client($this->host, $this->api_port);
|
||||
$this->api->set(['websocket_mask' => true]);
|
||||
$this->api->on('message', [$this, "onApiMessage"]);
|
||||
$this->api->on("close", function ($cli){
|
||||
Console::info(Console::setColor("API connection closed", "red"));
|
||||
});
|
||||
$this->api->upgrade('/api/', [$this, "onUpgrade"]);
|
||||
|
||||
Console::debug("master_pid = " . $server->master_pid);
|
||||
Console::debug("worker_id = " . $worker_id);
|
||||
Console::put("\n====================\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 (time() - $last_time < 2) {
|
||||
CQUtil::sendDebugMsg("检测到重复引起异常,停止服务器", 0);
|
||||
file_put_contents(CONFIG_DIR."last_error.log", "");
|
||||
$this->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);
|
||||
}
|
||||
}
|
||||
}
|
||||
81
src/cqbot/User.php
Executable file
81
src/cqbot/User.php
Executable file
@ -0,0 +1,81 @@
|
||||
<?php
|
||||
/**
|
||||
* Created by PhpStorm.
|
||||
* User: jerry
|
||||
* Date: 2018/4/14
|
||||
* Time: 13:29
|
||||
*/
|
||||
|
||||
namespace cqbot;
|
||||
|
||||
use cqbot\utils\Buffer;
|
||||
use cqbot\utils\DataProvider as DP;
|
||||
|
||||
class User
|
||||
{
|
||||
private $id;
|
||||
private $word_status = [];
|
||||
private $permission;
|
||||
private $is_friend = false;
|
||||
|
||||
private $buffer = null;
|
||||
|
||||
public function __construct($qid){
|
||||
$this->id = $qid;
|
||||
$this->permission = DP::getJsonData("permissions.json")[$qid] ?? 0;
|
||||
$this->is_friend = isset(Buffer::get("friend_list")[$qid]) ? true : false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取用户QQ号
|
||||
* @return mixed
|
||||
*/
|
||||
public function getId(){ return $this->id; }
|
||||
|
||||
/**
|
||||
* 获取用户添加词库的状态
|
||||
* @return array
|
||||
*/
|
||||
public function getWordStatus() : array{ return $this->word_status; }
|
||||
|
||||
/**
|
||||
* 获取用户权限值
|
||||
* @return int
|
||||
*/
|
||||
public function getPermission() : int{ return $this->permission; }
|
||||
|
||||
/**
|
||||
* @param array $word_status
|
||||
* @return User
|
||||
*/
|
||||
public function setWordStatus(array $word_status): User{
|
||||
$this->word_status = $word_status;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $permission
|
||||
* @return User
|
||||
*/
|
||||
public function setPermission(int $permission): User{
|
||||
$this->permission = $permission;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 和用户是否是好友//TODO功能
|
||||
* @return bool
|
||||
*/
|
||||
public function isFriend(): bool{
|
||||
return $this->is_friend;
|
||||
}
|
||||
|
||||
public function getBuffer(){
|
||||
return $this->buffer;
|
||||
}
|
||||
|
||||
public function setBuffer($buffer){
|
||||
$this->buffer = $buffer;
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
37
src/cqbot/loader.php
Executable file
37
src/cqbot/loader.php
Executable file
@ -0,0 +1,37 @@
|
||||
<?php
|
||||
/**
|
||||
* Created by PhpStorm.
|
||||
* User: jerry
|
||||
* Date: 2018/4/12
|
||||
* Time: 10:32
|
||||
*/
|
||||
|
||||
function loadAllClass($dir){
|
||||
$dir_obj = scandir($dir);
|
||||
unset($dir_obj[0], $dir_obj[1]);
|
||||
foreach ($dir_obj as $m) {
|
||||
$taskFileName = explode(".", $m);
|
||||
if (is_dir($dir . $m . "/")) loadAllClass($dir . $m . "/");
|
||||
else {
|
||||
if (count($taskFileName) < 2 || $taskFileName[1] != "php") continue;
|
||||
require_once($dir . $m);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//加载需要优先加载的文件
|
||||
require_once(WORKING_DIR."src/cqbot/mods/ModBase.php");
|
||||
|
||||
loadAllClass(WORKING_DIR."src/cqbot/");
|
||||
|
||||
//加载外部模块
|
||||
require_once(WORKING_DIR."src/extension/PHPMailer.phar");
|
||||
|
||||
/**
|
||||
* 下面是不能在loader里面加载的php文件,以下文件更新时必须停止脚本后再重启才能重新加载
|
||||
* start.php
|
||||
* src/cqbot/Framework.php
|
||||
* src/cqbot/Console.php
|
||||
* src/cqbot/utils/Buffer.php
|
||||
* src/cqbot/ErrorStatus.php
|
||||
*/
|
||||
41
src/cqbot/mods/Admin.php
Executable file
41
src/cqbot/mods/Admin.php
Executable file
@ -0,0 +1,41 @@
|
||||
<?php
|
||||
/**
|
||||
* Created by PhpStorm.
|
||||
* User: jerry
|
||||
* Date: 2018/4/19
|
||||
* 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);
|
||||
}
|
||||
|
||||
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]." 不存在!");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
44
src/cqbot/mods/ModBase.php
Executable file
44
src/cqbot/mods/ModBase.php
Executable file
@ -0,0 +1,44 @@
|
||||
<?php
|
||||
/**
|
||||
* Created by PhpStorm.
|
||||
* User: jerry
|
||||
* Date: 2018/4/12
|
||||
* Time: 10:39
|
||||
*/
|
||||
|
||||
namespace cqbot\mods;
|
||||
|
||||
|
||||
use cqbot\CQBot;
|
||||
use cqbot\utils\CQUtil;
|
||||
|
||||
abstract class ModBase
|
||||
{
|
||||
protected $main;
|
||||
protected $data;
|
||||
protected $cmds;
|
||||
|
||||
public function __construct(CQBot $main, $data, $mod_cmd = false){
|
||||
$this->main = $main;
|
||||
$this->data = $data;
|
||||
$this->cmds = $mod_cmd;
|
||||
}
|
||||
|
||||
public function getUser($data = null){
|
||||
return CQUtil::getUser($data === null ? $this->data["user_id"] : $data["user_id"]);
|
||||
}
|
||||
|
||||
public function getUserId($data = null){ return $data === null ? strval($this->data["user_id"]) : strval($data["user_id"]); }
|
||||
|
||||
public abstract function execute($it);
|
||||
|
||||
public function reply($msg){ $this->main->reply($msg); }
|
||||
|
||||
public function sendPrivateMsg($user, $msg){ $this->main->sendPrivateMsg($user, $msg); }
|
||||
|
||||
public function sendGroupMsg($user, $msg){ $this->main->sendGroupMsg($user, $msg); }
|
||||
|
||||
public function getMessageType(){ return $this->data["message_type"]; }
|
||||
|
||||
public function getCommands(){ return $this->cmds; }
|
||||
}
|
||||
49
src/cqbot/utils/Buffer.php
Executable file
49
src/cqbot/utils/Buffer.php
Executable file
@ -0,0 +1,49 @@
|
||||
<?php
|
||||
/**
|
||||
* Created by PhpStorm.
|
||||
* User: jerry
|
||||
* Date: 2018/3/29
|
||||
* Time: 11:30
|
||||
*/
|
||||
|
||||
namespace cqbot\utils;
|
||||
|
||||
|
||||
class Buffer
|
||||
{
|
||||
static $data = [];
|
||||
static $api_session = [];
|
||||
/** @var \swoole_http_client $api */
|
||||
static $api;
|
||||
/** @var \swoole_websocket_server $event */
|
||||
static $event;
|
||||
/** @var string $log_file */
|
||||
static $log_file = "";
|
||||
/** @var \swoole_server $comm */
|
||||
static $comm = null;
|
||||
/** @var \swoole_atomic $in_count */
|
||||
static $in_count;//接收消息
|
||||
/** @var \swoole_atomic $out_count */
|
||||
static $out_count;//发送消息数量
|
||||
/** @var \swoole_atomic $out_count */
|
||||
static $api_id;//API调用ID
|
||||
|
||||
static function get($name){ return self::$data[$name]; }
|
||||
|
||||
static function set($name, $value){ self::$data[$name] = $value; }
|
||||
|
||||
static function append($name, $value){ self::$data[$name][] = $value; }
|
||||
|
||||
static function appendKey($name, $key, $value){ self::$data[$name][$key] = $value; }
|
||||
|
||||
static function unset($name, $key){ unset(self::$data[$name][$key]); }
|
||||
|
||||
static function unsetByValue($name, $vale){
|
||||
$key = array_search($vale, self::$data[$name]);
|
||||
array_splice(self::$data[$name], $key, 1);
|
||||
}
|
||||
|
||||
static function isset($name){ return isset(self::$data[$name]); }
|
||||
|
||||
static function array_key_exists($name, $key){ return isset(self::$data[$name][$key]); }
|
||||
}
|
||||
488
src/cqbot/utils/CQUtil.php
Executable file
488
src/cqbot/utils/CQUtil.php
Executable file
@ -0,0 +1,488 @@
|
||||
<?php
|
||||
/**
|
||||
* Created by PhpStorm.
|
||||
* User: jerry
|
||||
* Date: 2018/4/12
|
||||
* 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;
|
||||
|
||||
class CQUtil
|
||||
{
|
||||
public static function loadAllFiles(){
|
||||
Buffer::set("su", DP::getJsonData("su.json"));//超级管理员用户列表
|
||||
Buffer::set("commands", DP::getJsonData("commands.json"));//非实时激活类指令对应模块列表
|
||||
|
||||
//TODO: load all config files to memory
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成报错日志
|
||||
* @param $log
|
||||
* @param string $head
|
||||
* @param int $send_debug_message
|
||||
*/
|
||||
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 {
|
||||
if ($send_debug_message)
|
||||
self::sendDebugMsg($msg, 0);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 发送调试信息到管理群(需先设置管理群号)
|
||||
* @param $msg
|
||||
* @param int $need_head
|
||||
* @return null
|
||||
*/
|
||||
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);
|
||||
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;
|
||||
}
|
||||
|
||||
/**
|
||||
* 推送API,给API端口
|
||||
* @param $data
|
||||
* @return bool
|
||||
*/
|
||||
static function APIPush($data){
|
||||
if ($data == null || $data == "") {
|
||||
Console::error("EMPTY DATA PUSH");
|
||||
return false;
|
||||
}
|
||||
if (self::checkAPIConnection() === -1) {
|
||||
//忽略掉framework链接API之前的消息
|
||||
self::errorlog("API推送失败,未发送的消息: \n" . $data, "API ERROR", 0);
|
||||
return false;
|
||||
}
|
||||
if (self::checkAPIConnection() === 0) {
|
||||
self::APIPushAfterConnected($data);
|
||||
return true;
|
||||
}
|
||||
if (Buffer::$api->push($data) === false) {
|
||||
$data = self::unicodeDecode($data);
|
||||
self::errorlog("API推送失败,未发送的消息: \n" . $data, "API ERROR", 0);
|
||||
self::sendErrorEmail("API推送失败", "未成功推送的消息:<br>$data<br>请检查酷q是否开启及网络链接情况<br>在此期间,机器人会中断所有消息处理<br>请及时处理");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static function APIPushDelayMsg(){
|
||||
$delay_push_list = Buffer::get("delay_push");
|
||||
$cur_time = time();
|
||||
foreach ($delay_push_list as $item) {
|
||||
$data = $item["data"];
|
||||
$time = $item["time"];
|
||||
if ($cur_time - $time <= 10) {
|
||||
self::APIPush($data);
|
||||
}
|
||||
}
|
||||
Buffer::set("delay_push", []);
|
||||
}
|
||||
|
||||
/**
|
||||
* 推迟推送API,用于酷Q重启后的重新连接API
|
||||
* @param $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);
|
||||
}
|
||||
|
||||
/**
|
||||
* 解码unicode中文编码
|
||||
* @param $str
|
||||
* @return null|string|string[]
|
||||
*/
|
||||
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);
|
||||
}
|
||||
|
||||
/**
|
||||
* 模拟发送一个HTML-get请求
|
||||
* @param $url
|
||||
* @return mixed
|
||||
*/
|
||||
static function getHTML($url){
|
||||
$ch = curl_init();
|
||||
$timeout = 5;
|
||||
curl_setopt($ch, CURLOPT_URL, $url);
|
||||
curl_setopt($ch, CURLOPT_HEADER, 1);
|
||||
curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/5.0 (Windows NT 6.1; WOW64; rv:39.0) Gecko/20100101 Firefox/39.0');
|
||||
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
|
||||
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, $timeout);
|
||||
$r = curl_exec($ch);
|
||||
curl_close($ch);
|
||||
return $r;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取字符串的反转结果
|
||||
* @param $str
|
||||
* @param string $encoding
|
||||
* @return string
|
||||
*/
|
||||
static public function getRev($str, $encoding = 'utf-8'){
|
||||
$result = '';
|
||||
$len = mb_strlen($str);
|
||||
for ($i = $len - 1; $i >= 0; $i--) {
|
||||
$result .= mb_substr($str, $i, 1, $encoding);
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 发送邮件功能,基于PHPMailer模块,需先安装phpmailer。默认此工程demo里已包含有phpmailer了。
|
||||
* 请根据实际自己的邮箱更新下面的用户名、密码、smtp服务器地址、端口等。
|
||||
* 此功能非基于本作者编写的代码,如有问题请在github上找PHPMailer项目进行反馈
|
||||
* @param $address
|
||||
* @param $title
|
||||
* @param $content
|
||||
* @param string $name
|
||||
* @param int $send_debug_message
|
||||
* @return bool|string
|
||||
*/
|
||||
static function sendEmail($address, $title, $content, $name = "CQ开发团队", $send_debug_message = 1){
|
||||
$mail = new \PHPMailer(true);
|
||||
try {
|
||||
$mail->isSMTP();
|
||||
$mail->Host = 'here your smtp host';
|
||||
$mail->SMTPAuth = true;
|
||||
$mail->Username = 'here your mailbox address';
|
||||
$mail->Password = 'here your password';
|
||||
$mail->SMTPSecure = 'ssl';
|
||||
$mail->Port = 465;
|
||||
$mail->setFrom('here your mailbox address', $name);
|
||||
if (is_array($address)) {
|
||||
foreach ($address as $item)
|
||||
$mail->addAddress($item);
|
||||
}
|
||||
else {
|
||||
$mail->addAddress($address);
|
||||
}
|
||||
//Content
|
||||
$mail->isHTML(true);
|
||||
$mail->Subject = $title;
|
||||
$mail->CharSet = "UTF-8";
|
||||
$mail->Body = $content;
|
||||
$mail->send();
|
||||
if (is_array($address))
|
||||
$address = implode(",", $address);
|
||||
Console::info("向 $address 发送的邮件完成");
|
||||
unset($mail);
|
||||
return true;
|
||||
} catch (\Exception $e) {
|
||||
self::errorLog("发送邮件错误!错误信息:" . $info = $mail->ErrorInfo, "ERROR", $send_debug_message);
|
||||
unset($mail);
|
||||
return $info;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取运行时间
|
||||
* @param $time
|
||||
* @return array
|
||||
*/
|
||||
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 {
|
||||
$run_time[0] = 0;
|
||||
}
|
||||
if (intval($time_len / 3600) > 0) {
|
||||
$run_time[1] = intval($time_len / 3600);
|
||||
$time_len = $time_len % 3600;
|
||||
}
|
||||
else {
|
||||
$run_time[1] = 0;
|
||||
}
|
||||
if (intval($time_len / 60) > 0) {
|
||||
$run_time[2] = intval($time_len / 60);
|
||||
$time_len = $time_len % 60;
|
||||
}
|
||||
else {
|
||||
$run_time[2] = 0;
|
||||
}
|
||||
$run_time[3] = $time_len;
|
||||
return $run_time;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取格式化的运行时间
|
||||
* @param $time
|
||||
* @return string
|
||||
*/
|
||||
static function getRunTimeFormat($time){
|
||||
$time_len = time() - $time;
|
||||
$msg = "";
|
||||
if (intval($time_len / 86400) > 0) {
|
||||
$msg .= intval($time_len / 86400) . "天";
|
||||
$time_len = $time_len % 86400;
|
||||
}
|
||||
if (intval($time_len / 3600) > 0) {
|
||||
$msg .= intval($time_len / 3600) . "小时";
|
||||
$time_len = $time_len % 3600;
|
||||
}
|
||||
if (intval($time_len / 60) > 0) {
|
||||
$msg .= intval($time_len / 60) . "分";
|
||||
$time_len = $time_len % 60;
|
||||
}
|
||||
$msg .= $time_len . "秒";
|
||||
return $msg;
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查是否为群组管理员或群主功能,此功能需要先获取群组列表,否则会产生一个warning
|
||||
* @param $group
|
||||
* @param $user_id
|
||||
* @return bool
|
||||
*/
|
||||
static function isGroupAdmin($group, $user_id){
|
||||
$ls = Buffer::get("group_list")[$group]["member"];
|
||||
$is_admin = false;
|
||||
foreach ($ls as $k => $v) {
|
||||
if ($v["user_id"] == $user_id) {
|
||||
if ($v["role"] == "admin" || $v["role"] == "owner") {
|
||||
$is_admin = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return $is_admin;
|
||||
}
|
||||
|
||||
/**
|
||||
* 用于发送错误日志邮件的功能,请根据实际情况填写邮箱。
|
||||
* 此功能基于sendMail,请看上方sendMail函数的介绍
|
||||
* @param $title
|
||||
* @param $content
|
||||
* @param string $name
|
||||
*/
|
||||
static function sendErrorEmail($title, $content, $name = "机器人错误提示"){
|
||||
self::sendEmail(["here your receive email address"], $title, $content, $name, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取所有已经加载到内存的用户。
|
||||
* read_all为true时,会加载所有User.dat到内存中,false时仅会读取已经加载到内存的用户
|
||||
* @param bool $real_all
|
||||
* @return array[User]
|
||||
*/
|
||||
static function getAllUsers($real_all = false): array{
|
||||
if ($real_all === true) {
|
||||
$dir = scandir(DP::getUserFolder());
|
||||
unset($dir[0], $dir[1]);
|
||||
foreach ($dir as $d => $v) {
|
||||
$vs = explode(".", $v);
|
||||
if (array_pop($vs) == "dat") {
|
||||
$class = unserialize(file_get_contents(DP::getUserFolder() . $v));
|
||||
if (!Buffer::array_key_exists("user", $vs[0])) {
|
||||
Buffer::appendKey("user", $vs[0], $class);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return Buffer::get("user");
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取用户实例
|
||||
* @param $id
|
||||
* @return User
|
||||
*/
|
||||
static function getUser($id){
|
||||
$d = Buffer::get("user");
|
||||
if (!isset($d[$id])) {
|
||||
self::initUser($id);
|
||||
$d = Buffer::get("user");
|
||||
}
|
||||
/** @var User $class */
|
||||
$class = $d[$id];
|
||||
return $class;
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化用户实例。如果没有此用户的实例数据,会创建
|
||||
* @param $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 . " 的数据,正在创建...");
|
||||
$class = new User($id);
|
||||
}
|
||||
Buffer::appendKey("user", $id, $class);
|
||||
}
|
||||
|
||||
/**
|
||||
* 发送群组消息,含控制台推出
|
||||
* @param $groupId
|
||||
* @param $msg
|
||||
* @return bool
|
||||
*/
|
||||
static function sendGroupMsg($groupId, $msg){
|
||||
$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)) {
|
||||
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);
|
||||
Buffer::$out_count->add(1);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 发送私聊消息
|
||||
* @param $userId
|
||||
* @param $msg
|
||||
* @return bool
|
||||
*/
|
||||
static function sendPrivateMsg($userId, $msg){
|
||||
$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)) {
|
||||
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);
|
||||
Buffer::$out_count->add(1);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
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"; }
|
||||
|
||||
/**
|
||||
* 发送其他API,HTTP插件支持的其他API都可以发送。
|
||||
* echo是返回内容,可以在APIHandler.php里面解析
|
||||
* @param $data
|
||||
* @param $echo
|
||||
*/
|
||||
static function sendAPI($data, $echo){
|
||||
if (!is_array($data)) {
|
||||
$api = [];
|
||||
$api["action"] = $data;
|
||||
}
|
||||
else {
|
||||
$api = $data;
|
||||
}
|
||||
$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 array
|
||||
*/
|
||||
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)){
|
||||
$name = substr($v, 0, -4);
|
||||
$ls[]=$name;
|
||||
}
|
||||
}
|
||||
return $ls;
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断模块是否存在
|
||||
* @param $mod_name
|
||||
* @return bool
|
||||
*/
|
||||
static function isModExists($mod_name){
|
||||
$ls = self::getMods();
|
||||
return in_array($mod_name, $ls);
|
||||
}
|
||||
}
|
||||
67
src/cqbot/utils/Console.php
Executable file
67
src/cqbot/utils/Console.php
Executable file
@ -0,0 +1,67 @@
|
||||
<?php
|
||||
/**
|
||||
* Created by PhpStorm.
|
||||
* User: jerry
|
||||
* Date: 2018/3/29
|
||||
* Time: 11:32
|
||||
*/
|
||||
|
||||
namespace cqbot;
|
||||
|
||||
|
||||
use cqbot\utils\Buffer;
|
||||
|
||||
class Console
|
||||
{
|
||||
static function setColor($string, $color = ""){
|
||||
switch ($color) {
|
||||
case "red":
|
||||
return "\x1b[38;5;203m" . $string . "\x1b[m";
|
||||
case "green":
|
||||
return "\x1b[38;5;83m" . $string . "\x1b[m";
|
||||
case "yellow":
|
||||
return "\x1b[38;5;227m" . $string . "\x1b[m";
|
||||
case "blue":
|
||||
return "\033[34m" . $string . "\033[0m";
|
||||
case "lightpurple":
|
||||
return "\x1b[38;5;207m" . $string . "\x1b[m";
|
||||
case "lightblue":
|
||||
return "\x1b[38;5;87m" . $string . "\x1b[m";
|
||||
case "gold":
|
||||
return "\x1b[38;5;214m" . $string . "\x1b[m";
|
||||
case "gray":
|
||||
return "\x1b[38;5;59m" . $string . "\x1b[m";
|
||||
case "pink":
|
||||
return "\x1b[38;5;207m" . $string . "\x1b[m";
|
||||
case "lightlightblue":
|
||||
return "\x1b[38;5;63m" . $string . "\x1b[m";
|
||||
default:
|
||||
return $string;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static function debug($obj, $head = null){
|
||||
if ($head === null) $head = "[DEBUG] " . date("H:i:s") . " ";
|
||||
if (Buffer::get("info_level") < 2) return;
|
||||
if (!is_string($obj)) var_dump($obj);
|
||||
else echo(self::setColor($head . $obj, "green") . "\n");
|
||||
}
|
||||
|
||||
static function error($obj, $head = null){
|
||||
if ($head === null) $head = "[ERROR] " . date("H:i:s") . " ";
|
||||
if (!is_string($obj)) var_dump($obj);
|
||||
else echo(self::setColor($head . $obj, "red") . "\n");
|
||||
}
|
||||
|
||||
static function info($obj, $head = null){
|
||||
if ($head === null) $head = "[INFO] " . date("H:i:s") . " ";
|
||||
if (!is_string($obj)) var_dump($obj);
|
||||
else echo(self::setColor($head . $obj, "blue") . "\n");
|
||||
}
|
||||
|
||||
static function put($obj, $color = ""){
|
||||
if (!is_string($obj)) var_dump($obj);
|
||||
else echo(self::setColor($obj, $color) . "\n");
|
||||
}
|
||||
}
|
||||
48
src/cqbot/utils/DataProvider.php
Executable file
48
src/cqbot/utils/DataProvider.php
Executable file
@ -0,0 +1,48 @@
|
||||
<?php
|
||||
/**
|
||||
* Created by PhpStorm.
|
||||
* User: jerry
|
||||
* Date: 2018/4/14
|
||||
* Time: 12:54
|
||||
*/
|
||||
|
||||
namespace cqbot\utils;
|
||||
|
||||
|
||||
class DataProvider
|
||||
{
|
||||
/**
|
||||
* 获取config文件夹
|
||||
* @return string
|
||||
*/
|
||||
public static function getDataFolder(){
|
||||
return CONFIG_DIR;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取用户数据的文件夹
|
||||
* @return string
|
||||
*/
|
||||
public static function getUserFolder(){
|
||||
return USER_DIR;
|
||||
}
|
||||
|
||||
/**
|
||||
* 打开json文件并转换为PHP数组,文件不存在则返回空数组
|
||||
* @param $filename
|
||||
* @return array|mixed
|
||||
*/
|
||||
static function getJsonData($filename){
|
||||
if (!file_exists(self::getDataFolder() . $filename)) return [];
|
||||
return json_decode(file_get_contents(self::getDataFolder() . $filename), true);
|
||||
}
|
||||
|
||||
/**
|
||||
* 储存PHP数组为json文件,文件不存在则会创建文件
|
||||
* @param $filename
|
||||
* @param array $args
|
||||
*/
|
||||
static function setJsonData($filename, array $args){
|
||||
file_put_contents(self::getDataFolder() . $filename, json_encode($args, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT | JSON_BIGINT_AS_STRING));
|
||||
}
|
||||
}
|
||||
50
src/cqbot/utils/ErrorStatus.php
Executable file
50
src/cqbot/utils/ErrorStatus.php
Executable file
@ -0,0 +1,50 @@
|
||||
<?php
|
||||
/**
|
||||
* Created by PhpStorm.
|
||||
* User: jerry
|
||||
* Date: 2018/3/29
|
||||
* Time: 11:31
|
||||
*/
|
||||
|
||||
namespace cqbot\utils;
|
||||
|
||||
|
||||
class ErrorStatus
|
||||
{
|
||||
static $error = [
|
||||
1400 => "POST 请求的正文格式不正确",
|
||||
1404 => "API 不存在",
|
||||
100 => "参数缺失或参数无效",
|
||||
102 => "酷q操作权限不足",
|
||||
103 => "用户权限不足或文件系统异常",
|
||||
201 => "工作线程池未正确初始化",
|
||||
-1 => "请求发送失败",
|
||||
-2 => "未收到服务器回复,可能未发送成功",
|
||||
-3 => "消息过长或为空",
|
||||
-4 => "消息解析过程异常",
|
||||
-5 => "日志功能未启用",
|
||||
-6 => "日志优先级错误",
|
||||
-7 => "数据入库失败",
|
||||
-8 => "不支持对系统帐号操作",
|
||||
-9 => "帐号不在该群内,消息无法发送",
|
||||
-10 => "该用户不存在/不在群内",
|
||||
-11 => "数据错误,无法请求发送",
|
||||
-12 => "不支持对匿名成员解除禁言",
|
||||
-13 => "无法解析要禁言的匿名成员数据",
|
||||
-14 => "由于未知原因,操作失败",
|
||||
-15 => "群未开启匿名发言功能,或匿名帐号被禁言",
|
||||
-16 => "帐号不在群内或网络错误,无法退出/解散该群",
|
||||
-17 => "帐号为群主,无法退出该群",
|
||||
-18 => "帐号非群主,无法解散该群",
|
||||
-19 => "临时消息已失效或未建立",
|
||||
-20 => "参数错误",
|
||||
-21 => "临时消息已失效或未建立",
|
||||
-22 => "获取QQ信息失败",
|
||||
-23 => "找不到与目标QQ的关系,消息无法发送",
|
||||
-26 => "消息过长"
|
||||
];
|
||||
|
||||
static function getMessage($retcode){
|
||||
return self::$error[$retcode] ?? "未知错误";
|
||||
}
|
||||
}
|
||||
BIN
src/extension/PHPMailer.phar
Executable file
BIN
src/extension/PHPMailer.phar
Executable file
Binary file not shown.
100
start.php
Executable file
100
start.php
Executable file
@ -0,0 +1,100 @@
|
||||
<?php
|
||||
/**
|
||||
* Created by PhpStorm.
|
||||
* User: jerry
|
||||
* Date: 2018/3/29
|
||||
* Time: 11:13
|
||||
*/
|
||||
|
||||
namespace {
|
||||
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
//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();
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user