The main reason I blog is to remember and share my life lessons (and get my thoughts out so my head doesn’t explode). It’s not always easy, between finding time to do it, not tearing apart my laptop after the first draft, and cringing over grammar mistakes notice months after posting.

But the toughest part is when I learn a lesson or overcome a struggle, only to realize I wrote about the same lesson months ago. Probably like most writers/bloggers/international spies, I have a hard time remembering my notes and how I’ve grown over time.

So last week, I made it a lot easier and wrote a script to email myself random bits of my writing each day.

Exposing all my site’s writing for this was as simple as making a couple of giant XML files. There’s one for blog posts, one for the Exocortex, and one for my notes. You can see the blog post example below, and you can see the output at this XML file.

{% assign posts = site.posts %}

{% for post in posts %}
  {% assign url = post.url | prepend: site.url %}

  <entry>
    <title type="html">{{ post.title }}</title>
    <link href="{{ url }}" rel="alternate" type="text/html" title="{{ post.title }}"/>

    <content type="html" xml:base="{{ url }}">
      {{ post.content | xml_escape }}
    </content>
  </entry>
{% endfor %}

Next up is a Ruby class that can visit any of these URLs, parse the content, and grab a random item.

require 'net/http'
require 'json'
require "base64"
require 'nokogiri'
require 'redcarpet'
require 'redcarpet/render_strip'

class WebsiteContent
  def initialize(content_type)
    @url = "https://www.maxwellantonucci.com/api/#{content_type}.xml"
  end

  def get_page
    response = api_response(@url)
    parse_xml(response)
  end

  private

  def parse_xml(body)
    xml_doc = Nokogiri::XML.parse(body)
    all_items = xml_doc.css("entry").map do |entry|
      {
        title: entry.css("title").text,
        content: render_markdown(entry.css("content").text)
      }
    end

    all_items.sample
  end

  def api_response(url)
    uri = URI(url)
    Net::HTTP.get(uri)
  end

  def render_markdown(content)
    markdown = Redcarpet::Markdown.new(Redcarpet::Render::HTML, disable_indented_code_blocks: true, fenced_code_blocks: true)
    markdown.render(content)
  end
end

Nokogiri is great for doing the parsing the XML document, and sample is one of those lovely Ruby methods for common tasks I wish JavaScript had.

All my site content is written in markdown, so that needs to be rendered into HTML. Redcarpet is good for this since it can handle the code blocks and snippets on some pages.

One last class is needed to email this content to me. It calls up the last class to grab something from my site and uses the mail gem to send it over. Any email server info I want to keep private is saved in environmental variables and pulled out with dotenv/load.

require 'mail'
require 'dotenv/load'
require_relative 'website_content.rb'

class EmailSender
  def initialize(type)
    @type = type
    options = email_options
    Mail.defaults do
      delivery_method :smtp, options
    end
  end

  def send_email
    page = WebsiteContent.new(@type).get_page
    sender = email_sender
    recipient = email_recipient

    Mail.deliver do
      from    sender
      to      recipient
      subject page[:title]

      html_part do
        content_type 'text/html; charset=UTF-8'
        body page[:content]
      end
    end
  end

  private

  def email_sender
    ENV['GMAIL_USERNAME']
  end

  def email_password
    ENV['GMAIL_PASSWORD']
  end

  def email_recipient
    ENV['RECIPIENT_EMAIL']
  end

  def email_options
    { address: "smtp.gmail.com",
      port: 587,
      user_name: email_sender,
      password: email_password,
      authentication: 'plain',
      enable_starttls_auto: true  }
  end
end

Now I just need a task to run all this, which I have in bin/send that runs the EmailSender class.

#!/usr/bin/env ruby

category = ARGV[0] || "blog" ;

require_relative '../lib/email_sender.rb'
EmailSender.new(category).send_email

From this project directory, I can call bin/send blog, bin/send notes, or bin/send exocortex and get an email with a random piece from said category. The joys of coding in Ruby! So simple and so enjoyable to write.

I admit all this is a little self-indulgent. But I’m an admitted selfish and casual blogger, so I feel no shame. If this little script helps remind myself to build good habits, write good Ruby, and embrace the horrors of life with humor and curiosity, then I’ll take it.