MongoDBNFT / app.py
ManTea's picture
Redis + Websocket
d27bdcb
raw
history blame
5.32 kB
from fastapi import FastAPI, HTTPException, Form, Request
from fastapi.middleware.cors import CORSMiddleware
from fastapi.responses import JSONResponse
from fastapi_socketio import SocketManager
from typing import Optional
import pymongo
from bson.objectid import ObjectId
import redis
import json
from redis.exceptions import RedisError
from pydantic import BaseModel
# Initialize FastAPI app
app = FastAPI()
socket_manager = SocketManager(app=app)
# Add CORS middleware
app.add_middleware(
CORSMiddleware,
allow_origins=["*"],
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
# Initialize Redis client
redis_client = redis.Redis(host='localhost', port=6379, db=0)
CACHE_EXPIRE_TIME = 300 # 5 minutes
# MongoDB connection
mongo_url = "mongodb+srv://ip6ofme:[email protected]/"
client = pymongo.MongoClient(mongo_url)
db = client["test"]
pdf_collection = db["PdfDetails"]
voter_collection = db["Voters"]
# Pydantic models for request validation
class VoterRegistration(BaseModel):
name: str
group: str
role: str
class VoteRequest(BaseModel):
voter_id: str
file_id: str
vote_count: Optional[int] = 1
@app.post("/upload-files")
async def upload_file(
title: str = Form(...),
group: str = Form(...),
url: str = Form(...)
):
new_pdf = {
'title': title,
'group': group,
'url': url,
'votes': 0
}
result = pdf_collection.insert_one(new_pdf)
return {'status': 'ok', 'id': str(result.inserted_id)}
@app.get("/get-votes")
async def get_votes(file_id: str):
try:
file = pdf_collection.find_one({'_id': ObjectId(file_id)})
if not file:
raise HTTPException(status_code=404, detail="File not found")
return {'status': 'ok', 'votes': file.get('votes', 0)}
except Exception as e:
raise HTTPException(status_code=500, detail=str(e))
@app.get("/get-files")
async def get_files():
try:
files = pdf_collection.find({})
file_list = [
{
'id': str(file['_id']),
'title': file['title'],
'group': file['group'],
'url': file['url'],
'votes': file.get('votes', 0)
}
for file in files
]
return {'status': 'ok', 'data': file_list}
except Exception as e:
raise HTTPException(status_code=500, detail=str(e))
@app.post("/register-voter")
async def register_voter(voter: VoterRegistration):
new_voter = {
'name': voter.name,
'group': voter.group,
'role': voter.role,
'number_of_votes': 0
}
result = voter_collection.insert_one(new_voter)
return {'status': 'ok', 'id': str(result.inserted_id)}
@app.post("/vote-by-voter")
async def vote_by_voter(vote_request: VoteRequest):
if vote_request.vote_count <= 0:
raise HTTPException(status_code=400, detail="Vote count must be greater than 0")
voter = voter_collection.find_one({'_id': ObjectId(vote_request.voter_id)})
if not voter:
raise HTTPException(status_code=404, detail="Voter not found")
max_votes = 10 if voter['role'] == 'judge' else 2
if voter['number_of_votes'] + vote_request.vote_count > max_votes:
raise HTTPException(status_code=400, detail="Maximum votes exceeded")
try:
# Update MongoDB
voter_collection.update_one(
{'_id': ObjectId(vote_request.voter_id)},
{'$inc': {'number_of_votes': vote_request.vote_count}}
)
pdf_collection.update_one(
{'_id': ObjectId(vote_request.file_id)},
{'$inc': {'votes': vote_request.vote_count}}
)
# Clear cache
redis_client.delete('all_files')
redis_client.delete(f'voter:{vote_request.voter_id}')
# Emit socket event
updated_file = pdf_collection.find_one({'_id': ObjectId(vote_request.file_id)})
await socket_manager.emit('vote_update', {
'file_id': vote_request.file_id,
'votes': updated_file.get('votes', 0)
})
return {'status': 'ok', 'message': f'Vote recorded successfully with {vote_request.vote_count} votes'}
except Exception as e:
raise HTTPException(status_code=500, detail=str(e))
@app.get("/get-voter")
async def get_voter(voter_id: str):
# Check cache
cached_voter = redis_client.get(f'voter:{voter_id}')
if cached_voter:
return json.loads(cached_voter)
voter = voter_collection.find_one({'_id': ObjectId(voter_id)})
if not voter:
raise HTTPException(status_code=404, detail="Voter not found")
voter_data = {
'status': 'ok',
'name': voter['name'],
'group': voter['group'],
'role': voter['role'],
'number_of_votes': voter['number_of_votes']
}
# Save to cache
redis_client.setex(f'voter:{voter_id}', CACHE_EXPIRE_TIME, json.dumps(voter_data))
return voter_data
@socket_manager.on('connect')
async def handle_connect():
print('Client connected')
@socket_manager.on('disconnect')
async def handle_disconnect():
print('Client disconnected')
if __name__ == "__main__":
import uvicorn
uvicorn.run(app, host="0.0.0.0", port=5000)