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
Exemple #2
0
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
Exemple #3
0
    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)
Exemple #4
0
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)
Exemple #5
0
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())
Exemple #7
0
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()
Exemple #8
0
    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())
Exemple #9
0
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
Exemple #10
0
    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
Exemple #12
0
    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())
Exemple #14
0
    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