#!/usr/bin/env python3 # -*- coding: utf-8 -*- """ 飞书机器人消息接收与处理脚本 接收飞书消息,解析内容,调用 WordPress 发布脚本 支持 AI 图片生成(含格式和尺寸控制) """ import os import sys import json import time import logging from datetime import datetime # 添加项目根目录到 Python 路径 BASE_DIR = os.path.dirname(os.path.abspath(__file__)) sys.path.insert(0, BASE_DIR) # 导入飞书 API 客户端 from modules.feishu_api import create_feishu_client # 分类映射(slug -> ID) CATEGORY_MAP = { 'ai-kepu': 12, 'ai-zixun': 11, 'geo': 16, 'ai': 9, 'jishu': 5, 'fenxiang': 10, 'wenzhang': 4, 'zaji': 8, 'suibi': 7, 'guanyu': 1 } # 尺寸快捷方式 SIZE_PRESETS = { '正方形': '1024*1024', '横图': '1280*720', '竖图': '720*1280', '宽屏': '1440*720', '手机': '720*1440', '小图': '512*512' } # 配置日志 LOG_DIR = os.path.join(BASE_DIR, 'logs') os.makedirs(LOG_DIR, exist_ok=True) logging.basicConfig( level=logging.INFO, format='%(asctime)s - %(name)s - %(levelname)s - %(message)s', handlers=[ logging.FileHandler(os.path.join(LOG_DIR, 'feishu_bot.log'), encoding='utf-8'), logging.StreamHandler() ] ) logger = logging.getLogger('feishu_bot') class FeishuBot: """飞书机器人""" def __init__(self): """初始化飞书机器人""" self.config = self._load_config() self.wp_script = os.path.join(BASE_DIR, 'scripts', 'wp_publish_text.py') self.word_script = os.path.join(BASE_DIR, 'scripts', 'wp_publish.py') self.image_gen_script = os.path.join(BASE_DIR, 'scripts', 'wp_generate_image.py') # 初始化飞书 API 客户端 self.feishu_client = create_feishu_client( app_id=self.config.get('app_id'), app_secret=self.config.get('app_secret') ) logger.info("🤖 飞书机器人初始化完成") logger.info(f" WordPress 发布脚本:{self.wp_script}") logger.info(f" Word 发布脚本:{self.word_script}") logger.info(f" AI 生图脚本:{self.image_gen_script}") logger.info(f" 飞书 API 客户端:已初始化") def _load_config(self): """加载配置""" try: from feishu_config import ( FEISHU_APP_ID, FEISHU_APP_SECRET, SERVER_HOST, SERVER_PORT, ALLOWED_USERS ) return { 'app_id': FEISHU_APP_ID, 'app_secret': FEISHU_APP_SECRET, 'host': SERVER_HOST, 'port': SERVER_PORT, 'allowed_users': ALLOWED_USERS } except ImportError: logger.warning("未找到 feishu_config.py,使用默认配置") return { 'app_id': '', 'app_secret': '', 'host': '0.0.0.0', 'port': 8080, 'allowed_users': [] } def process_message(self, message): """ 处理接收到的消息 Args: message: 飞书消息对象 Returns: str: 回复消息 """ try: # 解析消息内容 msg_type = message.get('msg_type', '') content = message.get('content', '') sender_id = message.get('sender', {}).get('sender_id', '') message_id = message.get('message_id', '') chat_id = message.get('chat_id', '') logger.info(f"📨 收到消息 - 类型:{msg_type}, 发送者:{sender_id}, 消息 ID: {message_id}") # 检查权限 if self.config['allowed_users'] and sender_id not in self.config['allowed_users']: return "⚠️ 您没有权限使用此机器人" # 处理不同类型的消息 if msg_type == 'text': return self._handle_text_message(content, sender_id, message_id, chat_id) elif msg_type == 'image': return self._handle_image_message(content, sender_id, message_id, chat_id) elif msg_type == 'file': return self._handle_file_message(content, sender_id, message_id, chat_id) elif msg_type == 'interactive': return self._handle_interactive_message(content, sender_id, message_id, chat_id) else: return f"📝 暂不支持的消息类型:{msg_type}" except Exception as e: logger.error(f"❌ 处理消息失败:{str(e)}", exc_info=True) return f"❌ 处理消息失败:{str(e)}" def _handle_text_message(self, content, sender_id, message_id=None, chat_id=None): """ 处理文字消息 Args: content: 消息内容 sender_id: 发送者 ID message_id: 消息 ID(用于获取图片) chat_id: 聊天 ID Returns: str: 回复消息 """ logger.info(f"📝 处理文字消息") # 解析指令 instruction = self._parse_instruction(content) # 获取消息中的图片(如果有) images = [] if message_id: images = self._get_message_images(message_id) # 检查是否为生图指令 if instruction.get('action') == 'generate_image': return self._generate_image( prompt=instruction.get('prompt', ''), count=instruction.get('image_count', 1), model=instruction.get('image_model', None), size=instruction.get('image_size', None), style=instruction.get('image_style', None), image_format=instruction.get('image_format', None) ) # 检查是否为发布+生图指令 elif instruction.get('action') == 'publish_with_image': return self._publish_with_generated_image( text=instruction.get('text', ''), title=instruction.get('title', ''), category=instruction.get('category', ''), tags=instruction.get('tags', ''), status=instruction.get('status', 'publish'), image_count=instruction.get('image_count', 1), model=instruction.get('image_model', None), size=instruction.get('image_size', None), style=instruction.get('image_style', None), image_format=instruction.get('image_format', None) ) # 检查是否为发布指令 elif instruction.get('action') == 'publish': return self._publish_article( text=instruction.get('text', ''), title=instruction.get('title', ''), category=instruction.get('category', ''), tags=instruction.get('tags', ''), status=instruction.get('status', 'publish'), images=images if images else None ) elif instruction.get('action') == 'update': return self._update_article( target=instruction.get('target', ''), text=instruction.get('text', ''), title=instruction.get('title', ''), status=instruction.get('status', 'publish') ) elif instruction.get('action') == 'help': return self._get_help_message() elif instruction.get('action') == 'status': return self._get_status_message() else: # 默认发布 return self._publish_article(text=content, images=images if images else None) def _get_message_images(self, message_id): """ 获取消息中的图片列表 Args: message_id: 消息 ID Returns: list: 图片本地路径列表 """ if not message_id: return [] logger.info(f"🔍 获取消息图片 - Message ID: {message_id}") try: # 使用飞书 API 客户端获取图片 images = self.feishu_client.get_message_images(message_id) if not images: logger.info("消息中没有图片") return [] # 下载所有图片 downloaded_images = [] for img in images: image_key = img.get('image_key', '') if image_key: image_path = self._download_image(image_key) if image_path: downloaded_images.append(image_path) logger.info(f"✅ 图片下载成功:{image_path}") else: logger.error(f"❌ 图片下载失败:{image_key}") logger.info(f"📊 共下载 {len(downloaded_images)} 张图片") return downloaded_images except Exception as e: logger.error(f"获取消息图片失败:{str(e)}") return [] def _handle_image_message(self, content, sender_id, message_id=None, chat_id=None): """ 处理图片消息 Args: content: 消息内容 sender_id: 发送者 ID message_id: 消息 ID(用于获取图片) chat_id: 聊天 ID Returns: str: 回复消息 """ logger.info(f"🖼️ 处理图片消息") try: image_key = json.loads(content).get('image_key', '') # 下载图片 image_path = self._download_image(image_key) if image_path: # 发布带图片的文章(保留原始文字内容) return self._publish_article( text="图片文章", # 默认文字,如果有文字消息会保留 images=[image_path], message_id=message_id, chat_id=chat_id ) else: return "❌ 图片下载失败" except Exception as e: logger.error(f"处理图片消息失败:{str(e)}") return f"❌ 处理图片消息失败:{str(e)}" def _handle_file_message(self, content, sender_id, message_id=None, chat_id=None): """ 处理文件消息 Args: content: 消息内容 sender_id: 发送者 ID message_id: 消息 ID chat_id: 聊天 ID Returns: str: 回复消息 """ logger.info(f"📁 处理文件消息") try: file_info = json.loads(content) file_key = file_info.get('file_key', '') file_name = file_info.get('file_name', '') # 检查是否为 Word 文档 if not file_name.endswith('.docx'): return "⚠️ 仅支持 .docx 格式的 Word 文档" # 下载文件 file_path = self._download_file(file_key, file_name) if file_path: # 发布 Word 文档 return self._publish_word_document(file_path) else: return "❌ 文件下载失败" except Exception as e: logger.error(f"处理文件消息失败:{str(e)}") return f"❌ 处理文件消息失败:{str(e)}" def _handle_interactive_message(self, content, sender_id, message_id=None, chat_id=None): """ 处理交互式消息 Args: content: 消息内容 sender_id: 发送者 ID message_id: 消息 ID chat_id: 聊天 ID Returns: str: 回复消息 """ logger.info(f"🔄 处理交互式消息") try: data = json.loads(content) action = data.get('action', '') if action == 'publish': return self._publish_article( text=data.get('text', ''), title=data.get('title', ''), category=data.get('category', '') ) else: return f"⚠️ 未知的交互动作:{action}" except Exception as e: logger.error(f"处理交互式消息失败:{str(e)}") return f"❌ 处理交互式消息失败:{str(e)}" def _parse_instruction(self, content): """ 解析消息指令 Args: content: 消息内容 Returns: dict: 解析结果 """ instruction = { 'action': 'publish', # 默认动作:发布 'text': '', 'title': '', 'category': '', 'tags': '', 'status': 'publish', 'prompt': '', 'image_count': 1, 'image_model': None, 'image_size': None, 'image_style': None, 'image_format': None } lines = content.strip().split('\n') text_lines = [] for line in lines: line = line.strip() # 解析指令 if line.startswith('#标题'): instruction['title'] = line.replace('#标题', '').strip() elif line.startswith('#分类') or line.startswith('#category'): instruction['category'] = line.replace('#分类', '').replace('#category', '').strip() elif line.startswith('#标签') or line.startswith('#tag'): instruction['tags'] = line.replace('#标签', '').replace('#tag', '').strip() elif line.startswith('#状态') or line.startswith('#status'): status = line.replace('#状态', '').replace('#status', '').strip().lower() if status in ['publish', 'draft', 'pending', 'private']: instruction['status'] = status elif line.startswith('#发布'): instruction['action'] = 'publish' elif line.startswith('#草稿'): instruction['status'] = 'draft' instruction['action'] = 'publish' elif line.startswith('#帮助') or line.startswith('#help'): instruction['action'] = 'help' elif line.startswith('#状态') or line.startswith('#status'): instruction['action'] = 'status' elif line.startswith('#更新') or line.startswith('#update'): instruction['action'] = 'update' instruction['target'] = line.replace('#更新', '').replace('#update', '').strip() # AI 生图指令 elif line.startswith('#生图') or line.startswith('#生成图片'): instruction['action'] = 'generate_image' prompt_text = line.replace('#生图', '').replace('#生成图片', '').strip() instruction['prompt'] = prompt_text elif line.startswith('#生图数量') or line.startswith('#图片数量'): try: count = int(line.replace('#生图数量', '').replace('#图片数量', '').strip()) instruction['image_count'] = min(max(count, 1), 4) except ValueError: pass elif line.startswith('#生图模型') or line.startswith('#图片模型'): model = line.replace('#生图模型', '').replace('#图片模型', '').strip() instruction['image_model'] = model elif line.startswith('#生图尺寸') or line.startswith('#图片尺寸'): size = line.replace('#生图尺寸', '').replace('#图片尺寸', '').strip() # 支持快捷方式 if size in SIZE_PRESETS: instruction['image_size'] = SIZE_PRESETS[size] else: instruction['image_size'] = size elif line.startswith('#生图风格') or line.startswith('#图片风格'): style = line.replace('#生图风格', '').replace('#图片风格', '').strip() instruction['image_style'] = style elif line.startswith('#生图格式') or line.startswith('#图片格式'): fmt = line.replace('#生图格式', '').replace('#图片格式', '').strip().lower() if fmt in ['jpg', 'png', 'webp']: instruction['image_format'] = fmt # 发布+生图指令 elif line.startswith('#发布并生图') or line.startswith('#发布+生图'): instruction['action'] = 'publish_with_image' else: text_lines.append(line) instruction['text'] = '\n'.join(text_lines) return instruction def _resolve_category(self, category_slug): """ 将分类 slug 转换为 ID Args: category_slug: 分类 slug Returns: int: 分类 ID """ if not category_slug: return None # 先尝试直接匹配 slug = category_slug.lower().strip() if slug in CATEGORY_MAP: return CATEGORY_MAP[slug] # 尝试模糊匹配 for key, value in CATEGORY_MAP.items(): if slug in key or key in slug: return value # 如果输入的是数字,直接返回 try: return int(slug) except ValueError: pass # 默认返回随笔分类 logger.warning(f"未找到分类:{category_slug},使用默认分类") return CATEGORY_MAP.get('suibi', 7) def _publish_article(self, text='', title='', category='', tags='', images=None, status='publish', message_id=None, chat_id=None): """ 发布文章(直接调用 Python 函数,避免 shell 引号问题) Args: text: 文章正文 title: 文章标题 category: 分类 tags: 标签 images: 图片列表 status: 发布状态 message_id: 消息 ID chat_id: 聊天 ID Returns: str: 回复消息 """ if not text: return "⚠️ 文章内容不能为空" logger.info(f"📝 准备发布文章 - 标题:{title}, 分类:{category}") try: # 直接导入并调用 Python 函数(避免 subprocess 的 shell 转义问题) from scripts.wp_publish_text import publish_text_with_images # 解析分类(如果是 slug 需要转换为 ID) category_id = self._resolve_category(category) if category else None # 调用发布函数 publish_result = publish_text_with_images( text=text, images=images, instruction=f"#分类 {category}" if category else None, status=status, category_id=category_id, title=title if title else None ) # 处理结果 if publish_result.get('success'): post_url = publish_result.get('post_url', '') post_id = publish_result.get('post_id', '') reply = "✅ 文章发布成功!\n" reply += f"📝 标题:{publish_result.get('title', title or '自动提取')}\n" reply += f"🔗 链接:{post_url}\n" reply += f"📊 文章 ID:{post_id}" if publish_result.get('images_uploaded', 0) > 0: reply += f"\n🖼️ 已上传图片:{publish_result['images_uploaded']} 张" return reply else: error_msg = publish_result.get('error', '未知错误') return f"❌ 发布失败:{error_msg}" except Exception as e: logger.error(f"发布文章失败:{str(e)}", exc_info=True) return f"❌ 发布失败:{str(e)}" def _publish_with_generated_image(self, text='', title='', category='', tags='', status='publish', image_count=1, model=None, size=None, style=None, image_format=None): """ 发布文章并自动生成配图 Args: text: 文章正文 title: 文章标题 category: 分类 tags: 标签 status: 发布状态 image_count: 生成图片数量 model: 生图模型 size: 图片尺寸 style: 图片风格 image_format: 图片格式 Returns: str: 回复消息 """ if not text and not title: return "⚠️ 请提供文章标题或内容" logger.info(f"📝 准备发布文章(含 AI 配图)- 标题:{title}") try: # 加载配置获取 API Key config = self._load_image_gen_config() if not config.get('dashscope_api_key'): return "⚠️ 未配置 DashScope API Key,无法生成图片\n\n请在 config.py 中配置 dashscope_api_key" # 生成图片 from scripts.wp_generate_image import generate_images_for_article pl = logger pl.info(f"🎨 开始生成 AI 配图...") image_result = generate_images_for_article( title=title or '自动提取', content=text, count=image_count, api_key=config.get('dashscope_api_key'), image_format=image_format ) if not image_result.get('success'): return f"⚠️ AI 配图生成失败:{image_result.get('error', '未知错误')}\n\n文章仍可发布,但不含配图。" image_paths = image_result.get('paths', []) pl.info(f"✅ 已生成 {len(image_paths)} 张配图") # 发布文章(带图片) from scripts.wp_publish_text import publish_text_with_images category_id = self._resolve_category(category) if category else None publish_result = publish_text_with_images( text=text, images=image_paths, instruction=f"#分类 {category}" if category else None, status=status, category_id=category_id, title=title if title else None ) # 处理结果 if publish_result.get('success'): post_url = publish_result.get('post_url', '') post_id = publish_result.get('post_id', '') reply = "✅ 文章发布成功(含 AI 配图)!\n" reply += f"📝 标题:{publish_result.get('title', title or '自动提取')}\n" reply += f"🔗 链接:{post_url}\n" reply += f"📊 文章 ID:{post_id}\n" reply += f"🎨 AI 配图:{len(image_paths)} 张" return reply else: error_msg = publish_result.get('error', '未知错误') return f"❌ 发布失败:{error_msg}" except Exception as e: logger.error(f"发布文章(含 AI 配图)失败:{str(e)}", exc_info=True) return f"❌ 发布失败:{str(e)}" def _generate_image(self, prompt='', count=1, model=None, size=None, style=None, image_format=None): """ 生成 AI 图片 Args: prompt: 图片描述 count: 生成数量 model: 模型名称 size: 图片尺寸 style: 图片风格 image_format: 图片格式 Returns: str: 回复消息 """ if not prompt: return "⚠️ 请提供图片描述\n\n示例:`#生图 一只可爱的猫咪在草地上晒太阳`" logger.info(f"🎨 开始 AI 生图 - 描述:{prompt}") try: # 加载配置获取 API Key config = self._load_image_gen_config() if not config.get('dashscope_api_key'): return "⚠️ 未配置 DashScope API Key,无法生成图片\n\n请在 config.py 中配置 dashscope_api_key" # 调用生图脚本 from scripts.wp_generate_image import generate_image result = generate_image( prompt=prompt, api_key=config.get('dashscope_api_key'), model=model, size=size, count=count, style=style, image_format=image_format ) if result.get('success'): paths = result.get('paths', []) reply = f"✅ AI 生图完成!成功生成 {len(paths)} 张图片\n" reply += f"📊 模型:{result.get('model', 'wanx-v1')}\n" reply += f"📐 尺寸:{result.get('size', '1024*1024')}\n" reply += f"🖼️ 格式:{result.get('format', 'webp')}\n\n" reply += "📁 本地路径:\n" for i, path in enumerate(paths): reply += f" {i+1}. {path}\n" return reply else: error_msg = result.get('error', '未知错误') return f"❌ AI 生图失败:{error_msg}" except Exception as e: logger.error(f"AI 生图失败:{str(e)}", exc_info=True) return f"❌ AI 生图失败:{str(e)}" def _load_image_gen_config(self): """加载图片生成配置""" config = { 'dashscope_api_key': '', 'image_model': 'wanx-v1', 'image_size': '1024*1024', 'image_format': 'webp', 'image_count': 1 } config_file = os.path.join(BASE_DIR, 'config.py') if os.path.exists(config_file): try: with open(config_file, 'r', encoding='utf-8') as f: exec(f.read(), config) except Exception as e: logger.warning(f"加载配置文件失败:{str(e)}") return config def _update_article(self, target='', text='', title='', status='publish'): """ 更新已有文章(追加内容模式) Args: target: 文章 ID 或标题关键词 text: 新增内容 title: 新标题(可选) status: 发布状态 Returns: str: 回复消息 """ if not target: return "⚠️ 请指定文章 ID 或标题,例如:\n`#更新 12345`\n`#更新 文章标题`" if not text: return "⚠️ 更新内容不能为空" logger.info(f"🔄 准备更新文章 - 目标:{target}") try: from scripts.wp_publish_text import update_post_with_text result = update_post_with_text( target=target, new_text=text, new_title=title if title else None, status=status ) if result.get('success'): reply = "✅ 文章更新成功!\n" reply += f"📝 标题:{result.get('title')}\n" reply += f"🔗 链接:{result.get('post_url')}\n" reply += f"📊 文章 ID:{result.get('post_id')}" return reply else: return f"❌ 更新失败:{result.get('error')}" except Exception as e: logger.error(f"更新文章失败:{str(e)}", exc_info=True) return f"❌ 更新失败:{str(e)}" def _publish_word_document(self, file_path): """ 发布 Word 文档(直接调用 Python 函数) Args: file_path: Word 文档路径 Returns: str: 回复消息 """ logger.info(f"📄 准备发布 Word 文档:{file_path}") try: # 直接导入并调用 Python 函数 from scripts.wp_publish import publish_word_document # 调用发布函数 publish_result = publish_word_document(word_file_path=file_path) # 处理结果 if publish_result.get('success'): post_url = publish_result.get('post_url', '') post_id = publish_result.get('post_id', '') title = publish_result.get('title', '自动提取') reply = "✅ Word 文档发布成功!\n" reply += f"📝 标题:{title}\n" reply += f"🔗 链接:{post_url}\n" reply += f"📊 文章 ID:{post_id}" if publish_result.get('images_uploaded', 0) > 0: reply += f"\n🖼️ 已上传图片:{publish_result['images_uploaded']} 张" return reply else: error_msg = publish_result.get('error', '未知错误') return f"❌ 发布失败:{error_msg}" except Exception as e: logger.error(f"发布 Word 文档失败:{str(e)}", exc_info=True) return f"❌ 发布失败:{str(e)}" def _get_help_message(self): """ 获取帮助信息 Returns: str: 帮助消息 """ help_text = """🤖 **WordPress 发布助手 - 使用说明** 📝 **发布文字文章** 直接发送文字内容即可发布 📄 **发布 Word 文档** 发送 .docx 格式的 Word 文档 🖼️ **发布图片文章** 发送图片即可发布 🎨 **AI 图片生成**(支持格式控制) 使用 AI 生成文章配图或独立图片 --- **基础指令**: `#标题 文章标题` - 指定文章标题 `#分类 分类名` - 指定分类(如:#分类 ai) `#标签 标签名` - 指定标签 `#草稿` - 保存为草稿 `#发布` - 立即发布(默认) `#更新 ID或标题` - 更新已有文章(追加内容) --- **AI 生图指令**: `#生图 图片描述` - 生成指定描述的图片 `#生图数量 2` - 设置生成数量(1-4) `#生图模型 wanx-v1` - 选择模型 `#生图尺寸 1024*1024` - 设置尺寸(支持快捷方式) `#生图风格 写实` - 设置风格 `#生图格式 webp` - 设置格式(webp, jpg, png) **尺寸快捷方式**: - 正方形 → 1024*1024 - 横图 → 1280*720 - 竖图 → 720*1280 - 宽屏 → 1440*720 - 手机 → 720*1440 - 小图 → 512*512 **发布+生图指令**: `#发布并生图` - 发布文章并自动生成配图 (与 #标题、#分类 等指令配合使用) --- **示例**: ``` #标题 AI 发展趋势 #分类 ai 人工智能正在改变世界... ``` **AI 生图示例**: ``` #生图 一只可爱的猫咪在草地上晒太阳,高质量插画 #生图数量 2 #生图尺寸 横图 #生图格式 webp ``` **发布+生图示例**: ``` #发布并生图 #标题 AI 未来展望 #分类 ai 人工智能正在改变世界... ``` **可用分类**: - ai - 人工智能 - ai-kepu - Ai 科普 - ai-zixun - Ai 资讯 - geo - GEO - jishu - 技术资料 - fenxiang - 好物分享 - wenzhang - 文章分享 - zaji - 杂记 - suibi - 随笔(默认) 发送 `#帮助` 查看此消息""" return help_text def _get_status_message(self): """ 获取系统状态 Returns: str: 状态消息 """ status_text = f"""📊 **系统状态** - **时间**:{datetime.now().strftime('%Y-%m-%d %H:%M:%S')} - **状态**:✅ 运行中 - **WordPress**:https://www.nanlou.net - **发布脚本**:已就绪 - **AI 生图**:✅ 支持(webp/jpg/png) 发送 `#帮助` 查看使用说明""" return status_text def _download_image(self, image_key): """ 下载飞书图片到本地 Args: image_key: 图片 key Returns: str: 图片本地路径 """ if not image_key: logger.warning("图片 key 为空") return None # 使用飞书 API 客户端下载图片 save_dir = os.path.join(BASE_DIR, 'temp') image_path = self.feishu_client.download_image(image_key, save_dir) if image_path: logger.info(f"✅ 图片下载成功:{image_path}") return image_path else: logger.error("❌ 图片下载失败") return None def _download_file(self, file_key, file_name): """ 下载飞书文件到本地 Args: file_key: 文件 key file_name: 文件名 Returns: str: 文件本地路径 """ if not file_key: logger.warning("文件 key 为空") return None # 使用飞书 API 客户端下载文件 save_dir = os.path.join(BASE_DIR, 'temp') file_path = self.feishu_client.download_file(file_key, file_name, save_dir) if file_path: logger.info(f"✅ 文件下载成功:{file_path}") return file_path else: logger.error("❌ 文件下载失败") return None # 创建机器人实例 bot = FeishuBot() def handle_message(message): """ 处理消息入口函数 Args: message: 飞书消息字典 Returns: str: 回复消息 """ return bot.process_message(message) if __name__ == '__main__': # 测试模式 print("🤖 飞书机器人测试模式") print("=" * 50) # 测试文字消息 test_message = { 'msg_type': 'text', 'content': '#标题 测试文章\n#分类 ai\n这是测试内容', 'sender': {'sender_id': 'test_user'} } reply = bot.process_message(test_message) print(f"\n📨 回复:\n{reply}")