<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom"><title>Rob Evans</title><link href="https://www.robertevans.org/" rel="alternate"></link><link href="https://www.robertevans.org/feeds/all.atom.xml" rel="self"></link><id>https://www.robertevans.org/</id><updated>2018-01-07T09:17:35-08:00</updated><entry><title>Plain text is worth it</title><link href="https://www.robertevans.org/plain-text-is-worth-it.html" rel="alternate"></link><published>2018-01-07T09:17:35-08:00</published><updated>2018-01-07T09:17:35-08:00</updated><author><name>Rob Evans</name></author><id>tag:www.robertevans.org,2018-01-07:/plain-text-is-worth-it.html</id><summary type="html">&lt;p&gt;&lt;a href="http://hledger.org/index.html"&gt;&lt;code&gt;hledger&lt;/code&gt;&lt;/a&gt; is one of my favorite pieces of
software. Written in &lt;a href="http://learnyouahaskell.com/"&gt;haskell&lt;/a&gt;, it allows you
to
&lt;a href="https://en.wikipedia.org/wiki/Double-entry_bookkeeping_system"&gt;balance your books&lt;/a&gt; by
recording transactions in a
simple &lt;a href="http://plaintextaccounting.org/"&gt;plain text format&lt;/a&gt;, which looks like
this:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;2018/01/01 Supermarket
    Expenses:Groceries           $45
    Assets:Cash                 $-45
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Expenses go up, assets go down, balance is …&lt;/p&gt;</summary><content type="html">&lt;p&gt;&lt;a href="http://hledger.org/index.html"&gt;&lt;code&gt;hledger&lt;/code&gt;&lt;/a&gt; is one of my favorite pieces of
software. Written in &lt;a href="http://learnyouahaskell.com/"&gt;haskell&lt;/a&gt;, it allows you
to
&lt;a href="https://en.wikipedia.org/wiki/Double-entry_bookkeeping_system"&gt;balance your books&lt;/a&gt; by
recording transactions in a
simple &lt;a href="http://plaintextaccounting.org/"&gt;plain text format&lt;/a&gt;, which looks like
this:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;2018/01/01 Supermarket
    Expenses:Groceries           $45
    Assets:Cash                 $-45
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Expenses go up, assets go down, balance is maintained. My discipline on this
front waxes and wanes, but no matter how out of whack my books are at any given
time, I always manage to balance them in January so that filing taxes for the
previous year is slightly less brutal. Normally this is a bit tedious, as I've
only automated the process with enough duct tape and &lt;code&gt;bash&lt;/code&gt; to get the job done.
Something like this (using &lt;a href="https://github.com/cantino/reckon"&gt;&lt;code&gt;reckon&lt;/code&gt;&lt;/a&gt; to
properly categorize new transactions) is typical:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;reckon -l 2017.ledger -f some_bank.csv -a &amp;quot;Assets:Some Bank&amp;quot; &amp;gt;&amp;gt; 2017.ledger
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Too cheap to pay my banks' extortionate fees
for
&lt;a href="http://support.lessaccounting.com/knowledge_base/topics/download-a-qif-or-qfx-file-from-my-bank"&gt;automatically downloading my own data&lt;/a&gt;,
I typically download either &lt;code&gt;.qfx&lt;/code&gt;, &lt;code&gt;.ofx&lt;/code&gt;, or &lt;code&gt;.csv&lt;/code&gt; from their sites and
massage it into the &lt;code&gt;ledger&lt;/code&gt; format.&lt;/p&gt;
&lt;h2&gt;Citi made a bad website for Costco&lt;/h2&gt;
&lt;p&gt;Costco
&lt;a href="https://www.marketwatch.com/story/5-things-to-know-about-the-costco-and-amex-breakup-2016-02-11"&gt;dumped AmEx&lt;/a&gt; a
couple of years ago and started offering Visa cards provided
by
&lt;a href="https://www.citi.com/credit-cards/credit-card-details/citi.action?ID=Citi-costco-anywhere-visa-credit-card"&gt;Citi&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The default transaction view is sane; that is, you can see all of the
transactions for a given time period via tabular HTML. There is a "Print Screen"
button. There is a search form with a dropdown that allows you to view
individual statements. However, &lt;strong&gt;there is no "Download Transactions" button&lt;/strong&gt;.
I stared at this view for quite a while, assuming I was missing something.
Apparently, what I was missing was the "Spend Summary" link, which takes you to
a page that looks like:&lt;/p&gt;
&lt;p&gt;&lt;img alt="Spend Summary" src="https://www.robertevans.org/images/spend_summary.png"&gt;&lt;/p&gt;
&lt;p&gt;Almost unbelievably, it's only possible to download a single category from this
view. You cannot download an entire "Year to Date" &lt;code&gt;.csv&lt;/code&gt;!&lt;/p&gt;
&lt;h2&gt;Back to the JSON&lt;/h2&gt;
&lt;p&gt;Returning to the HTML transaction view, it was a relief to see that the tabular
transaction view was populated by a mere &lt;code&gt;XHR&lt;/code&gt; call. Firefox's network monitor
lets you save a &lt;a href="https://en.wikipedia.org/wiki/.har"&gt;&lt;code&gt;.har&lt;/code&gt; file&lt;/a&gt; containing a
record of the data transferred during the browser session.&lt;/p&gt;
&lt;p&gt;Now that I actually had a way to download a complete log of transactions, the
only thing left was to write an abomination that combined the power of &lt;code&gt;jq&lt;/code&gt;,
&lt;code&gt;perl -pie&lt;/code&gt;, and &lt;code&gt;reckon&lt;/code&gt; to output proper &lt;code&gt;ledger&lt;/code&gt; files:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="ch"&gt;#!/usr/bin/env bash&lt;/span&gt;

&lt;span class="nb"&gt;set&lt;/span&gt; -euxo pipefail

&lt;span class="nv"&gt;HAR&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$1&lt;/span&gt;

&lt;span class="k"&gt;function&lt;/span&gt; har2csv&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    jq -r &lt;span class="s1"&gt;&amp;#39;&lt;/span&gt;
&lt;span class="s1"&gt;      .log.entries[] |&lt;/span&gt;
&lt;span class="s1"&gt;      select(.response.content.mimeType == &amp;quot;application/json&amp;quot;) |&lt;/span&gt;
&lt;span class="s1"&gt;      .response.content.text |&lt;/span&gt;
&lt;span class="s1"&gt;      fromjson |&lt;/span&gt;
&lt;span class="s1"&gt;      .accountActivity.postedTransactionJournals[] |&lt;/span&gt;
&lt;span class="s1"&gt;      .columns |&lt;/span&gt;
&lt;span class="s1"&gt;      map(.activityColumn) |&lt;/span&gt;
&lt;span class="s1"&gt;      flatten |&lt;/span&gt;
&lt;span class="s1"&gt;      del(.[] | nulls) |&lt;/span&gt;
&lt;span class="s1"&gt;      map(gsub(&amp;quot;[\\n]&amp;quot;; &amp;quot;&amp;quot;)) |&lt;/span&gt;
&lt;span class="s1"&gt;      map(&amp;quot;\&amp;quot;&amp;quot; + . + &amp;quot;\&amp;quot;&amp;quot;) |&lt;/span&gt;
&lt;span class="s1"&gt;      join (&amp;quot;,&amp;quot;)&amp;#39;&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;function&lt;/span&gt; clean&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    tr &lt;span class="s1"&gt;&amp;#39;|&amp;#39;&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39; &amp;#39;&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; perl -p -i -e &lt;span class="s1"&gt;&amp;#39;s/\$ //&amp;#39;&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

reckon -f &amp;lt;&lt;span class="o"&gt;(&lt;/span&gt;cat &lt;span class="nv"&gt;$HAR&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; har2csv &lt;span class="p"&gt;|&lt;/span&gt; clean&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
       --date-format &lt;span class="s1"&gt;&amp;#39;%B. %e, %Y %T&amp;#39;&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
       -u -i &lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="nv"&gt;$@&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Thanks Citi!&lt;/p&gt;</content><category term="citi"></category><category term="costco"></category><category term="cc"></category><category term="ledger"></category><category term="hledger"></category><category term="jq"></category><category term="csv"></category><category term="har"></category></entry><entry><title>Make a blog</title><link href="https://www.robertevans.org/make-a-blog.html" rel="alternate"></link><published>2017-12-22T13:41:20-08:00</published><updated>2018-01-01T22:27:42-08:00</updated><author><name>Rob Evans</name></author><id>tag:www.robertevans.org,2017-12-22:/make-a-blog.html</id><summary type="html">&lt;p&gt;In late December 2017, I went down the rabbit hole of investigating static site
generators in general, and markdown blog generators specifically.&lt;/p&gt;
&lt;h2&gt;Write some markdown&lt;/h2&gt;
&lt;p&gt;There are an &lt;a href="http://octopress.org/"&gt;absurd&lt;/a&gt; &lt;a
href="https://gohugo.io"&gt;number&lt;/a&gt; of &lt;a href="https://hexo.io"&gt;good&lt;/a&gt; &lt;a
href="https://jekyllrb.com/"&gt;candidates&lt;/a&gt; at this point, but eventually I
settled on &lt;a href="https://blog.getpelican.com/"&gt;Pelican&lt;/a&gt;, mostly because I
miss writing Python from time …&lt;/p&gt;</summary><content type="html">&lt;p&gt;In late December 2017, I went down the rabbit hole of investigating static site
generators in general, and markdown blog generators specifically.&lt;/p&gt;
&lt;h2&gt;Write some markdown&lt;/h2&gt;
&lt;p&gt;There are an &lt;a href="http://octopress.org/"&gt;absurd&lt;/a&gt; &lt;a
href="https://gohugo.io"&gt;number&lt;/a&gt; of &lt;a href="https://hexo.io"&gt;good&lt;/a&gt; &lt;a
href="https://jekyllrb.com/"&gt;candidates&lt;/a&gt; at this point, but eventually I
settled on &lt;a href="https://blog.getpelican.com/"&gt;Pelican&lt;/a&gt;, mostly because I
miss writing Python from time to time. The &lt;a
href="https://github.com/getpelican/pelican-plugins"&gt;plugin ecosystem&lt;/a&gt; seems
to have good enough solutions for a large number of common blog-related
integrations.&lt;/p&gt;
&lt;h2&gt;Deploy it for "free"&lt;/h2&gt;
&lt;p&gt;I &lt;a href="https://www.fastmail.com"&gt;pay for my email provider&lt;/a&gt; for a variety
of reasons, one of which is the integrated &lt;a
href="https://www.fastmail.com/help/files/usage.html"&gt;file storage&lt;/a&gt;. Fastmail
doesn't support https so I decided to use Cloudflare's &lt;a
href="https://www.cloudflare.com/plans/free"&gt;free CDN plan&lt;/a&gt;. The stack for
this blog includes:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Cloudflare for https CDN&lt;/li&gt;
&lt;li&gt;Fastmail to host the files via http&lt;/li&gt;
&lt;li&gt;CSS from &lt;a href="https://github.com/alexandrevicenzi/Flex"&gt;this theme&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://docs.getpelican.com/en/stable/index.html"&gt;Pelican&lt;/a&gt; to
  generate the html&lt;/li&gt;
&lt;li&gt;&lt;code&gt;rsync&lt;/code&gt; the html to a &lt;a
  href="https://wiki.archlinux.org/index.php/Davfs2#Using_fstab"&gt;davfs mount&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content><category term="pelican"></category><category term="blog"></category><category term="markdown"></category></entry></feed>