-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathfeed.xml.ts
106 lines (102 loc) · 3.35 KB
/
feed.xml.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
import TTLCache from '@isaacs/ttlcache'
import { Author, Feed, FeedOptions } from 'feed'
import { ActivitySearchResult } from '~/api/schema/activity'
import { Chapter } from '~/api/schema/series'
const cacheOptions = {
cacheKey: 'feed',
cacheTime: 1000 * 60 * 60 * 24, // 1 day
}
// global cache object
const cache = new TTLCache({ max: 1, ttl: cacheOptions.cacheTime })
function parseDateTime(str?: string | null): Date {
if (!str) return new Date()
// str in ISO 8601 format, like: 2008-09-15T15:53:16.619579.
const year = Number(str.substring(0, 4))
const month = Number(str.substring(5, 7)) - 1
const date = Number(str.substring(8, 10))
const hours = Number(str.substring(11, 13))
const minutes = Number(str.substring(14, 16))
const seconds = Number(str.substring(17, 19))
const ms = Number(str.substring(20))
return new Date(year, month, date, hours, minutes, seconds, ms)
}
export default defineEventHandler(async (event) => {
let feedString = ''
const cachedFeedString = cache.get<string>(cacheOptions.cacheKey)
if (cachedFeedString) {
feedString = cachedFeedString
} else {
const baseUrl = 'https://blog.kumano-te.com'
const apiBaseUrl = 'https://api.kumano-te.com/api/v1'
const author: Author = {
name: 'Hiroki Tanaka',
email: 'hiroki.tanaka@kumano-te.com',
link: 'https://kumano-te.com/members',
}
const feedOptions: FeedOptions = {
id: baseUrl,
title: 'Kumanote Tech Blog',
language: 'ja',
author,
link: `${baseUrl}/feed.xml`,
description:
'合同会社kumanoteのエンジニアブログです。開発に役立つ情報を発信しています。',
image: `${baseUrl}/icon.png`,
favicon: `${baseUrl}/favicon.ico`,
copyright: `@2016 Kumanote LLC. All right reserved.`,
}
const feed = new Feed(feedOptions)
feed.addCategory('blog')
feed.addContributor(author)
const activities = await $fetch<ActivitySearchResult>(
`${apiBaseUrl}/activities/search`,
{
params: {
type: 'latest',
skip: 0,
limit: -1,
},
}
)
if (activities && activities.list) {
activities.list.forEach((activity) => {
feed.addItem({
title: activity.title,
id: activity.slug,
link: `${baseUrl}/activities/${activity.slug}`,
description: activity.subtitle || undefined,
content: activity.content,
date: parseDateTime(activity.published_at),
image: activity.avatar_image_url || undefined,
})
})
}
const chapters = await $fetch<Array<Chapter>>(`${apiBaseUrl}/chapters/`, {
params: {
type: 'latest',
skip: 0,
limit: -1,
},
})
if (chapters) {
chapters.forEach((chapter) => {
feed.addItem({
title: chapter.title,
id: chapter.slug,
link: `${baseUrl}/series/${chapter.series_slug}/${chapter.slug}`,
description: chapter.subtitle || undefined,
content: chapter.content,
date: parseDateTime(chapter.published_at),
image: chapter.avatar_image_url || undefined,
})
})
}
feedString = feed.atom1()
cache.set(cacheOptions.cacheKey, feedString)
}
event.node.res.setHeader(
'content-type',
'application/atom+xml; charset=UTF-8'
)
event.node.res.end(feedString)
})