Nagesh Muralidhar commited on
Commit
1bcce96
·
1 Parent(s): 80c42b8

make changes

Browse files
.dockerignore ADDED
@@ -0,0 +1,50 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Git
2
+ .git
3
+ .gitignore
4
+ .gitattributes
5
+ .github
6
+
7
+ # Python
8
+ __pycache__/
9
+ *.py[cod]
10
+ *$py.class
11
+ *.so
12
+ .Python
13
+ venv/
14
+ ENV/
15
+ env/
16
+ .env
17
+ backend/venv/
18
+
19
+ # Node.js
20
+ node_modules/
21
+ npm-debug.log
22
+ yarn-debug.log
23
+ yarn-error.log
24
+ frontend/podcraft/node_modules/
25
+
26
+ # Build files
27
+ frontend/podcraft/build/
28
+ frontend/podcraft/dist/
29
+
30
+ # Audio and temp files
31
+ temp_audio/
32
+ temp/
33
+ backend/temp_audio/
34
+ backend/temp/
35
+
36
+ # Editor directories and files
37
+ .idea/
38
+ .vscode/
39
+ *.swp
40
+ *.swo
41
+ *~
42
+
43
+ # OS generated files
44
+ .DS_Store
45
+ .DS_Store?
46
+ ._*
47
+ .Spotlight-V100
48
+ .Trashes
49
+ ehthumbs.db
50
+ Thumbs.db
.gitattributes CHANGED
@@ -39,9 +39,3 @@ saved_model/**/* filter=lfs diff=lfs merge=lfs -text
39
  *.png filter=lfs diff=lfs merge=lfs -text
40
  *.jpg filter=lfs diff=lfs merge=lfs -text
41
  *.jpeg filter=lfs diff=lfs merge=lfs -text
42
- *.wav filter=lfs diff=lfs merge=lfs -text
43
- *.ogg filter=lfs diff=lfs merge=lfs -text
44
- *.woff filter=lfs diff=lfs merge=lfs -text
45
- *.woff2 filter=lfs diff=lfs merge=lfs -text
46
- *.ttf filter=lfs diff=lfs merge=lfs -text
47
- *.otf filter=lfs diff=lfs merge=lfs -text
 
39
  *.png filter=lfs diff=lfs merge=lfs -text
40
  *.jpg filter=lfs diff=lfs merge=lfs -text
41
  *.jpeg filter=lfs diff=lfs merge=lfs -text
 
 
 
 
 
 
.github/workflows/docker-image.yml DELETED
@@ -1,22 +0,0 @@
1
- name: Docker Image CI/CD
2
-
3
- on:
4
- push:
5
- branches: [ main ]
6
- pull_request:
7
- branches: [ main ]
8
-
9
- jobs:
10
- build:
11
- runs-on: ubuntu-latest
12
- steps:
13
- - uses: actions/checkout@v2
14
-
15
- - name: Set up Docker Buildx
16
- uses: docker/setup-buildx-action@v1
17
-
18
- - name: Build the Docker image
19
- run: |
20
- docker build . --file Dockerfile --tag podcraft-app:$(date +%s)
21
-
22
- # Add deployment steps here if needed for your specific platform
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
.gitignore CHANGED
@@ -1,87 +1,34 @@
1
- # Node.js dependencies
2
- node_modules/
3
- npm-debug.log
4
- yarn-error.log
5
- package-lock.json
6
- yarn.lock
7
-
8
- # Python cache files
9
- __pycache__/
10
- *.py[cod]
11
- *$py.class
12
- *.so
13
- .Python
14
- env/
15
- build/
16
- develop-eggs/
17
- dist/
18
- downloads/
19
- eggs/
20
- .eggs/
21
- lib/
22
- lib64/
23
- parts/
24
- sdist/
25
- var/
26
- *.egg-info/
27
- .installed.cfg
28
- *.egg
29
-
30
- # Virtual Environment
31
- venv/
32
- ENV/
33
- env/
34
-
35
- # Editor directories and files
36
- .idea/
37
- .vscode/
38
- *.swp
39
- *.swo
40
  .DS_Store
 
 
 
 
 
 
 
 
41
 
42
- # Environment variables
43
  .env
44
- .env.local
45
- .env.development.local
46
- .env.test.local
47
- .env.production.local
48
-
49
- # Audio files
50
  temp_audio/
51
- *.mp3
52
- *.wav
53
- *.ogg
54
-
55
- # Logs
56
- logs/
57
- *.log
58
- npm-debug.log*
59
- yarn-debug.log*
60
- yarn-error.log*
61
 
62
- # Distribution / packaging
63
- .Python
64
- build/
65
- develop-eggs/
66
- dist/
67
- downloads/
68
- eggs/
69
- .eggs/
70
- lib/
71
- lib64/
72
- parts/
73
- sdist/
74
- var/
75
- wheels/
76
- *.egg-info/
77
- .installed.cfg
78
- *.egg
79
 
80
- # Jupyter Notebook
81
- .ipynb_checkpoints
82
-
83
- # Docker
84
- .dockerignore
85
 
86
- # Frontend build
87
  frontend/podcraft/build/
 
 
1
+ backend/app/__pycache__
2
+ backend/.env
3
+ frontend/podcraft/node_modules
4
+ backend/.venv/
5
+ backend/venv/
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
6
  .DS_Store
7
+ frontend/podcraft/.DS_Store
8
+ backend/.DS_Store
9
+ frontend/.DS_Store
10
+ backend/temp_audio/*
11
+ !backend/temp_audio/Default/
12
+ !backend/temp_audio/Default/final_podcast.mp3
13
+ backend/temp/*
14
+ backend/app/agents/__pycache__/
15
 
16
+ # Docker
17
  .env
 
 
 
 
 
 
18
  temp_audio/
19
+ temp/
 
 
 
 
 
 
 
 
 
20
 
21
+ # Python
22
+ __pycache__/
23
+ *.py[cod]
24
+ *$py.class
 
 
 
 
 
 
 
 
 
 
 
 
 
25
 
26
+ # Node.js
27
+ node_modules/
28
+ npm-debug.log
29
+ yarn-debug.log
30
+ yarn-error.log
31
 
32
+ # Build files
33
  frontend/podcraft/build/
34
+ frontend/podcraft/dist/
Dockerfile CHANGED
@@ -1,46 +1,49 @@
1
- FROM python:3.9-slim
2
 
3
  WORKDIR /app
4
 
5
- # Install system dependencies including ffmpeg
6
  RUN apt-get update && \
7
  apt-get install -y --no-install-recommends \
8
  ffmpeg \
9
  build-essential \
10
- curl \
11
- gnupg \
 
 
12
  && rm -rf /var/lib/apt/lists/*
13
 
14
- # Copy requirements first to leverage Docker cache
15
- COPY backend/requirements.txt .
16
- RUN pip install --no-cache-dir -r requirements.txt
17
-
18
- # Copy backend code
19
- COPY backend/app/ /app/app/
20
 
21
- # Ensure static directory exists
22
- RUN mkdir -p /app/static
23
 
24
- # Copy frontend build to static directory
25
- COPY frontend/podcraft/build/ /app/static/
 
 
 
 
 
26
 
27
- # Install additional packages needed for serving frontend
28
- RUN pip install --no-cache-dir python-multipart
 
29
 
30
- # Create directory for temporary files
31
- RUN mkdir -p /app/temp_audio
 
32
 
33
- # Set environment variables
34
- ENV PYTHONPATH=/app
35
- ENV MONGODB_URL="mongodb+srv://NageshBM:Nash166^@podcraft.ozqmc.mongodb.net/?retryWrites=true&w=majority&appName=Podcraft"
36
 
37
- # Copy the placeholder index.html if the app/static directory is empty
38
- RUN if [ -z "$(ls -A /app/static 2>/dev/null)" ]; then \
39
- echo "<html><body><h1>PodCraft API</h1><p>Frontend not available. Please build the frontend before running.</p></body></html>" > /app/static/index.html; \
40
- fi
41
 
42
- # Expose the port the app runs on
43
- EXPOSE 8000
44
 
45
  # Command to run the application
46
- CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "8000"]
 
1
+ FROM python:3.11-slim
2
 
3
  WORKDIR /app
4
 
5
+ # Install ffmpeg and other dependencies
6
  RUN apt-get update && \
7
  apt-get install -y --no-install-recommends \
8
  ffmpeg \
9
  build-essential \
10
+ nodejs \
11
+ npm \
12
+ git \
13
+ && apt-get clean \
14
  && rm -rf /var/lib/apt/lists/*
15
 
16
+ # Copy the application code
17
+ COPY . .
 
 
 
 
18
 
19
+ # Execute the build frontend script to prepare frontend code
20
+ RUN chmod +x build_frontend.sh && ./build_frontend.sh
21
 
22
+ # Build frontend
23
+ WORKDIR /app/frontend/podcraft
24
+ RUN npm install && \
25
+ npm run build || \
26
+ (echo "Frontend build failed, creating dummy build directory" && \
27
+ mkdir -p build && \
28
+ echo "<html><body><h1>PodCraft</h1><p>Frontend not built correctly. Please check logs.</p></body></html>" > build/index.html)
29
 
30
+ # Return to app directory and install backend dependencies
31
+ WORKDIR /app
32
+ RUN pip install --no-cache-dir -r requirements.txt
33
 
34
+ # Create static directory and copy the built frontend
35
+ RUN mkdir -p ./static && \
36
+ cp -r frontend/podcraft/build/* ./static/ || echo "No frontend build files to copy"
37
 
38
+ # Create directories for temp files
39
+ RUN mkdir -p temp_audio temp
 
40
 
41
+ # Default environment variables
42
+ ENV PORT=7860
43
+ ENV HOST=0.0.0.0
 
44
 
45
+ # Expose the port
46
+ EXPOSE 7860
47
 
48
  # Command to run the application
49
+ CMD ["python", "app.py"]
Dockerfile.spaces DELETED
@@ -1,144 +0,0 @@
1
- FROM python:3.9-slim
2
-
3
- WORKDIR /app
4
-
5
- # Install system dependencies including ffmpeg
6
- RUN apt-get update && \
7
- apt-get install -y --no-install-recommends \
8
- ffmpeg \
9
- build-essential \
10
- curl \
11
- gnupg \
12
- && rm -rf /var/lib/apt/lists/*
13
-
14
- # Copy backend requirements and install
15
- COPY backend/requirements.txt .
16
- RUN pip install --no-cache-dir -r requirements.txt
17
-
18
- # Install additional packages needed for serving frontend
19
- RUN pip install --no-cache-dir python-multipart
20
-
21
- # Copy backend code
22
- COPY backend/ /app/backend/
23
-
24
- # Create static directory with a placeholder index.html
25
- RUN mkdir -p /app/static && \
26
- echo '<!DOCTYPE html>\
27
- <html lang="en">\
28
- <head>\
29
- <meta charset="UTF-8">\
30
- <meta name="viewport" content="width=device-width, initial-scale=1.0">\
31
- <title>PodCraft - Loading...</title>\
32
- <style>\
33
- body {\
34
- font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen, Ubuntu, Cantarell, "Open Sans", "Helvetica Neue", sans-serif;\
35
- background-color: #1a1a2e;\
36
- color: #ffffff;\
37
- display: flex;\
38
- flex-direction: column;\
39
- align-items: center;\
40
- justify-content: center;\
41
- height: 100vh;\
42
- margin: 0;\
43
- text-align: center;\
44
- }\
45
- h1 {\
46
- color: #8b5cf6;\
47
- font-size: 2.5rem;\
48
- margin-bottom: 1rem;\
49
- }\
50
- p {\
51
- max-width: 600px;\
52
- line-height: 1.6;\
53
- margin-bottom: 2rem;\
54
- }\
55
- .loading {\
56
- display: inline-block;\
57
- position: relative;\
58
- width: 80px;\
59
- height: 80px;\
60
- }\
61
- .loading div {\
62
- position: absolute;\
63
- top: 33px;\
64
- width: 13px;\
65
- height: 13px;\
66
- border-radius: 50%;\
67
- background: #8b5cf6;\
68
- animation-timing-function: cubic-bezier(0, 1, 1, 0);\
69
- }\
70
- .loading div:nth-child(1) {\
71
- left: 8px;\
72
- animation: loading1 0.6s infinite;\
73
- }\
74
- .loading div:nth-child(2) {\
75
- left: 8px;\
76
- animation: loading2 0.6s infinite;\
77
- }\
78
- .loading div:nth-child(3) {\
79
- left: 32px;\
80
- animation: loading2 0.6s infinite;\
81
- }\
82
- .loading div:nth-child(4) {\
83
- left: 56px;\
84
- animation: loading3 0.6s infinite;\
85
- }\
86
- @keyframes loading1 {\
87
- 0% {\
88
- transform: scale(0);\
89
- }\
90
- 100% {\
91
- transform: scale(1);\
92
- }\
93
- }\
94
- @keyframes loading3 {\
95
- 0% {\
96
- transform: scale(1);\
97
- }\
98
- 100% {\
99
- transform: scale(0);\
100
- }\
101
- }\
102
- @keyframes loading2 {\
103
- 0% {\
104
- transform: translate(0, 0);\
105
- }\
106
- 100% {\
107
- transform: translate(24px, 0);\
108
- }\
109
- }\
110
- </style>\
111
- </head>\
112
- <body>\
113
- <h1>PodCraft</h1>\
114
- <p>The AI-powered podcast generation platform is setting up. Please check back in a few minutes while we complete the build process.</p>\
115
- <div class="loading">\
116
- <div></div>\
117
- <div></div>\
118
- <div></div>\
119
- <div></div>\
120
- </div>\
121
- </body>\
122
- </html>' > /app/static/index.html
123
-
124
- # Create directory for temporary files
125
- RUN mkdir -p /app/temp_audio
126
-
127
- # Set environment variables
128
- ENV PYTHONPATH=/app
129
- ENV MONGODB_URL="mongodb+srv://NageshBM:Nash166^@podcraft.ozqmc.mongodb.net/?retryWrites=true&w=majority&appName=Podcraft"
130
- ENV OPENAI_API_KEY=""
131
-
132
- # Create a simple main.py for the HuggingFace Space
133
- RUN echo 'import sys\n\
134
- import os\n\
135
- # Add backend to Python path\n\
136
- sys.path.insert(0, os.path.join(os.path.dirname(__file__), "backend"))\n\
137
- # Import the main app\n\
138
- from backend.app.main import app' > /app/main.py
139
-
140
- # Expose the port the app runs on
141
- EXPOSE 7860
142
-
143
- # HuggingFace Spaces expects the app to run on port 7860
144
- CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "7860"]
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
app.py ADDED
@@ -0,0 +1,101 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import sys
3
+ import shutil
4
+ import logging
5
+ from pathlib import Path
6
+
7
+ # Set up logging
8
+ logging.basicConfig(level=logging.INFO)
9
+ logger = logging.getLogger(__name__)
10
+
11
+ # Add the backend directory to the Python path
12
+ sys.path.append(os.path.abspath("backend"))
13
+
14
+ # Create necessary directories if they don't exist
15
+ os.makedirs("./temp_audio", exist_ok=True)
16
+ os.makedirs("./temp", exist_ok=True)
17
+
18
+ # Set environment variables for MongoDB connection timeout
19
+ os.environ["MONGODB_CONNECT_TIMEOUT_MS"] = "5000" # 5 seconds timeout
20
+ os.environ["MONGODB_SERVER_SELECTION_TIMEOUT_MS"] = "5000" # 5 seconds timeout
21
+
22
+ try:
23
+ # Set up CORS headers to allow frontend to access backend
24
+ from backend.app.main import app
25
+ from fastapi.middleware.cors import CORSMiddleware
26
+
27
+ app.add_middleware(
28
+ CORSMiddleware,
29
+ allow_origins=["*"],
30
+ allow_credentials=True,
31
+ allow_methods=["*"],
32
+ allow_headers=["*"],
33
+ )
34
+
35
+ # Serve static files from the frontend build directory
36
+ from fastapi.staticfiles import StaticFiles
37
+
38
+ # Check if static directory exists with index.html
39
+ static_path = Path("./static")
40
+ if static_path.exists() and (static_path / "index.html").exists():
41
+ app.mount("/", StaticFiles(directory="./static", html=True), name="static")
42
+
43
+ # For Hugging Face Spaces - expose the app
44
+ if __name__ == "__main__":
45
+ import uvicorn
46
+
47
+ port = int(os.environ.get("PORT", 7860))
48
+ host = os.environ.get("HOST", "0.0.0.0")
49
+
50
+ logger.info(f"Starting server on {host}:{port}")
51
+ uvicorn.run(app, host=host, port=port)
52
+
53
+ except Exception as e:
54
+ # If there's an error, create a minimal FastAPI app to show the error
55
+ from fastapi import FastAPI
56
+ from fastapi.responses import HTMLResponse
57
+ from fastapi.staticfiles import StaticFiles
58
+
59
+ error_app = FastAPI()
60
+
61
+ @error_app.get("/", response_class=HTMLResponse)
62
+ async def root():
63
+ return f"""
64
+ <html>
65
+ <head>
66
+ <title>PodCraft - Error</title>
67
+ <style>
68
+ body {{ font-family: Arial, sans-serif; margin: 0; padding: 0; display: flex; justify-content: center; align-items: center; height: 100vh; background-color: #f8f9fa; }}
69
+ .container {{ max-width: 800px; padding: 2rem; background-color: white; border-radius: 0.5rem; box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1); }}
70
+ h1 {{ color: #d32f2f; }}
71
+ pre {{ background-color: #f5f5f5; padding: 1rem; border-radius: 0.25rem; overflow: auto; }}
72
+ </style>
73
+ </head>
74
+ <body>
75
+ <div class="container">
76
+ <h1>PodCraft Error</h1>
77
+ <p>An error occurred while starting the application:</p>
78
+ <pre>{str(e)}</pre>
79
+ <p>Please check your environment variables and configuration.</p>
80
+ <p>MongoDB URL format should be: <code>mongodb+srv://username:[email protected]/...</code></p>
81
+ <p>API keys should be properly formatted and valid.</p>
82
+ </div>
83
+ </body>
84
+ </html>
85
+ """
86
+
87
+ # Check if static directory exists with index.html
88
+ static_path = Path("./static")
89
+ if static_path.exists() and (static_path / "index.html").exists():
90
+ error_app.mount("/static", StaticFiles(directory="./static"), name="static")
91
+
92
+ if __name__ == "__main__":
93
+ import uvicorn
94
+
95
+ port = int(os.environ.get("PORT", 7860))
96
+ host = os.environ.get("HOST", "0.0.0.0")
97
+
98
+ logger.error(f"Application failed to start normally. Starting error app on {host}:{port}")
99
+ logger.error(f"Error: {str(e)}")
100
+
101
+ uvicorn.run(error_app, host=host, port=port)
app/main.py DELETED
@@ -1,238 +0,0 @@
1
- from fastapi import FastAPI, Request, HTTPException, Depends, status, File, UploadFile, Form
2
- from fastapi.security import OAuth2PasswordBearer, OAuth2PasswordRequestForm
3
- from fastapi.responses import JSONResponse, FileResponse, HTMLResponse, RedirectResponse
4
- from fastapi.staticfiles import StaticFiles
5
- from fastapi.middleware.cors import CORSMiddleware
6
- from pydantic import BaseModel
7
- from typing import Optional, Dict, List, Union, Any
8
- from datetime import datetime, timedelta
9
- import jwt
10
- from jwt.exceptions import PyJWTError
11
- from passlib.context import CryptContext
12
- import os
13
- import shutil
14
- import logging
15
- import json
16
- from motor.motor_asyncio import AsyncIOMotorClient
17
- from decouple import config
18
- import uuid
19
- from bson.objectid import ObjectId
20
- import asyncio
21
- import time
22
- import sys
23
- from pathlib import Path
24
-
25
- # Import the original app modules
26
- from app.models import *
27
- from app.agents.podcast_manager import PodcastManager
28
- from app.agents.researcher import Researcher
29
- from app.agents.debate_agent import DebateAgent
30
-
31
- # Setup logging
32
- logging.basicConfig(level=logging.INFO)
33
- logger = logging.getLogger(__name__)
34
-
35
- # Initialize FastAPI app
36
- app = FastAPI(title="PodCraft API")
37
-
38
- # Add CORS middleware
39
- app.add_middleware(
40
- CORSMiddleware,
41
- allow_origins=["*"], # Allow all origins in production
42
- allow_credentials=True,
43
- allow_methods=["*"],
44
- allow_headers=["*"],
45
- )
46
-
47
- # Get MongoDB connection string from environment or config
48
- MONGODB_URL = os.getenv("MONGODB_URL", config("MONGODB_URL", default="mongodb://localhost:27017"))
49
-
50
- # MongoDB client
51
- client = AsyncIOMotorClient(MONGODB_URL)
52
- db = client.podcraft
53
- users = db.users
54
- podcasts = db.podcasts
55
- agents = db.agents
56
- workflows = db.workflows
57
-
58
- # Initialize podcast manager
59
- podcast_manager = PodcastManager()
60
-
61
- # Initialize researcher
62
- researcher = Researcher()
63
-
64
- # Initialize debate agent
65
- debate_agent = DebateAgent()
66
-
67
- # Password hashing
68
- pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto")
69
-
70
- # JWT settings
71
- SECRET_KEY = os.getenv("SECRET_KEY", config("SECRET_KEY", default="your-secret-key"))
72
- ALGORITHM = "HS256"
73
- ACCESS_TOKEN_EXPIRE_MINUTES = 60 * 24 * 7 # 1 week
74
-
75
- # OAuth2 scheme
76
- oauth2_scheme = OAuth2PasswordBearer(tokenUrl="token")
77
-
78
- # Keep the original authentication and API routes
79
- # Include all the functions and routes from the original main.py
80
-
81
- def create_access_token(data: dict):
82
- to_encode = data.copy()
83
- expire = datetime.utcnow() + timedelta(minutes=ACCESS_TOKEN_EXPIRE_MINUTES)
84
- to_encode.update({"exp": expire})
85
- encoded_jwt = jwt.encode(to_encode, SECRET_KEY, algorithm=ALGORITHM)
86
- return encoded_jwt
87
-
88
- def verify_password(plain_password, hashed_password):
89
- return pwd_context.verify(plain_password, hashed_password)
90
-
91
- def get_password_hash(password):
92
- return pwd_context.hash(password)
93
-
94
- async def get_current_user(token: str = Depends(oauth2_scheme)):
95
- credentials_exception = HTTPException(
96
- status_code=status.HTTP_401_UNAUTHORIZED,
97
- detail="Could not validate credentials",
98
- headers={"WWW-Authenticate": "Bearer"},
99
- )
100
- try:
101
- payload = jwt.decode(token, SECRET_KEY, algorithms=[ALGORITHM])
102
- username: str = payload.get("sub")
103
- if username is None:
104
- raise credentials_exception
105
- except PyJWTError:
106
- raise credentials_exception
107
-
108
- user = await users.find_one({"username": username})
109
- if user is None:
110
- raise credentials_exception
111
-
112
- # Convert ObjectId to string for JSON serialization
113
- user["_id"] = str(user["_id"])
114
-
115
- return user
116
-
117
- # Route for health check
118
- @app.get("/health")
119
- async def health():
120
- return {"status": "healthy", "version": "1.0.0"}
121
-
122
- # API routes
123
- @app.post("/signup")
124
- async def signup(user: UserCreate):
125
- # Check if username exists
126
- existing_user = await users.find_one({"username": user.username})
127
- if existing_user:
128
- raise HTTPException(status_code=400, detail="Username already registered")
129
-
130
- # Hash the password
131
- hashed_password = get_password_hash(user.password)
132
-
133
- # Create new user
134
- user_obj = {"username": user.username, "password": hashed_password}
135
- new_user = await users.insert_one(user_obj)
136
-
137
- # Create access token
138
- access_token = create_access_token(data={"sub": user.username})
139
-
140
- return {"access_token": access_token, "token_type": "bearer"}
141
-
142
- @app.post("/token", response_model=Token)
143
- async def login_for_access_token(form_data: OAuth2PasswordRequestForm = Depends()):
144
- user = await users.find_one({"username": form_data.username})
145
- if not user or not verify_password(form_data.password, user["password"]):
146
- raise HTTPException(
147
- status_code=status.HTTP_401_UNAUTHORIZED,
148
- detail="Incorrect username or password",
149
- headers={"WWW-Authenticate": "Bearer"},
150
- )
151
-
152
- access_token = create_access_token(data={"sub": form_data.username})
153
- return {"access_token": access_token, "token_type": "bearer"}
154
-
155
- @app.post("/login", response_model=Token)
156
- async def login(request: Request, user: UserLogin):
157
- db_user = await users.find_one({"username": user.username})
158
- if not db_user or not verify_password(user.password, db_user["password"]):
159
- raise HTTPException(
160
- status_code=status.HTTP_401_UNAUTHORIZED,
161
- detail="Incorrect username or password"
162
- )
163
-
164
- access_token = create_access_token(data={"sub": user.username})
165
- return {"access_token": access_token, "token_type": "bearer"}
166
-
167
- # Add all the other API routes from the original main.py
168
- # ...
169
-
170
- # Determine static files path
171
- static_path = os.path.abspath(os.path.join(os.path.dirname(__file__), "..", "static"))
172
- if not os.path.exists(static_path):
173
- try:
174
- os.makedirs(static_path, exist_ok=True)
175
- with open(os.path.join(static_path, "index.html"), "w") as f:
176
- f.write("<html><body><h1>PodCraft API</h1><p>Frontend not found.</p></body></html>")
177
- except Exception as e:
178
- logger.error(f"Error creating static path: {e}")
179
-
180
- # Mount static files for frontend
181
- app.mount("/static", StaticFiles(directory=static_path), name="static")
182
-
183
- # Add route to serve audio files
184
- @app.get("/audio/{path:path}")
185
- async def serve_audio(path: str):
186
- audio_dir = "/app/temp_audio"
187
- if not os.path.exists(audio_dir):
188
- try:
189
- os.makedirs(audio_dir, exist_ok=True)
190
- except Exception as e:
191
- logger.error(f"Error creating audio directory: {e}")
192
-
193
- audio_file = os.path.join(audio_dir, path)
194
- if os.path.exists(audio_file):
195
- return FileResponse(audio_file)
196
- else:
197
- raise HTTPException(status_code=404, detail="Audio file not found")
198
-
199
- # Root path to serve frontend or redirect to static
200
- @app.get("/", response_class=HTMLResponse)
201
- async def serve_frontend():
202
- index_file = os.path.join(static_path, "index.html")
203
- if os.path.exists(index_file):
204
- with open(index_file, "r") as f:
205
- return HTMLResponse(content=f.read())
206
- else:
207
- # Create a minimal index.html if it doesn't exist
208
- html_content = """
209
- <!DOCTYPE html>
210
- <html>
211
- <head>
212
- <title>PodCraft API</title>
213
- <style>
214
- body { font-family: Arial, sans-serif; padding: 20px; }
215
- h1 { color: #8b5cf6; }
216
- </style>
217
- </head>
218
- <body>
219
- <h1>PodCraft API</h1>
220
- <p>The frontend application is not available. Please build the frontend or check the documentation.</p>
221
- </body>
222
- </html>
223
- """
224
- return HTMLResponse(content=html_content)
225
-
226
- # Catch-all route for SPA routing - all non-API routes should serve the frontend
227
- @app.get("/{full_path:path}")
228
- async def catch_all(full_path: str):
229
- # If path starts with "api", it's an API route not found
230
- if full_path.startswith("api/"):
231
- raise HTTPException(status_code=404, detail="API endpoint not found")
232
-
233
- # Otherwise serve the SPA
234
- return await serve_frontend()
235
-
236
- if __name__ == "__main__":
237
- import uvicorn
238
- uvicorn.run("main:app", host="0.0.0.0", port=8000, reload=True)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
apt.txt ADDED
@@ -0,0 +1,2 @@
 
 
 
1
+ ffmpeg
2
+ build-essential
build_and_deploy.sh DELETED
@@ -1,32 +0,0 @@
1
- #!/bin/bash
2
- set -e
3
-
4
- echo "===> Building PodCraft for deployment <===="
5
-
6
- # Navigate to frontend directory
7
- echo "Building frontend..."
8
- cd frontend/podcraft
9
-
10
- # Install dependencies
11
- echo "Installing frontend dependencies..."
12
- npm install
13
-
14
- # Build the frontend
15
- echo "Creating production build..."
16
- npm run build
17
-
18
- # Back to root directory
19
- cd ../../
20
-
21
- # Make sure static directory exists
22
- mkdir -p app/static
23
-
24
- # Copy build to static directory (this will be mounted by FastAPI)
25
- echo "Copying frontend build to static directory..."
26
- cp -r frontend/podcraft/build/* app/static/
27
-
28
- echo "Building Docker image..."
29
- docker build -t podcraft-app .
30
-
31
- echo "Build completed successfully!"
32
- echo "You can now run: docker run -p 8000:8000 podcraft-app"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
build_for_spaces.sh DELETED
@@ -1,33 +0,0 @@
1
- #!/bin/bash
2
- set -e
3
-
4
- echo "===> Building PodCraft for HuggingFace Spaces <===="
5
-
6
- # Navigate to frontend directory
7
- echo "Building frontend..."
8
- cd frontend/podcraft
9
-
10
- # Install dependencies
11
- echo "Installing frontend dependencies..."
12
- npm install
13
-
14
- # Build the frontend
15
- echo "Creating production build..."
16
- npm run build
17
-
18
- # Back to root directory
19
- cd ../../
20
-
21
- # Make sure static directory exists
22
- mkdir -p app/static
23
-
24
- # Copy build to static directory (this will be mounted by FastAPI)
25
- echo "Copying frontend build to static directory..."
26
- cp -r frontend/podcraft/build/* app/static/
27
-
28
- # Copy the Spaces Dockerfile to main Dockerfile
29
- echo "Setting up Dockerfile for Spaces deployment..."
30
- cp Dockerfile.spaces Dockerfile
31
-
32
- echo "Build setup completed successfully!"
33
- echo "You can now push this to your HuggingFace Space repository"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
build_frontend.sh ADDED
@@ -0,0 +1,150 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/bin/bash
2
+
3
+ # This script is used to pull the latest frontend code during the build process
4
+ # It is called from the Dockerfile
5
+
6
+ set -e # Exit on error
7
+
8
+ if [ -d "frontend/podcraft" ]; then
9
+ echo "Frontend code already exists"
10
+ else
11
+ echo "Frontend code not found, creating dummy placeholder"
12
+ mkdir -p frontend/podcraft/public
13
+ mkdir -p frontend/podcraft/src
14
+
15
+ # Create a minimal package.json
16
+ cat > frontend/podcraft/package.json << EOF
17
+ {
18
+ "name": "podcraft",
19
+ "private": true,
20
+ "version": "0.0.0",
21
+ "type": "module",
22
+ "scripts": {
23
+ "dev": "vite",
24
+ "build": "vite build",
25
+ "lint": "eslint .",
26
+ "preview": "vite preview"
27
+ },
28
+ "dependencies": {
29
+ "react": "^18.2.0",
30
+ "react-dom": "^18.2.0",
31
+ "react-icons": "^4.10.1",
32
+ "react-router-dom": "^6.15.0",
33
+ "reactflow": "^11.8.3"
34
+ },
35
+ "devDependencies": {
36
+ "@types/react": "^18.2.15",
37
+ "@types/react-dom": "^18.2.7",
38
+ "@vitejs/plugin-react": "^4.0.3",
39
+ "eslint": "^8.0.0",
40
+ "eslint-plugin-react-hooks": "^4.0.0",
41
+ "eslint-plugin-react-refresh": "^0.4.0",
42
+ "vite": "^4.0.0"
43
+ }
44
+ }
45
+ EOF
46
+
47
+ # Create a minimal index.html
48
+ cat > frontend/podcraft/index.html << EOF
49
+ <!DOCTYPE html>
50
+ <html lang="en">
51
+ <head>
52
+ <meta charset="UTF-8" />
53
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
54
+ <title>PodCraft</title>
55
+ </head>
56
+ <body>
57
+ <div id="root"></div>
58
+ <script type="module" src="/src/main.jsx"></script>
59
+ </body>
60
+ </html>
61
+ EOF
62
+
63
+ # Create a minimal vite.config.js
64
+ cat > frontend/podcraft/vite.config.js << EOF
65
+ import { defineConfig } from 'vite'
66
+ import react from '@vitejs/plugin-react'
67
+
68
+ export default defineConfig({
69
+ plugins: [react()],
70
+ server: {
71
+ proxy: {
72
+ '/api': 'http://localhost:8000',
73
+ '/login': 'http://localhost:8000',
74
+ '/signup': 'http://localhost:8000',
75
+ '/token': 'http://localhost:8000',
76
+ '/generate-podcast': 'http://localhost:8000'
77
+ }
78
+ }
79
+ })
80
+ EOF
81
+
82
+ # Create a minimal main.jsx
83
+ mkdir -p frontend/podcraft/src
84
+ cat > frontend/podcraft/src/main.jsx << EOF
85
+ import React from 'react'
86
+ import ReactDOM from 'react-dom/client'
87
+ import App from './App.jsx'
88
+ import './index.css'
89
+
90
+ ReactDOM.createRoot(document.getElementById('root')).render(
91
+ <React.StrictMode>
92
+ <App />
93
+ </React.StrictMode>,
94
+ )
95
+ EOF
96
+
97
+ # Create a minimal App.jsx
98
+ cat > frontend/podcraft/src/App.jsx << EOF
99
+ import React from 'react'
100
+ import './App.css'
101
+
102
+ function App() {
103
+ return (
104
+ <div className="App">
105
+ <header className="App-header">
106
+ <h1>PodCraft</h1>
107
+ <p>Welcome to PodCraft API. This is the backend server for the PodCraft application.</p>
108
+ <p>Please use the API endpoints to interact with the application.</p>
109
+ </header>
110
+ </div>
111
+ )
112
+ }
113
+
114
+ export default App
115
+ EOF
116
+
117
+ # Create minimal CSS files
118
+ cat > frontend/podcraft/src/index.css << EOF
119
+ body {
120
+ margin: 0;
121
+ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
122
+ 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue',
123
+ sans-serif;
124
+ -webkit-font-smoothing: antialiased;
125
+ -moz-osx-font-smoothing: grayscale;
126
+ }
127
+ EOF
128
+
129
+ cat > frontend/podcraft/src/App.css << EOF
130
+ .App {
131
+ text-align: center;
132
+ }
133
+
134
+ .App-header {
135
+ background-color: #282c34;
136
+ min-height: 100vh;
137
+ display: flex;
138
+ flex-direction: column;
139
+ align-items: center;
140
+ justify-content: center;
141
+ font-size: calc(10px + 2vmin);
142
+ color: white;
143
+ }
144
+ EOF
145
+
146
+ echo "Created dummy frontend code"
147
+ fi
148
+
149
+ # Make the script executable
150
+ chmod +x $0
docker-compose.yml CHANGED
@@ -1,15 +1,24 @@
1
- version: '3'
2
 
3
  services:
4
- podcraft-app:
5
- build: .
 
 
6
  ports:
7
- - "8000:8000"
8
- volumes:
9
- - ./app:/app/app
10
- - ./temp_audio:/app/temp_audio
11
  environment:
12
- - MONGODB_URL=mongodb+srv://NageshBM:Nash166^@podcraft.ozqmc.mongodb.net/?retryWrites=true&w=majority&appName=Podcraft
13
- - SECRET_KEY=your-secret-key-change-in-production
 
14
  - OPENAI_API_KEY=${OPENAI_API_KEY}
15
- restart: always
 
 
 
 
 
 
 
 
1
+ version: '3.8'
2
 
3
  services:
4
+ podcraft:
5
+ build:
6
+ context: .
7
+ dockerfile: Dockerfile
8
  ports:
9
+ - "7860:7860"
10
+ env_file:
11
+ - .env
 
12
  environment:
13
+ - MONGODB_URL=${MONGODB_URL}
14
+ - SECRET_KEY=${SECRET_KEY}
15
+ - ACCESS_TOKEN_EXPIRE_MINUTES=${ACCESS_TOKEN_EXPIRE_MINUTES}
16
  - OPENAI_API_KEY=${OPENAI_API_KEY}
17
+ - TAVILY_API_KEY=${TAVILY_API_KEY}
18
+ - TTS_OPENAI_API_KEY=${TTS_OPENAI_API_KEY}
19
+ - PORT=7860
20
+ - HOST=0.0.0.0
21
+ volumes:
22
+ - ./temp_audio:/app/temp_audio
23
+ - ./temp:/app/temp
24
+ restart: unless-stopped
push_to_huggingface.sh DELETED
@@ -1,60 +0,0 @@
1
- #!/bin/bash
2
- set -e
3
-
4
- echo "===> Preparing PodCraft for HuggingFace Spaces <===="
5
-
6
- # Check if repository is initialized
7
- if [ ! -d ".git" ]; then
8
- echo "Initializing git repository..."
9
- git init
10
- fi
11
-
12
- # Set up Git LFS
13
- echo "Setting up Git LFS..."
14
- git lfs install
15
- git lfs track "*.gif" "*.png" "*.jpg" "*.jpeg" "*.mp3" "*.mp4" "*.wav" "*.ogg"
16
- git add .gitattributes
17
-
18
- # Make sure we're using Dockerfile.spaces for HuggingFace
19
- echo "Ensuring space.yml is configured correctly..."
20
- if ! grep -q "dockerfile: Dockerfile.spaces" space.yml; then
21
- echo "Updating space.yml to use Dockerfile.spaces..."
22
- sed -i 's/sdk: docker/sdk: docker\ndockerfile: Dockerfile.spaces/' space.yml
23
- git add space.yml
24
- fi
25
-
26
- # Configure git if needed
27
- if ! git remote | grep -q "origin"; then
28
- echo "Please enter your HuggingFace username:"
29
- read username
30
- git remote add origin "https://huggingface.co/spaces/$username/podcraft"
31
- echo "Remote added: https://huggingface.co/spaces/$username/podcraft"
32
- fi
33
-
34
- # Check for large files
35
- echo "Checking for large files (>100MB)..."
36
- find . -type f -size +100M | while read file; do
37
- echo "Warning: Large file detected: $file"
38
- echo "Consider removing or excluding it from git."
39
- done
40
-
41
- # Remove the frontend/podcraft/build directory as it causes errors
42
- echo "Removing frontend/podcraft/build from git if it exists..."
43
- if [ -d "frontend/podcraft/build" ]; then
44
- git rm -r --cached frontend/podcraft/build || true
45
- fi
46
-
47
- # Prepare for commit
48
- echo "Adding files to git..."
49
- git add .
50
-
51
- # Commit changes
52
- echo "Committing changes..."
53
- git commit -m "Update PodCraft for HuggingFace Spaces"
54
-
55
- # Push to HuggingFace
56
- echo "Pushing to HuggingFace Spaces..."
57
- echo "This may take a while depending on the size of your repository."
58
- git push -u origin main
59
-
60
- echo "Push completed! Check your HuggingFace Space for build progress."
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
requirements.txt ADDED
@@ -0,0 +1,15 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ fastapi==0.104.1
2
+ uvicorn==0.24.0
3
+ motor==3.1.1
4
+ pymongo==4.3.3
5
+ certifi==2024.2.2
6
+ python-jose[cryptography]==3.3.0
7
+ passlib[bcrypt]==1.7.4
8
+ python-multipart==0.0.6
9
+ python-decouple==3.8
10
+ langgraph==0.2.14
11
+ langchain>=0.1.0
12
+ langchain-openai>=0.0.5
13
+ langchain-core>=0.2.35
14
+ langchain-community>=0.0.24
15
+ pydub==0.25.1
runtime.txt ADDED
@@ -0,0 +1 @@
 
 
1
+ python-3.11
space-metadata.json ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "title": "PodCraft - AI Podcast Generator",
3
+ "emoji": "🎙️",
4
+ "colorFrom": "indigo",
5
+ "colorTo": "purple",
6
+ "sdk": "docker",
7
+ "app_port": 7860,
8
+ "pinned": true
9
+ }
space.yml DELETED
@@ -1,9 +0,0 @@
1
- title: PodCraft
2
- emoji: 🎙️
3
- colorFrom: indigo
4
- colorTo: purple
5
- sdk: docker
6
- app_port: 7860
7
- dockerfile: Dockerfile.spaces
8
- pinned: false
9
- license: mit