publish_table.py 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104
  1. #!/usr/bin/env python3
  2. """Publish a CSV/XLS/XLSX file as a Feishu online spreadsheet."""
  3. from __future__ import annotations
  4. import argparse
  5. import json
  6. import os
  7. import sys
  8. from pathlib import Path
  9. from feishu_client import FeishuPublisher
  10. def build_parser() -> argparse.ArgumentParser:
  11. parser = argparse.ArgumentParser(
  12. description=(
  13. "将 CSV/XLS/XLSX 导入飞书在线表格,设置任何人可编辑,"
  14. "并可发送到群聊。"
  15. )
  16. )
  17. parser.add_argument("file", nargs="?", help="待发布的数据文件")
  18. parser.add_argument("--title", help="在线表格和消息卡片标题")
  19. parser.add_argument("--message", default="数据查询结果已生成,请点击查看。")
  20. target = parser.add_mutually_exclusive_group()
  21. target.add_argument("--chat-id", help="目标飞书群 chat_id")
  22. target.add_argument("--chat-name", help="机器人可见群中的精确群名")
  23. parser.add_argument("--no-notify", action="store_true", help="只创建表格,不发群消息")
  24. parser.add_argument("--dry-run", action="store_true", help="仅校验本地输入,不调用飞书 API")
  25. parser.add_argument("--list-chats", action="store_true", help="只读列出机器人可见群聊")
  26. parser.add_argument("--name", default="", help="配合 --list-chats 按名称模糊过滤")
  27. return parser
  28. def print_json(value: object) -> None:
  29. print(json.dumps(value, ensure_ascii=False, indent=2))
  30. def main() -> int:
  31. args = build_parser().parse_args()
  32. try:
  33. if args.list_chats:
  34. with FeishuPublisher.from_env() as publisher:
  35. token = publisher.tenant_access_token()
  36. print_json(publisher.list_chats(token, args.name))
  37. return 0
  38. if not args.file:
  39. raise ValueError("必须提供结果文件,或使用 --list-chats")
  40. file_path = Path(args.file).expanduser().resolve()
  41. extension = FeishuPublisher.validate_file(file_path)
  42. title = (args.title or file_path.stem).strip()
  43. if not title:
  44. raise ValueError("表格标题不能为空")
  45. chat_id = (
  46. args.chat_id
  47. if args.chat_id is not None
  48. else os.getenv("FEISHU_TARGET_CHAT_ID", "")
  49. ).strip()
  50. chat_name = (
  51. args.chat_name
  52. if args.chat_name is not None
  53. else os.getenv("FEISHU_TARGET_CHAT_NAME", "")
  54. ).strip()
  55. notify = not args.no_notify
  56. if notify and not chat_id and not chat_name:
  57. raise ValueError(
  58. "未配置目标群;请使用 --chat-id/--chat-name 或设置 "
  59. "FEISHU_TARGET_CHAT_ID/FEISHU_TARGET_CHAT_NAME"
  60. )
  61. if args.dry_run:
  62. print_json(
  63. {
  64. "dry_run": True,
  65. "file": str(file_path),
  66. "file_extension": extension,
  67. "title": title,
  68. "permission": "anyone_editable",
  69. "notify": notify,
  70. "target": chat_id or chat_name,
  71. }
  72. )
  73. return 0
  74. with FeishuPublisher.from_env() as publisher:
  75. result = publisher.publish(
  76. file_path,
  77. title=title,
  78. message=args.message,
  79. chat_id=chat_id,
  80. chat_name=chat_name,
  81. notify=notify,
  82. )
  83. print_json(result)
  84. return 0
  85. except Exception as exc:
  86. print(f"发布失败:{exc}", file=sys.stderr)
  87. return 1
  88. if __name__ == "__main__":
  89. raise SystemExit(main())