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
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)
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.")
def __getWeiboPostDict(messageType, **args): postDict = { "uid": 5175429989, "st": getValue("weiboToken") } if messageType == "text": postDict["content"] = args["content"] return postDict
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)
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)))
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
async def chat(fromId, token=None, messageType="text", **args): if token is None: token = getValue("weiboToken") postDict = __getWeiboPostDict(messageType, **args) async with __chatLock: sendTimestamp = datetime.utcnow().timestamp() sendFlag = await __sendWeiboMessage(token, postDict) if sendFlag: responseMessages = await __getWeiboMessage(sendTimestamp) else: responseMessages = ["消息发送失败,请稍后重试~"] for index, message in enumerate(responseMessages): sendFlag = await sendWechatMessage(content=message, touser=fromId) if not sendFlag: generalLogger.warning("Network error, ignore the remaining {} message(s).".format( len(responseMessages)-index)) return generalLogger.debug( "Send {} message(s) successfully!".format(len(responseMessages)))