Skip to content

Commit

Permalink
clean up data model to be minimalistic
Browse files Browse the repository at this point in the history
  • Loading branch information
lbernhard95 committed Oct 30, 2024
1 parent 51956c9 commit 3f1d821
Show file tree
Hide file tree
Showing 5 changed files with 81 additions and 47 deletions.
56 changes: 29 additions & 27 deletions lambda_handler.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from datetime import datetime
from typing import List

import boto3

Expand All @@ -10,21 +10,20 @@
def lambda_handler(event, context):
print(event)
dynamodb = boto3.resource("dynamodb")
poll_item = poll_table.load(dynamodb)
if is_poll_running(poll_item):
schedule_next_schafkopf_event(dynamodb, poll_item.running_poll_id)
poll = poll_table.load(dynamodb)
subscribed_emails = email_table.load_all_mails(dynamodb)
if poll.poll():
new_poll = schedule_next_schafkopf_event(subscribed_emails, poll)
elif poll.is_time_to_start_new_poll():
new_poll = start_new_poll(subscribed_emails)
else:
print("No action required, waiting before scheduling new poll:", poll)
return
print("Store new poll item:", new_poll)
poll_table.update(dynamodb, new_poll)

new_poll_item = start_new_poll(dynamodb)
print("Store new poll item:", new_poll_item)
poll_table.update(dynamodb, new_poll_item)


def is_poll_running(item: PollItem) -> bool:
return item.running_poll_id and datetime.now() < item.start_next_poll_date


def start_new_poll(dynamodb) -> PollItem:
def start_new_poll(subscribed_emails) -> PollItem:
print("Start a new poll")
print("Generate csrf token")
csrf_token = bitpoll.get_valid_csrf_token()
Expand All @@ -44,30 +43,33 @@ def start_new_poll(dynamodb) -> PollItem:

print("Send out email notifications")
gmail.send_bitpoll_invitation(
receivers=email_table.load_all_mails(dynamodb),
receivers=subscribed_emails,
bitpoll_link=new_poll_website
)
return PollItem(
running_poll_id=poll_id,
start_next_poll_date=max(dates)
return PollItem.create_new(
poll_id=poll_id,
next_poll_date=max(dates),
)


def schedule_next_schafkopf_event(dynamodb, poll_id: str):
poll_website = bitpoll.get_website_from_poll_id(poll_id)
def schedule_next_schafkopf_event(emails: List[str], poll: PollItem) -> PollItem:
poll_website = bitpoll.get_website_from_poll_id(poll.running_poll_id)
print("Try to schedule next schafkopf event for:", poll_website)
page = bitpoll.get_poll_webpage(poll_id=poll_id)
page = bitpoll.get_poll_webpage(poll_id=poll.running_poll_id)
votes = bitpoll.collect_vote_dates(page)
best_date = scheduler.find_best_date(votes)
print("Most promising date:", best_date)
best_vote = scheduler.find_best_date(votes)
print("Most promising vote:", best_vote)

if best_date:
if best_vote:
print("Found valid date, sending out invitation")
best_date = best_vote.date
# todo show "screenshot" of poll
gmail.send_schafkopf_meeting_invitation(
receivers=email_table.load_all_mails(dynamodb),
day=best_date.date,
bitpoll_link=poll_website
receivers=emails,
start=best_date,
bitpoll_link=poll_website,
)
poll.event_scheduled_update(event_date=best_date)
return poll


if __name__ == '__main__':
Expand Down
4 changes: 3 additions & 1 deletion scheduler/bitpoll.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,10 @@ class VoteDate(BaseModel):
@staticmethod
def from_bitpoll_date(date: str) -> "VoteDate":
locale.setlocale(locale.LC_TIME, 'de_DE')
date = datetime.strptime(date, "%a, %d. %b. %Y")
date = date.replace(hour=18, minute=30)
return VoteDate(
date=datetime.strptime(date, "%a, %d. %b. %Y"),
date=date,
yes_count=0,
no_count=0,
probably_no_count=0,
Expand Down
5 changes: 4 additions & 1 deletion scheduler/dynamodb/email_table.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@

from pydantic import BaseModel

from scheduler import env


class EmailItem(BaseModel):
email: str
Expand All @@ -14,7 +16,8 @@ def add(dynamodb, email: EmailItem):


def load_all_mails(dynamodb) -> List[str]:
return [i.email for i in load_all(dynamodb)]
registered = [i.email for i in load_all(dynamodb)]
return list(set(registered + [env.get_gmail_sender_address()]))


def load_all(dynamodb) -> List[EmailItem]:
Expand Down
29 changes: 27 additions & 2 deletions scheduler/dynamodb/poll_table.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,33 @@


class PollItem(BaseModel):
running_poll_id: Optional[str] = None
start_next_poll_date: Optional[datetime] = None
running_poll_id: str
start_next_poll_date: datetime
new_poll_email_sent: datetime
event_invitation_email_sent: Optional[datetime] = None

@staticmethod
def create_new(poll_id: str, next_poll_date: datetime) -> "PollItem":
return PollItem(
running_poll_id=poll_id,
start_next_poll_date=next_poll_date,
new_poll_email_sent=datetime.now()
)

def event_scheduled_update(self, event_date: datetime):
self.start_next_poll_date = event_date
self.event_invitation_email_sent = datetime.now()

def poll(self) -> bool:
return (
self.running_poll_id and
datetime.now() < self.start_next_poll_date and
self.event_invitation_email_sent is None
)

def is_time_to_start_new_poll(self) -> bool:
return datetime.now() >= self.start_next_poll_date


def load(dynamodb) -> PollItem:
try:
Expand Down
34 changes: 18 additions & 16 deletions scheduler/gmail.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,42 +14,43 @@ def send_bitpoll_invitation(receivers: List[str], bitpoll_link: str):
html = load_html_template("templates/poll_invitation.html")
html = html.replace("YOUR_BITPOLL_LINK_HERE", bitpoll_link)

send_email(
send(
receivers=receivers,
subject=f"Schafkopfen",
body=MIMEText(html, "html"),
subject="New Schafkopf Round",
body=MIMEText(html, "html")
)


def send_schafkopf_meeting_invitation(receivers: List[str], day: datetime, bitpoll_link: str):
start=datetime(year=day.year, month=day.month, day=day.day, hour=18, minute=30)
end=datetime(year=day.year, month=day.month, day=day.day, hour=23)

def send_schafkopf_meeting_invitation(receivers: List[str], start: datetime, bitpoll_link: str):
html = load_html_template("templates/schafkopf_scheduled.html")
html = html.replace("SCHEDULED_DATE_PLACEHOLDER", format_datetime(start))
html = html.replace("YOUR_BITPOLL_LINK_HERE", bitpoll_link)

send_email(
receivers=list(set(receivers + [env.get_gmail_sender_address()])),
subject=f"Schafkopfen on {day.strftime('%d.%m')}",
send(
receivers=receivers,
subject=f"Schafkopfen on {start.strftime('%d.%m')}",
body=MIMEText(html, "html"),
event=create_calendar_entry(
attachment=create_calendar_entry(
summary="[at] Schafkopfen",
start=start, end=end,
start=start, end=start.replace(hour=23, minute=0),
)
)


def send_email(receivers: List[str], subject: str, body: MIMEText, event: Optional[MIMEBase]=None):
def send(
receivers: List[str],
subject: str,
body: MIMEText,
attachment: Optional[MIMEBase]=None
):
sender = env.get_gmail_sender_address()

message = MIMEMultipart()
message['From'] = sender
message['To'] = ", ".join(receivers)
message['Subject'] = subject
message.attach(body)
if event:
message.attach(event)
if attachment:
message.attach(attachment)

smtpserver = smtplib.SMTP_SSL('smtp.gmail.com', 465)
smtpserver.ehlo()
Expand Down Expand Up @@ -83,6 +84,7 @@ def create_calendar_entry(start: datetime, end: datetime, summary: str) -> MIMEB
)
return part


def format_datetime(dt: datetime):
locale.setlocale(locale.LC_TIME, 'en_US.UTF-8')
weekday_name = dt.strftime('%A')
Expand Down

0 comments on commit 3f1d821

Please sign in to comment.