Hide keyboard shortcuts

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 

6 

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 

11 

12 

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 ) 

24 

25 try: 

26 game_data = GameBase.loads(games) 

27 

28 return pagination_resp( 

29 message="Game data sent", 

30 content=game_data, 

31 page=page, 

32 total_pages=total_pages 

33 ) 

34 

35 except Exception as error: 

36 current_app.logger.error(error) 

37 return internal_err_resp() 

38 

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) 

43 

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 ) 

51 

52 try: 

53 game_data = GameObject.loads(games) 

54 

55 return pagination_resp( 

56 message="Most popular game data sent", 

57 content=game_data, 

58 page=page, 

59 total_pages=total_pages 

60 ) 

61 

62 except Exception as error: 

63 current_app.logger.error(error) 

64 return internal_err_resp() 

65 

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) 

70 

71 filters = [RecommendedContentModel.user_id == user.user_id] 

72 if reco_engine is not None: 

73 filters.append(RecommendedContentModel.engine == reco_engine) 

74 

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 ) 

88 

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 

95 

96 game_data = list(map(c_load, games)) 

97 

98 return pagination_resp( 

99 message="Most popular game data sent", 

100 content=game_data, 

101 page=page, 

102 total_pages=total_pages 

103 ) 

104 

105 except Exception as error: 

106 current_app.logger.error(error) 

107 return internal_err_resp() 

108 

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) 

113 

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 ] 

119 

120 filters = [RecommendedContentForGroupModel.group_id.in_(groups_ids)] 

121 if reco_engine is not None: 

122 filters.append(RecommendedContentModel.engine == reco_engine) 

123 

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 ) 

137 

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 

144 

145 game_data = list(map(c_load, games)) 

146 

147 return pagination_resp( 

148 message="Most popular game data sent", 

149 content=game_data, 

150 page=page, 

151 total_pages=total_pages 

152 ) 

153 

154 except Exception as error: 

155 current_app.logger.error(error) 

156 return internal_err_resp() 

157 

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() 

164 

165 try: 

166 genres_data = GenreBase.loads(genres) 

167 

168 resp = message(True, "Game genres data sent") 

169 resp["content"] = genres_data 

170 return resp, 200 

171 

172 except Exception as error: 

173 current_app.logger.error(error) 

174 return internal_err_resp() 

175 

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) 

181 

182 if not (game := GameModel.query.filter_by(content_id=content_id).first()): 

183 return err_resp("Game not found!", 404) 

184 

185 try: 

186 for type, value in data.items(): 

187 if type in REASON_CATEGORIES['game']: 

188 for r in value: 

189 

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 ) 

196 

197 db.session.add(new_bad_reco) 

198 db.session.flush() 

199 db.session.commit() 

200 

201 resp = message(True, "Bad recommendation has been registered.") 

202 return resp, 201 

203 

204 except Exception as error: 

205 current_app.logger.error(error) 

206 return internal_err_resp() 

207 

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) 

213 

214 # Check permissions 

215 permissions = get_jwt_claims()['permissions'] 

216 if "add_content" not in permissions: 

217 return err_resp("Permission missing", 403) 

218 

219 try: 

220 

221 new_additional_game = GameAdditionalModel( 

222 name=data['name'], 

223 steamid=data['steamid'], 

224 ) 

225 

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'] 

240 

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) 

246 

247 db.session.add(new_additional_game) 

248 db.session.commit() 

249 

250 resp = message(True, "Game have been added to validation.") 

251 return resp, 201 

252 

253 except Exception as error: 

254 current_app.logger.error(error) 

255 return internal_err_resp() 

256 

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) 

261 

262 # Check permissions 

263 permissions = get_jwt_claims()['permissions'] 

264 if "add_content" not in permissions: 

265 return err_resp("Permission missing", 403) 

266 

267 games, total_pages = Paginator.get_from( 

268 GameAdditionalModel.query, 

269 page, 

270 ) 

271 

272 try: 

273 games_data = GameAdditionalBase.loads(games) 

274 

275 return pagination_resp( 

276 message="Additional game data sent", 

277 content=games_data, 

278 page=page, 

279 total_pages=total_pages 

280 ) 

281 

282 except Exception as error: 

283 current_app.logger.error(error) 

284 return internal_err_resp() 

285 

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) 

290 

291 # Check permissions 

292 permissions = get_jwt_claims()['permissions'] 

293 if "validate_added_content" not in permissions: 

294 return err_resp("Permission missing", 403) 

295 

296 if not (game := GameAdditionalModel.query.filter_by(game_id=game_id).first()): 

297 return err_resp("Additional game not found!", 404) 

298 

299 try: 

300 content = ContentModel(rating=None, genres=game.genres) 

301 db.session.add(content) 

302 db.session.flush() 

303 

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) 

318 

319 db.session.commit() 

320 

321 resp = message( 

322 True, "Additional game data successfully validated") 

323 return resp, 201 

324 

325 except Exception as error: 

326 current_app.logger.error(error) 

327 return internal_err_resp() 

328 

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) 

333 

334 # Check permissions 

335 permissions = get_jwt_claims()['permissions'] 

336 if "delete_content" not in permissions: 

337 return err_resp("Permission missing", 403) 

338 

339 if not (game := GameAdditionalModel.query.filter_by(game_id=game_id).first()): 

340 return err_resp("Additional game not found!", 404) 

341 

342 try: 

343 db.session.delete(game) 

344 db.session.commit() 

345 

346 resp = message(True, "Additional game successfully deleted") 

347 return resp, 201 

348 

349 except Exception as error: 

350 current_app.logger.error(error) 

351 return internal_err_resp()