$v) { $code .= ',' . $k . '=' . self::escape($v, true); } $code .= ']'; return $code; } /** * 反转义字符串中的CQ码敏感符号 * @param int|string|Stringable $msg 字符串 * @param bool $is_content 如果是解码CQ码本体内容,则为false(默认),如果是参数内的字符串,则为true * @return string 转义后的CQ码 */ public static function decode($msg, bool $is_content = false): string { $msg = str_replace(['&', '[', ']'], ['&', '[', ']'], $msg); if ($is_content) { $msg = str_replace(',', ',', $msg); } return $msg; } /** * 简单反转义替换CQ码的方括号 * @param int|string|Stringable $str 字符串 * @return string 字符串 */ public static function replace($str): string { $str = str_replace('{{', '[', $str); return str_replace('}}', ']', $str); } /** * 转义CQ码的特殊字符,同encode * @param int|string|Stringable $msg 字符串 * @param bool $is_content 如果是转义CQ码本体内容,则为false(默认),如果是参数内的字符串,则为true * @return string 转义后的CQ码 */ public static function escape($msg, bool $is_content = false): string { $msg = str_replace(['&', '[', ']'], ['&', '[', ']'], $msg); if ($is_content) { $msg = str_replace(',', ',', $msg); } return $msg; } /** * 转义CQ码的特殊字符 * @param int|string|Stringable $msg 字符串 * @param bool $is_content 如果是转义CQ码本体内容,则为false(默认),如果是参数内的字符串,则为true * @return string 转义后的CQ码 */ public static function encode($msg, bool $is_content = false): string { $msg = str_replace(['&', '[', ']'], ['&', '[', ']'], strval($msg)); if ($is_content) { $msg = str_replace(',', ',', $msg); } return $msg; } /** * 移除消息中所有的CQ码并返回移除CQ码后的消息 * @param string $msg 消息 * @return string 消息内容 */ public static function removeCQ(string $msg): string { $final = ''; $last_end = 0; foreach (self::getAllCQ($msg) as $v) { $final .= mb_substr($msg, $last_end, $v['start'] - $last_end); $last_end = $v['end'] + 1; } $final .= mb_substr($msg, $last_end); return $final; } /** * 获取消息中第一个CQ码 * @param string $msg 消息内容 * @param bool $is_object 是否以对象形式返回,如果为False的话,返回数组形式(默认为false) * @return null|array|CQObject 返回的CQ码(数组或对象) */ public static function getCQ(string $msg, bool $is_object = false) { if (($head = mb_strpos($msg, '[CQ:')) !== false) { $key_offset = mb_substr($msg, $head); $close = mb_strpos($key_offset, ']'); if ($close === false) { return null; } $content = mb_substr($msg, $head + 4, $close + $head - mb_strlen($msg)); $exp = explode(',', $content); $cq['type'] = array_shift($exp); foreach ($exp as $v) { $ss = explode('=', $v); $sk = array_shift($ss); $cq['params'][$sk] = self::decode(implode('=', $ss), true); } $cq['start'] = $head; $cq['end'] = $close + $head; return !$is_object ? $cq : CQObject::fromArray($cq); } return null; } /** * 获取消息中所有的CQ码 * @param string $msg 消息内容 * @param bool $is_object 是否以对象形式返回,如果为False的话,返回数组形式(默认为false) * @return array|CQObject[] 返回的CQ码们(数组或对象) */ public static function getAllCQ(string $msg, bool $is_object = false): array { $cqs = []; $offset = 0; while (($head = mb_strpos(($submsg = mb_substr($msg, $offset)), '[CQ:')) !== false) { $key_offset = mb_substr($submsg, $head); $tmpmsg = mb_strpos($key_offset, ']'); if ($tmpmsg === false) { break; } // 没闭合,不算CQ码 $content = mb_substr($submsg, $head + 4, $tmpmsg + $head - mb_strlen($submsg)); $exp = explode(',', $content); $cq = []; $cq['type'] = array_shift($exp); foreach ($exp as $v) { $ss = explode('=', $v); $sk = array_shift($ss); $cq['params'][$sk] = self::decode(implode('=', $ss), true); } $cq['start'] = $offset + $head; $cq['end'] = $offset + $tmpmsg + $head; $offset += $head + $tmpmsg + 1; $cqs[] = (!$is_object ? $cq : CQObject::fromArray($cq)); } return $cqs; } }