Exemplo n.º 1
0
def test_next_many_planned(db_connection):
    event1 = create_event(1, start_at=datetime(2021, 4, 15))  # noqa
    event2 = create_event(2, start_at=datetime(2021, 6, 1))  # noqa
    event3 = create_event(3, start_at=datetime(2021, 5, 3))
    event4 = create_event(4, start_at=datetime(2021, 3, 15))  # noqa

    assert Event.next(today=date(2021, 5, 2)) == event3
Exemplo n.º 2
0
def test_archive_listing(db_connection):
    event1 = create_event(1, start_at=datetime(2021, 4, 15))
    event2 = create_event(2, start_at=datetime(2021, 5, 1))
    event3 = create_event(3, start_at=datetime(2021, 5, 3))  # noqa
    event4 = create_event(4, start_at=datetime(2021, 3, 15))

    assert Event.archive_listing(today=date(2021, 5, 2)) == [event2, event1, event4]
Exemplo n.º 3
0
def test_list_speaking_members(db_connection):
    event1 = create_event(1)
    member1 = create_member(1)
    EventSpeaking.create(event=event1, speaker=member1)

    event2 = create_event(2)
    member2 = create_member(2)
    member3 = create_member(3)
    EventSpeaking.create(event=event2, speaker=member2)
    EventSpeaking.create(event=event2, speaker=member3)

    member4 = create_member(4)  # noqa

    assert set(Event.list_speaking_members()) == {member1, member2, member3}
Exemplo n.º 4
0
def main():
    with db:
        members = MessageAuthor.members_listing()
        changes = []
        top_members_limit = MessageAuthor.top_members_limit()
        log.info(
            f'members_count={len(members)}, top_members_limit={top_members_limit}'
        )

        # ROLE_MOST_DISCUSSING
        messages_count_stats = calc_stats(members,
                                          lambda m: m.messages_count(),
                                          top_members_limit)
        log.info(f"messages_count {repr_stats(members, messages_count_stats)}")

        recent_messages_count_stats = calc_stats(
            members, lambda m: m.recent_messages_count(), top_members_limit)
        log.info(
            f"recent_messages_count {repr_stats(members, recent_messages_count_stats)}"
        )

        most_discussing_members_ids = set(messages_count_stats.keys()) | set(
            recent_messages_count_stats.keys())
        log.info(
            f"most_discussing_members: {repr_ids(members, most_discussing_members_ids)}"
        )

        for member in members:
            changes.extend(
                evaluate_changes(member.id, member.roles,
                                 most_discussing_members_ids,
                                 ROLE_MOST_DISCUSSING))

        # ROLE_MOST_HELPFUL
        upvotes_count_stats = calc_stats(members, lambda m: m.upvotes_count(),
                                         top_members_limit)
        log.info(f"upvotes_count {repr_stats(members, upvotes_count_stats)}")

        recent_upvotes_count_stats = calc_stats(
            members, lambda m: m.recent_upvotes_count(), top_members_limit)
        log.info(
            f"recent_upvotes_count {repr_stats(members, recent_upvotes_count_stats)}"
        )

        most_helpful_members_ids = set(upvotes_count_stats.keys()) | set(
            recent_upvotes_count_stats.keys())
        log.info(
            f"most_helpful_members: {repr_ids(members, most_helpful_members_ids)}"
        )

        for member in members:
            changes.extend(
                evaluate_changes(member.id, member.roles,
                                 most_helpful_members_ids, ROLE_MOST_HELPFUL))

        # ROLE_HAS_INTRO_AND_AVATAR
        intro_avatar_members_ids = [
            member.id for member in members
            if member.has_avatar and member.has_intro()
        ]
        log.info(
            f"intro_avatar_members: {repr_ids(members, intro_avatar_members_ids)}"
        )
        for member in members:
            changes.extend(
                evaluate_changes(member.id, member.roles,
                                 intro_avatar_members_ids,
                                 ROLE_HAS_INTRO_AND_AVATAR))

        # ROLE_IS_NEW
        new_members_ids = [member.id for member in members if member.is_new()]
        log.info(f"new_members_ids: {repr_ids(members, new_members_ids)}")
        for member in members:
            changes.extend(
                evaluate_changes(member.id, member.roles, new_members_ids,
                                 ROLE_IS_NEW))

        # ROLE_IS_SPEAKER
        speaking_members_ids = [
            member.id for member in Event.list_speaking_members()
        ]
        log.info(
            f"speaking_members_ids: {repr_ids(members, speaking_members_ids)}")
        for member in members:
            changes.extend(
                evaluate_changes(member.id, member.roles, speaking_members_ids,
                                 ROLE_IS_SPEAKER))

    if DISCORD_MUTATIONS_ENABLED:
        apply_changes(changes)
    else:
        log.warning(
            "Skipping Discord mutations, DISCORD_MUTATIONS_ENABLED not set")
Exemplo n.º 5
0
def main():
    path = DATA_DIR / 'events.yml'
    records = [
        load_record(record.data) for record in load(path.read_text(), schema)
    ]

    if FLUSH_POSTERS:
        log.warning("Removing all existing posters, FLUSH_POSTERS is set")
        for poster_path in POSTERS_DIR.glob('*.png'):
            poster_path.unlink()

    with db:
        db.drop_tables([Event, EventSpeaking])
        db.create_tables([Event, EventSpeaking])

        # process data from the YAML, generate posters
        for record in records:
            name = record['title']
            log.info(f"Creating '{name}'")
            speakers_ids = record.pop('speakers', [])
            event = Event.create(**record)

            for speaker_id in speakers_ids:
                try:
                    avatar_path = next(
                        (IMAGES_DIR / 'speakers').glob(f"{speaker_id}.*"))
                except StopIteration:
                    log.info(f"Didn't find speaker avatar for {speaker_id}")
                    avatar_path = None
                else:
                    log.info(f"Downsizing speaker avatar for {speaker_id}")
                    avatar_path = downsize_square_photo(
                        avatar_path, 500).relative_to(IMAGES_DIR)

                log.info(f"Marking member {speaker_id} as a speaker")
                EventSpeaking.create(speaker=speaker_id,
                                     event=event,
                                     avatar_path=avatar_path)

            if event.logo_path:
                log.info(f"Checking '{event.logo_path}'")
                image_path = IMAGES_DIR / event.logo_path
                if not image_path.exists():
                    raise ValueError(
                        f"Event '{name}' references '{image_path}', but it doesn't exist"
                    )

            log.info(f"Rendering poster for '{name}'")
            context = dict(
                event=model_to_dict(event, extra_attrs=['first_avatar_path']))
            image_path = render_image_file('poster.html',
                                           context,
                                           POSTERS_DIR,
                                           filters={
                                               'md': md,
                                               'local_time': local_time,
                                               'weekday': weekday,
                                           })
            event.poster_path = image_path.relative_to(IMAGES_DIR)
            event.save()

            log.info(f"Rendering Instagram poster for '{name}'")
            save_as_ig_square(image_path)

        # discord messages
        if DISCORD_MUTATIONS_ENABLED:
            post_next_event_messages()
        else:
            log.warning(
                "Skipping Discord mutations, DISCORD_MUTATIONS_ENABLED not set"
            )
Exemplo n.º 6
0
async def post_next_event_messages(client):
    announcements_channel = await client.fetch_channel(ANNOUNCEMENTS_CHANNEL)
    events_chat_channel = await client.fetch_channel(EVENTS_CHAT_CHANNEL)

    event = Event.next()
    if not event:
        log.info("The next event is not announced yet")
        return
    speakers = ', '.join(
        [speaking.speaker.mention for speaking in event.list_speaking])

    log.info("About to post a message 7 days prior to the event")
    if event.start_at.date() - timedelta(days=7) == date.today():
        with db:
            message = Message.last_bot_message(ANNOUNCEMENTS_CHANNEL, '🗓',
                                               event.url)
        if message:
            log.info(f'Looks like the message already exists: {message.url}')
        else:
            log.info("Found no message, posting!")
            content = f"🗓 Už **za týden** bude v klubu „{event.title}” s {speakers}! {event.url}"
            await announcements_channel.send(content)
    else:
        log.info("It's not 1 day prior to the event")

    log.info("About to post a message 1 day prior to the event")
    if event.start_at.date() - timedelta(days=1) == date.today():
        with db:
            message = Message.last_bot_message(ANNOUNCEMENTS_CHANNEL, '🤩',
                                               event.url)
        if message:
            log.info(f'Looks like the message already exists: {message.url}')
        else:
            log.info("Found no message, posting!")
            content = f"🤩 Už **zítra v {event.start_at_prg:%H:%M}** bude v klubu „{event.title}” s {speakers}! {event.url}"
            await announcements_channel.send(content)
    else:
        log.info("It's not 1 day prior to the event")

    log.info("About to post a message on the day when the event is")
    if event.start_at.date() == date.today():
        with db:
            message = Message.last_bot_message(ANNOUNCEMENTS_CHANNEL, '⏰',
                                               event.url)
        if message:
            log.info(f'Looks like the message already exists: {message.url}')
        else:
            log.info("Found no message, posting!")
            content = f"⏰ @everyone Už **dnes v {event.start_at_prg:%H:%M}** bude v klubu „{event.title}” s {speakers}! Odehrávat se to bude v klubovně, případné dotazy v {events_chat_channel.mention} 💬 Akce se nahrávají, odkaz na záznam se objeví v tomto kanále. {event.url}"
            await announcements_channel.send(content)
    else:
        log.info("It's not the day when the event is")

    log.info(
        "About to post a message to event chat on the day when the event is")
    if event.start_at.date() == date.today():
        with db:
            message = Message.last_bot_message(EVENTS_CHAT_CHANNEL, '👋',
                                               event.url)
        if message:
            log.info(f'Looks like the message already exists: {message.url}')
        else:
            log.info("Found no message, posting!")
            content = [
                f"👋 Už **dnes v {event.start_at_prg:%H:%M}** tady bude probíhat „{event.title}” s {speakers} (viz {announcements_channel.mention}). Tento kanál slouží k pokládání dotazů, sdílení odkazů, slajdů k prezentaci…",
                "",
                "⚠️ Ve výchozím nastavení Discord udělá zvuk při každé aktivitě v hlasovém kanále, např. při připojení nového účastníka, odpojení, vypnutí zvuku, zapnutí, apod. Zvuky si vypni v _User Settings_, stránka _Notifications_, sekce _Sounds_. Většina zvuků souvisí s hovory, takže je potřeba povypínat skoro vše.",
                "",
                f"ℹ️ {strip_links(event.description.strip())}",
                "",
                f"🦸 {strip_links(event.bio).strip()}"
                "",
                "",
                f"👉 {event.url}",
            ]
            await events_chat_channel.send('\n'.join(content))
    else:
        log.info("It's not the day when the event is")
Exemplo n.º 7
0
def test_next_nothing_planned(db_connection):
    create_event(1, start_at=datetime(2021, 4, 15))
    create_event(2, start_at=datetime(2021, 5, 1))
    create_event(4, start_at=datetime(2021, 3, 15))

    assert Event.next(today=date(2021, 5, 2)) is None
Exemplo n.º 8
0
def create_event(id, **kwargs):
    return Event.create(id=id, **{
        'title': f"Event #{id}",
        'description': 'Markdown **description** of the _event_.',
        'start_at': datetime.now(),
    **kwargs})