Code reference › domain › schedule

module

pretalx.schedule.domain.notifications

Functions 7

compute_speakers_concerned(schedule)sourceReturns a dictionary of speakers with their new and changed talks in this schedule.

Each speaker is assigned a dictionary with create and update fields, each containing a list of submissions.

def compute_speakers_concerned(schedule):
    """Returns a dictionary of speakers with their new and changed talks in
    this schedule.

    Each speaker is assigned a dictionary with ``create`` and
    ``update`` fields, each containing a list of submissions.
    """
    result = {}
    if schedule.changes["action"] == "create":
        talks = (
            schedule.talks.filter(
                room__isnull=False, start__isnull=False, submission__isnull=False
            )
            .select_related("submission", "submission__event", "room")
            .with_sorted_speakers()
        )
        speakers = defaultdict(lambda: {"create": [], "update": []})
        for talk in talks:
            for speaker in talk.submission.sorted_speakers:
                speakers[speaker]["create"].append(talk)
        return dict(speakers)

    if schedule.changes["count"] == len(schedule.changes["canceled_talks"]):
        return result

    speakers = defaultdict(lambda: {"create": [], "update": []})
    for new_talk in schedule.changes["new_talks"]:
        for speaker in new_talk.submission.sorted_speakers:
            speakers[speaker]["create"].append(new_talk)
    for moved_talk in schedule.changes["moved_talks"]:
        for speaker in moved_talk["submission"].sorted_speakers:
            speakers[speaker]["update"].append(moved_talk)
    return dict(speakers)
count_pending_notifications(schedule)sourceHow many speaker notification mails generate_notifications would produce for this schedule.

One mail per concerned speaker.

def count_pending_notifications(schedule):
    """How many speaker notification mails :func:`generate_notifications`
    would produce for this schedule. One mail per concerned speaker."""
    return len(schedule.speakers_concerned)
generate_notifications(schedule)sourceRender the per-speaker schedule-change notifications and persist each as a DRAFT in the outbox.

Returns the list of saved mails.

def generate_notifications(schedule):
    """Render the per-speaker schedule-change notifications and persist
    each as a DRAFT in the outbox. Returns the list of saved mails."""
    from pretalx.mail.domain.queue import save_draft  # noqa: PLC0415 -- circular import
    from pretalx.mail.domain.recipient import (  # noqa: PLC0415 -- circular import
        Recipient,
    )
    from pretalx.mail.domain.render import (  # noqa: PLC0415 -- circular import
        render_template_to_mail,
    )

    template = mail_template_by_role(schedule.event, MailTemplateRoles.NEW_SCHEDULE)
    # Use cached data
    template.event = schedule.event
    schedule.event.current_schedule = schedule

    mails = []
    for speaker, data in schedule.speakers_concerned.items():
        locale = speaker.effective_locale
        slots = list(data.get("create") or []) + [
            talk["new_slot"] for talk in (data.get("update") or [])
        ]
        submissions = [slot.submission for slot in slots if slot]
        with language(locale):
            attachments = [
                {
                    "name": f"{slot.frab_slug[:200]}.ics",
                    "content": serialize_calendar(get_slot_ical(slot)),
                    "content_type": "text/calendar",
                }
                for slot in slots
            ]
        mail = render_template_to_mail(
            template, context_kwargs={"user": Recipient(speaker)}, locale=locale
        )
        if save_draft(
            mail,
            to_speakers=[speaker],
            submissions=submissions,
            attachments=attachments,
        ):
            mails.append(mail)
    return mails
get_current_notifications(speaker, event)source
def get_current_notifications(speaker, event):
    empty_result = {"create": [], "update": []}
    if not event.current_schedule or speaker is None:
        return empty_result
    concerned = event.current_schedule.speakers_concerned
    for concerned_speaker, data in concerned.items():
        if concerned_speaker.pk == speaker.pk:
            return data
    return empty_result
get_full_notifications(speaker, event)sourceBuilds a notification dict for a speaker, pretending that the current schedule version is the first one.

That is, all talks will be included in the create section.

def get_full_notifications(speaker, event):
    """Builds a notification dict for a speaker, pretending that the current
    schedule version is the first one. That is, all talks will be included
    in the create section."""
    if not event.current_schedule or speaker is None:
        return {"create": [], "update": []}
    return {
        "create": event.current_schedule.scheduled_talks.filter(
            submission__speakers=speaker
        ),
        "update": [],
    }
get_notification_date_format()sourceCall from correct locale context!
def get_notification_date_format():
    """Call from correct locale context!"""
    return get_day_month_date_format() + ", " + get_format("TIME_FORMAT")
render_notifications(data, event)sourceRenders the schedule notifications sent to speakers, in the form of a Markdown list.

The data format is expected to be a dict with the keys create and update, each containing a list of TalkSlot objects, as returned by the values of the Schedule.speakers.concerned return value.

def render_notifications(data, event):
    """Renders the schedule notifications sent to speakers, in the form of a
    Markdown list.

    The data format is expected to be a dict with the keys ``create`` and ``update``,
    each containing a list of TalkSlot objects, as returned by the values of the
    Schedule.speakers.concerned return value."""
    template = get_template("schedule/speaker_notification.txt")
    data = {
        key: list(value) if value is not None else [] for key, value in data.items()
    }
    with override(event.tz):
        date_format = get_notification_date_format()
        return template.render({"START_DATE_FORMAT": date_format, **data})