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 src.utils import err_resp, message, internal_err_resp, Spotify, TMDB, GBooks, validation_error 

2from src.model import UserModel, ExternalModel, TrackModel, MovieModel, SerieModel, BookModel, MetaUserContentModel, ContentModel 

3from src import db 

4from flask import current_app, session 

5from flask_jwt_extended import decode_token 

6 

7from dateutil.parser import parse 

8 

9 

10class ExternalService: 

11 @staticmethod 

12 def get_spotify_oauth(user_uuid): 

13 """ Get spotify oauth url """ 

14 if not (user := UserModel.query.filter_by(uuid=user_uuid).first()): 

15 return err_resp("User not found!", 404) 

16 

17 try: 

18 if (ExternalModel.query.filter_by(user_id=user.user_id, service_name="Spotify").first()) is None: 

19 resp = message(True, "Spotify oauth url sent") 

20 resp["spotify_url"] = Spotify.oauth_url(user) 

21 else: 

22 resp = message(True, "Spotify is already linked") 

23 resp["spotify_url"] = 'linked' 

24 return resp, 201 

25 except Exception as error: 

26 current_app.logger.error(error) 

27 return internal_err_resp() 

28 

29 @staticmethod 

30 def spotify_callback(csrf, code, user_uuid): 

31 """ Store Spotify access and refresh token """ 

32 if decode_token(csrf)['identity'] != user_uuid: 

33 return err_resp("CSRF invalid!", 404) 

34 if not (user := UserModel.query.filter_by(uuid=user_uuid).first()): 

35 return err_resp("User not found!", 404) 

36 # Check if the email is taken 

37 if ExternalModel.query.filter_by(user_id=user.user_id, service_name="Spotify").first() is not None: 

38 return validation_error(False, "Spotify Oauth is already done.") 

39 try: 

40 token_info = Spotify.get_tokens(code) 

41 

42 new_external = ExternalModel( 

43 service_name='Spotify', 

44 user_id=user.user_id, 

45 access_token=token_info['access_token'], 

46 refresh_token=token_info['refresh_token'] 

47 ) 

48 

49 db.session.add(new_external) 

50 db.session.flush() 

51 

52 # Commit changes to DB 

53 db.session.commit() 

54 

55 resp = message(True, "Spotify tokens stored") 

56 return resp, 201 

57 except Exception as error: 

58 current_app.logger.error(error) 

59 return internal_err_resp() 

60 

61 @staticmethod 

62 def get_spotify_data(user_uuid, app): 

63 """ Get spotify data : """ 

64 with app.app_context(): 

65 if not (user := UserModel.query.filter_by(uuid=user_uuid).first()): 

66 return err_resp("User not found!", 404) 

67 if not (external := ExternalModel.query.filter_by(user_id=user.user_id, service_name="Spotify").first()): 

68 return err_resp("External service not found!", 404) 

69 try: 

70 token_info = Spotify.refresh_token(external.refresh_token) 

71 if "access_token" not in token_info.keys(): 

72 ExternalModel.query.filter_by( 

73 user_id=user.user_id, service_name="Spotify").delete() 

74 db.session.commit() 

75 return err_resp("Spotify service oauth revoked!", 404) 

76 external.access_token = token_info['access_token'] 

77 

78 db.session.add(external) 

79 

80 db.session.commit() 

81 data = [] 

82 

83 data.append(Spotify.get_user_top_track(external.access_token)) 

84 data.append(Spotify.get_user_recently_played( 

85 external.access_token)) 

86 for item in Spotify.get_user_playlist(external.access_token): 

87 data.append(item['tracks']) 

88 

89 for d in data: 

90 for line in d: 

91 if TrackModel.query.filter_by(spotify_id=line['spotify_id']).first() is None: 

92 content = ContentModel(rating=None) 

93 db.session.add(content) 

94 db.session.flush() 

95 new_track = TrackModel( 

96 artist_name=line['artist_name'], 

97 title=line['title'], 

98 year=line['year'], 

99 release=line['release'], 

100 spotify_id=line['spotify_id'], 

101 covert_art_url=line['cover_art_url'], 

102 content=content 

103 ) 

104 db.session.add(new_track) 

105 db.session.flush() 

106 

107 db.session.commit() 

108 

109 for d in data: 

110 for line in d: 

111 track = TrackModel.query.filter_by( 

112 spotify_id=line['spotify_id']).first() 

113 if ((meta := MetaUserContentModel.query.filter_by(content_id=track.content_id).first()) is None): 

114 new_meta_user_track = MetaUserContentModel( 

115 user_id=user.user_id, 

116 content_id=track.content_id, 

117 play_count=1, 

118 last_played_date=line['played_at'] 

119 ) 

120 db.session.add(new_meta_user_track) 

121 db.session.flush() 

122 else: 

123 if ((line['played_at'] is not None) and ((meta.last_count_increment is None) or (line['played_at'] > meta.last_count_increment))): 

124 meta.last_count_increment = line['played_at'] 

125 db.session.commit() 

126 

127 except Exception as error: 

128 current_app.logger.error(error) 

129 return internal_err_resp() 

130 

131 @staticmethod 

132 def get_tmdb_oauth(user_uuid): 

133 """ Get TMDB oauth url """ 

134 if not (user := UserModel.query.filter_by(uuid=user_uuid).first()): 

135 return err_resp("User not found!", 404) 

136 

137 try: 

138 if (ExternalModel.query.filter_by(user_id=user.user_id, service_name="TMDB").first()) is None: 

139 resp = message(True, "TMDB oauth url sent") 

140 resp["tmdb_url"] = TMDB.oauth_url() 

141 else: 

142 resp = message(True, "TMDB is already linked") 

143 resp["tmdb_url"] = 'linked' 

144 return resp, 201 

145 except Exception as error: 

146 current_app.logger.error(error) 

147 return internal_err_resp() 

148 

149 @staticmethod 

150 def tmdb_callback(request_token, user_uuid): 

151 """ Store tmdb access """ 

152 if not (user := UserModel.query.filter_by(uuid=user_uuid).first()): 

153 return err_resp("User not found!", 404) 

154 # Check if the email is taken 

155 if ExternalModel.query.filter_by(user_id=user.user_id, service_name="TMDB").first() is not None: 

156 return validation_error(False, "tmdb Oauth is already done.") 

157 try: 

158 token_info = TMDB.get_tokens(request_token) 

159 

160 new_external = ExternalModel( 

161 service_name='TMDB', 

162 user_id=user.user_id, 

163 access_token=token_info['session_id'], 

164 ) 

165 

166 db.session.add(new_external) 

167 db.session.flush() 

168 

169 # Commit changes to DB 

170 db.session.commit() 

171 

172 resp = message(True, "TMDB token stored") 

173 return resp, 201 

174 except Exception as error: 

175 current_app.logger.error(error) 

176 return internal_err_resp() 

177 

178 @staticmethod 

179 def get_tmdb_data(user_uuid, app): 

180 """ Get tmdb data : """ 

181 with app.app_context(): 

182 if not (user := UserModel.query.filter_by(uuid=user_uuid).first()): 

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

184 if not (external := ExternalModel.query.filter_by(user_id=user.user_id, service_name="TMDB").first()): 

185 return err_resp("External service not found!", 404) 

186 try: 

187 token = external.access_token 

188 account_id = TMDB.get_account_id(token) 

189 if 'success' in account_id.keys(): 

190 ExternalModel.query.filter_by( 

191 user_id=user.user_id, service_name="TMDB").delete() 

192 db.session.commit() 

193 return err_resp("TMDB service oauth revoked!", 404) 

194 data = TMDB.get_created_list(token, account_id) 

195 movies = [] 

196 movies.append(TMDB.get_favorite_movies(token, account_id)) 

197 movies.append(TMDB.get_rated_movies(token, account_id)) 

198 movies.append(data['movies']) 

199 

200 series = [] 

201 series.append(TMDB.get_favorite_series(token, account_id)) 

202 series.append(TMDB.get_rated_series(token, account_id)) 

203 series.append(data['series']) 

204 

205 for movie in movies: 

206 for line in movie: 

207 if (movie_db := MovieModel.query.filter_by(imdbid=line['imdbid']).first()) is None: 

208 content = ContentModel(rating=None) 

209 db.session.add(content) 

210 db.session.flush() 

211 new_movie = MovieModel( 

212 title=line['title'], 

213 language=line['language'], 

214 actors=line['actors'], 

215 year=line['year'], 

216 producers=line['producers'], 

217 director=line['director'], 

218 writer=line['writer'], 

219 imdbid=line['imdbid'], 

220 tmdbid=line['tmdbid'], 

221 rating=line['rating'], 

222 rating_count=line['rating_count'], 

223 cover=line['cover'], 

224 content=content 

225 ) 

226 db.session.add(new_movie) 

227 db.session.flush() 

228 else: 

229 if line['rating'] != movie_db.rating: 

230 movie_db.rating = line['rating'] 

231 if line['rating_count'] != movie_db.rating_count: 

232 movie_db.rating_count = line['rating_count'] 

233 db.session.commit() 

234 

235 for movie in movies: 

236 for line in movie: 

237 ext_movie = MovieModel.query.filter_by( 

238 imdbid=line['imdbid']).first() 

239 if ((meta := MetaUserContentModel.query.filter_by(content_id=ext_movie.content_id).first()) is None): 

240 new_meta_user_track = MetaUserContentModel( 

241 user_id=user.user_id, 

242 content_id=ext_movie.content_id, 

243 rating=line['user_rating'] if "user_rating" in line.keys( 

244 ) else None, 

245 watch_count=1, 

246 review_see_count=1 

247 ) 

248 db.session.add(new_meta_user_track) 

249 db.session.flush() 

250 else: 

251 if line['rating'] != meta.rating: 

252 meta.rating = line['rating'] 

253 db.session.commit() 

254 

255 for serie in series: 

256 for line in serie: 

257 if (s := SerieModel.query.filter_by(title=line['title'], start_year=line['start_year']).first()) is None: 

258 content = ContentModel(rating=None) 

259 db.session.add(content) 

260 db.session.flush() 

261 new_serie = SerieModel( 

262 title=line['title'], 

263 actors=line['actors'], 

264 start_year=line['start_year'], 

265 end_year=line['end_year'], 

266 directors=line['directors'], 

267 writers=line['writers'], 

268 rating=line['rating'], 

269 rating_count=line['rating_count'], 

270 cover=line['cover'], 

271 content=content, 

272 ) 

273 db.session.add(new_serie) 

274 db.session.flush() 

275 else: 

276 if line['rating'] != s.rating: 

277 s.rating = line['rating'] 

278 if line['rating_count'] != s.rating_count: 

279 s.rating_count = line['rating_count'] 

280 db.session.commit() 

281 for serie in series: 

282 for line in serie: 

283 serie = SerieModel.query.filter_by( 

284 title=line['title'], start_year=line['start_year']).first() 

285 if ((serie_db := MetaUserContentModel.query.filter_by(serie_id=serie.serie_id).first()) is None): 

286 new_meta_user_track = MetaUserContentModel( 

287 user_id=user.user_id, 

288 content_id=serie.content_id, 

289 rating=line['user_rating'] if "user_rating" in line.keys( 

290 ) else None, 

291 review_see_count=1 

292 ) 

293 db.session.add(new_meta_user_track) 

294 db.session.flush() 

295 else: 

296 if line['rating'] != serie_db.rating: 

297 serie_db.rating != line['rating'] 

298 db.session.commit() 

299 except Exception as error: 

300 current_app.logger.error(error) 

301 return internal_err_resp() 

302 

303 @staticmethod 

304 def get_gbooks_oauth(user_uuid): 

305 """ Get GBooks oauth url """ 

306 if not (user := UserModel.query.filter_by(uuid=user_uuid).first()): 

307 return err_resp("User not found!", 404) 

308 

309 try: 

310 if (ExternalModel.query.filter_by(user_id=user.user_id, service_name="GBooks").first()) is None: 

311 resp = message(True, "GBooks oauth url sent") 

312 resp["gbooks_url"] = GBooks.oauth_url(user) 

313 else: 

314 resp = message(True, "GBooks is already linked") 

315 resp["gbooks_url"] = 'linked' 

316 return resp, 201 

317 except Exception as error: 

318 current_app.logger.error(error) 

319 return internal_err_resp() 

320 

321 @staticmethod 

322 def gbooks_callback(user_uuid, code, state): 

323 """ Store gbooks access """ 

324 if decode_token(state)['identity'] != user_uuid: 

325 return err_resp("CSRF invalid!", 404) 

326 if not (user := UserModel.query.filter_by(uuid=user_uuid).first()): 

327 return err_resp("User not found!", 404) 

328 

329 if ExternalModel.query.filter_by(user_id=user.user_id, service_name="GBooks").first() is not None: 

330 return validation_error(False, "gbooks Oauth is already done.") 

331 try: 

332 token_info = GBooks.get_token(code, state) 

333 

334 new_external = ExternalModel( 

335 service_name='GBooks', 

336 user_id=user.user_id, 

337 access_token=token_info['token'], 

338 refresh_token=token_info['refresh_token'] 

339 ) 

340 

341 db.session.add(new_external) 

342 db.session.flush() 

343 

344 # Commit changes to DB 

345 db.session.commit() 

346 

347 resp = message(True, "GBooks token stored") 

348 return resp, 201 

349 except Exception as error: 

350 current_app.logger.error(error) 

351 return internal_err_resp() 

352 

353 @staticmethod 

354 def get_gbooks_data(user_uuid, app): 

355 """ Get gbooks data : """ 

356 with app.app_context(): 

357 if not (user := UserModel.query.filter_by(uuid=user_uuid).first()): 

358 return err_resp("User not found!", 404) 

359 if not (external := ExternalModel.query.filter_by(user_id=user.user_id, service_name="GBooks").first()): 

360 return err_resp("External service not found!", 404) 

361 try: 

362 token = external.access_token 

363 refresh_token = external.refresh_token 

364 

365 books = GBooks.get_data(token, refresh_token) 

366 if books == "revoked": 

367 ExternalModel.query.filter_by( 

368 user_id=user.user_id, service_name="GBooks").delete() 

369 db.session.commit() 

370 return err_resp("Google Books service oauth revoked!", 404) 

371 

372 for line in books: 

373 if (book_db := BookModel.query.filter_by(isbn=line['isbn']).first()) is None: 

374 content = ContentModel(rating=None) 

375 db.session.add(content) 

376 db.session.flush() 

377 new_book = BookModel( 

378 isbn=line['isbn'], 

379 title=line['title'], 

380 author=line['author'], 

381 year_of_publication=line['year_of_publication'], 

382 publisher=line['publisher'], 

383 image_url_s=line['image_url_s'], 

384 image_url_m=line['image_url_m'], 

385 image_url_l=line['image_url_l'], 

386 rating=line['rating'], 

387 rating_count=line['rating_count'], 

388 content=content, 

389 ) 

390 db.session.add(new_book) 

391 db.session.flush() 

392 else: 

393 if line['rating'] != book_db.rating: 

394 book_db.rating = line['rating'] 

395 if line['rating_count'] != book_db.rating_count: 

396 book_db.rating_count = line['rating_count'] 

397 db.session.commit() 

398 

399 for line in books: 

400 if ((meta := MetaUserContentModel.query.filter_by(isbn=line['isbn']).first()) is None): 

401 new_meta_user_track = MetaUserContentModel( 

402 user_id=user.user_id, 

403 isbn=line['isbn'], 

404 rating=line['user_rating'], 

405 purchase=line['purchase'] 

406 ) 

407 db.session.add(new_meta_user_track) 

408 db.session.flush() 

409 else: 

410 if line['rating'] != meta.rating: 

411 meta.rating = line['rating'] 

412 if line['purchase'] != meta.purchase: 

413 meta.purchase = line['purchase'] 

414 db.session.commit() 

415 except Exception as error: 

416 current_app.logger.error(error) 

417 return internal_err_resp()