2022-03-15 18:05:33 +08:00
|
|
|
|
<?php
|
2020-03-02 16:14:20 +08:00
|
|
|
|
|
2022-03-15 18:05:33 +08:00
|
|
|
|
declare(strict_types=1);
|
2020-03-02 16:14:20 +08:00
|
|
|
|
|
|
|
|
|
|
namespace ZM\API;
|
|
|
|
|
|
|
2022-05-04 17:53:49 +08:00
|
|
|
|
use Stringable;
|
2020-08-31 10:11:06 +08:00
|
|
|
|
use ZM\Console\Console;
|
2021-03-15 02:54:16 +08:00
|
|
|
|
use ZM\Entity\CQObject;
|
2018-10-29 11:47:58 +08:00
|
|
|
|
|
|
|
|
|
|
class CQ
|
|
|
|
|
|
{
|
|
|
|
|
|
/**
|
|
|
|
|
|
* at一下QQ用户(仅在QQ群支持at全体)
|
2022-03-31 02:24:38 +08:00
|
|
|
|
* @param int|string $qq 用户QQ号/ID号
|
|
|
|
|
|
* @return string CQ码
|
2018-10-29 11:47:58 +08:00
|
|
|
|
*/
|
2022-03-31 02:24:38 +08:00
|
|
|
|
public static function at($qq): string
|
2022-03-15 18:05:33 +08:00
|
|
|
|
{
|
|
|
|
|
|
if (is_numeric($qq) || $qq === 'all') {
|
|
|
|
|
|
return '[CQ:at,qq=' . $qq . ']';
|
2018-10-29 11:47:58 +08:00
|
|
|
|
}
|
2022-03-15 18:05:33 +08:00
|
|
|
|
Console::warning(zm_internal_errcode('E00035') . "传入的QQ号码({$qq})错误!");
|
|
|
|
|
|
return ' ';
|
2018-10-29 11:47:58 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 发送QQ原生表情
|
2022-03-31 02:24:38 +08:00
|
|
|
|
* @param int|string $id 表情ID
|
|
|
|
|
|
* @return string CQ码
|
2018-10-29 11:47:58 +08:00
|
|
|
|
*/
|
2022-03-31 02:24:38 +08:00
|
|
|
|
public static function face($id): string
|
2022-03-15 18:05:33 +08:00
|
|
|
|
{
|
2018-10-29 11:47:58 +08:00
|
|
|
|
if (is_numeric($id)) {
|
2022-03-15 18:05:33 +08:00
|
|
|
|
return '[CQ:face,id=' . $id . ']';
|
2018-10-29 11:47:58 +08:00
|
|
|
|
}
|
2022-03-15 18:05:33 +08:00
|
|
|
|
Console::warning(zm_internal_errcode('E00035') . "传入的face id({$id})错误!");
|
|
|
|
|
|
return ' ';
|
2018-10-29 11:47:58 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
2020-12-31 13:56:59 +08:00
|
|
|
|
* 发送图片
|
2022-03-31 02:24:38 +08:00
|
|
|
|
* @param string $file 文件的路径、URL或者base64编码的图片数据
|
|
|
|
|
|
* @param bool $cache 是否缓存(默认为true)
|
|
|
|
|
|
* @param bool $flash 是否闪照(默认为false)
|
|
|
|
|
|
* @param bool $proxy 是否使用代理(默认为true)
|
|
|
|
|
|
* @param int $timeout 超时时间(默认不超时)
|
|
|
|
|
|
* @return string CQ码
|
2018-10-29 11:47:58 +08:00
|
|
|
|
*/
|
2022-03-31 02:24:38 +08:00
|
|
|
|
public static function image(string $file, bool $cache = true, bool $flash = false, bool $proxy = true, int $timeout = -1): string
|
2022-03-15 18:05:33 +08:00
|
|
|
|
{
|
2020-12-31 13:56:59 +08:00
|
|
|
|
return
|
2022-03-15 18:05:33 +08:00
|
|
|
|
'[CQ:image,file=' . self::encode($file, true) .
|
|
|
|
|
|
(!$cache ? ',cache=0' : '') .
|
|
|
|
|
|
($flash ? ',type=flash' : '') .
|
|
|
|
|
|
(!$proxy ? ',proxy=false' : '') .
|
|
|
|
|
|
($timeout != -1 ? (',timeout=' . $timeout) : '') .
|
|
|
|
|
|
']';
|
2018-10-29 11:47:58 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
2020-12-31 13:56:59 +08:00
|
|
|
|
* 发送语音
|
2022-03-31 02:24:38 +08:00
|
|
|
|
* @param string $file 文件的路径、URL或者base64编码的语音数据
|
|
|
|
|
|
* @param bool $magic 是否加特技(默认为false)
|
|
|
|
|
|
* @param bool $cache 是否缓存(默认为true)
|
|
|
|
|
|
* @param bool $proxy 是否使用代理(默认为true)
|
|
|
|
|
|
* @param int $timeout 超时时间(默认不超时)
|
|
|
|
|
|
* @return string CQ码
|
2018-10-29 11:47:58 +08:00
|
|
|
|
*/
|
2022-03-31 02:24:38 +08:00
|
|
|
|
public static function record(string $file, bool $magic = false, bool $cache = true, bool $proxy = true, int $timeout = -1): string
|
2022-03-15 18:05:33 +08:00
|
|
|
|
{
|
2020-12-31 13:56:59 +08:00
|
|
|
|
return
|
2022-03-15 18:05:33 +08:00
|
|
|
|
'[CQ:record,file=' . self::encode($file, true) .
|
|
|
|
|
|
($magic ? ',magic=1' : '') .
|
2022-03-31 02:24:38 +08:00
|
|
|
|
(!$cache ? ',cache=0' : '') .
|
2022-03-15 18:05:33 +08:00
|
|
|
|
(!$proxy ? ',proxy=false' : '') .
|
|
|
|
|
|
($timeout != -1 ? (',timeout=' . $timeout) : '') .
|
|
|
|
|
|
']';
|
2018-10-29 11:47:58 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
2020-12-31 13:56:59 +08:00
|
|
|
|
* 发送短视频
|
2022-03-31 02:24:38 +08:00
|
|
|
|
* @param string $file 文件的路径、URL或者base64编码的短视频数据
|
|
|
|
|
|
* @param bool $cache 是否缓存(默认为true)
|
|
|
|
|
|
* @param bool $proxy 是否使用代理(默认为true)
|
|
|
|
|
|
* @param int $timeout 超时时间(默认不超时)
|
|
|
|
|
|
* @return string CQ码
|
2018-10-29 11:47:58 +08:00
|
|
|
|
*/
|
2022-03-31 02:24:38 +08:00
|
|
|
|
public static function video(string $file, bool $cache = true, bool $proxy = true, int $timeout = -1): string
|
2022-03-15 18:05:33 +08:00
|
|
|
|
{
|
2020-12-31 13:56:59 +08:00
|
|
|
|
return
|
2022-03-15 18:05:33 +08:00
|
|
|
|
'[CQ:video,file=' . self::encode($file, true) .
|
|
|
|
|
|
(!$cache ? ',cache=0' : '') .
|
|
|
|
|
|
(!$proxy ? ',proxy=false' : '') .
|
|
|
|
|
|
($timeout != -1 ? (',timeout=' . $timeout) : '') .
|
|
|
|
|
|
']';
|
2018-10-29 11:47:58 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 发送投掷骰子(只能在单条回复中单独使用)
|
2022-03-31 02:24:38 +08:00
|
|
|
|
* @return string CQ码
|
2018-10-29 11:47:58 +08:00
|
|
|
|
*/
|
2022-03-31 02:24:38 +08:00
|
|
|
|
public static function rps(): string
|
2022-03-15 18:05:33 +08:00
|
|
|
|
{
|
|
|
|
|
|
return '[CQ:rps]';
|
2018-10-29 11:47:58 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 发送掷骰子表情(只能在单条回复中单独使用)
|
2022-03-31 02:24:38 +08:00
|
|
|
|
* @return string CQ码
|
2018-10-29 11:47:58 +08:00
|
|
|
|
*/
|
2022-03-31 02:24:38 +08:00
|
|
|
|
public static function dice(): string
|
2022-03-15 18:05:33 +08:00
|
|
|
|
{
|
|
|
|
|
|
return '[CQ:dice]';
|
2018-10-29 11:47:58 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 戳一戳(原窗口抖动,仅支持好友消息使用)
|
2022-03-31 02:24:38 +08:00
|
|
|
|
* @return string CQ码
|
2018-10-29 11:47:58 +08:00
|
|
|
|
*/
|
2022-03-31 02:24:38 +08:00
|
|
|
|
public static function shake(): string
|
2022-03-15 18:05:33 +08:00
|
|
|
|
{
|
|
|
|
|
|
return '[CQ:shake]';
|
2018-10-29 11:47:58 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2020-12-31 13:56:59 +08:00
|
|
|
|
/**
|
|
|
|
|
|
* 发送新的戳一戳
|
2022-03-31 02:24:38 +08:00
|
|
|
|
* @param int|string $type 焯一戳类型
|
|
|
|
|
|
* @param int|string $id 戳一戳ID号
|
|
|
|
|
|
* @param string $name 戳一戳名称(可选)
|
|
|
|
|
|
* @return string CQ码
|
2020-12-31 13:56:59 +08:00
|
|
|
|
*/
|
2022-03-31 02:24:38 +08:00
|
|
|
|
public static function poke($type, $id, string $name = ''): string
|
2022-03-15 18:05:33 +08:00
|
|
|
|
{
|
|
|
|
|
|
return "[CQ:poke,type={$type},id={$id}" . ($name != '' ? (',name=' . self::encode($name, true)) : '') . ']';
|
2020-12-31 13:56:59 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 发送匿名消息
|
2022-03-31 02:24:38 +08:00
|
|
|
|
* @param int $ignore 是否忽略错误(默认为1,0表示不忽略错误)
|
|
|
|
|
|
* @return string CQ码
|
2020-12-31 13:56:59 +08:00
|
|
|
|
*/
|
2022-03-31 02:24:38 +08:00
|
|
|
|
public static function anonymous(int $ignore = 1): string
|
2022-03-15 18:05:33 +08:00
|
|
|
|
{
|
|
|
|
|
|
return '[CQ:anonymous' . ($ignore != 1 ? ',ignore=0' : '') . ']';
|
2020-12-31 13:56:59 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 发送链接分享(只能在单条回复中单独使用)
|
2022-03-31 02:24:38 +08:00
|
|
|
|
* @param string $url 分享地址
|
|
|
|
|
|
* @param string $title 标题
|
|
|
|
|
|
* @param null|string $content 卡片内容(可选)
|
|
|
|
|
|
* @param null|string $image 卡片图片(可选)
|
|
|
|
|
|
* @return string CQ码
|
2020-12-31 13:56:59 +08:00
|
|
|
|
*/
|
2022-03-31 02:24:38 +08:00
|
|
|
|
public static function share(string $url, string $title, ?string $content = null, ?string $image = null): string
|
2022-03-15 18:05:33 +08:00
|
|
|
|
{
|
|
|
|
|
|
if ($content === null) {
|
|
|
|
|
|
$c = '';
|
|
|
|
|
|
} else {
|
|
|
|
|
|
$c = ',content=' . self::encode($content, true);
|
|
|
|
|
|
}
|
|
|
|
|
|
if ($image === null) {
|
|
|
|
|
|
$i = '';
|
|
|
|
|
|
} else {
|
|
|
|
|
|
$i = ',image=' . self::encode($image, true);
|
|
|
|
|
|
}
|
|
|
|
|
|
return '[CQ:share,url=' . self::encode($url, true) . ',title=' . self::encode($title, true) . $c . $i . ']';
|
2020-12-31 13:56:59 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 发送好友或群推荐名片
|
2022-05-04 17:53:49 +08:00
|
|
|
|
* @param int|string $type 名片类型
|
2022-03-31 02:24:38 +08:00
|
|
|
|
* @param int|string $id 好友或群ID
|
|
|
|
|
|
* @return string CQ码
|
2020-12-31 13:56:59 +08:00
|
|
|
|
*/
|
2022-05-04 17:53:49 +08:00
|
|
|
|
public static function contact($type, $id): string
|
2022-03-15 18:05:33 +08:00
|
|
|
|
{
|
|
|
|
|
|
return "[CQ:contact,type={$type},id={$id}]";
|
2020-12-31 13:56:59 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2021-02-20 16:57:19 +08:00
|
|
|
|
/**
|
|
|
|
|
|
* 发送位置
|
2022-03-31 02:24:38 +08:00
|
|
|
|
* @param float|string $lat 纬度
|
|
|
|
|
|
* @param float|string $lon 经度
|
|
|
|
|
|
* @param string $title 标题(可选)
|
|
|
|
|
|
* @param string $content 卡片内容(可选)
|
|
|
|
|
|
* @return string CQ码
|
2021-02-20 16:57:19 +08:00
|
|
|
|
*/
|
2022-03-31 02:24:38 +08:00
|
|
|
|
public static function location($lat, $lon, string $title = '', string $content = ''): string
|
2022-03-15 18:05:33 +08:00
|
|
|
|
{
|
|
|
|
|
|
return '[CQ:location' .
|
2022-03-31 02:24:38 +08:00
|
|
|
|
',lat=' . self::encode((string) $lat, true) .
|
|
|
|
|
|
',lon=' . self::encode((string) $lon, true) .
|
2022-03-15 18:05:33 +08:00
|
|
|
|
($title != '' ? (',title=' . self::encode($title, true)) : '') .
|
|
|
|
|
|
($content != '' ? (',content=' . self::encode($content, true)) : '') .
|
|
|
|
|
|
']';
|
2020-12-31 13:56:59 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2018-10-29 11:47:58 +08:00
|
|
|
|
/**
|
|
|
|
|
|
* 发送音乐分享(只能在单条回复中单独使用)
|
2022-03-31 02:24:38 +08:00
|
|
|
|
*
|
2018-10-29 11:47:58 +08:00
|
|
|
|
* qq、163、xiami为内置分享,需要先通过搜索功能获取id后使用
|
2022-03-31 02:24:38 +08:00
|
|
|
|
*
|
|
|
|
|
|
* @param string $type 分享类型(仅限 `qq`、`163`、`xiami` 或 `custom`)
|
|
|
|
|
|
* @param int|string $id_or_url 当分享类型不是 `custom` 时,表示的是分享音乐的ID(需要先通过搜索功能获取id后使用),反之表示的是音乐卡片点入的链接
|
|
|
|
|
|
* @param null|string $audio 当分享类型是 `custom` 时,表示为音乐(如mp3文件)的HTTP链接地址(不可为空)
|
|
|
|
|
|
* @param null|string $title 当分享类型是 `custom` 时,表示为音乐卡片的标题,建议12字以内(不可为空)
|
|
|
|
|
|
* @param null|string $content 当分享类型是 `custom` 时,表示为音乐卡片的简介(可忽略)
|
|
|
|
|
|
* @param null|string $image 当分享类型是 `custom` 时,表示为音乐卡片的图片链接地址(可忽略)
|
|
|
|
|
|
* @return string CQ码
|
2018-10-29 11:47:58 +08:00
|
|
|
|
*/
|
2022-03-31 02:24:38 +08:00
|
|
|
|
public static function music(string $type, $id_or_url, ?string $audio = null, ?string $title = null, ?string $content = null, ?string $image = null): string
|
2022-03-15 18:05:33 +08:00
|
|
|
|
{
|
2018-10-29 11:47:58 +08:00
|
|
|
|
switch ($type) {
|
2022-03-15 18:05:33 +08:00
|
|
|
|
case 'qq':
|
|
|
|
|
|
case '163':
|
|
|
|
|
|
case 'xiami':
|
|
|
|
|
|
return "[CQ:music,type={$type},id={$id_or_url}]";
|
|
|
|
|
|
case 'custom':
|
2018-10-29 11:47:58 +08:00
|
|
|
|
if ($title === null || $audio === null) {
|
2022-03-15 18:05:33 +08:00
|
|
|
|
Console::warning(zm_internal_errcode('E00035') . '传入CQ码实例的标题和音频链接不能为空!');
|
|
|
|
|
|
return ' ';
|
|
|
|
|
|
}
|
|
|
|
|
|
if ($content === null) {
|
|
|
|
|
|
$c = '';
|
|
|
|
|
|
} else {
|
|
|
|
|
|
$c = ',content=' . self::encode($content, true);
|
2018-10-29 11:47:58 +08:00
|
|
|
|
}
|
2022-03-15 18:05:33 +08:00
|
|
|
|
if ($image === null) {
|
|
|
|
|
|
$i = '';
|
|
|
|
|
|
} else {
|
|
|
|
|
|
$i = ',image=' . self::encode($image, true);
|
|
|
|
|
|
}
|
|
|
|
|
|
return '[CQ:music,type=custom,url=' .
|
2021-02-20 16:57:19 +08:00
|
|
|
|
self::encode($id_or_url, true) .
|
2022-03-15 18:05:33 +08:00
|
|
|
|
',audio=' . self::encode($audio, true) . ',title=' . self::encode($title, true) . $c . $i .
|
|
|
|
|
|
']';
|
2018-10-29 11:47:58 +08:00
|
|
|
|
default:
|
2022-03-15 18:05:33 +08:00
|
|
|
|
Console::warning(zm_internal_errcode('E00035') . "传入的music type({$type})错误!");
|
|
|
|
|
|
return ' ';
|
2018-10-29 11:47:58 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2022-03-31 02:24:38 +08:00
|
|
|
|
/**
|
|
|
|
|
|
* 合并转发消息
|
|
|
|
|
|
* @param int|string $id 合并转发ID, 需要通过 `/get_forward_msg` API获取转发的具体内容
|
|
|
|
|
|
* @return string CQ码
|
|
|
|
|
|
*/
|
|
|
|
|
|
public static function forward($id): string
|
2022-03-15 18:05:33 +08:00
|
|
|
|
{
|
2022-03-31 02:24:38 +08:00
|
|
|
|
return '[CQ:forward,id=' . self::encode((string) $id) . ']';
|
2020-12-31 13:56:59 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2022-03-31 02:24:38 +08:00
|
|
|
|
/**
|
|
|
|
|
|
* 合并转发消息节点
|
|
|
|
|
|
* 特殊说明: 需要使用单独的API /send_group_forward_msg 发送, 并且由于消息段较为复杂, 仅支持Array形式入参。
|
|
|
|
|
|
* 如果引用消息和自定义消息同时出现, 实际查看顺序将取消息段顺序。
|
|
|
|
|
|
* 另外按 CQHTTP 文档说明, data 应全为字符串, 但由于需要接收message 类型的消息, 所以 仅限此Type的content字段 支持Array套娃
|
|
|
|
|
|
* @deprecated 这个不推荐使用,因为 go-cqhttp 官方没有对其提供CQ码模式相关支持,仅支持Array模式发送
|
|
|
|
|
|
* @param int|string $user_id 转发消息id
|
|
|
|
|
|
* @param string $nickname 发送者显示名字
|
|
|
|
|
|
* @param string $content 具体消息
|
|
|
|
|
|
* @return string CQ码
|
|
|
|
|
|
*/
|
|
|
|
|
|
public static function node($user_id, string $nickname, string $content): string
|
2022-03-15 18:05:33 +08:00
|
|
|
|
{
|
|
|
|
|
|
return "[CQ:node,user_id={$user_id},nickname=" . self::encode($nickname, true) . ',content=' . self::encode($content, true) . ']';
|
2021-02-20 16:57:19 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2022-03-31 02:24:38 +08:00
|
|
|
|
/**
|
|
|
|
|
|
* XML消息
|
|
|
|
|
|
* @param string $data xml内容, xml中的value部分
|
|
|
|
|
|
* @return string CQ码
|
|
|
|
|
|
*/
|
|
|
|
|
|
public static function xml(string $data): string
|
2022-03-15 18:05:33 +08:00
|
|
|
|
{
|
|
|
|
|
|
return '[CQ:xml,data=' . self::encode($data, true) . ']';
|
2021-02-20 16:57:19 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2022-03-31 02:24:38 +08:00
|
|
|
|
/**
|
|
|
|
|
|
* JSON消息
|
|
|
|
|
|
* @param string $data json内容
|
|
|
|
|
|
* @param int $resid 0为走小程序通道,其他值为富文本通道(默认为0)
|
|
|
|
|
|
* @return string CQ码
|
|
|
|
|
|
*/
|
|
|
|
|
|
public static function json(string $data, int $resid = 0): string
|
2022-03-15 18:05:33 +08:00
|
|
|
|
{
|
2022-03-31 02:24:38 +08:00
|
|
|
|
return '[CQ:json,data=' . self::encode($data, true) . ',resid=' . $resid . ']';
|
2021-02-20 16:57:19 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2022-03-31 02:24:38 +08:00
|
|
|
|
/**
|
|
|
|
|
|
* 返回一个自定义扩展的CQ码(支持自定义类型和参数)
|
|
|
|
|
|
* @param string $type_name CQ码类型名称
|
|
|
|
|
|
* @param array $params 参数
|
|
|
|
|
|
* @return string CQ码
|
|
|
|
|
|
*/
|
|
|
|
|
|
public static function _custom(string $type_name, array $params): string
|
2022-03-15 18:05:33 +08:00
|
|
|
|
{
|
|
|
|
|
|
$code = '[CQ:' . $type_name;
|
2021-02-20 16:57:19 +08:00
|
|
|
|
foreach ($params as $k => $v) {
|
2022-03-15 18:05:33 +08:00
|
|
|
|
$code .= ',' . $k . '=' . self::escape($v, true);
|
2021-02-20 16:57:19 +08:00
|
|
|
|
}
|
2022-03-15 18:05:33 +08:00
|
|
|
|
$code .= ']';
|
2021-02-20 16:57:19 +08:00
|
|
|
|
return $code;
|
2018-10-29 11:47:58 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 反转义字符串中的CQ码敏感符号
|
2022-05-04 17:53:49 +08:00
|
|
|
|
* @param int|string|Stringable $msg 字符串
|
|
|
|
|
|
* @param bool $is_content 如果是解码CQ码本体内容,则为false(默认),如果是参数内的字符串,则为true
|
|
|
|
|
|
* @return string 转义后的CQ码
|
2018-10-29 11:47:58 +08:00
|
|
|
|
*/
|
2022-05-04 17:53:49 +08:00
|
|
|
|
public static function decode($msg, bool $is_content = false): string
|
2022-03-15 18:05:33 +08:00
|
|
|
|
{
|
|
|
|
|
|
$msg = str_replace(['&', '[', ']'], ['&', '[', ']'], $msg);
|
|
|
|
|
|
if ($is_content) {
|
|
|
|
|
|
$msg = str_replace(',', ',', $msg);
|
|
|
|
|
|
}
|
2021-02-20 16:57:19 +08:00
|
|
|
|
return $msg;
|
2018-10-29 11:47:58 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2022-03-31 02:24:38 +08:00
|
|
|
|
/**
|
|
|
|
|
|
* 简单反转义替换CQ码的方括号
|
2022-05-04 17:53:49 +08:00
|
|
|
|
* @param int|string|Stringable $str 字符串
|
|
|
|
|
|
* @return string 字符串
|
2022-03-31 02:24:38 +08:00
|
|
|
|
*/
|
2022-05-04 17:53:49 +08:00
|
|
|
|
public static function replace($str): string
|
2022-03-15 18:05:33 +08:00
|
|
|
|
{
|
|
|
|
|
|
$str = str_replace('{{', '[', $str);
|
|
|
|
|
|
return str_replace('}}', ']', $str);
|
2018-10-29 11:47:58 +08:00
|
|
|
|
}
|
2018-11-28 13:26:18 +08:00
|
|
|
|
|
2020-03-02 16:14:20 +08:00
|
|
|
|
/**
|
2021-02-20 16:57:19 +08:00
|
|
|
|
* 转义CQ码的特殊字符,同encode
|
2022-05-04 17:53:49 +08:00
|
|
|
|
* @param int|string|Stringable $msg 字符串
|
|
|
|
|
|
* @param bool $is_content 如果是转义CQ码本体内容,则为false(默认),如果是参数内的字符串,则为true
|
|
|
|
|
|
* @return string 转义后的CQ码
|
2020-03-02 16:14:20 +08:00
|
|
|
|
*/
|
2022-05-04 17:53:49 +08:00
|
|
|
|
public static function escape($msg, bool $is_content = false): string
|
2022-03-15 18:05:33 +08:00
|
|
|
|
{
|
|
|
|
|
|
$msg = str_replace(['&', '[', ']'], ['&', '[', ']'], $msg);
|
|
|
|
|
|
if ($is_content) {
|
|
|
|
|
|
$msg = str_replace(',', ',', $msg);
|
|
|
|
|
|
}
|
2020-03-02 16:14:20 +08:00
|
|
|
|
return $msg;
|
|
|
|
|
|
}
|
2018-11-28 13:26:18 +08:00
|
|
|
|
|
2021-02-20 16:57:19 +08:00
|
|
|
|
/**
|
|
|
|
|
|
* 转义CQ码的特殊字符
|
2022-05-04 17:53:49 +08:00
|
|
|
|
* @param int|string|Stringable $msg 字符串
|
|
|
|
|
|
* @param bool $is_content 如果是转义CQ码本体内容,则为false(默认),如果是参数内的字符串,则为true
|
|
|
|
|
|
* @return string 转义后的CQ码
|
2021-02-20 16:57:19 +08:00
|
|
|
|
*/
|
2022-05-04 17:53:49 +08:00
|
|
|
|
public static function encode($msg, bool $is_content = false): string
|
2022-03-15 18:05:33 +08:00
|
|
|
|
{
|
2022-05-04 22:30:56 +08:00
|
|
|
|
$msg = str_replace(['&', '[', ']'], ['&', '[', ']'], strval($msg));
|
2022-03-15 18:05:33 +08:00
|
|
|
|
if ($is_content) {
|
|
|
|
|
|
$msg = str_replace(',', ',', $msg);
|
|
|
|
|
|
}
|
2021-02-20 16:57:19 +08:00
|
|
|
|
return $msg;
|
2020-05-06 15:01:32 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2021-02-20 16:57:19 +08:00
|
|
|
|
/**
|
|
|
|
|
|
* 移除消息中所有的CQ码并返回移除CQ码后的消息
|
2022-03-31 02:24:38 +08:00
|
|
|
|
* @param string $msg 消息
|
|
|
|
|
|
* @return string 消息内容
|
2021-02-20 16:57:19 +08:00
|
|
|
|
*/
|
2022-03-31 02:24:38 +08:00
|
|
|
|
public static function removeCQ(string $msg): string
|
2022-03-15 18:05:33 +08:00
|
|
|
|
{
|
|
|
|
|
|
$final = '';
|
2021-02-20 16:57:19 +08:00
|
|
|
|
$last_end = 0;
|
2021-06-16 00:17:30 +08:00
|
|
|
|
foreach (self::getAllCQ($msg) as $v) {
|
2022-03-15 18:05:33 +08:00
|
|
|
|
$final .= mb_substr($msg, $last_end, $v['start'] - $last_end);
|
|
|
|
|
|
$last_end = $v['end'] + 1;
|
2018-11-28 13:26:18 +08:00
|
|
|
|
}
|
2021-02-20 16:57:19 +08:00
|
|
|
|
$final .= mb_substr($msg, $last_end);
|
|
|
|
|
|
return $final;
|
2018-11-28 13:26:18 +08:00
|
|
|
|
}
|
2020-05-08 16:37:38 +08:00
|
|
|
|
|
2021-02-20 16:57:19 +08:00
|
|
|
|
/**
|
|
|
|
|
|
* 获取消息中第一个CQ码
|
2022-04-03 01:47:38 +08:00
|
|
|
|
* @param string $msg 消息内容
|
|
|
|
|
|
* @param bool $is_object 是否以对象形式返回,如果为False的话,返回数组形式(默认为false)
|
|
|
|
|
|
* @return null|array|CQObject 返回的CQ码(数组或对象)
|
2021-02-20 16:57:19 +08:00
|
|
|
|
*/
|
2022-03-31 02:24:38 +08:00
|
|
|
|
public static function getCQ(string $msg, bool $is_object = false)
|
2022-03-15 18:05:33 +08:00
|
|
|
|
{
|
|
|
|
|
|
if (($head = mb_strpos($msg, '[CQ:')) !== false) {
|
2021-02-20 16:57:19 +08:00
|
|
|
|
$key_offset = mb_substr($msg, $head);
|
2022-03-15 18:05:33 +08:00
|
|
|
|
$close = mb_strpos($key_offset, ']');
|
|
|
|
|
|
if ($close === false) {
|
|
|
|
|
|
return null;
|
|
|
|
|
|
}
|
2021-02-20 16:57:19 +08:00
|
|
|
|
$content = mb_substr($msg, $head + 4, $close + $head - mb_strlen($msg));
|
2022-03-15 18:05:33 +08:00
|
|
|
|
$exp = explode(',', $content);
|
|
|
|
|
|
$cq['type'] = array_shift($exp);
|
2021-06-16 00:17:30 +08:00
|
|
|
|
foreach ($exp as $v) {
|
2022-03-15 18:05:33 +08:00
|
|
|
|
$ss = explode('=', $v);
|
2021-02-20 16:57:19 +08:00
|
|
|
|
$sk = array_shift($ss);
|
2022-03-15 18:05:33 +08:00
|
|
|
|
$cq['params'][$sk] = self::decode(implode('=', $ss), true);
|
2021-02-20 16:57:19 +08:00
|
|
|
|
}
|
2022-03-15 18:05:33 +08:00
|
|
|
|
$cq['start'] = $head;
|
|
|
|
|
|
$cq['end'] = $close + $head;
|
2021-03-15 02:54:16 +08:00
|
|
|
|
return !$is_object ? $cq : CQObject::fromArray($cq);
|
2021-02-20 16:57:19 +08:00
|
|
|
|
}
|
2022-03-15 18:05:33 +08:00
|
|
|
|
return null;
|
2021-02-20 16:57:19 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 获取消息中所有的CQ码
|
2022-03-31 02:24:38 +08:00
|
|
|
|
* @param string $msg 消息内容
|
|
|
|
|
|
* @param bool $is_object 是否以对象形式返回,如果为False的话,返回数组形式(默认为false)
|
|
|
|
|
|
* @return array|CQObject[] 返回的CQ码们(数组或对象)
|
2021-02-20 16:57:19 +08:00
|
|
|
|
*/
|
2022-03-31 02:24:38 +08:00
|
|
|
|
public static function getAllCQ(string $msg, bool $is_object = false): array
|
2022-03-15 18:05:33 +08:00
|
|
|
|
{
|
2021-02-20 16:57:19 +08:00
|
|
|
|
$cqs = [];
|
|
|
|
|
|
$offset = 0;
|
2022-03-15 18:05:33 +08:00
|
|
|
|
while (($head = mb_strpos(($submsg = mb_substr($msg, $offset)), '[CQ:')) !== false) {
|
2021-02-20 16:57:19 +08:00
|
|
|
|
$key_offset = mb_substr($submsg, $head);
|
2022-03-15 18:05:33 +08:00
|
|
|
|
$tmpmsg = mb_strpos($key_offset, ']');
|
|
|
|
|
|
if ($tmpmsg === false) {
|
|
|
|
|
|
break;
|
|
|
|
|
|
} // 没闭合,不算CQ码
|
2021-02-20 16:57:19 +08:00
|
|
|
|
$content = mb_substr($submsg, $head + 4, $tmpmsg + $head - mb_strlen($submsg));
|
2022-03-15 18:05:33 +08:00
|
|
|
|
$exp = explode(',', $content);
|
2021-02-20 16:57:19 +08:00
|
|
|
|
$cq = [];
|
2022-03-15 18:05:33 +08:00
|
|
|
|
$cq['type'] = array_shift($exp);
|
2021-06-16 00:17:30 +08:00
|
|
|
|
foreach ($exp as $v) {
|
2022-03-15 18:05:33 +08:00
|
|
|
|
$ss = explode('=', $v);
|
2021-02-20 16:57:19 +08:00
|
|
|
|
$sk = array_shift($ss);
|
2022-03-15 18:05:33 +08:00
|
|
|
|
$cq['params'][$sk] = self::decode(implode('=', $ss), true);
|
2021-02-20 16:57:19 +08:00
|
|
|
|
}
|
2022-03-15 18:05:33 +08:00
|
|
|
|
$cq['start'] = $offset + $head;
|
|
|
|
|
|
$cq['end'] = $offset + $tmpmsg + $head;
|
2021-11-08 22:05:41 +08:00
|
|
|
|
$offset += $head + $tmpmsg + 1;
|
2021-03-15 02:54:16 +08:00
|
|
|
|
$cqs[] = (!$is_object ? $cq : CQObject::fromArray($cq));
|
2020-05-08 16:37:38 +08:00
|
|
|
|
}
|
2021-02-20 16:57:19 +08:00
|
|
|
|
return $cqs;
|
2020-05-08 16:37:38 +08:00
|
|
|
|
}
|
2020-04-29 15:29:56 +08:00
|
|
|
|
}
|