from urllib.parse import quote from api import models from api.resources import AuthenticatedResource from tracker import db from flask import request import json class ChartResource(AuthenticatedResource): other_query_args_url = {} def fetch_artists(self, src, artist_ids, include_alerts=False): use_cache_only = request.args.get('use_cache_only') refresh_cache = request.args.get('refresh_cache') if use_cache_only: self.other_query_args_url['use_cache_only'] = '1' if refresh_cache: self.other_query_args_url['refresh_cache'] = '1' artists = list(models.artists(src, artist_ids, include_alerts=include_alerts, use_cache_only=use_cache_only, refresh_cache=refresh_cache)) return artists def get(self): return self.post() @property def Session(self): if request.args.get('_rr'): return db.ROSession return db.Session defaults = { "publishedDaysAgo": 10, "minPlays": 10000, "isScouted": True, "maxFollowers": 999999, "countries": None, } def get_setting(self, name, default=None): if not request.get_data(): # get_json will fail on empty body, I don't want to return default d = request.json if name in d: return d[name] return default def get_filters(self, **defaults): these_defaults = dict(self.defaults, **defaults) if not request.get_data(): # get_json will fail on empty body, I don't want to return these_defaults return dict(these_defaults, **((request.json or {}).get("filters") or {})) def _make_extra_query_args(self): if not self.other_query_args_url: return '' return "&" + "&".join([f'{k}={quote(v)}' for k,v in self.other_query_args_url.items()]) def render_json(self, results_list, limit, offset): next_api = f"{request.path}?offset={offset + limit}{self._make_extra_query_args()}" if results_list else None return { "nextApi": next_api, "results": results_list, } def post(self): limit = int(request.args.get("limit") or 20) offset = int(request.args.get("offset") or "0") keys = self.user.db_user.hidden_artist_keyset query_results = self.get_results_list(self.get_filters(), self.user.name, limit, offset) # Remove hidden artists. if request.args.get('useMatrix'): if keys and query_results.get('matrix') and 'artistKey' in query_results.get('schema') or []: field_index = query_results['schema'].index('artistKey') query_results['matrix'] = [r for r in query_results['matrix'] if r[field_index] not in keys] return query_results elif keys: query_results = [ r for r in query_results if not r.get('artist') or keys.isdisjoint(r['artist'].get('keys') or []) ] return self.render_json(query_results, limit, offset) def get_results_list(self, filters, username, limit, offset): raise NotImplementedError from .charts import ( Analyzer, SpotifyEmerging, SoundCloudNewTracks, InstagramFollowerJump, MostScoutedRecently, SoundCloudLocation, SpotifyOlap, SpotifyOfficialChart, TikTokTrending) from .newtube import YouTubeNew from .curated import CuratedList from .scoutings import InstagramMyScoutings, SoundCloudMyScoutings class ChartRoot(AuthenticatedResource): def get(self): return {} class MyCharts(AuthenticatedResource): def put(self): charts = request.json['charts'] assert isinstance(charts, list) db.Session.execute( "update users set charts = (:charts)::jsonb where username = :username", params=dict(charts=json.dumps(charts), username=self.user.name) ) db.Session.commit() return db.Session.execute('select charts from users where username = :username', params=dict(username=self.user.name)).fetchone()[0] def register_urls(api, root="/api/charts"): api.add_resource( ChartRoot, root ) api.add_resource( MyCharts, root + '/my_charts' ) api.add_resource( SoundCloudNewTracks, root + "/soundcloud_new_tracks", root + "/SoundCloudNewTracks", ) api.add_resource( SoundCloudLocation, root + "/SoundCloudLocation", ) api.add_resource( InstagramFollowerJump, root + "/InstagramFollowerJump", ) api.add_resource( Analyzer, root + "/Analyzer", ) api.add_resource( InstagramMyScoutings, root + "/instagram_follower_jump", root + "/InstagramMyScoutings", ) # api.add_resource( # SpotifyEmerging, # root + "/SpotifyEmerging/", # root + "/SpotifyEmerging", # ) api.add_resource( SpotifyOlap, root + "/SpotifyOlap", root + "/SpotifyEmerging" ) api.add_resource( SpotifyOfficialChart, root + "/SpotifyOfficialChart", ) api.add_resource( CuratedList, root + "/curated/", ) api.add_resource( MostScoutedRecently, root + "/most_scouted_recently", root + "/MostScoutedRecently", ) api.add_resource( YouTubeNew, root + "/YouTubeNew", ) api.add_resource( SoundCloudMyScoutings, root + "/SoundCloudMyScoutings", ) api.add_resource( TikTokTrending, root + "/tiktok", )