1
1
import { NextApiRequest , NextApiResponse } from 'next'
2
2
3
+ import got from 'got'
3
4
import { PageBlock } from 'notion-types'
4
5
import {
5
6
getBlockIcon ,
@@ -48,24 +49,6 @@ export default async (req: NextApiRequest, res: NextApiResponse) => {
48
49
const isBlogPost =
49
50
block . type === 'page' && block . parent_table === 'collection'
50
51
const title = getBlockTitle ( block , recordMap ) || libConfig . name
51
- let image = mapImageUrl (
52
- getPageProperty < string > ( 'Social Image' , block , recordMap ) ||
53
- ( block as PageBlock ) . format ?. page_cover ||
54
- libConfig . defaultPageCover ,
55
- block
56
- )
57
-
58
- if ( image ) {
59
- const imageUrl = new URL ( image )
60
-
61
- if ( imageUrl . host === 'images.unsplash.com' ) {
62
- if ( ! imageUrl . searchParams . has ( 'w' ) ) {
63
- imageUrl . searchParams . set ( 'w' , '1200' )
64
- imageUrl . searchParams . set ( 'fit' , 'max' )
65
- image = imageUrl . toString ( )
66
- }
67
- }
68
- }
69
52
70
53
const imageCoverPosition =
71
54
( block as PageBlock ) . format ?. page_cover_position ??
@@ -74,11 +57,23 @@ export default async (req: NextApiRequest, res: NextApiResponse) => {
74
57
? `center ${ ( 1 - imageCoverPosition ) * 100 } %`
75
58
: null
76
59
60
+ const imageBlockUrl = mapImageUrl (
61
+ getPageProperty < string > ( 'Social Image' , block , recordMap ) ||
62
+ ( block as PageBlock ) . format ?. page_cover ,
63
+ block
64
+ )
65
+ const imageFallbackUrl = mapImageUrl ( libConfig . defaultPageCover , block )
66
+
77
67
const blockIcon = getBlockIcon ( block , recordMap )
78
- const authorImage = mapImageUrl (
79
- blockIcon && isUrl ( blockIcon ) ? blockIcon : libConfig . defaultPageIcon ,
68
+ const authorImageBlockUrl = mapImageUrl (
69
+ blockIcon && isUrl ( blockIcon ) ? blockIcon : null ,
80
70
block
81
71
)
72
+ const authorImageFallbackUrl = mapImageUrl ( libConfig . defaultPageIcon , block )
73
+ const [ authorImage , image ] = await Promise . all ( [
74
+ getCompatibleImageUrl ( authorImageBlockUrl , authorImageFallbackUrl ) ,
75
+ getCompatibleImageUrl ( imageBlockUrl , imageFallbackUrl )
76
+ ] )
82
77
83
78
const author =
84
79
getPageProperty < string > ( 'Author' , block , recordMap ) || libConfig . author
@@ -119,7 +114,41 @@ export default async (req: NextApiRequest, res: NextApiResponse) => {
119
114
120
115
res . setHeader (
121
116
'Cache-Control' ,
122
- 'public, s-maxage=30 , max-age=30 , stale-while-revalidate=30 '
117
+ 'public, s-maxage=3600 , max-age=3600 , stale-while-revalidate=3600 '
123
118
)
124
119
res . status ( 200 ) . json ( pageInfo )
125
120
}
121
+
122
+ async function isUrlReachable ( url : string | null ) : Promise < boolean > {
123
+ if ( ! url ) {
124
+ return false
125
+ }
126
+
127
+ try {
128
+ await got . head ( url )
129
+ return true
130
+ } catch ( err ) {
131
+ return false
132
+ }
133
+ }
134
+
135
+ async function getCompatibleImageUrl (
136
+ url : string | null ,
137
+ fallbackUrl : string | null
138
+ ) : Promise < string | null > {
139
+ const image = ( await isUrlReachable ( url ) ) ? url : fallbackUrl
140
+
141
+ if ( image ) {
142
+ const imageUrl = new URL ( image )
143
+
144
+ if ( imageUrl . host === 'images.unsplash.com' ) {
145
+ if ( ! imageUrl . searchParams . has ( 'w' ) ) {
146
+ imageUrl . searchParams . set ( 'w' , '1200' )
147
+ imageUrl . searchParams . set ( 'fit' , 'max' )
148
+ return imageUrl . toString ( )
149
+ }
150
+ }
151
+ }
152
+
153
+ return image
154
+ }
0 commit comments