bb
Browse files
app.py
CHANGED
|
@@ -74,18 +74,20 @@ def get_wecom_token() -> str:
|
|
| 74 |
params={"corpid": WECOM_CORPID, "corpsecret": WECOM_SECRET},
|
| 75 |
timeout=10,
|
| 76 |
).json()
|
|
|
|
| 77 |
_wx_cache["token"] = r.get("access_token", "")
|
| 78 |
_wx_cache["expires"] = time.time() + r.get("expires_in", 7200)
|
| 79 |
return _wx_cache["token"]
|
| 80 |
|
| 81 |
def send_wecom_message(to_user: str, content: str):
|
| 82 |
token = get_wecom_token()
|
| 83 |
-
|
|
|
|
|
|
|
| 84 |
f"https://qyapi.weixin.qq.com/cgi-bin/message/send?access_token={token}",
|
| 85 |
-
json=
|
| 86 |
-
|
| 87 |
-
|
| 88 |
-
)
|
| 89 |
|
| 90 |
def decrypt_msg(encrypted: str) -> str:
|
| 91 |
aes_key = base64.b64decode(WECOM_AES_KEY + "=")
|
|
@@ -108,36 +110,62 @@ demo = gr.ChatInterface(
|
|
| 108 |
# โโ ๆ่ฝฝไผไธๅพฎไฟก่ทฏ็ฑๅฐ Gradio ๅ
็ฝฎ FastAPI app โโโโโโโโโโโโโโโโ
|
| 109 |
@demo.app.get("/gateway/wecom")
|
| 110 |
async def wecom_verify(request: Request):
|
|
|
|
|
|
|
| 111 |
try:
|
| 112 |
-
p = request.query_params
|
| 113 |
sig = verify_sig(p.get("timestamp",""), p.get("nonce",""), p.get("echostr",""))
|
| 114 |
-
|
|
|
|
|
|
|
| 115 |
return PlainTextResponse("")
|
| 116 |
-
|
| 117 |
-
|
|
|
|
|
|
|
|
|
|
| 118 |
return PlainTextResponse("")
|
| 119 |
|
| 120 |
@demo.app.post("/gateway/wecom")
|
| 121 |
async def wecom_message(request: Request):
|
|
|
|
|
|
|
| 122 |
try:
|
| 123 |
-
p = request.query_params
|
| 124 |
body = await request.body()
|
|
|
|
| 125 |
encrypt = ET.fromstring(body.decode()).findtext("Encrypt", "")
|
| 126 |
sig = verify_sig(p.get("timestamp",""), p.get("nonce",""), encrypt)
|
| 127 |
-
|
|
|
|
|
|
|
| 128 |
return PlainTextResponse("success")
|
| 129 |
root = ET.fromstring(decrypt_msg(encrypt))
|
| 130 |
-
|
| 131 |
-
|
|
|
|
|
|
|
| 132 |
content = root.findtext("Content", "").strip()
|
|
|
|
| 133 |
if content:
|
| 134 |
def reply():
|
| 135 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 136 |
threading.Thread(target=reply, daemon=True).start()
|
| 137 |
-
except Exception:
|
| 138 |
-
|
| 139 |
return PlainTextResponse("success")
|
| 140 |
|
| 141 |
# โโ ๅฏๅจ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
| 142 |
if __name__ == "__main__":
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 143 |
demo.launch(server_name="0.0.0.0", server_port=7860)
|
|
|
|
| 74 |
params={"corpid": WECOM_CORPID, "corpsecret": WECOM_SECRET},
|
| 75 |
timeout=10,
|
| 76 |
).json()
|
| 77 |
+
log.info("[WECOM] get_token response: %s", r)
|
| 78 |
_wx_cache["token"] = r.get("access_token", "")
|
| 79 |
_wx_cache["expires"] = time.time() + r.get("expires_in", 7200)
|
| 80 |
return _wx_cache["token"]
|
| 81 |
|
| 82 |
def send_wecom_message(to_user: str, content: str):
|
| 83 |
token = get_wecom_token()
|
| 84 |
+
payload = {"touser": to_user, "msgtype": "text",
|
| 85 |
+
"agentid": int(WECOM_AGENTID), "text": {"content": content}}
|
| 86 |
+
r = httpx.post(
|
| 87 |
f"https://qyapi.weixin.qq.com/cgi-bin/message/send?access_token={token}",
|
| 88 |
+
json=payload, timeout=10,
|
| 89 |
+
).json()
|
| 90 |
+
log.info("[WECOM] send_message to=%s result=%s", to_user, r)
|
|
|
|
| 91 |
|
| 92 |
def decrypt_msg(encrypted: str) -> str:
|
| 93 |
aes_key = base64.b64decode(WECOM_AES_KEY + "=")
|
|
|
|
| 110 |
# โโ ๆ่ฝฝไผไธๅพฎไฟก่ทฏ็ฑๅฐ Gradio ๅ
็ฝฎ FastAPI app โโโโโโโโโโโโโโโโ
|
| 111 |
@demo.app.get("/gateway/wecom")
|
| 112 |
async def wecom_verify(request: Request):
|
| 113 |
+
p = request.query_params
|
| 114 |
+
log.info("[WECOM] GET verify params: %s", dict(p))
|
| 115 |
try:
|
|
|
|
| 116 |
sig = verify_sig(p.get("timestamp",""), p.get("nonce",""), p.get("echostr",""))
|
| 117 |
+
expected = p.get("msg_signature","")
|
| 118 |
+
log.info("[WECOM] verify sig=%s expected=%s match=%s", sig, expected, sig==expected)
|
| 119 |
+
if sig != expected:
|
| 120 |
return PlainTextResponse("")
|
| 121 |
+
plain = decrypt_msg(p.get("echostr",""))
|
| 122 |
+
log.info("[WECOM] verify ok, echostr plain=%s", plain)
|
| 123 |
+
return PlainTextResponse(plain)
|
| 124 |
+
except Exception as e:
|
| 125 |
+
log.exception("[WECOM] verify error: %s", e)
|
| 126 |
return PlainTextResponse("")
|
| 127 |
|
| 128 |
@demo.app.post("/gateway/wecom")
|
| 129 |
async def wecom_message(request: Request):
|
| 130 |
+
p = request.query_params
|
| 131 |
+
log.info("[WECOM] POST params: %s", dict(p))
|
| 132 |
try:
|
|
|
|
| 133 |
body = await request.body()
|
| 134 |
+
log.info("[WECOM] POST body: %s", body.decode())
|
| 135 |
encrypt = ET.fromstring(body.decode()).findtext("Encrypt", "")
|
| 136 |
sig = verify_sig(p.get("timestamp",""), p.get("nonce",""), encrypt)
|
| 137 |
+
expected = p.get("msg_signature","")
|
| 138 |
+
log.info("[WECOM] msg sig=%s expected=%s match=%s", sig, expected, sig==expected)
|
| 139 |
+
if sig != expected:
|
| 140 |
return PlainTextResponse("success")
|
| 141 |
root = ET.fromstring(decrypt_msg(encrypt))
|
| 142 |
+
msg_type = root.findtext("MsgType")
|
| 143 |
+
from_user = root.findtext("FromUserName", "")
|
| 144 |
+
log.info("[WECOM] msg_type=%s from=%s", msg_type, from_user)
|
| 145 |
+
if msg_type == "text":
|
| 146 |
content = root.findtext("Content", "").strip()
|
| 147 |
+
log.info("[WECOM] user=%s msg=%s", from_user, content)
|
| 148 |
if content:
|
| 149 |
def reply():
|
| 150 |
+
try:
|
| 151 |
+
answer = chat_with_hermes(content, [])
|
| 152 |
+
log.info("[WECOM] reply to=%s answer=%s", from_user, answer)
|
| 153 |
+
send_wecom_message(from_user, answer)
|
| 154 |
+
except Exception as e:
|
| 155 |
+
log.exception("[WECOM] reply error: %s", e)
|
| 156 |
threading.Thread(target=reply, daemon=True).start()
|
| 157 |
+
except Exception as e:
|
| 158 |
+
log.exception("[WECOM] message error: %s", e)
|
| 159 |
return PlainTextResponse("success")
|
| 160 |
|
| 161 |
# โโ ๅฏๅจ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
| 162 |
if __name__ == "__main__":
|
| 163 |
+
log.info("Starting Hermes Agent...")
|
| 164 |
+
log.info("WECOM_TOKEN set: %s", bool(WECOM_TOKEN))
|
| 165 |
+
log.info("WECOM_AES_KEY set: %s", bool(WECOM_AES_KEY))
|
| 166 |
+
log.info("WECOM_CORPID set: %s", bool(WECOM_CORPID))
|
| 167 |
+
log.info("WECOM_SECRET set: %s", bool(WECOM_SECRET))
|
| 168 |
+
log.info("NVIDIA_API_KEY set: %s", bool(NVIDIA_API_KEY))
|
| 169 |
+
routes = [r.path for r in demo.app.routes]
|
| 170 |
+
log.info("Registered routes: %s", routes)
|
| 171 |
demo.launch(server_name="0.0.0.0", server_port=7860)
|