diff --git a/bun.lockb b/bun.lockb
index 10d527e..4da935d 100755
Binary files a/bun.lockb and b/bun.lockb differ
diff --git a/package.json b/package.json
index 5a3d77a..f15566d 100644
--- a/package.json
+++ b/package.json
@@ -13,34 +13,34 @@
},
"devDependencies": {
"@sveltejs/enhanced-img": "^0.3.10",
- "@sveltejs/kit": "^2.15.1",
+ "@sveltejs/kit": "^2.17.1",
"@sveltejs/vite-plugin-svelte": "^3.1.2",
- "@tailwindcss/forms": "^0.5.9",
- "@tailwindcss/typography": "^0.5.15",
+ "@tailwindcss/forms": "^0.5.10",
+ "@tailwindcss/typography": "^0.5.16",
"@types/eslint": "^9.6.1",
- "@types/node": "^22.10.3",
+ "@types/node": "^22.13.1",
"autoprefixer": "^10.4.20",
- "eslint": "^9.17.0",
+ "eslint": "^9.19.0",
"eslint-config-prettier": "^9.1.0",
"eslint-plugin-svelte": "^2.46.1",
"globals": "^15.14.0",
"mdsvex": "^0.12.3",
- "postcss": "^8.4.49",
+ "postcss": "^8.5.1",
"prettier": "^3.4.2",
- "prettier-plugin-svelte": "^3.3.2",
+ "prettier-plugin-svelte": "^3.3.3",
"svelte": "^4.2.19",
"svelte-adapter-bun": "^0.5.2",
"svelte-check": "^3.8.6",
"sveltekit-rate-limiter": "^0.6.1",
"tailwindcss": "^3.4.17",
"tslib": "^2.8.1",
- "typescript": "^5.7.2",
- "typescript-eslint": "^8.19.0",
- "vite": "^5.4.11"
+ "typescript": "^5.7.3",
+ "typescript-eslint": "^8.23.0",
+ "vite": "^5.4.14"
},
"type": "module",
"dependencies": {
- "@neodrag/svelte": "^2.2.0",
+ "@neodrag/svelte": "^2.3.0",
"@skyware/bot": "^0.3.8",
"@std/toml": "npm:@jsr/std__toml",
"base64url": "^3.0.1",
diff --git a/src/components/note.svelte b/src/components/note.svelte
index 0644807..6941878 100644
--- a/src/components/note.svelte
+++ b/src/components/note.svelte
@@ -1,9 +1,32 @@
+
-{#if !onlyContent}
{/if}
+{#if !onlyContent} {/if}
+{#if note.hasMedia}{/if}
+{#if note.hasQuote}{/if}
{#each note.outgoingLinks ?? [] as {name, link}}
{@const color = outgoingLinkColors[name]}
{name}
diff --git a/src/lib/bluesky.ts b/src/lib/bluesky.ts
index 11b8100..0b791d0 100644
--- a/src/lib/bluesky.ts
+++ b/src/lib/bluesky.ts
@@ -1,5 +1,5 @@
import { env } from '$env/dynamic/private'
-import { Bot } from "@skyware/bot";
+import { Bot, Post } from "@skyware/bot";
import { get, writable } from 'svelte/store'
const bskyClient = writable(null)
@@ -17,4 +17,19 @@ const loginToBsky = async () => {
const bot = new Bot({ service: "https://bsky.social" })
await bot.login({ identifier: 'gaze.systems', password: env.BSKY_PASSWORD ?? "" })
return bot
+}
+
+export const getUserPosts = async (did: string, includeReposts: boolean = false, count: number = 10) => {
+ const client = await getBskyClient()
+ let feedCursor = undefined;
+ let posts: Post[] = []
+ // fetch requested amount of posts
+ while (posts.length < count || feedCursor === undefined) {
+ let feedData = await client.getUserPosts(
+ did, { limit: count, filter: 'posts_no_replies', cursor: feedCursor }
+ )
+ posts.push(...feedData.posts.filter((post) => !includeReposts && post.author.did === did))
+ feedCursor = feedData.cursor
+ }
+ return posts
}
\ No newline at end of file
diff --git a/src/lib/notes.ts b/src/lib/notes.ts
deleted file mode 100644
index 9b73188..0000000
--- a/src/lib/notes.ts
+++ /dev/null
@@ -1,68 +0,0 @@
-import { existsSync, readFileSync, writeFileSync } from 'fs'
-import { nanoid } from 'nanoid'
-import { env } from '$env/dynamic/private'
-
-export interface OutgoingLinkData {
- name: string,
- link: string,
-}
-
-export interface Note {
- content: string,
- published: number,
- outgoingLinks?: OutgoingLinkData[],
- replyTo?: NoteId,
-}
-type NoteId = string
-
-export const notesFolder = `${env.WEBSITE_DATA_DIR}/note`
-export const notesListFile = `${env.WEBSITE_DATA_DIR}/notes`
-export const noteIdLength = 8;
-
-export const getNotePath = (id: NoteId) => { return `${notesFolder}/${id}` }
-export const genNoteId = () => {
- let id = nanoid(noteIdLength)
- while (existsSync(getNotePath(id))) {
- id = nanoid(noteIdLength)
- }
- return id
-}
-export const noteExists = (id: NoteId) => { return existsSync(getNotePath(id)) }
-export const readNote = (id: NoteId): Note => {
- return JSON.parse(readFileSync(getNotePath(id)).toString())
-}
-export const findReplyRoot = (id: NoteId): {rootNote: Note, rootNoteId: NoteId} => {
- let noteId: string | null = id
- let current: {rootNote?: Note, rootNoteId?: NoteId} = {}
- while (noteId !== null) {
- current.rootNote = readNote(noteId)
- current.rootNoteId = noteId
- noteId = current.rootNote.replyTo ?? null
- }
- if (current.rootNote === undefined || current.rootNoteId === undefined) {
- throw "no note with id found"
- }
- return {
- rootNote: current.rootNote,
- rootNoteId: current.rootNoteId,
- }
-}
-export const writeNote = (id: NoteId, note: Note) => {
- writeFileSync(getNotePath(id), JSON.stringify(note))
- // only append to note list if its not in it yet
- let noteList = readNotesList()
- if (noteList.indexOf(id) === -1) {
- writeNotesList([id].concat(noteList))
- }
-}
-export const createNote = (id: NoteId, note: Note) => {
- writeNote(id, note)
- return id
-}
-
-export const readNotesList = (): NoteId[] => {
- return JSON.parse(readFileSync(notesListFile).toString())
-}
-export const writeNotesList = (note_ids: NoteId[]) => {
- writeFileSync(notesListFile, JSON.stringify(note_ids))
-}
\ No newline at end of file
diff --git a/src/routes/+page.server.ts b/src/routes/+page.server.ts
index 3b28ffe..df4eeac 100644
--- a/src/routes/+page.server.ts
+++ b/src/routes/+page.server.ts
@@ -1,18 +1,18 @@
+import { getUserPosts } from "$lib/bluesky.js"
import { lastFmGetNowPlaying } from "$lib/lastfm"
-import { readNote, readNotesList } from "$lib/notes.js"
import { steamGetNowPlaying } from "$lib/steam"
+import { noteFromBskyPost } from "../components/note.svelte"
export const load = async ({}) => {
const lastTrack = await lastFmGetNowPlaying()
const lastGame = await steamGetNowPlaying()
+ const lastNote = noteFromBskyPost((await getUserPosts("did:plc:dfl62fgb7wtjj3fcbb72naae", false, 1))[0])
let banners: number[] = []
while (banners.length < 3) {
const no = getBannerNo(banners)
banners.push(no)
}
- const lastNoteId = readNotesList()[0]
- const lastNote = readNote(lastNoteId)
- return {banners, lastTrack, lastGame, lastNote, lastNoteId}
+ return {banners, lastTrack, lastGame, lastNote}
}
const getBannerNo = (others: number[]) => {
diff --git a/src/routes/+page.svelte b/src/routes/+page.svelte
index 2ccb709..7e5ec96 100644
--- a/src/routes/+page.svelte
+++ b/src/routes/+page.svelte
@@ -155,7 +155,7 @@
published on {renderDate(data.lastNote.published)}
-
+
{#if data.lastTrack}
diff --git a/src/routes/entries/+page.server.ts b/src/routes/entries/+page.server.ts
index ce806dd..3bc4e89 100644
--- a/src/routes/entries/+page.server.ts
+++ b/src/routes/entries/+page.server.ts
@@ -10,6 +10,6 @@ export const load = (params) => {
if (log_page !== null) {
url.searchParams.append("page", log_page)
}
- var logs_result = load_logs({url})
+ var logs_result = load_logs()
return logs_result
}
\ No newline at end of file
diff --git a/src/routes/log/+page.server.ts b/src/routes/log/+page.server.ts
index 49a3672..021775a 100644
--- a/src/routes/log/+page.server.ts
+++ b/src/routes/log/+page.server.ts
@@ -1,41 +1,12 @@
-import { noteExists, readNote, readNotesList } from '$lib/notes'
+import { getUserPosts } from '$lib/bluesky.js';
+import { noteFromBskyPost } from '../../components/note.svelte';
-const notesPerPage: number = 15
-
-export const load = ({ url }) => {
- return _load({ url })
+export const load = async ({ }) => {
+ return _load()
}
-export const _load = ({ url }: { url: URL }) => {
- // get the note id to search for and display the page it is in
- const noteId = url.searchParams.get("id")
- // get the page no if one is provided, otherwise default to 1
- let page = parseInt(url.searchParams.get("page") || "1")
- if (isNaN(page)) { page = 1 }
-
- // calculate page count
- const notesList = readNotesList()
- const pageCount = Math.ceil(notesList.length / notesPerPage)
-
- // find what page the note id if supplied is from
- if (noteId !== null && noteExists(noteId)) {
- const noteIndex = notesList.lastIndexOf(noteId)
- if (noteIndex > -1) {
- page = Math.floor(noteIndex / notesPerPage) + 1
- }
+export const _load = async () => {
+ return {
+ feedPosts: (await getUserPosts("did:plc:dfl62fgb7wtjj3fcbb72naae", false, 13)).map(noteFromBskyPost),
}
-
- // clamp page between our min and max
- page = Math.min(page, pageCount)
- page = Math.max(page, 1)
-
- // get the notes from the chosen page
- const notes = new Map(
- notesList.slice((page - 1) * notesPerPage, page * notesPerPage)
- .map(
- (id) => { return [id, readNote(id)] }
- )
- )
-
- return { notes, highlightedNote: noteId, page }
}
\ No newline at end of file
diff --git a/src/routes/log/+page.svelte b/src/routes/log/+page.svelte
index 52a26c2..f95dafc 100644
--- a/src/routes/log/+page.svelte
+++ b/src/routes/log/+page.svelte
@@ -4,17 +4,8 @@
import Note from '../../components/note.svelte';
export let data;
-
- const highlightedNote = data.notes.get(data.highlightedNote ?? '') ?? null
-
- {#if highlightedNote !== null}
-
-
- {/if}
-
-
gazesystems
-{#each data.notes as [id, note], index}
-{@const isHighlighted = id === data.highlightedNote}
-
-{#if index < data.notes.size - 1}
+{#each data.feedPosts as note, index}
+
+{#if index < data.feedPosts.length - 1}
{/if}
{/each}
diff --git a/src/routes/log/_rss/+server.ts b/src/routes/log/_rss/+server.ts
deleted file mode 100644
index e61687f..0000000
--- a/src/routes/log/_rss/+server.ts
+++ /dev/null
@@ -1,38 +0,0 @@
-import { PUBLIC_BASE_URL } from '$env/static/public';
-import { readNote, readNotesList, type Note } from '$lib/notes.ts';
-
-const logUrl = `${PUBLIC_BASE_URL}/log`;
-
-interface NoteData {
- data: Note,
- id: string,
-}
-
-export const GET = async ({ }) => {
- const log = readNotesList().map((id) => {return { data: readNote(id), id }})
- return new Response(
- render(log),
- {
- headers: {
- 'content-type': 'application/xml',
- 'cache-control': 'no-store',
- }
- })
-};
-
-const render = (log: NoteData[]) => `
-
-
-
- dusk's notes (@gaze.systems)
- ${logUrl}
- a collection of random notes i write whenever, aka my microblogging spot
- ${log.map((note) => `-
- ${logUrl}/?id=${note.id}
- ${logUrl}/?id=${note.id}
- ${note.data.content}
- ${new Date(note.data.published).toUTCString()}
-
`).join('')}
-
-
- `;
\ No newline at end of file
diff --git a/src/routes/log/create/+server.ts b/src/routes/log/create/+server.ts
deleted file mode 100644
index 03a4e3f..0000000
--- a/src/routes/log/create/+server.ts
+++ /dev/null
@@ -1,76 +0,0 @@
-import { env } from '$env/dynamic/private';
-import { PUBLIC_BASE_URL } from '$env/static/public';
-import { getBskyClient } from '$lib/bluesky.js';
-import { createNote, findReplyRoot, genNoteId, readNote, type Note } from '$lib/notes';
-import type { Post, PostPayload, PostReference, ReplyRef } from '@skyware/bot';
-
-interface NoteData {
- content: string,
- replyTo?: string,
- embedUri?: string,
- bskyPosse: boolean,
-}
-
-export const POST = async ({ request }) => {
- const token = request.headers.get('authorization')
- if (token !== env.GAZEBOT_TOKEN) {
- return new Response("rizz failed", { status: 403 })
- }
- // get id
- const noteId = genNoteId()
- // get note data
- const noteData: NoteData = await request.json()
- console.log(`want to create note #${noteId} with data: `, noteData)
- // get a date before we start publishing to other platforms
- let note: Note = {
- content: noteData.content,
- published: Date.now(),
- outgoingLinks: [],
- replyTo: noteData.replyTo,
- }
- let errors: string[] = []
- let repliedNote: Note | null = null
- if (noteData.replyTo !== undefined) {
- repliedNote = readNote(noteData.replyTo)
- }
- // bridge to bsky if want to bridge
- if (noteData.bskyPosse) {
- const postContent = `${noteData.content} (${PUBLIC_BASE_URL}/log?id=${noteId})`
- try {
- const bot = await getBskyClient()
- let postPayload: PostPayload = {
- text: postContent,
- createdAt: new Date(note.published),
- external: noteData.embedUri,
- }
- let postRef: PostReference
- // find parent and reply posts
- let replyRef: ReplyRef | null = null
- if (noteData.replyTo !== undefined && repliedNote !== null) {
- const getBskyUri = (note: Note) => { return note.outgoingLinks?.find((v) => {return v.name === "bsky"})?.link }
- const parentUri = getBskyUri(repliedNote)
- if (parentUri !== undefined) {
- const parentPost = await bot.getPost(parentUri)
- postRef = await parentPost.reply(postPayload)
- } else {
- throw "a reply was requested but no reply is found"
- }
- } else {
- postRef = await bot.post(postPayload)
- }
- note.outgoingLinks?.push({name: "bsky", link: postRef.uri})
- } catch(why) {
- console.log(`failed to post note #${noteId} to bsky: `, why)
- errors.push(`error while posting to bsky: ${why}`)
- }
- }
- // create note (this should never fail otherwise it would defeat the whole purpose lol)
- createNote(noteId, note)
- // send back created note id and any errors that occurred
- return new Response(JSON.stringify({ noteId, errors }), {
- headers: {
- 'content-type': 'application/json',
- 'cache-control': 'no-store',
- }
- })
-};
diff --git a/src/styles/app.css b/src/styles/app.css
index 0f1e888..e78b868 100644
--- a/src/styles/app.css
+++ b/src/styles/app.css
@@ -1,5 +1,9 @@
@import './prism-synthwave84.css';
+@import 'bluesky-profile-feed-embed/style.css';
+@import 'bluesky-profile-feed-embed/themes/light.css' (prefers-color-scheme: light);
+@import 'bluesky-profile-feed-embed/themes/dim.css' (prefers-color-scheme: dark);
+
@tailwind base;
@tailwind components;
@tailwind utilities;