Skip to content

Commit ec79299

Browse files
authored
Merge pull request ehForwarderBot#18 from RoyXiang/pr
[EWS]: Add an experimental flag: qr_target
2 parents c941407 + 72fe8b9 commit ec79299

File tree

2 files changed

+73
-18
lines changed

2 files changed

+73
-18
lines changed

docs/EWS.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,3 +104,8 @@ eh_wechat_slave = {
104104
List out all other messages (more than first one) for link messages with more than one link from MPS accounts.
105105
* `max_quote_length` _(int)_ [Default: `-1`]
106106
Maximum length of text for quotation messages. Set to 0 to fully disable quotation. Set to -1 to always quote full message.
107+
* `qr_target` _(string)_ [Default: `"console"`]
108+
The target channel which should receive a QR code to login the Wechat account.
109+
Available values:
110+
* `"console"`: the command line interface
111+
* `"master"`: the master channel

plugins/eh_wechat_slave.py

Lines changed: 68 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import mimetypes
44
import os
55
import re
6+
import threading
67
import time
78
import html
89
from binascii import crc32
@@ -100,6 +101,8 @@ class WeChatChannel(EFBChannel):
100101
supported_message_types = {MsgType.Text, MsgType.Sticker, MsgType.Image, MsgType.File, MsgType.Video, MsgType.Link}
101102
users = {}
102103
logger = logging.getLogger("plugins.%s.WeChatChannel" % channel_id)
104+
qr_callback = ""
105+
qr_uuid = ""
103106

104107
SYSTEM_USERNAMES = ["filehelper", "newsapp", "fmessage", "weibo", "qqmail", "fmessage", "tmessage", "qmessage",
105108
"qqsync", "floatbottle", "lbsapp", "shakeapp", "medianote", "qqfriend", "readerapp",
@@ -110,11 +113,14 @@ def __init__(self, queue):
110113
super().__init__(queue)
111114
self.itchat = itchat.new_instance()
112115
itchat.set_logging(showOnCmd=False)
113-
self.itchat.auto_login(enableCmdQR=2,
114-
hotReload=True,
115-
statusStorageDir="storage/%s.pkl" % self.channel_id,
116-
exitCallback=self.exit_callback,
117-
qrCallback=self.console_qr_code)
116+
self.itchat_msg_register()
117+
118+
qr_target = self._flag("qr_target", "console")
119+
if qr_target == "master":
120+
self.qr_callback = "master_qr_code"
121+
else:
122+
self.qr_callback = "console_qr_code"
123+
118124
self.logger.info("EWS Inited!!!\n---")
119125

120126
#
@@ -147,21 +153,54 @@ def console_qr_code(self, uuid, status, qrcode):
147153
QR += "\nIf you cannot read the QR code above, " \
148154
"Please generate a QR code with any tool with the following URL:\n" \
149155
"https://login.weixin.qq.com/l/" + uuid
150-
151156
self.logger.critical(QR)
152157

158+
def master_qr_code(self, uuid, status, qrcode):
159+
if uuid != self.qr_uuid:
160+
path = os.path.join("storage", self.channel_id)
161+
if not os.path.exists(path):
162+
os.makedirs(path)
163+
path = os.path.join(path, 'QR.jpg')
164+
with open(path, 'wb') as f:
165+
f.write(qrcode)
166+
msg = EFBMsg(self)
167+
msg.type = MsgType.Image
168+
msg.source = MsgSource.System
169+
msg.origin = {
170+
'name': 'WeChat System Message',
171+
'alias': 'WeChat System Message',
172+
'uid': -1
173+
}
174+
msg.text = '[%s] Scan this QR code to login your account' % self.channel_id
175+
msg.path = path
176+
msg.file = open(path, 'rb')
177+
msg.mime = 'image/jpeg'
178+
self.queue.put(msg)
179+
self.qr_uuid = uuid
180+
153181
def exit_callback(self):
154182
msg = EFBMsg(self)
155-
msg.type = MsgType.Text
156183
msg.source = MsgSource.System
157184
msg.origin = {
158185
'name': 'WeChat System Message',
159186
'alias': 'WeChat System Message',
160187
'uid': -1
161188
}
162-
163189
msg.text = "WeChat server logged out the user."
164-
190+
if self.qr_callback == "console_qr_code":
191+
msg.type = MsgType.Text
192+
else:
193+
msg.type = MsgType.Command
194+
msg.attributes = {
195+
"commands": [
196+
{
197+
"name": "Login again",
198+
"callable": "start_polling_thread",
199+
"args": [],
200+
"kwargs": {}
201+
}
202+
]
203+
}
165204
self.queue.put(msg)
166205

167206
def get_uid(self, UserName=None, NickName=None, alias=None, Uin=None):
@@ -301,8 +340,22 @@ def search_user(self, UserName=None, uid=None, uin=None, name=None, ActualUserNa
301340
return result
302341

303342
def poll(self):
343+
self.itchat.auto_login(enableCmdQR=2,
344+
hotReload=True,
345+
statusStorageDir="storage/%s.pkl" % self.channel_id,
346+
exitCallback=self.exit_callback,
347+
qrCallback=getattr(self, self.qr_callback))
304348
self.usersdata = self.itchat.get_friends(True) + self.itchat.get_chatrooms()
305349

350+
while self.itchat.alive and not self.stop_polling:
351+
self.itchat.configured_reply()
352+
353+
if self.itchat.useHotReload:
354+
self.itchat.dump_login_status()
355+
356+
self.logger.debug("%s (%s) gracefully stopped.", self.channel_name, self.channel_id)
357+
358+
def itchat_msg_register(self):
306359
@self.itchat.msg_register(['Text'], isFriendChat=True, isMpChat=True)
307360
def wcText(msg):
308361
self.textMsg(msg)
@@ -388,14 +441,6 @@ def wcSystemGroup(msg):
388441
def wcSysLog(msg):
389442
self.logger.debug("WeChat \"System\" message:\n%s", repr(msg))
390443

391-
while self.itchat.alive and not self.stop_polling:
392-
self.itchat.configured_reply()
393-
394-
if self.itchat.useHotReload:
395-
self.itchat.dump_login_status()
396-
397-
self.logger.debug("%s (%s) gracefully stopped.", self.channel_name, self.channel_id)
398-
399444
@incomeMsgMeta
400445
def textMsg(self, msg, isGroupChat=False):
401446
self.logger.info("TextMsg!!!\n---")
@@ -772,6 +817,11 @@ def uin_rate(self, param=""):
772817

773818
# Command functions
774819

820+
def start_polling_thread(self):
821+
thread = threading.Thread(target=self.poll)
822+
thread.start()
823+
return "Reconnecting..."
824+
775825
def add_friend(self, UserName=None, status=2, ticket="", UserInfo={}):
776826
if not UserName:
777827
return "Username is empty. (UE02)"
@@ -828,4 +878,4 @@ def _flag(self, key, value):
828878
Returns:
829879
Value for the flag.
830880
"""
831-
return getattr(config, self.channel_id, dict()).get('flags', dict()).get(key, value)
881+
return getattr(config, self.channel_id, dict()).get('flags', dict()).get(key, value)

0 commit comments

Comments
 (0)