add code for arpa web n-gon

This commit is contained in:
2025-07-05 03:58:24 -07:00
parent 9d5ca89d10
commit 8a4759ccf4
12 changed files with 225 additions and 10 deletions

57
srv/content/arpa_n_gon.hy Normal file
View File

@ -0,0 +1,57 @@
(import yaml [safe-load])
(setv ones-names [
"hena"
"di"
"tri"
"tetra"
"penta"
"hexa"
"hepta"
"octa"
"ennea"])
(setv tens-names [
"decagon"
"icosi"
"triconta"
"tetraconta"
"pentaconta"
"hexaconta"
"heptaconta"
"octaconta"
"enneaconta"])
(defn n-gon-name [n]
(when (> 10 n)
(return (+ (get ones-names (- n 1)) "gon")))
(when (= n 11)
(return "undecagon"))
(when (= n 12)
(return "dodecagon"))
(when (> 20 n)
(return (+ (get ones-names (- n 1)) "decagon")))
(when (= 20 n)
(return "icosagon"))
(let [[modc r] (divmod n 10)]
(+ (get tens-names (- modc 1)) "kai" (get ones-names (- r 1)) "gon")))
(defn get-members []
(with [f (open "www/src/data/arpa-n-gon.yaml" "r")]
(return (get (safe-load f) "members"))))
(defn get-member-by-domain [members domain]
(for [[idx member] (enumerate members)]
(when (= (get member "arpa-domain") domain)
(return #(idx member)))))
(defn next-member [members domain]
(get members (% (+ (get (get-member-by-domain members domain) 0) 1) (len members))))
(defn prev-member [members domain]
(get members (% (- (get (get-member-by-domain members domain) 0) 1) (len members))))

View File

@ -11,13 +11,16 @@
(. (check-output (.group sequence 1) :shell True :executable "/bin/bash" :env hy-env) (decode) (strip))) (. (check-output (.group sequence 1) :shell True :executable "/bin/bash" :env hy-env) (decode) (strip)))
data)) data))
(defn parse-html-file [path #** kwargs] (defn parse-html-file [path [no-exec False] #** kwargs]
(with [f (open path "r")] (with [f (open path "r")]
(setv data (.read f))) (setv data (.read f)))
(for [[k v] (.items kwargs)] (for [[k v] (.items kwargs)]
(setv data (.replace data f"{"{"}{k}{"}"}" (str v)))) (setv data (.replace data f"{"{"}{k}{"}"}" (str v))))
(when no-exec
(return data))
(execute-bash data)) (execute-bash data))
(defn send-raw-file [path] (defn send-raw-file [path]

View File

@ -4,6 +4,7 @@
(import hyrule.collections [assoc]) (import hyrule.collections [assoc])
(import content.file-io [parse-html-file send-raw-file]) (import content.file-io [parse-html-file send-raw-file])
(import content.comments [create-comment]) (import content.comments [create-comment])
(import content.arpa-n-gon :as arpa-n-gon)
(import re) (import re)
(import functools [lru-cache]) (import functools [lru-cache])
(import os.path [isdir :as dir? isfile :as file? abspath]) (import os.path [isdir :as dir? isfile :as file? abspath])
@ -81,15 +82,36 @@
:if (setx value (. request (get "route") (get "parameters") (get param None))) :if (setx value (. request (get "route") (get "parameters") (get param None)))
#(param value))))))) #(param value)))))))
(defn shtml-file-response [file [code 200] [template-params {}]] (defn require-params [#* params [otherwise (fn [#* _] (error 409 "missing required parameters"))]]
(fn [f]
(fn [method post request #** kwargs]
(if (all (lfor param params (in param (. request (get "route") (get "parameters") (keys)))))
(f method post request #** kwargs)
(otherwise method post request #** kwargs)))))
(defn 303-if-not-arpa [f]
(fn [method path request]
(if (. request (get "headers") (get "Host") (endswith "arpa"))
(f method path request)
(dict
:code 303
:headers {"Location" f"http://natalieee.net.8.f.9.e.0.7.4.0.1.0.0.2.ip6.arpa/{(. request (get "route") (get "unparsed_route"))}"}))))
(defn shtml-file-response [file [code 200] [no-exec False] [template-params {}]]
(dict (dict
:code code :code code
:headers {"Connection" "keep-alive" "Keep-Alive" "timeout=5 max=200"} :headers {"Connection" "keep-alive" "Keep-Alive" "timeout=5 max=200"}
:body (parse-html-file f"./www/site/html/{file}" #** template-params))) :body (parse-html-file f"./www/site/html/{file}" :no-exec no-exec #** template-params)))
(defn raw-file-response [file [code 200]] (defn raw-file-response [file [code 200]]
(dict :code code #** (dict (zip ["headers" "body"] (send-raw-file f"./www/site/{file}"))))) (dict :code code #** (dict (zip ["headers" "body"] (send-raw-file f"./www/site/{file}")))))
(defn+ match-request [{method "method" {path "path"} "route" :as request}]
;; (try
((get (routes.get-route-by-path path) method) method path request))
;; (except [Exception]
;; (return (error 500 "server error")))))
(defn [(route "/" "GET")] /home #route-args (shtml-file-response "home.html")) (defn [(route "/" "GET")] /home #route-args (shtml-file-response "home.html"))
(defn [(route "/html/*" "GET") (if-file-exists :base-path "./www/site/html" :otherwise (error 404 "not found"))] /html/* #route-args (shtml-file-response path)) (defn [(route "/html/*" "GET") (if-file-exists :base-path "./www/site/html" :otherwise (error 404 "not found"))] /html/* #route-args (shtml-file-response path))
(defn [lru-cache (route "/assets/*" "GET") (if-file-exists :base-path "./www/site/" :otherwise (error 404 "not found"))] /assets/* #route-args (raw-file-response path)) (defn [lru-cache (route "/assets/*" "GET") (if-file-exists :base-path "./www/site/" :otherwise (error 404 "not found"))] /assets/* #route-args (raw-file-response path))
@ -97,6 +119,22 @@
(defn [(route "/comment" "POST")] /comments #route-args (create-comment request)) (defn [(route "/comment" "POST")] /comments #route-args (create-comment request))
(defn [lru-cache (route "/robots.txt" "GET") ] /robots #route-args (dict :code 200 :headers {"Content-Type" "text/plain"} :body "User-agent *\nDisallow: /\n")) (defn [lru-cache (route "/robots.txt" "GET") ] /robots #route-args (dict :code 200 :headers {"Content-Type" "text/plain"} :body "User-agent *\nDisallow: /\n"))
(defn+ match-request [{method "method" {path "path"} "route" :as request}] ;; *.arpa web n-gon
((get (routes.get-route-by-path path) method) method path request)) (setv members (arpa-n-gon.get-members))
(defn [(route "/arpa-n-gon" GET) 303-if-not-arpa] /arpa-n-gon #route-args (shtml-file-response "arpa-n-gon.html" :template-params (dict :n_gon (arpa-n-gon.n-gon-name (len members)) :n_gon_inc (arpa-n-gon.n-gon-name (+ (len members) 1)) :n (len members))))
(defn [(route "/arpa-n-gon/nav" GET) 303-if-not-arpa (forward-params "current" "style") (require-params "current") ] /arpa-n-gon/nav #route-args [current [style None]]
(shtml-file-response "arpa-n-gon-nav.html" :no-exec True :template-params (dict
:style style
:next (+ "http://" (get (arpa-n-gon.next-member members current) "arpa-domain"))
:prev (+ "http://" (get (arpa-n-gon.prev-member members current) "arpa-domain"))
:n_gon (arpa-n-gon.n-gon-name (len members)))))
(defn [(route "/arpa-n-gon/next" GET) 303-if-not-arpa (forward-params "current" )(require-params "current")] /arpa-n-gon/next #route-args [current] (dict
:code 303
:headers {"Location" (+ "http://" (get (arpa-n-gon.next-member members current) "arpa-domain"))}))
(defn [(route "/arpa-n-gon/prev" GET) 303-if-not-arpa (forward-params "current") (require-params "current")] /arpa-n-gon/next #route-args [current] (dict
:code 303
:headers {"Location" (+ "http://" (get (arpa-n-gon.prev-member members current) "arpa-domain"))}))

View File

@ -43,7 +43,8 @@
segments)) segments))
:parameters (parse-url-encoded query)))) :parameters (parse-url-encoded query)
:unparsed-route route)))
(assoc "version" http-version) (assoc "version" http-version)
(assoc "headers" (hashable-dict (assoc "headers" (hashable-dict

View File

@ -0,0 +1,25 @@
:root {
--link: #33b1ff;
--visited-link: #be95ff;
}
body {
margin: 0;
display: flex;
div {
display: flex;
gap: 1ch;
font-size: 13px;
font-family: 'Liberation Mono', monospace;
> a {
text-underline-offset: 2px;
color: var(--link);
&:visited {
color: var(--visited-link);
}
}
}
}

View File

@ -191,6 +191,9 @@ body {
justify-content: flex-start; justify-content: flex-start;
> footnote > * { margin-top: 2px; } > footnote > * { margin-top: 2px; }
> footnote > iframe {
border: none;
}
> a { > a {
margin: 0 !important; margin: 0 !important;
@ -415,3 +418,10 @@ div.thought-list{
} }
} }
} }
.arpa-n-gon-list {
> li {
background: var(--alt-bg);
margin: 10px;
}
}

View File

@ -0,0 +1,3 @@
<a href="http://natalieee.net.8.f.9.e.0.7.4.0.1.0.0.2.ip6.arpa/arpa-n-gon/prev?current={domain}">prev</a>
<a href="http://natalieee.net.8.f.9.e.0.7.4.0.1.0.0.2.ip6.arpa/arpa-n-gon/">*.arpa web n-gon</a>
<a href="http://natalieee.net.8.f.9.e.0.7.4.0.1.0.0.2.ip6.arpa/arpa-n-gon/next?current={domain}">next</a>

View File

@ -0,0 +1 @@
<iframe src="http://natalieee.net.8.f.9.e.0.7.4.0.1.0.0.2.ip6.arpa/arpa-n-gon/nav?current={url}&style={style-url}"></iframe>

View File

@ -0,0 +1,5 @@
members:
- name: natalie
arpa-domain: natalieee.net.8.f.9.e.0.7.4.0.1.0.0.2.ip6.arpa
description: natalieee.net arpa domain

View File

@ -0,0 +1,8 @@
'(html
(head
(link (:rel stylesheet :href "{style}" :type text/css)))
(body
(div
(a (:href "{prev}" :target _parent) <-)
(a (:href "http://natalieee.net.8.f.9.e.0.7.4.0.1.0.0.2.ip6.arpa/arpa-n-gon" :target _parent) "*.arpa web {n_gon}")
(a (:href "{next}" :target _parent) ->))))

View File

@ -0,0 +1,62 @@
(page
:title ".arpa web {n_gon}"
:description "the homepage for the .arpa web {n_gon}"
`((section
(h1 "the *.arpa web {n_gon}")
(p "a web {n_gon} (read: webring with {n} members) for anyone with a domain under the arpa tld or any subdomain thereof."))
(section
(h2 "members")
(ol (:class "arpa-n-gon-list")
~(do
(import yaml [safe-load])
(with [f (open "data/arpa-n-gon.yaml")]
(setv members (get (safe-load f) "members")))
(hy.models.Expression (lfor member members
`(li (div
(div "member: " (a (:href ~(get member "arpa-domain") :title ~(get member "arpa-domain")) ~(get member "name")))
(div "domain: " ~(get member "arpa-domain")
(div "description: " ~(get member "description"))))))))))
(section
(h2 "joining")
(p "anyone meeting all of the following criteria is permitted to join this webring:")
(ul
(li "own a domain under the arpa tld")
(li "have a site accessible under that domain")
(li "on that site, have at least one instance of page elements complying with the section on acceptable notation of membership")
(li "be deemed by natalie to be generally acceptable; this is a low bar, and functionally translates to &quot;don't be an asshole&quot;"))
(p "should $READER align with the above conditions, and is interested in joining this web {n_gon} (thus making it a web {n_gon_inc}), $READER may send an e-mail containing their website's url to "
(a (:href "mailto:{n_gon}@8.f.9.e.0.7.4.0.1.0.0.2.ip6.arpa") "{n_gon}@8.f.9.e.0.7.4.0.1.0.0.2.ip6.arpa")))
(section
(h2 "acceptable notation of membership")
(p "there are two main modes of noting one's affiliation with this web {n_gon}, what is appropriate for $READER's website will depend on their preferences regarding loading of external resources.")
(br)
(h3 "1: iframe")
(p "the first option is to include an iframe linking to the navigation for the webring. this option is funnier, because requesting that natalieee.net renders the iframe contents allows
this server to return html containing the appropriate n-gon for the current member count. in order to conform with the css of some site, a style param can be passed in the iframe's src attribute,
which will get loaded as a stylesheet.")
(figure
(figcaption "iframe web {n_gon} html")
(code ~(run #[[syntax-hl data/arpa-n-gon-linking-iframe.html]])))
(br)
(h3 "2: anchors")
(p "the second option is to include various anchor tags. this option is less funny, because instead of asking natalieee.net for the appropriate n-gon, it simply labels the web {n_gon} as a web n-gon.")
(figure
(figcaption "anchor web {n_gon} html")
(code ~(run #[[syntax-hl data/arpa-n-gon-linking-anchors.html]])))
(p "of the above methods, one must appear anywhere within a site a number of times greater than 0. a valid website can include one of these
only once (on a webring page, should the site have a page dedicated to that), or on each page as with this site's footer.")
(br)
(h3 "proper linking")
(p "the `current` parameter in any given web {n_gon} related url should be set to the domain of one's site. in this one's case, this parameter gets set to natalieee.net.8.f.9.e.0.7.4.0.1.0.0.2.ip6.arpa. this is
the mechanism that allows the server to properly link to the next or previous site in the {n_gon}."))))

View File

@ -15,8 +15,10 @@
(div (div
(footnote (:style "margin-top: 5px") "▖▖▖▖▘▖▖▖▖▘▌▖▖▖▘") (footnote (:style "margin-top: 5px") "▖▖▖▖▘▖▖▖▖▘▌▖▖▖▘")
(footnote (:style "margin-top: 5px") (footnote (:style "margin-top: 5px")
(div (:style "flex-direction: row; width: 14ch; gap: 2ch; margin-right: 5px;") (div (:style "display: flex; flex-direction: row; width: 14ch; gap: 1ch; margin-right: 5px;")
(a (:href "https://stellophiliac.github.io/roboring/0x6e6174/previous") "<-") (a (:href "https://stellophiliac.github.io/roboring/0x6e6174/previous") "<-")
(a (:href "https://stellophiliac.github.io/roboring") "roboring") (a (:href "https://stellophiliac.github.io/roboring") "roboring")
(a (:href "https://stellophiliac.github.io/roboring/0x6e6174/next") "->")))) (a (:href "https://stellophiliac.github.io/roboring/0x6e6174/next") "->"))
(iframe (:src "/arpa-n-gon/nav?current=natalieee.net.8.f.9.e.0.7.4.0.1.0.0.2.ip6.arpa&style=/assets/arpa-n-gon.css"))))
(span ~(run "git log -1 --format=%h")))) (span ~(run "git log -1 --format=%h"))))