mirror of
https://github.com/OHV-IT/collabrix.git
synced 2025-12-15 16:48:36 +01:00
104 lines
3.9 KiB
Python
104 lines
3.9 KiB
Python
from fastapi import APIRouter, Depends, HTTPException, status
|
|
from sqlmodel import Session, select
|
|
from datetime import datetime
|
|
from typing import Optional
|
|
|
|
from app.database import get_session
|
|
from app.auth import get_current_user
|
|
from app.models import User, Channel, LastSeen
|
|
from app.websocket import manager
|
|
|
|
router = APIRouter(prefix="/me/last-seen", tags=["LastSeen"])
|
|
|
|
|
|
@router.post("/")
|
|
async def set_last_seen(
|
|
channel_id: Optional[int] = None,
|
|
dm_user_id: Optional[int] = None,
|
|
last_seen: Optional[str] = None,
|
|
session: Session = Depends(get_session),
|
|
current_user: User = Depends(get_current_user),
|
|
):
|
|
if not channel_id and not dm_user_id:
|
|
raise HTTPException(status_code=400, detail="channel_id or dm_user_id required")
|
|
|
|
# Validate target exists
|
|
if channel_id:
|
|
channel = session.get(Channel, channel_id)
|
|
if not channel:
|
|
raise HTTPException(status_code=404, detail="Channel not found")
|
|
# Basic access check: user must belong to the channel's department
|
|
user_dept_ids = [d.id for d in current_user.departments] if current_user.departments else []
|
|
if channel.department_id not in user_dept_ids:
|
|
raise HTTPException(status_code=403, detail="No access to channel")
|
|
|
|
if dm_user_id:
|
|
other = session.get(User, dm_user_id)
|
|
if not other:
|
|
raise HTTPException(status_code=404, detail="Target user not found")
|
|
|
|
ts = datetime.utcnow() if not last_seen else datetime.fromisoformat(last_seen)
|
|
|
|
# Upsert last seen
|
|
if channel_id:
|
|
statement = select(LastSeen).where(LastSeen.user_id == current_user.id, LastSeen.channel_id == channel_id)
|
|
else:
|
|
statement = select(LastSeen).where(LastSeen.user_id == current_user.id, LastSeen.dm_user_id == dm_user_id)
|
|
|
|
exists = session.exec(statement).first()
|
|
if exists:
|
|
exists.last_seen = ts
|
|
session.add(exists)
|
|
session.commit()
|
|
session.refresh(exists)
|
|
result = exists
|
|
else:
|
|
payload = LastSeen(user_id=current_user.id, channel_id=channel_id, dm_user_id=dm_user_id, last_seen=ts)
|
|
session.add(payload)
|
|
session.commit()
|
|
session.refresh(payload)
|
|
result = payload
|
|
|
|
# Broadcast read_marker to relevant channel or DM partner
|
|
try:
|
|
message = {
|
|
"type": "read_marker",
|
|
"user_id": current_user.id,
|
|
"last_seen": result.last_seen.isoformat(),
|
|
}
|
|
if channel_id:
|
|
message["channel_id"] = channel_id
|
|
await manager.broadcast_to_channel(message, channel_id)
|
|
elif dm_user_id:
|
|
message["dm_user_id"] = dm_user_id
|
|
# partner listens on channel id = -their_user_id
|
|
await manager.broadcast_to_channel(message, -dm_user_id)
|
|
# also broadcast to presence channel 0
|
|
await manager.broadcast_to_channel({**message, "type": "read_marker"}, 0)
|
|
except Exception:
|
|
pass
|
|
|
|
return {"id": result.id, "user_id": result.user_id, "channel_id": result.channel_id, "dm_user_id": result.dm_user_id, "last_seen": result.last_seen.isoformat()}
|
|
|
|
|
|
@router.get("/")
|
|
def get_last_seen(
|
|
channel_id: Optional[int] = None,
|
|
dm_user_id: Optional[int] = None,
|
|
session: Session = Depends(get_session),
|
|
current_user: User = Depends(get_current_user),
|
|
):
|
|
if not channel_id and not dm_user_id:
|
|
raise HTTPException(status_code=400, detail="channel_id or dm_user_id required")
|
|
|
|
if channel_id:
|
|
stmt = select(LastSeen).where(LastSeen.user_id == current_user.id, LastSeen.channel_id == channel_id)
|
|
else:
|
|
stmt = select(LastSeen).where(LastSeen.user_id == current_user.id, LastSeen.dm_user_id == dm_user_id)
|
|
|
|
found = session.exec(stmt).first()
|
|
if not found:
|
|
raise HTTPException(status_code=404, detail="LastSeen not found")
|
|
|
|
return {"id": found.id, "user_id": found.user_id, "channel_id": found.channel_id, "dm_user_id": found.dm_user_id, "last_seen": found.last_seen.isoformat()}
|