Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion Backend/.env-example
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,6 @@ port=5432
dbname=postgres
GROQ_API_KEY=
SUPABASE_URL=
SUPABASE_KEY=
SUPABASE_KEY=
GEMINI_API_KEY=
YOUTUBE_API_KEY=
15 changes: 9 additions & 6 deletions Backend/app/db/seed.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
from datetime import datetime, timezone
from db.db import AsyncSessionLocal
from models.models import User
from datetime import datetime
from app.db.db import AsyncSessionLocal
from app.models.models import User


async def seed_db():
Expand All @@ -12,6 +12,8 @@ async def seed_db():
"password": "password123",
"role": "creator",
"bio": "Lifestyle and travel content creator",
"profile_image": None,
"created_at": datetime.utcnow()
},
{
"id": "6dbfcdd5-795f-49c1-8f7a-a5538b8c6f6f",
Expand All @@ -20,6 +22,8 @@ async def seed_db():
"password": "password123",
"role": "brand",
"bio": "Sustainable fashion brand looking for influencers",
"profile_image": None,
"created_at": datetime.utcnow()
},
]

Expand All @@ -40,11 +44,10 @@ async def seed_db():
id=user_data["id"],
username=user_data["username"],
email=user_data["email"],
password_hash=user_data[
"password"
], # Using plain password directly
role=user_data["role"],
profile_image=user_data["profile_image"],
bio=user_data["bio"],
created_at=user_data["created_at"]
)
session.add(user)
print(f"Created user: {user_data['email']}")
Expand Down
15 changes: 10 additions & 5 deletions Backend/app/main.py
Original file line number Diff line number Diff line change
@@ -1,15 +1,17 @@
from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware
from db.db import engine
from db.seed import seed_db
from models import models, chat
from routes.post import router as post_router
from routes.chat import router as chat_router
from .db.db import engine
from .db.seed import seed_db
from .models import models, chat
from .routes.post import router as post_router
from .routes.chat import router as chat_router
from .routes.match import router as match_router
from sqlalchemy.exc import SQLAlchemyError
import logging
import os
from dotenv import load_dotenv
from contextlib import asynccontextmanager
from app.routes import ai

# Load environment variables
load_dotenv()
Expand Down Expand Up @@ -51,6 +53,9 @@ async def lifespan(app: FastAPI):
# Include the routes
app.include_router(post_router)
app.include_router(chat_router)
app.include_router(match_router)
app.include_router(ai.router)
app.include_router(ai.youtube_router)


@app.get("/")
Expand Down
2 changes: 1 addition & 1 deletion Backend/app/models/chat.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
from sqlalchemy import Column, String, ForeignKey, DateTime, Enum, UniqueConstraint
from sqlalchemy.orm import relationship
from datetime import datetime, timezone
from db.db import Base
from app.db.db import Base
import uuid
import enum

Expand Down
15 changes: 6 additions & 9 deletions Backend/app/models/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,11 @@
DECIMAL,
DateTime,
Boolean,
TIMESTAMP,
)
from sqlalchemy.orm import relationship
from datetime import datetime, timezone
from db.db import Base
from datetime import datetime
from app.db.db import Base
import uuid


Expand All @@ -27,18 +28,14 @@ class User(Base):
id = Column(String, primary_key=True, default=generate_uuid)
username = Column(String, unique=True, nullable=False)
email = Column(String, unique=True, nullable=False)
password_hash = Column(Text, nullable=False) # Restored for now
# password_hash = Column(Text, nullable=False) # Removed as Supabase handles auth
role = Column(String, nullable=False) # 'creator' or 'brand'
profile_image = Column(Text, nullable=True)
bio = Column(Text, nullable=True)
created_at = Column(
DateTime(timezone=True), default=lambda: datetime.now(timezone.utc)
)
created_at = Column(TIMESTAMP, default=datetime.utcnow)

is_online = Column(Boolean, default=False) # ✅ Track if user is online
last_seen = Column(
DateTime(timezone=True), default=lambda: datetime.now(timezone.utc)
)
last_seen = Column(TIMESTAMP, default=datetime.utcnow)
Comment on lines +35 to +38
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Fix timezone inconsistency in timestamp handling.

The User model now uses timezone-naive datetime.utcnow() with TIMESTAMP columns, while other models in the same file still use timezone-aware datetime.now(timezone.utc) with DateTime(timezone=True). This inconsistency can cause issues when comparing timestamps across different models or when the database expects consistent timezone handling.

Consider one of these solutions:

Option 1 (Recommended): Use timezone-aware timestamps consistently

-from datetime import datetime
+from datetime import datetime, timezone
-    created_at = Column(TIMESTAMP, default=datetime.utcnow)
+    created_at = Column(DateTime(timezone=True), default=lambda: datetime.now(timezone.utc))
-    last_seen = Column(TIMESTAMP, default=datetime.utcnow)
+    last_seen = Column(DateTime(timezone=True), default=lambda: datetime.now(timezone.utc))

Option 2: Update all models to use TIMESTAMP consistently

# Update all other DateTime(timezone=True) columns to use TIMESTAMP with datetime.utcnow
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
created_at = Column(TIMESTAMP, default=datetime.utcnow)
is_online = Column(Boolean, default=False) # ✅ Track if user is online
last_seen = Column(
DateTime(timezone=True), default=lambda: datetime.now(timezone.utc)
)
last_seen = Column(TIMESTAMP, default=datetime.utcnow)
# at the top of the file, update the import
-from datetime import datetime
+from datetime import datetime, timezone
# in your User model, replace the naive TIMESTAMP fields
created_at = Column(DateTime(timezone=True), default=lambda: datetime.now(timezone.utc))
is_online = Column(Boolean, default=False) # ✅ Track if user is online
- last_seen = Column(TIMESTAMP, default=datetime.utcnow)
+ last_seen = Column(DateTime(timezone=True), default=lambda: datetime.now(timezone.utc))
🤖 Prompt for AI Agents
In Backend/app/models/models.py around lines 35 to 38, the timestamp columns use
timezone-naive datetime.utcnow() with TIMESTAMP, causing inconsistency with
other models that use timezone-aware datetime.now(timezone.utc) and
DateTime(timezone=True). To fix this, update the created_at and last_seen
columns to use DateTime(timezone=True) and set their default to a timezone-aware
function like datetime.now(timezone.utc) to ensure consistent timezone handling
across all models.


audience = relationship("AudienceInsights", back_populates="user", uselist=False)
sponsorships = relationship("Sponsorship", back_populates="brand")
Expand Down
101 changes: 101 additions & 0 deletions Backend/app/routes/ai.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
# FastAPI router for AI-powered endpoints, including trending niches
from fastapi import APIRouter, HTTPException, Query
from datetime import date
import os
import requests
import json
from supabase import create_client, Client
from requests.adapters import HTTPAdapter
from urllib3.util.retry import Retry

# Initialize router
router = APIRouter()

# Load environment variables for Supabase and Gemini
SUPABASE_URL = os.environ.get("SUPABASE_URL")
SUPABASE_KEY = os.environ.get("SUPABASE_KEY")
GEMINI_API_KEY = os.environ.get("GEMINI_API_KEY")

# Validate required environment variables
if not all([SUPABASE_URL, SUPABASE_KEY, GEMINI_API_KEY]):
raise ValueError("Missing required environment variables: SUPABASE_URL, SUPABASE_KEY, GEMINI_API_KEY")

supabase: Client = create_client(SUPABASE_URL, SUPABASE_KEY)

def fetch_from_gemini():
prompt = (
"List the top 6 trending content niches for creators and brands this week. For each, provide: name (the niche), insight (a short qualitative reason why it's trending), and global_activity (a number from 1 to 5, where 5 means very high global activity in this category, and 1 means low).Return as a JSON array of objects with keys: name, insight, global_activity."
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  1. how will gemini know this week's trend? is this grounded on google trends data?
  2. why are we making api calls.. lets use sdks

)
url = f"https://generativelanguage.googleapis.com/v1beta/models/gemini-2.0-flash-lite:generateContent?key={GEMINI_API_KEY}"
# Set up retry strategy
retry_strategy = Retry(
total=3,
backoff_factor=1,
status_forcelist=[429, 500, 502, 503, 504],
allowed_methods=["POST"],
)
adapter = HTTPAdapter(max_retries=retry_strategy)
http = requests.Session()
http.mount("https://", adapter)
http.mount("http://", adapter)
resp = http.post(url, json={"contents": [{"parts": [{"text": prompt}]}]}, timeout=(3.05, 10))
resp.raise_for_status()
print("Gemini raw response:", resp.text)
data = resp.json()
print("Gemini parsed JSON:", data)
text = data['candidates'][0]['content']['parts'][0]['text']
Comment on lines +43 to +46
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Remove sensitive data from debug logs.

Printing raw API responses could expose sensitive information in logs. Consider using proper logging levels and sanitizing output.

-    print("Gemini raw response:", resp.text)
+    # Log success without exposing sensitive data
+    print("Gemini API request successful")
     data = resp.json()
-    print("Gemini parsed JSON:", data)
     text = data['candidates'][0]['content']['parts'][0]['text']
-    print("Gemini text to parse as JSON:", text)

Committable suggestion skipped: line range outside the PR's diff.

🤖 Prompt for AI Agents
In Backend/app/routes/ai.py around lines 27 to 30, the code prints the raw API
response and parsed JSON directly, which may expose sensitive data in logs.
Replace these print statements with logging calls at an appropriate log level
(e.g., debug) and sanitize or redact any sensitive information before logging.
Ensure that sensitive fields are not included in the logs to protect data
privacy.

print("Gemini text to parse as JSON:", text)
# Remove Markdown code block if present
if text.strip().startswith('```'):
text = text.strip().split('\n', 1)[1] # Remove the first line (```json)
text = text.rsplit('```', 1)[0] # Remove the last ```
text = text.strip()
return json.loads(text)
Comment on lines +46 to +53
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Unprotected JSON parse may explode on malformed output

If Gemini returns non-JSON or extra prose, json.loads will raise and the entire request falls into the broad except block. Wrap parsing in a dedicated try/except ValueError and surface a 502/500 with context instead of silent fallback.

-    return json.loads(text)
+    try:
+        return json.loads(text)
+    except ValueError as exc:
+        logger.warning("Gemini returned non-JSON payload: %s", text[:120])
+        raise RuntimeError("Gemini payload parsing failed") from exc

Committable suggestion skipped: line range outside the PR's diff.

🤖 Prompt for AI Agents
In Backend/app/routes/ai.py around lines 35 to 42, the call to json.loads is
unprotected and will raise an exception if the text is not valid JSON, causing
the entire request to fall into a broad except block. Wrap the json.loads call
in a try/except block that catches ValueError, and in the except block, return
or raise a 502 or 500 error with a clear message indicating JSON parsing failed,
so the error is surfaced with context instead of silently falling back.


@router.get("/api/trending-niches")
def trending_niches():
"""
API endpoint to get trending niches for the current day.
- If today's data exists in Supabase, return it.
- Otherwise, fetch from Gemini, store in Supabase, and return the new data.
- If Gemini fails, fallback to the most recent data available.
"""
today = str(date.today())
# Check if today's data exists in Supabase
result = supabase.table("trending_niches").select("*").eq("fetched_at", today).execute()
if not result.data:
# Fetch from Gemini and store
try:
niches = fetch_from_gemini()
for niche in niches:
supabase.table("trending_niches").insert({
"name": niche["name"],
"insight": niche["insight"],
"global_activity": int(niche["global_activity"]),
"fetched_at": today
}).execute()
result = supabase.table("trending_niches").select("*").eq("fetched_at", today).execute()
except Exception as e:
print("Gemini fetch failed:", e)
# fallback: serve most recent data
result = supabase.table("trending_niches").select("*").order("fetched_at", desc=True).limit(6).execute()
return result.data

youtube_router = APIRouter(prefix="/youtube", tags=["YouTube"])

@youtube_router.get("/channel-info")
def get_youtube_channel_info(channelId: str = Query(..., description="YouTube Channel ID")):
"""
Proxy endpoint to fetch YouTube channel info securely from the backend.
The API key is kept secret and rate limiting can be enforced here.
"""
api_key = os.getenv("YOUTUBE_API_KEY")
if not api_key:
raise HTTPException(status_code=500, detail="YouTube API key not configured on server.")
url = f"https://www.googleapis.com/youtube/v3/channels?part=snippet,statistics&id={channelId}&key={api_key}"
try:
resp = requests.get(url, timeout=10)
resp.raise_for_status()
return resp.json()
except requests.RequestException as e:
raise HTTPException(status_code=502, detail=f"YouTube API error: {str(e)}")
7 changes: 7 additions & 0 deletions Backend/app/routes/auth.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
from fastapi import APIRouter

router = APIRouter()

@router.get("/auth/ping")
def ping():
return {"message": "Auth route is working!"}
8 changes: 4 additions & 4 deletions Backend/app/routes/chat.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,12 @@
HTTPException,
)
from sqlalchemy.ext.asyncio import AsyncSession
from db.db import get_db
from services.chat_services import chat_service
from ..db.db import get_db
from ..services.chat_services import chat_service
from redis.asyncio import Redis
from services.redis_client import get_redis
from ..services.redis_client import get_redis
import asyncio
from services.chat_pubsub import listen_to_channel
from ..services.chat_pubsub import listen_to_channel
Comment on lines +10 to +15
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Verification agent

🧩 Analysis chain

Verify the relative import structure to avoid import resolution issues.

The change to relative imports may cause issues with the package structure. Static analysis tools are flagging these as "relative imports beyond top-level package."

Please verify the current package structure and ensure these relative imports work correctly in your deployment environment:

Consider reverting to absolute imports if the relative imports cause issues in your deployment environment:

-from ..db.db import get_db
-from ..services.chat_services import chat_service
-from ..services.redis_client import get_redis
-from ..services.chat_pubsub import listen_to_channel
+from app.db.db import get_db
+from app.services.chat_services import chat_service
+from app.services.redis_client import get_redis
+from app.services.chat_pubsub import listen_to_channel

🏁 Script executed:

#!/bin/bash
# Description: Check the package structure and verify import paths

# Check the directory structure
echo "=== Backend directory structure ==="
find Backend -type f -name "*.py" | head -20

echo -e "\n=== Checking if the imported modules exist ==="
# Check if the imported modules exist at the expected paths
ls -la Backend/app/db/db.py
ls -la Backend/app/services/chat_services.py
ls -la Backend/app/services/redis_client.py
ls -la Backend/app/services/chat_pubsub.py

echo -e "\n=== Checking for __init__.py files ==="
# Check for __init__.py files that make directories Python packages
find Backend -name "__init__.py" -type f

Length of output: 1409


Ensure package initialization or switch to absolute imports to resolve E0402

Verified that all referenced modules exist under Backend/app, but no __init__.py files are present—so static analysis flags “relative imports beyond top-level package.” Choose one of the following fixes:

• Add empty __init__.py in each folder to turn them into proper packages:

  • Backend/app/
  • Backend/app/db/
  • Backend/app/routes/
  • Backend/app/services/

• Or update imports in Backend/app/routes/chat.py to use the app package root:

-from ..db.db import get_db
-from ..services.chat_services import chat_service
-from ..services.redis_client import get_redis
-from ..services.chat_pubsub import listen_to_channel
+from app.db.db import get_db
+from app.services.chat_services import chat_service
+from app.services.redis_client import get_redis
+from app.services.chat_pubsub import listen_to_channel
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
from ..db.db import get_db
from ..services.chat_services import chat_service
from redis.asyncio import Redis
from services.redis_client import get_redis
from ..services.redis_client import get_redis
import asyncio
from services.chat_pubsub import listen_to_channel
from ..services.chat_pubsub import listen_to_channel
from app.db.db import get_db
from app.services.chat_services import chat_service
from redis.asyncio import Redis
from app.services.redis_client import get_redis
import asyncio
from app.services.chat_pubsub import listen_to_channel
🧰 Tools
🪛 Pylint (3.3.7)

[error] 10-10: Attempted relative import beyond top-level package

(E0402)


[error] 11-11: Attempted relative import beyond top-level package

(E0402)


[error] 13-13: Attempted relative import beyond top-level package

(E0402)


[error] 15-15: Attempted relative import beyond top-level package

(E0402)

🤖 Prompt for AI Agents
In Backend/app/routes/chat.py around lines 10 to 15, the relative imports cause
E0402 errors because the directories lack __init__.py files. Fix this by adding
empty __init__.py files in Backend/app/, Backend/app/db/, Backend/app/routes/,
and Backend/app/services/ to make them proper packages, or alternatively, change
the imports to use absolute imports starting from the app package root.


router = APIRouter(prefix="/chat", tags=["Chat"])

Expand Down
29 changes: 29 additions & 0 deletions Backend/app/routes/match.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
from fastapi import APIRouter, HTTPException
from supabase import create_client, Client
import os
from dotenv import load_dotenv
from ..services.db_service import match_creators_for_brand, match_brands_for_creator

# Load environment variables
# load_dotenv()
# url: str = os.getenv("SUPABASE_URL")
# key: str = os.getenv("SUPABASE_KEY")
# supabase: Client = create_client(url, key)

router = APIRouter(prefix="/match", tags=["Matching"])

@router.get("/creators-for-brand/{sponsorship_id}")
def get_creators_for_brand(sponsorship_id: str):
matches = match_creators_for_brand(sponsorship_id)
if not matches:
raise HTTPException(status_code=404, detail="No matching creators found.")
return {"matches": matches}

@router.get("/brands-for-creator/{creator_id}")
def get_brands_for_creator(creator_id: str):
matches = match_brands_for_creator(creator_id)
if not matches:
raise HTTPException(status_code=404, detail="No matching brand campaigns found.")
return {"matches": matches}

# Placeholder for endpoints, logic to be added next
7 changes: 3 additions & 4 deletions Backend/app/routes/post.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
from fastapi import APIRouter, Depends, HTTPException
from sqlalchemy.ext.asyncio import AsyncSession
from sqlalchemy.future import select
from db.db import AsyncSessionLocal
from models.models import (
from ..db.db import AsyncSessionLocal
from ..models.models import (
User, AudienceInsights, Sponsorship, UserPost,
SponsorshipApplication, SponsorshipPayment, Collaboration
)
from schemas.schema import (
from ..schemas.schema import (
UserCreate, AudienceInsightsCreate, SponsorshipCreate, UserPostCreate,
SponsorshipApplicationCreate, SponsorshipPaymentCreate, CollaborationCreate
)
Comment on lines +4 to 12
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Remove unused imports to clean up the codebase.

The static analysis tools correctly identified that these imports are unused. This file uses Supabase client directly for database operations, making the SQLAlchemy imports (AsyncSessionLocal, model classes, and schema classes) unnecessary.

Remove the unused imports:

-from ..db.db import AsyncSessionLocal
-from ..models.models import (
-    User, AudienceInsights, Sponsorship, UserPost,
-    SponsorshipApplication, SponsorshipPayment, Collaboration
-)
-from ..schemas.schema import (
-    UserCreate, AudienceInsightsCreate, SponsorshipCreate, UserPostCreate,
-    SponsorshipApplicationCreate, SponsorshipPaymentCreate, CollaborationCreate
-)
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
from ..db.db import AsyncSessionLocal
from ..models.models import (
User, AudienceInsights, Sponsorship, UserPost,
SponsorshipApplication, SponsorshipPayment, Collaboration
)
from schemas.schema import (
from ..schemas.schema import (
UserCreate, AudienceInsightsCreate, SponsorshipCreate, UserPostCreate,
SponsorshipApplicationCreate, SponsorshipPaymentCreate, CollaborationCreate
)
🧰 Tools
🪛 Ruff (0.11.9)

4-4: ..db.db.AsyncSessionLocal imported but unused

Remove unused import: ..db.db.AsyncSessionLocal

(F401)


6-6: ..models.models.User imported but unused

Remove unused import

(F401)


6-6: ..models.models.AudienceInsights imported but unused

Remove unused import

(F401)


6-6: ..models.models.Sponsorship imported but unused

Remove unused import

(F401)


6-6: ..models.models.UserPost imported but unused

Remove unused import

(F401)


7-7: ..models.models.SponsorshipApplication imported but unused

Remove unused import

(F401)


7-7: ..models.models.SponsorshipPayment imported but unused

Remove unused import

(F401)


7-7: ..models.models.Collaboration imported but unused

Remove unused import

(F401)

🪛 Flake8 (7.2.0)

[error] 4-4: '..db.db.AsyncSessionLocal' imported but unused

(F401)


[error] 5-5: '..models.models.User' imported but unused

(F401)


[error] 5-5: '..models.models.AudienceInsights' imported but unused

(F401)


[error] 5-5: '..models.models.Sponsorship' imported but unused

(F401)


[error] 5-5: '..models.models.UserPost' imported but unused

(F401)


[error] 5-5: '..models.models.SponsorshipApplication' imported but unused

(F401)


[error] 5-5: '..models.models.SponsorshipPayment' imported but unused

(F401)


[error] 5-5: '..models.models.Collaboration' imported but unused

(F401)

🪛 Pylint (3.3.7)

[error] 4-4: Attempted relative import beyond top-level package

(E0402)


[error] 5-8: Attempted relative import beyond top-level package

(E0402)


[error] 9-12: Attempted relative import beyond top-level package

(E0402)

🤖 Prompt for AI Agents
In Backend/app/routes/post.py around lines 4 to 12, remove all imports related
to AsyncSessionLocal, model classes (User, AudienceInsights, Sponsorship,
UserPost, SponsorshipApplication, SponsorshipPayment, Collaboration), and schema
classes (UserCreate, AudienceInsightsCreate, SponsorshipCreate, UserPostCreate,
SponsorshipApplicationCreate, SponsorshipPaymentCreate, CollaborationCreate)
since they are not used in this file. This cleanup will keep the codebase tidy
and avoid unnecessary dependencies.

Expand Down Expand Up @@ -44,7 +44,6 @@ async def create_user(user: UserCreate):
"id": user_id,
"username": user.username,
"email": user.email,
"password_hash": user.password_hash,
"role": user.role,
"profile_image": user.profile_image,
"bio": user.bio,
Expand Down
1 change: 0 additions & 1 deletion Backend/app/schemas/schema.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
class UserCreate(BaseModel):
username: str
email: str
password_hash: str
role: str
profile_image: Optional[str] = None
bio: Optional[str] = None
Expand Down
4 changes: 2 additions & 2 deletions Backend/app/services/chat_services.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@
from sqlalchemy.ext.asyncio import AsyncSession
from sqlalchemy.sql import select
from datetime import datetime, timezone
from models.models import User
from models.chat import ChatList, ChatMessage, MessageStatus
from app.models.models import User
from app.models.chat import ChatList, ChatMessage, MessageStatus
from typing import Dict
from redis.asyncio import Redis
import logging
Expand Down
Loading