-
Notifications
You must be signed in to change notification settings - Fork 1
/
main.go
157 lines (125 loc) · 3.66 KB
/
main.go
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
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
package main
import (
"bytes"
"encoding/json"
"fmt"
"log"
"net/http"
"sync"
"time"
"github.com/joho/godotenv"
"github.com/kelseyhightower/envconfig"
"github.com/mmcdole/gofeed"
)
type Config struct {
MisskeyHost string `envconfig:"MISSKEY_HOST" required:"true"`
AuthToken string `envconfig:"AUTH_TOKEN" required:"true"`
RSSURL []string `envconfig:"RSS_URL" required:"true"`
}
type MisskeyNote struct {
Text string `json:"text"`
}
type Cache struct {
mu sync.RWMutex
latestItem time.Time
}
func (c *Cache) getLatestItem() time.Time {
c.mu.RLock()
defer c.mu.RUnlock()
return c.latestItem
}
func (c *Cache) saveLatestItem(published time.Time) {
c.mu.Lock()
defer c.mu.Unlock()
c.latestItem = published
}
func processRSS(config Config, cache *Cache) error {
for _, rssURL := range config.RSSURL {
fp := gofeed.NewParser()
feed, err := fp.ParseURL(rssURL)
if err != nil {
log.Println("RSSのパースが上手くできませんでした。:", err)
return err
}
latestItem := cache.getLatestItem()
log.Println("Feed Title:", feed.Title)
log.Println("Feed Description:", feed.Description)
log.Println("Feed Link:", feed.Link)
if len(feed.Items) > 0 && feed.Items[0].PublishedParsed != nil {
newestItem := *feed.Items[0].PublishedParsed
if newestItem.After(latestItem) {
err := postToMisskey(config, feed.Items[0])
if err != nil {
log.Println("Misskeyの投稿をしくじりました...:", err)
return err
} else {
log.Println("Misskeyに投稿しました。:", feed.Items[0].Title)
cache.saveLatestItem(newestItem)
}
}
}
}
return nil
}
func getLatestItem(cache *Cache) time.Time {
return cache.getLatestItem()
}
func saveLatestItem(cache *Cache, published time.Time) {
cache.saveLatestItem(published)
}
func postToMisskey(config Config, item *gofeed.Item) error {
note := map[string]interface{}{
"i": config.AuthToken,
"text": fmt.Sprintf("新着ニュース!: %s\n%s", item.Title, item.Link),
"visibility": "home",
}
payload, err := json.Marshal(note)
if err != nil {
return err
}
url := fmt.Sprintf("https://%s/api/notes/create", config.MisskeyHost)
req, err := http.NewRequest("POST", url, bytes.NewBuffer(payload))
if err != nil {
return err
}
req.Header.Set("Content-Type", "application/json")
req.Header.Set("Authorization", config.AuthToken)
client := http.Client{}
resp, err := client.Do(req)
if err != nil {
return err
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
return fmt.Errorf("MisskeyAPIと以下の理由で接続を確立できません: %d", resp.StatusCode)
}
return nil
}
func main() {
fmt.Println("処理を開始しますっ!")
err := godotenv.Load()
if err != nil {
log.Fatal(".envファイルの読み込みに失敗しました。入力した内容を確認してください。:", err)
}
var config Config
err = envconfig.Process("", &config)
if err != nil {
log.Fatal("環境変数の読み込みをしくじりました...:", err)
}
cache := &Cache{}
//RSSを取得する間隔です。今回は結構頻繁に更新される事例を想定して短めに持たせているけど、NHKとかだと5分スパンで十分です。
//分数で指定する場合はtime.Minuteに書き換えてください。
interval := 30 * time.Second
ticker := time.NewTicker(interval)
for {
select {
case <-ticker.C:
log.Println("最新のRSS情報を取得しています")
errProcessRSS := processRSS(config, cache)
if errProcessRSS != nil {
log.Println("RSSの取得に失敗しました...:", errProcessRSS)
}
log.Println("最新のRSS情報を取得しました")
}
}
}