def notify_yim_users():
    lb_logo_cid = make_msgid()
    with open("/static/img/listenbrainz-logo.png", "rb") as img:
        lb_logo = img.read()

    with db.engine.connect() as connection:
        result = connection.execute("""
            SELECT user_id
                 , musicbrainz_id
                 , email
              FROM statistics.year_in_music yim
              JOIN "user"
                ON "user".id = yim.user_id
        """)
        rows = result.fetchall()

    for row in rows:
        user_name = row["musicbrainz_id"]

        # cannot use url_for because we do not set SERVER_NAME and
        # a request_context will not be available in this script.
        base_url = "https://listenbrainz.org"
        year_in_music = f"{base_url}/user/{user_name}/year-in-music/"
        params = {
            "user_name": user_name,
            "year_in_music": year_in_music,
            "statistics": f"{base_url}/user/{user_name}/reports/",
            "feed": f"{base_url}/feed/",
            "feedback": f"{base_url}/user/{user_name}/feedback/",
            "pins": f"{base_url}/user/{user_name}/pins/",
            "playlists": f"{base_url}/user/{user_name}/playlists/",
            "collaborations": f"{base_url}/user/{user_name}/collaborations/",
            "lb_logo_cid": lb_logo_cid[1:-1]
        }

        try:
            send_mail(subject="Year In Music 2021",
                      text=render_template("emails/year_in_music.txt",
                                           **params),
                      to_email=row["email"],
                      to_name=user_name,
                      html=render_template("emails/year_in_music.html",
                                           **params),
                      lb_logo_cid=lb_logo_cid,
                      lb_logo=lb_logo)
        except Exception:
            current_app.logger.error("Could not send YIM email to %s",
                                     user_name,
                                     exc_info=True)

        # create timeline event too
        timeline_message = 'ListenBrainz\' very own retrospective on 2021 has just dropped: Check out ' \
                           f'your own <a href="{year_in_music}">Year in Music</a> now!'
        metadata = NotificationMetadata(creator="troi-bot",
                                        message=timeline_message)
        create_user_notification_event(row["user_id"], metadata)
Exemplo n.º 2
0
def create_user_notification_event(user_name):
    """ Post a message with a link on a user's timeline. Only approved users are allowed to perform this action.

    The request should contain the following data:

    .. code-block:: json

        {
            "metadata": {
                "message": <the message to post, required>,
            }
        }

    :param user_name: The MusicBrainz ID of the user on whose timeline the message is to be posted.
    :type user_name: ``str``
    :statuscode 200: Successful query, message has been posted!
    :statuscode 400: Bad request, check ``response['error']`` for more details.
    :statuscode 403: Forbidden, you are not an approved user.
    :statuscode 404: User not found
    :resheader Content-Type: *application/json*

    """
    creator = validate_auth_header()
    if creator["musicbrainz_id"] not in current_app.config[
            'APPROVED_PLAYLIST_BOTS']:
        raise APIForbidden(
            "Only approved users are allowed to post a message on a user's timeline."
        )

    user = db_user.get_by_mb_id(user_name)
    if user is None:
        raise APINotFound(f"Cannot find user: {user_name}")

    try:
        data = ujson.loads(request.get_data())['metadata']
    except (ValueError, KeyError) as e:
        raise APIBadRequest(f"Invalid JSON: {str(e)}")

    if "message" not in data:
        raise APIBadRequest("Invalid metadata: message is missing")

    message = _filter_description_html(data["message"])
    metadata = NotificationMetadata(creator=creator['musicbrainz_id'],
                                    message=message)

    try:
        db_user_timeline_event.create_user_notification_event(
            user['id'], metadata)
    except DatabaseException:
        raise APIInternalServerError("Something went wrong, please try again.")

    return jsonify({'status': 'ok'})
Exemplo n.º 3
0
 def test_create_user_notification_event(self):
     message = 'You have a <a href="https://listenbrainz.org/non-existent-playlist">playlist</a>'
     event = db_user_timeline_event.create_user_notification_event(
         user_id=self.user['id'],
         metadata=NotificationMetadata(
             creator=self.user['musicbrainz_id'],
             message=message,
         ))
     self.assertEqual(self.user['id'], event.user_id)
     self.assertEqual(message, event.metadata.message)
     self.assertEqual(self.user['musicbrainz_id'], event.metadata.creator)
     self.assertEqual(UserTimelineEventType.NOTIFICATION, event.event_type)
Exemplo n.º 4
0
    def test_delete_feed_events(self):
        # creating recording recommendation and checking
        event_rec = db_user_timeline_event.create_user_track_recommendation_event(
            user_id=self.user['id'],
            metadata=RecordingRecommendationMetadata(
                track_name="All Caps",
                artist_name="MF DOOM",
                recording_msid=str(uuid.uuid4()),
                artist_msid=str(uuid.uuid4()),
            ))
        self.assertEqual(UserTimelineEventType.RECORDING_RECOMMENDATION,
                         event_rec.event_type)
        self.assertEqual(self.user['id'], event_rec.user_id)

        # creating a new user for notification
        new_user = db_user.get_or_create(2, 'riksucks')
        message = 'You have a <a href="https://listenbrainz.org/non-existent-playlist">playlist</a>'
        event_not = db_user_timeline_event.create_user_notification_event(
            user_id=new_user['id'],
            metadata=NotificationMetadata(
                creator=new_user['musicbrainz_id'],
                message=message,
            ))
        self.assertEqual(new_user['id'], event_not.user_id)
        self.assertEqual(message, event_not.metadata.message)
        self.assertEqual(new_user['musicbrainz_id'],
                         event_not.metadata.creator)
        self.assertEqual(UserTimelineEventType.NOTIFICATION,
                         event_not.event_type)

        # deleting recording recommendation
        db_user_timeline_event.delete_user_timeline_event(
            id=event_rec.id,
            user_id=self.user["id"],
        )
        event_rec = db_user_timeline_event.get_user_notification_events(
            user_id=self.user["id"],
            count=1,
        )
        self.assertEqual(0, len(event_rec))

        # deleting notification
        db_user_timeline_event.delete_user_timeline_event(
            id=event_not.id,
            user_id=new_user["id"],
        )
        event_not = db_user_timeline_event.get_user_notification_events(
            user_id=new_user["id"],
            count=1,
        )
        self.assertEqual(0, len(event_not))