Skill: showdownagain/feishu-task-integration-skill (version 1.0.0)

--- name: feishu-task-integration description: 飞书任务对接集成技能，实现待办事项与飞书任务的双向同步。自动创建飞书任务、智能解析时间表达式、设置任务负责人，支持任务状态同步和完成管理。使用场景：需要将本地待办事项同步到飞书任务、设置任务截止时间、指派任务负责人、跟踪任务完成状态。 --- # 飞书任务对接集成 ## 功能概述 飞书任务对接集成技能实现了本地待办事项系统与飞书任务平台的无缝对接，提供智能化的任务管理和同步功能。 ## 核心能力 ### 1. 自动任务创建 - 使用 `todo任务内容` 命令自动创建飞书任务 - 自动设置任务负责人和关注人 - 生成任务唯一标识符和访问链接 ### 2. 智能时间解析 - 支持自然语言时间表达："今天"、"明天"、"本周"、"下周"、"本月" - 支持具体时间："下午3点"、"晚上11点" - 自动转换为标准时间戳格式 ### 3. 任务负责人管理 - 自动指派任务给配置的用户 - 支持多人协作（关注人和负责人分离） - 符合飞书任务API规范 ### 4. 状态同步 - 本地完成任务自动同步到飞书 - 实时获取任务完成状态 - 双向数据一致性保证 ## 快速开始 ### 基本使用 ```bash # 创建任务（自动同步到飞书） todo完成项目报告 # 查看任务列表 todo # 完成任务（同步到飞书） done0 ``` ### 时间表达式示例 ```bash # 今天截止 todo今天完成文档整理 # 明天截止 todo明天提交周报 # 本周截止 todo本周完成项目总结 # 具体时间 todo今天晚上8点之前完成演示准备 ``` ## 配置说明 ### 必要配置 在 `feishu_config.json` 中配置以下信息： ```json { "app_id": "your_app_id", "app_secret": "your_app_secret", "assignee_user_id": "ou_your_user_id" } ``` ### 获取配置信息 1. **App ID & Secret**: 在飞书开发者后台创建应用获取 2. **User ID**: 用户的open_id，格式为 `ou_xxxxxxxx` ## 技术实现 ### 文件结构 - `todo_handler.py` - 主处理器，处理todo命令 - `feishu_task_integration.py` - 飞书任务API集成 - `feishu_config.json` - 配置文件 ### API集成 - 使用飞书任务v2 API - 正确的字段命名：`members`、`assignee_list` - 符合飞书API规范和权限要求 ## 故障排除 ### 常见问题 1. **任务创建失败**: 检查API密钥和用户ID配置 2. **负责人设置无效**: 确认用户ID格式正确（ou_开头） 3. **时间解析错误**: 使用标准时间表达格式 ### 调试信息 查看详细日志输出： ```bash python3 todo_handler.py "todo测试任务" 2>&1 ``` ## 资源文件 ### scripts/ 包含核心功能脚本： - `todo_handler.py` - 待办事项处理器 - `feishu_task_integration.py` - 飞书API集成 ### references/ 包含参考文档： - `api_guide.md` - 飞书任务API使用指南 - `configuration.md` - 详细配置说明 ### assets/ 包含配置文件模板： - `feishu_config_template.json` - 配置文件模板

path: scripts/feishu_task_integration.py
content: #!/usr/bin/env python3
import json
import requests
import os
from datetime import datetime, date
import sys

class FeishuTaskManager:
    def __init__(self):
        # 尝试从环境变量获取，如果没有则使用默认值
        self.app_id = os.environ.get('FEISHU_APP_ID')
        self.app_secret = os.environ.get('FEISHU_APP_SECRET')
        
        # 如果没有环境变量，尝试从配置文件读取
        if not self.app_id or not self.app_secret:
            self.load_config_from_file()
        
        self.tenant_access_token = None
        self.user_access_token = None
        
        # 用户信息
        self.yangbin_user_id = None
        self.current_user_id = [REDACTED_SECRET]  # 当前用户ID
        
        self.load_yangbin_info()
    
    def load_config_from_file(self):
        """从配置文件加载凭证"""
        config_file = '/home/gary/.openclaw/workspace/feishu_config.json'
        try:
            if os.path.exists(config_file):
                with open(config_file, 'r', encoding='utf-8') as f:
                    config = json.load(f)
                    self.app_id = config.get('app_id')
                    self.app_secret = config.get('app_secret')
        except Exception as e:
            print(f"读取配置文件失败: {e}")
        
        # 如果还是没有，使用占位符（仅用于测试）
        if not self.app_id:
            self.app_id = 'cli_a6b5d8c9e0f1g2h3'  # 占位符
        if not self.app_secret:
            self.app_secret = 'your_app_secret'  # 占位符
    
    def load_yangbin_info(self):
        """加载用户信息"""
        config_file = '/home/gary/.openclaw/workspace/feishu_config.json'
        try:
            if os.path.exists(config_file):
                with open(config_file, 'r', encoding='utf-8') as f:
                    config = json.load(f)
                    self.yangbin_user_id = config.get('yangbin_user_id')
                    self.assignee_user_id = config.get('assignee_user_id')
                    
                    if self.yangbin_user_id:
                        print(f"✅ 已加载杨彬用户ID: {self.yangbin_user_id}")
                    else:
                        print("⚠️  配置文件中未找到杨彬用户ID")
                        
                    if self.assignee_user_id:
                        print(f"✅ 已加载负责人用户ID: {self.assignee_user_id}")
                    else:
                        print("⚠️  配置文件中未找到负责人用户ID")
        except Exception as e:
            print(f"读取用户信息失败: {e}")
        
    def get_tenant_access_token(self):
        """获取租户访问令牌"""
        url = "https://open.feishu.cn/open-apis/auth/v3/tenant_access_token/internal"
        headers = {"Content-Type": "application/json"}
        data = {
            "app_id": self.app_id,
            "app_secret": self.app_secret
        }
        
        try:
            response = requests.post(url, headers=headers, json=data)
            result = response.json()
            if result.get('code') == 0:
                self.tenant_access_token = result['tenant_access_token']
                return True
            else:
                print(f"获取tenant_access_token失败: {result}")
                return False
        except Exception as e:
            print(f"获取tenant_access_token异常: {e}")
            return False
    
    def get_user_access_token(self, code):
        """获取用户访问令牌"""
        url = "https://open.feishu.cn/open-apis/authen/v1/access_token"
        headers = {"Authorization": f"Bearer {self.tenant_access_token}", "Content-Type": "application/json"}
        data = {
            "grant_type": "authorization_code",
            "code": code
        }
        
        try:
            response = requests.post(url, headers=headers, json=data)
            result = response.json()
            if result.get('code') == 0:
                self.user_access_token = result['data']['access_token']
                return True
            else:
                print(f"获取user_access_token失败: {result}")
                return False
        except Exception as e:
            print(f"获取user_access_token异常: {e}")
            return False
    
    def create_task(self, title, description="", due_date=None, followers=None, assignees=None, add_yangbin=True, add_current_user=True):
        """创建任务
        
        Args:
            title: 任务标题
            description: 任务描述
            due_date: 截止日期（时间戳）
            followers: 关注人列表，格式 [{"id": "用户open_id"}]
            assignees: 负责人列表，格式 [{"id": "用户open_id"}]
            add_yangbin: 是否自动添加杨彬为关注人和负责人
            add_current_user: 是否自动添加当前用户为执行人和关注者
        """
        if not self.tenant_access_token:
            if not self.get_tenant_access_token():
                return None
        
        url = "https://open.feishu.cn/open-apis/task/v2/tasks"
        headers = {
            "Authorization": f"Bearer {self.tenant_access_token}",
            "Content-Type": "application/json"
        }
        
        data = {
            "summary": title,
            "description": description
        }
        
        if due_date:
            data["due"] = {"timestamp": due_date}
        
        # 处理关注人
        final_followers = followers or []
        
        # 添加当前用户为关注者
        if add_current_user and self.current_user_id:
            current_user_follower = {"id": self.current_user_id}
            if current_user_follower not in final_followers:
                final_followers.append(current_user_follower)
        
        # 添加杨彬为关注人
        if add_yangbin and self.yangbin_user_id:
            yangbin_follower = {"id": self.yangbin_user_id}
            if yangbin_follower not in final_followers:
                final_followers.append(yangbin_follower)
        
        # 处理负责人
        final_assignees = assignees or []
        
        # 添加当前用户为负责人（执行人）
        if add_current_user and self.current_user_id:
            current_user_assignee = {"id": self.current_user_id}
            if current_user_assignee not in final_assignees:
                final_assignees.append(current_user_assignee)
        
        # 添加杨彬为负责人
        if add_yangbin and self.yangbin_user_id:
            yangbin_assignee = {"id": self.yangbin_user_id}
            if yangbin_assignee not in final_assignees:
                final_assignees.append(yangbin_assignee)
        
        # 添加关注人和负责人到请求数据
        if final_followers:
            data["followers"] = final_followers
        if final_assignees:
            data["assignees"] = final_assignees
        
        print(f"📋 创建任务: {title}")
        print(f"   关注人: {len(final_followers)}")
        print(f"   负责人: {len(final_assignees)}")
        
        try:
            response = requests.post(url, headers=headers, json=data)
            result = response.json()
            print(f"创建任务响应: {result}")
            if result.get('code') == 0:
                # 修复：使用正确的字段名获取任务ID
                task_data = result['data']['task']
                task_id = task_data.get('task_id') or task_data.get('id') or task_data.get('guid')
                if task_id:
                    print(f"✅ 任务创建成功，ID: {task_id}")
                    return task_id
                else:
                    print(f"❌ 无法获取任务ID，响应数据: {task_data}")
                    return None
            else:
                print(f"❌ 创建任务失败: {result}")
                return None
        except Exception as e:
            print(f"❌ 创建任务异常: {e}")
            return None
    
    def complete_task(self, task_id):
        """完成任务 - 使用PATCH方法更新任务状态
        
        Args:
            task_id: 可以是task_id（t开头）或guid（uuid格式）
        """
        if not self.tenant_access_token:
            if not self.get_tenant_access_token():
                return False
        
        # 如果task_id是task_id格式（t开头），需要转换为guid
        task_guid = task_id
        if task_id.startswith('t'):
            # 尝试从task_id获取guid
            task_guid = self.get_task_guid_from_id(task_id)
            if not task_guid:
                print(f"❌ 无法获取任务 {task_id} 的guid")
                return False
        
        url = f"https://open.feishu.cn/open-apis/task/v2/tasks/{task_guid}"
        headers = {
            "Authorization": f"Bearer {self.tenant_access_token}",
            "Content-Type": "application/json"
        }
        
        import time
        data = {
            "task": {
                "completed_at": str(int(time.time() * 1000))  # 当前时间戳（毫秒）
            },
            "update_fields": ["completed_at"]
        }
        
        try:
            response = requests.patch(url, headers=headers, json=data)
            response_text = response.text
            print(f"完成任务API响应: {response_text}")
            
            if response.status_code != 200:
                print(f"HTTP错误: {response.status_code}")
                return False
            
            try:
                result = response.json()
                if result.get('code') == 0:
                    print("✅ 任务完成成功")
                    return True
                else:
                    print(f"完成任务失败: {result}")
                    return False
            except json.JSONDecodeError as e:
                print(f"JSON解析错误: {e}")
                return False
        except Exception as e:
            print(f"完成任务异常: {e}")
            return False
    
    def get_task_guid_from_id(self, task_id):
        """从task_id获取guid - 通过创建临时任务来获取映射关系"""
        # 这是一个临时的解决方案
        # 在实际应用中，应该维护一个task_id到guid的映射表
        print(f"⚠️  需要task_id到guid的映射，暂时返回None")
        return None
    
    def get_user_tasks(self, user_id, completed=False):
        """获取用户任务 - 使用正确的API端点"""
        if not self.tenant_access_token:
            if not self.get_tenant_access_token():
                return []
        
        # 使用正确的任务列表API端点
        url = "https://open.feishu.cn/open-apis/task/v2/tasks"
        headers = {
            "Authorization": f"Bearer {self.tenant_access_token}",
            "Content-Type": "application/json"
        }
        
        params = {
            "page_size": 50
        }
        
        try:
            response = requests.get(url, headers=headers, params=params)
            response_text = response.text
            print(f"API响应: {response_text}")
            
            if response.status_code != 200:
                print(f"HTTP错误: {response.status_code}")
                return []
            
            result = response.json()
            if result.get('code') == 0:
                all_tasks = result['data']['items'] or []
                # 根据完成状态过滤任务
                filtered_tasks = []
                for task in all_tasks:
                    task_completed = task.get('completed', False)
                    if completed and task_completed:
                        filtered_tasks.append(task)
                    elif not completed and not task_completed:
                        filtered_tasks.append(task)
                return filtered_tasks
            else:
                print(f"获取任务失败: {result}")
                return []
        except Exception as e:
            print(f"获取任务异常: {e}")
            return []
    
    def get_tasks_completed_today(self, user_id):
        """获取今天完成的任务"""
        all_tasks = self.get_user_tasks(user_id, completed=True)
        today = date.today().isoformat()
        
        completed_today = []
        for task in all_tasks:
            completed_at = task.get('completed_at', '')
            if completed_at and completed_at.startswith(today):
                completed_today.append(task)
        
        return completed_today
    
    def get_pending_tasks(self, user_id):
        """获取未完成的任务"""
        return self.get_user_tasks(user_id, completed=False)
    
    def get_user_id(self):
        """获取当前用户ID"""
        # 这里应该使用飞书的用户信息API
        # 暂时返回固定的用户ID
        return "ou_19c0ea5e1a6d3e318b52f4978684bd03"

def main():
    manager = FeishuTaskManager()
    
    if len(sys.argv) < 2:
        print("Usage: feishu_task_integration.py [create|complete|list|pending|completed_today] [args...]")
        return
    
    action = sys.argv[1]
    
    if action == 'create' and len(sys.argv) > 2:
        title = sys.argv[2]
        task_id = manager.create_task(title)
        if task_id:
            print(f"任务创建成功，ID: {task_id}")
        else:
            print("任务创建失败")
    
    elif action == 'complete' and len(sys.argv) > 2:
        task_id = sys.argv[2]
        if manager.complete_task(task_id):
            print(f"任务 {task_id} 已完成")
        else:
            print(f"任务 {task_id} 完成失败")
    
    elif action == 'pending':
        user_id = manager.get_user_id()
        tasks = manager.get_pending_tasks(user_id)
        print(f"待办任务 ({len(tasks)}):")
        for task in tasks:
            print(f"- {task['summary']} (ID: {task['id']})")
    
    elif action == 'completed_today':
        user_id = manager.get_user_id()
        tasks = manager.get_tasks_completed_today(user_id)
        print(f"今日已完成 ({len(tasks)}):")
        for task in tasks:
            print(f"- {task['summary']} (ID: {task['id']})")
    
    elif action == 'list':
        user_id = manager.get_user_id()
        pending = manager.get_pending_tasks(user_id)
        completed = manager.get_tasks_completed_today(user_id)
        
        print(f"📋 任务概览 | {datetime.now().strftime('%Y-%m-%d %H:%M')}")
        print(f"\n📌 待办任务 ({len(pending)}):")
        for task in pending:
            print(f"- {task['summary']} (ID: {task['id']})")
        
        print(f"\n🎉 今日已完成 ({len(completed)}):")
        for task in completed:
            print(f"- {task['summary']} (ID: {task['id']})")
    
    else:
        print("无效的命令")

if __name__ == '__main__':
    main()

path: scripts/feishu_task_integration_clean.py
content: #!/usr/bin/env python3
"""
飞书任务API集成 (清理版)
移除了所有个人信息和敏感配置
"""

import json
import requests
import os
from datetime import datetime, date
import sys

class FeishuTaskManager:
    def __init__(self):
        # 从配置文件加载凭证
        self.load_config()
        self.tenant_access_token = None
        self.user_access_token = None
        
        # 用户信息
        self.current_user_id = None
        self.assignee_user_id = None
        
        self.load_user_info()
    
    def load_config(self):
        """从配置文件加载凭证"""
        config_file = 'feishu_config.json'
        try:
            if os.path.exists(config_file):
                with open(config_file, 'r', encoding='utf-8') as f:
                    config = json.load(f)
                    self.app_id = config.get('app_id')
                    self.app_secret = config.get('app_secret')
        except Exception as e:
            print(f"读取配置文件失败: {e}")
            self.app_id = None
            self.app_secret = None
    
    def load_user_info(self):
        """加载用户信息"""
        config_file = 'feishu_config.json'
        try:
            if os.path.exists(config_file):
                with open(config_file, 'r', encoding='utf-8') as f:
                    config = json.load(f)
                    self.current_user_id = config.get('current_user_id')
                    self.assignee_user_id = config.get('assignee_user_id')
                    
                    if self.current_user_id:
                        print(f"✅ 已加载当前用户ID: {self.current_user_id}")
                    if self.assignee_user_id:
                        print(f"✅ 已加载负责人用户ID: {self.assignee_user_id}")
        except Exception as e:
            print(f"读取用户信息失败: {e}")
    
    def get_tenant_access_token(self):
        """获取租户访问令牌"""
        if not self.app_id or not self.app_secret:
            print("❌ 缺少应用凭证")
            return False
            
        url = "https://open.feishu.cn/open-apis/auth/v3/tenant_access_token/internal"
        headers = {"Content-Type": "application/json"}
        data = {
            "app_id": self.app_id,
            "app_secret": self.app_secret
        }
        
        try:
            response = requests.post(url, headers=headers, json=data)
            result = response.json()
            if result.get('code') == 0:
                self.tenant_access_token = result['tenant_access_token']
                return True
            else:
                print(f"获取tenant_access_token失败: {result}")
                return False
        except Exception as e:
            print(f"获取tenant_access_token异常: {e}")
            return False
    
    def create_task(self, title, description="", due_date=None, followers=None, assignees=None):
        """创建任务
        
        Args:
            title: 任务标题
            description: 任务描述
            due_date: 截止日期（时间戳）
            followers: 关注人列表
            assignees: 负责人列表
        """
        if not self.tenant_access_token:
            if not self.get_tenant_access_token():
                return None
        
        url = "https://open.feishu.cn/open-apis/task/v2/tasks"
        headers = {
            "Authorization": f"Bearer {self.tenant_access_token}",
            "Content-Type": "application/json"
        }
        
        data = {
            "summary": title,
            "description": description
        }
        
        if due_date:
            data["due"] = {"timestamp": due_date}
        
        # 根据飞书API示例，使用members字段设置负责人
        members = []
        
        # 使用指定的负责人用户ID
        if self.assignee_user_id:
            members.append({
                "id": self.assignee_user_id,
                "type": "user",
                "role": "assignee"
            })
        elif self.current_user_id:
            members.append({
                "id": self.current_user_id,
                "type": "user", 
                "role": "assignee"
            })
        
        if members:
            data["members"] = members
        
        print(f"📋 创建任务: {title}")
        print(f"   负责人: {len(members)}")
        
        try:
            response = requests.post(url, headers=headers, json=data)
            result = response.json()
            if result.get('code') == 0:
                task_data = result['data']['task']
                task_id = task_data.get('task_id') or task_data.get('id') or task_data.get('guid')
                if task_id:
                    print(f"✅ 任务创建成功，ID: {task_id}")
                    return task_id
                else:
                    print(f"❌ 无法获取任务ID，响应数据: {task_data}")
                    return None
            else:
                print(f"❌ 创建任务失败: {result}")
                return None
        except Exception as e:
            print(f"❌ 创建任务异常: {e}")
            return None
    
    def complete_task(self, task_id):
        """完成任务
        
        Args:
            task_id: 可以是task_id（t开头）或guid（uuid格式）
        """
        if not self.tenant_access_token:
            if not self.get_tenant_access_token():
                return False
        
        # 如果task_id是task_id格式（t开头），需要转换为guid
        task_guid = task_id
        if task_id.startswith('t'):
            print(f"⚠️  需要task_id到guid的映射")
            return False
        
        url = f"https://open.feishu.cn/open-apis/task/v2/tasks/{task_guid}"
        headers = {
            "Authorization": f"Bearer {self.tenant_access_token}",
            "Content-Type": "application/json"
        }
        
        import time
        data = {
            "task": {
                "completed_at": str(int(time.time() * 1000))  # 当前时间戳（毫秒）
            },
            "update_fields": ["completed_at"]
        }
        
        try:
            response = requests.patch(url, headers=headers, json=data)
            response_text = response.text
            print(f"完成任务API响应: {response_text}")
            
            if response.status_code != 200:
                print(f"HTTP错误: {response.status_code}")
                return False
            
            try:
                result = response.json()
                if result.get('code') == 0:
                    print("✅ 任务完成成功")
                    return True
                else:
                    print(f"完成任务失败: {result}")
                    return False
            except json.JSONDecodeError as e:
                print(f"JSON解析错误: {e}")
                return False
        except Exception as e:
            print(f"完成任务异常: {e}")
            return False

def main():
    manager = FeishuTaskManager()
    
    if len(sys.argv) < 2:
        print("Usage: feishu_task_integration.py [create|complete] [args...]")
        return
    
    action = sys.argv[1]
    
    if action == 'create' and len(sys.argv) > 2:
        title = sys.argv[2]
        task_id = manager.create_task(title)
        if task_id:
            print(f"任务创建成功，ID: {task_id}")
        else:
            print("任务创建失败")
    
    elif action == 'complete' and len(sys.argv) > 2:
        task_id = sys.argv[2]
        if manager.complete_task(task_id):
            print(f"任务 {task_id} 已完成")
        else:
            print(f"任务 {task_id} 完成失败")
    
    else:
        print("无效的命令")

if __name__ == '__main__':
    main()

path: scripts/todo_handler.py
content: #!/usr/bin/env python3
import json
import os
import sys
import requests
from datetime import datetime, date

class TodoHandlerV2:
    def __init__(self):
        self.todo_file = '/home/gary/.openclaw/workspace/todo_data.json'
        self.feishu_enabled = False  # 暂时禁用飞书集成
        self.load_data()
    
    def load_data(self):
        if os.path.exists(self.todo_file):
            with open(self.todo_file, 'r', encoding='utf-8') as f:
                self.data = json.load(f)
        else:
            self.data = {'todos': [], 'completed': [], 'current_date': str(date.today())}
    
    def save_data(self):
        with open(self.todo_file, 'w', encoding='utf-8') as f:
            json.dump(self.data, f, ensure_ascii=False, indent=2)
    
    def process_command(self, message):
        """处理todo命令"""
        message = message.strip()
        
        if message == 'todo':
            return self.show_all()
        elif message.startswith('todo'):
            content = message[4:].strip()
            if content:
                return self.add_todo(content)
            else:
                return self.show_all()
        elif message.startswith('done'):
            try:
                todo_id = int(message[4:].strip())
                return self.complete_todo(todo_id)
            except ValueError:
                return "❌ 无效的任务序号"
        else:
            return "❌ 未知命令"
    
    def add_todo(self, content):
        """添加待办事项"""
        today = str(date.today())
        
        # 新的一天重置序号
        if self.data['current_date'] != today:
            self.data['current_date'] = today
            old_todos = self.data['todos']
            self.data['todos'] = []
            for i, todo in enumerate(old_todos):
                if not todo['completed']:
                    self.data['todos'].append({
                        'id': i,
                        'content': todo['content'],
                        'created_at': datetime.now().strftime('%Y-%m-%d %H:%M:%S'),
                        'completed': False
                    })
        
        todo_id = len(self.data['todos'])
        
        # 解析截止时间
        due_date = self.parse_due_date(content)
        
        # 尝试添加到飞书任务
        feishu_result = self.add_to_feishu_task(content, due_date)
        
        new_todo = {
            'id': todo_id,
            'content': content,
            'created_at': datetime.now().strftime('%Y-%m-%d %H:%M:%S'),
            'completed': False,
            'feishu_task_id': feishu_result.get('task_id'),
            'feishu_guid': feishu_result.get('guid'),
            'feishu_status': feishu_result.get('status', 'failed')
        }
        self.data['todos'].append(new_todo)
        self.save_data()
        
        if feishu_result.get('success'):
            return f"✅ 待办事项已添加并同步到飞书任务，ID: {feishu_result['task_id']}"
        else:
            return f"✅ 待办事项已添加（飞书同步待配置），序号：{todo_id}"
    
    def add_to_feishu_task(self, content, due_date=None):
        """添加到飞书任务"""
        try:
            from feishu_task_integration import FeishuTaskManager
            import requests
            import time
            
            manager = FeishuTaskManager()
            
            # 直接调用API创建任务并获取完整响应
            if not manager.get_tenant_access_token():
                return {
                    'success': False,
                    'task_id': None,
                    'guid': None,
                    'status': 'auth_failed'
                }
            
            url = "https://open.feishu.cn/open-apis/task/v2/tasks"
            headers = {
                "Authorization": f"Bearer {manager.tenant_access_token}",
                "Content-Type": "application/json"
            }
            
            data = {
                "summary": content,
                "description": f"来自力工助手的待办事项\n创建时间: {self.get_current_time()}"
            }
            
            # 添加截止时间（如果提供了的话）
            if due_date:
                data["due"] = {"timestamp": due_date}
            else:
                # 默认设置为3天后
                default_due = int(time.time() * 1000) + (3 * 24 * 60 * 60 * 1000)
                data["due"] = {"timestamp": default_due}
            
            # 根据飞书API示例，使用members字段设置负责人
            members = []
            
            # 使用指定的负责人用户ID
            if hasattr(manager, 'assignee_user_id') and manager.assignee_user_id:
                members.append({
                    "id": manager.assignee_user_id,
                    "type": "user",
                    "role": "assignee"
                })
            else:
                # 默认使用当前用户
                members.append({
                    "id": manager.current_user_id,
                    "type": "user", 
                    "role": "assignee"
                })
            
            data["members"] = members
            
            response = requests.post(url, headers=headers, json=data)
            result = response.json()
            
            if result.get('code') == 0:
                task_data = result['data']['task']
                task_id = task_data.get('task_id')
                guid = task_data.get('guid')
                
                print(f"✅ 任务创建成功，task_id: {task_id}, guid: {guid}")
                
                return {
                    'success': True,
                    'task_id': task_id,
                    'guid': guid,
                    'status': 'created_with_yangbin'
                }
            else:
                print(f"❌ 任务创建失败: {result}")
                return {
                    'success': False,
                    'task_id': None,
                    'guid': None,
                    'status': 'creation_failed'
                }
                
        except Exception as e:
            print(f"飞书任务创建异常: {e}")
            return {
                'success': False,
                'task_id': None,
                'guid': None,
                'status': 'error'
            }
    
    def get_task_guid(self, manager, task_id):
        """获取任务的guid - 通过创建任务时的响应获取"""
        try:
            # 由于我们已经有了创建任务时的完整响应，可以直接从中提取guid
            # 这里是一个临时方案，在实际应用中应该保存创建时的完整响应
            
            # 尝试通过API获取任务详情
            url = f"https://open.feishu.cn/open-apis/task/v2/tasks/{task_id}"
            headers = {
                "Authorization": f"Bearer {manager.tenant_access_token}",
                "Content-Type": "application/json"
            }
            
            response = requests.get(url, headers=headers)
            print(f"获取任务详情响应: {response.text}")
            
            if response.status_code == 200:
                result = response.json()
                if result.get('code') == 0:
                    return result['data']['task']['guid']
            else:
                print(f"获取任务详情失败: HTTP {response.status_code}")
            
            return None
        except Exception as e:
            print(f"获取任务guid异常: {e}")
            return None
    
    def parse_due_date(self, content):
        """解析截止时间"""
        import time
        import re
        from datetime import datetime, timedelta
        
        # 检查是否包含时间关键词
        content_lower = content.lower()
        
        # 今天
        if '今天' in content_lower:
            return int(time.time() * 1000)
        
        # 明天
        elif '明天' in content_lower:
            tomorrow = datetime.now() + timedelta(days=1)
            return int(tomorrow.timestamp() * 1000)
        
        # 本周
        elif '本周' in content_lower:
            # 计算本周日
            today = datetime.now()
            days_to_sunday = 6 - today.weekday()
            this_week = today + timedelta(days=days_to_sunday)
            return int(this_week.timestamp() * 1000)
        
        # 下周
        elif '下周' in content_lower:
            # 计算下周日
            today = datetime.now()
            days_to_next_sunday = 13 - today.weekday()
            next_week = today + timedelta(days=days_to_next_sunday)
            return int(next_week.timestamp() * 1000)
        
        # 本月
        elif '本月' in content_lower:
            # 计算本月最后一天
            today = datetime.now()
            if today.month == 12:
                last_day = datetime(today.year + 1, 1, 1) - timedelta(days=1)
            else:
                last_day = datetime(today.year, today.month + 1, 1) - timedelta(days=1)
            return int(last_day.timestamp() * 1000)
        
        # 默认3天后
        else:
            default_due = datetime.now() + timedelta(days=3)
            return int(default_due.timestamp() * 1000)
    
    def get_current_time(self):
        """获取当前时间"""
        from datetime import datetime
        return datetime.now().strftime('%Y-%m-%d %H:%M:%S')
    
    def complete_todo(self, todo_id):
        """完成待办事项"""
        for todo in self.data['todos']:
            if todo['id'] == todo_id and not todo['completed']:
                todo['completed'] = True
                todo['completed_at'] = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
                
                # 尝试同步到飞书任务
                if todo.get('feishu_task_id'):
                    feishu_guid = todo.get('feishu_guid')
                    self.complete_feishu_task(todo['feishu_task_id'], feishu_guid)
                
                self.data['completed'].append(todo.copy())
                self.save_data()
                return f"✅ 待办事项 {todo_id} 已标记为完成"
        return f"❌ 未找到待办事项 {todo_id}"
    
    def complete_feishu_task(self, task_id, guid=None):
        """完成飞书任务"""
        try:
            from feishu_task_integration import FeishuTaskManager
            
            manager = FeishuTaskManager()
            
            # 优先使用guid，如果没有则使用task_id
            task_identifier = guid if guid else task_id
            success = manager.complete_task(task_identifier)
            
            if success:
                print(f"✅ 飞书任务 {task_id} 已完成")
                return True
            else:
                print(f"❌ 飞书任务 {task_id} 完成失败")
                return False
                
        except Exception as e:
            print(f"飞书任务完成异常: {e}")
            return False
    
    def show_all(self):
        """显示所有待办和已完成事项"""
        pending = [todo for todo in self.data['todos'] if not todo['completed']]
        today = str(date.today())
        completed_today = [todo for todo in self.data['completed'] 
                          if todo.get('completed_at', '').startswith(today)]
        
        response = f"📋 **待办事项报告** | {datetime.now().strftime('%Y-%m-%d %H:%M')}\n\n"
        
        if pending:
            response += "📌 **待办事项**\n"
            for todo in pending:
                feishu_status = "" if todo.get('feishu_status') == 'failed' else " 📌飞书"
                response += f"{todo['id']}. {todo['content']}{feishu_status}\n"
        else:
            response += "✅ **暂无待办事项**\n"
        
        if completed_today:
            response += "\n🎉 **今日已完成**\n"
            for todo in completed_today:
                response += f"✅ {todo['content']}\n"
        
        response += "\n🤖 **力工助手** | 飞书任务集成（开发中）"
        return response

def main():
    if len(sys.argv) > 1:
        handler = TodoHandlerV2()
        result = handler.process_command(sys.argv[1])
        print(result)
    else:
        print("需要提供命令参数")

if __name__ == '__main__':
    main()

path: assets/feishu_config_template.json
content: app_id: cli_your_app_id_here
app_secret: your_app_secret_here
assignee_user_id: ou_your_user_id_here

Security scan verdicts — ClawScan: suspicious | static analysis: clean | VirusTotal: suspicious | SkillSpector: suspicious (CRITICAL)