Spaces:
Running
Running
Upload router_messages.py
Browse files- router_messages.py +44 -54
router_messages.py
CHANGED
|
@@ -9,41 +9,41 @@ from models import PrivateMessage
|
|
| 9 |
|
| 10 |
router = APIRouter()
|
| 11 |
|
| 12 |
-
# ===
|
|
|
|
|
|
|
| 13 |
class SystemAnnouncement(BaseModel):
|
| 14 |
admin_account: str
|
| 15 |
content: str
|
| 16 |
|
| 17 |
-
# ===
|
|
|
|
|
|
|
| 18 |
@router.post("/api/system/announcement")
|
| 19 |
async def publish_announcement(ann: SystemAnnouncement):
|
| 20 |
-
#
|
| 21 |
if ann.admin_account != "666666":
|
| 22 |
raise HTTPException(status_code=403, detail="无权发布系统公告")
|
| 23 |
|
| 24 |
announcements_db = db.load_data("announcements.json", default_data=[])
|
| 25 |
|
| 26 |
-
# 【防御性修复】:确保就算之前存成了别的格式,这里也强制转换为列表,防止 append 报错
|
| 27 |
-
if not isinstance(announcements_db, list):
|
| 28 |
-
announcements_db = []
|
| 29 |
-
|
| 30 |
-
# 构造一条标准的系统公告数据结构
|
| 31 |
new_ann = {
|
| 32 |
"id": f"sys_{int(time.time())}_{uuid.uuid4().hex[:6]}",
|
| 33 |
"type": "system",
|
| 34 |
"from_user": "666666",
|
| 35 |
"from_name": "官方团队",
|
| 36 |
-
"from_avatar": "https://via.placeholder.com/150/FF9800/FFFFFF?text=Sys",
|
| 37 |
"content": ann.content,
|
| 38 |
"created_at": int(time.time())
|
| 39 |
}
|
| 40 |
|
| 41 |
announcements_db.append(new_ann)
|
| 42 |
db.save_data("announcements.json", announcements_db)
|
| 43 |
-
|
| 44 |
-
return {"status": "success", "data": new_ann}
|
| 45 |
-
|
| 46 |
|
|
|
|
|
|
|
|
|
|
| 47 |
@router.post("/api/messages/private")
|
| 48 |
async def send_private_message(msg: PrivateMessage):
|
| 49 |
chats_db = db.load_data("chats.json", default_data={})
|
|
@@ -65,18 +65,15 @@ async def get_chat_list(account: str):
|
|
| 65 |
chat_list = []
|
| 66 |
for conv_id, msgs in chats_db.items():
|
| 67 |
if account in conv_id:
|
| 68 |
-
|
| 69 |
-
target_account = participants[0] if participants[1] == account else participants[1]
|
| 70 |
if not msgs: continue
|
| 71 |
-
|
| 72 |
-
last_msg = sorted(msgs, key=lambda x: x.get("created_at", 0))[-1]
|
| 73 |
unread_count = sum(1 for m in msgs if m["receiver"] == account and not m.get("is_read"))
|
| 74 |
-
|
| 75 |
-
target_user = users_db.get(target_account, {})
|
| 76 |
chat_list.append({
|
| 77 |
-
"
|
| 78 |
-
"
|
| 79 |
-
"
|
| 80 |
"last_message": last_msg["content"],
|
| 81 |
"last_time": last_msg["created_at"],
|
| 82 |
"unread_count": unread_count
|
|
@@ -97,8 +94,7 @@ async def get_chat_history(account: str, target_account: str):
|
|
| 97 |
modified = False
|
| 98 |
|
| 99 |
for m in msgs:
|
| 100 |
-
|
| 101 |
-
if now - m.get("created_at", 0) < seven_days:
|
| 102 |
valid_msgs.append(m)
|
| 103 |
else:
|
| 104 |
modified = True
|
|
@@ -114,48 +110,40 @@ async def get_chat_history(account: str, target_account: str):
|
|
| 114 |
|
| 115 |
return {"status": "success", "data": valid_msgs}
|
| 116 |
|
|
|
|
|
|
|
|
|
|
| 117 |
@router.get("/api/messages/{account}")
|
| 118 |
async def get_messages(account: str):
|
| 119 |
msgs_db = db.load_data("messages.json", default_data={})
|
| 120 |
user_msgs = msgs_db.get(account, [])
|
| 121 |
|
| 122 |
-
#
|
| 123 |
-
if not isinstance(user_msgs, list):
|
| 124 |
-
user_msgs = []
|
| 125 |
-
|
| 126 |
-
# =========================================================
|
| 127 |
-
# 系统公告懒加载注入逻辑 (Lazy Push)
|
| 128 |
-
# =========================================================
|
| 129 |
announcements_db = db.load_data("announcements.json", default_data=[])
|
| 130 |
-
|
| 131 |
-
announcements_db = []
|
| 132 |
-
|
| 133 |
-
# 获取用户已经拥有的消息 ID 集合,用于快速比对(加入防脏数据判断)
|
| 134 |
-
user_msg_ids = {m.get("id") for m in user_msgs if isinstance(m, dict)}
|
| 135 |
|
| 136 |
injected = False
|
| 137 |
for ann in announcements_db:
|
| 138 |
-
if
|
| 139 |
-
|
| 140 |
-
new_sys_msg = dict(ann) # 浅拷贝,防止修改全局数据
|
| 141 |
new_sys_msg["is_read"] = False
|
| 142 |
new_sys_msg["receiver"] = account
|
| 143 |
user_msgs.append(new_sys_msg)
|
| 144 |
injected = True
|
| 145 |
|
| 146 |
if injected:
|
| 147 |
-
#
|
| 148 |
-
user_msgs.sort(key=lambda x: x.get("created_at", 0)
|
| 149 |
-
#
|
| 150 |
|
| 151 |
now = int(time.time())
|
| 152 |
seven_days = 7 * 24 * 3600
|
| 153 |
valid = []
|
| 154 |
-
|
|
|
|
| 155 |
modified = injected
|
| 156 |
|
| 157 |
for m in user_msgs:
|
| 158 |
-
if not isinstance(m, dict): continue
|
| 159 |
if not m.get("is_read") or (now - m.get("created_at", 0) < seven_days):
|
| 160 |
valid.append(m)
|
| 161 |
else:
|
|
@@ -165,22 +153,24 @@ async def get_messages(account: str):
|
|
| 165 |
msgs_db[account] = valid
|
| 166 |
db.save_data("messages.json", msgs_db)
|
| 167 |
|
| 168 |
-
return {
|
|
|
|
|
|
|
|
|
|
|
|
|
| 169 |
|
| 170 |
@router.post("/api/messages/{account}/read")
|
| 171 |
async def mark_messages_read(account: str):
|
| 172 |
msgs_db = db.load_data("messages.json", default_data={})
|
| 173 |
user_msgs = msgs_db.get(account, [])
|
| 174 |
modified = False
|
| 175 |
-
|
| 176 |
-
|
| 177 |
-
|
| 178 |
-
|
| 179 |
-
|
| 180 |
-
|
| 181 |
-
|
| 182 |
-
|
| 183 |
-
msgs_db[account] = user_msgs
|
| 184 |
-
db.save_data("messages.json", msgs_db)
|
| 185 |
|
| 186 |
return {"status": "success"}
|
|
|
|
| 9 |
|
| 10 |
router = APIRouter()
|
| 11 |
|
| 12 |
+
# ==========================================
|
| 13 |
+
# 新增:系统公告请求体模型
|
| 14 |
+
# ==========================================
|
| 15 |
class SystemAnnouncement(BaseModel):
|
| 16 |
admin_account: str
|
| 17 |
content: str
|
| 18 |
|
| 19 |
+
# ==========================================
|
| 20 |
+
# 新增:发布系统公告接口 (仅限管理员)
|
| 21 |
+
# ==========================================
|
| 22 |
@router.post("/api/system/announcement")
|
| 23 |
async def publish_announcement(ann: SystemAnnouncement):
|
| 24 |
+
# 硬编码限制仅超级管理员账号可发布
|
| 25 |
if ann.admin_account != "666666":
|
| 26 |
raise HTTPException(status_code=403, detail="无权发布系统公告")
|
| 27 |
|
| 28 |
announcements_db = db.load_data("announcements.json", default_data=[])
|
| 29 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 30 |
new_ann = {
|
| 31 |
"id": f"sys_{int(time.time())}_{uuid.uuid4().hex[:6]}",
|
| 32 |
"type": "system",
|
| 33 |
"from_user": "666666",
|
| 34 |
"from_name": "官方团队",
|
| 35 |
+
"from_avatar": "https://via.placeholder.com/150/FF9800/FFFFFF?text=Sys",
|
| 36 |
"content": ann.content,
|
| 37 |
"created_at": int(time.time())
|
| 38 |
}
|
| 39 |
|
| 40 |
announcements_db.append(new_ann)
|
| 41 |
db.save_data("announcements.json", announcements_db)
|
| 42 |
+
return {"status": "success"}
|
|
|
|
|
|
|
| 43 |
|
| 44 |
+
# ==========================================
|
| 45 |
+
# 原有功能:私信与聊天
|
| 46 |
+
# ==========================================
|
| 47 |
@router.post("/api/messages/private")
|
| 48 |
async def send_private_message(msg: PrivateMessage):
|
| 49 |
chats_db = db.load_data("chats.json", default_data={})
|
|
|
|
| 65 |
chat_list = []
|
| 66 |
for conv_id, msgs in chats_db.items():
|
| 67 |
if account in conv_id:
|
| 68 |
+
other_account = conv_id.replace(account, "").replace("_", "")
|
|
|
|
| 69 |
if not msgs: continue
|
| 70 |
+
last_msg = msgs[-1]
|
|
|
|
| 71 |
unread_count = sum(1 for m in msgs if m["receiver"] == account and not m.get("is_read"))
|
| 72 |
+
other_user = users_db.get(other_account, {})
|
|
|
|
| 73 |
chat_list.append({
|
| 74 |
+
"account": other_account,
|
| 75 |
+
"name": other_user.get("name", other_account),
|
| 76 |
+
"avatar": other_user.get("avatarDataUrl", "https://via.placeholder.com/150"),
|
| 77 |
"last_message": last_msg["content"],
|
| 78 |
"last_time": last_msg["created_at"],
|
| 79 |
"unread_count": unread_count
|
|
|
|
| 94 |
modified = False
|
| 95 |
|
| 96 |
for m in msgs:
|
| 97 |
+
if not m.get("is_read") or (now - m.get("created_at", 0) < seven_days):
|
|
|
|
| 98 |
valid_msgs.append(m)
|
| 99 |
else:
|
| 100 |
modified = True
|
|
|
|
| 110 |
|
| 111 |
return {"status": "success", "data": valid_msgs}
|
| 112 |
|
| 113 |
+
# ==========================================
|
| 114 |
+
# 改造:获取通知列表 (加入系统公告懒加载注入)
|
| 115 |
+
# ==========================================
|
| 116 |
@router.get("/api/messages/{account}")
|
| 117 |
async def get_messages(account: str):
|
| 118 |
msgs_db = db.load_data("messages.json", default_data={})
|
| 119 |
user_msgs = msgs_db.get(account, [])
|
| 120 |
|
| 121 |
+
# --- 核心改造区:瞬间比对并注入全局公告 ---
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 122 |
announcements_db = db.load_data("announcements.json", default_data=[])
|
| 123 |
+
user_msg_ids = {m.get("id") for m in user_msgs}
|
|
|
|
|
|
|
|
|
|
|
|
|
| 124 |
|
| 125 |
injected = False
|
| 126 |
for ann in announcements_db:
|
| 127 |
+
if ann.get("id") not in user_msg_ids:
|
| 128 |
+
new_sys_msg = dict(ann)
|
|
|
|
| 129 |
new_sys_msg["is_read"] = False
|
| 130 |
new_sys_msg["receiver"] = account
|
| 131 |
user_msgs.append(new_sys_msg)
|
| 132 |
injected = True
|
| 133 |
|
| 134 |
if injected:
|
| 135 |
+
# 重新按照时间倒序排列,让新公告置顶
|
| 136 |
+
user_msgs.sort(key=lambda x: x.get("created_at", 0), reverse=True)
|
| 137 |
+
# ----------------------------------------
|
| 138 |
|
| 139 |
now = int(time.time())
|
| 140 |
seven_days = 7 * 24 * 3600
|
| 141 |
valid = []
|
| 142 |
+
|
| 143 |
+
# 如果注入了新公告,则判定为需要回写数据库保存
|
| 144 |
modified = injected
|
| 145 |
|
| 146 |
for m in user_msgs:
|
|
|
|
| 147 |
if not m.get("is_read") or (now - m.get("created_at", 0) < seven_days):
|
| 148 |
valid.append(m)
|
| 149 |
else:
|
|
|
|
| 153 |
msgs_db[account] = valid
|
| 154 |
db.save_data("messages.json", msgs_db)
|
| 155 |
|
| 156 |
+
return {
|
| 157 |
+
"status": "success",
|
| 158 |
+
"data": valid,
|
| 159 |
+
"unread_count": sum(1 for m in valid if not m.get("is_read"))
|
| 160 |
+
}
|
| 161 |
|
| 162 |
@router.post("/api/messages/{account}/read")
|
| 163 |
async def mark_messages_read(account: str):
|
| 164 |
msgs_db = db.load_data("messages.json", default_data={})
|
| 165 |
user_msgs = msgs_db.get(account, [])
|
| 166 |
modified = False
|
| 167 |
+
for m in user_msgs:
|
| 168 |
+
if not m.get("is_read"):
|
| 169 |
+
m["is_read"] = True
|
| 170 |
+
modified = True
|
| 171 |
+
|
| 172 |
+
if modified:
|
| 173 |
+
msgs_db[account] = user_msgs
|
| 174 |
+
db.save_data("messages.json", msgs_db)
|
|
|
|
|
|
|
| 175 |
|
| 176 |
return {"status": "success"}
|