Files
aiagent/backend/app/services/notification_service.py
renjianbo 7ee80c74b2 feat: 集成飞书通知和机器人对话系统
- 新增通知系统 (notifications 表、服务、API)
- 新增飞书定时任务结果推送 (webhook + 应用消息)
- 新增飞书应用消息发送服务 (feishu_app_service)
- 新增飞书 WebSocket 长连接事件监听 (苹果应用)
- 新增飞书账号绑定/解绑 API
- 新增橙子飞书机器人 (独立 WS 连接,固定路由到橙子助手 Agent)
- 执行记录添加 schedule_id,用户添加飞书绑定字段

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-02 16:17:49 +08:00

129 lines
3.4 KiB
Python

"""通知服务 — 创建与查询系统通知"""
from __future__ import annotations
import logging
from datetime import datetime
from typing import List, Optional
from sqlalchemy.orm import Session
from app.models.notification import Notification
logger = logging.getLogger(__name__)
def create_notification(
db: Session,
user_id: str,
title: str,
content: Optional[str] = None,
category: str = "system",
ref_type: Optional[str] = None,
ref_id: Optional[str] = None,
) -> Notification:
"""创建一条通知。
Args:
db: 数据库会话
user_id: 接收用户 ID
title: 通知标题
content: 通知正文(可选)
category: 分类,如 schedule / alert / system
ref_type: 关联对象类型
ref_id: 关联对象 ID
Returns:
创建的 Notification ORM 对象
"""
notification = Notification(
user_id=user_id,
title=title,
content=content,
category=category,
ref_type=ref_type,
ref_id=ref_id,
)
db.add(notification)
db.flush()
logger.info("通知已创建: user=%s title=%s category=%s", user_id, title, category)
return notification
def get_user_notifications(
db: Session,
user_id: str,
unread_only: bool = False,
category: Optional[str] = None,
limit: int = 50,
offset: int = 0,
) -> List[Notification]:
"""获取用户的通知列表(按创建时间倒序)。
Args:
db: 数据库会话
user_id: 用户 ID
unread_only: 仅未读
category: 按分类过滤
limit: 分页大小
offset: 分页偏移
Returns:
通知列表
"""
query = db.query(Notification).filter(Notification.user_id == user_id)
if unread_only:
query = query.filter(Notification.is_read == False) # noqa: E712
if category:
query = query.filter(Notification.category == category)
return query.order_by(Notification.created_at.desc()).offset(offset).limit(limit).all()
def get_unread_count(db: Session, user_id: str) -> int:
"""获取用户未读通知数。"""
return (
db.query(Notification)
.filter(Notification.user_id == user_id, Notification.is_read == False) # noqa: E712
.count()
)
def mark_as_read(db: Session, notification_id: str, user_id: str) -> Optional[Notification]:
"""将指定通知标记为已读。"""
notification = (
db.query(Notification)
.filter(Notification.id == notification_id, Notification.user_id == user_id)
.first()
)
if not notification:
return None
notification.is_read = True
db.flush()
return notification
def mark_all_as_read(db: Session, user_id: str) -> int:
"""将用户所有通知标记为已读。返回更新的条数。"""
count = (
db.query(Notification)
.filter(Notification.user_id == user_id, Notification.is_read == False) # noqa: E712
.update({"is_read": True})
)
db.flush()
return count
def delete_notification(db: Session, notification_id: str, user_id: str) -> bool:
"""删除一条通知。"""
notification = (
db.query(Notification)
.filter(Notification.id == notification_id, Notification.user_id == user_id)
.first()
)
if not notification:
return False
db.delete(notification)
db.flush()
return True