feat: use bsky posts for log instead of custom thing
This commit is contained in:
parent
c4c4cae944
commit
2538bb614c
22
package.json
22
package.json
@ -13,34 +13,34 @@
|
|||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@sveltejs/enhanced-img": "^0.3.10",
|
"@sveltejs/enhanced-img": "^0.3.10",
|
||||||
"@sveltejs/kit": "^2.15.1",
|
"@sveltejs/kit": "^2.17.1",
|
||||||
"@sveltejs/vite-plugin-svelte": "^3.1.2",
|
"@sveltejs/vite-plugin-svelte": "^3.1.2",
|
||||||
"@tailwindcss/forms": "^0.5.9",
|
"@tailwindcss/forms": "^0.5.10",
|
||||||
"@tailwindcss/typography": "^0.5.15",
|
"@tailwindcss/typography": "^0.5.16",
|
||||||
"@types/eslint": "^9.6.1",
|
"@types/eslint": "^9.6.1",
|
||||||
"@types/node": "^22.10.3",
|
"@types/node": "^22.13.1",
|
||||||
"autoprefixer": "^10.4.20",
|
"autoprefixer": "^10.4.20",
|
||||||
"eslint": "^9.17.0",
|
"eslint": "^9.19.0",
|
||||||
"eslint-config-prettier": "^9.1.0",
|
"eslint-config-prettier": "^9.1.0",
|
||||||
"eslint-plugin-svelte": "^2.46.1",
|
"eslint-plugin-svelte": "^2.46.1",
|
||||||
"globals": "^15.14.0",
|
"globals": "^15.14.0",
|
||||||
"mdsvex": "^0.12.3",
|
"mdsvex": "^0.12.3",
|
||||||
"postcss": "^8.4.49",
|
"postcss": "^8.5.1",
|
||||||
"prettier": "^3.4.2",
|
"prettier": "^3.4.2",
|
||||||
"prettier-plugin-svelte": "^3.3.2",
|
"prettier-plugin-svelte": "^3.3.3",
|
||||||
"svelte": "^4.2.19",
|
"svelte": "^4.2.19",
|
||||||
"svelte-adapter-bun": "^0.5.2",
|
"svelte-adapter-bun": "^0.5.2",
|
||||||
"svelte-check": "^3.8.6",
|
"svelte-check": "^3.8.6",
|
||||||
"sveltekit-rate-limiter": "^0.6.1",
|
"sveltekit-rate-limiter": "^0.6.1",
|
||||||
"tailwindcss": "^3.4.17",
|
"tailwindcss": "^3.4.17",
|
||||||
"tslib": "^2.8.1",
|
"tslib": "^2.8.1",
|
||||||
"typescript": "^5.7.2",
|
"typescript": "^5.7.3",
|
||||||
"typescript-eslint": "^8.19.0",
|
"typescript-eslint": "^8.23.0",
|
||||||
"vite": "^5.4.11"
|
"vite": "^5.4.14"
|
||||||
},
|
},
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@neodrag/svelte": "^2.2.0",
|
"@neodrag/svelte": "^2.3.0",
|
||||||
"@skyware/bot": "^0.3.8",
|
"@skyware/bot": "^0.3.8",
|
||||||
"@std/toml": "npm:@jsr/std__toml",
|
"@std/toml": "npm:@jsr/std__toml",
|
||||||
"base64url": "^3.0.1",
|
"base64url": "^3.0.1",
|
||||||
|
@ -1,9 +1,32 @@
|
|||||||
|
<script context="module" lang="ts">
|
||||||
|
import type { Post } from "@skyware/bot";
|
||||||
|
|
||||||
|
export interface OutgoingLink {
|
||||||
|
name: string,
|
||||||
|
link: string,
|
||||||
|
}
|
||||||
|
export interface NoteData {
|
||||||
|
content: string,
|
||||||
|
published: number,
|
||||||
|
hasMedia: boolean,
|
||||||
|
hasQuote: boolean,
|
||||||
|
outgoingLinks?: OutgoingLink[],
|
||||||
|
}
|
||||||
|
|
||||||
|
export const noteFromBskyPost = (post: Post): NoteData => {
|
||||||
|
return {
|
||||||
|
content: post.text,
|
||||||
|
published: post.createdAt.getTime(),
|
||||||
|
outgoingLinks: [{ name: "bsky", link: post.uri }],
|
||||||
|
hasMedia: (post.embed?.isImages() || post.embed?.isVideo()) ?? false,
|
||||||
|
hasQuote: post.embed?.isRecord() ?? false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import type { Note } from "$lib/notes";
|
|
||||||
import Token from "./token.svelte";
|
import Token from "./token.svelte";
|
||||||
|
|
||||||
export let id: string;
|
export let note: NoteData;
|
||||||
export let note: Note;
|
|
||||||
export let isHighlighted = false;
|
export let isHighlighted = false;
|
||||||
export let onlyContent = false;
|
export let onlyContent = false;
|
||||||
|
|
||||||
@ -19,10 +42,7 @@
|
|||||||
|
|
||||||
const getOutgoingLink = (name: string, link: string) => {
|
const getOutgoingLink = (name: string, link: string) => {
|
||||||
if (name === "bsky") {
|
if (name === "bsky") {
|
||||||
if (link.startsWith("https://bsky.gaze.systems")) {
|
return `https://bsky.app/profile/gaze.systems/post/${link.split('/').pop()}`
|
||||||
return link
|
|
||||||
}
|
|
||||||
return `https://bsky.gaze.systems/post/${link.split('/').pop()}`
|
|
||||||
}
|
}
|
||||||
return link
|
return link
|
||||||
}
|
}
|
||||||
@ -36,7 +56,9 @@
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="text-wrap break-words max-w-[70ch] leading-none">
|
<div class="text-wrap break-words max-w-[70ch] leading-none">
|
||||||
{#if !onlyContent}<Token v={renderDate(note.published)} small={!isHighlighted}/> <Token v={id} keywd small={!isHighlighted}/><Token v="#" punct/> {/if}<Token v={note.content} str/>
|
{#if !onlyContent}<Token v={renderDate(note.published)} small={!isHighlighted}/> {/if}<Token v={note.content} str/>
|
||||||
|
{#if note.hasMedia}<Token v="-contains media-" keywd small/>{/if}
|
||||||
|
{#if note.hasQuote}<Token v="-contains quote-" keywd small/>{/if}
|
||||||
{#each note.outgoingLinks ?? [] as {name, link}}
|
{#each note.outgoingLinks ?? [] as {name, link}}
|
||||||
{@const color = outgoingLinkColors[name]}
|
{@const color = outgoingLinkColors[name]}
|
||||||
<span class="text-sm"><Token v="(" punct/><a style="color: {color};{getTextShadowStyle(color)}" href={getOutgoingLink(name, link)}>{name}</a><Token v=")" punct/></span>
|
<span class="text-sm"><Token v="(" punct/><a style="color: {color};{getTextShadowStyle(color)}" href={getOutgoingLink(name, link)}>{name}</a><Token v=")" punct/></span>
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { env } from '$env/dynamic/private'
|
import { env } from '$env/dynamic/private'
|
||||||
import { Bot } from "@skyware/bot";
|
import { Bot, Post } from "@skyware/bot";
|
||||||
import { get, writable } from 'svelte/store'
|
import { get, writable } from 'svelte/store'
|
||||||
|
|
||||||
const bskyClient = writable<null | Bot>(null)
|
const bskyClient = writable<null | Bot>(null)
|
||||||
@ -18,3 +18,18 @@ const loginToBsky = async () => {
|
|||||||
await bot.login({ identifier: 'gaze.systems', password: env.BSKY_PASSWORD ?? "" })
|
await bot.login({ identifier: 'gaze.systems', password: env.BSKY_PASSWORD ?? "" })
|
||||||
return bot
|
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
|
||||||
|
}
|
@ -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))
|
|
||||||
}
|
|
@ -1,18 +1,18 @@
|
|||||||
|
import { getUserPosts } from "$lib/bluesky.js"
|
||||||
import { lastFmGetNowPlaying } from "$lib/lastfm"
|
import { lastFmGetNowPlaying } from "$lib/lastfm"
|
||||||
import { readNote, readNotesList } from "$lib/notes.js"
|
|
||||||
import { steamGetNowPlaying } from "$lib/steam"
|
import { steamGetNowPlaying } from "$lib/steam"
|
||||||
|
import { noteFromBskyPost } from "../components/note.svelte"
|
||||||
|
|
||||||
export const load = async ({}) => {
|
export const load = async ({}) => {
|
||||||
const lastTrack = await lastFmGetNowPlaying()
|
const lastTrack = await lastFmGetNowPlaying()
|
||||||
const lastGame = await steamGetNowPlaying()
|
const lastGame = await steamGetNowPlaying()
|
||||||
|
const lastNote = noteFromBskyPost((await getUserPosts("did:plc:dfl62fgb7wtjj3fcbb72naae", false, 1))[0])
|
||||||
let banners: number[] = []
|
let banners: number[] = []
|
||||||
while (banners.length < 3) {
|
while (banners.length < 3) {
|
||||||
const no = getBannerNo(banners)
|
const no = getBannerNo(banners)
|
||||||
banners.push(no)
|
banners.push(no)
|
||||||
}
|
}
|
||||||
const lastNoteId = readNotesList()[0]
|
return {banners, lastTrack, lastGame, lastNote}
|
||||||
const lastNote = readNote(lastNoteId)
|
|
||||||
return {banners, lastTrack, lastGame, lastNote, lastNoteId}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const getBannerNo = (others: number[]) => {
|
const getBannerNo = (others: number[]) => {
|
||||||
|
@ -155,7 +155,7 @@
|
|||||||
<span class="border-4 pl-[1ch]" style="border-style: none none none double;">published on {renderDate(data.lastNote.published)}</span>
|
<span class="border-4 pl-[1ch]" style="border-style: none none none double;">published on {renderDate(data.lastNote.published)}</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="mt-0 p-1 border-4 border-double bg-ralsei-black min-w-full max-w-[40ch]">
|
<div class="mt-0 p-1 border-4 border-double bg-ralsei-black min-w-full max-w-[40ch]">
|
||||||
<Note id={data.lastNoteId} note={data.lastNote} onlyContent/>
|
<Note note={data.lastNote} onlyContent/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{#if data.lastTrack}
|
{#if data.lastTrack}
|
||||||
|
@ -10,6 +10,6 @@ export const load = (params) => {
|
|||||||
if (log_page !== null) {
|
if (log_page !== null) {
|
||||||
url.searchParams.append("page", log_page)
|
url.searchParams.append("page", log_page)
|
||||||
}
|
}
|
||||||
var logs_result = load_logs({url})
|
var logs_result = load_logs()
|
||||||
return logs_result
|
return logs_result
|
||||||
}
|
}
|
@ -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 = async ({ }) => {
|
||||||
|
return _load()
|
||||||
export const load = ({ url }) => {
|
|
||||||
return _load({ url })
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export const _load = ({ url }: { url: URL }) => {
|
export const _load = async () => {
|
||||||
// get the note id to search for and display the page it is in
|
return {
|
||||||
const noteId = url.searchParams.get("id")
|
feedPosts: (await getUserPosts("did:plc:dfl62fgb7wtjj3fcbb72naae", false, 13)).map(noteFromBskyPost),
|
||||||
// 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
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// 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 }
|
|
||||||
}
|
}
|
@ -4,17 +4,8 @@
|
|||||||
import Note from '../../components/note.svelte';
|
import Note from '../../components/note.svelte';
|
||||||
|
|
||||||
export let data;
|
export let data;
|
||||||
|
|
||||||
const highlightedNote = data.notes.get(data.highlightedNote ?? '') ?? null
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<svelte:head>
|
|
||||||
{#if highlightedNote !== null}
|
|
||||||
<meta property="og:description" content={highlightedNote.content} />
|
|
||||||
<meta property="og:title" content="log #{data.highlightedNote}" />
|
|
||||||
{/if}
|
|
||||||
</svelte:head>
|
|
||||||
|
|
||||||
<Window title="terminal" removePadding>
|
<Window title="terminal" removePadding>
|
||||||
<div
|
<div
|
||||||
class="
|
class="
|
||||||
@ -29,10 +20,9 @@
|
|||||||
<Token v="[" punct/>gazesystems <Token v="/" keywd/><Token v="]$" punct/> <Token v="ls" funct/> <Token v="log" /> <Token v="|" punct/> <Token v="each" funct/> <Token v="{" punct/><Token v="|" punct/><Token v="file"/><Token v="|" punct/> <Token v="render" funct/> <Token v="(" punct/><Token v="open" funct/> <Token v="$file.name" /><Token v=")" punct/><Token v="}" punct/>
|
<Token v="[" punct/>gazesystems <Token v="/" keywd/><Token v="]$" punct/> <Token v="ls" funct/> <Token v="log" /> <Token v="|" punct/> <Token v="each" funct/> <Token v="{" punct/><Token v="|" punct/><Token v="file"/><Token v="|" punct/> <Token v="render" funct/> <Token v="(" punct/><Token v="open" funct/> <Token v="$file.name" /><Token v=")" punct/><Token v="}" punct/>
|
||||||
<br>
|
<br>
|
||||||
<br>
|
<br>
|
||||||
{#each data.notes as [id, note], index}
|
{#each data.feedPosts as note, index}
|
||||||
{@const isHighlighted = id === data.highlightedNote}
|
<Note {note}/>
|
||||||
<Note {id} {note} {isHighlighted}/>
|
{#if index < data.feedPosts.length - 1}
|
||||||
{#if index < data.notes.size - 1}
|
|
||||||
<div class="mt-3"/>
|
<div class="mt-3"/>
|
||||||
{/if}
|
{/if}
|
||||||
{/each}
|
{/each}
|
||||||
|
@ -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[]) => `<?xml version="1.0" encoding="UTF-8" ?>
|
|
||||||
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
|
|
||||||
<channel>
|
|
||||||
<atom:link href="${logUrl}/_rss" rel="self" type="application/rss+xml" />
|
|
||||||
<title>dusk's notes (@gaze.systems)</title>
|
|
||||||
<link>${logUrl}</link>
|
|
||||||
<description>a collection of random notes i write whenever, aka my microblogging spot</description>
|
|
||||||
${log.map((note) => `<item>
|
|
||||||
<guid>${logUrl}/?id=${note.id}</guid>
|
|
||||||
<link>${logUrl}/?id=${note.id}</link>
|
|
||||||
<description>${note.data.content}</description>
|
|
||||||
<pubDate>${new Date(note.data.published).toUTCString()}</pubDate>
|
|
||||||
</item>`).join('')}
|
|
||||||
</channel>
|
|
||||||
</rss>
|
|
||||||
`;
|
|
@ -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',
|
|
||||||
}
|
|
||||||
})
|
|
||||||
};
|
|
@ -1,5 +1,9 @@
|
|||||||
@import './prism-synthwave84.css';
|
@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 base;
|
||||||
@tailwind components;
|
@tailwind components;
|
||||||
@tailwind utilities;
|
@tailwind utilities;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user