You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
hugobot/export/export.go

215 lines
4.7 KiB
Go

package export
import (
"fmt"
"log"
"os"
"path/filepath"
"strings"
"time"
"git.sp4ke.com/sp4ke/hugobot/v3/config"
"git.sp4ke.com/sp4ke/hugobot/v3/encoder"
"git.sp4ke.com/sp4ke/hugobot/v3/feeds"
"git.sp4ke.com/sp4ke/hugobot/v3/filters"
"git.sp4ke.com/sp4ke/hugobot/v3/posts"
"git.sp4ke.com/sp4ke/hugobot/v3/types"
"git.sp4ke.com/sp4ke/hugobot/v3/utils"
)
var PostMappers []PostMapper
var FeedMappers []FeedMapper
type Map map[string]interface{}
type PostMapper func(Map, feeds.Feed, posts.Post) error
type FeedMapper func(Map, feeds.Feed) error
// Exported version of a post
type PostExport struct {
ID int64 `json:"id"`
Title string `json:"title"`
Link string `json:"link"`
Published time.Time `json:"published"`
Content string `json:"content"`
}
type PostMap map[int64]Map
type FeedExport struct {
Name string `json:"name"`
Section string `json:"section"`
Categories types.StringList `json:"categories"`
Posts PostMap `json:"posts"`
}
type HugoExporter struct{}
func (he HugoExporter) Handle(feed feeds.Feed) error {
return he.export(feed)
}
func (he HugoExporter) export(feed feeds.Feed) error {
log.Printf("Exporting %s to %s", feed.Name, config.HugoData())
posts, err := posts.GetPostsByFeedId(feed.FeedID)
if err != nil {
return err
}
if len(posts) == 0 {
log.Printf("nothing to export")
return nil
}
// Run filters on posts
for _, p := range posts {
filters.RunPostFilterHooks(feed, p)
}
// Dir and filename
dirPath := filepath.Join(config.HugoData(), feed.Section)
cleanFeedName := strings.Replace(feed.Name, "/", "-", -1)
filePath := filepath.Join(dirPath, cleanFeedName+".json")
err = utils.Mkdir(dirPath)
if err != nil {
return err
}
feedExp := Map{
"name": feed.Name,
"section": feed.Section,
"categories": feed.Categories,
}
runFeedMappers(feedExp, feed)
postsMap := make(PostMap)
for _, p := range posts {
exp := Map{
"id": p.PostID,
"title": p.Title,
"link": p.Link,
"published": p.Published,
"updated": p.Updated,
//"content": p.Content,
}
runPostMappers(exp, feed, *p)
postsMap[p.PostID] = exp
}
feedExp["posts"] = postsMap
outputFile, err := os.Create(filePath)
defer outputFile.Close()
if err != nil {
return err
}
exportEncoder := encoder.NewExportEncoder(outputFile, encoder.JSON)
exportEncoder.Encode(feedExp)
//jsonEnc.Encode(feedExp)
// Handle feeds which export posts individually as hugo posts
// Like bulletin
if feed.ExportPosts {
for _, p := range posts {
exp := map[string]interface{}{
"id": p.PostID,
"title": p.Title,
"name": feed.Name,
"author": p.Author,
"description": p.PostDescription,
"externalLink": feed.UseExternalLink,
"display_name": feed.DisplayName,
"publishdate": p.Published,
"date": p.Updated,
"issuedate": utils.NextThursday(p.Updated),
"use_data": true,
"slug": p.ShortID,
"link": p.Link,
// Content is written in the post
"content": p.Content,
"categories": feed.Categories,
"tags": strings.Split(p.Tags, ","),
}
if feed.Publications != "" {
exp["publications"] = strings.Split(feed.Publications, ",")
}
runPostMappers(exp, feed, *p)
dirPath := filepath.Join(config.HugoContent(), feed.Section)
cleanFeedName := strings.Replace(feed.Name, "/", "-", -1)
fileName := fmt.Sprintf("%s-%s.md", cleanFeedName, p.ShortID)
filePath := filepath.Join(dirPath, fileName)
outputFile, err := os.Create(filePath)
defer outputFile.Close()
if err != nil {
return err
}
exportEncoder := encoder.NewExportEncoder(outputFile, encoder.TOML)
exportEncoder.Encode(exp)
}
}
return nil
}
// Runs in goroutine
func (he HugoExporter) Export(feed feeds.Feed) {
err := he.export(feed)
if err != nil {
log.Fatal(err)
}
}
func NewHugoExporter() HugoExporter {
// Make sure path exists
err := utils.Mkdir(config.HugoData())
if err != nil {
log.Fatal(err)
}
return HugoExporter{}
}
func runPostMappers(e Map, f feeds.Feed, p posts.Post) {
for _, fn := range PostMappers {
err := fn(e, f, p)
if err != nil {
log.Print(err)
}
}
}
func runFeedMappers(e Map, f feeds.Feed) {
for _, fn := range FeedMappers {
err := fn(e, f)
if err != nil {
log.Print(err)
}
}
}
func RegisterPostMapper(mapper PostMapper) {
PostMappers = append(PostMappers, mapper)
}
func RegisterFeedMapper(mapper FeedMapper) {
FeedMappers = append(FeedMappers, mapper)
}
func init() {
RegisterPostMapper(BulletinExport)
RegisterPostMapper(NewsletterPostLayout)
RegisterPostMapper(RFCExport)
RegisterPostMapper(ReleaseExport)
}