-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathfeed.go
More file actions
127 lines (113 loc) · 2.99 KB
/
Copy pathfeed.go
File metadata and controls
127 lines (113 loc) · 2.99 KB
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
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
package main
import (
"encoding/json"
"encoding/xml"
"io"
"net/http"
"strings"
"time"
)
type ArticlesData struct {
Articles []Article `json:"articles"`
}
type Article struct {
Title string `json:"title"`
URL string `json:"url"`
PublishedAt string `json:"published_at"`
Platform string `json:"platform"`
}
type RSS struct {
XMLName xml.Name `xml:"rss"`
Version string `xml:"version,attr"`
AtomNS string `xml:"xmlns:atom,attr"`
Channel Channel `xml:"channel"`
}
type Channel struct {
Title string `xml:"title"`
Link string `xml:"link"`
Description string `xml:"description"`
Language string `xml:"language"`
LastBuildDate string `xml:"lastBuildDate"`
AtomLink AtomLink `xml:"atom:link"`
Items []Item `xml:"item"`
}
type AtomLink struct {
Href string `xml:"href,attr"`
Rel string `xml:"rel,attr"`
Type string `xml:"type,attr"`
}
type Item struct {
Title string `xml:"title"`
Link string `xml:"link"`
GUID GUID `xml:"guid"`
PubDate string `xml:"pubDate"`
Description string `xml:"description"`
}
type GUID struct {
Value string `xml:",chardata"`
IsPermaLink string `xml:"isPermaLink,attr"`
}
func feedHandler(w http.ResponseWriter, req *http.Request) {
obj, err := bucket.Get("articles.json")
if err != nil {
http.Error(w, "get error: "+err.Error(), http.StatusInternalServerError)
return
}
if obj == nil {
http.Error(w, "articles.json not found", http.StatusNotFound)
return
}
body, err := io.ReadAll(obj.Body)
if err != nil {
http.Error(w, "read error: "+err.Error(), http.StatusInternalServerError)
return
}
var data ArticlesData
if err := json.Unmarshal(body, &data); err != nil {
http.Error(w, "json error: "+err.Error(), http.StatusInternalServerError)
return
}
items := make([]Item, 0, len(data.Articles))
for _, article := range data.Articles {
pubDate := article.PublishedAt
if t, err := time.Parse(time.RFC3339, article.PublishedAt); err == nil {
pubDate = t.Format(time.RFC1123Z)
}
// Convert relative path to absolute URL for RSS feed
link := article.URL
if strings.HasPrefix(link, "/") {
link = "https://ujiprog.com" + link
}
items = append(items, Item{
Title: article.Title,
Link: link,
GUID: GUID{
Value: link,
IsPermaLink: "true",
},
PubDate: pubDate,
Description: article.Title,
})
}
rss := RSS{
Version: "2.0",
AtomNS: "http://www.w3.org/2005/Atom",
Channel: Channel{
Title: "ujiprog.com",
Link: "https://ujiprog.com/",
Description: "uji のブログ",
Language: "ja",
LastBuildDate: time.Now().Format(time.RFC1123Z),
AtomLink: AtomLink{
Href: "https://ujiprog.com/feed.xml",
Rel: "self",
Type: "application/rss+xml",
},
Items: items,
},
}
w.Header().Set("Content-Type", "application/rss+xml; charset=utf-8")
w.Header().Set("Cache-Control", "public, max-age=3600")
w.Write([]byte(xml.Header))
xml.NewEncoder(w).Encode(rss)
}