Josh

Building in the open

Bringing Back Webmentions

A year and a half ago I dropped support for webmentions on this blog, but I’ve brought them back over the last month.

At the time I removed them, I wasn’t getting any webmentions sent to my site and I wasn’t sending any webmentions because the sites I was linking to didn’t support them. I thought it was a dead end and instead built POSSE for this site to the likes of Mastodon and Bluesky.

Recently, I have started seeing webmentions for some of my more popular posts, and I started displaying them on post pages and added a simple little form for people to manually send them when they write their own responses to my things. I’m receiving them through webmention.io and displaying them through their simple+fast API.

Webmention display on my posts
Webmention display on my posts

Because I have I’ve started seeing a slight uptick in people sending me webmentions and I started displaying them, I figured I should re-enable my automations to send them to others. Here’s how that works:

require 'net/http'
require 'webmention'
require 'uri'
require 'nokogiri'

class SendMentionsFromRss
  Config = Struct.new(
    'MentionsFromRssConfig',
    :feed_url,
    :item_selector,
    :item_href_proc,
    :excluded_url_matcher,
    :verbose,
    keyword_init: true
  )

  def self.execute(config)
    raise ArgumentError, 'Must use a Config' unless config.is_a?(Config)

    puts "Loading RSS feed from #{config.feed_url}"
    export_uri = URI.parse(config.feed_url)
    export_req = Net::HTTP::Get.new(export_uri)
    export_res = Net::HTTP.start(export_uri.hostname, export_uri.port, use_ssl: true) do |http|
      http.request(export_req)
    end
    raise StandardError, 'Feed request failed' unless export_res.is_a?(Net::HTTPSuccess)

    doc = Nokogiri::XML(export_res.body)
    doc.css(config.item_selector).each do |link|
      href = config.item_href_proc.call(link)
      Webmention.mentioned_urls(href).each do |url|
        if url.match?(config.excluded_url_matcher)
          puts "skipping #{url}" if config.verbose
          next
        end

        result = Webmention.send_webmention(href, url)
        if result.ok?
          puts "Sent mention of #{url} by #{href}"
        else
          puts result.message
        end
      end
    end
  end
end

site_config = SendMentionsFromRss::Config.new(
  feed_url: 'https://www.joshbeckman.org/feed.xml',
  item_selector: 'entry link',
  item_href_proc: -> (link) { link['href'] },
  excluded_url_matcher: [
    /www.joshbeckman.org/,
    /notes.joshbeckman.org/,
    /readwise.io\/open\//,
    /readwise.io\/reader\//,
    /s2.googleusercontent.com/,
    /gravatar.com\/avatar/,
    /indieweb.org\/Webmention/
  ].join('|'),
  verbose: false
)
SendMentionsFromRss.execute(site_config)

I hope to see it discover endpoints on sites I’m linking to and sending webmentions out in the new year.

Keyboard Shortcuts

Key Action
o Source
e Edit
i Insight
r Random
h Home
s or / Search
Josh Beckman: https://www.joshbeckman.org/blog/practicing/bringing-back-webmentions