Skip to content

Commit a1dbcdc

Browse files
Added the rss file #3833 (#3839)
1 parent 8e390ca commit a1dbcdc

2 files changed

Lines changed: 114 additions & 0 deletions

File tree

web/app/api/newsletter-rss/groq.global.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,9 @@ import type { Figure } from '@/core/Image/imageUtilities'
33
import markDefs from '@/sanity/queries/common/blockEditorMarks'
44
import { functions } from '@/sanity/queries/common/functions'
55
import { sameLang } from '@/sanity/queries/common/langAndDrafts'
6+
import { ingressForNewsQuery } from '@/sanity/queries/common/newsSubqueries'
67
import { publishDateTimeQuery } from '@/sanity/queries/common/publishDateTime'
8+
import { excludeCrudeOilAssays } from '@/sanity/queries/news'
79

810
export type LatestNewsType = {
911
_id: string
@@ -21,6 +23,18 @@ dateTime(${publishDateTimeQuery}) > dateTime(now()) - 86400
2123
`
2224
//add groq to collect only ones with category that has been published since yesterday
2325

26+
export const latestNewsRss = /* groq */ `
27+
${functions}
28+
*[_type == "news" && ${excludeCrudeOilAssays} ${sameLang}] | order(${publishDateTimeQuery} desc)[0...20] {
29+
_id,
30+
"slug": slug.current,
31+
title,
32+
"hero": heroImage,
33+
"publishDateTime": ${publishDateTimeQuery},
34+
${ingressForNewsQuery},
35+
}
36+
`
37+
2438
export const latestNews = /* groq */ `
2539
${functions}
2640
*[_type == "news" && ${publishedSinceYesterday} && ((defined(subscriptionType) && ${sameLang}) || subscriptionType == "Crude")] | order(${publishDateTimeQuery} desc)[0...5] {

web/app/api/rss/route.ts

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
import { defaultComponents, toHTML } from '@portabletext/to-html'
2+
import { NextResponse } from 'next/server'
3+
import { toPlainText } from 'next-sanity'
4+
import { noCdnClient as client } from '@/sanity/lib/client'
5+
import { urlForImage } from '@/sanity/lib/utils'
6+
import {
7+
type LatestNewsType,
8+
latestNewsRss,
9+
} from '../newsletter-rss/groq.global'
10+
11+
const generateRssFeed = async (lang: 'no' | 'en') => {
12+
try {
13+
const map = {
14+
en: {
15+
language: 'en_GB',
16+
title: 'Equinor News',
17+
description: 'Latest news',
18+
},
19+
no: {
20+
language: 'nb_NO',
21+
title: 'Equinor Nyheter',
22+
description: 'Siste nytt',
23+
},
24+
}
25+
const languageCode = map[lang].language || 'en_GB'
26+
27+
const articles: LatestNewsType[] = await client.fetch(latestNewsRss, {
28+
lang: languageCode,
29+
})
30+
31+
console.log(`Fetched ${articles.length} articles for RSS feed in ${lang}`)
32+
33+
let rss = `<?xml version="1.0" encoding="UTF-8"?>
34+
<rss version="2.0">
35+
<channel>
36+
<title>${map[lang].title}</title>
37+
<description>${map[lang].description}</description>
38+
<language>${lang}</language>
39+
<link>https://www.equinor.com</link>`
40+
41+
const serializers = {
42+
...defaultComponents,
43+
marks: {
44+
...defaultComponents.marks,
45+
sub: ({ children }: { children: string }) => `<sub>${children}</sub>`,
46+
sup: ({ children }: { children: string }) => `<sup>${children}</sup>`,
47+
},
48+
}
49+
50+
articles.forEach(article => {
51+
const hero = article.hero
52+
const bannerImageUrl = hero?.image?.asset
53+
? urlForImage(hero.image)?.size(560, 280).auto('format').toString() ||
54+
''
55+
: ''
56+
const imageAlt = hero?.image?.alt ? ` alt="${hero.image.alt}"` : ''
57+
const title =
58+
typeof article.title === 'string'
59+
? article.title
60+
: toPlainText(article.title)
61+
const ingress = Array.isArray(article.ingress) ? article.ingress : []
62+
63+
const descriptionHtml = toHTML(ingress, {
64+
components: serializers,
65+
onMissingComponent: e => String(e),
66+
})
67+
68+
rss += `
69+
<item>
70+
<title>${title}</title>
71+
<link>https://equinor.com${lang === 'no' ? '/no' : ''}${article.slug}</link>
72+
<guid>https://equinor.com${lang === 'no' ? '/no' : ''}${article.slug}</guid>
73+
<pubDate>${new Date(article.publishDateTime).toUTCString()}</pubDate>
74+
<description><![CDATA[<img src="${bannerImageUrl}"${imageAlt}/><br/>${descriptionHtml}]]></description>
75+
</item>`
76+
})
77+
78+
rss += `
79+
</channel>
80+
</rss>`
81+
82+
return rss
83+
} catch (error) {
84+
console.error('Error generating RSS feed:', error)
85+
throw new Error('Failed to generate RSS feed.')
86+
}
87+
}
88+
89+
export async function GET(req: Request) {
90+
const { searchParams } = new URL(req.url)
91+
const lang = searchParams.get('lang') === 'no' ? 'no' : 'en'
92+
const rss = await generateRssFeed(lang)
93+
94+
return new NextResponse(rss, {
95+
headers: {
96+
'Content-Type': 'text/xml; charset=utf-8',
97+
'Cache-Control': 'public, s-maxage=1200, stale-while-revalidate=600',
98+
},
99+
})
100+
}

0 commit comments

Comments
 (0)