forked from OpenEthan/SMSBoom
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
4 changed files
with
173 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
# SMSBoom (Remake) | ||
|
||
## Feature | ||
|
||
1. 通过自定义 `api.json` 的方式定义接口. | ||
api.json: | ||
|
||
```json | ||
[ | ||
{ | ||
"desc": "接口描述", | ||
"url": "请求地址", | ||
"method": "请求方法 GET(default)/POST", | ||
"ua": "请求UA 若为空则默认", | ||
"data": {} | ||
} | ||
] | ||
``` | ||
|
||
支持关键字替换.`{timestamp}` `{phone}` | ||
|
||
2. 多线程请求. | ||
3. 通过 Flask 提供网页测试/添加接口. | ||
4. 友好的命令行参数支持. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
[ | ||
{ | ||
"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" | ||
} | ||
} | ||
] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
httpx |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,132 @@ | ||
# coding=utf-8 | ||
import httpx | ||
import json | ||
import sys | ||
import pathlib | ||
import asyncio | ||
from loguru import logger | ||
from pydantic import BaseModel, validator | ||
from typing import Optional, List, Union | ||
from datetime import datetime | ||
from urllib3 import disable_warnings | ||
disable_warnings() | ||
|
||
# logger config | ||
logger.remove() | ||
logger.add( | ||
sink=sys.stdout, | ||
format="<green>{time:YYYY-MM-DD at HH:mm:ss}</green> - <level>{level}</level> - <level>{message}</level>", | ||
colorize=True, | ||
backtrace=True | ||
) | ||
|
||
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" | ||
} | ||
|
||
# current directory | ||
path = pathlib.Path(__file__).parent | ||
|
||
phone = "19820294268" | ||
|
||
|
||
class API(BaseModel): | ||
desc: str = "Default" | ||
url: str | ||
method: str = "GET" | ||
header: Optional[dict] | ||
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 load_json() -> List[API]: | ||
""" | ||
load json for api.json | ||
:return: api list | ||
""" | ||
json_path = pathlib.Path(path, 'api.json') | ||
if not json_path.exists(): | ||
logger.error("Json file not exists!") | ||
return None | ||
|
||
with open(json_path.resolve(), mode="r", encoding="utf8") as j: | ||
try: | ||
datas = json.loads(j.read()) | ||
APIs = [ | ||
API(**data) | ||
for data in datas | ||
] | ||
return APIs | ||
except Exception as why: | ||
logger.error(f"Json file syntax error:{why}") | ||
return None | ||
|
||
|
||
def timestamp_new() -> str: | ||
"""返回整数字符串时间戳""" | ||
return str(int(datetime.now().timestamp())) | ||
|
||
|
||
def replace_data(content: Union[str, dict]) -> str: | ||
if isinstance(content, dict): | ||
for key, value in content.items(): | ||
content[key] = value.replace("{phone}", phone).replace( | ||
"{timestamp}", timestamp_new()) | ||
else: | ||
content.replace("{phone}", phone).replace( | ||
"{timestamp}", timestamp_new()) | ||
return content | ||
|
||
|
||
def handle_API(API: API) -> API: | ||
""" | ||
:param API: one API basemodel | ||
:return: API basemodel | ||
""" | ||
if API.method != "POST": | ||
API.method = "GET" | ||
API.data = replace_data(API.data) | ||
API.url = replace_data(API.url) | ||
return API | ||
|
||
|
||
async def rqs(API: API): | ||
"""requests api async function | ||
:param API: one API basemodel | ||
:return: | ||
""" | ||
API = handle_API(API) | ||
# print(API.dict()) | ||
async with httpx.AsyncClient(headers=default_header) as client: | ||
try: | ||
# 判断是否传递 json 数据 | ||
if isinstance(API.data, dict): | ||
r = await client.request(method=API.method, url=API.url, json=API.data, headers=API.header) | ||
else: | ||
r = await client.request(method=API.method, url=API.url, data=API.data, headers=API.header) | ||
logger.info(f"{API.desc} {r.text}") | ||
except httpx.HTTPError as exc: | ||
logger.error(f"{API.desc} Error:{exc}") | ||
|
||
|
||
@logger.catch | ||
async def main(): | ||
APIs = load_json() | ||
if APIs is None: | ||
return | ||
|
||
# 接收一个元组需要用 * 传参 | ||
await asyncio.gather( | ||
*(rqs(api) | ||
for api in APIs) | ||
) | ||
|
||
|
||
if __name__ == "__main__": | ||
asyncio.run(main()) |