コード例 #1
0
ファイル: main.py プロジェクト: alchemist-clover/qyWechatBot
def start():
    options.parse_command_line()
    loadLogConfig()
    if not os.path.exists(dataBaseDir):
        os.mkdir(dataBaseDir)
    with syncDataBase(cacheFilePath) as dataBase:
        tableNames = dataBase.tableNames()
        if config["cacheTableName"] not in tableNames:
            dataBase.createTable(config["cacheTableName"], cacheTableStructure)
            for key in globalState:
                dataBase.insertRow(config["cacheTableName"], key, pickle.dumps(
                    globalState[key], pickle.HIGHEST_PROTOCOL))
            dataBase.insertRow(config["cacheTableName"], "pendingJobs",
                               pickle.dumps([], pickle.HIGHEST_PROTOCOL))
        else:
            cacheList = dataBase.queryTable("*", config["cacheTableName"])
            for key, value in cacheList:
                if key != "pendingJobs":
                    setValue(key, pickle.loads(value))
                else:
                    taskScheduler.addPendingJobs(pickle.loads(value))
    taskScheduler.start()
    httpServer.listen(config["botListenPort"])
    httpServer.start()
    generalLogger.info("wechatBot start successfully!")
コード例 #2
0
async def __getWeiboToken():
    getUrl = urljoin(weiboApiUrl, "list?uid=5175429989&count=10&unfollowing=0")
    tryCount = 0
    async with aiohttp.ClientSession() as session:
        while tryCount < config["maxTryCount"]:
            errorType = 0
            try:
                response = await session.get(getUrl, headers=weiboHeaders)
            except Exception as e:
                errorMessage = "Network connection error, will retry in two seconds, here is the error message:\n{}".format(
                    e)
                errorType = 1
            else:
                generalLogger.info("WeiboToken gotten!")
                oldWeiboToken = getValue("weiboToken")
                newWeiboToken = response.cookies["XSRF-TOKEN"].value
                setValue("weiboToken", newWeiboToken)
                weiboHeaders["X-XSRF-TOKEN"] = newWeiboToken
                weiboHeaders["Cookie"] = weiboHeaders["Cookie"].replace(
                    "XSRF-TOKEN=" + oldWeiboToken, "XSRF-TOKEN=" + newWeiboToken)
            finally:
                tryCount += 1
                if errorType == 0:
                    break
                else:
                    if tryCount != config["maxTryCount"]:
                        generalLogger.warning(errorMessage)
                        await asyncio.sleep(2)
                    else:
                        generalLogger.info(
                            "MaxTryCount has been reached, weiboToken cannot be gotten.")
コード例 #3
0
def __saveWechatMessage(postDict):
    pendingWechatMessages = getValue("pendingWechatMessages")
    if len(pendingWechatMessages) >= config["maxPendingWechatMessages"]:
        generalLogger.warning(
            "MaxPendingWechatMessages has been reached, ignoring this wechat message.")
    else:
        generalLogger.info(
            "WechatToken cannot be gotten temporarily, saved this wechat message until the token can be gotten.")
        pendingWechatMessages.append(postDict)
コード例 #4
0
 def get(self):
     msgSignature = self.get_query_argument("msg_signature", None)
     timestamp = self.get_query_argument("timestamp", None)
     nonce = self.get_query_argument("nonce", None)
     echoString = self.get_query_argument("echostr", None)
     responseString = verifyUrl(msgSignature, timestamp, nonce, echoString)
     if responseString is None:
         generalLogger.info("Input error, ignore this request.")
         self.set_status(200)
     else:
         generalLogger.info("Response successfully!")
         self.write(responseString)
コード例 #5
0
async def sendWechatMessage(token=None, messageType="text", tokenInvalidSaved=False, **args):
    if token is None:
        token = getValue("wechatToken")
    if not (tokenInvalidSaved or getValue("wechatTokenAvailable")):
        generalLogger.info(
            "WechatToken cannot be gotten and tokenInvalidSaved is false, so ignoring this wechat message.")
        return False
    postDict = __getWechatPostDict(messageType, **args)
    if not getValue("wechatTokenAvailable"):
        __saveWechatMessage(postDict)
        return False
    return await __sendWechatMessage(token, postDict, tokenInvalidSaved)
コード例 #6
0
async def __getWechatToken():
    getUrlParameters = "gettoken?corpid={}&corpsecret={}".format(
        config["corpId"], config["secret"])
    getUrl = urljoin(qywxApiUrl, getUrlParameters)
    tryCount = 0
    async with aiohttp.ClientSession() as session:
        while tryCount < config["maxTryCount"]:
            errorType = 0
            try:
                response = await session.get(getUrl)
            except Exception as e:
                errorMessage = "Network connection error, will retry in two seconds, here is the error message:\n{}".format(
                    e)
                errorType = 1
            else:
                responseDict = await response.json()
                if responseDict["errcode"] == 0:
                    generalLogger.info("WechatToken gotten!")
                    setValue("wechatToken", responseDict["access_token"])
                    setValue("wechatTokenAvailable", True)
                    pendingWechatMessages = getValue("pendingWechatMessages")
                    if pendingWechatMessages:
                        asyncio.gather(
                            *[__sendWechatMessage(responseDict["access_token"], postDict, True) for postDict in pendingWechatMessages])
                        setValue("pendingWechatMessages", [])
                elif responseDict["errcode"] == -1:
                    errorMessage = "Wechat api system busy, will retry in two seconds."
                    errorType = 1
                else:
                    generalLogger.warning("An unresolved error occurred, here is the error code: {}".format(
                        responseDict["errcode"]))
                    setValue("wechatTokenAvailable", False)
            finally:
                tryCount += 1
                if errorType == 0:
                    break
                else:
                    setValue("wechatTokenAvailable", False)
                    if tryCount != config["maxTryCount"]:
                        generalLogger.warning(errorMessage)
                        await asyncio.sleep(2)
                    else:
                        generalLogger.warning(
                            "MaxTryCount has been reached, will retry getting wechatToken in five minutes.")
                        await taskScheduler.addJob("getToken", __getWechatToken, description="Try to get token", triggerName="date", runDate=(datetime.utcnow() + timedelta(minutes=5)))
コード例 #7
0
async def __getWeiboMessage(sendTimestamp):
    getUrl = urljoin(weiboApiUrl, "list?uid=5175429989&count=10&unfollowing=0")
    tryCount = 0
    responseMessages = []
    await asyncio.sleep(1.5)
    async with aiohttp.ClientSession() as session:
        while tryCount < config["maxTryCount"]:
            errorType = 0
            try:
                response = await session.get(getUrl, headers=weiboHeaders)
            except Exception as e:
                errorMessage = "Network connection error, will retry in one second, here is the error message:\n{}".format(
                    e)
                errorType = 1
            else:
                responseDict = await response.json()
                for message in responseDict["data"]["msgs"]:
                    receiveTimestamp = datetime.strptime(
                        message["created_at"], "%a %b %d %H:%M:%S %z %Y").timestamp()
                    if receiveTimestamp < sendTimestamp:
                        break
                    elif message["sender_id"] == 5175429989:
                        if message["media_type"] == 0:
                            responseMessages.append(message["text"])
                        else:
                            responseMessages.append("暂不支持显示非文本类消息哦~")
                if responseMessages:
                    generalLogger.info("Weibo message(s) gotten!")
                else:
                    errorMessage = "Weibo message(s) cannot be gotten temporarily, will retry in one second."
                    errorType = 1
            finally:
                tryCount += 1
                if errorType == 0:
                    break
                else:
                    if tryCount != config["maxTryCount"]:
                        generalLogger.warning(errorMessage)
                        await asyncio.sleep(1)
                    else:
                        generalLogger.info(
                            "MaxTryCount has been reached, weibo message(s) failed to get.")
                        responseMessages.append("获取消息失败,请稍后重试~")
    responseMessages.reverse()
    return responseMessages
コード例 #8
0
 def post(self):
     msgSignature = self.get_query_argument("msg_signature", None)
     timestamp = self.get_query_argument("timestamp", None)
     nonce = self.get_query_argument("nonce", None)
     xmlText = decryptMsg(self.request.body.decode("utf-8"), msgSignature,
                          timestamp, nonce)
     if xmlText is not None:
         xmlTree = fromstring(xmlText)
         fromId = xmlTree.find("FromUserName").text
         messageType = xmlTree.find("MsgType").text
         generalLogger.info("Message parsed successfully!")
         if messageType == "text":
             callbackHandler.__ioLoop.add_callback(
                 chat, fromId, content=xmlTree.find("Content").text)
         else:
             callbackHandler.__ioLoop.add_callback(sendWechatMessage,
                                                   content="暂不支持非文本类消息哦~",
                                                   touser=fromId)
     else:
         generalLogger.debug("Input error, ignore this request.")
     self.set_status(200)
コード例 #9
0
async def __sendWechatMessage(token, postDict, tokenInvalidSaved):
    getUrl = urljoin(qywxApiUrl, "message", "send?access_token={}")
    tryCount = 0
    sendFlag = False
    async with aiohttp.ClientSession() as session:
        while tryCount < config["maxTryCount"]:
            errorType = 0
            try:
                response = await session.post(getUrl.format(token), json=postDict)
            except Exception as e:
                errorMessage = "Network connection error, will retry in two seconds, here is the error message:\n{}".format(
                    e)
                errorType = 1
            else:
                responseDict = await response.json()
                if responseDict["errcode"] == 0:
                    generalLogger.info("This wechat message has been sent!")
                    sendFlag = True
                elif responseDict["errcode"] == -1:
                    errorMessage = "Wechat api system busy, will retry in two seconds."
                    errorType = 1
                elif responseDict["errcode"] == 40014:
                    retry = False
                    async with __getWechatTokenLock:
                        if getValue("wechatTokenAvailable"):
                            if token == getValue("wechatToken"):
                                await __getWechatToken()
                                retry = getValue("wechatTokenAvailable")
                            else:
                                retry = True
                    if retry:
                        generalLogger.info(
                            "Retry sending the message with the new token.")
                        token = getValue("wechatToken")
                        errorType = 2
                    elif tokenInvalidSaved:
                        __saveWechatMessage(postDict)
                    else:
                        generalLogger.info(
                            "WechatToken cannot be gotten and tokenInvalidSaved is false, so ignoring this wechat message.")
                else:
                    generalLogger.warning("An unresolved error occurred, here is the error code: {}".format(
                        responseDict["errcode"]))
            finally:
                tryCount += 1
                if errorType == 0:
                    break
                elif errorType == 1:
                    if tryCount != config["maxTryCount"]:
                        generalLogger.warning(errorMessage)
                        await asyncio.sleep(2)
                    else:
                        generalLogger.warning(
                            "MaxTryCount has been reached, ignoring this wechat message.")
                else:
                    tryCount -= 1
    return sendFlag
コード例 #10
0
async def __sendWeiboMessage(token, postDict):
    getUrl = urljoin(weiboApiUrl, "send")
    tryCount = 0
    sendFlag = False
    async with aiohttp.ClientSession() as session:
        while tryCount < config["maxTryCount"]:
            errorType = 0
            try:
                response = await session.post(getUrl, headers=weiboHeaders, data=postDict)
            except Exception as e:
                errorMessage = "Network connection error, will retry in two seconds, here is the error message:\n{}".format(
                    e)
                errorType = 1
            else:
                responseDict = await response.json()
                if responseDict["ok"] == 1:
                    generalLogger.info("This weibo message has been sent!")
                    sendFlag = True
                elif responseDict["errno"] == "100006":
                    await __getWeiboToken()
                    if getValue("weiboToken") == token:
                        generalLogger.info(
                            "WeiboToken cannot be gotten, ignoring this weibo message.")
                    else:
                        generalLogger.info(
                            "Retry sending the message with the new token.")
                        errorType = 2
                else:
                    generalLogger.warning(
                        "An unresolved error occurred, here is the error number: {}".format(responseDict["errno"]))
            finally:
                tryCount += 1
                if errorType == 0:
                    break
                elif errorType == 1:
                    if tryCount != config["maxTryCount"]:
                        generalLogger.warning(errorMessage)
                        await asyncio.sleep(2)
                    else:
                        generalLogger.warning(
                            "MaxTryCount has been reached, ignoring this weibo message.")
                else:
                    tryCount -= 1
    return sendFlag