def pins(user_name: str): """ Show user pin history """ user = _get_user(user_name) user_data = { "name": user.musicbrainz_id, "id": user.id, } pins = get_pin_history_for_user(user_id=user.id, count=25, offset=0) pins = [dict(pin) for pin in fetch_track_metadata_for_items(pins)] total_count = get_pin_count_for_user(user_id=user.id) props = { "user": user_data, "pins": pins, "profile_url": url_for('user.profile', user_name=user_name), "total_count": total_count, "logged_in_user_follows_user": logged_in_user_follows_user(user), } return render_template("user/pins.html", active_section="pins", props=ujson.dumps(props), user=user)
def test_unpin(self): pinned = self.pin_single_sample(self.user["id"], 0) db_pinned_rec.unpin(self.user["id"]) self.assertIsNone(db_pinned_rec.get_current_pin_for_user(self.user["id"])) # test that the pinned_until value was updated unpinned = db_pinned_rec.get_pin_history_for_user(user_id=self.user["id"], count=50, offset=0)[0] self.assertGreater(pinned.pinned_until, unpinned.pinned_until)
def test_get_current_pin_for_user(self): self.pin_single_sample(self.user["id"], 0) expected_pinned = db_pinned_rec.get_current_pin_for_user(self.user["id"]) recieved_pinned = db_pinned_rec.get_pin_history_for_user(user_id=self.user["id"], count=50, offset=0)[0] self.assertEqual(recieved_pinned, expected_pinned) self.pin_single_sample(self.user["id"], 1) expected_pinned = db_pinned_rec.get_current_pin_for_user(self.user["id"]) recieved_pinned = db_pinned_rec.get_current_pin_for_user(self.user["id"]) self.assertEqual(recieved_pinned, expected_pinned)
def test_delete(self): keptIndex = 0 # insert two records and delete the newer one self.pin_single_sample(self.user["id"], keptIndex) self.pin_single_sample(self.user["id"], 1) old_pin_history = db_pinned_rec.get_pin_history_for_user(user_id=self.user["id"], count=50, offset=0) pin_to_delete = old_pin_history[0] db_pinned_rec.delete(pin_to_delete.row_id, self.user["id"]) # test that only the older pin remained in the database pin_history = db_pinned_rec.get_pin_history_for_user(user_id=self.user["id"], count=50, offset=0) pin_remaining = pin_history[0] self.assertEqual(len(pin_history), len(old_pin_history) - 1) self.assertEqual(pin_remaining.blurb_content, self.pinned_rec_samples[keptIndex]["blurb_content"]) # delete the remaining pin db_pinned_rec.delete(pin_remaining.row_id, self.user["id"]) pin_history = db_pinned_rec.get_pin_history_for_user(user_id=self.user["id"], count=50, offset=0) self.assertFalse(pin_history)
def test_get_pins_for_user_following(self): # user follows followed_user_1 db_user_relationship.insert(self.user["id"], self.followed_user_1["id"], "follow") self.assertTrue( db_user_relationship.is_following_user(self.user["id"], self.followed_user_1["id"])) # test that followed_pins contains followed_user_1's pinned recording self.pin_single_sample(self.followed_user_1["id"], 0) followed_pins = db_pinned_rec.get_pins_for_user_following(user_id=1, count=50, offset=0) self.assertEqual(len(followed_pins), 1) self.assertEqual(followed_pins[0].user_name, "followed_user_1") # test that pins from users that the user is not following are not included self.pin_single_sample(self.followed_user_2["id"], 0) self.assertEqual(len(followed_pins), 1) # test that followed_user_2's pin is included after user follows db_user_relationship.insert(self.user["id"], self.followed_user_2["id"], "follow") followed_pins = db_pinned_rec.get_pins_for_user_following(user_id=1, count=50, offset=0) self.assertEqual(len(followed_pins), 2) self.assertEqual(followed_pins[0].user_name, "followed_user_2") # test that list is returned in descending order of creation date self.assertGreater(followed_pins[0].created, followed_pins[1].created) self.assertEqual(followed_pins[1].user_name, "followed_user_1") # test the limit argument limit = 1 limited_following_pins = db_pinned_rec.get_pins_for_user_following( user_id=self.user["id"], count=limit, offset=0) self.assertEqual(len(limited_following_pins), limit) limit = 999 limited_following_pins = db_pinned_rec.get_pins_for_user_following( user_id=self.user["id"], count=limit, offset=0) self.assertEqual(len(limited_following_pins), 2) # test the offset argument offset = 1 offset_following_pins = db_pinned_rec.get_pins_for_user_following( user_id=self.user["id"], count=50, offset=offset) self.assertEqual(len(offset_following_pins), 2 - offset) offset = 999 offset_following_pins = db_pinned_rec.get_pin_history_for_user( user_id=self.user["id"], count=50, offset=offset) self.assertFalse(offset_following_pins)
def test_get_pin_history_for_user(self): count = 4 self.insert_test_data(self.user["id"], count) # test that pin history includes unpinned recordings pin_history = db_pinned_rec.get_pin_history_for_user(user_id=self.user["id"], count=50, offset=0) db_pinned_rec.unpin(user_id=self.user["id"]) new_pin_history = db_pinned_rec.get_pin_history_for_user(user_id=self.user["id"], count=50, offset=0) self.assertEqual(len(new_pin_history), len(pin_history)) # test that the list was returned in descending order of creation date self.assertGreater(pin_history[0].created, pin_history[1].created) # test the limit argument limit = 1 limited_pin_history = db_pinned_rec.get_pin_history_for_user(user_id=self.user["id"], count=limit, offset=0) self.assertEqual(len(limited_pin_history), limit) limit = 999 limited_pin_history = db_pinned_rec.get_pin_history_for_user(user_id=self.user["id"], count=limit, offset=0) self.assertEqual(len(limited_pin_history), count) # test the offset argument offset = 1 offset_pin_history = db_pinned_rec.get_pin_history_for_user(user_id=self.user["id"], count=50, offset=offset) self.assertEqual(len(offset_pin_history), count - offset) offset = 999 offset_pin_history = db_pinned_rec.get_pin_history_for_user(user_id=self.user["id"], count=50, offset=offset) self.assertFalse(offset_pin_history)
def test_unpin_if_active_currently_pinned(self): original_pinned = self.pin_single_sample(self.user["id"], 0) new_pinned = self.pin_single_sample(self.user["id"], 1) original_unpinned = db_pinned_rec.get_pin_history_for_user(user_id=self.user["id"], count=50, offset=0)[1] # only the pinned_until value of the record should be updated self.assertEqual(original_unpinned.user_id, original_pinned.user_id) self.assertEqual(original_unpinned.recording_msid, original_pinned.recording_msid) self.assertEqual(original_unpinned.recording_mbid, original_pinned.recording_mbid) self.assertEqual(original_unpinned.blurb_content, original_pinned.blurb_content) self.assertEqual(original_unpinned.created, original_pinned.created) self.assertLess(original_unpinned.pinned_until, original_pinned.pinned_until) self.assertNotEqual(new_pinned, original_pinned)
def test_get_pin_count_for_user(self): self.insert_test_data(self.user["id"]) pin_history = db_pinned_rec.get_pin_history_for_user(user_id=self.user["id"], count=50, offset=0) pin_count = db_pinned_rec.get_pin_count_for_user(user_id=self.user["id"]) self.assertEqual(pin_count, len(pin_history)) # test that pin_count includes unpinned recordings db_pinned_rec.unpin(user_id=self.user["id"]) pin_count = db_pinned_rec.get_pin_count_for_user(user_id=self.user["id"]) self.assertEqual(pin_count, len(pin_history)) # test that pin_count excludes deleted recordings pin_to_delete = pin_history[1] db_pinned_rec.delete(pin_to_delete.row_id, self.user["id"]) pin_count = db_pinned_rec.get_pin_count_for_user(user_id=self.user["id"]) self.assertEqual(pin_count, len(pin_history) - 1)
def get_pins_for_user(user_name): """ Get a list of all recordings ever pinned by a user with given ``user_name`` in descending order of the time they were originally pinned. The JSON returned by the API will look like the following: .. code-block:: json { "count": 10, "offset": 0, "pinned_recordings": [ { "blurb_content": "Awesome recording!", "created": 1623997168, "row_id": 10, "pinned_until": 1623997485, "recording_mbid": null, "recording_msid": "fd7d9162-a284-4a10-906c-faae4f1e166b" "track_metadata": { "artist_msid": "8c7b4641-e363-4598-ae70-7709840fb934", "artist_name": "Rick Astley", "track_name": "Never Gonna Give You Up" } }, "-- more pinned recording items here ---" ], "total_count": 10, "user_name": "-- the MusicBrainz ID of the user --" } :param user_name: the MusicBrainz ID of the user whose pin track history requested. :type user_name: ``str`` :param count: Optional, number of pinned recording items to return, Default: :data:`~webserver.views.api.DEFAULT_ITEMS_PER_GET` Max: :data:`~webserver.views.api.MAX_ITEMS_PER_GET` :type count: ``int`` :param offset: Optional, number of pinned recording items to skip from the beginning, for pagination. Ex. An offset of 5 means the most recent 5 pinned recordings from the user will be skipped, defaults to 0 :type offset: ``int`` :statuscode 200: Yay, you have data! :statuscode 400: Invalid query parameters. See error message for details. :statuscode 404: The requested user was not found. :resheader Content-Type: *application/json* """ offset = get_non_negative_param("offset", default=0) count = get_non_negative_param("count", default=DEFAULT_ITEMS_PER_GET) count = min(count, MAX_ITEMS_PER_GET) user = db_user.get_by_mb_id(user_name) if user is None: raise APINotFound("Cannot find user: %s" % user_name) try: pinned_recordings = db_pinned_rec.get_pin_history_for_user( user_id=user["id"], count=count, offset=offset) except Exception as e: current_app.logger.error( "Error while retrieving pins for user: {}".format(e)) raise APIInternalServerError("Something went wrong. Please try again.") pinned_recordings = fetch_track_metadata_for_pins(pinned_recordings) pinned_recordings = [ _pinned_recording_to_api(pin) for pin in pinned_recordings ] total_count = db_pinned_rec.get_pin_count_for_user(user_id=user["id"]) return jsonify({ "pinned_recordings": pinned_recordings, "total_count": total_count, "count": len(pinned_recordings), "offset": offset, "user_name": user_name, })
def test_pin(self): count = self.insert_test_data(self.user["id"]) pin_history = db_pinned_rec.get_pin_history_for_user(user_id=self.user["id"], count=50, offset=0) self.assertEqual(len(pin_history), count)
def test_pinned_recording_with_metadata(self): recordings = [{ "title": "Strangers", "artist": "Portishead", "release": "Dummy" }, { "title": "Wicked Game", "artist": "Tom Ellis", "release": "Lucifer" }] submitted_data = msb_db.insert_all_in_transaction(recordings) msids = [x["ids"]["recording_msid"] for x in submitted_data] with ts.engine.connect() as connection: query = """ INSERT INTO mbid_mapping_metadata (recording_mbid, release_mbid, release_name, artist_credit_id, artist_mbids, artist_credit_name, recording_name) VALUES ('076255b4-1575-11ec-ac84-135bf6a670e3', '1fd178b4-1575-11ec-b98a-d72392cd8c97', 'Dummy', 65, '{6a221fda-2200-11ec-ac7d-dfa16a57158f}'::UUID[], 'Portishead', 'Strangers') """ connection.execute(sqlalchemy.text(query)) query = """INSERT INTO mbid_mapping (recording_msid, recording_mbid, match_type, last_updated) VALUES (:msid, '076255b4-1575-11ec-ac84-135bf6a670e3', 'exact_match', now())""" connection.execute(sqlalchemy.text(query), msid=msids[0]) pinned_recs = [{ "recording_msid": msids[0], "recording_mbid": "076255b4-1575-11ec-ac84-135bf6a670e3", "blurb_content": "Awesome recordings with mapped data" }, { "recording_msid": msids[1], "recording_mbid": None, "blurb_content": "Great recording but unmapped" }] for data in pinned_recs: db_pinned_rec.pin( WritablePinnedRecording( user_id=self.user["id"], recording_msid=data["recording_msid"], recording_mbid=data["recording_mbid"], blurb_content=data["blurb_content"], )) pins = db_pinned_rec.get_pin_history_for_user(self.user["id"], 5, 0) pins_with_metadata = fetch_track_metadata_for_items(pins) received = [x.dict() for x in pins_with_metadata] # pinned recs returned in reverse order of submitted because order newest to oldest self.assertEqual(received[0]["recording_msid"], pinned_recs[1]["recording_msid"]) self.assertEqual(received[0]["recording_mbid"], pinned_recs[1]["recording_mbid"]) self.assertEqual(received[0]["blurb_content"], pinned_recs[1]["blurb_content"]) self.assertEqual( received[0]["track_metadata"], { "track_name": "Wicked Game", "artist_name": "Tom Ellis", "additional_info": { "recording_msid": msids[1] } }) self.assertEqual(received[1]["recording_msid"], pinned_recs[0]["recording_msid"]) self.assertEqual(received[1]["recording_mbid"], pinned_recs[0]["recording_mbid"]) self.assertEqual(received[1]["blurb_content"], pinned_recs[0]["blurb_content"]) self.assertEqual( received[1]["track_metadata"], { "track_name": "Strangers", "artist_name": "Portishead", "release_name": "Dummy", "additional_info": { "recording_mbid": "076255b4-1575-11ec-ac84-135bf6a670e3", "release_mbid": "1fd178b4-1575-11ec-b98a-d72392cd8c97", "artist_mbids": ["6a221fda-2200-11ec-ac7d-dfa16a57158f"], "recording_msid": msids[0] } })