feat: add reply to functionality to log
This commit is contained in:
parent
a3525f1fa4
commit
ab8ce81e18
22
package.json
22
package.json
@ -13,35 +13,35 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"@sveltejs/enhanced-img": "^0.3.10",
|
||||
"@sveltejs/kit": "^2.8.4",
|
||||
"@sveltejs/kit": "^2.11.1",
|
||||
"@sveltejs/vite-plugin-svelte": "^3.1.2",
|
||||
"@tailwindcss/forms": "^0.5.9",
|
||||
"@tailwindcss/typography": "^0.5.15",
|
||||
"@types/eslint": "^9.6.1",
|
||||
"@types/node": "^22.10.0",
|
||||
"@types/node": "^22.10.2",
|
||||
"autoprefixer": "^10.4.20",
|
||||
"eslint": "^9.15.0",
|
||||
"eslint": "^9.17.0",
|
||||
"eslint-config-prettier": "^9.1.0",
|
||||
"eslint-plugin-svelte": "^2.46.0",
|
||||
"globals": "^15.12.0",
|
||||
"eslint-plugin-svelte": "^2.46.1",
|
||||
"globals": "^15.13.0",
|
||||
"mdsvex": "^0.12.3",
|
||||
"postcss": "^8.4.49",
|
||||
"prettier": "^3.4.1",
|
||||
"prettier": "^3.4.2",
|
||||
"prettier-plugin-svelte": "^3.3.2",
|
||||
"svelte": "^4.2.19",
|
||||
"svelte-adapter-bun": "^0.5.2",
|
||||
"svelte-check": "^3.8.6",
|
||||
"sveltekit-rate-limiter": "^0.6.1",
|
||||
"tailwindcss": "^3.4.15",
|
||||
"tailwindcss": "^3.4.16",
|
||||
"tslib": "^2.8.1",
|
||||
"typescript": "^5.7.2",
|
||||
"typescript-eslint": "^8.16.0",
|
||||
"typescript-eslint": "^8.18.0",
|
||||
"vite": "^5.4.11"
|
||||
},
|
||||
"type": "module",
|
||||
"dependencies": {
|
||||
"@atproto/api": "^0.13.18",
|
||||
"@neodrag/svelte": "^2.0.6",
|
||||
"@neodrag/svelte": "^2.2.0",
|
||||
"@skyware/bot": "^0.3.8",
|
||||
"@std/toml": "npm:@jsr/std__toml",
|
||||
"base64url": "^3.0.1",
|
||||
"nanoid": "^5.0.9",
|
||||
@ -49,7 +49,7 @@
|
||||
"rehype-slug": "^6.0.0",
|
||||
"robots-parser": "^3.0.1",
|
||||
"steamgriddb": "^2.2.0",
|
||||
"typescript-svelte-plugin": "^0.3.43"
|
||||
"typescript-svelte-plugin": "^0.3.44"
|
||||
},
|
||||
"trustedDependencies": [
|
||||
"@sveltejs/kit",
|
||||
|
@ -1,8 +1,8 @@
|
||||
import { env } from '$env/dynamic/private'
|
||||
import { Agent, CredentialSession, RichText } from '@atproto/api'
|
||||
import { Bot } from "@skyware/bot";
|
||||
import { get, writable } from 'svelte/store'
|
||||
|
||||
const bskyClient = writable<null | Agent>(null)
|
||||
const bskyClient = writable<null | Bot>(null)
|
||||
|
||||
export const getBskyClient = async () => {
|
||||
let client = get(bskyClient)
|
||||
@ -13,19 +13,15 @@ export const getBskyClient = async () => {
|
||||
return client
|
||||
}
|
||||
|
||||
export const postToBsky = async (text: string) => {
|
||||
let client = await getBskyClient()
|
||||
const rt = new RichText({ text })
|
||||
await rt.detectFacets(client)
|
||||
const {uri} = await client.post({
|
||||
text: rt.text,
|
||||
facets: rt.facets,
|
||||
})
|
||||
export const parseAtUri = (uri: string) => {
|
||||
if (uri.startsWith("https://bsky.gaze.systems")) {
|
||||
return uri
|
||||
}
|
||||
return `https://bsky.gaze.systems/post/${uri.split('/').pop()}`
|
||||
}
|
||||
|
||||
const loginToBsky = async () => {
|
||||
const creds = new CredentialSession(new URL("https://bsky.social"))
|
||||
await creds.login({ identifier: 'gaze.systems', password: env.BSKY_PASSWORD ?? "" })
|
||||
return new Agent(creds)
|
||||
const bot = new Bot({ service: "https://bsky.social" })
|
||||
await bot.login({ identifier: 'gaze.systems', password: env.BSKY_PASSWORD ?? "" })
|
||||
return bot
|
||||
}
|
@ -11,6 +11,7 @@ export interface Note {
|
||||
content: string,
|
||||
published: number,
|
||||
outgoingLinks?: OutgoingLinkData[],
|
||||
replyTo?: NoteId,
|
||||
}
|
||||
type NoteId = string
|
||||
|
||||
@ -30,6 +31,21 @@ 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 currentNoteId: string | null = id
|
||||
let currentNote: Note | null = null
|
||||
while (currentNoteId !== null) {
|
||||
currentNote = readNote(currentNoteId)
|
||||
currentNoteId = currentNote.replyTo ?? null
|
||||
}
|
||||
if (currentNote === null || currentNoteId === null) {
|
||||
throw "no note with id found"
|
||||
}
|
||||
return {
|
||||
rootNote: currentNote,
|
||||
rootNoteId: currentNoteId,
|
||||
}
|
||||
}
|
||||
export const writeNote = (id: NoteId, note: Note) => {
|
||||
writeFileSync(getNotePath(id), JSON.stringify(note))
|
||||
// only append to note list if its not in it yet
|
||||
|
@ -1,6 +1,7 @@
|
||||
<script lang="ts">
|
||||
import Window from '../../components/window.svelte';
|
||||
import Token from '../../components/token.svelte';
|
||||
import { parseAtUri } from '$lib/bluesky.js';
|
||||
|
||||
export let data;
|
||||
|
||||
@ -16,6 +17,12 @@
|
||||
|
||||
const highlightedNote = data.notes.get(data.highlightedNote ?? '') ?? null
|
||||
|
||||
const getOutgoingLink = (name: string, link: string) => {
|
||||
if (name === "bsky") {
|
||||
return parseAtUri(link)
|
||||
}
|
||||
return link
|
||||
}
|
||||
// this is ASS this should be a tailwind class
|
||||
const getTextShadowStyle = (color: string) => {
|
||||
return `text-shadow: 0 0 1px theme(colors.ralsei.black), 0 0 5px ${color};`
|
||||
@ -52,7 +59,7 @@
|
||||
<Token v={renderDate(note.published)} small={!isHighlighted}/> <Token v={noteId} keywd small={!isHighlighted}/><Token v="#" punct/> <Token v={note.content} str/>
|
||||
{#each note.outgoingLinks ?? [] as {name, link}}
|
||||
{@const color = outgoingLinkColors[name]}
|
||||
<span class="text-sm"><Token v="(" punct/><a style="color: {color};{getTextShadowStyle(color)}" href={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>
|
||||
{/each}
|
||||
</div>
|
||||
{#if index < data.notes.size - 1}
|
||||
|
@ -1,10 +1,12 @@
|
||||
import { env } from '$env/dynamic/private';
|
||||
import { PUBLIC_BASE_URL } from '$env/static/public';
|
||||
import { postToBsky } from '$lib/bluesky';
|
||||
import { createNote, genNoteId, type Note } from '$lib/notes';
|
||||
import { getBskyClient } from '$lib/bluesky.js';
|
||||
import { createNote, findReplyRoot, genNoteId, readNote, type Note } from '$lib/notes';
|
||||
import type { Post, ReplyRef } from '@skyware/bot';
|
||||
|
||||
interface NoteData {
|
||||
content: string,
|
||||
replyTo?: string,
|
||||
bskyPosse: boolean,
|
||||
}
|
||||
|
||||
@ -23,14 +25,45 @@ export const POST = async ({ request }) => {
|
||||
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 bskyUrl = await postToBsky(postContent)
|
||||
note.outgoingLinks?.push({name: "bsky", link: bskyUrl})
|
||||
const bot = await getBskyClient()
|
||||
// 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)
|
||||
let parentPost: Post | null = null
|
||||
if (parentUri !== undefined) {
|
||||
parentPost = await bot.getPost(parentUri)
|
||||
}
|
||||
const rootUri = getBskyUri(findReplyRoot(noteData.replyTo).rootNote)
|
||||
let rootPost: Post | null = null
|
||||
if (rootUri !== undefined) {
|
||||
rootPost = await bot.getPost(rootUri)
|
||||
}
|
||||
if (parentPost !== null && rootPost !== null) {
|
||||
replyRef = {
|
||||
parent: parentPost,
|
||||
root: rootPost,
|
||||
}
|
||||
}
|
||||
}
|
||||
const postRef = await bot.post({
|
||||
text: postContent,
|
||||
createdAt: new Date(note.published),
|
||||
replyRef: replyRef ?? undefined
|
||||
})
|
||||
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}`)
|
||||
|
Loading…
x
Reference in New Issue
Block a user