diff --git a/modules/runtime/server/_social/bluesky.get.ts b/modules/runtime/server/_social/bluesky.get.ts
index c15bf3e2..0abe12cc 100644
--- a/modules/runtime/server/_social/bluesky.get.ts
+++ b/modules/runtime/server/_social/bluesky.get.ts
@@ -1,73 +1,70 @@
import { AppBskyEmbedImages, AppBskyFeedPost, AtpAgent } from '@atproto/api'
import MagicString from 'magic-string'
-export default defineLazyEventHandler(async () => {
- const { identifier, password } = useRuntimeConfig().social.networks.bluesky
+export default defineEventHandler(async event => {
const agent = new AtpAgent({ service: 'https://bsky.social' })
+ const { identifier, password } = useRuntimeConfig(event).social.networks.bluesky
await agent.login({
identifier,
password,
})
-
- return defineEventHandler(async () => {
- const posts = await agent.getAuthorFeed({ actor: identifier })
- return Promise.all(
- posts.data.feed
- .filter(p => AppBskyFeedPost.isRecord(p.post.record) && p.post.author.handle === identifier && !p.reply && (!p.post.embed || AppBskyEmbedImages.isMain(p.post.embed)))
- .map(p => {
- const post = p.post.record as AppBskyFeedPost.Record
- const embed = AppBskyEmbedImages.isMain(p.post.embed) ? p.post.embed : undefined
- const text = new MagicString(post.text)
- for (const facet of post.facets || []) {
- const startIndex = [...post.text].findIndex(
- (_, i) =>
- Buffer.byteLength(post.text.slice(0, i + 1))
- > facet.index.byteStart,
- )
- const endIndex = [...post.text].findIndex(
- (_, i) =>
- Buffer.byteLength(post.text.slice(0, i + 1))
- >= facet.index.byteEnd,
- )
- for (const feature of facet.features) {
- if (feature.$type === 'app.bsky.richtext.facet#link') {
- text.appendRight(startIndex, ``)
- text.appendLeft(endIndex === -1 ? post.text.length : endIndex + 1, '')
- continue
- }
+ const posts = await agent.getAuthorFeed({ actor: identifier })
+ return Promise.all(
+ posts.data.feed
+ .filter(p => AppBskyFeedPost.isRecord(p.post.record) && p.post.author.handle === identifier && !p.reply && (!p.post.embed || AppBskyEmbedImages.isMain(p.post.embed)))
+ .map(p => {
+ const post = p.post.record as AppBskyFeedPost.Record
+ const embed = AppBskyEmbedImages.isMain(p.post.embed) ? p.post.embed : undefined
+ const text = new MagicString(post.text)
+ for (const facet of post.facets || []) {
+ const startIndex = [...post.text].findIndex(
+ (_, i) =>
+ Buffer.byteLength(post.text.slice(0, i + 1))
+ > facet.index.byteStart,
+ )
+ const endIndex = [...post.text].findIndex(
+ (_, i) =>
+ Buffer.byteLength(post.text.slice(0, i + 1))
+ >= facet.index.byteEnd,
+ )
+ for (const feature of facet.features) {
+ if (feature.$type === 'app.bsky.richtext.facet#link') {
+ text.appendRight(startIndex, ``)
+ text.appendLeft(endIndex === -1 ? post.text.length : endIndex + 1, '')
+ continue
}
}
+ }
- text.replaceAll(/[<>&]/g, r => ({
- '<': '<',
- '>': '>',
- '&': '&',
- }[r]!))
+ text.replaceAll(/[<>&]/g, r => ({
+ '<': '<',
+ '>': '>',
+ '&': '&',
+ }[r]!))
- for (const match of post.text.matchAll(/\n\n/g)) {
- text.overwrite(match.index!, match.index! + 2, '
')
- }
+ for (const match of post.text.matchAll(/\n\n/g)) {
+ text.overwrite(match.index!, match.index! + 2, '
')
+ }
- text.prepend('
')
- text.append('
')
+ text.prepend('')
+ text.append('
')
- return {
- network: 'bluesky' as const,
- accountLink: `https://staging.bsky.app/profile/${p.post.author.handle}`,
- avatar: p.post.author.avatar,
- handle: p.post.author.displayName,
- createdAt: post.createdAt,
- permalink:
+ return {
+ network: 'bluesky' as const,
+ accountLink: `https://staging.bsky.app/profile/${p.post.author.handle}`,
+ avatar: p.post.author.avatar,
+ handle: p.post.author.displayName,
+ createdAt: post.createdAt,
+ permalink:
`https://staging.bsky.app/profile/${p.post.author.handle}/post`
+ p.post.uri.match(/(\/[^/]+)$/)?.[1],
- html: text.toString().replace(/\n/g, '
'),
- media: embed?.images?.map(i => ({
- url: i.fullsize,
- alt: i.alt,
- })),
- }
- }),
- )
- })
+ html: text.toString().replace(/\n/g, '
'),
+ media: embed?.images?.map(i => ({
+ url: i.fullsize,
+ alt: i.alt,
+ })),
+ }
+ }),
+ )
})
diff --git a/modules/runtime/server/_social/mastodon.get.ts b/modules/runtime/server/_social/mastodon.get.ts
index ebe9a5c7..cbe9736d 100644
--- a/modules/runtime/server/_social/mastodon.get.ts
+++ b/modules/runtime/server/_social/mastodon.get.ts
@@ -1,8 +1,8 @@
import { createRestAPIClient } from 'masto'
import { parseURL, withProtocol } from 'ufo'
-export default defineLazyEventHandler(async () => {
- const acct = useRuntimeConfig().social.networks.mastodon.identifier
+export default defineEventHandler(async event => {
+ const acct = useRuntimeConfig(event).social.networks.mastodon.identifier
const server = acct.split('@')[1]
if (!server) throw createError('Invalid Mastodon account identifier')
@@ -21,38 +21,35 @@ export default defineLazyEventHandler(async () => {
url: withProtocol(host!, protocol!),
})
const { id } = await client.v1.accounts.lookup({ acct })
-
- return defineEventHandler(async () => {
- const posts = await client.v1.accounts
- .$select(id)
- .statuses.list({ limit: 200 })
- return Promise.all(
- posts
- .filter(p => p.content && !p.inReplyToId)
- .map(p => ({
- network: 'mastodon' as const,
- accountLink: `https://elk.zone/${host}/@${p.account.acct}`,
- avatar: p.account.avatar,
- handle: p.account.displayName.replace(
- /:([a-z-]+):/g,
- (string, shortcode) => {
- const emoji = p.account.emojis.find(
- e => e.shortcode === shortcode,
- )
- if (!emoji) return string
- return `
`
- },
- ),
- createdAt: p.createdAt,
- permalink: p.url?.replace('https://', 'https://elk.zone/') ?? p.uri,
- media: p.mediaAttachments.map(m => ({
- url: m.url,
- width: m.meta?.original?.width,
- height: m.meta?.original?.height,
- alt: m.description,
- })),
- html: p.content,
+ const posts = await client.v1.accounts
+ .$select(id)
+ .statuses.list({ limit: 200 })
+ return Promise.all(
+ posts
+ .filter(p => p.content && !p.inReplyToId)
+ .map(p => ({
+ network: 'mastodon' as const,
+ accountLink: `https://elk.zone/${host}/@${p.account.acct}`,
+ avatar: p.account.avatar,
+ handle: p.account.displayName.replace(
+ /:([a-z-]+):/g,
+ (string, shortcode) => {
+ const emoji = p.account.emojis.find(
+ e => e.shortcode === shortcode,
+ )
+ if (!emoji) return string
+ return `
`
+ },
+ ),
+ createdAt: p.createdAt,
+ permalink: p.url?.replace('https://', 'https://elk.zone/') ?? p.uri,
+ media: p.mediaAttachments.map(m => ({
+ url: m.url,
+ width: m.meta?.original?.width,
+ height: m.meta?.original?.height,
+ alt: m.description,
})),
- )
- })
+ html: p.content,
+ })),
+ )
})
diff --git a/modules/runtime/server/auth/github/[slug].ts b/modules/runtime/server/auth/github/[slug].ts
index 5d6ef574..df7039a8 100644
--- a/modules/runtime/server/auth/github/[slug].ts
+++ b/modules/runtime/server/auth/github/[slug].ts
@@ -1,7 +1,7 @@
import type { RuntimeConfig } from 'nuxt/schema'
export default defineEventHandler(async event => {
- const config = useRuntimeConfig()
+ const config = useRuntimeConfig(event)
const slug = getRouterParam(event, 'slug')
const repo = slug && config.invites?.map?.[slug as keyof RuntimeConfig['invites']['map']]
if (!repo) {
diff --git a/server/api/feedback.post.ts b/server/api/feedback.post.ts
index 6ac62f4f..e5544bc9 100644
--- a/server/api/feedback.post.ts
+++ b/server/api/feedback.post.ts
@@ -1,5 +1,5 @@
export default defineEventHandler(async event => {
- const config = useRuntimeConfig()
+ const config = useRuntimeConfig(event)
const { feedback } = await readBody(event)
if (!feedback) {
throw createError({ statusCode: 400, statusMessage: 'Missing feedback' })
diff --git a/server/api/idea.post.ts b/server/api/idea.post.ts
index 1827c4a6..62f818b8 100644
--- a/server/api/idea.post.ts
+++ b/server/api/idea.post.ts
@@ -16,6 +16,7 @@ export default defineEventHandler(async event => {
}
const { idea } = await readBody(event)
await sendEmail(
+ event,
'Idea from website',
[`Idea from ${payload.name}:`, '', idea].join('\n'),
)
diff --git a/server/api/question.ts b/server/api/question.ts
index a8706f8d..9ab5bd6e 100644
--- a/server/api/question.ts
+++ b/server/api/question.ts
@@ -5,6 +5,6 @@ export default defineEventHandler(async event => {
const { question } = await readBody(event)
if (!question) throw createError({ statusCode: 422 })
event.waitUntil(createTypefullyDraft(event, question).catch(console.error))
- await sendEmail('Anonymous question', question)
+ await sendEmail(event, 'Anonymous question', question)
return null
})
diff --git a/server/api/sponsors.get.ts b/server/api/sponsors.get.ts
index 2da3dc32..265a2ebe 100644
--- a/server/api/sponsors.get.ts
+++ b/server/api/sponsors.get.ts
@@ -1,10 +1,10 @@
import { getSponsors } from '../utils/sponsors'
export default defineCachedEventHandler(
- async () => {
+ async event => {
if (import.meta.test) return []
- const sponsors = await getSponsors()
+ const sponsors = await getSponsors(event)
return sponsors
.map(s => s.avatarUrl?.replace(/(\?|%3Fu).*$/, ''))
.filter((r): r is string => !!r)
diff --git a/server/api/streams.ts b/server/api/streams.ts
index ab657833..d55407d1 100644
--- a/server/api/streams.ts
+++ b/server/api/streams.ts
@@ -1,7 +1,7 @@
-export default defineCachedEventHandler(async () => {
+export default defineCachedEventHandler(async event => {
if (import.meta.test) return []
- const config = useRuntimeConfig()
+ const config = useRuntimeConfig(event)
const token = await $fetch(
'https://id.twitch.tv/oauth2/token',
{
diff --git a/server/routes/auth/[...provider].get.ts b/server/routes/auth/[...provider].get.ts
index 7cff3070..76fc72a4 100644
--- a/server/routes/auth/[...provider].get.ts
+++ b/server/routes/auth/[...provider].get.ts
@@ -8,7 +8,7 @@ export default defineEventHandler(async event => {
})
}
- const config = useRuntimeConfig()
+ const config = useRuntimeConfig(event)
const { access_token } = await $fetch<{ access_token: string }>(
'https://github.com/login/oauth/access_token',
{
@@ -38,7 +38,7 @@ export default defineEventHandler(async event => {
console.error('viewer', err)
return {}
}),
- getSponsors()
+ getSponsors(event)
.then(r => r.map(s => s.id))
.catch(err => {
console.error('sponsor', err)
diff --git a/server/routes/v/[slug].ts b/server/routes/v/[slug].ts
index d204eeba..bbfbb599 100644
--- a/server/routes/v/[slug].ts
+++ b/server/routes/v/[slug].ts
@@ -1,5 +1,5 @@
export default defineEventHandler(async event => {
- const config = useRuntimeConfig()
+ const config = useRuntimeConfig(event)
const slug = getRouterParam(event, 'slug')
if (!slug || !/^[\da-z]+$/.test(slug)) {
throw createError({ statusCode: 400, statusMessage: 'Missing slug' })
diff --git a/server/utils/email.ts b/server/utils/email.ts
index c9c966b2..c04d0f9e 100644
--- a/server/utils/email.ts
+++ b/server/utils/email.ts
@@ -1,8 +1,10 @@
-export function sendEmail (subject: string, body: string) {
+import type { H3Event } from 'h3'
+
+export function sendEmail (event: H3Event, subject: string, body: string) {
return $fetch('https://api.resend.com/email', {
method: 'POST',
headers: {
- Authorization: `Bearer ${useRuntimeConfig().resendApiKey}`,
+ Authorization: `Bearer ${useRuntimeConfig(event).resendApiKey}`,
},
body: {
subject,
diff --git a/server/utils/session.ts b/server/utils/session.ts
index 2b28f877..cf406563 100644
--- a/server/utils/session.ts
+++ b/server/utils/session.ts
@@ -8,7 +8,7 @@ interface SessionData {
}
export function getUserSession (event: H3Event) {
- const config = useRuntimeConfig()
+ const config = useRuntimeConfig(event)
return getSession(event, {
password: config.sessionPassword,
name: 'token',
@@ -17,7 +17,7 @@ export function getUserSession (event: H3Event) {
}
export function setUserSession (event: H3Event, data: any) {
- const config = useRuntimeConfig()
+ const config = useRuntimeConfig(event)
return updateSession(
event,
{
@@ -30,7 +30,7 @@ export function setUserSession (event: H3Event, data: any) {
}
export function clearUserSession (event: H3Event) {
- const config = useRuntimeConfig()
+ const config = useRuntimeConfig(event)
return clearSession(event, {
password: config.sessionPassword,
name: 'token',
diff --git a/server/utils/sponsors.ts b/server/utils/sponsors.ts
index 550d3b9c..2adb0344 100644
--- a/server/utils/sponsors.ts
+++ b/server/utils/sponsors.ts
@@ -1,3 +1,4 @@
+import type { H3Event } from 'h3'
import { query } from './github'
interface Sponsor {
@@ -12,8 +13,8 @@ interface CacheEntry {
mtime: number
}
-export async function getSponsors (): Promise {
- if (!useRuntimeConfig().github.token) return []
+export async function getSponsors (event: H3Event): Promise {
+ if (!useRuntimeConfig(event).github.token) return []
const entry: CacheEntry = ((await useStorage().getItem('sponsors')) as any) || {}
const ttl = 60
@@ -22,12 +23,12 @@ export async function getSponsors (): Promise {
const expired = Date.now() - (entry.mtime || 0) > ttl
if (!entry.value || expired) {
entry.value = await query(
- useRuntimeConfig().github.token,
+ useRuntimeConfig(event).github.token,
sponsorQuery,
).then(r => r.data?.user.sponsors.edges.map((e: any) => e.node) || [])
// my ID
- entry.value.push({ id: useRuntimeConfig().github.id })
+ entry.value.push({ id: useRuntimeConfig(event).github.id })
// NuxtLabs
entry.value.push({