From ff4c91e6f69ab78daae89986d103c2f4610ba03b Mon Sep 17 00:00:00 2001 From: John Bowdre Date: Mon, 29 Jul 2024 20:05:42 -0500 Subject: [PATCH 01/15] generate robots.txt from darkvisitors api --- .github/workflows/deploy-prod.yml | 5 ++++- config/_default/params.toml | 30 ++++------------------------- config/local/hugo.toml | 3 ++- config/preview/hugo.toml | 3 ++- layouts/partials/dark-visitors.html | 27 ++++++++++++++++++++++++++ layouts/robots.txt | 6 ++---- 6 files changed, 41 insertions(+), 33 deletions(-) create mode 100644 layouts/partials/dark-visitors.html diff --git a/.github/workflows/deploy-prod.yml b/.github/workflows/deploy-prod.yml index 5001cf6..487ed45 100644 --- a/.github/workflows/deploy-prod.yml +++ b/.github/workflows/deploy-prod.yml @@ -45,7 +45,10 @@ jobs: echo "${{ secrets.SSH_KNOWN_HOSTS }}" > ~/.ssh/known_hosts chmod 644 ~/.ssh/known_hosts - name: Build with Hugo - run: HUGO_REMOTE_FONT_PATH=${{ secrets.REMOTE_FONT_PATH }} hugo --minify + run: | + HUGO_REMOTE_FONT_PATH=${{ secrets.REMOTE_FONT_PATH }} \ + HUGO_DARKVISITORS=${{ secrets.DARKVISITORS_TOKEN }} \ + hugo --minify - name: Insert 404 page run: | mkdir -p public/bunnycdn_errors diff --git a/config/_default/params.toml b/config/_default/params.toml index 9a5dc3e..e0f5d42 100644 --- a/config/_default/params.toml +++ b/config/_default/params.toml @@ -8,32 +8,10 @@ numberOfRelatedPosts = 5 indexTitle = ".-. ..- -. - .. -- . - . .-. .-. --- .-." -bad_robots = [ - "AdsBot-Google", - "Amazonbot", - "anthropic-ai", - "Applebot-Extended", - "AwarioRssBot", - "AwarioSmartBot", - "Bytespider", - "CCBot", - "ChatGPT", - "ChatGPT-User", - "Claude-Web", - "ClaudeBot", - "cohere-ai", - "DataForSeoBot", - "Diffbot", - "FacebookBot", - "Google-Extended", - "GPTBot", - "ImagesiftBot", - "magpie-crawler", - "omgili", - "Omgilibot", - "peer39_crawler", - "PerplexityBot", - "YouBot" +darkVisitors = [ + "AI Assistant", + "AI Data Scraper", + "AI Search Crawler" ] # Comments diff --git a/config/local/hugo.toml b/config/local/hugo.toml index 0873821..fe992f0 100644 --- a/config/local/hugo.toml +++ b/config/local/hugo.toml @@ -1 +1,2 @@ -baseURL = "http://localhost:1313/" \ No newline at end of file +baseURL = "http://localhost:1313/" +enableRobotsTXT = false \ No newline at end of file diff --git a/config/preview/hugo.toml b/config/preview/hugo.toml index f9f012b..bdba38b 100644 --- a/config/preview/hugo.toml +++ b/config/preview/hugo.toml @@ -1 +1,2 @@ -baseURL = "https://preview.runtimeterror.dev/" \ No newline at end of file +baseURL = "https://preview.runtimeterror.dev/" +enableRobotsTXT = false \ No newline at end of file diff --git a/layouts/partials/dark-visitors.html b/layouts/partials/dark-visitors.html new file mode 100644 index 0000000..00c234b --- /dev/null +++ b/layouts/partials/dark-visitors.html @@ -0,0 +1,27 @@ +{{/* borrowed from https://github.com/lkhrs/hugo-dark-visitors */}} +{{- $url := "https://api.darkvisitors.com/robots-txts" -}} +{{- $api_key := getenv "HUGO_DARKVISITORS" -}} +{{- $bearer := printf "Bearer %v" $api_key -}} +{{- $agent_types := slice -}} +{{- if .Site.Params.darkVisitors -}} + {{- range .Site.Params.darkVisitors -}} + {{- $agent_types = $agent_types | append . -}} + {{- end -}} +{{- else -}} + {{- $agent_types = slice "AI Data Scraper" -}} +{{- end -}} +{{- $agent_types := $agent_types | jsonify -}} +{{- $opts := dict + "method" "post" + "headers" (dict "Authorization" (slice $bearer) "Content-Type" "application/json") + "body" (printf `{"agent_types": %s,"disallow": "/"}` $agent_types) +-}} +{{- with resources.GetRemote $url $opts -}} + {{- with .Err -}} + {{- errorf "%s" . -}} + {{- else -}} + {{- .Content -}} + {{- end -}} +{{- else -}} + {{- errorf "Unable to get remote resource %q" $url -}} +{{- end -}} \ No newline at end of file diff --git a/layouts/robots.txt b/layouts/robots.txt index 6c7d9c0..2a7e039 100644 --- a/layouts/robots.txt +++ b/layouts/robots.txt @@ -7,7 +7,5 @@ User-agent: * Disallow: # except for these bots which are not friends: -{{ range .Site.Params.bad_robots }} -User-agent: {{ . }} -{{- end }} -Disallow: / + +{{ partial "dark-visitors.html" . }} From 16aa1d580c0d30fb8ac800f98bcfc5c9baee089f Mon Sep 17 00:00:00 2001 From: John Bowdre Date: Mon, 29 Jul 2024 20:57:39 -0500 Subject: [PATCH 02/15] changelog: dark visitors --- content/changelog.md | 5 ++++- layouts/partials/dark-visitors.html | 2 +- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/content/changelog.md b/content/changelog.md index 5d48d4c..5c245da 100644 --- a/content/changelog.md +++ b/content/changelog.md @@ -1,7 +1,7 @@ --- title: "/changelog" date: "2024-05-26T21:19:08Z" -lastmod: "2024-07-04T02:32:27Z" +lastmod: "2024-07-30T01:49:28Z" description: "Maybe I should keep a log of all my site-related tinkering?" featured: false toc: false @@ -10,6 +10,9 @@ categories: slashes --- *High-level list of config/layout changes to the site. The full changelog is of course [on GitHub](https://github.com/jbowdre/runtimeterror/commits/main/).* +**2024-07-29:** +- Build `robots.txt` dynamically with [Dark Visitors API](https://darkvisitors.com/) and code from [Luke Harris](https://www.lkhrs.com/blog/2024/darkvisitors-hugo/) + **2024-07-03:** - Remove `target="_blank"` from external links for improved security and accessibility diff --git a/layouts/partials/dark-visitors.html b/layouts/partials/dark-visitors.html index 00c234b..e7aec71 100644 --- a/layouts/partials/dark-visitors.html +++ b/layouts/partials/dark-visitors.html @@ -1,4 +1,4 @@ -{{/* borrowed from https://github.com/lkhrs/hugo-dark-visitors */}} +{{/* borrowed from Luke Harris @ https://github.com/lkhrs/hugo-dark-visitors */}} {{- $url := "https://api.darkvisitors.com/robots-txts" -}} {{- $api_key := getenv "HUGO_DARKVISITORS" -}} {{- $bearer := printf "Bearer %v" $api_key -}} From 2b0e8998143ea38b20d00d2cdd8f484813c0306f Mon Sep 17 00:00:00 2001 From: John Bowdre Date: Tue, 30 Jul 2024 09:00:12 -0500 Subject: [PATCH 03/15] update post with note on davfs2 group membership --- .../taking-taildrive-testdrive/davfs-suid.png | Bin 92698 -> 0 bytes .../posts/taking-taildrive-testdrive/index.md | 16 ++++++++++------ 2 files changed, 10 insertions(+), 6 deletions(-) delete mode 100644 content/posts/taking-taildrive-testdrive/davfs-suid.png diff --git a/content/posts/taking-taildrive-testdrive/davfs-suid.png b/content/posts/taking-taildrive-testdrive/davfs-suid.png deleted file mode 100644 index 71a658e12ba61423dcf1277f877338e4d1610e4d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 92698 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 o{qJJ_w}` response... before I realized that was probably a mistake (at least for this particular use case). +I need to be able mount the share as my standard user account (*without* elevation) to ensure that the ownership and permissions are correctly inherited. The `davfs2` installer offered to enable the SUID bit to support this, but that change on its own doesn't seem to have been sufficient in my testing. In addition (or perhaps instead?), I had to add my account to the `davfs2` group: -So I ran `sudo dpkg-reconfigure davfs2` to try again and this time made sure to select ``: +```shell +sudo usermod -aG davfs2 $USER # [tl! .cmd] +``` -![Should unprivileged users be allowed to mount WebDAV resources?](davfs-suid.png) +And then use the `newgrp` command to load the new membership without having to log out and back in again: -That should ensure that the share gets mounted with appropriate privileges (otherwise, all the files would be owned by `root` and that could pose some additional challenges). +```shell +newgrp davfs2 # [tl! .cmd] +``` -I also created a folder inside my home directory to use as a mountpoint: +Next I created a folder inside my home directory to use as a mountpoint: ```shell mkdir ~/taildrive # [tl! .cmd] From 6d48fbdd60db05e202363d6d3e04ae829e740b28 Mon Sep 17 00:00:00 2001 From: John Bowdre Date: Wed, 31 Jul 2024 17:03:14 -0500 Subject: [PATCH 04/15] update flake --- flake.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/flake.lock b/flake.lock index 8d2ab6e..7adbffd 100644 --- a/flake.lock +++ b/flake.lock @@ -2,11 +2,11 @@ "nodes": { "nixpkgs": { "locked": { - "lastModified": 1719254875, - "narHash": "sha256-ECni+IkwXjusHsm9Sexdtq8weAq/yUyt1TWIemXt3Ko=", + "lastModified": 1722185531, + "narHash": "sha256-veKR07psFoJjINLC8RK4DiLniGGMgF3QMlS4tb74S6k=", "owner": "nixos", "repo": "nixpkgs", - "rev": "2893f56de08021cffd9b6b6dfc70fd9ccd51eb60", + "rev": "52ec9ac3b12395ad677e8b62106f0b98c1f8569d", "type": "github" }, "original": { From 42dabaa2f4a1904d5d0fa86a2d481e65ff5c51fb Mon Sep 17 00:00:00 2001 From: John Bowdre Date: Wed, 31 Jul 2024 17:03:25 -0500 Subject: [PATCH 05/15] update colophon with robots.txt info --- content/colophon.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/content/colophon.md b/content/colophon.md index fda61d4..46d5644 100644 --- a/content/colophon.md +++ b/content/colophon.md @@ -1,7 +1,7 @@ --- title: "/colophon" date: "2024-05-26T22:30:58Z" -lastmod: "2024-06-29T03:29:46Z" +lastmod: "2024-07-31T22:01:11Z" description: "There's a lot that goes into this site. Let me tell you how it works." featured: false toc: true @@ -15,9 +15,10 @@ categories: slashes - uses the font face [Berkeley Mono](https://berkeleygraphics.com/typefaces/berkeley-mono/) ([details](/using-custom-font-hugo/)), and icons from [Font Awesome](https://fontawesome.com/) and [Fork Awesome](https://forkaweso.me/). - performs syntax highlighting with [Torchlight](https://torchlight.dev) ([details](/spotlight-on-torchlight/)). - provides site search with [lunr](https://lunrjs.com/) based on an implementation detailed by [Victoria Drake](https://victoria.dev/blog/add-search-to-hugo-static-sites-with-lunr/). +- uses [Dark Visitors](https://darkvisitors.com/docs/robots-txt)'s API to dynamically generate a [robots.txt](/robots.txt) discouraging AI scrapers with some Hugo code from [Luke Harris](https://github.com/lkhrs/hugo-dark-visitors). - leverages [Cabin](https://withcabin.com) for [privacy-friendly](https://withcabin.com/privacy/runtimeterror.dev) analytics. - resolves via [Bunny DNS](https://bunny.net/dns/). -- is published to / hosted on [Bunny Storage](https://bunny.net/storage/) and [Bunny CDN](https://bunny.net/cdn/) with a [GitHub Actions workflow](//further-down-the-bunny-hole/) +- is published to / hosted on [Bunny Storage](https://bunny.net/storage/) and [Bunny CDN](https://bunny.net/cdn/) with a [GitHub Actions workflow](//further-down-the-bunny-hole/). - has a [Gemini](https://geminiprotocol.net) mirror at `gemini://gmi.runtimeterror.dev`. This is generated from a [Hugo gemtext post layout](https://github.com/jbowdre/runtimeterror/blob/main/layouts/_default/single.gmi), deployed to a [Vultr](https://www.vultr.com/) VPS through that same GitHub Actions workflow, and served with [Agate](https://github.com/mbrubeck/agate). The post content is licensed under [CC BY-NC-SA 4.0](https://creativecommons.org/licenses/by-nc-sa/4.0/); the site code is under the [MIT License](https://github.com/jbowdre/runtimeterror/blob/main/LICENSE). From 797560c7a3a684ca46bbce2755a19c20a42735ef Mon Sep 17 00:00:00 2001 From: John Bowdre Date: Fri, 2 Aug 2024 16:19:45 -0500 Subject: [PATCH 06/15] avoid uncorrected typos at end of string --- assets/js/typo.js | 232 ++++++++++++++++++++-------------------------- 1 file changed, 102 insertions(+), 130 deletions(-) diff --git a/assets/js/typo.js b/assets/js/typo.js index b1416e6..7fc1ccf 100644 --- a/assets/js/typo.js +++ b/assets/js/typo.js @@ -28,168 +28,140 @@ SOFTWARE. */ function num_between(min, max) { - return Math.floor(Math.random() * (max- min + 1) + min); + return Math.floor(Math.random() * (max- min + 1) + min); } function chance(val) { - if(num_between(0, 100) < val) return true; - else return false; + if(num_between(0, 100) < val) return true; + else return false; } function sleep(ms) { - return new Promise(resolve => setTimeout(resolve, ms)); + return new Promise(resolve => setTimeout(resolve, ms)); } var typos = { - q:['w','a'], - w:['q','r','s'], - e:['w','d','r'], - r:['e','f','t'], - t:['r','g','y'], - y:['t','h','u'], - u:['y','j','i'], - i:['u','k','o'], - o:['i','l','p'], - p:['o',';','['], - a:['q','s','z'], - s:['w','a','x','d'], - d:['e','s','c','f'], - f:['r','d','v','g'], - g:['t','f','b','h'], - h:['y','g','n','j'], - j:['u','h','m','k'], - k:['i','j',',','l'], - l:['o','k','.',';'], - z:['a','x'], - x:['z','s','c'], - c:['x','d','v'], - v:['c','f','b'], - b:['v','g','n'], - n:['b','h','m'], - m:['n','j',','], + q:['w','a'], + w:['q','r','s'], + e:['w','d','r'], + r:['e','f','t'], + t:['r','g','y'], + y:['t','h','u'], + u:['y','j','i'], + i:['u','k','o'], + o:['i','l','p'], + p:['o',';','['], + a:['q','s','z'], + s:['w','a','x','d'], + d:['e','s','c','f'], + f:['r','d','v','g'], + g:['t','f','b','h'], + h:['y','g','n','j'], + j:['u','h','m','k'], + k:['i','j',',','l'], + l:['o','k','.',';'], + z:['a','x'], + x:['z','s','c'], + c:['x','d','v'], + v:['c','f','b'], + b:['v','g','n'], + n:['b','h','m'], + m:['n','j',','], } async function typo(element, text) { - var buffer = ''; - var typo_active = false; - var tag_active = false; - var typing_typos = (element.dataset.typoChance) ? element.dataset.typoChance : 10; - var typing_speed = (element.dataset.typingDelay) ? element.dataset.typingDelay : 50; - var typing_jitter = (element.dataset.typingJitter) ? element.dataset.typingJitter : 15; + var buffer = ''; + var typo_active = false; + var typing_typos = (element.dataset.typoChance) ? element.dataset.typoChance : 10; + var typing_speed = (element.dataset.typingDelay) ? element.dataset.typingDelay : 50; + var typing_jitter = (element.dataset.typingJitter) ? element.dataset.typingJitter : 15; - for (var i = 0; i < text.length; i++) { + for (var i = 0; i < text.length; i++) { + // Get the letter that we're supposed to type + letter = text.charAt(i); - // Get the letter that we’re supposed to type - letter = text.charAt(i); + // Trigger a typo + if(chance(typing_typos) && typo_active === false && i > 1 && i < text.length - 3) { + if(typeof typos[letter] !== 'undefined') { + // Swap the letter with a random typo + typo = typos[letter][Math.floor(Math.random() * typos[letter].length)]; - // TODO: actual support for html or markup or whatever + // Append the letter to the buffer + buffer = buffer + typo; - /* - // Handle elements/markup - if(letter == '<' && ( - text.charAt(i+1) == 's' || - text.charAt(i+1) == 'p' || - text.charAt(i+1) == 'a' || - text.charAt(i+1) == '/' || - text.charAt(i+1) == 'i') - ) { - tag_active = true; - } + // Write the buffer + element.innerHTML = buffer; - if(tag_active) { + typo_active = true; + var seed = num_between(2,5); // Reduced max seed to ensure correction + realization_delay = seed; + realization_delay_counter = seed; + } + } - buffer = buffer + letter; - element.innerHTML = buffer; + // Append the letter to the buffer + buffer = buffer + letter; - if(letter == '>' && ( - text.charAt(i-1) == 'n' || - text.charAt(i-1) == 'a' || - text.charAt(i-1) == 'p' || - text.charAt(i+1) == '"' || - text.charAt(i+1) == '/') - ) { - tag_active = false; - await sleep(typing_speed); - } - continue; - } - */ + // Write the buffer + element.innerHTML = buffer; - // Trigger a typo - if(chance(typing_typos) && typo_active === false && i > 1) { + // Typical typing speed + var speed_lower = parseFloat(typing_speed) - parseInt(typing_jitter); + var speed_upper = parseFloat(typing_speed) + parseInt(typing_jitter); - if(typeof typos[letter] !== 'undefined') { + delay = num_between(speed_lower,speed_upper); - // Swap the letter with a random typo - typo = typos[letter][Math.floor(Math.random() * typos[letter].length)]; + // Chance of longer delay though + if(chance(5)) delay = num_between(100, 200); + await sleep(delay); - // Append the letter to the buffer - buffer = buffer + typo; + if(typo_active) { + realization_delay_counter--; - // Write the buffer - element.innerHTML = buffer; + if(realization_delay_counter == 0) { + for (var k = 0; k < seed+1; k++) { + // Pause at realization of typo + await sleep(typing_jitter); - typo_active = true; - var seed = num_between(2,5); - realization_delay = seed; - realization_delay_counter = seed; - } - } + // Rewind the buffer! + buffer = buffer.substring(0, buffer.length - 1); - // Append the letter to the buffer - buffer = buffer + letter; + // Write rewound buffer + element.innerHTML = buffer; - // Write the buffer - element.innerHTML = buffer; + // Brief pause before continuing + await sleep(30); + } - // Typical typing speed - var speed_lower = parseFloat(typing_speed) - parseInt(typing_jitter); - var speed_upper = parseFloat(typing_speed) + parseInt(typing_jitter); + typo_active = false; - delay = num_between(speed_lower,speed_upper); + // Add the letters back + i = i - seed; + await sleep(100); + } + } + } - // Chance of longer delay though - if(chance(5)) delay = num_between(100, 200); - await sleep(delay); + // Ensure any remaining typo is corrected + if(typo_active) { + await sleep(typing_jitter * 2); + for (var k = 0; k < seed+1; k++) { + buffer = buffer.substring(0, buffer.length - 1); + element.innerHTML = buffer; + await sleep(30); + } + for (var k = 0; k < seed; k++) { + buffer += text.charAt(text.length - seed + k); + element.innerHTML = buffer; + await sleep(typing_speed); + } + } - if(typo_active) { - - realization_delay_counter--; - - if(realization_delay_counter == 0) { - - for (var k = 0; k < seed+1; k++) { - - // Pause at realization of typo - await sleep(typing_jitter); - - // Rewind the buffer! - buffer = buffer.substring(0, buffer.length - 1); - - // Write rewound buffer - element.innerHTML = buffer; - - // Brief pause before continuing - await sleep(30); - } - - typo_active = false; - - // Add the letters back - i = i - seed; - await sleep(100); - } - } - } - - // Whatever you do here will happen when the typing is finished - //do_something(); - - return new Promise(resolve => setTimeout(resolve, 1)); + return new Promise(resolve => setTimeout(resolve, 1)); } document.addEventListener('DOMContentLoaded', function() { - var element = document.getElementById('tagline'); - var text = element.innerHTML; - typo(element, text); + var element = document.getElementById('tagline'); + var text = element.innerHTML; + typo(element, text); }); \ No newline at end of file From a318d91ed24568491baf24b03b286201bc8ea435 Mon Sep 17 00:00:00 2001 From: John Bowdre Date: Fri, 2 Aug 2024 16:20:36 -0500 Subject: [PATCH 07/15] retrieve recent pinned track from musicthread --- assets/js/theme-song.js | 20 ++++++++++++++++++++ config/_default/params.toml | 3 +++ layouts/partials/aside.html | 11 ++++++++--- static/css/custom.css | 26 +++++++++++++++++++------- 4 files changed, 50 insertions(+), 10 deletions(-) create mode 100644 assets/js/theme-song.js diff --git a/assets/js/theme-song.js b/assets/js/theme-song.js new file mode 100644 index 0000000..ae1c2a4 --- /dev/null +++ b/assets/js/theme-song.js @@ -0,0 +1,20 @@ +// retreives the latest link from a musicthread thread and displays it on the page +const themeSongScript = document.currentScript +const urlParams = new URLSearchParams(themeSongScript.src.split('.js')[1]) +const params = Object.fromEntries(urlParams.entries()) + +if (params.id) +{ + const musicthread = `https://musicthread.app/api/v0/thread/${params.id}` + fetch(musicthread) + .then((response) => response.json()) + .then((thread) => { + let themeSong = thread.links[0] + console.log(themeSong) + themeSongContainer = document.createElement('div') + themeSongContainer.className = 'theme-song' + themeSongContainer.style + themeSongContainer.innerHTML = `
${themeSong.title}
${themeSong.artist}` + themeSongScript.parentNode.insertBefore(themeSongContainer, themeSongScript) + }) +} \ No newline at end of file diff --git a/config/_default/params.toml b/config/_default/params.toml index e0f5d42..54b31c3 100644 --- a/config/_default/params.toml +++ b/config/_default/params.toml @@ -14,6 +14,9 @@ darkVisitors = [ "AI Search Crawler" ] +omgUser = "jbowdre" +musicThreadId = "2aVjZUocjk96LELFbV5JvJjm14v" + # Comments analytics = true reply = true diff --git a/layouts/partials/aside.html b/layouts/partials/aside.html index fb1f687..334cd32 100644 --- a/layouts/partials/aside.html +++ b/layouts/partials/aside.html @@ -51,10 +51,15 @@ {{- end }} {{- end }} +{{ with .Site.Params.omgUser }}

status.lol

- + +{{ end }} +{{ with .Site.Params.musicThreadId }}
-

latest track

- +

current theme song

+{{ $jsThemeSong := resources.Get "js/theme-song.js" | minify }} + +{{ end }} diff --git a/static/css/custom.css b/static/css/custom.css index 957eb3d..95717b2 100644 --- a/static/css/custom.css +++ b/static/css/custom.css @@ -238,16 +238,28 @@ small[style^="opacity: .5"] { opacity: 1 !important; } -/* recentfm styling */ -.recent-played { +/* theme song styling */ +.theme-song { background: var(--off-bg) !important; - flex-direction:column; - border-radius: 0.5em; - padding: 0.5em; + display: flex; + flex-direction: column; + border-radius: 0.5rem; + padding: 0.7rem; + font-size: 0.9rem; + line-height: 0.9rem; } -.recent-played-track { - margin: 0.5em 0; +.theme-song img { + width: 14rem; + height: auto; + object-fit: cover; +} + +@media (min-width: 45rem) { + .theme-song img { + max-width: 100%; + margin: 0 auto; + } } /* code overrides */ From 739e21645b1140333912b56dacf833828e07f338 Mon Sep 17 00:00:00 2001 From: John Bowdre Date: Fri, 2 Aug 2024 16:20:47 -0500 Subject: [PATCH 08/15] update changelog, colophon --- content/changelog.md | 6 +++++- content/colophon.md | 4 +++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/content/changelog.md b/content/changelog.md index 5c245da..32d9526 100644 --- a/content/changelog.md +++ b/content/changelog.md @@ -1,7 +1,7 @@ --- title: "/changelog" date: "2024-05-26T21:19:08Z" -lastmod: "2024-07-30T01:49:28Z" +lastmod: "2024-08-02T21:16:14Z" description: "Maybe I should keep a log of all my site-related tinkering?" featured: false toc: false @@ -10,6 +10,10 @@ categories: slashes --- *High-level list of config/layout changes to the site. The full changelog is of course [on GitHub](https://github.com/jbowdre/runtimeterror/commits/main/).* +**2024-08-02:** +- Display "pinned" recent track in sidebar using [MusicThread](https://musicthread.app) instead of latest scrobble +- Tweak Typo behavior to avoid uncorrected mistakes near the end of the string + **2024-07-29:** - Build `robots.txt` dynamically with [Dark Visitors API](https://darkvisitors.com/) and code from [Luke Harris](https://www.lkhrs.com/blog/2024/darkvisitors-hugo/) diff --git a/content/colophon.md b/content/colophon.md index 46d5644..d7c8c6b 100644 --- a/content/colophon.md +++ b/content/colophon.md @@ -1,7 +1,7 @@ --- title: "/colophon" date: "2024-05-26T22:30:58Z" -lastmod: "2024-07-31T22:01:11Z" +lastmod: "2024-08-02T21:16:41Z" description: "There's a lot that goes into this site. Let me tell you how it works." featured: false toc: true @@ -17,6 +17,8 @@ categories: slashes - provides site search with [lunr](https://lunrjs.com/) based on an implementation detailed by [Victoria Drake](https://victoria.dev/blog/add-search-to-hugo-static-sites-with-lunr/). - uses [Dark Visitors](https://darkvisitors.com/docs/robots-txt)'s API to dynamically generate a [robots.txt](/robots.txt) discouraging AI scrapers with some Hugo code from [Luke Harris](https://github.com/lkhrs/hugo-dark-visitors). - leverages [Cabin](https://withcabin.com) for [privacy-friendly](https://withcabin.com/privacy/runtimeterror.dev) analytics. +- fetches recently-played music from [MusicThread](https://musicthread.app/). +- displays my latest status from [omg.lol](https://home.omg.lol/referred-by/jbowdre). - resolves via [Bunny DNS](https://bunny.net/dns/). - is published to / hosted on [Bunny Storage](https://bunny.net/storage/) and [Bunny CDN](https://bunny.net/cdn/) with a [GitHub Actions workflow](//further-down-the-bunny-hole/). - has a [Gemini](https://geminiprotocol.net) mirror at `gemini://gmi.runtimeterror.dev`. This is generated from a [Hugo gemtext post layout](https://github.com/jbowdre/runtimeterror/blob/main/layouts/_default/single.gmi), deployed to a [Vultr](https://www.vultr.com/) VPS through that same GitHub Actions workflow, and served with [Agate](https://github.com/mbrubeck/agate). From e3bceb49d91b3a023b611dfdb47384ff1e2cbc0b Mon Sep 17 00:00:00 2001 From: John Bowdre Date: Sat, 3 Aug 2024 10:52:12 -0500 Subject: [PATCH 09/15] blog.jbowdre.lol -> srsbsns.lol --- config/_default/params.toml | 2 +- content/about.md | 2 +- content/changelog.md | 2 +- content/homelab.md | 2 +- content/posts/display-tempest-weather-static-site/index.md | 2 +- content/posts/further-down-the-bunny-hole/index.md | 4 ++-- content/posts/kudos-with-cabin/index.md | 2 +- content/posts/prettify-hugo-rss-feed-xslt/index.md | 2 +- content/posts/using-custom-font-hugo/index.md | 4 ++-- content/save.md | 2 +- content/uses.md | 2 +- 11 files changed, 13 insertions(+), 13 deletions(-) diff --git a/config/_default/params.toml b/config/_default/params.toml index 54b31c3..eb7775c 100644 --- a/config/_default/params.toml +++ b/config/_default/params.toml @@ -148,7 +148,7 @@ url = "https://jbowdre.lol" [[socialLinks]] icon = "fa-solid fa-pen-to-square" title = "Weblog" -url = "https://blog.jbowdre.lol" +url = "https://srsbsns.lol" [[socialLinks]] icon = "fa-solid fa-satellite" diff --git a/content/about.md b/content/about.md index 60c0d3c..de4197d 100644 --- a/content/about.md +++ b/content/about.md @@ -27,7 +27,7 @@ And in the free time I have left, I game on my Steam Deck. ### See what I've been up to on: - [GitHub](https://github.com/jbowdre) -- [Weblog](https://blog.jbowdre.lol) +- [Weblog](https://srsbsns.lol) - [Gemlog](https://capsule.jbowdre.lol/gemlog/) - [status.lol](https://status.jbowdre.lol) - [social.lol](https://social.lol/@jbowdre) diff --git a/content/changelog.md b/content/changelog.md index 32d9526..28539f9 100644 --- a/content/changelog.md +++ b/content/changelog.md @@ -23,7 +23,7 @@ categories: slashes **2024-06-28:** - Add [recentfm.js](https://recentfm.rknight.me/) recently-played widget to sidebar - Use [Hugo render-hook](https://gohugo.io/render-hooks/links/#examples) to add β†— marker to external links -- Redirect /uses and /saves to pages on the [personal blog](https://blog.jbowdre.lol) +- Redirect /uses and /saves to pages on the [personal blog](https://srsbsns.lol) **2024-06-24:** - Select the [CC BY-NC-SA 4.0](https://creativecommons.org/licenses/by-nc-sa/4.0/?ref=chooser-v1) license diff --git a/content/homelab.md b/content/homelab.md index ee10ba9..07d11a1 100644 --- a/content/homelab.md +++ b/content/homelab.md @@ -79,6 +79,6 @@ I like to know what's flying overhead, and I'm also feeding flight data to [flig - [Kineto](https://github.com/beelux/kineto) Gemini-to-HTTP proxy ([post](/gemini-capsule-gempost-github-actions/)) - [Linkding](https://github.com/sissbruecker/linkding) bookmark manager serving [links.bowdre.net](https://links.bowdre.net/bookmarks/shared) - [ntfy](https://ntfy.sh/) notification service ([post](/easy-push-notifications-with-ntfy/)) - - [SearXNG](https://docs.searxng.org/) self-hosted metasearch engine serving [grep.vpota.to](https://grep.vpota.to) ([post](https://blog.jbowdre.lol/post/self-hosting-a-search-engine-iyjdlk6y)) + - [SearXNG](https://docs.searxng.org/) self-hosted metasearch engine serving [grep.vpota.to](https://grep.vpota.to) ([post](https://srsbsns.lol/post/self-hosting-a-search-engine-iyjdlk6y)) - [Uptime Kuma](https://github.com/louislam/uptime-kuma) for monitoring internal services (via Tailscale) - [vault-unseal](https://github.com/lrstanley/vault-unseal) to auto-unseal my on-prem Vault instance diff --git a/content/posts/display-tempest-weather-static-site/index.md b/content/posts/display-tempest-weather-static-site/index.md index c5e8693..446ad32 100644 --- a/content/posts/display-tempest-weather-static-site/index.md +++ b/content/posts/display-tempest-weather-static-site/index.md @@ -14,7 +14,7 @@ tags: - meta - serverless --- -As I covered briefly [in a recent Scribble](https://blog.jbowdre.lol/post/near-realtime-weather-on-profile-lol-ku4yq-zr), I was inspired by the way [Kris's omg.lol page](https://kris.omg.lol/) displays realtime data from his [Weatherflow Tempest weather station](https://shop.weatherflow.com/products/tempest). I thought that was really neat and wanted to do the same on [my omg.lol page](https://jbowdre.lol) with data from my own Tempest, but I wanted to find a way to do it without needing to include an authenticated API call in the client-side JavaScript. +As I covered briefly [in a recent Scribble](https://srsbsns.lol/post/near-realtime-weather-on-profile-lol-ku4yq-zr), I was inspired by the way [Kris's omg.lol page](https://kris.omg.lol/) displays realtime data from his [Weatherflow Tempest weather station](https://shop.weatherflow.com/products/tempest). I thought that was really neat and wanted to do the same on [my omg.lol page](https://jbowdre.lol) with data from my own Tempest, but I wanted to find a way to do it without needing to include an authenticated API call in the client-side JavaScript. I realized I could use a GitHub Actions workflow to retrieve the data from the authenticated Tempest API, post it somewhere publicly accessible, and then have the client-side code fetch the data from there without needing any authentication. After a few days of tinkering, I came up with a presentation I'm happy with. diff --git a/content/posts/further-down-the-bunny-hole/index.md b/content/posts/further-down-the-bunny-hole/index.md index dab9a40..2cc4af2 100644 --- a/content/posts/further-down-the-bunny-hole/index.md +++ b/content/posts/further-down-the-bunny-hole/index.md @@ -14,11 +14,11 @@ tags: - meta - selfhosting --- -It wasn't too long ago (January, in fact) that I started [hosting this site with Neocities](/deploy-hugo-neocities-github-actions/). I was pretty pleased with that setup, but a few weeks ago my [monitoring setup](https://blog.jbowdre.lol/post/upptime-serverless-server-monitoring-c88fbaz7) started reporting that the site was down. And sure enough, trying to access the site would return a generic error message stating that the site was unknown. I eventually discovered that this was due to Neocities "forgetting" that the site was linked to the `runtimeterror.dev` domain. It was easy enough to just re-enter that domain in the configuration, and that immediately fixed things... until a few days later when the same thing happened again. +It wasn't too long ago (January, in fact) that I started [hosting this site with Neocities](/deploy-hugo-neocities-github-actions/). I was pretty pleased with that setup, but a few weeks ago my [monitoring setup](https://srsbsns.lol/post/upptime-serverless-server-monitoring-c88fbaz7) started reporting that the site was down. And sure enough, trying to access the site would return a generic error message stating that the site was unknown. I eventually discovered that this was due to Neocities "forgetting" that the site was linked to the `runtimeterror.dev` domain. It was easy enough to just re-enter that domain in the configuration, and that immediately fixed things... until a few days later when the same thing happened again. The same problem has now occurred five or six times, and my messages to the Neocities support contact have gone unanswered. I didn't see anyone else online reporting this exact issue, but I found several posts on Reddit about sites getting randomly broken (or even deleted!) and support taking a week (or more) to reply. I don't have that kind of patience, so I started to consider moving my content away from Neocities and cancelling my $5/month Supporter subscription. -I [recently](https://blog.jbowdre.lol/post/i-just-hopped-to-bunny-net) started using [bunny.net](https://bunny.net) for the site's DNS, and had also [leveraged Bunny's CDN for hosting font files](/using-custom-font-hugo/). This setup has been working great for me, and I realized that I could also use Bunny's CDN for hosting the entirety of my static site as well. After all, serving static files on the web is exactly what a CDN is great at. After an hour or two of tinkering, I successfully switched hosting setups with just a few seconds of downtime. +I [recently](https://srsbsns.lol/post/i-just-hopped-to-bunny-net) started using [bunny.net](https://bunny.net) for the site's DNS, and had also [leveraged Bunny's CDN for hosting font files](/using-custom-font-hugo/). This setup has been working great for me, and I realized that I could also use Bunny's CDN for hosting the entirety of my static site as well. After all, serving static files on the web is exactly what a CDN is great at. After an hour or two of tinkering, I successfully switched hosting setups with just a few seconds of downtime. Here's how I did it. diff --git a/content/posts/kudos-with-cabin/index.md b/content/posts/kudos-with-cabin/index.md index e768da2..4430cc6 100644 --- a/content/posts/kudos-with-cabin/index.md +++ b/content/posts/kudos-with-cabin/index.md @@ -18,7 +18,7 @@ I'm not one to really worry about page view metrics, but I do like to see which In my quest for such knowledge, last week I switched my various web properties back to using [Cabin](https://withcabin.com/) for "privacy-first, carbon conscious web analytics". I really like how lightweight and deliberately minimal Cabin is, and the portal does a great job of presenting the information that I care about. With this change, though, I gave up the cute little upvote widgets provided by the previous analytics platform. -I recently shared [on my Bear weblog](https://blog.jbowdre.lol/tracking-bear-upvotes-from-my-cabin/) about how I was hijacking Bear's built-in upvote button to send a "kudos" [event](https://docs.withcabin.com/events.html) to Cabin and tally those actions there. +I recently shared [on my Bear weblog](https://srsbsns.lol/tracking-bear-upvotes-from-my-cabin/) about how I was hijacking Bear's built-in upvote button to send a "kudos" [event](https://docs.withcabin.com/events.html) to Cabin and tally those actions there. Well today I implemented a similar thing on *this* blog. Without an existing widget to hijack, I needed to create this one from scratch using a combination of HTML in my page template, CSS to style it, and JavaScript to fire the event. diff --git a/content/posts/prettify-hugo-rss-feed-xslt/index.md b/content/posts/prettify-hugo-rss-feed-xslt/index.md index 3398947..77544ad 100644 --- a/content/posts/prettify-hugo-rss-feed-xslt/index.md +++ b/content/posts/prettify-hugo-rss-feed-xslt/index.md @@ -180,7 +180,7 @@ That's getting there: ![A darker styled RSS page](getting-there-feed.png) -Including those CSS styles means that the rendered page now uses my color palette and the [font I worked so hard to integrate](/using-custom-font-hugo/). I'm just going to make a few more tweaks to change some of the formatting, put the `New to feeds?` bit on its own line, and point to [Mojeek](https://mojeek.com) instead of DDG ([why?](https://blog.jbowdre.lol/post/a-comprehensive-evaluation-of-various-search-engines-i-ve-used)). +Including those CSS styles means that the rendered page now uses my color palette and the [font I worked so hard to integrate](/using-custom-font-hugo/). I'm just going to make a few more tweaks to change some of the formatting, put the `New to feeds?` bit on its own line, and point to [Mojeek](https://mojeek.com) instead of DDG ([why?](https://srsbsns.lol/post/a-comprehensive-evaluation-of-various-search-engines-i-ve-used)). Here's my final (for now) `static/xml/feed.xsl` file: diff --git a/content/posts/using-custom-font-hugo/index.md b/content/posts/using-custom-font-hugo/index.md index 8fd2389..db0c2ff 100644 --- a/content/posts/using-custom-font-hugo/index.md +++ b/content/posts/using-custom-font-hugo/index.md @@ -13,7 +13,7 @@ tags: - meta - tailscale --- -Last week, I came across and immediately fell in love with a delightfully-retro monospace font called [Berkeley Mono](https://berkeleygraphics.com/typefaces/berkeley-mono/). I promptly purchased a "personal developer" license and set to work [applying the font in my IDE and terminal](https://blog.jbowdre.lol/post/trying-tabby-terminal). I didn't want to stop there, though; the license also permits me to use the font on my personal site, and Berkeley Mono will fit in beautifully with the whole runtimeterror aesthetic. +Last week, I came across and immediately fell in love with a delightfully-retro monospace font called [Berkeley Mono](https://berkeleygraphics.com/typefaces/berkeley-mono/). I promptly purchased a "personal developer" license and set to work [applying the font in my IDE and terminal](https://srsbsns.lol/post/trying-tabby-terminal). I didn't want to stop there, though; the license also permits me to use the font on my personal site, and Berkeley Mono will fit in beautifully with the whole runtimeterror aesthetic. Well, you're looking at the slick new font here, and I'm about to tell you how I added the font both to the site itself and to the [dynamically-generated OpenGraph share images](/dynamic-opengraph-images-with-hugo/) setup. It wasn't terribly hard to implement, but the Hugo documentation is a bit light on how to do it (and I'm kind of inept at this whole web development thing). @@ -81,7 +81,7 @@ And that would work just fine... but it *would* require storing those web font f So instead, I opted to try using a [Content Delivery Network (CDN)](https://en.wikipedia.org/wiki/Content_delivery_network) to host the font files. This would allow for some degree of access control, help me learn more about a web technology I hadn't played with much, and make use of a cool `cdn.*` subdomain in the process. {{% notice note "Double the CDN, double the fun" %}} -Of course, while writing this post I gave in to my impulsive nature and [migrated the site from Cloudflare to Bunny.net](https://blog.jbowdre.lol/post/i-just-hopped-to-bunny-net). Rather than scrap the content I'd already written, I'll go ahead and describe how I set this up first on [Cloudflare R2](https://www.cloudflare.com/developer-platform/r2/) and later on [Bunny Storage](https://bunny.net/storage/). +Of course, while writing this post I gave in to my impulsive nature and [migrated the site from Cloudflare to Bunny.net](https://srsbsns.lol/post/i-just-hopped-to-bunny-net). Rather than scrap the content I'd already written, I'll go ahead and describe how I set this up first on [Cloudflare R2](https://www.cloudflare.com/developer-platform/r2/) and later on [Bunny Storage](https://bunny.net/storage/). {{% /notice %}} #### Cloudflare R2 diff --git a/content/save.md b/content/save.md index 4377699..e81583d 100644 --- a/content/save.md +++ b/content/save.md @@ -1,4 +1,4 @@ --- type: redirect -target: https://blog.jbowdre.lol/save +target: https://srsbsns.lol/save --- \ No newline at end of file diff --git a/content/uses.md b/content/uses.md index e2bde9a..39b33e2 100644 --- a/content/uses.md +++ b/content/uses.md @@ -1,4 +1,4 @@ --- type: redirect -target: https://blog.jbowdre.lol/uses +target: https://srsbsns.lol/uses --- From d27e2846f9d335f0fc0f860ea70f9dc7469d9ebd Mon Sep 17 00:00:00 2001 From: John Bowdre Date: Sun, 4 Aug 2024 13:18:03 -0500 Subject: [PATCH 10/15] adjust kudos-button:disabled styling (disable transparency) --- static/css/custom.css | 1 + 1 file changed, 1 insertion(+) diff --git a/static/css/custom.css b/static/css/custom.css index 95717b2..c7c6ddf 100644 --- a/static/css/custom.css +++ b/static/css/custom.css @@ -444,6 +444,7 @@ p:has(+ ul) { .kudos-button:disabled { cursor: default; + color: var(--fg); } .kudos-button .emoji { From a2c7211b6764d7df59b4f2f8079946a8b3ccbcdb Mon Sep 17 00:00:00 2001 From: John Bowdre Date: Sun, 4 Aug 2024 13:19:40 -0500 Subject: [PATCH 11/15] move shared js resources to cdn --- assets/js/kudos.js | 25 ------ assets/js/theme-song.js | 20 ----- assets/js/typo.js | 167 ----------------------------------- layouts/_default/single.html | 3 +- layouts/partials/aside.html | 3 +- layouts/partials/head.html | 3 +- 6 files changed, 3 insertions(+), 218 deletions(-) delete mode 100644 assets/js/kudos.js delete mode 100644 assets/js/theme-song.js delete mode 100644 assets/js/typo.js diff --git a/assets/js/kudos.js b/assets/js/kudos.js deleted file mode 100644 index 95ce547..0000000 --- a/assets/js/kudos.js +++ /dev/null @@ -1,25 +0,0 @@ -// manipulates the post upvote "kudos" button behavior - -window.onload = function() { - // get the button and text elements - const kudosButton = document.querySelector('.kudos-button'); - const kudosText = document.querySelector('.kudos-text'); - const emojiSpan = kudosButton.querySelector('.emoji'); - - kudosButton.addEventListener('click', function(event) { - // send the event to Cabin - cabin.event('kudos') - // disable the button - kudosButton.disabled = true; - kudosButton.classList.add('clicked'); - // change the displayed text - kudosText.textContent = 'Thanks!'; - kudosText.classList.add('thanks'); - // spin the emoji - emojiSpan.style.transform = 'rotate(360deg)'; - // change the emoji to celebrate - setTimeout(function() { - emojiSpan.textContent = 'πŸŽ‰'; - }, 150); // half of the css transition time for a smooth mid-rotation change - }); -} diff --git a/assets/js/theme-song.js b/assets/js/theme-song.js deleted file mode 100644 index ae1c2a4..0000000 --- a/assets/js/theme-song.js +++ /dev/null @@ -1,20 +0,0 @@ -// retreives the latest link from a musicthread thread and displays it on the page -const themeSongScript = document.currentScript -const urlParams = new URLSearchParams(themeSongScript.src.split('.js')[1]) -const params = Object.fromEntries(urlParams.entries()) - -if (params.id) -{ - const musicthread = `https://musicthread.app/api/v0/thread/${params.id}` - fetch(musicthread) - .then((response) => response.json()) - .then((thread) => { - let themeSong = thread.links[0] - console.log(themeSong) - themeSongContainer = document.createElement('div') - themeSongContainer.className = 'theme-song' - themeSongContainer.style - themeSongContainer.innerHTML = `
${themeSong.title}
${themeSong.artist}` - themeSongScript.parentNode.insertBefore(themeSongContainer, themeSongScript) - }) -} \ No newline at end of file diff --git a/assets/js/typo.js b/assets/js/typo.js deleted file mode 100644 index 7fc1ccf..0000000 --- a/assets/js/typo.js +++ /dev/null @@ -1,167 +0,0 @@ -/* - -Typo, a more natural web typing thing - -https://neatnik.net/typo -https://github.com/neatnik/typo - -Copyright (c) 2021 Neatnik LLC - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. - -*/ - -function num_between(min, max) { - return Math.floor(Math.random() * (max- min + 1) + min); -} - -function chance(val) { - if(num_between(0, 100) < val) return true; - else return false; -} - -function sleep(ms) { - return new Promise(resolve => setTimeout(resolve, ms)); -} - -var typos = { - q:['w','a'], - w:['q','r','s'], - e:['w','d','r'], - r:['e','f','t'], - t:['r','g','y'], - y:['t','h','u'], - u:['y','j','i'], - i:['u','k','o'], - o:['i','l','p'], - p:['o',';','['], - a:['q','s','z'], - s:['w','a','x','d'], - d:['e','s','c','f'], - f:['r','d','v','g'], - g:['t','f','b','h'], - h:['y','g','n','j'], - j:['u','h','m','k'], - k:['i','j',',','l'], - l:['o','k','.',';'], - z:['a','x'], - x:['z','s','c'], - c:['x','d','v'], - v:['c','f','b'], - b:['v','g','n'], - n:['b','h','m'], - m:['n','j',','], -} - -async function typo(element, text) { - var buffer = ''; - var typo_active = false; - var typing_typos = (element.dataset.typoChance) ? element.dataset.typoChance : 10; - var typing_speed = (element.dataset.typingDelay) ? element.dataset.typingDelay : 50; - var typing_jitter = (element.dataset.typingJitter) ? element.dataset.typingJitter : 15; - - for (var i = 0; i < text.length; i++) { - // Get the letter that we're supposed to type - letter = text.charAt(i); - - // Trigger a typo - if(chance(typing_typos) && typo_active === false && i > 1 && i < text.length - 3) { - if(typeof typos[letter] !== 'undefined') { - // Swap the letter with a random typo - typo = typos[letter][Math.floor(Math.random() * typos[letter].length)]; - - // Append the letter to the buffer - buffer = buffer + typo; - - // Write the buffer - element.innerHTML = buffer; - - typo_active = true; - var seed = num_between(2,5); // Reduced max seed to ensure correction - realization_delay = seed; - realization_delay_counter = seed; - } - } - - // Append the letter to the buffer - buffer = buffer + letter; - - // Write the buffer - element.innerHTML = buffer; - - // Typical typing speed - var speed_lower = parseFloat(typing_speed) - parseInt(typing_jitter); - var speed_upper = parseFloat(typing_speed) + parseInt(typing_jitter); - - delay = num_between(speed_lower,speed_upper); - - // Chance of longer delay though - if(chance(5)) delay = num_between(100, 200); - await sleep(delay); - - if(typo_active) { - realization_delay_counter--; - - if(realization_delay_counter == 0) { - for (var k = 0; k < seed+1; k++) { - // Pause at realization of typo - await sleep(typing_jitter); - - // Rewind the buffer! - buffer = buffer.substring(0, buffer.length - 1); - - // Write rewound buffer - element.innerHTML = buffer; - - // Brief pause before continuing - await sleep(30); - } - - typo_active = false; - - // Add the letters back - i = i - seed; - await sleep(100); - } - } - } - - // Ensure any remaining typo is corrected - if(typo_active) { - await sleep(typing_jitter * 2); - for (var k = 0; k < seed+1; k++) { - buffer = buffer.substring(0, buffer.length - 1); - element.innerHTML = buffer; - await sleep(30); - } - for (var k = 0; k < seed; k++) { - buffer += text.charAt(text.length - seed + k); - element.innerHTML = buffer; - await sleep(typing_speed); - } - } - - return new Promise(resolve => setTimeout(resolve, 1)); -} - -document.addEventListener('DOMContentLoaded', function() { - var element = document.getElementById('tagline'); - var text = element.innerHTML; - typo(element, text); -}); \ No newline at end of file diff --git a/layouts/_default/single.html b/layouts/_default/single.html index 1d7b9fb..62d73c2 100644 --- a/layouts/_default/single.html +++ b/layouts/_default/single.html @@ -47,8 +47,7 @@ Enjoyed this? - {{ $kudos := resources.Get "js/kudos.js" | minify }} - + πŸ“§ Reply by email {{- end }}
diff --git a/layouts/partials/aside.html b/layouts/partials/aside.html index 334cd32..a3273f1 100644 --- a/layouts/partials/aside.html +++ b/layouts/partials/aside.html @@ -59,7 +59,6 @@ {{ with .Site.Params.musicThreadId }}

current theme song

-{{ $jsThemeSong := resources.Get "js/theme-song.js" | minify }} - + {{ end }} diff --git a/layouts/partials/head.html b/layouts/partials/head.html index d6ed8bb..f8977c1 100644 --- a/layouts/partials/head.html +++ b/layouts/partials/head.html @@ -49,5 +49,4 @@ {{ end }} -{{ $jsTypo := resources.Get "js/typo.js" | minify }} - \ No newline at end of file + \ No newline at end of file From d595e67de78154b4087722f3e40ea3fa0e18e407 Mon Sep 17 00:00:00 2001 From: John Bowdre Date: Sun, 4 Aug 2024 13:20:08 -0500 Subject: [PATCH 12/15] don't block on js resources --- layouts/partials/aside.html | 2 +- layouts/partials/footer.html | 2 +- layouts/partials/head.html | 2 +- layouts/partials/search-index.html | 4 ++-- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/layouts/partials/aside.html b/layouts/partials/aside.html index a3273f1..326392e 100644 --- a/layouts/partials/aside.html +++ b/layouts/partials/aside.html @@ -54,7 +54,7 @@ {{ with .Site.Params.omgUser }}

status.lol

- + {{ end }} {{ with .Site.Params.musicThreadId }}
diff --git a/layouts/partials/footer.html b/layouts/partials/footer.html index e82425f..9f713ba 100644 --- a/layouts/partials/footer.html +++ b/layouts/partials/footer.html @@ -13,5 +13,5 @@ {{ if (findRE " + {{ end }} diff --git a/layouts/partials/head.html b/layouts/partials/head.html index f8977c1..113b5ee 100644 --- a/layouts/partials/head.html +++ b/layouts/partials/head.html @@ -37,7 +37,7 @@ {{ if eq .Site.Params.analytics true }} - + {{ end }} diff --git a/layouts/partials/search-index.html b/layouts/partials/search-index.html index 4276532..f2ebf86 100644 --- a/layouts/partials/search-index.html +++ b/layouts/partials/search-index.html @@ -12,6 +12,6 @@ } {{ $jsLunr := resources.Get "js/lunr.js" | minify }} - + {{ $jsSearch := resources.Get "js/search.js" | minify }} - \ No newline at end of file + \ No newline at end of file From ce1213cd14395a1ed3512143211a6076d58f1a89 Mon Sep 17 00:00:00 2001 From: John Bowdre Date: Sun, 4 Aug 2024 17:33:37 -0500 Subject: [PATCH 13/15] build robots.txt from ai.robots.txt on github --- content/changelog.md | 4 ++-- content/colophon.md | 2 +- layouts/partials/bad-robots.html | 15 +++++++++++++++ layouts/partials/dark-visitors.html | 27 --------------------------- layouts/robots.txt | 2 +- 5 files changed, 19 insertions(+), 31 deletions(-) create mode 100644 layouts/partials/bad-robots.html delete mode 100644 layouts/partials/dark-visitors.html diff --git a/content/changelog.md b/content/changelog.md index 28539f9..0e48232 100644 --- a/content/changelog.md +++ b/content/changelog.md @@ -1,14 +1,14 @@ --- title: "/changelog" date: "2024-05-26T21:19:08Z" -lastmod: "2024-08-02T21:16:14Z" +lastmod: "2024-08-04T22:30:43Z" description: "Maybe I should keep a log of all my site-related tinkering?" featured: false toc: false timeless: true categories: slashes --- -*High-level list of config/layout changes to the site. The full changelog is of course [on GitHub](https://github.com/jbowdre/runtimeterror/commits/main/).* +*Running list of config/layout changes to the site. The full changelog is of course [on GitHub](https://github.com/jbowdre/runtimeterror/commits/main/).* **2024-08-02:** - Display "pinned" recent track in sidebar using [MusicThread](https://musicthread.app) instead of latest scrobble diff --git a/content/colophon.md b/content/colophon.md index d7c8c6b..4e531a9 100644 --- a/content/colophon.md +++ b/content/colophon.md @@ -15,7 +15,7 @@ categories: slashes - uses the font face [Berkeley Mono](https://berkeleygraphics.com/typefaces/berkeley-mono/) ([details](/using-custom-font-hugo/)), and icons from [Font Awesome](https://fontawesome.com/) and [Fork Awesome](https://forkaweso.me/). - performs syntax highlighting with [Torchlight](https://torchlight.dev) ([details](/spotlight-on-torchlight/)). - provides site search with [lunr](https://lunrjs.com/) based on an implementation detailed by [Victoria Drake](https://victoria.dev/blog/add-search-to-hugo-static-sites-with-lunr/). -- uses [Dark Visitors](https://darkvisitors.com/docs/robots-txt)'s API to dynamically generate a [robots.txt](/robots.txt) discouraging AI scrapers with some Hugo code from [Luke Harris](https://github.com/lkhrs/hugo-dark-visitors). +- fetches [ai.robots.txt](https://github.com/ai-robots-txt/ai.robots.txt) to dynamically generate a [robots.txt](/robots.txt) discouraging AI scrapers with Hugo's [`resources.GetRemote` capability](https://gohugo.io/functions/resources/getremote/). - leverages [Cabin](https://withcabin.com) for [privacy-friendly](https://withcabin.com/privacy/runtimeterror.dev) analytics. - fetches recently-played music from [MusicThread](https://musicthread.app/). - displays my latest status from [omg.lol](https://home.omg.lol/referred-by/jbowdre). diff --git a/layouts/partials/bad-robots.html b/layouts/partials/bad-robots.html new file mode 100644 index 0000000..2dd28e3 --- /dev/null +++ b/layouts/partials/bad-robots.html @@ -0,0 +1,15 @@ +{{- $url := "https://raw.githubusercontent.com/ai-robots-txt/ai.robots.txt/main/robots.json" -}} +{{- with resources.GetRemote $url -}} + {{- with .Err -}} + {{- errorf "%s" . -}} + {{- else -}} + {{- $robots := unmarshal .Content -}} + {{- range $botname, $props := $robots }} + {{- printf "User-agent: %s\n" $botname }} + {{- end }} + {{- printf "Disallow: /\n" }} + {{- printf "\n# (bad bots bundled by https://github.com/ai-robots-txt/ai.robots.txt)" }} + {{- end -}} +{{- else -}} + {{- errorf "Unable to get remote resource %q" $url -}} +{{- end -}} \ No newline at end of file diff --git a/layouts/partials/dark-visitors.html b/layouts/partials/dark-visitors.html deleted file mode 100644 index e7aec71..0000000 --- a/layouts/partials/dark-visitors.html +++ /dev/null @@ -1,27 +0,0 @@ -{{/* borrowed from Luke Harris @ https://github.com/lkhrs/hugo-dark-visitors */}} -{{- $url := "https://api.darkvisitors.com/robots-txts" -}} -{{- $api_key := getenv "HUGO_DARKVISITORS" -}} -{{- $bearer := printf "Bearer %v" $api_key -}} -{{- $agent_types := slice -}} -{{- if .Site.Params.darkVisitors -}} - {{- range .Site.Params.darkVisitors -}} - {{- $agent_types = $agent_types | append . -}} - {{- end -}} -{{- else -}} - {{- $agent_types = slice "AI Data Scraper" -}} -{{- end -}} -{{- $agent_types := $agent_types | jsonify -}} -{{- $opts := dict - "method" "post" - "headers" (dict "Authorization" (slice $bearer) "Content-Type" "application/json") - "body" (printf `{"agent_types": %s,"disallow": "/"}` $agent_types) --}} -{{- with resources.GetRemote $url $opts -}} - {{- with .Err -}} - {{- errorf "%s" . -}} - {{- else -}} - {{- .Content -}} - {{- end -}} -{{- else -}} - {{- errorf "Unable to get remote resource %q" $url -}} -{{- end -}} \ No newline at end of file diff --git a/layouts/robots.txt b/layouts/robots.txt index 2a7e039..b5d0b09 100644 --- a/layouts/robots.txt +++ b/layouts/robots.txt @@ -8,4 +8,4 @@ Disallow: # except for these bots which are not friends: -{{ partial "dark-visitors.html" . }} +{{ partial "bad-robots.html" . }} From 6a3cb9888b2ebd3506ab1b0ec5fcd191475940fb Mon Sep 17 00:00:00 2001 From: John Bowdre Date: Sun, 4 Aug 2024 17:36:57 -0500 Subject: [PATCH 14/15] remove darkvisitors params --- .github/workflows/deploy-prod.yml | 1 - config/_default/params.toml | 6 ------ 2 files changed, 7 deletions(-) diff --git a/.github/workflows/deploy-prod.yml b/.github/workflows/deploy-prod.yml index 487ed45..acb4f5b 100644 --- a/.github/workflows/deploy-prod.yml +++ b/.github/workflows/deploy-prod.yml @@ -47,7 +47,6 @@ jobs: - name: Build with Hugo run: | HUGO_REMOTE_FONT_PATH=${{ secrets.REMOTE_FONT_PATH }} \ - HUGO_DARKVISITORS=${{ secrets.DARKVISITORS_TOKEN }} \ hugo --minify - name: Insert 404 page run: | diff --git a/config/_default/params.toml b/config/_default/params.toml index eb7775c..d990007 100644 --- a/config/_default/params.toml +++ b/config/_default/params.toml @@ -8,12 +8,6 @@ numberOfRelatedPosts = 5 indexTitle = ".-. ..- -. - .. -- . - . .-. .-. --- .-." -darkVisitors = [ - "AI Assistant", - "AI Data Scraper", - "AI Search Crawler" -] - omgUser = "jbowdre" musicThreadId = "2aVjZUocjk96LELFbV5JvJjm14v" From 7b096314bfd73880646d90dc51ef3e930dbb8bfe Mon Sep 17 00:00:00 2001 From: John Bowdre Date: Sun, 4 Aug 2024 17:39:12 -0500 Subject: [PATCH 15/15] update changelog --- content/changelog.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/content/changelog.md b/content/changelog.md index 0e48232..af5241a 100644 --- a/content/changelog.md +++ b/content/changelog.md @@ -10,6 +10,9 @@ categories: slashes --- *Running list of config/layout changes to the site. The full changelog is of course [on GitHub](https://github.com/jbowdre/runtimeterror/commits/main/).* +**2024-08-04:** +- Dynamically build `robots.txt` based on [ai.robots.txt](https://github.com/ai-robots-txt/ai.robots.txt) + **2024-08-02:** - Display "pinned" recent track in sidebar using [MusicThread](https://musicthread.app) instead of latest scrobble - Tweak Typo behavior to avoid uncorrected mistakes near the end of the string