diff options
author | Christian Cleberg <hello@cleberg.net> | 2023-12-02 23:27:35 -0600 |
---|---|---|
committer | Christian Cleberg <hello@cleberg.net> | 2023-12-02 23:27:35 -0600 |
commit | 3d4da5ac6000a4871c5caa80d1e61f2782da3069 (patch) | |
tree | 29f36b50823d22f4c7df0a3db3ede83192ae649f /blog/2022-06-22-daily-poetry.org | |
parent | dcf0186e16b6ac8f0e00a3aeb9734421ce548177 (diff) | |
download | cleberg.net-3d4da5ac6000a4871c5caa80d1e61f2782da3069.tar.gz cleberg.net-3d4da5ac6000a4871c5caa80d1e61f2782da3069.tar.bz2 cleberg.net-3d4da5ac6000a4871c5caa80d1e61f2782da3069.zip |
feat: finish converting md to org
Diffstat (limited to 'blog/2022-06-22-daily-poetry.org')
-rw-r--r-- | blog/2022-06-22-daily-poetry.org | 254 |
1 files changed, 140 insertions, 114 deletions
diff --git a/blog/2022-06-22-daily-poetry.org b/blog/2022-06-22-daily-poetry.org index 37a9e0b..dd1e249 100644 --- a/blog/2022-06-22-daily-poetry.org +++ b/blog/2022-06-22-daily-poetry.org @@ -1,71 +1,80 @@ -+++ -date = 2022-06-22 -title = "Daily Plaintext Poetry via Email" -description = "A quick tutorial showing how to use Python and the PoetryDB API to email daily poetry." -draft = false -+++ - -## Source Code - -I don't want to bury the lede here, so if you'd like to see the full source -code I use to email myself plaintext poems daily, visit the repository: -[daily-poem](https://git.sr.ht/~cmc/daily-poem/). - -## My Daily Dose of Poetry - -Most of my programming projects are small, random projects that are made +#+title: Daily Plaintext Poetry via Email +#+date: 2022-06-22 + +** Source Code +:PROPERTIES: +:CUSTOM_ID: source-code +:END: +I don't want to bury the lede here, so if you'd like to see the full +source code I use to email myself plaintext poems daily, visit the +repository: [[https://git.sr.ht/~cmc/daily-poem/][daily-poem]]. + +** My Daily Dose of Poetry +:PROPERTIES: +:CUSTOM_ID: my-daily-dose-of-poetry +:END: +Most of my programming projects are small, random projects that are made strictly to fix some small problem I have or enhance my quality of life. -In this case, I was looking for a simply and easy way to get a daily dose of -literature or poetry to read in the mornings. - -However, I don't want to sign up for a random mailing list on just any website. -I also don't want to have to work to find the reading content each morning, as I -know I would simply give up and stop reading daily. +In this case, I was looking for a simply and easy way to get a daily +dose of literature or poetry to read in the mornings. -Thus, I found a way to deliver poetry to myself in plain-text format, on a daily -basis, and scheduled to deliver automatically. +However, I don't want to sign up for a random mailing list on just any +website. I also don't want to have to work to find the reading content +each morning, as I know I would simply give up and stop reading daily. -## Prerequisites +Thus, I found a way to deliver poetry to myself in plain-text format, on +a daily basis, and scheduled to deliver automatically. -This solution uses Python and email, so the following process requires the -following to be installed: +** Prerequisites +:PROPERTIES: +:CUSTOM_ID: prerequisites +:END: +This solution uses Python and email, so the following process requires +the following to be installed: -1. An SMTP server, which can be as easy as installing `mailutils` if you're on -a Debian-based distro. +1. An SMTP server, which can be as easy as installing =mailutils= if + you're on a Debian-based distro. 2. Python (& pip!) -3. The following Python packages: `email`, `smtplib`, `json`, and `requests` - -## Breaking Down the Logic - -I want to break down the logic for this program, as it's quite simple and -informational. - -### Required Packages - -This program starts with a simple import of the required packages, so I wanted -to explain why each package is used: - -```py +3. The following Python packages: =email=, =smtplib=, =json=, and + =requests= + +** Breaking Down the Logic +:PROPERTIES: +:CUSTOM_ID: breaking-down-the-logic +:END: +I want to break down the logic for this program, as it's quite simple +and informational. + +*** Required Packages +:PROPERTIES: +:CUSTOM_ID: required-packages +:END: +This program starts with a simple import of the required packages, so I +wanted to explain why each package is used: + +#+begin_src py from email.mime.text import MIMEText # Required for translating MIMEText import smtplib # Required to process the SMTP mail delivery import json # Required to parse the poetry API results import requests # Required to send out a request to the API -``` - -### Sending the API Request +#+end_src -Next, we need to actually send the API request. In my case, I'm calling a random -poem from the entire API. If you want, you can call specific poems or authors -from this API. +*** Sending the API Request +:PROPERTIES: +:CUSTOM_ID: sending-the-api-request +:END: +Next, we need to actually send the API request. In my case, I'm calling +a random poem from the entire API. If you want, you can call specific +poems or authors from this API. -```py +#+begin_src py json_data = requests.get('https://poetrydb.org/random').json() -``` +#+end_src This gives us the following result in JSON: -```json +#+begin_src json [ { "title": "Sonnet XXII: With Fools and Children", @@ -91,80 +100,95 @@ This gives us the following result in JSON: "linecount": "15" } ] -``` - -### Parsing the API Results - -In order to parse this into a readable format, we need to use the `json` package -and extract the fields we want. In the example below, I am grabbing every field -presented by the API. - -For the actual poem content, we need to loop over each line in the `lines` -variable since each line is a separate string by default. - -> You *could* also extract the title or author and make another call out to the -> API to avoid having to build the plaintext poem with a loop, but it just -> doesn't make sense to me to send multiple requests when we can create a simple -> loop on our local machine to work with the data we already have. -> -> For -> [example](https://poetrydb.org/title/Sonnet%20XXII:%20With%20Fools%20and%20Children/lines.text), -> look at the raw data response of this link to see the poem's lines returned -> in plaintext. - -```py +#+end_src + +*** Parsing the API Results +:PROPERTIES: +:CUSTOM_ID: parsing-the-api-results +:END: +In order to parse this into a readable format, we need to use the =json= +package and extract the fields we want. In the example below, I am +grabbing every field presented by the API. + +For the actual poem content, we need to loop over each line in the +=lines= variable since each line is a separate string by default. + +#+begin_quote +You /could/ also extract the title or author and make another call out +to the API to avoid having to build the plaintext poem with a loop, but +it just doesn't make sense to me to send multiple requests when we can +create a simple loop on our local machine to work with the data we +already have. + +For +[[https://poetrydb.org/title/Sonnet%20XXII:%20With%20Fools%20and%20Children/lines.text][example]], +look at the raw data response of this link to see the poem's lines +returned in plaintext. + +#+end_quote + +#+begin_src py title = json_data[0]['title'] author = json_data[0]['author'] line_count = json_data[0]['linecount'] lines = '' for line in json_data[0]['lines']: lines = lines + line + "\n" -``` - -### Composing the Email +#+end_src -Now that I have all the data I need, I just need to compose it into a message -and prepare the message metadata. +*** Composing the Email +:PROPERTIES: +:CUSTOM_ID: composing-the-email +:END: +Now that I have all the data I need, I just need to compose it into a +message and prepare the message metadata. -For my daily email, I want to see the title of the poem first, followed by the -author, then a blank line, and finally the full poem. This code snippet combines -that data and packages it into a MIMEText container, ready to be emailed. +For my daily email, I want to see the title of the poem first, followed +by the author, then a blank line, and finally the full poem. This code +snippet combines that data and packages it into a MIMEText container, +ready to be emailed. -```py +#+begin_src py msg_body = title + "\n" + author + "\n\n" + lines msg = MIMEText(msg_body) -``` +#+end_src -Before we send the email, we need to prepare the metadata (subject, from, to, -etc.): +Before we send the email, we need to prepare the metadata (subject, +from, to, etc.): -```py +#+begin_src py sender_email = 'example@server.local' recipient_emails = ['user@example.com'] msg['Subject'] = 'Your Daily Poem (' + line_count + ' lines)' msg['From'] = sender_email msg['To'] = recipient_email -``` - -### Sending the Email - -Now that I have everything ready to be emailed, the last step is to simply -connect to an SMTP server and send the email out to the recipients. In my case, -I installed `mailutils` on Ubuntu and let my SMTP server be `localhost`. - -```py +#+end_src + +*** Sending the Email +:PROPERTIES: +:CUSTOM_ID: sending-the-email +:END: +Now that I have everything ready to be emailed, the last step is to +simply connect to an SMTP server and send the email out to the +recipients. In my case, I installed =mailutils= on Ubuntu and let my +SMTP server be =localhost=. + +#+begin_src py smtp_server = 'localhost' s = smtplib.SMTP(smtp_server) s.sendmail(sender_email, recipient_emails, msg.as_string()) s.quit() -``` +#+end_src -## The Result! +** The Result! +:PROPERTIES: +:CUSTOM_ID: the-result +:END: +Instead of including a screenshot, I've copied the contents of the email +that was delivered to my inbox below since I set this process up in +plaintext format. -Instead of including a screenshot, I've copied the contents of the email that -was delivered to my inbox below since I set this process up in plaintext format. - -```txt +#+begin_src txt Date: Wed, 22 Jun 2022 14:37:19 +0000 (UTC) From: REDACTED To: REDACTED @@ -190,24 +214,26 @@ You that behold us, laugh us not to scorn; Give Nature thanks you are not such as we. Yet fools and children sometimes tell in play Some, wise in show, more fools indeed than they. -``` - -## Scheduling the Daily Email +#+end_src -Last, but not least, is scheduling this Python script with `crontab`. To -schedule a script to run daily, you can add it to the `crontab` file. To do -this, open `crontab` in editing mode: +** Scheduling the Daily Email +:PROPERTIES: +:CUSTOM_ID: scheduling-the-daily-email +:END: +Last, but not least, is scheduling this Python script with =crontab=. To +schedule a script to run daily, you can add it to the =crontab= file. To +do this, open =crontab= in editing mode: -```sh +#+begin_src sh crontab -e -``` +#+end_src -In the file, simply paste the following snippet at the bottom of the file and -ensure that the file path is correctly pointing to wherever you saved your -Python script: +In the file, simply paste the following snippet at the bottom of the +file and ensure that the file path is correctly pointing to wherever you +saved your Python script: -```config +#+begin_src config 0 8 * * * python3 /home/<your_user>/dailypoem/main.py -``` +#+end_src We have now set up the script and scheduled it to run daily at 08:00! |