def main(username, keep_alive=True): user = Bot(username) action, source, result_code = user.action() print('m1') print(action) print(source) print(result_code) user.db_manager.SaveCurrentAction(source, action, result_code) print('m2') if not keep_alive: return 0 plural = 's' minutes, seconds = RandomizeTime() if minutes <= 1: plural = '' if minutes == 0: cmd = 'echo "sleep %s ; python drifter_main.py %s > /dev/null" | at -M now &' % ( seconds, username) else: cmd = 'echo "sleep %s ; python drifter_main.py %s > /dev/null" | at -M now + %s minute%s &' % ( seconds, username, minutes, plural) os.system(cmd)
def index(): req = request.get_json() #Pega o que foi enviado pelo Telegram bot = Bot() #Instacia o bot do arquivo bot.py importado no inicio bot.passando_dados(req) #Passa os dados da requisição para ser trabalhado. time.sleep( 5 ) #Coloquei esse sleep pois a API do google estava dando erro e ele ajudou a cortar um pouco dos erros. success = bot.action( ) #Aqui ele trata o dado e retorna o código da operação, isso pode ser melhor entendido em HTML onde o código 200 indica que tudo foi certo. return jsonify( success=success ) #Retornando o código para o Telegram. (posso estar errado)
class Core(object): def __str__(self): description = \ "=========================\n" + \ "[#] Web Weixin\n" + \ "[#] Debug Mode: " + str(self.DEBUG) + "\n" + \ "[#] Uuid: " + self.uuid + "\n" + \ "[#] Uin: " + str(self.uin) + "\n" + \ "[#] Sid: " + self.sid + "\n" + \ "[#] Skey: " + self.skey + "\n" + \ "[#] DeviceId: " + self.deviceId + "\n" + \ "[#] PassTicket: " + self.pass_ticket + "\n" + \ "=========================" return description def __init__(self): self.DEBUG = False self.uuid = '' self.base_uri = '' self.redirect_uri = '' self.uin = '' self.sid = '' self.skey = '' self.pass_ticket = '' self.deviceId = 'e' + repr(random.random())[2:17] self.BaseRequest = {} self.synckey = '' self.SyncKey = [] self.User = [] self.MemberList = [] self.ContactList = [] # 好友 self.GroupList = [] # 群 self.GroupMemeberList = [] # 群友 self.PublicUsersList = [] # 公众号/服务号 self.SpecialUsersList = [] # 特殊账号 self.autoReplyMode = False self.syncHost = '' self.user_agent = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/48.0.2564.109 Safari/537.36' self.interactive = True self.autoOpen = False self.saveFolder = os.path.join(os.getcwd(), 'saved') self.saveSubFolders = {'webwxgeticon': 'icons', 'webwxgetheadimg': 'headimgs', 'webwxgetmsgimg': 'msgimgs', 'webwxgetvideo': 'videos', 'webwxgetvoice': 'voices', '_showQRCodeImg': 'qrcodes'} self.appid = 'wx782c26e4c19acffb' self.lang = 'zh_CN' self.lastCheckTs = time.time() self.memberCount = 0 self.SpecialUsers = ['newsapp', 'fmessage', 'filehelper', 'weibo', 'qqmail', 'fmessage', 'tmessage', 'qmessage', 'qqsync', 'floatbottle', 'lbsapp', 'shakeapp', 'medianote', 'qqfriend', 'readerapp', 'blogapp', 'facebookapp', 'masssendapp', 'meishiapp', 'feedsapp', 'voip', 'blogappweixin', 'weixin', 'brandsessionholder', 'weixinreminder', 'wxid_novlwrv3lqwv11', 'gh_22b87fa7cb3c', 'officialaccounts', 'notification_messages', 'wxid_novlwrv3lqwv11', 'gh_22b87fa7cb3c', 'wxitil', 'userexperience_alarm', 'notification_messages'] self.TimeOut = 20 # 同步最短时间间隔(单位:秒) self.media_count = -1 self.bot = Bot() self.cookie = cookielib.CookieJar() opener = urllib2.build_opener(urllib2.HTTPCookieProcessor(self.cookie)) opener.addheaders = [('User-agent', self.user_agent)] urllib2.install_opener(opener) def loadConfig(self, config): if config['DEBUG']: self.DEBUG = config['DEBUG'] if config['autoReplyMode']: self.autoReplyMode = config['autoReplyMode'] if config['user_agent']: self.user_agent = config['user_agent'] if config['interactive']: self.interactive = config['interactive'] if config['autoOpen']: self.autoOpen = config['autoOpen'] def getUUID(self): url = 'https://login.weixin.qq.com/jslogin' params = { 'appid': self.appid, 'fun': 'new', 'lang': self.lang, '_': int(time.time()), } data = self._post(url, params, False) if data == '': return False regx = r'window.QRLogin.code = (\d+); window.QRLogin.uuid = "(\S+?)"' pm = re.search(regx, data) if pm: code = pm.group(1) self.uuid = pm.group(2) return code == '200' return False def genQRCode(self): #return self._showQRCodeImg() if sys.platform.startswith('win'): self._showQRCodeImg() else: self._str2qr('https://login.weixin.qq.com/l/' + self.uuid) def _showQRCodeImg(self): url = 'https://login.weixin.qq.com/qrcode/' + self.uuid params = { 't': 'webwx', '_': int(time.time()) } data = self._post(url, params, False) if data == '': return QRCODE_PATH = self._saveFile('qrcode.jpg', data, '_showQRCodeImg') os.startfile(QRCODE_PATH) def waitForLogin(self, tip=1): time.sleep(tip) url = 'https://login.weixin.qq.com/cgi-bin/mmwebwx-bin/login?tip=%s&uuid=%s&_=%s' % ( tip, self.uuid, int(time.time())) data = self._get(url) if data == '': return False pm = re.search(r'window.code=(\d+);', data) code = pm.group(1) if code == '201': return True elif code == '200': pm = re.search(r'window.redirect_uri="(\S+?)";', data) r_uri = pm.group(1) + '&fun=new' self.redirect_uri = r_uri self.base_uri = r_uri[:r_uri.rfind('/')] return True elif code == '408': self._echo('[登陆超时] \n') else: self._echo('[登陆异常] \n') return False def login(self): data = self._get(self.redirect_uri) if data == '': return False doc = xml.dom.minidom.parseString(data) root = doc.documentElement for node in root.childNodes: if node.nodeName == 'skey': self.skey = node.childNodes[0].data elif node.nodeName == 'wxsid': self.sid = node.childNodes[0].data elif node.nodeName == 'wxuin': self.uin = node.childNodes[0].data elif node.nodeName == 'pass_ticket': self.pass_ticket = node.childNodes[0].data if '' in (self.skey, self.sid, self.uin, self.pass_ticket): return False self.BaseRequest = { 'Uin': int(self.uin), 'Sid': self.sid, 'Skey': self.skey, 'DeviceID': self.deviceId, } return True def webwxinit(self): url = self.base_uri + '/webwxinit?pass_ticket=%s&skey=%s&r=%s' % ( self.pass_ticket, self.skey, int(time.time())) params = { 'BaseRequest': self.BaseRequest } dic = self._post(url, params) if dic == '': return False self.SyncKey = dic['SyncKey'] self.User = dic['User'] # synckey for synccheck self.synckey = '|'.join( [str(keyVal['Key']) + '_' + str(keyVal['Val']) for keyVal in self.SyncKey['List']]) return dic['BaseResponse']['Ret'] == 0 def webwxstatusnotify(self): url = self.base_uri + \ '/webwxstatusnotify?lang=zh_CN&pass_ticket=%s' % (self.pass_ticket) params = { 'BaseRequest': self.BaseRequest, "Code": 3, "FromUserName": self.User['UserName'], "ToUserName": self.User['UserName'], "ClientMsgId": int(time.time()) } dic = self._post(url, params) if dic == '': return False return dic['BaseResponse']['Ret'] == 0 def webwxgetcontact(self): SpecialUsers = self.SpecialUsers url = self.base_uri + '/webwxgetcontact?pass_ticket=%s&skey=%s&r=%s' % ( self.pass_ticket, self.skey, int(time.time())) dic = self._post(url, {}) if dic == '': return False self.MemberCount = dic['MemberCount'] self.MemberList = dic['MemberList'] ContactList = self.MemberList[:] GroupList = self.GroupList[:] PublicUsersList = self.PublicUsersList[:] SpecialUsersList = self.SpecialUsersList[:] for i in xrange(len(ContactList) - 1, -1, -1): Contact = ContactList[i] if Contact['VerifyFlag'] & 8 != 0: # 公众号/服务号 ContactList.remove(Contact) self.PublicUsersList.append(Contact) elif Contact['UserName'] in SpecialUsers: # 特殊账号 ContactList.remove(Contact) self.SpecialUsersList.append(Contact) elif Contact['UserName'].find('@@') != -1: # 群聊 ContactList.remove(Contact) self.GroupList.append(Contact) elif Contact['UserName'] == self.User['UserName']: # 自己 ContactList.remove(Contact) self.ContactList = ContactList return True def webwxbatchgetcontact(self): url = self.base_uri + \ '/webwxbatchgetcontact?type=ex&r=%s&pass_ticket=%s' % ( int(time.time()), self.pass_ticket) params = { 'BaseRequest': self.BaseRequest, "Count": len(self.GroupList), "List": [{"UserName": g['UserName'], "EncryChatRoomId":""} for g in self.GroupList] } dic = self._post(url, params) if dic == '': return False # blabla ... ContactList = dic['ContactList'] ContactCount = dic['Count'] self.GroupList = ContactList for i in xrange(len(ContactList) - 1, -1, -1): Contact = ContactList[i] MemberList = Contact['MemberList'] for member in MemberList: self.GroupMemeberList.append(member) return True def getNameById(self, id): url = self.base_uri + \ '/webwxbatchgetcontact?type=ex&r=%s&pass_ticket=%s' % ( int(time.time()), self.pass_ticket) params = { 'BaseRequest': self.BaseRequest, "Count": 1, "List": [{"UserName": id, "EncryChatRoomId": ""}] } dic = self._post(url, params) if dic == '': return None # blabla ... return dic['ContactList'] def testsynccheck(self): SyncHost = [ 'webpush.weixin.qq.com', #'webpush2.weixin.qq.com', 'webpush.wechat.com', #'webpush1.wechat.com', #'webpush2.wechat.com', 'webpush.wx.qq.com', 'webpush2.wx.qq.com' #'webpush.wechatapp.com' ] for host in SyncHost: self.syncHost = host [retcode, selector] = self.synccheck() if retcode == '0': return True return False def synccheck(self): params = { 'r': int(time.time()), 'sid': self.sid, 'uin': self.uin, 'skey': self.skey, 'deviceid': self.deviceId, 'synckey': self.synckey, '_': int(time.time()), } url = 'https://' + self.syncHost + \ '/cgi-bin/mmwebwx-bin/synccheck?' + urllib.urlencode(params) data = self._get(url) if data == '': return [-1,-1] pm = re.search( r'window.synccheck={retcode:"(\d+)",selector:"(\d+)"}', data) retcode = pm.group(1) selector = pm.group(2) return [retcode, selector] def webwxsync(self): url = self.base_uri + \ '/webwxsync?sid=%s&skey=%s&pass_ticket=%s' % ( self.sid, self.skey, self.pass_ticket) params = { 'BaseRequest': self.BaseRequest, 'SyncKey': self.SyncKey, 'rr': ~int(time.time()) } dic = self._post(url, params) if dic == '': return None if self.DEBUG: print json.dumps(dic, indent=4) (json.dumps(dic, indent=4)) if dic['BaseResponse']['Ret'] == 0: self.SyncKey = dic['SyncKey'] self.synckey = '|'.join( [str(keyVal['Key']) + '_' + str(keyVal['Val']) for keyVal in self.SyncKey['List']]) return dic def webwxsendmsg(self, word, to='filehelper'): url = self.base_uri + \ '/webwxsendmsg?pass_ticket=%s' % (self.pass_ticket) clientMsgId = str(int(time.time() * 1000)) + \ str(random.random())[:5].replace('.', '') params = { 'BaseRequest': self.BaseRequest, 'Msg': { "Type": 1, "Content": self._transcoding(word), "FromUserName": self.User['UserName'], "ToUserName": to, "LocalID": clientMsgId, "ClientMsgId": clientMsgId } } headers = {'content-type': 'application/json; charset=UTF-8'} data = json.dumps(params, ensure_ascii=False).encode('utf8') r = requests.post(url, data=data, headers=headers) dic = r.json() return dic['BaseResponse']['Ret'] == 0 def webwxuploadmedia(self, image_name): url = 'https://file2.wx.qq.com/cgi-bin/mmwebwx-bin/webwxuploadmedia?f=json' # 计数器 self.media_count = self.media_count + 1 # 文件名 file_name = image_name # MIME格式 # mime_type = application/pdf, image/jpeg, image/png, etc. mime_type = mimetypes.guess_type(image_name, strict=False)[0] # 微信识别的文档格式,微信服务器应该只支持两种类型的格式。pic和doc # pic格式,直接显示。doc格式则显示为文件。 media_type = 'pic' if mime_type.split('/')[0] == 'image' else 'doc' # 上一次修改日期 lastModifieDate = 'Thu Mar 17 2016 00:55:10 GMT+0800 (CST)' # 文件大小 file_size = os.path.getsize(file_name) # PassTicket pass_ticket = self.pass_ticket # clientMediaId client_media_id = str(int(time.time() * 1000)) + \ str(random.random())[:5].replace('.', '') # webwx_data_ticket webwx_data_ticket = '' for item in self.cookie: if item.name == 'webwx_data_ticket': webwx_data_ticket = item.value break if (webwx_data_ticket == ''): return "None F**k Cookie" uploadmediarequest = json.dumps({ "BaseRequest": self.BaseRequest, "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': file_name, 'type': mime_type, 'lastModifieDate': lastModifieDate, 'size': str(file_size), 'mediatype': media_type, 'uploadmediarequest': uploadmediarequest, 'webwx_data_ticket': webwx_data_ticket, 'pass_ticket': pass_ticket, 'filename': (file_name, open(file_name, 'rb'), mime_type.split('/')[1]) }, boundary='-----------------------------1575017231431605357584454111' ) headers = { 'Host': 'file2.wx.qq.com', 'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10.10; rv:42.0) Gecko/20100101 Firefox/42.0', '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://wx2.qq.com/', 'Content-Type': multipart_encoder.content_type, 'Origin': 'https://wx2.qq.com', 'Connection': 'keep-alive', 'Pragma': 'no-cache', 'Cache-Control': 'no-cache' } r = requests.post(url, data=multipart_encoder, headers=headers) response_json = r.json() if response_json['BaseResponse']['Ret'] == 0: return response_json return None def webwxsendmsgimg(self, user_id, media_id): url = 'https://wx2.qq.com/cgi-bin/mmwebwx-bin/webwxsendmsgimg?fun=async&f=json&pass_ticket=%s' % self.pass_ticket clientMsgId = str(int(time.time() * 1000)) + \ str(random.random())[:5].replace('.', '') data_json = { "BaseRequest": self.BaseRequest, "Msg": { "Type": 3, "MediaId": media_id, "FromUserName": self.User['UserName'], "ToUserName": user_id, "LocalID": clientMsgId, "ClientMsgId": clientMsgId } } headers = {'content-type': 'application/json; charset=UTF-8'} data = json.dumps(data_json, ensure_ascii=False).encode('utf8') r = requests.post(url, data=data, headers=headers) dic = r.json() return dic['BaseResponse']['Ret'] == 0 def webwxsendmsgemotion(self, user_id, media_id): url = 'https://wx2.qq.com/cgi-bin/mmwebwx-bin/webwxsendemoticon?fun=sys&f=json&pass_ticket=%s' % self.pass_ticket clientMsgId = str(int(time.time() * 1000)) + \ str(random.random())[:5].replace('.', '') data_json = { "BaseRequest": self.BaseRequest, "Msg": { "Type": 47, "EmojiFlag": 2, "MediaId": media_id, "FromUserName": self.User['UserName'], "ToUserName": user_id, "LocalID": clientMsgId, "ClientMsgId": clientMsgId } } headers = {'content-type': 'application/json; charset=UTF-8'} data = json.dumps(data_json, ensure_ascii=False).encode('utf8') r = requests.post(url, data=data, headers=headers) dic = r.json() if self.DEBUG: self._show_info(json.dumps(dic, indent=4)) return dic['BaseResponse']['Ret'] == 0 def webwxgeticon(self, id): url = self.base_uri + \ '/webwxgeticon?username=%s&skey=%s' % (id, self.skey) data = self._get(url) if data == '': return '' fn = 'img_' + id + '.jpg' return self._saveFile(fn, data, 'webwxgeticon') def webwxgetheadimg(self, id): url = self.base_uri + \ '/webwxgetheadimg?username=%s&skey=%s' % (id, self.skey) data = self._get(url) if data == '': return '' fn = 'img_' + id + '.jpg' return self._saveFile(fn, data, 'webwxgetheadimg') def webwxgetmsgimg(self, msgid): url = self.base_uri + \ '/webwxgetmsgimg?MsgID=%s&skey=%s' % (msgid, self.skey) data = self._get(url) if data == '': return '' fn = 'img_' + msgid + '.jpg' return self._saveFile(fn, data, 'webwxgetmsgimg') # Not work now for weixin haven't support this API def webwxgetvideo(self, msgid): url = self.base_uri + \ '/webwxgetvideo?msgid=%s&skey=%s' % (msgid, self.skey) data = self._get(url, api='webwxgetvideo') if data == '': return '' fn = 'video_' + msgid + '.mp4' return self._saveFile(fn, data, 'webwxgetvideo') def webwxgetvoice(self, msgid): url = self.base_uri + \ '/webwxgetvoice?msgid=%s&skey=%s' % (msgid, self.skey) data = self._get(url) if data == '': return '' fn = 'voice_' + msgid + '.mp3' return self._saveFile(fn, data, 'webwxgetvoice') def getGroupName(self, id): name = '未知群' for member in self.GroupList: if member['UserName'] == id: name = member['NickName'] if name == '未知群': # 现有群里面查不到 GroupList = self.getNameById(id) for group in GroupList: self.GroupList.append(group) if group['UserName'] == id: name = group['NickName'] MemberList = group['MemberList'] for member in MemberList: self.GroupMemeberList.append(member) return name def getUserRemarkName(self, id): name = '未知群' if id[:2] == '@@' else '陌生人' if id == self.User['UserName']: return self.User['NickName'] # 自己 if id[:2] == '@@': # 群 name = self.getGroupName(id) else: # 特殊账号 for member in self.SpecialUsersList: if member['UserName'] == id: name = member['RemarkName'] if member[ 'RemarkName'] else member['NickName'] # 公众号或服务号 for member in self.PublicUsersList: if member['UserName'] == id: name = member['RemarkName'] if member[ 'RemarkName'] else member['NickName'] # 直接联系人 for member in self.ContactList: if member['UserName'] == id: name = member['RemarkName'] if member[ 'RemarkName'] else member['NickName'] # 群友 for member in self.GroupMemeberList: if member['UserName'] == id: name = member['DisplayName'] if member[ 'DisplayName'] else member['NickName'] if name == '未知群' or name == '陌生人': self._show_info(id) return name def getUSerID(self, name): for member in self.MemberList: if name == member['RemarkName'] or name == member['NickName']: return member['UserName'] return None ### supervision and auto-reply module start def handleMsg(self, r): for msg in r['AddMsgList']: self._show_info('[*] 你有新的消息,请注意查收') msgType = msg['MsgType'] name = self.getUserRemarkName(msg['FromUserName']) content = msg['Content'].replace('<', '<').replace('>', '>') msgid = msg['MsgId'] ans = self.bot.action(msgType, content) if msgType == 1: raw_msg = {'raw_msg': msg} self._showMsg(raw_msg,"[*] 文字信息") self._save_log(msg) self._show_info("回答:->"+ans) if self.autoReplyMode: if self.webwxsendmsg("[hugo bot serve for you]"+ans, msg['FromUserName']): logging.info('自动回复: ' + ans) else: print '自动回复失败' logging.info('自动回复失败') elif msgType == 3: image = self.webwxgetmsgimg(msgid) raw_msg = {'raw_msg': msg, 'message': '%s 发送了一张图片: %s' % (name, image)} self._showMsg(raw_msg,"[*] 图像信息") self._safe_open(image) elif msgType == 34: voice = self.webwxgetvoice(msgid) raw_msg = {'raw_msg': msg, 'message': '%s 发了一段语音: %s' % (name, voice)} self._showMsg(raw_msg,"[*] 语音信息") self._safe_open(voice) elif msgType == 42: info = msg['RecommendInfo'] print '%s 发送了一张名片:' % name print '=========================' print '= 昵称: %s' % info['NickName'] print '= 微信号: %s' % info['Alias'] print '= 地区: %s %s' % (info['Province'], info['City']) print '= 性别: %s' % ['未知', '男', '女'][info['Sex']] print '=========================' raw_msg = {'raw_msg': msg, 'message': '%s 发送了一张名片: %s' % ( name.strip(), json.dumps(info))} self._showMsg(raw_msg,"[*] 名片信息") elif msgType == 47: url = self._searchContent('cdnurl', content) raw_msg = {'raw_msg': msg, 'message': '%s 发了一个动画表情,点击下面链接查看: %s' % (name, url)} self._showMsg(raw_msg,"[*] 动画表情") self._safe_open(url) elif msgType == 49: appMsgType = defaultdict(lambda: "") appMsgType.update({5: '链接', 3: '音乐', 7: '微博'}) print '%s 分享了一个%s:' % (name, appMsgType[msg['AppMsgType']]) print '=========================' print '= 标题: %s' % msg['FileName'] print '= 描述: %s' % self._searchContent('des', content, 'xml') print '= 链接: %s' % msg['Url'] print '= 来自: %s' % self._searchContent('appname', content, 'xml') print '=========================' card = { 'title': msg['FileName'], 'description': self._searchContent('des', content, 'xml'), 'url': msg['Url'], 'appname': self._searchContent('appname', content, 'xml') } raw_msg = {'raw_msg': msg, 'message': '%s 分享了一个%s: %s' % ( name, appMsgType[msg['AppMsgType']], json.dumps(card))} self._showMsg(raw_msg,"[*] 平台分享") elif msgType == 51: raw_msg = {'raw_msg': msg, 'message': '[*] 成功获取联系人信息'} self._showMsg(raw_msg,"[*] 微信初始化信息") elif msgType == 62: video = self.webwxgetvideo(msgid) raw_msg = {'raw_msg': msg, 'message': '%s 发了一段小视频: %s' % (name, video)} self._showMsg(raw_msg,"[*] 小视频信息") self._safe_open(video) elif msgType == 10002: raw_msg = {'raw_msg': msg, 'message': '%s 撤回了一条消息' % name} self._showMsg(raw_msg,"[*] 撤回信息") else: self._show_info('[*] 该消息类型为: %d,可能是表情,图片, 链接或红包: %s' % (msg['MsgType'], json.dumps(msg))) raw_msg = { 'raw_msg': msg, 'message': '[*] 该消息类型为: %d,可能是表情,图片, 链接或红包' % msg['MsgType']} self._showMsg(raw_msg,"[*] 系统信息") def listenMsgMode(self): self._show_info('[*] 进入消息监听模式 ... 成功') self._run('[*] 进行同步线路测试 ... ', self.testsynccheck) playWeChat = 0 redEnvelope = 0 while True: self.lastCheckTs = time.time() [retcode, selector] = self.synccheck() if self.DEBUG: self._show_info('retcode: %s, selector: %s' % (retcode, selector)) if retcode == '1100': self._show_info('[*] 你在手机上登出了微信,债见') break if retcode == '1101': self._show_info('[*] 你在其他地方登录了 WEB 版微信,债见') break elif retcode == '0': if selector == '2': r = self.webwxsync() if r is not None: self.handleMsg(r) elif selector == '7': playWeChat += 1 self._show_info('[*] 你在手机上玩微信被我发现了 %d 次' % playWeChat) r = self.webwxsync() elif selector == '0': time.sleep(1) ''' elif selector == '6': # TODO redEnvelope += 1 self._show_info('[*] 收到疑似红包消息 %d 次' % redEnvelope) if (time.time() - self.lastCheckTs) <= 20: time.sleep(time.time() - self.lastCheckTs) ''' ### supervise and auto-reply module end ### action module start def sendMsg(self, name, word, isfile=False): id = self.getUSerID(name) if id: if isfile: with open(word, 'r') as f: for line in f.readlines(): line = line.replace('\n', '') self._echo('-> ' + name + ': ' + line) if self.webwxsendmsg(line, id): print ' [成功]' else: print ' [失败]' time.sleep(1) else: if self.webwxsendmsg(word, id): self._show_info('[*] 消息发送成功') else: self._show_info('[*] 消息发送失败') else: self._show_info('[*] 此用户不存在') def sendMsgToAll(self, word): for contact in self.ContactList: name = contact['RemarkName'] if contact[ 'RemarkName'] else contact['NickName'] id = contact['UserName'] self._echo('-> ' + name + ': ' + word) if self.webwxsendmsg(word, id): print ' [成功]' else: print ' [失败]' time.sleep(1) def sendImg(self, name, file_name): response = self.webwxuploadmedia(file_name) media_id = "" if response is not None: media_id = response['MediaId'] user_id = self.getUSerID(name) response = self.webwxsendmsgimg(user_id, media_id) def sendEmotion(self, name, file_name): response = self.webwxuploadmedia(file_name) media_id = "" if response is not None: media_id = response['MediaId'] user_id = self.getUSerID(name) response = self.webwxsendmsgemotion(user_id, media_id) ### action module end @catchKeyboardInterrupt def start(self): self._show_info('[*] 微信网页版 ... 开动') print while True: self._run('[*] 正在获取 uuid ... ', self.getUUID) self._echo('[*] 正在获取二维码 ... 成功') print self.genQRCode() print '[*] 请使用微信扫描二维码以登录 ... ' if not self.waitForLogin(): continue print '[*] 请在手机上点击确认以登录 ... ' if not self.waitForLogin(0): continue break self._run('[*] 正在登录 ... ', self.login) self._run('[*] 微信初始化 ... ', self.webwxinit) self._run('[*] 开启状态通知 ... ', self.webwxstatusnotify) self._run('[*] 获取联系人 ... ', self.webwxgetcontact) self._echo('[*] 应有 %s 个联系人,读取到联系人 %d 个' % (self.MemberCount, len(self.MemberList))) print self._echo('[*] 共有 %d 个群 | %d 个直接联系人 | %d 个特殊账号 | %d 公众号或服务号' % (len(self.GroupList), len(self.ContactList), len(self.SpecialUsersList), len(self.PublicUsersList))) print self._run('[*] 获取群 ... ', self.webwxbatchgetcontact) self._show_info('[*] 微信网页版 ... 开动') if self.interactive and raw_input('[*] 是否开启自动回复模式(y/n): ') == 'y': self.autoReplyMode = True self._show_info('[*] 自动回复模式 ... 开启') else: self._show_info('[*] 自动回复模式 ... 关闭') if self.interactive and raw_input('[*] 是否开启自动Debug模式(y/n): ') == 'y': self.DEBUG = True self._show_info('[*] Debug模式 ... 开启') else: self._show_info('[*] Debug模式 ... 关闭') if sys.platform.startswith('win'): import thread thread.start_new_thread(self.listenMsgMode()) else: listenProcess = multiprocessing.Process(target=self.listenMsgMode) listenProcess.start() while True: text = raw_input('') if text == 'quit': listenProcess.terminate() self._show_info('[*] 退出微信') exit() elif text[:2] == '->': [name, word] = text[2:].split('~:~') if name == 'all': self.sendMsgToAll(word) else: self.sendMsg(name, word) elif text[:3] == 'm->': [name, file] = text[3:].split('~:~') self.sendMsg(name, file, True) elif text[:3] == 'f->': self._show_info('发送文件') elif text[:3] == 'i->': [name, file_name] = text[3:].split('~:~') self.sendImg(name, file_name) self._show_info('发送图片') elif text[:3] == 'e->': [name, file_name] = text[3:].split('~:~') self.sendEmotion(name, file_name) self._show_info('发送表情') def _showMsg(self, message, type): srcName = None dstName = None groupName = None content = None msg = message #self._show_info(msg) self._show_info(type) if msg['raw_msg']: srcName = self.getUserRemarkName(msg['raw_msg']['FromUserName']) dstName = self.getUserRemarkName(msg['raw_msg']['ToUserName']) content = msg['raw_msg']['Content'].replace( '<', '<').replace('>', '>') message_id = msg['raw_msg']['MsgId'] if content.find('http://weixin.qq.com/cgi-bin/redirectforward?args=') != -1: # 地理位置消息 data = self._get(content) if data == '': return data.decode('gbk').encode('utf-8') pos = self._searchContent('title', data, 'xml') temp = self._get(content) if temp == '': return tree = html.fromstring(temp) url = tree.xpath('//html/body/div/img')[0].attrib['src'] for item in urlparse(url).query.split('&'): if item.split('=')[0] == 'center': loc = item.split('=')[-1:] content = '%s 发送了一个 位置消息 - 我在 [%s](%s) @ %s]' % ( srcName, pos, url, loc) if msg['raw_msg']['ToUserName'] == 'filehelper': # 文件传输助手 dstName = '文件传输助手' if msg['raw_msg']['FromUserName'][:2] == '@@': # 接收到来自群的消息 if re.search(":<br/>", content, re.IGNORECASE): [people, content] = content.split(':<br/>') groupName = srcName srcName = self.getUserRemarkName(people) dstName = 'GROUP' else: groupName = srcName srcName = 'SYSTEM' elif msg['raw_msg']['ToUserName'][:2] == '@@': # 自己发给群的消息 groupName = dstName dstName = 'GROUP' # 收到了红包 if content == '收到红包,请在手机上查看': msg['message'] = content # 指定了消息内容 if 'message' in msg.keys(): content = msg['message'] if groupName != None: print '%s |%s| %s -> %s: %s' % (message_id, groupName.strip(), srcName.strip(), dstName.strip(), content.replace('<br/>', '\n')) logging.info('%s |%s| %s -> %s: %s' % (message_id, groupName.strip(), srcName.strip(), dstName.strip(), content.replace('<br/>', '\n'))) else: print '%s %s -> %s: %s' % (message_id, srcName.strip(), dstName.strip(), content.replace('<br/>', '\n')) logging.info('%s %s -> %s: %s' % (message_id, srcName.strip(), dstName.strip(), content.replace('<br/>', '\n'))) def _save_log(self,info): dirName = 'saved/message/' if not os.path.exists(dirName): os.makedirs(dirName) fn = dirName + 'msg' + str(int(time.time())) + '.json' with open(fn, 'w') as f: f.write(json.dumps(info)) self._show_info('[*] 该消息已储存到文件: %s' % (fn)) def _saveFile(self, filename, data, api=None): fn = filename if self.saveSubFolders[api]: dirName = os.path.join(self.saveFolder, self.saveSubFolders[api]) if not os.path.exists(dirName): os.makedirs(dirName) fn = os.path.join(dirName, filename) self._show_info('Saved file: %s' % fn) with open(fn, 'wb') as f: f.write(data) f.close() return fn def _show_info(self,info): if self.DEBUG is True: logging.debug(info) else: print info def _safe_open(self, path): if self.autoOpen: if platform.system() == "Linux": os.system("xdg-open %s &" % path) else: os.system('open %s &' % path) def _run(self, str, func, *args): self._echo(str) if func(*args): self._show_info('%s... 成功' % (str)) else: self._show_info('%s... 失败' % (str)) self._show_info('[*] 退出程序') exit() def _echo(self, str): sys.stdout.write(str) sys.stdout.flush() def _printQR(self, mat): for i in mat: BLACK = '\033[40m \033[0m' WHITE = '\033[47m \033[0m' print ''.join([BLACK if j else WHITE for j in i]) def _str2qr(self, str): print(str) qr = qrcode.QRCode() qr.border = 1 qr.add_data(str) qr.make() # img = qr.make_image() # img.save("qrcode.png") #mat = qr.get_matrix() #self._printQR(mat) # qr.print_tty() or qr.print_ascii() qr.print_ascii(invert=True) def _transcoding(self, data): if not data: return data result = None if type(data) == unicode: result = data elif type(data) == str: result = data.decode('utf-8') return result def _get(self, url, api=None): request = urllib2.Request(url=url) request.add_header('Referer', 'https://wx.qq.com/') if api == 'webwxgetvoice': request.add_header('Range', 'bytes=0-') if api == 'webwxgetvideo': request.add_header('Range', 'bytes=0-') try: response = urllib2.urlopen(request) data = response.read() if self.DEBUG is True: self._show_info(url) return data except urllib2.HTTPError, e: logging.error('HTTPError = ' + str(e.code)) except urllib2.URLError, e: logging.error('URLError = ' + str(e.reason))