async def test_start_event_from_db(
    mock_mobilizon_success_answer,
    mobilizon_answer,
    caplog,
    mock_publisher_config,
    message_collector,
    event_generator,
):
    event = event_generator()
    event_model = event_to_model(event)
    await event_model.save()

    with caplog.at_level(DEBUG):
        # calling the start command
        assert await start() is not None

        # since the db contains at least one event, this has to be picked and published
        assert "Event to publish found" in caplog.text
        assert message_collector == [
            "test event|description of the event",
        ]

        await event_model.fetch_related("publications",
                                        "publications__publisher")
        # it should create a publication for each publisher
        publications = event_model.publications
        assert len(publications) == 1, publications

        # all the publications for the first event should be saved as COMPLETED
        for p in publications:
            assert p.status == PublicationStatus.COMPLETED

        # the derived status for the event should be COMPLETED
        assert event_from_model(
            event_model).status == EventPublicationStatus.COMPLETED
async def events_without_publications(
    from_date: Optional[Arrow] = None,
    to_date: Optional[Arrow] = None,
) -> list[MobilizonEvent]:
    query = Event.filter(publications__id=None)
    events = await prefetch_event_relations(
        _add_date_window(query, "begin_datetime", from_date, to_date))
    return [event_from_model(event) for event in events]
async def get_all_events(
    from_date: Optional[Arrow] = None,
    to_date: Optional[Arrow] = None,
) -> list[MobilizonEvent]:
    return [
        event_from_model(event) for event in await prefetch_event_relations(
            _add_date_window(Event.all(), "begin_datetime", from_date, to_date)
        )
    ]
async def format_event(event_id, publisher_name: str):
    event = await Event.get_or_none(
        mobilizon_id=event_id).prefetch_related("publications__publisher")
    if not event:
        click.echo(f"Event with mobilizon_id {event_id} not found.")
        return
    event = event_from_model(event)
    message = get_formatter_class(publisher_name)().get_message_from_event(
        event)
    click.echo(message)
async def get_publication(publication_id):
    try:
        publication = await prefetch_publication_relations(
            Publication.get(id=publication_id).first())
        # TODO: this is redundant but there's some prefetch problem otherwise
        publication.event = await get_event(publication.event.mobilizon_id)
        return publication_from_orm(event=event_from_model(publication.event),
                                    model=publication)
    except DoesNotExist:
        return None
async def get_failed_publications_for_event(
    event_mobilizon_id: UUID, ) -> list[EventPublication]:
    event = await get_event(event_mobilizon_id)
    failed_publications = list(
        filter(
            lambda publications: publications.status == PublicationStatus.
            FAILED,
            event.publications,
        ))
    for p in failed_publications:
        await p.fetch_related("publisher")
    mobilizon_event = event_from_model(event)
    return list(
        map(partial(publication_from_orm, event=mobilizon_event),
            failed_publications))
async def test_mobilizon_event_from_model(event_model_generator,
                                          publication_model_generator,
                                          publisher_model_generator):
    event_model = event_model_generator()
    await event_model.save()

    publisher_model = publisher_model_generator()
    await publisher_model.save()
    publisher_model_2 = publisher_model_generator(idx=2)
    await publisher_model_2.save()

    publication = publication_model_generator(
        status=PublicationStatus.FAILED,
        event_id=event_model.id,
        publisher_id=publisher_model.id,
    )
    await publication.save()
    publication_2 = publication_model_generator(
        status=PublicationStatus.COMPLETED,
        event_id=event_model.id,
        publisher_id=publisher_model_2.id,
    )
    await publication_2.save()

    event_db = (await Event.all().prefetch_related(
        "publications").prefetch_related("publications__publisher").first())
    event = event_from_model(event=event_db)

    begin_date_utc = arrow.Arrow(year=2021, month=1, day=1, hour=11, minute=30)

    assert event.name == "event_1"
    assert event.description == "desc_1"
    assert event.begin_datetime == begin_date_utc
    assert event.end_datetime == begin_date_utc.shift(hours=2)
    assert event.mobilizon_link == "moblink_1"
    assert event.mobilizon_id == UUID(int=1)
    assert event.thumbnail_link == "thumblink_1"
    assert event.location == ", loc_1, "
    assert event.publication_time[
        publisher_model.name] == publication.timestamp
    assert event.status == EventPublicationStatus.PARTIAL
async def test_start_new_event(
    mock_mobilizon_success_answer,
    mobilizon_answer,
    caplog,
    mock_publisher_config,
    message_collector,
    elements,
):
    with caplog.at_level(DEBUG):
        # calling the start command
        assert await start() is not None

        # since the mobilizon_answer contains at least one result, one event to publish must be found and published
        # by the publisher coordinator
        assert "Event to publish found" in caplog.text
        assert message_collector == [
            "test event|Some description",
        ]

        all_events = (await Event.all().prefetch_related(
            "publications").prefetch_related("publications__publisher"))

        # the start command should save all the events in the database
        assert len(all_events) == len(elements), all_events

        # it should create a publication for each publisher
        publications = all_events[0].publications
        assert len(publications) == 1, publications

        # all the other events should have no publication
        for e in all_events[1:]:
            assert len(e.publications) == 0, e.publications

        # all the publications for the first event should be saved as COMPLETED
        for p in publications[1:]:
            assert p.status == PublicationStatus.COMPLETED

        # the derived status for the event should be COMPLETED
        assert event_from_model(
            all_events[0]).status == EventPublicationStatus.COMPLETED
async def test_start_publisher_failure(
    mock_mobilizon_success_answer,
    mobilizon_answer,
    caplog,
    mock_publisher_config,
    message_collector,
    event_generator,
    mock_notifier_config,
):
    event = event_generator()
    event_model = event_to_model(event)
    await event_model.save()

    with caplog.at_level(DEBUG):
        # calling the start command
        assert await start() is not None

        # since the db contains at least one event, this has to be picked and published

        await event_model.fetch_related("publications",
                                        "publications__publisher")
        # it should create a publication for each publisher
        publications = event_model.publications
        assert len(publications) == 1, publications

        # all the publications for event should be saved as FAILED
        for p in publications:
            assert p.status == PublicationStatus.FAILED
            assert p.reason == "credentials error"

        assert "Event to publish found" in caplog.text
        assert message_collector == [
            f"Publication {p.id} failed with status: 0."
            f"\nReason: credentials error\nPublisher: mock\nEvent: test event"
            for p in publications for _ in range(2)
        ]  # 2 publications failed * 2 notifiers
        # the derived status for the event should be FAILED
        assert event_from_model(
            event_model).status == EventPublicationStatus.FAILED