152 lines
3.6 KiB
Go
152 lines
3.6 KiB
Go
package app
|
|
|
|
import (
|
|
"fmt"
|
|
"net/url"
|
|
"owl-blogs/app/owlhttp"
|
|
"owl-blogs/app/repository"
|
|
"owl-blogs/domain/model"
|
|
"owl-blogs/interactions"
|
|
"time"
|
|
)
|
|
|
|
type WebmentionService struct {
|
|
siteConfigService *SiteConfigService
|
|
InteractionRepository repository.InteractionRepository
|
|
EntryRepository repository.EntryRepository
|
|
Http owlhttp.HttpClient
|
|
}
|
|
|
|
func NewWebmentionService(
|
|
siteConfigService *SiteConfigService,
|
|
interactionRepository repository.InteractionRepository,
|
|
entryRepository repository.EntryRepository,
|
|
http owlhttp.HttpClient,
|
|
bus *EventBus,
|
|
) *WebmentionService {
|
|
svc := &WebmentionService{
|
|
siteConfigService: siteConfigService,
|
|
InteractionRepository: interactionRepository,
|
|
EntryRepository: entryRepository,
|
|
Http: http,
|
|
}
|
|
bus.Subscribe(svc)
|
|
return svc
|
|
}
|
|
|
|
func (s *WebmentionService) GetExistingWebmention(entryId string, source string, target string) (*interactions.Webmention, error) {
|
|
inters, err := s.InteractionRepository.FindAll(entryId)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
for _, interaction := range inters {
|
|
if webm, ok := interaction.(*interactions.Webmention); ok {
|
|
m := webm.MetaData().(*interactions.WebmentionMetaData)
|
|
if m.Source == source && m.Target == target {
|
|
return webm, nil
|
|
}
|
|
}
|
|
}
|
|
return nil, nil
|
|
}
|
|
|
|
func (s *WebmentionService) ProcessWebmention(source string, target string) error {
|
|
resp, err := s.Http.Get(source)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
hEntry, err := ParseHEntry(resp)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
entryId := UrlToEntryId(target)
|
|
_, err = s.EntryRepository.FindById(entryId)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
webmention, err := s.GetExistingWebmention(entryId, source, target)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if webmention != nil {
|
|
data := interactions.WebmentionMetaData{
|
|
Source: source,
|
|
Target: target,
|
|
Title: hEntry.Title,
|
|
}
|
|
webmention.SetMetaData(&data)
|
|
webmention.SetEntryID(entryId)
|
|
webmention.SetCreatedAt(time.Now())
|
|
err = s.InteractionRepository.Update(webmention)
|
|
return err
|
|
} else {
|
|
webmention = &interactions.Webmention{}
|
|
data := interactions.WebmentionMetaData{
|
|
Source: source,
|
|
Target: target,
|
|
Title: hEntry.Title,
|
|
}
|
|
webmention.SetMetaData(&data)
|
|
webmention.SetEntryID(entryId)
|
|
webmention.SetCreatedAt(time.Now())
|
|
err = s.InteractionRepository.Create(webmention)
|
|
return err
|
|
}
|
|
}
|
|
|
|
func (s *WebmentionService) ScanForLinks(entry model.Entry) ([]string, error) {
|
|
content := string(entry.Content())
|
|
return ParseLinksFromString(content)
|
|
}
|
|
|
|
func (s *WebmentionService) FullEntryUrl(entry model.Entry) string {
|
|
siteConfig, _ := s.siteConfigService.GetSiteConfig()
|
|
|
|
url, _ := url.JoinPath(
|
|
siteConfig.FullUrl,
|
|
fmt.Sprintf("/posts/%s/", entry.ID()),
|
|
)
|
|
return url
|
|
}
|
|
|
|
func (s *WebmentionService) SendWebmention(entry model.Entry) error {
|
|
links, err := s.ScanForLinks(entry)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
for _, target := range links {
|
|
resp, err := s.Http.Get(target)
|
|
if err != nil {
|
|
continue
|
|
}
|
|
endpoint, err := GetWebmentionEndpoint(resp)
|
|
if err != nil {
|
|
continue
|
|
}
|
|
payload := url.Values{}
|
|
payload.Set("source", s.FullEntryUrl(entry))
|
|
payload.Set("target", target)
|
|
_, err = s.Http.PostForm(endpoint, payload)
|
|
if err != nil {
|
|
continue
|
|
}
|
|
println("Send webmention for target", target)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (s *WebmentionService) NotifyEntryCreated(entry model.Entry) {
|
|
s.SendWebmention(entry)
|
|
}
|
|
|
|
func (s *WebmentionService) NotifyEntryUpdated(entry model.Entry) {
|
|
s.SendWebmention(entry)
|
|
}
|
|
|
|
func (s *WebmentionService) NotifyEntryDeleted(entry model.Entry) {
|
|
s.SendWebmention(entry)
|
|
}
|