| ---------------------------------------- | |
| Cosmic Voyage - Part 1 | |
| January 20th, 2019 | |
| ---------------------------------------- | |
| slackz [0] asked me to do some write-ups on cosmic.voyage from the | |
| architect POV. Here's part 1 of who knows how many. | |
| [0] slackz | |
| If you don't know what cosmic.voyage is read this first [1] | |
| [1] Cosmic Voyage | |
| Being a text-based writing adventure, and me being me, | |
| I immediately set out to make Cosmic sit primarily on gopher | |
| rather than web. At first I didn't plan to have a web presence for | |
| it at all, but that changed as things went along. Really, my goals | |
| and understanding of the system are ever-evolving and greatly | |
| informed by the active users. | |
| Regardless, things started with gopher. I knew I wanted a few | |
| things right away: | |
| - A single gopher structure, not individual user folders. | |
| - Users to be able to fully control their ships and stories, but | |
| not mess with other users' things | |
| - An ongoing log that linked everything together. | |
| I use motsognir [2] on gopher.black, but I thought it might be | |
| easier to write scripts as gophermaps for cosmic if I stuck with | |
| gophernicus. I could have made things in cgi scripts, but I like | |
| the transparent heirarchical structure I get to this way instead. | |
| [2] motsognir | |
| The structure of cosmic's gopher hole looks like this: | |
| ├── gophermap | |
| ├── intro.gophermap | |
| ├── listing.gophermap | |
| ├── log | |
| │ ├── gophermap | |
| │ └── intro.gophermap | |
| ├── Melchizedek (or any old ship) | |
| │ ├── 001.txt | |
| │ ├── 002.txt | |
| │ ├── 003.txt | |
| ├── Melvin P Feltersnatch (another example ship) | |
| │ ├── 001.txt | |
| │ ├── 002.txt | |
| │ └── 003.txt | |
| ├── rss.xml | |
| └── ships | |
| ├── gophermap | |
| ├── Melchizedek (example ship page directory) | |
| │ └── gophermap -> /var/gopher/ships/ship/gophermap | |
| ├── Melvin P Feltersnatch (another example ship page dir) | |
| │ └── gophermap -> /var/gopher/ships/ship/gophermap | |
| ├── ship | |
| │ └── gophermap | |
| └── ships.gophermap | |
| At the root level I have a gophermap that pulls in and processes | |
| other gophermaps, does a little shell scripting, and displays the | |
| basic content. Let's start by having a look at that code: | |
| =intro.gophermap | |
| 1Complete Transmission Log /log | |
| 1Ships, Colonies, Outposts /ships | |
| 0RSS Feed /rss.xml | |
| Most recent (20) log entries: | |
| =head -n 20 listing.gophermap | sed 's|^0||' | awk -v tot="$(wc -l listing.go… | |
| Gophernicus allows us to source in other gophermaps by using | |
| saying =gophermapname. In this way I can keep my intro text for | |
| cosmic in a separate file (which becomes helpful later when we | |
| look at web generation). Following that I have a few regular | |
| gophermap links using gophernicus' friendly shorthand syntax (no | |
| servername or port required). Finally I list the most recent log | |
| entries. | |
| In this, I grab the top 20 lines from listing.gophermap and number | |
| them properly. | |
| listing.gophermap is the heart of the cosmic log system. Each time | |
| a user adds a log to the site, it gets prepended to that file. | |
| That file in turn generates the log page, the short listings here, | |
| and content for the individual ship pages. It's a sensitive file | |
| because it needs to be writable by all users on the system. I've | |
| kicked around better ways to do that, but for now it seems to | |
| work. At least I back it up regularly. | |
| The /log/ page works very much like the root gophermap, but with | |
| a simpler rendering. | |
| =intro.gophermap | |
| =sed 's|^0||' /var/gopher/listing.gophermap | awk -v tot="$(wc -l /var/gopher… | |
| Simple, right? awk is the best. | |
| So what about the ship pages? Those are a little funkier. On the | |
| one hand, they pretty much just sed/awk their way through the | |
| listing.gophermap file as well, but there's also the matter of | |
| a navigable directory. | |
| From the list above you can see that there's a ships directory. | |
| Lets look more closely at an example: | |
| └── ships | |
| ├── gophermap | |
| ├── Enterprise NCC-1701 | |
| │ └── gophermap -> /var/gopher/ships/ship/gophermap | |
| ├── ship | |
| │ └── gophermap | |
| └── ships.gophermap | |
| The root gophermap of the ships page does a little more hard work. | |
| This has a few long lines that might not render well on your | |
| screen. I apologize!: | |
| #!/bin/sh | |
| cat "ships.gophermap" | |
| find "/var/gopher/" -maxdepth 1 ! -path "/var/gopher/" ! -path "/var/gopher/s… | |
| do | |
| entry_num=$(grep -c "^0${ship}" "/var/gopher/listing.gophermap") | |
| if [ "$entry_num" != "0" ]; then | |
| printf "1%s (%s)\\t/ships/%s\\n" "$ship" "$entry_num" "$ship" | |
| fi | |
| done | |
| We start by catting out the intro for the ships page from | |
| ships.gophermap, then we loop through all the ship directories on | |
| the system. Using each of those ships, we then check against | |
| listing.gophermap to see how many entries they have. If they don't | |
| have any entries, we leave them out of the listings. That was | |
| a nice idea from one of the cosmic users to avoid cluttering up | |
| the ship page with empty ships. If there ARE entries, we print | |
| a link to the ship page. | |
| The ship pages themselves are a bit of trickery. There's really | |
| only one ship page /ships/ship/gophermap. All the rest are just | |
| symlinks to it. But how!!?? What manner of sorcery is this? | |
| #!/bin/sh | |
| ship="$(/bin/pwd -L | sed 's|.*/||')" | |
| desc="/var/gopher/${ship}/.description" | |
| if [ -f "$desc" ]; then | |
| cat "$desc" | |
| printf "\\n" | |
| fi | |
| printf "%s - Ship Log\\n" "$ship" | |
| tac "/var/gopher/listing.gophermap" | sed "s|^0||" | awk '{print 0 NR " >> " … | |
| pwd -L gets the path of the current symlink, which reveals the | |
| ship name! Then we look to see if there's a ship description and | |
| finally we grab all the relevant logs from listings and number | |
| everything. | |
| Huzzah! | |
| That's it. That's the whole gopher structure that drives Cosmic | |
| Voyage. Next time I'll talk about the web generation and RSS | |
| feeds. | |
| If this inspired you to join the system, instructions can be found | |
| on cosmic's home page. See you in the stars! |