Micropub endpoint for my blog https://jlelse.blog/posts/hugo-micropub/
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.
 
 

204 lines
5.8 KiB

package main
import (
"errors"
"log"
"os"
"strings"
"sync"
"gopkg.in/yaml.v3"
)
var (
BlogUrl string
MediaEndpointUrl string
SyndicationTargets []SyndicationTarget
SelectedStorage Storage
SelectedMediaStorage MediaStorage
SelectedNotificationServices NotificationServices
SelectedImageCompression ImageCompression
DefaultLanguage string
Languages map[string]Language
)
type SyndicationTarget struct {
Uid string `json:"uid"`
Name string `json:"name"`
}
type YamlConfig struct {
BlogUrl string `yaml:"blogUrl"`
BaseUrl string `yaml:"baseUrl"`
MediaUrl string `yaml:"mediaUrl"`
DefaultLanguage string `yaml:"defaultLang"`
Languages map[string]Language `yaml:"languages"`
Git GitConfig `yaml:"git"`
BunnyCdn BunnyCdnConfig `yaml:"bunnyCdn"`
Telegram TelegramConfig `yaml:"telegram"`
Tinify TinifyConfig `yaml:"tinify"`
SyndicationTargets []string `yaml:"syndication"`
}
type BunnyCdnConfig struct {
StorageKey string `yaml:"storageKey"`
StorageName string `yaml:"storageName"`
}
type TelegramConfig struct {
UserId int `yaml:"userId"`
BotToken string `yaml:"botToken"`
}
type TinifyConfig struct {
Key string `yaml:"key"`
}
type GitConfig struct {
Filepath string `yaml:"filepath"`
Url string `yaml:"url"`
Username string `yaml:"username"`
Password string `yaml:"password"`
AuthorName string `yaml:"authorName"`
AuthorEmail string `yaml:"authorEmail"`
}
type Language struct {
BlogUrl string `yaml:"blogUrl"`
ContentDir string `yaml:"contentDir"`
DefaultSection string `yaml:"defaultSection"`
Sections map[string]Section `yaml:"sections"`
}
type Section struct {
FilenameTemplate string `yaml:"file"`
LocationTemplate string `yaml:"location"`
}
func initConfig() (err error) {
configFileName, configSet := os.LookupEnv("CONFIG")
if !configSet {
configFileName = "config.yml"
}
configFile, err := os.Open(configFileName)
if err != nil {
return errors.New("failed to open config file")
}
cfg := YamlConfig{}
err = yaml.NewDecoder(configFile).Decode(&cfg)
if err != nil {
return errors.New("failed to parse yaml")
}
// Blog URL (required)
if len(cfg.BlogUrl) < 1 {
return errors.New("blogUrl not configured")
}
if !strings.HasSuffix(cfg.BlogUrl, "/") {
return errors.New("missing trailing slash in configured blogUrl")
}
BlogUrl = cfg.BlogUrl
// Media endpoint (required)
if len(cfg.BaseUrl) < 1 {
return errors.New("baseUrl not configured")
}
if len(cfg.MediaUrl) < 1 {
return errors.New("mediaUrl not configured")
}
if !strings.HasSuffix(cfg.BaseUrl, "/") {
return errors.New("missing trailing slash in configured baseUrl")
}
MediaEndpointUrl = cfg.BaseUrl + "media"
// Languages (required)
if len(cfg.DefaultLanguage) < 1 {
return errors.New("no default language configured")
}
DefaultLanguage = cfg.DefaultLanguage
if len(cfg.Languages) > 0 {
for _, lang := range cfg.Languages {
if len(lang.ContentDir) < 1 || len(lang.DefaultSection) < 1 || len(lang.Sections) < 1 {
return errors.New("language not completely configured")
}
for _, section := range lang.Sections {
if len(section.FilenameTemplate) < 1 || len(section.LocationTemplate) < 1 {
return errors.New("section not completely configured")
}
}
}
Languages = cfg.Languages
} else {
return errors.New("no languages configured")
}
// Syndication Targets (optional)
targets := make([]SyndicationTarget, 0)
for _, url := range cfg.SyndicationTargets {
targets = append(targets, SyndicationTarget{
Uid: url,
Name: url,
})
}
SyndicationTargets = targets
// Find selected storage
SelectedStorage = func() Storage {
// Git
if len(cfg.Git.Filepath) > 0 && len(cfg.Git.Url) > 0 && len(cfg.Git.Username) > 0 && len(cfg.Git.Password) > 0 && len(cfg.Git.AuthorName) > 0 && len(cfg.Git.AuthorEmail) > 0 {
return &Git{
filepath: cfg.Git.Filepath,
url: cfg.Git.Url,
username: cfg.Git.Username,
password: cfg.Git.Password,
name: cfg.Git.AuthorName,
email: cfg.Git.AuthorEmail,
lock: &sync.Mutex{},
}
}
return nil
}()
if SelectedStorage == nil {
return errors.New("no storage configured")
}
// Find selected media storage (Optional)
SelectedMediaStorage = func() MediaStorage {
// BunnyCDN
// MEDIA_URL needs trailing slash too
if len(cfg.BunnyCdn.StorageKey) > 0 && len(cfg.BunnyCdn.StorageName) > 0 && len(cfg.MediaUrl) > 0 && strings.HasSuffix(cfg.MediaUrl, "/") {
return &BunnyCdnStorage{
key: cfg.BunnyCdn.StorageKey,
storageZoneName: cfg.BunnyCdn.StorageName,
baseLocation: cfg.MediaUrl,
}
}
return nil
}()
if SelectedMediaStorage == nil {
log.Println("no media storage configured")
}
// Find configured notification services (optional)
SelectedNotificationServices = func() NotificationServices {
var notificationServices []NotificationService = nil
// Telegram
if cfg.Telegram.UserId > 0 && len(cfg.Telegram.BotToken) > 0 {
notificationServices = append(notificationServices, &Telegram{
userId: cfg.Telegram.UserId,
botToken: cfg.Telegram.BotToken,
})
}
return notificationServices
}()
if SelectedNotificationServices == nil {
log.Println("No notification services configured")
}
// Find configured image compression service (optional)
SelectedImageCompression = func() ImageCompression {
// Tinify
if len(cfg.Tinify.Key) > 0 {
return &Tinify{
key: cfg.Tinify.Key,
}
}
return nil
}()
if SelectedImageCompression == nil {
log.Println("no image compression configured")
}
return nil
}