]> Sergey Matveev's repositories - feeder.git/blob - cmd/feed2mdir/main.go
b8d2863a88350c09acf78669ad73621815adf38d
[feeder.git] / cmd / feed2mdir / main.go
1 /*
2 go.stargrave.org/feeder  -- newsfeeds aggregator
3 Copyright (C) 2022 Sergey Matveev <stargrave@stargrave.org>
4
5 This program is free software: you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation, version 3 of the License.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with this program.  If not, see <http://www.gnu.org/licenses/>.
16 */
17
18 package main
19
20 import (
21         "crypto/sha512"
22         "encoding/base64"
23         "encoding/hex"
24         "flag"
25         "fmt"
26         "log"
27         "mime"
28         "os"
29         "path"
30         "strings"
31         "time"
32
33         "github.com/mmcdole/gofeed"
34 )
35
36 func main() {
37         maxEntries := flag.Uint("max-entries", 100, "Max entries to process")
38         flag.Parse()
39         mdir := flag.Arg(0)
40         fp := gofeed.NewParser()
41         feed, err := fp.Parse(os.Stdin)
42         if err != nil {
43                 log.Fatalln(err)
44         }
45         news := 0
46         var when *time.Time
47         now := time.Now()
48         max := int(*maxEntries) - 1
49         for n, item := range feed.Items {
50                 if n == max {
51                         break
52                 }
53                 when = nil
54                 if item.PublishedParsed != nil {
55                         when = item.PublishedParsed
56                 } else if item.UpdatedParsed != nil {
57                         when = item.UpdatedParsed
58                 } else {
59                         when = &now
60                 }
61                 fn := hex.EncodeToString(h.Sum(nil)[:sha512.Size/2])
62                 var what string
63                 if len(item.Content) == 0 {
64                         what = item.Description
65                 } else {
66                         what = item.Content
67                 }
68                 exists := false
69                 for _, d := range []string{"cur", "new"} {
70                         entries, err := os.ReadDir(path.Join(mdir, d))
71                         if err != nil {
72                                 log.Fatalln(err)
73                         }
74                         for _, entry := range entries {
75                                 if strings.HasPrefix(entry.Name(), fn) {
76                                         exists = true
77                                         break
78                                 }
79                         }
80                 }
81                 if exists {
82                         continue
83                 }
84                 fn = path.Join(mdir, "new", fn)
85                 fd, err := os.OpenFile(fn, os.O_WRONLY|os.O_CREATE|os.O_EXCL, os.FileMode(0666))
86                 if err != nil {
87                         log.Fatalln(err)
88                 }
89                 fd.WriteString("From: \"" + feed.Title + "\" <feeder@go.stargrave.org>\n")
90                 fd.WriteString("Date: " + when.Format(time.RFC1123Z) + "\n")
91                 fd.WriteString("Subject: " + mime.BEncoding.Encode("UTF-8", item.Title) + "\n")
92                 fd.WriteString("MIME-Version: 1.0\n")
93                 fd.WriteString("Content-Type: text/html; charset=utf-8\n")
94                 fd.WriteString("Content-Transfer-Encoding: base64\n")
95                 for _, link := range item.Links {
96                         fd.WriteString("X-URL: " + link + "\n")
97                 }
98                 for _, author := range item.Authors {
99                         fd.WriteString("X-Author: " + author.Name + "\n")
100                 }
101                 for _, cat := range item.Categories {
102                         fd.WriteString("X-Category: " + cat + "\n")
103                 }
104                 fd.WriteString("\n")
105                 what = base64.StdEncoding.EncodeToString([]byte(what))
106                 for i := 0; i < len(what); i += 72 {
107                         b := i + 72
108                         if b > len(what) {
109                                 b = len(what)
110                         }
111                         fd.WriteString(what[i:b] + "\n")
112                 }
113                 fd.Close()
114                 if err = os.Chtimes(fn, *when, *when); err != nil {
115                         log.Fatalln(err)
116                 }
117                 news++
118         }
119         when = nil
120         if feed.PublishedParsed != nil {
121                 when = feed.PublishedParsed
122         } else if feed.UpdatedParsed != nil {
123                 when = feed.UpdatedParsed
124         }
125         if when != nil {
126                 for _, d := range []string{"cur", "new"} {
127                         if err = os.Chtimes(path.Join(mdir, d), *when, *when); err != nil {
128                                 log.Fatalln(err)
129                         }
130                 }
131         }
132         fmt.Println(feed.Title)
133 }