feat: 将flask改造成fastapi

This commit is contained in:
hackrobot
2024-03-20 19:10:14 +08:00
parent 0cce9b9a2c
commit 9ec5ffc0f1
16 changed files with 430 additions and 1 deletions

View File

@@ -25,8 +25,8 @@ def hello():
return json.dumps({"Code": 0}) return json.dumps({"Code": 0})
# 发送小程序模版,建议远程更新
def sendminiProgram(data, account_wxid, wxid, msgXml): def sendminiProgram(data, account_wxid, wxid, msgXml):
# 发送小程序 # 发送小程序
if data.get('isSender') != 1: if data.get('isSender') != 1:
root = ET.fromstring(msgXml) #xml-字符串形式 root = ET.fromstring(msgXml) #xml-字符串形式
@@ -163,6 +163,10 @@ def kp(event_data):
xml_msg.get('encryptusername'), xml_msg.get('encryptusername'),
xml_msg.get('ticket'), xml_msg.get('ticket'),
xml_msg.get('scene')) xml_msg.get('scene'))
newFriendWxid=xml_msg.get('alias')
# 将好友信息=>保存到数据库
newFriendDict=WXBotService.get_friend_info(account_wxid, newFriendWxid)
elif msg_type == 42: # 42 名片消息 elif msg_type == 42: # 42 名片消息
xml_msg = ET.fromstring(msg) xml_msg = ET.fromstring(msg)
kp_log = f'{type_str} 企业微信名片消息 {xml_msg.get("nickname")}{xml_msg.get("username")}' kp_log = f'{type_str} 企业微信名片消息 {xml_msg.get("nickname")}{xml_msg.get("username")}'

0
__init__.py Normal file
View File

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
app.db Normal file

Binary file not shown.

41
crud.py Normal file
View File

@@ -0,0 +1,41 @@
from sqlalchemy.orm import Session
# from . import models, schemas
import models, schemas
# 通过id获取用户
def get_user(db: Session, user_id: int):
return db.query(models.User).filter(models.User.id == user_id).first()
# 通过openId岔村用户
def get_user_by_openId(db: Session, openId: str):
return db.query(models.User).filter(models.User.openId == openId).first()
# 分页查询-用户all
def get_users(db: Session, skip: int = 0, limit: int = 100):
return db.query(models.User).offset(skip).limit(limit).all()
# 创建用户
# user:schemas.UserCreate
def create_user(db: Session, user:schemas.UserCreate):
db_user = models.User(
wxid=user.wxid,
openId=user.openId,
sex=user.sex,
country=user.country,
province=user.province,
sourceStr=user.sourceStr,
usertype=user.usertype,
nickname=user.nickname,
wxaccount=user.wxaccount,
remark=user.remark,
smallhead=user.smallhead,
)
db.add(db_user)
db.commit()
db.refresh(db_user)
return db_user

13
database.py Normal file
View File

@@ -0,0 +1,13 @@
from sqlalchemy import create_engine
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker
SQLALCHEMY_DATABASE_URL = "sqlite:///./kunpeng.db"
# SQLALCHEMY_DATABASE_URL = "postgresql://user:password@postgresserver/db"
engine = create_engine(
SQLALCHEMY_DATABASE_URL, connect_args={"check_same_thread": False}
)
SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)
Base = declarative_base()

BIN
kunpeng.db Normal file

Binary file not shown.

321
main.py Normal file
View File

@@ -0,0 +1,321 @@
from fastapi import Depends, FastAPI, HTTPException
from sqlalchemy.orm import Session
# from . import crud, models, schemas
import crud, models, schemas
from database import SessionLocal, engine
# from .database import SessionLocal, engine
import json
import os
import threading
import time
from flask import request, Flask
try:
import xml.etree.cElementTree as ET
except ImportError:
import xml.etree.ElementTree as ET
import WXBotService
from planet import planetXml
from lxml import etree
import xml.dom.minidom
from pydantic import BaseModel
models.Base.metadata.create_all(bind=engine)
app = FastAPI()
# Dependency
def get_db():
db = SessionLocal()
try:
yield db
finally:
db.close()
# 默认首页
@app.get("/")
async def root():
return {"message": "Hello World"}
# 创建用户
@app.post("/users/")
# schemas.UserCreate决定了swagger文档
def create_user(user: schemas.UserCreate, db: Session = Depends(get_db)):
db_user = crud.create_user(db, user)
if db_user:
raise HTTPException(status_code=400,
detail="openId already registered")
return crud.create_user(db=db, user=user)
# 分页查询-用户
@app.get("/users/")
def read_users(skip: int = 0, limit: int = 100, db: Session = Depends(get_db)):
users = crud.get_users(db, skip=skip, limit=limit)
return users
# 根据openId查询用户
@app.get("/users/{openId}")
def read_user(openId, db: Session = Depends(get_db)):
db_user = crud.get_user_by_openId(db, openId=openId)
if db_user is None:
raise HTTPException(status_code=404, detail="User not found")
return db_user
@app.get("/wxbot")
def helloget(q:dict):
data = q
t = threading.Thread(target=kp, args=(data, )) # 通过当前线程开启新的线程去执行
t.start()
return json.dumps({"Code": 0})
@app.post("/wxbot")
# def hellopost(requestData:schemas.User):
def hellopost(requestData:dict):
# data = request.get_json()
print('requestData---',requestData)
data = requestData
t = threading.Thread(target=kp, args=(data, )) # 通过当前线程开启新的线程去执行
t.start()
return json.dumps({"Code": 0})
# 发送小程序模版,建议远程更新
def sendminiProgram(data, account_wxid, wxid, msgXml):
# 发送小程序
if data.get('isSender') != 1:
root = ET.fromstring(msgXml) #xml-字符串形式
#打开xml文档
# current_dir = os.path.dirname(os.path.abspath(__file__))
# print('current_dir+/planet.xml',current_dir+'\planet.xml')
# tree = ET.parse(current_dir+'\planet.xml')
# root = tree.getroot()
# 微信好友的wxid
# wxid='wxid_w2imh7ki5s4q12'
for pagepath in root.iter('pagepath'):
print(pagepath.text) # 打印名字
pagepath.text = pagepath.text + f'?wxid={wxid}'
print('修改path', pagepath.text) # 打印名字
# 修改后的xml转成string , method='xml'
msgXml = ET.tostring(root, encoding='utf-8').decode('utf-8')
WXBotService.send_xml_message(
account_wxid, wxid, msgXml
# account_wxid, "wxid_w2imh7ki5s4q12", planetXml
)
def kp(event_data):
# unicode [\\uxxxxx] 转 emoji 表情
event_data = json.loads(
WXBotService.unicode_to_emoji(
json.dumps(event_data, ensure_ascii=False), 'json'))
kp_log = '' # 定义鲲鹏日志消息
event_type = event_data.get('event_type') #事件类型
account_wxid = event_data.get('account_wxid') #机器人id
data = event_data.get('data')
msg_type = data.get('msgtype') #消息类型
msg = data.get('content')
to_wxid = data.get('to_wxid') #发送给
to_name = data.get('to_name')
filepath = data.get("filepath")
subtype = data.get('subtype') #类型
thumbpath = data.get('thumbpath') #图片,存在电脑绝对路径
wxid = data.get('final_from_wxid') #消息来源用户
wx_name = data.get('final_from_name')
group = None if data.get('from_wxid') == wxid else data.get('from_wxid')
group_name = None if data.get('from_name') == wx_name else data.get(
'from_name')
'''event类型判断'''
if event_type == 1001: # 1001 创建WeChat进程成功通讯连接成功
kp_log = f'创建WeChat进程成功通讯连接成功'
elif event_type == 1002: # 1002 登录成功
kp_log = f'登录成功 {data.get("nickname")}{data.get("wxid")}'
elif event_type == 1003: # 1003 账号注销登录
kp_log = f'账号注销登录 {data.get("wxid")} {data.get("reason")}'
elif event_type == 1004: # 1004 切换聊天对象事件
kp_log = f'切换聊天对象事件 {data.get("nickname")}{data.get("wxid")}'
elif event_type == 1005: # 1005 切换联系人事件
kp_log = f'切换联系人事件 {data.get("nickname")}{data.get("wxid")}'
elif event_type == 1007: # 1005 二维码刷新事件
kp_log = f'二维码刷新事件 {data.get("qrcode")}'
elif event_type == 1008: # 1008 连接断开
kp_log = f'连接断开'
elif event_type == 1009: # 1009 群员退群通知
member_list = []
for member in data.get('memberlist'):
member_list.append(
f'{member.get("nickname")}{member.get("wxid")}')
kp_log = f'群员退群通知 {"".join(member_list)} 退出了群聊 {data.get("roomname")}{data.get("roomid")} ' \
f'人数:{data.get("membercount")}'
elif event_type == 1010: # 1010 群员进群通知
member_list = []
for member in data.get('memberlist'):
member_list.append(
f'{member.get("nickName")}{member.get("userName")}')
kp_log = f'群员进群通知 {"".join(member_list)} 加入了群聊 {data.get("roomname")}{data.get("roomid")}'
elif event_type == 1011: # 1011 收款消息
pay_msg = ET.fromstring(msg).find('paymsg')
pay_msg_type = pay_msg.findtext('PayMsgType')
if pay_msg_type == '9': # 二维码收款
status = pay_msg.findtext('status')
username = pay_msg.findtext('username')
display_name = pay_msg.findtext('displayname')
fee = pay_msg.findtext('fee')
if status == '0':
kp_log = f'收款消息 {display_name}{username} 扫描收款二维码'
elif status == '1':
kp_log = f'收款消息 {display_name}{username} 付款成功 {int(fee) / 100}'
elif status == '2':
kp_log = f'收款消息 {display_name}{username} 取消付款'
elif pay_msg_type == '45': # 貌似有未收款转账或转账红包过期会触发 42 和 45 类型
pass # kp_log = f'收款消息 {pay_msg.findtext("fromusername")} {pay_msg.findtext("content")}'
elif event_type == 1040: # 1040 撤回消息事件
if not group:
kp_log = f'撤回消息事件 {wx_name}{wxid} 撤回了 {msg}'
else:
kp_log = f'撤回消息事件 {wx_name}{wxid} 从群 {group_name}{group} 撤回了 {msg}'
elif event_type == 1100: # 1100 同步消息
if group:
type_str = f'同步消息 群聊消息 群聊:{group_name}{group} 发送者:{wx_name}{wxid}'
elif 'gh_' in wxid:
type_str = f'同步消息 公众号消息 {wx_name}{wxid}'
elif '@openim' in wxid:
type_str = f'同步消息 企业微信消息 {wx_name}{wxid}'
else:
type_str = f'同步消息 私聊消息 {wx_name}{wxid}'
if data.get('isSender') == 1:
# 手机发送还是电脑发送这里判断不是很准确
if to_wxid == account_wxid:
type_str = f'机器人手机端 发送的 ' + type_str
else:
type_str = f'机器人电脑端 发送的 ' + type_str
if msg_type == 1: # 1 文本消息/自带表情
kp_log = f'{type_str} 文本消息 内容:{msg}'
elif msg_type == 3: # 3 图片消息
kp_log = f'{type_str} 图片消息 内容:{filepath}'
# 本地dat图片解密
decrypt_path = WXBotService.local_decrypt_image(
filepath, os.path.join(os.getcwd(), '解密图片'))
print(f'{type_str} 图片消息 解密路径:{decrypt_path}')
elif msg_type == 34: # 34 语言消息(需要在设置中打开语言自动转文字)
xml_msg = ET.fromstring(msg)
kp_log = f'{type_str} 语音消息 内容:{xml_msg.find("voicetrans").get("transtext")}'
elif msg_type == 37: # 37 好友请求
xml_msg = ET.fromstring(msg)
kp_log = f'同步消息 好友请求 {xml_msg.get("fromnickname")}{xml_msg.get("fromusername")} ' \
f'验证内容:{xml_msg.get("content")}'
# 同意好友请求
WXBotService.agree_friend_request(account_wxid,
xml_msg.get('alias'),
xml_msg.get('encryptusername'),
xml_msg.get('ticket'),
xml_msg.get('scene'))
newFriendWxid=xml_msg.get('alias')
# 将好友信息=>保存到数据库
newFriendDict=WXBotService.get_friend_info(account_wxid, newFriendWxid)
elif msg_type == 42: # 42 名片消息
xml_msg = ET.fromstring(msg)
kp_log = f'{type_str} 企业微信名片消息 {xml_msg.get("nickname")}{xml_msg.get("username")}'
elif msg_type == 43: # 43 视频消息
kp_log = f'{type_str} 视频消息 内容:{filepath}'
elif msg_type == 47: # 47 表情包
kp_log = f'{type_str} 表情包消息 网址:{ET.fromstring(msg).find("emoji").get("cdnurl".replace("amp;", ""))}'
# 本地下载图片
down_path = WXBotService.local_download_image(
msg, os.path.join(os.getcwd(), '下载图片'))
print(f'{type_str} 表情包消息 下载路径:{down_path}')
elif msg_type == 48: # 48 地理位置
kp_log = f'{type_str} 地理位置 内容:{msg}'
elif msg_type == 49: # 49 xml消息
# 获取根节点
root = ET.fromstring(msg)
xml_appmsg = root.find('appmsg')
xml_title = xml_appmsg.findtext('title')
xml_type = xml_appmsg.findtext('type')
xml_des = xml_appmsg.findtext('des')
xml_url = xml_appmsg.findtext('url')
if xml_type == '1': # 1 文本
kp_log = f'收到 {wxid} xml文本消息'
elif xml_type == '3': # 3 歌曲
kp_log = f'{type_str} 音乐消息 歌曲:{xml_title} 歌手:{xml_des} 网址:{xml_url}'
elif xml_type == '5': # 5 链接
kp_log = f'{type_str} 链接消息 标题:{xml_title} 内容:{xml_des} 网址:{xml_url}'
print("kp_log--------------------------------", msg)
# 本身也是系统消息-link,会无线循环
# 判断是不是自己发的消息
# if data.get('isSender') != 1:
# WXBotService.send_link_message(
# account_wxid, "wxid_w2imh7ki5s4q12", "title", "dec",
# "https://www.baidu.com",
# "https://p1-q.mafengwo.net/s17/M00/E3/9C/CoUBXl_cawCAQWMcAAGGhEoBcRU77.jpeg")
elif xml_type == '6': # 6 文件
kp_log = f'{type_str} 文件消息 文件名:{xml_title} 文件大小:{xml_des} 文件路径:{filepath}'
elif xml_type == '19': # 19 合并转发聊天记录
kp_log = f'{type_str} 合并转发聊天记录 文件名:{xml_title} 文件大小:{xml_des} 文件路径:{filepath}'
elif xml_type == '33': # 33 小程序
kp_log = f'{type_str} 小程序消息 小程序名:{xml_appmsg.findtext("sourcedisplayname")} 标题:{xml_title} ' \
f'appid{xml_appmsg.findtext("weappinfo/appid")} ' \
f'pagepath{xml_appmsg.findtext("weappinfo/pagepath")}'
print("---------------------------kp_log", msg)
# 发送小程序
sendminiProgram(data, account_wxid, wxid, planetXml)
elif xml_type == '57': # 引用消息
kp_log = f'{type_str} 引用消息 内容:{msg}'
elif xml_type == '2000': # 2000 转账消息
money = xml_appmsg.findtext('wcpayinfo/feedesc').replace(
'', '')
pay_subtype = xml_appmsg.findtext('wcpayinfo/paysubtype')
transfer_id = xml_appmsg.findtext('wcpayinfo/transferid')
if pay_subtype == '1':
kp_log = f'{type_str} 转账消息 {money}'
# 自动接收转账
WXBotService.transfer_receipt(account_wxid, wxid,
transfer_id)
elif pay_subtype == '3':
kp_log = f'{type_str} 已收款 {money} 元 转账'
elif msg_type == 66: # 66 企业微信名片消息
xml_msg = ET.fromstring(msg)
kp_log = f'企业微信名片消息 {xml_msg.get("nickname")}{xml_msg.get("username")}'
elif msg_type == 10000: # 10000 系统消息
kp_log = f'系统消息 {wx_name}{wxid} {msg}'
#获取通讯录
# allFriends=WXBotService.get_address_list(account_wxid)
# print('allFriends',allFriends)
# 发送H5链接
if not kp_log:
print(
'===================================================================================='
)
print(event_data)
print(
'===================================================================================='
)
else:
print(kp_log)

22
models.py Normal file
View File

@@ -0,0 +1,22 @@
from sqlalchemy import Boolean, Column, ForeignKey, Integer, String
from sqlalchemy.orm import relationship
from database import Base
# from .database import Base
class User(Base):
__tablename__ = "users"
id = Column(Integer, primary_key=True)
wxid = Column(String)
openId = Column(String)
sex = Column(String) #性别
country = Column(String) #"CN"
province = Column(String) #"Hubei"
sourceStr = Column(String) #:"通过朋友验证消息添加"
usertype = Column(String)
nickname = Column(String) #昵称
wxaccount = Column(String) #微信号
remark = Column(String) #备注
smallhead = Column(String) #头像

28
schemas.py Normal file
View File

@@ -0,0 +1,28 @@
from pydantic import BaseModel
# 用户信息
class UserCreate(BaseModel):
password: str
wxid: str
openId: str
sex: str
country: str
province: str
sourceStr: str
usertype: str
nickname: str
wxaccount: str
remark: str
smallhead: str
class User(UserCreate):
id: int
is_active: bool
class Config:
orm_mode = True