diff --git a/clients/http/MANIFEST.in b/clients/http/MANIFEST.in
deleted file mode 100644
index e228aeb..0000000
--- a/clients/http/MANIFEST.in
+++ /dev/null
@@ -1,2 +0,0 @@
-include wcferry/*.dll
-include wcferry/*.exe
diff --git a/clients/http/README.MD b/clients/http/README.MD
index c9d8684..f06d39a 100644
--- a/clients/http/README.MD
+++ b/clients/http/README.MD
@@ -1,32 +1,3 @@
-# WeChatFerry HTTP 客户端
-[](https://pypi.python.org/pypi/wcfhttp) [](https://pypi.python.org/pypi/wcfhttp) [](https://wechatferry.readthedocs.io/zh/latest/?badge=latest)
+# ~~WeChatFerry HTTP 客户端~~
-基于 [wcferry](https://pypi.org/project/wcferry/) 封装的 HTTP 客户端。
-
-## 快速开始
-### 安装
-```sh
-pip install --upgrade wcfhttp
-```
-
-### 运行
-```sh
-# 查看版本
-wcfhttp -v
-
-# 查看帮助
-wcfhttp -h
-
-# 忽略新消息运行
-wcfhttp
-
-# 新消息转发到指定地址
-wcfhttp --cb http://your_host:your_port/callback
-```
-
-### 接收消息回调接口文档
-参考文档(默认地址为:http://localhost:9999/docs )`接收消息回调样例`。
-
-|||
-|:-:|:-:|
-|后台回复 `WCF` 加群交流|如果你觉得有用|
+❗ **wcfhttp 不再维护,有需要可以使用 [WcfRust](https://github.com/lich0821/wcf-client-rust) 或者 [GoHttp](clients/gohttp/README.md)。**
diff --git a/clients/http/setup.py b/clients/http/setup.py
deleted file mode 100644
index f4e4771..0000000
--- a/clients/http/setup.py
+++ /dev/null
@@ -1,50 +0,0 @@
-#! /usr/bin/env python3
-# -*- coding: utf-8 -*-
-
-
-from __future__ import print_function
-from setuptools import setup, find_packages
-
-import wcfhttp
-
-with open("README.md", "r", encoding="utf-8") as fh:
- long_description = fh.read()
-
-
-setup(
- name="wcfhttp",
- version=wcfhttp.core.__version__,
- author="Changhua",
- author_email="lichanghua0821@gmail.com",
- description="一个玩微信的工具",
- long_description=long_description,
- long_description_content_type="text/markdown",
- license="MIT",
- url="https://github.com/lich0821/WeChatFerry",
- python_requires=">=3.8",
- packages=find_packages(),
- include_package_data=True,
- entry_points={
- 'console_scripts': [
- 'wcfhttp=wcfhttp.main:main'
- ]
- },
- install_requires=[
- "setuptools",
- "fastapi",
- "uvicorn[standard]",
- "wcferry>=39.0.10.0",
- ],
- classifiers=[
- "Environment :: Win32 (MS Windows)",
- "Intended Audience :: Developers",
- "Intended Audience :: Customer Service",
- "Topic :: Communications :: Chat",
- "Operating System :: Microsoft :: Windows",
- "Programming Language :: Python",
- ],
- project_urls={
- "Documentation": "https://wechatferry.readthedocs.io/zh/latest/index.html",
- "GitHub": "https://github.com/lich0821/WeChatFerry/",
- },
-)
diff --git a/clients/http/wcfhttp/__init__.py b/clients/http/wcfhttp/__init__.py
deleted file mode 100644
index c8795b3..0000000
--- a/clients/http/wcfhttp/__init__.py
+++ /dev/null
@@ -1,3 +0,0 @@
-# -*- coding: utf-8 -*-
-
-from wcfhttp.core import Http, __version__
\ No newline at end of file
diff --git a/clients/http/wcfhttp/core.py b/clients/http/wcfhttp/core.py
deleted file mode 100644
index b7dd7fb..0000000
--- a/clients/http/wcfhttp/core.py
+++ /dev/null
@@ -1,550 +0,0 @@
-#! /usr/bin/env python3
-# -*- coding: utf-8 -*-
-
-import base64
-import logging
-from queue import Empty
-from threading import Thread
-from typing import Any
-
-import requests
-from fastapi import Body, FastAPI, Query
-from pydantic import BaseModel
-from wcferry import Wcf, WxMsg
-
-__version__ = "39.0.10.0"
-
-
-class Msg(BaseModel):
- id: int
- ts: int
- sign: str
- type: int
- xml: str
- sender: str
- roomid: str
- content: str
- thumb: str
- extra: str
- is_at: bool
- is_self: bool
- is_group: bool
-
-
-class Http(FastAPI):
- """WeChatFerry HTTP 客户端,文档地址:http://IP:PORT/docs"""
-
- def __init__(self, wcf: Wcf, cb: str, **extra: Any) -> None:
- super().__init__(**extra)
- self.LOG = logging.getLogger(__name__)
- self.LOG.info(f"wcfhttp version: {__version__}")
- self.wcf = wcf
- self._set_cb(cb)
- self.add_api_route("/msg_cb", self.msg_cb, methods=["POST"], summary="接收消息回调样例", tags=["示例"])
-
- self.add_api_route("/login", self.is_login, methods=["GET"], summary="获取登录状态")
- self.add_api_route("/wxid", self.get_self_wxid, methods=["GET"], summary="获取登录账号 wxid")
- self.add_api_route("/user-info", self.get_user_info, methods=["GET"], summary="获取登录账号个人信息")
- self.add_api_route("/msg-types", self.get_msg_types, methods=["GET"], summary="获取消息类型")
- self.add_api_route("/contacts", self.get_contacts, methods=["GET"], summary="获取完整通讯录")
- self.add_api_route("/friends", self.get_friends, methods=["GET"], summary="获取好友列表")
- self.add_api_route("/dbs", self.get_dbs, methods=["GET"], summary="获取所有数据库")
- self.add_api_route("/{db}/tables", self.get_tables, methods=["GET"], summary="获取 db 中所有表")
- self.add_api_route("/pyq", self.refresh_pyq, methods=["GET"], summary="刷新朋友圈(数据从消息回调中查看)")
- self.add_api_route("/chatroom-member", self.get_chatroom_members, methods=["GET"], summary="获取群成员")
- self.add_api_route("/alias-in-chatroom", self.get_alias_in_chatroom, methods=["GET"], summary="获取群成员名片")
- self.add_api_route("/ocr-result", self.get_ocr_result, methods=["GET"], summary="获取 OCR 结果")
-
- self.add_api_route("/text", self.send_text, methods=["POST"], summary="发送文本消息")
- self.add_api_route("/image", self.send_image, methods=["POST"], summary="发送图片消息")
- self.add_api_route("/file", self.send_file, methods=["POST"], summary="发送文件消息")
- self.add_api_route("/rich-text", self.send_rich_text, methods=["POST"], summary="发送卡片消息")
- self.add_api_route("/pat", self.send_pat_msg, methods=["POST"], summary="发送拍一拍消息")
- # self.add_api_route("/xml", self.send_xml, methods=["POST"], summary="发送 XML 消息")
- # self.add_api_route("/emotion", self.send_emotion, methods=["POST"], summary="发送表情消息")
- self.add_api_route("/sql", self.query_sql, methods=["POST"], summary="执行 SQL,如果数据量大注意分页,以免 OOM")
- self.add_api_route("/new-friend", self.accept_new_friend, methods=["POST"], summary="通过好友申请")
- self.add_api_route("/chatroom-member", self.add_chatroom_members, methods=["POST"], summary="添加群成员")
- self.add_api_route("/cr-members", self.invite_chatroom_members, methods=["POST"], summary="邀请群成员")
- self.add_api_route("/transfer", self.receive_transfer, methods=["POST"], summary="接收转账")
- self.add_api_route("/dec-image", self.decrypt_image, methods=["POST"], summary="(废弃)解密图片")
- self.add_api_route("/attachment", self.download_attachment, methods=["POST"], summary="(废弃)下载图片、文件和视频")
- self.add_api_route("/save-image", self.download_image, methods=["POST"], summary="下载图片")
- self.add_api_route("/save-audio", self.get_audio_msg, methods=["POST"], summary="保存语音")
-
- self.add_api_route("/chatroom-member", self.del_chatroom_members, methods=["DELETE"], summary="删除群成员")
-
- def _forward_msg(self, msg: WxMsg, cb: str):
- data = {}
- data["id"] = msg.id
- data["ts"] = msg.ts
- data["sign"] = msg.sign
- data["type"] = msg.type
- data["xml"] = msg.xml
- data["sender"] = msg.sender
- data["roomid"] = msg.roomid
- data["content"] = msg.content
- data["thumb"] = msg.thumb
- data["extra"] = msg.extra
- data["is_at"] = msg.is_at(self.wcf.self_wxid)
- data["is_self"] = msg.from_self()
- data["is_group"] = msg.from_group()
-
- try:
- rsp = requests.post(url=cb, json=data, timeout=30)
- if rsp.status_code != 200:
- self.LOG.error(f"消息转发失败,HTTP 状态码为: {rsp.status_code}")
- except Exception as e:
- self.LOG.error(f"消息转发异常: {e}")
-
- def _set_cb(self, cb: str):
- def callback(wcf: Wcf):
- while wcf.is_receiving_msg():
- try:
- msg = wcf.get_msg()
- self.LOG.info(msg)
- self._forward_msg(msg, cb)
- except Empty:
- continue # Empty message
- except Exception as e:
- self.LOG.error(f"Receiving message error: {e}")
-
- if cb:
- self.LOG.info(f"消息回调: {cb}")
- self.wcf.enable_receiving_msg(pyq=True) # 同时允许接收朋友圈消息
- Thread(target=callback, name="GetMessage", args=(self.wcf,), daemon=True).start()
- else:
- self.LOG.info(f"没有设置回调,打印消息")
- self.wcf.enable_recv_msg(print)
-
- def is_login(self) -> dict:
- """获取登录状态"""
- ret = self.wcf.is_login()
- return {"status": 0, "message": "成功", "data": {"login": ret}}
-
- def get_self_wxid(self) -> dict:
- """获取登录账号 wxid"""
- ret = self.wcf.get_self_wxid()
- if ret:
- return {"status": 0, "message": "成功", "data": {"wxid": ret}}
- return {"status": -1, "message": "失败"}
-
- def get_msg_types(self) -> dict:
- """获取消息类型"""
- ret = self.wcf.get_msg_types()
- if ret:
- return {"status": 0, "message": "成功", "data": {"types": ret}}
- return {"status": -1, "message": "失败"}
-
- def get_contacts(self) -> dict:
- """获取完整通讯录"""
- ret = self.wcf.get_contacts()
- if ret:
- return {"status": 0, "message": "成功", "data": {"contacts": ret}}
- return {"status": -1, "message": "失败"}
-
- def get_friends(self) -> dict:
- """获取好友列表"""
- ret = self.wcf.get_friends()
- if ret:
- return {"status": 0, "message": "成功", "data": {"friends": ret}}
- return {"status": -1, "message": "失败"}
-
- def get_dbs(self) -> dict:
- """获取所有数据库"""
- ret = self.wcf.get_dbs()
- if ret:
- return {"status": 0, "message": "成功", "data": {"dbs": ret}}
- return {"status": -1, "message": "失败"}
-
- def get_tables(self, db: str) -> dict:
- """获取 db 中所有表
-
- Args:
- db (str): 数据库名(可通过 `get_dbs` 查询)
-
- Returns:
- List[dict]: `db` 下的所有表名及对应建表语句
- """
- ret = self.wcf.get_tables(db)
- if ret:
- return {"status": 0, "message": "成功", "data": {"tables": ret}}
- return {"status": -1, "message": "失败"}
-
- def get_user_info(self) -> dict:
- """获取登录账号个人信息"""
- ret = self.wcf.get_user_info()
- if ret:
- return {"status": 0, "message": "成功", "data": {"ui": ret}}
- return {"status": -1, "message": "失败"}
-
- def get_ocr_result(self, extra: str = Body("C:/...", description="消息中的 extra"),
- timeout: int = Body("30", description="超时时间(秒)")) -> dict:
- """获取 OCR 结果。鸡肋,需要图片能自动下载;通过下载接口下载的图片无法识别。
-
- Args:
- extra (str): 待识别的图片路径,消息里的 extra
-
- Returns:
- str: OCR 结果
- """
- ret = self.wcf.get_ocr_result(extra, timeout)
- if ret:
- return {"status": 0, "message": "成功", "data": {"ocr": ret}}
- return {"status": -1, "message": "可能失败,可以看看日志。这接口没啥用,别用了。"}
-
- def msg_cb(self, msg: Msg = Body(description="微信消息")):
- """示例回调方法,简单打印消息"""
- print(f"收到消息:{msg}")
- return {"status": 0, "message": "成功"}
-
- def send_text(
- self, msg: str = Body(description="要发送的消息,换行用\\n表示"),
- receiver: str = Body("filehelper", description="消息接收者,roomid 或者 wxid"),
- aters: str = Body("", description="要 @ 的 wxid,多个用逗号分隔;@所有人 用 notify@all")) -> dict:
- """发送文本消息,可参考:https://github.com/lich0821/WeChatRobot/blob/master/robot.py 里 sendTextMsg
-
- Args:
- msg (str): 要发送的消息,换行使用 `\\n`;如果 @ 人的话,需要带上跟 `aters` 里数量相同的 @
- receiver (str): 消息接收人,wxid 或者 roomid
- aters (str): 要 @ 的 wxid,多个用逗号分隔;`@所有人` 只需要 `notify@all`
-
- Returns:
- int: 0 为成功,其他失败
- """
- ret = self.wcf.send_text(msg, receiver, aters)
- return {"status": ret, "message": "成功"if ret == 0 else "失败"}
-
- def send_image(self,
- path: str = Body("C:\\Projs\\WeChatRobot\\TEQuant.jpeg", description="图片路径"),
- receiver: str = Body("filehelper", description="消息接收者,roomid 或者 wxid")) -> dict:
- """发送图片,非线程安全
-
- Args:
- path (str): 图片路径,如:`C:/Projs/WeChatRobot/TEQuant.jpeg` 或 `https://raw.githubusercontent.com/lich0821/WeChatRobot/master/TEQuant.jpeg`
- receiver (str): 消息接收人,wxid 或者 roomid
-
- Returns:
- int: 0 为成功,其他失败
- """
- ret = self.wcf.send_image(path, receiver)
- return {"status": ret, "message": "成功"if ret == 0 else "失败"}
-
- def send_file(self,
- path: str = Body("C:\\Projs\\WeChatRobot\\TEQuant.jpeg", description="本地文件路径,不支持网络路径"),
- receiver: str = Body("filehelper", description="roomid 或者 wxid")) -> dict:
- """发送文件
-
- Args:
- path (str): 本地文件路径,如:`C:/Projs/WeChatRobot/README.MD`
- receiver (str): 消息接收人,wxid 或者 roomid
-
- Returns:
- int: 0 为成功,其他失败
- """
- ret = self.wcf.send_file(path, receiver)
- return {"status": ret, "message": "成功"if ret == 0 else "失败"}
-
- def send_rich_text(
- self, name: str = Body("碲矿", description="左下显示的名字"),
- account: str = Body("gh_75dea2d6c71f", description="填公众号 id 可以显示对应的头像"),
- title: str = Body("【FAQ】WeChatFerry 机器人常见问题 v39.0.10", description="标题,最多两行"),
- digest: str = Body("先看再问,少走弯路。", description="最多三行,会占位"),
- url:
- str = Body(
- "http://mp.weixin.qq.com/s?__biz=MzI0MjI1OTk0OQ==&mid=2247487601&idx=1&sn=1bf7a0d1c659f8bc78a00cba18d7b204&chksm=e97e52f3de09dbe591fe23f335ce73bc468bd107a8c7bc5a458752a47f9d2d55a5fcdc5dd386&mpshare=1&scene=1&srcid=1209eP4EsXnynxyRQHzCK2bY&sharer_shareinfo=a12096ee76b4e3a9e72c9aedaf51a5ef&sharer_shareinfo_first=a12096ee76b4e3a9e72c9aedaf51a5ef#rd",
- description="点击后跳转的链接"),
- thumburl: str = Body("https://mmbiz.qpic.cn/mmbiz_jpg/XaSOeHibHicMGIiaZsBeYYjcuS2KfBGXfm8ibb9QrKJqk0H0W3JHia9icVica9nlWMiaD0xWmA0pKHpMOWbeBCJaAQc2IQ/0?wx_fmt=jpeg", description="缩略图的链接"),
- receiver: str = Body("filehelper", description="接收人, wxid 或者 roomid")) -> dict:
- """发送卡片消息
- 卡片样式(格式乱了,看这里:https://github.com/lich0821/WeChatFerry/blob/master/clients/python/wcferry/client.py#L421):
- |-------------------------------------|
- |title, 最长两行
- |(长标题, 标题短的话这行没有)
- |digest, 最多三行,会占位 |--------|
- |digest, 最多三行,会占位 |thumburl|
- |digest, 最多三行,会占位 |--------|
- |(account logo) name
- |-------------------------------------|
- Args:
- name (str): 左下显示的名字
- account (str): 填公众号 id 可以显示对应的头像(gh_ 开头的)
- title (str): 标题,最多两行
- digest (str): 摘要,三行
- url (str): 点击后跳转的链接
- thumburl (str): 缩略图的链接
- receiver (str): 接收人, wxid 或者 roomid
-
- Returns:
- int: 0 为成功,其他失败
- """
- ret = self.wcf.send_rich_text(name, account, title, digest, url, thumburl, receiver)
- return {"status": ret, "message": "成功"if ret == 0 else "失败,原因见日志"}
-
- def send_pat_msg(
- self, roomid: str = Body(description="要发送的消息,换行用\\n表示"),
- wxid: str = Body("filehelper", description="消息接收者,roomid 或者 wxid")) -> dict:
- """拍一拍群友
-
- Args:
- roomid (str): 群友所在群 roomid
- wxid (str): 要拍的群友的 wxid
-
- Returns:
- int: 1 为成功,其他失败
- """
- ret = self.wcf.send_pat_msg(roomid, wxid)
- return {"status": ret, "message": "成功"if ret == 1 else "失败,原因见日志"}
-
- def send_xml(
- self, receiver: str = Body("filehelper", description="roomid 或者 wxid"),
- xml:
- str = Body(
- '
![]() |
-![]() |
-
---|---|
后台回复 WeChatFerry 加群交流 |
-如果你觉得有用 | -