Пример #1
0
def reset_latest_import_timestamp():
    form = FlaskForm()
    if form.validate_on_submit():
        try:
            listens_importer.update_latest_listened_at(
                current_user.id, ExternalServiceType.LASTFM, 0)
            flash.info(
                "Latest import time reset, we'll now import all your data instead of stopping at your last imported listen."
            )
        except DatabaseException:
            flash.error(
                "Something went wrong! Unable to reset latest import timestamp right now."
            )
        return redirect(url_for("profile.info"))

    if form.csrf_token.errors:
        flash.error(
            'Cannot reset import time due to error during authentication, please try again later.'
        )
        return redirect(url_for('profile.info'))

    return render_template(
        "profile/resetlatestimportts.html",
        form=form,
    )
Пример #2
0
 def test_update_latest_listened_at(self):
     spotify_user = db_spotify.get_user_import_details(self.user_id)
     self.assertIsNone(spotify_user['latest_listened_at'])
     self.assertIsNone(spotify_user['last_updated'])
     t = int(time.time())
     db_import.update_latest_listened_at(self.user_id, ExternalServiceType.SPOTIFY, t)
     spotify_user = db_spotify.get_user_import_details(self.user_id)
     self.assertEqual(t, int(spotify_user['latest_listened_at'].strftime('%s')))
     self.assertIsNotNone(spotify_user['last_updated'])
Пример #3
0
    def update_latest_listen_ts(self, user_id: int, timestamp: int):
        """ Update the latest_listened_at field for user with specified ListenBrainz user ID.

        Args:
            user_id (int): the ListenBrainz row ID of the user
            timestamp (int): the unix timestamp of the latest listen imported for the user
        """
        listens_importer.update_latest_listened_at(user_id, self.service,
                                                   timestamp)
Пример #4
0
def delete_listens_history(user_id: int):
    """ Delete a user's listens from ListenBrainz completely.

    Args:
        user_id: the LB row ID of the user
    """
    timescale_connection._ts.delete(user_id)
    listens_importer.update_latest_listened_at(user_id,
                                               ExternalServiceType.LASTFM, 0)
    db_stats.delete_user_stats(user_id)
Пример #5
0
    def test_update_latest_import(self):
        user = db_user.get_or_create(3, 'updatelatestimportuser')

        val = int(time.time())
        listens_importer.update_latest_listened_at(user['id'], ExternalServiceType.LASTFM, val)
        ts = listens_importer.get_latest_listened_at(user['id'], ExternalServiceType.LASTFM)
        self.assertEqual(int(ts.strftime('%s')), val)

        listens_importer.update_latest_listened_at(user['id'], ExternalServiceType.LASTFM, 0)
        ts = listens_importer.get_latest_listened_at(user['id'], ExternalServiceType.LASTFM)
        self.assertEqual(int(ts.strftime('%s')), 0)
Пример #6
0
def delete_listens_history(musicbrainz_id):
    """ Delete a user's listens from ListenBrainz completely.
    Args:
        musicbrainz_id (str): the MusicBrainz ID of the user
    Raises:
        NotFound if user isn't present in the database
    """

    user = _get_user(musicbrainz_id)
    timescale_connection._ts.delete(user.musicbrainz_id)
    timescale_connection._ts.reset_listen_count(user.musicbrainz_id)
    listens_importer.update_latest_listened_at(user.id,
                                               ExternalServiceType.LASTFM, 0)
    db_stats.delete_user_stats(user.id)
Пример #7
0
    def test_reset_import_timestamp(self):
        # we do a get request first to put the CSRF token in the flask global context
        # so that we can access it for using in the post request in the next step
        val = int(time.time())
        listens_importer.update_latest_listened_at(self.user['id'], ExternalServiceType.LASTFM, val)
        self.temporary_login(self.user['login_id'])
        response = self.client.get(url_for('profile.reset_latest_import_timestamp'))
        self.assertTemplateUsed('profile/resetlatestimportts.html')
        self.assert200(response)

        response = self.client.post(
            url_for('profile.reset_latest_import_timestamp'),
            data={'csrf_token': g.csrf_token}
        )
        self.assertStatus(response, 302)  # should have redirected to the info page
        self.assertRedirects(response, url_for('profile.info'))
        ts = listens_importer.get_latest_listened_at(self.user['id'], ExternalServiceType.LASTFM)
        self.assertEqual(int(ts.strftime('%s')), 0)
Пример #8
0
    def test_get_active_users_to_process(self):
        db_user.create(2, 'newspotifyuser')
        db_oauth.save_token(
            user_id=2,
            service=ExternalServiceType.SPOTIFY,
            access_token='token',
            refresh_token='refresh_token',
            token_expires_ts=int(time.time()),
            record_listens=True,
            scopes=['user-read-recently-played']
        )
        users = db_spotify.get_active_users_to_process()
        self.assertEqual(len(users), 2)
        self.assertEqual(users[0]['user_id'], 1)
        self.assertEqual(users[0]['musicbrainz_row_id'], 1)
        self.assertEqual(users[1]['user_id'], 2)
        self.assertEqual(users[1]['musicbrainz_row_id'], 2)

        # check order, the users should be sorted by latest_listened_at timestamp
        db_user.create(3, 'newnewspotifyuser')
        db_oauth.save_token(
            user_id=3,
            service=ExternalServiceType.SPOTIFY,
            access_token='tokentoken',
            refresh_token='newrefresh_token',
            token_expires_ts=int(time.time()),
            record_listens=True,
            scopes=['user-read-recently-played']
        )
        t = int(time.time())
        db_import.update_latest_listened_at(2, ExternalServiceType.SPOTIFY, t + 20)
        db_import.update_latest_listened_at(1, ExternalServiceType.SPOTIFY, t + 10)
        users = db_spotify.get_active_users_to_process()
        self.assertEqual(len(users), 3)
        self.assertEqual(users[0]['user_id'], 2)
        self.assertEqual(users[1]['user_id'], 1)
        self.assertEqual(users[2]['user_id'], 3)

        db_import.update_import_status(2, ExternalServiceType.SPOTIFY, 'something broke')
        db_import.update_import_status(3, ExternalServiceType.SPOTIFY, 'oops.')
        users = db_spotify.get_active_users_to_process()
        self.assertEqual(len(users), 1)
        self.assertEqual(users[0]['user_id'], 1)
Пример #9
0
def latest_import():
    """
    Get and update the timestamp of the newest listen submitted in previous imports to ListenBrainz.

    In order to get the timestamp for a user, make a GET request to this endpoint. The data returned will
    be JSON of the following format:

    .. code-block:: json

        {
            "musicbrainz_id": "the MusicBrainz ID of the user",
            "latest_import": "the timestamp of the newest listen submitted in previous imports. Defaults to 0"
        }

    :param user_name: the MusicBrainz ID of the user whose data is needed
    :type user_name: ``str``
    :statuscode 200: Yay, you have data!
    :resheader Content-Type: *application/json*

    In order to update the timestamp of a user, you'll have to provide a user token in the Authorization
    Header. User tokens can be found on https://listenbrainz.org/profile/ .

    The JSON that needs to be posted must contain a field named `ts` in the root with a valid unix timestamp.

    :reqheader Authorization: Token <user token>
    :reqheader Content-Type: *application/json*
    :statuscode 200: latest import timestamp updated
    :statuscode 400: invalid JSON sent, see error message for details.
    :statuscode 401: invalid authorization. See error message for details.
    :statuscode 404: user or service not found. See error message for details.
    """
    if request.method == 'GET':
        user_name = request.args.get('user_name', '')
        service_name = request.args.get('service', 'lastfm')
        try:
            service = ExternalServiceType[service_name.upper()]
        except KeyError:
            raise APINotFound(
                "Service does not exist: {}".format(service_name))
        user = db_user.get_by_mb_id(user_name)
        if user is None:
            raise APINotFound(
                "Cannot find user: {user_name}".format(user_name=user_name))
        latest_import_ts = listens_importer.get_latest_listened_at(
            user["id"], service)
        return jsonify({
            'musicbrainz_id':
            user['musicbrainz_id'],
            'latest_import':
            0 if not latest_import_ts else int(latest_import_ts.strftime('%s'))
        })
    elif request.method == 'POST':
        user = validate_auth_header()

        try:
            data = ujson.loads(request.get_data())
            ts = int(data.get('ts', 0))
            service_name = data.get('service', 'lastfm')
            service = ExternalServiceType[service_name.upper()]
        except (ValueError, KeyError):
            raise APIBadRequest('Invalid data sent')

        try:
            last_import_ts = listens_importer.get_latest_listened_at(
                user["id"], service)
            last_import_ts = 0 if not last_import_ts else int(
                last_import_ts.strftime('%s'))
            if ts > last_import_ts:
                listens_importer.update_latest_listened_at(
                    user["id"], service, ts)
        except DatabaseException:
            current_app.logger.error("Error while updating latest import: ",
                                     exc_info=True)
            raise APIInternalServerError(
                'Could not update latest_import, try again')

        # During unrelated tests _ts may be None -- improving this would be a great headache.
        # However, during the test of this code and while serving requests _ts is set.
        if _ts:
            _ts.set_listen_count_expiry_for_user(user['musicbrainz_id'])

        return jsonify({'status': 'ok'})