Ejemplo n.º 1
0
def get_podcast_episode(db: DatabaseHandler,
                        stories_id: int) -> PodcastEpisode:
    """
    Get podcast episode object for story ID.

    :param db: Database handler.
    :param stories_id: Story ID.
    :return: Podcast episode object.
    """
    try:
        podcast_episodes = db.select(
            table='podcast_episodes',
            what_to_select='*',
            condition_hash={
                'stories_id': stories_id
            },
        ).hashes()

    except Exception as ex:
        raise McPodcastDatabaseErrorException(
            f"Unable to fetch story's {stories_id} podcast episodes: {ex}")

    if not podcast_episodes:
        raise McPodcastNoEpisodesException(
            f"There are no podcast episodes for story {stories_id}")

    if len(podcast_episodes) > 1:
        # That's very weird, there should be only one episode per story
        raise McPodcastDatabaseErrorException(
            f"There's more than one podcast episode for story {stories_id}")

    try:
        episode = PodcastEpisode(stories_id=stories_id,
                                 db_row=podcast_episodes[0])
    except Exception as ex:
        raise McPodcastInvalidInputException(
            f"Invalid episode for story {stories_id}: {ex}")

    if episode.duration > MAX_DURATION:
        raise McPodcastEpisodeTooLongException(
            f"Story's {stories_id} podcast episode is too long ({episode.duration} seconds)."
        )

    return episode
Ejemplo n.º 2
0
    def update_tags_for_story(self, db: DatabaseHandler,
                              stories_id: int) -> None:
        """Add version, country and story tags for story."""

        # MC_REWRITE_TO_PYTHON: remove after rewrite to Python
        if isinstance(stories_id, bytes):
            stories_id = decode_object_from_bytes_if_needed(stories_id)

        stories_id = int(stories_id)

        annotation = self.__annotation_store.fetch_annotation_for_story(
            db=db, stories_id=stories_id)
        if annotation is None:
            raise McJSONAnnotationTaggerException(
                "Unable to fetch annotation for story %d" % stories_id)

        tags = None
        try:
            tags = self._tags_for_annotation(annotation)
        except Exception as ex:
            # Programming error (should at least return an empty list)
            fatal_error("Unable to fetch tags for story %d: %s" % (
                stories_id,
                str(ex),
            ))

        if tags is None:
            raise McJSONAnnotationTaggerException(
                "Returned tags is None for story %d." % stories_id)

        log.debug("Tags for story %d: %s" % (
            stories_id,
            str(tags),
        ))

        db.begin()

        unique_tag_sets_names = set()
        for tag in tags:
            tag_sets_name = self.__strip_linebreaks_and_whitespace(
                tag.tag_sets_name)
            unique_tag_sets_names.add(tag_sets_name)

        # Delete old tags the story might have under a given tag set
        db.query(
            """
            DELETE FROM stories_tags_map
            WHERE stories_id = %(stories_id)s
              AND tags_id IN (
                SELECT tags_id
                FROM tags
                WHERE tag_sets_id IN (
                  SELECT tag_sets_id
                  FROM tag_sets
                  WHERE name = ANY(%(tag_sets_names)s)
                )
              )
        """, {
                'stories_id': stories_id,
                'tag_sets_names': list(unique_tag_sets_names)
            })

        for tag in tags:
            tag_sets_name = self.__strip_linebreaks_and_whitespace(
                tag.tag_sets_name)
            tags_name = self.__strip_linebreaks_and_whitespace(tag.tags_name)

            # Not using find_or_create() because tag set / tag might already exist
            # with slightly different label / description

            # Find or create a tag set
            db_tag_set = db.select(table='tag_sets',
                                   what_to_select='*',
                                   condition_hash={
                                       'name': tag_sets_name
                                   }).hash()
            if db_tag_set is None:
                db.query(
                    """
                    INSERT INTO tag_sets (name, label, description)
                    VALUES (%(name)s, %(label)s, %(description)s)
                    ON CONFLICT (name) DO NOTHING
                """, {
                        'name': tag_sets_name,
                        'label': tag.tag_sets_label,
                        'description': tag.tag_sets_description
                    })
                db_tag_set = db.select(table='tag_sets',
                                       what_to_select='*',
                                       condition_hash={
                                           'name': tag_sets_name
                                       }).hash()
            tag_sets_id = int(db_tag_set['tag_sets_id'])

            # Find or create tag
            db_tag = db.select(table='tags',
                               what_to_select='*',
                               condition_hash={
                                   'tag_sets_id': tag_sets_id,
                                   'tag': tags_name,
                               }).hash()
            if db_tag is None:
                db.query(
                    """
                    INSERT INTO tags (tag_sets_id, tag, label, description)
                    VALUES (%(tag_sets_id)s, %(tag)s, %(label)s, %(description)s)
                    ON CONFLICT (tag, tag_sets_id) DO NOTHING
                """, {
                        'tag_sets_id': tag_sets_id,
                        'tag': tags_name,
                        'label': tag.tags_label,
                        'description': tag.tags_description,
                    })
                db_tag = db.select(table='tags',
                                   what_to_select='*',
                                   condition_hash={
                                       'tag_sets_id': tag_sets_id,
                                       'tag': tags_name,
                                   }).hash()
            tags_id = int(db_tag['tags_id'])

            # Assign story to tag (if no such mapping exists yet)
            #
            # (partitioned table's INSERT trigger will take care of conflicts)
            #
            # Not using db.create() because it tests last_inserted_id, and on duplicates there would be no such
            # "last_inserted_id" set.
            db.query(
                """
                INSERT INTO stories_tags_map (stories_id, tags_id)
                VALUES (%(stories_id)s, %(tags_id)s)
            """, {
                    'stories_id': stories_id,
                    'tags_id': tags_id,
                })

        db.commit()
Ejemplo n.º 3
0
    def update_tags_for_story(self, db: DatabaseHandler, stories_id: int) -> None:
        """Add version, country and story tags for story."""

        if not self.annotator_is_enabled():
            fatal_error("Annotator is not enabled in the configuration.")

        # MC_REWRITE_TO_PYTHON: remove after rewrite to Python
        if isinstance(stories_id, bytes):
            stories_id = decode_object_from_bytes_if_needed(stories_id)

        stories_id = int(stories_id)

        annotation = self.fetch_annotation_for_story(db=db, stories_id=stories_id)
        if annotation is None:
            raise McJSONAnnotatorException("Unable to fetch annotation for story %d" % stories_id)

        tags = None
        try:
            tags = self._tags_for_annotation(annotation)
        except Exception as ex:
            # Programming error (should at least return an empty list)
            fatal_error("Unable to fetch tags for story %d: %s" % (stories_id, str(ex),))

        if tags is None:
            raise McJSONAnnotatorException("Returned tags is None for story %d." % stories_id)

        log.debug("Tags for story %d: %s" % (stories_id, str(tags),))

        db.begin()

        unique_tag_sets_names = set()
        for tag in tags:
            tag_sets_name = self.__strip_linebreaks_and_whitespace(tag.tag_sets_name)
            unique_tag_sets_names.add(tag_sets_name)

        # Delete old tags the story might have under a given tag set
        db.query("""
            DELETE FROM stories_tags_map
            WHERE stories_id = %(stories_id)s
              AND tags_id IN (
                SELECT tags_id
                FROM tags
                WHERE tag_sets_id IN (
                  SELECT tag_sets_id
                  FROM tag_sets
                  WHERE name = ANY(%(tag_sets_names)s)
                )
              )
        """, {'stories_id': stories_id, 'tag_sets_names': list(unique_tag_sets_names)})

        for tag in tags:
            tag_sets_name = self.__strip_linebreaks_and_whitespace(tag.tag_sets_name)
            tags_name = self.__strip_linebreaks_and_whitespace(tag.tags_name)

            # Not using find_or_create() because tag set / tag might already exist
            # with slightly different label / description

            # Find or create a tag set
            db_tag_set = db.select(table='tag_sets', what_to_select='*', condition_hash={'name': tag_sets_name}).hash()
            if db_tag_set is None:
                db.query("""
                    INSERT INTO tag_sets (name, label, description)
                    VALUES (%(name)s, %(label)s, %(description)s)
                    ON CONFLICT (name) DO NOTHING
                """, {
                    'name': tag_sets_name,
                    'label': tag.tag_sets_label,
                    'description': tag.tag_sets_description
                })
                db_tag_set = db.select(table='tag_sets',
                                       what_to_select='*',
                                       condition_hash={'name': tag_sets_name}).hash()
            tag_sets_id = int(db_tag_set['tag_sets_id'])

            # Find or create tag
            db_tag = db.select(table='tags', what_to_select='*', condition_hash={
                'tag_sets_id': tag_sets_id,
                'tag': tags_name,
            }).hash()
            if db_tag is None:
                db.query("""
                    INSERT INTO tags (tag_sets_id, tag, label, description)
                    VALUES (%(tag_sets_id)s, %(tag)s, %(label)s, %(description)s)
                    ON CONFLICT (tag, tag_sets_id) DO NOTHING
                """, {
                    'tag_sets_id': tag_sets_id,
                    'tag': tags_name,
                    'label': tag.tags_label,
                    'description': tag.tags_description,
                })
                db_tag = db.select(table='tags', what_to_select='*', condition_hash={
                    'tag_sets_id': tag_sets_id,
                    'tag': tags_name,
                }).hash()
            tags_id = int(db_tag['tags_id'])

            # Assign story to tag (if no such mapping exists yet)
            # (partitioned table's INSERT trigger will take care of conflicts)
            #
            # db.create() can't be used here because:
            #
            # 1) Master table for partitioned table might not have a primary key itself, only the partitions do --
            #    FIXME maybe master tables should have primary keys? Or let's wait for when we move to PostgreSQL 10+.
            #
            # 2) Partitioned table's INSERT trigger doesn't return last_inserted_id which db.create() requires
            #    FIXME there might be a way for it to return the inserted row
            #
            db.query("""
                INSERT INTO stories_tags_map (stories_id, tags_id)
                VALUES (%(stories_id)s, %(tags_id)s)
            """, {
                'stories_id': stories_id,
                'tags_id': tags_id,
            })

        db.commit()
Ejemplo n.º 4
0
    def update_tags_for_story(self, db: DatabaseHandler,
                              stories_id: int) -> None:
        """Add version, country and story tags for story."""

        if not self.annotator_is_enabled():
            fatal_error("Annotator is not enabled in the configuration.")

        # MC_REWRITE_TO_PYTHON: remove after rewrite to Python
        if isinstance(stories_id, bytes):
            stories_id = decode_object_from_bytes_if_needed(stories_id)

        stories_id = int(stories_id)

        annotation = self.fetch_annotation_for_story(db=db,
                                                     stories_id=stories_id)
        if annotation is None:
            raise McJSONAnnotatorException(
                "Unable to fetch annotation for story %d" % stories_id)

        tags = None
        try:
            tags = self._tags_for_annotation(annotation)
        except Exception as ex:
            # Programming error (should at least return an empty list)
            fatal_error("Unable to fetch tags for story %d: %s" % (
                stories_id,
                str(ex),
            ))

        if tags is None:
            raise McJSONAnnotatorException(
                "Returned tags is None for story %d." % stories_id)

        log.debug("Tags for story %d: %s" % (
            stories_id,
            str(tags),
        ))

        db.begin()

        # Delete old tags the story might have under a given tag set
        for tag in tags:
            tag_sets_name = self.__strip_linebreaks_and_whitespace(
                tag.tag_sets_name)
            db.query(
                """
                DELETE FROM stories_tags_map
                    USING tags, tag_sets
                WHERE stories_tags_map.tags_id = tags.tags_id
                  AND tags.tag_sets_id = tag_sets.tag_sets_id
                  AND stories_tags_map.stories_id = %(stories_id)s
                  AND tag_sets.name = %(tag_sets_name)s
            """, {
                    'stories_id': stories_id,
                    'tag_sets_name': tag_sets_name
                })

        for tag in tags:
            tag_sets_name = self.__strip_linebreaks_and_whitespace(
                tag.tag_sets_name)
            tags_name = self.__strip_linebreaks_and_whitespace(tag.tags_name)

            # Not using find_or_create() because tag set / tag might already exist
            # with slightly different label / description

            # Create tag set
            db_tag_set = db.select(table='tag_sets',
                                   what_to_select='*',
                                   condition_hash={
                                       'name': tag_sets_name
                                   }).hash()
            if db_tag_set is None:
                db.query(
                    """
                    INSERT INTO tag_sets (name, label, description)
                    VALUES (%(name)s, %(label)s, %(description)s)
                    ON CONFLICT (name) DO NOTHING
                """, {
                        'name': tag_sets_name,
                        'label': tag.tag_sets_label,
                        'description': tag.tag_sets_description
                    })
                db_tag_set = db.select(table='tag_sets',
                                       what_to_select='*',
                                       condition_hash={
                                           'name': tag_sets_name
                                       }).hash()
            tag_sets_id = int(db_tag_set['tag_sets_id'])

            # Create tag
            db_tag = db.select(table='tags',
                               what_to_select='*',
                               condition_hash={
                                   'tag_sets_id': tag_sets_id,
                                   'tag': tags_name,
                               }).hash()
            if db_tag is None:
                db.query(
                    """
                    INSERT INTO tags (tag_sets_id, tag, label, description)
                    VALUES (%(tag_sets_id)s, %(tag)s, %(label)s, %(description)s)
                    ON CONFLICT (tag, tag_sets_id) DO NOTHING
                """, {
                        'tag_sets_id': tag_sets_id,
                        'tag': tags_name,
                        'label': tag.tags_label,
                        'description': tag.tags_description,
                    })
                db_tag = db.select(table='tags',
                                   what_to_select='*',
                                   condition_hash={
                                       'tag_sets_id': tag_sets_id,
                                       'tag': tags_name,
                                   }).hash()
            tags_id = int(db_tag['tags_id'])

            # Assign story to tag (if no such mapping exists yet)
            db.query(
                """
                INSERT INTO stories_tags_map (stories_id, tags_id)
                VALUES (%(stories_id)s, %(tags_id)s)
                ON CONFLICT (stories_id, tags_id) DO NOTHING
            """, {
                    'stories_id': stories_id,
                    'tags_id': tags_id,
                })

        db.commit()