Files
gitlab-instance-0a899031_an…/app/main.py
hackrobot 7e6001bc1f update
2024-09-12 18:00:49 +08:00

438 lines
16 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.
from sqlite3 import IntegrityError
from fastapi import BackgroundTasks, FastAPI, HTTPException, Depends, Query
from fastapi.responses import JSONResponse, PlainTextResponse
from sqlalchemy.orm import Session
from typing import List, Optional, Any
from pydantic import BaseModel
from app import models, schemas, crud
from app.database import SessionLocal, engine
from fastapi.middleware.cors import CORSMiddleware
from PIL import Image
import qrcode
import os
from fastapi.responses import FileResponse
from fastapi.staticfiles import StaticFiles
# from app import tgMessage # type: ignore #发送tg消息
from datetime import datetime
import requests
# from tentcentSMS import sendSms
import random
from tencentcloud.common import credential
from tencentcloud.common.exception.tencent_cloud_sdk_exception import TencentCloudSDKException
from tencentcloud.sms.v20210111 import sms_client, models as smsmodels
from tencentcloud.common.profile.client_profile import ClientProfile
from tencentcloud.common.profile.http_profile import HttpProfile
import hashlib
from urllib.parse import urlencode, unquote
import time
# 初始化数据库
models.Base.metadata.create_all(bind=engine)
"""
JSAPI 支付
"""
key = "zA2hBU6pv6CIBzkW" # 填写通信密钥
mchid = "1561724891" # 特写商户号
# 构造签名函数
def sign(attributes):
attributes_new = {k: attributes[k] for k in sorted(attributes.keys())}
return (
hashlib.md5(
(unquote(urlencode(attributes_new)) + "&key=" + key).encode(
encoding="utf-8"
)
)
.hexdigest()
.upper()
)
class Item(BaseModel):
event: str
EventGroupMsg: None = None
prirobot_wxidce: None = None
type: None = None
# event
# "":"EventGroupMsg",//事件标示(当前值为群消息事件)
# "robot_wxid":"wxid_5hxa04j4z6pg22",//机器人wxid
# "robot_name":"",//机器人昵称,一般为空
# "type":1,//1/文本消息 3/图片消息 34/语音消息 42/名片消息 43/视频 47/动态表情 48/地理位置 49/分享链接 2000/转账 2001/红包 2002/小程序 2003/群邀请
# "from_wxid":"18900134932@chatroom",//群id群消息事件才有
# "from_name":"微群测",//群名字
# "final_from_wxid":"sundreamer",//发该消息的用户微信id
# "final_from_name":"遗忘悠剑o",//微信昵称
# "to_wxid":"wxid_5hxa04j4z6pg22",//接收消息的人id一般是机器人收到了也有可能是机器人发出的消息别人收到了那就是别人
# "msg":"图片https://b3logfile.com/bing/20201024.jpg",//消息内容(string/array) 使用时候根据不同的事件标示来定义这个值,字符串类型或者数据类型
# "money":0.01 //金额,只有"EventReceivedTransfer"事件才有该参数
app = FastAPI()
# 挂载 images 文件夹
app.mount("/images", StaticFiles(directory="images"), name="images")
# 允许所有来源跨域访问(不推荐用于生产环境)
origins = ["*"]
# 设置CORS跨域资源共享策略
app.add_middleware(
CORSMiddleware,
allow_origins=["*"], # 允许所有来源
allow_credentials=True,
allow_methods=["*"], # 允许所有方法
allow_headers=["*"], # 允许所有请求头
)
# 依赖注入
def get_db():
db = SessionLocal()
try:
yield db
finally:
db.close()
# @app.get("/")
# def root():
# return {"message": "Hello World"}
# phoneNum="+8613243889782"
def sendSms(phoneNum,verification_code=None):
try:
cred = credential.Credential("AKIDOaT6SZQ0JL7cqnTryoOhkW1FBqELAizz",
"kDPKyMTJs99sKVP1NREkzxKQFo66pIUP")
httpProfile = HttpProfile()
httpProfile.reqMethod = "POST" # post请求(默认为post请求)
httpProfile.reqTimeout = 30 # 请求超时时间,单位为秒(默认60秒)
httpProfile.endpoint = "sms.tencentcloudapi.com" # 指定接入地域域名(默认就近接入)
clientProfile = ClientProfile()
clientProfile.signMethod = "TC3-HMAC-SHA256" # 指定签名算法
clientProfile.language = "en-US"
clientProfile.httpProfile = httpProfile
client = sms_client.SmsClient(cred, "ap-beijing", clientProfile)
req = smsmodels.SendSmsRequest()
req.SmsSdkAppId = "1400808237"
req.SignName = "异度世界公众号"
req.TemplateId = "1795415" #验证码为:{1}, 若非本人操作,请忽略。
req.TemplateParamSet = [verification_code]
newphoneNum = '+86' + phoneNum
req.PhoneNumberSet = [newphoneNum]
req.SessionContext = ""
req.ExtendCode = ""
req.SenderId = ""
resp = client.SendSms(req)
print(resp.to_json_string(indent=2))
except TencentCloudSDKException as err:
print(err)
def sengTgmesage(message):
url = "http://192.168.31.38:8521/send_message"
data = {"message": message}
headers = {"Content-Type": "application/json"}
response = requests.post(url, json=data, headers=headers)
try:
response_data = response.json()
print(response_data)
except requests.exceptions.JSONDecodeError:
print("Response content is not in JSON format")
print("Response content:", response.text)
@app.get("/hello")
def hello():
# response = f"你好,\n..........................\n一名开发者\n副业:跨境电商\n#公众号:异度世界\n..........................\n回复关键词,了解更多:\n1. 微信机器人\n2. 数字游民\n3. 加群\n..........................\n[该消息是接受好友自动回复]"
response = f"你好,\n..........................\n一名开发者\n副业:跨境电商\n#公众号:异度世界\n..........................\n回复关键词,了解更多:\n1. 数字游民\n..........................\n[该消息是接受好友自动回复]"
return PlainTextResponse(content=response)
@app.post("/payh5")
async def payh5(item: dict):
print('item', item)
# 时间戳
timenew = str(int(time.time()))
order = {
"mchid": mchid,
"body": timenew, # 订单标题
"out_trade_no": timenew, # 订单号
"total_fee":item['total_fee'], # 金额,单位:分
# "openid": "o7LFAwWu3OhSrs49-1x5cSlFm0D8", # 通过openid接口获取到的openid
# "notify_url": ""
# "callback_url":'https://aiimg.hackrobot.cn/api'
}
order["callback_url"] =item['callback_url']
order["openid"] =item['openid']
order["sign"] = sign(order)
request_url = "https://payjs.cn/api/jsapi"
# 返回结果中包含`jsapi`字段该字段的值即是前端发起时所需的6个支付参数
headers = {"content-type": "application/x-www-form-urlencoded"}
response = requests.post(request_url, data=order, headers=headers)
if response:
print(response.json())
return response.json()
@app.get("/tgMessage")
def tgMessagefun(openid: Optional[str] = None, db: Session = Depends(get_db)):
current_time = datetime.now()
# 格式化日期和时间,不包含空格
formatted_now = current_time.strftime("%Y%m%d%H%M%S")
print("Current Date and Time:", formatted_now)
# 发送tg消息通知 wxid_4413224132412 || o7LFAwR32hWGq9XOpd7ZxK1wZxq8
# openid = "o7LFAwR32hWGq9XOpd7ZxK1wZxq8"
print('openid', openid)
if openid:
# 查询用户信息:昵称
data = read_user(openid, db=db)
# print('data==>', data)
userInfo = data['userInfo']
# print('userInfo==>', userInfo)
if userInfo:
# print('userInfo==>', userInfo)
# message = f"{userInfo['nickname']}/{userInfo['gender']}在{current_time}进行了访问"
message = f"{userInfo.nickname}/{userInfo.gender}{formatted_now}进行了访问"
print(message)
sengTgmesage(message)
# tgMessage.sendTg(message)
else:
print('openid未关联')
message = f'openid: {openid}-未关联,在{formatted_now}访问网页'
print(message)
sengTgmesage(message)
# tgMessage.sendTg(message)
def create_user_task(db: Session, user: schemas.UserCreate):
try:
existing_user = db.query(
models.User).filter(models.User.wxid == user.wxid).first()
if existing_user:
# 可以选择更新用户信息或返回错误
print("用户已存在create_user_task")
return "用户已存在"
else:
user = models.User(nickname=user.nickname,
remark=user.remark,
wechat_number=user.wechat_number,
wxid=user.wxid,
gender=user.gender,
friendaddtime=user.friendaddtime,
openid=user.openid)
db.add(user)
db.commit()
db.refresh(user)
except IntegrityError:
db.rollback()
print("IntegrityError")
return "IntegrityError"
# 生成二维码图片
def generateqr(url="http://nomad.hackrobot.cn",
wxid=None,
group_image_path="images/group.jpg"):
# url = "http://nomad.hackrobot.cn"
# url="http://192.168.31.219:10086"
if wxid:
url += f"?wxid={wxid}"
# 创建二维码
qr = qrcode.QRCode(version=1, box_size=5, border=2) # 调整二维码大小
qr.add_data(url)
qr.make(fit=True)
img = qr.make_image(fill='black', back_color='white')
# 保存二维码图像
qr_image_path = f"images/{wxid}-qr_code.png"
img.save(qr_image_path)
# 加载原图
# group_image_path = "images/group.jpg"
# 在原图上添加二维码(右下角)
group_image = Image.open(group_image_path)
qr_image = Image.open(qr_image_path)
# 将二维码放置在右下角
qr_image = qr_image.resize((200, 200)) # 调整二维码大小
qr_position = (group_image.width - qr_image.width - 50,
group_image.height - qr_image.height - 50) # 距离20像素
# 在原图上添加二维码
group_image.paste(qr_image, qr_position)
current_time = datetime.now()
# 格式化日期和时间,不包含空格
formatted_now = current_time.strftime("%Y%m%d%H%M%S")
# 保存合成的图像
# combined_image_path = f"images/combined_{wxid}_{datetime.now()}.jpg"
combined_image_path = f"images/combined_{wxid}_{formatted_now}.jpg"
group_image.save(combined_image_path)
# 压缩图片
group_image.save(combined_image_path, "JPEG",
quality=10) # 85 是压缩质量,可根据需要调整
# 删除二维码文件
os.remove(qr_image_path)
print(combined_image_path)
return combined_image_path
# return FileResponse(combined_image_path)
@app.get("/add")
def add_user(nickname: Optional[Any] = None,
remark: Optional[Any] = None,
wechat_number: Optional[Any] = None,
wxid: Optional[Any] = None,
gender: Optional[Any] = None,
friendaddtime: Optional[Any] = None,
openid: Optional[Any] = None,
keyword: Optional[Any] = None,
db: Session = Depends(get_db),
background_tasks: BackgroundTasks = None):
response = None
user_data = schemas.UserCreate(
nickname=nickname,
remark=remark,
wechat_number=wechat_number,
wxid=wxid,
gender=gender,
# friendaddtime=friendaddtime,
friendaddtime=str(datetime.now().strftime("%Y%m%d%H%M%S")),
openid=openid)
if background_tasks:
background_tasks.add_task(create_user_task, db, user_data)
# response = f"{nickname}你好,\n..........................\n一名开发者\n副业:跨境电商\n#公众号:异度世界\n..........................\n回复关键词,了解更多:\n1. 微信机器人\n2. 数字游民\n3. 加群\n..........................\n[该消息是接受好友自动回复]"
if gender=="":
response = f"{nickname}你好,\n..........................\n一名开发者\n副业:跨境电商\n#公众号:异度世界\n..........................\n个人主页:nomad.hackrobot.cn\n..........................\n[该消息是接受好友自动回复]"
else:
response = f"{nickname}你好,\n..........................\n一名开发者\n副业:跨境电商\n#公众号:异度世界\n..........................\n回复关键词:加群\n..........................\n[该消息是接受好友自动回复]"
# 关键词回复
if keyword == '加群' or keyword == "数字游民" or keyword == "3" or keyword == "1":
print("keyword==加群")
combined_image_path = generateqr(url="http://nomad.hackrobot.cn",
wxid=wxid,
group_image_path="images/nomadqr.jpg")
return FileResponse(combined_image_path)
elif keyword == '手册':
print("keyword==手册")
response = f"手册正在编写中"
combined_image_path = generateqr(url="http://nomad.hackrobot.cn",
wxid=wxid,
group_image_path="images/bookqr.jpg")
return FileResponse(combined_image_path)
elif keyword == '活动':
print("keyword==活动")
response = f"活动正在筹备中"
combined_image_path = generateqr(
url="http://nomad.hackrobot.cn",
wxid=wxid,
group_image_path="images/meetupqr.jpg")
return FileResponse(combined_image_path)
elif keyword == 'qrcode':
print("keyword==qrcode")
combined_image_path = generateqr(
url="http://nomad.hackrobot.cn",
# wxid='qrcode',
group_image_path="images/nomadqr.jpg")
return FileResponse(combined_image_path)
else:
print('其他keyword')
return PlainTextResponse(content=response)
@app.get("/users/")
def read_users(skip: int = 0, limit: int = 10, db: Session = Depends(get_db)):
return crud.get_users(db=db, skip=skip, limit=limit)
@app.get("/user/{identifier}")
def read_user(identifier: str, db: Session = Depends(get_db)):
user = crud.get_user_by_openid_or_wxid(db, identifier=identifier)
if user is None:
# raise HTTPException(status_code=404, detail="User not found")
print('查询用户不存在')
return {"code": '400', "userInfo": None}
# return user
return {"code": '200', "userInfo": user}
@app.delete("/user/{user_id}")
def delete_user(user_id: int, db: Session = Depends(get_db)):
user = crud.get_user(db=db, user_id=user_id)
if user is None:
raise HTTPException(status_code=404, detail="User not found")
return crud.delete_user(db=db, user=user)
@app.put("/user/{identifier}")
def update_user(identifier: str,
user_update: schemas.UserUpdate,
db: Session = Depends(get_db)):
user = crud.get_user_by_openid_or_wxid(db, identifier=identifier)
if user is None:
# raise HTTPException(status_code=404, detail="User not found")
# return user
return {"code": '400', "userInfo": None}
# return crud.update_user(db=db, user=user, user_update=user_update)
return {
"code": '200',
"userInfo": crud.update_user(db=db, user=user, user_update=user_update)
}
# 获取手机号=>生成验证码
@app.post("/get_verification_code/")
def get_verification_code(wxid: str,
phone_number: str,
db: Session = Depends(get_db)):
verification_code = '{:04d}'.format(random.randint(0, 9999))
user = db.query(models.User).filter(models.User.wxid == wxid).first()
if not user:
raise HTTPException(status_code=404, detail="User not found")
user.phone_number = phone_number
user.verification_code = verification_code
db.commit()
sendSms(phone_number)
return {
"message": "Verification code sent",
"verification_code": verification_code
}
# 验证码校验
@app.post("/verify_code/")
def verify_code(phone_number: str, code: str, db: Session = Depends(get_db)):
user = db.query(
models.User).filter(models.User.phone_number == phone_number).first()
if not user:
raise HTTPException(status_code=404, detail="User not found")
if user.verification_code == code:
return {"message": "Verification successful"}
else:
raise HTTPException(status_code=400,
detail="Invalid verification code")