Coverage for src/service/application_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 ApplicationModel, UserModel, GenreModel, ContentType, ContentModel, RecommendedContentModel, RecommendedContentForGroupModel, MetaUserContentModel, BadRecommendationContentModel, ApplicationAdditionalModel
10from src.schemas import ApplicationBase, GenreBase, MetaUserContentBase, ApplicationExtra, ApplicationAdditionalBase
13class ApplicationService:
14 @staticmethod
15 def search_application_data(search_term, page, connected_user_uuid):
16 """ Search application data by name """
17 if not (UserModel.query.filter_by(uuid=connected_user_uuid).first()):
18 return err_resp("User not found!", 404)
19 applications, total_pages = Paginator.get_from(
20 ApplicationModel.query.filter(ApplicationModel.name.ilike(search_term+"%")).union(
21 ApplicationModel.query.filter(ApplicationModel.name.ilike("%"+search_term+"%"))),
22 page,
23 )
25 try:
26 application_data = ApplicationBase.loads(applications)
28 return pagination_resp(
29 message="Application data sent",
30 content=application_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_applications(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 IMDB measure of popularity does not seem to be relevant for this media.
45 applications, total_pages = Paginator.get_from(
46 ApplicationModel.query.join(ApplicationModel.content, aliased=True).order_by(
47 ContentModel.rating_count.desc().nullslast(),
48 ContentModel.rating.desc().nullslast(),
49 ),
50 page,
51 )
53 try:
54 application_data = ApplicationBase.loads(applications)
56 return pagination_resp(
57 message="Most popular application data sent",
58 content=application_data,
59 page=page,
60 total_pages=total_pages
61 )
63 except Exception as error:
64 current_app.logger.error(error)
65 return internal_err_resp()
67 @staticmethod
68 def get_recommended_applications_for_user(page, connected_user_uuid, reco_engine):
69 if not (user := UserModel.query.filter_by(uuid=connected_user_uuid).first()):
70 return err_resp("User not found!", 404)
72 filters = [RecommendedContentModel.user_id == user.user_id]
73 if reco_engine is not None:
74 filters.append(RecommendedContentModel.engine == reco_engine)
76 applications, total_pages = Paginator.get_from(
77 db.session.query(RecommendedContentModel, ApplicationModel)
78 .join(ApplicationModel.content)
79 .join(RecommendedContentModel, RecommendedContentModel.content_id == ContentModel.content_id)
80 .filter(
81 and_(*filters)
82 )
83 .order_by(
84 RecommendedContentModel.score.desc().nullslast(),
85 ContentModel.rating_count.desc().nullslast(),
86 ContentModel.rating.desc().nullslast(),
87 ),
88 page,
89 )
91 try:
92 def c_load(row):
93 app = ApplicationExtra.load(row[1])
94 app["reco_engine"] = row[0].engine
95 app["reco_score"] = row[0].score
96 return app
98 application_data = list(map(c_load, applications))
100 return pagination_resp(
101 message="Most popular application data sent",
102 content=application_data,
103 page=page,
104 total_pages=total_pages
105 )
107 except Exception as error:
108 current_app.logger.error(error)
109 return internal_err_resp()
111 @staticmethod
112 def get_recommended_applications_for_group(page, connected_user_uuid, reco_engine):
113 if not (user := UserModel.query.filter_by(uuid=connected_user_uuid).first()):
114 return err_resp("User not found!", 404)
116 # Query for recommendation from group
117 groups_ids = [
118 *list(map(lambda x: x.group_id, user.groups)),
119 *list(map(lambda x: x.group_id, user.owned_groups))
120 ]
122 filters = [RecommendedContentForGroupModel.group_id.in_(groups_ids)]
123 if reco_engine is not None:
124 filters.append(RecommendedContentModel.engine == reco_engine)
126 applications, total_pages = Paginator.get_from(
127 db.session.query(RecommendedContentForGroupModel, ApplicationModel)
128 .join(ApplicationModel.content)
129 .join(RecommendedContentForGroupModel, RecommendedContentForGroupModel.content_id == ContentModel.content_id)
130 .filter(
131 and_(*filters)
132 )
133 .order_by(
134 RecommendedContentModel.score.desc().nullslast(),
135 ContentModel.rating_count.desc().nullslast(),
136 ContentModel.rating.desc().nullslast(),
137 ),
138 page,
139 )
141 try:
142 def c_load(row):
143 app = ApplicationExtra.load(row[1])
144 app["reco_engine"] = row[0].engine
145 app["reco_score"] = row[0].score
146 return app
148 application_data = list(map(c_load, applications))
150 return pagination_resp(
151 message="Most popular application data sent",
152 content=application_data,
153 page=page,
154 total_pages=total_pages
155 )
157 except Exception as error:
158 current_app.logger.error(error)
159 return internal_err_resp()
161 @staticmethod
162 def get_ordered_genres(connected_user_uuid):
163 if not (UserModel.query.filter_by(uuid=connected_user_uuid).first()):
164 return err_resp("User not found!", 404)
166 genres = GenreModel.query.filter_by(
167 content_type=ContentType.APPLICATION).order_by(GenreModel.count.desc()).all()
169 # Check permissions
170 permissions = get_jwt_claims()['permissions']
171 if "indicate_interest" not in permissions:
172 return err_resp("Permission missing", 403)
174 try:
175 genres_data = GenreBase.loads(genres)
177 resp = message(True, "Application genres data sent")
178 resp["content"] = genres_data
179 return resp, 200
181 except Exception as error:
182 current_app.logger.error(error)
183 return internal_err_resp()
185 @staticmethod
186 def add_bad_recommendation(user_uuid, content_id, data):
187 """ Add bad user recommendation """
188 if not (user := UserModel.query.filter_by(uuid=user_uuid).first()):
189 return err_resp("User not found!", 404)
191 if not (app := ApplicationModel.query.filter_by(content_id=content_id).first()):
192 return err_resp("Application not found!", 404)
194 try:
195 for type, value in data.items():
196 if type in REASON_CATEGORIES['application']:
197 for r in value:
199 new_bad_reco = BadRecommendationContentModel(
200 user_id=user.user_id,
201 content_id=app.content_id,
202 reason_categorie=type,
203 reason=r
204 )
206 db.session.add(new_bad_reco)
207 db.session.flush()
208 db.session.commit()
210 resp = message(True, "Bad recommendation has been registered.")
211 return resp, 201
213 except Exception as error:
214 current_app.logger.error(error)
215 return internal_err_resp()
217 @staticmethod
218 def add_additional_application(user_uuid, data):
219 """ Add additional application"""
220 if not (user := UserModel.query.filter_by(uuid=user_uuid).first()):
221 return err_resp("User not found!", 404)
223 # Check permissions
224 permissions = get_jwt_claims()['permissions']
225 if "add_content" not in permissions:
226 return err_resp("Permission missing", 403)
228 try:
230 new_additional_application = ApplicationAdditionalModel(
231 name=data['name'],
232 )
234 if 'size' in data:
235 new_additional_application.size = data['size']
236 if 'installs' in data:
237 new_additional_application.installs = data['installs']
238 if 'type' in data:
239 new_additional_application.type = data['type']
240 if 'price' in data:
241 new_additional_application.price = data['price']
242 if 'content_rating' in data:
243 new_additional_application.content_rating = data['content_rating']
244 if 'last_updated' in data:
245 new_additional_application.last_updated = data['last_updated']
246 if 'current_version' in data:
247 new_additional_application.current_version = data['current_version']
248 if 'android_version' in data:
249 new_additional_application.android_version = data['android_version']
250 if 'cover' in data:
251 new_additional_application.cover = data['cover']
253 for genre_id in data["genres"]:
254 if (ge := GenreModel.query.filter_by(genre_id=genre_id).first()):
255 new_additional_application.genres.append(ge)
256 else:
257 return err_resp("Genre %s not found!" % genre_id, 404)
259 db.session.add(new_additional_application)
260 db.session.commit()
262 resp = message(True, "Application have been added to validation.")
263 return resp, 201
265 except Exception as error:
266 current_app.logger.error(error)
267 return internal_err_resp()
269 @staticmethod
270 def get_additional_application(connected_user_uuid, page):
271 if not (user := UserModel.query.filter_by(uuid=connected_user_uuid).first()):
272 return err_resp("User not found!", 404)
274 # Check permissions
275 permissions = get_jwt_claims()['permissions']
276 if "add_content" not in permissions:
277 return err_resp("Permission missing", 403)
279 applications, total_pages = Paginator.get_from(
280 ApplicationAdditionalModel.query,
281 page,
282 )
284 try:
285 application_data = ApplicationAdditionalBase.loads(applications)
287 return pagination_resp(
288 message="Additional application data sent",
289 content=application_data,
290 page=page,
291 total_pages=total_pages
292 )
294 except Exception as error:
295 current_app.logger.error(error)
296 return internal_err_resp()
298 @staticmethod
299 def validate_additional_application(connected_user_uuid, app_id):
300 if not (user := UserModel.query.filter_by(uuid=connected_user_uuid).first()):
301 return err_resp("User not found!", 404)
303 # Check permissions
304 permissions = get_jwt_claims()['permissions']
305 if "validate_added_content" not in permissions:
306 return err_resp("Permission missing", 403)
308 if not (app := ApplicationAdditionalModel.query.filter_by(app_id=app_id).first()):
309 return err_resp("Additional application not found!", 404)
311 try:
312 content = ContentModel(rating=None, genres=app.genres)
313 db.session.add(content)
314 db.session.flush()
316 new_application = ApplicationModel(
317 name=app.name,
318 size=app.size,
319 installs=app.installs,
320 type=app.type,
321 price=app.price,
322 content_rating=app.content_rating,
323 last_updated=app.last_updated,
324 current_version=app.current_version,
325 android_version=app.android_version,
326 cover=app.cover,
327 content=content
328 )
329 db.session.add(new_application)
330 db.session.delete(app)
332 db.session.commit()
334 resp = message(
335 True, "Additional application data successfully validated")
336 return resp, 201
338 except Exception as error:
339 current_app.logger.error(error)
340 return internal_err_resp()
342 @staticmethod
343 def decline_additional_application(connected_user_uuid, app_id):
344 if not (user := UserModel.query.filter_by(uuid=connected_user_uuid).first()):
345 return err_resp("User not found!", 404)
347 # Check permissions
348 permissions = get_jwt_claims()['permissions']
349 if "delete_content" not in permissions:
350 return err_resp("Permission missing", 403)
352 if not (app := ApplicationAdditionalModel.query.filter_by(app_id=app_id).first()):
353 return err_resp("Additional application not found!", 404)
355 try:
356 db.session.delete(app)
357 db.session.commit()
359 resp = message(True, "Additional application successfully deleted")
360 return resp, 201
362 except Exception as error:
363 current_app.logger.error(error)
364 return internal_err_resp()