Ved Gupta commited on
Commit
8713eac
·
1 Parent(s): 9d9b02c
README.md CHANGED
@@ -80,4 +80,13 @@ uvicorn app.main:app --reload
80
 
81
  ```bash
82
  python -m unittest
 
 
 
 
 
 
 
 
 
83
  ```
 
80
 
81
  ```bash
82
  python -m unittest
83
+ ```
84
+
85
+ # Upload File
86
+ ```bash
87
+ curl -X 'POST' \
88
+ 'http://localhost:8000/api/v1/transcribe/' \
89
+ -H 'accept: application/json' \
90
+ -H 'Content-Type: multipart/form-data' \
91
+ -F 'audio_file=@ElevenLabs_2023-08-10T13 53 05.000Z_VedVoice_bFrkzQsyKvReo52Q6712.mp3;type=audio/mpeg'
92
  ```
app/api/__init__.py CHANGED
@@ -1,9 +1,10 @@
1
  # File: whisper.api/app/api/__init__.py
2
 
3
  from fastapi import APIRouter
4
- from .endpoints import items, users
5
 
6
  api_router = APIRouter()
7
 
8
  api_router.include_router(items.router, prefix="/items", tags=["items"])
9
  api_router.include_router(users.router, prefix="/users", tags=["users"])
 
 
1
  # File: whisper.api/app/api/__init__.py
2
 
3
  from fastapi import APIRouter
4
+ from .endpoints import items, users, transcribe
5
 
6
  api_router = APIRouter()
7
 
8
  api_router.include_router(items.router, prefix="/items", tags=["items"])
9
  api_router.include_router(users.router, prefix="/users", tags=["users"])
10
+ api_router.include_router(transcribe.router, prefix="/transcribe", tags=["transcribe"])
app/api/endpoints/__init__.py CHANGED
@@ -2,9 +2,10 @@
2
 
3
  from fastapi import APIRouter
4
 
5
- from . import items, users
6
 
7
  router = APIRouter()
8
 
9
  router.include_router(items.router, prefix="/items", tags=["items"])
10
  router.include_router(users.router, prefix="/users", tags=["users"])
 
 
2
 
3
  from fastapi import APIRouter
4
 
5
+ from . import items, users, transcribe
6
 
7
  router = APIRouter()
8
 
9
  router.include_router(items.router, prefix="/items", tags=["items"])
10
  router.include_router(users.router, prefix="/users", tags=["users"])
11
+ router.include_router(transcribe.router, prefix="/transcribe", tags=["transcribe"])
app/api/endpoints/transcribe.py ADDED
@@ -0,0 +1,22 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from fastapi import APIRouter, File, UploadFile, Request, Header
2
+ from pydantic import BaseModel
3
+
4
+ router = APIRouter()
5
+
6
+
7
+ class AudioFile(BaseModel):
8
+ filename: str
9
+ content_type: str
10
+
11
+
12
+ @router.post("/")
13
+ async def post_audio(
14
+ request: Request, file: UploadFile = File(...), Authorization: str = Header(...)
15
+ ):
16
+ """Receive audio file and save it to disk."""
17
+ print(f"Authorization header: {Authorization}")
18
+
19
+ with open(file.filename, "wb") as f:
20
+ f.write(file.file.read())
21
+
22
+ return AudioFile(filename=file.filename, content_type=file.content_type)
app/api/endpoints/users.py CHANGED
@@ -10,7 +10,7 @@ database = SessionLocal()
10
  users_router = router = APIRouter()
11
 
12
 
13
- @router.post("/", response_model=UserResponse, status_code=201)
14
  async def create_user(user: User):
15
  db_user = UserInDB(
16
  username=user.username,
@@ -20,7 +20,8 @@ async def create_user(user: User):
20
  database.add(db_user)
21
  database.commit()
22
  database.refresh(db_user)
23
- return {**user.dict(), "id": db_user.id, "hashed_password": None}
 
24
 
25
 
26
  @router.get("/{user_id}/", response_model=UserResponse)
@@ -50,7 +51,7 @@ async def update_user(user_id: UUID, user: UpdateUser):
50
  return {**user.dict(), "id": db_user.id, "hashed_password": None}
51
 
52
 
53
- @router.delete("/{user_id}/", response_model=int)
54
  async def delete_user(user_id: UUID):
55
  db_user = database.query(UserInDB).filter(UserInDB.id == user_id).first()
56
  database.delete(db_user)
 
10
  users_router = router = APIRouter()
11
 
12
 
13
+ @router.post("/", status_code=201)
14
  async def create_user(user: User):
15
  db_user = UserInDB(
16
  username=user.username,
 
20
  database.add(db_user)
21
  database.commit()
22
  database.refresh(db_user)
23
+ print(db_user)
24
+ return {**db_user.data()}
25
 
26
 
27
  @router.get("/{user_id}/", response_model=UserResponse)
 
51
  return {**user.dict(), "id": db_user.id, "hashed_password": None}
52
 
53
 
54
+ @router.delete("/{user_id}/")
55
  async def delete_user(user_id: UUID):
56
  db_user = database.query(UserInDB).filter(UserInDB.id == user_id).first()
57
  database.delete(db_user)
app/core/config.py CHANGED
@@ -24,7 +24,11 @@ class Settings(BaseSettings):
24
  POSTGRES_DATABASE_URL: str = env.get("POSTGRES_DATABASE_URL")
25
  TEST_DATABASE_URL: str = env.get("POSTGRES_DATABASE_URL")
26
 
27
- BACKEND_CORS_ORIGINS: List[AnyHttpUrl] = ["http://localhost:3000"]
 
 
 
 
28
 
29
  @validator("SECRET_KEY", pre=True)
30
  def secret_key_must_be_set(cls, v: Optional[str], values: Dict[str, Any]) -> str:
 
24
  POSTGRES_DATABASE_URL: str = env.get("POSTGRES_DATABASE_URL")
25
  TEST_DATABASE_URL: str = env.get("POSTGRES_DATABASE_URL")
26
 
27
+ BACKEND_CORS_ORIGINS: List[AnyHttpUrl] = [
28
+ "http://localhost:3000",
29
+ "http://localhost:8080",
30
+ "http://localhost:8000",
31
+ ]
32
 
33
  @validator("SECRET_KEY", pre=True)
34
  def secret_key_must_be_set(cls, v: Optional[str], values: Dict[str, Any]) -> str:
app/core/errors.py CHANGED
@@ -1,39 +1,21 @@
1
- from fastapi import Request
2
  from fastapi.responses import JSONResponse
3
  from fastapi.exceptions import HTTPException, RequestValidationError
4
 
5
 
6
- async def http_exception_handler(request: Request, exc: HTTPException):
7
  """
8
- Exception handler for HTTP errors
9
- """
10
- return JSONResponse(
11
- status_code=exc.status_code,
12
- content={"message": exc.detail},
13
- )
14
 
 
 
 
15
 
16
- async def http_error_handler(request: Request, exc: Exception):
 
17
  """
18
- Exception handler for HTTP errors
19
- """
20
- if isinstance(exc, HTTPException):
21
- detail = exc.detail
22
- status_code = exc.status_code
23
- else:
24
- detail = "Internal server error"
25
- status_code = 500
26
- return JSONResponse(
27
- status_code=status_code,
28
- content={"message": detail},
29
- )
30
-
31
 
32
- def http422_error_handler(request: Request, exc: RequestValidationError):
33
- """
34
- Exception handler for HTTP 422 errors
35
- """
36
  return JSONResponse(
37
- status_code=422,
38
- content={"message": "Validation error", "details": exc.errors()},
39
  )
 
1
+ from fastapi import Request, Response
2
  from fastapi.responses import JSONResponse
3
  from fastapi.exceptions import HTTPException, RequestValidationError
4
 
5
 
6
+ async def error_handler(request: Request, exc: Exception) -> JSONResponse:
7
  """
8
+ Error handler function for FastAPI.
 
 
 
 
 
9
 
10
+ Args:
11
+ request: The HTTP request that caused the error.
12
+ exc: The exception that was raised.
13
 
14
+ Returns:
15
+ The error response.
16
  """
 
 
 
 
 
 
 
 
 
 
 
 
 
17
 
 
 
 
 
18
  return JSONResponse(
19
+ status_code=500,
20
+ content={"detail": "Error Occurs"},
21
  )
app/core/models/AuthToken.py CHANGED
@@ -9,7 +9,7 @@ from sqlalchemy.dialects.postgresql import UUID
9
  from sqlalchemy import Column, String, Boolean, ForeignKey, DateTime
10
  from sqlalchemy.sql import func
11
 
12
- from app.core.database import Base, engine
13
 
14
 
15
  class AuthToken(Base):
@@ -29,10 +29,14 @@ class AuthToken(Base):
29
  return token
30
 
31
  def generate_bearer_token(self):
32
- token_prefix = str(self.id).replace("-", "") # Remove hyphens from UUID
33
- token_suffix = str(uuid.uuid4().hex) # Generate a random UUID string
 
 
 
 
34
  return f"{token_prefix}{token_suffix}"
35
 
36
  @staticmethod
37
- def validate_bearer_token(request_token):
38
  ...
 
9
  from sqlalchemy import Column, String, Boolean, ForeignKey, DateTime
10
  from sqlalchemy.sql import func
11
 
12
+ from app.core.database import Base
13
 
14
 
15
  class AuthToken(Base):
 
29
  return token
30
 
31
  def generate_bearer_token(self):
32
+ token_prefix = str(uuid.uuid4()).replace("-", "")
33
+ token_suffix = "".join(
34
+ random.choices(
35
+ string.ascii_uppercase + string.ascii_lowercase + string.digits, k=32
36
+ )
37
+ )
38
  return f"{token_prefix}{token_suffix}"
39
 
40
  @staticmethod
41
+ def validate_bearer_token(request_token: str):
42
  ...
app/core/models/Transcribe.py CHANGED
@@ -1,6 +1,5 @@
1
  from datetime import datetime, timedelta
2
 
3
-
4
  import uuid
5
  from app.core.config import settings
6
 
@@ -19,3 +18,4 @@ class TranscibeInDB(Base):
19
  text = Column(String)
20
  user_id = Column(UUID(as_uuid=True), ForeignKey("users.id"))
21
  user = relationship("UserInDB", back_populates="transcribes")
 
 
1
  from datetime import datetime, timedelta
2
 
 
3
  import uuid
4
  from app.core.config import settings
5
 
 
18
  text = Column(String)
19
  user_id = Column(UUID(as_uuid=True), ForeignKey("users.id"))
20
  user = relationship("UserInDB", back_populates="transcribes")
21
+ created_at = Column(DateTime(timezone=True), server_default=func.now())
app/core/models/User.py CHANGED
@@ -4,10 +4,11 @@ import uuid
4
  from app.core.config import settings
5
 
6
  from sqlalchemy.dialects.postgresql import UUID
7
- from sqlalchemy import Column, String, Boolean
8
  from sqlalchemy.orm import relationship
 
9
 
10
- from app.core.database import Base, engine
11
 
12
 
13
  class UserInDB(Base):
@@ -19,8 +20,17 @@ class UserInDB(Base):
19
  hashed_password = Column(String)
20
  is_active = Column(Boolean, default=True)
21
  transcribes = relationship("TranscibeInDB", back_populates="user")
 
22
 
23
  def __init__(self, username: str, email: str, hashed_password: str):
24
  self.username = username
25
  self.email = email
26
  self.hashed_password = hashed_password
 
 
 
 
 
 
 
 
 
4
  from app.core.config import settings
5
 
6
  from sqlalchemy.dialects.postgresql import UUID
7
+ from sqlalchemy import Column, String, Boolean, DateTime
8
  from sqlalchemy.orm import relationship
9
+ from sqlalchemy.sql import func
10
 
11
+ from app.core.database import Base
12
 
13
 
14
  class UserInDB(Base):
 
20
  hashed_password = Column(String)
21
  is_active = Column(Boolean, default=True)
22
  transcribes = relationship("TranscibeInDB", back_populates="user")
23
+ created_at = Column(DateTime(timezone=True), server_default=func.now())
24
 
25
  def __init__(self, username: str, email: str, hashed_password: str):
26
  self.username = username
27
  self.email = email
28
  self.hashed_password = hashed_password
29
+
30
+ def data(self):
31
+ return {
32
+ "id": self.id,
33
+ "username": self.username,
34
+ "email": self.email,
35
+ "created_at": self.created_at,
36
+ }
app/main.py CHANGED
@@ -1,8 +1,7 @@
1
  from fastapi import FastAPI
2
  from app.api import api_router
3
  from app.core.config import settings
4
- from app.core.errors import http_error_handler
5
- from app.core.errors import http422_error_handler
6
  from fastapi.middleware.cors import CORSMiddleware
7
 
8
  from app.utils import print_routes
@@ -25,8 +24,8 @@ if settings.BACKEND_CORS_ORIGINS:
25
  app.include_router(api_router, prefix=settings.API_V1_STR)
26
 
27
  # # Error handlers
28
- app.add_exception_handler(422, http422_error_handler)
29
- app.add_exception_handler(500, http_error_handler)
30
 
31
  # Print all routes
32
  print_routes(app)
 
1
  from fastapi import FastAPI
2
  from app.api import api_router
3
  from app.core.config import settings
4
+ from app.core.errors import error_handler
 
5
  from fastapi.middleware.cors import CORSMiddleware
6
 
7
  from app.utils import print_routes
 
24
  app.include_router(api_router, prefix=settings.API_V1_STR)
25
 
26
  # # Error handlers
27
+ app.add_exception_handler(422, error_handler)
28
+ app.add_exception_handler(500, error_handler)
29
 
30
  # Print all routes
31
  print_routes(app)
requirements.txt CHANGED
@@ -9,4 +9,5 @@ faker
9
  requests-mock
10
  passlib
11
  httpx
12
- PyJWT
 
 
9
  requests-mock
10
  passlib
11
  httpx
12
+ PyJWT
13
+ python-multipart