nlink/nomad/post.go

163 lines
3.0 KiB
Go

package nomad
import (
"bytes"
"errors"
"fmt"
"net/url"
"path/filepath"
"git.sr.ht/~thrrgilag/woodstock"
"git.wntrmute.dev/kyle/goutils/log"
"github.com/anaskhan96/soup"
)
func nomadLink(item Item) string {
if item.Title != "" {
return fmt.Sprintf("[%s](%s)", item.Title, item.URL.ID())
}
u, err := url.Parse(item.URL.ID())
if err != nil {
log.Errf("nomadLink: %s", err)
return fmt.Sprintf("[%s](%s)", item.URL.ID(), item.URL.ID())
}
return fmt.Sprintf("[%s](%s)", u.Host, item.URL.ID())
}
type sel struct {
selectors []string
}
func selector(selectors ...string) sel {
return sel{selectors: selectors}
}
type imageFinder func(soup.Root) (string, bool)
var imageFinders = []imageFinder{
func(root soup.Root) (string, bool) {
return find(
root, "src",
selector("div", "class", "entry-image"),
selector("img"))
},
func(root soup.Root) (string, bool) {
return find(
root, "src",
selector("div", "class", "gh-inner"),
selector("img"))
},
}
func find(root soup.Root, attr string, selectors ...sel) (string, bool) {
result := root
for _, selector := range selectors {
result = result.Find(selector.selectors...)
if result.Pointer == nil {
return "", false
}
}
if attr == "" {
text := result.Text()
return text, text != ""
}
value, hasAttr := result.Attrs()[attr]
return value, hasAttr
}
type Post struct {
Title string
Image Source
Body string
URL Source
}
func NewPost(item Item) Post {
post := Post{
Body: nomadLink(item),
URL: item.URL,
}
return post
}
func (p *Post) Fetch() error {
pageSource, err := p.URL.Fetch()
if err != nil {
return err
}
root := soup.HTMLParse(pageSource)
body, hasBody := find(root, "", selector("p", "class", "entry-body"))
if hasBody {
p.Body = body + " " + p.Body
}
var imageURL string
var hasImageURL bool
for _, finder := range imageFinders {
imageURL, hasImageURL = finder(root)
if hasImageURL {
break
}
}
if hasImageURL {
p.Image = NewURLSource(imageURL)
}
return nil
}
func (p Post) Post(client *woodstock.Client) error {
pnutPost := woodstock.NewPost{
Text: p.Body,
}
if p.Image != nil {
imageData, err := p.Image.FetchBytes()
if err != nil {
return err
}
params := map[string]string{
"name": filepath.Base(p.Image.ID()),
"is_public": "1",
"type": "photo",
}
r := bytes.NewBuffer(imageData)
file, err := client.CreateFile(params, r)
if err != nil {
panic(err.Error())
return err
}
pnutPost.Raw = []woodstock.Raw{pnutOembedRaw(file)}
}
result, err := client.Post(pnutPost)
if err != nil {
return err
}
if result.Meta.ErrorMessage != "" {
return errors.New("woodstock: " + result.Meta.ErrorMessage)
}
return nil
}
func pnutOembedRaw(file woodstock.FileResult) woodstock.Raw {
fval := map[string]string{
"file_id": file.Data.ID,
"file_token": file.Data.FileToken,
"format": "oembed",
}
value := map[string]map[string]string{"+io.pnut.core.file": fval}
return woodstock.Raw{Type: "io.pnut.core.oembed", Value: value}
}