Coverage for src/service/game_service.py : 64%
Hot-keys on this page
r m x p toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
1from settings import REASON_CATEGORIES
2from flask import current_app
3from flask_jwt_extended import get_jwt_claims
4from sqlalchemy import func, text, select, and_
5from sqlalchemy.sql.expression import null
7from src import db, settings
8from src.utils import pagination_resp, internal_err_resp, message, Paginator, err_resp
9from src.model import GameModel, GenreModel, ContentType, UserModel, ContentModel, RecommendedContentModel, RecommendedContentForGroupModel, MetaUserContentModel, BadRecommendationContentModel, GameAdditionalModel
10from src.schemas import GameBase, GameObject, GenreBase, GameExtra, MetaUserContentBase, GameAdditionalBase
13class GameService:
14 @staticmethod
15 def search_game_data(search_term, page, connected_user_uuid):
16 """ Search game data by name """
17 if not (UserModel.query.filter_by(uuid=connected_user_uuid).first()):
18 return err_resp("User not found!", 404)
19 games, total_pages = Paginator.get_from(
20 GameModel.query.filter(GameModel.name.ilike(search_term+"%")).union(
21 GameModel.query.filter(GameModel.name.ilike("%"+search_term+"%"))),
22 page,
23 )
25 try:
26 game_data = GameBase.loads(games)
28 return pagination_resp(
29 message="Game data sent",
30 content=game_data,
31 page=page,
32 total_pages=total_pages
33 )
35 except Exception as error:
36 current_app.logger.error(error)
37 return internal_err_resp()
39 @staticmethod
40 def get_popular_games(page, connected_user_uuid):
41 if not (user := UserModel.query.filter_by(uuid=connected_user_uuid).first()):
42 return err_resp("User not found!", 404)
44 # NOTE we do not have any rating for game (cold start), so we use 'recommendations' field instead of 'popularity_score' that is computed by 'reco_engine' service
45 games, total_pages = Paginator.get_from(
46 GameModel.query.join(GameModel.content, aliased=True).order_by(
47 GameModel.recommendations.desc().nullslast(),
48 ),
49 page,
50 )
52 try:
53 game_data = GameObject.loads(games)
55 return pagination_resp(
56 message="Most popular game data sent",
57 content=game_data,
58 page=page,
59 total_pages=total_pages
60 )
62 except Exception as error:
63 current_app.logger.error(error)
64 return internal_err_resp()
66 @staticmethod
67 def get_recommended_games_for_user(page, connected_user_uuid, reco_engine):
68 if not (user := UserModel.query.filter_by(uuid=connected_user_uuid).first()):
69 return err_resp("User not found!", 404)
71 filters = [RecommendedContentModel.user_id == user.user_id]
72 if reco_engine is not None:
73 filters.append(RecommendedContentModel.engine == reco_engine)
75 games, total_pages = Paginator.get_from(
76 db.session.query(RecommendedContentModel, GameModel)
77 .join(GameModel.content)
78 .join(RecommendedContentModel, RecommendedContentModel.content_id == ContentModel.content_id)
79 .filter(
80 and_(*filters)
81 )
82 .order_by(
83 RecommendedContentModel.score.desc().nullslast(),
84 GameModel.recommendations.desc().nullslast(),
85 ),
86 page,
87 )
89 try:
90 def c_load(row):
91 app = GameExtra.load(row[1])
92 app["reco_engine"] = row[0].engine
93 app["reco_score"] = row[0].score
94 return app
96 game_data = list(map(c_load, games))
98 return pagination_resp(
99 message="Most popular game data sent",
100 content=game_data,
101 page=page,
102 total_pages=total_pages
103 )
105 except Exception as error:
106 current_app.logger.error(error)
107 return internal_err_resp()
109 @staticmethod
110 def get_recommended_games_for_group(page, connected_user_uuid, reco_engine):
111 if not (user := UserModel.query.filter_by(uuid=connected_user_uuid).first()):
112 return err_resp("User not found!", 404)
114 # Query for recommendation from group
115 groups_ids = [
116 *list(map(lambda x: x.group_id, user.groups)),
117 *list(map(lambda x: x.group_id, user.owned_groups))
118 ]
120 filters = [RecommendedContentForGroupModel.group_id.in_(groups_ids)]
121 if reco_engine is not None:
122 filters.append(RecommendedContentModel.engine == reco_engine)
124 games, total_pages = Paginator.get_from(
125 db.session.query(RecommendedContentForGroupModel, GameModel)
126 .join(GameModel.content)
127 .join(RecommendedContentForGroupModel, RecommendedContentForGroupModel.content_id == ContentModel.content_id)
128 .filter(
129 and_(*filters)
130 )
131 .order_by(
132 RecommendedContentModel.score.desc().nullslast(),
133 GameModel.recommendations.desc().nullslast(),
134 ),
135 page,
136 )
138 try:
139 def c_load(row):
140 app = GameExtra.load(row[1])
141 app["reco_engine"] = row[0].engine
142 app["reco_score"] = row[0].score
143 return app
145 game_data = list(map(c_load, games))
147 return pagination_resp(
148 message="Most popular game data sent",
149 content=game_data,
150 page=page,
151 total_pages=total_pages
152 )
154 except Exception as error:
155 current_app.logger.error(error)
156 return internal_err_resp()
158 @staticmethod
159 def get_ordered_genre(connected_user_uuid):
160 if not (UserModel.query.filter_by(uuid=connected_user_uuid).first()):
161 return err_resp("User not found!", 404)
162 genres = GenreModel.query.filter_by(
163 content_type=ContentType.GAME).order_by(GenreModel.count.desc()).all()
165 try:
166 genres_data = GenreBase.loads(genres)
168 resp = message(True, "Game genres data sent")
169 resp["content"] = genres_data
170 return resp, 200
172 except Exception as error:
173 current_app.logger.error(error)
174 return internal_err_resp()
176 @staticmethod
177 def add_bad_recommendation(user_uuid, content_id, data):
178 """ Add bad user recommendation """
179 if not (user := UserModel.query.filter_by(uuid=user_uuid).first()):
180 return err_resp("User not found!", 404)
182 if not (game := GameModel.query.filter_by(content_id=content_id).first()):
183 return err_resp("Game not found!", 404)
185 try:
186 for type, value in data.items():
187 if type in REASON_CATEGORIES['game']:
188 for r in value:
190 new_bad_reco = BadRecommendationContentModel(
191 user_id=user.user_id,
192 content_id=game.content_id,
193 reason_categorie=type,
194 reason=r
195 )
197 db.session.add(new_bad_reco)
198 db.session.flush()
199 db.session.commit()
201 resp = message(True, "Bad recommendation has been registered.")
202 return resp, 201
204 except Exception as error:
205 current_app.logger.error(error)
206 return internal_err_resp()
208 @staticmethod
209 def add_additional_game(user_uuid, data):
210 """ Add additional game"""
211 if not (user := UserModel.query.filter_by(uuid=user_uuid).first()):
212 return err_resp("User not found!", 404)
214 # Check permissions
215 permissions = get_jwt_claims()['permissions']
216 if "add_content" not in permissions:
217 return err_resp("Permission missing", 403)
219 try:
221 new_additional_game = GameAdditionalModel(
222 name=data['name'],
223 steamid=data['steamid'],
224 )
226 if 'short_description' in data:
227 new_additional_game.short_description = data['short_description']
228 if 'header_image' in data:
229 new_additional_game.header_image = data['header_image']
230 if 'website' in data:
231 new_additional_game.website = data['website']
232 if 'developers' in data:
233 new_additional_game.developers = data['developers']
234 if 'publishers' in data:
235 new_additional_game.publishers = data['publishers']
236 if 'price' in data:
237 new_additional_game.price = data['price']
238 if 'release_date' in data:
239 new_additional_game.release_date = data['release_date']
241 for genre_id in data["genres"]:
242 if (ge := GenreModel.query.filter_by(genre_id=genre_id).first()):
243 new_additional_game.genres.append(ge)
244 else:
245 return err_resp("Genre %s not found!" % genre_id, 404)
247 db.session.add(new_additional_game)
248 db.session.commit()
250 resp = message(True, "Game have been added to validation.")
251 return resp, 201
253 except Exception as error:
254 current_app.logger.error(error)
255 return internal_err_resp()
257 @staticmethod
258 def get_additional_game(connected_user_uuid, page):
259 if not (user := UserModel.query.filter_by(uuid=connected_user_uuid).first()):
260 return err_resp("User not found!", 404)
262 # Check permissions
263 permissions = get_jwt_claims()['permissions']
264 if "add_content" not in permissions:
265 return err_resp("Permission missing", 403)
267 games, total_pages = Paginator.get_from(
268 GameAdditionalModel.query,
269 page,
270 )
272 try:
273 games_data = GameAdditionalBase.loads(games)
275 return pagination_resp(
276 message="Additional game data sent",
277 content=games_data,
278 page=page,
279 total_pages=total_pages
280 )
282 except Exception as error:
283 current_app.logger.error(error)
284 return internal_err_resp()
286 @staticmethod
287 def validate_additional_game(connected_user_uuid, game_id):
288 if not (user := UserModel.query.filter_by(uuid=connected_user_uuid).first()):
289 return err_resp("User not found!", 404)
291 # Check permissions
292 permissions = get_jwt_claims()['permissions']
293 if "validate_added_content" not in permissions:
294 return err_resp("Permission missing", 403)
296 if not (game := GameAdditionalModel.query.filter_by(game_id=game_id).first()):
297 return err_resp("Additional game not found!", 404)
299 try:
300 content = ContentModel(rating=None, genres=game.genres)
301 db.session.add(content)
302 db.session.flush()
304 new_game = GameModel(
305 steamid=game.steamid,
306 name=game.name,
307 short_description=game.short_description,
308 header_image=game.header_image,
309 website=game.website,
310 developers=game.developers,
311 publishers=game.publishers,
312 price=game.price,
313 release_date=game.release_date,
314 content=content
315 )
316 db.session.add(new_game)
317 db.session.delete(game)
319 db.session.commit()
321 resp = message(
322 True, "Additional game data successfully validated")
323 return resp, 201
325 except Exception as error:
326 current_app.logger.error(error)
327 return internal_err_resp()
329 @staticmethod
330 def decline_additional_game(connected_user_uuid, game_id):
331 if not (user := UserModel.query.filter_by(uuid=connected_user_uuid).first()):
332 return err_resp("User not found!", 404)
334 # Check permissions
335 permissions = get_jwt_claims()['permissions']
336 if "delete_content" not in permissions:
337 return err_resp("Permission missing", 403)
339 if not (game := GameAdditionalModel.query.filter_by(game_id=game_id).first()):
340 return err_resp("Additional game not found!", 404)
342 try:
343 db.session.delete(game)
344 db.session.commit()
346 resp = message(True, "Additional game successfully deleted")
347 return resp, 201
349 except Exception as error:
350 current_app.logger.error(error)
351 return internal_err_resp()