""" Channels API - Channel management and operations """ from fastapi import APIRouter, Depends, HTTPException, status from sqlalchemy.orm import Session from pydantic import BaseModel from typing import List, Optional from core.database import get_db from core.models import Channel, User, ChannelType from api.auth import get_current_user router = APIRouter() # Pydantic models class ChannelCreate(BaseModel): name: str description: Optional[str] = None type: ChannelType = ChannelType.PUBLIC class ChannelResponse(BaseModel): id: int name: str description: Optional[str] type: ChannelType member_count: int created_at: str class Config: from_attributes = True class ChannelListResponse(BaseModel): id: int name: str description: Optional[str] type: ChannelType unread_count: int = 0 # TODO: Implement actual unread counting class Config: from_attributes = True @router.post("/", response_model=ChannelResponse) async def create_channel( channel_data: ChannelCreate, current_user: User = Depends(get_current_user), db: Session = Depends(get_db) ): """Create a new channel""" # Check if channel name already exists existing = db.query(Channel).filter(Channel.name == channel_data.name).first() if existing: raise HTTPException( status_code=status.HTTP_400_BAD_REQUEST, detail="Channel name already exists" ) # Create channel channel = Channel( name=channel_data.name, description=channel_data.description, type=channel_data.type, created_by=current_user.id ) db.add(channel) db.commit() db.refresh(channel) # Add creator as member channel.members.append(current_user) db.commit() db.refresh(channel) return ChannelResponse( id=channel.id, name=channel.name, description=channel.description, type=channel.type, member_count=len(channel.members), created_at=channel.created_at.isoformat() ) @router.get("/", response_model=List[ChannelListResponse]) async def list_channels( current_user: User = Depends(get_current_user), db: Session = Depends(get_db) ): """List all channels user is a member of""" channels = current_user.channels return [ { "id": c.id, "name": c.name, "description": c.description, "type": c.type, "unread_count": 0 # TODO: Implement } for c in channels ] @router.get("/{channel_id}", response_model=ChannelResponse) async def get_channel( channel_id: int, current_user: User = Depends(get_current_user), db: Session = Depends(get_db) ): """Get channel details""" channel = db.query(Channel).filter(Channel.id == channel_id).first() if not channel: raise HTTPException( status_code=status.HTTP_404_NOT_FOUND, detail="Channel not found" ) # Check if user is member (for private channels) if channel.type == ChannelType.PRIVATE: if current_user not in channel.members: raise HTTPException( status_code=status.HTTP_403_FORBIDDEN, detail="Not a member of this channel" ) return { **channel.__dict__, "member_count": len(channel.members), "created_at": channel.created_at.isoformat() } @router.post("/{channel_id}/join") async def join_channel( channel_id: int, current_user: User = Depends(get_current_user), db: Session = Depends(get_db) ): """Join a channel""" channel = db.query(Channel).filter(Channel.id == channel_id).first() if not channel: raise HTTPException( status_code=status.HTTP_404_NOT_FOUND, detail="Channel not found" ) # Can't join private channels (must be invited) if channel.type == ChannelType.PRIVATE: raise HTTPException( status_code=status.HTTP_403_FORBIDDEN, detail="Cannot join private channel" ) # Check if already a member if current_user in channel.members: raise HTTPException( status_code=status.HTTP_400_BAD_REQUEST, detail="Already a member" ) channel.members.append(current_user) db.commit() return {"message": f"Joined channel #{channel.name}"} @router.post("/{channel_id}/leave") async def leave_channel( channel_id: int, current_user: User = Depends(get_current_user), db: Session = Depends(get_db) ): """Leave a channel""" channel = db.query(Channel).filter(Channel.id == channel_id).first() if not channel: raise HTTPException( status_code=status.HTTP_404_NOT_FOUND, detail="Channel not found" ) if current_user not in channel.members: raise HTTPException( status_code=status.HTTP_400_BAD_REQUEST, detail="Not a member of this channel" ) channel.members.remove(current_user) db.commit() return {"message": f"Left channel #{channel.name}"}