<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Robin Goudeketting</title>
    <description>The latest articles on Forem by Robin Goudeketting (@goudekettingrm).</description>
    <link>https://forem.com/goudekettingrm</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F393732%2F36f2b2c5-147f-4016-afd3-028772c30ea8.jpg</url>
      <title>Forem: Robin Goudeketting</title>
      <link>https://forem.com/goudekettingrm</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/goudekettingrm"/>
    <language>en</language>
    <item>
      <title>Automating Insulin Ordering: Rethinking Google Calendar Integration (Part 6)</title>
      <dc:creator>Robin Goudeketting</dc:creator>
      <pubDate>Thu, 22 Aug 2024 12:38:00 +0000</pubDate>
      <link>https://forem.com/goudekettingrm/automating-insulin-ordering-rethinking-google-calendar-integration-part-6-10f1</link>
      <guid>https://forem.com/goudekettingrm/automating-insulin-ordering-rethinking-google-calendar-integration-part-6-10f1</guid>
      <description>&lt;p&gt;After we discussed automating the prescription request and sending emails to the pharmacy, in the previous part of this series, we explored integrating a task scheduler by adding an event to Google Calendar using &lt;code&gt;gcalcli&lt;/code&gt;. However, as promising as this solution seemed, a significant issue has arisen during using the script for a while: the need for reauthentication with Google Calendar every week.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Issue with Google Calendar CLI (gcalcli)
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;gcalcli&lt;/code&gt; is a command-line tool that allows you to interact with your Google Calendar directly from the terminal. It’s convenient for creating, viewing, and managing events without leaving the command line. However, it relies on OAuth 2.0 authentication, and requires you to reauthorize the tool with Google every seven days if you use it via a test application.&lt;/p&gt;

&lt;p&gt;This frequent reauthorization poses a problem for automation. A script designed to run unattended, such as the one we’ve been building to order insulin and schedule reminders, would fail after a week due to this reauthentication requirement. This makes &lt;code&gt;gcalcli&lt;/code&gt; unsuitable for long-term, fully automated tasks, unless we want to open up your google calendar to the world (the regular reauthorization is not required on published applications).&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Reauthentication Happens
&lt;/h2&gt;

&lt;p&gt;Google’s security policies enforce a regular reauthentication process to protect user data. This is particularly stringent for tools like &lt;code&gt;gcalcli&lt;/code&gt; that use OAuth 2.0. Even though this enhances security, it complicates the use of such tools in automated scripts where human intervention is not desired.&lt;/p&gt;

&lt;h2&gt;
  
  
  Alternative Approach - IFTTT
&lt;/h2&gt;

&lt;p&gt;Instead of &lt;code&gt;gcalcli&lt;/code&gt;, I've decided to use IFTTT (if this then that). This is a service that allows you to trigger actions, such as creating a calendar event, by sending an email with a specific tag.&lt;/p&gt;

&lt;p&gt;Here’s how I set it up:&lt;/p&gt;

&lt;h3&gt;
  
  
  Step-by-Step Guide for IFTTT Setup
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Create an IFTTT Account:&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;Sign up for an account using your Google account for easier integration.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Create a New Applet:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Click the “Create” button on the top left of the IFTTT dashboard.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Set Up the Trigger:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Click “Add” on the “If This” section.&lt;/li&gt;
&lt;li&gt;Search for the &lt;code&gt;Email&lt;/code&gt; service and select the “Send IFTTT an email tagged” trigger.&lt;/li&gt;
&lt;li&gt;Input a tag to trigger the event. For example, use &lt;code&gt;insulin_ordered&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Click “Create Trigger.”&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Set Up the Action:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Click “Add” on the “Then That” section.&lt;/li&gt;
&lt;li&gt;Search for &lt;code&gt;Google Calendar&lt;/code&gt; and select the “Create a detailed event” action.&lt;/li&gt;
&lt;li&gt;Connect your Google Calendar if you haven’t done so already.&lt;/li&gt;
&lt;li&gt;Fill out the form using the following details:

&lt;ul&gt;
&lt;li&gt;Title: Pick up insulin&lt;/li&gt;
&lt;li&gt;Start Time: Tomorrow 13:00&lt;/li&gt;
&lt;li&gt;End Time: Tomorrow 13:15&lt;/li&gt;
&lt;li&gt;All Day: Select “No”&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;I left the description and location fields blank.&lt;/li&gt;
&lt;li&gt;Click “Create Action,” then “Continue,” and finally “Create” to finalize the applet.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Test the Setup:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Send an email to &lt;code&gt;trigger@applet.ifttt.com&lt;/code&gt; with the subject &lt;code&gt;#insulin_ordered&lt;/code&gt;. If everything is set up correctly, you should see a new event in your Google Calendar.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Script to Automate Event Creation
&lt;/h2&gt;

&lt;p&gt;Now, we will create a script that sends the email to IFTTT whenever we have successfully sent an email to the pharmacy and need to create a calendar event. This script uses the same SMTP credentials as the email we send to the pharmacy, so it should work without a hitch.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="k"&gt;function &lt;/span&gt;create_event_in_google&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
  &lt;span class="nv"&gt;SMTP_SERVER&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"smtp.gmail.com"&lt;/span&gt;
  &lt;span class="nv"&gt;SMTP_PORT&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"587"&lt;/span&gt;
  &lt;span class="nv"&gt;SMTP_USERNAME&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&amp;lt;your gmail account&amp;gt;"&lt;/span&gt;
  &lt;span class="nv"&gt;SMTP_PASSWORD&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&amp;lt;app password&amp;gt;"&lt;/span&gt;
  &lt;span class="nv"&gt;TO&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"trigger@applet.ifttt.com"&lt;/span&gt;
  &lt;span class="nv"&gt;SUBJECT&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"#insulin_ordered"&lt;/span&gt;
  &lt;span class="nv"&gt;MESSAGE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"Subject: &lt;/span&gt;&lt;span class="nv"&gt;$SUBJECT&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;To: &lt;/span&gt;&lt;span class="nv"&gt;$TO&lt;/span&gt;&lt;span class="se"&gt;\n\n&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;

  curl &lt;span class="nt"&gt;--url&lt;/span&gt; &lt;span class="s2"&gt;"smtp://&lt;/span&gt;&lt;span class="nv"&gt;$SMTP_SERVER&lt;/span&gt;&lt;span class="s2"&gt;:&lt;/span&gt;&lt;span class="nv"&gt;$SMTP_PORT&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
      &lt;span class="nt"&gt;--ssl-reqd&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
      &lt;span class="nt"&gt;--mail-from&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$SMTP_USERNAME&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
      &lt;span class="nt"&gt;--mail-rcpt&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$TO&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
      &lt;span class="nt"&gt;--user&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$SMTP_USERNAME&lt;/span&gt;&lt;span class="s2"&gt;:&lt;/span&gt;&lt;span class="nv"&gt;$SMTP_PASSWORD&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
      &lt;span class="nt"&gt;--tlsv1&lt;/span&gt;.2 &lt;span class="se"&gt;\&lt;/span&gt;
      &lt;span class="nt"&gt;-T&lt;/span&gt; &amp;lt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$MESSAGE&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;

  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="nv"&gt;$?&lt;/span&gt; &lt;span class="nt"&gt;-eq&lt;/span&gt; 0 &lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
      &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Done, created event in Google Calendar"&lt;/span&gt;
      &lt;span class="k"&gt;return &lt;/span&gt;0
  &lt;span class="k"&gt;else
      &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Failed to create event in Google Calendar"&lt;/span&gt;
      &lt;span class="k"&gt;return &lt;/span&gt;1
  &lt;span class="k"&gt;fi&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  How It Works:
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;SMTP Details:&lt;/strong&gt; The script uses the same SMTP configuration as the email sent to your pharmacy.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;IFTTT Trigger:&lt;/strong&gt; The &lt;code&gt;TO&lt;/code&gt; field is set to IFTTT’s trigger email, and the &lt;code&gt;SUBJECT&lt;/code&gt; contains the tag you configured in IFTTT (&lt;code&gt;#insulin_ordered&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Success/Failure Handling:&lt;/strong&gt; The script checks if the email was successfully sent and provides feedback.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This method bypasses the need for &lt;code&gt;gcalcli&lt;/code&gt; and its reauthentication requirement, offering a simple and effective way to automate event creation in Google Calendar.&lt;/p&gt;

&lt;h2&gt;
  
  
  What’s Next?
&lt;/h2&gt;

&lt;p&gt;With the update in place, the next step will be to have this automation run regularly in the background. I can now already order insulin with one command in my terminal, but ideal would be if it runs periodically in the background.&lt;/p&gt;

&lt;p&gt;Stay tuned for any further enhancements and refinements to this process!&lt;/p&gt;

&lt;p&gt;Thank you for following along! If you have any questions or suggestions, feel free to leave a comment below. Don't forget to share this post with anyone who might find it useful.&lt;/p&gt;

</description>
      <category>automation</category>
      <category>programming</category>
      <category>productivity</category>
      <category>processoptimisation</category>
    </item>
    <item>
      <title>Automating Insulin Ordering: Adding an Event to Google Calendar (Part 5)</title>
      <dc:creator>Robin Goudeketting</dc:creator>
      <pubDate>Thu, 06 Jun 2024 08:20:47 +0000</pubDate>
      <link>https://forem.com/goudekettingrm/automating-insulin-ordering-adding-an-event-to-google-calendar-part-5-3bhn</link>
      <guid>https://forem.com/goudekettingrm/automating-insulin-ordering-adding-an-event-to-google-calendar-part-5-3bhn</guid>
      <description>&lt;p&gt;In the previous parts of this series, we discussed capturing the browser request to the GP's website and sending an email to the pharmacy. Now, we will focus on automating the addition of an event to Google Calendar. We're going to be using &lt;code&gt;gcalcli&lt;/code&gt; to reduce the amount of manual labor.&lt;/p&gt;

&lt;h2&gt;
  
  
  Installing &lt;code&gt;gcalcli&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;First, we need to install &lt;code&gt;gcalcli&lt;/code&gt;. I'm using MacOS, so I can install in using homebrew:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;brew &lt;span class="nb"&gt;install &lt;/span&gt;gcalcli
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you're on a different Operating System, check out &lt;a href="https://github.com/insanum/gcalcli" rel="noopener noreferrer"&gt;the gcalcli docs&lt;/a&gt; to find your installation method. &lt;/p&gt;

&lt;h2&gt;
  
  
  Setting Up Google Calendar API
&lt;/h2&gt;

&lt;p&gt;To enable making events, we need to create a project in the Google Developer Console and set up OAuth credentials. Otherwise Google does not allow us using the Calendar API to create events. Here are the steps I used:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 1.&lt;/strong&gt; Go to &lt;a href="https://console.developers.google.com" rel="noopener noreferrer"&gt;Google Developers Console&lt;/a&gt; and create a new project, e.g., gcalcli or Insulin Orderer. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4jd2uqijyibdbgt5kpcv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4jd2uqijyibdbgt5kpcv.png" alt="Create a new project in the modal" width="800" height="191"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 2.&lt;/strong&gt; In the left sidebar, click Enabled APIs and Services and click on "+ Enable APIs and Services". Look for the Google Calendar API and enable it.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0x78bivtlxrblrlndvx9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0x78bivtlxrblrlndvx9.png" alt="Look for the Google Calendar API" width="800" height="365"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 3.&lt;/strong&gt; Create Credentials:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Go back to the project gcalcli in the Developers Console.&lt;/li&gt;
&lt;li&gt;Navigate to the "Credentials" section in the left menu.&lt;/li&gt;
&lt;li&gt;Click "+ Create Credentials" &amp;gt; "OAuth client ID".&lt;/li&gt;
&lt;li&gt;Choose "Application type Desktop App".&lt;/li&gt;
&lt;li&gt;Name it gcalcli.&lt;/li&gt;
&lt;li&gt;The credentials produced here are needed in step 5.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Step 4.&lt;/strong&gt; OAuth Consent Screen:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Navigate to the "OAuth consent screen" section in the left menu.&lt;/li&gt;
&lt;li&gt;Select "External" users.&lt;/li&gt;
&lt;li&gt;Fill in the App name (e.g., gcalcli), User support email, and Developer contact information with your Gmail address.&lt;/li&gt;
&lt;li&gt;Leave the App domain blank.&lt;/li&gt;
&lt;li&gt;For Scopes, choose all calendar API-related scopes.&lt;/li&gt;
&lt;li&gt;Add your Gmail address as a Test user.&lt;/li&gt;
&lt;li&gt;Save everything and then go back to the dashboard. It is important to leave the Publishing status as Testing, otherwise your google calendar will be openly available to the world.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Step 5.&lt;/strong&gt; Authenticate locally:&lt;br&gt;
There are two ways in which you can authenticate your machine to enable interacting with Google Calendar. Either you login using the OAuth screen from google or you create a configuration file. &lt;/p&gt;

&lt;p&gt;To login using the Google OAuth screen, paste the following command into your terminal (here you of course change the values of the &lt;code&gt;--client-id&lt;/code&gt; and &lt;code&gt;--client-secret&lt;/code&gt;):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;gcalcli &lt;span class="nt"&gt;--client-id&lt;/span&gt; &lt;span class="s2"&gt;"your client ID ending in ...apps.googleusercontent.com"&lt;/span&gt; &lt;span class="nt"&gt;--client-secret&lt;/span&gt; &lt;span class="s2"&gt;"your client secret"&lt;/span&gt; agenda
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will open your browser and allow you to login. &lt;/p&gt;

&lt;p&gt;Alternatively, you can create a configuration file like this: &lt;code&gt;touch ~/.gcalclirc&lt;/code&gt;. Then edit this file and add the following to it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nt"&gt;--client-id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"your client ID ending in ...apps.googleusercontent.com"&lt;/span&gt; &lt;span class="nt"&gt;--client-secret&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"your client secret"&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In either case, after you've done this, you should be able to run &lt;code&gt;gcalcli agenda&lt;/code&gt; and it should show you your agenda items.&lt;/p&gt;

&lt;h2&gt;
  
  
  Adding a Task to Google Calendar
&lt;/h2&gt;

&lt;p&gt;To check if the gcalcli command works, run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;gcalcli add
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If this command runs correctly, it will ask you a few questions regarding the event you want to add. The most important parts are 'Title', 'When', 'Duration', and to which calendar to add the event to. Since I have access to multiple calendars, I needed to select the calendar to add the event to. I copied the name of the calendar to use in the command itself.&lt;/p&gt;

&lt;p&gt;Here is the command I use to add an event to my Google Calendar:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;gcalcli add &lt;span class="nt"&gt;--calendar&lt;/span&gt; &lt;span class="s1"&gt;'Calendar Name'&lt;/span&gt; &lt;span class="nt"&gt;--title&lt;/span&gt; &lt;span class="s1"&gt;'Pick up insulin'&lt;/span&gt; &lt;span class="nt"&gt;--when&lt;/span&gt; &lt;span class="s1"&gt;'Tomorrow 13:00'&lt;/span&gt; &lt;span class="nt"&gt;--duration&lt;/span&gt; 15 &lt;span class="nt"&gt;--noprompt&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will add the event to the calendar with name &lt;code&gt;Calendar Name&lt;/code&gt;. The title of the event will be &lt;code&gt;Pick up insulin&lt;/code&gt;. It will be an event of 15 minutes and it will be scheduled for tomorrow at 13:00. Tomorrow is important, because it can take up to 24h before the prescription is available on my insurance card. Lastly, &lt;code&gt;--noprompt&lt;/code&gt; will ensure that if data is missing (like the Location), it will not go into interactive mode to fill in the missing information, which is important for a script that needs to run autonomously.&lt;/p&gt;

&lt;p&gt;The command can be added into the bash function relatively simply:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="k"&gt;function &lt;/span&gt;add_calendar_task&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
  gcalcli add &lt;span class="nt"&gt;--calendar&lt;/span&gt; &lt;span class="s1"&gt;'Robin Goudeketting (privé)'&lt;/span&gt; &lt;span class="nt"&gt;--title&lt;/span&gt; &lt;span class="s1"&gt;'Pick up insulin'&lt;/span&gt; &lt;span class="nt"&gt;--when&lt;/span&gt; &lt;span class="s1"&gt;'Tomorrow 13:00'&lt;/span&gt; &lt;span class="nt"&gt;--duration&lt;/span&gt; 15 &lt;span class="nt"&gt;--noprompt&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  What’s Next?
&lt;/h2&gt;

&lt;p&gt;With the complete automation script in place, the next step will be to have this automation run regularly in the background. I can now already order insulin with one command in my terminal, but ideal would be if it runs periodically in the background.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://dev.to/goudekettingrm/automating-insulin-ordering-rethinking-google-calendar-integration-part-6-10f1"&gt;Read part 6&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Thank you for following along! If you have any questions or suggestions, feel free to leave a comment below. Don't forget to share this post with anyone who might find it useful.&lt;/p&gt;

</description>
      <category>automation</category>
      <category>productivity</category>
      <category>programming</category>
      <category>processoptimisation</category>
    </item>
    <item>
      <title>Automating Insulin Ordering: Sending the Email to the Pharmacy (Part 4)</title>
      <dc:creator>Robin Goudeketting</dc:creator>
      <pubDate>Wed, 05 Jun 2024 07:34:51 +0000</pubDate>
      <link>https://forem.com/goudekettingrm/automating-insulin-ordering-sending-the-email-to-the-pharmacy-part-4-1bp</link>
      <guid>https://forem.com/goudekettingrm/automating-insulin-ordering-sending-the-email-to-the-pharmacy-part-4-1bp</guid>
      <description>&lt;p&gt;In this part of the series, we will focus on automating the step of sending an email to the pharmacy to pre-order insulin. We will use Gmail's SMTP server to send the email directly to the pharmacy's inbox. For this, we need the SMTP server details and our account credentials.&lt;/p&gt;

&lt;p&gt;I made the choice to use Gmail, because my email in known in the inbox of my pharmacy and therefore my automated email will be unlikely to land in their spam. It also allows my pharmacy to answer my email without me having to worry about anything.&lt;/p&gt;

&lt;h2&gt;
  
  
  Setting Up Gmail SMTP
&lt;/h2&gt;

&lt;p&gt;If you have 2FA enabled, you'll need to create an app password:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Go to Gmail and click on your avatar.&lt;/li&gt;
&lt;li&gt;Select "Manage your Google Account".&lt;/li&gt;
&lt;li&gt;Navigate to the "Security" section.&lt;/li&gt;
&lt;li&gt;Search for "App passwords" in the search bar.&lt;/li&gt;
&lt;li&gt;Create a new app password and use it for sending the email.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;If you don't have 2FA enabled, you would need to allow less secure apps to use your email address, but I highly recommend to use 2FA for security reasons.&lt;/p&gt;

&lt;h2&gt;
  
  
  Sending the Email Using cURL
&lt;/h2&gt;

&lt;p&gt;We will use cURL to send the email via Gmail's SMTP server. Here’s the basic structure of the cURL command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;--url&lt;/span&gt; &lt;span class="s2"&gt;"smtp://&lt;/span&gt;&lt;span class="nv"&gt;$SMTP_SERVER&lt;/span&gt;&lt;span class="s2"&gt;:&lt;/span&gt;&lt;span class="nv"&gt;$SMTP_PORT&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--ssl-reqd&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--mail-from&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$SMTP_USERNAME&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--mail-rcpt&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$TO&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--user&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$SMTP_USERNAME&lt;/span&gt;&lt;span class="s2"&gt;:&lt;/span&gt;&lt;span class="nv"&gt;$SMTP_PASSWORD&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--tlsv1&lt;/span&gt;.2 &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;-T&lt;/span&gt; &amp;lt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$MESSAGE&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Gathering the Required Data
&lt;/h2&gt;

&lt;p&gt;To send the email, we need to fill in the data in the request above. This means we need the following data:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;SMTP server: &lt;code&gt;smtp.gmail.com&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;SMTP port: &lt;code&gt;587&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;SMTP username: Your Gmail account email&lt;/li&gt;
&lt;li&gt;SMTP password: The app password created in your Google account management dashboard&lt;/li&gt;
&lt;li&gt;Recipient email address: The email address of the pharmacy&lt;/li&gt;
&lt;li&gt;Subject and body of the email: The actual content of the email&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The message in the email will be added in the last line of the curl request. The email message should consist of a list of headers and then the body text. Each header is the header name, followed by a colon and then the value. The most basic setup for this would be something like: &lt;code&gt;Subject: &amp;lt;The Subject&amp;gt;\n\n&amp;lt;Email Body&amp;gt;&lt;/code&gt;. Here, the &lt;code&gt;Subject:&lt;/code&gt; is the header. For me, that would look something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;SUBJECT&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"Preorder insulin"&lt;/span&gt;
&lt;span class="nv"&gt;BODY&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;$'Hello&lt;/span&gt;&lt;span class="se"&gt;\n\n&lt;/span&gt;&lt;span class="s1"&gt;I would like a new insulin prescription.&lt;/span&gt;&lt;span class="se"&gt;\n\n&lt;/span&gt;&lt;span class="s1"&gt;Thanks,&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s1"&gt;Robin'&lt;/span&gt;

&lt;span class="nv"&gt;MESSAGE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"Subject: &lt;/span&gt;&lt;span class="nv"&gt;$SUBJECT&lt;/span&gt;&lt;span class="se"&gt;\n\n&lt;/span&gt;&lt;span class="nv"&gt;$BODY&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The last thing I want to do in this script is send a copy of the email to myself as a BCC address. This way, I will get a push notification from gmail every time this automation triggers. To do that, we need to ensure that the true recipient is added as a header to the message on it's own line (&lt;code&gt;To: $TO&lt;/code&gt;). If we then add another email recipient in the curl request, it will be pushed to the BCC list. So my message would look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;MESSAGE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"Subject: &lt;/span&gt;&lt;span class="nv"&gt;$SUBJECT&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;To: &lt;/span&gt;&lt;span class="nv"&gt;$TO&lt;/span&gt;&lt;span class="se"&gt;\n\n&lt;/span&gt;&lt;span class="nv"&gt;$BODY&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If we then add &lt;code&gt;--mail-rcpt "$SMTP_USERNAME"\&lt;/code&gt; to the curl request, a BCC will be sent to the &lt;code&gt;$SMTP_USERNAME&lt;/code&gt; email address. &lt;/p&gt;

&lt;h2&gt;
  
  
  Complete Script
&lt;/h2&gt;

&lt;p&gt;Below is the complete script to send the email to the pharmacy. It includes error handling to ensure the email is sent successfully.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="k"&gt;function &lt;/span&gt;send_pharmacy_email&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
  &lt;span class="c"&gt;# Set the default value to true to prevent sending too many emails to my pharmacy while testing&lt;/span&gt;
  &lt;span class="nb"&gt;test&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;1&lt;/span&gt;&lt;span class="k"&gt;:-&lt;/span&gt;&lt;span class="nv"&gt;true&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;

  &lt;span class="nv"&gt;SMTP_SERVER&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"smtp.gmail.com"&lt;/span&gt;
  &lt;span class="nv"&gt;SMTP_PORT&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"587"&lt;/span&gt;
  &lt;span class="nv"&gt;SMTP_USERNAME&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&amp;lt;gmail account email to use&amp;gt;"&lt;/span&gt;
  &lt;span class="nv"&gt;SMTP_PASSWORD&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&amp;lt;app password&amp;gt;"&lt;/span&gt;

  &lt;span class="c"&gt;# Recipient email address&lt;/span&gt;
  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[[&lt;/span&gt; &lt;span class="nv"&gt;$test&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s1"&gt;'true'&lt;/span&gt; &lt;span class="o"&gt;]]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
      &lt;/span&gt;&lt;span class="nv"&gt;TO&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"testemail@test.com"&lt;/span&gt;
  &lt;span class="k"&gt;else
      &lt;/span&gt;&lt;span class="nv"&gt;TO&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"mypharmacy@pharmacy.com"&lt;/span&gt;
  &lt;span class="k"&gt;fi

  &lt;/span&gt;&lt;span class="nv"&gt;SUBJECT&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"Preorder insulin"&lt;/span&gt;
  &lt;span class="nv"&gt;BODY&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;$'Hello&lt;/span&gt;&lt;span class="se"&gt;\n\n&lt;/span&gt;&lt;span class="s1"&gt;I would like a new insulin prescription.&lt;/span&gt;&lt;span class="se"&gt;\n\n&lt;/span&gt;&lt;span class="s1"&gt;Thanks,&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s1"&gt;Robin'&lt;/span&gt;

  &lt;span class="nv"&gt;MESSAGE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"Subject: &lt;/span&gt;&lt;span class="nv"&gt;$SUBJECT&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;To: &lt;/span&gt;&lt;span class="nv"&gt;$TO&lt;/span&gt;&lt;span class="se"&gt;\n\n&lt;/span&gt;&lt;span class="nv"&gt;$BODY&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;

  curl &lt;span class="nt"&gt;--url&lt;/span&gt; &lt;span class="s2"&gt;"smtp://&lt;/span&gt;&lt;span class="nv"&gt;$SMTP_SERVER&lt;/span&gt;&lt;span class="s2"&gt;:&lt;/span&gt;&lt;span class="nv"&gt;$SMTP_PORT&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
      &lt;span class="nt"&gt;--ssl-reqd&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
      &lt;span class="nt"&gt;--mail-from&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$SMTP_USERNAME&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
      &lt;span class="nt"&gt;--mail-rcpt&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$TO&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
      &lt;span class="nt"&gt;--mail-rcpt&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$SMTP_USERNAME&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
      &lt;span class="nt"&gt;--user&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$SMTP_USERNAME&lt;/span&gt;&lt;span class="s2"&gt;:&lt;/span&gt;&lt;span class="nv"&gt;$SMTP_PASSWORD&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
      &lt;span class="nt"&gt;--tlsv1&lt;/span&gt;.2 &lt;span class="se"&gt;\&lt;/span&gt;
      &lt;span class="nt"&gt;-T&lt;/span&gt; &amp;lt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$MESSAGE&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;

  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="nv"&gt;$?&lt;/span&gt; &lt;span class="nt"&gt;-eq&lt;/span&gt; 0 &lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
      &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Done, e-mail sent to &lt;/span&gt;&lt;span class="nv"&gt;$TO&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
      &lt;span class="k"&gt;return &lt;/span&gt;0
  &lt;span class="k"&gt;else
      &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Failed to send email"&lt;/span&gt;
      &lt;span class="k"&gt;return &lt;/span&gt;1
  &lt;span class="k"&gt;fi&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Testing this in my terminal result into the following output. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyun0a7cri5aivadtrmwa.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyun0a7cri5aivadtrmwa.png" alt="Terminal output after running the function" width="671" height="98"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Moreover, the proof of the pudding as it were, in the inbox of my test email address I see the email come in correctly.&lt;/p&gt;

&lt;p&gt;I added a test variable that defaults to true to prevent sending an overload of messages to my pharmacy while working on the script. That means that once the script should actually run automatically, we need to pass an argument to the &lt;code&gt;send_pharmacy_email&lt;/code&gt; function in the wrapper to ensure it doesn't run in test mode anymore.&lt;/p&gt;

&lt;h2&gt;
  
  
  What’s Next?
&lt;/h2&gt;

&lt;p&gt;In the next part of this series, we will focus on implementing the add_calendar_task function, which automates adding a task to Google Calendar to remind you to pick up the insulin.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://dev.to/goudekettingrm/automating-insulin-ordering-adding-an-event-to-google-calendar-part-5-3bhn"&gt;Read part 5&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Thank you for following along! If you have any questions or suggestions, feel free to leave a comment below. Don't forget to share this post with anyone who might find it useful.&lt;/p&gt;

</description>
      <category>programming</category>
      <category>productivity</category>
      <category>automation</category>
      <category>processoptimisation</category>
    </item>
    <item>
      <title>Automating Insulin Ordering: Creating the Wrapping Function (Part 3)</title>
      <dc:creator>Robin Goudeketting</dc:creator>
      <pubDate>Tue, 04 Jun 2024 08:20:07 +0000</pubDate>
      <link>https://forem.com/goudekettingrm/automating-insulin-ordering-creating-the-wrapping-function-part-3-517k</link>
      <guid>https://forem.com/goudekettingrm/automating-insulin-ordering-creating-the-wrapping-function-part-3-517k</guid>
      <description>&lt;p&gt;In the previous parts of this series, we discussed capturing the browser request to the GP's website and converting it into a cURL command. We also created a bash function to automate this request. Now, we'll take the next step by creating a wrapping function that orchestrates the entire automation process.&lt;/p&gt;

&lt;h2&gt;
  
  
  Updating the order_insulin Function
&lt;/h2&gt;

&lt;p&gt;To facilitate the wrapping function, we first need to update our order_insulin function to return an exit code. The function should return &lt;code&gt;0&lt;/code&gt; if the prescription request is successful and &lt;code&gt;1&lt;/code&gt; if it fails. I also renamed it, to actually capture the step of the process it does. Here’s the updated function:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="k"&gt;function &lt;/span&gt;request_prescription&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
  &lt;span class="nv"&gt;insulin_order_response&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&amp;lt;cURL Request&amp;gt;&lt;span class="si"&gt;)&lt;/span&gt;

  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="nv"&gt;$?&lt;/span&gt; &lt;span class="nt"&gt;-eq&lt;/span&gt; 0 &lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
      &lt;/span&gt;&lt;span class="nv"&gt;insulin_order_status&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="nv"&gt;$insulin_order_response&lt;/span&gt; | jq &lt;span class="nt"&gt;-r&lt;/span&gt; &lt;span class="s1"&gt;'.status'&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;
      &lt;span class="nv"&gt;insulin_order_message&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="nv"&gt;$insulin_order_response&lt;/span&gt; | jq &lt;span class="nt"&gt;-r&lt;/span&gt; &lt;span class="s1"&gt;'.message'&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;

      &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[[&lt;/span&gt; &lt;span class="nv"&gt;$insulin_order_status&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s2"&gt;"mail_sent"&lt;/span&gt; &lt;span class="o"&gt;]]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
          &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Ordered: &lt;/span&gt;&lt;span class="nv"&gt;$insulin_order_message&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
          &lt;span class="k"&gt;return &lt;/span&gt;0
      &lt;span class="k"&gt;else
          &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Something went wrong, order via the website and update the curl request"&lt;/span&gt;
          &lt;span class="k"&gt;return &lt;/span&gt;1
      &lt;span class="k"&gt;fi
  else
      &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Something went wrong, order via the website and update the curl request"&lt;/span&gt;
      &lt;span class="k"&gt;return &lt;/span&gt;1
  &lt;span class="k"&gt;fi&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Creating the Wrapping Function
&lt;/h2&gt;

&lt;p&gt;Next, we need a wrapping function that triggers the prescription request and checks the exit code. If the prescription request is successful, it will proceed to the next steps: sending an email to the pharmacy (Step 4) and adding a task to Google Calendar (Step 5). These two steps will be implemented in future articles, but we will set up the structure for them now.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="k"&gt;function &lt;/span&gt;order_insulin&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
  request_prescription
  &lt;span class="nv"&gt;exit_code&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$?&lt;/span&gt;

  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[[&lt;/span&gt; &lt;span class="nv"&gt;$exit_code&lt;/span&gt; &lt;span class="nt"&gt;-ne&lt;/span&gt; 0 &lt;span class="o"&gt;]]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
    &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Prescription request failed"&lt;/span&gt;
    &lt;span class="k"&gt;return &lt;/span&gt;1
  &lt;span class="k"&gt;fi

  &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Prescription requested successfully"&lt;/span&gt;

  send_pharmacy_email
  &lt;span class="nv"&gt;email_exit_code&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$?&lt;/span&gt;

  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[[&lt;/span&gt; &lt;span class="nv"&gt;$email_exit_code&lt;/span&gt; &lt;span class="nt"&gt;-ne&lt;/span&gt; 0 &lt;span class="o"&gt;]]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
    &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Failed to send email to pharmacy"&lt;/span&gt;
    &lt;span class="k"&gt;return &lt;/span&gt;1
  &lt;span class="k"&gt;fi

  &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Email sent successfully"&lt;/span&gt;

  add_calendar_task
  &lt;span class="nv"&gt;calendar_exit_code&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$?&lt;/span&gt;

  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[[&lt;/span&gt; &lt;span class="nv"&gt;$calendar_exit_code&lt;/span&gt; &lt;span class="nt"&gt;-ne&lt;/span&gt; 0 &lt;span class="o"&gt;]]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
    &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Calendar task added successfully"&lt;/span&gt;
    &lt;span class="k"&gt;return &lt;/span&gt;0
  &lt;span class="k"&gt;else
    &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Failed to add calendar task"&lt;/span&gt;
    &lt;span class="k"&gt;return &lt;/span&gt;1
  &lt;span class="k"&gt;fi&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Of course, these two functions do not yet exist, but they will soon. I added early returns in the cases that the other methods fail, as well as returns for the error or success states. This will allow me to add some error handling in the future, if I think it's needed.&lt;/p&gt;

&lt;h2&gt;
  
  
  Explanation of the Wrapping Function
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;order_insulin Function&lt;/strong&gt;: This is the main wrapping function that coordinates the entire process. It calls the request_prescription function and checks its exit code to determine the next steps.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Exit Code Check&lt;/strong&gt;: The function checks if the request_prescription function returns 0 (success). If successful, it proceeds to the next steps.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Step 4 - Sending Email to Pharmacy&lt;/strong&gt;: The function send_pharmacy_email is called. The script checks the exit code of this function to determine if the email was sent successfully.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Step 5 - Adding Task to Google Calendar&lt;/strong&gt;: If the email was sent successfully, the function add_calendar_task is called. The script checks the exit code of this function to determine if the calendar task was added successfully.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What’s Next?
&lt;/h2&gt;

&lt;p&gt;In the next part of this series, we will focus on implementing the send_pharmacy_email function, which automates sending an email to the pharmacy to pre-order the insulin.&lt;/p&gt;

&lt;p&gt;Stay tuned as we continue to streamline the insulin ordering process, one step at a time.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://dev.to/goudekettingrm/automating-insulin-ordering-sending-the-email-to-the-pharmacy-part-4-1bp"&gt;Read part 4&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Thank you for following along! If you have any questions or suggestions, feel free to leave a comment below. Don't forget to share this post with anyone who might find it useful.&lt;/p&gt;

</description>
      <category>programming</category>
      <category>productivity</category>
      <category>automation</category>
      <category>processoptimisation</category>
    </item>
    <item>
      <title>Automating Insulin Ordering: Capturing the GP Request (Part 2)</title>
      <dc:creator>Robin Goudeketting</dc:creator>
      <pubDate>Tue, 04 Jun 2024 08:19:06 +0000</pubDate>
      <link>https://forem.com/goudekettingrm/automating-insulin-ordering-capturing-the-gp-request-part-2-4pl0</link>
      <guid>https://forem.com/goudekettingrm/automating-insulin-ordering-capturing-the-gp-request-part-2-4pl0</guid>
      <description>&lt;p&gt;In the first part of this series, I outlined the problem of manually ordering my insulin and introduced the idea of automating this process. Now, we will dive into the first step of this automation: figuring out how to send a request to my GP using a cURL command.&lt;/p&gt;

&lt;h2&gt;
  
  
  Capturing the Browser Request
&lt;/h2&gt;

&lt;p&gt;To understand how my GP’s website processes the prescription request, I went to their site and filled out the necessary form. Before hitting the send button, I opened my browser's network tab to log all outgoing queries. This step is crucial as it allows us to see the exact request being sent to the server. Before submitting the form, I cleared all the network requests that it had already logged to ensure I would only see the query or queries that are triggered upon the form submission.  Once I'd done that, I filled in the form and checked the queries that appeared.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Faerfq447cirmpxtvai9s.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Faerfq447cirmpxtvai9s.png" alt="Network tab with the relevant network request" width="800" height="320"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I then submitted the form and I observed two network requests. I inspected both and saw that the one labeled &lt;code&gt;Feedback&lt;/code&gt; was the request that actually sent my information to my GP and it contained all the information I had entered. This request is the key to our automation. The server's response was a confirmation message stating that the prescription would be uploaded to my health insurance card within 24 hours.&lt;/p&gt;

&lt;h2&gt;
  
  
  Analysing the Request
&lt;/h2&gt;

&lt;p&gt;The requests from the network tab are easily copy-able. You just right click the request, and then copy &amp;gt; copy as X. I copied the request as cURL. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqupuqn9p5yzklcli3wuv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqupuqn9p5yzklcli3wuv.png" alt="How to copy the outgoing network request" width="800" height="395"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I moved it over to a code editor to analyse it in depth. The request included headers, the payload, and other parameters essential for successful submission. Here's a redacted version of the cURL command derived from the network request:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="s1"&gt;'https://www.mygp.com/order-insulin'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s1"&gt;'accept: application/json, */*;q=0.1'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s1"&gt;'accept-language: en-GB,en;q=0.5'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s1"&gt;'cache-control: no-cache'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s1"&gt;'content-type: multipart/form-data; boundary=----WebKitFormBoundarynE0B7A3bJADDu4sV'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s1"&gt;'origin: https://www.mygp.com'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s1"&gt;'pragma: no-cache'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s1"&gt;'sec-ch-ua-mobile: ?0'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s1"&gt;'sec-fetch-dest: empty'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s1"&gt;'sec-fetch-mode: cors'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s1"&gt;'sec-fetch-site: same-origin'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s1"&gt;'sec-gpc: 1'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s1"&gt;'user-agent: MyDevice'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--data-raw&lt;/span&gt; &lt;span class="s1"&gt;$'------WebKitFormBoundarynE0B7A3bJADDu4sV&lt;/span&gt;&lt;span class="se"&gt;\r\n&lt;/span&gt;&lt;span class="s1"&gt;Content-Disposition: form-data; name="_wpcf7"&lt;/span&gt;&lt;span class="se"&gt;\r\n\r\n&lt;/span&gt;&lt;span class="s1"&gt;834&lt;/span&gt;&lt;span class="se"&gt;\r\n&lt;/span&gt;&lt;span class="s1"&gt;------WebKitFormBoundarynE0B7A3bJADDu4sV&lt;/span&gt;&lt;span class="se"&gt;\r\n&lt;/span&gt;&lt;span class="s1"&gt;Content-Disposition: form-data; name="_wpcf7_version"&lt;/span&gt;&lt;span class="se"&gt;\r\n\r\n&lt;/span&gt;&lt;span class="s1"&gt;5.9.3&lt;/span&gt;&lt;span class="se"&gt;\r\n&lt;/span&gt;&lt;span class="s1"&gt;------WebKitFormBoundarynE0B7A3bJADDu4sV&lt;/span&gt;&lt;span class="se"&gt;\r\n&lt;/span&gt;&lt;span class="s1"&gt;Content-Disposition: form-data; name="_wpcf7_locale"&lt;/span&gt;&lt;span class="se"&gt;\r\n\r\n&lt;/span&gt;&lt;span class="s1"&gt;de_DE_formal&lt;/span&gt;&lt;span class="se"&gt;\r\n&lt;/span&gt;&lt;span class="s1"&gt;------WebKitFormBoundarynE0B7A3bJADDu4sV&lt;/span&gt;&lt;span class="se"&gt;\r\n&lt;/span&gt;&lt;span class="s1"&gt;Content-Disposition: form-data; name="_wpcf7_unit_tag"&lt;/span&gt;&lt;span class="se"&gt;\r\n\r\n&lt;/span&gt;&lt;span class="s1"&gt;wpcf7-f834-p922-o1&lt;/span&gt;&lt;span class="se"&gt;\r\n&lt;/span&gt;&lt;span class="s1"&gt;------WebKitFormBoundarynE0B7A3bJADDu4sV&lt;/span&gt;&lt;span class="se"&gt;\r\n&lt;/span&gt;&lt;span class="s1"&gt;Content-Disposition: form-data; name="_wpcf7_container_post"&lt;/span&gt;&lt;span class="se"&gt;\r\n\r\n&lt;/span&gt;&lt;span class="s1"&gt;922&lt;/span&gt;&lt;span class="se"&gt;\r\n&lt;/span&gt;&lt;span class="s1"&gt;------WebKitFormBoundarynE0B7A3bJADDu4sV&lt;/span&gt;&lt;span class="se"&gt;\r\n&lt;/span&gt;&lt;span class="s1"&gt;Content-Disposition: form-data; name="_wpcf7_posted_data_hash"&lt;/span&gt;&lt;span class="se"&gt;\r\n\r\n\r\n&lt;/span&gt;&lt;span class="s1"&gt;------WebKitFormBoundarynE0B7A3bJADDu4sV&lt;/span&gt;&lt;span class="se"&gt;\r\n&lt;/span&gt;&lt;span class="s1"&gt;Content-Disposition: form-data; name="name"&lt;/span&gt;&lt;span class="se"&gt;\r\n\r\M&lt;/span&gt;&lt;span class="s1"&gt;YNAME&lt;/span&gt;&lt;span class="se"&gt;\r\n&lt;/span&gt;&lt;span class="s1"&gt;------WebKitFormBoundarynE0B7A3bJADDu4sV&lt;/span&gt;&lt;span class="se"&gt;\r\n&lt;/span&gt;&lt;span class="s1"&gt;Content-Disposition: form-data; name="insurance-number"&lt;/span&gt;&lt;span class="se"&gt;\r\n\r\n&lt;/span&gt;&lt;span class="s1"&gt;INSURANCENUMBER&lt;/span&gt;&lt;span class="se"&gt;\r\n&lt;/span&gt;&lt;span class="s1"&gt;------WebKitFormBoundarynE0B7A3bJADDu4sV&lt;/span&gt;&lt;span class="se"&gt;\r\n&lt;/span&gt;&lt;span class="s1"&gt;Content-Disposition: form-data; name="phone"&lt;/span&gt;&lt;span class="se"&gt;\r\n\r\n&lt;/span&gt;&lt;span class="s1"&gt;MYPHONENUMBER&lt;/span&gt;&lt;span class="se"&gt;\r\n&lt;/span&gt;&lt;span class="s1"&gt;------WebKitFormBoundarynE0B7A3bJADDu4sV&lt;/span&gt;&lt;span class="se"&gt;\r\n&lt;/span&gt;&lt;span class="s1"&gt;Content-Disposition: form-data; name="email-195"&lt;/span&gt;&lt;span class="se"&gt;\r\n\r\n&lt;/span&gt;&lt;span class="s1"&gt;MYEMAIL@EMAIL.COM&lt;/span&gt;&lt;span class="se"&gt;\r\n&lt;/span&gt;&lt;span class="s1"&gt;------WebKitFormBoundarynE0B7A3bJADDu4sV&lt;/span&gt;&lt;span class="se"&gt;\r\n&lt;/span&gt;&lt;span class="s1"&gt;Content-Disposition: form-data; name="order"&lt;/span&gt;&lt;span class="se"&gt;\r\n\r\n&lt;/span&gt;&lt;span class="s1"&gt;THE ORDER INFORMATION GOES HERE&lt;/span&gt;&lt;span class="se"&gt;\r\n&lt;/span&gt;&lt;span class="s1"&gt;------WebKitFormBoundarynE0B7A3bJADDu4sV&lt;/span&gt;&lt;span class="se"&gt;\r\n&lt;/span&gt;&lt;span class="s1"&gt;Content-Disposition: form-data; name="acceptance-255"&lt;/span&gt;&lt;span class="se"&gt;\r\n\r\n&lt;/span&gt;&lt;span class="s1"&gt;1&lt;/span&gt;&lt;span class="se"&gt;\r\n&lt;/span&gt;&lt;span class="s1"&gt;------WebKitFormBoundarynE0B7A3bJADDu4sV--&lt;/span&gt;&lt;span class="se"&gt;\r\n&lt;/span&gt;&lt;span class="s1"&gt;'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Breaking Down the cURL Command
&lt;/h2&gt;

&lt;p&gt;Let's break down what happens in this cURL command:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;curl '&lt;a href="https://www.mygp.com/order-insulin"&gt;https://www.mygp.com/order-insulin&lt;/a&gt;'&lt;/strong&gt;: This initiates a POST request to the specified URL.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;-H 'accept: application/json, &lt;em&gt;/&lt;/em&gt;;q=0.1'&lt;/strong&gt;: Specifies that the request can accept JSON responses.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;-H 'accept-language: en-GB,en;q=0.5'&lt;/strong&gt;: Specifies the preferred language for the response.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;-H 'cache-control: no-cache'&lt;/strong&gt;: Ensures that the request bypasses any cached responses.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;-H 'content-type: multipart/form-data; boundary=----WebKitFormBoundarynE0B7A3bJADDu4sV'&lt;/strong&gt;: Sets the content type to multipart/form-data, which is required for file uploads and form submissions.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;-H 'origin: &lt;a href="https://www.mygp.com"&gt;https://www.mygp.com&lt;/a&gt;'&lt;/strong&gt;: Specifies the origin of the request.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;-H 'pragma: no-cache'&lt;/strong&gt;: Similar to cache-control, it instructs the server not to cache the request.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;-H 'sec-ch-ua...'&lt;/strong&gt;: These headers provide additional information about the user agent and its platform.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;--data-raw '...'&lt;/strong&gt;: This flag sends the form data in the request body, including my name, insurance number, contact details, and the medication details.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Some of these headers might be superfluous, but I figured it would be best for me to just leave the request as is. That would limit the potential issues with sending it via my terminal later.&lt;/p&gt;

&lt;h2&gt;
  
  
  Automating the Request
&lt;/h2&gt;

&lt;p&gt;To automate this process, I created a bash function that uses the cURL command to send the request to my GP's website. This function will be the backbone of our automation script, ensuring that the prescription request is sent automatically. &lt;/p&gt;

&lt;p&gt;I am using oh-my-zsh and I have a file sourced in my .zshrc in which I add custom methods. However, it would work identically if you put the function into .bashrc or .zshrc directly.&lt;/p&gt;

&lt;p&gt;Here's the script:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="k"&gt;function &lt;/span&gt;order_insulin&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
  &lt;span class="nv"&gt;insulin_order_response&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;curl &lt;span class="s1"&gt;'https://www.mygp.com/order-insulin'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s1"&gt;'accept: application/json, */*;q=0.1'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s1"&gt;'accept-language: en-GB,en;q=0.5'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s1"&gt;'cache-control: no-cache'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s1"&gt;'content-type: multipart/form-data; boundary=----WebKitFormBoundarynE0B7A3bJADDu4sV'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s1"&gt;'origin: https://www.mygp.com'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s1"&gt;'pragma: no-cache'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s1"&gt;'sec-ch-ua-mobile: ?0'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s1"&gt;'sec-fetch-dest: empty'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s1"&gt;'sec-fetch-mode: cors'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s1"&gt;'sec-fetch-site: same-origin'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s1"&gt;'sec-gpc: 1'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s1"&gt;'user-agent: MyDevice'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--data-raw&lt;/span&gt; &lt;span class="s1"&gt;$'------WebKitFormBoundarynE0B7A3bJADDu4sV&lt;/span&gt;&lt;span class="se"&gt;\r\n&lt;/span&gt;&lt;span class="s1"&gt;Content-Disposition: form-data; name="_wpcf7"&lt;/span&gt;&lt;span class="se"&gt;\r\n\r\n&lt;/span&gt;&lt;span class="s1"&gt;834&lt;/span&gt;&lt;span class="se"&gt;\r\n&lt;/span&gt;&lt;span class="s1"&gt;------WebKitFormBoundarynE0B7A3bJADDu4sV&lt;/span&gt;&lt;span class="se"&gt;\r\n&lt;/span&gt;&lt;span class="s1"&gt;Content-Disposition: form-data; name="_wpcf7_version"&lt;/span&gt;&lt;span class="se"&gt;\r\n\r\n&lt;/span&gt;&lt;span class="s1"&gt;5.9.3&lt;/span&gt;&lt;span class="se"&gt;\r\n&lt;/span&gt;&lt;span class="s1"&gt;------WebKitFormBoundarynE0B7A3bJADDu4sV&lt;/span&gt;&lt;span class="se"&gt;\r\n&lt;/span&gt;&lt;span class="s1"&gt;Content-Disposition: form-data; name="_wpcf7_locale"&lt;/span&gt;&lt;span class="se"&gt;\r\n\r\n&lt;/span&gt;&lt;span class="s1"&gt;de_DE_formal&lt;/span&gt;&lt;span class="se"&gt;\r\n&lt;/span&gt;&lt;span class="s1"&gt;------WebKitFormBoundarynE0B7A3bJADDu4sV&lt;/span&gt;&lt;span class="se"&gt;\r\n&lt;/span&gt;&lt;span class="s1"&gt;Content-Disposition: form-data; name="_wpcf7_unit_tag"&lt;/span&gt;&lt;span class="se"&gt;\r\n\r\n&lt;/span&gt;&lt;span class="s1"&gt;wpcf7-f834-p922-o1&lt;/span&gt;&lt;span class="se"&gt;\r\n&lt;/span&gt;&lt;span class="s1"&gt;------WebKitFormBoundarynE0B7A3bJADDu4sV&lt;/span&gt;&lt;span class="se"&gt;\r\n&lt;/span&gt;&lt;span class="s1"&gt;Content-Disposition: form-data; name="_wpcf7_container_post"&lt;/span&gt;&lt;span class="se"&gt;\r\n\r\n&lt;/span&gt;&lt;span class="s1"&gt;922&lt;/span&gt;&lt;span class="se"&gt;\r\n&lt;/span&gt;&lt;span class="s1"&gt;------WebKitFormBoundarynE0B7A3bJADDu4sV&lt;/span&gt;&lt;span class="se"&gt;\r\n&lt;/span&gt;&lt;span class="s1"&gt;Content-Disposition: form-data; name="_wpcf7_posted_data_hash"&lt;/span&gt;&lt;span class="se"&gt;\r\n\r\n\r\n&lt;/span&gt;&lt;span class="s1"&gt;------WebKitFormBoundarynE0B7A3bJADDu4sV&lt;/span&gt;&lt;span class="se"&gt;\r\n&lt;/span&gt;&lt;span class="s1"&gt;Content-Disposition: form-data; name="name"&lt;/span&gt;&lt;span class="se"&gt;\r\n\r\M&lt;/span&gt;&lt;span class="s1"&gt;YNAME&lt;/span&gt;&lt;span class="se"&gt;\r\n&lt;/span&gt;&lt;span class="s1"&gt;------WebKitFormBoundarynE0B7A3bJADDu4sV&lt;/span&gt;&lt;span class="se"&gt;\r\n&lt;/span&gt;&lt;span class="s1"&gt;Content-Disposition: form-data; name="insurance-number"&lt;/span&gt;&lt;span class="se"&gt;\r\n\r\n&lt;/span&gt;&lt;span class="s1"&gt;INSURANCENUMBER&lt;/span&gt;&lt;span class="se"&gt;\r\n&lt;/span&gt;&lt;span class="s1"&gt;------WebKitFormBoundarynE0B7A3bJADDu4sV&lt;/span&gt;&lt;span class="se"&gt;\r\n&lt;/span&gt;&lt;span class="s1"&gt;Content-Disposition: form-data; name="phone"&lt;/span&gt;&lt;span class="se"&gt;\r\n\r\n&lt;/span&gt;&lt;span class="s1"&gt;MYPHONENUMBER&lt;/span&gt;&lt;span class="se"&gt;\r\n&lt;/span&gt;&lt;span class="s1"&gt;------WebKitFormBoundarynE0B7A3bJADDu4sV&lt;/span&gt;&lt;span class="se"&gt;\r\n&lt;/span&gt;&lt;span class="s1"&gt;Content-Disposition: form-data; name="email-195"&lt;/span&gt;&lt;span class="se"&gt;\r\n\r\n&lt;/span&gt;&lt;span class="s1"&gt;MYEMAIL@EMAIL.COM&lt;/span&gt;&lt;span class="se"&gt;\r\n&lt;/span&gt;&lt;span class="s1"&gt;------WebKitFormBoundarynE0B7A3bJADDu4sV&lt;/span&gt;&lt;span class="se"&gt;\r\n&lt;/span&gt;&lt;span class="s1"&gt;Content-Disposition: form-data; name="order"&lt;/span&gt;&lt;span class="se"&gt;\r\n\r\n&lt;/span&gt;&lt;span class="s1"&gt;THE ORDER INFORMATION GOES HERE&lt;/span&gt;&lt;span class="se"&gt;\r\n&lt;/span&gt;&lt;span class="s1"&gt;------WebKitFormBoundarynE0B7A3bJADDu4sV&lt;/span&gt;&lt;span class="se"&gt;\r\n&lt;/span&gt;&lt;span class="s1"&gt;Content-Disposition: form-data; name="acceptance-255"&lt;/span&gt;&lt;span class="se"&gt;\r\n\r\n&lt;/span&gt;&lt;span class="s1"&gt;1&lt;/span&gt;&lt;span class="se"&gt;\r\n&lt;/span&gt;&lt;span class="s1"&gt;------WebKitFormBoundarynE0B7A3bJADDu4sV--&lt;/span&gt;&lt;span class="se"&gt;\r\n&lt;/span&gt;&lt;span class="s1"&gt;'&lt;/span&gt; &lt;span class="nt"&gt;-s&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;

  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="nv"&gt;$?&lt;/span&gt; &lt;span class="nt"&gt;-eq&lt;/span&gt; 0 &lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then&lt;/span&gt;
      &lt;span class="c"&gt;# Using jq to parse JSON and extract fields&lt;/span&gt;
      &lt;span class="nv"&gt;insulin_order_status&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="nv"&gt;$insulin_order_response&lt;/span&gt; | jq &lt;span class="nt"&gt;-r&lt;/span&gt; &lt;span class="s1"&gt;'.status'&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;
      &lt;span class="nv"&gt;insulin_order_message&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="nv"&gt;$insulin_order_response&lt;/span&gt; | jq &lt;span class="nt"&gt;-r&lt;/span&gt; &lt;span class="s1"&gt;'.message'&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;

      &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[[&lt;/span&gt; &lt;span class="nv"&gt;$insulin_order_status&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s2"&gt;"mail_sent"&lt;/span&gt; &lt;span class="o"&gt;]]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
          &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Ordered: &lt;/span&gt;&lt;span class="nv"&gt;$insulin_order_message&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
      &lt;span class="k"&gt;else
          &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Something went wrong, order via the website and update the curl request"&lt;/span&gt;
      &lt;span class="k"&gt;fi
  else
      &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Something went wrong, order via the website and update the curl request"&lt;/span&gt;
  &lt;span class="k"&gt;fi&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Explanation
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;cURL Command&lt;/strong&gt;: The curl command sends a POST request to the GP's website with the necessary headers and form data.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Response Handling&lt;/strong&gt;: The response is captured in the insulin_order_response variable. We use the &lt;code&gt;-s&lt;/code&gt; flag to run curl in silent mode, which suppresses progress output.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Error Checking&lt;/strong&gt;: The script checks if the curl command executed successfully using &lt;code&gt;$?&lt;/code&gt;. If the command fails, an error message is displayed.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Parsing JSON Response&lt;/strong&gt;: If the curl command is successful, the script uses &lt;code&gt;jq&lt;/code&gt; to parse the JSON response and extract the status and message fields.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Conditional Logic&lt;/strong&gt;: Based on the status field, the script determines if the request was successful (&lt;code&gt;'mail_sent'&lt;/code&gt;) or if there was an error.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In order to get to the information I needed to make the &lt;code&gt;if&lt;/code&gt;-statement work and to figure out the required information, I went back to my network tab. In the response there, the returned JSON looked as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"contact_form_id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;834&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"status"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"mail_sent"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"message"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Prescription requested successfully."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"posted_data_hash"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2905f838031fbd4619d89658928fbb2a"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"into"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"#wpcf7-f834-p922-o1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"invalid_fields"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can clearly see the status and the reply there. Since I am only interested in the success state, I can just check for &lt;code&gt;mail_sent&lt;/code&gt;. If the mail wouldn't be sent, then I can log an error. Since I assume that the cURL request will only fail if they change their API, I added the message:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;order via the website and update the curl request.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Lastly, I started a new terminal window and tried my new script. Indeed, I saw &lt;code&gt;Ordered: Prescription requested successfully.&lt;/code&gt; in my terminal. Does that mean I requested two prescriptions in a short time? Yes it does. I hope nobody comes knocking for that. &lt;/p&gt;

&lt;h2&gt;
  
  
  What’s Next?
&lt;/h2&gt;

&lt;p&gt;In the next part of this series, we will focus on automating the email to the pharmacy. This involves setting up an email client within our script to send the pre-order request automatically.&lt;/p&gt;

&lt;p&gt;Stay tuned as we continue to streamline the insulin ordering process, one step at a time.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://dev.to/goudekettingrm/automating-insulin-ordering-creating-the-wrapping-function-part-3-517k"&gt;Read Part 3&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Thank you for following along! If you have any questions or suggestions, feel free to leave a comment below. Don't forget to share this post with anyone who might find it useful.&lt;/p&gt;

</description>
      <category>programming</category>
      <category>productivity</category>
      <category>automation</category>
      <category>processoptimisation</category>
    </item>
    <item>
      <title>Automating Insulin Ordering: A Journey Towards Convenience (Part 1)</title>
      <dc:creator>Robin Goudeketting</dc:creator>
      <pubDate>Tue, 04 Jun 2024 08:18:56 +0000</pubDate>
      <link>https://forem.com/goudekettingrm/automating-insulin-ordering-a-journey-towards-convenience-part-1-573n</link>
      <guid>https://forem.com/goudekettingrm/automating-insulin-ordering-a-journey-towards-convenience-part-1-573n</guid>
      <description>&lt;p&gt;Living with Type 1 diabetes comes with its own set of challenges, one of which is managing a regular supply of insulin. As someone who relies on this life-saving medication, I've often found myself entangled in a convoluted system just to get my prescription filled. This multi-part series will walk you through my journey of automating the insulin ordering process, saving time and reducing the hassle involved. In this first part, I'll outline the problem and set the stage for the solution we'll be building.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Problem
&lt;/h2&gt;

&lt;p&gt;In my region, obtaining insulin isn't as straightforward as it might be elsewhere. Here’s a breakdown of the steps I currently need to take:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Contacting the GP: I have to get in touch with my General Practitioner (GP) to request a new prescription. This involves logging onto their website and sending a message asking them to upload the prescription to my healthcare insurance card.&lt;/li&gt;
&lt;li&gt;Waiting for the Prescription: Once the GP uploads the prescription, I can then take my healthcare card to the pharmacy.&lt;/li&gt;
&lt;li&gt;Pharmacy Visit: However, the pharmacy usually doesn’t have my specific insulin in stock. This means I have to go there, request the prescription to be filled, and wait for them to order it.&lt;/li&gt;
&lt;li&gt;Second Pharmacy Visit: After they’ve ordered it, I have to return the next day to pick up my insulin.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This does not seem like too much hassle, but due to the local restrictions, I have to repeat this process every 2 weeks. &lt;/p&gt;

&lt;h2&gt;
  
  
  A Slight Improvement
&lt;/h2&gt;

&lt;p&gt;To reduce the number of visits, I've started emailing the pharmacy in advance. I inform them of my prescription and ask them to pre-order the insulin. This way, I only need to visit the pharmacy once, to collect the prescription. While this is a step in the right direction, it still requires multiple manual steps:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Requesting the prescription from my GP.&lt;/li&gt;
&lt;li&gt;Sending an email to the pharmacy to pre-order the insulin.&lt;/li&gt;
&lt;li&gt;Setting a reminder to pick up the insulin the next day.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The Automation Idea
&lt;/h2&gt;

&lt;p&gt;To streamline this process, I'm planning to write a terminal command that will automate these tasks and can be run in a cronjob on a schedule:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Automated Request to GP: The command will send a request to my GP to upload the prescription.&lt;/li&gt;
&lt;li&gt;Automated Email to Pharmacy: Upon receiving a confirmation from the GP, it will send an automated email to the pharmacy to pre-order the insulin.&lt;/li&gt;
&lt;li&gt;Google Calendar Integration: Finally, it will add a task to my Google Calendar, reminding me to pick up the insulin.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;By automating these steps, I aim to minimise the manual effort and ensure that I never miss an insulin pickup. This series will detail the technical aspects of creating this automation, including writing the script, setting up a cron job, and integrating with email and calendar APIs.&lt;/p&gt;

&lt;h2&gt;
  
  
  What’s Next?
&lt;/h2&gt;

&lt;p&gt;In the next part of this series, we'll dive into the specifics of writing a terminal command to send a request to the GP. We'll cover everything from figuring out the request to send and how to convert it to a terminal command.&lt;/p&gt;

&lt;p&gt;Stay tuned for the next instalment where we take the first step towards a fully automated insulin ordering system.&lt;/p&gt;

&lt;p&gt;I hope this series will not only help others facing similar challenges but also provide an interesting automation project for tech enthusiasts. If you have any questions or suggestions, feel free to leave a comment below!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://dev.to/goudekettingrm/automating-insulin-ordering-capturing-the-gp-request-part-2-4pl0"&gt;Read Part 2&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Thank you for reading! If you enjoyed this post, don't forget to follow me for more updates and share it with anyone who might find it useful.&lt;/p&gt;

</description>
      <category>programming</category>
      <category>productivity</category>
      <category>automation</category>
      <category>processoptimisation</category>
    </item>
    <item>
      <title>Publishing my first NPM package only took 3 steps</title>
      <dc:creator>Robin Goudeketting</dc:creator>
      <pubDate>Wed, 15 Jul 2020 20:42:18 +0000</pubDate>
      <link>https://forem.com/goudekettingrm/publishing-my-first-npm-package-only-took-3-steps-3fpi</link>
      <guid>https://forem.com/goudekettingrm/publishing-my-first-npm-package-only-took-3-steps-3fpi</guid>
      <description>&lt;p&gt;Check it out! ~ TL;DR at the End&lt;br&gt;
&lt;em&gt;&lt;a href="https://www.npmjs.com/package/titleizejs"&gt;NPM&lt;/a&gt;&lt;/em&gt; ~ &lt;em&gt;&lt;a href="https://github.com/goudekettingrm/titleize"&gt;Github&lt;/a&gt;&lt;/em&gt; ~ &lt;em&gt;&lt;a href="https://goudekettingrm.github.io/titleize/"&gt;Docs&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Learning to code
&lt;/h2&gt;

&lt;p&gt;When I started programming at the beginning of this, I had no clue how much I would like it. Starting at &lt;a href="https://codaisseur.com/"&gt;Codaisseur Academy&lt;/a&gt; I learned the basics and after 8 weeks and 50 hours of coding and hands on work per day, I officially graduated and was able to make full-stack applications. &lt;/p&gt;

&lt;p&gt;I learned how to use NPM and use packages in the Node.js back-end applications as well as importing them into the front-end React.js applications. However, never was I told how to make and publish packages of my own. It seemed so daunting in the beginning. What do you make? How do you publish? Version control? Testing? CI? Where would you start? Then I saw this comic:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F2gsda1jqtp6jmnxr7w4r.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F2gsda1jqtp6jmnxr7w4r.jpg" alt="Bunny and a fox trying to start a garden and the fox realises in the end that starting is the first thing to do." width="800" height="800"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Starting the project
&lt;/h2&gt;

&lt;p&gt;So a short while ago I decided to just start with making something. I picked something I encountered in my job, where we use Ruby. In Ruby there are methods, called &lt;a href="https://api.rubyonrails.org/classes/ActiveSupport/Inflector.html"&gt;inflections&lt;/a&gt;, that convert strings into (sort of) formatted strings. One of those is called &lt;code&gt;titleize&lt;/code&gt;, which converts a string into something that represents a title. I decided to make that as a package for NPM. &lt;/p&gt;

&lt;p&gt;I created a folder, initialised NPM, and created a file that held my function. Then there are a few things to note:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Set the &lt;code&gt;"main"&lt;/code&gt; key in your &lt;code&gt;package.json&lt;/code&gt; to the file that holds your function, like this:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt; 
  &lt;span class="p"&gt;...,&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;main&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./titleize.js&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// or something more generic like "./index.js"&lt;/span&gt;
  &lt;span class="p"&gt;...,&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Make an account on NPM. This can be done via their website, but is also easily done via the NPM cli. You can run &lt;code&gt;npm adduser&lt;/code&gt; and it will guide you through the creation of a user. When you're done, running &lt;code&gt;npm whoami&lt;/code&gt; should tell you your username:&lt;br&gt;
&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F2kz2c8l7c87lqzm7c26c.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F2kz2c8l7c87lqzm7c26c.png" alt="Response from running the command npm whoami will tell you the currently logged in user." width="800" height="107"&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Almost ready to publish your package. First we have to check if our package name is not taken by someone else, otherwise you might get stuck. My terminal started asking for a One-Time Password. Turned out, the name of my project already existed and probably I was trying to publish to that package. If you cannot find a package with the name you chose, you should be good to run &lt;code&gt;npm publish&lt;/code&gt;. &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Only thing that's left to do is installing your package into a different project. Just run&lt;br&gt;
&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;npm&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="nx"&gt;titleizejs&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Or whatever you called your package and import it into your files! &lt;/p&gt;

&lt;p&gt;I also then added some Mocha/Chai test and hooked it up to Github Actions for automated testing. Also I hooked it up to Github Pages to generate a nice website for the docs. I might write about how that works if you are interested. &lt;/p&gt;

&lt;h4&gt;
  
  
  TL;DR
&lt;/h4&gt;

&lt;p&gt;Publishing a package is super easy:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Create your package: run &lt;code&gt;npm init&lt;/code&gt; and create you files.&lt;/li&gt;
&lt;li&gt;Create an NPM account: run &lt;code&gt;npm adduser&lt;/code&gt; (or &lt;code&gt;npm login&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;Publish your package: run &lt;code&gt;npm publish&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Check out Titleize JS: run &lt;code&gt;npm i titleizejs&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>javascript</category>
      <category>npm</category>
      <category>node</category>
      <category>github</category>
    </item>
  </channel>
</rss>
