ManTea commited on
Commit
0ba59ec
·
1 Parent(s): ecf06e7

Redis + Websocket

Browse files
Files changed (2) hide show
  1. app.py +137 -101
  2. requirements.txt +5 -1
app.py CHANGED
@@ -1,20 +1,20 @@
1
- from fastapi import FastAPI, HTTPException, Request, Form, Depends
2
- from fastapi.responses import JSONResponse
3
- from fastapi.middleware.cors import CORSMiddleware
4
- from pydantic import BaseModel
5
- from bson import ObjectId
6
  import pymongo
 
 
 
 
7
 
8
- app = FastAPI()
 
 
 
9
 
10
- # Enable CORS
11
- app.add_middleware(
12
- CORSMiddleware,
13
- allow_origins=["*"],
14
- allow_credentials=True,
15
- allow_methods=["*"],
16
- allow_headers=["*"],
17
- )
18
 
19
  # MongoDB connection
20
  mongo_url = "mongodb+srv://ip6ofme:[email protected]/"
@@ -23,111 +23,147 @@ db = client["test"]
23
  pdf_collection = db["PdfDetails"]
24
  voter_collection = db["Voters"]
25
 
26
- # Models
27
- class VoteRequest(BaseModel):
28
- id: str
29
-
30
- class VoterVoteRequest(BaseModel):
31
- voter_id: str
32
- file_id: str
33
-
34
- class RegisterVoterRequest(BaseModel):
35
- name: str
36
- group: str
37
- role: str
38
-
39
- # API to upload file information to MongoDB
40
- @app.post("/upload-files")
41
- async def upload_file(title: str = Form(...), group: str = Form(...), url: str = Form(...)):
42
  new_pdf = {
43
- "title": title,
44
- "group": group,
45
- "url": url,
46
- "votes": 0,
47
  }
48
  result = pdf_collection.insert_one(new_pdf)
49
- return {"status": "ok", "id": str(result.inserted_id)}
50
 
51
- # API to increment file vote count by ID
52
- @app.post("/vote")
53
- async def vote(request: VoteRequest):
54
- file_id = request.id
55
- try:
56
- file = pdf_collection.find_one({"_id": ObjectId(file_id)})
57
- if not file:
58
- raise HTTPException(status_code=404, detail="File not found")
59
- pdf_collection.update_one({"_id": ObjectId(file_id)}, {"$inc": {"votes": 1}})
60
- return {"status": "ok"}
61
- except Exception as e:
62
- raise HTTPException(status_code=500, detail=str(e))
63
 
64
- # API to get vote count by file ID
65
- @app.get("/get-votes")
66
- async def get_votes(id: str):
67
  try:
68
- file = pdf_collection.find_one({"_id": ObjectId(id)})
69
  if not file:
70
- raise HTTPException(status_code=404, detail="File not found")
71
- return {"status": "ok", "votes": file.get("votes", 0)}
 
72
  except Exception as e:
73
- raise HTTPException(status_code=500, detail=str(e))
74
 
75
- # API to retrieve list of all files
76
- @app.get("/get-files")
77
- async def get_files():
78
  try:
79
  files = pdf_collection.find({})
80
- file_list = [
81
- {
82
- "id": str(file["_id"]),
83
- "title": file["title"],
84
- "group": file["group"],
85
- "url": file["url"],
86
- "votes": file.get("votes", 0),
87
- }
88
- for file in files
89
- ]
90
- return {"status": "ok", "data": file_list}
91
  except Exception as e:
92
- raise HTTPException(status_code=500, detail=str(e))
 
93
 
94
- # API to register a voter
95
- @app.post("/register-voter")
96
- async def register_voter(request: RegisterVoterRequest):
 
 
 
 
 
97
  new_voter = {
98
- "name": request.name,
99
- "group": request.group,
100
- "role": request.role,
101
- "number_of_votes": 0,
102
  }
103
  result = voter_collection.insert_one(new_voter)
104
- return {"status": "ok", "id": str(result.inserted_id)}
 
 
 
 
 
 
 
 
105
 
106
- # API for voting by voter
107
- @app.post("/vote-by-voter")
108
- async def vote_by_voter(request: VoterVoteRequest):
109
- voter = voter_collection.find_one({"_id": ObjectId(request.voter_id)})
110
  if not voter:
111
- raise HTTPException(status_code=404, detail="Voter not found")
112
-
113
- max_votes = 5 if voter["role"] == "judge" else 2
114
- if voter["number_of_votes"] >= max_votes:
115
- raise HTTPException(status_code=400, detail="Maximum votes reached")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
116
 
117
- voter_collection.update_one({"_id": ObjectId(request.voter_id)}, {"$inc": {"number_of_votes": 1}})
118
- pdf_collection.update_one({"_id": ObjectId(request.file_id)}, {"$inc": {"votes": 1}})
119
- return {"status": "ok", "message": "Vote recorded successfully"}
120
-
121
- # API to get voter information
122
- @app.get("/get-voter")
123
- async def get_voter(id: str):
124
- voter = voter_collection.find_one({"_id": ObjectId(id)})
125
  if not voter:
126
- raise HTTPException(status_code=404, detail="Voter not found")
127
- return {
128
- "status": "ok",
129
- "name": voter["name"],
130
- "group": voter["group"],
131
- "role": voter["role"],
132
- "number_of_votes": voter["number_of_votes"],
 
133
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from flask import Flask, request, jsonify
2
+ from flask_cors import CORS
3
+ from flask_socketio import SocketIO, emit
 
 
4
  import pymongo
5
+ from bson.objectid import ObjectId
6
+ import redis
7
+ import json
8
+ from redis.exceptions import RedisError
9
 
10
+ # Khởi tạo Flask app SocketIO
11
+ app = Flask(__name__)
12
+ CORS(app)
13
+ socketio = SocketIO(app, cors_allowed_origins="*")
14
 
15
+ # Khởi tạo Redis client
16
+ redis_client = redis.Redis(host='localhost', port=6379, db=0)
17
+ CACHE_EXPIRE_TIME = 300 # 5 phút
 
 
 
 
 
18
 
19
  # MongoDB connection
20
  mongo_url = "mongodb+srv://ip6ofme:[email protected]/"
 
23
  pdf_collection = db["PdfDetails"]
24
  voter_collection = db["Voters"]
25
 
26
+ # API để upload file và lưu thông tin vào MongoDB
27
+ @app.route('/upload-files', methods=['POST'])
28
+ def upload_file():
29
+ # Chỉ lưu thông tin vào MongoDB
30
+ title = request.form.get('title')
31
+ group = request.form.get('group')
32
+ firebase_url = request.form.get('url')
 
 
 
 
 
 
 
 
 
33
  new_pdf = {
34
+ 'title': title,
35
+ 'group': group,
36
+ 'url': firebase_url,
37
+ 'votes': 0
38
  }
39
  result = pdf_collection.insert_one(new_pdf)
40
+ return jsonify({'status': 'ok', 'id': str(result.inserted_id)})
41
 
42
+ # API để lấy số lượng votes của file theo ID
43
+ @app.route('/get-votes', methods=['GET'])
44
+ def get_votes():
45
+ file_id = request.args.get('id')
 
 
 
 
 
 
 
 
46
 
 
 
 
47
  try:
48
+ file = pdf_collection.find_one({'_id': ObjectId(file_id)})
49
  if not file:
50
+ return jsonify({'status': 'error', 'message': 'File not found'}), 404
51
+
52
+ return jsonify({'status': 'ok', 'votes': file.get('votes', 0)})
53
  except Exception as e:
54
+ return jsonify({'status': 'error', 'message': str(e)}), 500
55
 
56
+ # API để lấy danh sách tất cả các file
57
+ @app.route('/get-files', methods=['GET'])
58
+ def get_files():
59
  try:
60
  files = pdf_collection.find({})
61
+ file_list = []
62
+ for file in files:
63
+ file_list.append({
64
+ 'id': str(file['_id']),
65
+ 'title': file['title'],
66
+ 'group': file['group'],
67
+ 'url': file['url'],
68
+ 'votes': file.get('votes', 0)
69
+ })
70
+ return jsonify({'status': 'ok', 'data': file_list})
 
71
  except Exception as e:
72
+ print(f"Error: {str(e)}")
73
+ return jsonify({'status': 'error', 'message': str(e)}), 500
74
 
75
+ # API để đăng người bình chọn
76
+ @app.route('/register-voter', methods=['POST'])
77
+ def register_voter():
78
+ data = request.json
79
+ name = data.get('name')
80
+ group = data.get('group')
81
+ role = data.get('role') # Thêm trường role
82
+
83
  new_voter = {
84
+ 'name': name,
85
+ 'group': group,
86
+ 'role': role, # Lưu role vào MongoDB
87
+ 'number_of_votes': 0
88
  }
89
  result = voter_collection.insert_one(new_voter)
90
+ return jsonify({'status': 'ok', 'id': str(result.inserted_id)})
91
+
92
+ # API để bình chọn
93
+ @app.route('/vote-by-voter', methods=['POST'])
94
+ def vote_by_voter():
95
+ data = request.json
96
+ voter_id = data.get('voter_id')
97
+ file_id = data.get('file_id')
98
+ vote_count = data.get('vote_count', 1)
99
 
100
+ if vote_count <= 0:
101
+ return jsonify({'status': 'error', 'message': 'Vote count must be greater than 0'}), 400
102
+
103
+ voter = voter_collection.find_one({'_id': ObjectId(voter_id)})
104
  if not voter:
105
+ return jsonify({'status': 'error', 'message': 'Voter not found'}), 404
106
+
107
+ max_votes = 10 if voter['role'] == 'judge' else 2
108
+
109
+ if voter['number_of_votes'] + vote_count > max_votes:
110
+ return jsonify({'status': 'error', 'message': 'Maximum votes exceeded'}), 400
111
+
112
+ try:
113
+ # Cập nhật MongoDB
114
+ voter_collection.update_one({'_id': ObjectId(voter_id)}, {'$inc': {'number_of_votes': vote_count}})
115
+ pdf_collection.update_one({'_id': ObjectId(file_id)}, {'$inc': {'votes': vote_count}})
116
+
117
+ # Xóa cache
118
+ redis_client.delete('all_files')
119
+ redis_client.delete(f'voter:{voter_id}')
120
+
121
+ # Emit socket event
122
+ updated_file = pdf_collection.find_one({'_id': ObjectId(file_id)})
123
+ socketio.emit('vote_update', {
124
+ 'file_id': file_id,
125
+ 'votes': updated_file.get('votes', 0)
126
+ })
127
+
128
+ return jsonify({'status': 'ok', 'message': f'Vote recorded successfully with {vote_count} votes'})
129
+ except Exception as e:
130
+ return jsonify({'status': 'error', 'message': str(e)}), 500
131
+
132
+ # API để lấy thông tin người bình chọn
133
+ @app.route('/get-voter', methods=['GET'])
134
+ def get_voter():
135
+ voter_id = request.args.get('id')
136
 
137
+ # Kiểm tra cache
138
+ cached_voter = redis_client.get(f'voter:{voter_id}')
139
+ if cached_voter:
140
+ return jsonify(json.loads(cached_voter))
141
+
142
+ voter = voter_collection.find_one({'_id': ObjectId(voter_id)})
 
 
143
  if not voter:
144
+ return jsonify({'status': 'error', 'message': 'Voter not found'}), 404
145
+
146
+ voter_data = {
147
+ 'status': 'ok',
148
+ 'name': voter['name'],
149
+ 'group': voter['group'],
150
+ 'role': voter['role'],
151
+ 'number_of_votes': voter['number_of_votes']
152
  }
153
+
154
+ # Lưu vào cache
155
+ redis_client.setex(f'voter:{voter_id}', CACHE_EXPIRE_TIME, json.dumps(voter_data))
156
+ return jsonify(voter_data)
157
+
158
+ # Socket events
159
+ @socketio.on('connect')
160
+ def handle_connect():
161
+ print('Client connected')
162
+
163
+ @socketio.on('disconnect')
164
+ def handle_disconnect():
165
+ print('Client disconnected')
166
+
167
+ # Khởi chạy server
168
+ if __name__ == "__main__":
169
+ socketio.run(app, port=5000, debug=True)
requirements.txt CHANGED
@@ -3,4 +3,8 @@ uvicorn[standard]
3
  firebase_admin
4
  uuid
5
  python-multipart
6
- pymongo
 
 
 
 
 
3
  firebase_admin
4
  uuid
5
  python-multipart
6
+ pymongo
7
+ redis
8
+ flask
9
+ flask-socketio
10
+ python-socketio