publish.py 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102
  1. #!/usr/bin/env python3
  2. """
  3. TappoCloud Store 应用发布脚本
  4. 用法:
  5. python publish.py <zip文件路径> [--api URL]
  6. python publish.py cloudfs-v0.1.0.zip
  7. python publish.py *.zip # 批量上传
  8. """
  9. import argparse
  10. import getpass
  11. import json
  12. import sys
  13. from pathlib import Path
  14. try:
  15. import requests
  16. except ImportError:
  17. print("请先安装 requests: pip install requests")
  18. sys.exit(1)
  19. TOKEN_FILE = Path.home() / ".tappocloud_token"
  20. def login(api_base: str) -> str:
  21. username = input("用户名: ")
  22. password = getpass.getpass("密码: ")
  23. resp = requests.post(
  24. f"{api_base}/api/v1/admin/login",
  25. json={"username": username, "password": password},
  26. )
  27. if resp.status_code != 200:
  28. print(f"登录失败: {resp.text}")
  29. sys.exit(1)
  30. token = resp.json()["token"]
  31. TOKEN_FILE.write_text(token)
  32. print("登录成功,token 已保存")
  33. return token
  34. def get_token(api_base: str) -> str:
  35. if TOKEN_FILE.exists():
  36. token = TOKEN_FILE.read_text().strip()
  37. # 验证 token
  38. resp = requests.get(
  39. f"{api_base}/api/v1/apps",
  40. headers={"Authorization": f"Bearer {token}"},
  41. )
  42. if resp.status_code == 200:
  43. return token
  44. TOKEN_FILE.unlink()
  45. return login(api_base)
  46. def upload(api_base: str, token: str, zip_path: Path) -> dict:
  47. print(f"正在上传: {zip_path.name}")
  48. with open(zip_path, "rb") as f:
  49. resp = requests.post(
  50. f"{api_base}/api/v1/admin/apps/upload",
  51. headers={"Authorization": f"Bearer {token}"},
  52. files={"file": (zip_path.name, f, "application/zip")},
  53. )
  54. if resp.status_code != 200:
  55. print(f"上传失败: {resp.text}")
  56. return None
  57. return resp.json()
  58. def main():
  59. parser = argparse.ArgumentParser(description="TappoCloud 应用发布工具")
  60. parser.add_argument("files", nargs="+", help="要上传的 zip 文件")
  61. parser.add_argument("--api", default="https://app.tappo.dev", help="API 地址")
  62. args = parser.parse_args()
  63. token = get_token(args.api)
  64. for file_path in args.files:
  65. path = Path(file_path)
  66. if not path.exists():
  67. print(f"文件不存在: {path}")
  68. continue
  69. if not path.suffix == ".zip":
  70. print(f"跳过非 zip 文件: {path}")
  71. continue
  72. result = upload(args.api, token, path)
  73. if result:
  74. print(f"✓ {result['app_uid']} v{result['version']} 上传成功")
  75. print(f" 存储地址: {result['storage_url']}")
  76. print()
  77. if __name__ == "__main__":
  78. main()