diff --git a/bots/aiocqhttp/message.py b/bots/aiocqhttp/message.py index 0758f13f3c9..b3008741ee5 100644 --- a/bots/aiocqhttp/message.py +++ b/bots/aiocqhttp/message.py @@ -139,7 +139,7 @@ async def send_message( parts = re.split(r"(\[CQ:[^\]]+\])", x.text) parts = [part for part in parts if part] previous_was_cq = False - # CQ码消息段相连会导致自动转义,故使用零宽字符`\u200B`隔开 + # CQ码消息段相连会导致自动转义,故使用零宽字符`\u200B`隔开 for i, part in enumerate(parts): if re.match(r"\[CQ:[^\]]+\]", part): try: diff --git a/core/builtins/message/chain.py b/core/builtins/message/chain.py index c675389fa38..4fe7f26eadd 100644 --- a/core/builtins/message/chain.py +++ b/core/builtins/message/chain.py @@ -1,6 +1,7 @@ from __future__ import annotations import base64 +import html import re from typing import List, Optional, Tuple, Union, Any from typing import TYPE_CHECKING @@ -176,6 +177,29 @@ def as_sendable(self, msg: MessageSession = None, embed: bool = True) -> list: value += x.to_message_chain(msg) elif isinstance(x, PlainElement): if x.text != "": + if msg: + pattern = r'\[i18n:([^\s,]+)(?:,([^\]]+))?\]' + matches = re.findall(pattern, x.text) + + for match in matches: + key = html.unescape(match[0]) + kwargs = {} + + if match[1]: + params = match[1].split(',') + for param in params: + k, v = param.split('=') + kwargs[html.unescape(k)] = html.unescape(v) + + t_value = msg.locale.t(key, **kwargs) + if isinstance(t_value, str): + x.text = x.text.replace( + f"[i18n:{ + match[0]}{ + ',' + + match[1] if match[1] else ''}]", + t_value) + value.append(x) else: value.append( @@ -301,10 +325,11 @@ def __iadd__(self, other): return self -def match_kecode(text: str) -> List[Union[PlainElement, ImageElement, VoiceElement]]: +def match_kecode(text: str) -> List[Union[PlainElement, ImageElement, VoiceElement, I18NContextElement]]: split_all = re.split(r"(\[Ke:.*?])", text) split_all = [x for x in split_all if x] elements = [] + for e in split_all: match = re.match(r"\[Ke:(.*?),(.*)]", e) if not match: @@ -313,18 +338,21 @@ def match_kecode(text: str) -> List[Union[PlainElement, ImageElement, VoiceEleme else: element_type = match.group(1).lower() args = re.split(r",|,.\s", match.group(2)) - for x in args: - if not x: - args.remove("") + + args = [x for x in args if x] + if element_type == "plain": for a in args: ma = re.match(r"(.*?)=(.*)", a) if ma: if ma.group(1) == "text": - elements.append(PlainElement.assign(ma.group(2))) + ua = html.unescape(ma.group(2)) + elements.append(PlainElement.assign(ua)) else: + a = html.unescape(a) elements.append(PlainElement.assign(a)) else: + a = html.unescape(a) elements.append(PlainElement.assign(a)) elif element_type == "image": for a in args: @@ -333,17 +361,17 @@ def match_kecode(text: str) -> List[Union[PlainElement, ImageElement, VoiceEleme img = None if ma.group(1) == "path": parse_url = urlparse(ma.group(2)) - if parse_url[0] == "file" or url_pattern.match( - parse_url[1] - ): + if parse_url[0] == "file" or url_pattern.match(parse_url[1]): img = ImageElement.assign(path=ma.group(2)) - if ma.group(1) == "headers": - img.headers = json.loads( - str(base64.b64decode(ma.group(2)), "UTF-8") - ) + if ma.group(1) == "headers" and img: + img.headers = json.loads(str(base64.b64decode(ma.group(2)), "UTF-8")) if img: elements.append(img) + else: + a = html.unescape(a) + elements.append(ImageElement.assign(a)) else: + a = html.unescape(a) elements.append(ImageElement.assign(a)) elif element_type == "voice": for a in args: @@ -351,26 +379,26 @@ def match_kecode(text: str) -> List[Union[PlainElement, ImageElement, VoiceEleme if ma: if ma.group(1) == "path": parse_url = urlparse(ma.group(2)) - if parse_url[0] == "file" or url_pattern.match( - parse_url[1] - ): + if parse_url[0] == "file" or url_pattern.match(parse_url[1]): elements.append(VoiceElement.assign(ma.group(2))) else: + a = html.unescape(a) elements.append(VoiceElement.assign(a)) else: + a = html.unescape(a) elements.append(VoiceElement.assign(a)) elif element_type == "i18n": - key = "" + i18nkey = None kwargs = {} for a in args: ma = re.match(r"(.*?)=(.*)", a) if ma: if ma.group(1) == "i18nkey": - key = ma.group(2) + i18nkey = html.unescape(ma.group(2)) else: - kwargs[ma.group(1)] = ma.group(2) - - elements.append(I18NContextElement.assign(key, **kwargs)) + kwargs[ma.group(1)] = html.unescape(ma.group(2)) + if i18nkey: + elements.append(I18NContextElement.assign(i18nkey, **kwargs)) return elements diff --git a/core/dirty_check.py b/core/dirty_check.py index c554efcf294..87fc7b8f0b1 100644 --- a/core/dirty_check.py +++ b/core/dirty_check.py @@ -43,20 +43,17 @@ def parse_data(result: dict, additional_text=None) -> Dict: if "positions" in itemContext: for pos in itemContext["positions"]: filter_words_length = pos["endPos"] - pos["startPos"] - reason = f"[Ke:i18n,i18nkey=check.redacted,reason={itemDetail['label']}]" - content = ( - content[: pos["startPos"] + _offset] - + reason - + content[pos["endPos"] + _offset:] - ) + reason = f"[i18n:check.redacted,reason={itemDetail['label']}]" + content = (content[: pos["startPos"] + _offset] + + reason + content[pos["endPos"] + _offset:]) if additional_text: content += "\n" + additional_text + "\n" _offset += len(reason) - filter_words_length else: - content = f"[Ke:i18n,i18nkey=check.redacted,reason={itemDetail['label']}]" + content = f"[i18n:i18nkey=check.redacted,reason={itemDetail['label']}]" status = False else: - content = f"[Ke:i18n,i18nkey=check.redacted.all,reason={itemDetail['label']}]" + content = f"[i18n:i18nkey=check.redacted.all,reason={itemDetail['label']}]" if additional_text: content += "\n" + additional_text + "\n" diff --git a/modules/ip/__init__.py b/modules/ip/__init__.py index 970eceb3adb..e0fd9e7450a 100644 --- a/modules/ip/__init__.py +++ b/modules/ip/__init__.py @@ -84,24 +84,30 @@ async def check_ip(ip: str): 'real_ip': real_ip } if not skip_geoip: - data = json.loads(await get_url('https://api.ip.sb/geoip/' + ip)) + data = await get_url(f"https://api.ip.sb/geoip/{ip}", 200, fmt="json") for key in res: if key in data: res[key] = data[key] - try: reverse = socket.getnameinfo((ip, 0), 0) res['reverse'] = reverse[0] - except BaseException: + except Exception: Logger.warning("Unable to fetch reverse DNS.") return res +def zzzq(msg: Bot.MessageSession, country: str): + if msg.target.client_name in ["KOOK", "QQ", "QQ|Bot"] and \ + country in ["Hong Kong", "Macao", "Taiwan"]: + return "China" + return country + + def parse_coordinate(axis: str, value: float): - if axis == 'latitude': + if axis == "latitude": return f'{value}°{"N" if value > 0 else "S"}' - if axis == 'longitude': + if axis == "longitude": return f'{value}°{"E" if value > 0 else "W"}' @@ -122,26 +128,18 @@ async def format_ip(msg, info: Dict[str, Any]): 'unknown': msg.locale.t('message.unknown') } - res.append(info['ip']) + res.append(info["ip"]) res.append(f"{msg.locale.t('ip.message.type')}IPv{info['version']} { ip_property[info['ip_property']]}{msg.locale.t('ip.message.ip_property')}") res.append(f"{msg.locale.t('ip.message.real_ip')}{info['real_ip']}" if info['real_ip'] else '') res.append( f"""{ - f'''{ - msg.locale.t('ip.message.location')}{ - f"{ - info['city']}, " if info['city'] else ''}{ - f"{ - info['region']}, " if info['region'] else ''}{ - info['country']}''' if info['country'] else ''}{ - f" ({ - parse_coordinate( - 'longitude', - info['longitude'])}, { - parse_coordinate( - 'latitude', - info['latitude'])})" if info['longitude'] and info['latitude'] else ''}""") + f'''{msg.locale.t('ip.message.location')}{ + f"{info['city']}, " if info['city'] else ''}{ + f"{info['region']}, " if info['region'] else ''}{ + zzzq(msg, info['country'])}''' if info['country'] else ''}{ + f" ({parse_coordinate('longitude', info['longitude'])}, { + parse_coordinate('latitude', info['latitude'])})" if info['longitude'] and info['latitude'] else ''}""") res.append(f"{msg.locale.t('ip.message.postal_code')}{info['postal_code']}" if info['postal_code'] else '') res.append(f"{msg.locale.t('ip.message.organization')}{info['organization']}" if info['organization'] else '') res.append(f"""{f"{msg.locale.t('ip.message.asn')}{info['asn']}" if info['asn'] else ''}{ diff --git a/modules/ncmusic/__init__.py b/modules/ncmusic/__init__.py index 24ee38c5de4..bd25fa75fee 100644 --- a/modules/ncmusic/__init__.py +++ b/modules/ncmusic/__init__.py @@ -150,7 +150,7 @@ async def _(msg: Bot.MessageSession, keyword: str): msg.locale.t("ncmusic.message.search.invalid.non_digital") ) - if Bot.client_name == "QQ" and Config("ncmusic_enable_card", False): + if msg.target.client_name == "QQ" and Config("ncmusic_enable_card", False): await msg.finish(f"[CQ:music,type=163,id={sid}]", quote=False) else: await info(msg, sid)