Source code for AutomateTheBoringStuff.Ch16.Projects.P1_assignChores

"""Assign chores

Write a program that takes a list of people’s email addresses and a list of chores
that need to be done and randomly assigns chores to people. Email each person their
assigned chores.

If you’re feeling ambitious, keep a record of each person’s previously assigned
chores so that you can make sure the program avoids assigning anyone the same chore
they did last time.

For another possible feature, schedule the program to run once a week automatically.

Notes:
    * ``smtp_info`` file has each item on a separate line.
    * Use :func:`input` for password to prevent storing in unencrypted file.
    * It may be easier to:

      * Setup a crontab to run weekly.
      * Store `saved_time` and `prev_chores` in a :py:mod:`shelve` database.

"""


[docs]def main(): import openpyxl, random, smtplib, datetime # Open the spreadsheet and get the lists of data. wb = openpyxl.load_workbook('choresList.xlsx') sheet = wb['Sheet1'] names, emails, chores, prev_chores = [], [], [], [] for row in range(2, sheet.max_row + 1): # skip title row name = sheet['A' + str(row)].value email = sheet['B' + str(row)].value chore = sheet['C' + str(row)].value prev_chore = sheet['D' + str(row)].value names.append(name) emails.append(email) chores.append(chore) prev_chores.append(prev_chore) # Run weekly saved_time = sheet['E2'].value interval = datetime.timedelta(days=7) now = datetime.datetime.now() if saved_time is None: saved_time = now - interval # First run, so it's been a week timedelta = saved_time + interval if timedelta > now: time_left = round((timedelta - now).total_seconds()/60, 2) print(f"RuntimeError: Need to wait {time_left} minutes before running again.") raise RuntimeError else: sheet['E2'].value = now # save to spreadsheet # Log in to email account. with open('../smtp_info') as config: myEmail, password, server, port = config.read().splitlines() smtpObj = smtplib.SMTP_SSL(server, port) # Using port 465 smtpObj.ehlo() smtpObj.login(myEmail, password) # Randomly assign chores for i in range(0, len(names)): random_chore = random.choice(chores) # Check previous chore before assignment while random_chore == prev_chores[i] and len(chores) > 1: random_chore = random.choice(chores) # Keep track of chores assigned sheet['D' + str(i + 2)].value = random_chore chores.remove(random_chore) # remove assigned chore from pool # Send email. body = "Subject: Chore for the Week: %s.\nDear %s,\n\nThis week, you're in charge of:\n%s. " \ "\n\nThank you in advance for your efforts!" % (random_chore, names[i], random_chore) print(f'Sending email to {emails[i]}...') sendmailStatus = smtpObj.sendmail(myEmail, emails[i], body) if sendmailStatus != {}: print(f'There was a problem sending email to {emails[i]}: {sendmailStatus}') smtpObj.quit() wb.save('choresList.xlsx')
if __name__ == '__main__': main()