2022-08-03 14:55:48 +00:00
|
|
|
package owl
|
2022-07-21 17:02:37 +00:00
|
|
|
|
|
|
|
import (
|
2022-07-21 17:44:07 +00:00
|
|
|
"bytes"
|
2022-09-10 12:22:06 +00:00
|
|
|
"errors"
|
2022-09-04 15:10:40 +00:00
|
|
|
"net/url"
|
2022-10-13 19:00:28 +00:00
|
|
|
"os"
|
2022-07-21 17:02:37 +00:00
|
|
|
"path"
|
2022-09-01 19:53:06 +00:00
|
|
|
"sort"
|
2022-09-09 19:14:49 +00:00
|
|
|
"sync"
|
2022-09-04 15:10:40 +00:00
|
|
|
"time"
|
2022-07-21 17:44:07 +00:00
|
|
|
|
|
|
|
"github.com/yuin/goldmark"
|
2022-07-27 19:26:37 +00:00
|
|
|
"github.com/yuin/goldmark/extension"
|
2022-07-21 17:44:07 +00:00
|
|
|
"github.com/yuin/goldmark/parser"
|
2022-08-21 09:31:48 +00:00
|
|
|
"github.com/yuin/goldmark/renderer/html"
|
2022-08-13 17:07:10 +00:00
|
|
|
"gopkg.in/yaml.v2"
|
2022-07-21 17:02:37 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
type Post struct {
|
2022-08-22 19:15:36 +00:00
|
|
|
user *User
|
|
|
|
id string
|
|
|
|
title string
|
|
|
|
metaLoaded bool
|
|
|
|
meta PostMeta
|
2022-09-09 19:14:49 +00:00
|
|
|
wmLock sync.Mutex
|
2022-07-21 17:02:37 +00:00
|
|
|
}
|
|
|
|
|
2022-10-10 18:59:06 +00:00
|
|
|
type Reply struct {
|
|
|
|
Url string `yaml:"url"`
|
|
|
|
Text string `yaml:"text"`
|
|
|
|
}
|
2022-12-04 14:45:51 +00:00
|
|
|
type Bookmark struct {
|
|
|
|
Url string `yaml:"url"`
|
|
|
|
Text string `yaml:"text"`
|
|
|
|
}
|
2022-10-10 18:59:06 +00:00
|
|
|
|
2022-08-13 17:07:10 +00:00
|
|
|
type PostMeta struct {
|
2022-11-29 19:36:50 +00:00
|
|
|
Type string `yaml:"type"`
|
2022-10-19 19:14:31 +00:00
|
|
|
Title string `yaml:"title"`
|
|
|
|
Description string `yaml:"description"`
|
|
|
|
Aliases []string `yaml:"aliases"`
|
|
|
|
Date time.Time `yaml:"date"`
|
|
|
|
Draft bool `yaml:"draft"`
|
|
|
|
Reply Reply `yaml:"reply"`
|
2022-12-04 14:45:51 +00:00
|
|
|
Bookmark Bookmark `yaml:"bookmark"`
|
2022-09-11 15:25:26 +00:00
|
|
|
}
|
|
|
|
|
2022-09-11 15:34:50 +00:00
|
|
|
func (pm PostMeta) FormattedDate() string {
|
|
|
|
return pm.Date.Format("02-01-2006 15:04:05")
|
|
|
|
}
|
|
|
|
|
2022-09-11 15:25:26 +00:00
|
|
|
func (pm *PostMeta) UnmarshalYAML(unmarshal func(interface{}) error) error {
|
|
|
|
type T struct {
|
2022-11-29 19:36:50 +00:00
|
|
|
Type string `yaml:"type"`
|
2022-10-19 19:14:31 +00:00
|
|
|
Title string `yaml:"title"`
|
|
|
|
Description string `yaml:"description"`
|
|
|
|
Aliases []string `yaml:"aliases"`
|
|
|
|
Draft bool `yaml:"draft"`
|
|
|
|
Reply Reply `yaml:"reply"`
|
2022-12-04 14:45:51 +00:00
|
|
|
Bookmark Bookmark `yaml:"bookmark"`
|
2022-09-11 15:25:26 +00:00
|
|
|
}
|
|
|
|
type S struct {
|
|
|
|
Date string `yaml:"date"`
|
|
|
|
}
|
|
|
|
|
|
|
|
var t T
|
|
|
|
var s S
|
|
|
|
if err := unmarshal(&t); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
if err := unmarshal(&s); err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
2022-11-29 19:36:50 +00:00
|
|
|
pm.Type = t.Type
|
|
|
|
if pm.Type == "" {
|
|
|
|
pm.Type = "article"
|
|
|
|
}
|
2022-09-11 15:25:26 +00:00
|
|
|
pm.Title = t.Title
|
2022-10-19 19:14:31 +00:00
|
|
|
pm.Description = t.Description
|
2022-09-11 15:25:26 +00:00
|
|
|
pm.Aliases = t.Aliases
|
|
|
|
pm.Draft = t.Draft
|
2022-10-10 18:59:06 +00:00
|
|
|
pm.Reply = t.Reply
|
2022-12-04 14:45:51 +00:00
|
|
|
pm.Bookmark = t.Bookmark
|
2022-09-11 15:25:26 +00:00
|
|
|
|
|
|
|
possibleFormats := []string{
|
|
|
|
"2006-01-02",
|
|
|
|
time.Layout,
|
|
|
|
time.ANSIC,
|
|
|
|
time.UnixDate,
|
|
|
|
time.RubyDate,
|
|
|
|
time.RFC822,
|
|
|
|
time.RFC822Z,
|
|
|
|
time.RFC850,
|
|
|
|
time.RFC1123,
|
|
|
|
time.RFC1123Z,
|
|
|
|
time.RFC3339,
|
|
|
|
time.RFC3339Nano,
|
|
|
|
time.Stamp,
|
|
|
|
time.StampMilli,
|
|
|
|
time.StampMicro,
|
|
|
|
time.StampNano,
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, format := range possibleFormats {
|
|
|
|
if t, err := time.Parse(format, s.Date); err == nil {
|
|
|
|
pm.Date = t
|
|
|
|
break
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
2022-08-13 17:07:10 +00:00
|
|
|
}
|
|
|
|
|
2022-09-07 20:06:59 +00:00
|
|
|
type PostWebmetions struct {
|
|
|
|
Incoming []WebmentionIn `ymal:"incoming"`
|
|
|
|
Outgoing []WebmentionOut `ymal:"outgoing"`
|
2022-09-04 13:03:16 +00:00
|
|
|
}
|
|
|
|
|
2022-09-09 19:14:49 +00:00
|
|
|
func (post *Post) Id() string {
|
2022-08-03 17:41:13 +00:00
|
|
|
return post.id
|
|
|
|
}
|
|
|
|
|
2022-10-07 17:51:13 +00:00
|
|
|
func (post *Post) User() *User {
|
|
|
|
return post.user
|
|
|
|
}
|
|
|
|
|
2022-09-09 19:14:49 +00:00
|
|
|
func (post *Post) Dir() string {
|
2022-07-21 17:02:37 +00:00
|
|
|
return path.Join(post.user.Dir(), "public", post.id)
|
|
|
|
}
|
|
|
|
|
2022-10-07 14:49:26 +00:00
|
|
|
func (post *Post) IncomingWebmentionsFile() string {
|
|
|
|
return path.Join(post.Dir(), "incoming_webmentions.yml")
|
|
|
|
}
|
|
|
|
|
|
|
|
func (post *Post) OutgoingWebmentionsFile() string {
|
|
|
|
return path.Join(post.Dir(), "outgoing_webmentions.yml")
|
2022-09-04 13:32:37 +00:00
|
|
|
}
|
|
|
|
|
2022-09-09 19:14:49 +00:00
|
|
|
func (post *Post) MediaDir() string {
|
2022-08-01 17:50:29 +00:00
|
|
|
return path.Join(post.Dir(), "media")
|
|
|
|
}
|
|
|
|
|
2022-09-09 19:14:49 +00:00
|
|
|
func (post *Post) UrlPath() string {
|
2022-08-03 17:41:13 +00:00
|
|
|
return post.user.UrlPath() + "posts/" + post.id + "/"
|
|
|
|
}
|
|
|
|
|
2022-09-09 19:14:49 +00:00
|
|
|
func (post *Post) FullUrl() string {
|
2022-08-13 16:47:27 +00:00
|
|
|
return post.user.FullUrl() + "posts/" + post.id + "/"
|
|
|
|
}
|
|
|
|
|
2022-09-09 19:14:49 +00:00
|
|
|
func (post *Post) UrlMediaPath(filename string) string {
|
2022-08-03 17:41:13 +00:00
|
|
|
return post.UrlPath() + "media/" + filename
|
2022-07-23 15:19:47 +00:00
|
|
|
}
|
|
|
|
|
2022-09-09 19:14:49 +00:00
|
|
|
func (post *Post) Title() string {
|
2022-07-21 17:44:07 +00:00
|
|
|
return post.title
|
|
|
|
}
|
|
|
|
|
2022-09-09 19:14:49 +00:00
|
|
|
func (post *Post) ContentFile() string {
|
2022-07-21 17:02:37 +00:00
|
|
|
return path.Join(post.Dir(), "index.md")
|
|
|
|
}
|
|
|
|
|
2022-08-22 19:15:36 +00:00
|
|
|
func (post *Post) Meta() PostMeta {
|
|
|
|
if !post.metaLoaded {
|
|
|
|
post.LoadMeta()
|
|
|
|
}
|
|
|
|
return post.meta
|
|
|
|
}
|
|
|
|
|
2022-09-09 19:14:49 +00:00
|
|
|
func (post *Post) Content() []byte {
|
2022-07-21 17:02:37 +00:00
|
|
|
// read file
|
2022-10-13 19:00:28 +00:00
|
|
|
data, _ := os.ReadFile(post.ContentFile())
|
2022-07-21 17:02:37 +00:00
|
|
|
return data
|
|
|
|
}
|
2022-07-21 17:44:07 +00:00
|
|
|
|
2022-12-01 18:37:13 +00:00
|
|
|
func (post *Post) RenderedContent() string {
|
2022-07-21 17:44:07 +00:00
|
|
|
data := post.Content()
|
2022-08-13 17:07:10 +00:00
|
|
|
|
2022-08-22 19:15:36 +00:00
|
|
|
// trim yaml block
|
|
|
|
// TODO this can be done nicer
|
2022-08-13 17:07:10 +00:00
|
|
|
trimmedData := bytes.TrimSpace(data)
|
2022-12-05 17:46:00 +00:00
|
|
|
// ensure that data ends with a newline
|
|
|
|
trimmedData = append(trimmedData, []byte("\n")...)
|
2022-08-13 17:07:10 +00:00
|
|
|
// check first line is ---
|
|
|
|
if string(trimmedData[0:4]) == "---\n" {
|
|
|
|
trimmedData = trimmedData[4:]
|
|
|
|
// find --- end
|
|
|
|
end := bytes.Index(trimmedData, []byte("\n---\n"))
|
|
|
|
if end != -1 {
|
|
|
|
data = trimmedData[end+5:]
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-08-21 09:31:48 +00:00
|
|
|
options := goldmark.WithRendererOptions()
|
2022-09-05 18:50:46 +00:00
|
|
|
if config, _ := post.user.repo.Config(); config.AllowRawHtml {
|
2022-08-21 09:31:48 +00:00
|
|
|
options = goldmark.WithRendererOptions(
|
|
|
|
html.WithUnsafe(),
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
2022-07-21 17:44:07 +00:00
|
|
|
markdown := goldmark.New(
|
2022-08-21 09:31:48 +00:00
|
|
|
options,
|
2022-07-21 17:44:07 +00:00
|
|
|
goldmark.WithExtensions(
|
2022-08-13 17:07:10 +00:00
|
|
|
// meta.Meta,
|
2022-07-27 19:26:37 +00:00
|
|
|
extension.GFM,
|
2022-07-21 17:44:07 +00:00
|
|
|
),
|
|
|
|
)
|
|
|
|
var buf bytes.Buffer
|
|
|
|
context := parser.NewContext()
|
|
|
|
if err := markdown.Convert(data, &buf, parser.WithContext(context)); err != nil {
|
|
|
|
panic(err)
|
|
|
|
}
|
|
|
|
|
2022-12-01 18:37:13 +00:00
|
|
|
return buf.String()
|
2022-07-21 17:44:07 +00:00
|
|
|
|
|
|
|
}
|
2022-08-06 17:38:13 +00:00
|
|
|
|
2022-09-09 19:14:49 +00:00
|
|
|
func (post *Post) Aliases() []string {
|
2022-08-22 19:15:36 +00:00
|
|
|
return post.Meta().Aliases
|
|
|
|
}
|
|
|
|
|
|
|
|
func (post *Post) LoadMeta() error {
|
|
|
|
data := post.Content()
|
|
|
|
|
|
|
|
// get yaml metadata block
|
|
|
|
meta := PostMeta{}
|
|
|
|
trimmedData := bytes.TrimSpace(data)
|
|
|
|
// check first line is ---
|
|
|
|
if string(trimmedData[0:4]) == "---\n" {
|
|
|
|
trimmedData = trimmedData[4:]
|
|
|
|
// find --- end
|
2022-10-10 18:59:06 +00:00
|
|
|
end := bytes.Index(trimmedData, []byte("---\n"))
|
2022-08-22 19:15:36 +00:00
|
|
|
if end != -1 {
|
|
|
|
metaData := trimmedData[:end]
|
|
|
|
err := yaml.Unmarshal(metaData, &meta)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
post.meta = meta
|
|
|
|
return nil
|
2022-08-06 17:38:13 +00:00
|
|
|
}
|
2022-08-23 15:59:17 +00:00
|
|
|
|
2022-10-07 14:49:26 +00:00
|
|
|
func (post *Post) IncomingWebmentions() []WebmentionIn {
|
2022-09-10 11:44:25 +00:00
|
|
|
// return parsed webmentions
|
2022-10-07 14:49:26 +00:00
|
|
|
fileName := post.IncomingWebmentionsFile()
|
2022-09-10 11:44:25 +00:00
|
|
|
if !fileExists(fileName) {
|
2022-10-07 14:49:26 +00:00
|
|
|
return []WebmentionIn{}
|
2022-09-10 11:44:25 +00:00
|
|
|
}
|
|
|
|
|
2022-10-07 14:49:26 +00:00
|
|
|
webmentions := []WebmentionIn{}
|
2022-10-13 18:48:01 +00:00
|
|
|
loadFromYaml(fileName, &webmentions)
|
2022-09-10 11:44:25 +00:00
|
|
|
|
|
|
|
return webmentions
|
|
|
|
}
|
|
|
|
|
|
|
|
func (post *Post) OutgoingWebmentions() []WebmentionOut {
|
2022-10-07 14:49:26 +00:00
|
|
|
// return parsed webmentions
|
|
|
|
fileName := post.OutgoingWebmentionsFile()
|
|
|
|
if !fileExists(fileName) {
|
|
|
|
return []WebmentionOut{}
|
|
|
|
}
|
2022-09-10 11:44:25 +00:00
|
|
|
|
2022-10-07 14:49:26 +00:00
|
|
|
webmentions := []WebmentionOut{}
|
2022-10-13 18:48:01 +00:00
|
|
|
loadFromYaml(fileName, &webmentions)
|
2022-09-10 11:44:25 +00:00
|
|
|
|
2022-10-07 14:49:26 +00:00
|
|
|
return webmentions
|
2022-09-10 11:44:25 +00:00
|
|
|
}
|
|
|
|
|
2022-09-10 12:04:13 +00:00
|
|
|
// PersistWebmentionOutgoing persists incoming webmention
|
2022-09-07 20:06:59 +00:00
|
|
|
func (post *Post) PersistIncomingWebmention(webmention WebmentionIn) error {
|
2022-09-10 12:04:13 +00:00
|
|
|
post.wmLock.Lock()
|
|
|
|
defer post.wmLock.Unlock()
|
|
|
|
|
2022-10-07 14:49:26 +00:00
|
|
|
wms := post.IncomingWebmentions()
|
2022-09-01 19:34:33 +00:00
|
|
|
|
2022-09-07 20:06:59 +00:00
|
|
|
// if target is not in status, add it
|
|
|
|
replaced := false
|
2022-10-07 14:49:26 +00:00
|
|
|
for i, t := range wms {
|
2022-09-07 20:06:59 +00:00
|
|
|
if t.Source == webmention.Source {
|
2022-10-07 14:49:26 +00:00
|
|
|
wms[i].UpdateWith(webmention)
|
2022-09-07 20:06:59 +00:00
|
|
|
replaced = true
|
|
|
|
break
|
|
|
|
}
|
2022-09-01 19:34:33 +00:00
|
|
|
}
|
|
|
|
|
2022-09-07 20:06:59 +00:00
|
|
|
if !replaced {
|
2022-10-07 14:49:26 +00:00
|
|
|
wms = append(wms, webmention)
|
|
|
|
}
|
|
|
|
|
2022-10-13 18:48:01 +00:00
|
|
|
err := saveToYaml(post.IncomingWebmentionsFile(), wms)
|
2022-10-07 14:49:26 +00:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
2022-09-10 11:44:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// PersistOutgoingWebmention persists a webmention to the webmention file.
|
2022-09-10 12:04:13 +00:00
|
|
|
func (post *Post) PersistOutgoingWebmention(webmention *WebmentionOut) error {
|
2022-09-10 11:44:25 +00:00
|
|
|
post.wmLock.Lock()
|
|
|
|
defer post.wmLock.Unlock()
|
|
|
|
|
2022-10-07 14:49:26 +00:00
|
|
|
wms := post.OutgoingWebmentions()
|
2022-09-10 11:44:25 +00:00
|
|
|
|
|
|
|
// if target is not in webmention, add it
|
|
|
|
replaced := false
|
2022-10-07 14:49:26 +00:00
|
|
|
for i, t := range wms {
|
2022-09-10 11:44:25 +00:00
|
|
|
if t.Target == webmention.Target {
|
2022-10-07 14:49:26 +00:00
|
|
|
wms[i].UpdateWith(*webmention)
|
2022-09-10 11:44:25 +00:00
|
|
|
replaced = true
|
|
|
|
break
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if !replaced {
|
2022-10-07 14:49:26 +00:00
|
|
|
wms = append(wms, *webmention)
|
2022-09-10 11:44:25 +00:00
|
|
|
}
|
|
|
|
|
2022-10-13 18:48:01 +00:00
|
|
|
err := saveToYaml(post.OutgoingWebmentionsFile(), wms)
|
2022-10-07 14:49:26 +00:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
2022-09-07 20:06:59 +00:00
|
|
|
}
|
2022-09-01 19:34:33 +00:00
|
|
|
|
2022-09-07 20:06:59 +00:00
|
|
|
func (post *Post) AddIncomingWebmention(source string) error {
|
2022-08-24 20:11:39 +00:00
|
|
|
// Check if file already exists
|
2022-09-10 12:04:13 +00:00
|
|
|
wm := WebmentionIn{
|
|
|
|
Source: source,
|
2022-08-24 20:11:39 +00:00
|
|
|
}
|
2022-09-01 19:34:33 +00:00
|
|
|
|
2022-09-10 12:04:13 +00:00
|
|
|
defer func() {
|
|
|
|
go post.EnrichWebmention(wm)
|
|
|
|
}()
|
|
|
|
return post.PersistIncomingWebmention(wm)
|
|
|
|
}
|
2022-09-09 19:14:49 +00:00
|
|
|
|
2022-09-10 12:04:13 +00:00
|
|
|
func (post *Post) EnrichWebmention(webmention WebmentionIn) error {
|
|
|
|
resp, err := post.user.repo.HttpClient.Get(webmention.Source)
|
2022-08-31 18:01:58 +00:00
|
|
|
if err == nil {
|
2022-09-06 18:32:21 +00:00
|
|
|
entry, err := post.user.repo.Parser.ParseHEntry(resp)
|
2022-08-31 18:01:58 +00:00
|
|
|
if err == nil {
|
2022-09-01 19:34:33 +00:00
|
|
|
webmention.Title = entry.Title
|
2022-09-07 20:06:59 +00:00
|
|
|
return post.PersistIncomingWebmention(webmention)
|
2022-08-31 18:01:58 +00:00
|
|
|
}
|
|
|
|
}
|
2022-09-01 19:34:33 +00:00
|
|
|
return err
|
2022-08-23 15:59:17 +00:00
|
|
|
}
|
|
|
|
|
2022-09-10 11:44:25 +00:00
|
|
|
func (post *Post) ApprovedIncomingWebmentions() []WebmentionIn {
|
2022-09-07 20:06:59 +00:00
|
|
|
webmentions := post.IncomingWebmentions()
|
2022-09-04 13:03:16 +00:00
|
|
|
approved := []WebmentionIn{}
|
2022-09-01 19:53:06 +00:00
|
|
|
for _, webmention := range webmentions {
|
|
|
|
if webmention.ApprovalStatus == "approved" {
|
|
|
|
approved = append(approved, webmention)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// sort by retrieved date
|
|
|
|
sort.Slice(approved, func(i, j int) bool {
|
|
|
|
return approved[i].RetrievedAt.After(approved[j].RetrievedAt)
|
|
|
|
})
|
|
|
|
return approved
|
|
|
|
}
|
2022-09-04 13:32:37 +00:00
|
|
|
|
|
|
|
// ScanForLinks scans the post content for links and adds them to the
|
|
|
|
// `status.yml` file for the post. The links are not scanned by this function.
|
|
|
|
func (post *Post) ScanForLinks() error {
|
|
|
|
// this could be done in markdown parsing, but I don't want to
|
|
|
|
// rely on goldmark for this (yet)
|
2022-09-06 18:00:12 +00:00
|
|
|
postHtml := post.RenderedContent()
|
2022-12-01 18:37:13 +00:00
|
|
|
links, _ := post.user.repo.Parser.ParseLinksFromString(postHtml)
|
2022-10-10 19:06:33 +00:00
|
|
|
// add reply url if set
|
|
|
|
if post.Meta().Reply.Url != "" {
|
|
|
|
links = append(links, post.Meta().Reply.Url)
|
|
|
|
}
|
2022-09-04 13:32:37 +00:00
|
|
|
for _, link := range links {
|
2022-09-10 11:44:25 +00:00
|
|
|
post.PersistOutgoingWebmention(&WebmentionOut{
|
|
|
|
Target: link,
|
2022-09-10 12:04:13 +00:00
|
|
|
})
|
2022-09-04 13:32:37 +00:00
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|
2022-09-04 15:10:40 +00:00
|
|
|
|
|
|
|
func (post *Post) SendWebmention(webmention WebmentionOut) error {
|
2022-09-10 12:04:13 +00:00
|
|
|
defer post.PersistOutgoingWebmention(&webmention)
|
2022-09-10 12:16:22 +00:00
|
|
|
|
|
|
|
// if last scan is less than 7 days ago, don't send webmention
|
|
|
|
if webmention.ScannedAt.After(time.Now().Add(-7*24*time.Hour)) && !webmention.Supported {
|
2022-09-10 12:22:06 +00:00
|
|
|
return errors.New("did not scan. Last scan was less than 7 days ago")
|
2022-09-10 12:16:22 +00:00
|
|
|
}
|
|
|
|
|
2022-09-04 15:10:40 +00:00
|
|
|
webmention.ScannedAt = time.Now()
|
|
|
|
|
2022-09-06 18:32:21 +00:00
|
|
|
resp, err := post.user.repo.HttpClient.Get(webmention.Target)
|
2022-09-04 15:10:40 +00:00
|
|
|
if err != nil {
|
|
|
|
webmention.Supported = false
|
|
|
|
return err
|
|
|
|
}
|
2022-09-06 17:47:15 +00:00
|
|
|
|
2022-09-06 18:32:21 +00:00
|
|
|
endpoint, err := post.user.repo.Parser.GetWebmentionEndpoint(resp)
|
2022-09-04 15:10:40 +00:00
|
|
|
if err != nil {
|
|
|
|
webmention.Supported = false
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
webmention.Supported = true
|
|
|
|
|
|
|
|
// send webmention
|
|
|
|
payload := url.Values{}
|
|
|
|
payload.Set("source", post.FullUrl())
|
|
|
|
payload.Set("target", webmention.Target)
|
2022-09-06 18:32:21 +00:00
|
|
|
_, err = post.user.repo.HttpClient.PostForm(endpoint, payload)
|
2022-09-04 15:10:40 +00:00
|
|
|
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
// update webmention status
|
|
|
|
webmention.LastSentAt = time.Now()
|
|
|
|
return nil
|
|
|
|
}
|