st/tp/scripts/beauty.py

132 lines
3.9 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/usr/bin/env python3
from __future__ import annotations
import io
import json
import os
import sys
import traceback
import urllib.error
import urllib.request
# 将 stdout 编码设置为 UTF-8
if hasattr(sys.stdout, "reconfigure"):
sys.stdout.reconfigure(encoding="utf-8")
else:
sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding="utf-8")
sys.stderr = sys.stdout
# 三个图片接口
API_LIST = [
{"name": "meinvpic", "url": "https://api.ust1.cc/api/meinvpic?return=302"},
{"name": "baisi", "url": "https://api.ust1.cc/api/baisi?return=302"},
{"name": "heisi", "url": "https://api.ust1.cc/api/heisi?return=302"},
]
DEFAULT_KEY = "14e655df72c1b429"
FALLBACK_TEXT = "今天的美女图片暂时没拿到,等我再找找。"
def get_key() -> str:
return os.environ.get("BEAUTY_KEY", "").strip() or DEFAULT_KEY
class NoRedirectHandler(urllib.request.HTTPRedirectHandler):
"""不跟随重定向,用于捕获 302 的 Location 头"""
def http_error_302(self, req, fp, code, msg, headers):
return fp
http_error_301 = http_error_302
http_error_303 = http_error_302
http_error_307 = http_error_302
def fetch_single_image(api: dict) -> str | None:
"""从单个接口获取图片地址通过302重定向的Location头"""
key = get_key()
try:
opener = urllib.request.build_opener(NoRedirectHandler())
req = urllib.request.Request(api["url"], headers={"key": key})
resp = opener.open(req, timeout=10)
location = resp.headers.get("Location")
if location:
return location.strip()
except urllib.error.HTTPError as e:
if e.code in (301, 302, 303, 307):
location = e.headers.get("Location")
if location:
return location.strip()
except (urllib.error.URLError, TimeoutError, OSError):
pass
return None
def fetch_all_images() -> list[str]:
"""从全部3个接口获取图片返回图片地址列表"""
urls = []
for api in API_LIST:
url = fetch_single_image(api)
if url:
urls.append(url)
return urls
def send_images(image_urls: list[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_urls,
}
).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=30) as response:
body_text = response.read().decode("utf-8", errors="replace")
if 200 <= response.status < 300:
# 200 也要检查返回体是否有错误
try:
result = json.loads(body_text)
code = result.get("code")
if code == 200 or code == 0:
return True
# 返回了200但code不对打印错误
sys.stdout.write(f"[debug] 发图接口返回异常: {body_text[:200]}\n")
return False
except (json.JSONDecodeError, AttributeError):
return True
except (urllib.error.URLError, TimeoutError, json.JSONDecodeError, OSError):
return False
return False
def main() -> int:
urls = fetch_all_images()
if len(urls) >= 2 and send_images(urls):
return 0
sys.stdout.write(FALLBACK_TEXT)
sys.stdout.write("\n")
return 0
if __name__ == "__main__":
try:
raise SystemExit(main())
except SystemExit:
raise
except Exception:
traceback.print_exc(file=sys.stdout)
raise SystemExit(1)