Skip to content

Commit e09b253

Browse files
committed
add user auth and modify readme
1 parent 7e9b042 commit e09b253

16 files changed

+506
-181
lines changed

README.md

+30-19
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,42 @@
1-
# feedreader
1+
# FeedReader
22

3-
> FeedReader - Self-hosted RSS Feed Aggregator Service
3+
> **FeedReader**: A Self-hosted RSS Feed Aggregator Service
4+
5+
FeedReader offers a sleek solution for aggregating RSS and ATOM feeds. Designed for those who prefer self-hosted services, it features a minimalistic web UI and supports the Fever API, making it compatible with mainstream RSS clients.
6+
7+
## Screenshots
8+
9+
### Web UI
10+
11+
The server comes with a built-in, minimal web UI for easy feed management.
12+
13+
![Web UI](./screenshots/web.jpg)
14+
15+
### Fever API Support
16+
17+
FeedReader supports the [Fever API](https://github.com/song940/fever-go), enabling integration with various RSS client apps.
18+
19+
![Fever API](./screenshots/app.jpg)
20+
21+
## Features
22+
23+
- **Minimalist Implementation**: Supports both RSS and ATOM feeds, with OPML import/export functionality.
24+
- **Fever API Integration**: Compatible with popular RSS client apps through built-in Fever API support.
425

526
## Installation
627

28+
To install FeedReader, run the following commands in your terminal:
29+
730
```shell
8-
curl -L https://github.com/song940/feedreader/releases/download/latest/reader-linux-amd64 -o /usr/bin/feedreader
9-
chmod +x /usr/bin/feedreader
31+
curl -L https://github.com/song940/feedreader/releases/download/<tag>/reader-linux-$(uname -m) -o /usr/local/bin/feedreader
32+
chmod +x /usr/local/bin/feedreader
1033
```
1134

12-
Create a service file in `/etc/systemd/system/feedreader.service`:
35+
Then, create a systemd service file for FeedReader:
1336

1437
```ini
1538
[Unit]
16-
Description=FeedReader - Self-hosted RSS Feed Aggregator Service
39+
Description=FeedReader - A Self-hosted RSS Feed Aggregator Service
1740
Documentation=https://github.com/song940/feedreader
1841
After=network-online.target
1942
Wants=network-online.target systemd-networkd-wait-online.service
@@ -25,18 +48,6 @@ ExecStart=/usr/local/bin/feedreader
2548
WantedBy=multi-user.target
2649
```
2750

28-
## Usage
29-
30-
```shell
31-
Usage of feedreader:
32-
-d string
33-
working directory (default "/etc/feedreader")
34-
-l string
35-
address to listen (default ":8080")
36-
```
37-
38-
## Contributors
39-
4051
## License
4152

42-
MIT
53+
FeedReader is released under the MIT License. For more details, see the [LICENSE](LICENSE) file in the repository.

config.yaml

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
2+
title: Kubernetes Cluster
3+
4+
users:
5+
- username: admin
6+
password: admin12311

go.mod

+2-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,8 @@ go 1.22
55
require (
66
github.com/glebarez/go-sqlite v1.21.2
77
github.com/song940/feedparser-go v0.0.0-20240223130218-14bcc1571069
8-
github.com/song940/fever-go v0.0.0-20240222065552-1b87f4b59c91
8+
github.com/song940/fever-go v0.0.0-20240312072349-37e9e89e38f9
9+
gopkg.in/yaml.v2 v2.4.0
910
)
1011

1112
require (

go.sum

+8
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,17 @@ github.com/song940/feedparser-go v0.0.0-20240223130218-14bcc1571069 h1:4+gpJBJl+
1515
github.com/song940/feedparser-go v0.0.0-20240223130218-14bcc1571069/go.mod h1:/k8QoFfeRkL4X11Kek7kztz4iMkmz+JgWtjfFWUi6Rs=
1616
github.com/song940/fever-go v0.0.0-20240222065552-1b87f4b59c91 h1:0ej6sHA3Xb0JSqqOcUmvRML+yLm/OPdR+mss09S8J+s=
1717
github.com/song940/fever-go v0.0.0-20240222065552-1b87f4b59c91/go.mod h1:Ox/T/hOL3vvkaINHo6cgcuLTh6nGCs8D0bYlIxlJ6qk=
18+
github.com/song940/fever-go v0.0.0-20240312064621-8877d03c4761 h1:w3yEYRPbZJkvPJk1Ye0VXqOBGTGBIqVXvis3JFTqPDk=
19+
github.com/song940/fever-go v0.0.0-20240312064621-8877d03c4761/go.mod h1:Ox/T/hOL3vvkaINHo6cgcuLTh6nGCs8D0bYlIxlJ6qk=
20+
github.com/song940/fever-go v0.0.0-20240312072349-37e9e89e38f9 h1:wTT0BKW2u3zYF8Ar0WHD0Mmqqika46jtPnwaMEBppfw=
21+
github.com/song940/fever-go v0.0.0-20240312072349-37e9e89e38f9/go.mod h1:Ox/T/hOL3vvkaINHo6cgcuLTh6nGCs8D0bYlIxlJ6qk=
1822
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
1923
golang.org/x/sys v0.7.0 h1:3jlCCIQZPdOYu1h8BkNvLz8Kgwtae2cagcG/VamtZRU=
2024
golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
25+
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
26+
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
27+
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
28+
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
2129
modernc.org/libc v1.22.5 h1:91BNch/e5B0uPbJFgqbxXuOnxBQjlS//icfQEGmvyjE=
2230
modernc.org/libc v1.22.5/go.mod h1:jj+Z7dTNX8fBScMVNRAYZ/jF91K8fdT2hYMThc3YjBY=
2331
modernc.org/mathutil v1.5.0 h1:rV0Ko/6SfM+8G+yKiyI830l3Wuz1zRutdslNoQ0kfiQ=

main.go

+23-21
Original file line numberDiff line numberDiff line change
@@ -5,41 +5,43 @@ import (
55
"net/http"
66
"os"
77
"path"
8-
"time"
98

109
"github.com/song940/feedreader/reader"
1110
"github.com/song940/fever-go/fever"
1211
)
1312

1413
func main() {
15-
var root, addr string
16-
userconfig, err := os.UserConfigDir()
14+
config := reader.NewConfig()
15+
conf, err := os.UserConfigDir()
1716
if err != nil {
18-
panic(err)
17+
conf = "/etc"
1918
}
20-
root = path.Join(userconfig, "feedreader")
21-
flag.StringVar(&root, "d", root, "working directory")
22-
flag.StringVar(&addr, "l", ":8080", "address to listen")
19+
dir := path.Join(conf, "feedreader")
20+
flag.StringVar(&config.Dir, "d", dir, "config directory")
2321
flag.Parse()
22+
config.Load()
2423

25-
server, err := reader.NewReader(&reader.Config{
26-
Dir: root,
27-
Interval: 5 * time.Minute,
28-
})
24+
server, err := reader.NewReader(config)
2925
if err != nil {
3026
panic(err)
3127
}
28+
3229
api := fever.New(server)
33-
http.HandleFunc("/", server.IndexView)
34-
http.HandleFunc("/new", server.NewView)
35-
http.HandleFunc("/posts", server.PostView)
36-
http.HandleFunc("/feeds", server.FeedView)
37-
http.HandleFunc("/import", server.ImportView)
38-
http.HandleFunc("/rss.xml", server.RssXML)
39-
http.HandleFunc("/atom.xml", server.AomXML)
40-
http.HandleFunc("/opml.xml", server.OpmlXML)
41-
http.Handle("/fever/", api)
42-
err = http.ListenAndServe(addr, nil)
30+
router := http.NewServeMux()
31+
router.HandleFunc("/", server.IndexView)
32+
router.HandleFunc("/new", server.NewView)
33+
router.HandleFunc("/posts", server.PostView)
34+
router.HandleFunc("/feeds", server.FeedView)
35+
router.HandleFunc("/refresh", server.RefreshView)
36+
router.HandleFunc("/import", server.ImportView)
37+
router.HandleFunc("/categories", server.CategoryView)
38+
router.HandleFunc("/rss.xml", server.RssXml)
39+
router.HandleFunc("/atom.xml", server.AomXml)
40+
router.HandleFunc("/opml.xml", server.OpmlXml)
41+
router.HandleFunc("/feeds.json", server.FeedsJson)
42+
router.HandleFunc("/posts.json", server.PostsJson)
43+
router.Handle("/fever/", api)
44+
err = http.ListenAndServe(config.Listen, router)
4345
if err != nil {
4446
panic(err)
4547
}

reader/api.go

+41-16
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package reader
22

33
import (
4+
"crypto/md5"
45
"fmt"
56
"log"
67
"strconv"
@@ -9,26 +10,50 @@ import (
910
"github.com/song940/fever-go/fever"
1011
)
1112

13+
func (user *User) FeverAuthKey() string {
14+
// md5(user.username +":"+ user.password)
15+
str := fmt.Sprintf("%s:%s", user.Username, user.Password)
16+
return fmt.Sprintf("%X", md5.Sum([]byte(str)))
17+
}
18+
1219
// FeverAuthenticate implements fever.Handler.
13-
func (*Reader) FeverAuthenticate(apiKey string) bool {
14-
return true
20+
func (r *Reader) FeverAuthenticate(apiKey string) bool {
21+
log.Println("Authenticating", apiKey)
22+
for _, user := range r.config.Users {
23+
if apiKey == user.FeverAuthKey() {
24+
return true
25+
}
26+
}
27+
return false
1528
}
1629

1730
func (r *Reader) FeverGroups() (response fever.GroupsResponse) {
31+
categories, err := r.GetCategories()
32+
if err != nil {
33+
log.Fatalf("Failed to get categories: %v", err)
34+
return
35+
}
36+
response.Groups = make([]fever.Group, 0, len(categories))
37+
for _, group := range categories {
38+
response.Groups = append(response.Groups, fever.Group{
39+
ID: int64(group.Id),
40+
Title: group.Name,
41+
})
42+
}
1843
feeds, err := r.GetFeeds(nil)
1944
if err != nil {
20-
log.Fatalf("Failed to get subscriptions: %v", err)
45+
log.Fatalf("Failed to get feeds: %v", err)
2146
return
2247
}
23-
feedIds := make([]string, 0, len(feeds))
48+
var feedGroups = make(map[int][]string)
2449
for _, feed := range feeds {
25-
feedIds = append(feedIds, strconv.Itoa(int(feed.Id)))
50+
feedGroups[feed.Category.Id] = append(feedGroups[feed.Category.Id], strconv.Itoa(feed.Id))
2651
}
27-
response.Groups = []fever.Group{
28-
{ID: 1, Title: "All"},
29-
}
30-
response.FeedsGroups = []fever.FeedsGroups{
31-
{GroupID: 1, FeedIDs: strings.Join(feedIds, ",")},
52+
for groupId, feedIds := range feedGroups {
53+
response.FeedsGroups = append(response.FeedsGroups, fever.FeedsGroups{
54+
GroupID: int64(groupId),
55+
FeedIDs: strings.Join(feedIds, ","),
56+
})
3257
}
3358
return
3459
}
@@ -39,6 +64,7 @@ func (r *Reader) FeverFeeds() (response fever.FeedsResponse) {
3964
log.Fatalf("Failed to get subscriptions: %v", err)
4065
return
4166
}
67+
var groups map[int][]string = make(map[int][]string)
4268
for _, feed := range feeds {
4369
response.Feeds = append(response.Feeds, fever.Feed{
4470
ID: int64(feed.Id),
@@ -49,13 +75,12 @@ func (r *Reader) FeverFeeds() (response fever.FeedsResponse) {
4975
IsSpark: 1,
5076
LastUpdated: feed.CreatedAt.Unix(),
5177
})
78+
groups[feed.Category.Id] = append(groups[feed.Category.Id], strconv.Itoa(feed.Id))
5279
}
53-
feedIds := make([]string, 0, len(feeds))
54-
for _, feed := range feeds {
55-
feedIds = append(feedIds, strconv.Itoa(int(feed.Id)))
56-
}
57-
response.FeedsGroups = []fever.FeedsGroups{
58-
{GroupID: 1, FeedIDs: strings.Join(feedIds, ",")},
80+
for id, feedIds := range groups {
81+
response.FeedsGroups = append(response.FeedsGroups, fever.FeedsGroups{
82+
GroupID: int64(id), FeedIDs: strings.Join(feedIds, ","),
83+
})
5984
}
6085
return response
6186
}

0 commit comments

Comments
 (0)