dev2004v commited on
Commit
1b8f908
·
verified ·
1 Parent(s): 7480dec

Update routes/recommend.py

Browse files
Files changed (1) hide show
  1. routes/recommend.py +318 -222
routes/recommend.py CHANGED
@@ -1,222 +1,318 @@
1
- from flask import Blueprint, request, jsonify
2
- import requests
3
- import os
4
- from dotenv import load_dotenv
5
- from utils.jwt_helper import decode_jwt
6
- from models.history import History
7
-
8
- load_dotenv()
9
-
10
- recommend_bp = Blueprint('recommend', __name__)
11
-
12
- RECOMMENDER_ENDPOINTS = {
13
- "movie": os.getenv("MOVIE_RECOMMENDER_URL"),
14
- "book": os.getenv("BOOK_RECOMMENDER_URL"),
15
- "tv": os.getenv("TV_RECOMMENDER_URL")
16
- }
17
-
18
- RESPONSE_KEYS = {
19
- "movie": "movies",
20
- "book": "books",
21
- "tv": "shows"
22
- }
23
-
24
- @recommend_bp.route('/recommend/tvshowrec', methods=['POST'])
25
- def recommend():
26
- try:
27
- data = request.get_json()
28
-
29
- if not data:
30
- return jsonify({"error": "No data provided"}), 400
31
-
32
- rec_type = data.get('type')
33
- genre = data.get('genre')
34
- top_k = data.get('top_k', 10)
35
-
36
- if not rec_type or not genre:
37
- return jsonify({"error": "Missing 'type' or 'genre'"}), 400
38
-
39
- if rec_type not in RECOMMENDER_ENDPOINTS or not RECOMMENDER_ENDPOINTS[rec_type]:
40
- return jsonify({"error": "Invalid or missing recommender URL for type."}), 400
41
-
42
- # JWT Authentication
43
- auth_header = request.headers.get('Authorization')
44
- if not auth_header or not auth_header.startswith('Bearer '):
45
- return jsonify({"error": "Missing or invalid Authorization header"}), 401
46
-
47
- token = auth_header.split(" ")[1]
48
- try:
49
- user_data = decode_jwt(token)
50
- user_id = user_data.get("user_id")
51
- except Exception as e:
52
- return jsonify({"error": "Invalid or expired token"}), 401
53
-
54
- # Process genres
55
- genres_list = [g.strip() for g in genre.split(",")] if isinstance(genre, str) else genre
56
-
57
- # Call microservice
58
- try:
59
- recommender_url = RECOMMENDER_ENDPOINTS[rec_type]
60
- response = requests.post(
61
- recommender_url,
62
- json={"genres": genres_list},
63
- timeout=10
64
- )
65
-
66
- if not response.ok:
67
- return jsonify({
68
- "error": f"{rec_type} service error",
69
- "details": response.text,
70
- "status_code": response.status_code
71
- }), 500
72
-
73
- result = response.json()
74
- if result.get("status") != "success":
75
- return jsonify({"error": result.get("message", "Unknown error")}), 500
76
-
77
- raw_items = result.get(RESPONSE_KEYS.get(rec_type, "items"), [])
78
-
79
- # Normalize response format
80
- normalized = []
81
- for item in raw_items:
82
- normalized.append({
83
- "type": rec_type,
84
- "name": item.get("name") or item.get("title"),
85
- "creator": item.get("director") or item.get("author") or item.get("creator"),
86
- "description": item.get("description", ""),
87
- "genre": item.get("genre", []),
88
- "rating": item.get("rating"),
89
- "year": item.get("year"),
90
- "image_url": item.get("image_url")
91
- })
92
-
93
- # Save to history
94
- try:
95
- history = History(
96
- user_id=user_id,
97
- recommendation_type=rec_type,
98
- genre=genres_list,
99
- items=normalized,
100
- query_params={"top_k": top_k}
101
- )
102
- history.save()
103
- print(f"Saved recommendation history for user {user_id}")
104
- except Exception as e:
105
- print(f"Failed to save history: {e}")
106
- # Don't fail the request if history saving fails
107
-
108
- return jsonify({
109
- "status": "success",
110
- "recommendations": normalized,
111
- "count": len(normalized),
112
- "type": rec_type,
113
- "genres": genres_list
114
- }), 200
115
-
116
- except requests.exceptions.Timeout:
117
- return jsonify({"error": f"{rec_type} service timeout"}), 504
118
- except requests.exceptions.RequestException as e:
119
- return jsonify({"error": f"Failed to connect to {rec_type} service", "details": str(e)}), 503
120
-
121
- except Exception as e:
122
- print(f"Recommend error: {e}")
123
- return jsonify({"error": "Internal server error"}), 500
124
-
125
- @recommend_bp.route('/recommend/movies', methods=['POST'])
126
- def recommend():
127
- try:
128
- data = request.get_json()
129
-
130
- if not data:
131
- return jsonify({"error": "No data provided"}), 400
132
-
133
- rec_type = data.get('type')
134
- genre = data.get('genre')
135
- top_k = data.get('top_k', 10)
136
-
137
- if not rec_type or not genre:
138
- return jsonify({"error": "Missing 'type' or 'genre'"}), 400
139
-
140
- if rec_type not in RECOMMENDER_ENDPOINTS or not RECOMMENDER_ENDPOINTS[rec_type]:
141
- return jsonify({"error": "Invalid or missing recommender URL for type."}), 400
142
-
143
- # JWT Authentication
144
- auth_header = request.headers.get('Authorization')
145
- if not auth_header or not auth_header.startswith('Bearer '):
146
- return jsonify({"error": "Missing or invalid Authorization header"}), 401
147
-
148
- token = auth_header.split(" ")[1]
149
- try:
150
- user_data = decode_jwt(token)
151
- user_id = user_data.get("user_id")
152
- except Exception as e:
153
- return jsonify({"error": "Invalid or expired token"}), 401
154
-
155
- # Process genres
156
- genres_list = [g.strip() for g in genre.split(",")] if isinstance(genre, str) else genre
157
-
158
- # Call microservice
159
- try:
160
- recommender_url = RECOMMENDER_ENDPOINTS[rec_type]
161
- response = requests.post(
162
- recommender_url,
163
- json={"genres": genres_list, "top_k": top_k},
164
- timeout=10
165
- )
166
-
167
- if not response.ok:
168
- return jsonify({
169
- "error": f"{rec_type} service error",
170
- "details": response.text,
171
- "status_code": response.status_code
172
- }), 500
173
-
174
- result = response.json()
175
- if result.get("status") != "success":
176
- return jsonify({"error": result.get("message", "Unknown error")}), 500
177
-
178
- raw_items = result.get(RESPONSE_KEYS.get(rec_type, "items"), [])
179
-
180
- # Normalize response format
181
- normalized = []
182
- for item in raw_items:
183
- normalized.append({
184
- "type": rec_type,
185
- "name": item.get("name") or item.get("title"),
186
- "creator": item.get("director") or item.get("author") or item.get("creator"),
187
- "description": item.get("description", ""),
188
- "genre": item.get("genre", []),
189
- "rating": item.get("rating")
190
- })
191
-
192
- # Save to history
193
- try:
194
- history = History(
195
- user_id=user_id,
196
- recommendation_type=rec_type,
197
- genre=genres_list,
198
- items=normalized,
199
- query_params={"top_k": top_k}
200
- )
201
- history.save()
202
- print(f"Saved recommendation history for user {user_id}")
203
- except Exception as e:
204
- print(f"Failed to save history: {e}")
205
- # Don't fail the request if history saving fails
206
-
207
- return jsonify({
208
- "status": "success",
209
- "recommendations": normalized,
210
- "count": len(normalized),
211
- "type": rec_type,
212
- "genres": genres_list
213
- }), 200
214
-
215
- except requests.exceptions.Timeout:
216
- return jsonify({"error": f"{rec_type} service timeout"}), 504
217
- except requests.exceptions.RequestException as e:
218
- return jsonify({"error": f"Failed to connect to {rec_type} service", "details": str(e)}), 503
219
-
220
- except Exception as e:
221
- print(f"Recommend error: {e}")
222
- return jsonify({"error": "Internal server error"}), 500
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from flask import Blueprint, request, jsonify
2
+ import requests
3
+ import os
4
+ from dotenv import load_dotenv
5
+ from utils.jwt_helper import decode_jwt
6
+ from models.history import History
7
+
8
+ load_dotenv()
9
+
10
+ recommend_bp = Blueprint('recommend', __name__)
11
+
12
+ RECOMMENDER_ENDPOINTS = {
13
+ "movie": os.getenv("MOVIE_RECOMMENDER_URL"),
14
+ "book": os.getenv("BOOK_RECOMMENDER_URL"),
15
+ "tv": os.getenv("TV_RECOMMENDER_URL")
16
+ }
17
+
18
+ RESPONSE_KEYS = {
19
+ "movie": "movies",
20
+ "book": "books",
21
+ "tv": "shows"
22
+ }
23
+
24
+ @recommend_bp.route('/recommend/tvshowrec', methods=['POST'])
25
+ def recommend_tv():
26
+ try:
27
+ data = request.get_json()
28
+
29
+ if not data:
30
+ return jsonify({"error": "No data provided"}), 400
31
+
32
+ rec_type = data.get('type')
33
+ genre = data.get('genre')
34
+ top_k = data.get('top_k', 10)
35
+
36
+ if not rec_type or not genre:
37
+ return jsonify({"error": "Missing 'type' or 'genre'"}), 400
38
+
39
+ if rec_type not in RECOMMENDER_ENDPOINTS or not RECOMMENDER_ENDPOINTS[rec_type]:
40
+ return jsonify({"error": "Invalid or missing recommender URL for type."}), 400
41
+
42
+ # JWT Authentication
43
+ auth_header = request.headers.get('Authorization')
44
+ if not auth_header or not auth_header.startswith('Bearer '):
45
+ return jsonify({"error": "Missing or invalid Authorization header"}), 401
46
+
47
+ token = auth_header.split(" ")[1]
48
+ try:
49
+ user_data = decode_jwt(token)
50
+ user_id = user_data.get("user_id")
51
+ except Exception as e:
52
+ return jsonify({"error": "Invalid or expired token"}), 401
53
+
54
+ # Process genres
55
+ genres_list = [g.strip() for g in genre.split(",")] if isinstance(genre, str) else genre
56
+
57
+ # Call microservice
58
+ try:
59
+ recommender_url = RECOMMENDER_ENDPOINTS[rec_type]
60
+ response = requests.post(
61
+ recommender_url,
62
+ json={"genres": genres_list},
63
+ timeout=10
64
+ )
65
+
66
+ if not response.ok:
67
+ return jsonify({
68
+ "error": f"{rec_type} service error",
69
+ "details": response.text,
70
+ "status_code": response.status_code
71
+ }), 500
72
+
73
+ result = response.json()
74
+ if result.get("status") != "success":
75
+ return jsonify({"error": result.get("message", "Unknown error")}), 500
76
+
77
+ raw_items = result.get(RESPONSE_KEYS.get(rec_type, "items"), [])
78
+
79
+ # Normalize response format
80
+ normalized = []
81
+ for item in raw_items:
82
+ normalized.append({
83
+ "type": rec_type,
84
+ "name": item.get("name") or item.get("title"),
85
+ "creator": item.get("director") or item.get("author") or item.get("creator"),
86
+ "description": item.get("description", ""),
87
+ "genre": item.get("genre", []),
88
+ "rating": item.get("rating"),
89
+ "year": item.get("year"),
90
+ "image_url": item.get("image_url")
91
+ })
92
+
93
+ # Save to history
94
+ try:
95
+ history = History(
96
+ user_id=user_id,
97
+ recommendation_type=rec_type,
98
+ genre=genres_list,
99
+ items=normalized,
100
+ query_params={"top_k": top_k}
101
+ )
102
+ history.save()
103
+ print(f"Saved recommendation history for user {user_id}")
104
+ except Exception as e:
105
+ print(f"Failed to save history: {e}")
106
+ # Don't fail the request if history saving fails
107
+
108
+ return jsonify({
109
+ "status": "success",
110
+ "recommendations": normalized,
111
+ "count": len(normalized),
112
+ "type": rec_type,
113
+ "genres": genres_list
114
+ }), 200
115
+
116
+ except requests.exceptions.Timeout:
117
+ return jsonify({"error": f"{rec_type} service timeout"}), 504
118
+ except requests.exceptions.RequestException as e:
119
+ return jsonify({"error": f"Failed to connect to {rec_type} service", "details": str(e)}), 503
120
+
121
+ except Exception as e:
122
+ print(f"Recommend error: {e}")
123
+ return jsonify({"error": "Internal server error"}), 500
124
+
125
+ @recommend_bp.route('/recommend/movies', methods=['POST'])
126
+ def recommend_movie():
127
+ try:
128
+ data = request.get_json()
129
+
130
+ if not data:
131
+ return jsonify({"error": "No data provided"}), 400
132
+
133
+ rec_type = data.get('type')
134
+ genre = data.get('genre')
135
+ top_k = data.get('top_k', 10)
136
+
137
+ if not rec_type or not genre:
138
+ return jsonify({"error": "Missing 'type' or 'genre'"}), 400
139
+
140
+ if rec_type not in RECOMMENDER_ENDPOINTS or not RECOMMENDER_ENDPOINTS[rec_type]:
141
+ return jsonify({"error": "Invalid or missing recommender URL for type."}), 400
142
+
143
+ # JWT Authentication
144
+ auth_header = request.headers.get('Authorization')
145
+ if not auth_header or not auth_header.startswith('Bearer '):
146
+ return jsonify({"error": "Missing or invalid Authorization header"}), 401
147
+
148
+ token = auth_header.split(" ")[1]
149
+ try:
150
+ user_data = decode_jwt(token)
151
+ user_id = user_data.get("user_id")
152
+ except Exception as e:
153
+ return jsonify({"error": "Invalid or expired token"}), 401
154
+
155
+ # Process genres
156
+ genres_list = [g.strip() for g in genre.split(",")] if isinstance(genre, str) else genre
157
+
158
+ # Call microservice
159
+ try:
160
+ recommender_url = RECOMMENDER_ENDPOINTS[rec_type]
161
+ response = requests.post(
162
+ recommender_url,
163
+ json={"genres": genres_list, "top_k": top_k},
164
+ timeout=10
165
+ )
166
+
167
+ if not response.ok:
168
+ return jsonify({
169
+ "error": f"{rec_type} service error",
170
+ "details": response.text,
171
+ "status_code": response.status_code
172
+ }), 500
173
+
174
+ result = response.json()
175
+ if result.get("status") != "success":
176
+ return jsonify({"error": result.get("message", "Unknown error")}), 500
177
+
178
+ raw_items = result.get(RESPONSE_KEYS.get(rec_type, "items"), [])
179
+
180
+ # Normalize response format
181
+ normalized = []
182
+ for item in raw_items:
183
+ normalized.append({
184
+ "type": rec_type,
185
+ "name": item.get("name") or item.get("title"),
186
+ "creator": item.get("director") or item.get("author") or item.get("creator"),
187
+ "description": item.get("description", ""),
188
+ "genre": item.get("genre", []),
189
+ "rating": item.get("rating")
190
+ })
191
+
192
+ # Save to history
193
+ try:
194
+ history = History(
195
+ user_id=user_id,
196
+ recommendation_type=rec_type,
197
+ genre=genres_list,
198
+ items=normalized,
199
+ query_params={"top_k": top_k}
200
+ )
201
+ history.save()
202
+ print(f"Saved recommendation history for user {user_id}")
203
+ except Exception as e:
204
+ print(f"Failed to save history: {e}")
205
+ # Don't fail the request if history saving fails
206
+
207
+ return jsonify({
208
+ "status": "success",
209
+ "recommendations": normalized,
210
+ "count": len(normalized),
211
+ "type": rec_type,
212
+ "genres": genres_list
213
+ }), 200
214
+
215
+ except requests.exceptions.Timeout:
216
+ return jsonify({"error": f"{rec_type} service timeout"}), 504
217
+ except requests.exceptions.RequestException as e:
218
+ return jsonify({"error": f"Failed to connect to {rec_type} service", "details": str(e)}), 503
219
+
220
+ except Exception as e:
221
+ print(f"Recommend error: {e}")
222
+ return jsonify({"error": "Internal server error"}), 500
223
+
224
+
225
+ @recommend_bp.route('/recommend/book', methods=['POST'])
226
+ def recommend_book():
227
+ try:
228
+ data = request.get_json()
229
+
230
+ if not data:
231
+ return jsonify({"error": "No data provided"}), 400
232
+
233
+ rec_type = data.get('type')
234
+ genre = data.get('genre')
235
+ top_k = data.get('top_k', 10)
236
+
237
+ if not rec_type or not genre:
238
+ return jsonify({"error": "Missing 'type' or 'genre'"}), 400
239
+
240
+ if rec_type not in RECOMMENDER_ENDPOINTS or not RECOMMENDER_ENDPOINTS[rec_type]:
241
+ return jsonify({"error": "Invalid or missing recommender URL for type."}), 400
242
+
243
+ # JWT Authentication
244
+ auth_header = request.headers.get('Authorization')
245
+ if not auth_header or not auth_header.startswith('Bearer '):
246
+ return jsonify({"error": "Missing or invalid Authorization header"}), 401
247
+
248
+ token = auth_header.split(" ")[1]
249
+ try:
250
+ user_data = decode_jwt(token)
251
+ user_id = user_data.get("user_id")
252
+ except Exception as e:
253
+ return jsonify({"error": "Invalid or expired token"}), 401
254
+
255
+ # Process genres
256
+ genres_list = [g.strip() for g in genre.split(",")] if isinstance(genre, str) else genre
257
+
258
+ # Call microservice
259
+ try:
260
+ recommender_url = RECOMMENDER_ENDPOINTS[rec_type]
261
+ response = requests.post(
262
+ recommender_url,
263
+ json={"genres": genres_list, "top_k": top_k},
264
+ timeout=10
265
+ )
266
+
267
+ if not response.ok:
268
+ return jsonify({
269
+ "error": f"{rec_type} service error",
270
+ "details": response.text,
271
+ "status_code": response.status_code
272
+ }), 500
273
+
274
+ result = response.json()
275
+ if result.get("status") != "success":
276
+ return jsonify({"error": result.get("message", "Unknown error")}), 500
277
+
278
+ raw_items = result.get(RESPONSE_KEYS.get(rec_type, "items"), [])
279
+
280
+ # Normalize response format
281
+ normalized = []
282
+ for item in raw_items:
283
+ normalized.append({
284
+ "type": rec_type,
285
+ "name": item.get("name") or item.get("title"),
286
+ "creator": item.get("director") or item.get("author") or item.get("creator"),
287
+ "description": item.get("description", ""),
288
+ "genre": item.get("genre", []),
289
+ "rating": item.get("rating")
290
+ })
291
+
292
+ # Save to history
293
+ try:
294
+ history = History(
295
+ user_id=user_id,
296
+ recommendation_type=rec_type,
297
+ genre=genres_list,
298
+ items=normalized,
299
+ query_params={"top_k": top_k}
300
+ )
301
+ history.save()
302
+ print(f"Saved recommendation history for user {user_id}")
303
+ except Exception as e:
304
+ print(f"Failed to save history: {e}")
305
+ # Don't fail the request if history saving fails
306
+
307
+ return jsonify({
308
+ "status": "success",
309
+ "recommendations": normalized,
310
+ "count": len(normalized),
311
+ "type": rec_type,
312
+ "genres": genres_list
313
+ }), 200
314
+
315
+ except requests.exceptions.Timeout:
316
+ return jsonify({"error": f"{rec_type} service timeout"}), 504
317
+ except requests.exceptions.RequestException as e:
318
+ return jsonify({"error": f"Failed to connect to {rec_type} service", "details": str(e)}), 503