feat: store 'bridged' posts in note data and display it
All checks were successful
create archive with lfs / tag (push) Successful in 12s
All checks were successful
create archive with lfs / tag (push) Successful in 12s
This commit is contained in:
parent
22c773c38e
commit
ce0871b052
@ -1,5 +1,5 @@
|
|||||||
import { env } from '$env/dynamic/private'
|
import { env } from '$env/dynamic/private'
|
||||||
import { Agent, CredentialSession } from '@atproto/api'
|
import { Agent, CredentialSession, RichText } from '@atproto/api'
|
||||||
import { get, writable } from 'svelte/store'
|
import { get, writable } from 'svelte/store'
|
||||||
|
|
||||||
const bskyClient = writable<null | Agent>(null)
|
const bskyClient = writable<null | Agent>(null)
|
||||||
@ -13,6 +13,17 @@ export const getBskyClient = async () => {
|
|||||||
return client
|
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,
|
||||||
|
})
|
||||||
|
return uri
|
||||||
|
}
|
||||||
|
|
||||||
const loginToBsky = async () => {
|
const loginToBsky = async () => {
|
||||||
const creds = new CredentialSession(new URL("https://bsky.social"))
|
const creds = new CredentialSession(new URL("https://bsky.social"))
|
||||||
await creds.login({ identifier: 'gaze.systems', password: env.BSKY_PASSWORD ?? "" })
|
await creds.login({ identifier: 'gaze.systems', password: env.BSKY_PASSWORD ?? "" })
|
||||||
|
@ -2,9 +2,15 @@ import { existsSync, readFileSync, writeFileSync } from 'fs'
|
|||||||
import { nanoid } from 'nanoid'
|
import { nanoid } from 'nanoid'
|
||||||
import { env } from '$env/dynamic/private'
|
import { env } from '$env/dynamic/private'
|
||||||
|
|
||||||
|
export interface OutgoingLinkData {
|
||||||
|
name: string,
|
||||||
|
link: string,
|
||||||
|
}
|
||||||
|
|
||||||
export interface Note {
|
export interface Note {
|
||||||
content: string,
|
content: string,
|
||||||
published: number,
|
published: number,
|
||||||
|
outgoingLinks?: OutgoingLinkData[],
|
||||||
}
|
}
|
||||||
type NoteId = string
|
type NoteId = string
|
||||||
|
|
||||||
@ -32,8 +38,7 @@ export const writeNote = (id: NoteId, note: Note) => {
|
|||||||
writeNotesList([id].concat(noteList))
|
writeNotesList([id].concat(noteList))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
export const createNote = (note: Note) => {
|
export const createNote = (id: NoteId, note: Note) => {
|
||||||
const id = genNoteId()
|
|
||||||
writeNote(id, note)
|
writeNote(id, note)
|
||||||
return id
|
return id
|
||||||
}
|
}
|
||||||
|
@ -15,6 +15,14 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
const highlightedNote = data.notes.get(data.highlightedNote ?? '') ?? null
|
const highlightedNote = data.notes.get(data.highlightedNote ?? '') ?? null
|
||||||
|
|
||||||
|
// 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};`
|
||||||
|
}
|
||||||
|
const outgoingLinkColors: Record<string, string> = {
|
||||||
|
bsky: "rgb(0, 133, 255)",
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<svelte:head>
|
<svelte:head>
|
||||||
@ -33,15 +41,19 @@
|
|||||||
"
|
"
|
||||||
>
|
>
|
||||||
<pre class="language-bash"><code class="language-bash"><nobr>
|
<pre class="language-bash"><code class="language-bash"><nobr>
|
||||||
<Token v="[" punct/>gazesystems <Token v="/log/" keywd/><Token v="]$" punct/> <Token v="source" funct/> log.nu
|
<Token v="[" punct/>gazesystems <Token v="/" keywd/><Token v="]$" punct/> <Token v="source" funct/> <Token v="scripts/log.nu" />
|
||||||
<br>
|
<br>
|
||||||
<Token v="[" punct/>gazesystems <Token v="/log/" keywd/><Token v="]$" punct/> <Token v="ls" funct/> log <Token v="|" punct/> <Token v="each" funct/> <Token v="{" punct/><Token v="|" punct/>file<Token v="|" punct/> <Token v="render" funct/> <Token v="(" punct/><Token v="open" funct/> $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 [noteId, note], index}
|
{#each data.notes as [noteId, note], index}
|
||||||
{@const isHighlighted = noteId === data.highlightedNote}
|
{@const isHighlighted = noteId === data.highlightedNote}
|
||||||
<div class="text-wrap break-words max-w-[70ch] leading-none">
|
<div class="text-wrap break-words max-w-[70ch] leading-none">
|
||||||
<Token v={renderDate(note.published)} small={!isHighlighted}/> <Token v={noteId} keywd small={!isHighlighted}/><Token v="#" punct/> <Token v={note.content} str/>
|
<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>
|
||||||
|
{/each}
|
||||||
</div>
|
</div>
|
||||||
{#if index < data.notes.size - 1}
|
{#if index < data.notes.size - 1}
|
||||||
<div class="mt-3"/>
|
<div class="mt-3"/>
|
||||||
|
@ -1,9 +1,7 @@
|
|||||||
import { env } from '$env/dynamic/private';
|
import { env } from '$env/dynamic/private';
|
||||||
import { PUBLIC_BASE_URL } from '$env/static/public';
|
import { PUBLIC_BASE_URL } from '$env/static/public';
|
||||||
import { getBskyClient } from '$lib/bluesky.ts';
|
import { postToBsky } from '$lib/bluesky';
|
||||||
import { createNote } from '$lib/notes.js';
|
import { createNote, genNoteId, type Note } from '$lib/notes';
|
||||||
import { RichText } from '@atproto/api';
|
|
||||||
import { get } from 'svelte/store';
|
|
||||||
|
|
||||||
interface NoteData {
|
interface NoteData {
|
||||||
content: string,
|
content: string,
|
||||||
@ -15,26 +13,33 @@ export const POST = async ({ request }) => {
|
|||||||
if (token !== env.GAZEBOT_TOKEN) {
|
if (token !== env.GAZEBOT_TOKEN) {
|
||||||
return new Response("rizz failed", { status: 403 })
|
return new Response("rizz failed", { status: 403 })
|
||||||
}
|
}
|
||||||
|
// get id
|
||||||
|
const noteId = genNoteId()
|
||||||
// get note data
|
// get note data
|
||||||
const noteData: NoteData = await request.json()
|
const noteData: NoteData = await request.json()
|
||||||
console.log("want to create note with data: ", noteData)
|
console.log(`want to create note #${noteId} with data: `, noteData)
|
||||||
// create note
|
// get a date before we start publishing to other platforms
|
||||||
const published = Date.now()
|
let note: Note = {
|
||||||
const noteId = createNote({ content: noteData.content, published })
|
content: noteData.content,
|
||||||
|
published: Date.now(),
|
||||||
|
outgoingLinks: [],
|
||||||
|
}
|
||||||
|
let errors: string[] = []
|
||||||
// bridge to bsky if want to bridge
|
// bridge to bsky if want to bridge
|
||||||
if (noteData.bskyPosse) {
|
if (noteData.bskyPosse) {
|
||||||
let client = await getBskyClient()
|
const postContent = `${noteData.content} (${PUBLIC_BASE_URL}/log?id=${noteId})`
|
||||||
const rt = new RichText({
|
try {
|
||||||
text: `${noteData.content} (${PUBLIC_BASE_URL}/log?id=${noteId})`,
|
const bskyUrl = await postToBsky(postContent)
|
||||||
})
|
note.outgoingLinks?.push({name: "bsky", link: bskyUrl})
|
||||||
await rt.detectFacets(client)
|
} catch(why) {
|
||||||
await client.post({
|
console.log(`failed to post note #${noteId} to bsky: `, why)
|
||||||
text: rt.text,
|
errors.push(`error while posting to bsky: ${why}`)
|
||||||
facets: rt.facets,
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
// send back created note id
|
}
|
||||||
return new Response(JSON.stringify({ noteId }), {
|
// 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: {
|
headers: {
|
||||||
'content-type': 'application/json',
|
'content-type': 'application/json',
|
||||||
'cache-control': 'no-store',
|
'cache-control': 'no-store',
|
||||||
|
Loading…
Reference in New Issue
Block a user