From 54c1cbbaaa63ef17da523007eb7e21f9fa4d8ee1 Mon Sep 17 00:00:00 2001 From: XYenon Date: Mon, 31 May 2021 01:16:50 +0800 Subject: [PATCH] Support go-cqhttp --- efb_qq_plugin_coolq/__version__.py | 3 - .../ChatMgr.py | 45 ------- .../CoolQ.py | 112 ++++-------------- .../Exceptions.py | 0 .../MsgDecorator.py | 2 - .../Utils.py | 66 +---------- .../__init__.py | 0 efb_qq_plugin_go_cqhttp/__version__.py | 1 + setup.py | 16 +-- 9 files changed, 30 insertions(+), 215 deletions(-) delete mode 100644 efb_qq_plugin_coolq/__version__.py rename {efb_qq_plugin_coolq => efb_qq_plugin_go_cqhttp}/ChatMgr.py (70%) rename {efb_qq_plugin_coolq => efb_qq_plugin_go_cqhttp}/CoolQ.py (90%) rename {efb_qq_plugin_coolq => efb_qq_plugin_go_cqhttp}/Exceptions.py (100%) rename {efb_qq_plugin_coolq => efb_qq_plugin_go_cqhttp}/MsgDecorator.py (99%) rename {efb_qq_plugin_coolq => efb_qq_plugin_go_cqhttp}/Utils.py (87%) rename {efb_qq_plugin_coolq => efb_qq_plugin_go_cqhttp}/__init__.py (100%) create mode 100644 efb_qq_plugin_go_cqhttp/__version__.py diff --git a/efb_qq_plugin_coolq/__version__.py b/efb_qq_plugin_coolq/__version__.py deleted file mode 100644 index 876b5de..0000000 --- a/efb_qq_plugin_coolq/__version__.py +++ /dev/null @@ -1,3 +0,0 @@ -# coding: utf-8 - -__version__ = '2.0.0a0' diff --git a/efb_qq_plugin_coolq/ChatMgr.py b/efb_qq_plugin_go_cqhttp/ChatMgr.py similarity index 70% rename from efb_qq_plugin_coolq/ChatMgr.py rename to efb_qq_plugin_go_cqhttp/ChatMgr.py index ad09e4d..a57f3d0 100644 --- a/efb_qq_plugin_coolq/ChatMgr.py +++ b/efb_qq_plugin_go_cqhttp/ChatMgr.py @@ -1,4 +1,3 @@ -# coding: utf-8 import contextlib import logging @@ -10,7 +9,6 @@ from efb_qq_slave import QQMessengerChannel class ChatManager: - def __init__(self, channel: 'QQMessengerChannel'): self.channel: 'QQMessengerChannel' = channel self.logger: logging.Logger = logging.getLogger(__name__) @@ -27,49 +25,6 @@ class ChatManager: name="Chat Missing" ) - """ - def build_efb_chat_as_user(self, uid, is_chat, in_group=None, is_discuss=False): - efb_chat = EFBChat(self.channel) - efb_chat.chat_uid = 'user' + str(uid) - i: dict = self.channel.QQClient.get_stranger_info(uid) - efb_chat.chat_name = i['nickname'] - efb_chat.chat_alias = None - efb_chat.chat_type = ChatType.User - efb_chat.is_chat = is_chat - efb_chat.vendor_specific = {'is_anonymous': False} - if in_group is not None: - efb_chat.group = self.build_efb_chat_as_group(in_group, is_discuss) - return efb_chat - - def build_efb_chat_as_group(self, uid, discuss=False): - efb_chat = EFBChat(self.channel) - if not discuss: - efb_chat.chat_uid = 'group' + str(uid) - i = self.channel.QQClient.get_group_info(uid) - efb_chat.chat_name = i['group_name'] - efb_chat.chat_type = ChatType.Group - efb_chat.vendor_specific = {'is_discuss': False} - # todo Add user to efb_chat.member - else: - efb_chat.chat_uid = 'discuss' + str(uid) - efb_chat.chat_name = 'Discuss Group' # todo Find a way to distinguish from different discuss group - efb_chat.chat_type = ChatType.Group - efb_chat.vendor_specific = {'is_discuss': True} - return efb_chat - - def build_efb_chat_as_anonymous_user(self, nickname, flag, anonymous_id, group_id, is_discuss): - efb_chat = EFBChat(self.channel) - efb_chat.chat_uid = flag - efb_chat.chat_name = nickname - efb_chat.chat_type = ChatType.User - efb_chat.is_chat = False - efb_chat.vendor_specific = {'is_anonymous': True, - 'anonymous_id': anonymous_id} - efb_chat.group = self.build_efb_chat_as_group(group_id, is_discuss) - return efb_chat - - """ - def build_efb_chat_as_private(self, context): uid = context['user_id'] if 'sender' not in context or 'nickname' not in context['sender']: diff --git a/efb_qq_plugin_coolq/CoolQ.py b/efb_qq_plugin_go_cqhttp/CoolQ.py similarity index 90% rename from efb_qq_plugin_coolq/CoolQ.py rename to efb_qq_plugin_go_cqhttp/CoolQ.py index 49a5414..f5bd413 100644 --- a/efb_qq_plugin_coolq/CoolQ.py +++ b/efb_qq_plugin_go_cqhttp/CoolQ.py @@ -1,4 +1,3 @@ -# coding: utf-8 import logging import tempfile import threading @@ -30,8 +29,8 @@ from .Exceptions import CoolQDisconnectedException, CoolQAPIFailureException, Co CoolQUnknownException from .MsgDecorator import QQMsgProcessor from .Utils import qq_emoji_list, async_send_messages_to_master, process_quote_text, coolq_text_encode, \ - upload_image_smms, download_file_from_qzone, download_user_avatar, download_group_avatar, \ - get_friend_group_via_qq_show, upload_image_vim_cn, upload_image_mi, upload_image_sogou, get_stranger_info_via_qzone + upload_image_smms, download_user_avatar, download_group_avatar, upload_image_vim_cn, upload_image_mi, \ + upload_image_sogou, download_file class CoolQ(BaseClient): @@ -257,18 +256,11 @@ class CoolQ(BaseClient): context['message'] = text self.send_efb_group_notice(context) - cred = self.coolq_api_query('get_credentials') - cookies = cred['cookies'] - csrf_token = cred['csrf_token'] param_dict = { 'context': context, - 'cookie': cookies, - 'csrf_token': csrf_token, - 'uin': self.get_qq_uid(), 'group_id': context['group_id'], 'file_id': context['file']['id'], - 'filename': context['file']['name'], - 'file_size': context['file']['size'] + 'busid': context['file']['busid'] } threading.Thread(target=self.async_download_file, args=[], kwargs=param_dict).start() @@ -404,9 +396,7 @@ class CoolQ(BaseClient): return 'Done' def get_stranger_info(self, user_id): - return get_stranger_info_via_qzone(user_id) - # return self.coolq_api_query('get_stranger_info', user_id=user_id, no_cache=False) - # return self.coolq_bot.get_stranger_info(user_id=user_id, no_cache=False) + return self.coolq_api_query('get_stranger_info', user_id=user_id) def get_login_info(self) -> Dict[Any, Any]: res = self.coolq_bot.get_status() @@ -450,41 +440,18 @@ class CoolQ(BaseClient): self.deliver_alert_to_master(self._('Failed to retrieve the friend list.\n' 'Only groups are shown.')) return [] - res = self.friend_list users = [] - for i in range(len(res)): # friend group - current_user = res[i] - txt = '' - if str(current_user['user_id']) in self.friend_group: - txt = '[{}] {}' - txt = txt.format(self.friend_group[str(current_user['user_id'])], current_user['nickname']) + for current_user in self.friend_list: # friend group + if current_user['user_id'] in self.friend_group: + txt = '[{}] {}'.format(self.friend_group[current_user['user_id']], current_user['nickname']) else: - txt = '{}' - txt = txt.format(current_user['nickname']) + txt = '{}'.format(current_user['nickname']) # Disable nickname & remark comparison for it's too time-consuming context = {'user_id': str(current_user['user_id']), 'nickname': txt, 'alias': current_user['remark']} efb_chat = self.chat_manager.build_efb_chat_as_private(context) - # efb_chat = self.chat_manager.build_efb_chat_as_user(context, True) users.append(efb_chat) - ''' - for i in range(len(res)): # friend group - for j in range(len(res[i]['friends'])): - current_user = res[i]['friends'][j] - txt = '[{}] {}' - txt = txt.format(res[i]['friend_group_name'], current_user['remark']) - if current_user['nickname'] == current_user['remark']: # no remark name - context = {'user_id': str(current_user['user_id']), - 'nickname': txt, - 'alias': None} - else: - context = {'user_id': str(current_user['user_id']), - 'nickname': current_user['nickname'], - 'alias': txt} - efb_chat = self.chat_manager.build_efb_chat_as_user(context, True) - users.append(efb_chat) - ''' return users def receive_message(self): @@ -778,31 +745,15 @@ class CoolQ(BaseClient): def update_friend_group(self): # Mirai doesn't support retrieving friend group, neither does get_credentials unfortunately return {} - # Warning: Experimental API - try: - # res = self.coolq_api_query('_get_friend_list') - # relationship = {} - # if res: - # for group in res: - # for friend in group['friends']: - # relationship[str(friend['user_id'])] = str(group['friend_group_name']) - # self.friend_group = relationship - # Use QShow API - cred = self.coolq_api_query('get_credentials') - cookies = cred['cookies'] - csrf_token = cred['csrf_token'] - self.friend_group = get_friend_group_via_qq_show(cookies, csrf_token) - except Exception as e: - self.logger.warning('Failed to update friend group' + str(e)) def update_friend_list(self): 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)) for friend in self.friend_list: - if(friend['remark']==''): + if friend['remark'] == '': friend['remark'] = friend['nickname'] - self.friend_remark[str(friend['user_id'])] = { + self.friend_remark[friend['user_id']] = { 'nickname': friend['nickname'], 'remark': friend['remark'] } @@ -839,44 +790,16 @@ class CoolQ(BaseClient): self.update_contacts_timer.start() def get_friend_remark(self, uid): - if not self.friend_list: + if (not self.friend_list) or (uid not in self.friend_remark): try: self.update_friend_list() except CoolQAPIFailureException: # self.deliver_alert_to_master(self._('Failed to update friend remark name')) self.logger.exception(self._('Failed to update friend remark name')) return '' - # if not self.friend_group: - # try: - # self.update_friend_group() - # except CoolQAPIFailureException: - # self.deliver_alert_to_master(self._('Failed to get friend groups')) - # self.logger.exception(self._('Failed to get friend groups')) - # return '' - if str(uid) not in self.friend_remark: + if uid not in self.friend_remark: return None # I don't think you have such a friend - return self.friend_remark[str(uid)]['remark'] - ''' - for i in range(len(self.friend_list)): # friend group - for j in range(len(self.friend_list[i]['friend'])): - current_user = self.friend_list[i]['friend'][j] - if current_user['uin'] != str(uid): - continue - return current_user['name'] - ''' - ''' - for i in range(len(self.friend_list)): # friend group - for j in range(len(self.friend_list[i]['friends'])): - current_user = self.friend_list[i]['friends'][j] - if current_user['user_id'] != uid: - continue - if current_user['nickname'] == current_user['remark'] or current_user['nickname'] == '': - # no remark name - return current_user['nickname'] - else: - return current_user['remark'] - return None # I don't think you've got such a friend - ''' + return self.friend_remark[uid]['remark'] def send_efb_group_notice(self, context): context['message_type'] = 'group' @@ -978,8 +901,13 @@ class CoolQ(BaseClient): + getattr(e, 'message', repr(e))) return 'Done' - def async_download_file(self, context, **kwargs): - res = download_file_from_qzone(**kwargs) + def async_download_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'] + res = download_file(download_url) if isinstance(res, str): context['message'] = self._("[Download] ") + res self.send_efb_group_notice(context) diff --git a/efb_qq_plugin_coolq/Exceptions.py b/efb_qq_plugin_go_cqhttp/Exceptions.py similarity index 100% rename from efb_qq_plugin_coolq/Exceptions.py rename to efb_qq_plugin_go_cqhttp/Exceptions.py diff --git a/efb_qq_plugin_coolq/MsgDecorator.py b/efb_qq_plugin_go_cqhttp/MsgDecorator.py similarity index 99% rename from efb_qq_plugin_coolq/MsgDecorator.py rename to efb_qq_plugin_go_cqhttp/MsgDecorator.py index c17a69c..fb0e4e8 100644 --- a/efb_qq_plugin_coolq/MsgDecorator.py +++ b/efb_qq_plugin_go_cqhttp/MsgDecorator.py @@ -1,5 +1,3 @@ -# coding: utf-8 - import base64 import html import json diff --git a/efb_qq_plugin_coolq/Utils.py b/efb_qq_plugin_go_cqhttp/Utils.py similarity index 87% rename from efb_qq_plugin_coolq/Utils.py rename to efb_qq_plugin_go_cqhttp/Utils.py index f047b66..e5e97c0 100644 --- a/efb_qq_plugin_coolq/Utils.py +++ b/efb_qq_plugin_go_cqhttp/Utils.py @@ -1,14 +1,10 @@ -# coding: utf-8 -import re import json import logging import ntpath import tempfile import urllib.request from gettext import translation -from typing import * from urllib.error import URLError, HTTPError, ContentTooShortError -from urllib.parse import quote import requests from ehforwarderbot import Message, coordinator @@ -704,21 +700,10 @@ def param_spliter(str_param): return param -def download_file_from_qzone(cookie: str, csrf_token: str, uin, group_id, file_id, filename, file_size): - cookie_arr = param_spliter(cookie) - url = "http://qun.qzone.qq.com/cgi-bin/group_share_get_downurl?uin=" + str(uin) + "&pa=/104/" + \ - str(file_id) + "&groupid=" + str(group_id) + "&bussinessid=0&charset=utf-8&g_tk=" + str(csrf_token) + "&r=888" - ret = requests.get(url, cookies=cookie_arr) - data = json.loads(ret.text.split("(")[1].split(")")[0])['data'] - cookie += "; FTN5K=" + str(data['cookie']) - download_url = data['url'] - download_url += "/" + quote(filename) - if file_size >= 50*1024*1024: # File size is bigger than 50MiB - return _("File is too big to be downloaded") +def download_file(download_url): file = tempfile.NamedTemporaryFile() try: opener = urllib.request.build_opener() - opener.addheaders.append(('Cookie', cookie)) urllib.request.install_opener(opener) urllib.request.urlretrieve(download_url, file.name) except (URLError, HTTPError, ContentTooShortError) as e: @@ -729,20 +714,6 @@ def download_file_from_qzone(cookie: str, csrf_token: str, uin, group_id, file_i raise EOFError('File downloaded is Empty') file.seek(0) return file - ''' - try: - opener = urllib.request.build_opener() - opener.addheaders.append(('Cookie', cookie)) - with opener.open(download_url) as response, tempfile.NamedTemporaryFile() as f: - shutil.copyfileobj(response, f) - if f.seek(0, 2) <= 0: - raise EOFError('File downloaded is Empty') - f.seek(0) - return f - except Exception as e: - logging.getLogger(__name__).warning("Error occurs when downloading files" + str(e)) - return url - ''' def download_user_avatar(uid: str): @@ -777,22 +748,6 @@ def download_group_avatar(uid: str): return file -def get_friend_group_via_qq_show(cookie: str, csrf_token: str) -> Dict[str, str]: - # This function won't check before execute, instead all the exceptions will be thrown - cookie_arr = param_spliter(cookie) - url = "https://show.qq.com/cgi-bin/qqshow_user_friendgroup?g_tk={csrf_token}&omode=4" \ - .format(csrf_token=csrf_token) - ret = requests.get(url, cookies=cookie_arr) - data = json.loads(ret.text) - friend_group = {} - for i in range(len(data['data']['group'])): # friend group - for j in range(len(data['data']['group'][i]['friend'])): - current_user = str(data['data']['group'][i]['friend'][j]['uin']) - current_group = data['data']['group'][i]['name'] - friend_group[current_user] = current_group - return friend_group - - 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) @@ -809,22 +764,3 @@ def download_voice(filename: str, api_root: str, access_token: str): raise EOFError('File downloaded is Empty') file.seek(0) return file - - -def get_stranger_info_via_qzone(uin: str): - pattern = re.compile(r"\((.*)\)") - resp = requests.get("https://users.qzone.qq.com/fcg-bin/cgi_get_portrait.fcg?uins={id}".format(id=uin)) - # Assume that this API is always available - data = pattern.findall(resp.text) - if not data: - return "" - try: - data = json.loads(data[0]) - ret = { - "uin": uin, - "nickname": data[uin][6], - "avatar_url": data[uin][0] - } - return ret - except: - return "" diff --git a/efb_qq_plugin_coolq/__init__.py b/efb_qq_plugin_go_cqhttp/__init__.py similarity index 100% rename from efb_qq_plugin_coolq/__init__.py rename to efb_qq_plugin_go_cqhttp/__init__.py diff --git a/efb_qq_plugin_go_cqhttp/__version__.py b/efb_qq_plugin_go_cqhttp/__version__.py new file mode 100644 index 0000000..3f39079 --- /dev/null +++ b/efb_qq_plugin_go_cqhttp/__version__.py @@ -0,0 +1 @@ +__version__ = '2.0.1' diff --git a/setup.py b/setup.py index ee14e81..44d5ca5 100644 --- a/setup.py +++ b/setup.py @@ -5,24 +5,24 @@ if sys.version_info < (3, 6): raise Exception("Python 3.6 or higher is required. Your version is %s." % sys.version) __version__ = "" -exec(open('efb_qq_plugin_coolq/__version__.py').read()) +exec(open('efb_qq_plugin_go_cqhttp/__version__.py').read()) long_description = open('README.rst').read() setup( - name='efb-qq-plugin-coolq', + name='efb-qq-plugin-go-cqhttp', packages=find_packages(exclude=["*.tests", "*.tests.*", "tests.*", "tests"]), version=__version__, - description='EQS plugin for CoolQ API Compatible Client.', + description='EQS plugin for Go-CQHttp API Compatible Client.', long_description=long_description, include_package_data=True, - author='Milkice', - author_email='milkice@milkice.me', - url='https://github.com/milkice233/efb-qq-plugin-coolq', + author='XYenon', + author_email='i@xyenon.bid', + url='https://github.com/XYenon/efb-qq-plugin-go-cqhttp', license='GPLv3', python_requires='>=3.6', keywords=['ehforwarderbot', 'EH Forwarder Bot', 'EH Forwarder Bot Slave Channel', - 'qq', 'chatbot', 'EQS', 'CoolQ'], + 'qq', 'chatbot', 'EQS', 'CoolQ', 'go-cqhttp'], classifiers=[ "Development Status :: 3 - Alpha", "License :: OSI Approved :: GNU General Public License v3 (GPLv3)", @@ -40,6 +40,6 @@ setup( 'requests', 'python-magic', 'Pillow', 'cqhttp>=1.3.0', 'cherrypy>=18.5.0' ], entry_points={ - 'ehforwarderbot.qq.plugin': 'CoolQ = efb_qq_plugin_coolq:CoolQ' + 'ehforwarderbot.qq.plugin': 'CoolQ = efb_qq_plugin_go_cqhttp:CoolQ' } ) \ No newline at end of file