
Byted Sms Sender
- 3 installs
- 408 repo stars
- Updated August 3, 2026
- volcengine/agentkit-samples
Helps with ai & agent building tasks.
About
byted-sms-sender is a Claude Code skill for ai & agent building. It helps solo builders move faster with AI-assisted development.
- byted-sms-sender
- AI & Agent Building
- AI-coding skill
Byted Sms Sender by the numbers
- 3 all-time installs (skills.sh)
- Ranked #13,655 of 16,556 AI & Agent Building skills by installs in the Skillselion catalog
- Data as of Aug 4, 2026 (Skillselion catalog sync)
npx skills add https://github.com/volcengine/agentkit-samples --skill byted-sms-senderAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 3 |
|---|---|
| repo stars | ★ 408 |
| Last updated | August 3, 2026 |
| Repository | volcengine/agentkit-samples ↗ |
What it does
Helps with ai & agent building tasks.
Files
Byted SMS Sender
火山引擎短信服务 API,版本 2026-01-01
何时使用
当用户有以下需求时,使用本 skill:
发送短信场景:
- 需要发送验证码短信
- 需要发送通知类短信
- 需要发送营销类短信
- 用户说"发短信""发送验证码""发通知"时
查询场景:
- 需要查询可用的消息组(子账号)
- 需要查询已审核通过的短信签名
- 需要查询已审核通过的短信模板
- 需要查询短信发送记录
- 需要查询发送统计(成功率等)
使用前检查
检查是否已配置以下凭证:
ARK_SKILL_API_KEY- API 密钥ARK_SKILL_API_BASE- API 基础地址
这些凭证由 ArkClaw 预先配置在终端环境中,配置文件位置: /root/.openclaw/.env
检查方式:
echo $ARK_SKILL_API_KEY
echo $ARK_SKILL_API_BASE如果缺少凭证: 1. 检查配置文件 /root/.openclaw/.env 是否存在 2. 如果仍然找不到,请联系 oncall 获取帮助
6个接口说明
1. send\_sms - 发送短信
场景: 用户需要发送验证码、通知、营销短信
使用方式:
python3 scripts/volc_sms.py send_sms \
--sub-account "消息组ID" \
--signature "签名" \
--template-id "模板ID" \
--mobiles "手机号" \
--template-param '{"code":"123456"}'参数说明:
--sub-account: 消息组ID(必填),从 list\_sub\_account 获取--signature: 短信签名(必填),从 list\_signature 获取--template-id: 模板ID(必填),从 list\_sms\_template 获取--mobiles: 手机号(必填),多个用逗号分隔--template-param: 模板参数(可选),JSON格式
2. list\_sub\_account - 查询消息组
场景: 需要知道可以用哪个消息组发送短信
使用方式:
python3 scripts/volc_sms.py list_sub_account参数说明:
--sub-account-name: 可选,按名称模糊搜索
3. list\_signature - 查询签名
场景: 需要知道可以用哪个签名,或者查询签名是否审核通过
使用方式:
python3 scripts/volc_sms.py list_signature --signature "火山引擎"参数说明:
--signature: 可选,按签名模糊搜索--sub-accounts: 可选,按子账号过滤--page: 页码,默认1--page-size: 每页数量,默认20
4. list\_sms\_template - 查询模板
场景: 需要知道可以用哪个模板,或者查询模板参数
使用方式:
python3 scripts/volc_sms.py list_sms_template --signatures "火山引擎"参数说明:
--template-id: 可选,按模板ID模糊搜索--signatures: 可选,按签名过滤--sub-accounts: 可选,按子账号过滤--page: 页码,默认1--page-size: 每页数量,默认20
5. list\_sms\_send\_log - 查询发送记录
场景: 需要查看某条短信的发送状态,或批量查询发送历史
使用方式:
python3 scripts/volc_sms.py list_sms_send_log \
--sub-account "消息组ID" \
--from-time 1773113285 \
--to-time 1773213285参数说明:
--sub-account: 必填,消息组ID--from-time: 开始时间戳(秒)--to-time: 结束时间戳(秒)--mobile: 可选,按手机号过滤--template-id: 可选,按模板ID过滤--signature: 可选,按签名过滤--message-id: 可选,按消息ID精确查询--page: 页码,默认1--page-size: 每页数量,默认100
6. list\_total\_send\_count\_stat - 查询发送统计
场景: 需要查看发送成功率、接收成功率等统计信息
使用方式:
python3 scripts/volc_sms.py list_total_send_count_stat \
--start-time 1773113285 \
--end-time 1773213285参数说明:
--start-time: 必填,开始时间戳(秒)--end-time: 必填,结束时间戳(秒)--sub-account: 可选,按消息组过滤--channel-type: 可选,通道类型--signature: 可选,按签名过滤--template-id: 可选,按模板ID过滤
返回字段:
- TotalSendCount: 总发送数
- TotalSendSuccessCount: 发送成功数
- TotalSendSuccessRate: 发送成功率
- TotalReceiptSuccessCount: 接收成功数
- TotalReceiptSuccessRate: 接收成功率
典型使用流程
第一次发送短信
1. 查询可用的消息组
python3 scripts/volc_sms.py list_sub_account2. 查询可用的签名
python3 scripts/volc_sms.py list_signature3. 查询可用的模板
python3 scripts/volc_sms.py list_sms_template --signatures "火山引擎"4. 发送短信
python3 scripts/volc_sms.py send_sms \
--sub-account "xxxx" \
--signature "xxx" \
--template-id "ST_xxxx" \
--mobiles "188xxxxxxx8" \
--template-param '{"code":"888888"}'查询发送状态
python3 scripts/volc_sms.py list_sms_send_log \
--sub-account "77da1acf" \
--from-time 1773113285 \
--to-time 1773213285常见错误码
RE:0001: 账号短信服务未开通RE:0003: 子账号不存在(消息组ID错误)RE:0004: 签名错误(签名不存在或未审核通过)RE:0005: 模板错误(模板不存在或未审核通过)RE:0006: 手机号格式错误RE:0010: 账号欠费ZJ10200: 请求参数错误
注意事项
1. 签名和模板: 必须使用已审核通过的签名和模板 2. 手机号格式:
- 国内短信: 11位手机号或 +86开头
- 国际短信: 必须包含国际区号,符合 E.164 标准
3. 批量限制: 单次最多200个手机号 4. 签名子账号匹配: 签名和消息组需要匹配,可从 list\_signature 的 SubAccounts 字段确认 5. 模板签名匹配: 模板和签名需要匹配,可从 list\_sms\_template 的 Signature 字段确认
故障排查
- 缺少凭证: 检查
/root/.openclaw/.env文件,如仍找不到请联系 oncall - 发送失败: 先用 list\_sub\_account、list\_signature、list\_sms\_template 确认参数正确
- 鉴权失败: 检查自己配置的 AK/SK 是否开通正确
- 权限错误: 检查凭证是否正确,如问题持续请联系 oncall
- 欠费错误: 请联系 oncall 处理
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but not
limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
Byted SMS Sender — 凭证配置指南
本文档说明 Byted SMS Sender 所需的 API 凭证配置。
凭证说明
本技能使用以下两个环境变量进行认证:
ARK_SKILL_API_KEY- API 密钥(Bearer Token)ARK_SKILL_API_BASE- API 基础地址
cat /root/.openclaw/.env凭证示例
ARK_SKILL_API_KEY=sk-xxxx
ARK_SKILL_API_BASE=http://xxx凭证缺失处理
如果检查后发现凭证缺失:
1. 确认配置文件 /root/.openclaw/.env 是否存在 2. 确认环境变量是否正确加载 3. 如果仍然找不到,请联系 oncall 获取帮助
验证配置
cd skills/byted-sms-sender
python3 scripts/volc_sms.py list_sub_account如果返回消息组列表,说明配置正确。
认证方式说明
所有 API 请求使用 Bearer Token 认证,请求格式如下:
curl -X POST 'https://<ARK_SKILL_API_BASE>?Action=ListSubAccountForAgent&Version=2026-01-01' \
-H 'Content-Type: application/json' \
-H 'ServiceName: volcSMS' \
-H 'Authorization: Bearer <ARK_SKILL_API_KEY>' \
-d '{}'请求头说明
| Header | 说明 |
|---|---|
Content-Type | 固定为 application/json |
ServiceName | 固定为 volcSMS |
Authorization | 格式为 Bearer <ARK_SKILL_API_KEY> |
常见问题
Q: 环境变量未生效怎么办?
A: 检查以下几点: 1. 确认配置文件路径正确:/root/.openclaw/.env 2. 确认环境变量名称正确(区分大小写) 3. 尝试重新加载配置:source /root/.openclaw/.env
Q: 找不到凭证怎么办?
A: 凭证由 ArkClaw 预先配置,如果找不到请联系 oncall 获取帮助。
Q: API 调用返回认证错误?
A: 检查: 1. 自己配置的 AK/SK 是否正确 2. 凭证是否已过期,如过期请联系 oncall
# Copyright (c) 2025 Beijing Volcano Engine Technology Co., Ltd. and/or its affiliates.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#!/usr/bin/env python3
"""火山引擎短信发送 API - openclaw专用接口 (2026-01-01).
Version: 2026-01-01
分组: openclaw专用
6个接口:
- send_sms: 发送短信
- list_sms_send_log: 查询发送记录
- list_sub_account: 查询消息组列表
- list_signature: 查询签名列表
- list_sms_template: 查询模板列表
- list_total_send_count_stat: 查询发送统计
Usage:
python volc_sms.py <action> [options]
Examples:
# 发送短信
python volc_sms.py send_sms \
--sub-account 77da1acf --signature "火山引擎" --template-id "ST_xxx" \
--mobiles "13800138000" --template-param '{"code":"123456"}'
# 查询消息组
python volc_sms.py list_sub_account
# 查询签名
python volc_sms.py list_signature --signature "火山引擎"
# 查询模板
python volc_sms.py list_sms_template --signatures "火山引擎"
# 查询发送记录
python volc_sms.py list_sms_send_log \
--sub-account 77da1acf --from-time 1773113285 --to-time 1773213285
# 查询发送统计
python volc_sms.py list_total_send_count_stat \
--start-time 1773113285 --end-time 1773213285
"""
import argparse
import json
import os
import sys
SERVICE = "volcSMS"
VERSION = "2026-01-01"
def get_credentials() -> tuple:
api_key = os.getenv("ARK_SKILL_API_KEY")
api_base = os.getenv("ARK_SKILL_API_BASE")
if not api_key or not api_base:
raise ValueError(
"未找到凭证,请设置环境变量 ARK_SKILL_API_KEY 和 ARK_SKILL_API_BASE\n"
"配置文件位置: /root/.openclaw/.env\n"
"示例:\n"
" ARK_SKILL_API_KEY=sk-xxxx\n"
" ARK_SKILL_API_BASE=http://xxx"
)
return api_key, api_base
def call_api(action: str, body: dict) -> dict:
try:
import requests
except ImportError:
print("Error: requests not installed. Run: pip install requests", file=sys.stderr)
sys.exit(1)
api_key, api_base = get_credentials()
api_base = api_base.rstrip("/")
url = f"{api_base}?Action={action}&Version={VERSION}"
headers = {
"Content-Type": "application/json",
"ServiceName": SERVICE,
"Authorization": f"Bearer {api_key}",
}
body_str = json.dumps(body, ensure_ascii=False)
response = requests.post(url, headers=headers, data=body_str.encode("utf-8"), timeout=30)
response.raise_for_status()
return response.json()
def send_sms(args) -> dict:
"""发送短信 (SendSmsForAgent).
Request:
"Account": "",
"SubAccount": "",
"Signature": "",
"TemplateId": "",
"Mobiles": "",
"TemplateParam": ""
Response:
"MessageIds": ["xxx", "xxx"]
"""
body = {
"SubAccount": args.sub_account,
"Signature": args.signature,
"TemplateId": args.template_id,
"Mobiles": args.mobiles,
}
if args.account:
body["Account"] = args.account
if args.template_param:
body["TemplateParam"] = args.template_param
return call_api("SendSmsForAgent", body)
def list_sms_send_log(args) -> dict:
"""查询发送记录 (ListSmsSendLogForAgent).
Request:
"SubAccount": "",
"FromTime": 1773113285,
"ToTime": 1773113285,
"Mobile": "",
"TemplateId": "",
"Signature": "",
"MessageId": "",
"Page": 1,
"PageSize": 100
Response:
"Total": 123,
"List": [...]
"""
body = {
"SubAccount": args.sub_account,
"Page": args.page,
"PageSize": args.page_size,
}
if args.from_time:
body["FromTime"] = args.from_time
if args.to_time:
body["ToTime"] = args.to_time
if args.mobile:
body["Mobile"] = args.mobile
if args.template_id:
body["TemplateId"] = args.template_id
if args.signature:
body["Signature"] = args.signature
if args.message_id:
body["MessageId"] = args.message_id
return call_api("ListSmsSendLogForAgent", body)
def list_sub_account(args) -> dict:
"""查询消息组列表 (ListSubAccountForAgent).
说明: 只返回审核通过的消息组
Request:
"SubAccountName": ""
Response:
"Total": 123,
"List": [{"SubAccountName": "", "SubAccount": ""}]
"""
body = {}
if args.sub_account_name:
body["SubAccountName"] = args.sub_account_name
return call_api("ListSubAccountForAgent", body)
def list_signature(args) -> dict:
"""查询签名列表 (ListSignatureForAgent).
说明: 返回审核通过的签名
Request:
"Signature": "qm",
"SubAccounts": ["a", "b"],
"Page": 1,
"PageSize": 2
Response:
"Total": 100,
"List": [{"Signature": "", "Description": "", "Status": 1, ...}]
"""
body = {
"Page": args.page,
"PageSize": args.page_size,
}
if args.signature:
body["Signature"] = args.signature
if args.sub_accounts:
body["SubAccounts"] = args.sub_accounts.split(",")
return call_api("ListSignatureForAgent", body)
def list_sms_template(args) -> dict:
"""查询模板列表 (ListSmsTemplateForAgent).
说明: 返回审核通过的模板信息
Request:
"TemplateId": "qm",
"SubAccounts": ["a", "b"],
"Signatures": ["aqm", "bqm"],
"Page": 1,
"PageSize": 2
Response:
"Total": 100,
"List": [{"TemplateId": "", "SecondTemplateId": "", ...}]
"""
body = {
"Page": args.page,
"PageSize": args.page_size,
}
if args.template_id:
body["TemplateId"] = args.template_id
if args.sub_accounts:
body["SubAccounts"] = args.sub_accounts.split(",")
if args.signatures:
body["Signatures"] = args.signatures.split(",")
return call_api("ListSmsTemplateForAgent", body)
def list_total_send_count_stat(args) -> dict:
"""查询发送统计 (ListTotalSendCountStatForAgent).
Request:
"StartTime": 16934224000,
"EndTime": 16934224000,
"SubAccount": "",
"ChannelType": "",
"Signature": "",
"TemplateId": ""
Response:
"TotalSendCount": 1122,
"TotalSendSuccessCount": 120,
"TotalAllSendCount": 123,
"TotalReceiptSuccessCount": 123,
"TotalReceiptFailureCount": 123,
"TotalSendSuccessRate": 0.87,
"TotalReceiptSuccessRate": 0.99
"""
body = {
"StartTime": args.start_time,
"EndTime": args.end_time,
}
if args.sub_account:
body["SubAccount"] = args.sub_account
if args.channel_type:
body["ChannelType"] = args.channel_type
if args.signature:
body["Signature"] = args.signature
if args.template_id:
body["TemplateId"] = args.template_id
return call_api("ListTotalSendCountStatForAgent", body)
def main():
parser = argparse.ArgumentParser(
description="火山引擎短信发送 API (openclaw专用)\nVersion: 2026-01-01",
formatter_class=argparse.RawDescriptionHelpFormatter,
epilog=__doc__
)
parser.add_argument("action", help="操作: send_sms, list_sms_send_log, list_sub_account, list_signature, list_sms_template, list_total_send_count_stat")
# send_sms 参数
parser.add_argument("--account", help="账号")
parser.add_argument("--sub-account", help="子账号/消息组ID")
parser.add_argument("--signature", help="短信签名")
parser.add_argument("--template-id", help="短信模板ID")
parser.add_argument("--mobiles", help="手机号(逗号分隔)")
parser.add_argument("--template-param", help="模板参数JSON")
# list_sms_send_log 参数
parser.add_argument("--from-time", type=int, help="开始时间戳")
parser.add_argument("--to-time", type=int, help="结束时间戳")
parser.add_argument("--mobile", help="手机号")
parser.add_argument("--message-id", help="消息ID")
parser.add_argument("--page", type=int, default=1, help="页码")
parser.add_argument("--page-size", type=int, default=100, help="每页数量")
# list_sub_account 参数
parser.add_argument("--sub-account-name", help="消息组名称(模糊匹配)")
# list_signature 参数
parser.add_argument("--sub-accounts", help="子账号列表(逗号分隔)")
# list_sms_template 参数
parser.add_argument("--signatures", help="签名列表(逗号分隔)")
# list_total_send_count_stat 参数
parser.add_argument("--start-time", type=int, help="开始时间戳")
parser.add_argument("--end-time", type=int, help="结束时间戳")
parser.add_argument("--channel-type", help="通道类型")
args = parser.parse_args()
action_map = {
"send_sms": send_sms,
"list_sms_send_log": list_sms_send_log,
"list_sub_account": list_sub_account,
"list_signature": list_signature,
"list_sms_template": list_sms_template,
"list_total_send_count_stat": list_total_send_count_stat,
}
if args.action not in action_map:
print(f"Error: 未知的操作 {args.action}", file=sys.stderr)
print(f"支持的操作为: {', '.join(action_map.keys())}", file=sys.stderr)
sys.exit(1)
try:
result = action_map[args.action](args)
except ValueError as exc:
print(f"Error: {exc}", file=sys.stderr)
sys.exit(1)
except Exception as exc:
response = getattr(exc, "response", None)
if response is not None:
print(f"HTTP Error: {exc}", file=sys.stderr)
response_text = getattr(response, "text", None)
if response_text:
print(response_text, file=sys.stderr)
else:
print(f"Error: {exc}", file=sys.stderr)
sys.exit(1)
print(json.dumps(result, indent=2, ensure_ascii=False))
if __name__ == "__main__":
main()