diff options
author | Brian Picciano <mediocregopher@gmail.com> | 2021-08-03 15:20:32 -0600 |
---|---|---|
committer | Brian Picciano <mediocregopher@gmail.com> | 2021-08-03 15:20:32 -0600 |
commit | ec4aac24abc35fcf192c13a3fc9b2b65875c3444 (patch) | |
tree | 47fc25a28925459c2f4df9affea24559ca9b7a91 /static/src | |
parent | 20b92130106007585cbdde73f6622428d9cf68c8 (diff) |
got pow working on the subscribe endpoint
Diffstat (limited to 'static/src')
-rw-r--r-- | static/src/assets/solvePow.js | 28 | ||||
-rw-r--r-- | static/src/follow.md | 123 |
2 files changed, 144 insertions, 7 deletions
diff --git a/static/src/assets/solvePow.js b/static/src/assets/solvePow.js new file mode 100644 index 0000000..900400c --- /dev/null +++ b/static/src/assets/solvePow.js @@ -0,0 +1,28 @@ +const fromHexString = hexString => + new Uint8Array(hexString.match(/.{1,2}/g).map(byte => parseInt(byte, 16))); + +const toHexString = bytes => + bytes.reduce((str, byte) => str + byte.toString(16).padStart(2, '0'), ''); + +onmessage = async (e) => { + const seed = fromHexString(e.data.seedHex); + const target = e.data.target; + + const fullBuf = new ArrayBuffer(seed.byteLength*2); + + const fullBufSeed = new Uint8Array(fullBuf, 0, seed.byteLength); + seed.forEach((v, i) => fullBufSeed[i] = v); + + const randBuf = new Uint8Array(fullBuf, seed.byteLength); + + while (true) { + crypto.getRandomValues(randBuf); + const digest = await crypto.subtle.digest('SHA-512', fullBuf); + const digestView = new DataView(digest); + if (digestView.getUint32(0) < target) { + postMessage(toHexString(randBuf)); + return; + } + } + +}; diff --git a/static/src/follow.md b/static/src/follow.md index 8093267..4e949dd 100644 --- a/static/src/follow.md +++ b/static/src/follow.md @@ -6,7 +6,121 @@ nofollow: true Here's your options for receiving updates about new blog posts: -## Option 1: RSS +## Option 1: Email + +Email is by far my preferred option for notifying followers of new posts. + +The entire email list system for this blog, from storing subscriber email +addresses to the email server which sends the notifications out, has been +designed from scratch and is completely self-hosted in my living room. + +I solemnly swear that: + +* You will never receive an email from this blog except to notify of a new post. + +* Your email will never be provided or sold to anyone else for any reason. + +With all that said, if you'd like to receive an email everytime a new blog post +is published then input your email below and smash that subscribe button! + +<style> + +#emailStatus.success { + color: green; +} + +#emailStatus.fail { + color: red; +} + +</style> + +<input type="email" placeholder="name@host.com" id="emailAddress" /> +<input class="button-primary" type="submit" value="Subscribe" id="emailSubscribe" /> +<span id="emailStatus"></span> + +<script> +const emailAddress = document.getElementById("emailAddress"); +const emailSubscribe = document.getElementById("emailSubscribe"); +const emailSubscribeOrigValue = emailSubscribe.value; +const emailStatus = document.getElementById("emailStatus"); + +const solvePow = async (seedHex, target) => { + + const worker = new Worker('/assets/solvePow.js'); + + const p = new Promise((resolve, reject) => { + worker.postMessage({seedHex, target}); + worker.onmessage = resolve; + }); + + const solutionHex = (await p).data; + worker.terminate(); + + return solutionHex; +} + +emailSubscribe.onclick = async () => { + + emailSubscribe.disabled = true; + emailSubscribe.className = ""; + emailSubscribe.value = "Please hold..."; + + await (async () => { + + setErr = (errStr, retry) => { + emailStatus.className = "fail"; + emailStatus.innerHTML = errStr + if (retry) emailStatus.innerHTML += " (please try again)"; + }; + + if (!window.isSecureContext) { + setErr("The browser environment is not secure.", false); + return; + } + + const getPowReq = new Request('/api/pow/challenge'); + const res = await fetch(getPowReq) + .then(response => response.json()) + + if (res.error) { + setErr(res.error, true); + return; + } + + const powSol = await solvePow(res.seed, res.target); + + const subscribeForm = new FormData(); + subscribeForm.append('powSeed', res.seed); + subscribeForm.append('powSolution', powSol); + subscribeForm.append('email', emailAddress.value); + + const subscribeReq = new Request('/api/mailinglist/subscribe', { + method: 'POST', + body: subscribeForm, + }); + + const subRes = await fetch(subscribeReq) + .then(response => response.json()); + + if (subRes.error) { + setErr(subRes.error, true); + return; + } + + emailStatus.className = "success"; + emailStatus.innerHTML = "Verification email sent (check your spam folder)"; + + })(); + + emailSubscribe.disabled = false; + emailSubscribe.className = "button-primary"; + emailSubscribe.value = emailSubscribeOrigValue; +}; + +</script> + +## Option 2: RSS RSS is the classic way to follow any blog. It comes from a time before aggregators like reddit and twitter stole the show, when people felt capable to @@ -31,14 +145,9 @@ recommendations: iPhone/iPad/Mac devices, so I'm told. Their homepage description makes a much better sales pitch for RSS than I ever could. -## Option 2: Twitter +## Option 3: Twitter New posts are automatically published to [my Twitter](https://twitter.com/{{ site.twitter_username }}). Simply follow me there and pray the algorithm smiles upon my tweets enough to show them to you! :pray: :pray: :pray: -## Option 3: Email? - -I tried setting up an RSS-to-Email list thing on Mailchimp but it doesn't seem -to like my RSS feed. If anyone knows a better alternative please [email -me.](mailto:mediocregopher@gmail.com) |