42 Commits

Author SHA1 Message Date
hackrobot
594bec0cb9 update 2024-07-21 14:43:10 +08:00
hackrobot
3ad4a2a58c update 2024-07-21 14:42:33 +08:00
hackrobot
1bdd3dbc19 update 2024-07-21 14:31:44 +08:00
hackrobot
1b6d488688 feat: 腾讯云sms接口 2024-07-21 13:56:54 +08:00
hackrobot
8e8fee9e2f update 2024-07-19 21:50:14 +08:00
hackrobot
92a2a496d7 update 2024-07-19 21:25:38 +08:00
hackrobot
18528febae fqfqef 2024-07-19 20:57:02 +08:00
hackrobot
f0b5cdbfb5 update 2024-07-18 11:19:17 +08:00
hackrobot
d264cc65ba update 2024-07-18 10:42:46 +08:00
hackrobot
73b7c3104d upate 2024-07-18 10:23:18 +08:00
hackrobot
d7c4cf1b5f tgmeasage 2024-07-18 09:49:33 +08:00
hackrobot
20ed342a9e upte 2024-07-17 23:36:00 +08:00
hackrobot
1aba12e54d update 2024-07-17 22:47:51 +08:00
hackrobot
1ad9dfc8da update 2024-07-17 22:44:57 +08:00
hackrobot
a2ed0966d0 update 2024-07-17 22:42:25 +08:00
hackrobot
e9d4a2642c update 2024-07-17 22:38:32 +08:00
hackrobot
ecf9b300d1 update 2024-07-17 22:22:27 +08:00
hackrobot
36091e7796 update 2024-07-17 19:29:51 +08:00
hackrobot
147ce255c0 后端添加tg通知 2024-07-16 19:19:20 +08:00
hackrobot
66fd29dd02 update 2024-07-16 12:04:39 +08:00
hackrobot
054689e158 update 2024-07-16 11:59:40 +08:00
hackrobot
8ef8418ff4 update 2024-07-16 07:53:56 +08:00
hackrobot
83edc822a2 update 2024-07-16 07:42:11 +08:00
hackrobot
371e0e21b6 update 2024-07-16 07:34:09 +08:00
hackrobot
abea0b82f4 修改字段 2024-07-16 07:21:22 +08:00
hackrobot
3782e53cdd update 2024-07-15 23:44:42 +08:00
hackrobot
d090b04b37 update 2024-07-15 23:40:55 +08:00
hackrobot
3db9a63aca update 2024-07-15 22:18:17 +08:00
hackrobot
f96930dcc8 update 2024-07-15 22:13:55 +08:00
hackrobot
ddad2bb1b2 update 2024-07-15 22:03:11 +08:00
hackrobot
6fa209518e update 2024-07-15 21:43:44 +08:00
hackrobot
306bc8c9ad update 2024-07-15 20:44:48 +08:00
hackrobot
b8857953b3 允许跨域 2024-07-15 20:39:16 +08:00
hackrobot
dc9a30e346 update 2024-07-15 20:25:28 +08:00
hackrobot
37e02ffc69 8700 2024-07-15 19:49:07 +08:00
hackrobot
e533d6b5fa 0.0.0.0 2024-07-15 19:41:38 +08:00
hackrobot
7f8d4f55f1 update 2024-07-15 19:36:57 +08:00
hackrobot
77a79360bc update 2024-07-15 18:53:26 +08:00
hackrobot
b50e370c85 'add' 2024-07-15 18:52:03 +08:00
hackrobot
7f9f3bbb49 update 2024-07-15 18:50:47 +08:00
hackrobot
585aa4b36e chore:修改端口 2024-07-15 18:46:26 +08:00
hackrobot
745a3df44e 'dev' 2024-07-15 18:43:15 +08:00
34 changed files with 617 additions and 0 deletions

0
app/__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.

Binary file not shown.

44
app/crud.py Normal file
View File

@@ -0,0 +1,44 @@
from sqlalchemy.orm import Session
from app import models, schemas
from sqlalchemy.exc import IntegrityError
from fastapi import HTTPException
def get_user(db: Session, user_id: int):
return db.query(models.User).filter(models.User.id == user_id).first()
def get_user_by_openid_or_wxid(db: Session, identifier: str):
return db.query(models.User).filter((models.User.openid == identifier) | (models.User.wxid == identifier)).first()
def get_users(db: Session, skip: int = 0, limit: int = 10):
return db.query(models.User).offset(skip).limit(limit).all()
def create_user(db: Session, user: schemas.UserCreate):
db_user = models.User(**user.dict())
try:
db.add(db_user)
db.commit()
db.refresh(db_user)
except IntegrityError:
db.rollback()
# wxid的唯一性
raise HTTPException(status_code=400, detail="wxid must be unique")
return db_user
def delete_user(db: Session, user: models.User):
db.delete(user)
db.commit()
return user
# def update_user(db: Session, user: models.User, user_update: schemas.UserUpdate):
# for key, value in user_update.dict(exclude_unset=True).items():
# setattr(user, key, value)
# db.commit()
# db.refresh(user)
# return user
def update_user(db: Session, user: models.User, user_update: schemas.UserUpdate):
for var, value in vars(user_update).items():
if value is not None:
setattr(user, var, value)
db.commit()
db.refresh(user)
return user

11
app/database.py Normal file
View File

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

318
app/main.py Normal file
View File

@@ -0,0 +1,318 @@
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 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
# 初始化数据库
models.Base.metadata.create_all(bind=engine)
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"}
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.get("/tgMessage")
def tgMessagefun(openid: Optional[str] = None, db: Session = Depends(get_db)):
current_time = datetime.now()
print("Current Date and Time:", current_time)
# 发送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}{current_time}进行了访问"
print(message)
sengTgmesage(message)
# tgMessage.sendTg(message)
else:
print('openid未关联')
message = f'openid: {openid}-未关联,在{current_time}访问网页'
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)
# 保存合成的图像
# combined_image_path = f"images/combined_{wxid}_{datetime.now()}.jpg"
combined_image_path = f"images/combined_{wxid}_{datetime.date.today()}.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()),
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[该消息是接受好友自动回复]"
response = f"{nickname}你好,\n..........................\n一名开发者\n副业:跨境电商\n#公众号:异度世界\n..........................\n回复关键词,了解更多:\n1. 数字游民\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()
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")

64
app/models.py Normal file
View File

@@ -0,0 +1,64 @@
from sqlalchemy import Boolean, Column, Integer, String
from app.database import Base
import requests
from sqlalchemy.orm import Session
from sqlalchemy import event
from sqlalchemy.orm.attributes import get_history
class User(Base):
__tablename__ = "users"
id = Column(Integer, primary_key=True, index=True)
nickname = Column(String, index=True)
remark = Column(String)
wechat_number = Column(String)
wxid = Column(String, index=True, unique=True)
gender = Column(String)
friendaddtime = Column(String)
openid = Column(String, index=True)
ebook = Column(Boolean, default=False) # 新增电子书字段
activity_status = Column(String, default="0") # 新增活动报名字段
vip_member = Column(Boolean, default=False) # 新增VIP会员字段
verification_code = Column(String, index=True) # 新增验证码字段
phone_number = Column(String, index=True, unique=True) # 新增手机号字段
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)
def handle_change(mapper, connection, target):
"""监听器函数"""
if target.__class__.__name__ == 'User': # 确保只监听User类的变动
changed_fields = []
original_value=None
new_value=None
for attr in target.__mapper__.column_attrs:
history = get_history(target, attr.key)
if history.has_changes():
changed_fields.append(attr.key)
original_value = history.deleted[0] if history.deleted else None
new_value = history.added[0] if history.added else None
if changed_fields:
print(f"检测到用户 {target.nickname}-{target.remark} 的字段变化: {changed_fields}-{new_value}")
msg=f"检测到用户 {target.nickname}-{target.remark} 的字段变化: {changed_fields}-{new_value}"
sengTgmesage(msg)
# 发起HTTP请求
# requests.post("http://your-fastapi-endpoint/notify_change", json={"user_id": target.id, "changed_fields": changed_fields})
event.listen(User, "after_update", handle_change)

29
app/schemas.py Normal file
View File

@@ -0,0 +1,29 @@
from pydantic import BaseModel
from typing import Optional
class UserBase(BaseModel):
nickname: Optional[str] = None
remark: Optional[str] = None
wechat_number: Optional[str] = None
wxid: Optional[str] = None
gender: Optional[str] = None
friendaddtime: Optional[str] = None
openid: Optional[str] = None
ebook: Optional[bool] = None # 新增电子书字段
activity_status: Optional[str] = None # 新增活动报名字段
vip_member: Optional[bool] = None # 新增VIP会员字段
verification_code: Optional[bool] = None #新增验证码字段
class UserCreate(UserBase):
pass
class UserUpdate(UserBase):
pass
class User(UserBase):
id: int
class Config:
# orm_mode = True
from_attributes = True

124
app/tentcentSMS.py Normal file
View File

@@ -0,0 +1,124 @@
# -*- coding: utf-8 -*-
# pip install --upgrade tencentcloud-sdk-python
from tencentcloud.common import credential
from tencentcloud.common.exception.tencent_cloud_sdk_exception import TencentCloudSDKException
# 导入对应产品模块的client models。
from tencentcloud.sms.v20210111 import sms_client, models
# github地址 https://github.com/TencentCloud/tencentcloud-sdk-python
# pip install --upgrade tencentcloud-sdk-python
# 导入可选配置类
from tencentcloud.common.profile.client_profile import ClientProfile
from tencentcloud.common.profile.http_profile import HttpProfile
import random
# phoneNum="+8613243889782"
def sendSms(phoneNum,verification_code=None):
try:
# 必要步骤:
# 实例化一个认证对象入参需要传入腾讯云账户密钥对secretIdsecretKey。
# 这里采用的是从环境变量读取的方式,需要在环境变量中先设置这两个值。
# 你也可以直接在代码中写死密钥对,但是小心不要将代码复制、上传或者分享给他人,
# 以免泄露密钥对危及你的财产安全。
# SecretId、SecretKey 查询: https://console.cloud.tencent.com/cam/capi
cred = credential.Credential("AKIDOaT6SZQ0JL7cqnTryoOhkW1FBqELAizz",
"kDPKyMTJs99sKVP1NREkzxKQFo66pIUP")
# cred = credential.Credential(
# os.environ.get(""),
# os.environ.get("")
# )
# 实例化一个http选项可选的没有特殊需求可以跳过。
httpProfile = HttpProfile()
# 如果需要指定proxy访问接口可以按照如下方式初始化hp无需要直接忽略
# httpProfile = HttpProfile(proxy="http://用户名:密码@代理IP:代理端口")
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.language = "en-ZH"
clientProfile.httpProfile = httpProfile
# 实例化要请求产品(以sms为例)的client对象
# 第二个参数是地域信息可以直接填写字符串ap-guangzhou支持的地域列表参考 https://cloud.tencent.com/document/api/382/52071#.E5.9C.B0.E5.9F.9F.E5.88.97.E8.A1.A8
client = sms_client.SmsClient(cred, "ap-beijing", clientProfile)
# 实例化一个请求对象,根据调用的接口和实际情况,可以进一步设置请求参数
# 你可以直接查询SDK源码确定SendSmsRequest有哪些属性可以设置
# 属性可能是基本类型,也可能引用了另一个数据结构
# 推荐使用IDE进行开发可以方便的跳转查阅各个接口和数据结构的文档说明
req = models.SendSmsRequest()
# 基本类型的设置:
# SDK采用的是指针风格指定参数即使对于基本类型你也需要用指针来对参数赋值。
# SDK提供对基本类型的指针引用封装函数
# 帮助链接:
# 短信控制台: https://console.cloud.tencent.com/smsv2
# 腾讯云短信小助手: https://cloud.tencent.com/document/product/382/3773#.E6.8A.80.E6.9C.AF.E4.BA.A4.E6.B5.81
# 短信应用ID: 短信SdkAppId在 [短信控制台] 添加应用后生成的实际SdkAppId示例如1400006666
# 应用 ID 可前往 [短信控制台](https://console.cloud.tencent.com/smsv2/app-manage) 查看
req.SmsSdkAppId = "1400808237"
# 短信签名内容: 使用 UTF-8 编码,必须填写已审核通过的签名
# 签名信息可前往 [国内短信](https://console.cloud.tencent.com/smsv2/csms-sign) 或 [国际/港澳台短信](https://console.cloud.tencent.com/smsv2/isms-sign) 的签名管理查看
req.SignName = "异度世界公众号"
# 模板 ID: 必须填写已审核通过的模板 ID
# 模板 ID 可前往 [国内短信](https://console.cloud.tencent.com/smsv2/csms-template) 或 [国际/港澳台短信](https://console.cloud.tencent.com/smsv2/isms-template) 的正文模板管理查看
# req.TemplateId = "1976081" #口令3399将数字复制,发送到机器人(hackrobot),会自动加
req.TemplateId = "1795415" #验证码为:{1}, 若非本人操作,请忽略。
# 模板参数: 模板参数的个数需要与 TemplateId 对应模板的变量个数保持一致,,若无模板参数,则设置为空
# 随机4位数字
# verification_code = '{:04d}'.format(random.randint(0, 9999))
req.TemplateParamSet = [verification_code]
# 下发手机号码,采用 E.164 标准,+[国家或地区码][手机号]
# 示例如:+8613711112222 其中前面有一个+号 86为国家码13711112222为手机号最多不要超过200个手机号
newphoneNum = '+86' + phoneNum
req.PhoneNumberSet = [newphoneNum]
# 用户的 session 内容(无需要可忽略): 可以携带用户侧 ID 等上下文信息server 会原样返回
req.SessionContext = ""
# 短信码号扩展号(无需要可忽略): 默认未开通,如需开通请联系 [腾讯云短信小助手]
req.ExtendCode = ""
# 国内短信无需填写该项;国际/港澳台短信已申请独立 SenderId 需要填写该字段,默认使用公共 SenderId无需填写该字段。注月度使用量达到指定量级可申请独立 SenderId 使用,详情请联系 [腾讯云短信小助手](https://cloud.tencent.com/document/product/382/3773#.E6.8A.80.E6.9C.AF.E4.BA.A4.E6.B5.81)。
req.SenderId = ""
resp = client.SendSms(req)
# 输出json格式的字符串回包`
print(resp.to_json_string(indent=2))
# {
# "SendStatusSet": [
# {
# "SerialNo": "4412:418220390917215411841458978",
# "PhoneNumber": "+8613243889782",
# "Fee": 1,
# "SessionContext": "",
# "Code": "Ok",
# "Message": "send success",
# "IsoCode": "CN"
# }
# ],
# "RequestId": "5c23933c-df3d-4fd7-9445-1e5c7745492d"
# }
# 当出现以下错误码时,快速解决方案参考
# - [FailedOperation.SignatureIncorrectOrUnapproved](https://cloud.tencent.com/document/product/382/9558#.E7.9F.AD.E4.BF.A1.E5.8F.91.E9.80.81.E6.8F.90.E7.A4.BA.EF.BC.9Afailedoperation.signatureincorrectorunapproved-.E5.A6.82.E4.BD.95.E5.A4.84.E7.90.86.EF.BC.9F)
# - [FailedOperation.TemplateIncorrectOrUnapproved](https://cloud.tencent.com/document/product/382/9558#.E7.9F.AD.E4.BF.A1.E5.8F.91.E9.80.81.E6.8F.90.E7.A4.BA.EF.BC.9Afailedoperation.templateincorrectorunapproved-.E5.A6.82.E4.BD.95.E5.A4.84.E7.90.86.EF.BC.9F)
# - [UnauthorizedOperation.SmsSdkAppIdVerifyFail](https://cloud.tencent.com/document/product/382/9558#.E7.9F.AD.E4.BF.A1.E5.8F.91.E9.80.81.E6.8F.90.E7.A4.BA.EF.BC.9Aunauthorizedoperation.smssdkappidverifyfail-.E5.A6.82.E4.BD.95.E5.A4.84.E7.90.86.EF.BC.9F)
# - [UnsupportedOperation.ContainDomesticAndInternationalPhoneNumber](https://cloud.tencent.com/document/product/382/9558#.E7.9F.AD.E4.BF.A1.E5.8F.91.E9.80.81.E6.8F.90.E7.A4.BA.EF.BC.9Aunsupportedoperation.containdomesticandinternationalphonenumber-.E5.A6.82.E4.BD.95.E5.A4.84.E7.90.86.EF.BC.9F)
# - 更多错误,可咨询[腾讯云助手](https://tccc.qcloud.com/web/im/index.html#/chat?webAppId=8fa15978f85cb41f7e2ea36920cb3ae1&title=Sms)
except TencentCloudSDKException as err:
print(err)
sendSms('13243889782')

16
app/tgMessage.py Normal file
View File

@@ -0,0 +1,16 @@
import time
import requests
# bot发消息到tg群组
def sendTg(message):
baseUrl="https://api.telegram.org/bot"
toekn="558659722:AAENA3v8gKq7R7_nsr8V58Iu-_Z6BWx2SCw"
chat_id="-861577609"
text=message
url=f'{baseUrl}{toekn}/sendMessage?chat_id={chat_id}&text={text}'
try:
r = requests.get(url)
except:
print('请检查网络代理')
# https://api.telegram.org/bot558659722:AAENA3v8gKq7R7_nsr8V58Iu-_Z6BWx2SCw/sendMessage?chat_id=-861577609&text=1234

BIN
images/111.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 75 KiB

BIN
images/bookqr.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 105 KiB

BIN
images/combined_.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 137 KiB

BIN
images/combined_222.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 138 KiB

BIN
images/combined_None.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 57 KiB

BIN
images/combined_qrcode.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 56 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 56 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 611 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 58 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 140 KiB

BIN
images/group.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 104 KiB

BIN
images/group2.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 324 KiB

BIN
images/meetupqr.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 106 KiB

BIN
images/nomadqr.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 102 KiB

4
requirements.txt Normal file
View File

@@ -0,0 +1,4 @@
fastapi
uvicorn
sqlalchemy
pydantic

6
run.py Normal file
View File

@@ -0,0 +1,6 @@
import uvicorn
if __name__ == "__main__":
uvicorn.run("app.main:app", host="0.0.0.0", port=8700, reload=True)
# uvicorn.run("app.main:app", host="127.0.0.1", port=8700, reload=True)

1
run.sh Normal file
View File

@@ -0,0 +1 @@
python3 run.py

BIN
test.db Normal file

Binary file not shown.