2022-01-04 21:35:43 +01:00
|
|
|
from functools import partial
|
2022-07-12 07:39:56 +02:00
|
|
|
from typing import Iterable, Optional, Iterator
|
2021-08-05 00:29:50 +02:00
|
|
|
from uuid import UUID
|
|
|
|
|
2021-08-04 18:53:58 +02:00
|
|
|
from arrow import Arrow
|
2022-02-14 21:10:27 +01:00
|
|
|
from tortoise.exceptions import DoesNotExist
|
2021-07-15 18:13:11 +02:00
|
|
|
from tortoise.queryset import QuerySet
|
2021-07-05 23:07:12 +02:00
|
|
|
from tortoise.transactions import atomic
|
|
|
|
|
2021-08-16 10:49:52 +02:00
|
|
|
from mobilizon_reshare.event.event import MobilizonEvent, EventPublicationStatus
|
|
|
|
from mobilizon_reshare.models.event import Event
|
|
|
|
from mobilizon_reshare.models.publication import Publication, PublicationStatus
|
2022-02-09 00:54:56 +01:00
|
|
|
from mobilizon_reshare.models.publisher import Publisher
|
2021-11-24 23:58:06 +01:00
|
|
|
from mobilizon_reshare.publishers.abstract import EventPublication
|
2022-02-23 17:26:13 +01:00
|
|
|
from mobilizon_reshare.storage.query.converter import (
|
|
|
|
event_from_model,
|
|
|
|
compute_event_status,
|
|
|
|
publication_from_orm,
|
|
|
|
)
|
2022-02-14 21:10:27 +01:00
|
|
|
from mobilizon_reshare.storage.query.exceptions import EventNotFound
|
2021-07-12 22:17:49 +02:00
|
|
|
|
2021-08-05 00:29:50 +02:00
|
|
|
|
2021-11-11 15:18:04 +01:00
|
|
|
async def get_published_events(
|
|
|
|
from_date: Optional[Arrow] = None, to_date: Optional[Arrow] = None
|
|
|
|
) -> Iterable[MobilizonEvent]:
|
|
|
|
"""
|
|
|
|
Retrieves events that are not waiting. Function could be renamed to something more fitting
|
|
|
|
:return:
|
|
|
|
"""
|
|
|
|
return await events_with_status(
|
|
|
|
[
|
|
|
|
EventPublicationStatus.COMPLETED,
|
|
|
|
EventPublicationStatus.PARTIAL,
|
|
|
|
EventPublicationStatus.FAILED,
|
|
|
|
],
|
|
|
|
from_date=from_date,
|
|
|
|
to_date=to_date,
|
2021-08-27 23:45:24 +02:00
|
|
|
)
|
2021-08-05 00:29:50 +02:00
|
|
|
|
|
|
|
|
2021-07-05 23:07:12 +02:00
|
|
|
async def events_with_status(
|
2021-08-05 00:29:50 +02:00
|
|
|
status: list[EventPublicationStatus],
|
2021-08-04 18:53:58 +02:00
|
|
|
from_date: Optional[Arrow] = None,
|
|
|
|
to_date: Optional[Arrow] = None,
|
2021-07-05 23:07:12 +02:00
|
|
|
) -> Iterable[MobilizonEvent]:
|
2021-08-04 18:53:58 +02:00
|
|
|
def _filter_event_with_status(event: Event) -> bool:
|
|
|
|
# This computes the status client-side instead of running in the DB. It shouldn't pose a performance problem
|
|
|
|
# in the short term, but should be moved to the query if possible.
|
2022-02-23 17:26:13 +01:00
|
|
|
event_status = compute_event_status(list(event.publications))
|
2021-08-04 18:53:58 +02:00
|
|
|
return event_status in status
|
|
|
|
|
|
|
|
query = Event.all()
|
2021-08-05 00:29:50 +02:00
|
|
|
|
2021-05-31 01:11:50 +02:00
|
|
|
return map(
|
2022-02-23 17:26:13 +01:00
|
|
|
event_from_model,
|
2021-08-05 00:29:50 +02:00
|
|
|
filter(
|
|
|
|
_filter_event_with_status,
|
|
|
|
await prefetch_event_relations(
|
|
|
|
_add_date_window(query, "begin_datetime", from_date, to_date)
|
|
|
|
),
|
|
|
|
),
|
2021-05-31 01:11:50 +02:00
|
|
|
)
|
2021-07-05 23:07:12 +02:00
|
|
|
|
|
|
|
|
2021-12-01 01:08:37 +01:00
|
|
|
async def get_all_publications(
|
2022-09-24 16:46:03 +02:00
|
|
|
from_date: Optional[Arrow] = None, to_date: Optional[Arrow] = None,
|
2022-05-17 23:14:52 +02:00
|
|
|
) -> Iterable[Publication]:
|
2021-12-01 01:08:37 +01:00
|
|
|
return await prefetch_publication_relations(
|
|
|
|
_add_date_window(Publication.all(), "timestamp", from_date, to_date)
|
|
|
|
)
|
|
|
|
|
|
|
|
|
2021-08-04 18:53:58 +02:00
|
|
|
async def get_all_events(
|
2022-09-24 16:46:03 +02:00
|
|
|
from_date: Optional[Arrow] = None, to_date: Optional[Arrow] = None,
|
2022-03-22 21:16:34 +01:00
|
|
|
) -> list[MobilizonEvent]:
|
|
|
|
return [
|
|
|
|
event_from_model(event)
|
|
|
|
for event in await prefetch_event_relations(
|
2021-08-05 00:29:50 +02:00
|
|
|
_add_date_window(Event.all(), "begin_datetime", from_date, to_date)
|
2022-03-22 21:16:34 +01:00
|
|
|
)
|
|
|
|
]
|
2021-07-05 23:07:12 +02:00
|
|
|
|
|
|
|
|
2022-05-17 23:14:52 +02:00
|
|
|
async def get_all_publishers() -> list[Publisher]:
|
|
|
|
return await Publisher.all()
|
|
|
|
|
|
|
|
|
2021-11-11 15:18:04 +01:00
|
|
|
async def prefetch_event_relations(queryset: QuerySet[Event]) -> list[Event]:
|
|
|
|
return (
|
|
|
|
await queryset.prefetch_related("publications__publisher")
|
|
|
|
.order_by("begin_datetime")
|
|
|
|
.distinct()
|
2021-08-05 00:29:50 +02:00
|
|
|
)
|
2021-07-12 22:17:49 +02:00
|
|
|
|
|
|
|
|
2022-01-04 21:35:43 +01:00
|
|
|
async def prefetch_publication_relations(
|
|
|
|
queryset: QuerySet[Publication],
|
|
|
|
) -> list[Publication]:
|
2022-02-14 21:10:27 +01:00
|
|
|
publication = (
|
2021-12-01 01:08:37 +01:00
|
|
|
await queryset.prefetch_related("publisher", "event")
|
|
|
|
.order_by("timestamp")
|
|
|
|
.distinct()
|
|
|
|
)
|
2022-02-14 21:10:27 +01:00
|
|
|
return publication
|
2021-12-01 01:08:37 +01:00
|
|
|
|
|
|
|
|
2021-11-11 15:18:04 +01:00
|
|
|
def _add_date_window(
|
|
|
|
query,
|
|
|
|
field_name: str,
|
|
|
|
from_date: Optional[Arrow] = None,
|
|
|
|
to_date: Optional[Arrow] = None,
|
|
|
|
):
|
|
|
|
if from_date:
|
|
|
|
query = query.filter(**{f"{field_name}__gt": from_date.to("utc").datetime})
|
|
|
|
if to_date:
|
|
|
|
query = query.filter(**{f"{field_name}__lt": to_date.to("utc").datetime})
|
|
|
|
return query
|
2021-08-05 00:29:50 +02:00
|
|
|
|
|
|
|
|
2022-07-26 22:23:47 +02:00
|
|
|
@atomic()
|
2021-11-11 15:18:04 +01:00
|
|
|
async def publications_with_status(
|
|
|
|
status: PublicationStatus,
|
|
|
|
from_date: Optional[Arrow] = None,
|
|
|
|
to_date: Optional[Arrow] = None,
|
2022-03-06 10:41:02 +01:00
|
|
|
) -> Iterable[Publication]:
|
2021-11-11 15:18:04 +01:00
|
|
|
query = Publication.filter(status=status)
|
2021-08-05 00:29:50 +02:00
|
|
|
|
2021-12-01 01:08:37 +01:00
|
|
|
return await prefetch_publication_relations(
|
|
|
|
_add_date_window(query, "timestamp", from_date, to_date)
|
|
|
|
)
|
2021-07-05 23:07:12 +02:00
|
|
|
|
|
|
|
|
2021-11-11 15:18:04 +01:00
|
|
|
async def events_without_publications(
|
2022-09-24 16:46:03 +02:00
|
|
|
from_date: Optional[Arrow] = None, to_date: Optional[Arrow] = None,
|
2021-11-24 23:58:06 +01:00
|
|
|
) -> list[MobilizonEvent]:
|
2021-11-11 15:18:04 +01:00
|
|
|
query = Event.filter(publications__id=None)
|
|
|
|
events = await prefetch_event_relations(
|
|
|
|
_add_date_window(query, "begin_datetime", from_date, to_date)
|
2021-07-05 23:07:12 +02:00
|
|
|
)
|
2022-03-22 21:16:34 +01:00
|
|
|
return [event_from_model(event) for event in events]
|
2021-07-05 23:07:12 +02:00
|
|
|
|
|
|
|
|
2022-02-09 00:54:56 +01:00
|
|
|
async def get_event(event_mobilizon_id: UUID) -> Event:
|
|
|
|
events = await prefetch_event_relations(
|
|
|
|
Event.filter(mobilizon_id=event_mobilizon_id)
|
|
|
|
)
|
|
|
|
if not events:
|
|
|
|
raise EventNotFound(f"No event with mobilizon_id {event_mobilizon_id} found.")
|
2021-07-05 23:07:12 +02:00
|
|
|
|
2022-02-09 00:54:56 +01:00
|
|
|
return events[0]
|
2021-11-11 15:18:04 +01:00
|
|
|
|
2022-02-09 00:54:56 +01:00
|
|
|
|
2022-10-26 00:43:25 +02:00
|
|
|
async def get_event_publications(
|
|
|
|
mobilizon_event: MobilizonEvent,
|
|
|
|
) -> list[EventPublication]:
|
|
|
|
event = await get_event(mobilizon_event.mobilizon_id)
|
|
|
|
return [publication_from_orm(p, mobilizon_event) for p in event.publications]
|
|
|
|
|
|
|
|
|
2022-05-17 23:14:52 +02:00
|
|
|
async def get_mobilizon_event(event_mobilizon_id: UUID) -> MobilizonEvent:
|
|
|
|
return event_from_model(await get_event(event_mobilizon_id))
|
|
|
|
|
|
|
|
|
2022-02-09 00:54:56 +01:00
|
|
|
async def get_publisher_by_name(name) -> Publisher:
|
|
|
|
return await Publisher.filter(name=name).first()
|
|
|
|
|
|
|
|
|
|
|
|
async def is_known(event: MobilizonEvent) -> bool:
|
|
|
|
try:
|
|
|
|
await get_event(event.mobilizon_id)
|
|
|
|
return True
|
|
|
|
except EventNotFound:
|
|
|
|
return False
|
2021-11-24 23:58:06 +01:00
|
|
|
|
|
|
|
|
2022-07-26 22:23:47 +02:00
|
|
|
@atomic()
|
2022-05-17 23:14:52 +02:00
|
|
|
async def build_publications(
|
2022-07-12 07:39:56 +02:00
|
|
|
event: MobilizonEvent, publishers: Iterator[str]
|
2022-05-17 23:14:52 +02:00
|
|
|
) -> list[EventPublication]:
|
2022-02-09 00:54:56 +01:00
|
|
|
event_model = await get_event(event.mobilizon_id)
|
2021-11-24 23:58:06 +01:00
|
|
|
models = [
|
|
|
|
await event_model.build_publication_by_publisher_name(name)
|
2022-05-17 23:14:52 +02:00
|
|
|
for name in publishers
|
2021-11-24 23:58:06 +01:00
|
|
|
]
|
2022-05-17 23:14:52 +02:00
|
|
|
return [publication_from_orm(m, event) for m in models]
|
2022-01-04 21:35:43 +01:00
|
|
|
|
|
|
|
|
2022-07-26 22:23:47 +02:00
|
|
|
@atomic()
|
2022-02-09 00:54:56 +01:00
|
|
|
async def get_failed_publications_for_event(
|
|
|
|
event_mobilizon_id: UUID,
|
2022-03-06 10:41:02 +01:00
|
|
|
) -> list[EventPublication]:
|
2022-01-04 21:35:43 +01:00
|
|
|
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")
|
2022-03-06 10:41:02 +01:00
|
|
|
mobilizon_event = event_from_model(event)
|
|
|
|
return list(
|
|
|
|
map(partial(publication_from_orm, event=mobilizon_event), failed_publications)
|
|
|
|
)
|
2022-02-14 21:10:27 +01:00
|
|
|
|
|
|
|
|
2022-07-26 22:23:47 +02:00
|
|
|
@atomic()
|
2022-05-17 23:14:52 +02:00
|
|
|
async def get_publication(publication_id: UUID):
|
2022-02-14 21:10:27 +01:00
|
|
|
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)
|
2022-03-06 10:41:02 +01:00
|
|
|
return publication_from_orm(
|
|
|
|
event=event_from_model(publication.event), model=publication
|
|
|
|
)
|
2022-02-14 21:10:27 +01:00
|
|
|
except DoesNotExist:
|
|
|
|
return None
|