diff --git a/cmd/owl/webmention.go b/cmd/owl/webmention.go new file mode 100644 index 0000000..0de0233 --- /dev/null +++ b/cmd/owl/webmention.go @@ -0,0 +1,70 @@ +package main + +import ( + "h4kor/owl-blogs" + + "github.com/spf13/cobra" +) + +func init() { + rootCmd.AddCommand(webmentionCmd) +} + +var webmentionCmd = &cobra.Command{ + Use: "webmention", + Short: "Send webmentions for posts, optionally for a specific user", + Long: `Send webmentions for posts, optionally for a specific user`, + Run: func(cmd *cobra.Command, args []string) { + repo, err := owl.OpenRepository(repoPath) + if err != nil { + println("Error opening repository: ", err.Error()) + return + } + + var users []owl.User + if user == "" { + // send webmentions for all users + users, err = repo.Users() + if err != nil { + println("Error getting users: ", err.Error()) + return + } + } else { + // send webmentions for a specific user + user, err := repo.GetUser(user) + users = append(users, user) + if err != nil { + println("Error getting user: ", err.Error()) + return + } + } + + for _, user := range users { + posts, err := user.Posts() + if err != nil { + println("Error getting posts: ", err.Error()) + } + + for _, post := range posts { + println("Webmentions for post: ", post.Title()) + + err := post.ScanForLinks() + if err != nil { + println("Error scanning post for links: ", err.Error()) + continue + } + + webmentions := post.OutgoingWebmentions() + println("Found ", len(webmentions), " links") + for _, webmention := range webmentions { + err = post.SendWebmention(webmention) + if err != nil { + println("Error sending webmentions: ", err.Error()) + } else { + println("Webmention sent to ", webmention.Target) + } + } + } + } + }, +} diff --git a/post.go b/post.go index bc6479f..7cbb729 100644 --- a/post.go +++ b/post.go @@ -375,13 +375,12 @@ func (post *Post) SendWebmention(webmention WebmentionOut) error { html, err := post.user.repo.HttpClient.Get(webmention.Target) if err != nil { - // TODO handle error webmention.Supported = false return err } + endpoint, err := post.user.repo.Parser.GetWebmentionEndpoint(html) if err != nil { - // TODO handle error webmention.Supported = false return err } @@ -394,7 +393,6 @@ func (post *Post) SendWebmention(webmention WebmentionOut) error { _, err = post.user.repo.HttpClient.Post(endpoint, payload) if err != nil { - // TODO handle error return err } diff --git a/webmention.go b/webmention.go index df4ab33..8b4eb70 100644 --- a/webmention.go +++ b/webmention.go @@ -3,6 +3,8 @@ package owl import ( "bytes" "errors" + "fmt" + "io" "net/http" "net/url" "strings" @@ -46,13 +48,16 @@ type ParsedHEntry struct { func (OwlHttpClient) Get(url string) ([]byte, error) { resp, err := http.Get(url) + + if resp.StatusCode < 200 || resp.StatusCode > 299 { + return make([]byte, 0), errors.New("Failed to get url. Status code: " + fmt.Sprint(resp.StatusCode)) + } + if err != nil { return []byte{}, err } - var data []byte - _, err = resp.Body.Read(data) - // TODO: encoding - return data, err + defer resp.Body.Close() + return io.ReadAll(resp.Body) } func (OwlHttpClient) Post(url string, data url.Values) ([]byte, error) { @@ -60,10 +65,8 @@ func (OwlHttpClient) Post(url string, data url.Values) ([]byte, error) { if err != nil { return []byte{}, err } - var respData []byte - _, err = resp.Body.Read(respData) - - return respData, err + defer resp.Body.Close() + return io.ReadAll(resp.Body) } func collectText(n *html.Node, buf *bytes.Buffer) { @@ -152,7 +155,7 @@ func (OwlHtmlParser) GetWebmentionEndpoint(data []byte) (string, error) { var findEndpoint func(*html.Node) (string, error) findEndpoint = func(n *html.Node) (string, error) { - if n.Type == html.ElementNode && n.Data == "link" { + if n.Type == html.ElementNode && (n.Data == "link" || n.Data == "a") { for _, attr := range n.Attr { if attr.Key == "rel" && attr.Val == "webmention" { for _, attr := range n.Attr { diff --git a/webmention_test.go b/webmention_test.go index c7e95c7..c49d158 100644 --- a/webmention_test.go +++ b/webmention_test.go @@ -34,3 +34,29 @@ func TestParseValidHEntryWithoutTitle(t *testing.T) { t.Errorf("Wrong Title. Expected %v, got %v", "Foo", entry.Title) } } + +func TestGetWebmentionEndpointLink(t *testing.T) { + html := []byte("") + parser := &owl.OwlHtmlParser{} + endpoint, err := parser.GetWebmentionEndpoint(html) + + if err != nil { + t.Errorf("Unable to parse feed: %v", err) + } + if endpoint != "http://example.com/webmention" { + t.Errorf("Wrong endpoint. Expected %v, got %v", "http://example.com/webmention", endpoint) + } +} + +func TestGetWebmentionEndpointLinkA(t *testing.T) { + html := []byte("") + parser := &owl.OwlHtmlParser{} + endpoint, err := parser.GetWebmentionEndpoint(html) + + if err != nil { + t.Errorf("Unable to parse feed: %v", err) + } + if endpoint != "http://example.com/webmention" { + t.Errorf("Wrong endpoint. Expected %v, got %v", "http://example.com/webmention", endpoint) + } +}