Compare commits
3 Commits
d2621bbb3a
...
e3e020a0d0
Author | SHA1 | Date |
---|---|---|
Rin | e3e020a0d0 | |
Rin | fe6e122b1b | |
Rin | 4dad03e3c9 |
|
@ -2,6 +2,7 @@
|
|||
/public/
|
||||
/resources/_gen/
|
||||
/assets/jsconfig.json
|
||||
/static/fonts
|
||||
hugo_stats.json
|
||||
|
||||
# Executable may be added to repository
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,74 @@
|
|||
---
|
||||
title: "Cleaning up fortune and friends"
|
||||
date: 2022-11-20T22:22:22+11:00
|
||||
draft: true
|
||||
showSummary: true
|
||||
summary: "As it turns out, fortune-mod has an -o option for \"offensive\" fortunes, which range from vaguely off-colour
|
||||
to wildly homophobic and outright racist. We figured someone should clean up and reorganise the program to get rid
|
||||
of anything vile, and replace the offensive category with an NSFW category."
|
||||
---
|
||||
|
||||
# Background
|
||||
|
||||
> **(Selene)** Hi there. Unlike most of the blogs on here, I'll be narrating this one. This topic is closer to my heart,
|
||||
> and requires less technical expertise than most of the others. I'll still defer to Ashe for any code changes, though.
|
||||
> The gods know I can't grok C to save my life.
|
||||
|
||||
The [original fortune package](https://en.wikipedia.org/wiki/Fortune_(Unix)) was written in 1979, a good 43 years ago.
|
||||
Obviously, times have changed since than, and the package itself has gone through several revisions and re-writes.
|
||||
Fortunes have also been added, removed, and moved around.
|
||||
|
||||
There currently exist two maintained distributions. The [original BSD version](https://github.com/ahills/fortune),
|
||||
repackaged to run on Alpine Linux, and [fortune-mod](https://github.com/shlomif/fortune-mod), which is a re-write in C.
|
||||
|
||||
## Why is this a problem?
|
||||
|
||||
Three Reasons:
|
||||
|
||||
1. A lot of the "offensive" fortunes are simply insensitive, mocking, or degrading by today's standards.
|
||||
Even were they not, it sets a bad example to have a fortunes package that spits out slurs or homophobia[^1]
|
||||
at people by default, even if it *is* gated behind a flag. If people truly want these fortunes, they should
|
||||
be contained in their own package that distros can opt and out of as they please,
|
||||
instead of everything being clubbed together.
|
||||
2. Sensibilities have changed since the 1970s, and while some fortunes have been removed, a lot of the fortunes in these
|
||||
packages would get you a stern talking-to if your manager saw it. These should live in an NSFW category.
|
||||
While this overlaps with an "offensive" category, it is not the same thing.
|
||||
3. As fortunes have been written, added, modified, and removed, the categories have gotten blurry and indistinct. The
|
||||
fortunes themselves need a re-organisation and trim.
|
||||
|
||||
[^1]: Or Hitler quotes, for that matter.
|
||||
|
||||
## How do we fix this?
|
||||
|
||||
There's a number of problems here, but fundamentally, they are all organisational problems. As such, our first task is to tag each fortune as NSFW, a candidate for removal, or inaccurate in its category.
|
||||
|
||||
From there we can restructure the packages and propose these changes upstream.
|
||||
|
||||
## Where do we start?
|
||||
|
||||
We'll start with BSD's `fortune` package, as used in Alpine, for two reasons. For one, it is smaller than `fortunes-mod`. For two, the Alpine Linux maintainers tend to be relatively sensible, so this will be a good proving ground.
|
||||
|
||||
## Let's get to it
|
||||
|
||||
We started by mirroring the [fortune](https://github.com/ahills/fortune) package used on Alpine.
|
||||
|
||||
### First steps
|
||||
|
||||
The very first thing we'll do is move the default branch from `master` to `main`. This is a very small thing, but if we should be thorough if we're going to do this.
|
||||
|
||||
### Scanning through the fortunes
|
||||
In the BSD/Alpine version, the fortunes are located in the `datfiles` directory, and the files we care about are:
|
||||
- fortunes-o
|
||||
- fortunes2-o
|
||||
- limerick
|
||||
|
||||
These are noted as having the "offensive" fortunes, however we'll also give the non-offensive fortunes a scan. Since the fortunes in this version aren't categorised, we'll leave them uncategorised for now. Maybe a project for later.
|
||||
|
||||
> **(Doll)** Doll will remind Miss Selene about this another time!
|
||||
>
|
||||
> **(Selene)** Thanks Doll.
|
||||
|
||||
We've created a [full breakdown]({{< ref "lists/fortunes-cleanup" >}}) of each fortune that was removed, moved, or altered, and *why*, if you're interested. Content Notices for that page are **everything**. This is not a joke. I try to provide a summary near the top of the kinds
|
||||
of content present, but it is not exhaustive, and fortunes are not individually marked and spoilered.
|
||||
|
||||
By the by, huge thanks to the Treehouse Systems community for helping us out with screening these.
|
|
@ -0,0 +1,157 @@
|
|||
<head>
|
||||
{{/* Instant Page Script */}}
|
||||
{{/* Optimised by A Friend */}}
|
||||
<link rel="preload" href="{{ .Site.BaseURL }}instant.page.v5.1.1.js" as="script" />
|
||||
<script defer>
|
||||
window.addEventListener('load', () => {
|
||||
const el = document.createElement('script')
|
||||
el.src = '{{ .Site.BaseURL }}instant.page.v5.1.1.js'
|
||||
document.body.append(el)
|
||||
})
|
||||
</script>
|
||||
<meta charset="utf-8" />
|
||||
{{ with .Site.Language.Params.htmlCode | default .Site.LanguageCode }}
|
||||
<meta http-equiv="content-language" content="{{ . }}" />
|
||||
{{ end }}
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
|
||||
{{/* Title */}}
|
||||
{{ if .IsHome -}}
|
||||
<title>{{ .Site.Title | emojify }}</title>
|
||||
<meta name="title" content="{{ .Site.Title | emojify }}" />
|
||||
{{- else -}}
|
||||
<title>{{ .Title | emojify }} · {{ .Site.Title | emojify }}</title>
|
||||
<meta name="title" content="{{ .Title | emojify }} · {{ .Site.Title | emojify }}" />
|
||||
{{- end }}
|
||||
{{/* Metadata */}}
|
||||
{{ with .Site.Params.description -}}
|
||||
<meta name="description" content="{{ . }}" />
|
||||
{{- end }}
|
||||
{{ with .Site.Params.keywords -}}
|
||||
<meta name="keywords" content="{{ . }}" />
|
||||
{{- end }}
|
||||
{{ with .Site.Params.robots }}
|
||||
<meta name="robots" content="{{ . }}" />
|
||||
{{ end }}
|
||||
{{ with .Params.robots }}
|
||||
<meta name="robots" content="{{ . }}" />
|
||||
{{ end }}
|
||||
<link rel="canonical" href="{{ .Permalink }}" />
|
||||
{{ range .AlternativeOutputFormats -}}
|
||||
{{ printf `
|
||||
<link rel="%s" type="%s" href="%s" title="%s" />` .Rel .MediaType.Type .RelPermalink ($.Site.Title | emojify) |
|
||||
safeHTML }}
|
||||
{{ end -}}
|
||||
{{/* Asset bundles */}}
|
||||
{{ $assets := newScratch }}
|
||||
{{ $cssScheme := resources.Get (printf "css/schemes/%s.css" (.Site.Params.colorScheme | default "blowfish")) }}
|
||||
{{ if not $cssScheme }}
|
||||
{{ $cssScheme = resources.Get "css/schemes/blowfish.css" }}
|
||||
{{ end }}
|
||||
{{ $assets.Add "css" (slice $cssScheme) }}
|
||||
{{ $cssMain := resources.Get "css/compiled/main.css" }}
|
||||
{{ $assets.Add "css" (slice $cssMain) }}
|
||||
{{ $cssCustom := resources.Get "css/custom.css" }}
|
||||
{{ if $cssCustom }}
|
||||
{{ $assets.Add "css" (slice $cssCustom) }}
|
||||
{{ end }}
|
||||
{{ $bundleCSS := $assets.Get "css" | resources.Concat "css/main.bundle.css" | resources.Minify | resources.Fingerprint
|
||||
"sha512" }}
|
||||
<link type="text/css" rel="stylesheet" href="{{ $bundleCSS.RelPermalink }}"
|
||||
integrity="{{ $bundleCSS.Data.Integrity }}" />
|
||||
{{ $jsAppearance := resources.Get "js/appearance.js" }}
|
||||
{{ $jsAppearance = $jsAppearance | resources.Minify | resources.Fingerprint "sha512" }}
|
||||
<script type="text/javascript" src="{{ $jsAppearance.RelPermalink }}"
|
||||
integrity="{{ $jsAppearance.Data.Integrity }}"></script>
|
||||
{{ if .Site.Params.enableSearch | default false }}
|
||||
{{ $jsFuse := resources.Get "lib/fuse/fuse.min.js" }}
|
||||
{{ $jsSearch := resources.Get "js/search.js" }}
|
||||
{{ $assets.Add "js" (slice $jsFuse $jsSearch) }}
|
||||
{{ end }}
|
||||
{{ if .Site.Params.enableCodeCopy | default false }}
|
||||
{{ $jsCode := resources.Get "js/code.js" }}
|
||||
{{ $assets.Add "js" (slice $jsCode) }}
|
||||
{{ end }}
|
||||
{{ if .Site.Params.rtl | default false }}
|
||||
{{ $jsRTL := resources.Get "js/rtl.js" }}
|
||||
{{ $assets.Add "js" (slice $jsRTL) }}
|
||||
{{ end }}
|
||||
{{ if $assets.Get "js" }}
|
||||
{{ $bundleJS := $assets.Get "js" | resources.Concat "js/main.bundle.js" | resources.Minify | resources.Fingerprint
|
||||
"sha512" }}
|
||||
<script defer type="text/javascript" id="script-bundle" src="{{ $bundleJS.RelPermalink }}"
|
||||
integrity="{{ $bundleJS.Data.Integrity }}" data-copy="{{ i18n " code.copy" }}" data-copied="{{ i18n " code.copied"
|
||||
}}"></script>
|
||||
{{ end }}
|
||||
<script src="/js/zoom.min.js"></script>
|
||||
{{/* Icons */}}
|
||||
{{ if templates.Exists "partials/favicons.html" }}
|
||||
{{ partialCached "favicons.html" .Site }}
|
||||
{{ else }}
|
||||
<link rel="apple-touch-icon" sizes="180x180" href="{{ "apple-touch-icon.png" | relURL }}" />
|
||||
<link rel="icon" type="image/png" sizes="32x32" href="{{ "favicon-32x32.png" | relURL }}" />
|
||||
<link rel="icon" type="image/png" sizes="16x16" href="{{ "favicon-16x16.png" | relURL }}" />
|
||||
<link rel="manifest" href="{{ "site.webmanifest" | relURL }}" />
|
||||
{{ end }}
|
||||
{{/* Site Verification */}}
|
||||
{{ with .Site.Params.verification.google }}
|
||||
<meta name="google-site-verification" content="{{ . }}" />
|
||||
{{ end }}
|
||||
{{ with .Site.Params.verification.bing }}
|
||||
<meta name="msvalidate.01" content="{{ . }}" />
|
||||
{{ end }}
|
||||
{{ with .Site.Params.verification.pinterest }}
|
||||
<meta name="p:domain_verify" content="{{ . }}" />
|
||||
{{ end }}
|
||||
{{ with .Site.Params.verification.yandex }}
|
||||
<meta name="yandex-verification" content="{{ . }}" />
|
||||
{{ end }}
|
||||
{{/* Social */}}
|
||||
{{ template "_internal/opengraph.html" . }}
|
||||
{{ template "_internal/twitter_cards.html" . }}
|
||||
{{/* Schema */}}
|
||||
{{ partial "schema.html" . }}
|
||||
{{/* Me */}}
|
||||
{{ with .Site.Author.name }}
|
||||
<meta name="author" content="{{ . }}" />{{ end }}
|
||||
{{ with .Site.Author.links }}
|
||||
{{ range $links := . }}
|
||||
{{ range $name, $url := $links }}
|
||||
<link href="{{ $url }}" rel="me" />{{ end }}
|
||||
{{ end }}
|
||||
{{ end }}
|
||||
{{/* Vendor */}}
|
||||
{{ partial "vendor.html" . }}
|
||||
{{/* Analytics */}}
|
||||
{{ partialCached "analytics.html" .Site }}
|
||||
{{/* Extend head - eg. for custom analytics scripts, etc. */}}
|
||||
{{ if templates.Exists "partials/extend-head.html" }}
|
||||
{{ partialCached "extend-head.html" .Site }}
|
||||
{{ end }}
|
||||
|
||||
{{/* Firebase */}}
|
||||
{{ with $.Site.Params.firebase }}
|
||||
{{ if isset $.Site.Params "firebase" }}
|
||||
<script src="https://www.gstatic.com/firebasejs/8.10.0/firebase-app.js"></script>
|
||||
<script src="https://www.gstatic.com/firebasejs/8.10.0/firebase-firestore.js"></script>
|
||||
<script src="https://www.gstatic.com/firebasejs/8.10.0/firebase-auth.js"></script>
|
||||
<script>
|
||||
|
||||
const firebaseConfig = {
|
||||
apiKey: {{ $.Site.Params.firebase.apiKey }},
|
||||
authDomain: {{ $.Site.Params.firebase.apiKey }},
|
||||
projectId: {{ $.Site.Params.firebase.projectId }},
|
||||
storageBucket: {{ $.Site.Params.firebase.storageBucket }},
|
||||
messagingSenderId: {{ $.Site.Params.firebase.messagingSenderId }},
|
||||
appId: {{ $.Site.Params.firebase.appId }},
|
||||
measurementId: {{ $.Site.Params.firebase.measurementId }}
|
||||
};
|
||||
|
||||
var app = firebase.initializeApp(firebaseConfig);
|
||||
var db = firebase.firestore();
|
||||
var auth = firebase.auth();
|
||||
|
||||
</script>
|
||||
{{ end }}
|
||||
{{ end }}
|
||||
</head>
|
|
@ -1,14 +1,4 @@
|
|||
<head>
|
||||
{{/* Instant Page Script */}}
|
||||
{{/* Optimised by A Friend */}}
|
||||
<link rel="preload" href="{{ .Site.BaseURL }}instant.page.v5.1.1.js" as="script" />
|
||||
<script defer>
|
||||
window.addEventListener('load', () => {
|
||||
const el = document.createElement('script')
|
||||
el.src = '{{ .Site.BaseURL }}instant.page.v5.1.1.js'
|
||||
document.body.append(el)
|
||||
})
|
||||
</script>
|
||||
<meta charset="utf-8" />
|
||||
{{ with .Site.Language.Params.htmlCode | default .Site.LanguageCode }}
|
||||
<meta http-equiv="content-language" content="{{ . }}" />
|
||||
|
@ -24,11 +14,11 @@
|
|||
<meta name="title" content="{{ .Title | emojify }} · {{ .Site.Title | emojify }}" />
|
||||
{{- end }}
|
||||
{{/* Metadata */}}
|
||||
{{ with .Site.Params.description -}}
|
||||
{{ with (.Params.Summary | default .Params.Description) | default .Site.Params.description -}}
|
||||
<meta name="description" content="{{ . }}" />
|
||||
{{- end }}
|
||||
{{ with .Site.Params.keywords -}}
|
||||
<meta name="keywords" content="{{ . }}" />
|
||||
{{ with .Params.Tags | default .Site.Params.keywords -}}
|
||||
<meta name="keywords" content="{{ range . }}{{ . }}, {{ end -}}" />
|
||||
{{- end }}
|
||||
{{ with .Site.Params.robots }}
|
||||
<meta name="robots" content="{{ . }}" />
|
||||
|
@ -60,7 +50,7 @@
|
|||
<link type="text/css" rel="stylesheet" href="{{ $bundleCSS.RelPermalink }}"
|
||||
integrity="{{ $bundleCSS.Data.Integrity }}" />
|
||||
{{ $jsAppearance := resources.Get "js/appearance.js" }}
|
||||
{{ $jsAppearance = $jsAppearance | resources.Minify | resources.Fingerprint "sha512" }}
|
||||
{{ $jsAppearance = $jsAppearance | resources.ExecuteAsTemplate $jsAppearance.RelPermalink . | resources.Minify | resources.Fingerprint "sha512" }}
|
||||
<script type="text/javascript" src="{{ $jsAppearance.RelPermalink }}"
|
||||
integrity="{{ $jsAppearance.Data.Integrity }}"></script>
|
||||
{{ if .Site.Params.enableSearch | default false }}
|
||||
|
@ -83,7 +73,7 @@
|
|||
integrity="{{ $bundleJS.Data.Integrity }}" data-copy="{{ i18n " code.copy" }}" data-copied="{{ i18n " code.copied"
|
||||
}}"></script>
|
||||
{{ end }}
|
||||
<script src="/js/zoom.min.js"></script>
|
||||
<script src="{{ "js/zoom.min.js" | relURL }}"></script>
|
||||
{{/* Icons */}}
|
||||
{{ if templates.Exists "partials/favicons.html" }}
|
||||
{{ partialCached "favicons.html" .Site }}
|
||||
|
@ -123,12 +113,12 @@
|
|||
{{/* Vendor */}}
|
||||
{{ partial "vendor.html" . }}
|
||||
{{/* Analytics */}}
|
||||
{{ partialCached "analytics.html" .Site }}
|
||||
{{ partial "analytics/main.html" .Site }}
|
||||
{{/* Extend head - eg. for custom analytics scripts, etc. */}}
|
||||
{{ if templates.Exists "partials/extend-head.html" }}
|
||||
{{ partialCached "extend-head.html" .Site }}
|
||||
{{ end }}
|
||||
|
||||
<meta name="theme-color"/>
|
||||
{{/* Firebase */}}
|
||||
{{ with $.Site.Params.firebase }}
|
||||
{{ if isset $.Site.Params "firebase" }}
|
||||
|
@ -152,6 +142,17 @@
|
|||
var auth = firebase.auth();
|
||||
|
||||
</script>
|
||||
{{/* Instant Page Script */}}
|
||||
{{/* Optimised by A Friend */}}
|
||||
<link rel="preload" href="/assets/instant.page.v5.1.1.js" as="script" />
|
||||
<script defer>
|
||||
window.addEventListener('load', () => {
|
||||
const el = document.createElement('script')
|
||||
el.src = '/assets/instant.page.v5.1.1.js'
|
||||
document.body.append(el)
|
||||
})
|
||||
</script>
|
||||
|
||||
{{ end }}
|
||||
{{ end }}
|
||||
</head>
|
||||
|
|
|
@ -1 +1 @@
|
|||
Subproject commit 7df01846210fb56fc8ba2bcadea53317505094bb
|
||||
Subproject commit aa03e677db8ae083906cffececb14ec1db4dc879
|
Loading…
Reference in New Issue