diff --git a/recv_sms.py b/recv_sms.py new file mode 100644 index 0000000..300db92 --- /dev/null +++ b/recv_sms.py @@ -0,0 +1,67 @@ +import re +from typing import List + +import redis +import uvicorn +from fastapi import FastAPI, HTTPException, status +from pydantic import BaseModel + +import config +from tools import utils + +app = FastAPI() + +redis_client = redis.Redis(host=config.REDIS_DB_HOST, password=config.REDIS_DB_PWD) + + +class SmsNotification(BaseModel): + platform: str + current_number: str + from_number: str + sms_content: str + timestamp: str + + +def extract_verification_code(message: str) -> str: + """ + Extract verification code of 6 digits from the SMS. + """ + pattern = re.compile(r'\b[0-9]{6}\b') + codes: List[str] = pattern.findall(message) + return codes[0] if codes else "" + + +@app.post("/") +def receive_sms_notification(sms: SmsNotification): + """ + Receive SMS notification and send it to Redis. + Args: + sms: + { + "platform": "xhs", + "from_number": "1069421xxx134", + "sms_content": "【小红书】您的验证码是: 171959, 3分钟内有效。请勿向他人泄漏。如非本人操作,可忽略本消息。", + "timestamp": "1686720601614", + "current_number": "13152442222" + } + + Returns: + + """ + utils.logger.info(f"Received SMS notification: {sms.platform}, {sms.current_number}") + sms_code = extract_verification_code(sms.sms_content) + if sms_code: + # Save the verification code in Redis and set the expiration time to 3 minutes. + key = f"{sms.platform}_{sms.current_number}" + redis_client.set(key, sms_code, ex=60 * 3) + + return {"status": "ok"} + + +@app.get("/", status_code=status.HTTP_404_NOT_FOUND) +async def not_found(): + raise HTTPException(status_code=404, detail="Not Found") + + +if __name__ == '__main__': + uvicorn.run(app, port=8000, host='0.0.0.0') \ No newline at end of file diff --git a/recv_sms_notification.py b/recv_sms_notification.py deleted file mode 100644 index 31aa9be..0000000 --- a/recv_sms_notification.py +++ /dev/null @@ -1,86 +0,0 @@ -# Start an HTTP server to receive SMS forwarding notifications and store them in Redis. -import asyncio -import json -import re -from typing import List - -import redis -import tornado.web - -import config - - -def extract_verification_code(message) -> str: - """ - Extract verification code of 6 digits from the SMS. - """ - pattern = re.compile(r'\b[0-9]{6}\b') - codes: List[str] = pattern.findall(message) - return codes[0] if codes and len(codes) > 0 else "" - - -class RecvSmsNotificationHandler(tornado.web.RequestHandler): - async def get(self): - self.set_status(404) - self.write("404") - - async def post(self): - # GitHub address for the SMS forwarding function:https://github.com/pppscn/SmsForwarder - # Document address::https://gitee.com/pp/SmsForwarder/wikis/pages?sort_id=6040999&doc_id=1821427 - # Forwarding channel definition: - # { - # "platform": "xhs", - # "current_number": "138xxxxxxxx", - # "from_number": "[from]", - # "sms_content": "[org_content]", - # "timestamp": "[timestamp]" - # } - - # SMS message body: - # { - # 'platform': 'xhs', # or dy - # 'current_number': '138xxxxxxxx', - # 'from_number': '1069421xxx134', - # 'sms_content': '【小红书】您的验证码是: 171959, 3分钟内有效。请勿向他人泄漏。如非本人操作,可忽略本消息。', - # 'timestamp': '1686720601614' - # } - request_body = self.request.body.decode("utf-8") - req_body_dict = json.loads(request_body) - print("recv sms notification and body content: ", req_body_dict) - redis_obj = redis.Redis(host=config.REDIS_DB_HOST, password=config.REDIS_DB_PWD) - sms_content = req_body_dict.get("sms_content") - sms_code = extract_verification_code(sms_content) - if sms_code: - # Save the verification code in Redis and set the expiration time to 3 minutes. - # Use Redis string data structure, in the following format: - # xhs_138xxxxxxxx -> 171959 - key = f"{req_body_dict.get('platform')}_{req_body_dict.get('current_number')}" - redis_obj.set(name=key, value=sms_code, ex=60 * 3) - self.set_status(200) - self.write("ok") - - -class Application(tornado.web.Application): - def __init__(self): - handlers = [(r'/', RecvSmsNotificationHandler)] - settings = dict( - gzip=True, - autoescape=None, - autoreload=True - ) - super(Application, self).__init__(handlers, **settings) - - -async def main(): - app = Application() - app.listen(port=9435) - print("Recv sms notification app running ...") - shutdown_event = tornado.locks.Event() - await shutdown_event.wait() - - -if __name__ == '__main__': - try: - asyncio.run(main()) - except KeyboardInterrupt: - pass diff --git a/requirements.txt b/requirements.txt index a607e2d..203c5b4 100644 --- a/requirements.txt +++ b/requirements.txt @@ -2,10 +2,10 @@ httpx==0.24.0 Pillow==9.5.0 playwright==1.42.0 tenacity==8.2.2 -tornado PyExecJS==1.5.1 -opencv-python==4.7.0.72 +opencv-python aiomysql==0.2.0 redis~=4.6.0 pydantic==2.5.2 aiofiles~=23.2.1 +fastapi==0.110.2