github-actions[bot]
Deploy to Hugging Face Space
abf702c
from fastapi import APIRouter, Depends, HTTPException
from sqlalchemy.ext.asyncio import AsyncSession
from app.db.session import get_db
from app.services.user_service import user_service
from app.services.yahoo_finance import yahoo_finance_service
from pydantic import BaseModel
from typing import List, Optional
from app.core.auth import get_current_user, get_authenticated_user, get_user_or_demo
from app.models.database import User as DBUser
router = APIRouter()
class WatchlistItemSchema(BaseModel):
symbol: str
name: str
exchange: str
class WatchlistEnrichedSchema(WatchlistItemSchema):
price: str
change: str
percentage: str
isPositive: bool
class UserProfileSchema(BaseModel):
username: str
full_name: str
avatar_url: Optional[str]
theme: Optional[str] = "dark"
class ThemeUpdateSchema(BaseModel):
theme: str
class IndicatorsUpdateSchema(BaseModel):
indicators: List[str]
@router.get("/profile", response_model=UserProfileSchema)
async def get_profile(user: DBUser = Depends(get_user_or_demo)):
return {
"username": user.username or user.email.split('@')[0],
"full_name": user.full_name,
"avatar_url": user.avatar_url,
"theme": user.theme or "dark"
}
@router.put("/profile/theme")
async def update_theme(data: ThemeUpdateSchema, db: AsyncSession = Depends(get_db), user: DBUser = Depends(get_authenticated_user)):
user.theme = data.theme
await db.commit()
return {"status": "success", "theme": user.theme}
@router.get("/watchlist", response_model=List[WatchlistEnrichedSchema])
async def get_watchlist(db: AsyncSession = Depends(get_db), user: DBUser = Depends(get_user_or_demo)):
items = await user_service.get_watchlist(db, user.id)
if not items:
return []
# Fetch live data for these symbols
symbols = [item.symbol for item in items]
quotes = await yahoo_finance_service.get_quotes(symbols)
quote_map = {q.symbol: q for q in quotes}
results = []
for item in items:
quote = quote_map.get(item.symbol)
results.append({
"symbol": item.symbol,
"name": item.name,
"exchange": item.exchange,
"price": quote.price if quote else "0.00",
"change": quote.change if quote else "0.00",
"percentage": quote.percentage if quote else "0.00%",
"isPositive": quote.isPositive if quote else True
})
return results
@router.post("/watchlist")
async def add_to_watchlist(item: WatchlistItemSchema, db: AsyncSession = Depends(get_db), user: DBUser = Depends(get_authenticated_user)):
await user_service.add_to_watchlist(
db, user.id, item.symbol, item.name, item.exchange
)
return {"status": "success"}
@router.delete("/watchlist/{symbol}")
async def remove_from_watchlist(symbol: str, db: AsyncSession = Depends(get_db), user: DBUser = Depends(get_authenticated_user)):
await user_service.remove_from_watchlist(db, user.id, symbol)
return {"status": "success"}
@router.get("/indicators", response_model=List[str])
async def get_indicators(db: AsyncSession = Depends(get_db), user: DBUser = Depends(get_user_or_demo)):
return await user_service.get_indicators(db, user.id)
@router.post("/indicators")
async def update_indicators(data: IndicatorsUpdateSchema, db: AsyncSession = Depends(get_db), user: DBUser = Depends(get_authenticated_user)):
await user_service.update_indicators(db, user.id, data.indicators)
return {"status": "success"}
from app.models.database import UserAgenticScan
from sqlalchemy import select, desc
class AgenticScanSchema(BaseModel):
id: int
symbol: str
decision: str
confidence: float
recommendation: str
created_at: str
risk_warning: Optional[str] = None
# We might want entry_price too if available
entry_price: Optional[str] = None
@router.get("/scans", response_model=List[AgenticScanSchema])
async def get_scans(db: AsyncSession = Depends(get_db), user: DBUser = Depends(get_user_or_demo)):
result = await db.execute(
select(UserAgenticScan)
.where(UserAgenticScan.user_id == user.id)
.order_by(desc(UserAgenticScan.created_at))
)
scans = result.scalars().all()
return [
AgenticScanSchema(
id=s.id,
symbol=s.symbol,
decision=s.decision,
confidence=s.confidence,
recommendation=s.recommendation,
created_at=s.created_at.isoformat(),
risk_warning=s.risk_warning,
entry_price=s.entry_price
)
for s in scans
]