Files
g0v0-server/app/router/chat/channel.py
2025-08-16 05:29:16 +00:00

139 lines
4.2 KiB
Python

from __future__ import annotations
from typing import Any
from app.database.chat import (
ChannelType,
ChatChannel,
ChatChannelResp,
)
from app.database.lazer_user import User, UserResp
from app.dependencies.database import get_db, get_redis
from app.dependencies.user import get_current_user
from app.router.v2 import api_v2_router as router
from .server import server
from fastapi import Depends, HTTPException, Query, Security
from pydantic import BaseModel, Field
from redis.asyncio import Redis
from sqlmodel import select
from sqlmodel.ext.asyncio.session import AsyncSession
class UpdateResponse(BaseModel):
presence: list[ChatChannelResp] = Field(default_factory=list)
silences: list[Any] = Field(default_factory=list)
@router.get("/chat/updates", response_model=UpdateResponse)
async def get_update(
history_since: int | None = Query(None),
since: int | None = Query(None),
current_user: User = Security(get_current_user, scopes=["chat.read"]),
session: AsyncSession = Depends(get_db),
includes: list[str] = Query(["presence"], alias="includes[]"),
redis: Redis = Depends(get_redis),
):
resp = UpdateResponse()
if "presence" in includes:
channel_ids = server.get_user_joined_channel(current_user.id)
for channel_id in channel_ids:
channel = await ChatChannel.get(channel_id, session)
if channel:
resp.presence.append(
await ChatChannelResp.from_db(
channel,
session,
server.channels.get(channel_id, []),
current_user,
redis,
)
)
return resp
@router.put("/chat/channels/{channel}/users/{user}", response_model=ChatChannelResp)
async def join_channel(
channel: str,
user: str,
current_user: User = Security(get_current_user, scopes=["chat.write_manage"]),
session: AsyncSession = Depends(get_db),
):
db_channel = await ChatChannel.get(channel, session)
if db_channel is None:
raise HTTPException(status_code=404, detail="Channel not found")
return await server.join_channel(current_user, db_channel, session)
@router.delete(
"/chat/channels/{channel}/users/{user}",
status_code=204,
)
async def leave_channel(
channel: str,
user: str,
current_user: User = Security(get_current_user, scopes=["chat.write_manage"]),
session: AsyncSession = Depends(get_db),
):
db_channel = await ChatChannel.get(channel, session)
if db_channel is None:
raise HTTPException(status_code=404, detail="Channel not found")
await server.leave_channel(current_user, db_channel, session)
return
@router.get("/chat/channels")
async def get_channel_list(
current_user: User = Security(get_current_user, scopes=["chat.read"]),
session: AsyncSession = Depends(get_db),
redis: Redis = Depends(get_redis),
):
channels = (
await session.exec(
select(ChatChannel).where(ChatChannel.type == ChannelType.PUBLIC)
)
).all()
results = []
for channel in channels:
assert channel.channel_id is not None
results.append(
await ChatChannelResp.from_db(
channel,
session,
server.channels.get(channel.channel_id, []),
current_user,
redis,
)
)
return results
class GetChannelResp(BaseModel):
channel: ChatChannelResp
users: list[UserResp] = Field(default_factory=list)
@router.get("/chat/channels/{channel}")
async def get_channel(
channel: str,
current_user: User = Security(get_current_user, scopes=["chat.read"]),
session: AsyncSession = Depends(get_db),
redis: Redis = Depends(get_redis),
):
db_channel = await ChatChannel.get(channel, session)
if db_channel is None:
raise HTTPException(status_code=404, detail="Channel not found")
assert db_channel.channel_id is not None
return GetChannelResp(
channel=await ChatChannelResp.from_db(
db_channel,
session,
server.channels.get(db_channel.channel_id, []),
current_user,
redis,
)
)