Spaces:
Sleeping
Sleeping
File size: 7,454 Bytes
d27bdcb 19a6cbe 0ba59ec ac27b27 d27bdcb ac27b27 d27bdcb 8e6465c d27bdcb 19a6cbe f8a47c9 19a6cbe ac27b27 d27bdcb ac27b27 d27bdcb 19a6cbe 0ba59ec d27bdcb 0ba59ec 19a6cbe d27bdcb f8a47c9 d27bdcb 19a6cbe 0ba59ec 19a6cbe d27bdcb 19a6cbe d27bdcb 19a6cbe d27bdcb 19a6cbe d27bdcb 0ba59ec d27bdcb 19a6cbe d27bdcb 5c82ae4 19a6cbe d27bdcb 5c82ae4 19a6cbe d27bdcb 19a6cbe d27bdcb 0ba59ec d27bdcb 19a6cbe d27bdcb 0ba59ec 8e6465c 5c82ae4 0ba59ec 8e6465c d27bdcb 8e6465c d27bdcb 0ba59ec 8e6465c 0ba59ec d27bdcb 0ba59ec d27bdcb 0ba59ec d27bdcb 0ba59ec d27bdcb 5ef0fc4 ac27b27 8e6465c ac27b27 5ef0fc4 ac27b27 8e6465c ac27b27 8e6465c ac27b27 5ef0fc4 ac27b27 0ba59ec d27bdcb ac27b27 0ba59ec d27bdcb ac27b27 8e6465c 0ba59ec 5d97d55 d27bdcb |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 |
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, validator
from pymongo.errors import ConnectionFailure
# Initialize FastAPI app
app = FastAPI()
socket_manager = SocketManager(app=app, cors_allowed_origins="*", mount_location="/socket.io")
# Add CORS middleware
app.add_middleware(
CORSMiddleware,
allow_origins=["*"],
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
# Sửa phần khởi tạo Redis client và thêm biến để kiểm tra Redis status
redis_available = False
try:
redis_client = redis.Redis(host='localhost', port=6379, db=0)
redis_client.ping() # Kiểm tra kết nối
redis_available = True
except redis.ConnectionError:
print("Redis không khả dụng - hệ thống sẽ chạy không có cache")
redis_client = None
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"]
# Kiểm tra kết nối MongoDB khi khởi động
try:
# The ismaster command is cheap and does not require auth.
client.admin.command('ismaster')
except ConnectionFailure:
print("Server not available")
raise
# 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
class Config:
@validator('vote_count')
def validate_vote_count(cls, v):
if v <= 0:
raise ValueError('Vote count must be greater than 0')
return v
@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):
# Xác định số lượng vote tối đa dựa vào role
max_votes = 10 if voter.role == 'judge' else 2
new_voter = {
'name': voter.name,
'group': voter.group,
'role': voter.role,
'number_of_votes': max_votes # Khởi tạo với số vote tối đa
}
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")
remaining_votes = voter['number_of_votes']
if vote_request.vote_count > remaining_votes:
raise HTTPException(status_code=400, detail=f"Not enough votes remaining. You have {remaining_votes} votes left")
try:
# Cập nhật 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}}
)
# Chỉ xóa cache nếu Redis khả dụng
if redis_available:
try:
redis_client.delete('all_files')
redis_client.delete(f'voter:{vote_request.voter_id}')
except redis.RedisError:
print("Không thể xóa cache Redis")
# 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(id: str):
try:
# Chỉ check cache nếu Redis khả dụng
if redis_available:
try:
cached_voter = redis_client.get(f'voter:{id}')
if cached_voter:
return json.loads(cached_voter)
except redis.RedisError:
print("Không thể đọc cache Redis")
voter = voter_collection.find_one({'_id': ObjectId(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']
}
# Chỉ lưu cache nếu Redis khả dụng
if redis_available:
try:
redis_client.setex(f'voter:{id}', CACHE_EXPIRE_TIME, json.dumps(voter_data))
except redis.RedisError:
print("Không thể lưu cache Redis")
return voter_data
except Exception as e:
print(f"Error in get_voter: {str(e)}")
raise HTTPException(status_code=500, detail=str(e))
@socket_manager.on('connect')
async def handle_connect(sid, environ):
print(f'Client connected: {sid}')
@socket_manager.on('disconnect')
async def handle_disconnect(sid):
print(f'Client disconnected: {sid}')
@app.get("/")
async def index():
return {'status': 'ok', 'message': 'Server is running'}
@app.on_event("shutdown")
async def shutdown_event():
# Close MongoDB connection
client.close()
# Close Redis connection if available
if redis_available and redis_client:
redis_client.close()
if __name__ == "__main__":
import uvicorn
uvicorn.run(app, host="0.0.0.0", port=5000) |