Files
dc-docs/fetch_tb.py
T
2026-06-08 10:04:12 +08:00

135 lines
4.4 KiB
Python

#!/usr/bin/env python3
"""TeamBition 数据拉取入口 - 隐秘之潮项目"""
import sys
import os
import json
from datetime import datetime
# Add project root to path
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
from tb.tb_config import TBConfig
from tb.teambition_api import TeambitionAPI
from tb.task_analyzer import TaskAnalyzer
from tb.task_manager import TaskManager
def fetch_tb_data(send_to_dingtalk=False, mode="daily"):
"""拉取 TeamBition 任务数据并分析"""
config = TBConfig()
api = TeambitionAPI(config)
analyzer = TaskAnalyzer(config)
task_manager = TaskManager(
os.path.join(os.path.dirname(__file__), "data", "tb", "task_state.json")
)
project_id = config.get("teambition.project_id", "unknown")
print(f"\n{'='*60}")
print(f"拉取 TeamBition 任务数据 - 项目: {project_id}")
print(f"{'='*60}\n")
# 1. Export tasks via TeamBition API
csv_content = api.fetch_tasks()
if not csv_content:
print("获取任务数据失败")
return None
# 2. Save CSV
output_dir = os.path.join(os.path.dirname(__file__), "data", "tb")
os.makedirs(output_dir, exist_ok=True)
csv_path = api.save_csv(csv_content, output_dir=output_dir)
if not csv_path:
print("保存 CSV 失败")
return None
# 3. Analyze
df = analyzer.load_csv(csv_path)
if df.empty:
print("CSV 数据为空")
return None
# 4. Fetch task activities for contribution tracking
id_col = next(
(c for c in ["任务 ObjectId", "_id", "id", "taskId", "任务ID"] if c in df.columns),
None,
)
activities = []
if id_col:
task_ids = [t for t in df[id_col].dropna().astype(str).tolist() if t and t != "nan"]
if task_ids:
print(f"获取 {len(task_ids)} 个任务的动态...")
try:
activities = api.fetch_tasks_activities(task_ids)
except Exception as e:
print(f"[Warning] 获取动态失败: {e}")
# 5. Generate summary
summary = analyzer.analyze_tasks(df, activities)
summary_path = os.path.join(output_dir, "summary.json")
analyzer.save_summary(summary)
# 6. Detect changes
current_tasks = analyzer.get_task_dict(df)
old_state = task_manager.load_state()
prev_tasks = old_state.get("tasks", {})
changes = task_manager.detect_changes(prev_tasks, current_tasks)
if changes:
print("\n[变动检测]")
for c in changes:
print(f" {c}")
else:
print("\n[变动检测] 无变动")
task_manager.save_state(current_tasks)
# 7. Optionally send to DingTalk
if send_to_dingtalk:
from tb.dingtalk_sender import DingTalkSender
dingtalk_config = config.get("dingtalk", {})
if dingtalk_config.get("enabled"):
robots = dingtalk_config.get("robots", {})
user_roles = config.get("user_roles", {})
user_mobiles = config.get("user_mobiles", {})
switches = dingtalk_config.get("switches", {})
temp_sender = DingTalkSender("")
report, at_mobiles = temp_sender.format_task_report(
summary, user_roles, user_mobiles,
dashboard_url=config.get("dashboard_url"),
switches=switches,
)
if switches.get("daily_diff", True):
report = temp_sender.format_diff_report(changes, report)
for name, bot_cfg in robots.items():
webhook = bot_cfg.get("webhook")
secret = bot_cfg.get("secret")
if webhook:
sender = DingTalkSender(webhook)
sender.send_markdown("Teambition 任务日报", report, secret=secret, at_mobiles=at_mobiles)
print(f"已发送到钉钉机器人: {name}")
# 8. Cleanup CSV
if csv_path and os.path.exists(csv_path):
os.remove(csv_path)
print(f"\n完成! 共 {summary.get('total_tasks', 0)} 个任务")
return summary
if __name__ == "__main__":
import argparse
parser = argparse.ArgumentParser(description="TeamBition 数据拉取")
parser.add_argument("--dingtalk", action="store_true", help="发送到钉钉群")
parser.add_argument("--mode", default="daily", choices=["daily", "interval"])
args = parser.parse_args()
fetch_tb_data(send_to_dingtalk=args.dingtalk, mode=args.mode)