initial commit

This commit is contained in:
Administrator 2023-03-08 00:17:34 +01:00
commit 69416eb896
12 changed files with 321 additions and 0 deletions

133
.gitignore vendored Normal file
View File

@ -0,0 +1,133 @@
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
*$py.class
# C extensions
*.so
# Distribution / packaging
.Python
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
pip-wheel-metadata/
share/python-wheels/
*.egg-info/
.installed.cfg
*.egg
MANIFEST
# PyInstaller
# Usually these files are written by a python script from a template
# before PyInstaller builds the exe, so as to inject date/other infos into it.
*.manifest
*.spec
# Installer logs
pip-log.txt
pip-delete-this-directory.txt
# Unit test / coverage reports
htmlcov/
.tox/
.nox/
.coverage
.coverage.*
.cache
nosetests.xml
coverage.xml
*.cover
*.py,cover
.hypothesis/
.pytest_cache/
# Translations
*.mo
*.pot
# Django stuff:
*.log
local_settings.py
db.sqlite3
db.sqlite3-journal
# Flask stuff:
instance/
.webassets-cache
# Scrapy stuff:
.scrapy
# Sphinx documentation
docs/_build/
# PyBuilder
target/
# Jupyter Notebook
.ipynb_checkpoints
# IPython
profile_default/
ipython_config.py
# pyenv
.python-version
# pipenv
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
# However, in case of collaboration, if having platform-specific dependencies or dependencies
# having no cross-platform support, pipenv may install dependencies that don't work, or not
# install all needed dependencies.
#Pipfile.lock
# PEP 582; used by e.g. github.com/David-OConnor/pyflow
__pypackages__/
# Celery stuff
celerybeat-schedule
celerybeat.pid
# SageMath parsed files
*.sage.py
# Environments
.env
.env.*
.venv
env/
venv/
ENV/
env.bak/
venv.bak/
# Spyder project settings
.spyderproject
.spyproject
# Rope project settings
.ropeproject
# mkdocs documentation
/site
# mypy
.mypy_cache/
.dmypy.json
dmypy.json
# Pyre type checker
.pyre/
.idea/
.vercel

0
__init__.py Normal file
View File

18
app.py Normal file
View File

@ -0,0 +1,18 @@
from fastapi import FastAPI
from config.config import initiate_database
from routes.request import router as RequestRouter
from routes.admin import router as AdminRouter
from config import Settings
app = FastAPI()
@app.on_event("startup")
async def start_database():
await initiate_database()
app.include_router(RequestRouter, tags=["Requests"])
if Settings().ENV == "dev":
app.include_router(AdminRouter, tags=["Admin"])

1
azure/__init__.py Normal file
View File

@ -0,0 +1 @@
from .functions import translate

27
azure/functions.py Normal file
View File

@ -0,0 +1,27 @@
import requests
import uuid
from config import Settings
def translate(data):
constructed_url = Settings().AZURE_ENDPOINT + '/translate'
params = {
'api-version': '3.0',
'from': data.language_from,
'to': [data.language_to]
}
headers = {
'Ocp-Apim-Subscription-Key': Settings().AZURE_KEY,
'Ocp-Apim-Subscription-Region': Settings().AZURE_LOCATION,
'Content-type': 'application/json',
'X-ClientTraceId': str(uuid.uuid4())
}
body = [{
'text': data.requested_text
}]
request = requests.post(constructed_url, params=params, headers=headers, json=body)
return request.json()

1
config/__init__.py Normal file
View File

@ -0,0 +1 @@
from .config import Settings

23
config/config.py Normal file
View File

@ -0,0 +1,23 @@
from beanie import init_beanie
from motor.motor_asyncio import AsyncIOMotorClient
from pydantic import BaseSettings
from typing import Literal
from models.request import Request
class Settings(BaseSettings):
DATABASE_URL: str
AZURE_KEY: str
AZURE_ENDPOINT: str
AZURE_LOCATION: str
ENV: Literal["dev", "prod"]
class Config:
env_file = ".env"
orm_mode = True
async def initiate_database():
client = AsyncIOMotorClient(Settings().DATABASE_URL)
await init_beanie(database=client.get_default_database(), document_models=[Request])

18
database/database.py Normal file
View File

@ -0,0 +1,18 @@
from typing import List
from models.request import Request
request_collection = Request
async def add_request(item: Request) -> Request:
return await item.create()
async def retrieve_requests() -> List[Request]:
return await request_collection.all().to_list()
async def retrieve_request(text: str, language_from: str, language_to: str) -> List[Request]:
return await request_collection.find({"requested_text": text, "language_from": language_from, "language_to": language_to}).to_list()
async def clear_requests() -> None:
return await request_collection.delete_all()

40
models/request.py Normal file
View File

@ -0,0 +1,40 @@
from beanie import Document
from pydantic import BaseModel
class Request(Document):
id: str
requested_text: str
response_text: str
language_from: str
language_to: str
unixdate: int
class Settings:
name = "request"
class Config:
schema_extra = {
"example": {
"id": "9e90b529-05d0-4b0e-a8f8-de17e72e553c",
"requested_text": "I would really like to drive your car around the block a few times!",
"response_text": "Ich würde wirklich gerne mit Ihrem Auto ein paar Mal um den Block fahren!",
"language_from": "en",
"language_to": "de",
"date": 1678225669
}
}
class RequestData(BaseModel):
requested_text: str
language_from: str
language_to: str
class Config:
schema_extra = {
"example": {
"requested_text": "I would really like to drive your car around the block a few times!",
"language_from": "en",
"language_to": "de",
}
}

9
requirements.txt Normal file
View File

@ -0,0 +1,9 @@
requests==2.28.2
uuid==1.30
motor==3.1.1
uvicorn==0.20.0
pymongo==4.3.3
fastapi==0.93.0
pydantic==1.10.5
passlib==1.7.4
beanie==1.17.0

14
routes/admin.py Normal file
View File

@ -0,0 +1,14 @@
from fastapi import APIRouter
from database.database import *
from models.request import *
router = APIRouter()
@router.post("/cleardb", response_description="Clears database cache")
async def cleardb():
await clear_requests()
@router.get("/dbcache", response_description="Show database contents", response_model=List[Request])
async def showcache():
return await retrieve_requests()

37
routes/request.py Normal file
View File

@ -0,0 +1,37 @@
from fastapi import APIRouter
import uuid
import time
from azure import translate as azure_translate
from database.database import *
from models.request import *
router = APIRouter()
@router.post("/translate", response_description="Translate text", response_model=Request)
async def translate(data: RequestData):
# Check if this request is saved in the database
check_db = await retrieve_request(data.requested_text, data.language_from, data.language_to)
if len(check_db) == 0: # Not in database, use azure api
print("Not in database, use Azure api")
# Make api request
response = azure_translate(data)
print(response)
# Create object
item = Request(
id=str(uuid.uuid4()),
requested_text=data.requested_text,
response_text=response[0]['translations'][0]['text'],
language_from=data.language_from,
language_to=data.language_to,
unixdate=int(time.time())
)
# Save it to the database and return it
return await add_request(item=item)
else:
print("Already in database, serving the cached result")
return check_db[0]