From 8c9ce842d54e3637014740c3890309ac60cd1279 Mon Sep 17 00:00:00 2001 From: Florian <45694132+flo-bit@users.noreply.github.com> Date: Thu, 9 Apr 2026 00:38:35 +0200 Subject: [PATCH] remove /events and /rsvp --- .../[[actor=actor]]/events/+layout.server.ts | 28 - .../[[actor=actor]]/events/+layout.svelte | 9 - .../[[actor=actor]]/events/+page.server.ts | 71 - .../[[actor=actor]]/events/+page.svelte | 202 --- .../events/[rkey]/+page.server.ts | 60 - .../events/[rkey]/+page.svelte | 490 ------- .../events/[rkey]/EventAttendees.svelte | 205 --- .../events/[rkey]/EventRsvp.svelte | 245 ---- .../events/[rkey]/api.remote.ts | 75 - .../events/[rkey]/edit/+page.server.ts | 65 - .../events/[rkey]/edit/+page.svelte | 1259 ----------------- .../events/[rkey]/og.png/+server.ts | 66 - .../events/[rkey]/og.png/EventOgImage.svelte | 62 - .../events/api/refresh/+server.ts | 47 - .../events/calendar/+server.ts | 97 -- .../[[actor=actor]]/rsvp/+layout.server.ts | 28 - .../[[actor=actor]]/rsvp/+layout.svelte | 9 - .../[[actor=actor]]/rsvp/+page.server.ts | 48 - src/routes/[[actor=actor]]/rsvp/+page.svelte | 191 --- .../rsvp/api/refresh/+server.ts | 37 - .../[[actor=actor]]/rsvp/calendar/+server.ts | 106 -- 21 files changed, 3400 deletions(-) delete mode 100644 src/routes/[[actor=actor]]/events/+layout.server.ts delete mode 100644 src/routes/[[actor=actor]]/events/+layout.svelte delete mode 100644 src/routes/[[actor=actor]]/events/+page.server.ts delete mode 100644 src/routes/[[actor=actor]]/events/+page.svelte delete mode 100644 src/routes/[[actor=actor]]/events/[rkey]/+page.server.ts delete mode 100644 src/routes/[[actor=actor]]/events/[rkey]/+page.svelte delete mode 100644 src/routes/[[actor=actor]]/events/[rkey]/EventAttendees.svelte delete mode 100644 src/routes/[[actor=actor]]/events/[rkey]/EventRsvp.svelte delete mode 100644 src/routes/[[actor=actor]]/events/[rkey]/api.remote.ts delete mode 100644 src/routes/[[actor=actor]]/events/[rkey]/edit/+page.server.ts delete mode 100644 src/routes/[[actor=actor]]/events/[rkey]/edit/+page.svelte delete mode 100644 src/routes/[[actor=actor]]/events/[rkey]/og.png/+server.ts delete mode 100644 src/routes/[[actor=actor]]/events/[rkey]/og.png/EventOgImage.svelte delete mode 100644 src/routes/[[actor=actor]]/events/api/refresh/+server.ts delete mode 100644 src/routes/[[actor=actor]]/events/calendar/+server.ts delete mode 100644 src/routes/[[actor=actor]]/rsvp/+layout.server.ts delete mode 100644 src/routes/[[actor=actor]]/rsvp/+layout.svelte delete mode 100644 src/routes/[[actor=actor]]/rsvp/+page.server.ts delete mode 100644 src/routes/[[actor=actor]]/rsvp/+page.svelte delete mode 100644 src/routes/[[actor=actor]]/rsvp/api/refresh/+server.ts delete mode 100644 src/routes/[[actor=actor]]/rsvp/calendar/+server.ts diff --git a/src/routes/[[actor=actor]]/events/+layout.server.ts b/src/routes/[[actor=actor]]/events/+layout.server.ts deleted file mode 100644 index 5a88b2b..0000000 --- a/src/routes/[[actor=actor]]/events/+layout.server.ts +++ /dev/null @@ -1,28 +0,0 @@ -import { getRecord } from '$lib/atproto/methods.js'; -import type { Did } from '@atcute/lexicons'; -import { getActor } from '$lib/actor.js'; - -export async function load({ params, platform, request }) { - const did = await getActor({ request, paramActor: params.actor, platform }); - - if (!did) return { accentColor: undefined, baseColor: undefined }; - - try { - const publication = await getRecord({ - did: did as Did, - collection: 'site.standard.publication', - rkey: 'blento.self' - }); - - const preferences = publication?.value?.preferences as - | { accentColor?: string; baseColor?: string } - | undefined; - - return { - accentColor: preferences?.accentColor, - baseColor: preferences?.baseColor - }; - } catch { - return { accentColor: undefined, baseColor: undefined }; - } -} diff --git a/src/routes/[[actor=actor]]/events/+layout.svelte b/src/routes/[[actor=actor]]/events/+layout.svelte deleted file mode 100644 index ea1c6fc..0000000 --- a/src/routes/[[actor=actor]]/events/+layout.svelte +++ /dev/null @@ -1,9 +0,0 @@ - - - - -{@render children()} diff --git a/src/routes/[[actor=actor]]/events/+page.server.ts b/src/routes/[[actor=actor]]/events/+page.server.ts deleted file mode 100644 index 9475139..0000000 --- a/src/routes/[[actor=actor]]/events/+page.server.ts +++ /dev/null @@ -1,71 +0,0 @@ -import { error } from '@sveltejs/kit'; -import type { EventData } from '$lib/cards/social/EventCard'; -import { getBlentoOrBskyProfile, listRecords } from '$lib/atproto/methods.js'; -import { createCache, type CachedProfile } from '$lib/cache'; -import type { Did } from '@atcute/lexicons'; -import { getActor } from '$lib/actor.js'; - -export async function load({ params, platform, request }) { - const cache = createCache(platform); - - const did = await getActor({ request, paramActor: params.actor, platform }); - - if (!did) { - throw error(404, 'Events not found'); - } - - try { - // Try cache first - if (cache) { - const cached = await cache.getJSON<{ - events: (EventData & { rkey: string })[]; - did: string; - hostProfile: CachedProfile | null; - }>('events', did); - if (cached) return cached; - } - - const [records, hostProfile] = await Promise.all([ - listRecords({ - did: did as Did, - collection: 'community.lexicon.calendar.event', - limit: 100 - }), - cache - ? cache.getProfile(did as Did).catch(() => null) - : getBlentoOrBskyProfile({ did: did as Did }) - .then( - (p): CachedProfile => ({ - did: p.did as string, - handle: p.handle as string, - displayName: p.displayName as string | undefined, - avatar: p.avatar as string | undefined, - hasBlento: p.hasBlento, - url: p.url - }) - ) - .catch(() => null) - ]); - - const events = records.map((r) => ({ - ...(r.value as EventData), - rkey: r.uri.split('/').pop() as string - })); - - const result = { - events, - did, - hostProfile: hostProfile ?? null - }; - - // Cache the result - if (cache) { - await cache.putJSON('events', did, result).catch(() => {}); - } - - return result; - } catch (e) { - if (e && typeof e === 'object' && 'status' in e) throw e; - throw error(404, 'Events not found'); - } -} diff --git a/src/routes/[[actor=actor]]/events/+page.svelte b/src/routes/[[actor=actor]]/events/+page.svelte deleted file mode 100644 index 3900789..0000000 --- a/src/routes/[[actor=actor]]/events/+page.svelte +++ /dev/null @@ -1,202 +0,0 @@ - - - - {hostName} - Events - - - - - - - - -
-
- -
-
-

- {showPast ? 'Past' : 'Upcoming'} events -

-
- Hosted by - - - {hostName} - -
-
-
- - -
- - -
- - {#if filteredEvents.length === 0} -

- No {showPast ? 'past' : 'upcoming'} events. -

- {:else} -
- {#each filteredEvents as event (event.rkey)} - {@const thumbnail = getThumbnail(event)} - {@const location = getLocationString(event.locations)} - {@const rkey = event.rkey} - - -
- {#if thumbnail} - {thumbnail.alt} - {:else} -
- -
- {/if} -
- - -
-

- {event.name} -

- -

- {formatDate(event.startsAt)} · {formatTime(event.startsAt)} -

- -
- {#if event.mode} - {getModeLabel(event.mode)} - {/if} - - {#if location} - {location} - {/if} -
-
-
- {/each} -
- {/if} -
-
diff --git a/src/routes/[[actor=actor]]/events/[rkey]/+page.server.ts b/src/routes/[[actor=actor]]/events/[rkey]/+page.server.ts deleted file mode 100644 index c99bb06..0000000 --- a/src/routes/[[actor=actor]]/events/[rkey]/+page.server.ts +++ /dev/null @@ -1,60 +0,0 @@ -import { error } from '@sveltejs/kit'; -import type { EventData } from '$lib/cards/social/EventCard'; -import { getBlentoOrBskyProfile, getRecord } from '$lib/atproto/methods.js'; -import { createCache, type CachedProfile } from '$lib/cache'; -import type { Did } from '@atcute/lexicons'; -import { getActor } from '$lib/actor'; - -export async function load({ params, platform, request }) { - const { rkey } = params; - - const cache = createCache(platform); - - const did = await getActor({ request, paramActor: params.actor, platform }); - - if (!did || !rkey) { - throw error(404, 'Event not found'); - } - - try { - const [eventRecord, hostProfile] = await Promise.all([ - getRecord({ - did: did as Did, - collection: 'community.lexicon.calendar.event', - rkey - }), - cache - ? cache.getProfile(did as Did).catch(() => null) - : getBlentoOrBskyProfile({ did: did as Did }) - .then( - (p): CachedProfile => ({ - did: p.did as string, - handle: p.handle as string, - displayName: p.displayName as string | undefined, - avatar: p.avatar as string | undefined, - hasBlento: p.hasBlento, - url: p.url - }) - ) - .catch(() => null) - ]); - - if (!eventRecord?.value) { - throw error(404, 'Event not found'); - } - - const eventData: EventData = eventRecord.value as EventData; - console.log(eventData); - - return { - eventData, - did, - rkey, - hostProfile: hostProfile ?? null, - eventCid: (eventRecord.cid as string) ?? null - }; - } catch (e) { - if (e && typeof e === 'object' && 'status' in e) throw e; - throw error(404, 'Event not found'); - } -} diff --git a/src/routes/[[actor=actor]]/events/[rkey]/+page.svelte b/src/routes/[[actor=actor]]/events/[rkey]/+page.svelte deleted file mode 100644 index faaf429..0000000 --- a/src/routes/[[actor=actor]]/events/[rkey]/+page.svelte +++ /dev/null @@ -1,490 +0,0 @@ - - - - {eventData.name} - - - - - - - - - - -
-
- - {#if isBannerOnly && displayImage} - {displayImage.alt} - {/if} - - -
- - {#if !isBannerOnly} -
- {#if displayImage} - {displayImage.alt} - {:else} -
- -
- {/if} -
- {/if} - - -
-
-

- {eventData.name} -

- {#if isOwner} - - {/if} -
- - - {#if eventData.mode} -
- {getModeLabel(eventData.mode)} -
- {/if} - - -
-
- - {formatMonth(startDate)} - - - {formatDay(startDate)} - -
-
-

- {formatWeekday(startDate)}, {formatFullDate(startDate)} - {#if endDate && !isSameDay} - - {formatWeekday(endDate)}, {formatFullDate(endDate)} - {/if} -

-

- {formatTime(startDate)} - {#if endDate && isSameDay} - - {formatTime(endDate)} - {/if} -

-
-
- - - {#if location} -
-
- - - - -
-

{location}

-
- {/if} - - - - - {#if descriptionHtml} -
-

- About -

-
- {@html descriptionHtml} -
-
- {/if} -
- - -
- - - - {#if eventData.uris && eventData.uris.length > 0} - -
-

- Links -

-
- {#each eventData.uris as link (link.name + link.uri)} - - - - - {link.name || link.uri.replace(/^https?:\/\//, '')} - - {/each} -
-
- {/if} - - - - - - -
- - - -
-
-
diff --git a/src/routes/[[actor=actor]]/events/[rkey]/EventAttendees.svelte b/src/routes/[[actor=actor]]/events/[rkey]/EventAttendees.svelte deleted file mode 100644 index dfd090d..0000000 --- a/src/routes/[[actor=actor]]/events/[rkey]/EventAttendees.svelte +++ /dev/null @@ -1,205 +0,0 @@ - - -{#if loading} -
-
-
-{:else if totalCount > 0} -
- {#if goingCount > 0} - - {/if} - - {#if interestedCount > 0} - - {/if} -
-{/if} - - e.preventDefault()} - class="p-0" -> -

- {modalTitle} - - ({modalAttendees.length}) - -

-
- {#each modalAttendees as person (person.did)} - - -
-

- {person.name} -

- {#if person.handle} -

- @{person.handle} -

- {/if} -
-
- {/each} -
-
diff --git a/src/routes/[[actor=actor]]/events/[rkey]/EventRsvp.svelte b/src/routes/[[actor=actor]]/events/[rkey]/EventRsvp.svelte deleted file mode 100644 index 09ba553..0000000 --- a/src/routes/[[actor=actor]]/events/[rkey]/EventRsvp.svelte +++ /dev/null @@ -1,245 +0,0 @@ - - -
- {#if user.isInitializing || rsvpLoading} -
-
-
-
- {:else if !user.isLoggedIn} -
-

Log in to RSVP to this event

- - -
- {:else if rsvpStatus === 'going'} -
-
-
- - - -
-

You're Going

-
- -
- {:else if rsvpStatus === 'interested'} -
-
-
- - - -
-

You're Interested

-
- -
- {:else if rsvpStatus === 'notgoing'} -
-
-
- - - -
-

Not Going

-
- -
- {:else} - {#if user.profile} -
- RSVPing as - - - {user.profile.displayName || user.profile.handle} - -
- {/if} -
- - -
- {/if} -
diff --git a/src/routes/[[actor=actor]]/events/[rkey]/api.remote.ts b/src/routes/[[actor=actor]]/events/[rkey]/api.remote.ts deleted file mode 100644 index fbc5df1..0000000 --- a/src/routes/[[actor=actor]]/events/[rkey]/api.remote.ts +++ /dev/null @@ -1,75 +0,0 @@ -import { query, getRequestEvent } from '$app/server'; -import { createCache } from '$lib/cache'; -import { fetchEventRsvps, resolveProfile } from '$lib/events/fetch-attendees'; - -export type AttendeeInfo = { - did: string; - status: 'going' | 'interested'; - avatar?: string; - name: string; - handle?: string; - url?: string; -}; - -export type EventAttendeesResult = { - going: AttendeeInfo[]; - interested: AttendeeInfo[]; - goingCount: number; - interestedCount: number; -}; - -export const fetchEventAttendees = query( - 'unchecked', - async (eventUri: string): Promise => { - const rsvpMap = await fetchEventRsvps(eventUri); - - const going: string[] = []; - const interested: string[] = []; - for (const [did, status] of rsvpMap) { - if (status === 'going') going.push(did); - else interested.push(did); - } - - // Fetch profiles for attendees (with caching) - const uniqueDids = [...new Set([...going, ...interested])]; - const { platform } = getRequestEvent(); - const cache = createCache(platform); - - const profileMap = new Map< - string, - { handle?: string; displayName?: string; avatar?: string; hasBlento?: boolean; url?: string } - >(); - - await Promise.all( - uniqueDids.map(async (did) => { - const profile = await resolveProfile(did, cache).catch(() => null); - if (profile) profileMap.set(did, profile); - }) - ); - - function toAttendeeInfo(did: string, status: 'going' | 'interested'): AttendeeInfo { - const profile = profileMap.get(did); - const handle = profile?.handle; - const url = profile?.hasBlento - ? profile.url || (handle ? `/${handle}` : undefined) - : handle - ? `https://bsky.app/profile/${handle}` - : `https://bsky.app/profile/${did}`; - return { - did, - status, - avatar: profile?.avatar, - name: profile?.displayName || handle || did, - handle, - url - }; - } - - return { - going: going.map((did) => toAttendeeInfo(did, 'going')), - interested: interested.map((did) => toAttendeeInfo(did, 'interested')), - goingCount: going.length, - interestedCount: interested.length - }; - } -); diff --git a/src/routes/[[actor=actor]]/events/[rkey]/edit/+page.server.ts b/src/routes/[[actor=actor]]/events/[rkey]/edit/+page.server.ts deleted file mode 100644 index 8334407..0000000 --- a/src/routes/[[actor=actor]]/events/[rkey]/edit/+page.server.ts +++ /dev/null @@ -1,65 +0,0 @@ -import { error } from '@sveltejs/kit'; -import type { EventData } from '$lib/cards/social/EventCard'; -import { getBlentoOrBskyProfile, getRecord } from '$lib/atproto/methods.js'; -import { createCache, type CachedProfile } from '$lib/cache'; -import type { Did } from '@atcute/lexicons'; -import { getActor } from '$lib/actor'; - -export async function load({ params, platform, request }) { - const { rkey } = params; - - const cache = createCache(platform); - - const did = await getActor({ request, paramActor: params.actor, platform }); - - if (!did || !rkey) { - throw error(404, 'Event not found'); - } - - try { - const [eventRecord, hostProfile] = await Promise.all([ - getRecord({ - did: did as Did, - collection: 'community.lexicon.calendar.event', - rkey - }).catch(() => null), - cache - ? cache.getProfile(did as Did).catch(() => null) - : getBlentoOrBskyProfile({ did: did as Did }) - .then( - (p): CachedProfile => ({ - did: p.did as string, - handle: p.handle as string, - displayName: p.displayName as string | undefined, - avatar: p.avatar as string | undefined, - hasBlento: p.hasBlento, - url: p.url - }) - ) - .catch(() => null) - ]); - - if (!eventRecord?.value) { - return { - eventData: null, - did, - rkey, - hostProfile: hostProfile ?? null, - eventCid: null - }; - } - - const eventData: EventData = eventRecord.value as EventData; - - return { - eventData, - did, - rkey, - hostProfile: hostProfile ?? null, - eventCid: (eventRecord.cid as string) ?? null - }; - } catch (e) { - if (e && typeof e === 'object' && 'status' in e) throw e; - throw error(404, 'Event not found'); - } -} diff --git a/src/routes/[[actor=actor]]/events/[rkey]/edit/+page.svelte b/src/routes/[[actor=actor]]/events/[rkey]/edit/+page.svelte deleted file mode 100644 index 9213731..0000000 --- a/src/routes/[[actor=actor]]/events/[rkey]/edit/+page.svelte +++ /dev/null @@ -1,1259 +0,0 @@ - - - - {isNew ? 'Create Event' : 'Edit Event'} - - -
-
- {#if user.isInitializing} -
-
-
-
- {:else if !user.isLoggedIn} -
-

- Log in to {isNew ? 'create an event' : 'edit this event'}. -

- -
- {:else} -
{ - e.preventDefault(); - handleSubmit(); - }} - > - -
- - -
- -
- {#if thumbnailPreview} - Thumbnail preview - {:else} -
- -
- {/if} - - - {#if thumbnailPreview} - - {/if} -
-
- - -
- -
- - -
- - -
- { - return mode; - }, - (val) => { - if (val) mode = val; - } - } - class="w-fit" - > - In Person - Virtual - Hybrid - -
- - -
-
- {#if startDate} - - {formatMonth(startDate)} - - - {formatDay(startDate)} - - {:else} - - - - {/if} -
-
- {#if startDate && !editingDates} - -
- - -
- {:else} - -
-
- {#if endsAt} - Start - {/if} - -
- {#if endsAt} -
- End - - -
- {:else} - - {/if} - {#if startDate} - - {/if} -
- {/if} -
-
- - - {#if location} -
-
- - - - -
-

- {getLocationDisplayString(location)} -

- -
- {:else} -
- -
- {/if} - - -
-

- About -

- -
- - {#if error} -

{error}

- {/if} - - -
- - -
-

- Hosted By -

-
- - - {hostName} - -
-
- - -
-

- Links -

-
- {#each links as link, i (i)} -
- - - - - {link.name || link.uri.replace(/^https?:\/\//, '')} - - -
- {/each} -
- -
- - - - - - { - if (e.key === 'Enter') { - e.preventDefault(); - addLink(); - } - }} - /> - { - if (e.key === 'Enter') { - e.preventDefault(); - addLink(); - } - }} - /> - {#if linkError} -

{linkError}

- {/if} -
- - -
-
-
-
-
-
- - {#if !isNew} -
- {#if showDeleteConfirm} -
-

- Are you sure? This cannot be undone. -

- - -
- {:else} - - {/if} -
- {/if} -
- {/if} -
-
- - - -

Add location

-
{ - e.preventDefault(); - searchLocation(); - }} - class="mt-2" - > -
- - -
-
- - {#if locationError} -

{locationError}

- {/if} - - {#if locationResult} -
-
- - - - -
-

- {getLocationDisplayString(locationResult.location)} -

-

- {locationResult.displayName} -

-
-
-
- -
-
- {/if} - -

- Geocoding by Nominatim - / © - OpenStreetMap contributors -

-
diff --git a/src/routes/[[actor=actor]]/events/[rkey]/og.png/+server.ts b/src/routes/[[actor=actor]]/events/[rkey]/og.png/+server.ts deleted file mode 100644 index 1a7e0d8..0000000 --- a/src/routes/[[actor=actor]]/events/[rkey]/og.png/+server.ts +++ /dev/null @@ -1,66 +0,0 @@ -import { getCDNImageBlobUrl, getRecord } from '$lib/atproto/methods.js'; - -import type { Did } from '@atcute/lexicons'; -import type { EventData } from '$lib/cards/social/EventCard'; -import { ImageResponse } from '@ethercorps/sveltekit-og'; -import { error } from '@sveltejs/kit'; -import EventOgImage from './EventOgImage.svelte'; -import { getActor } from '$lib/actor'; - -function formatDate(dateStr: string): string { - const date = new Date(dateStr); - const weekday = date.toLocaleDateString('en-US', { weekday: 'long' }); - const month = date.toLocaleDateString('en-US', { month: 'long' }); - const day = date.getDate(); - return `${weekday}, ${month} ${day}`; -} - -export async function GET({ params, platform, request }) { - const { rkey } = params; - - const did = await getActor({ request, paramActor: params.actor, platform }); - - if (!did || !rkey) { - throw error(404, 'Event not found'); - } - - let eventData: EventData; - - try { - const eventRecord = await getRecord({ - did: did as Did, - collection: 'community.lexicon.calendar.event', - rkey - }); - - if (!eventRecord?.value) { - throw error(404, 'Event not found'); - } - - eventData = eventRecord.value as EventData; - } catch (e) { - if (e && typeof e === 'object' && 'status' in e) throw e; - throw error(404, 'Event not found'); - } - - const dateStr = formatDate(eventData.startsAt); - - let thumbnailUrl: string | null = null; - if (eventData.media && eventData.media.length > 0) { - const media = eventData.media.find((m) => m.role === 'thumbnail'); - if (media?.content) { - thumbnailUrl = getCDNImageBlobUrl({ did, blob: media.content, type: 'jpeg' }) ?? null; - } - } - - return new ImageResponse( - EventOgImage, - { width: 1200, height: 630, debug: false }, - { - name: eventData.name, - dateStr, - thumbnailUrl, - rkey - } - ); -} diff --git a/src/routes/[[actor=actor]]/events/[rkey]/og.png/EventOgImage.svelte b/src/routes/[[actor=actor]]/events/[rkey]/og.png/EventOgImage.svelte deleted file mode 100644 index fa498fb..0000000 --- a/src/routes/[[actor=actor]]/events/[rkey]/og.png/EventOgImage.svelte +++ /dev/null @@ -1,62 +0,0 @@ - - -
-
-
- {#if thumbnailUrl} - {name} - {:else} - - {/if} -
-
- -
-

- {name} -

- -
- - - - {dateStr} -
-
-
diff --git a/src/routes/[[actor=actor]]/events/api/refresh/+server.ts b/src/routes/[[actor=actor]]/events/api/refresh/+server.ts deleted file mode 100644 index d571444..0000000 --- a/src/routes/[[actor=actor]]/events/api/refresh/+server.ts +++ /dev/null @@ -1,47 +0,0 @@ -import { createCache } from '$lib/cache'; -import { error, json } from '@sveltejs/kit'; -import { getActor } from '$lib/actor'; -import { listRecords } from '$lib/atproto/methods.js'; -import type { EventData } from '$lib/cards/social/EventCard'; -import type { Did } from '@atcute/lexicons'; - -export async function GET({ params, platform, request }) { - const cache = createCache(platform); - if (!cache) return json('no cache'); - - const did = await getActor({ request, paramActor: params.actor, platform, blockBoth: false }); - - if (!did) { - throw error(404, 'Not found'); - } - - // Delete stale caches - await Promise.all([cache.delete('events', did), cache.delete('ical', `${did}:calendar`)]).catch( - () => {} - ); - - // Re-fetch and cache - const [records, hostProfile] = await Promise.all([ - listRecords({ - did: did as Did, - collection: 'community.lexicon.calendar.event', - limit: 100 - }), - cache.getProfile(did as Did).catch(() => null) - ]); - - const events = records.map((r) => ({ - ...(r.value as EventData), - rkey: r.uri.split('/').pop() as string - })); - - const result = { - events, - did, - hostProfile: hostProfile ?? null - }; - - await cache.putJSON('events', did, result).catch(() => {}); - - return json(result); -} diff --git a/src/routes/[[actor=actor]]/events/calendar/+server.ts b/src/routes/[[actor=actor]]/events/calendar/+server.ts deleted file mode 100644 index 75d732a..0000000 --- a/src/routes/[[actor=actor]]/events/calendar/+server.ts +++ /dev/null @@ -1,97 +0,0 @@ -import { error } from '@sveltejs/kit'; -import type { EventData } from '$lib/cards/social/EventCard'; -import { getCDNImageBlobUrl, listRecords } from '$lib/atproto/methods.js'; -import { createCache } from '$lib/cache'; -import type { Did } from '@atcute/lexicons'; -import { getActor } from '$lib/actor'; -import { generateICalFeed, type ICalAttendee, type ICalEvent } from '$lib/ical'; -import { fetchEventRsvps, getProfileUrl, resolveProfile } from '$lib/events/fetch-attendees'; - -export async function GET({ params, platform, request }) { - const cache = createCache(platform); - - const did = await getActor({ request, paramActor: params.actor, platform }); - - if (!did) { - throw error(404, 'Not found'); - } - - try { - // Check cache first - const cacheKey = `${did}:calendar`; - if (cache) { - const cached = await cache.get('ical', cacheKey); - if (cached) { - return new Response(cached, { - headers: { - 'Content-Type': 'text/calendar; charset=utf-8', - 'Cache-Control': 'public, max-age=3600' - } - }); - } - } - - const [records, hostProfile] = await Promise.all([ - listRecords({ - did: did as Did, - collection: 'community.lexicon.calendar.event', - limit: 100 - }), - resolveProfile(did, cache) - ]); - - const actor = hostProfile?.handle || did; - - // Fetch attendees for all events in parallel - const events: ICalEvent[] = await Promise.all( - records.map(async (r) => { - const eventData = r.value as EventData; - const thumbnail = eventData.media?.find((m) => m.role === 'thumbnail'); - const imageUrl = thumbnail?.content - ? getCDNImageBlobUrl({ did, blob: thumbnail.content, type: 'jpeg' }) - : undefined; - - // Fetch RSVPs and resolve handles - const rsvpMap = await fetchEventRsvps(r.uri).catch(() => new Map()); - const attendees: ICalAttendee[] = []; - await Promise.all( - Array.from(rsvpMap.entries()).map(async ([attendeeDid, status]) => { - const profile = await resolveProfile(attendeeDid, cache).catch(() => null); - attendees.push({ - name: profile?.handle || attendeeDid, - status, - url: getProfileUrl(attendeeDid, profile) - }); - }) - ); - - return { - eventData, - uid: r.uri, - url: `https://blento.app/${actor}/events/${r.uri.split('/').pop()}`, - organizer: actor, - imageUrl, - attendees - }; - }) - ); - - const calendarName = `${hostProfile?.displayName || actor}'s Events`; - const ical = generateICalFeed(events, calendarName); - - // Store in cache - if (cache) { - await cache.put('ical', cacheKey, ical).catch(() => {}); - } - - return new Response(ical, { - headers: { - 'Content-Type': 'text/calendar; charset=utf-8', - 'Cache-Control': 'public, max-age=3600' - } - }); - } catch (e) { - if (e && typeof e === 'object' && 'status' in e) throw e; - throw error(500, 'Failed to generate calendar'); - } -} diff --git a/src/routes/[[actor=actor]]/rsvp/+layout.server.ts b/src/routes/[[actor=actor]]/rsvp/+layout.server.ts deleted file mode 100644 index 5a88b2b..0000000 --- a/src/routes/[[actor=actor]]/rsvp/+layout.server.ts +++ /dev/null @@ -1,28 +0,0 @@ -import { getRecord } from '$lib/atproto/methods.js'; -import type { Did } from '@atcute/lexicons'; -import { getActor } from '$lib/actor.js'; - -export async function load({ params, platform, request }) { - const did = await getActor({ request, paramActor: params.actor, platform }); - - if (!did) return { accentColor: undefined, baseColor: undefined }; - - try { - const publication = await getRecord({ - did: did as Did, - collection: 'site.standard.publication', - rkey: 'blento.self' - }); - - const preferences = publication?.value?.preferences as - | { accentColor?: string; baseColor?: string } - | undefined; - - return { - accentColor: preferences?.accentColor, - baseColor: preferences?.baseColor - }; - } catch { - return { accentColor: undefined, baseColor: undefined }; - } -} diff --git a/src/routes/[[actor=actor]]/rsvp/+layout.svelte b/src/routes/[[actor=actor]]/rsvp/+layout.svelte deleted file mode 100644 index ea1c6fc..0000000 --- a/src/routes/[[actor=actor]]/rsvp/+layout.svelte +++ /dev/null @@ -1,9 +0,0 @@ - - - - -{@render children()} diff --git a/src/routes/[[actor=actor]]/rsvp/+page.server.ts b/src/routes/[[actor=actor]]/rsvp/+page.server.ts deleted file mode 100644 index 9dc0160..0000000 --- a/src/routes/[[actor=actor]]/rsvp/+page.server.ts +++ /dev/null @@ -1,48 +0,0 @@ -import { error } from '@sveltejs/kit'; -import { createCache } from '$lib/cache'; -import type { CachedProfile } from '$lib/cache'; -import { getActor } from '$lib/actor.js'; -import { fetchUserRsvps, resolveProfile, type ResolvedRsvp } from '$lib/events/fetch-attendees'; - -export async function load({ params, platform, request }) { - const cache = createCache(platform); - - const did = await getActor({ request, paramActor: params.actor, platform }); - - if (!did) { - throw error(404, 'RSVPs not found'); - } - - try { - // Try cache first - if (cache) { - const cached = await cache.getJSON<{ - rsvps: ResolvedRsvp[]; - did: string; - userProfile: CachedProfile | null; - }>('rsvps', did); - if (cached) return cached; - } - - const [rsvps, userProfile] = await Promise.all([ - fetchUserRsvps(did, cache), - resolveProfile(did, cache) - ]); - - const result = { - rsvps, - did, - userProfile: userProfile ?? null - }; - - // Cache the result - if (cache) { - await cache.putJSON('rsvps', did, result).catch(() => {}); - } - - return result; - } catch (e) { - if (e && typeof e === 'object' && 'status' in e) throw e; - throw error(404, 'RSVPs not found'); - } -} diff --git a/src/routes/[[actor=actor]]/rsvp/+page.svelte b/src/routes/[[actor=actor]]/rsvp/+page.svelte deleted file mode 100644 index 3127550..0000000 --- a/src/routes/[[actor=actor]]/rsvp/+page.svelte +++ /dev/null @@ -1,191 +0,0 @@ - - - - {userName} - RSVPs - - - - - - - - -
-
- -
-
-

- {showPast ? 'Past' : 'Upcoming'} RSVPs -

-
- - {userName} -
-
-
- - -
- - -
- - {#if filteredRsvps.length === 0} -

- No {showPast ? 'past' : 'upcoming'} RSVPs. -

- {:else} -
- {#each filteredRsvps as rsvp (rsvp.eventUri)} - {@const thumbnail = getThumbnail(rsvp.event, rsvp.hostDid)} - {@const hostHandle = rsvp.hostProfile?.handle || rsvp.hostDid} - - -
- {#if thumbnail} - {thumbnail.alt} - {:else} -
- -
- {/if} -
- - -
-

- {rsvp.event.name} -

- -

- {formatDate(rsvp.event.startsAt)} · {formatTime(rsvp.event.startsAt)} -

- -
- {#if rsvp.event.mode} - {getModeLabel(rsvp.event.mode)} - {/if} - - {getStatusLabel(rsvp.status)} -
-
-
- {/each} -
- {/if} -
-
diff --git a/src/routes/[[actor=actor]]/rsvp/api/refresh/+server.ts b/src/routes/[[actor=actor]]/rsvp/api/refresh/+server.ts deleted file mode 100644 index b0d32b9..0000000 --- a/src/routes/[[actor=actor]]/rsvp/api/refresh/+server.ts +++ /dev/null @@ -1,37 +0,0 @@ -import { createCache } from '$lib/cache'; -import { error, json } from '@sveltejs/kit'; -import { getActor } from '$lib/actor'; -import { fetchUserRsvps, resolveProfile } from '$lib/events/fetch-attendees'; - -export async function GET({ params, platform, request }) { - const cache = createCache(platform); - if (!cache) return json('no cache'); - - const did = await getActor({ request, paramActor: params.actor, platform, blockBoth: false }); - - if (!did) { - throw error(404, 'Not found'); - } - - // Delete stale caches - await Promise.all([ - cache.delete('rsvps', did), - cache.delete('ical', `${did}:rsvp-calendar`) - ]).catch(() => {}); - - // Re-fetch and cache - const [rsvps, userProfile] = await Promise.all([ - fetchUserRsvps(did, cache), - resolveProfile(did, cache) - ]); - - const result = { - rsvps, - did, - userProfile: userProfile ?? null - }; - - await cache.putJSON('rsvps', did, result).catch(() => {}); - - return json(result); -} diff --git a/src/routes/[[actor=actor]]/rsvp/calendar/+server.ts b/src/routes/[[actor=actor]]/rsvp/calendar/+server.ts deleted file mode 100644 index c0f038e..0000000 --- a/src/routes/[[actor=actor]]/rsvp/calendar/+server.ts +++ /dev/null @@ -1,106 +0,0 @@ -import { error } from '@sveltejs/kit'; -import { getCDNImageBlobUrl } from '$lib/atproto/methods.js'; -import { createCache } from '$lib/cache'; -import { getActor } from '$lib/actor'; -import { generateICalFeed, type ICalAttendee, type ICalEvent } from '$lib/ical'; -import { - fetchEventRsvps, - fetchUserRsvps, - getProfileUrl, - resolveProfile -} from '$lib/events/fetch-attendees'; - -export async function GET({ params, platform, request }) { - const cache = createCache(platform); - - const did = await getActor({ request, paramActor: params.actor, platform }); - - if (!did) { - throw error(404, 'Not found'); - } - - try { - // Check cache first - const cacheKey = `${did}:rsvp-calendar`; - if (cache) { - const cached = await cache.get('ical', cacheKey); - if (cached) { - return new Response(cached, { - headers: { - 'Content-Type': 'text/calendar; charset=utf-8', - 'Cache-Control': 'public, max-age=3600' - } - }); - } - } - - const [rsvps, userProfile] = await Promise.all([ - fetchUserRsvps(did, cache), - resolveProfile(did, cache) - ]); - - // Enrich each RSVP with attendees and image URLs for the iCal feed - const events: ICalEvent[] = ( - await Promise.all( - rsvps.map(async (rsvp) => { - try { - const actor = rsvp.hostProfile?.handle || rsvp.hostDid; - const thumbnail = rsvp.event.media?.find((m) => m.role === 'thumbnail'); - const imageUrl = thumbnail?.content - ? getCDNImageBlobUrl({ - did: rsvp.hostDid, - blob: thumbnail.content, - type: 'jpeg' - }) - : undefined; - - const rsvpMap = await fetchEventRsvps(rsvp.eventUri).catch( - () => new Map() - ); - const attendees: ICalAttendee[] = []; - await Promise.all( - Array.from(rsvpMap.entries()).map(async ([attendeeDid, status]) => { - const profile = await resolveProfile(attendeeDid, cache).catch(() => null); - attendees.push({ - name: profile?.handle || attendeeDid, - status, - url: getProfileUrl(attendeeDid, profile) - }); - }) - ); - - return { - eventData: rsvp.event, - uid: rsvp.eventUri, - url: `https://blento.app/${actor}/events/${rsvp.rkey}`, - organizer: actor, - imageUrl, - attendees - } satisfies ICalEvent; - } catch { - return null; - } - }) - ) - ).filter((e) => e !== null); - - const actor = userProfile?.handle || did; - const calendarName = `${userProfile?.displayName || actor}'s RSVP Events`; - const ical = generateICalFeed(events, calendarName); - - // Store in cache - if (cache) { - await cache.put('ical', cacheKey, ical).catch(() => {}); - } - - return new Response(ical, { - headers: { - 'Content-Type': 'text/calendar; charset=utf-8', - 'Cache-Control': 'public, max-age=3600' - } - }); - } catch (e) { - if (e && typeof e === 'object' && 'status' in e) throw e; - throw error(500, 'Failed to generate calendar'); - } -} -- 2.51.2