123 lines
2.7 KiB
Go
123 lines
2.7 KiB
Go
package main
|
|
|
|
import (
|
|
"fmt"
|
|
"log"
|
|
"os"
|
|
"path/filepath"
|
|
"strings"
|
|
"sync"
|
|
"time"
|
|
|
|
"github.com/dhowden/tag"
|
|
"github.com/google/uuid"
|
|
)
|
|
|
|
type Episode struct {
|
|
Title string
|
|
File string
|
|
Cover string
|
|
PubDate string
|
|
Artist string
|
|
Size int64
|
|
}
|
|
|
|
var (
|
|
lastMod time.Time
|
|
rssLock sync.Mutex
|
|
)
|
|
|
|
func generateUUIDFromString(input string) uuid.UUID {
|
|
namespace := uuid.NameSpaceDNS // Namespace fisso per consistenza
|
|
return uuid.NewSHA1(namespace, []byte(input))
|
|
}
|
|
|
|
func generateRSS() error {
|
|
rssLock.Lock()
|
|
defer rssLock.Unlock()
|
|
|
|
episodes, err := scanEpisodes()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
rss := fmt.Sprintf(`<?xml version="1.0" encoding="UTF-8"?>
|
|
<rss version="2.0"
|
|
xmlns:itunes="http://www.itunes.com/dtds/podcast-1.0.dtd"
|
|
xmlns:podcast="https://podcastindex.org/namespace/1.0"
|
|
xmlns:atom="http://www.w3.org/2005/Atom"
|
|
xmlns:content="http://purl.org/rss/1.0/modules/content/">
|
|
<channel>
|
|
<description>%s</description>
|
|
<title>%s</title>
|
|
<link>%s</link>`, podTitle, podTitle, baseURL)
|
|
|
|
for _, ep := range episodes {
|
|
rss += fmt.Sprintf(`
|
|
<item>
|
|
<title>%s</title>
|
|
<enclosure url="%s/audio/%s" type="audio/mpeg" length="%d"/>
|
|
<pubDate>%s</pubDate>
|
|
`, ep.Title, baseURL, filepath.Base(ep.File), ep.Size, ep.PubDate)
|
|
|
|
if ep.Cover != "" {
|
|
rss += fmt.Sprintf(`
|
|
<itunes:image href="%s/covers/%s"/>`, baseURL, ep.Cover)
|
|
}
|
|
|
|
if ep.Artist != "" {
|
|
rss += fmt.Sprintf(`
|
|
<itunes:author>%s</itunes:author>`, ep.Artist)
|
|
}
|
|
|
|
rss += fmt.Sprintf(`<link>%s/audio/%s</link>`, baseURL, filepath.Base(ep.File))
|
|
rss += fmt.Sprintf(`<guid isPermaLink="false">%s</guid>`, generateUUIDFromString(ep.Title).String())
|
|
rss += fmt.Sprintf(`<description>%s</description>`, ep.Title)
|
|
rss += "\n </item>"
|
|
}
|
|
|
|
rss += "\n</channel>\n</rss>"
|
|
|
|
return os.WriteFile("feed.xml", []byte(rss), 0644)
|
|
}
|
|
|
|
func scanEpisodes() ([]Episode, error) {
|
|
var episodes []Episode
|
|
|
|
err := filepath.Walk(audioDir, func(path string, info os.FileInfo, err error) error {
|
|
if err != nil || info.IsDir() || !strings.HasSuffix(strings.ToLower(path), ".mp3") {
|
|
return nil
|
|
}
|
|
|
|
file, err := os.Open(path)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer file.Close()
|
|
|
|
meta, err := tag.ReadFrom(file)
|
|
if err != nil {
|
|
log.Printf("File %s senza metadati ID3: %v", path, err)
|
|
return nil
|
|
}
|
|
|
|
// relPath, _ := filepath.Rel(".", path)
|
|
baseName := strings.TrimSuffix(filepath.Base(path), filepath.Ext(path))
|
|
// coverPath := filepath.Join(coversDir, baseName+".jpg")
|
|
|
|
ep := Episode{
|
|
Title: meta.Title(),
|
|
Artist: meta.Artist(),
|
|
File: baseName + ".mp3",
|
|
Cover: baseName + ".jpg",
|
|
PubDate: info.ModTime().Format(time.RFC1123),
|
|
Size: info.Size(),
|
|
}
|
|
|
|
episodes = append(episodes, ep)
|
|
return nil
|
|
})
|
|
|
|
return episodes, err
|
|
}
|