163 lines
3.0 KiB
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}
|
|
}
|