feat: beauty
This commit is contained in:
parent
fad57fcc5e
commit
b239d7b16d
72
skills/beauty/SKILL.md
Normal file
72
skills/beauty/SKILL.md
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
---
|
||||||
|
name: beauty
|
||||||
|
description: "当用户发送「999」时触发。调用美女图片接口获取图片链接,再调用本地微信机器人发图接口把图片发给当前用户。"
|
||||||
|
argument-hint: "无需参数,直接调用即可"
|
||||||
|
---
|
||||||
|
|
||||||
|
# Beauty Skill
|
||||||
|
|
||||||
|
## 描述
|
||||||
|
|
||||||
|
这是一个用于获取美女图片并直接发送给当前用户的技能。
|
||||||
|
|
||||||
|
当用户发送 `999` 时,调用外部接口获取图片链接,再调用本地微信机器人接口把图片发出去。
|
||||||
|
|
||||||
|
这个仓库里额外提供了一个可执行脚本 `beauty/scripts/beauty.py`,方便宿主机器人直接调用。
|
||||||
|
|
||||||
|
## 触发条件
|
||||||
|
|
||||||
|
- 用户发送 `999`
|
||||||
|
|
||||||
|
## 接口信息
|
||||||
|
|
||||||
|
- 获取图片地址:`https://api.pearktrue.cn/api/today_wife`
|
||||||
|
- 请求方式:`GET`
|
||||||
|
- 发图接口:`http://127.0.0.1:{ROBOT_WECHAT_CLIENT_PORT}/api/v1/robot/message/send/image/url`
|
||||||
|
- 请求方式:`POST`
|
||||||
|
- 本地脚本:`beauty/scripts/beauty.py`
|
||||||
|
- 获取图片返回示例:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"code": 200,
|
||||||
|
"msg": "获取成功",
|
||||||
|
"data": {
|
||||||
|
"image_url": "https://api.pearktrue.cn/api_assets/wife/9a6a9c38-7d6e-464f-8930-eb9dac41cde9.webp",
|
||||||
|
"role_name": "初音未来、巡音流歌",
|
||||||
|
"width": 2480,
|
||||||
|
"height": 3508
|
||||||
|
},
|
||||||
|
"api_source": "官方API网:https://api.pearktrue.cn/"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
- 关键字段:`data.image_url`,表示需要发送出去的图片链接。
|
||||||
|
|
||||||
|
## 环境变量
|
||||||
|
|
||||||
|
- `ROBOT_WECHAT_CLIENT_PORT`:本地微信机器人服务端口。
|
||||||
|
- `ROBOT_FROM_WX_ID`:当前消息来源用户的 wxid。
|
||||||
|
|
||||||
|
## 执行步骤
|
||||||
|
|
||||||
|
1. 当用户发送 `999` 时触发该技能。
|
||||||
|
2. 在仓库根目录下执行本地脚本:`python3 beauty/scripts/beauty.py`。
|
||||||
|
3. 脚本内部发送 `GET` 请求到 `https://api.pearktrue.cn/api/today_wife`。
|
||||||
|
4. 脚本解析返回的 JSON,并提取 `data.image_url`。
|
||||||
|
5. 脚本从环境变量中读取 `ROBOT_WECHAT_CLIENT_PORT` 和 `ROBOT_FROM_WX_ID`。
|
||||||
|
6. 脚本发送 `POST` 请求到 `http://127.0.0.1:{ROBOT_WECHAT_CLIENT_PORT}/api/v1/robot/message/send/image/url`,请求体为:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"to_wxid": "{ROBOT_FROM_WX_ID}",
|
||||||
|
"image_urls": ["image_url"]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
7. 如果任一步骤失败,回复兜底文案:`今天的美女图片暂时没拿到,等我再找找。`
|
||||||
|
|
||||||
|
## 回复要求
|
||||||
|
|
||||||
|
- 成功时,直接发送图片,不要额外追加解释文字。
|
||||||
|
- 失败时,使用固定兜底文案回复。
|
||||||
78
skills/beauty/scripts/beauty.py
Normal file
78
skills/beauty/scripts/beauty.py
Normal file
@ -0,0 +1,78 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
import json
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
import urllib.error
|
||||||
|
import urllib.request
|
||||||
|
|
||||||
|
|
||||||
|
FETCH_API_URL = "https://api.pearktrue.cn/api/today_wife"
|
||||||
|
FALLBACK_TEXT = "今天的美女图片暂时没拿到,等我再找找。"
|
||||||
|
|
||||||
|
|
||||||
|
def fetch_image_url() -> str | None:
|
||||||
|
try:
|
||||||
|
with urllib.request.urlopen(FETCH_API_URL, timeout=10) as response:
|
||||||
|
payload = json.load(response)
|
||||||
|
except (urllib.error.URLError, TimeoutError, json.JSONDecodeError):
|
||||||
|
return None
|
||||||
|
|
||||||
|
data = payload.get("data")
|
||||||
|
if not isinstance(data, dict):
|
||||||
|
return None
|
||||||
|
|
||||||
|
image_url = data.get("image_url")
|
||||||
|
if isinstance(image_url, str) and image_url.strip():
|
||||||
|
return image_url.strip()
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
def send_image(image_url: str) -> bool:
|
||||||
|
robot_port = os.environ.get("ROBOT_WECHAT_CLIENT_PORT", "").strip()
|
||||||
|
to_wxid = os.environ.get("ROBOT_FROM_WX_ID", "").strip()
|
||||||
|
if not robot_port or not to_wxid:
|
||||||
|
return False
|
||||||
|
|
||||||
|
api_url = (
|
||||||
|
f"http://127.0.0.1:{robot_port}/api/v1/robot/message/send/image/url"
|
||||||
|
)
|
||||||
|
body = json.dumps(
|
||||||
|
{
|
||||||
|
"to_wxid": to_wxid,
|
||||||
|
"image_urls": [image_url],
|
||||||
|
}
|
||||||
|
).encode("utf-8")
|
||||||
|
request = urllib.request.Request(
|
||||||
|
api_url,
|
||||||
|
data=body,
|
||||||
|
headers={"Content-Type": "application/json"},
|
||||||
|
method="POST",
|
||||||
|
)
|
||||||
|
|
||||||
|
try:
|
||||||
|
with urllib.request.urlopen(request, timeout=10) as response:
|
||||||
|
if 200 <= response.status < 300:
|
||||||
|
return True
|
||||||
|
payload = json.load(response)
|
||||||
|
except (urllib.error.URLError, TimeoutError, json.JSONDecodeError):
|
||||||
|
return False
|
||||||
|
|
||||||
|
code = payload.get("code")
|
||||||
|
return code == 200 or code == 0
|
||||||
|
|
||||||
|
|
||||||
|
def main() -> int:
|
||||||
|
image_url = fetch_image_url()
|
||||||
|
if image_url and send_image(image_url):
|
||||||
|
return 0
|
||||||
|
|
||||||
|
sys.stdout.write(FALLBACK_TEXT)
|
||||||
|
sys.stdout.write("\n")
|
||||||
|
return 0
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
raise SystemExit(main())
|
||||||
Loading…
Reference in New Issue
Block a user