diff --git a/api.json b/api.json index e8f4024..5937965 100644 --- a/api.json +++ b/api.json @@ -12,5 +12,31 @@ "phone_num": "{phone}", "area_code": "86" } + }, + { + "desc": "彩云小译", + "url": "https://biz.caiyunapp.com/v1/send_sms_code", + "method": "POST", + "header": { + "Referer": "https://fanyi.caiyunapp.com/", + "Cy-Token": "token 9876032166" + }, + "data": { + "phone_num": "{phone}", + "area_code": "86" + } + }, + { + "desc": "彩云小译", + "url": "https://biz.caiyunapp.com/v1/send_sms_code", + "method": "POST", + "header": { + "Referer": "https://fanyi.caiyunapp.com/", + "Cy-Token": "token 9876032166" + }, + "data": { + "phone_num": "{phone}", + "area_code": "86" + } } ] \ No newline at end of file diff --git a/apiback/api_back_2022_04_03_21_02_12.json b/apiback/api_back_2022_04_03_21_02_12.json new file mode 100644 index 0000000..2fae989 --- /dev/null +++ b/apiback/api_back_2022_04_03_21_02_12.json @@ -0,0 +1 @@ +[{"desc": "С", "url": "https://biz.caiyunapp.com/v1/send_sms_code", "method": "POST", "header": {"Referer": "https://fanyi.caiyunapp.com/", "Cookie": "UM_distinctid=17fd5c7a9ba69a-0200a7005bf45a-56171958-146d15-17fd5c7a9bb749; _gid=GA1.2.2046680529.1648971157; _gat_gtag_UA_185151443_2=1; _ga=GA1.2.44459633.1648559084; _ga_65TZCJSDBD=GS1.1.1648971156.4.1.1648971164.0; _ga_R9YPR75N68=GS1.1.1648971156.4.1.1648971164.52", "Cy-Token": "token 9876032166"}, "data": {"phone_num": "{phone}", "area_code": "86"}}, {"desc": "С", "url": "https://biz.caiyunapp.com/v1/send_sms_code", "method": "POST", "header": {"Referer": "https://fanyi.caiyunapp.com/", "Cy-Token": "token 9876032166"}, "data": {"phone_num": "{phone}", "area_code": "86"}}, {"desc": "С", "url": "https://biz.caiyunapp.com/v1/send_sms_code", "method": "POST", "header": {"Referer": "https://fanyi.caiyunapp.com/", "Cy-Token": "token 9876032166"}, "data": {"phone_num": "{phone}", "area_code": "86"}}] \ No newline at end of file diff --git a/flask_app/README.md b/flask_app/README.md new file mode 100644 index 0000000..8f6235b --- /dev/null +++ b/flask_app/README.md @@ -0,0 +1,3 @@ +# Flask APP For SMSBoom + +用于添加测试更改短信接口的 Flask 项目,方便短信接口的维护. \ No newline at end of file diff --git a/flask_app/__pycache__/utils.cpython-38.pyc b/flask_app/__pycache__/utils.cpython-38.pyc new file mode 100644 index 0000000..38f49c5 Binary files /dev/null and b/flask_app/__pycache__/utils.cpython-38.pyc differ diff --git a/flask_app/app.py b/flask_app/app.py new file mode 100644 index 0000000..c0785bb --- /dev/null +++ b/flask_app/app.py @@ -0,0 +1,113 @@ +# encoding=utf8 +import json +import time +from flask import Flask, make_response, request, jsonify +from flask_cors import CORS +from urllib3 import disable_warnings + +from utils import * + +disable_warnings() + +app = Flask(__name__) +CORS(app, supports_credentials=True, resources="/*") # 跨域 + + +def request_parse(req_data: request) -> dict: + '''解析请求数据并以字典的形式返回''' + if req_data.method == 'POST': + data = req_data.form + + elif req_data.method == 'GET': + data = req_data.args + + return dict(data) + + +class BaseResponse(BaseModel): + """返回的响应""" + status: int = 0 # 状态码 0-->成功 1-->失败 + msg: str = "前端显示的简短信息" + data: Optional[str] + + @property + def resp(self): + '''BaseModel类型返回json''' + response = make_response( + json.dumps( + self.dict(), + ensure_ascii=False, + sort_keys=False + ), + ) + response.mimetype = 'application/json' + # 跨域设置 + response.headers['Access-Control-Allow-Origin'] = '*' + response.headers['Access-Control-Allow-Methods'] = 'OPTIONS,HEAD,GET,POST' + response.headers['Access-Control-Allow-Headers'] = 'x-requested-with' + return response + + +@app.route("/testapi/", methods=['POST']) +def testapi(): + brs = BaseResponse() + # 需要传入 json 数据 + try: + jsonData = request.get_json() + api = API(**jsonData) + phone = jsonData.get('phone') + if not phone: + raise ValueError("参数 phone 没有!") + try: + resp = test_resq(api, phone) + brs.status = 0 + brs.msg = f"请求成功!{resp}" + brs.data = resp.text + except Exception as why: + brs.status = 1 + brs.msg = f"请求失败:{why}" + except Exception as why: + brs.status = 1 + brs.msg = f"参数有误:{why}" + return brs.resp + + +@app.route("/submitapi/", methods=['POST']) +def submitapi(): + """提交API到json文件""" + # 需要传入 json 数据 + jsonData = request.get_json() + api = API(**jsonData) + data = json.loads(json_path.read_text(encoding='utf8')) + with open(json_path, mode="w", encoding="utf8") as j: + try: + data.append(api.dict()) + json.dump(data, j, ensure_ascii=False, sort_keys=False) + return BaseResponse(status=0, msg="写入成功!").resp + except Exception as why: + return BaseResponse(status=1, msg=f"写入失败!{why}").resp + + +@app.route("/backapi/", methods=['GET']) +def backjson(): + """备份json文件""" + try: + timeStruct = time.localtime(int(time.time())) + strTime = time.strftime("%Y_%m_%d_%H_%M_%S", timeStruct) + Path.mkdir(Path(json_path.parent, 'apiback', exist_ok=True)) + json_back_path = Path(json_path.parent, 'apiback', + f"api_back_{strTime}.json") + with open(json_back_path, mode="w") as j: + j_data = json.loads(json_path.read_text(encoding='utf8')) + json.dump(j_data, j, ensure_ascii=False, sort_keys=False) + return BaseResponse(status=0, msg="备份成功!").resp + except Exception as why: + return BaseResponse(status=1, msg=f"备份失败{why}").resp + +@app.route("/downloadapi/", methods=['GET']) +def downloadapi(): + """下载接口文件""" + return json_path.read_text(encoding='utf8') + + +app.run(host="0.0.0.0", port=1098, debug=True) diff --git a/flask_app/templates/admin.html b/flask_app/templates/admin.html new file mode 100644 index 0000000..5dea57a --- /dev/null +++ b/flask_app/templates/admin.html @@ -0,0 +1,205 @@ + + + + + + + + 短信轰炸接口调试工具. + + + + + + + + + + + + + +
+ + + + +
+ URL: + + + + +
+
+ + +
+ + +
+ + + + + +
+
+
+ Type:视频 + Type:图文 +
+
+
+
+ 文案: {{ resp.data.title }} +
+
+
+
+ 作者: {{ resp.data.author }} +
+
+
+
+ 音乐:(点击下载) +
+
+ + +
+ +
+
+ 点击图片即可下载! +
+
+ + 加载失败 + +
+ +
+
+
+
+
+
+
+ 视频链接: + (点击下载) +
+
+ +
+ +
+
+
+
+ +
+ +
+ +
+ +
+
+ + + + \ No newline at end of file diff --git a/flask_app/utils.py b/flask_app/utils.py new file mode 100644 index 0000000..845b83e --- /dev/null +++ b/flask_app/utils.py @@ -0,0 +1,86 @@ +# encoding=utf8 +from pathlib import Path +from loguru import logger +import sys +from pydantic import BaseModel, validator +from typing import Optional, Union +import httpx +from datetime import datetime +import json + +# logger config +logger.remove() +logger.add( + sink=sys.stdout, + format="{time:YYYY-MM-DD at HH:mm:ss} - {level} - {message}", + colorize=True, + backtrace=True +) + +json_path = Path(Path(__file__).parent.parent, "api.json") +if not json_path.exists(): + logger.error("Json file not exists in default directory!") + sys.exit(1) + +default_header = { + "User-Agent": "Mozilla/5.0 (Linux; U; Android 10; zh-cn; Mi 10 Build/QKQ1.191117.002) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/79.0.3945.147 Mobile Safari/537.36 XiaoMi/MiuiBrowser/13.5.40" +} + + +class API(BaseModel): + desc: str = "Default" + url: str + method: str = "GET" + header: Optional[Union[str, dict]] = default_header + data: Optional[Union[str, dict]] + + @validator('url') + def name_must_contain_space(cls, v: str): + """验证链接是否正确""" + if not v.startswith('https' or 'http'): + raise ValueError('url must startswith http(s)!') + return v + + def replace_data(self, content: Union[str, dict], phone) -> str: + if isinstance(content, dict): + for key, value in content.items(): + content[key] = value.replace("{phone}", phone).replace( + "{timestamp}", self.timestamp_new()) + else: + if isinstance(content, str): + content.replace("{phone}", phone).replace( + "{timestamp}", self.timestamp_new()) + return content + + def timestamp_new(self) -> str: + """返回整数字符串时间戳""" + return str(int(datetime.now().timestamp())) + + def handle_API(self, phone): + """ + :param API: one API basemodel + :return: API basemodel + """ + if self.method != "POST": + self.method = "GET" + self.data = self.replace_data(self.data, phone) + self.url = self.replace_data(self.url, phone) + if isinstance(self.header, str): + self.header = json.loads(self.header) + return self + + +def test_resq(api: API, phone) -> httpx.Response: + """测试 API 返回响应 + :param api: API model + :param phone: 手机号 + :return: httpx 请求对象. + """ + api = api.handle_API(phone) + with httpx.Client(headers=default_header, timeout=8) as client: + if not isinstance(api.data, dict): + client.request(method=api.method, headers=api.header, + url=api.url, data=api.data) + resp = client.request( + method=api.method, headers=api.header, url=api.url, json=api.data) + return resp diff --git a/smsboom.py b/smsboom.py index c114404..5a3856b 100644 --- a/smsboom.py +++ b/smsboom.py @@ -1,4 +1,4 @@ -# coding=utf-8 +# encoding=utf8 import httpx import json import sys @@ -79,8 +79,10 @@ def replace_data(content: Union[str, dict]) -> str: content[key] = value.replace("{phone}", phone).replace( "{timestamp}", timestamp_new()) else: - content.replace("{phone}", phone).replace( - "{timestamp}", timestamp_new()) + # fix: add str判断 + if isinstance(content, str): + content.replace("{phone}", phone).replace( + "{timestamp}", timestamp_new()) return content