新增了完整的Confluence集成插件,包含以下核心功能: 1. 基础认证与配置管理,支持API Token和OAuth2两种认证方式 2. 评论去重、权限控制与提及解析 3. 知识库检索与页面内容处理 4. 评论收发、编辑删除与流式回复支持 5. 附件与页面标签管理 6. 内容属性存储与AI元数据管理 7. Webhook事件接收与处理 8. 完整的插件配置与状态检查
92 lines
3.3 KiB
Python
92 lines
3.3 KiB
Python
import logging
|
|
from datetime import datetime, UTC
|
|
|
|
from yuxi.channel.extensions.confluence.gateway import ConfluenceGateway
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
|
|
class ContentPropertyStore:
|
|
NAMESPACE = "forcepilot_ai"
|
|
|
|
def __init__(self, gateway: ConfluenceGateway):
|
|
self._gateway = gateway
|
|
|
|
async def _get_properties(self, page_id: str, account_id: str = "default") -> list[dict]:
|
|
client = self._gateway.get_client(account_id)
|
|
if client is None:
|
|
return []
|
|
try:
|
|
result = await client._request("GET", f"/wiki/api/v2/pages/{page_id}/properties")
|
|
return result.get("results", [])
|
|
except Exception as e:
|
|
logger.error("Failed to get properties for page %s: %s", page_id, e)
|
|
return []
|
|
|
|
async def _set(
|
|
self, page_id: str, key: str, value: dict, account_id: str = "default",
|
|
) -> dict | None:
|
|
client = self._gateway.get_client(account_id)
|
|
if client is None:
|
|
return None
|
|
try:
|
|
return await client._request(
|
|
"POST",
|
|
f"/wiki/api/v2/pages/{page_id}/properties",
|
|
json={"key": key, "value": value},
|
|
)
|
|
except Exception as e:
|
|
logger.error("Failed to set property '%s' for page %s: %s", key, page_id, e)
|
|
return None
|
|
|
|
async def _delete(
|
|
self, page_id: str, property_id: str, account_id: str = "default",
|
|
) -> bool:
|
|
client = self._gateway.get_client(account_id)
|
|
if client is None:
|
|
return False
|
|
try:
|
|
await client._request(
|
|
"DELETE", f"/wiki/api/v2/pages/{page_id}/properties/{property_id}",
|
|
)
|
|
return True
|
|
except Exception as e:
|
|
logger.error("Failed to delete property %s from page %s: %s", property_id, page_id, e)
|
|
return False
|
|
|
|
async def mark_processed(self, page_id: str, processor: str, account_id: str = "default") -> dict | None:
|
|
return await self._set(
|
|
page_id,
|
|
f"{self.NAMESPACE}.{processor}.processed_at",
|
|
{"timestamp": datetime.now(tz=UTC).isoformat()},
|
|
account_id,
|
|
)
|
|
|
|
async def store_summary(self, page_id: str, summary: str, account_id: str = "default") -> dict | None:
|
|
return await self._set(
|
|
page_id,
|
|
f"{self.NAMESPACE}.summary",
|
|
{"text": summary},
|
|
account_id,
|
|
)
|
|
|
|
async def get_ai_metadata(self, page_id: str, account_id: str = "default") -> dict:
|
|
properties = await self._get_properties(page_id, account_id)
|
|
metadata = {}
|
|
for prop in properties:
|
|
key = prop.get("key", "")
|
|
if key.startswith(self.NAMESPACE):
|
|
metadata[key] = prop.get("value", {})
|
|
return metadata
|
|
|
|
async def clear_ai_metadata(self, page_id: str, account_id: str = "default") -> bool:
|
|
properties = await self._get_properties(page_id, account_id)
|
|
success = True
|
|
for prop in properties:
|
|
key = prop.get("key", "")
|
|
prop_id = prop.get("id")
|
|
if key.startswith(self.NAMESPACE) and prop_id:
|
|
if not await self._delete(page_id, prop_id, account_id):
|
|
success = False
|
|
return success
|