Add Media Endpoint support
parent
35770cecc9
commit
222afd3957
193
config.go
193
config.go
|
@ -2,10 +2,8 @@ package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
|
"github.com/caarlos0/env/v6"
|
||||||
"log"
|
"log"
|
||||||
"os"
|
|
||||||
"strconv"
|
|
||||||
"strings"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
@ -13,9 +11,11 @@ var (
|
||||||
IgnoredWebmentionUrls []string
|
IgnoredWebmentionUrls []string
|
||||||
SyndicationTargets []SyndicationTarget
|
SyndicationTargets []SyndicationTarget
|
||||||
SelectedStorage Storage
|
SelectedStorage Storage
|
||||||
|
SelectedMediaStorage MediaStorage
|
||||||
SelectedCdn Cdn
|
SelectedCdn Cdn
|
||||||
SelectedSocials Socials
|
SelectedSocials Socials
|
||||||
SelectedNotificationServices NotificationServices
|
SelectedNotificationServices NotificationServices
|
||||||
|
MediaEndpointUrl string
|
||||||
)
|
)
|
||||||
|
|
||||||
type SyndicationTarget struct {
|
type SyndicationTarget struct {
|
||||||
|
@ -23,80 +23,106 @@ type SyndicationTarget struct {
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func initConfig() {
|
type config struct {
|
||||||
|
BlogUrl string `env:"BLOG_URL,required"`
|
||||||
|
BaseUrl string `env:"BASE_URL,required"`
|
||||||
|
MediaUrl string `env:"MEDIA_URL"`
|
||||||
|
GiteaEndpoint string `env:"GITEA_ENDPOINT"`
|
||||||
|
GiteaToken string `env:"GITEA_TOKEN"`
|
||||||
|
BunnyCdnKey string `env:"BUNNY_CDN_KEY"`
|
||||||
|
BunnyCdnStorageKey string `env:"BUNNY_CDN_STORAGE_KEY"`
|
||||||
|
BunnyCdnStorageName string `env:"BUNNY_CDN_STORAGE_NAME"`
|
||||||
|
MicroblogUrl string `env:"MICROBLOG_URL"`
|
||||||
|
MicroblogToken string `env:"MICROBLOG_TOKEN"`
|
||||||
|
TelegramUserId int64 `env:"TELEGRAM_USER_ID"`
|
||||||
|
TelegramBotToken string `env:"TELEGRAM_BOT_TOKEN"`
|
||||||
|
IgnoredWebmentionUrls []string `env:"WEBMENTION_IGNORED" envSeparator:","`
|
||||||
|
SyndicationTargets []string `env:"SYNDICATION" envSeparator:","`
|
||||||
|
}
|
||||||
|
|
||||||
|
func initConfig() (err error) {
|
||||||
|
cfg := config{}
|
||||||
|
if err := env.Parse(&cfg); err != nil {
|
||||||
|
return errors.New("failed to parse config, probably not all required env vars set")
|
||||||
|
}
|
||||||
// Blog URL (required)
|
// Blog URL (required)
|
||||||
blogUrl, err := blogUrl()
|
BlogUrl = cfg.BlogUrl
|
||||||
if err != nil {
|
// Media endpoint
|
||||||
log.Fatal(err)
|
MediaEndpointUrl = cfg.BaseUrl + "/media"
|
||||||
}
|
|
||||||
BlogUrl = blogUrl
|
|
||||||
// Ignored Webmention URLs (optional)
|
// Ignored Webmention URLs (optional)
|
||||||
ignoredWebmentionUrls, err := ignoredWebmentionUrls()
|
IgnoredWebmentionUrls = cfg.IgnoredWebmentionUrls
|
||||||
if err != nil {
|
|
||||||
log.Println(err)
|
|
||||||
}
|
|
||||||
IgnoredWebmentionUrls = ignoredWebmentionUrls
|
|
||||||
// Syndication Targets (optional)
|
// Syndication Targets (optional)
|
||||||
syndicationTargets, err := syndicationTargets()
|
targets := make([]SyndicationTarget, 0)
|
||||||
if err != nil {
|
for _, url := range cfg.SyndicationTargets {
|
||||||
log.Println(err)
|
targets = append(targets, SyndicationTarget{
|
||||||
|
Uid: url,
|
||||||
|
Name: url,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
SyndicationTargets = syndicationTargets
|
SyndicationTargets = targets
|
||||||
// Find selected storage
|
// Find selected storage
|
||||||
SelectedStorage = func() Storage {
|
SelectedStorage = func() Storage {
|
||||||
// Gitea
|
// Gitea
|
||||||
giteaEndpoint, err1 := giteaEndpoint()
|
if len(cfg.GiteaEndpoint) > 0 && len(cfg.GiteaToken) >= 0 {
|
||||||
giteaToken, err2 := giteaToken()
|
|
||||||
if err1 == nil && err2 == nil {
|
|
||||||
return &Gitea{
|
return &Gitea{
|
||||||
endpoint: giteaEndpoint,
|
endpoint: cfg.GiteaEndpoint,
|
||||||
token: giteaToken,
|
token: cfg.GiteaToken,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}()
|
}()
|
||||||
if SelectedStorage == nil {
|
if SelectedStorage == nil {
|
||||||
log.Fatal("No storage configured")
|
return errors.New("no storage configured")
|
||||||
|
}
|
||||||
|
// Find selected media storage
|
||||||
|
SelectedMediaStorage = func() MediaStorage {
|
||||||
|
// BunnyCDN
|
||||||
|
if len(cfg.BunnyCdnStorageKey) > 0 && len(cfg.BunnyCdnStorageName) > 0 && len(cfg.MediaUrl) > 0 {
|
||||||
|
return &BunnyCdnStorage{
|
||||||
|
key: cfg.BunnyCdnStorageKey,
|
||||||
|
storageZoneName: cfg.BunnyCdnStorageName,
|
||||||
|
baseLocation: cfg.MediaUrl,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}()
|
||||||
|
if SelectedMediaStorage == nil {
|
||||||
|
return errors.New("no media storage configured")
|
||||||
}
|
}
|
||||||
// Find selected CDN (optional)
|
// Find selected CDN (optional)
|
||||||
SelectedCdn = func() Cdn {
|
SelectedCdn = func() Cdn {
|
||||||
// BunnyCDN (optional)
|
// BunnyCDN (optional)
|
||||||
bunnyCdnKey, err := bunnyCdnKey()
|
if len(cfg.BunnyCdnKey) > 0 {
|
||||||
if err == nil {
|
return &BunnyCdn{key: cfg.BunnyCdnKey}
|
||||||
return &BunnyCdn{key: bunnyCdnKey}
|
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}()
|
}()
|
||||||
if SelectedCdn == nil {
|
if SelectedCdn == nil {
|
||||||
log.Println("No CDN configured")
|
log.Println("no CDN configured")
|
||||||
}
|
}
|
||||||
// Find configured social networks (optional)
|
// Find configured social networks (optional)
|
||||||
SelectedSocials = func() Socials {
|
SelectedSocials = func() Socials {
|
||||||
var socials []Social = nil
|
var socials []Social = nil
|
||||||
// Microblog.pub
|
// Microblog.pub
|
||||||
microblogUrl, err1 := microblogUrl()
|
if len(cfg.MicroblogUrl) > 0 && len(cfg.MicroblogToken) > 0 {
|
||||||
microblogToken, err2 := microblogToken()
|
|
||||||
if err1 == nil && err2 == nil {
|
|
||||||
socials = append(socials, &MicroblogPub{
|
socials = append(socials, &MicroblogPub{
|
||||||
url: microblogUrl,
|
url: cfg.MicroblogUrl,
|
||||||
token: microblogToken,
|
token: cfg.MicroblogToken,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
return socials
|
return socials
|
||||||
}()
|
}()
|
||||||
if SelectedSocials == nil {
|
if SelectedSocials == nil {
|
||||||
log.Println("No social networks configured")
|
log.Println("no social networks configured")
|
||||||
}
|
}
|
||||||
// Find configured notification services (optional)
|
// Find configured notification services (optional)
|
||||||
SelectedNotificationServices = func() NotificationServices {
|
SelectedNotificationServices = func() NotificationServices {
|
||||||
var notificationServices []NotificationService = nil
|
var notificationServices []NotificationService = nil
|
||||||
// Telegram
|
// Telegram
|
||||||
telegramUserId, err1 := telegramUserId()
|
if cfg.TelegramUserId > 0 && len(cfg.TelegramBotToken) > 0 {
|
||||||
telegramBotToken, err2 := telegramBotToken()
|
|
||||||
if err1 == nil && err2 == nil {
|
|
||||||
notificationServices = append(notificationServices, &Telegram{
|
notificationServices = append(notificationServices, &Telegram{
|
||||||
userId: telegramUserId,
|
userId: cfg.TelegramUserId,
|
||||||
botToken: telegramBotToken,
|
botToken: cfg.TelegramBotToken,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
return notificationServices
|
return notificationServices
|
||||||
|
@ -104,92 +130,5 @@ func initConfig() {
|
||||||
if SelectedNotificationServices == nil {
|
if SelectedNotificationServices == nil {
|
||||||
log.Println("No notification services configured")
|
log.Println("No notification services configured")
|
||||||
}
|
}
|
||||||
}
|
return nil
|
||||||
|
|
||||||
func giteaEndpoint() (string, error) {
|
|
||||||
giteaEndpoint := os.Getenv("GITEA_ENDPOINT")
|
|
||||||
if len(giteaEndpoint) == 0 || giteaEndpoint == "" {
|
|
||||||
return "", errors.New("GITEA_ENDPOINT not specified")
|
|
||||||
}
|
|
||||||
return giteaEndpoint, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func giteaToken() (string, error) {
|
|
||||||
giteaToken := os.Getenv("GITEA_TOKEN")
|
|
||||||
if len(giteaToken) == 0 || giteaToken == "" {
|
|
||||||
return "", errors.New("GITEA_TOKEN not specified")
|
|
||||||
}
|
|
||||||
return giteaToken, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func blogUrl() (string, error) {
|
|
||||||
blogURL := os.Getenv("BLOG_URL")
|
|
||||||
if len(blogURL) == 0 || blogURL == "" {
|
|
||||||
return "", errors.New("BLOG_URL not specified")
|
|
||||||
}
|
|
||||||
return blogURL, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func bunnyCdnKey() (string, error) {
|
|
||||||
bunnyCDNKey := os.Getenv("BUNNY_CDN_KEY")
|
|
||||||
if len(bunnyCDNKey) == 0 || bunnyCDNKey == "" {
|
|
||||||
return "", errors.New("BUNNY_CDN_KEY not specified, BunnyCDN features are deactivated")
|
|
||||||
}
|
|
||||||
return bunnyCDNKey, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func microblogUrl() (string, error) {
|
|
||||||
microblogUrl := os.Getenv("MICROBLOG_URL")
|
|
||||||
if len(microblogUrl) == 0 || microblogUrl == "" {
|
|
||||||
return "", errors.New("MICROBLOG_URL not specified, microblog.pub features are deactivated")
|
|
||||||
}
|
|
||||||
return microblogUrl, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func microblogToken() (string, error) {
|
|
||||||
microblogToken := os.Getenv("MICROBLOG_TOKEN")
|
|
||||||
if len(microblogToken) == 0 || microblogToken == "" {
|
|
||||||
return "", errors.New("MICROBLOG_TOKEN not specified, microblog.pub features are deactivated")
|
|
||||||
}
|
|
||||||
return microblogToken, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func telegramUserId() (int64, error) {
|
|
||||||
telegramUserIdString := os.Getenv("TELEGRAM_USER_ID")
|
|
||||||
telegramUserId, err := strconv.ParseInt(telegramUserIdString, 10, 64)
|
|
||||||
if err != nil || len(telegramUserIdString) == 0 || telegramUserIdString == "" {
|
|
||||||
return 0, errors.New("TELEGRAM_USER_ID not specified, Telegram features are deactivated")
|
|
||||||
}
|
|
||||||
return telegramUserId, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func telegramBotToken() (string, error) {
|
|
||||||
telegramBotToken := os.Getenv("TELEGRAM_BOT_TOKEN")
|
|
||||||
if len(telegramBotToken) == 0 || telegramBotToken == "" {
|
|
||||||
return "", errors.New("TELEGRAM_BOT_TOKEN not specified, Telegram features are deactivated")
|
|
||||||
}
|
|
||||||
return telegramBotToken, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func ignoredWebmentionUrls() ([]string, error) {
|
|
||||||
webmentionIgnored := os.Getenv("WEBMENTION_IGNORED")
|
|
||||||
if len(webmentionIgnored) == 0 {
|
|
||||||
return make([]string, 0), errors.New("WEBMENTION_IGNORED not set, no URLs are ignored on Webmention sending")
|
|
||||||
}
|
|
||||||
return strings.Split(webmentionIgnored, ","), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func syndicationTargets() ([]SyndicationTarget, error) {
|
|
||||||
syndication := os.Getenv("SYNDICATION")
|
|
||||||
targets := make([]SyndicationTarget, 0)
|
|
||||||
if len(syndication) == 0 {
|
|
||||||
return targets, errors.New("SYNDICATION not set, no targets are returned when querying for syndication targets")
|
|
||||||
}
|
|
||||||
for _, url := range strings.Split(syndication, ",") {
|
|
||||||
targets = append(targets, SyndicationTarget{
|
|
||||||
Uid: url,
|
|
||||||
Name: url,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
return targets, nil
|
|
||||||
}
|
}
|
||||||
|
|
1
go.mod
1
go.mod
|
@ -3,6 +3,7 @@ module codeberg.org/jlelse/hugo-micropub
|
||||||
go 1.13
|
go 1.13
|
||||||
|
|
||||||
require (
|
require (
|
||||||
|
github.com/caarlos0/env/v6 v6.1.0
|
||||||
github.com/go-telegram-bot-api/telegram-bot-api v4.6.5-0.20190904012038-b33efeebc785+incompatible
|
github.com/go-telegram-bot-api/telegram-bot-api v4.6.5-0.20190904012038-b33efeebc785+incompatible
|
||||||
github.com/technoweenie/multipartstreamer v1.0.1 // indirect
|
github.com/technoweenie/multipartstreamer v1.0.1 // indirect
|
||||||
gopkg.in/yaml.v2 v2.2.7
|
gopkg.in/yaml.v2 v2.2.7
|
||||||
|
|
8
go.sum
8
go.sum
|
@ -1,9 +1,16 @@
|
||||||
github.com/andybalholm/cascadia v1.0.0 h1:hOCXnnZ5A+3eVDX8pvgl4kofXv2ELss0bKcqRySc45o=
|
github.com/andybalholm/cascadia v1.0.0 h1:hOCXnnZ5A+3eVDX8pvgl4kofXv2ELss0bKcqRySc45o=
|
||||||
github.com/andybalholm/cascadia v1.0.0/go.mod h1:GsXiBklL0woXo1j/WYWtSYYC4ouU9PqHO0sqidkEA4Y=
|
github.com/andybalholm/cascadia v1.0.0/go.mod h1:GsXiBklL0woXo1j/WYWtSYYC4ouU9PqHO0sqidkEA4Y=
|
||||||
|
github.com/caarlos0/env/v6 v6.1.0 h1:4FbM+HmZA/Q5wdSrH2kj0KQXm7xnhuO8y3TuOTnOvqc=
|
||||||
|
github.com/caarlos0/env/v6 v6.1.0/go.mod h1:iUA6X3VCAOwDhoqvgKlTGjjwJzQseIJaFYApUqQkt+8=
|
||||||
|
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
github.com/go-telegram-bot-api/telegram-bot-api v4.6.5-0.20190904012038-b33efeebc785+incompatible h1:OT02onvXX618RBcjxeUA4H7d1PSm5Apg4IET72VgVlE=
|
github.com/go-telegram-bot-api/telegram-bot-api v4.6.5-0.20190904012038-b33efeebc785+incompatible h1:OT02onvXX618RBcjxeUA4H7d1PSm5Apg4IET72VgVlE=
|
||||||
github.com/go-telegram-bot-api/telegram-bot-api v4.6.5-0.20190904012038-b33efeebc785+incompatible/go.mod h1:qf9acutJ8cwBUhm1bqgz6Bei9/C/c93FPDljKWwsOgM=
|
github.com/go-telegram-bot-api/telegram-bot-api v4.6.5-0.20190904012038-b33efeebc785+incompatible/go.mod h1:qf9acutJ8cwBUhm1bqgz6Bei9/C/c93FPDljKWwsOgM=
|
||||||
github.com/google/go-cmp v0.3.0 h1:crn/baboCvb5fXaQ0IJ1SGTsTVrWpDsCWC8EGETZijY=
|
github.com/google/go-cmp v0.3.0 h1:crn/baboCvb5fXaQ0IJ1SGTsTVrWpDsCWC8EGETZijY=
|
||||||
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||||
|
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||||
|
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||||
|
github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk=
|
||||||
|
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||||
github.com/technoweenie/multipartstreamer v1.0.1 h1:XRztA5MXiR1TIRHxH2uNxXxaIkKQDeX7m2XsSOlQEnM=
|
github.com/technoweenie/multipartstreamer v1.0.1 h1:XRztA5MXiR1TIRHxH2uNxXxaIkKQDeX7m2XsSOlQEnM=
|
||||||
github.com/technoweenie/multipartstreamer v1.0.1/go.mod h1:jNVxdtShOxzAsukZwTSw6MDx5eUJoiEBsSvzDU9uzog=
|
github.com/technoweenie/multipartstreamer v1.0.1/go.mod h1:jNVxdtShOxzAsukZwTSw6MDx5eUJoiEBsSvzDU9uzog=
|
||||||
github.com/wsxiaoys/terminal v0.0.0-20160513160801-0940f3fc43a0/go.mod h1:IXCdmsXIht47RaVFLEdVnh1t+pgYtTAhQGj73kz+2DM=
|
github.com/wsxiaoys/terminal v0.0.0-20160513160801-0940f3fc43a0/go.mod h1:IXCdmsXIht47RaVFLEdVnh1t+pgYtTAhQGj73kz+2DM=
|
||||||
|
@ -12,6 +19,7 @@ golang.org/x/net v0.0.0-20180911220305-26e67e76b6c3 h1:czFLhve3vsQetD6JOJ8NZZvGQ
|
||||||
golang.org/x/net v0.0.0-20180911220305-26e67e76b6c3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
golang.org/x/net v0.0.0-20180911220305-26e67e76b6c3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
|
||||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
|
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
gopkg.in/yaml.v2 v2.2.7 h1:VUgggvou5XRW9mHwD/yXxIYSMtY0zoKQf/v226p2nyo=
|
gopkg.in/yaml.v2 v2.2.7 h1:VUgggvou5XRW9mHwD/yXxIYSMtY0zoKQf/v226p2nyo=
|
||||||
gopkg.in/yaml.v2 v2.2.7/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
gopkg.in/yaml.v2 v2.2.7/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
willnorris.com/go/webmention v0.0.0-20191104072158-c7fb13569b62 h1:jqC8A1S2/9WjXSOK/Nl2rYwVgxU7DCnZ/zpOTL1BErI=
|
willnorris.com/go/webmention v0.0.0-20191104072158-c7fb13569b62 h1:jqC8A1S2/9WjXSOK/Nl2rYwVgxU7DCnZ/zpOTL1BErI=
|
||||||
|
|
6
main.go
6
main.go
|
@ -8,12 +8,16 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
initConfig()
|
err := initConfig()
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
log.Println("Starting micropub server...")
|
log.Println("Starting micropub server...")
|
||||||
log.Println("Current time: " + time.Now().Format(time.RFC3339))
|
log.Println("Current time: " + time.Now().Format(time.RFC3339))
|
||||||
log.Println("Blog URL: " + BlogUrl)
|
log.Println("Blog URL: " + BlogUrl)
|
||||||
log.Println("Ignored URLs for Webmention: " + strings.Join(IgnoredWebmentionUrls, ", "))
|
log.Println("Ignored URLs for Webmention: " + strings.Join(IgnoredWebmentionUrls, ", "))
|
||||||
http.HandleFunc("/micropub", HandleMicroPub)
|
http.HandleFunc("/micropub", HandleMicroPub)
|
||||||
|
http.HandleFunc("/media", HandleMedia)
|
||||||
http.HandleFunc("/webmention", HandleWebmention)
|
http.HandleFunc("/webmention", HandleWebmention)
|
||||||
log.Fatal(http.ListenAndServe(":5555", nil))
|
log.Fatal(http.ListenAndServe(":5555", nil))
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,58 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
func HandleMedia(w http.ResponseWriter, r *http.Request) {
|
||||||
|
if r.Method != "POST" {
|
||||||
|
w.WriteHeader(http.StatusMethodNotAllowed)
|
||||||
|
_, _ = w.Write([]byte("The HTTP method is not allowed, make a POST request"))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if contentType := r.Header.Get("content-type"); !strings.Contains(contentType, "multipart/form-data") {
|
||||||
|
w.WriteHeader(http.StatusBadRequest)
|
||||||
|
_, _ = w.Write([]byte("Wrong Content-Type"))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
err := r.ParseMultipartForm(0)
|
||||||
|
if err != nil {
|
||||||
|
w.WriteHeader(http.StatusInternalServerError)
|
||||||
|
_, _ = w.Write([]byte("Failed to parse Multipart"))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
authCode := r.Header.Get("authorization")
|
||||||
|
if formAuth := r.FormValue("authorization"); len(authCode) == 0 && len(formAuth) > 0 {
|
||||||
|
authCode = formAuth
|
||||||
|
}
|
||||||
|
if CheckAuthorization(authCode) {
|
||||||
|
file, header, err := r.FormFile("file")
|
||||||
|
if err != nil {
|
||||||
|
w.WriteHeader(http.StatusInternalServerError)
|
||||||
|
_, _ = w.Write([]byte("Failed to get file"))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
fileName := generateRandomString(time.Now(), 15)
|
||||||
|
mimeType := header.Header.Get("content-type")
|
||||||
|
originalName := header.Filename
|
||||||
|
if strings.Contains(mimeType, "jpeg") || strings.Contains(originalName, ".jpeg") || strings.Contains(originalName, ".jpg") {
|
||||||
|
fileName += ".jpg"
|
||||||
|
} else if strings.Contains(mimeType, "png") || strings.Contains(originalName, ".png") {
|
||||||
|
fileName += ".png"
|
||||||
|
}
|
||||||
|
location, err := SelectedMediaStorage.Upload(fileName, file)
|
||||||
|
if err != nil {
|
||||||
|
w.WriteHeader(http.StatusInternalServerError)
|
||||||
|
_, _ = w.Write([]byte("Failed to upload file"))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
w.Header().Add("Location", location)
|
||||||
|
w.WriteHeader(http.StatusCreated)
|
||||||
|
} else {
|
||||||
|
w.WriteHeader(http.StatusForbidden)
|
||||||
|
_, _ = w.Write([]byte("Forbidden, there was a problem with the provided access token"))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,35 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"mime/multipart"
|
||||||
|
"net/http"
|
||||||
|
"net/url"
|
||||||
|
)
|
||||||
|
|
||||||
|
type MediaStorage interface {
|
||||||
|
Upload(fileName string, file multipart.File) (location string, err error)
|
||||||
|
}
|
||||||
|
|
||||||
|
// BunnyCDN
|
||||||
|
type BunnyCdnStorage struct {
|
||||||
|
// Access Key
|
||||||
|
key string
|
||||||
|
// Storage zone name
|
||||||
|
storageZoneName string
|
||||||
|
// Base location
|
||||||
|
baseLocation string
|
||||||
|
}
|
||||||
|
|
||||||
|
var bunnyCdnStorageUrl = "https://storage.bunnycdn.com"
|
||||||
|
|
||||||
|
func (b BunnyCdnStorage) Upload(fileName string, file multipart.File) (location string, err error) {
|
||||||
|
client := &http.Client{}
|
||||||
|
req, _ := http.NewRequest("PUT", bunnyCdnStorageUrl+"/"+url.PathEscape(b.storageZoneName)+"/"+url.PathEscape("/"+fileName), file)
|
||||||
|
req.Header.Add("AccessKey", b.key)
|
||||||
|
resp, err := client.Do(req)
|
||||||
|
if err != nil || resp.StatusCode != 201 {
|
||||||
|
return "", errors.New("failed to upload file to BunnyCDN")
|
||||||
|
}
|
||||||
|
return b.baseLocation + fileName, nil
|
||||||
|
}
|
|
@ -9,6 +9,7 @@ import (
|
||||||
|
|
||||||
type MicropubConfig struct {
|
type MicropubConfig struct {
|
||||||
SyndicateTo []SyndicationTarget `json:"syndicate-to,omitempty"`
|
SyndicateTo []SyndicationTarget `json:"syndicate-to,omitempty"`
|
||||||
|
MediaEndpoint string `json:"media-endpoint,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func HandleMicroPub(w http.ResponseWriter, r *http.Request) {
|
func HandleMicroPub(w http.ResponseWriter, r *http.Request) {
|
||||||
|
@ -19,6 +20,7 @@ func HandleMicroPub(w http.ResponseWriter, r *http.Request) {
|
||||||
w.WriteHeader(http.StatusOK)
|
w.WriteHeader(http.StatusOK)
|
||||||
jsonBytes, err := json.Marshal(&MicropubConfig{
|
jsonBytes, err := json.Marshal(&MicropubConfig{
|
||||||
SyndicateTo: SyndicationTargets,
|
SyndicateTo: SyndicationTargets,
|
||||||
|
MediaEndpoint: MediaEndpointUrl,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
w.WriteHeader(http.StatusBadRequest)
|
w.WriteHeader(http.StatusBadRequest)
|
||||||
|
@ -71,7 +73,10 @@ func HandleMicroPub(w http.ResponseWriter, r *http.Request) {
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if CheckAuthorization(entry, r.Header.Get("authorization")) {
|
if authHeader := r.Header.Get("authorization"); len(entry.token) == 0 && len(authHeader) > 0 {
|
||||||
|
entry.token = authHeader
|
||||||
|
}
|
||||||
|
if CheckAuthorization(entry.token) {
|
||||||
location, err := WriteEntry(entry)
|
location, err := WriteEntry(entry)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
w.WriteHeader(http.StatusBadRequest)
|
w.WriteHeader(http.StatusBadRequest)
|
||||||
|
|
|
@ -75,13 +75,8 @@ func checkAccess(token string) (bool, error) {
|
||||||
return true, nil
|
return true, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func CheckAuthorization(entry *Entry, token string) bool {
|
func CheckAuthorization(token string) bool {
|
||||||
if len(token) < 1 { // there is no token provided
|
if ok, err := checkAccess(token); ok {
|
||||||
return false
|
|
||||||
} else {
|
|
||||||
entry.token = token
|
|
||||||
}
|
|
||||||
if ok, err := checkAccess(entry.token); ok {
|
|
||||||
return true
|
return true
|
||||||
} else if err != nil {
|
} else if err != nil {
|
||||||
return false
|
return false
|
||||||
|
|
Loading…
Reference in New Issue