gophering on Homepage
/ The single-page phlog  \
\ "a place to store all my junk" /
   \ ,   _ ___.--'''`--''//-,-_--_.
      \`"' ` || \\ \ \\/ / // / ,-\\`,_
     /'`  \ \ || Y  | \|/ / // / - |__ `-,
    /@"\  ` \ `\ |  | ||/ // | \/  \  `-._`-,_.,
   /  _.-. `.-\,___/\ _/|_/_\_\/|_/ |     `-._._)
   `-'``/  /  |  // \__/\__  /  \__/ \
        `-'  /-\/  | -|   \__ \   |-' |
          __/\ / _/ \/ __,-'   ) ,' _|'
         (((__/(((_.' ((___..-'((__,'
I've made several significant additions to my gopherhole over the
past few weeks. I haven't particularly felt like writing a phlog
post, so I've given myself permission to have fun tinkering without
documenting anything.
I've been thinking about making some sort of telnet game/application.
I found this great Python telnet library that I want to use:
shmup/miniboa (github)
But I realized that I don't actually know how the TELNET protocol
works, so I've been slogging through all of the old RFCs. I enjoy
reading the RFC documents for old protocols. They're succinct and
written in clear, precise language. It's such a stark contrast from
the overly verbose papers that are coming out of academia.
Presenting a new gopher applet...
A Random Dad Joke!
(Start preview)
        A Random Dad Joke
        / Two fish are in a tank, one turns to  \
        | the other and says, "how do you drive |
        \ this thing?"                          /
               \   ^__^
                \  (oo)\_______
                   (__)\       )\/\
                       ||----w |
                       ||     ||
        (refresh the page for a new joke)
        Powered by
(End preview)
This was a fun little 15-minute gopher app that I decided to create
after stumbling upon the following site:
The Python (3) code was only a few lines long:
from subprocess import run, PIPE
from unidecode import unidecode
def generate():
    command = 'curl | cowsay'
    resp = run(command, shell=True, stdout=PIPE, encoding='utf-8')
    return unidecode(resp.stdout)
I had to throw the unidecode converter in there because the service
returns those annoying UTF-8 quotation marks and apostrophes.
I briefly considered scraping all of the dad jokes into a local file
so it wasn't depending on making an HTTP request. But then I decided
that I was probably over-thinking it. Maybe I'll come back to this
later if I'm still interested.
I updated the layout of some of the pages on my main gopherhole.
Specifically, I added formatted gopher directories to the top-level
listing pages for file repositories. I wanted to be able to group
similar files and include helpful descriptions, instead of simply
dumping all of the file names to a page. I also added some nifty
ASCII art banners.
- Music Library
- Flash Library
- Qi/Ph Source Code
I can't stop myself from tweaking things. Every time I start browsing
through other sites in the gopherverse, I end up with a bunch of new
ideas for how to display content. Everyone has their own little
personal touches that they add. I still have a lot to learn.
My latest gopher app is live!
Cocktails (Drink Recipe Search Engine)
I'm really happy with how it turned out! The only bug that I've
encountered so far is that the floodgap HTTP-proxy chokes on the
type "7" search query, because the URL contains a "?" character. For
some reason, it URL escapes the "?" character when it shouldn't be...
But that's a small nitpick, everything else works great :)
It's nice to be able to work on a gopher site for a couple of days,
pronounce it as "done", and then move on to something new. This was
the perfect size. I'm going to try to do more projects like this in
the future. Right now I'm thinking about porting some ASCII art over
to gopher. The artist below is who I've gotten like 90 percent of
the art for my sites so far. She's really incredible:
Joan Stark's ASCII Art Gallery
I've been increasingly negative on the prospect of gopher over TLS.
Not from a technical perspective. I added TLS to Flask-Gopher a while
ago and it works just fine.
TLS using FLask-Gopher
Rather, from a perspective of "Why is everyone wasting their time on
this?". I can't think of any good reasons for gopher to *need* TLS
connections. Let's be real here:
1. Nobody is sending passwords or secure information over search
   queries. It's just not a reality in gopher. There are several
   non-TLS reasons for this, including gopher's lack of support for
   session cookies.
2. Your ISP is not going MITM your port 70 gopher connection. Yes,
   they technically *could* if they wanted to. But there are not ads
   on gopher, no commercialization opportunities. There's simply no
   financial incentive for them to give a damn about gopher.
3. Yes, a government agency could spy on your requests. But if you're
   being targeted by a nation state (or any sophisticated individual),
   you've already lost. No amount of TLS encryption will save you.
I added my library of flash (.swf) files to the gopher
homepage. They were already sitting on the server being used by
another webapp, so I figured "why not?".
Flash Library
I want to be careful to avoid turning my gopher server into a dumping
ground for 1000's of random files, just for the sake of it. It feels
messy and pointless. In this case, I'm going to let it slide because
there's some poetic beauty in serving a dead file format (.swf) over
a dead server protocol.
For the same reason, I also want to avoid adding an "external links"
section with links to other gopher holes that I appreciate. There are
already plenty of gopher servers that do a good job aggregating links.
Let's keep mozz focused on serving unique and delightful content.
The past few days, I've been working on a new gopher service that
contains a sortable database to cocktail drink recipes. I was inspired
after seeing a few recipes on gopher and noticing how nice they looked
formatted as ASCII. Basically, I like the A E S T H E T I C.
So first I wrote a scraper to pull recipes from
That part was surprisingly easy. The hard part now is building some
kind of menu system in gopher to allow selecting and filtering by tags
like "Difficulty: [Medium]". That's what I'm working on for the moment
whenever I can find the time.
Here's a preview of what the recipes look like formatted. All of the
information is pulled from a sqlite database.
Manhattan Drink Recipe
I keep flip-flopping on how I should format headers on my main page.
The problem is this: I can chose something and it looks great in lynx
because links are highlighted in a different color so they stand out
from the header info lines. But when I test using a different browser,
it becomes hard to read because there's no visual separation between
headers and content.
So, I need to pick a format that meets the following criteria:
  - Easily distinguishable on clients that don't use text formatting.
  - Gracefully degrades on screens that wrap less than 70 characters.
  - Allows the header text to include non-alphanum characters (like
    parenthesis) without looking awkward.
Today, I've settled on using a tilde character + uppercase. Tilde is
nice because it's not often used in ASCII for other purposes.
Some example styles that I have been playing around with
I will probably change my mind again tomorrow.
Here's a little rock-paper-scissors app that I made for gopher. I
felt that the quality turned out too low to post it on the main page,
but there's no harm in sharing it here.
Rock Paper Scissors - The Ultimate Game of Strategy
The random token at the end of the URL (e.g "/bfhqK3kH") doesn't
actually represent anything. I only added it for cache-busting on
lynx (otherwise you would always see the same result as the first
time you loaded the page). I really hate doing that because it screws
with the purity of my gopher routes. But a lot of people (including
myself) use lynx. It sort of reminds me of JS hacking to support old
Internet Explorer versions.
Now that I think about it, in the future I might disregard lynx and
settle with putting a disclaimer on the page about browser caching
breaking dynamic applications.
I recently stumbled across this interesting article on formatting:
ASCII Formatting in Gopher Menus
TITLE = Deeply indent, then precede and end phrase with arrows:
                ---> Title <---
HEADING = Left align, then box above and below with equal-signs:
BULLET = Indent, then precede with a dash and a space:
             - bullet
SUB-BULLET = Heavily indent, then precede with a tilde and a space:
                ~ sub-bullet
BOLD = Type phrase using all capitals:
ITALIC = Precede and end phrase with a dash:
BOLD/ITALIC = Combine the bold and italic indicators:
UNDERLINE = Precede and end phrase with a double-quote:
HIGHLIGHT = Precede and end phrase with a single-quote:
Unfortunately I couldn't find the date of when this was published.
It seems to be more-or-less a primitive version of markdown. Using
quotes for underline instead of _underline_ doesn't make any sense
to me. Using arrows for the title is an interesting idea though. I
wonder how many servers back in the 90's settled on a common scheme
for formatting. It's not something that was ever outlined in any of
the RFCs.
In related news, I've started using three periods to divide sections,
kind of like a 
 tag. I think it works pretty well.
New Release: Flask-Gopher 2.1.1
(GitHub) Flask-Gopher 2.1.1 Release Notes
Yesterday I discovered a bug in Flask-Gopher that was causing query
parameters to be chopped off the end of HTTP links.
The link that lead to the discovery
was redirecting here instead
Here's the source of the bug:
    def gopher_url_redirect(url):
        url = url_quote(url)
        return self.URL_REDIRECT_TEMPLATE.format(url=url).strip()
I had assumed that the flask  regex would capture
everything after the "/URL:". However, flask has special behavior
for query parameters where they get stripped and parsed separately
from the rest of the path. So the ``url`` variable only contained
the base path before the ? character.
This also got me thinking about how the URL string should be escaped
in the HTML redirect page. I was using URL escaping, when I *should*
have been using HTML *escaping*. At least... I think so.
Otherwise you could craft a malicious URL like this
(turns into)
(Stack Overflow) Difference between URL encode and HTML encode
Here's what I ended up changing it to:
    def gopher_url_redirect(url):
        # Use the full_path because it keeps any query params intact
        url = request.full_path.split(':', 1)[1]  # Drop the "/URL:"
        url = url.rstrip('?')  # Flask adds an ? even if there are no 
        url = escape(url)
        return self.URL_REDIRECT_TEMPLATE.format(url=url).strip()
Plaintext is beautiful!
...but is it, really?
I would rather read a LaTeX generated pdf than an ASCII version of
the same document. I would also rather read a Markdown formatted on Github than a plain text README in a project's root dir.
A little formatting can go a long way towards improving readability.
- headings are nice
- bold / italics / underlines are nice
- hypertext links are nice
I would absolutely love it if there was a link descriptor type in
gopher for markdown formatted text (say, "m"?). There are already
lots of cool tools for converting markdown to ANSI terminal codes.
Terminal Markdown Viewer (Github)
Go ahead, I know, you can't resist asking: "What is Mozz?"
Mozz is a 4-letter domain name that was still available in 2018.
Often short for "mozzarella" (a damn good cheese, in my top 5).
Pronunciation rhymes with "Woz", as in "Steve Woz-niak".
"Mozz in the morning, mozz in the evening, mozz at suppertime.
 When mozz is on a bagel, you can eat anytime!"
Fuck it, I'm starting a phlog.
I want a place to jot down random observations on gopher and
technology, site updates, and other junk. But I don't want the
pressure of maintaining an active blog and writing long-form
articles. To be honest, I don't actually like writing very much.
This'll work for now.
Don't expect much, and you won't be disappointed.
ps. That kick ass tiger logo was generated with "$ cowsay -f meow"
Wikipedia article on cowsay
                                . . .