diff --git a/.eleventy.js b/.eleventy.js
index e74cd36..0671434 100644
--- a/.eleventy.js
+++ b/.eleventy.js
@@ -1,10 +1,90 @@
+const { ACTOR_OBJ } = require("./src/env")
+
module.exports = function(eleventyConfig) {
+ // I'm .gitignoring my content for now, so 11ty should not ignore that
eleventyConfig.setUseGitIgnore(false)
+
+ // Filters are in a separate function to try and keep this config less cluttered
+ addFilters(eleventyConfig)
+ // same with shortcodes
+ addShortcodes(eleventyConfig)
+ // and collections
+ addCollections(eleventyConfig)
+
+ eleventyConfig.addGlobalData("actor_obj", () => ACTOR_OBJ);
+
+ // TODO: assets?
+ // files to passthrough copy
+ eleventyConfig.addPassthroughCopy({"img":"assets/img"})
+ eleventyConfig.addPassthroughCopy({"js":"assets/js"})
+ eleventyConfig.addPassthroughCopy("css")
+ eleventyConfig.addPassthroughCopy("CNAME")
+
+ // plugins
+ eleventyConfig.addPlugin(require("@11ty/eleventy-plugin-rss"))
+
// Return your Object options:
return {
dir: {
input: "_content",
output: "_site"
- }
+ },
+ htmlTemplateEngine: "njk",
+ templateFormats: ["md","html","njk"]
}
-};
\ No newline at end of file
+}
+
+function addCollections(eleventyConfig) {
+ eleventyConfig.addCollection("feed", function(collectionApi) {
+ return collectionApi.getAllSorted().reverse().filter(item => {
+ if(!item.data.published) return false
+ return item.filePathStem.startsWith('/posts/')
+ }).map(item => {
+ item.data.author = ACTOR_OBJ
+ return item
+ }).sort((a, b) => new Date(b.published).getTime() - new Date(a.published).getTime())
+ })
+}
+
+function addShortcodes(eleventyConfig) {
+ eleventyConfig.addNunjucksShortcode("getVar", function(varString){ return this.ctx[varString] })
+ eleventyConfig.addShortcode('renderlayoutblock', function(name){ return (this.page.layoutblock || {})[name] || '' })
+ eleventyConfig.addPairedShortcode('layoutblock', function(content, name) {
+ if (!this.page.layoutblock) this.page.layoutblock = {}
+ this.page.layoutblock[name] = content
+ return ''
+ })
+}
+
+function addFilters(eleventyConfig) {
+ eleventyConfig.addFilter("formatDate", formatDateFilter)
+ eleventyConfig.addFilter("dateISOString", dateISOStringFilter)
+ eleventyConfig.addFilter("concat", (value, other) => value + '' + other)
+ eleventyConfig.addNunjucksAsyncFilter("await", (promise) => promise.then(res => callback(null, res)).catch(err => callback(err)))
+}
+
+// default date formatting
+function formatDateFilter(value) {
+ try{
+ const date = new Date(value)
+ if(date) return date.toISOString().replace('T', ' ').slice(0, -5)
+ else throw 'Unrecognized data format'
+ }
+ catch(e) {
+ console.error(`Could not convert "${value}"`, e)
+ return value;
+ }
+}
+
+// dates as iso string
+function dateISOStringFilter(value) {
+ try{
+ const date = new Date(value)
+ if(date) return date.toISOString()
+ else throw 'Unrecognized data format'
+ }
+ catch(e) {
+ console.error(`Could not convert "${value}"`, e)
+ return value;
+ }
+}
\ No newline at end of file
diff --git a/.gitignore b/.gitignore
index 06100bd..2d8c964 100644
--- a/.gitignore
+++ b/.gitignore
@@ -169,5 +169,7 @@ dist
.pnp.\*
# My custom ignores
-_content
+_content/_data/_inbox
+_content/_data/_outbox
+_content/posts
_site
diff --git a/CNAME b/CNAME
new file mode 100644
index 0000000..c9df399
--- /dev/null
+++ b/CNAME
@@ -0,0 +1 @@
+death.id.au
\ No newline at end of file
diff --git a/README.md b/README.md
index 978e908..c50a938 100644
--- a/README.md
+++ b/README.md
@@ -14,6 +14,10 @@ I may also experiment with pushing the content to a seperate git repository so I
- Bun has it's own built-in http server, so this project uses that rather than something like Express.
- It uses [`node-forge`](https://github.com/digitalbazaar/forge) for signing and verifying signed posts, as Bun does not yet implement the required `node:crypto` methods
- It uses [`gray-matter`](https://github.com/jonschlinkert/gray-matter) for writing and parsing YAML frontmatter in Markdown files
+- It uses [11ty](https://www.11ty.dev/) to compile those Markdown files into a static website
+Note: there is an error with 11ty in Bun, tracked [here](https://github.com/oven-sh/bun/issues/5560). Until there is a fix, there is a workaround:
+`node_modules/graceful-fs/graceful-fs.js:299` — remove the `, this` from the end of the line
+ - The [RSS Plugin](https://www.11ty.dev/docs/plugins/rss/) for 11ty is also used to generate RSS feeds of the posts
## Development
diff --git a/_content/_data/layout.js b/_content/_data/layout.js
new file mode 100644
index 0000000..c98ebc5
--- /dev/null
+++ b/_content/_data/layout.js
@@ -0,0 +1 @@
+module.exports = "layout-default.njk"
\ No newline at end of file
diff --git a/_content/_includes/layout-default.njk b/_content/_includes/layout-default.njk
new file mode 100644
index 0000000..07f180f
--- /dev/null
+++ b/_content/_includes/layout-default.njk
@@ -0,0 +1,13 @@
+---js
+{
+ layout: "layout-main.njk",
+ ctx: function() { return this.ctx }
+}
+---
+{% from "macro-entry.njk" import entryMacro %}
+
+{{ entryMacro(ctx(), author, url, content) }}
+
+{% layoutblock 'foot' %}
+
+{% endlayoutblock %}
diff --git a/_content/_includes/layout-feed.njk b/_content/_includes/layout-feed.njk
new file mode 100644
index 0000000..9977d86
--- /dev/null
+++ b/_content/_includes/layout-feed.njk
@@ -0,0 +1,15 @@
+---
+title: Feed
+layout: layout-main.njk
+scripts_foot: ''
+---
+
+
{{ title }}
+ {{ content | safe }}
+
+
+{% include 'partial-pagination.njk' %}
+
+{% layoutblock 'foot' %}
+
+{% endlayoutblock %}
\ No newline at end of file
diff --git a/_content/_includes/layout-main.njk b/_content/_includes/layout-main.njk
new file mode 100644
index 0000000..658fecc
--- /dev/null
+++ b/_content/_includes/layout-main.njk
@@ -0,0 +1,38 @@
+---
+title: Mon Repos (Death's Domain)
+---
+
+
+
+
+
+
+
+
+
+
+
+ {#
+
+
+
+ #}
+
+
+
+
+
+
+ {{ title }}
+ {% renderlayoutblock 'head' %}
+
+
+
+ {% renderlayoutblock 'header' %}
+
+ {{ content | safe }}
+
+
+{% renderlayoutblock 'footer' %}
+{% renderlayoutblock 'foot' %}
+
diff --git a/_content/_includes/macro-author.njk b/_content/_includes/macro-author.njk
new file mode 100644
index 0000000..141d191
--- /dev/null
+++ b/_content/_includes/macro-author.njk
@@ -0,0 +1,10 @@
+{% macro authorMacro(author) %}
+ {# {{ author | getAuthorData | log }} #}
+
+
+
+ {{ author.name }}
+ {{ author.preferredUsername }}
+
+
+{% endmacro %}
\ No newline at end of file
diff --git a/_content/_includes/macro-card-head.njk b/_content/_includes/macro-card-head.njk
new file mode 100644
index 0000000..0260e5b
--- /dev/null
+++ b/_content/_includes/macro-card-head.njk
@@ -0,0 +1,9 @@
+{% from "macro-author.njk" import authorMacro %}
+{% macro cardHeadMacro(author, date, url) %}
+
+{% endmacro %}
\ No newline at end of file
diff --git a/_content/_includes/macro-entry.njk b/_content/_includes/macro-entry.njk
new file mode 100644
index 0000000..623a5ce
--- /dev/null
+++ b/_content/_includes/macro-entry.njk
@@ -0,0 +1,14 @@
+{% from "macro-card-head.njk" import cardHeadMacro %}
+{% from "macro-summary.njk" import summaryMacro %}
+{% macro entryMacro(item, author, url, content, summaryOnly=false) %}
+
+ {{ cardHeadMacro(author, item.published, url) }}
+
+ {{ summaryMacro(item, url) }}
+ {% if item.type == 'article' and summaryOnly %}
+ {% elseif content %}
+
{{ content | safe }}
+ {% endif %}
+
+
+{% endmacro %}
\ No newline at end of file
diff --git a/_content/_includes/macro-summary.njk b/_content/_includes/macro-summary.njk
new file mode 100644
index 0000000..6ad8083
--- /dev/null
+++ b/_content/_includes/macro-summary.njk
@@ -0,0 +1,83 @@
+{% macro summaryMacro(item, url) %}
+{% switch item.type %}
+ {% case "article" %} {# article summary: #}
+
+ {% if item.summary %}
+ {{ item.summary | safe }}
+ {% endif %}
+
+ {% case "reply" %} {# reply summary: #}
+ Reply to {{ item["in-reply-to"] }}
+
+ {% case "like" %} {# like summary: #}
+ Favourited {{ item['like-of'] }}
+
+ {% case "boost" %} {# boost summary: #}
+ Boosted {{ item["repost-of"] }}
+
+ {% case "bookmark" %} {# bookmark summary: #}
+ Bookmarked {{ item["bookmark-of"] }}
+
+ {% case "read" %} {# read summary: #}
+
+ {% if item["read-status"].toLowerCase() == "to-read" %}
+ To Read:
+
+ {% elseif item["read-status"].toLowerCase() == "reading" %}
+ Currently Reading:
+
+ {% elseif item["read-status"].toLowerCase() == "finished" %}
+ Finished Reading:
+
+ {% endif %}
+
+ {% if item["read-of"].startsWith("http") %}
+ {{ item["read-of"] }}
+ {% else %}
+ {{ item["read-of"] }}
+ {% endif %}
+
+
+ {% case "watch" %} {# watch summary: #}
+
+ {% if item["watch-status"].toLowerCase() == "to-watch" %}
+ To Watch:
+ {% elseif item["watch-status"].toLowerCase() == "watching" %}
+ Currently Watching:
+ {% elseif item["watch-status"].toLowerCase() == "watched" or item["watch-status"].toLowerCase() == "finished" %}
+ Finished watching:
+ {% else %}
+ Watched:
+ {% endif %}
+
+
+ {% if item["watch-of"].startsWith("http") %}
+ {{ item["watch-of"] }}
+ {% else %}
+ {{ item["watch-of"] }}
+ {% endif %}
+
+
+ {% case "rsvp" %} {# rsvp summary: #}
+
+
+ {% if item.rsvp.toLowerCase() == "yes" %}
+
+ Will attend
+ {% elseif item.rsvp.toLowerCase() == "maybe" %}
+
+ Might attend
+ {% elseif item.rsvp.toLowerCase() == "no" %}
+
+ Won't attend
+ {% elseif item.rsvp.toLowerCase() == "interested" %}
+
+ Interested in
+ {% endif %}
+
+ {{ item["in-reply-to"] }}
+
+ {% endswitch %}
+{% endmacro %}
\ No newline at end of file
diff --git a/_content/_includes/partial-pagination.njk b/_content/_includes/partial-pagination.njk
new file mode 100644
index 0000000..10f0194
--- /dev/null
+++ b/_content/_includes/partial-pagination.njk
@@ -0,0 +1,15 @@
+{% if pagination %}
+
+{% endif %}
\ No newline at end of file
diff --git a/_content/_includes/summary-article.njk b/_content/_includes/summary-article.njk
new file mode 100644
index 0000000..edb3ccb
--- /dev/null
+++ b/_content/_includes/summary-article.njk
@@ -0,0 +1,6 @@
+
+{% if item.summary %}
+ {{ item.summary | safe }}
+{% endif %}
\ No newline at end of file
diff --git a/_content/_includes/summary-reply.njk b/_content/_includes/summary-reply.njk
new file mode 100644
index 0000000..e69de29
diff --git a/_content/index.html b/_content/index.html
new file mode 100644
index 0000000..d1f810e
--- /dev/null
+++ b/_content/index.html
@@ -0,0 +1,66 @@
+---
+layout: layout-main.njk
+eleventyExcludeFromCollections: true
+---
+
+
+
+
+
+ I'm Gordon Pedersen, a.k.a death.au
+
+
+ ...and I am a human on the Internet.
+
+
+ Go check out some stuff I wrote
+ Or stay up-to-date by following me
+
+
+
+
+
+{% layoutblock 'foot' %}
+
+
+
+{% endlayoutblock %}
diff --git a/_content/posts/index.njk b/_content/posts/index.njk
new file mode 100644
index 0000000..bbd4c63
--- /dev/null
+++ b/_content/posts/index.njk
@@ -0,0 +1,18 @@
+---
+title: My Feed
+layout: layout-feed.njk
+pagination:
+ data: collections.feed
+ size: 20
+eleventyExcludeFromCollections: true
+---
+{% from "macro-entry.njk" import entryMacro %}
+
+
+{% for item in pagination.items %}
+ -
+ {{ entryMacro(item.data, item.data.author, item.url, item.templateContent, true) }}
+
+{% endfor %}
+
+
diff --git a/bun.lockb b/bun.lockb
index 62950fa..1a02095 100755
Binary files a/bun.lockb and b/bun.lockb differ
diff --git a/css/styles.css b/css/styles.css
new file mode 100644
index 0000000..dfea86d
--- /dev/null
+++ b/css/styles.css
@@ -0,0 +1,211 @@
+:root {
+ --bg-rgb: 238, 238, 238;
+ --on-bg-rgb: 4, 4, 4;
+ --primary-rgb: 160, 116, 196;
+ --on-primary-rgb: 238, 238, 238;
+ --bg: rgb(var(--bg-rgb));
+ --on-bg: rgb(var(--on-bg-rgb));
+ --primary: rgb(var(--primary-rgb));
+ --on-primary: rgb(var(--on-primary-rgb));
+
+ --fade-alpha: 0.06;
+ --mute-alpha: 0.3;
+
+ --bg-fade: rgba(var(--bg-rgb), var(--fade-alpha));
+ --on-bg-fade: rgba(var(--on-bg-rgb), var(--fade-alpha));
+ --primary-fade: rgba(var(--primary-rgb), var(--fade-alpha));
+ --on-primary-fade: rgba(var(--on-primary-rgb), var(--fade-alpha));
+
+ --bg-muted: rgba(var(--bg-rgb), var(--mute-alpha));
+ --on-bg-muted: rgba(var(--on-bg-rgb), var(--mute-alpha));
+ --primary-muted: rgba(var(--primary-rgb), var(--mute-alpha));
+ --on-primary-muted: rgba(var(--on-primary-rgb), var(--mute-alpha));
+
+}
+@media (prefers-color-scheme: dark) {
+ :root{
+ --bg-rgb: 17, 17, 17;
+ --on-bg-rgb: 251, 251, 251;
+ --on-primary-rgb: 251, 251, 251;
+
+ --fade-alpha: 0.16;
+ }
+}
+html {
+ background-color: var(--bg);
+ color: var(--on-bg);
+}
+
+a {
+ color: var(--primary);
+ text-decoration: none;
+}
+
+a:hover {
+ text-decoration: underline;
+}
+
+body {
+ line-height: 1.6;
+ font-family: system-ui, -apple-system, BlinkMacSystemFont, Roboto, Helvetica, Arial, sans-serif;
+ text-align: center;
+ margin: 0;
+ min-height: 90vh;
+ display: flex;
+ flex-direction: column;
+ justify-content: center;
+ align-items: center;
+ overflow-x: hidden;
+}
+
+p:last-child {
+ margin-block-end: 0;
+}
+
+
+img.u-photo { border-radius: 50%; max-height:200px; }
+/* .p-author img.u-photo{
+ max-height: 48px;
+} */
+ul { padding: 0; list-style: none; }
+img.u-featured {
+ display:block;
+ z-index:0;
+ margin-bottom:-125px
+}
+
+button.icon-button {
+ line-height: 24px;
+ background-color: #666289;
+ color:#fff;
+ border:none;
+ border-radius:4px;
+}
+button.icon-button>img {
+ max-height: 24px;
+ vertical-align: bottom;
+}
+
+.button-input-container>label{
+ display:block;
+}
+.button-input-container>input{
+ background-color: #666289;
+ color:#fff;
+ border:none;
+ border-radius: 4px;
+ padding: 4px 66px 4px 6px;
+ margin-right: -60px;
+}
+.button-input-container>input:focus{
+ border:none;
+}
+.button-input-container>button{
+ background-color: #666289;
+ color:#fff;
+ border-radius: 4px;
+ border-color: #fff;
+}
+i>img{
+ max-height: 1em;
+ vertical-align: middle;
+}
+img.tiny-avatar {
+ max-height: 17px;
+}
+
+img.small-avatar {
+ max-height: 40px;
+}
+
+/* Pagination */
+.pagination {
+ margin: 50px auto;
+}
+.pagination li {
+ display: inline-block;
+}
+.pagination a {
+ padding: 8px 16px;
+ text-decoration: none;
+ border-radius: 5px;
+ border: 1px solid var(--on-bg-fade);
+}
+.pagination a.active {
+ background-color: var(--primary);
+ color: var(--on-primary);
+ }
+
+.pagination a:hover:not(.active) { background-color: var(--on-bg-fade); }
+
+.pagination a.disabled {
+ color: var(--primary-fade);
+ pointer-events: none;
+ }
+
+/* End Pagination */
+
+/* Feed Entries */
+
+.h-entry {
+ max-width: 500px;
+ min-width: 320px;
+ background-color: var(--primary-fade);
+ padding: 20px;
+ margin: 0;
+ border: 1px solid var(--on-bg-fade);
+ text-align: left;
+}
+
+.h-entry:not(:last-child) {
+ border-bottom: none;
+}
+
+.h-entry .p-author {
+ max-width: calc(100% - 80px);
+ display: flex;
+ align-items: center;
+ gap: 10px;
+ overflow: hidden;
+}
+
+.h-entry .u-photo {
+ vertical-align: baseline;
+}
+
+.h-entry .display-name {
+ display: block;
+ max-width: 100%;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ white-space: nowrap;
+}
+
+.h-entry .display-name .p-name {
+ white-space: nowrap;
+ display: block;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ font-weight: 700;
+}
+
+.h-entry .display-name .p-nickname {
+ white-space: nowrap;
+ display: block;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ color: var(--on-primary-muted);
+}
+
+.h-entry .permalink {
+ float:right;
+ text-align: right;
+ font-size: 0.8em;
+ color: var(--on-primary-muted);
+ display: block;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ max-width:80px;
+}
+
+/* End Feed Entries */
\ No newline at end of file
diff --git a/img/Fediverse_logo_proposal.svg b/img/Fediverse_logo_proposal.svg
new file mode 100644
index 0000000..854e6f0
--- /dev/null
+++ b/img/Fediverse_logo_proposal.svg
@@ -0,0 +1,170 @@
+
+
+
+
diff --git a/img/Obsidian.svg b/img/Obsidian.svg
new file mode 100644
index 0000000..57c05a2
--- /dev/null
+++ b/img/Obsidian.svg
@@ -0,0 +1,6 @@
+
diff --git a/img/avatar-tiny.png b/img/avatar-tiny.png
new file mode 100644
index 0000000..390531e
Binary files /dev/null and b/img/avatar-tiny.png differ
diff --git a/img/avatar-tt-trans.svg b/img/avatar-tt-trans.svg
new file mode 100644
index 0000000..90e8520
--- /dev/null
+++ b/img/avatar-tt-trans.svg
@@ -0,0 +1,37 @@
+
\ No newline at end of file
diff --git a/img/avatar-tt.svg b/img/avatar-tt.svg
new file mode 100644
index 0000000..3712fd0
--- /dev/null
+++ b/img/avatar-tt.svg
@@ -0,0 +1,38 @@
+
\ No newline at end of file
diff --git a/img/avatar-tt@800.png b/img/avatar-tt@800.png
new file mode 100644
index 0000000..4929c9c
Binary files /dev/null and b/img/avatar-tt@800.png differ
diff --git a/img/banner-1500x500.jpg b/img/banner-1500x500.jpg
new file mode 100644
index 0000000..cf44a30
Binary files /dev/null and b/img/banner-1500x500.jpg differ
diff --git a/js/button-input.js b/js/button-input.js
new file mode 100644
index 0000000..40b18e9
--- /dev/null
+++ b/js/button-input.js
@@ -0,0 +1,61 @@
+function buttonInputClick() {
+ this.style.display = 'none'
+
+ const buttonInput = document.createElement('div')
+ buttonInput.classList.add('button-input-container')
+
+ if(this.dataset.instruction){
+ const label = document.createElement('label')
+ buttonInput.appendChild(label)
+ label.innerText = this.dataset.instruction
+ }
+
+ const input = document.createElement('input')
+ buttonInput.appendChild(input)
+ input.type = 'text'
+ if(this.dataset.placeholder){
+ input.placeholder = this.dataset.placeholder
+ }
+
+ const button = document.createElement('button')
+ buttonInput.appendChild(button)
+ button.innerText = "Submit"
+ button.addEventListener('click', () => {
+ if(this.onsubmit){
+ const event = new Event('button-input-value')
+ event.value = input.value
+ this.onsubmit(event)
+ }
+
+ buttonInput.parentNode.removeChild(buttonInput)
+ if(this.dataset.success){
+ const span = document.createElement('span')
+ span.classList.add('success')
+ span.innerText = this.dataset.success
+ setTimeout(() => {
+ span.parentNode.removeChild(span)
+ this.style.display = null
+ }, 5000);
+ this.parentNode.insertBefore(span, this.nextSibling)
+ }
+ else{
+ this.style.display = null
+ }
+ })
+
+ input.addEventListener("keypress", function(event) {
+ if (event.key === "Enter") {
+ event.preventDefault();
+ button.click();
+ }
+ });
+
+ this.parentNode.insertBefore(buttonInput, this.nextSibling)
+ input.focus()
+}
+
+document.addEventListener('DOMContentLoaded', () => {
+ document.querySelectorAll('.button-input').forEach(button => {
+ button.addEventListener('click', buttonInputClick)
+ });
+}, false);
\ No newline at end of file
diff --git a/js/follow.js b/js/follow.js
new file mode 100644
index 0000000..f8891c1
--- /dev/null
+++ b/js/follow.js
@@ -0,0 +1,35 @@
+const SUBSCRIBE_LINK_REL = 'http://ostatus.org/schema/1.0/subscribe'
+function follow(username, handle) {
+ if(!handle){
+ handle = prompt("Please enter your fediverse / mastodon handle (e.g. '@user@domain.social')", "@")
+ }
+
+ if(handle) {
+ const input = handle
+ handle = handle.trim().replace(/^@/,'')
+ const split = handle.split('@')
+ if(split.length == 2) {
+ const resource = `acct:${handle}`
+ const domain = split[1]
+
+ // look up remote user via webfinger
+ const url = `https://${domain}/.well-known/webfinger?resource=${resource}`
+ fetch(url, {headers: {
+ 'Content-Type': 'application/activity+json'
+ }}).then(async result => {
+ const json = await result.json()
+ const subscribe = json.links.find(link => link.rel && link.rel == SUBSCRIBE_LINK_REL)
+ let template = subscribe.template
+ window.open(template.replace("{uri}", username), '_blank').focus()
+ })
+ .catch(e => {
+ console.error(e)
+ throw `Sorry, we couldn't find a subscribe uri for ${input}.\n\nTry searching for "${username}" on ${domain} (or in your fediverse client of choice)`
+ })
+
+ }
+ else {
+ throw 'Please enter your fediverse address in @user@domain.social format'
+ }
+ }
+}
\ No newline at end of file
diff --git a/js/relative-time.js b/js/relative-time.js
new file mode 100644
index 0000000..0dfba51
--- /dev/null
+++ b/js/relative-time.js
@@ -0,0 +1,6 @@
+document.addEventListener('DOMContentLoaded', () => {
+ document.querySelectorAll('time').forEach(time => {
+ const datetime = luxon.DateTime.fromISO(time.getAttribute('datetime'))
+ time.innerText = datetime.toRelative()
+ });
+}, false);
\ No newline at end of file
diff --git a/package.json b/package.json
index 55d599b..1fd791f 100644
--- a/package.json
+++ b/package.json
@@ -15,6 +15,7 @@
},
"dependencies": {
"@11ty/eleventy": "^2.0.1",
+ "@11ty/eleventy-plugin-rss": "^1.2.0",
"gray-matter": "^4.0.3",
"node-forge": "^1.3.1"
}
diff --git a/src/activitypub.ts b/src/activitypub.ts
index af71645..4affea7 100644
--- a/src/activitypub.ts
+++ b/src/activitypub.ts
@@ -1,4 +1,4 @@
-import { ACCOUNT, ACTOR, HOSTNAME, PUBLIC_KEY } from "./env"
+import { ACCOUNT, ACTOR, ACTOR_OBJ, HOSTNAME, PUBLIC_KEY } from "./env"
import * as db from "./db"
import { reqIsActivityPub, send, verify } from "./request"
import outbox from "./outbox"
@@ -162,28 +162,7 @@ const getActor = async (req:Request, account:string):Promise => {
console.log("GetActor", account)
if (ACCOUNT !== account) return new Response("", { status: 404 })
- if(reqIsActivityPub(req)) return Response.json({
- "@context": [
- "https://www.w3.org/ns/activitystreams",
- "https://w3id.org/security/v1",
- ],
- id: ACTOR,
- type: "Person",
- preferredUsername: ACCOUNT,
- url: ACTOR,
- manuallyApprovesFollowers: false,
- discoverable: true,
- published: "2023-09-14T00:00:00Z",
- inbox: `${ACTOR}/inbox`,
- outbox: `${ACTOR}/outbox`,
- followers: `${ACTOR}/followers`,
- following: `${ACTOR}/following`,
- publicKey: {
- id: `${ACTOR}#main-key`,
- owner: ACTOR,
- publicKeyPem: PUBLIC_KEY,
- },
- }, { headers: { "Content-Type": "application/activity+json"}})
+ if(reqIsActivityPub(req)) return Response.json(ACTOR_OBJ, { headers: { "Content-Type": "application/activity+json"}})
else return Response.json(await db.listPosts())
}
diff --git a/src/db.ts b/src/db.ts
index 722ec9f..5e00a45 100644
--- a/src/db.ts
+++ b/src/db.ts
@@ -1,4 +1,4 @@
-import { ACTIVITY_INBOX_PATH, ACTIVITY_OUTBOX_PATH, ACTOR, CONTENT_PATH, DATA_PATH, POSTS_PATH, STATIC_PATH } from "./env";
+import { ACCOUNT, ACTIVITY_INBOX_PATH, ACTIVITY_OUTBOX_PATH, ACTOR, CONTENT_PATH, DATA_PATH, POSTS_PATH, PUBLIC_KEY, STATIC_PATH } from "./env";
import path from "path"
import { readdir } from "fs/promises"
import { unlinkSync } from "node:fs"
diff --git a/src/env.ts b/src/env.ts
index 6b30c42..1e6d976 100644
--- a/src/env.ts
+++ b/src/env.ts
@@ -48,4 +48,32 @@ export const DEFAULT_DOCUMENTS = process.env.DEFAULT_DOCUMENTS || [
'Index.htm',
'default.html',
'default.htm'
-]
\ No newline at end of file
+]
+
+export const ACTOR_OBJ = {
+ "@context": [
+ "https://www.w3.org/ns/activitystreams",
+ "https://w3id.org/security/v1",
+ ],
+ id: ACTOR,
+ type: "Person",
+ preferredUsername: ACCOUNT,
+ url: ACTOR,
+ manuallyApprovesFollowers: false,
+ discoverable: true,
+ published: "2023-09-14T00:00:00Z",
+ inbox: `${ACTOR}/inbox`,
+ outbox: `${ACTOR}/outbox`,
+ followers: `${ACTOR}/followers`,
+ following: `${ACTOR}/following`,
+ publicKey: {
+ id: `${ACTOR}#main-key`,
+ owner: ACTOR,
+ publicKeyPem: PUBLIC_KEY,
+ },
+ icon: {
+ type: "Image",
+ mediaType: "image/png",
+ url: BASE_URL + "/assets/img/avatar-tt@800.png"
+ },
+}
\ No newline at end of file
diff --git a/src/index.ts b/src/index.ts
index c7758e8..5005561 100644
--- a/src/index.ts
+++ b/src/index.ts
@@ -1,10 +1,12 @@
-import { ACCOUNT, ACTOR, DEFAULT_DOCUMENTS, HOSTNAME, PORT, STATIC_PATH } from "./env";
+import { ACCOUNT, ACTOR, DEFAULT_DOCUMENTS, HOSTNAME, STATIC_PATH } from "./env";
import admin from './admin'
import activitypub from "./activitypub";
import { fetchObject } from "./request";
import path from "path"
import { BunFile } from "bun";
-const { stat } = require("fs").promises
+import { rebuild } from "./db";
+
+rebuild()
const server = Bun.serve({
port: 3000,