SubscribeAccount.py 9.1KB

пре 1 година
пре 1 година
пре 1 година
пре 1 година
пре 1 година
пре 1 година
пре 1 година
пре 1 година
пре 1 година
пре 1 година
пре 1 година
пре 1 година
пре 1 година
пре 1 година
пре 1 година
пре 1 година
пре 1 година
пре 1 година
пре 1 година
пре 1 година
пре 1 година
пре 1 година
пре 1 година
пре 1 година
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172
  1. import web
  2. import time
  3. import channel.wechatmp.reply as reply
  4. import channel.wechatmp.receive as receive
  5. from config import conf
  6. from common.log import logger
  7. from bridge.context import *
  8. from channel.wechatmp.common import *
  9. from channel.wechatmp.wechatmp_channel import WechatMPChannel
  10. # This class is instantiated once per query
  11. class Query():
  12. def GET(self):
  13. return verify_server(web.input())
  14. def POST(self):
  15. # Make sure to return the instance that first created, @singleton will do that.
  16. channel = WechatMPChannel()
  17. try:
  18. query_time = time.time()
  19. webData = web.data()
  20. logger.debug("[wechatmp] Receive request:\n" + webData.decode("utf-8"))
  21. wechatmp_msg = receive.parse_xml(webData)
  22. if wechatmp_msg.msg_type == 'text':
  23. from_user = wechatmp_msg.from_user_id
  24. to_user = wechatmp_msg.to_user_id
  25. message = wechatmp_msg.content.decode("utf-8")
  26. message_id = wechatmp_msg.msg_id
  27. logger.info("[wechatmp] {}:{} Receive post query {} {}: {}".format(web.ctx.env.get('REMOTE_ADDR'), web.ctx.env.get('REMOTE_PORT'), from_user, message_id, message))
  28. supported = True
  29. if "【收到不支持的消息类型,暂无法显示】" in message:
  30. supported = False # not supported, used to refresh
  31. cache_key = from_user
  32. reply_text = ""
  33. # New request
  34. if cache_key not in channel.cache_dict and cache_key not in channel.running:
  35. # The first query begin, reset the cache
  36. context = channel._compose_context(ContextType.TEXT, message, isgroup=False, msg=wechatmp_msg)
  37. logger.debug("[wechatmp] context: {} {}".format(context, wechatmp_msg))
  38. if message_id in channel.received_msgs: # received and finished
  39. # no return because of bandwords or other reasons
  40. return "success"
  41. if supported and context:
  42. # set private openai_api_key
  43. # if from_user is not changed in itchat, this can be placed at chat_channel
  44. user_data = conf().get_user_data(from_user)
  45. context['openai_api_key'] = user_data.get('openai_api_key') # None or user openai_api_key
  46. channel.received_msgs[message_id] = wechatmp_msg
  47. channel.running.add(cache_key)
  48. channel.produce(context)
  49. else:
  50. trigger_prefix = conf().get('single_chat_prefix',[''])[0]
  51. if trigger_prefix or not supported:
  52. if trigger_prefix:
  53. content = textwrap.dedent(f"""\
  54. 请输入'{trigger_prefix}'接你想说的话跟我说话。
  55. 例如:
  56. {trigger_prefix}你好,很高兴见到你。""")
  57. else:
  58. content = textwrap.dedent("""\
  59. 你好,很高兴见到你。
  60. 请跟我说话吧。""")
  61. else:
  62. logger.error(f"[wechatmp] unknown error")
  63. content = textwrap.dedent("""\
  64. 未知错误,请稍后再试""")
  65. replyMsg = reply.TextMsg(wechatmp_msg.from_user_id, wechatmp_msg.to_user_id, content)
  66. return replyMsg.send()
  67. channel.query1[cache_key] = False
  68. channel.query2[cache_key] = False
  69. channel.query3[cache_key] = False
  70. # User request again, and the answer is not ready
  71. elif cache_key in channel.running and channel.query1.get(cache_key) == True and channel.query2.get(cache_key) == True and channel.query3.get(cache_key) == True:
  72. channel.query1[cache_key] = False #To improve waiting experience, this can be set to True.
  73. channel.query2[cache_key] = False #To improve waiting experience, this can be set to True.
  74. channel.query3[cache_key] = False
  75. # User request again, and the answer is ready
  76. elif cache_key in channel.cache_dict:
  77. # Skip the waiting phase
  78. channel.query1[cache_key] = True
  79. channel.query2[cache_key] = True
  80. channel.query3[cache_key] = True
  81. assert not (cache_key in channel.cache_dict and cache_key in channel.running)
  82. if channel.query1.get(cache_key) == False:
  83. # The first query from wechat official server
  84. logger.debug("[wechatmp] query1 {}".format(cache_key))
  85. channel.query1[cache_key] = True
  86. cnt = 0
  87. while cache_key in channel.running and cnt < 45:
  88. cnt = cnt + 1
  89. time.sleep(0.1)
  90. if cnt == 45:
  91. # waiting for timeout (the POST query will be closed by wechat official server)
  92. time.sleep(1)
  93. # and do nothing
  94. return
  95. else:
  96. pass
  97. elif channel.query2.get(cache_key) == False:
  98. # The second query from wechat official server
  99. logger.debug("[wechatmp] query2 {}".format(cache_key))
  100. channel.query2[cache_key] = True
  101. cnt = 0
  102. while cache_key in channel.running and cnt < 45:
  103. cnt = cnt + 1
  104. time.sleep(0.1)
  105. if cnt == 45:
  106. # waiting for timeout (the POST query will be closed by wechat official server)
  107. time.sleep(1)
  108. # and do nothing
  109. return
  110. else:
  111. pass
  112. elif channel.query3.get(cache_key) == False:
  113. # The third query from wechat official server
  114. logger.debug("[wechatmp] query3 {}".format(cache_key))
  115. channel.query3[cache_key] = True
  116. cnt = 0
  117. while cache_key in channel.running and cnt < 40:
  118. cnt = cnt + 1
  119. time.sleep(0.1)
  120. if cnt == 40:
  121. # Have waiting for 3x5 seconds
  122. # return timeout message
  123. reply_text = "【正在思考中,回复任意文字尝试获取回复】"
  124. logger.info("[wechatmp] Three queries has finished For {}: {}".format(from_user, message_id))
  125. replyPost = reply.TextMsg(from_user, to_user, reply_text).send()
  126. return replyPost
  127. else:
  128. pass
  129. if cache_key not in channel.cache_dict and cache_key not in channel.running:
  130. # no return because of bandwords or other reasons
  131. return "success"
  132. # if float(time.time()) - float(query_time) > 4.8:
  133. # reply_text = "【正在思考中,回复任意文字尝试获取回复】"
  134. # logger.info("[wechatmp] Timeout for {} {}, return".format(from_user, message_id))
  135. # replyPost = reply.TextMsg(from_user, to_user, reply_text).send()
  136. # return replyPost
  137. if cache_key in channel.cache_dict:
  138. content = channel.cache_dict[cache_key]
  139. if len(content.encode('utf8'))<=MAX_UTF8_LEN:
  140. reply_text = channel.cache_dict[cache_key]
  141. channel.cache_dict.pop(cache_key)
  142. else:
  143. continue_text = "\n【未完待续,回复任意文字以继续】"
  144. splits = split_string_by_utf8_length(content, MAX_UTF8_LEN - len(continue_text.encode('utf-8')), max_split= 1)
  145. reply_text = splits[0] + continue_text
  146. channel.cache_dict[cache_key] = splits[1]
  147. logger.info("[wechatmp] {}:{} Do send {}".format(web.ctx.env.get('REMOTE_ADDR'), web.ctx.env.get('REMOTE_PORT'), reply_text))
  148. replyPost = reply.TextMsg(from_user, to_user, reply_text).send()
  149. return replyPost
  150. elif wechatmp_msg.msg_type == 'event':
  151. logger.info("[wechatmp] Event {} from {}".format(wechatmp_msg.content, wechatmp_msg.from_user_id))
  152. content = subscribe_msg()
  153. replyMsg = reply.TextMsg(wechatmp_msg.from_user_id, wechatmp_msg.to_user_id, content)
  154. return replyMsg.send()
  155. else:
  156. logger.info("暂且不处理")
  157. return "success"
  158. except Exception as exc:
  159. logger.exception(exc)
  160. return exc