diff --git a/.flake8 b/.flake8
new file mode 100644
index 0000000..6deafc2
--- /dev/null
+++ b/.flake8
@@ -0,0 +1,2 @@
+[flake8]
+max-line-length = 120
diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml
new file mode 100644
index 0000000..a5add71
--- /dev/null
+++ b/.pre-commit-config.yaml
@@ -0,0 +1,17 @@
+repos:
+ - repo: https://github.com/psf/black
+ rev: 22.1.0
+ hooks:
+ - id: black
+
+ - repo: https://github.com/PyCQA/flake8
+ rev: 4.0.1
+ hooks:
+ - id: flake8
+ additional_dependencies:
+ - flake8-bugbear
+
+ - repo: https://github.com/PyCQA/isort
+ rev: 5.10.1
+ hooks:
+ - id: isort
diff --git a/efb_qq_plugin_go_cqhttp/ChatMgr.py b/efb_qq_plugin_go_cqhttp/ChatMgr.py
index cca1867..ee0698a 100644
--- a/efb_qq_plugin_go_cqhttp/ChatMgr.py
+++ b/efb_qq_plugin_go_cqhttp/ChatMgr.py
@@ -8,95 +8,100 @@ from ehforwarderbot.types import ChatID
class ChatManager:
- def __init__(self, channel: 'QQMessengerChannel'):
- self.channel: 'QQMessengerChannel' = channel
+ def __init__(self, channel: "QQMessengerChannel"):
+ self.channel: "QQMessengerChannel" = channel
self.logger: logging.Logger = logging.getLogger(__name__)
self.MISSING_GROUP: GroupChat = GroupChat(
- channel=self.channel,
- uid=ChatID("__error_group__"),
- name="Group Missing"
+ channel=self.channel, uid=ChatID("__error_group__"), name="Group Missing"
)
self.MISSING_CHAT: PrivateChat = PrivateChat(
- channel=self.channel,
- uid=ChatID("__error_chat__"),
- name="Chat Missing"
+ channel=self.channel, uid=ChatID("__error_chat__"), name="Chat Missing"
)
def build_efb_chat_as_private(self, context):
- uid = context['user_id']
- if 'sender' not in context or 'nickname' not in context['sender']:
+ uid = context["user_id"]
+ if "sender" not in context or "nickname" not in context["sender"]:
i: dict = self.channel.QQClient.get_stranger_info(uid)
chat_name = ""
if i:
- chat_name = i['nickname']
+ chat_name = i["nickname"]
else:
- chat_name = context['sender']['nickname']
- efb_chat = PrivateChat(channel=self.channel,
- uid='private' + '_' + str(uid),
- name=str(chat_name),
- alias=None if 'alias' not in context else str(context['alias']))
+ chat_name = context["sender"]["nickname"]
+ efb_chat = PrivateChat(
+ channel=self.channel,
+ uid="private" + "_" + str(uid),
+ name=str(chat_name),
+ alias=None if "alias" not in context else str(context["alias"]),
+ )
return efb_chat
def build_or_get_efb_member(self, chat: Chat, context):
- member_uid = context['user_id']
+ member_uid = context["user_id"]
with contextlib.suppress(KeyError):
return chat.get_member(str(member_uid))
- chat_name = ''
- if 'nickname' not in context:
+ chat_name = ""
+ if "nickname" not in context:
i: dict = self.channel.QQClient.get_stranger_info(member_uid)
chat_name = ""
if i:
- chat_name = i['nickname']
+ chat_name = i["nickname"]
else:
- chat_name = context['nickname']
- return chat.add_member(name=str(chat_name),
- alias=None if 'alias' not in context else str(context['alias']),
- uid=str(member_uid))
+ chat_name = context["nickname"]
+ return chat.add_member(
+ name=str(chat_name),
+ alias=None if "alias" not in context else str(context["alias"]),
+ uid=str(member_uid),
+ )
def build_efb_chat_as_group(self, context, update_member=False): # Should be cached
- is_discuss = False if context['message_type'] == 'group' else True
- chat_uid = context['discuss_id'] if is_discuss else context['group_id']
- efb_chat = GroupChat(
- channel=self.channel,
- uid=str(chat_uid)
- )
+ is_discuss = False if context["message_type"] == "group" else True
+ chat_uid = context["discuss_id"] if is_discuss else context["group_id"]
+ efb_chat = GroupChat(channel=self.channel, uid=str(chat_uid))
if not is_discuss:
- efb_chat.uid = 'group' + '_' + str(chat_uid)
+ efb_chat.uid = "group" + "_" + str(chat_uid)
i = self.channel.QQClient.get_group_info(chat_uid)
if i is not None:
- efb_chat.name = str(i['group_name']) if 'group_name' not in context else str(context['group_name'])
+ efb_chat.name = str(i["group_name"]) if "group_name" not in context else str(context["group_name"])
else:
efb_chat.name = str(chat_uid)
- efb_chat.vendor_specific = {'is_discuss': False}
+ efb_chat.vendor_specific = {"is_discuss": False}
if update_member:
members = self.channel.QQClient.get_group_member_list(chat_uid, False)
if members:
for member in members:
- efb_chat.add_member(name=str(member['card']),
- alias=str(member['nickname']),
- uid=str(member['user_id']))
+ efb_chat.add_member(
+ name=str(member["card"]),
+ alias=str(member["nickname"]),
+ uid=str(member["user_id"]),
+ )
else:
- efb_chat.uid = 'discuss' + '_' + str(chat_uid)
- efb_chat.name = 'Discuss Group' + '_' + str(chat_uid)
+ efb_chat.uid = "discuss" + "_" + str(chat_uid)
+ efb_chat.name = "Discuss Group" + "_" + str(chat_uid)
# todo Find a way to distinguish from different discuss group
- efb_chat.vendor_specific = {'is_discuss': True}
+ efb_chat.vendor_specific = {"is_discuss": True}
return efb_chat
def build_efb_chat_as_anonymous_user(self, chat: Chat, context):
- anonymous_data = context['anonymous']
- member_uid = 'anonymous' + '_' + anonymous_data['flag']
+ anonymous_data = context["anonymous"]
+ member_uid = "anonymous" + "_" + anonymous_data["flag"]
with contextlib.suppress(KeyError):
return chat.get_member(member_uid)
- chat_name = '[Anonymous] ' + anonymous_data['name']
- return chat.add_member(name=str(chat_name),
- alias=None if 'alias' not in context else str(context['alias']),
- uid=str(member_uid),
- vendor_specific={'is_anonymous': True,
- 'anonymous_id': anonymous_data['id']})
+ chat_name = "[Anonymous] " + anonymous_data["name"]
+ return chat.add_member(
+ name=str(chat_name),
+ alias=None if "alias" not in context else str(context["alias"]),
+ uid=str(member_uid),
+ vendor_specific={
+ "is_anonymous": True,
+ "anonymous_id": anonymous_data["id"],
+ },
+ )
def build_efb_chat_as_system_user(self, context): # System user only!
- return SystemChat(channel=self.channel,
- name=str(context['event_description']),
- uid=ChatID("__{context[uid_prefix]}__".format(context=context)))
+ return SystemChat(
+ channel=self.channel,
+ name=str(context["event_description"]),
+ uid=ChatID("__{context[uid_prefix]}__".format(context=context)),
+ )
diff --git a/efb_qq_plugin_go_cqhttp/GoCQHttp.py b/efb_qq_plugin_go_cqhttp/GoCQHttp.py
index eb8e7bb..97d363e 100644
--- a/efb_qq_plugin_go_cqhttp/GoCQHttp.py
+++ b/efb_qq_plugin_go_cqhttp/GoCQHttp.py
@@ -4,32 +4,52 @@ import tempfile
import threading
import time
import uuid
-from datetime import timedelta, datetime
+from datetime import datetime, timedelta
from gettext import translation
-from typing import Any, Dict, List, BinaryIO, Tuple, Optional, Union
+from typing import Any, BinaryIO, Dict, List, Optional, Tuple, Union
import cherrypy
import cqhttp
-from PIL import Image
from cherrypy._cpserver import Server
from cherrypy.process.wspbus import states
from cqhttp import CQHttp
from efb_qq_slave import BaseClient, QQMessengerChannel
-from ehforwarderbot import Message, MsgType, Chat, coordinator, Status
-from ehforwarderbot.chat import SelfChatMember, ChatMember, SystemChatMember, PrivateChat
-from ehforwarderbot.exceptions import EFBMessageError, EFBOperationNotSupported, EFBChatNotFound
-from ehforwarderbot.message import MessageCommands, MessageCommand
+from ehforwarderbot import Chat, Message, MsgType, Status, coordinator
+from ehforwarderbot.chat import (
+ ChatMember,
+ PrivateChat,
+ SelfChatMember,
+ SystemChatMember,
+)
+from ehforwarderbot.exceptions import (
+ EFBChatNotFound,
+ EFBMessageError,
+ EFBOperationNotSupported,
+)
+from ehforwarderbot.message import MessageCommand, MessageCommands
from ehforwarderbot.status import MessageRemoval
from ehforwarderbot.types import ChatID
from ehforwarderbot.utils import extra
+from PIL import Image
from pkg_resources import resource_filename
from requests import RequestException
from .ChatMgr import ChatManager
-from .Exceptions import CoolQDisconnectedException, CoolQAPIFailureException, CoolQOfflineException
+from .Exceptions import (
+ CoolQAPIFailureException,
+ CoolQDisconnectedException,
+ CoolQOfflineException,
+)
from .MsgDecorator import QQMsgProcessor
-from .Utils import qq_emoji_list, async_send_messages_to_master, process_quote_text, coolq_text_encode, \
- download_user_avatar, download_group_avatar, download_file
+from .Utils import (
+ async_send_messages_to_master,
+ coolq_text_encode,
+ download_file,
+ download_group_avatar,
+ download_user_avatar,
+ process_quote_text,
+ qq_emoji_list,
+)
class GoCQHttp(BaseClient):
@@ -41,9 +61,11 @@ class GoCQHttp(BaseClient):
logger: logging.Logger = logging.getLogger(__name__)
channel: QQMessengerChannel
- translator = translation("efb_qq_slave",
- resource_filename('efb_qq_slave', 'Clients/CoolQ/locale'),
- fallback=True)
+ translator = translation(
+ "efb_qq_slave",
+ resource_filename("efb_qq_slave", "Clients/CoolQ/locale"),
+ fallback=True,
+ )
_ = translator.gettext
ngettext = translator.ngettext
@@ -71,9 +93,10 @@ class GoCQHttp(BaseClient):
def __init__(self, client_id: str, config: Dict[str, Any], channel):
super().__init__(client_id, config)
self.client_config = config[self.client_id]
- self.coolq_bot = CQHttp(api_root=self.client_config['api_root'],
- access_token=self.client_config['access_token']
- )
+ self.coolq_bot = CQHttp(
+ api_root=self.client_config["api_root"],
+ access_token=self.client_config["access_token"],
+ )
self.channel = channel
self.chat_manager = ChatManager(channel)
@@ -81,59 +104,65 @@ class GoCQHttp(BaseClient):
self.is_logged_in = False
self.msg_decorator = QQMsgProcessor(instance=self)
- def message_element_wrapper(context: Dict[str, Any], msg_element: Dict[str, Any], chat: Chat) -> \
- Tuple[str, List[Message], List[Tuple[Tuple[int, int], Union[Chat, ChatMember]]]]:
- msg_type = msg_element['type']
- msg_data = msg_element['data']
- main_text: str = ''
+ def message_element_wrapper(
+ context: Dict[str, Any], msg_element: Dict[str, Any], chat: Chat
+ ) -> Tuple[str, List[Message], List[Tuple[Tuple[int, int], Union[Chat, ChatMember]]]]:
+ msg_type = msg_element["type"]
+ msg_data = msg_element["data"]
+ main_text: str = ""
messages: List[Message] = []
at_list: List[Tuple[Tuple[int, int], Union[Chat, ChatMember]]] = []
- if msg_type == 'text':
- main_text = msg_data['text']
- elif msg_type == 'face':
- qq_face = int(msg_data['id'])
+ if msg_type == "text":
+ main_text = msg_data["text"]
+ elif msg_type == "face":
+ qq_face = int(msg_data["id"])
if qq_face in qq_emoji_list:
main_text = qq_emoji_list[qq_face]
else:
- main_text = '\u2753' # ❓
- elif msg_type == 'sface':
- main_text = '\u2753' # ❓
- elif msg_type == 'at':
+ main_text = "\u2753" # ❓
+ elif msg_type == "sface":
+ main_text = "\u2753" # ❓
+ elif msg_type == "at":
# todo Recheck if bug exists
- g_id = context['group_id']
+ g_id = context["group_id"]
my_uid = self.get_qq_uid()
- self.logger.debug('My QQ uid: %s\n'
- 'QQ mentioned: %s\n', my_uid, msg_data['qq'])
- if str(msg_data['qq']) == 'all':
- group_card = 'all'
+ self.logger.debug("My QQ uid: %s\n" "QQ mentioned: %s\n", my_uid, msg_data["qq"])
+ if str(msg_data["qq"]) == "all":
+ group_card = "all"
else:
- member_info = self.get_user_info(msg_data['qq'], group_id=g_id)['in_group_info']
- group_card = member_info['card'] if member_info['card'] != '' else member_info['nickname']
- self.logger.debug('Group card: {}'.format(group_card))
+ member_info = self.get_user_info(msg_data["qq"], group_id=g_id)["in_group_info"]
+ group_card = member_info["card"] if member_info["card"] != "" else member_info["nickname"]
+ self.logger.debug("Group card: {}".format(group_card))
substitution_begin = len(main_text)
substitution_end = len(main_text) + len(group_card) + 1
- main_text = '@{} '.format(group_card)
- if str(my_uid) == str(msg_data['qq']) or str(msg_data['qq']) == 'all':
+ main_text = "@{} ".format(group_card)
+ if str(my_uid) == str(msg_data["qq"]) or str(msg_data["qq"]) == "all":
at_dict = ((substitution_begin, substitution_end), chat.self)
at_list.append(at_dict)
- elif msg_type == 'reply':
- ref_user = self.get_user_info(msg_data['qq'])
- main_text = f'「{ref_user["remark"]}({ref_user["nickname"]}):{msg_data["text"]}」\n' \
- '- - - - - - - - - - - - - - -\n'
+ elif msg_type == "reply":
+ ref_user = self.get_user_info(msg_data["qq"])
+ main_text = (
+ f'「{ref_user["remark"]}({ref_user["nickname"]}):{msg_data["text"]}」\n'
+ "- - - - - - - - - - - - - - -\n"
+ )
else:
messages.extend(self.call_msg_decorator(msg_type, msg_data, chat))
return main_text, messages, at_list
- def message_elements_wrapper(context: Dict[str, Any], msg_elements: List[Dict[str, Any]], chat: Chat) -> \
- Tuple[str, List[Message], Dict[Tuple[int, int], Union[Chat, ChatMember]]]:
+ def message_elements_wrapper(
+ context: Dict[str, Any], msg_elements: List[Dict[str, Any]], chat: Chat
+ ) -> Tuple[str, List[Message], Dict[Tuple[int, int], Union[Chat, ChatMember]]]:
messages: List[Message] = []
- main_text: str = ''
+ main_text: str = ""
at_dict: Dict[Tuple[int, int], Union[Chat, ChatMember]] = {}
for msg_element in msg_elements:
sub_main_text, sub_messages, sub_at_list = message_element_wrapper(context, msg_element, chat)
main_text_len = len(main_text)
for at_tuple in sub_at_list:
- pos = (at_tuple[0][0] + main_text_len, at_tuple[0][1] + main_text_len)
+ pos = (
+ at_tuple[0][0] + main_text_len,
+ at_tuple[0][1] + main_text_len,
+ )
at_dict[pos] = at_tuple[1]
main_text += sub_main_text
messages.extend(sub_messages)
@@ -142,33 +171,33 @@ class GoCQHttp(BaseClient):
@self.coolq_bot.on_message
def handle_msg(context):
self.logger.debug(repr(context))
- msg_elements = context['message']
- qq_uid = context['user_id']
+ msg_elements = context["message"]
+ qq_uid = context["user_id"]
chat: Chat
author: ChatMember
user = self.get_user_info(qq_uid)
- if context['message_type'] == 'private':
- context['alias'] = user['remark']
+ if context["message_type"] == "private":
+ context["alias"] = user["remark"]
chat: PrivateChat = self.chat_manager.build_efb_chat_as_private(context)
else:
chat = self.chat_manager.build_efb_chat_as_group(context)
- if 'anonymous' not in context or context['anonymous'] is None:
- if context['message_type'] == 'group':
- if context['sub_type'] == 'notice':
- context['event_description'] = self._("System Notification")
- context['uid_prefix'] = 'group_notification'
+ if "anonymous" not in context or context["anonymous"] is None:
+ if context["message_type"] == "group":
+ if context["sub_type"] == "notice":
+ context["event_description"] = self._("System Notification")
+ context["uid_prefix"] = "group_notification"
author = chat.add_system_member(
- name=context['event_description'],
- uid=ChatID("__{context[uid_prefix]}__".format(context=context))
+ name=context["event_description"],
+ uid=ChatID("__{context[uid_prefix]}__".format(context=context)),
)
else:
- user = self.get_user_info(qq_uid, group_id=context['group_id'])
- context['nickname'] = user['remark']
- context['alias'] = user['in_group_info']['card']
+ user = self.get_user_info(qq_uid, group_id=context["group_id"])
+ context["nickname"] = user["remark"]
+ context["alias"] = user["in_group_info"]["card"]
author = self.chat_manager.build_or_get_efb_member(chat, context)
- elif context['message_type'] == 'private':
+ elif context["message_type"] == "private":
author = chat.other
else:
author = self.chat_manager.build_or_get_efb_member(chat, context)
@@ -180,18 +209,18 @@ class GoCQHttp(BaseClient):
if main_text != "":
messages.append(self.msg_decorator.qq_text_simple_wrapper(main_text, at_dict))
uid: str = str(uuid.uuid4())
- coolq_msg_id = context['message_id']
+ coolq_msg_id = context["message_id"]
for i in range(len(messages)):
if not isinstance(messages[i], Message):
continue
efb_msg: Message = messages[i]
- efb_msg.uid = uid + '_' + str(coolq_msg_id) + '_' + str(i)
+ efb_msg.uid = uid + "_" + str(coolq_msg_id) + "_" + str(i)
efb_msg.chat = chat
efb_msg.author = author
# if qq_uid != '80000000':
# Append discuss group into group list
- if context['message_type'] == 'discuss' and efb_msg.chat not in self.discuss_list:
+ if context["message_type"] == "discuss" and efb_msg.chat not in self.discuss_list:
self.discuss_list.append(efb_msg.chat)
efb_msg.deliver_to = coordinator.master
@@ -201,170 +230,192 @@ class GoCQHttp(BaseClient):
send_message_wrapper(efb_msg)
- @self.coolq_bot.on_notice('group_increase')
+ @self.coolq_bot.on_notice("group_increase")
def handle_group_increase_msg(context):
- context['event_description'] = self._('\u2139 Group Member Increase Event')
- if (context['sub_type']) == 'invite':
- text = self._('{nickname}({context[user_id]}) joined the group({group_name}) via invitation')
+ context["event_description"] = self._("\u2139 Group Member Increase Event")
+ if (context["sub_type"]) == "invite":
+ text = self._("{nickname}({context[user_id]}) joined the group({group_name}) via invitation")
else:
- text = self._('{nickname}({context[user_id]}) joined the group({group_name})')
+ text = self._("{nickname}({context[user_id]}) joined the group({group_name})")
- original_group = self.get_group_info(context['group_id'], False)
- group_name = context['group_id']
- if original_group is not None and 'group_name' in original_group:
- group_name = original_group['group_name']
- text = text.format(nickname=self.get_stranger_info(context['user_id'])['nickname'],
- context=context,
- group_name=group_name)
+ original_group = self.get_group_info(context["group_id"], False)
+ group_name = context["group_id"]
+ if original_group is not None and "group_name" in original_group:
+ group_name = original_group["group_name"]
+ text = text.format(
+ nickname=self.get_stranger_info(context["user_id"])["nickname"],
+ context=context,
+ group_name=group_name,
+ )
- context['message'] = text
+ context["message"] = text
self.send_efb_group_notice(context)
- @self.coolq_bot.on_notice('group_decrease')
+ @self.coolq_bot.on_notice("group_decrease")
def handle_group_decrease_msg(context):
- context['event_description'] = self._("\u2139 Group Member Decrease Event")
- original_group = self.get_group_info(context['group_id'], False)
- group_name = context['group_id']
- if original_group is not None and 'group_name' in original_group:
- group_name = original_group['group_name']
- text = ''
- if context['sub_type'] == 'kick_me':
+ context["event_description"] = self._("\u2139 Group Member Decrease Event")
+ original_group = self.get_group_info(context["group_id"], False)
+ group_name = context["group_id"]
+ if original_group is not None and "group_name" in original_group:
+ group_name = original_group["group_name"]
+ text = ""
+ if context["sub_type"] == "kick_me":
text = self._("You've been kicked from the group({})").format(group_name)
else:
- if context['sub_type'] == 'leave':
- text = self._('{nickname}({context[user_id]}) quited the group({group_name})')
+ if context["sub_type"] == "leave":
+ text = self._("{nickname}({context[user_id]}) quited the group({group_name})")
else:
- text = self._('{nickname}({context[user_id]}) was kicked from the group({group_name})')
- text = text.format(nickname=self.get_stranger_info(context['user_id'])['nickname'],
- context=context,
- group_name=group_name)
- context['message'] = text
+ text = self._("{nickname}({context[user_id]}) was kicked from the group({group_name})")
+ text = text.format(
+ nickname=self.get_stranger_info(context["user_id"])["nickname"],
+ context=context,
+ group_name=group_name,
+ )
+ context["message"] = text
self.send_efb_group_notice(context)
- @self.coolq_bot.on_notice('offline_file')
+ @self.coolq_bot.on_notice("offline_file")
def handle_offline_file_upload_msg(context):
- context['event_description'] = self._("\u2139 Offline File Upload Event")
- context['uid_prefix'] = 'offline_file'
- file_info_msg = self._('Filename: {file[name]}\n'
- 'File size: {file[size]}').format(file=context['file'])
- user = self.get_user_info(context['user_id'])
- text = self._('{remark}({nickname}) uploaded a file to you\n')
- text = text.format(remark=user['remark'], nickname=user['nickname']) + file_info_msg
- context['message'] = text
+ context["event_description"] = self._("\u2139 Offline File Upload Event")
+ context["uid_prefix"] = "offline_file"
+ file_info_msg = self._("Filename: {file[name]}\n" "File size: {file[size]}").format(file=context["file"])
+ user = self.get_user_info(context["user_id"])
+ text = self._("{remark}({nickname}) uploaded a file to you\n")
+ text = text.format(remark=user["remark"], nickname=user["nickname"]) + file_info_msg
+ context["message"] = text
self.send_msg_to_master(context)
param_dict = {
- 'context': context,
- 'download_url': context['file']['url'],
+ "context": context,
+ "download_url": context["file"]["url"],
}
threading.Thread(target=self.async_download_file, args=[], kwargs=param_dict).start()
- @self.coolq_bot.on_notice('group_upload')
+ @self.coolq_bot.on_notice("group_upload")
def handle_group_file_upload_msg(context):
- context['event_description'] = self._("\u2139 Group File Upload Event")
- context['uid_prefix'] = 'group_upload'
- original_group = self.get_group_info(context['group_id'], False)
- group_name = context['group_id']
- if original_group is not None and 'group_name' in original_group:
- group_name = original_group['group_name']
+ context["event_description"] = self._("\u2139 Group File Upload Event")
+ context["uid_prefix"] = "group_upload"
+ original_group = self.get_group_info(context["group_id"], False)
+ group_name = context["group_id"]
+ if original_group is not None and "group_name" in original_group:
+ group_name = original_group["group_name"]
- file_info_msg = self._('File ID: {file[id]}\n'
- 'Filename: {file[name]}\n'
- 'File size: {file[size]}').format(file=context['file'])
- member_info = self.get_user_info(context['user_id'], group_id=context['group_id'])['in_group_info']
- group_card = member_info['card'] if member_info['card'] != '' else member_info['nickname']
- text = self._('{member_card}({context[user_id]}) uploaded a file to group({group_name})\n')
- text = text.format(member_card=group_card,
- context=context,
- group_name=group_name) + file_info_msg
- context['message'] = text
+ file_info_msg = self._("File ID: {file[id]}\n" "Filename: {file[name]}\n" "File size: {file[size]}").format(
+ file=context["file"]
+ )
+ member_info = self.get_user_info(context["user_id"], group_id=context["group_id"])["in_group_info"]
+ group_card = member_info["card"] if member_info["card"] != "" else member_info["nickname"]
+ text = self._("{member_card}({context[user_id]}) uploaded a file to group({group_name})\n")
+ text = text.format(member_card=group_card, context=context, group_name=group_name) + file_info_msg
+ context["message"] = text
self.send_efb_group_notice(context)
param_dict = {
- 'context': context,
- 'group_id': context['group_id'],
- 'file_id': context['file']['id'],
- 'busid': context['file']['busid']
+ "context": context,
+ "group_id": context["group_id"],
+ "file_id": context["file"]["id"],
+ "busid": context["file"]["busid"],
}
threading.Thread(target=self.async_download_group_file, args=[], kwargs=param_dict).start()
- @self.coolq_bot.on_notice('friend_add')
+ @self.coolq_bot.on_notice("friend_add")
def handle_friend_add_msg(context):
- context['event_description'] = self._('\u2139 New Friend Event')
- context['uid_prefix'] = 'friend_add'
- text = self._('{nickname}({context[user_id]}) has become your friend!')
- text = text.format(nickname=self.get_stranger_info(context['user_id'])['nickname'],
- context=context)
- context['message'] = text
+ context["event_description"] = self._("\u2139 New Friend Event")
+ context["uid_prefix"] = "friend_add"
+ text = self._("{nickname}({context[user_id]}) has become your friend!")
+ text = text.format(
+ nickname=self.get_stranger_info(context["user_id"])["nickname"],
+ context=context,
+ )
+ context["message"] = text
self.send_msg_to_master(context)
- @self.coolq_bot.on_request('friend') # Add friend request
+ @self.coolq_bot.on_request("friend") # Add friend request
def handle_add_friend_request(context):
self.logger.debug(repr(context))
- context['event_description'] = self._('\u2139 New Friend Request')
- context['uid_prefix'] = 'friend_request'
- text = self._('{nickname}({context[user_id]}) wants to be your friend!\n'
- 'Here is the verification comment:\n'
- '{context[comment]}')
- text = text.format(nickname=self.get_stranger_info(context['user_id'])['nickname'],
- context=context)
- context['message'] = text
- commands = [MessageCommand(
- name=self._("Accept"),
- callable_name="process_friend_request",
- kwargs={'result': 'accept',
- 'flag': context['flag']}
- ), MessageCommand(
- name=self._("Decline"),
- callable_name="process_friend_request",
- kwargs={'result': 'decline',
- 'flag': context['flag']}
- )]
- context['commands'] = commands
+ context["event_description"] = self._("\u2139 New Friend Request")
+ context["uid_prefix"] = "friend_request"
+ text = self._(
+ "{nickname}({context[user_id]}) wants to be your friend!\n"
+ "Here is the verification comment:\n"
+ "{context[comment]}"
+ )
+ text = text.format(
+ nickname=self.get_stranger_info(context["user_id"])["nickname"],
+ context=context,
+ )
+ context["message"] = text
+ commands = [
+ MessageCommand(
+ name=self._("Accept"),
+ callable_name="process_friend_request",
+ kwargs={"result": "accept", "flag": context["flag"]},
+ ),
+ MessageCommand(
+ name=self._("Decline"),
+ callable_name="process_friend_request",
+ kwargs={"result": "decline", "flag": context["flag"]},
+ ),
+ ]
+ context["commands"] = commands
self.send_msg_to_master(context)
- @self.coolq_bot.on_request('group')
+ @self.coolq_bot.on_request("group")
def handle_group_request(context):
self.logger.debug(repr(context))
- context['uid_prefix'] = 'group_request'
- context['group_name'] = self._('[Request]') + self.get_group_info(context['group_id'])['group_name']
- context['group_id_orig'] = context['group_id']
- context['group_id'] = str(context['group_id']) + "_notification"
- context['message_type'] = 'group'
- context['event_description'] = '\u2139 New Group Join Request'
- original_group = self.get_group_info(context['group_id'], False)
- group_name = context['group_id']
- if original_group is not None and 'group_name' in original_group:
- group_name = original_group['group_name']
+ context["uid_prefix"] = "group_request"
+ context["group_name"] = self._("[Request]") + self.get_group_info(context["group_id"])["group_name"]
+ context["group_id_orig"] = context["group_id"]
+ context["group_id"] = str(context["group_id"]) + "_notification"
+ context["message_type"] = "group"
+ context["event_description"] = "\u2139 New Group Join Request"
+ original_group = self.get_group_info(context["group_id"], False)
+ group_name = context["group_id"]
+ if original_group is not None and "group_name" in original_group:
+ group_name = original_group["group_name"]
msg = Message()
- msg.uid = 'group' + '_' + str(context['group_id'])
+ msg.uid = "group" + "_" + str(context["group_id"])
msg.author = self.chat_manager.build_efb_chat_as_system_user(context)
msg.chat = self.chat_manager.build_efb_chat_as_group(context)
msg.deliver_to = coordinator.master
msg.type = MsgType.Text
name = ""
- if not self.get_friend_remark(context['user_id']):
+ if not self.get_friend_remark(context["user_id"]):
name = "{}({})[{}] ".format(
- self.get_stranger_info(context['user_id'])['nickname'], self.get_friend_remark(context['user_id']),
- context['user_id'])
+ self.get_stranger_info(context["user_id"])["nickname"],
+ self.get_friend_remark(context["user_id"]),
+ context["user_id"],
+ )
else:
- name = "{}[{}] ".format(self.get_stranger_info(context['user_id'])['nickname'], context['user_id'])
+ name = "{}[{}] ".format(
+ self.get_stranger_info(context["user_id"])["nickname"],
+ context["user_id"],
+ )
msg.text = "{} wants to join the group {}({}). \nHere is the comment: {}".format(
- name, group_name, context['group_id_orig'], context['comment']
+ name, group_name, context["group_id_orig"], context["comment"]
+ )
+ msg.commands = MessageCommands(
+ [
+ MessageCommand(
+ name=self._("Accept"),
+ callable_name="process_group_request",
+ kwargs={
+ "result": "accept",
+ "flag": context["flag"],
+ "sub_type": context["sub_type"],
+ },
+ ),
+ MessageCommand(
+ name=self._("Decline"),
+ callable_name="process_group_request",
+ kwargs={
+ "result": "decline",
+ "flag": context["flag"],
+ "sub_type": context["sub_type"],
+ },
+ ),
+ ]
)
- msg.commands = MessageCommands([MessageCommand(
- name=self._("Accept"),
- callable_name="process_group_request",
- kwargs={'result': 'accept',
- 'flag': context['flag'],
- 'sub_type': context['sub_type']}
- ), MessageCommand(
- name=self._("Decline"),
- callable_name="process_group_request",
- kwargs={'result': 'decline',
- 'flag': context['flag'],
- 'sub_type': context['sub_type']}
- )])
coordinator.send_message(msg)
self.check_status_periodically(threading.Event())
@@ -377,46 +428,51 @@ class GoCQHttp(BaseClient):
cherrypy.tree.graft(self.coolq_bot.wsgi, "/")
cherrypy.server.unsubscribe()
self.cherryServer = Server()
- self.cherryServer.socket_host = self.client_config['host']
- self.cherryServer.socket_port = self.client_config['port']
+ self.cherryServer.socket_host = self.client_config["host"]
+ self.cherryServer.socket_port = self.client_config["port"]
self.cherryServer.subscribe()
cherrypy.engine.start()
cherrypy.engine.wait(states.EXITING)
- @extra(name=_("Restart CoolQ Client"),
- desc=_("Force CoolQ to restart\n"
- "Usage: {function_name} [-l] [-c] [-e]\n"
- " -l: Restart and clean log\n"
- " -c: Restart and clean cache\n"
- " -e: Restart and clean event\n"))
+ @extra(
+ name=_("Restart CoolQ Client"),
+ desc=_(
+ "Force CoolQ to restart\n"
+ "Usage: {function_name} [-l] [-c] [-e]\n"
+ " -l: Restart and clean log\n"
+ " -c: Restart and clean cache\n"
+ " -e: Restart and clean event\n"
+ ),
+ )
def relogin(self, param: str = ""):
param_dict = dict()
if param:
- params = param.split(' ')
+ params = param.split(" ")
for each_param in params:
- if each_param == ' ':
+ if each_param == " ":
continue
- if each_param == '-l':
- param_dict['clean_log'] = 'true'
- elif each_param == '-c':
- param_dict['clean_cache'] = 'true'
- elif each_param == '-e':
- param_dict['clean_event'] = 'true'
+ if each_param == "-l":
+ param_dict["clean_log"] = "true"
+ elif each_param == "-c":
+ param_dict["clean_cache"] = "true"
+ elif each_param == "-e":
+ param_dict["clean_event"] = "true"
else:
return self._("Unknown parameter: {}.").format(param)
self.logger.debug(repr(param_dict))
- self.coolq_api_query('_set_restart', **param_dict)
- return 'Done. Please wait for a while.'
+ self.coolq_api_query("_set_restart", **param_dict)
+ return "Done. Please wait for a while."
def logout(self):
raise NotImplementedError
- @extra(name=_("Check CoolQ Status"),
- desc=_("Force efb-qq-slave to refresh status from CoolQ Client.\n"
- "Usage: {function_name}"))
+ @extra(
+ name=_("Check CoolQ Status"),
+ desc=_("Force efb-qq-slave to refresh status from CoolQ Client.\n" "Usage: {function_name}"),
+ )
def login(self, param: str = ""):
self.check_status_periodically(None)
- return 'Done'
+ return "Done"
def get_stranger_info(self, user_id: int, no_cache: bool = False) -> Dict[str, Any]:
user_id = int(user_id)
@@ -424,11 +480,14 @@ class GoCQHttp(BaseClient):
def get_login_info(self) -> Dict[Any, Any]:
res = self.coolq_bot.get_status()
- if 'good' in res or 'online' in res:
+ if "good" in res or "online" in res:
data = self.coolq_bot.get_login_info()
- return {'status': 0, 'data': {'uid': data['user_id'], 'nickname': data['nickname']}}
+ return {
+ "status": 0,
+ "data": {"uid": data["user_id"], "nickname": data["nickname"]},
+ }
else:
- return {'status': 1}
+ return {"status": 1}
def get_groups(self) -> List:
# todo Add support for discuss group iteration
@@ -437,20 +496,21 @@ class GoCQHttp(BaseClient):
# res = self.coolq_bot.get_group_list()
groups = []
for i in range(len(res)):
- context = {'message_type': 'group',
- 'group_id': res[i]['group_id']}
+ context = {"message_type": "group", "group_id": res[i]["group_id"]}
efb_chat = self.chat_manager.build_efb_chat_as_group(context)
groups.append(efb_chat)
for i in range(len(self.extra_group_list)):
does_exist = False
- for j in range(len(res)):
- if str(self.extra_group_list[i]['group_id']) == str(res[i]['group_id']):
+ for _j in range(len(res)):
+ if str(self.extra_group_list[i]["group_id"]) == str(res[i]["group_id"]):
does_exist = True
break
if does_exist:
continue
- context = {'message_type': 'group',
- 'group_id': self.extra_group_list[i]['group_id']}
+ context = {
+ "message_type": "group",
+ "group_id": self.extra_group_list[i]["group_id"],
+ }
efb_chat = self.chat_manager.build_efb_chat_as_group(context)
groups.append(efb_chat)
return groups + self.discuss_list
@@ -459,14 +519,15 @@ class GoCQHttp(BaseClient):
try:
self.update_friend_list() # Force update friend list
except CoolQAPIFailureException:
- self.deliver_alert_to_master(self._('Failed to retrieve the friend list.\n'
- 'Only groups are shown.'))
+ self.deliver_alert_to_master(self._("Failed to retrieve the friend list.\n" "Only groups are shown."))
return []
users = []
for current_user in self.friend_list:
- context = {'user_id': str(current_user['user_id']),
- 'nickname': current_user['nickname'],
- 'alias': current_user['remark']}
+ context = {
+ "user_id": str(current_user["user_id"]),
+ "nickname": current_user["nickname"],
+ "alias": current_user["remark"],
+ }
efb_chat = self.chat_manager.build_efb_chat_as_private(context)
users.append(efb_chat)
return users
@@ -475,7 +536,7 @@ class GoCQHttp(BaseClient):
# Replaced by handle_msg()
pass
- def send_message(self, msg: 'Message') -> 'Message':
+ def send_message(self, msg: "Message") -> "Message":
# todo Add support for edited message
"""
self.logger.info("[%s] Sending message to WeChat:\n"
@@ -488,43 +549,47 @@ class GoCQHttp(BaseClient):
msg.chat.chat_uid, msg.type, msg.text, repr(msg.target.chat), msg.target.uid)
"""
m = QQMsgProcessor(instance=self)
- chat_type = msg.chat.uid.split('_')
+ chat_type = msg.chat.uid.split("_")
- self.logger.debug('[%s] Is edited: %s', msg.uid, msg.edit)
+ self.logger.debug("[%s] Is edited: %s", msg.uid, msg.edit)
if msg.edit:
try:
- uid_type = msg.uid.split('_')
+ uid_type = msg.uid.split("_")
self.recall_message(uid_type[1])
except CoolQAPIFailureException:
- raise EFBOperationNotSupported(self._("Failed to recall the message!\n"
- "This message may have already expired."))
+ raise EFBOperationNotSupported(
+ self._("Failed to recall the message!\n" "This message may have already expired.")
+ )
if msg.type in [MsgType.Text, MsgType.Link]:
if msg.text == "kick`":
group_id = chat_type[1]
user_id = msg.target.author.uid
- self.coolq_api_query("set_group_kick",
- group_id=group_id,
- user_id=user_id)
+ self.coolq_api_query("set_group_kick", group_id=group_id, user_id=user_id)
else:
if isinstance(msg.target, Message):
max_length = 50
tgt_text = coolq_text_encode(process_quote_text(msg.target.text, max_length))
tgt_alias = ""
- if chat_type[0] != 'private' and not isinstance(msg.target.author, SelfChatMember):
+ if chat_type[0] != "private" and not isinstance(msg.target.author, SelfChatMember):
tgt_alias += m.coolq_code_at_wrapper(msg.target.author.uid)
else:
tgt_alias = ""
- msg.text = "%s%s\n\n%s" % (tgt_alias, tgt_text, coolq_text_encode(msg.text))
+ msg.text = "%s%s\n\n%s" % (
+ tgt_alias,
+ tgt_text,
+ coolq_text_encode(msg.text),
+ )
msg.uid = self.coolq_send_message(chat_type[0], chat_type[1], msg.text)
- self.logger.debug('[%s] Sent as a text message. %s', msg.uid, msg.text)
+ self.logger.debug("[%s] Sent as a text message. %s", msg.uid, msg.text)
elif msg.type in (MsgType.Image, MsgType.Sticker, MsgType.Animation):
self.logger.info("[%s] Image/Sticker/Animation %s", msg.uid, msg.type)
- text = ''
+ text = ""
if not self.can_send_image:
self.check_features() # Force checking features
- raise EFBOperationNotSupported(self._("Unable to send image now. Please check your CoolQ version "
- "or retry later"))
+ raise EFBOperationNotSupported(
+ self._("Unable to send image now. Please check your CoolQ version " "or retry later")
+ )
if msg.type != MsgType.Sticker:
text += m.coolq_code_image_wrapper(msg.file, msg.path)
else:
@@ -535,7 +600,7 @@ class GoCQHttp(BaseClient):
mask = Image.eval(alpha, lambda a: 255 if a <= 128 else 0)
except IndexError:
mask = Image.eval(img.split()[0], lambda a: 0)
- img = img.convert('RGB').convert('P', palette=Image.ADAPTIVE, colors=255)
+ img = img.convert("RGB").convert("P", palette=Image.ADAPTIVE, colors=255)
img.paste(255, mask)
img.save(f, transparency=255)
msg.file.close()
@@ -549,8 +614,12 @@ class GoCQHttp(BaseClient):
elif msg.type is MsgType.Voice:
if not self.can_send_voice:
self.check_features() # Force checking features
- raise EFBOperationNotSupported(self._("Unable to send voice now. Please check your CoolQ version "
- " and install CoolQ audio library or retry later"))
+ raise EFBOperationNotSupported(
+ self._(
+ "Unable to send voice now. Please check your CoolQ version "
+ " and install CoolQ audio library or retry later"
+ )
+ )
text = m.coolq_voice_image_wrapper(msg.file, msg.path)
msg.uid = self.coolq_send_message(chat_type[0], chat_type[1], text)
if msg.text:
@@ -559,7 +628,7 @@ class GoCQHttp(BaseClient):
def call_msg_decorator(self, msg_type: str, *args) -> List[Message]:
try:
- func = getattr(self.msg_decorator, 'qq_{}_wrapper'.format(msg_type))
+ func = getattr(self.msg_decorator, "qq_{}_wrapper".format(msg_type))
except AttributeError:
msg = f"Unsupported message type: {msg_type}"
self.logger.error(msg)
@@ -569,24 +638,27 @@ class GoCQHttp(BaseClient):
def get_qq_uid(self):
res = self.get_login_info()
- if res['status'] == 0:
- return res['data']['uid']
+ if res["status"] == 0:
+ return res["data"]["uid"]
else:
return None
def get_group_member_list(self, group_id, no_cache=False) -> List[Dict[str, Any]]:
- if no_cache or (group_id not in self.group_member_dict) \
- or (datetime.now() - self.group_member_dict[group_id]['time'] > timedelta(hours=1)): # Force Update
+ if (
+ no_cache
+ or (group_id not in self.group_member_dict)
+ or (datetime.now() - self.group_member_dict[group_id]["time"] > timedelta(hours=1))
+ ): # Force Update
try:
- member_list = self.coolq_api_query('get_group_member_list', group_id=group_id, no_cache=no_cache)
+ member_list = self.coolq_api_query("get_group_member_list", group_id=group_id, no_cache=no_cache)
except CoolQAPIFailureException as e:
self.deliver_alert_to_master(self._("Failed the get group member detail.") + "{}".format(e))
return []
self.group_member_dict[group_id] = {
- 'members': member_list,
- 'time': datetime.now()
+ "members": member_list,
+ "time": datetime.now(),
}
- return self.group_member_dict[group_id]['members']
+ return self.group_member_dict[group_id]["members"]
def get_user_info(self, user_id: int, group_id: Optional[str] = None, no_cache=False):
user_id = int(user_id)
@@ -595,23 +667,23 @@ class GoCQHttp(BaseClient):
friend = copy.deepcopy(self.friend_dict.get(user_id))
if friend:
user = friend
- user['is_friend'] = True
+ user["is_friend"] = True
else:
user = copy.deepcopy(self.stranger_dict.get(user_id))
if no_cache or (user is None):
- user = self.coolq_api_query('get_stranger_info', user_id=user_id)
+ user = self.coolq_api_query("get_stranger_info", user_id=user_id)
self.stranger_dict[user_id] = copy.deepcopy(user)
- user['is_friend'] = False
+ user["is_friend"] = False
if group_id is not None:
- user['is_in_group'] = False
+ user["is_in_group"] = False
for member in self.get_group_member_list(group_id):
- if member['user_id'] == user_id:
- user['is_in_group'] = True
- user['in_group_info'] = member
+ if member["user_id"] == user_id:
+ user["is_in_group"] = True
+ user["in_group_info"] = member
break
- remark = user.get('remark')
+ remark = user.get("remark")
if not remark:
- user['remark'] = user['nickname']
+ user["remark"] = user["nickname"]
return user
def get_group_info(self, group_id, no_cache=False):
@@ -622,78 +694,88 @@ class GoCQHttp(BaseClient):
return group
if no_cache:
for extra_group in self.extra_group_list:
- if extra_group['group_id'] == group_id:
+ if extra_group["group_id"] == group_id:
return extra_group
try:
external_group = self.get_external_group_info(group_id)
except CoolQAPIFailureException:
- self.logger.error(f'Get external group({group_id}) info failed.')
+ self.logger.error(f"Get external group({group_id}) info failed.")
return None
else:
self.extra_group_list.append(external_group)
return external_group
def coolq_send_message(self, msg_type, uid, message):
- keyword = msg_type if msg_type != 'private' else 'user'
- res = self.coolq_api_query('send_msg', message_type=msg_type, **{keyword + '_id': uid}, message=message)
- return str(uuid.uuid4()) + '_' + str(res['message_id'])
+ keyword = msg_type if msg_type != "private" else "user"
+ res = self.coolq_api_query("send_msg", message_type=msg_type, **{keyword + "_id": uid}, message=message)
+ return str(uuid.uuid4()) + "_" + str(res["message_id"])
def _coolq_api_wrapper(self, func_name, **kwargs):
try:
func = getattr(self.coolq_bot, func_name)
res = func(**kwargs)
except RequestException as e:
- raise CoolQDisconnectedException(self._('Unable to connect to CoolQ Client!'
- 'Error Message:\n{}').format(str(e)))
+ raise CoolQDisconnectedException(
+ self._("Unable to connect to CoolQ Client!" "Error Message:\n{}").format(str(e))
+ )
except cqhttp.Error as ex:
- api_ex = CoolQAPIFailureException(self._('CoolQ HTTP API encountered an error!\n'
- 'Status Code:{} '
- 'Return Code:{}').format(ex.status_code, ex.retcode))
- setattr(api_ex, 'status_code', ex.status_code)
- setattr(api_ex, 'retcode', ex.retcode)
+ api_ex = CoolQAPIFailureException(
+ self._("CoolQ HTTP API encountered an error!\n" "Status Code:{} " "Return Code:{}").format(
+ ex.status_code, ex.retcode
+ )
+ )
+ api_ex.status_code = ex.status_code
+ api_ex.retcode = ex.retcode
raise api_ex
else:
return res
def check_running_status(self):
- res = self._coolq_api_wrapper('get_status')
- if res['good'] or res['online']:
+ res = self._coolq_api_wrapper("get_status")
+ if res["good"] or res["online"]:
return True
else:
raise CoolQOfflineException(self._("CoolQ Client isn't working correctly!"))
def coolq_api_query(self, func_name, **kwargs):
- """ # Do not call get_status too frequently
+ """# Do not call get_status too frequently
if self.check_running_status():
return self._coolq_api_wrapper(func_name, **kwargs)
"""
if self.is_logged_in and self.is_connected:
return self._coolq_api_wrapper(func_name, **kwargs)
elif self.repeat_counter < 3:
- self.deliver_alert_to_master(self._('Your status is offline.\n'
- 'You may try login with /0_login'))
+ self.deliver_alert_to_master(self._("Your status is offline.\n" "You may try login with /0_login"))
self.repeat_counter += 1
def check_status_periodically(self, t_event):
- self.logger.debug('Start checking status...')
+ self.logger.debug("Start checking status...")
flag = True
interval = 300
try:
flag = self.check_running_status()
except CoolQDisconnectedException as e:
if self.repeat_counter < 3:
- self.deliver_alert_to_master(self._("We're unable to communicate with CoolQ Client.\n"
- "Please check the connection and credentials provided.\n"
- "{}").format(str(e)))
+ self.deliver_alert_to_master(
+ self._(
+ "We're unable to communicate with CoolQ Client.\n"
+ "Please check the connection and credentials provided.\n"
+ "{}"
+ ).format(str(e))
+ )
self.repeat_counter += 1
self.is_connected = False
self.is_logged_in = False
interval = 3600
except (CoolQOfflineException, CoolQAPIFailureException):
if self.repeat_counter < 3:
- self.deliver_alert_to_master(self._('CoolQ is running in abnormal status.\n'
- 'You may need to relogin your account '
- 'or have a check in CoolQ Client.\n'))
+ self.deliver_alert_to_master(
+ self._(
+ "CoolQ is running in abnormal status.\n"
+ "You may need to relogin your account "
+ "or have a check in CoolQ Client.\n"
+ )
+ )
self.repeat_counter += 1
self.is_connected = True
self.is_logged_in = False
@@ -701,15 +783,19 @@ class GoCQHttp(BaseClient):
else:
if not flag:
if self.repeat_counter < 3:
- self.deliver_alert_to_master(self._("We don't know why, but status check failed.\n"
- "Please enable debug mode and consult the log "
- "for more details."))
+ self.deliver_alert_to_master(
+ self._(
+ "We don't know why, but status check failed.\n"
+ "Please enable debug mode and consult the log "
+ "for more details."
+ )
+ )
self.repeat_counter += 1
self.is_connected = True
self.is_logged_in = False
interval = 3600
else:
- self.logger.debug('Status: OK')
+ self.logger.debug("Status: OK")
self.is_connected = True
self.is_logged_in = True
self.repeat_counter = 0
@@ -719,47 +805,49 @@ class GoCQHttp(BaseClient):
self.check_status_timer.start()
def deliver_alert_to_master(self, message: str):
- context = {'message': message, 'uid_prefix': 'alert', 'event_description': self._('CoolQ Alert')}
+ context = {
+ "message": message,
+ "uid_prefix": "alert",
+ "event_description": self._("CoolQ Alert"),
+ }
self.send_msg_to_master(context)
def update_friend_list(self):
- self.friend_list = self.coolq_api_query('get_friend_list')
+ self.friend_list = self.coolq_api_query("get_friend_list")
if self.friend_list:
- self.logger.debug('Update friend list completed. Entries: %s', len(self.friend_list))
+ self.logger.debug("Update friend list completed. Entries: %s", len(self.friend_list))
for friend in self.friend_list:
- if friend['remark'] == '':
- friend['remark'] = friend['nickname']
- self.friend_dict[friend['user_id']] = friend
+ if friend["remark"] == "":
+ friend["remark"] = friend["nickname"]
+ self.friend_dict[friend["user_id"]] = friend
else:
- self.logger.warning('Failed to update friend list')
+ self.logger.warning("Failed to update friend list")
def update_group_list(self):
- self.group_list = self.coolq_api_query('get_group_list')
+ self.group_list = self.coolq_api_query("get_group_list")
if self.group_list:
- self.logger.debug('Update group list completed. Entries: %s', len(self.group_list))
+ self.logger.debug("Update group list completed. Entries: %s", len(self.group_list))
for group in self.group_list:
- self.group_dict[group['group_id']] = group
+ self.group_dict[group["group_id"]] = group
else:
- self.logger.warning('Failed to update group list')
+ self.logger.warning("Failed to update group list")
def update_contacts_periodically(self, t_event):
- self.logger.debug('Start updating friend & group list')
+ self.logger.debug("Start updating friend & group list")
interval = 1800
if self.is_connected and self.is_logged_in:
try:
self.update_friend_list()
self.update_group_list()
except CoolQAPIFailureException as ex:
- if getattr(ex, 'status_code') == 200 and getattr(ex, 'retcode') == 104 \
- and self.update_repeat_counter < 3:
+ if (ex.status_code) == 200 and (ex.retcode) == 104 and self.update_repeat_counter < 3:
self.send_cookie_expired_alarm()
if self.update_repeat_counter < 3:
- self.deliver_alert_to_master(self._('Errors occurred when updating contacts: ')
- + getattr(ex, 'message'))
+ self.deliver_alert_to_master(self._("Errors occurred when updating contacts: ") + (ex.message))
self.update_repeat_counter += 1
else:
self.update_repeat_counter = 0
- self.logger.debug('Update completed')
+ self.logger.debug("Update completed")
if t_event is not None and not t_event.is_set():
self.update_contacts_timer = threading.Timer(interval, self.update_contacts_periodically, [t_event])
self.update_contacts_timer.start()
@@ -769,10 +857,10 @@ class GoCQHttp(BaseClient):
self.update_friend_list()
if uid not in self.friend_dict:
return None # I don't think you have such a friend
- return self.friend_dict[uid]['remark']
+ return self.friend_dict[uid]["remark"]
def send_efb_group_notice(self, context):
- context['message_type'] = 'group'
+ context["message_type"] = "group"
self.logger.debug(repr(context))
chat = self.chat_manager.build_efb_chat_as_group(context)
try:
@@ -784,125 +872,116 @@ class GoCQHttp(BaseClient):
type=MsgType.Text,
chat=chat,
author=author,
- text=context['message'],
- deliver_to=coordinator.master
+ text=context["message"],
+ deliver_to=coordinator.master,
)
coordinator.send_message(msg)
def send_msg_to_master(self, context):
self.logger.debug(repr(context))
- if not getattr(coordinator, 'master', None): # Master Channel not initialized
- raise Exception(context['message'])
+ if not getattr(coordinator, "master", None): # Master Channel not initialized
+ raise Exception(context["message"])
chat = self.chat_manager.build_efb_chat_as_system_user(context)
try:
author = chat.get_member(SystemChatMember.SYSTEM_ID)
except KeyError:
author = chat.add_system_member()
msg = Message(
- uid="__{context[uid_prefix]}__.{uni_id}".format(context=context,
- uni_id=str(int(time.time()))),
+ uid="__{context[uid_prefix]}__.{uni_id}".format(context=context, uni_id=str(int(time.time()))),
type=MsgType.Text,
chat=chat,
author=author,
- deliver_to=coordinator.master
+ deliver_to=coordinator.master,
)
- if 'message' in context:
- msg.text = context['message']
- if 'commands' in context:
- msg.commands = MessageCommands(context['commands'])
+ if "message" in context:
+ msg.text = context["message"]
+ if "commands" in context:
+ msg.commands = MessageCommands(context["commands"])
coordinator.send_message(msg)
# As the old saying goes
# A programmer spent 20% of time on coding
# while the rest 80% on considering a variable/function/class name
def get_external_group_info(self, group_id): # Special thanks to @lwl12 for thinking of this name
- res = self.coolq_api_query('get_group_info', group_id=group_id)
+ res = self.coolq_api_query("get_group_info", group_id=group_id)
return res
- def send_status(self, status: 'Status'):
+ def send_status(self, status: "Status"):
if isinstance(status, MessageRemoval):
if not isinstance(status.message.author, SelfChatMember):
- raise EFBMessageError(self._('You can only recall your own messages.'))
+ raise EFBMessageError(self._("You can only recall your own messages."))
try:
- uid_type = status.message.uid.split('_')
+ uid_type = status.message.uid.split("_")
self.recall_message(uid_type[1])
except CoolQAPIFailureException:
- raise EFBMessageError(
- self._('Failed to recall the message. This message may have already expired.'))
+ raise EFBMessageError(self._("Failed to recall the message. This message may have already expired."))
else:
raise EFBOperationNotSupported()
# todo
def recall_message(self, message_id):
- self.coolq_api_query('delete_msg',
- message_id=message_id)
+ self.coolq_api_query("delete_msg", message_id=message_id)
def send_cookie_expired_alarm(self):
- self.deliver_alert_to_master(self._('Your cookie of CoolQ Client seems to be expired. '
- 'Although it will not affect the normal functioning of sending/receiving '
- 'messages, however, you may encounter issues like failing to retrieve '
- 'friend list. Please consult '
- 'https://github.com/milkice233/efb-qq-slave/wiki/Workaround-for-expired'
- '-cookies-of-CoolQ for solutions.'))
+ self.deliver_alert_to_master(
+ self._(
+ "Your cookie of CoolQ Client seems to be expired. "
+ "Although it will not affect the normal functioning of sending/receiving "
+ "messages, however, you may encounter issues like failing to retrieve "
+ "friend list. Please consult "
+ "https://github.com/milkice233/efb-qq-slave/wiki/Workaround-for-expired"
+ "-cookies-of-CoolQ for solutions."
+ )
+ )
def process_friend_request(self, result, flag):
- res = 'true' if result == 'accept' else 'false'
+ res = "true" if result == "accept" else "false"
try:
- self.coolq_api_query('set_friend_add_request',
- approve=res,
- flag=flag)
+ self.coolq_api_query("set_friend_add_request", approve=res, flag=flag)
except CoolQAPIFailureException as e:
- return (self._('Failed to process request! Error Message:\n')
- + getattr(e, 'message', repr(e)))
- return 'Done'
+ return self._("Failed to process request! Error Message:\n") + getattr(e, "message", repr(e))
+ return "Done"
def process_group_request(self, result, flag, sub_type):
- res = 'true' if result == 'accept' else 'false'
+ res = "true" if result == "accept" else "false"
try:
- self.coolq_api_query('set_group_add_request',
- approve=res,
- flag=flag,
- sub_type=sub_type)
+ self.coolq_api_query("set_group_add_request", approve=res, flag=flag, sub_type=sub_type)
except CoolQAPIFailureException as e:
- return (self._('Failed to process request! Error Message:\n')
- + getattr(e, 'message', repr(e)))
- return 'Done'
+ return self._("Failed to process request! Error Message:\n") + getattr(e, "message", repr(e))
+ return "Done"
def async_download_file(self, context, download_url):
res = download_file(download_url)
if isinstance(res, str):
- context['message'] = self._("[Download] ") + res
+ context["message"] = self._("[Download] ") + res
self.send_efb_group_notice(context)
elif res is None:
pass
else:
- data = {'file': res, 'filename': context['file']['name']}
- context['message_type'] = 'group'
+ data = {"file": res, "filename": context["file"]["name"]}
+ context["message_type"] = "group"
efb_msg = self.msg_decorator.qq_file_after_wrapper(data)
- efb_msg.uid = str(context['user_id']) + '_' + str(uuid.uuid4()) + '_' + str(1)
- efb_msg.text = 'Sent a file\n{}'.format(context['file']['name'])
- if context['uid_prefix'] == 'offline_file':
+ efb_msg.uid = str(context["user_id"]) + "_" + str(uuid.uuid4()) + "_" + str(1)
+ efb_msg.text = "Sent a file\n{}".format(context["file"]["name"])
+ if context["uid_prefix"] == "offline_file":
efb_msg.chat = self.chat_manager.build_efb_chat_as_private(context)
- elif context['uid_prefix'] == 'group_upload':
+ elif context["uid_prefix"] == "group_upload":
efb_msg.chat = self.chat_manager.build_efb_chat_as_group(context)
efb_msg.author = self.chat_manager.build_or_get_efb_member(efb_msg.chat, context)
efb_msg.deliver_to = coordinator.master
async_send_messages_to_master(efb_msg)
def async_download_group_file(self, context, group_id, file_id, busid):
- file = self.coolq_api_query('get_group_file_url',
- group_id=group_id,
- file_id=file_id,
- busid=busid)
- download_url = file['url']
+ file = self.coolq_api_query("get_group_file_url", group_id=group_id, file_id=file_id, busid=busid)
+ download_url = file["url"]
self.async_download_file(context, download_url)
- def get_chat_picture(self, chat: 'Chat') -> BinaryIO:
- chat_type = chat.uid.split('_')
- if chat_type[0] == 'private':
+ def get_chat_picture(self, chat: "Chat") -> BinaryIO:
+ chat_type = chat.uid.split("_")
+ if chat_type[0] == "private":
return download_user_avatar(chat_type[1])
- elif chat_type[0] == 'group':
+ elif chat_type[0] == "group":
return download_group_avatar(chat_type[1])
else:
return download_group_avatar("")
@@ -912,23 +991,23 @@ class GoCQHttp(BaseClient):
group_chats = self.get_groups()
return qq_chats + group_chats
- def get_chat(self, chat_uid: ChatID) -> 'Chat':
+ def get_chat(self, chat_uid: ChatID) -> "Chat":
# todo what is member_uid used for?
- chat_type = chat_uid.split('_')
- if chat_type[0] == 'private':
+ chat_type = chat_uid.split("_")
+ if chat_type[0] == "private":
qq_uid = int(chat_type[1])
remark = self.get_friend_remark(qq_uid)
context = {"user_id": qq_uid}
if remark is not None:
- context['alias'] = remark
+ context["alias"] = remark
return self.chat_manager.build_efb_chat_as_private(context)
- elif chat_type[0] == 'group':
+ elif chat_type[0] == "group":
group_id = int(chat_type[1])
- context = {'message_type': 'group', 'group_id': group_id}
+ context = {"message_type": "group", "group_id": group_id}
return self.chat_manager.build_efb_chat_as_group(context, update_member=True)
- elif chat_type[0] == 'discuss':
+ elif chat_type[0] == "discuss":
discuss_id = int(chat_type[1])
- context = {'message_type': 'discuss', 'discuss_id': discuss_id}
+ context = {"message_type": "discuss", "discuss_id": discuss_id}
return self.chat_manager.build_efb_chat_as_group(context)
raise EFBChatNotFound()
@@ -936,10 +1015,11 @@ class GoCQHttp(BaseClient):
interval = 60 * 60 * 24
latest_version = self.channel.check_updates()
if latest_version is not None:
- self.deliver_alert_to_master("New version({version}) of EFB-QQ-Slave has released! "
- "Please manually update EQS by stopping ehForwarderbot first and then execute "
- "pip3 install --upgrade efb-qq-slave
"
- .format(version=latest_version))
+ self.deliver_alert_to_master(
+ "New version({version}) of EFB-QQ-Slave has released! "
+ "Please manually update EQS by stopping ehForwarderbot first and then execute "
+ "pip3 install --upgrade efb-qq-slave
".format(version=latest_version)
+ )
else:
if t_event is not None and not t_event.is_set():
self.self_update_timer = threading.Timer(interval, self.check_self_update, [t_event])
@@ -947,7 +1027,11 @@ class GoCQHttp(BaseClient):
def poll(self):
self.check_self_update(threading.Event())
- self.run_instance(host=self.client_config['host'], port=self.client_config['port'], debug=False)
+ self.run_instance(
+ host=self.client_config["host"],
+ port=self.client_config["port"],
+ debug=False,
+ )
self.logger.debug("EQS gracefully shut down")
def stop_polling(self):
@@ -957,5 +1041,5 @@ class GoCQHttp(BaseClient):
cherrypy.engine.exit()
def check_features(self):
- self.can_send_image = self.coolq_api_query('can_send_image')['yes']
- self.can_send_voice = self.coolq_api_query('can_send_record')['yes']
+ self.can_send_image = self.coolq_api_query("can_send_image")["yes"]
+ self.can_send_voice = self.coolq_api_query("can_send_record")["yes"]
diff --git a/efb_qq_plugin_go_cqhttp/MsgDecorator.py b/efb_qq_plugin_go_cqhttp/MsgDecorator.py
index f23ae29..2f42d51 100644
--- a/efb_qq_plugin_go_cqhttp/MsgDecorator.py
+++ b/efb_qq_plugin_go_cqhttp/MsgDecorator.py
@@ -2,13 +2,14 @@ import base64
import html
import json
import logging
+import sys
import magic
-from ehforwarderbot import Message, MsgType, Chat
-from ehforwarderbot.message import LocationAttribute, LinkAttribute, Substitutions
+from ehforwarderbot import Chat, Message, MsgType
+from ehforwarderbot.message import LinkAttribute, LocationAttribute, Substitutions
from . import GoCQHttp
-from .Utils import cq_get_image, download_voice, download_file
+from .Utils import cq_get_image, download_file, download_voice
class QQMsgProcessor:
@@ -22,23 +23,23 @@ class QQMsgProcessor:
def qq_image_wrapper(self, data, chat: Chat = None):
efb_msg = Message()
- if 'url' not in data:
+ if "url" not in data:
efb_msg.type = MsgType.Text
- efb_msg.text = self._('[Image Source missing]')
+ efb_msg.text = self._("[Image Source missing]")
return [efb_msg]
- efb_msg.file = cq_get_image(data['url'])
+ efb_msg.file = cq_get_image(data["url"])
if efb_msg.file is None:
efb_msg.type = MsgType.Text
- efb_msg.text = self._('[Download image failed, please check on your QQ client]')
+ efb_msg.text = self._("[Download image failed, please check on your QQ client]")
return [efb_msg]
efb_msg.type = MsgType.Image
mime = magic.from_file(efb_msg.file.name, mime=True)
if isinstance(mime, bytes):
mime = mime.decode()
- efb_msg.filename = data['file'] if 'file' in data else efb_msg.file.name
- efb_msg.filename += '.' + str(mime).split('/')[1]
+ efb_msg.filename = data["file"] if "file" in data else efb_msg.file.name
+ efb_msg.filename += "." + str(mime).split("/")[1]
efb_msg.path = efb_msg.file.name
efb_msg.mime = mime
if "gif" in mime:
@@ -48,11 +49,13 @@ class QQMsgProcessor:
def qq_record_wrapper(self, data, chat: Chat = None): # Experimental!
efb_msg = Message()
try:
- transformed_file = self.inst.coolq_api_query("get_record", file=data['file'], out_format='mp3')
+ transformed_file = self.inst.coolq_api_query("get_record", file=data["file"], out_format="mp3")
efb_msg.type = MsgType.Audio
- efb_msg.file = download_voice(transformed_file['file'],
- self.inst.client_config['api_root'].rstrip("/"),
- self.inst.client_config['access_token'])
+ efb_msg.file = download_voice(
+ transformed_file["file"],
+ self.inst.client_config["api_root"].rstrip("/"),
+ self.inst.client_config["access_token"],
+ )
mime = magic.from_file(efb_msg.file.name, mime=True)
if isinstance(mime, bytes):
mime = mime.decode()
@@ -60,52 +63,48 @@ class QQMsgProcessor:
efb_msg.mime = mime
except Exception:
efb_msg.type = MsgType.Unsupported
- efb_msg.text = self._('[Voice Message] Please check it on your QQ')
+ efb_msg.text = self._("[Voice Message] Please check it on your QQ")
logging.getLogger(__name__).exception("Failed to download voice")
return [efb_msg]
def qq_share_wrapper(self, data, chat: Chat = None):
efb_msg = Message(
type=MsgType.Link,
- text='',
+ text="",
attributes=LinkAttribute(
- title='' if 'title' not in data else data['title'],
- description='' if 'content' not in data else data['content'],
- image='' if 'image' not in data else data['image'],
- url=data['url']
- )
+ title="" if "title" not in data else data["title"],
+ description="" if "content" not in data else data["content"],
+ image="" if "image" not in data else data["image"],
+ url=data["url"],
+ ),
)
return [efb_msg]
def qq_location_wrapper(self, data, chat: Chat = None):
efb_msg = Message(
- text=data['content'],
+ text=data["content"],
type=MsgType.Location,
- attributes=LocationAttribute(longitude=float(data['lon']),
- latitude=float(data['lat']))
+ attributes=LocationAttribute(longitude=float(data["lon"]), latitude=float(data["lat"])),
)
return [efb_msg]
def qq_shake_wrapper(self, data, chat: Chat = None):
- efb_msg = Message(
- type=MsgType.Text,
- text=self._('[Your friend shakes you!]')
- )
+ efb_msg = Message(type=MsgType.Text, text=self._("[Your friend shakes you!]"))
return [efb_msg]
def qq_contact_wrapper(self, data, chat: Chat = None):
- uid = data['id']
- contact_type = data['type']
+ uid = data["id"]
+ contact_type = data["type"]
efb_msg = Message(
type=MsgType.Text,
- text=self._("Chat Recommendation Received\nID: {}\nType: {}").format(uid, contact_type)
+ text=self._("Chat Recommendation Received\nID: {}\nType: {}").format(uid, contact_type),
)
return [efb_msg]
def qq_bface_wrapper(self, data, chat: Chat = None):
efb_msg = Message(
type=MsgType.Unsupported,
- text=self._('[Here comes the BigFace Emoji, please check it on your phone]')
+ text=self._("[Here comes the BigFace Emoji, please check it on your phone]"),
)
return [efb_msg]
@@ -114,12 +113,11 @@ class QQMsgProcessor:
pass
def qq_sign_wrapper(self, data, chat: Chat = None):
- location = self._('at {}').format(data['location']) if 'location' in data else self._('at Unknown Place')
- title = '' if 'title' not in data else (self._('with title {}').format(data['title']))
+ location = self._("at {}").format(data["location"]) if "location" in data else self._("at Unknown Place")
+ title = "" if "title" not in data else (self._("with title {}").format(data["title"]))
efb_msg = Message(
type=MsgType.Text,
- text=self._('signed in {location} {title}').format(title=title,
- location=location)
+ text=self._("signed in {location} {title}").format(title=title, location=location),
)
return [efb_msg]
@@ -127,10 +125,10 @@ class QQMsgProcessor:
efb_messages = list()
efb_msg = Message(
type=MsgType.Unsupported,
- text=self._('[Here comes the Rich Text, dumping...] \n')
+ text=self._("[Here comes the Rich Text, dumping...] \n"),
)
for key, value in data.items():
- efb_msg.text += key + ': ' + value + '\n'
+ efb_msg.text += key + ": " + value + "\n"
efb_messages.append(efb_msg)
# Optimizations for rich messages
# Group Broadcast
@@ -142,12 +140,12 @@ class QQMsgProcessor:
def qq_music_wrapper(self, data, chat: Chat = None):
efb_msg = Message()
- if data['type'] == '163': # Netease Cloud Music
+ if data["type"] == "163": # Netease Cloud Music
efb_msg.type = MsgType.Text
- efb_msg.text = 'https://music.163.com/#/song?id=' + data['id']
+ efb_msg.text = "https://music.163.com/#/song?id=" + data["id"]
else:
efb_msg.type = MsgType.Text
- efb_msg.text = data['text']
+ efb_msg.text = data["text"]
return [efb_msg] # todo Port for other music platform
def qq_text_simple_wrapper(self, text: str, ats: dict): # This cute function only accepts string!
@@ -160,7 +158,7 @@ class QQMsgProcessor:
return efb_msg
def coolq_code_at_wrapper(self, uid):
- return '[CQ:at,qq={}]'.format(uid)
+ return "[CQ:at,qq={}]".format(uid)
def coolq_code_image_wrapper(self, file, file_path):
if file.closed:
@@ -168,7 +166,7 @@ class QQMsgProcessor:
encoded_string = base64.b64encode(file.read())
# Since base64 doesn't contain characters which isn't allowed in CQ Code,
# there's no need to escape the special characters
- return '[CQ:image,file=base64://{}]'.format(encoded_string.decode())
+ return "[CQ:image,file=base64://{}]".format(encoded_string.decode())
def coolq_voice_image_wrapper(self, file, file_path):
if file.closed:
@@ -176,38 +174,39 @@ class QQMsgProcessor:
encoded_string = base64.b64encode(file.read())
# Since base64 doesn't contain characters which isn't allowed in CQ Code,
# there's no need to escape the special characters
- return '[CQ:record,file=base64://{}]'.format(encoded_string.decode())
+ return "[CQ:record,file=base64://{}]".format(encoded_string.decode())
def qq_file_after_wrapper(self, data):
efb_msg = Message()
- efb_msg.file = data['file']
+ efb_msg.file = data["file"]
efb_msg.type = MsgType.File
mime = magic.from_file(efb_msg.file.name, mime=True)
if isinstance(mime, bytes):
mime = mime.decode()
efb_msg.path = efb_msg.file.name
efb_msg.mime = mime
- efb_msg.filename = data['filename']
+ efb_msg.filename = data["filename"]
return efb_msg
def qq_group_broadcast_wrapper(self, data, chat: Chat = None):
try:
at_list = {}
- content_data = json.loads(data['content'])
- text_data = base64.b64decode(content_data['mannounce']['text']).decode("UTF-8")
- title_data = base64.b64decode(content_data['mannounce']['title']).decode("UTF-8")
+ content_data = json.loads(data["content"])
+ text_data = base64.b64decode(content_data["mannounce"]["text"]).decode("UTF-8")
+ title_data = base64.b64decode(content_data["mannounce"]["title"]).decode("UTF-8")
text = "[群公告] 【{title}】\n{text}".format(title=title_data, text=text_data)
substitution_begin = len(text) + 1
- substitution_end = len(text) + len('@all') + 2
- text += ' @all '
+ substitution_end = len(text) + len("@all") + 2
+ text += " @all "
at_list[(substitution_begin, substitution_end)] = chat.self
- if 'pic' in content_data['mannounce']: # Picture Attached
+ if "pic" in content_data["mannounce"]: # Picture Attached
# Assuming there's only one picture
- data['url'] = "http://gdynamic.qpic.cn/gdynamic/{}/628".format(
- content_data['mannounce']['pic'][0]['url'])
+ data["url"] = "http://gdynamic.qpic.cn/gdynamic/{}/628".format(
+ content_data["mannounce"]["pic"][0]["url"]
+ )
efb_message = self.qq_image_wrapper(data)[0]
efb_message.text = text
efb_message.substitutions = Substitutions(at_list)
@@ -220,24 +219,23 @@ class QQMsgProcessor:
def qq_group_broadcast_alternative_wrapper(self, data, chat: Chat = None):
try:
at_list = {}
- content_data = json.loads(data['content'])
- group_id = content_data['mannounce']['gc']
- notice_raw_data = self.inst.coolq_api_query("_get_group_notice",
- group_id=group_id)
+ content_data = json.loads(data["content"])
+ group_id = content_data["mannounce"]["gc"]
+ notice_raw_data = self.inst.coolq_api_query("_get_group_notice", group_id=group_id)
notice_data = json.loads(notice_raw_data)
- title_data = html.unescape(notice_data[0]['msg']['title'])
- text_data = html.unescape(notice_data[0]['msg']['text'])
+ title_data = html.unescape(notice_data[0]["msg"]["title"])
+ text_data = html.unescape(notice_data[0]["msg"]["text"])
text = "[群公告] 【{title}】\n{text}".format(title=title_data, text=text_data)
substitution_begin = len(text) + 1
- substitution_end = len(text) + len('@all') + 2
- text += ' @all '
+ substitution_end = len(text) + len("@all") + 2
+ text += " @all "
at_list[(substitution_begin, substitution_end)] = chat.self
- if 'pics' in html.unescape(notice_data[0]['msg']): # Picture Attached
+ if "pics" in html.unescape(notice_data[0]["msg"]): # Picture Attached
# Assuming there's only one picture
- data['url'] = "http://gdynamic.qpic.cn/gdynamic/{}/628".format(notice_data[0]['msg']['pics'][0]['id'])
+ data["url"] = "http://gdynamic.qpic.cn/gdynamic/{}/628".format(notice_data[0]["msg"]["pics"][0]["id"])
efb_message = self.qq_image_wrapper(data)[0]
efb_message.text = text
efb_message.substitutions = Substitutions(at_list)
@@ -250,66 +248,75 @@ class QQMsgProcessor:
def qq_xml_wrapper(self, data, chat: Chat = None):
efb_msg = Message()
efb_msg.type = MsgType.Text
- efb_msg.text = data['data']
+ efb_msg.text = data["data"]
return [efb_msg]
def qq_json_wrapper(self, data, chat: Chat = None):
efb_msg = Message()
efb_msg.type = MsgType.Text
- efb_msg.text = data['data']
+ efb_msg.text = data["data"]
try:
# In general, data['data'] is a JSON string
dict_data = json.loads(efb_msg.text)
- if type(dict_data) != dict or 'app' not in dict_data:
+ if type(dict_data) != dict or "app" not in dict_data:
return [efb_msg]
# Group of announcement
- if dict_data['app'] == 'com.tencent.mannounce':
- meta_mannounce = dict_data['meta']['mannounce']
- efb_msg.text = "[{prompt}]\n\n{text}".format(prompt=str(base64.b64decode(meta_mannounce['title']), 'UTF-8'), text=str(base64.b64decode(meta_mannounce['text']), 'UTF-8'))
+ if dict_data["app"] == "com.tencent.mannounce":
+ meta_mannounce = dict_data["meta"]["mannounce"]
+ efb_msg.text = "[{prompt}]\n\n{text}".format(
+ prompt=str(base64.b64decode(meta_mannounce["title"]), "UTF-8"),
+ text=str(base64.b64decode(meta_mannounce["text"]), "UTF-8"),
+ )
# Watch, listen and play together
- elif dict_data['app'] == 'com.tencent.together':
- meta_invite = dict_data['meta']['invite']
- efb_msg.text = "[{prompt}]\n\n{text}\n\n{cover}".format(prompt=meta_invite['title'], text=meta_invite['summary'], cover=meta_invite['cover'])
+ elif dict_data["app"] == "com.tencent.together":
+ meta_invite = dict_data["meta"]["invite"]
+ efb_msg.text = "[{prompt}]\n\n{text}\n\n{cover}".format(
+ prompt=meta_invite["title"],
+ text=meta_invite["summary"],
+ cover=meta_invite["cover"],
+ )
# QQ vip card
- elif dict_data['app'] == 'com.tencent.qqvip_singlepic':
+ elif dict_data["app"] == "com.tencent.qqvip_singlepic":
efb_msg.text = efb_msg.text
# Tencent mini App (01 unknown)
- elif dict_data['app'] == 'com.tencent.miniapp_01':
- meta_detail1 = dict_data['meta']['detail_1']
- url = meta_detail1['qqdocurl'] if 'qqdocurl' in meta_detail1 else meta_detail1['url']
- efb_msg.text = "{prompt}\n\n{desc}\n\n{url}\n\n{preview}".format(prompt=dict_data['prompt'], desc=meta_detail1['desc'], url=url, preview=meta_detail1['preview'])
+ elif dict_data["app"] == "com.tencent.miniapp_01":
+ meta_detail1 = dict_data["meta"]["detail_1"]
+ url = meta_detail1["qqdocurl"] if "qqdocurl" in meta_detail1 else meta_detail1["url"]
+ efb_msg.text = "{prompt}\n\n{desc}\n\n{url}\n\n{preview}".format(
+ prompt=dict_data["prompt"],
+ desc=meta_detail1["desc"],
+ url=url,
+ preview=meta_detail1["preview"],
+ )
# Shared third-party Apps
- elif dict_data['app'] == 'com.tencent.structmsg':
- meta_view = dict_data['meta'][dict_data['view']]
- efb_msg.text = "{prompt}\n\n{desc}\n\n{url}\n\n{preview}".format(prompt=dict_data['prompt'], desc=meta_view['desc'], url=meta_view['jumpUrl'], preview=meta_view['preview'])
+ elif dict_data["app"] == "com.tencent.structmsg":
+ meta_view = dict_data["meta"][dict_data["view"]]
+ efb_msg.text = "{prompt}\n\n{desc}\n\n{url}\n\n{preview}".format(
+ prompt=dict_data["prompt"],
+ desc=meta_view["desc"],
+ url=meta_view["jumpUrl"],
+ preview=meta_view["preview"],
+ )
- except:
+ except Exception:
self.logger.error(f"json_wrapper_info: {data}\nexc_info:{sys.exc_info()[0]}")
return [efb_msg]
def qq_video_wrapper(self, data, chat: Chat = None):
- res = download_file(data['url'])
+ res = download_file(data["url"])
mime = magic.from_file(res.name, mime=True)
if isinstance(mime, bytes):
mime = mime.decode()
- efb_msg = Message(
- type=MsgType.Video,
- file=res,
- filename=res.name,
- mime=mime
- )
+ efb_msg = Message(type=MsgType.Video, file=res, filename=res.name, mime=mime)
return [efb_msg]
def qq_unsupported_wrapper(self, data, chat: Chat = None):
- efb_msg = Message(
- type=MsgType.Unsupported,
- text=data
- )
+ efb_msg = Message(type=MsgType.Unsupported, text=data)
return [efb_msg]
diff --git a/efb_qq_plugin_go_cqhttp/Utils.py b/efb_qq_plugin_go_cqhttp/Utils.py
index 8655705..a7ef858 100644
--- a/efb_qq_plugin_go_cqhttp/Utils.py
+++ b/efb_qq_plugin_go_cqhttp/Utils.py
@@ -2,643 +2,646 @@ import logging
import tempfile
import urllib.request
from gettext import translation
-from urllib.error import URLError, HTTPError, ContentTooShortError
+from urllib.error import ContentTooShortError, HTTPError, URLError
from ehforwarderbot import Message, coordinator
from pkg_resources import resource_filename
-qq_emoji_list = { # created by JogleLew and jqqqqqqqqqq, optimized based on Tim's emoji support, updated by xzsk2 to mobileqq v8.8.11
- 0: '😮',
- 1: '😣',
- 2: '😍',
- 3: '😳',
- 4: '😎',
- 5: '😭',
- 6: '☺️',
- 7: '😷',
- 8: '😴',
- 9: '😭',
- 10: '😰',
- 11: '😡',
- 12: '😝',
- 13: '😃',
- 14: '🙂',
- 15: '🙁',
- 16: '🤓',
- 17: '[Empty]',
- 18: '😤',
- 19: '😨',
- 20: '😏',
- 21: '😊',
- 22: '🙄',
- 23: '😕',
- 24: '🤤',
- 25: '😪',
- 26: '😨',
- 27: '😓',
- 28: '😬',
- 29: '🤑',
- 30: '✊',
- 31: '😤',
- 32: '🤔',
- 33: '🤐',
- 34: '😵',
- 35: '😩',
- 36: '💣',
- 37: '💀',
- 38: '🔨',
- 39: '👋',
- 40: '[Empty]',
- 41: '😮',
- 42: '💑',
- 43: '🕺',
- 44: '[Empty]',
- 45: '[Empty]',
- 46: '🐷',
- 47: '[Empty]',
- 48: '[Empty]',
- 49: '🤷',
- 50: '[Empty]',
- 51: '[Empty]',
- 52: '[Empty]',
- 53: '🎂',
- 54: '⚡',
- 55: '💣',
- 56: '🔪',
- 57: '⚽️',
- 58: '[Empty]',
- 59: '💩',
- 60: '☕️',
- 61: '🍚',
- 62: '[Empty]',
- 63: '🌹',
- 64: '🥀',
- 65: '[Empty]',
- 66: '❤️',
- 67: '💔️',
- 68: '[Empty]',
- 69: '🎁',
- 70: '[Empty]',
- 71: '[Empty]',
- 72: '[Empty]',
- 73: '[Empty]',
- 74: '🌞️',
- 75: '🌃',
- 76: '👍',
- 77: '👎',
- 78: '🤝',
- 79: '✌️',
- 80: '[Empty]',
- 81: '[Empty]',
- 82: '[Empty]',
- 83: '[Empty]',
- 84: '[Empty]',
- 85: '🥰',
- 86: '[怄火]',
- 87: '[Empty]',
- 88: '[Empty]',
- 89: '🍉',
- 90: '[Empty]',
- 91: '[Empty]',
- 92: '[Empty]',
- 93: '[Empty]',
- 94: '[Empty]',
- 95: '[Empty]',
- 96: '😅',
- 97: '[擦汗]',
- 98: '[抠鼻]',
- 99: '👏',
- 100: '[糗大了]',
- 101: '😏',
- 102: '😏',
- 103: '😏',
- 104: '🥱',
- 105: '[鄙视]',
- 106: '😭',
- 107: '😭',
- 108: '[阴险]',
- 109: '😚',
- 110: '🙀',
- 111: '[可怜]',
- 112: '🔪',
- 113: '🍺',
- 114: '🏀',
- 115: '🏓',
- 116: '❤️',
- 117: '🐞',
- 118: '[抱拳]',
- 119: '[勾引]',
- 120: '✊',
- 121: '[差劲]',
- 122: '🤟',
- 123: '🚫',
- 124: '👌',
- 125: '[转圈]',
- 126: '[磕头]',
- 127: '[回头]',
- 128: '[跳绳]',
- 129: '👋',
- 130: '[激动]',
- 131: '[街舞]',
- 132: '😘',
- 133: '[左太极]',
- 134: '[右太极]',
- 135: '[Empty]',
- 136: '[双喜]',
- 137: '🧨',
- 138: '🏮',
- 139: '💰',
- 140: '[K歌]',
- 141: '🛍️',
- 142: '📧',
- 143: '[帅]',
- 144: '👏',
- 145: '🙏',
- 146: '[爆筋]',
- 147: '🍭',
- 148: '🍼',
- 149: '[下面]',
- 150: '🍌',
- 151: '🛩',
- 152: '🚗',
- 153: '🚅',
- 154: '[车厢]',
- 155: '[高铁右车头]',
- 156: '🌥',
- 157: '下雨',
- 158: '💵',
- 159: '🐼',
- 160: '💡',
- 161: '[风车]',
- 162: '⏰',
- 163: '🌂',
- 164: '[彩球]',
- 165: '💍',
- 166: '🛋',
- 167: '[纸巾]',
- 168: '💊',
- 169: '🔫',
- 170: '🐸',
- 171: '🍵',
- 172: '[眨眼睛]',
- 173: '😭',
- 174: '[无奈]',
- 175: '[卖萌]',
- 176: '[小纠结]',
- 177: '[喷血]',
- 178: '[斜眼笑]',
- 179: '[doge]',
- 180: '[惊喜]',
- 181: '[骚扰]',
- 182: '😹',
- 183: '[我最美]',
- 184: '🦀',
- 185: '[羊驼]',
- 186: '[Empty]',
- 187: '👻',
- 188: '🥚',
- 189: '[Empty]',
- 190: '🌼',
- 191: '[Empty]',
- 192: '🧧',
- 193: '😄',
- 194: '😞',
- 195: '[Empty]',
- 196: '[Empty]',
- 197: '[冷漠]',
- 198: '[呃]',
- 199: '👍',
- 200: '👋',
- 201: '👍',
- 202: '[无聊]',
- 203: '[托脸]',
- 204: '[吃]',
- 205: '💐',
- 206: '😨',
- 207: '[花痴]',
- 208: '[小样儿]',
- 209: '[Empty]',
- 210: '😭',
- 211: '[我不看]',
- 212: '[托腮]',
- 213: '[Empty]',
- 214: '😙',
- 215: '[糊脸]',
- 216: '[拍头]',
- 217: '[扯一扯]',
- 218: '[舔一舔]',
- 219: '[蹭一蹭]',
- 220: '[拽炸天]',
- 221: '[顶呱呱]',
- 222: '🤗',
- 223: '[暴击]',
- 224: '🔫',
- 225: '[撩一撩]',
- 226: '[拍桌]',
- 227: '👏',
- 228: '[恭喜]',
- 229: '🍻',
- 230: '[嘲讽]',
- 231: '[哼]',
- 232: '[佛系]',
- 233: '[掐一掐]',
- 234: '😮',
- 235: '[颤抖]',
- 236: '[啃头]',
- 237: '[偷看]',
- 238: '[扇脸]',
- 239: '[原谅]',
- 240: '[喷脸]',
- 241: '🎂',
- 242: '[头撞击]',
- 243: '[甩头]',
- 244: '[扔狗]',
- 245: '[加油必胜]',
- 246: '[加油抱抱]',
- 247: '[口罩护体]',
- 248: '[Empty]',
- 249: '[Empty]',
- 250: '[Empty]',
- 251: '[Empty]',
- 252: '[Empty]',
- 253: '[Empty]',
- 254: '[Empty]',
- 255: '[Empty]',
- 256: '😲',
- 257: '😟',
- 258: '😍',
- 259: '😳',
- 260: '[搬砖中]',
- 261: '[忙到飞起]',
- 262: '[脑阔疼]',
- 263: '[沧桑]',
- 264: '[捂脸]',
- 265: '[辣眼睛]',
- 266: '[哦哟]',
- 267: '[头秃]',
- 268: '[问号脸]',
- 269: '[暗中观察]',
- 270: '[emm]',
- 271: '[吃瓜]',
- 272: '[呵呵哒]',
- 273: '[我酸了]',
- 274: '[太南了]',
- 275: '[Empty]',
- 276: '[辣椒酱]',
- 277: '[汪汪]',
- 278: '[汗]',
- 279: '[打脸]',
- 280: '[击掌]',
- 281: '[无眼笑]',
- 282: '[敬礼]',
- 283: '[狂笑]',
- 284: '[面无表情]',
- 285: '[摸鱼]',
- 286: '[魔鬼笑]',
- 287: '[哦]',
- 288: '[请]',
- 289: '[睁眼]',
- 290: '[敲开心]',
- 291: '[震惊]',
- 292: '[让我康康]',
- 293: '[摸锦鲤]',
- 294: '[期待]',
- 295: '[拿到红包]',
- 296: '[真好]',
- 297: '[拜谢]',
- 298: '[元宝]',
- 299: '[牛啊]',
- 300: '[胖三斤]',
- 301: '[好闪]',
- 302: '[左拜年]',
- 303: '[右拜年]',
- 304: '[红包包]',
- 305: '[右亲亲]',
- 306: '[牛气冲天]',
- 307: '[喵喵]',
- 308: '[求红包]',
- 309: '[谢红包]',
- 310: '[新年烟花]',
- 311: '[打call]',
- 312: '[变形]',
- 313: '[嗑到了]',
- 314: '[仔细分析]',
- 315: '[加油]',
- 316: '[我没事]',
- 317: '[菜狗]',
- 318: '[崇拜]',
- 319: '[比心]',
- 320: '[庆祝]',
- 321: '[老色痞]',
- 322: '[拒绝]',
- 323: '[嫌弃]',
+# created by JogleLew and jqqqqqqqqqq, optimized based on Tim's emoji support, updated by xzsk2 to mobileqq v8.8.11
+qq_emoji_list = {
+ 0: "😮",
+ 1: "😣",
+ 2: "😍",
+ 3: "😳",
+ 4: "😎",
+ 5: "😭",
+ 6: "☺️",
+ 7: "😷",
+ 8: "😴",
+ 9: "😭",
+ 10: "😰",
+ 11: "😡",
+ 12: "😝",
+ 13: "😃",
+ 14: "🙂",
+ 15: "🙁",
+ 16: "🤓",
+ 17: "[Empty]",
+ 18: "😤",
+ 19: "😨",
+ 20: "😏",
+ 21: "😊",
+ 22: "🙄",
+ 23: "😕",
+ 24: "🤤",
+ 25: "😪",
+ 26: "😨",
+ 27: "😓",
+ 28: "😬",
+ 29: "🤑",
+ 30: "✊",
+ 31: "😤",
+ 32: "🤔",
+ 33: "🤐",
+ 34: "😵",
+ 35: "😩",
+ 36: "💣",
+ 37: "💀",
+ 38: "🔨",
+ 39: "👋",
+ 40: "[Empty]",
+ 41: "😮",
+ 42: "💑",
+ 43: "🕺",
+ 44: "[Empty]",
+ 45: "[Empty]",
+ 46: "🐷",
+ 47: "[Empty]",
+ 48: "[Empty]",
+ 49: "🤷",
+ 50: "[Empty]",
+ 51: "[Empty]",
+ 52: "[Empty]",
+ 53: "🎂",
+ 54: "⚡",
+ 55: "💣",
+ 56: "🔪",
+ 57: "⚽️",
+ 58: "[Empty]",
+ 59: "💩",
+ 60: "☕️",
+ 61: "🍚",
+ 62: "[Empty]",
+ 63: "🌹",
+ 64: "🥀",
+ 65: "[Empty]",
+ 66: "❤️",
+ 67: "💔️",
+ 68: "[Empty]",
+ 69: "🎁",
+ 70: "[Empty]",
+ 71: "[Empty]",
+ 72: "[Empty]",
+ 73: "[Empty]",
+ 74: "🌞️",
+ 75: "🌃",
+ 76: "👍",
+ 77: "👎",
+ 78: "🤝",
+ 79: "✌️",
+ 80: "[Empty]",
+ 81: "[Empty]",
+ 82: "[Empty]",
+ 83: "[Empty]",
+ 84: "[Empty]",
+ 85: "🥰",
+ 86: "[怄火]",
+ 87: "[Empty]",
+ 88: "[Empty]",
+ 89: "🍉",
+ 90: "[Empty]",
+ 91: "[Empty]",
+ 92: "[Empty]",
+ 93: "[Empty]",
+ 94: "[Empty]",
+ 95: "[Empty]",
+ 96: "😅",
+ 97: "[擦汗]",
+ 98: "[抠鼻]",
+ 99: "👏",
+ 100: "[糗大了]",
+ 101: "😏",
+ 102: "😏",
+ 103: "😏",
+ 104: "🥱",
+ 105: "[鄙视]",
+ 106: "😭",
+ 107: "😭",
+ 108: "[阴险]",
+ 109: "😚",
+ 110: "🙀",
+ 111: "[可怜]",
+ 112: "🔪",
+ 113: "🍺",
+ 114: "🏀",
+ 115: "🏓",
+ 116: "❤️",
+ 117: "🐞",
+ 118: "[抱拳]",
+ 119: "[勾引]",
+ 120: "✊",
+ 121: "[差劲]",
+ 122: "🤟",
+ 123: "🚫",
+ 124: "👌",
+ 125: "[转圈]",
+ 126: "[磕头]",
+ 127: "[回头]",
+ 128: "[跳绳]",
+ 129: "👋",
+ 130: "[激动]",
+ 131: "[街舞]",
+ 132: "😘",
+ 133: "[左太极]",
+ 134: "[右太极]",
+ 135: "[Empty]",
+ 136: "[双喜]",
+ 137: "🧨",
+ 138: "🏮",
+ 139: "💰",
+ 140: "[K歌]",
+ 141: "🛍️",
+ 142: "📧",
+ 143: "[帅]",
+ 144: "👏",
+ 145: "🙏",
+ 146: "[爆筋]",
+ 147: "🍭",
+ 148: "🍼",
+ 149: "[下面]",
+ 150: "🍌",
+ 151: "🛩",
+ 152: "🚗",
+ 153: "🚅",
+ 154: "[车厢]",
+ 155: "[高铁右车头]",
+ 156: "🌥",
+ 157: "下雨",
+ 158: "💵",
+ 159: "🐼",
+ 160: "💡",
+ 161: "[风车]",
+ 162: "⏰",
+ 163: "🌂",
+ 164: "[彩球]",
+ 165: "💍",
+ 166: "🛋",
+ 167: "[纸巾]",
+ 168: "💊",
+ 169: "🔫",
+ 170: "🐸",
+ 171: "🍵",
+ 172: "[眨眼睛]",
+ 173: "😭",
+ 174: "[无奈]",
+ 175: "[卖萌]",
+ 176: "[小纠结]",
+ 177: "[喷血]",
+ 178: "[斜眼笑]",
+ 179: "[doge]",
+ 180: "[惊喜]",
+ 181: "[骚扰]",
+ 182: "😹",
+ 183: "[我最美]",
+ 184: "🦀",
+ 185: "[羊驼]",
+ 186: "[Empty]",
+ 187: "👻",
+ 188: "🥚",
+ 189: "[Empty]",
+ 190: "🌼",
+ 191: "[Empty]",
+ 192: "🧧",
+ 193: "😄",
+ 194: "😞",
+ 195: "[Empty]",
+ 196: "[Empty]",
+ 197: "[冷漠]",
+ 198: "[呃]",
+ 199: "👍",
+ 200: "👋",
+ 201: "👍",
+ 202: "[无聊]",
+ 203: "[托脸]",
+ 204: "[吃]",
+ 205: "💐",
+ 206: "😨",
+ 207: "[花痴]",
+ 208: "[小样儿]",
+ 209: "[Empty]",
+ 210: "😭",
+ 211: "[我不看]",
+ 212: "[托腮]",
+ 213: "[Empty]",
+ 214: "😙",
+ 215: "[糊脸]",
+ 216: "[拍头]",
+ 217: "[扯一扯]",
+ 218: "[舔一舔]",
+ 219: "[蹭一蹭]",
+ 220: "[拽炸天]",
+ 221: "[顶呱呱]",
+ 222: "🤗",
+ 223: "[暴击]",
+ 224: "🔫",
+ 225: "[撩一撩]",
+ 226: "[拍桌]",
+ 227: "👏",
+ 228: "[恭喜]",
+ 229: "🍻",
+ 230: "[嘲讽]",
+ 231: "[哼]",
+ 232: "[佛系]",
+ 233: "[掐一掐]",
+ 234: "😮",
+ 235: "[颤抖]",
+ 236: "[啃头]",
+ 237: "[偷看]",
+ 238: "[扇脸]",
+ 239: "[原谅]",
+ 240: "[喷脸]",
+ 241: "🎂",
+ 242: "[头撞击]",
+ 243: "[甩头]",
+ 244: "[扔狗]",
+ 245: "[加油必胜]",
+ 246: "[加油抱抱]",
+ 247: "[口罩护体]",
+ 248: "[Empty]",
+ 249: "[Empty]",
+ 250: "[Empty]",
+ 251: "[Empty]",
+ 252: "[Empty]",
+ 253: "[Empty]",
+ 254: "[Empty]",
+ 255: "[Empty]",
+ 256: "😲",
+ 257: "😟",
+ 258: "😍",
+ 259: "😳",
+ 260: "[搬砖中]",
+ 261: "[忙到飞起]",
+ 262: "[脑阔疼]",
+ 263: "[沧桑]",
+ 264: "[捂脸]",
+ 265: "[辣眼睛]",
+ 266: "[哦哟]",
+ 267: "[头秃]",
+ 268: "[问号脸]",
+ 269: "[暗中观察]",
+ 270: "[emm]",
+ 271: "[吃瓜]",
+ 272: "[呵呵哒]",
+ 273: "[我酸了]",
+ 274: "[太南了]",
+ 275: "[Empty]",
+ 276: "[辣椒酱]",
+ 277: "[汪汪]",
+ 278: "[汗]",
+ 279: "[打脸]",
+ 280: "[击掌]",
+ 281: "[无眼笑]",
+ 282: "[敬礼]",
+ 283: "[狂笑]",
+ 284: "[面无表情]",
+ 285: "[摸鱼]",
+ 286: "[魔鬼笑]",
+ 287: "[哦]",
+ 288: "[请]",
+ 289: "[睁眼]",
+ 290: "[敲开心]",
+ 291: "[震惊]",
+ 292: "[让我康康]",
+ 293: "[摸锦鲤]",
+ 294: "[期待]",
+ 295: "[拿到红包]",
+ 296: "[真好]",
+ 297: "[拜谢]",
+ 298: "[元宝]",
+ 299: "[牛啊]",
+ 300: "[胖三斤]",
+ 301: "[好闪]",
+ 302: "[左拜年]",
+ 303: "[右拜年]",
+ 304: "[红包包]",
+ 305: "[右亲亲]",
+ 306: "[牛气冲天]",
+ 307: "[喵喵]",
+ 308: "[求红包]",
+ 309: "[谢红包]",
+ 310: "[新年烟花]",
+ 311: "[打call]",
+ 312: "[变形]",
+ 313: "[嗑到了]",
+ 314: "[仔细分析]",
+ 315: "[加油]",
+ 316: "[我没事]",
+ 317: "[菜狗]",
+ 318: "[崇拜]",
+ 319: "[比心]",
+ 320: "[庆祝]",
+ 321: "[老色痞]",
+ 322: "[拒绝]",
+ 323: "[嫌弃]",
}
# original text copied from Tim
qq_emoji_text_list = {
- 0: '[惊讶]',
- 1: '[撇嘴]',
- 2: '[色]',
- 3: '[发呆]',
- 4: '[得意]',
- 5: '[流泪]',
- 6: '[害羞]',
- 7: '[闭嘴]',
- 8: '[睡]',
- 9: '[大哭]',
- 10: '[尴尬]',
- 11: '[发怒]',
- 12: '[调皮]',
- 13: '[呲牙]',
- 14: '[微笑]',
- 15: '[难过]',
- 16: '[酷]',
- 17: '[Empty]',
- 18: '[抓狂]',
- 19: '[吐]',
- 20: '[偷笑]',
- 21: '[可爱]',
- 22: '[白眼]',
- 23: '[傲慢]',
- 24: '[饥饿]',
- 25: '[困]',
- 26: '[惊恐]',
- 27: '[流汗]',
- 28: '[憨笑]',
- 29: '[悠闲]',
- 30: '[奋斗]',
- 31: '[咒骂]',
- 32: '[疑问]',
- 33: '[嘘]',
- 34: '[晕]',
- 35: '[折磨]',
- 36: '[衰]',
- 37: '[骷髅]',
- 38: '[敲打]',
- 39: '[再见]',
- 40: '[Empty]',
- 41: '[发抖]',
- 42: '[爱情]',
- 43: '[跳跳]',
- 44: '[Empty]',
- 45: '[Empty]',
- 46: '[猪头]',
- 47: '[Empty]',
- 48: '[Empty]',
- 49: '[拥抱]',
- 50: '[Empty]',
- 51: '[Empty]',
- 52: '[Empty]',
- 53: '[蛋糕]',
- 54: '[闪电]',
- 55: '[炸弹]',
- 56: '[刀]',
- 57: '[足球]',
- 58: '[Empty]',
- 59: '[便便]',
- 60: '[咖啡]',
- 61: '[饭]',
- 62: '[Empty]',
- 63: '[玫瑰]',
- 64: '[凋谢]',
- 65: '[Empty]',
- 66: '[爱心]',
- 67: '[心碎]',
- 68: '[Empty]',
- 69: '[礼物]',
- 70: '[Empty]',
- 71: '[Empty]',
- 72: '[Empty]',
- 73: '[Empty]',
- 74: '[太阳]',
- 75: '[月亮]',
- 76: '[赞]',
- 77: '[踩]',
- 78: '[握手]',
- 79: '[胜利]',
- 80: '[Empty]',
- 81: '[Empty]',
- 82: '[Empty]',
- 83: '[Empty]',
- 84: '[Empty]',
- 85: '[飞吻]',
- 86: '[怄火]',
- 87: '[Empty]',
- 88: '[Empty]',
- 89: '[西瓜]',
- 90: '[Empty]',
- 91: '[Empty]',
- 92: '[Empty]',
- 93: '[Empty]',
- 94: '[Empty]',
- 95: '[Empty]',
- 96: '[冷汗]',
- 97: '[擦汗]',
- 98: '[抠鼻]',
- 99: '[鼓掌]',
- 100: '[糗大了]',
- 101: '[坏笑]',
- 102: '[左哼哼]',
- 103: '[右哼哼]',
- 104: '[哈欠]',
- 105: '[鄙视]',
- 106: '[委屈]',
- 107: '[快哭了]',
- 108: '[阴险]',
- 109: '[亲亲]',
- 110: '[吓]',
- 111: '[可怜]',
- 112: '[菜刀]',
- 113: '[啤酒]',
- 114: '[篮球]',
- 115: '[乒乓]',
- 116: '[示爱]',
- 117: '[瓢虫]',
- 118: '[抱拳]',
- 119: '[勾引]',
- 120: '[拳头]',
- 121: '[差劲]',
- 122: '[爱你]',
- 123: '[NO]',
- 124: '[OK]',
- 125: '[转圈]',
- 126: '[磕头]',
- 127: '[回头]',
- 128: '[跳绳]',
- 129: '[挥手]',
- 130: '[激动]',
- 131: '[街舞]',
- 132: '[献吻]',
- 133: '[左太极]',
- 134: '[右太极]',
- 135: '[Empty]',
- 136: '[双喜]',
- 137: '[鞭炮]',
- 138: '[灯笼]',
- 139: '[发财]',
- 140: '[K歌]',
- 141: '[购物]',
- 142: '[邮件]',
- 143: '[帅]',
- 144: '[喝彩]',
- 145: '[祈祷]',
- 146: '[爆筋]',
- 147: '[棒棒糖]',
- 148: '[喝奶]',
- 149: '[下面]',
- 150: '[香蕉]',
- 151: '[飞机]',
- 152: '[开车]',
- 153: '[高铁左车头]',
- 154: '[车厢]',
- 155: '[高铁右车头]',
- 156: '[多云]',
- 157: '[下雨]',
- 158: '[钞票]',
- 159: '[熊猫]',
- 160: '[灯泡]',
- 161: '[风车]',
- 162: '[闹钟]',
- 163: '[打伞]',
- 164: '[彩球]',
- 165: '[钻戒]',
- 166: '[沙发]',
- 167: '[纸巾]',
- 168: '[药]',
- 169: '[手枪]',
- 170: '[青蛙]',
- 171: '[茶]',
- 172: '[眨眼睛]',
- 173: '[泪奔]',
- 174: '[无奈]',
- 175: '[卖萌]',
- 176: '[小纠结]',
- 177: '[喷血]',
- 178: '[斜眼笑]',
- 179: '[doge]',
- 180: '[惊喜]',
- 181: '[骚扰]',
- 182: '[笑哭]',
- 183: '[我最美]',
- 184: '[河蟹]',
- 185: '[羊驼]',
- 186: '[Empty]',
- 187: '[幽灵]',
- 188: '[蛋]',
- 189: '[Empty]',
- 190: '[菊花]',
- 191: '[Empty]',
- 192: '[红包]',
- 193: '[大笑]',
- 194: '[不开心]',
- 195: '[Empty]',
- 196: '[Empty]',
- 197: '[冷漠]',
- 198: '[呃]',
- 199: '[好棒]',
- 200: '[拜托]',
- 201: '[点赞]',
- 202: '[无聊]',
- 203: '[托脸]',
- 204: '[吃]',
- 205: '[送花]',
- 206: '[害怕]',
- 207: '[花痴]',
- 208: '[小样儿]',
- 209: '[Empty]',
- 210: '[飙泪]',
- 211: '[我不看]',
- 212: '[托腮]',
- 213: '[Empty]',
- 214: '[啵啵]',
- 215: '[糊脸]',
- 216: '[拍头]',
- 217: '[扯一扯]',
- 218: '[舔一舔]',
- 219: '[蹭一蹭]',
- 220: '[拽炸天]',
- 221: '[顶呱呱]',
- 222: '[抱抱]',
- 223: '[暴击]',
- 224: '[开枪]',
- 225: '[撩一撩]',
- 226: '[拍桌]',
- 227: '[拍手]',
- 228: '[恭喜]',
- 229: '[干杯]',
- 230: '[嘲讽]',
- 231: '[哼]',
- 232: '[佛系]',
- 233: '[掐一掐]',
- 234: '[惊呆]',
- 235: '[颤抖]',
- 236: '[啃头]',
- 237: '[偷看]',
- 238: '[扇脸]',
- 239: '[原谅]',
- 240: '[喷脸]',
- 241: '[生日快乐]',
- 242: '[Empty]',
- 243: '[Empty]',
- 244: '[Empty]',
- 245: '[Empty]',
- 246: '[Empty]',
- 247: '[Empty]',
- 248: '[Empty]',
- 249: '[Empty]',
- 250: '[Empty]',
- 251: '[Empty]',
- 252: '[Empty]',
- 253: '[Empty]',
- 254: '[Empty]',
- 255: '[Empty]',
+ 0: "[惊讶]",
+ 1: "[撇嘴]",
+ 2: "[色]",
+ 3: "[发呆]",
+ 4: "[得意]",
+ 5: "[流泪]",
+ 6: "[害羞]",
+ 7: "[闭嘴]",
+ 8: "[睡]",
+ 9: "[大哭]",
+ 10: "[尴尬]",
+ 11: "[发怒]",
+ 12: "[调皮]",
+ 13: "[呲牙]",
+ 14: "[微笑]",
+ 15: "[难过]",
+ 16: "[酷]",
+ 17: "[Empty]",
+ 18: "[抓狂]",
+ 19: "[吐]",
+ 20: "[偷笑]",
+ 21: "[可爱]",
+ 22: "[白眼]",
+ 23: "[傲慢]",
+ 24: "[饥饿]",
+ 25: "[困]",
+ 26: "[惊恐]",
+ 27: "[流汗]",
+ 28: "[憨笑]",
+ 29: "[悠闲]",
+ 30: "[奋斗]",
+ 31: "[咒骂]",
+ 32: "[疑问]",
+ 33: "[嘘]",
+ 34: "[晕]",
+ 35: "[折磨]",
+ 36: "[衰]",
+ 37: "[骷髅]",
+ 38: "[敲打]",
+ 39: "[再见]",
+ 40: "[Empty]",
+ 41: "[发抖]",
+ 42: "[爱情]",
+ 43: "[跳跳]",
+ 44: "[Empty]",
+ 45: "[Empty]",
+ 46: "[猪头]",
+ 47: "[Empty]",
+ 48: "[Empty]",
+ 49: "[拥抱]",
+ 50: "[Empty]",
+ 51: "[Empty]",
+ 52: "[Empty]",
+ 53: "[蛋糕]",
+ 54: "[闪电]",
+ 55: "[炸弹]",
+ 56: "[刀]",
+ 57: "[足球]",
+ 58: "[Empty]",
+ 59: "[便便]",
+ 60: "[咖啡]",
+ 61: "[饭]",
+ 62: "[Empty]",
+ 63: "[玫瑰]",
+ 64: "[凋谢]",
+ 65: "[Empty]",
+ 66: "[爱心]",
+ 67: "[心碎]",
+ 68: "[Empty]",
+ 69: "[礼物]",
+ 70: "[Empty]",
+ 71: "[Empty]",
+ 72: "[Empty]",
+ 73: "[Empty]",
+ 74: "[太阳]",
+ 75: "[月亮]",
+ 76: "[赞]",
+ 77: "[踩]",
+ 78: "[握手]",
+ 79: "[胜利]",
+ 80: "[Empty]",
+ 81: "[Empty]",
+ 82: "[Empty]",
+ 83: "[Empty]",
+ 84: "[Empty]",
+ 85: "[飞吻]",
+ 86: "[怄火]",
+ 87: "[Empty]",
+ 88: "[Empty]",
+ 89: "[西瓜]",
+ 90: "[Empty]",
+ 91: "[Empty]",
+ 92: "[Empty]",
+ 93: "[Empty]",
+ 94: "[Empty]",
+ 95: "[Empty]",
+ 96: "[冷汗]",
+ 97: "[擦汗]",
+ 98: "[抠鼻]",
+ 99: "[鼓掌]",
+ 100: "[糗大了]",
+ 101: "[坏笑]",
+ 102: "[左哼哼]",
+ 103: "[右哼哼]",
+ 104: "[哈欠]",
+ 105: "[鄙视]",
+ 106: "[委屈]",
+ 107: "[快哭了]",
+ 108: "[阴险]",
+ 109: "[亲亲]",
+ 110: "[吓]",
+ 111: "[可怜]",
+ 112: "[菜刀]",
+ 113: "[啤酒]",
+ 114: "[篮球]",
+ 115: "[乒乓]",
+ 116: "[示爱]",
+ 117: "[瓢虫]",
+ 118: "[抱拳]",
+ 119: "[勾引]",
+ 120: "[拳头]",
+ 121: "[差劲]",
+ 122: "[爱你]",
+ 123: "[NO]",
+ 124: "[OK]",
+ 125: "[转圈]",
+ 126: "[磕头]",
+ 127: "[回头]",
+ 128: "[跳绳]",
+ 129: "[挥手]",
+ 130: "[激动]",
+ 131: "[街舞]",
+ 132: "[献吻]",
+ 133: "[左太极]",
+ 134: "[右太极]",
+ 135: "[Empty]",
+ 136: "[双喜]",
+ 137: "[鞭炮]",
+ 138: "[灯笼]",
+ 139: "[发财]",
+ 140: "[K歌]",
+ 141: "[购物]",
+ 142: "[邮件]",
+ 143: "[帅]",
+ 144: "[喝彩]",
+ 145: "[祈祷]",
+ 146: "[爆筋]",
+ 147: "[棒棒糖]",
+ 148: "[喝奶]",
+ 149: "[下面]",
+ 150: "[香蕉]",
+ 151: "[飞机]",
+ 152: "[开车]",
+ 153: "[高铁左车头]",
+ 154: "[车厢]",
+ 155: "[高铁右车头]",
+ 156: "[多云]",
+ 157: "[下雨]",
+ 158: "[钞票]",
+ 159: "[熊猫]",
+ 160: "[灯泡]",
+ 161: "[风车]",
+ 162: "[闹钟]",
+ 163: "[打伞]",
+ 164: "[彩球]",
+ 165: "[钻戒]",
+ 166: "[沙发]",
+ 167: "[纸巾]",
+ 168: "[药]",
+ 169: "[手枪]",
+ 170: "[青蛙]",
+ 171: "[茶]",
+ 172: "[眨眼睛]",
+ 173: "[泪奔]",
+ 174: "[无奈]",
+ 175: "[卖萌]",
+ 176: "[小纠结]",
+ 177: "[喷血]",
+ 178: "[斜眼笑]",
+ 179: "[doge]",
+ 180: "[惊喜]",
+ 181: "[骚扰]",
+ 182: "[笑哭]",
+ 183: "[我最美]",
+ 184: "[河蟹]",
+ 185: "[羊驼]",
+ 186: "[Empty]",
+ 187: "[幽灵]",
+ 188: "[蛋]",
+ 189: "[Empty]",
+ 190: "[菊花]",
+ 191: "[Empty]",
+ 192: "[红包]",
+ 193: "[大笑]",
+ 194: "[不开心]",
+ 195: "[Empty]",
+ 196: "[Empty]",
+ 197: "[冷漠]",
+ 198: "[呃]",
+ 199: "[好棒]",
+ 200: "[拜托]",
+ 201: "[点赞]",
+ 202: "[无聊]",
+ 203: "[托脸]",
+ 204: "[吃]",
+ 205: "[送花]",
+ 206: "[害怕]",
+ 207: "[花痴]",
+ 208: "[小样儿]",
+ 209: "[Empty]",
+ 210: "[飙泪]",
+ 211: "[我不看]",
+ 212: "[托腮]",
+ 213: "[Empty]",
+ 214: "[啵啵]",
+ 215: "[糊脸]",
+ 216: "[拍头]",
+ 217: "[扯一扯]",
+ 218: "[舔一舔]",
+ 219: "[蹭一蹭]",
+ 220: "[拽炸天]",
+ 221: "[顶呱呱]",
+ 222: "[抱抱]",
+ 223: "[暴击]",
+ 224: "[开枪]",
+ 225: "[撩一撩]",
+ 226: "[拍桌]",
+ 227: "[拍手]",
+ 228: "[恭喜]",
+ 229: "[干杯]",
+ 230: "[嘲讽]",
+ 231: "[哼]",
+ 232: "[佛系]",
+ 233: "[掐一掐]",
+ 234: "[惊呆]",
+ 235: "[颤抖]",
+ 236: "[啃头]",
+ 237: "[偷看]",
+ 238: "[扇脸]",
+ 239: "[原谅]",
+ 240: "[喷脸]",
+ 241: "[生日快乐]",
+ 242: "[Empty]",
+ 243: "[Empty]",
+ 244: "[Empty]",
+ 245: "[Empty]",
+ 246: "[Empty]",
+ 247: "[Empty]",
+ 248: "[Empty]",
+ 249: "[Empty]",
+ 250: "[Empty]",
+ 251: "[Empty]",
+ 252: "[Empty]",
+ 253: "[Empty]",
+ 254: "[Empty]",
+ 255: "[Empty]",
}
qq_sface_list = {
- 1: '[拜拜]',
- 2: '[鄙视]',
- 3: '[菜刀]',
- 4: '[沧桑]',
- 5: '[馋了]',
- 6: '[吃惊]',
- 7: '[微笑]',
- 8: '[得意]',
- 9: '[嘚瑟]',
- 10: '[瞪眼]',
- 11: '[震惊]',
- 12: '[鼓掌]',
- 13: '[害羞]',
- 14: '[好的]',
- 15: '[惊呆了]',
- 16: '[静静看]',
- 17: '[可爱]',
- 18: '[困]',
- 19: '[脸红]',
- 20: '[你懂的]',
- 21: '[期待]',
- 22: '[亲亲]',
- 23: '[伤心]',
- 24: '[生气]',
- 25: '[摇摆]',
- 26: '[帅]',
- 27: '[思考]',
- 28: '[震惊哭]',
- 29: '[痛心]',
- 30: '[偷笑]',
- 31: '[挖鼻孔]',
- 32: '[抓狂]',
- 33: '[笑着哭]',
- 34: '[无语]',
- 35: '[捂脸]',
- 36: '[喜欢]',
- 37: '[笑哭]',
- 38: '[疑惑]',
- 39: '[赞]',
- 40: '[眨眼]'
+ 1: "[拜拜]",
+ 2: "[鄙视]",
+ 3: "[菜刀]",
+ 4: "[沧桑]",
+ 5: "[馋了]",
+ 6: "[吃惊]",
+ 7: "[微笑]",
+ 8: "[得意]",
+ 9: "[嘚瑟]",
+ 10: "[瞪眼]",
+ 11: "[震惊]",
+ 12: "[鼓掌]",
+ 13: "[害羞]",
+ 14: "[好的]",
+ 15: "[惊呆了]",
+ 16: "[静静看]",
+ 17: "[可爱]",
+ 18: "[困]",
+ 19: "[脸红]",
+ 20: "[你懂的]",
+ 21: "[期待]",
+ 22: "[亲亲]",
+ 23: "[伤心]",
+ 24: "[生气]",
+ 25: "[摇摆]",
+ 26: "[帅]",
+ 27: "[思考]",
+ 28: "[震惊哭]",
+ 29: "[痛心]",
+ 30: "[偷笑]",
+ 31: "[挖鼻孔]",
+ 32: "[抓狂]",
+ 33: "[笑着哭]",
+ 34: "[无语]",
+ 35: "[捂脸]",
+ 36: "[喜欢]",
+ 37: "[笑哭]",
+ 38: "[疑惑]",
+ 39: "[赞]",
+ 40: "[眨眼]",
}
-translator = translation("efb_qq_slave",
- resource_filename('efb_qq_slave', 'Clients/CoolQ/locale'),
- fallback=True)
+translator = translation(
+ "efb_qq_slave",
+ resource_filename("efb_qq_slave", "Clients/CoolQ/locale"),
+ fallback=True,
+)
_ = translator.gettext
ngettext = translator.ngettext
@@ -648,12 +651,12 @@ def cq_get_image(image_link: str) -> tempfile: # Download image from QQ
try:
urllib.request.urlretrieve(image_link, file.name)
except (URLError, HTTPError, ContentTooShortError) as e:
- logging.getLogger(__name__).warning('Image download failed.')
+ logging.getLogger(__name__).warning("Image download failed.")
logging.getLogger(__name__).warning(str(e))
return None
else:
if file.seek(0, 2) <= 0:
- raise EOFError('File downloaded is Empty')
+ raise EOFError("File downloaded is Empty")
file.seek(0)
return file
@@ -679,14 +682,14 @@ def process_quote_text(text, max_length): # Simple wrapper for processing quote
def coolq_text_encode(text: str): # Escape special characters for CQ Code text
- expr = (('&', '&'), ('[', '['), (']', ']'))
+ expr = (("&", "&"), ("[", "["), ("]", "]"))
for r in expr:
text = text.replace(*r)
return text
def coolq_para_encode(text: str): # Escape special characters for CQ Code parameters
- expr = (('&', '&'), ('[', '['), (']', ']'), (',', ','))
+ expr = (("&", "&"), ("[", "["), ("]", "]"), (",", ","))
for r in expr:
text = text.replace(*r)
return text
@@ -712,7 +715,7 @@ def download_file(download_url):
return _("Error occurs when downloading files: ") + str(e)
else:
if file.seek(0, 2) <= 0:
- raise EOFError('File downloaded is Empty')
+ raise EOFError("File downloaded is Empty")
file.seek(0)
return file
@@ -728,7 +731,7 @@ def download_user_avatar(uid: str):
logging.getLogger(__name__).warning("Error occurs when downloading files: " + str(e))
return _("Error occurs when downloading files: ") + str(e)
if file.seek(0, 2) <= 0:
- raise EOFError('File downloaded is Empty')
+ raise EOFError("File downloaded is Empty")
file.seek(0)
return file
@@ -744,14 +747,14 @@ def download_group_avatar(uid: str):
logging.getLogger(__name__).warning("Error occurs when downloading files: " + str(e))
return _("Error occurs when downloading files: ") + str(e)
if file.seek(0, 2) <= 0:
- raise EOFError('File downloaded is Empty')
+ raise EOFError("File downloaded is Empty")
file.seek(0)
return file
def download_voice(filename: str, api_root: str, access_token: str):
file = tempfile.NamedTemporaryFile()
- url = '{url}/data/record/{file}'.format(url=api_root, file=filename)
+ url = "{url}/data/record/{file}".format(url=api_root, file=filename)
try:
opener = urllib.request.build_opener()
opener.addheaders = [("Authorization", "Bearer {at}".format(at=access_token))]
@@ -762,6 +765,6 @@ def download_voice(filename: str, api_root: str, access_token: str):
logging.getLogger(__name__).warning("Error occurs when downloading files: " + str(e))
return _("Error occurs when downloading files: ") + str(e)
if file.seek(0, 2) <= 0:
- raise EOFError('File downloaded is Empty')
+ raise EOFError("File downloaded is Empty")
file.seek(0)
return file
diff --git a/efb_qq_plugin_go_cqhttp/__init__.py b/efb_qq_plugin_go_cqhttp/__init__.py
index 31009fb..7500abb 100644
--- a/efb_qq_plugin_go_cqhttp/__init__.py
+++ b/efb_qq_plugin_go_cqhttp/__init__.py
@@ -1,3 +1,3 @@
-from . import GoCQHttp
+from . import GoCQHttp # noqa: F401
-__version__ = '2.0.9'
+__version__ = "2.0.9"
diff --git a/pdm.lock b/pdm.lock
index c3953ad..a0d16a6 100644
--- a/pdm.lock
+++ b/pdm.lock
@@ -8,6 +8,12 @@ name = "certifi"
version = "2021.10.8"
summary = "Python package for providing Mozilla's CA Bundle."
+[[package]]
+name = "cfgv"
+version = "3.3.1"
+requires_python = ">=3.6.1"
+summary = "Validate configuration and produce human readable error messages."
+
[[package]]
name = "charset-normalizer"
version = "2.0.11"
@@ -70,6 +76,11 @@ dependencies = [
"requests",
]
+[[package]]
+name = "distlib"
+version = "0.3.4"
+summary = "Distribution utilities"
+
[[package]]
name = "efb-qq-slave"
version = "2.0.1.dev0"
@@ -99,6 +110,12 @@ dependencies = [
"typing-extensions",
]
+[[package]]
+name = "filelock"
+version = "3.4.2"
+requires_python = ">=3.7"
+summary = "A platform independent file lock."
+
[[package]]
name = "flask"
version = "2.0.2"
@@ -111,6 +128,12 @@ dependencies = [
"itsdangerous>=2.0",
]
+[[package]]
+name = "identify"
+version = "2.4.8"
+requires_python = ">=3.7"
+summary = "File identification library for Python"
+
[[package]]
name = "idna"
version = "3.3"
@@ -208,12 +231,23 @@ version = "8.12.0"
requires_python = ">=3.5"
summary = "More routines for operating on iterables, beyond itertools"
+[[package]]
+name = "nodeenv"
+version = "1.6.0"
+summary = "Node.js virtual environment builder"
+
[[package]]
name = "pillow"
version = "9.0.1"
requires_python = ">=3.7"
summary = "Python Imaging Library (Fork)"
+[[package]]
+name = "platformdirs"
+version = "2.4.1"
+requires_python = ">=3.7"
+summary = "A small Python module for determining appropriate platform-specific dirs, e.g. a \"user data dir\"."
+
[[package]]
name = "portend"
version = "3.1.0"
@@ -223,6 +257,21 @@ dependencies = [
"tempora>=1.8",
]
+[[package]]
+name = "pre-commit"
+version = "2.17.0"
+requires_python = ">=3.6.1"
+summary = "A framework for managing and maintaining multi-language pre-commit hooks."
+dependencies = [
+ "cfgv>=2.0.0",
+ "identify>=1.0.0",
+ "importlib-metadata; python_version < \"3.8\"",
+ "nodeenv>=0.11.1",
+ "pyyaml>=5.1",
+ "toml",
+ "virtualenv>=20.0.8",
+]
+
[[package]]
name = "python-magic"
version = "0.4.25"
@@ -294,6 +343,12 @@ dependencies = [
"pytz",
]
+[[package]]
+name = "toml"
+version = "0.10.2"
+requires_python = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*"
+summary = "Python Library for Tom's Obvious, Minimal Language"
+
[[package]]
name = "typing-extensions"
version = "4.0.1"
@@ -306,6 +361,19 @@ version = "1.26.8"
requires_python = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, <4"
summary = "HTTP library with thread-safe connection pooling, file post, and more."
+[[package]]
+name = "virtualenv"
+version = "20.13.0"
+requires_python = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.7"
+summary = "Virtual Python Environment builder"
+dependencies = [
+ "distlib<1,>=0.3.1",
+ "filelock<4,>=3.2",
+ "importlib-metadata>=0.12; python_version < \"3.8\"",
+ "platformdirs<3,>=2",
+ "six<2,>=1.9.0",
+]
+
[[package]]
name = "werkzeug"
version = "2.0.2"
@@ -328,7 +396,7 @@ summary = "Backport of pathlib-compatible object wrapper for zip files"
[metadata]
lock_version = "3.1"
-content_hash = "sha256:0e2a42ddc2fd648d8001d7be1ebfedbae88d34a2a78de0d941a23637dd7199dd"
+content_hash = "sha256:63656839bd77b534cd7236e11ac80dcbb103f86659970673c7bba62c02f393c3"
[metadata.files]
"bullet 2.2.0" = [
@@ -339,6 +407,10 @@ content_hash = "sha256:0e2a42ddc2fd648d8001d7be1ebfedbae88d34a2a78de0d941a23637d
{file = "certifi-2021.10.8-py2.py3-none-any.whl", hash = "sha256:d62a0163eb4c2344ac042ab2bdf75399a71a2d8c7d47eac2e2ee91b9d6339569"},
{file = "certifi-2021.10.8.tar.gz", hash = "sha256:78884e7c1d4b00ce3cea67b44566851c4343c120abd683433ce934a68ea58872"},
]
+"cfgv 3.3.1" = [
+ {file = "cfgv-3.3.1-py2.py3-none-any.whl", hash = "sha256:c6a0883f3917a037485059700b9e75da2464e6c27051014ad85ba6aaa5884426"},
+ {file = "cfgv-3.3.1.tar.gz", hash = "sha256:f5a830efb9ce7a445376bb66ec94c638a9787422f96264c98edc6bdeed8ab736"},
+]
"charset-normalizer 2.0.11" = [
{file = "charset_normalizer-2.0.11-py3-none-any.whl", hash = "sha256:2842d8f5e82a1f6aa437380934d5e1cd4fcf2003b06fed6940769c164a480a45"},
{file = "charset-normalizer-2.0.11.tar.gz", hash = "sha256:98398a9d69ee80548c762ba991a4728bfc3836768ed226b3945908d1a688371c"},
@@ -366,14 +438,26 @@ content_hash = "sha256:0e2a42ddc2fd648d8001d7be1ebfedbae88d34a2a78de0d941a23637d
"cqhttp 1.3.1" = [
{file = "cqhttp-1.3.1.tar.gz", hash = "sha256:4cb0dae03872162df395ef49f3bb2ec69501cc0d686193dfb1b413097b062821"},
]
+"distlib 0.3.4" = [
+ {file = "distlib-0.3.4-py2.py3-none-any.whl", hash = "sha256:6564fe0a8f51e734df6333d08b8b94d4ea8ee6b99b5ed50613f731fd4089f34b"},
+ {file = "distlib-0.3.4.zip", hash = "sha256:e4b58818180336dc9c529bfb9a0b58728ffc09ad92027a3f30b7cd91e3458579"},
+]
"ehforwarderbot 2.1.1" = [
{file = "ehforwarderbot-2.1.1-py3-none-any.whl", hash = "sha256:33e02015cc7dabde9d7e719a6486ccedd681e33246ab746d5ed6de4ec9b96dac"},
{file = "ehforwarderbot-2.1.1.tar.gz", hash = "sha256:414c3de4e9ad151d3ad38d37d89f0b626a5fa7fb04d9d30ff152b5230d34099b"},
]
+"filelock 3.4.2" = [
+ {file = "filelock-3.4.2-py3-none-any.whl", hash = "sha256:cf0fc6a2f8d26bd900f19bf33915ca70ba4dd8c56903eeb14e1e7a2fd7590146"},
+ {file = "filelock-3.4.2.tar.gz", hash = "sha256:38b4f4c989f9d06d44524df1b24bd19e167d851f19b50bf3e3559952dddc5b80"},
+]
"flask 2.0.2" = [
{file = "Flask-2.0.2-py3-none-any.whl", hash = "sha256:cb90f62f1d8e4dc4621f52106613488b5ba826b2e1e10a33eac92f723093ab6a"},
{file = "Flask-2.0.2.tar.gz", hash = "sha256:7b2fb8e934ddd50731893bdcdb00fc8c0315916f9fcd50d22c7cc1a95ab634e2"},
]
+"identify 2.4.8" = [
+ {file = "identify-2.4.8-py2.py3-none-any.whl", hash = "sha256:a55bdd671b6063eb837af938c250ec00bba6e610454265133b0d2db7ae718d0f"},
+ {file = "identify-2.4.8.tar.gz", hash = "sha256:97e839c1779f07011b84c92af183e1883d9745d532d83412cca1ca76d3808c1c"},
+]
"idna 3.3" = [
{file = "idna-3.3-py3-none-any.whl", hash = "sha256:84d9dd047ffa80596e0f246e2eab0b391788b0503584e8945f2368256d2735ff"},
{file = "idna-3.3.tar.gz", hash = "sha256:9d643ff0a55b762d5cdb124b8eaa99c66322e2157b69160bc32796e824360e6d"},
@@ -489,6 +573,10 @@ content_hash = "sha256:0e2a42ddc2fd648d8001d7be1ebfedbae88d34a2a78de0d941a23637d
{file = "more_itertools-8.12.0-py3-none-any.whl", hash = "sha256:43e6dd9942dffd72661a2c4ef383ad7da1e6a3e968a927ad7a6083ab410a688b"},
{file = "more-itertools-8.12.0.tar.gz", hash = "sha256:7dc6ad46f05f545f900dd59e8dfb4e84a4827b97b3cfecb175ea0c7d247f6064"},
]
+"nodeenv 1.6.0" = [
+ {file = "nodeenv-1.6.0-py2.py3-none-any.whl", hash = "sha256:621e6b7076565ddcacd2db0294c0381e01fd28945ab36bcf00f41c5daf63bef7"},
+ {file = "nodeenv-1.6.0.tar.gz", hash = "sha256:3ef13ff90291ba2a4a7a4ff9a979b63ffdd00a464dbe04acf0ea6471517a4c2b"},
+]
"pillow 9.0.1" = [
{file = "Pillow-9.0.1-1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:a5d24e1d674dd9d72c66ad3ea9131322819ff86250b30dc5821cbafcfa0b96b4"},
{file = "Pillow-9.0.1-1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:2632d0f846b7c7600edf53c48f8f9f1e13e62f66a6dbc15191029d950bfed976"},
@@ -526,10 +614,18 @@ content_hash = "sha256:0e2a42ddc2fd648d8001d7be1ebfedbae88d34a2a78de0d941a23637d
{file = "Pillow-9.0.1-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:a9f44cd7e162ac6191491d7249cceb02b8116b0f7e847ee33f739d7cb1ea1f70"},
{file = "Pillow-9.0.1.tar.gz", hash = "sha256:6c8bc8238a7dfdaf7a75f5ec5a663f4173f8c367e5a39f87e720495e1eed75fa"},
]
+"platformdirs 2.4.1" = [
+ {file = "platformdirs-2.4.1-py3-none-any.whl", hash = "sha256:1d7385c7db91728b83efd0ca99a5afb296cab9d0ed8313a45ed8ba17967ecfca"},
+ {file = "platformdirs-2.4.1.tar.gz", hash = "sha256:440633ddfebcc36264232365d7840a970e75e1018d15b4327d11f91909045fda"},
+]
"portend 3.1.0" = [
{file = "portend-3.1.0-py3-none-any.whl", hash = "sha256:9e735cee3a5c1961f09e3f3ba6dc498198c2d70b473d98d0d1504b8d1e7a3d61"},
{file = "portend-3.1.0.tar.gz", hash = "sha256:239e3116045ea823f6df87d6168107ad75ccc0590e37242af0cc1e98c5d224e4"},
]
+"pre-commit 2.17.0" = [
+ {file = "pre_commit-2.17.0-py2.py3-none-any.whl", hash = "sha256:725fa7459782d7bec5ead072810e47351de01709be838c2ce1726b9591dad616"},
+ {file = "pre_commit-2.17.0.tar.gz", hash = "sha256:c1a8040ff15ad3d648c70cc3e55b93e4d2d5b687320955505587fd79bbaed06a"},
+]
"python-magic 0.4.25" = [
{file = "python_magic-0.4.25-py2.py3-none-any.whl", hash = "sha256:1a2c81e8f395c744536369790bd75094665e9644110a6623bcc3bbea30f03973"},
{file = "python-magic-0.4.25.tar.gz", hash = "sha256:21f5f542aa0330f5c8a64442528542f6215c8e18d2466b399b0d9d39356d83fc"},
@@ -634,6 +730,10 @@ content_hash = "sha256:0e2a42ddc2fd648d8001d7be1ebfedbae88d34a2a78de0d941a23637d
{file = "tempora-5.0.1-py3-none-any.whl", hash = "sha256:fbca6a229af666ea4ea8b2f9f80ac9a074f7cf53a97987855b1d15b6e93fd63b"},
{file = "tempora-5.0.1.tar.gz", hash = "sha256:cba0f197a64883bf3e73657efbc0324d5bf17179e7769b1385b4d75d26cd9127"},
]
+"toml 0.10.2" = [
+ {file = "toml-0.10.2-py2.py3-none-any.whl", hash = "sha256:806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b"},
+ {file = "toml-0.10.2.tar.gz", hash = "sha256:b3bda1d108d5dd99f4a20d24d9c348e91c4db7ab1b749200bded2f839ccbe68f"},
+]
"typing-extensions 4.0.1" = [
{file = "typing_extensions-4.0.1-py3-none-any.whl", hash = "sha256:7f001e5ac290a0c0401508864c7ec868be4e701886d5b573a9528ed3973d9d3b"},
{file = "typing_extensions-4.0.1.tar.gz", hash = "sha256:4ca091dea149f945ec56afb48dae714f21e8692ef22a395223bcd328961b6a0e"},
@@ -642,6 +742,10 @@ content_hash = "sha256:0e2a42ddc2fd648d8001d7be1ebfedbae88d34a2a78de0d941a23637d
{file = "urllib3-1.26.8-py2.py3-none-any.whl", hash = "sha256:000ca7f471a233c2251c6c7023ee85305721bfdf18621ebff4fd17a8653427ed"},
{file = "urllib3-1.26.8.tar.gz", hash = "sha256:0e7c33d9a63e7ddfcb86780aac87befc2fbddf46c58dbb487e0855f7ceec283c"},
]
+"virtualenv 20.13.0" = [
+ {file = "virtualenv-20.13.0-py2.py3-none-any.whl", hash = "sha256:339f16c4a86b44240ba7223d0f93a7887c3ca04b5f9c8129da7958447d079b09"},
+ {file = "virtualenv-20.13.0.tar.gz", hash = "sha256:d8458cf8d59d0ea495ad9b34c2599487f8a7772d796f9910858376d1600dd2dd"},
+]
"werkzeug 2.0.2" = [
{file = "Werkzeug-2.0.2-py3-none-any.whl", hash = "sha256:63d3dc1cf60e7b7e35e97fa9861f7397283b75d765afcaefd993d6046899de8f"},
{file = "Werkzeug-2.0.2.tar.gz", hash = "sha256:aa2bb6fc8dee8d6c504c0ac1e7f5f7dc5810a9903e793b6f715a9f015bdadb9a"},
diff --git a/pyproject.toml b/pyproject.toml
index e616f88..389b5d0 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -46,10 +46,20 @@ homepage = "https://github.com/ehForwarderBot/efb-qq-plugin-go-cqhttp"
[project.entry-points."ehforwarderbot.qq.plugin"]
GoCQHttp = "efb_qq_plugin_go_cqhttp:GoCQHttp"
-[tool]
-[tool.pdm]
-version = { from = "efb_qq_plugin_go_cqhttp/__init__.py" }
-
[build-system]
requires = ["pdm-pep517"]
build-backend = "pdm.pep517.api"
+
+[tool.pdm]
+version = { from = "efb_qq_plugin_go_cqhttp/__init__.py" }
+
+[tool.pdm.dev-dependencies]
+dev = ["pre-commit"]
+
+[tool.black]
+line-length = 120
+
+[tool.isort]
+profile = "black"
+atomic = true
+filter_files = true