def snapshot(self): """ @brief Save basic infos for next login. @return Bool: whether operation succeed. """ try: conf = { 'uuid': self.uuid, 'redirect_uri': self.redirect_uri, 'uin': self.uin, 'sid': self.sid, 'skey': self.skey, 'pass_ticket': self.pass_ticket, 'synckey': self.synckey, 'device_id': self.device_id, 'last_login': time.time(), } cm = ConfigManager() Log.debug('save wechat config') cm.set_wechat_config(conf) # save cookie Log.debug('save cookie') if self.cookie: self.cookie.save(ignore_discard=True) # save contacts Log.debug('save contacts') self.save_contacts() except Exception, e: Log.error(traceback.format_exc()) return False
def auto_reload(mod): """ @brief reload modules @param mod: the need reload modules """ try: module = sys.modules[mod] except: Log.error(traceback.format_exc()) return False filename = module.__file__ # .pyc 修改时间不会变 # 所以就用 .py 的修改时间 if filename.endswith(".pyc"): filename = filename.replace(".pyc", ".py") mod_time = os.path.getmtime(filename) if not "loadtime" in module.__dict__: module.loadtime = 0 try: if mod_time > module.loadtime: reload(module) else: return False except: Log.error(traceback.format_exc()) return False module.loadtime = mod_time echo('[*] load \'%s\' successful.\n' % mod) return True
def send_file(self, user_id, file_path): """ @brief send file @param user_id String @param file_path String @return Bool: whether operation succeed """ title = file_path.split('/')[-1] data = { 'appid': Constant.API_WXAPPID, 'title': title, 'totallen': '', 'attachid': '', 'type': self.wx_conf['APPMSGTYPE_ATTACH'], 'fileext': title.split('.')[-1], } response = self.webwxuploadmedia(file_path) if response is not None: data['totallen'] = response['StartPos'] data['attachid'] = response['MediaId'] else: Log.error('File upload error') return self.webwxsendappmsg(user_id, data)
def post(url, params, jsonfmt=True): """ @brief http post request @param url String @param params Dict, post params @param jsonfmt Bool, whether is json format @return http response """ Log.debug('POST -> ' + url) Log.debug(params) if jsonfmt: request = urllib2.Request( url=url, data=json.dumps(params, ensure_ascii=False).encode('utf8')) request.add_header(*Constant.HTTP_HEADER_CONTENTTYPE) else: request = urllib2.Request(url=url, data=urllib.urlencode(params)) while True: try: response = urllib2.urlopen(request, timeout=30) data = response.read() response.close() if jsonfmt: Log.debug(data) return json.loads(data, object_hook=_decode_data) return data except (KeyboardInterrupt, SystemExit): raise except: Log.error(traceback.format_exc()) time.sleep(1)
def get(url, api=None): """ @brief http get request @param url String @param api wechat api @return http response """ Log.debug('GET -> ' + url) request = urllib2.Request(url=url) request.add_header(*Constant.HTTP_HEADER_CONNECTION) request.add_header(*Constant.HTTP_HEADER_REFERER) if api in ['webwxgetvoice', 'webwxgetvideo']: request.add_header(*Constant.HTTP_HEADER_RANGE) while True: try: response = urllib2.urlopen(request, timeout=30) data = response.read() response.close() if api == None: Log.debug(data) return data except (KeyboardInterrupt, SystemExit): raise except: Log.error(traceback.format_exc()) time.sleep(1)
def recover_contacts(self): """ @brief recover contacts. @return Bool: whether operation succeed. """ try: self.User = pickle_load(self.pickle_file['User']) self.MemberList = pickle_load(self.pickle_file['MemberList']) self.GroupList = pickle_load(self.pickle_file['GroupList']) self.GroupMemeberList = pickle_load(self.pickle_file['GroupMemeberList']) self.SpecialUsersList = pickle_load(self.pickle_file['SpecialUsersList']) return True except Exception, e: Log.error(traceback.format_exc())
def run(str, func, *args): t = time.time() echo(str) r = False try: r = func(*args) except: Log.error(traceback.format_exc()) if r: totalTime = int(time.time() - t) echo(Constant.RUN_RESULT_SUCCESS % totalTime) else: echo(Constant.RUN_RESULT_FAIL) exit()
def insertmany(self, table, values): """ @brief Insert many rows in table @param table String @param values Array of tuple """ c = self.conn.cursor() self.lock.acquire() n = len(values[0]) sql = ("INSERT INTO %s VALUES (" + ",".join(['?'] * n) + ");") % table Log.debug('DB -> %s' % sql) try: c.executemany(sql, values) except Exception, e: Log.error(traceback.format_exc())
def set_cookie(cookie_file): """ @brief Load cookie from file @param cookie_file @param user_agent @return cookie, LWPCookieJar """ cookie = cookielib.LWPCookieJar(cookie_file) try: cookie.load(ignore_discard=True) except: Log.error(traceback.format_exc()) opener = urllib2.build_opener(urllib2.HTTPCookieProcessor(cookie)) opener.addheaders = Constant.HTTP_HEADER_USERAGENT urllib2.install_opener(opener) return cookie
def execute(self, sql, value=None): """ @brief execute sql commands, return result if it has @param sql String @param value Tuple @return result Array """ c = self.conn.cursor() self.lock.acquire() hasReturn = sql.lstrip().upper().startswith("SELECT") try: if value: c.execute(sql, value) else: c.execute(sql) if hasReturn: result = c.fetchall() except Exception, e: Log.error(traceback.format_exc())
def mass_send(method, data, func): j = {'ret': -1, 'unsend_list': []} if method == 'POST' and data: to_list = data['to_list'] msg = data['msg'] media_type = data.get('media_type', '') if media_type in ['img', 'emot']: file_path = os.path.join(app.config['UPLOAD_FOLDER'], msg) response = wechat.webwxuploadmedia(file_path) if response is not None: msg = response['MediaId'] elif media_type == 'file': file_path = os.path.join(app.config['UPLOAD_FOLDER'], msg) data = { 'appid': Constant.API_WXAPPID, 'title': msg, 'totallen': '', 'attachid': '', 'type': wechat.wx_conf['APPMSGTYPE_ATTACH'], 'fileext': msg.split('.')[-1], } response = wechat.webwxuploadmedia(file_path) if response is not None: data['totallen'] = response['StartPos'] data['attachid'] = response['MediaId'] else: Log.error('File upload error') msg = data for groups in split_array(to_list, 20): for g in groups: r = func(g, msg) if not r: j['unsend_list'].append(g) time.sleep(1) j['ret'] = len(j['unsend_list']) return j
def start(self): echo(Constant.LOG_MSG_START) print('[*] wechat.wechat.start 启动微信') run(Constant.LOG_MSG_RECOVER, self.recover) timeOut = time.time() - self.last_login echo(Constant.LOG_MSG_TRY_INIT) if self.webwxinit(): echo(Constant.LOG_MSG_SUCCESS) run(Constant.LOG_MSG_RECOVER_CONTACT, self.recover_contacts) else: echo(Constant.LOG_MSG_FAIL) while True: # first try to login by uin without qrcode print '[*] 关联登录无需二维码' echo(Constant.LOG_MSG_ASSOCIATION_LOGIN) if self.association_login(): print '[*] 关联登录,成功' echo(Constant.LOG_MSG_SUCCESS) else: print '[*] 关联登录,失败' echo(Constant.LOG_MSG_FAIL) # scan qrcode to login run(Constant.LOG_MSG_GET_UUID, self.getuuid) echo(Constant.LOG_MSG_GET_QRCODE) self.genqrcode() echo(Constant.LOG_MSG_SCAN_QRCODE) if not self.waitforlogin(): continue echo(Constant.LOG_MSG_CONFIRM_LOGIN) print '[*] 登录确认' if not self.waitforlogin(0): continue break run(Constant.LOG_MSG_LOGIN, self.login) run(Constant.LOG_MSG_INIT, self.webwxinit) run(Constant.LOG_MSG_STATUS_NOTIFY, self.webwxstatusnotify) run(Constant.LOG_MSG_GET_CONTACT, self.webwxgetcontact) echo(Constant.LOG_MSG_CONTACT_COUNT % ( self.MemberCount, len(self.MemberList) )) echo(Constant.LOG_MSG_OTHER_CONTACT_COUNT % ( len(self.GroupList), len(self.ContactList), len(self.SpecialUsersList), len(self.PublicUsersList) )) run(Constant.LOG_MSG_GET_GROUP_MEMBER, self.fetch_group_contacts) run(Constant.LOG_MSG_SNAPSHOT, self.snapshot) #------------------------ # add by haining.qin 17-05-04 # instance a MsgProcessor # msgProcessor = WeChatMsgProcessor() #------------------------ while True: print('\n[*] while 监听 微信消息') [retcode, selector] = self.synccheck() Log.debug('retcode: %s, selector: %s' % (retcode, selector)) self.exit_code = int(retcode) print('[*] 返回[retcode,selector]=',[retcode,selector]) if retcode == '1100': echo(Constant.LOG_MSG_LOGOUT) break if retcode == '1101': echo(Constant.LOG_MSG_LOGIN_OTHERWHERE) break if retcode == '1102': echo(Constant.LOG_MSG_QUIT_ON_PHONE) break elif retcode == '0': if selector == '2': r = self.webwxsync() if r is not None: try: self.handle_msg(r) except: traceback.print_exc() Log.error(traceback.format_exc()) elif selector == '7': r = self.webwxsync() elif selector == '0': time.sleep(self.time_out) elif selector == '4': print '[*] 保存群聊,修改群名,增删联系' ''''' # 保存群聊到通讯 # 修改群名 # 新增或删除联系人 # 群聊成员数目变化 ''' r = self.webwxsync() if r is not None: try: self.handle_mod(r) except: traceback.print_exc() Log.error(traceback.format_exc()) elif selector == '3' or selector == '6': break else: r = self.webwxsync() Log.debug('webwxsync: %s\n' % json.dumps(r)) # 执行定时任务 if self.msg_handler: self.msg_handler.check_schedule_task() print '[*] 判断bot是否存在? ', self.bot if self.bot: r = self.bot.time_schedule() if r: for g in self.GroupList: echo('[*] 推送-> %s: %s' % (g['NickName'], r)) g_id = g['UserName'] print '[*] 推送-> %s: %s' % (g['NickName'], r) self.webwxsendmsg(r, g_id)
def run_server(): app.run(port=PORT) if cm.get('setting', 'server_mode') == 'True': serverProcess = threading.Thread(target=run_server) serverProcess.start() while True: try: # wechat start wechat.start() except KeyboardInterrupt: traceback.print_exc() print '# 微信登录退出' echo(Constant.LOG_MSG_QUIT) wechat.exit_code = 1 else: print '微信登录遇到错误' Log.error(traceback.format_exc()) finally: print '[*] 微信停止' wechat.stop() if wechat.exit_code == 0: echo(Constant.MAIN_RESTART) else: # kill process os.system(Constant.LOG_MSG_KILL_PROCESS % os.getpid())
def webwxuploadmedia(self, file_path): """ @brief upload image @param file_path String @return Dict: json """ url = self.wx_conf['API_webwxuploadmedia'] + '?f=json' # 计数器 self.media_count = self.media_count + 1 fn = file_path # mime_type: # 'application/pdf' # 'image/jpeg' # 'image/png' # ... mime_type = mimetypes.guess_type(fn, strict=False)[0] if not mime_type: mime_type = 'text/plain' # 文档格式 # 微信服务器目前应该支持3种类型: # pic 直接显示,包含图片,表情 # video 不清楚 # doc 显示为文件,包含PDF等 media_type = 'pic' if mime_type.split('/')[0] == 'image' else 'doc' time_format = "%a %b %d %Y %T GMT%z (%Z)" last_modifie_date = time.strftime(time_format, time.localtime()) file_size = os.path.getsize(fn) pass_ticket = self.pass_ticket client_media_id = str(int(time.time() * 1000)) + \ str(random.random())[:5].replace('.', '') webwx_data_ticket = '' for item in self.cookie: if item.name == 'webwx_data_ticket': webwx_data_ticket = item.value break if (webwx_data_ticket == ''): Log.error("No Cookie\n") return None uploadmediarequest = json.dumps( { "BaseRequest": self.base_request, "ClientMediaId": client_media_id, "TotalLen": file_size, "StartPos": 0, "DataLen": file_size, "MediaType": 4 }, ensure_ascii=False).encode('utf8') multipart_encoder = MultipartEncoder( fields={ 'id': 'WU_FILE_' + str(self.media_count), 'name': fn, 'type': mime_type, 'lastModifieDate': last_modifie_date, 'size': str(file_size), 'mediatype': media_type, 'uploadmediarequest': uploadmediarequest, 'webwx_data_ticket': webwx_data_ticket, 'pass_ticket': pass_ticket, 'filename': (fn, open(fn, 'rb'), mime_type.split('/')[1]) }, boundary=('-----------------------------' '1575017231431605357584454111')) headers = { 'Host': self.wx_filehost, 'User-Agent': self.user_agent, 'Accept': ('text/html,application/xhtml+xml,' 'application/xml;q=0.9,*/*;q=0.8'), 'Accept-Language': 'en-US,en;q=0.5', 'Accept-Encoding': 'gzip, deflate', 'Referer': 'https://' + self.wx_host, 'Content-Type': multipart_encoder.content_type, 'Origin': 'https://' + self.wx_host, 'Connection': 'keep-alive', 'Pragma': 'no-cache', 'Cache-Control': 'no-cache', } dic = requests.post(url, data=multipart_encoder, headers=headers).json() # 末尾加json反序列化 print '[*] webwxuploadmedia上传图片至微信服务器,\n# dic=', dic, 'type(dic)=', type( dic) if dic['BaseResponse']['Ret'] == 0: return dic return None