mirror of
http://88.130.71.182:3000/BlitTech/contexta_be.git
synced 2026-06-13 10:39:00 +00:00
195 lines
6.6 KiB
Python
195 lines
6.6 KiB
Python
from fastapi import APIRouter, HTTPException, Depends, Query
|
|
from app.models import ChatbotPublicResponse, MarketplaceResponse, RatingCreate
|
|
from app.database import get_supabase
|
|
from app.dependencies import get_optional_user, get_current_user
|
|
from typing import Optional
|
|
import logging
|
|
|
|
logger = logging.getLogger(__name__)
|
|
router = APIRouter(prefix="/marketplace", tags=["Marketplace"])
|
|
|
|
# ═══════════════════════════════════════════════════════════════════════════════
|
|
# CATEGORIES & INDUSTRIES — Expanded to support all business types:
|
|
# Individuals, small businesses (restaurants, barbershops, malls, phone shops),
|
|
# and large enterprises.
|
|
# ═══════════════════════════════════════════════════════════════════════════════
|
|
|
|
CATEGORIES = [
|
|
# What the chatbot does
|
|
"Customer Support",
|
|
"Sales Assistant",
|
|
"FAQ & Knowledge Base",
|
|
"Appointment Booking",
|
|
"Order & Delivery Tracking",
|
|
"Product Recommendations",
|
|
"Lead Generation",
|
|
"Onboarding & Training",
|
|
"Feedback & Surveys",
|
|
"Personal Assistant",
|
|
"Consultation",
|
|
"Other",
|
|
]
|
|
|
|
INDUSTRIES = [
|
|
# Small businesses / Local services
|
|
"Restaurant & Food",
|
|
"Beauty & Barbershop",
|
|
"Retail & Shopping",
|
|
"Phone & Electronics",
|
|
"Automotive & Repair",
|
|
"Fitness & Wellness",
|
|
"Cleaning & Home Services",
|
|
"Photography & Events",
|
|
# Professional services
|
|
"Healthcare & Medical",
|
|
"Legal & Law",
|
|
"Finance & Insurance",
|
|
"Real Estate",
|
|
"Accounting & Tax",
|
|
# Tech & Digital
|
|
"Technology & SaaS",
|
|
"E-commerce",
|
|
"Agency & Marketing",
|
|
# Education & Non-profit
|
|
"Education & Training",
|
|
"Non-profit & NGO",
|
|
# Large scale
|
|
"Hospitality & Hotels",
|
|
"Travel & Tourism",
|
|
"Manufacturing",
|
|
"Logistics & Transport",
|
|
"Agriculture",
|
|
"Government",
|
|
# Personal
|
|
"Personal Brand",
|
|
"Freelancer & Consultant",
|
|
"Other",
|
|
]
|
|
|
|
|
|
@router.get("/chatbots", response_model=MarketplaceResponse)
|
|
async def list_marketplace_chatbots(
|
|
category: Optional[str] = Query(None),
|
|
industry: Optional[str] = Query(None),
|
|
language: Optional[str] = Query(None),
|
|
search: Optional[str] = Query(None),
|
|
page: int = Query(1, ge=1),
|
|
limit: int = Query(20, ge=1, le=100),
|
|
user=Depends(get_optional_user),
|
|
):
|
|
supabase = get_supabase()
|
|
|
|
query = supabase.table("chatbots").select(
|
|
"*, companies(name, logo_url)"
|
|
).eq("is_published", True).eq("visibility", "published")
|
|
|
|
if category:
|
|
query = query.eq("category", category)
|
|
if industry:
|
|
query = query.eq("industry", industry)
|
|
if search:
|
|
query = query.ilike("name", f"%{search}%")
|
|
|
|
offset = (page - 1) * limit
|
|
result = query.order("created_at", desc=True).range(offset, offset + limit - 1).execute()
|
|
all_result = supabase.table("chatbots").select("id", count="exact").eq("is_published", True).execute()
|
|
total = all_result.count or 0
|
|
|
|
chatbots = []
|
|
for c in (result.data or []):
|
|
company_data = c.get("companies") or {}
|
|
chatbots.append(
|
|
ChatbotPublicResponse(
|
|
id=c["id"],
|
|
name=c["name"],
|
|
description=c.get("description"),
|
|
category=c.get("category"),
|
|
industry=c.get("industry"),
|
|
languages=c.get("languages", ["en"]),
|
|
primary_color=c.get("primary_color", "#6366f1"),
|
|
welcome_message=c.get("welcome_message", "Hello!"),
|
|
logo_url=c.get("logo_url"),
|
|
average_rating=c.get("average_rating"),
|
|
total_conversations=c.get("total_conversations", 0),
|
|
company_name=company_data.get("name"),
|
|
company_logo=company_data.get("logo_url"),
|
|
created_at=c.get("created_at"),
|
|
published_at=c.get("published_at"),
|
|
)
|
|
)
|
|
|
|
return MarketplaceResponse(
|
|
chatbots=chatbots,
|
|
total=total,
|
|
page=page,
|
|
limit=limit,
|
|
has_more=(offset + limit < total),
|
|
)
|
|
|
|
|
|
@router.get("/chatbots/{chatbot_id}", response_model=ChatbotPublicResponse)
|
|
async def get_marketplace_chatbot(chatbot_id: str, user=Depends(get_optional_user)):
|
|
supabase = get_supabase()
|
|
|
|
result = supabase.table("chatbots").select(
|
|
"*, companies(name, logo_url)"
|
|
).eq("id", chatbot_id).eq("is_published", True).execute()
|
|
|
|
if not result.data:
|
|
raise HTTPException(status_code=404, detail="Chatbot not found")
|
|
|
|
c = result.data[0]
|
|
company_data = c.get("companies") or {}
|
|
|
|
conv_count = supabase.table("conversations").select("id", count="exact") \
|
|
.eq("chatbot_id", chatbot_id).execute()
|
|
|
|
return ChatbotPublicResponse(
|
|
id=c["id"],
|
|
name=c["name"],
|
|
description=c.get("description"),
|
|
category=c.get("category"),
|
|
industry=c.get("industry"),
|
|
languages=c.get("languages", ["en"]),
|
|
primary_color=c.get("primary_color", "#6366f1"),
|
|
welcome_message=c.get("welcome_message", "Hello!"),
|
|
logo_url=c.get("logo_url"),
|
|
average_rating=c.get("average_rating"),
|
|
total_conversations=conv_count.count or 0,
|
|
company_name=company_data.get("name"),
|
|
company_logo=company_data.get("logo_url"),
|
|
created_at=c.get("created_at"),
|
|
published_at=c.get("published_at"),
|
|
)
|
|
|
|
|
|
@router.get("/categories")
|
|
async def get_categories():
|
|
return {"categories": CATEGORIES, "industries": INDUSTRIES}
|
|
|
|
|
|
@router.post("/chatbots/{chatbot_id}/rate")
|
|
async def rate_chatbot(
|
|
chatbot_id: str,
|
|
rating: RatingCreate,
|
|
user=Depends(get_current_user),
|
|
):
|
|
supabase = get_supabase()
|
|
chatbot = supabase.table("chatbots") \
|
|
.select("id, average_rating, rating_count") \
|
|
.eq("id", chatbot_id).eq("is_published", True).execute()
|
|
if not chatbot.data:
|
|
raise HTTPException(status_code=404, detail="Chatbot not found")
|
|
|
|
row = chatbot.data[0]
|
|
current_avg = row.get("average_rating") or 0.0
|
|
current_count = row.get("rating_count") or 0
|
|
|
|
new_count = current_count + 1
|
|
new_avg = round((current_avg * current_count + rating.rating) / new_count, 2)
|
|
|
|
supabase.table("chatbots").update({
|
|
"average_rating": new_avg,
|
|
"rating_count": new_count,
|
|
}).eq("id", chatbot_id).execute()
|
|
return {"average_rating": new_avg, "rating_count": new_count} |