# Path: fimfarchive/exceptions.py
# class InvalidStoryError(FimfarchiveError):
#     """
#     Story does not exist.
#     """
# 
# Path: fimfarchive/flavors.py
# class UpdateStatus(Flavor):
#     """
#     Indicates if and how a story has changed.
#     """
#     CREATED = ()
#     REVIVED = ()
#     UPDATED = ()
#     DELETED = ()
# 
# Path: fimfarchive/mappers.py
# class StoryDateMapper(Mapper[Optional[Arrow]]):
#     """
#     Returns the latest timestamp in a story, or None.
#     """
# 
#     def __call__(self, story: Story) -> Optional[Arrow]:
#         try:
#             meta = getattr(story, 'meta', None)
#         except InvalidStoryError:
#             return None
# 
#         if not meta:
#             return None
# 
#         dates = {
#             meta.get('date_modified'),
#         }
# 
#         for chapter in meta.get('chapters') or tuple():
#             dates.add(chapter.get('date_modified'))
# 
#         dates.discard(None)
# 
#         if dates:
#             return max(arrow.get(date) for date in dates)
#         else:
#             return None


from fimfarchive.exceptions import InvalidStoryError
from fimfarchive.flavors import UpdateStatus
from fimfarchive.mappers import StoryDateMapper
            raise ValueError("Missing new date.")
        elif old_date < new_date:
            return new
        else:
            return None

    def flavored(self, story, *flavors):
        """
        Returns the story after applying the specified flavors.
        """
        story.flavors.update(flavors)

        return story

    def __call__(self, old, new):
        old = self.filter_empty(old)
        new = self.filter_empty(new)
        deleted = old and not new

        if old:
            old = self.filter_invalid(old)

        if old and new:
            new = self.filter_unchanged(old, new)

        if new:
            new = self.filter_invalid(new)
            deleted = old and not new

        if not old and new:

# Path: fimfarchive/exceptions.py
# class InvalidStoryError(FimfarchiveError):
#     """
#     Story does not exist.
#     """
# 
# Path: fimfarchive/flavors.py
# class UpdateStatus(Flavor):
#     """
#     Indicates if and how a story has changed.
#     """
#     CREATED = ()
#     REVIVED = ()
#     UPDATED = ()
#     DELETED = ()
# 
# Path: fimfarchive/mappers.py
# class StoryDateMapper(Mapper[Optional[Arrow]]):
#     """
#     Returns the latest timestamp in a story, or None.
#     """
# 
#     def __call__(self, story: Story) -> Optional[Arrow]:
#         try:
#             meta = getattr(story, 'meta', None)
#         except InvalidStoryError:
#             return None
# 
#         if not meta:
#             return None
# 
#         dates = {
#             meta.get('date_modified'),
#         }
# 
#         for chapter in meta.get('chapters') or tuple():
#             dates.add(chapter.get('date_modified'))
# 
#         dates.discard(None)
# 
#         if dates:
#             return max(arrow.get(date) for date in dates)
#         else:
#             return None


# Path: fimfarchive/selectors.py
from fimfarchive.exceptions import InvalidStoryError
from fimfarchive.flavors import UpdateStatus
from fimfarchive.mappers import StoryDateMapper

            raise ValueError("Missing new date.")
        elif old_date < new_date:
            return new
        else:
            return None

    def flavored(self, story, *flavors):
        """
        Returns the story after applying the specified flavors.
        """
        story.flavors.update(flavors)

        return story

    def __call__(self, old, new):
        old = self.filter_empty(old)
        new = self.filter_empty(new)
        deleted = old and not new

        if old:
            old = self.filter_invalid(old)

        if old and new:
            new = self.filter_unchanged(old, new)

        if new:
            new = self.filter_invalid(new)
            deleted = old and not new

        if not old and new:

            return self.flavored(new, UpdateStatus.CREATED)