📜 feeds is a multi-protocol / multi-platform feed aggregation service that produces twtxt feeds for consumption by twtxt clients. https://feeds.twtxt.net
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

101 lines
2.5 KiB

package main
import (
"fmt"
"io/ioutil"
"net/url"
"os"
"path/filepath"
"github.com/go-yaml/yaml"
log "github.com/sirupsen/logrus"
)
type Config struct {
Addr string
Debug bool
DataDir string
BaseURL string
FeedsFile string
MaxFeedSize int64 // maximum feed size before rotating
Feeds map[string]*Feed // name -> url
}
func (conf *Config) LoadFeeds() error {
f, err := os.Open(conf.FeedsFile)
if err != nil {
log.WithError(err).Errorf("error opening feeds file %s", conf.FeedsFile)
return fmt.Errorf("error opening feeds file %s: %w", conf.FeedsFile, err)
}
defer f.Close()
data, err := ioutil.ReadAll(f)
if err != nil {
log.WithError(err).Errorf("error reading feeds file %s", conf.FeedsFile)
return fmt.Errorf("error reading feeds file %s: %w", conf.FeedsFile, err)
}
if err := yaml.Unmarshal(data, conf.Feeds); err != nil {
log.WithError(err).Errorf("error parsing feeds file %s", conf.FeedsFile)
return fmt.Errorf("error parsing feeds file %s: %w", conf.FeedsFile, err)
}
for _, feed := range conf.Feeds {
fn := filepath.Join(conf.DataDir, fmt.Sprintf("%s.png", feed.Name))
if !Exists(fn) {
continue
}
u, err := url.Parse(fn)
if err != nil {
log.WithError(err).Errorf("error parsing avatar url for %s", feed.Name)
continue
}
avatarURL := fmt.Sprintf("%s/%s/avatar.png", conf.BaseURL, feed.Name)
avatarHash, err := FastHashFile(fn)
if err != nil {
log.WithError(err).Errorf("error computing avatar hash for %s", feed.Name)
fileInfo, err := os.Stat(fn)
if err != nil {
log.WithError(err).Errorf("error computing avatar stat for %s", feed.Name)
continue
}
avatarURL += fmt.Sprintf("#%s", fileInfo.ModTime())
} else {
if u.Fragment != avatarHash {
avatarURL += "#" + avatarHash
}
}
feed.Avatar = avatarURL
}
return nil
}
func (conf *Config) SaveFeeds() error {
f, err := os.OpenFile(conf.FeedsFile, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, 0644)
if err != nil {
log.WithError(err).Errorf("error opening feeds file %s", conf.FeedsFile)
return fmt.Errorf("error opening feeds file %s: %w", conf.FeedsFile, err)
}
defer f.Close()
data, err := yaml.Marshal(conf.Feeds)
if err != nil {
log.WithError(err).Errorf("error serializing feeds")
return fmt.Errorf("error serializing feeds: %w", err)
}
data = append([]byte("---\n"), data...)
if _, err := f.Write(data); err != nil {
log.WithError(err).Errorf("error writing feeds file %s", conf.FeedsFile)
return fmt.Errorf("error writing feeds file %s: %w", conf.FeedsFile, err)
}
return nil
}