3
3
import mimetypes
4
4
import os
5
5
import re
6
+ import threading
6
7
import time
7
8
import html
8
9
from binascii import crc32
@@ -100,6 +101,8 @@ class WeChatChannel(EFBChannel):
100
101
supported_message_types = {MsgType .Text , MsgType .Sticker , MsgType .Image , MsgType .File , MsgType .Video , MsgType .Link }
101
102
users = {}
102
103
logger = logging .getLogger ("plugins.%s.WeChatChannel" % channel_id )
104
+ qr_callback = ""
105
+ qr_uuid = ""
103
106
104
107
SYSTEM_USERNAMES = ["filehelper" , "newsapp" , "fmessage" , "weibo" , "qqmail" , "fmessage" , "tmessage" , "qmessage" ,
105
108
"qqsync" , "floatbottle" , "lbsapp" , "shakeapp" , "medianote" , "qqfriend" , "readerapp" ,
@@ -110,11 +113,14 @@ def __init__(self, queue):
110
113
super ().__init__ (queue )
111
114
self .itchat = itchat .new_instance ()
112
115
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
+
118
124
self .logger .info ("EWS Inited!!!\n ---" )
119
125
120
126
#
@@ -147,21 +153,54 @@ def console_qr_code(self, uuid, status, qrcode):
147
153
QR += "\n If you cannot read the QR code above, " \
148
154
"Please generate a QR code with any tool with the following URL:\n " \
149
155
"https://login.weixin.qq.com/l/" + uuid
150
-
151
156
self .logger .critical (QR )
152
157
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
+
153
181
def exit_callback (self ):
154
182
msg = EFBMsg (self )
155
- msg .type = MsgType .Text
156
183
msg .source = MsgSource .System
157
184
msg .origin = {
158
185
'name' : 'WeChat System Message' ,
159
186
'alias' : 'WeChat System Message' ,
160
187
'uid' : - 1
161
188
}
162
-
163
189
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
+ }
165
204
self .queue .put (msg )
166
205
167
206
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
301
340
return result
302
341
303
342
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 ))
304
348
self .usersdata = self .itchat .get_friends (True ) + self .itchat .get_chatrooms ()
305
349
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 ):
306
359
@self .itchat .msg_register (['Text' ], isFriendChat = True , isMpChat = True )
307
360
def wcText (msg ):
308
361
self .textMsg (msg )
@@ -388,14 +441,6 @@ def wcSystemGroup(msg):
388
441
def wcSysLog (msg ):
389
442
self .logger .debug ("WeChat \" System\" message:\n %s" , repr (msg ))
390
443
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
-
399
444
@incomeMsgMeta
400
445
def textMsg (self , msg , isGroupChat = False ):
401
446
self .logger .info ("TextMsg!!!\n ---" )
@@ -772,6 +817,11 @@ def uin_rate(self, param=""):
772
817
773
818
# Command functions
774
819
820
+ def start_polling_thread (self ):
821
+ thread = threading .Thread (target = self .poll )
822
+ thread .start ()
823
+ return "Reconnecting..."
824
+
775
825
def add_friend (self , UserName = None , status = 2 , ticket = "" , UserInfo = {}):
776
826
if not UserName :
777
827
return "Username is empty. (UE02)"
@@ -828,4 +878,4 @@ def _flag(self, key, value):
828
878
Returns:
829
879
Value for the flag.
830
880
"""
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