<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet href="https://shkspr.mobi/blog/wp-content/themes/edent-wordpress-theme/rss-style.xsl" type="text/xsl"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	    xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	     xmlns:dc="http://purl.org/dc/elements/1.1/"
	   xmlns:atom="http://www.w3.org/2005/Atom"
	     xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	  xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>
<channel>
	<title>ActivityPub &#8211; Terence Eden’s Blog</title>
	<atom:link href="https://shkspr.mobi/blog/tag/activitypub/feed/" rel="self" type="application/rss+xml" />
	<link>https://shkspr.mobi/blog</link>
	<description>Regular nonsense about tech and its effects 🙃</description>
	<lastBuildDate>Tue, 07 Apr 2026 09:19:52 +0000</lastBuildDate>
	<language>en-GB</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.9.4</generator>

<image>
	<url>https://shkspr.mobi/blog/wp-content/uploads/2023/07/cropped-avatar-32x32.jpeg</url>
	<title>ActivityPub &#8211; Terence Eden’s Blog</title>
	<link>https://shkspr.mobi/blog</link>
	<width>32</width>
	<height>32</height>
</image> 
	<item>
		<title><![CDATA[Some updates to ActivityBot]]></title>
		<link>https://shkspr.mobi/blog/2026/03/some-updates-to-activitybot/</link>
					<comments>https://shkspr.mobi/blog/2026/03/some-updates-to-activitybot/#comments</comments>
				<dc:creator><![CDATA[@edent]]></dc:creator>
		<pubDate>Mon, 16 Mar 2026 12:34:57 +0000</pubDate>
				<category><![CDATA[/etc/]]></category>
		<category><![CDATA[ActivityBot]]></category>
		<category><![CDATA[ActivityPub]]></category>
		<category><![CDATA[mastodon]]></category>
		<category><![CDATA[php]]></category>
		<guid isPermaLink="false">https://shkspr.mobi/blog/?p=68592</guid>

					<description><![CDATA[I couple of years ago, I developed ActivityBot - the simplest way to build Mastodon Bots. It is a single PHP file which can run an entire ActivityPub server and it is less than 80KB.  It works! You can follow @openbenches@bot.openbenches.org to see the latest entries on OpenBenches.org, and @colours@colours.bots.edent.tel for a slice of colour in your day, and @solar@solar.bots.edent.tel to see…]]></description>
										<content:encoded><![CDATA[<p>I couple of years ago, I developed <a href="https://shkspr.mobi/blog/2024/11/introducing-activitybot-the-simplest-way-to-build-mastodon-bots/">ActivityBot - the simplest way to build Mastodon Bots</a>. It is a <em>single</em> PHP file which can run an entire ActivityPub server and it is less than 80KB.</p>

<p>It works! You can follow <code>@openbenches@bot.openbenches.org</code> to see the latest entries on OpenBenches.org, and <code>@colours@colours.bots.edent.tel</code> for a slice of colour in your day, and <code>@solar@solar.bots.edent.tel</code> to see what my solar panels are up to.</p>

<p>This is <em>so</em> easy to use. Copy the PHP file (and a <code>.env</code> and <code>.htaccess</code>) to literally any web host running PHP 8.5 and you have a fully-fledged bot which can post to Mastodon.</p>

<p><a href="https://gitlab.com/edent/activity-bot/">Grab the code and start today</a>!</p>

<h2 id="features"><a href="https://shkspr.mobi/blog/2026/03/some-updates-to-activitybot/#features">Features</a></h2>

<p>Over the years I've added a few more features to it, so I thought I'd run through what they are. Note, this is all hand-written. No sycophantic plagiarism machines were involved in this code or blog post. I just really like emoji, OK⁉️</p>

<h3 id="%f0%9f%94%8d-be-discovered-on-the-fediverse"><a href="https://shkspr.mobi/blog/2026/03/some-updates-to-activitybot/#%f0%9f%94%8d-be-discovered-on-the-fediverse">🔍 Be discovered on the Fediverse</a></h3>

<p>This is the big one, you can find <code>@example@example.viii.fi</code> on your favourite Fediverse client.  This is thanks to its WebFinger support.</p>

<h3 id="%f0%9f%91%89-be-followed-by-other-accounts"><a href="https://shkspr.mobi/blog/2026/03/some-updates-to-activitybot/#%f0%9f%91%89-be-followed-by-other-accounts">👉 Be followed by other accounts</a></h3>

<p>No point being discovered if you can't be followed. This accepts follow requests and sends back a signed accept.</p>

<h3 id="%f0%9f%9a%ab-be-unfollowed-by-accounts"><a href="https://shkspr.mobi/blog/2026/03/some-updates-to-activitybot/#%f0%9f%9a%ab-be-unfollowed-by-accounts">🚫 Be unfollowed by accounts</a></h3>

<p>Sometimes people want to unfollow. Too bad, so sad. Again, this will accept the undo request and delete the unfollowing user's information.</p>

<h3 id="%f0%9f%93%a9-send-messages-to-the-fediverse"><a href="https://shkspr.mobi/blog/2026/03/some-updates-to-activitybot/#%f0%9f%93%a9-send-messages-to-the-fediverse">📩 Send messages to the Fediverse</a></h3>

<p>If a bot can be followed, but never posts, does it make a sound? This sends a post to all of your followers' (shared) inboxes. Includes some HTML formatting.</p>

<h3 id="%f0%9f%92%8c-send-direct-messages-to-users"><a href="https://shkspr.mobi/blog/2026/03/some-updates-to-activitybot/#%f0%9f%92%8c-send-direct-messages-to-users">💌 Send direct messages to users</a></h3>

<p>Not every message is for the wider public. If you want a bot which sends you a private message, this'll set the visibility correctly.</p>

<h3 id="%f0%9f%93%b7-attach-images-alt-text-to-a-message-%f0%9f%86%95%f0%9f%86%95"><a href="https://shkspr.mobi/blog/2026/03/some-updates-to-activitybot/#%f0%9f%93%b7-attach-images-alt-text-to-a-message-%f0%9f%86%95%f0%9f%86%95">📷 Attach images &amp; alt text to a message 🆕🆕</a></h3>

<p>A picture is worth a thousand words. But those pictures are meaningless without alt text. Attach as many images as you like. Note, most Mastodon services only accept a maximum of four.</p>

<h3 id="%f0%9f%8d%bf-video-upload-%f0%9f%86%95%f0%9f%86%95"><a href="https://shkspr.mobi/blog/2026/03/some-updates-to-activitybot/#%f0%9f%8d%bf-video-upload-%f0%9f%86%95%f0%9f%86%95">🍿 Video Upload 🆕🆕</a></h3>

<p>No transcoding or anything fancy. Upload a video and it'll be sent to your followers.</p>

<h3 id="%f0%9f%94%8a-audio-upload-%f0%9f%86%95%f0%9f%86%95"><a href="https://shkspr.mobi/blog/2026/03/some-updates-to-activitybot/#%f0%9f%94%8a-audio-upload-%f0%9f%86%95%f0%9f%86%95">🔊 Audio Upload 🆕🆕</a></h3>

<p>Same as video. Raw audio posted to your followers' feeds.</p>

<h3 id="%f0%9f%95%b8%ef%b8%8f-autolink-urls-hashtags-and-mentions"><a href="https://shkspr.mobi/blog/2026/03/some-updates-to-activitybot/#%f0%9f%95%b8%ef%b8%8f-autolink-urls-hashtags-and-mentions">🕸️ Autolink URls, hashtags, and @ mentions</a></h3>

<p>Including URls, tags, and mentions are <em>mostly</em> autolinked correctly. There's a lot of fuzziness in how it works.</p>

<h3 id="%f0%9f%a7%b5-threads"><a href="https://shkspr.mobi/blog/2026/03/some-updates-to-activitybot/#%f0%9f%a7%b5-threads">🧵 Threads</a></h3>

<p>You can reply to specific messages in order to create a thread.</p>

<h3 id="%f0%9f%91%88-follow-unfollow-block-and-unblock-other-accounts"><a href="https://shkspr.mobi/blog/2026/03/some-updates-to-activitybot/#%f0%9f%91%88-follow-unfollow-block-and-unblock-other-accounts">👈 Follow, Unfollow, Block, and Unblock other accounts</a></h3>

<p>It might be useful for you to remove followers or follow specific accounts.</p>

<h3 id="%f0%9f%97%91%ef%b8%8f-delete-posted-messages-and-their-attachments-%f0%9f%86%95%f0%9f%86%95"><a href="https://shkspr.mobi/blog/2026/03/some-updates-to-activitybot/#%f0%9f%97%91%ef%b8%8f-delete-posted-messages-and-their-attachments-%f0%9f%86%95%f0%9f%86%95">🗑️ Delete posted messages and their attachments 🆕🆕</a></h3>

<p>We all make mistakes. This will delete your post along with any attachments and send that delete message to everyone. Note, because of the federated nature of the Fediverse, you cannot guarantee that a remote server will delete anything.</p>

<h3 id="%e2%9c%8f%ef%b8%8f-edit-posts-%f0%9f%86%95%f0%9f%86%95"><a href="https://shkspr.mobi/blog/2026/03/some-updates-to-activitybot/#%e2%9c%8f%ef%b8%8f-edit-posts-%f0%9f%86%95%f0%9f%86%95">✏️ Edit Posts 🆕🆕</a></h3>

<p>If you don't want to delete and re-post, you can edit your existing posts.</p>

<h3 id="%f0%9f%a6%8b-bridge-to-bluesky-with-your-domain-name-via-bridgy-fed"><a href="https://shkspr.mobi/blog/2026/03/some-updates-to-activitybot/#%f0%9f%a6%8b-bridge-to-bluesky-with-your-domain-name-via-bridgy-fed">🦋 Bridge to BlueSky with your domain name via Bridgy Fed</a></h3>

<p>Not everyone is on the Fediverse. If you want to bridge to BlueSky, you can use the <a href="https://fed.brid.gy/">Bridgy Fed service</a>.</p>

<h3 id="%f0%9f%9a%9a-move-followers-from-an-old-account-and-to-a-new-account-%f0%9f%86%95%f0%9f%86%95"><a href="https://shkspr.mobi/blog/2026/03/some-updates-to-activitybot/#%f0%9f%9a%9a-move-followers-from-an-old-account-and-to-a-new-account-%f0%9f%86%95%f0%9f%86%95">🚚 Move followers from an old account and to a new account 🆕🆕</a></h3>

<p>Perhaps you started as <code>@electric@sex.pants</code> but now you want to become <code>@chaste@nunslife.biz</code> - no worries! You can tell followers you've moved and what your new name is.</p>

<p>Similarly, if ActivityBot is no longer right for you, it's simple to tell your existing follower to move to your new account.</p>

<h3 id="%f0%9f%97%a8%ef%b8%8f-allow-quote-posts-%f0%9f%86%95%f0%9f%86%95"><a href="https://shkspr.mobi/blog/2026/03/some-updates-to-activitybot/#%f0%9f%97%a8%ef%b8%8f-allow-quote-posts-%f0%9f%86%95%f0%9f%86%95">🗨️ Allow quote posts 🆕🆕</a></h3>

<p>Rather than just reposting your message, this sets the quote policy to allow people to share your message and attach some commentary of your own.</p>

<h3 id="%f0%9f%91%80-show-followers"><a href="https://shkspr.mobi/blog/2026/03/some-updates-to-activitybot/#%f0%9f%91%80-show-followers">👀 Show followers</a></h3>

<p>Your follower count isn't just a number, it is a living list of <em>who</em> chooses to follow you.</p>

<h3 id="%e2%9a%a0%ef%b8%8f-content-warnings-%f0%9f%86%95%f0%9f%86%95"><a href="https://shkspr.mobi/blog/2026/03/some-updates-to-activitybot/#%e2%9a%a0%ef%b8%8f-content-warnings-%f0%9f%86%95%f0%9f%86%95">⚠️ Content Warnings 🆕🆕</a></h3>

<p>Perhaps you want to hide a bit of what you're saying. Add a content warning to hide part of your message.</p>

<h3 id="%f0%9f%94%8f-verify-cryptographic-signatures"><a href="https://shkspr.mobi/blog/2026/03/some-updates-to-activitybot/#%f0%9f%94%8f-verify-cryptographic-signatures">🔏 Verify cryptographic signatures</a></h3>

<p><a href="https://shkspr.mobi/blog/2024/03/i-made-a-mistake-in-verifying-http-message-signatures/">HTTP Message Signatures is <em>hard</em></a>. I think I've mostly got it sorted.</p>

<h3 id="%f0%9f%aa%b5-log-sent-messages-and-errors"><a href="https://shkspr.mobi/blog/2026/03/some-updates-to-activitybot/#%f0%9f%aa%b5-log-sent-messages-and-errors">🪵 Log sent messages and errors</a></h3>

<p>This is primarily a learning aide, so have a rummage through the logs and see what's going on.</p>

<h3 id="%f0%9f%9a%ae-clear-logs-when-there-are-too-many"><a href="https://shkspr.mobi/blog/2026/03/some-updates-to-activitybot/#%f0%9f%9a%ae-clear-logs-when-there-are-too-many">🚮 Clear logs when there are too many</a></h3>

<p>ActivityPub is a <em>chatty</em> protocol. Your server can easily fill up with hundreds of thousands of messages from others. This regularly prunes down to something more manageable.</p>

<h3 id="%ef%b8%8f%e2%83%a3-hashed-passwords-for-posting-%f0%9f%86%95%f0%9f%86%95"><a href="https://shkspr.mobi/blog/2026/03/some-updates-to-activitybot/#%ef%b8%8f%e2%83%a3-hashed-passwords-for-posting-%f0%9f%86%95%f0%9f%86%95">#️⃣ Hashed passwords for posting 🆕🆕</a></h3>

<p>Bit of a guilty moment here. I was originally storing the password in plaintext. Naughty! Passwords are now salted and hashed.</p>

<h3 id="%f0%9f%92%bb-basic-website-for-showing-posts"><a href="https://shkspr.mobi/blog/2026/03/some-updates-to-activitybot/#%f0%9f%92%bb-basic-website-for-showing-posts">💻 Basic website for showing posts</a></h3>

<p>A nice-enough looking front end if people want to view the posts directly on your domain.</p>

<h2 id="some-deficiencies"><a href="https://shkspr.mobi/blog/2026/03/some-updates-to-activitybot/#some-deficiencies">Some Deficiencies</a></h2>

<p>Not every piece of software is perfect. ActivityBot is less perfect than most things. Here are some of the things it can't do and, perhaps, will never do.  If you'd like to help tackle any of these, <a href="https://gitlab.com/edent/activity-bot/">fork the code from my git repo</a>!</p>

<h3 id="%e2%8f%b3-retry-failed-messages"><a href="https://shkspr.mobi/blog/2026/03/some-updates-to-activitybot/#%e2%8f%b3-retry-failed-messages">⏳ Retry Failed Messages</a></h3>

<p>A <em>proper</em> Mastodon server will keep trying to send messages to unresponsive hosts. ActivityBot is one-and-done. If a remote server didn't respond in time, or was offline, or something else went wrong - it may not get the message.</p>

<h3 id="%f0%9f%94%84-reposts-announce-quote"><a href="https://shkspr.mobi/blog/2026/03/some-updates-to-activitybot/#%f0%9f%94%84-reposts-announce-quote">🔄 Reposts / Announce / Quote</a></h3>

<p>You cannot boost other posts, or even your own. Nor can you send quote posts.</p>

<h3 id="%f0%9f%a4%96-act-on-instructions"><a href="https://shkspr.mobi/blog/2026/03/some-updates-to-activitybot/#%f0%9f%a4%96-act-on-instructions">🤖 Act On Instructions</a></h3>

<p>This is a basic bot. It contains no logic. If you send it a message asking it to take action, it will not. You will need to build something else to make it truly interactive.</p>

<h3 id="%f0%9f%93%a5-receive-messages"><a href="https://shkspr.mobi/blog/2026/03/some-updates-to-activitybot/#%f0%9f%93%a5-receive-messages">📥 Receive Messages</a></h3>

<p>In fact, other than the follow / unfollow stuff, the bot can't receive any messages from the Fediverse. It doesn't know when a post has been replied to, liked, or reposted.</p>

<h3 id="%f0%9f%98%8e-set-post-visibility"><a href="https://shkspr.mobi/blog/2026/03/some-updates-to-activitybot/#%f0%9f%98%8e-set-post-visibility">😎 Set Post Visibility</a></h3>

<p>Your posts are either public or a DM. There's no support for things like quiet followers.</p>

<h3 id="%f0%9f%93%8a-create-polls"><a href="https://shkspr.mobi/blog/2026/03/some-updates-to-activitybot/#%f0%9f%93%8a-create-polls">📊 Create Polls</a></h3>

<p>Everyone loves to vote on meaningless polls - but this is quite a hard problem for ActivityBot. It would need to keep track of votes, prevent double voting, and probably some other difficult stuff.</p>

<h3 id="%f0%9f%97%a8%ef%b8%8f-change-quote-post-visibility"><a href="https://shkspr.mobi/blog/2026/03/some-updates-to-activitybot/#%f0%9f%97%a8%ef%b8%8f-change-quote-post-visibility">🗨️ Change Quote Post Visibility</a></h3>

<p>As quote posts are still quite new to Mastodon, I'm not sure how best to implement this.</p>

<h3 id="%f0%9f%94%97-proper-html-markdown-support"><a href="https://shkspr.mobi/blog/2026/03/some-updates-to-activitybot/#%f0%9f%94%97-proper-html-markdown-support">🔗 Proper HTML / Markdown Support</a></h3>

<p>Autolinking names, hashtags, and links just about works - but not very reliably. In theory the bot <em>could</em> parse Markdown and create richly formatted HTML from it. But that may require an external library which would bloat the size. Perhaps posting raw HTML could work?</p>

<h3 id="%f0%9f%96%bc%ef%b8%8f-focus-points-for-images"><a href="https://shkspr.mobi/blog/2026/03/some-updates-to-activitybot/#%f0%9f%96%bc%ef%b8%8f-focus-points-for-images">🖼️ Focus Points for Images</a></h3>

<p>Perhaps of less use now, but still of interest to people?</p>

<h3 id="%e2%9d%93-other-stuff"><a href="https://shkspr.mobi/blog/2026/03/some-updates-to-activitybot/#%e2%9d%93-other-stuff">❓ Other Stuff</a></h3>

<p>I don't know what I don't know. Maybe some stuff is total broken? Maybe it is wildly out of spec? If you spot something dodgy, please let me know or <a href="https://gitlab.com/edent/activity-bot/">raise a Pull Request</a>.</p>
<img src="https://shkspr.mobi/blog/wp-content/themes/edent-wordpress-theme/info/okgo.php?ID=68592&HTTP_REFERER=RSS" alt="" width="1" height="1" loading="eager">]]></content:encoded>
					
					<wfw:commentRss>https://shkspr.mobi/blog/2026/03/some-updates-to-activitybot/feed/</wfw:commentRss>
			<slash:comments>1</slash:comments>
		
		
			</item>
		<item>
		<title><![CDATA[Now witness the power of this fully operational Fediverse!]]></title>
		<link>https://shkspr.mobi/blog/2025/11/now-witness-the-power-of-this-fully-operational-fediverse/</link>
					<comments>https://shkspr.mobi/blog/2025/11/now-witness-the-power-of-this-fully-operational-fediverse/#comments</comments>
				<dc:creator><![CDATA[@edent]]></dc:creator>
		<pubDate>Sun, 23 Nov 2025 12:34:35 +0000</pubDate>
				<category><![CDATA[/etc/]]></category>
		<category><![CDATA[ActivityPub]]></category>
		<category><![CDATA[BlueSky]]></category>
		<category><![CDATA[fediverse]]></category>
		<category><![CDATA[mastodon]]></category>
		<category><![CDATA[statistics]]></category>
		<guid isPermaLink="false">https://shkspr.mobi/blog/?p=63716</guid>

					<description><![CDATA[How can you measure the popularity of a social network site? Perhaps by counting the number of active accounts, or the quality of the discourse, or even how many people reply to your witty memes.  Me? I prefer to look at how many people visit my blog from each site. It is an imperfect measure - and a vain one - but lets me know where I should be spending my time. No point posting on a network…]]></description>
										<content:encoded><![CDATA[<p>How can you measure the popularity of a social network site? Perhaps by counting the number of active accounts, or the quality of the discourse, or even how many people reply to your witty memes.</p>

<p>Me? I prefer to look at how many people visit my blog from each site. It is an imperfect measure - and a vain one - but lets me know where I should be spending my time. No point posting on a network which is just bots talking to each other, right?</p>

<p>Earlier this year <a href="https://shkspr.mobi/blog/2025/09/reasonably-accurate-privacy-conscious-cookieless-visitor-tracking-for-wordpress/">I built a stats-counter for my blog</a>. Every time someone clicks from a website which links to my blog, it records that visit in a database. I get to see which blog posts are doing numbers, and where those numbers came from.</p>

<p>Until fairly recently, the Mastodon social network didn't send referer details. I thought that reduced the visibility of the network and <a href="https://shkspr.mobi/blog/2024/12/mastodon-now-sends-referer-headers-hurrah/">lobbied for it to change</a>. As various Mastodon servers upgrade, and admins opt-in, it is becoming more apparent just how much traffic originates from the Fediverse.</p>

<p>Over the last few weeks, here's how many people have clicked <em>from</em> BlueSky and Mastodon <em>to</em> one of my blog posts.</p>

<table class="edent_stats_column"><thead><tr><th class="totals">Total</th><th>Source</th></tr></thead><tbody>
<tr><td class="stats-count">1,607</td><td><img class="pingback-favicon" src="https://shkspr.mobi/favicons/?domain=bsky.app"><a href="https://bsky.app">bsky.app</a></td></tr>
<tr><td class="stats-count">752</td><td><img class="pingback-favicon" src="https://shkspr.mobi/favicons/?domain=mastodon.social"><a href="https://mastodon.social">mastodon.social</a></td></tr>
</tbody></table>

<p>At first glance, it doesn't look good for our elephantine friends, does it? The butterfly sends over twice the traffic. Game over!</p>

<p>But, of course, while Mastodon.social is the biggest instance - it is far from the only one. What happens if we slide down the long tail? Here's all the Mastodon-ish instances which sent me over 10 clicks.</p>

<table class="edent_stats_column"><thead><tr><th class="totals">Total</th><th>Source</th></tr></thead><tbody>
<tr><td class="stats-count">193</td><td><img class="pingback-favicon" src="https://shkspr.mobi/favicons/?domain=phanpy.social"><a href="https://phanpy.social">phanpy.social</a></td></tr>
<tr><td class="stats-count">120</td><td><img class="pingback-favicon" src="https://shkspr.mobi/favicons/?domain=joinmastodon.org"> android-app://org.joinmastodon.android/</td></tr>
<tr><td class="stats-count">106</td><td><img class="pingback-favicon" src="https://shkspr.mobi/favicons/?domain=infosec.exchange"><a href="https://infosec.exchange">infosec.exchange</a></td></tr>
<tr><td class="stats-count">62</td><td><img class="pingback-favicon" src="https://shkspr.mobi/favicons/?domain=mas.to"><a href="https://mas.to">mas.to</a></td></tr>
<tr><td class="stats-count">59</td><td><img class="pingback-favicon" src="https://shkspr.mobi/favicons/?domain=mstdn.social"><a href="https://mstdn.social">mstdn.social</a></td></tr>
<tr><td class="stats-count">55</td><td><img class="pingback-favicon" src="https://shkspr.mobi/favicons/?domain=social.vivaldi.net"><a href="https://social.vivaldi.net">social.vivaldi.net</a></td></tr>
<tr><td class="stats-count">49</td><td><img class="pingback-favicon" src="https://shkspr.mobi/favicons/?domain=wandering.shop"><a href="https://wandering.shop">wandering.shop</a></td></tr>
<tr><td class="stats-count">48</td><td><img class="pingback-favicon" src="https://shkspr.mobi/favicons/?domain=fosstodon.org"><a href="https://fosstodon.org">fosstodon.org</a></td></tr>
<tr><td class="stats-count">33</td><td><img class="pingback-favicon" src="https://shkspr.mobi/favicons/?domain=mathstodon.xyz"><a href="https://mathstodon.xyz">mathstodon.xyz</a></td></tr>
<tr><td class="stats-count">27</td><td><img class="pingback-favicon" src="https://shkspr.mobi/favicons/?domain=mastodon.online"><a href="https://mastodon.online">mastodon.online</a></td></tr>
<tr><td class="stats-count">26</td><td><img class="pingback-favicon" src="https://shkspr.mobi/favicons/?domain=mastodon.scot"><a href="https://mastodon.scot">mastodon.scot</a></td></tr>
<tr><td class="stats-count">24</td><td><img class="pingback-favicon" src="https://shkspr.mobi/favicons/?domain=app.wafrn.net"><a href="https://app.wafrn.net">app.wafrn.net</a></td></tr>
<tr><td class="stats-count">19</td><td><img class="pingback-favicon" src="https://shkspr.mobi/favicons/?domain=indieweb.social"><a href="https://indieweb.social">indieweb.social</a></td></tr>
<tr><td class="stats-count">18</td><td><img class="pingback-favicon" src="https://shkspr.mobi/favicons/?domain=social.lol"><a href="https://social.lol">social.lol</a></td></tr>
<tr><td class="stats-count">17</td><td><img class="pingback-favicon" src="https://shkspr.mobi/favicons/?domain=tech.lgbt"><a href="https://tech.lgbt">tech.lgbt</a></td></tr>
<tr><td class="stats-count">17</td><td><img class="pingback-favicon" src="https://shkspr.mobi/favicons/?domain=toot.wales"><a href="https://toot.wales">toot.wales</a></td></tr>
<tr><td class="stats-count">16</td><td><img class="pingback-favicon" src="https://shkspr.mobi/favicons/?domain=en.osm.town"><a href="https://en.osm.town">en.osm.town</a></td></tr>
<tr><td class="stats-count">16</td><td><img class="pingback-favicon" src="https://shkspr.mobi/favicons/?domain=feditrends.com"><a href="https://feditrends.com">feditrends.com</a></td></tr>
<tr><td class="stats-count">14</td><td><img class="pingback-favicon" src="https://shkspr.mobi/favicons/?domain=mstdn.ca"><a href="https://mstdn.ca">mstdn.ca</a></td></tr>
<tr><td class="stats-count">14</td><td><img class="pingback-favicon" src="https://shkspr.mobi/favicons/?domain=piefed.social"><a href="https://piefed.social">piefed.social</a></td></tr>
<tr><td class="stats-count">12</td><td><img class="pingback-favicon" src="https://shkspr.mobi/favicons/?domain=wetdry.world"><a href="https://wetdry.world">wetdry.world</a></td></tr>
<tr><td class="stats-count">11</td><td><img class="pingback-favicon" src="https://shkspr.mobi/favicons/?domain=c.im"><a href="https://c.im">c.im</a></td></tr>
<tr><td class="stats-count">11</td><td><img class="pingback-favicon" src="https://shkspr.mobi/favicons/?domain=mastodon.nl"><a href="https://mastodon.nl">mastodon.nl</a></td></tr>
<tr><td class="stats-count">51</td><td><img class="pingback-favicon" src="https://shkspr.mobi/favicons/?domain=mastodon.social"> Sites sending &lt; 10 clicks</td></tr>
</tbody></table>

<p>Ah! Add them all up and you get a grand total of <strong>1,773 visitors from Mastodon-powered sites</strong>.  That's <em>more</em> than BlueSky.</p>

<p>Now, there are some obvious caveats to the data:</p>

<ul>
<li>I have a smaller follower count on BlueSky than I do on Mastodon.</li>
<li>My posts may appeal more to one demographic than another.</li>
<li>People may have strict privacy controls which suppress the true volume of visitors.</li>
<li>There's no way to measure how long someone spends reading my posts.</li>
<li>RSS and newsletter visitors aren't counted.</li>
<li>Clicks from apps may not always show a referer.</li>
<li>Some people may be on multiple services.</li>
<li>Fediverse users can follow the post directly, so don't need to visit the site to read it.</li>
</ul>

<p>And yet… no matter how you slice it, Fediverse servers are sending as much traffic as BlueSky!</p>

<p>I think this is brilliant. Web services should be able to scale from small to big - and each ActivityPub-powered site helps power the open Internet.</p>

<p>Just for completeness, this is how Reddit, Facebook, LinkedIn, Twitter, and Lemmy do over the same period:</p>

<table class="edent_stats_column"><thead><tr><th class="totals">Total</th><th>Source</th></tr></thead><tbody>
<tr><td class="stats-count">1,158</td><td><img class="pingback-favicon" src="https://shkspr.mobi/favicons/?domain=reddit.com"><a href="https://reddit.com">reddit.com</a></td></tr>
<tr><td class="stats-count">585</td><td><img class="pingback-favicon" src="https://shkspr.mobi/favicons/?domain=reddit.com"> android-app://com.reddit.frontpage/</td></tr>
<tr><td class="stats-count">76</td><td><img class="pingback-favicon" src="https://shkspr.mobi/favicons/?domain=facebook.com"><a href="https://facebook.com">facebook.com</a></td></tr>
<tr><td class="stats-count">76</td><td><img class="pingback-favicon" src="https://shkspr.mobi/favicons/?domain=old.reddit.com"><a href="https://old.reddit.com/r/programming/">https://old.reddit.com/r/programming/</a></td></tr>
<tr><td class="stats-count">56</td><td><img class="pingback-favicon" src="https://shkspr.mobi/favicons/?domain=www.reddit.com"><a href="https://www.reddit.com/r/programming/">https://www.reddit.com/r/programming/</a></td></tr>
<tr><td class="stats-count">52</td><td><img class="pingback-favicon" src="https://shkspr.mobi/favicons/?domain=youtube.com"><a href="https://youtube.com">youtube.com</a></td></tr>
<tr><td class="stats-count">41</td><td><img class="pingback-favicon" src="https://shkspr.mobi/favicons/?domain=t.co"><a href="https://t.co">t.co</a></td></tr>
<tr><td class="stats-count">38</td><td><img class="pingback-favicon" src="https://shkspr.mobi/favicons/?domain=old.reddit.com"><a href="https://old.reddit.com/r/todayilearned/comments/1nsw7f4/til_in_mongolia_instead_of_a_street_address_a/">https://old.reddit.com/r/todayilearned/comments/1nsw7f4/til_in_mongolia_instead_of_a_street_address_a/</a></td></tr>
<tr><td class="stats-count">31</td><td><img class="pingback-favicon" src="https://shkspr.mobi/favicons/?domain=linkedin.com"><a href="https://linkedin.com">linkedin.com</a></td></tr>
<tr><td class="stats-count">27</td><td><img class="pingback-favicon" src="https://shkspr.mobi/favicons/?domain=lemmy.world"> android-app://io.syncapps.lemmy_sync/</td></tr>
<tr><td class="stats-count">27</td><td><img class="pingback-favicon" src="https://shkspr.mobi/favicons/?domain=www.reddit.com"><a href="https://www.reddit.com/r/todayilearned/comments/1nsw7f4/til_in_mongolia_instead_of_a_street_address_a/">https://www.reddit.com/r/todayilearned/comments/1nsw7f4/til_in_mongolia_instead_of_a_street_address_a/</a></td></tr>
<tr><td class="stats-count">22</td><td><img class="pingback-favicon" src="https://shkspr.mobi/favicons/?domain=old.reddit.com"><a href="https://old.reddit.com/r/programming/comments/1n96ftn/40_years_later_are_bentleys_programming_pearls/">https://old.reddit.com/r/programming/comments/1n96ftn/40_years_later_are_bentleys_programming_pearls/</a></td></tr>
<tr><td class="stats-count">22</td><td><img class="pingback-favicon" src="https://shkspr.mobi/favicons/?domain=lemmy.ca"><a href="https://lemmy.ca">lemmy.ca</a></td></tr>
<tr><td class="stats-count">17</td><td><img class="pingback-favicon" src="https://shkspr.mobi/favicons/?domain=linkedin.com"> android-app://com.linkedin.android/</td></tr>
<tr><td class="stats-count">16</td><td><img class="pingback-favicon" src="https://shkspr.mobi/favicons/?domain=lemmy.dbzer0.com"><a href="https://lemmy.dbzer0.com">lemmy.dbzer0.com</a></td></tr>
<tr><td class="stats-count">14</td><td><img class="pingback-favicon" src="https://shkspr.mobi/favicons/?domain=feddit.org"><a href="https://feddit.org">feddit.org</a></td></tr>
<tr><td class="stats-count">11</td><td><img class="pingback-favicon" src="https://shkspr.mobi/favicons/?domain=www.reddit.com"><a href="https://www.reddit.com/r/programming/comments/1n96ftn/40_years_later_are_bentleys_programming_pearls/">https://www.reddit.com/r/programming/comments/1n96ftn/40_years_later_are_bentleys_programming_pearls/</a></td></tr>
<tr><td class="stats-count">10</td><td><img class="pingback-favicon" src="https://shkspr.mobi/favicons/?domain=discuss.tchncs.de"><a href="https://discuss.tchncs.de">discuss.tchncs.de</a></td></tr>
<tr><td class="stats-count">10</td><td><img class="pingback-favicon" src="https://shkspr.mobi/favicons/?domain=l.instagram.com"><a href="https://l.instagram.com">l.instagram.com</a></td></tr>
<tr><td class="stats-count">8</td><td><img class="pingback-favicon" src="https://shkspr.mobi/favicons/?domain=lemmy.blahaj.zone"><a href="https://lemmy.blahaj.zone">lemmy.blahaj.zone</a></td></tr>
<tr><td class="stats-count">6</td><td><img class="pingback-favicon" src="https://shkspr.mobi/favicons/?domain=www.reddit.com"><a href="https://www.reddit.com/r/GrapheneOS/comments/1m2l84b/considering_making_the_switch_does_google_pay/">https://www.reddit.com/r/GrapheneOS/comments/1m2l84b/considering_making_the_switch_does_google_pay/</a></td></tr>
<tr><td class="stats-count">6</td><td><img class="pingback-favicon" src="https://shkspr.mobi/favicons/?domain=reddthat.com"><a href="https://reddthat.com">reddthat.com</a></td></tr>
</tbody></table>

<p>If you add up all the Lemmy instances, they send about as much traffic as Facebook and LinkedIn combined. That's not a huge surprise - those platforms hate anyone clicking away to the wider web.</p>

<p>Twitter is basically <a href="https://en.wikipedia.org/wiki/Dead_Internet_theory">the Dead Internet</a>. I'm no longer on there, but I do occasionally search it to see who is sharing my posts. The popular posts I write get shared a <em>lot</em> - sometimes by accounts with huge followers - yet there are no comments or retweets and barely and clicks.</p>

<p>I don't do Instagram or Threads, and that might be reflected in their low numbers. But I'm not active on YouTube either - yet people there occasionally link back to me.</p>

<h2 id="final-thoughts"><a href="https://shkspr.mobi/blog/2025/11/now-witness-the-power-of-this-fully-operational-fediverse/#final-thoughts">Final Thoughts</a></h2>

<p>Firstly, my stats only represent my site. Your site might be very different.</p>

<p>Secondly, I've ignored search engine traffic, big blogs, newsletters, and other sources.</p>

<p>Thirdly, and most importantly, this <em>isn't</em> a competition! The desire for a "winner-takes-all" service is dangerous and disturbing. An ecosystem is at its most vibrant when there are multiple participants each thriving in their own niche.</p>

<p>I want a thousand sites, running a hundred different software stacks, some of which only serve a dozen people, or even a lone participant.</p>

<p>Diversity is strength.</p>
<img src="https://shkspr.mobi/blog/wp-content/themes/edent-wordpress-theme/info/okgo.php?ID=63716&HTTP_REFERER=RSS" alt="" width="1" height="1" loading="eager">]]></content:encoded>
					
					<wfw:commentRss>https://shkspr.mobi/blog/2025/11/now-witness-the-power-of-this-fully-operational-fediverse/feed/</wfw:commentRss>
			<slash:comments>10</slash:comments>
		
		
			</item>
		<item>
		<title><![CDATA[Getting started with Mastodon's Quote Posts - technical implementation details for servers]]></title>
		<link>https://shkspr.mobi/blog/2025/10/getting-started-with-mastodons-quote-posts-technical-implementation-details-for-servers/</link>
					<comments>https://shkspr.mobi/blog/2025/10/getting-started-with-mastodons-quote-posts-technical-implementation-details-for-servers/#comments</comments>
				<dc:creator><![CDATA[@edent]]></dc:creator>
		<pubDate>Fri, 03 Oct 2025 11:34:27 +0000</pubDate>
				<category><![CDATA[/etc/]]></category>
		<category><![CDATA[ActivityPub]]></category>
		<category><![CDATA[fediverse]]></category>
		<category><![CDATA[mastodon]]></category>
		<category><![CDATA[MastodonAPI]]></category>
		<guid isPermaLink="false">https://shkspr.mobi/blog/?p=63527</guid>

					<description><![CDATA[Quoting posts on Mastodon is slightly complex. Because of the privacy conscious nature of the platform and its users, reposting isn&#039;t merely a case of sharing a URl.  A user writes a status. The user can choose to make their statuses quotable or not. What happens when a quoter quotes that post?  I&#039;ve read through the specification and tried to simplify it.  Quoting is a multi-step process:   The…]]></description>
										<content:encoded><![CDATA[<p>Quoting posts on Mastodon is <em>slightly</em> complex. Because of the privacy conscious nature of the platform and its users, reposting isn't merely a case of sharing a URl.</p>

<p>A user writes a status. The user can choose to make their statuses quotable or not. What happens when a quoter quotes that post?</p>

<p>I've <a href="https://codeberg.org/fediverse/fep/src/branch/main/fep/044f/fep-044f.md">read through the specification</a> and tried to simplify it.  Quoting is a multi-step process:</p>

<ol>
<li>The status <em>must</em> opt-in to being shared.</li>
<li>The quoter quotes the status.</li>
<li>The quoter's server sends a request to the status's server.</li>
<li>The status's server sends an accept message back to the quoter's server.</li>
<li>When other servers see the quote, they check with the status's server to see if it is allowed.</li>
</ol>

<p>I'm going to walk you through each stage as best as I understand them.</p>

<h2 id="opting-in"><a href="https://shkspr.mobi/blog/2025/10/getting-started-with-mastodons-quote-posts-technical-implementation-details-for-servers/#opting-in">Opting In</a></h2>

<p>An ActivityPub status message is JSON. In order to opt-in, it needs this additional field.</p>

<pre><code class="language-JSON">"interactionPolicy": {
  "canQuote": {
    "automaticApproval": "https://www.w3.org/ns/activitystreams#Public"
  }
}
</code></pre>

<p>That tells ActivityPub clients that anyone is allowed to quote this post. It is also possible to say that only specific users, or only followers, or no-one is allowed.</p>

<h2 id="the-quoterequest"><a href="https://shkspr.mobi/blog/2025/10/getting-started-with-mastodons-quote-posts-technical-implementation-details-for-servers/#the-quoterequest">The QuoteRequest</a></h2>

<p>Someone has hit the quote post button, typed their own message, and shared their wisdom. Their server sends the following message to the server which hosts the quoted status. This has been edited for brevity.</p>

<pre><code class="language-JSON">{
  "@context": [
    "https://www.w3.org/ns/activitystreams",
    {
      "QuoteRequest":   "https://w3id.org/fep/044f#QuoteRequest"
    }
  ],
  "type": "QuoteRequest",
  "id":     "https://mastodon.test/users/Edent/quote_requests/1234-5678-9101",
  "actor":  "https://mastodon.test/users/Edent",
  "object": "https://example.com/posts/987654321.json",
  "instrument": {
    "id":           "https://mastodon.test/users/Edent/statuses/123456789",
    "url":          "https://mastodon.test/@Edent/123456789",
    "attributedTo": "https://mastodon.test/users/Edent",
    "quote":          "https://example.com/posts/987654321.json",
    "_misskey_quote": "https://example.com/posts/987654321.json",
    "quoteUri":       "https://example.com/posts/987654321.json"
  }
}
</code></pre>

<p>All this says is "I would like permission to quote you."</p>

<h2 id="the-stamp"><a href="https://shkspr.mobi/blog/2025/10/getting-started-with-mastodons-quote-posts-technical-implementation-details-for-servers/#the-stamp">The Stamp</a></h2>

<p>The quoted server needs to approve this quote. First, it generates a "stamp".</p>

<p>This is a file which lives on the quoted server. It is proof that the quote is allowed. If it is deleted, the quote permission is revoked. When the <a href="https://socialhub.activitypub.rocks/t/quote-post-implementation-issues/8032/2?u=eden_t">stamp's ID is requested the stamp <em>must</em> be returned</a>.</p>

<pre><code class="language-JSON">{
  "@context": [
    "https://www.w3.org/ns/activitystreams",
    {
      "gts": "https://gotosocial.org/ns#",
      "QuoteAuthorization": {
        "@id": "https://w3id.org/fep/044f#QuoteAuthorization",
        "@type": "@id"
      },
      "interactingObject": {
        "@id": "gts:interactingObject"
      },
      "interactionTarget": {
        "@id": "gts:interactionTarget"
      }
    }
  ],
  "type": "QuoteAuthorization",
  "id":                "https://example.com/quote-987654321.json",
  "attributedTo":      "https://example.com/users/username",
  "interactionTarget": "https://example.com/posts/987654321.json",
  "interactingObject": "https://mastodon.test/users/Edent/statuses/123456789"
}
</code></pre>

<p>If the quoted status is viewed from a different server, that server will query the stamp to make sure the share is allowed.</p>

<h2 id="the-accept"><a href="https://shkspr.mobi/blog/2025/10/getting-started-with-mastodons-quote-posts-technical-implementation-details-for-servers/#the-accept">The Accept</a></h2>

<p>This is the message that the quoted server sends to the quoting server. It references the request and the stamp.</p>

<pre><code class="language-JSON">{
  "@context": [
    "https://www.w3.org/ns/activitystreams",
    {
      "QuoteRequest": "https://w3id.org/fep/044f#QuoteRequest"
    }
  ],
  "type": "Accept",
  "to":    "https://mastodon.test/users/Edent",
  "id":    "https://example.com/posts/987654321.json",
  "actor": "https://example.com/account",
  "object": {
    "type": "QuoteRequest",
    "id":         "https://mastodon.test/users/Edent/quote_requests/1234-5678-9101",
    "actor":      "https://mastodon.test/users/Edent",
    "instrument": "https://mastodon.test/users/Edent/statuses/123456789",
    "object":     "https://example.com/posts/987654321.json"
  },
  "result": "https://example.com/quote-987654321.json"
}
</code></pre>

<p>The "result" <em>must</em> be the same as the stamp's URl.</p>

<h2 id="and-then"><a href="https://shkspr.mobi/blog/2025/10/getting-started-with-mastodons-quote-posts-technical-implementation-details-for-servers/#and-then">And then?</a></h2>

<p>You can follow and quote <a href="https://colours.bots.edent.tel/">@colours@colours.bots.edent.tel</a> on your favourite Fediverse platform.</p>

<p>I've written an ActivityPub server in a single file which is designed to teach you have the protocol works. Have a play with <a href="https://gitlab.com/edent/activity-bot">ActivityBot</a>.</p>
<img src="https://shkspr.mobi/blog/wp-content/themes/edent-wordpress-theme/info/okgo.php?ID=63527&HTTP_REFERER=RSS" alt="" width="1" height="1" loading="eager">]]></content:encoded>
					
					<wfw:commentRss>https://shkspr.mobi/blog/2025/10/getting-started-with-mastodons-quote-posts-technical-implementation-details-for-servers/feed/</wfw:commentRss>
			<slash:comments>5</slash:comments>
		
		
			</item>
		<item>
		<title><![CDATA[Presenting ActivityBot at FOSDEM]]></title>
		<link>https://shkspr.mobi/blog/2025/02/presenting-activitybot-at-fosdem/</link>
					<comments>https://shkspr.mobi/blog/2025/02/presenting-activitybot-at-fosdem/#comments</comments>
				<dc:creator><![CDATA[@edent]]></dc:creator>
		<pubDate>Sun, 09 Feb 2025 12:34:17 +0000</pubDate>
				<category><![CDATA[/etc/]]></category>
		<category><![CDATA[ActivityPub]]></category>
		<category><![CDATA[fosdem]]></category>
		<category><![CDATA[presentation]]></category>
		<guid isPermaLink="false">https://shkspr.mobi/blog/?p=58000</guid>

					<description><![CDATA[Because I&#039;m an optimist, I submitted a few talks to FOSDEM in the hope one might be accepted.  Because I&#039;m lucky, I got two speaking slots. Because I&#039;m an idiot, I decided to do both talks. On the same day. An hour apart. On opposite ends of the venue.  Fool!  My first talk was at the Social Web Birds-of-a-Feather session. I told people about my ActivityBot social networking server and how I…]]></description>
										<content:encoded><![CDATA[<p>Because I'm an optimist, I submitted a few talks to FOSDEM in the hope one might be accepted.  Because I'm lucky, I got two speaking slots. Because I'm an idiot, I decided to do both talks. On the same day. An hour apart. On opposite ends of the venue.</p>

<p>Fool!</p>

<p>My first talk was at <a href="https://fosdem.org/2025/schedule/event/fosdem-2025-6617-social-web-bof/">the Social Web Birds-of-a-Feather</a> session. I told people about my ActivityBot social networking server and how I built it into a single file. In the spirit of minimalism, I only had 8 minutes to present.  Time for a speed-run!</p>

<p>Sadly / Luckily there's no audio or video of the session (if you have some, let me know) so you'll have to make do with some slides. Speaker notes are included - read them rapidly for the full effect!</p>

<h2 id="i-built-an-activitypub-bot-server-in-64kb-of-php-sorry"><a href="https://shkspr.mobi/blog/2025/02/presenting-activitybot-at-fosdem/#i-built-an-activitypub-bot-server-in-64kb-of-php-sorry">I built an ActivityPub bot server in 64KB of PHP. Sorry!</a></h2>

<iframe src="https://docs.google.com/presentation/d/e/2PACX-1vQXHq1eURXSUSoMmNZVVQ07HMEUxe39G28HJZGIgKxPJo5Xkhei4BOVTshCXn2ZPi2n4kRvIqebERwr/embed?start=false&amp;loop=false&amp;delayms=30000" frameborder="0" width="1920" height="1080" allowfullscreen="true" mozallowfullscreen="true" webkitallowfullscreen="true" style="height: auto; aspect-ratio: 16/9;"></iframe>

<h2 id="feedback-and-photos"><a href="https://shkspr.mobi/blog/2025/02/presenting-activitybot-at-fosdem/#feedback-and-photos">Feedback and Photos</a></h2>

<blockquote class="social-embed" id="social-embed-113934050377736127" lang="en" itemscope="" itemtype="https://schema.org/SocialMediaPosting"><header class="social-embed-header" itemprop="author" itemscope="" itemtype="https://schema.org/Person"><a href="https://hachyderm.io/@ioana" class="social-embed-user" itemprop="url"><img class="social-embed-avatar" src="https://media.hachyderm.io/accounts/avatars/109/811/317/559/644/637/original/b2d24e089597a462.jpg" alt="" itemprop="image"><div class="social-embed-user-names"><p class="social-embed-user-names-name" itemprop="name">@ioana@hachyderm.io</p>Ioana</div></a><img class="social-embed-logo" alt="Mastodon" src="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' aria-label='Mastodon' role='img' viewBox='0 0 512 512' fill='%23fff'%3E%3Cpath d='m0 0H512V512H0'/%3E%3ClinearGradient id='a' y2='1'%3E%3Cstop offset='0' stop-color='%236364ff'/%3E%3Cstop offset='1' stop-color='%23563acc'/%3E%3C/linearGradient%3E%3Cpath fill='url(%23a)' d='M317 381q-124 28-123-39 69 15 149 2 67-13 72-80 3-101-3-116-19-49-72-58-98-10-162 0-56 10-75 58-12 31-3 147 3 32 9 53 13 46 70 69 83 23 138-9'/%3E%3Cpath d='M360 293h-36v-93q-1-26-29-23-20 3-20 34v47h-36v-47q0-31-20-34-30-3-30 28v88h-36v-91q1-51 44-60 33-5 51 21l9 15 9-15q16-26 51-21 43 9 43 60'/%3E%3C/svg%3E"></header><section class="social-embed-text" itemprop="articleBody"><p>Best start for the Social BoF with <span class="h-card" translate="no"><a href="https://mastodon.social/@Edent" class="u-url mention">@<span>Edent</span></a></span> talk! <br><a href="https://hachyderm.io/tags/Fosdem" class="mention hashtag" rel="tag">#<span>Fosdem</span></a> <a href="https://hachyderm.io/tags/fosdem2025" class="mention hashtag" rel="tag">#<span>fosdem2025</span></a> <a href="https://hachyderm.io/tags/fosdem25" class="mention hashtag" rel="tag">#<span>fosdem25</span></a></p><div class="social-embed-media-grid"><a href="https://media.hachyderm.io/media_attachments/files/113/934/048/014/498/003/original/701d5a1938889538.jpg" class="social-embed-media-link"><img class="social-embed-media" alt="" src="data:image/webp;base64,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"></a><a href="https://media.hachyderm.io/media_attachments/files/113/934/048/999/136/306/original/552b87a01b48404e.jpg" class="social-embed-media-link"><img class="social-embed-media" alt="" src="data:image/webp;base64,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"></a></div></section><hr class="social-embed-hr"><footer class="social-embed-footer"><a href="https://hachyderm.io/@ioana/113934050377736127"><span aria-label="9 likes" class="social-embed-meta">❤️ 9</span><span aria-label="1 replies" class="social-embed-meta">💬 1</span><span aria-label="2 reposts" class="social-embed-meta">🔁 2</span><time datetime="2025-02-02T11:27:21.758Z" itemprop="datePublished">11:27 - Sun 02 February 2025</time></a></footer></blockquote>

<blockquote class="social-embed" id="social-embed-113934150415658493" lang="en" itemscope="" itemtype="https://schema.org/SocialMediaPosting"><header class="social-embed-header" itemprop="author" itemscope="" itemtype="https://schema.org/Person"><a href="https://hachyderm.io/@ioana" class="social-embed-user" itemprop="url"><img class="social-embed-avatar" src="https://media.hachyderm.io/accounts/avatars/109/811/317/559/644/637/original/b2d24e089597a462.jpg" alt="" itemprop="image"><div class="social-embed-user-names"><p class="social-embed-user-names-name" itemprop="name">@ioana@hachyderm.io</p>Ioana</div></a><img class="social-embed-logo" alt="Mastodon" src="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' aria-label='Mastodon' role='img' viewBox='0 0 512 512' fill='%23fff'%3E%3Cpath d='m0 0H512V512H0'/%3E%3ClinearGradient id='a' y2='1'%3E%3Cstop offset='0' stop-color='%236364ff'/%3E%3Cstop offset='1' stop-color='%23563acc'/%3E%3C/linearGradient%3E%3Cpath fill='url(%23a)' d='M317 381q-124 28-123-39 69 15 149 2 67-13 72-80 3-101-3-116-19-49-72-58-98-10-162 0-56 10-75 58-12 31-3 147 3 32 9 53 13 46 70 69 83 23 138-9'/%3E%3Cpath d='M360 293h-36v-93q-1-26-29-23-20 3-20 34v47h-36v-47q0-31-20-34-30-3-30 28v88h-36v-91q1-51 44-60 33-5 51 21l9 15 9-15q16-26 51-21 43 9 43 60'/%3E%3C/svg%3E"></header><section class="social-embed-text" itemprop="articleBody"><p><span class="h-card" translate="no"><a href="https://mastodon.social/@Edent" class="u-url mention">@<span>Edent</span></a></span>Loved the <br>- I do not have time for applause. Please don't clap 😂<br>- I do not have time for reactions<br>- I do not have time for questions </p><p>PS for those reading this, it was fun and nice <br>😅</p><div class="social-embed-media-grid"></div></section><hr class="social-embed-hr"><footer class="social-embed-footer"><a href="https://hachyderm.io/@ioana/113934150415658493"><span aria-label="1 likes" class="social-embed-meta">❤️ 1</span><span aria-label="0 replies" class="social-embed-meta">💬 0</span><span aria-label="0 reposts" class="social-embed-meta">🔁 0</span><time datetime="2025-02-02T11:52:48.208Z" itemprop="datePublished">11:52 - Sun 02 February 2025</time></a></footer></blockquote>

<blockquote class="social-embed" id="social-embed-113933997287100597" lang="en" itemscope="" itemtype="https://schema.org/SocialMediaPosting"><header class="social-embed-header" itemprop="author" itemscope="" itemtype="https://schema.org/Person"><a href="https://social.wake.st/@liaizon" class="social-embed-user" itemprop="url"><img class="social-embed-avatar" src="https://files.mastodon.social/cache/accounts/avatars/000/711/648/original/8920ce43fe0d7a74.png" alt="" itemprop="image"><div class="social-embed-user-names"><p class="social-embed-user-names-name" itemprop="name">@liaizon@social.wake.st</p>wakest ⁂</div></a><img class="social-embed-logo" alt="Mastodon" src="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' aria-label='Mastodon' role='img' viewBox='0 0 512 512' fill='%23fff'%3E%3Cpath d='m0 0H512V512H0'/%3E%3ClinearGradient id='a' y2='1'%3E%3Cstop offset='0' stop-color='%236364ff'/%3E%3Cstop offset='1' stop-color='%23563acc'/%3E%3C/linearGradient%3E%3Cpath fill='url(%23a)' d='M317 381q-124 28-123-39 69 15 149 2 67-13 72-80 3-101-3-116-19-49-72-58-98-10-162 0-56 10-75 58-12 31-3 147 3 32 9 53 13 46 70 69 83 23 138-9'/%3E%3Cpath d='M360 293h-36v-93q-1-26-29-23-20 3-20 34v47h-36v-47q0-31-20-34-30-3-30 28v88h-36v-91q1-51 44-60 33-5 51 21l9 15 9-15q16-26 51-21 43 9 43 60'/%3E%3C/svg%3E"></header><section class="social-embed-text" itemprop="articleBody"><p>First thing this morning at Social Web <a href="https://social.wake.st/tags/BOF" class="mention hashtag" rel="nofollow noopener" target="_blank">#<span>BOF</span></a> we have <span class="h-card" translate="no"><a href="https://mastodon.social/@Edent" class="u-url mention" rel="nofollow noopener" target="_blank">@<span>Edent</span></a></span> presenting their single file php <a href="https://social.wake.st/tags/ActivityPub" class="mention hashtag" rel="nofollow noopener" target="_blank">#<span>ActivityPub</span></a> project that is entirely contained in one slide!</p><div class="social-embed-media-grid"><a href="https://files.mastodon.social/cache/media_attachments/files/113/933/997/248/931/154/original/22d792a494540dfa.jpg" class="social-embed-media-link"><img class="social-embed-media" alt="A person stands in front of a projection screen filled with php" src="data:image/webp;base64,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"></a></div></section><hr class="social-embed-hr"><footer class="social-embed-footer"><a href="https://social.wake.st/@liaizon/113933997213561169"><span aria-label="1 likes" class="social-embed-meta">❤️ 1</span><span aria-label="6 replies" class="social-embed-meta">💬 6</span><span aria-label="11 reposts" class="social-embed-meta">🔁 11</span><time datetime="2025-02-02T11:13:50.000Z" itemprop="datePublished">11:13 - Sun 02 February 2025</time></a></footer></blockquote>

<blockquote class="social-embed" id="social-embed-113933987857350668" lang="de" itemscope="" itemtype="https://schema.org/SocialMediaPosting"><header class="social-embed-header" itemprop="author" itemscope="" itemtype="https://schema.org/Person"><a href="https://bonn.social/@Sascha" class="social-embed-user" itemprop="url"><img class="social-embed-avatar" src="https://files.mastodon.social/cache/accounts/avatars/000/082/561/original/fcd9431c3455ed84.jpg" alt="" itemprop="image"><div class="social-embed-user-names"><p class="social-embed-user-names-name" itemprop="name">@Sascha@bonn.social</p>Sascha Foerster :bonndigital:</div></a><img class="social-embed-logo" alt="Mastodon" src="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' aria-label='Mastodon' role='img' viewBox='0 0 512 512' fill='%23fff'%3E%3Cpath d='m0 0H512V512H0'/%3E%3ClinearGradient id='a' y2='1'%3E%3Cstop offset='0' stop-color='%236364ff'/%3E%3Cstop offset='1' stop-color='%23563acc'/%3E%3C/linearGradient%3E%3Cpath fill='url(%23a)' d='M317 381q-124 28-123-39 69 15 149 2 67-13 72-80 3-101-3-116-19-49-72-58-98-10-162 0-56 10-75 58-12 31-3 147 3 32 9 53 13 46 70 69 83 23 138-9'/%3E%3Cpath d='M360 293h-36v-93q-1-26-29-23-20 3-20 34v47h-36v-47q0-31-20-34-30-3-30 28v88h-36v-91q1-51 44-60 33-5 51 21l9 15 9-15q16-26 51-21 43 9 43 60'/%3E%3C/svg%3E"></header><section class="social-embed-text" itemprop="articleBody"><p>Wir lachen so viel, wir haben keine Zeit zum Posten. Fantastischer Vortrag über den kleinsten ActivityPub-Bot possible, made by <span class="h-card" translate="no"><a href="https://mastodon.social/@Edent" class="u-url mention" rel="nofollow noopener" target="_blank">@<span>Edent</span></a></span>.</p><div class="social-embed-media-grid"><a href="https://files.mastodon.social/cache/media_attachments/files/113/933/987/805/710/279/original/a06acab6c90a6d4b.jpg" class="social-embed-media-link"><img class="social-embed-media" alt="" src="data:image/webp;base64,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"></a></div></section><hr class="social-embed-hr"><footer class="social-embed-footer"><a href="https://bonn.social/@Sascha/113933987520310093"><span aria-label="1 likes" class="social-embed-meta">❤️ 1</span><span aria-label="1 replies" class="social-embed-meta">💬 1</span><span aria-label="0 reposts" class="social-embed-meta">🔁 0</span><time datetime="2025-02-02T11:11:22.000Z" itemprop="datePublished">11:11 - Sun 02 February 2025</time></a></footer></blockquote>

<blockquote class="social-embed" id="social-embed-113935060594615512" lang="en" itemscope="" itemtype="https://schema.org/SocialMediaPosting"><header class="social-embed-header" itemprop="author" itemscope="" itemtype="https://schema.org/Person"><a href="https://mastodon.social/@_elena" class="social-embed-user" itemprop="url"><img class="social-embed-avatar" src="https://files.mastodon.social/accounts/avatars/109/246/411/862/197/824/original/16b4d03c1b5adeaf.jpeg" alt="" itemprop="image"><div class="social-embed-user-names"><p class="social-embed-user-names-name" itemprop="name">@_elena@mastodon.social</p>Elena Rossini ⁂</div></a><img class="social-embed-logo" alt="Mastodon" src="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' aria-label='Mastodon' role='img' viewBox='0 0 512 512' fill='%23fff'%3E%3Cpath d='m0 0H512V512H0'/%3E%3ClinearGradient id='a' y2='1'%3E%3Cstop offset='0' stop-color='%236364ff'/%3E%3Cstop offset='1' stop-color='%23563acc'/%3E%3C/linearGradient%3E%3Cpath fill='url(%23a)' d='M317 381q-124 28-123-39 69 15 149 2 67-13 72-80 3-101-3-116-19-49-72-58-98-10-162 0-56 10-75 58-12 31-3 147 3 32 9 53 13 46 70 69 83 23 138-9'/%3E%3Cpath d='M360 293h-36v-93q-1-26-29-23-20 3-20 34v47h-36v-47q0-31-20-34-30-3-30 28v88h-36v-91q1-51 44-60 33-5 51 21l9 15 9-15q16-26 51-21 43 9 43 60'/%3E%3C/svg%3E"></header><section class="social-embed-text" itemprop="articleBody"><p><span class="h-card" translate="no"><a href="https://mastodon.social/@Edent" class="u-url mention">@<span>Edent</span></a></span> your BOF talk was absolutely brilliant Terence! 👏👏👏👏👏</p><div class="social-embed-media-grid"></div></section><hr class="social-embed-hr"><footer class="social-embed-footer"><a href="https://mastodon.social/@_elena/113935060594615512"><span aria-label="0 likes" class="social-embed-meta">❤️ 0</span><span aria-label="1 replies" class="social-embed-meta">💬 1</span><span aria-label="0 reposts" class="social-embed-meta">🔁 0</span><time datetime="2025-02-02T15:44:16.438Z" itemprop="datePublished">15:44 - Sun 02 February 2025</time></a></footer></blockquote>

<blockquote class="social-embed" id="social-embed-113976199068587690" lang="en" itemscope="" itemtype="https://schema.org/SocialMediaPosting"><header class="social-embed-header" itemprop="author" itemscope="" itemtype="https://schema.org/Person"><a href="https://typo.social/@redmer" class="social-embed-user" itemprop="url"><img class="social-embed-avatar" src="https://files.mastodon.social/cache/accounts/avatars/109/364/169/463/476/377/original/bd3d155574eaff72.jpeg" alt="" itemprop="image"><div class="social-embed-user-names"><p class="social-embed-user-names-name" itemprop="name">@redmer@typo.social</p>Redmer</div></a><img class="social-embed-logo" alt="Mastodon" src="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' aria-label='Mastodon' role='img' viewBox='0 0 512 512' fill='%23fff'%3E%3Cpath d='m0 0H512V512H0'/%3E%3ClinearGradient id='a' y2='1'%3E%3Cstop offset='0' stop-color='%236364ff'/%3E%3Cstop offset='1' stop-color='%23563acc'/%3E%3C/linearGradient%3E%3Cpath fill='url(%23a)' d='M317 381q-124 28-123-39 69 15 149 2 67-13 72-80 3-101-3-116-19-49-72-58-98-10-162 0-56 10-75 58-12 31-3 147 3 32 9 53 13 46 70 69 83 23 138-9'/%3E%3Cpath d='M360 293h-36v-93q-1-26-29-23-20 3-20 34v47h-36v-47q0-31-20-34-30-3-30 28v88h-36v-91q1-51 44-60 33-5 51 21l9 15 9-15q16-26 51-21 43 9 43 60'/%3E%3C/svg%3E"></header><section class="social-embed-text" itemprop="articleBody"><p><span class="h-card" translate="no"><a href="https://mastodon.social/@Edent" class="u-url mention" rel="nofollow noopener" target="_blank">@<span>Edent</span></a></span> I have a photo!</p><div class="social-embed-media-grid"><a href="https://files.mastodon.social/cache/media_attachments/files/113/976/199/005/479/268/original/49bd02b853fdc39c.jpeg" class="social-embed-media-link"><img class="social-embed-media" alt="Photo of Terence Eden in a lecture room in front of a presentation. The slide says:  gitlab.com/exent/activity-bot link. Requires: Docker, Node, MongoDB, Wayland, Glados, Rust, LLM, Adobe Creative Cloud, Maven, React, HAL9000 (absolutely NONE of these!)" src="data:image/webp;base64,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"></a></div></section><hr class="social-embed-hr"><footer class="social-embed-footer"><a href="https://typo.social/@redmer/113976198958422873"><span aria-label="1 likes" class="social-embed-meta">❤️ 1</span><span aria-label="1 replies" class="social-embed-meta">💬 1</span><span aria-label="0 reposts" class="social-embed-meta">🔁 0</span><time datetime="2025-02-09T22:06:18.000Z" itemprop="datePublished">22:06 - Sun 09 February 2025</time></a></footer></blockquote>

<blockquote class="social-embed" id="social-embed-113978387603149933" lang="en" itemscope="" itemtype="https://schema.org/SocialMediaPosting"><header class="social-embed-header" itemprop="author" itemscope="" itemtype="https://schema.org/Person"><a href="https://fosstodon.org/@mala" class="social-embed-user" itemprop="url"><img class="social-embed-avatar" src="https://files.mastodon.social/cache/accounts/avatars/108/344/944/461/785/366/original/eb3c7e69b284be82.jpeg" alt="" itemprop="image"><div class="social-embed-user-names"><p class="social-embed-user-names-name" itemprop="name">@mala@fosstodon.org</p>Davide Eynard (+mala)</div></a><img class="social-embed-logo" alt="Mastodon" src="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' aria-label='Mastodon' role='img' viewBox='0 0 512 512' fill='%23fff'%3E%3Cpath d='m0 0H512V512H0'/%3E%3ClinearGradient id='a' y2='1'%3E%3Cstop offset='0' stop-color='%236364ff'/%3E%3Cstop offset='1' stop-color='%23563acc'/%3E%3C/linearGradient%3E%3Cpath fill='url(%23a)' d='M317 381q-124 28-123-39 69 15 149 2 67-13 72-80 3-101-3-116-19-49-72-58-98-10-162 0-56 10-75 58-12 31-3 147 3 32 9 53 13 46 70 69 83 23 138-9'/%3E%3Cpath d='M360 293h-36v-93q-1-26-29-23-20 3-20 34v47h-36v-47q0-31-20-34-30-3-30 28v88h-36v-91q1-51 44-60 33-5 51 21l9 15 9-15q16-26 51-21 43 9 43 60'/%3E%3C/svg%3E"></header><section class="social-embed-text" itemprop="articleBody"><p><span class="h-card" translate="no"><a href="https://mastodon.social/@Edent" class="u-url mention" rel="nofollow noopener" target="_blank">@<span>Edent</span></a></span> here’s, sadly, the only photo I took - I regret not having more now and I’d love to see one of those “he is lying to you” moments again! 😂</p><div class="social-embed-media-grid"><a href="https://files.mastodon.social/cache/media_attachments/files/113/978/387/562/133/682/original/d4a09ed617e0002c.jpeg" class="social-embed-media-link"><img class="social-embed-media" alt="A man talking in front of a presentation slide. The slide shows a “color picker” circle at the top and below it the following text:Colours BotTooting a beautiful new color every few hours.Made by @Edent@mastodon.socialFollowing: 0 | Followers: 1051This software is licensed under AGPL 3.0This site is a basic ActivityPub server designed to be a lightweight […]Terence Eden - Open Ideas Ltd" src="data:image/webp;base64,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"></a></div></section><hr class="social-embed-hr"><footer class="social-embed-footer"><a href="https://fosstodon.org/@mala/113978387535114301"><span aria-label="1 likes" class="social-embed-meta">❤️ 1</span><span aria-label="1 replies" class="social-embed-meta">💬 1</span><span aria-label="0 reposts" class="social-embed-meta">🔁 0</span><time datetime="2025-02-10T07:22:53.000Z" itemprop="datePublished">07:22 - Mon 10 February 2025</time></a></footer></blockquote>
<img src="https://shkspr.mobi/blog/wp-content/themes/edent-wordpress-theme/info/okgo.php?ID=58000&HTTP_REFERER=RSS" alt="" width="1" height="1" loading="eager">]]></content:encoded>
					
					<wfw:commentRss>https://shkspr.mobi/blog/2025/02/presenting-activitybot-at-fosdem/feed/</wfw:commentRss>
			<slash:comments>4</slash:comments>
		
		
			</item>
		<item>
		<title><![CDATA[Introducing ActivityBot - the simplest way to build Mastodon Bots]]></title>
		<link>https://shkspr.mobi/blog/2024/11/introducing-activitybot-the-simplest-way-to-build-mastodon-bots/</link>
					<comments>https://shkspr.mobi/blog/2024/11/introducing-activitybot-the-simplest-way-to-build-mastodon-bots/#comments</comments>
				<dc:creator><![CDATA[@edent]]></dc:creator>
		<pubDate>Sun, 10 Nov 2024 12:34:00 +0000</pubDate>
				<category><![CDATA[/etc/]]></category>
		<category><![CDATA[ActivityPub]]></category>
		<category><![CDATA[bot]]></category>
		<category><![CDATA[fediverse]]></category>
		<guid isPermaLink="false">https://shkspr.mobi/blog/?p=53728</guid>

					<description><![CDATA[As you may have read, BotsIn.Space is closing down, I have lots of automated bot accounts living on the Fediverse - and I want them to continue posting.  Installing and maintaining an entire Mastodon instance sounds like hard work. Paying people to host my stuff feels like putting my fate in someone else&#039;s hands.  Say… didn&#039;t I write my own ActivityPub server? Why, yes! Yes I did!  I took the c…]]></description>
										<content:encoded><![CDATA[<p>As you may have read, <a href="https://muffinlabs.com/posts/2024/10/29/10-29-rip-botsin-space/">BotsIn.Space is closing down</a>, I have lots of automated bot accounts living on the Fediverse - and I want them to continue posting.  Installing and maintaining an entire Mastodon instance sounds like hard work. Paying people to host my stuff feels like putting my fate in someone else's hands.</p>

<p>Say… didn't I write <a href="https://shkspr.mobi/blog/2024/03/updates-to-activitypub-in-a-single-php-file/">my own ActivityPub server</a>? Why, yes! Yes I did!</p>

<p>I took the code and stripped it down to the bare essentials. All you need to do is upload two files<sup id="fnref:env"><a href="https://shkspr.mobi/blog/2024/11/introducing-activitybot-the-simplest-way-to-build-mastodon-bots/#fn:env" class="footnote-ref" title="You can also upload a .env file for your configuration if you want." role="doc-noteref">0</a></sup> - <code>index.php</code> and <code>.htaccess</code> - fill in your details, and you're done.</p>

<p><a href="https://gitlab.com/edent/activity-bot/">Get the ActivityBot source code on GitLab</a>.</p>

<p>There's no database, no containers, no caching. It is as simple as I could make it</p>

<p>This bot can do the following:</p>

<ul>
<li>🔍 Be discovered on the Fediverse</li>
<li>👉 Be followed by other accounts</li>
<li>🚫 Be unfollowed by accounts</li>
<li>📩 Send messages to the Fediverse</li>
<li>💌 Send direct messages to users</li>
<li>🖼️ Attach an image &amp; alt text to a message</li>
<li>🕸️ Autolink URls, hashtags, and @ mentions</li>
<li>🚚 Move followers from an old account</li>
<li>🔏 Verify cryptographic signatures</li>
<li>🪵 Log sent messages and error.</li>
</ul>

<p>That's it! Here's what it <em>doesn't</em> do:</p>

<ul>
<li>❌ Receive messages (other than follows and unfollows)</li>
<li>❌ Thread replies</li>
<li>❌ Delete or update a post</li>
<li>❌ Create Polls</li>
<li>❌ Attach multiple images</li>
<li>❌ Set focus point for images</li>
<li>❌ Set sensitivity for images / blur</li>
<li>❌ Set "Content Warning"</li>
<li>❌ Accurate support for converting user's text to HTML</li>
<li>❌ Cannot be discovered by Lemmy instances</li>
</ul>

<p>Grab a subdomain (don't buy a whole new domain name!) and <a href="https://gitlab.com/edent/activity-bot/">stick this code on it</a>. You'll have an ActivityPub bot running in minutes.</p>

<p>You can follow one of my bots <code>@colours@colours.bots.edent.tel</code></p>

<p>Feedback very much welcome.</p>

<div id="footnotes" role="doc-endnotes">
<hr>
<ol start="0">

<li id="fn:env">
<p>You can also upload a <code>.env</code> file for your configuration if you want.&nbsp;<a href="https://shkspr.mobi/blog/2024/11/introducing-activitybot-the-simplest-way-to-build-mastodon-bots/#fnref:env" class="footnote-backref" role="doc-backlink">↩︎</a></p>
</li>

</ol>
</div>
<img src="https://shkspr.mobi/blog/wp-content/themes/edent-wordpress-theme/info/okgo.php?ID=53728&HTTP_REFERER=RSS" alt="" width="1" height="1" loading="eager">]]></content:encoded>
					
					<wfw:commentRss>https://shkspr.mobi/blog/2024/11/introducing-activitybot-the-simplest-way-to-build-mastodon-bots/feed/</wfw:commentRss>
			<slash:comments>9</slash:comments>
		
		
			</item>
		<item>
		<title><![CDATA[Social Media Blocking Has Always Been A Lie]]></title>
		<link>https://shkspr.mobi/blog/2024/09/social-media-blocking-has-always-been-a-lie/</link>
					<comments>https://shkspr.mobi/blog/2024/09/social-media-blocking-has-always-been-a-lie/#comments</comments>
				<dc:creator><![CDATA[@edent]]></dc:creator>
		<pubDate>Tue, 24 Sep 2024 11:34:48 +0000</pubDate>
				<category><![CDATA[/etc/]]></category>
		<category><![CDATA[ActivityPub]]></category>
		<category><![CDATA[BlueSky]]></category>
		<category><![CDATA[mastodon]]></category>
		<category><![CDATA[Social Media]]></category>
		<category><![CDATA[twitter]]></category>
		<guid isPermaLink="false">https://shkspr.mobi/blog/?p=53274</guid>

					<description><![CDATA[What does it mean to block someone on a social media site?  Way back in the mists of time, we dealt with trolls on Usenet with the almighty PLONK - PLaced On Newsgroup Killfile.  It meant your newsreader never downloaded their posts. They could rant at you all day long, and you&#039;d never hear from them.  It&#039;s what we would nowadays call &#34;Mute&#34;.  But, whether you&#039;re on Usenet or a modern social…]]></description>
										<content:encoded><![CDATA[<p>What does it mean to block someone on a social media site?</p>

<p>Way back in the mists of time, we dealt with trolls on Usenet with the almighty PLONK - <a href="https://members.newsdemon.com/what-is-plonk.php">PLaced On Newsgroup Killfile</a>.  It meant your newsreader never downloaded their posts. They could rant at you all day long, and you'd never hear from them.  It's what we would nowadays call "Mute".</p>

<p>But, whether you're on Usenet or a modern social network, muting someone doesn't actually stop them replying to you. The miscreant can still see your posts, interact with them, quote them. And everyone on that service can see their abuse. Perhaps they will also join in?</p>

<p>Most modern social networks now have the concept of "Block". When Alice blocks Bob, it means Bob cannot see Alice's posts.  The service doesn't deliver her content to him. If he goes looking, he can't find it. She is invisible to him.</p>

<p>Except, of course, that's a lie. If Bob logs out of his account, he can see Alice's public content. If he logs into an alternative account, he isn't blocked.</p>

<p>The block is a <em>social signal</em> backed up with mild technical restrictions.</p>

<p>What do I mean by that? Ordinarily, you will have no idea that you have been blocked by someone. They will simply vanish from your screens.  You do not receive an alert that you've been blocked. Technical restrictions mean you won't see their posts, nor replies to them.  The only way you might know is if you deliberately look for the person blocking you.</p>

<p>Seeing that you have been blocked is a "social signal". It lets you know that your behaviour was unwanted, or that your contributions weren't valued, or that someone just doesn't like you.  For most people, that sort of chastisement probably induces a little shame or grief.  For others, it is enraging.</p>

<p>Again, it isn't impossible for a blocked user to see content - but technical restrictions means it takes <em>effort</em>.  And, it turns out, for all but the most obsessive abusers - a mild bit of UI friction is all that it takes for them to stop.</p>

<p>On a centralised social media platform, like Twitter and Facebook, your blocks are private. The only people who know you have blocked Taylor Swift are you, the platform, and T-Swizzle herself.</p>

<p>On decentralised social media platforms, it is more complicated.</p>

<p>Mastodon / ActivityPub lets you block a user. In doing so, you have to tell that user's server that you don't want them seeing your messages. That means your server knows about the block, their server know, and the user knows. But, crucially, there's nothing to stop a malicious server ignoring your wishes.  While your server can mute all the interactions from them, there are only <a href="https://fedi.tips/authorized-fetch/">weak technological restrictions on their behaviour</a>.</p>

<p>BlueSky / AT Protocol takes a different (and more worrying) approach. BlueSky tells <em>everyone</em> about your blocks. If Alice blocks Bob - the system lets everyone know. This means that if Bob starts replying to your posts, other clients will know to ignore his interactions with you. I've written more <a href="https://bsky.app/profile/edent.tel/post/3l4rjxx32br2j">about the dangers of public blocklists over on BSky</a>.</p>

<p>But, crucially, <strong>none of these systems actually block users</strong>.  This isn't like that <a href="https://black-mirror.fandom.com/wiki/White_Christmas">Black Mirror episode</a> where people are literally blurred out from your eyeballs.</p>

<p>In <em>all</em> cases, a user can log out and see your public posts. They can sign in with an alternative account. And, in the case of decentralised social media, they can choose to ignore the technological restrictions you impose.</p>

<p>Social networks have a responsibility to keep their users safe. That means having enough friction to prevent casual abuse.</p>

<p>But blocking is <em>only</em> a social signal.  That's all it ever has been. It is a boop on the nose with a rolled up newspaper. It is a message to tell someone that they might want to adjust their attitude.</p>

<p>You should block - and block often. You should feel empowered to curate an environment that is safe for you. But you should also understand the limitations of the technical controls which underpin these social signals.</p>
<img src="https://shkspr.mobi/blog/wp-content/themes/edent-wordpress-theme/info/okgo.php?ID=53274&HTTP_REFERER=RSS" alt="" width="1" height="1" loading="eager">]]></content:encoded>
					
					<wfw:commentRss>https://shkspr.mobi/blog/2024/09/social-media-blocking-has-always-been-a-lie/feed/</wfw:commentRss>
			<slash:comments>2</slash:comments>
		
		
			</item>
		<item>
		<title><![CDATA[No, ActivityPub votes aren't anonymous]]></title>
		<link>https://shkspr.mobi/blog/2024/09/no-activitypub-isnt-anonymous/</link>
					<comments>https://shkspr.mobi/blog/2024/09/no-activitypub-isnt-anonymous/#comments</comments>
				<dc:creator><![CDATA[@edent]]></dc:creator>
		<pubDate>Mon, 09 Sep 2024 11:34:07 +0000</pubDate>
				<category><![CDATA[/etc/]]></category>
		<category><![CDATA[ActivityPub]]></category>
		<category><![CDATA[fediverse]]></category>
		<category><![CDATA[mastodon]]></category>
		<category><![CDATA[privacy]]></category>
		<guid isPermaLink="false">https://shkspr.mobi/blog/?p=52999</guid>

					<description><![CDATA[Several years ago, I posted this poll on Twitter.  Terence Eden is on Mastodon@edentIf the recent Twitter hack had exposed they way you voted on every Twitter poll, how would you feel?(There is no suggestion that this has happened, I&#039;m just curious about people&#039;s relationships to voting and privacy.)Meh. So what?: (167)167Hmph. That&#039;s annoying.: (68)68Umm… This could be bad!: (32)32Delete account …]]></description>
										<content:encoded><![CDATA[<p>Several years ago, I posted this poll on Twitter.</p>

<blockquote class="social-embed" id="social-embed-1286178187937042432" lang="en" itemscope="" itemtype="https://schema.org/SocialMediaPosting"><header class="social-embed-header" itemprop="author" itemscope="" itemtype="https://schema.org/Person"><a href="https://twitter.com/edent" class="social-embed-user" itemprop="url"><img class="social-embed-avatar social-embed-avatar-circle" src="data:image/webp;base64,UklGRkgBAABXRUJQVlA4IDwBAACQCACdASowADAAPrVQn0ynJCKiJyto4BaJaQAIIsx4Au9dhDqVA1i1RoRTO7nbdyy03nM5FhvV62goUj37tuxqpfpPeTBZvrJ78w0qAAD+/hVyFHvYXIrMCjny0z7wqsB9/QE08xls/AQdXJFX0adG9lISsm6kV96J5FINBFXzHwfzMCr4N6r3z5/Aa/wfEoVGX3H976she3jyS8RqJv7Jw7bOxoTSPlu4gNbfXYZ9TnbdQ0MNnMObyaRQLIu556jIj03zfJrVgqRM8GPwRoWb1M9AfzFe6Mtg13uEIqrTHmiuBpH+bTVB5EEQ3uby0C//XOAPJOFv4QV8RZDPQd517Khyba8Jlr97j2kIBJD9K3mbOHSHiQDasj6Y3forATbIg4QZHxWnCeqqMkVYfUAivuL0L/68mMnagAAA" alt="" itemprop="image"><div class="social-embed-user-names"><p class="social-embed-user-names-name" itemprop="name">Terence Eden is on Mastodon</p>@edent</div></a><img class="social-embed-logo" alt="Twitter" src="data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%0Aaria-label%3D%22Twitter%22%20role%3D%22img%22%0AviewBox%3D%220%200%20512%20512%22%3E%3Cpath%0Ad%3D%22m0%200H512V512H0%22%0Afill%3D%22%23fff%22%2F%3E%3Cpath%20fill%3D%22%231d9bf0%22%20d%3D%22m458%20140q-23%2010-45%2012%2025-15%2034-43-24%2014-50%2019a79%2079%200%2000-135%2072q-101-7-163-83a80%2080%200%200024%20106q-17%200-36-10s-3%2062%2064%2079q-19%205-36%201s15%2053%2074%2055q-50%2040-117%2033a224%20224%200%2000346-200q23-16%2040-41%22%2F%3E%3C%2Fsvg%3E"></header><section class="social-embed-text" itemprop="articleBody">If the recent Twitter hack had exposed they way you voted on every Twitter poll, how would you feel?<br><br>(There is no suggestion that this has happened, I'm just curious about people's relationships to voting and privacy.)<hr class="social-embed-hr"><label for="poll_1_count">Meh. So what?: (167)</label><br><meter class="social-embed-meter" id="poll_1_count" min="0" max="100" low="33" high="66" value="60.7">167</meter><br><label for="poll_2_count">Hmph. That's annoying.: (68)</label><br><meter class="social-embed-meter" id="poll_2_count" min="0" max="100" low="33" high="66" value="24.7">68</meter><br><label for="poll_3_count">Umm… This could be bad!: (32)</label><br><meter class="social-embed-meter" id="poll_3_count" min="0" max="100" low="33" high="66" value="11.6">32</meter><br><label for="poll_4_count">Delete account &amp; run away: (8)</label><br><meter class="social-embed-meter" id="poll_4_count" min="0" max="100" low="33" high="66" value="2.9">8</meter></section><hr class="social-embed-hr"><footer class="social-embed-footer"><a href="https://twitter.com/edent/status/1286178187937042432"><span aria-label="0 likes" class="social-embed-meta">❤️ 0</span><span aria-label="8 replies" class="social-embed-meta">💬 8</span><span aria-label="0 reposts" class="social-embed-meta">🔁 0</span><time datetime="2020-07-23T05:55:50.000Z" itemprop="datePublished">05:55 - Thu 23 July 2020</time></a></footer></blockquote>

<p>Most of the tech world that I interact with has moved to Mastodon and other ActivityPub-based social networks.  Decentralised social media is <em>great</em>. It allows you to be fully in control of what you post, what you see, and how you interact with others.</p>

<p>Of course, there are downsides. No centralised authorities means verification is difficult. Abuse (of all sorts) can only be dealt with in a piecemeal fashion. And anonymity takes a bit of a nosedive.</p>

<p>When you block or mute someone, that information <a href="https://shkspr.mobi/blog/2023/07/fediverse-account-portability-and-blocking/">might leak to the offending user</a>. By its nature, you need to send a message to someone else's server in order to interact with them.</p>

<p>So what about polls on the Fediverse?  This poll, for example, is gathering sensitive personal information.</p>

<blockquote class="social-embed" id="social-embed-113079948257450773" lang="en" itemscope="" itemtype="https://schema.org/SocialMediaPosting"><header class="social-embed-header" itemprop="author" itemscope="" itemtype="https://schema.org/Person"><a href="https://blackrock.city/@farooqkz" class="social-embed-user" itemprop="url"><img class="social-embed-avatar" src="https://files.mastodon.social/cache/accounts/avatars/110/487/620/471/518/769/original/8e8c3e9b9b7b122e.png" alt="" itemprop="image"><div class="social-embed-user-names"><p class="social-embed-user-names-name" itemprop="name">@farooqkz@blackrock.city</p>Farooq Karimi Zadeh</div></a><img class="social-embed-logo" alt="Mastodon" src="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' aria-label='Mastodon' role='img' viewBox='0 0 512 512' fill='%23fff'%3E%3Cpath d='m0 0H512V512H0'/%3E%3ClinearGradient id='a' y2='1'%3E%3Cstop offset='0' stop-color='%236364ff'/%3E%3Cstop offset='1' stop-color='%23563acc'/%3E%3C/linearGradient%3E%3Cpath fill='url(%23a)' d='M317 381q-124 28-123-39 69 15 149 2 67-13 72-80 3-101-3-116-19-49-72-58-98-10-162 0-56 10-75 58-12 31-3 147 3 32 9 53 13 46 70 69 83 23 138-9'/%3E%3Cpath d='M360 293h-36v-93q-1-26-29-23-20 3-20 34v47h-36v-47q0-31-20-34-30-3-30 28v88h-36v-91q1-51 44-60 33-5 51 21l9 15 9-15q16-26 51-21 43 9 43 60'/%3E%3C/svg%3E"></header><section class="social-embed-text" itemprop="articleBody"><p>Let's see how many Muslims are out there on Fediverse. Are you a <a href="https://blackrock.city/tags/muslim" class="mention hashtag" rel="nofollow noopener noreferrer" target="_blank">#<span>muslim</span></a>? </p><p><a href="https://blackrock.city/tags/Islam" class="mention hashtag" rel="nofollow noopener noreferrer" target="_blank">#<span>Islam</span></a> <a href="https://blackrock.city/tags/Religion" class="mention hashtag" rel="nofollow noopener noreferrer" target="_blank">#<span>Religion</span></a> <a href="https://blackrock.city/tags/God" class="mention hashtag" rel="nofollow noopener noreferrer" target="_blank">#<span>God</span></a> </p><p>Please boost it so we can have more accurate statistics.</p><div class="social-embed-media-grid"></div><hr class="social-embed-hr"><label for="poll_0">I am a Muslim: (62)</label><br><meter class="social-embed-meter" id="poll_0" min="0" max="100" low="33" high="66" value="1.6">62</meter><br><label for="poll_1">Not a Muslim: (3,696)</label><br><meter class="social-embed-meter" id="poll_1" min="0" max="100" low="33" high="66" value="98.4">3696</meter><br></section><hr class="social-embed-hr"><footer class="social-embed-footer"><a href="https://blackrock.city/@farooqkz/113079948160094406"><span aria-label="11 likes" class="social-embed-meta">❤️ 11</span><span aria-label="30 replies" class="social-embed-meta">💬 30</span><span aria-label="874 reposts" class="social-embed-meta">🔁 874</span><time datetime="2024-09-04T15:17:56.000Z" itemprop="datePublished">15:17 - Wed 04 September 2024</time></a></footer></blockquote>

<p>In order to vote on the poll, your server sends a message to the poll's server saying "I am user @someone@example.com. I wish to vote for option X. Here is an HTTP signature confirming my message."</p>

<p>Does the receiving server abide by GDPR? Who knows!</p>

<p>The <a href="https://www.w3.org/TR/activitystreams-vocabulary/#questions">specification around questions</a> is a little ill-defined and the <a href="https://docs.joinmastodon.org/methods/polls/#vote">Mastodon documentation</a> is also a bit vague. Neither of them discuss privacy.</p>

<p>There is an <a href="https://humberto.io/blog/mastodon_poll_in_activitypub/">excellent blog post by Humberto Rocha looking at Mastodon Poll in ActivityPub</a>. It shows quite clearly that a vote is just a normal message which is passed onto the receiving server.</p>

<p>Services like Mastodon won't let the poll's author see who voted for which option. But that's by convention. There's nothing technical to stop them. Indeed, I understand that <a href="https://outerheaven.club/notice/Aln6q1bVGpyToIx7J2">the Akkoma social network <em>does</em> show users how users voted</a>.</p>

<p>Of course, on a centralised service like Facebook or Twitter your vote is still recorded somewhere. It can be subpoenaed or looked at by unscrupulous engineers.</p>

<p>Privacy is, of course, a social construct. In some communities it might be sensible to have all votes on the public record. In others, it could be deadly.  Some countries have laws mandating strong privacy protections, others less so.</p>

<p>Conduct yourself with that in mind!</p>
<img src="https://shkspr.mobi/blog/wp-content/themes/edent-wordpress-theme/info/okgo.php?ID=52999&HTTP_REFERER=RSS" alt="" width="1" height="1" loading="eager">]]></content:encoded>
					
					<wfw:commentRss>https://shkspr.mobi/blog/2024/09/no-activitypub-isnt-anonymous/feed/</wfw:commentRss>
			<slash:comments>4</slash:comments>
		
		
			</item>
		<item>
		<title><![CDATA[Who can reply?]]></title>
		<link>https://shkspr.mobi/blog/2024/06/who-can-reply/</link>
					<comments>https://shkspr.mobi/blog/2024/06/who-can-reply/#comments</comments>
				<dc:creator><![CDATA[@edent]]></dc:creator>
		<pubDate>Tue, 25 Jun 2024 11:34:08 +0000</pubDate>
				<category><![CDATA[/etc/]]></category>
		<category><![CDATA[ActivityPub]]></category>
		<category><![CDATA[mastodon]]></category>
		<category><![CDATA[Social Media]]></category>
		<guid isPermaLink="false">https://shkspr.mobi/blog/?p=50898</guid>

					<description><![CDATA[Vague thoughts as they enter my brainbox.  The BlueSky social network has introduced &#34;Reply Gating&#34; - it looks like this:   You can write your hot take on Taylor Swift and not be inundated by weirdos replying to you. Nifty!  This is nothing new. Twitter has it. Facebook has the concept of &#34;audiences&#34; to restrict who your post is visible to.    And, of course, blogging has this! There is a comment …]]></description>
										<content:encoded><![CDATA[<p>Vague thoughts as they enter my brainbox.</p>

<p>The <a href="https://bsky.app/">BlueSky social network</a> has introduced "Reply Gating" - it looks like this:
<img src="https://shkspr.mobi/blog/wp-content/uploads/2024/06/Bluesky-fs8.png" alt="Who can reply?
Choose &quot;Everybody&quot; or &quot;Nobody&quot; Or combine these options: Mentioned users, Followed users." width="720" height="472" class="aligncenter size-full wp-image-50899"></p>

<p>You can write your hot take on Taylor Swift and <em>not</em> be inundated by weirdos replying to you. Nifty!</p>

<p>This is nothing new. Twitter has it. Facebook has the concept of "audiences" to restrict who your post is visible to.</p>

<img src="https://shkspr.mobi/blog/wp-content/uploads/2024/06/Facebook-fs8.png" alt="Facebook's audience page with options to share to select groups." width="720" height="869" class="aligncenter size-full wp-image-50900">

<p>And, of course, blogging has this! There is a comment form at the bottom of this page - and I moderate it. If you post something stupid, I don't have to subject my audience to your inanities. I can (and do) block users from commenting.</p>

<p>ActivityPub doesn't have this (yet). It's much more like a public mailing list.  I can block or mute you - which stops me from seeing your abuse - but doesn't stop anyone else from seeing it.</p>

<p>Should ActivityPub have something similar? Yeah, I reckon so. I'd like to be able to say "Anyone I know want to go to the pub tonight" and only have mutuals reply. I want to prune away spam or repetitive replies.  It would be helpful to have a conversation in public that other people can't interrupt.</p>

<p>The UI would be complex. And the social model needs a bit of work. And there are some technical challenges around syndicating <em>which</em> replies should be included.</p>

<p>But, ultimately, social media should respond to the needs of its users.</p>
<img src="https://shkspr.mobi/blog/wp-content/themes/edent-wordpress-theme/info/okgo.php?ID=50898&HTTP_REFERER=RSS" alt="" width="1" height="1" loading="eager">]]></content:encoded>
					
					<wfw:commentRss>https://shkspr.mobi/blog/2024/06/who-can-reply/feed/</wfw:commentRss>
			<slash:comments>16</slash:comments>
		
		
			</item>
		<item>
		<title><![CDATA[The Fediverse of Things]]></title>
		<link>https://shkspr.mobi/blog/2024/04/the-fediverse-of-things/</link>
					<comments>https://shkspr.mobi/blog/2024/04/the-fediverse-of-things/#comments</comments>
				<dc:creator><![CDATA[@edent]]></dc:creator>
		<pubDate>Sun, 07 Apr 2024 11:34:31 +0000</pubDate>
				<category><![CDATA[/etc/]]></category>
		<category><![CDATA[ActivityPub]]></category>
		<category><![CDATA[fediverse]]></category>
		<category><![CDATA[IoT]]></category>
		<category><![CDATA[Social Networks]]></category>
		<guid isPermaLink="false">https://shkspr.mobi/blog/?p=50085</guid>

					<description><![CDATA[One of the most frustrating things in modern technology is the effort spent trying to artificially restrict abundance.  Take, for example, this tale from museum-worker Aaron Cope:  I was out with a friend who worked for Twitter and I asked them whether it would be possible for the museum to “create 200,000 Twitter accounts, one for each object in the Cooper Hewitt’s collection”. My friend looked a…]]></description>
										<content:encoded><![CDATA[<p>One of the most frustrating things in modern technology is the effort spent trying to artificially restrict abundance.</p>

<p>Take, for example, <a href="https://millsfield.sfomuseum.org/blog/2024/03/12/activitypub/">this tale from museum-worker Aaron Cope</a>:</p>

<blockquote><p>I was out with a friend who worked for Twitter and I asked them whether it would be possible for the museum to “create 200,000 Twitter accounts, one for each object in the Cooper Hewitt’s collection”. My friend looked at me for a moment, laughed, and then simply said: No.
</p></blockquote>

<p>In that blog post, Aaron reveals that the San Francisco International Airport Museum is using ActivityPub to create automated social-media bot accounts for all its exhibits and, possibly, every object it hold.</p>

<p>And why not! That would be close to impossible to do on a centralised service. But on a decentralised service under your own control, it is relatively simple.  Perhaps I only want to follow the museum's canteen, or I just want to engage with a specific artefact. The Fediverse makes that possible.</p>

<p>This reminds me of the <a href="https://www.bbc.co.uk/news/magazine-33560182">Melbourne "treemail" phenomenon</a>. Every tree in the city had an email address, ostensibly so residents could email maintenance issues for a specific tree. Instead, people started interacting with the trees and sending them little love notes!</p>

<blockquote><p>Dearest Golden Elm Tree, I finally found you! As in I see you everyday on my way to uni, but I had no idea of what kind of tree you are. You are the most beautiful tree in the city and I love you
</p></blockquote>

<p>A few weeks ago, I read about <a href="https://bensmith.blog/posts/i-invented-tweeting-trains-probably">Ben Smith inventing Tweeting trains</a>. With a bit of code, every train line in the UK was suddenly represented on the web in a convenient format. Well… Convenient if you were on Twitter.</p>

<p>Museums, trees, and trains naturally brings me on to the Internet of Things. I think it is fair to say that IoT is in a bit of an odd place right now. <a href="https://csa-iot.org/all-solutions/matter/">Matter</a> is a confusing mishmash of standards.  Security and privacy issues dog the simplest devices. Many people don't even <em>want</em> their toaster online!</p>

<p>For the majority of domestic uses, people want an <em>Intranet</em> of Things. There's little need to have your light-bulbs controlled when you're outside of WiFi range.  Similarly, it is probably a <em>really</em> bad idea to have your <a href="https://www.politico.com/news/2023/11/28/federal-government-investigating-multiple-hacks-of-us-water-utilities-00128977">hydroelectric dam connected to the Internet</a>.</p>

<p>Which brings me back to the Fediverse.</p>

<p>On the one hand, it would be nice to be able to follow <code>@Yellow_Line@Transit_Authority.gov</code> - or even <code>@Bus_Stop_1234@bus_company.biz</code> - that would allow for hyperfocused data getting to the right people.  It seems feasible that <em>every</em> civic object could have a Fediverse account. From the individual streetlights to the municipal sewerage system.  Perhaps people won't send love letters to overflowing drains - but a social-dashboard of your civic environment could be both practical and delightful.</p>

<p>And, as for your <em>domestic</em> gadgets? Why not give every room, or every light-bulb, in your home a <em>private</em> Fediverse account? You could send a message like:</p>

<blockquote><p>Hey @thermostat@My_Home.example.com, please set the temperature to 19°C. Thanks!
</p></blockquote>

<p>That might be a bit much! But I like the idea of a <em>private</em> social network which consists of all my IoT gadgets talking to me and each other.</p>
<img src="https://shkspr.mobi/blog/wp-content/themes/edent-wordpress-theme/info/okgo.php?ID=50085&HTTP_REFERER=RSS" alt="" width="1" height="1" loading="eager">]]></content:encoded>
					
					<wfw:commentRss>https://shkspr.mobi/blog/2024/04/the-fediverse-of-things/feed/</wfw:commentRss>
			<slash:comments>15</slash:comments>
		
		
			</item>
		<item>
		<title><![CDATA[How updates work in ActivityPub / Mastodon]]></title>
		<link>https://shkspr.mobi/blog/2024/03/how-updates-work-in-activitypub-mastodon/</link>
					<comments>https://shkspr.mobi/blog/2024/03/how-updates-work-in-activitypub-mastodon/#comments</comments>
				<dc:creator><![CDATA[@edent]]></dc:creator>
		<pubDate>Fri, 15 Mar 2024 12:34:28 +0000</pubDate>
				<category><![CDATA[/etc/]]></category>
		<category><![CDATA[ActivityPub]]></category>
		<category><![CDATA[mastodon]]></category>
		<guid isPermaLink="false">https://shkspr.mobi/blog/?p=49894</guid>

					<description><![CDATA[I didn&#039;t realise this, so I&#039;m documenting it to stop other people making the same silly mistake that I did.  Messages in ActivityPub have two distinct ID strings.  Here&#039;s a (truncated) view of what happens when I send a new message on Mastodon:    &#38;quot;id&#38;quot;: &#38;quot;https://mastodon.social/users/Edent/statuses/1234567890/activity&#38;quot;,   &#38;quot;type&#38;quot;: &#38;quot;Create&#38;quot;,  …]]></description>
										<content:encoded><![CDATA[<p>I didn't realise this, so I'm documenting it to stop other people making the same silly mistake that I did.</p>

<p>Messages in ActivityPub have <em>two distinct</em> ID strings.  Here's a (truncated) view of what happens when I send a new message on Mastodon:</p>

<pre><code class="language-json">  &amp;quot;id&amp;quot;: &amp;quot;https://mastodon.social/users/Edent/statuses/1234567890/activity&amp;quot;,
  &amp;quot;type&amp;quot;: &amp;quot;Create&amp;quot;,
  &amp;quot;actor&amp;quot;: &amp;quot;https://mastodon.social/users/Edent&amp;quot;,
  &amp;quot;published&amp;quot;: &amp;quot;2024-03-10T16:13:49Z&amp;quot;,
  &amp;quot;object&amp;quot;: {
    &amp;quot;id&amp;quot;: &amp;quot;https://mastodon.social/users/Edent/statuses/1234567890&amp;quot;,
    &amp;quot;type&amp;quot;: &amp;quot;Note&amp;quot;,
    &amp;quot;content&amp;quot;: &amp;quot;Hello&amp;quot;
...
</code></pre>

<p>The "Note" has some human-readable content, some metadata, and an ID - in this case a URl ending with <code>1234567890</code></p>

<p>But that Note is wrapped in an <em>Activity</em>. In this case, it is a "Create" message, with some metadata, and it's <em>own</em> ID - in this case ending <code>1234567890/activity</code></p>

<p>What happens if I edit the post? Here's a truncated view of what the server sends:</p>

<pre><code class="language-json">  &amp;quot;id&amp;quot;: &amp;quot;https://mastodon.social/users/Edent/statuses/1234567890#updates/1710087334&amp;quot;,
  &amp;quot;type&amp;quot;: &amp;quot;Update&amp;quot;,
  &amp;quot;actor&amp;quot;: &amp;quot;https://mastodon.social/users/Edent&amp;quot;,
  &amp;quot;published&amp;quot;: &amp;quot;2024-03-10T16:15:34Z&amp;quot;,
  &amp;quot;object&amp;quot;: {
    &amp;quot;id&amp;quot;: &amp;quot;https://mastodon.social/users/Edent/statuses/1234567890&amp;quot;,
    &amp;quot;type&amp;quot;: &amp;quot;Note&amp;quot;,
    &amp;quot;content&amp;quot;: &amp;quot;I meant Goodbye!&amp;quot;
...
</code></pre>

<p>The "Note" has the <em>same</em> ID as before - but the activity has a <em>different</em> ID.</p>

<p>Further updates follow the same pattern:</p>

<pre><code class="language-JSON">  &amp;quot;id&amp;quot;: &amp;quot;https://mastodon.social/users/Edent/statuses/1234567890#updates/1984651324&amp;quot;,
  &amp;quot;type&amp;quot;: &amp;quot;Update&amp;quot;,
  &amp;quot;object&amp;quot;: {
    &amp;quot;id&amp;quot;: &amp;quot;https://mastodon.social/users/Edent/statuses/1234567890&amp;quot;,
...
</code></pre>

<p>So what happens when I <em>Delete</em> a previously updated post?</p>

<p>Here's what's sent:</p>

<pre><code class="language-JSON">  &amp;quot;id&amp;quot;: &amp;quot;https://mastodon.social/users/Edent/statuses/1234567890#delete&amp;quot;,
  &amp;quot;type&amp;quot;: &amp;quot;Delete&amp;quot;,
  &amp;quot;actor&amp;quot;: &amp;quot;https://mastodon.social/users/Edent&amp;quot;,
  &amp;quot;object&amp;quot;: {
    &amp;quot;id&amp;quot;: &amp;quot;https://mastodon.social/users/Edent/statuses/1234567890&amp;quot;,
    &amp;quot;type&amp;quot;: &amp;quot;Tombstone&amp;quot;,
...
</code></pre>

<p>Again, the Activity has its own, unique, ID. But it is <em>the original ID</em> of the Note which is to be deleted!</p>

<p>The <a href="https://www.w3.org/TR/activitypub/#obj-id">spec says that all IDs must be URls</a> - but it doesn't say what format they should be in. Mastodon helpfully makes the Activity's ID somewhat related to the object's ID - but not all software will do that.</p>

<p>So, if you're doing something like saving messages to disk or a database, use the <em>object</em> ID as the canonical reference. The ID of the Activity isn't particularly important when it comes to receiving updates, deletes, replies, or anything else.</p>
<img src="https://shkspr.mobi/blog/wp-content/themes/edent-wordpress-theme/info/okgo.php?ID=49894&HTTP_REFERER=RSS" alt="" width="1" height="1" loading="eager">]]></content:encoded>
					
					<wfw:commentRss>https://shkspr.mobi/blog/2024/03/how-updates-work-in-activitypub-mastodon/feed/</wfw:commentRss>
			<slash:comments>2</slash:comments>
		
		
			</item>
		<item>
		<title><![CDATA[I made a mistake in verifying HTTP Message Signatures]]></title>
		<link>https://shkspr.mobi/blog/2024/03/i-made-a-mistake-in-verifying-http-message-signatures/</link>
					<comments>https://shkspr.mobi/blog/2024/03/i-made-a-mistake-in-verifying-http-message-signatures/#comments</comments>
				<dc:creator><![CDATA[@edent]]></dc:creator>
		<pubDate>Thu, 14 Mar 2024 12:34:05 +0000</pubDate>
				<category><![CDATA[/etc/]]></category>
		<category><![CDATA[ActivityPub]]></category>
		<category><![CDATA[CyberSecurity]]></category>
		<category><![CDATA[http]]></category>
		<category><![CDATA[security]]></category>
		<guid isPermaLink="false">https://shkspr.mobi/blog/?p=49885</guid>

					<description><![CDATA[It&#039;s never great to find out you&#039;re wrong, but that&#039;s how learning and personal growth happens.  HTTP Message Signatures are hard. There are lots of complex parts and getting any aspect wrong means certain death.  In a previous post, I wrote A simple(ish) guide to verifying HTTP Message Signatures in PHP. It turns out that it was too simple. And far too trusting.  An HTTP Message Signature is a…]]></description>
										<content:encoded><![CDATA[<p>It's never great to find out you're wrong, but that's how learning and personal growth happens.</p>

<p>HTTP Message Signatures are hard<sup id="fnref:hard"><a href="https://shkspr.mobi/blog/2024/03/i-made-a-mistake-in-verifying-http-message-signatures/#fn:hard" class="footnote-ref" title="You might think the Entscheidungsproblem is hard, but that's just peanuts compared to etc. etc." role="doc-noteref">0</a></sup>. There are lots of complex parts and getting any aspect wrong means certain death<sup id="fnref:death"><a href="https://shkspr.mobi/blog/2024/03/i-made-a-mistake-in-verifying-http-message-signatures/#fn:death" class="footnote-ref" title="Or cake." role="doc-noteref">1</a></sup>.</p>

<p>In a previous post, I wrote <a href="https://shkspr.mobi/blog/2024/02/a-simpleish-guide-to-verifying-http-message-signatures-in-php/">A simple(ish) guide to verifying HTTP Message Signatures in PHP</a>. It turns out that it was <em>too</em> simple. And far too trusting.</p>

<p>An HTTP Message Signature is a header which is separate to the message it signs.  You might receive a JSON message like this:</p>

<pre><code class="language-json">{
   "actor":   "https://example.com/user/Alice",
   "message": "We strike at dawn!"
}
</code></pre>

<p>How do you know that <em>really</em> came from Alice? You look at the header of the message. It will be something like:</p>

<pre><code class="language-_">Signature: 
   keyId="https://example.org/user/Alice#main-key",
   algorithm="rsa-sha256",
   headers="(request-target) host date digest",
   signature="/AJ4Dv/wSL3XE1dLjFHCYVc7AF4f3+Q10G/r8+6cPsooiUh2K3YX3z++Nclo4qKHYr61yu+T4OMqUry1T6ZHmZqmNkg1RpVg=="
</code></pre>

<p>We want to check that Alice signed this message with her <em>private</em> key. So we grab her <em>public</em> key given by the <code>keyId</code>.
From there, we do some fancy maths using RSA-SHA256 and conclude that, when you put together the <code>(request-target) host date digest content-type</code> and compare them to the public key, they can only have be signed by the private key. Hurrah!</p>

<p>Did you spot the mistake I made? It wasn't in the maths, or the complex ordering of the data, or the algorithm choice, or some weird Unicode problem.</p>

<p>I made an error in <em>trust</em>.</p>

<p>Take a look at the Signature again.</p>

<p>The <code>keyId</code> is from example.<strong>org</strong>. But the actor is from example.<strong>com</strong>.</p>

<p>This message <em>is</em> signed correctly. It <em>is</em> cryptographically valid. <strong>But it wasn't signed by the actor in the message!</strong></p>

<p>In this case, the fix is simple.  Get the public key from <code>keyId</code>. Then <em>independently</em> get the named actor's public key.  If they match, all is well. If not, skulduggery is afoot.</p>

<p>I'm <em>almost</em> tempted to say that you should <em>ignore</em> the provided <code>keyId</code> entirely; the source of truth is the actor's key - and the best way to get that is directly from the actor's profile.</p>

<p>Please explain why I'm wrong in the comments.</p>

<div id="footnotes" role="doc-endnotes">
<hr>
<ol start="0">

<li id="fn:hard">
<p>You might think the <i lang="de">Entscheidungsproblem</i> is hard, but that's just <em>peanuts</em> compared to etc. etc.&nbsp;<a href="https://shkspr.mobi/blog/2024/03/i-made-a-mistake-in-verifying-http-message-signatures/#fnref:hard" class="footnote-backref" role="doc-backlink">↩︎</a></p>
</li>

<li id="fn:death">
<p>Or cake.&nbsp;<a href="https://shkspr.mobi/blog/2024/03/i-made-a-mistake-in-verifying-http-message-signatures/#fnref:death" class="footnote-backref" role="doc-backlink">↩︎</a></p>
</li>

</ol>
</div>
<img src="https://shkspr.mobi/blog/wp-content/themes/edent-wordpress-theme/info/okgo.php?ID=49885&HTTP_REFERER=RSS" alt="" width="1" height="1" loading="eager">]]></content:encoded>
					
					<wfw:commentRss>https://shkspr.mobi/blog/2024/03/i-made-a-mistake-in-verifying-http-message-signatures/feed/</wfw:commentRss>
			<slash:comments>5</slash:comments>
		
		
			</item>
		<item>
		<title><![CDATA[Updates to ActivityPub in a single PHP file]]></title>
		<link>https://shkspr.mobi/blog/2024/03/updates-to-activitypub-in-a-single-php-file/</link>
					<comments>https://shkspr.mobi/blog/2024/03/updates-to-activitypub-in-a-single-php-file/#comments</comments>
				<dc:creator><![CDATA[@edent]]></dc:creator>
		<pubDate>Sun, 03 Mar 2024 12:34:16 +0000</pubDate>
				<category><![CDATA[/etc/]]></category>
		<category><![CDATA[ActivityPub]]></category>
		<category><![CDATA[php]]></category>
		<guid isPermaLink="false">https://shkspr.mobi/blog/?p=49829</guid>

					<description><![CDATA[A few weeks ago, I built an ActivityPub Server in a Single PHP File. It&#039;s a proof of concept showing how easy it is to turn a website into a full-featured Fediverse participant.  After a bunch of feedback and testing, I&#039;ve added a some features to make it slightly more useful.   A single PHP file - 45KB of no-library goodness. Just add your details, upload, and done. No databases. Everything…]]></description>
										<content:encoded><![CDATA[<p>A few weeks ago, I <a href="https://shkspr.mobi/blog/2024/02/activitypub-server-in-a-single-file/">built an ActivityPub Server in a Single PHP File</a>. It's a proof of concept showing how easy it is to turn a website into a full-featured Fediverse participant.</p>

<p>After a bunch of feedback and testing, I've added a some features to make it slightly more useful.</p>

<ul>
<li>A single PHP file - 45KB of no-library goodness. Just add your details, upload, and done.</li>
<li>No databases. Everything stored as JSON files on disk.</li>
<li>Be followed. External users can discover and follow you.</li>
<li>Send messages. You can send messages to all your followers.</li>
<li>🆕 Follow users. You can follow other Fediverse actors.</li>
<li>🆕 Read messages. You can read the messages sent to your Inbox. If media is attached, those will be displayed.</li>
<li>🆕 Verify signatures. ActivityPub messages can by cryptographically signed. <a href="https://shkspr.mobi/blog/2024/02/a-simpleish-guide-to-verifying-http-message-signatures-in-php/">This now verifies those signatures</a>.</li>
</ul>

<p>You can <a href="https://gitlab.com/edent/activitypub-single-php-file/">grab the code here</a> - pull requests welcome.  If you want to see what it looks like in action, visit <a href="https://example.viii.fi/">https://example.viii.fi/</a> or follow <code>@example@example.viii.fi</code>.</p>

<p>Again, to re-emphasise what it says in the README - this is <strong>not</strong> suitable for production use. This is primarily a way to explain all the different functions of an ActivityPub server.  It is adequately commented and I hope a moderately competent programmer could follow what's going on. It is almost certainly insecure and is considered harmful to aquatic life.</p>

<p>I would be delighted if you took the code and did something interesting with it. Perhaps create a single-file server in your favourite language?</p>

<h2 id="todo"><a href="https://shkspr.mobi/blog/2024/03/updates-to-activitypub-in-a-single-php-file/#todo">ToDo</a></h2>

<p>A few random things which I might add - or which you might consider making and sending a Pull Request:</p>

<ul>
<li>Better UI. It is deliberately bare-bones, see the <a href="https://example.viii.fi/read"><code>/read</code> interface</a>. But perhaps there's a simpler way to make it look nice?</li>
<li>No threading in the UI - and no ability to reply to messages.</li>
<li>Support for reading hashtagged posts on the site.</li>
<li>Reply highlighting - at the moment you can't see if a message was sent to you.</li>
<li>Some Fediverse posts contain polls, content warnings, and other extended features. That could be fun to support - both for reading and writing.</li>
<li>Support for reading <a href="https://docs.joinmastodon.org/spec/activitypub/#Emoji">custom emoji</a>.
</li><li>Deletes, Updates, and Undos are received - but it currently doesn't remove the previously saved file.</li>
<li>There's no way to unfollow a user - except for manually deleting data from the file-system.</li>
<li>Only supports one image upload. Could support more? Or even other media?</li>
<li>I don't think CC works properly.</li>
<li>Message visibility could be useful.</li>
<li>Boring stuff like better error handling.</li>
</ul>

<p>If you have opinions, please let me know!</p>
<img src="https://shkspr.mobi/blog/wp-content/themes/edent-wordpress-theme/info/okgo.php?ID=49829&HTTP_REFERER=RSS" alt="" width="1" height="1" loading="eager">]]></content:encoded>
					
					<wfw:commentRss>https://shkspr.mobi/blog/2024/03/updates-to-activitypub-in-a-single-php-file/feed/</wfw:commentRss>
			<slash:comments>3</slash:comments>
		
		
			</item>
		<item>
		<title><![CDATA[A simple(ish) guide to verifying HTTP Message Signatures in PHP]]></title>
		<link>https://shkspr.mobi/blog/2024/02/a-simpleish-guide-to-verifying-http-message-signatures-in-php/</link>
					<comments>https://shkspr.mobi/blog/2024/02/a-simpleish-guide-to-verifying-http-message-signatures-in-php/#comments</comments>
				<dc:creator><![CDATA[@edent]]></dc:creator>
		<pubDate>Tue, 27 Feb 2024 12:34:04 +0000</pubDate>
				<category><![CDATA[/etc/]]></category>
		<category><![CDATA[ActivityPub]]></category>
		<category><![CDATA[cryptography]]></category>
		<category><![CDATA[http]]></category>
		<category><![CDATA[mastodon]]></category>
		<category><![CDATA[security]]></category>
		<guid isPermaLink="false">https://shkspr.mobi/blog/?p=49733</guid>

					<description><![CDATA[Mastodon makes heavy use of HTTP Message Signatures. They&#039;re a newish almost-standard which allows a server to verify that a request made to it came from the person who sent it.  This is a quick example to show how to verify these signatures using PHP. I don&#039;t claim that it covers every use-case, and it is no-doubt missing some weird edge cases. But it successfully verifies messages sent by…]]></description>
										<content:encoded><![CDATA[<p>Mastodon makes heavy use of <a href="https://datatracker.ietf.org/doc/rfc9421/">HTTP Message Signatures</a>. They're a newish almost-standard which allows a server to verify that a request made to it came from the person who sent it.</p>

<p>This is a quick example to show how to verify these signatures using PHP. I don't claim that it covers every use-case, and it is no-doubt missing some weird edge cases. But it successfully verifies messages sent by multiple Fediverse servers.</p>

<p>Let's step through it with an example of a message sent from Mastodon to my server.</p>

<h2 id="headers"><a href="https://shkspr.mobi/blog/2024/02/a-simpleish-guide-to-verifying-http-message-signatures-in-php/#headers">Headers</a></h2>

<p>The HTTP request starts with these headers:</p>

<pre><code class="language-_">User-Agent:  http.rb/5.1.1 (Mastodon/4.3.0-nightly.2024-02-23; +https://mastodon.social/)
Host:  example.com
Date:  Sun, 25 Feb 2024 10:48:22 GMT
Accept-Encoding:  gzip
Digest:  SHA-256=Hqu/6MR2imi8DTzbNp5PNEAFSyk0poN7+x5F+Z4vZMg=
Content-Type:  application/activity+json
Signature:  keyId="https://mastodon.social/users/Edent#main-key",algorithm="rsa-sha256",headers="(request-target) host date digest content-type",signature="P07V5I2zflR8FRsDMHshHmhgOwSkjWevujEbOyKMwjycrdVXjTD0ACiLuc5lTqDEXZ/...4eg=="
Connection:  Keep-Alive
Content-Length:  2857
</code></pre>

<p>Some of those you may be familiar with, some not.  The first thing we'll do is a sanity check; was this message sent recently? Because clocks drift in and out of synchronisation, we'll check if the message was within ±30 seconds.</p>

<pre><code class="language-php">$headers = getallheaders();
if ( !isset( $headers["Date"] ) ) { return null; }  //  No date set
$dateHeader = $headers["Date"];
$headerDatetime  = DateTime::createFromFormat('D, d M Y H:i:s T', $dateHeader);
$currentDatetime = new DateTime();

// Calculate the time difference in seconds
$timeDifference = abs( $currentDatetime-&gt;getTimestamp() - $headerDatetime-&gt;getTimestamp() );
return ( $timeDifference &lt; 30 );
</code></pre>

<p>That was easy! On to the next bit.</p>

<h2 id="digest"><a href="https://shkspr.mobi/blog/2024/02/a-simpleish-guide-to-verifying-http-message-signatures-in-php/#digest">Digest</a></h2>

<p>A message posted to the server usually has a body. In this case it is a long string of JSON data.  To ensure the message hasn't been altered in transit, one of the headers is:</p>

<pre><code class="language-_">Digest:  SHA-256=Hqu/6MR2imi8DTzbNp5PNEAFSyk0poN7+x5F+Z4vZMg=
</code></pre>

<p>That says, if you do a SHA-256 hash of the JSON you received, and convert that hash to Base64, it should match the digest in the header.</p>

<pre><code class="language-php">$digestString = $headers["Digest"];
//  Usually in the form `SHA-256=Hqu/6MR2imi8DTzbNp5PNEAFSyk0poN7+x5F+Z4vZMg=`
//  The Base64 encoding may have multiple `=` at the end. So split this at the first `=`
$digestData = explode( "=", $digestString, 2 );
$digestAlgorithm = $digestData[0];
$digestHash = $digestData[1];

//  There might be many different hashing algorithms
//  TODO: Find a way to transform these automatically
if ( "SHA-256" == $digestAlgorithm ) {
    $digestAlgorithm = "sha256";
} else if ( "SHA-512" == $digestAlgorithm ) {
    $digestAlgorithm = "sha512";
}

$json = file_get_contents( "php://input" );

//  Manually calculate the digest based on the data sent
$digestCalculated = base64_encode( hash( $digestAlgorithm, $json, true ) );

return ( $digestCalculated == $digestHash );
</code></pre>

<p>But, of course, if someone has manipulated the JSON, they may also have manipulated the digest. So it is time to look at the signature.</p>

<h2 id="the-signature"><a href="https://shkspr.mobi/blog/2024/02/a-simpleish-guide-to-verifying-http-message-signatures-in-php/#the-signature">The Signature</a></h2>

<p>Let's take a look at the signature header:</p>

<pre><code class="language-_">Signature:
  keyId="https://mastodon.social/users/Edent#main-key",
  algorithm="rsa-sha256",
  headers="(request-target) host date digest content-type",
  signature="P07V5I2zflR8FRsDMHshHmhgOwSkjWevujEbOyKMwjycrdVXjTD0ACiLuc5lTqDEXZ/...4eg=="
</code></pre>

<p>This contains 4 pieces of information.</p>

<ol>
<li><code>keyID</code> - a link to the user's public key.</li>
<li><code>algorithm</code> - the algorithm used by this signature.</li>
<li><code>headers</code> - the headers which make up the string to be signed.</li>
<li><code>signature</code> - the signature string.</li>
</ol>

<p>Let's split them up so they can be used:</p>

<pre><code class="language-php">//  Examine the signature
$signatureHeader = $headers["Signature"];

// Extract key information from the Signature header
$signatureParts = [];
//  Converts 'a=b,c=d e f' into ["a"=&gt;"b", "c"=&gt;"d e f"]
               // word="text"
preg_match_all('/(\w+)="([^"]+)"/', $signatureHeader, $matches);
foreach ($matches[1] as $index =&gt; $key) {
    $signatureParts[$key] = $matches[2][$index];
}
</code></pre>

<p>Let's tackle each part in order.</p>

<h3 id="get-the-users-public-key"><a href="https://shkspr.mobi/blog/2024/02/a-simpleish-guide-to-verifying-http-message-signatures-in-php/#get-the-users-public-key">Get the user's public key</a></h3>

<p>You might think you can just get <code>https://mastodon.social/users/Edent#main-key</code> - but you would be wrong.</p>

<p>Firstly, you need to tell the key server that you want the JSON representation of the URl - otherwise you'll end up with HTML.</p>

<pre><code class="language-php">$publicKeyURL = $signatureParts["keyId"];
$context   = stream_context_create(
    [ "http" =&gt; [ "header" =&gt; "Accept: application/activity+json" ] ] 
);
$userJSON  = file_get_contents( $publicKeyURL, false, $context );
</code></pre>

<p>That gets you the JSON representation of the user.  On Mastodon, the key can be found at:
<img src="https://shkspr.mobi/blog/wp-content/uploads/2024/02/jsonkey.pnh-fs8.png" alt="Screenshot of JSON. As described in text." width="938" height="355" class="aligncenter size-full wp-image-49734"></p>

<p>I don't know how to automatically find the key, so I've hard-coded its location.</p>

<pre><code class="language-php">$userData  = json_decode( $userJSON, true );
$publicKey = $userData["publicKey"]["publicKeyPem"];
</code></pre>

<h3 id="get-the-algorithm"><a href="https://shkspr.mobi/blog/2024/02/a-simpleish-guide-to-verifying-http-message-signatures-in-php/#get-the-algorithm">Get the algorithm</a></h3>

<p>This is rather straightforward. It's just the text in the signature header:</p>

<pre><code class="language-php">$algorithm = $signatureParts["algorithm"];
</code></pre>

<h3 id="reconstruct-the-signing-header"><a href="https://shkspr.mobi/blog/2024/02/a-simpleish-guide-to-verifying-http-message-signatures-in-php/#reconstruct-the-signing-header">Reconstruct the signing header</a></h3>

<p>Let's take a look at the third piece of the puzzle:</p>

<p><code>headers="(request-target) host date digest content-type"</code></p>

<p>This says "The signature is based on the following parts in order". So we only care about the headers which make up the request, the host, the date, the digest, and the content type. Other servers may require different parts of the headers.</p>

<p>Again, let's tackle them in order.</p>

<h4 id="request-target"><a href="https://shkspr.mobi/blog/2024/02/a-simpleish-guide-to-verifying-http-message-signatures-in-php/#request-target"><code>(request-target)</code></a></h4>

<p>This means the method of the request and the target it was sent to.  In our example, this is a <code>POST</code> sent to the path <code>/inbox</code>.</p>

<h4 id="host"><a href="https://shkspr.mobi/blog/2024/02/a-simpleish-guide-to-verifying-http-message-signatures-in-php/#host"><code>host</code></a></h4>

<p>This is the HTTP host the message was sent to.  This should be retrieved from the server, not taken from the sent headers.</p>

<h4 id="date-digest-content-type"><a href="https://shkspr.mobi/blog/2024/02/a-simpleish-guide-to-verifying-http-message-signatures-in-php/#date-digest-content-type"><code>date digest content-type</code></a></h4>

<p>These are the values from the headers which were sent with the request.</p>

<h4 id="putting-it-all-together"><a href="https://shkspr.mobi/blog/2024/02/a-simpleish-guide-to-verifying-http-message-signatures-in-php/#putting-it-all-together">Putting it all together</a></h4>

<p>Annoyingly, the HTTP headers are written in Title-Case whereas the headers in the Signature are in lower-case. So some conversion is necessary:</p>

<pre><code class="language-php">//  Manually reconstruct the header string
$signatureHeaders = explode(" ", $signatureParts["headers"] );
$signatureString = "";
foreach ($signatureHeaders as $signatureHeader) {
    if ( "(request-target)" == $signatureHeader ) {
        $method = strtolower( $_SERVER["REQUEST_METHOD"] );
        $target = strtolower( $_SERVER["REQUEST_URI"] );
        $signatureString .= "(request-target): {$method} {$target}\n";
    } else if ( "host" == $signatureHeader ) {
        $host = strtolower( $_SERVER["HTTP_HOST"] );    
        $signatureString .= "host: {$host}\n";
    } else {
        //  In the HTTP header, the keys use Title Case
        $signatureString .= "{$signatureHeader}: " . $headers[ ucwords( $signatureHeader, "-" ) ] . "\n";
    }
}

//  Remove trailing newline
$signatureString = trim( $signatureString );
</code></pre>

<p>This results in a string like this:</p>

<pre><code class="language-_">(request-target): post /inbox
host: example.com
date: Sun, 25 Feb 2024 10:48:22 GMT
digest: SHA-256=Hqu/6MR2imi8DTzbNp5PNEAFSyk0poN7+x5F+Z4vZMg=
content-type: application/activity+json
</code></pre>

<h2 id="get-the-signature"><a href="https://shkspr.mobi/blog/2024/02/a-simpleish-guide-to-verifying-http-message-signatures-in-php/#get-the-signature">Get the signature</a></h2>

<p>The signature that we are sent is in Base64.</p>

<p><code>signature="P07V5I2zflR8FRsDMHshHmhgOwSkjWevujEbOyKMwjycrdVXjTD0ACiLuc5lTqDEXZ/...4eg=="</code></p>

<p>It needs to be decoded before we can use it.</p>

<pre><code class="language-php">$signature = base64_decode( $signatureParts["signature"] );
</code></pre>

<h2 id="verify-the-signature"><a href="https://shkspr.mobi/blog/2024/02/a-simpleish-guide-to-verifying-http-message-signatures-in-php/#verify-the-signature">Verify the signature</a></h2>

<p>We're nearly there!  Luckily, we don't have to do any crazy cryptography by hand. We use PHP's <a href="https://www.php.net/manual/en/function.openssl-verify"><code>openssl_verify()</code></a>:</p>

<pre><code class="language-php">//  Finally! Calculate whether the signature is valid
$verified = openssl_verify(
    $signatureString, 
    $signature, 
    $publicKey, 
    $algorithm
);
</code></pre>

<p>That takes the reconstructed string based on the headers, the signature which was sent, the public key we retrieved, and the algorithm.</p>

<p>If it all matches, it will return <code>true</code>.  If not... time for some debugging!</p>

<h2 id="but-what-about"><a href="https://shkspr.mobi/blog/2024/02/a-simpleish-guide-to-verifying-http-message-signatures-in-php/#but-what-about">But what about...?</a></h2>

<p>This is <em>not</em> a complete solution. My code almost certainly contains bugs, unforeseen edge-cases, memory leaks, black holes, and poisonous frogs.  This is intended to step you through the practical process of verifying an HTTP Message Signature.</p>

<p>Then you should get a properly tested and validated library and use that instead.</p>
<img src="https://shkspr.mobi/blog/wp-content/themes/edent-wordpress-theme/info/okgo.php?ID=49733&HTTP_REFERER=RSS" alt="" width="1" height="1" loading="eager">]]></content:encoded>
					
					<wfw:commentRss>https://shkspr.mobi/blog/2024/02/a-simpleish-guide-to-verifying-http-message-signatures-in-php/feed/</wfw:commentRss>
			<slash:comments>2</slash:comments>
		
		
			</item>
		<item>
		<title><![CDATA[HTTP Signature Infinite Loop?]]></title>
		<link>https://shkspr.mobi/blog/2024/02/http-signature-infinite-loop/</link>
					<comments>https://shkspr.mobi/blog/2024/02/http-signature-infinite-loop/#comments</comments>
				<dc:creator><![CDATA[@edent]]></dc:creator>
		<pubDate>Mon, 26 Feb 2024 12:34:28 +0000</pubDate>
				<category><![CDATA[/etc/]]></category>
		<category><![CDATA[ActivityPub]]></category>
		<category><![CDATA[CyberSecurity]]></category>
		<category><![CDATA[encryption]]></category>
		<category><![CDATA[fediverse]]></category>
		<category><![CDATA[http]]></category>
		<guid isPermaLink="false">https://shkspr.mobi/blog/?p=49728</guid>

					<description><![CDATA[I&#039;m trying to get my head round HTTP Signatures as they&#039;re used extensively in the Fediverse.  Conceptually, they&#039;re relatively straightforward.  You send me a normal HTTP request. For example, you want to POST something to https://example.com/data  You send me these headers:  POST /data Host: example.com Date: Sat, 24 Feb 2024 14:43:48 GMT Accept-Encoding: gzip Digest:…]]></description>
										<content:encoded><![CDATA[<p>I'm trying to get my head round <a href="https://www.rfc-editor.org/rfc/rfc9421.html">HTTP Signatures</a> as they're used extensively in the Fediverse.</p>

<p>Conceptually, they're relatively straightforward.</p>

<p>You send me a normal HTTP request. For example, you want to POST something to <code>https://example.com/data</code></p>

<p>You send me these headers:</p>

<pre><code class="language-_">POST /data
Host: example.com
Date: Sat, 24 Feb 2024 14:43:48 GMT
Accept-Encoding: gzip
Digest: SHA-256=aaC57TDzM0Wq+50We2TkCsdMDvdqON92edg7KI+Hk8M=
Content-Type: application/activity+json
Signature: keyId="https://your_website.biz/publicKey",algorithm="rsa-sha256",headers="(request-target) host date digest content-type",signature="JGQ53kEoIiMWRp9By9jajVGCOCu4n7XBeiA1uY5xLcnAxL2Y1GIgU/...=="
Connection: Keep-Alive
Content-Length: 751
</code></pre>

<p>In order to verify the contents of the message, I need to do three things:</p>

<ol>
<li>Check the SHA-256 hash of the message matches the content of the "Digest" header.</li>
<li>Check the timestamp is somewhat fresh.</li>
<li>Check the signature matches.</li>
</ol>

<p>The first is simple: <code>base64_encode( hash( "sha256", $request_body, true ) )</code>.</p>

<p>The second is a matter of opinion. I might be happy to receive messages from the distant past or far in the future. For the sake of a little clock drift, let's allow 60 seconds either way.</p>

<p>The third gets <em>complicated</em>.</p>

<p>First, I need to get the public key published at <code>keyId="https://your_website.biz/publicKey"</code>.</p>

<p>Next, I need to know which algorithm is being used to sign the headers: <code>algorithm="rsa-sha256"</code></p>

<p>Then, I need to know which headers - and in what order - are being signed: <code>headers="(request-target) host date digest content-type"</code></p>

<p>So I create a string using the received details which matches those headers in that specific order:</p>

<pre><code class="language-_">(request-target) POST /data
Host: example.com
Date: Sat, 24 Feb 2024 14:43:48 GMT
Digest: SHA-256=aaC57TDzM0Wq+50We2TkCsdMDvdqON92edg7KI+Hk8M=
Content-Type: application/activity+json
</code></pre>

<p>I can verify if the signature - <code>signature="JGQ53kEoIiMWRp9By9jajVGCOCu4n7XBeiA1uY5xLcnAxL2Y1GIgU/...=="</code> matches by:</p>

<pre><code class="language-php">openssl_verify(
    $headersString, 
    $signature, 
    $publicKey, 
    $algorithm
);
</code></pre>

<p>If that's <code>TRUE</code> then all is well.</p>

<p>But can you spot the implicit problem?</p>

<p><em>How</em> do I get your server's public key?</p>

<p>I just GET <code>https://your_website.biz/publicKey</code> - but if your server uses something like <a href="https://docs.joinmastodon.org/admin/config/#authorized_fetch">Authorised Fetch</a> then I have to sign my request to you.</p>

<p>Which means your server will need to validate my signature by obtaining my public key. Which it will get by signing a request and sending it to me. Which, before I return my public key, I will need to validate your signature by obtaining your public key. Which I will get by signing a request... and so on.</p>

<p>This <a href="https://www.w3.org/wiki/SocialCG/ActivityPub/Authentication_Authorization#Instance_actors">deadlock loop</a> is documented. The usual way around it is either for the <em>sending</em> server to <a href="https://socialhub.activitypub.rocks/t/authorized-fetch-and-the-instance-actor/3868">use an instance-specific signature</a> which can be retrieved by an unsigned request, or to allow any unsigned request to access a user's public key.</p>

<p>I get why things happen this way - I just wish it were easier to implement!</p>
<img src="https://shkspr.mobi/blog/wp-content/themes/edent-wordpress-theme/info/okgo.php?ID=49728&HTTP_REFERER=RSS" alt="" width="1" height="1" loading="eager">]]></content:encoded>
					
					<wfw:commentRss>https://shkspr.mobi/blog/2024/02/http-signature-infinite-loop/feed/</wfw:commentRss>
			<slash:comments>10</slash:comments>
		
		
			</item>
		<item>
		<title><![CDATA[ActivityPub Server in a Single PHP File]]></title>
		<link>https://shkspr.mobi/blog/2024/02/activitypub-server-in-a-single-file/</link>
					<comments>https://shkspr.mobi/blog/2024/02/activitypub-server-in-a-single-file/#comments</comments>
				<dc:creator><![CDATA[@edent]]></dc:creator>
		<pubDate>Sun, 18 Feb 2024 12:34:48 +0000</pubDate>
				<category><![CDATA[/etc/]]></category>
		<category><![CDATA[ActivityPub]]></category>
		<category><![CDATA[mastodon]]></category>
		<category><![CDATA[php]]></category>
		<guid isPermaLink="false">https://shkspr.mobi/blog/?p=49641</guid>

					<description><![CDATA[Any computer program can be designed to run from a single file if you architect it wrong enough!  I wanted to create the simplest possible Fediverse server which can be used as an educational tool to show how ActivityPub / Mastodon works.  The design goals were:   Upload a single PHP file to the server. No databases or separate config files. Single Actor (i.e. not multi-user). Allow the Actor to…]]></description>
										<content:encoded><![CDATA[<p>Any computer program can be designed to run from a single file if you architect it wrong enough!</p>

<p>I wanted to create the simplest possible Fediverse server which can be used as an educational tool to show how ActivityPub / Mastodon works.</p>

<p>The design goals were:</p>

<ul>
<li>Upload a single PHP file to the server.</li>
<li>No databases or separate config files.</li>
<li>Single Actor (i.e. not multi-user).</li>
<li>Allow the Actor to be followed.</li>
<li>Post plain-text messages to followers.</li>
<li>Be <em>roughly</em> standards compliant.</li>
</ul>

<p>And those goals have all been met! <a href="https://gitlab.com/edent/activitypub-single-php-file/">Check it out on GitLab</a>. I warn you though, it is the <em>nadir</em> of bad coding. There are no tests, bugger-all security, scalability isn't considered, and it is a mess. But it <em>works</em>.</p>

<p>You can follow the test user <code>@example@example.viii.fi</code></p>

<h2 id="architecture"><a href="https://shkspr.mobi/blog/2024/02/activitypub-server-in-a-single-file/#architecture">Architecture</a></h2>

<p>Firstly, I've slightly cheated on my "single file" stipulation. There's an <code>.htaccess</code> file which turns <code>example.com/whatever</code> into <code>example.com/index.php?path=whatever</code></p>

<p>The <code>index.php</code> file then takes that path and does <em>stuff</em>. It also contains all the configuration variables which is <strong>very bad</strong> practice.</p>

<p>Rather than using a database, it saves files to disk.</p>

<p>Again, this is <strong>not suitable</strong> for any real world use. This is an educational tool to help explain the basics of posting messages to the Fediverse.  It requires absolutely no dependencies. You do not need to spin up a dockerised hypervisor to manage your node bundles and re-compile everything to WASM. Just FTP the file up to prod and you're done.</p>

<h2 id="walkthrough"><a href="https://shkspr.mobi/blog/2024/02/activitypub-server-in-a-single-file/#walkthrough">Walkthrough</a></h2>

<p>This is a quick ramble through the code. It is reasonably well documented, I hope.</p>

<h3 id="preamble"><a href="https://shkspr.mobi/blog/2024/02/activitypub-server-in-a-single-file/#preamble">Preamble</a></h3>

<p>This is where you set up your account's name and bio. You also need to provide a public/private keypair. The posting page is protected with a password that also needs to be set here.</p>

<pre><code class="language-php">    //  Set up the Actor's information
    $username = rawurlencode("example");    //  Encoded as it is often used as part of a URl
    $realName = "E. Xample. Jr.";
    $summary  = "Some text about the user.";
    $server   = $_SERVER["SERVER_NAME"];    //  Domain name this is hosted on

    //  Generate locally or from https://cryptotools.net/rsagen
    //  Newlines must be replaced with "\n"
    $key_private = "-----BEGIN RSA PRIVATE KEY-----\n...\n-----END RSA PRIVATE KEY-----";
    $key_public  = "-----BEGIN PUBLIC KEY-----\n...\n-----END PUBLIC KEY-----";

    //  Password for sending messages
    $password = "P4ssW0rd";
</code></pre>

<h3 id="logging"><a href="https://shkspr.mobi/blog/2024/02/activitypub-server-in-a-single-file/#logging">Logging</a></h3>

<p>ActivityPub is a "chatty" protocol. This takes all the requests your server receives and saves them in <code>/logs/</code> as a datestamped text file.</p>

<pre><code class="language-php">    // Get all headers and requests sent to this server
    $headers     = print_r( getallheaders(), true );
    $postData    = print_r( $_POST,    true );
    $getData     = print_r( $_GET,     true );
    $filesData   = print_r( $_FILES,   true );
    $body        = json_decode( file_get_contents( "php://input" ), true );
    $bodyData    = print_r( $body,    true );
    $requestData = print_r( $_REQUEST, true );
    $serverData  = print_r( $_SERVER,  true );

    //  Get the type of request - used in the log filename
    if ( isset( $body["type"] ) ) {
        $type = " " . $body["type"];
    } else {
        $type = "";
    }

    //  Create a timestamp in ISO 8601 format for the filename
    $timestamp = date( "c" );
    //  Filename for the log
    $filename  = "{$timestamp}{$type}.txt";

    //  Save headers and request data to the timestamped file in the logs directory
    if( ! is_dir( "logs" ) ) { mkdir( "logs"); }

    file_put_contents( "logs/{$filename}", 
        "Headers:     \n$headers    \n\n" .
        "Body Data:   \n$bodyData   \n\n" .
        "POST Data:   \n$postData   \n\n" .
        "GET Data:    \n$getData    \n\n" .
        "Files Data:  \n$filesData  \n\n" .
        "Request Data:\n$requestData\n\n" .
        "Server Data: \n$serverData \n\n"
    );
</code></pre>

<h3 id="routing"><a href="https://shkspr.mobi/blog/2024/02/activitypub-server-in-a-single-file/#routing">Routing</a></h3>

<p>The <code>.htaccess</code> changes <code>/whatever</code> to <code>/?path=whatever</code>
This runs the function of the path requested.</p>

<pre><code class="language-php">    !empty( $_GET["path"] )  ? $path = $_GET["path"] : die();
    switch ($path) {
        case ".well-known/webfinger":
            webfinger();
        case rawurldecode( $username ):
            username();
        case "following":
            following();
        case "followers":
            followers();
        case "inbox":
            inbox();
        case "write":
            write();
        case "send":
            send();
        default:
            die();
    }
</code></pre>

<h3 id="webfinger"><a href="https://shkspr.mobi/blog/2024/02/activitypub-server-in-a-single-file/#webfinger">WebFinger</a></h3>

<p>The <a href="https://docs.joinmastodon.org/spec/webfinger/">WebFinger Protocol</a> is used to identify accounts.
It is requested with <code>example.com/.well-known/webfinger?resource=acct:username@example.com</code>
This server only has one user, so it ignores the query string and always returns the same details.</p>

<pre><code class="language-php">    function webfinger() {
        global $username, $server;

        $webfinger = array(
            "subject" =&gt; "acct:{$username}@{$server}",
              "links" =&gt; array(
                array(
                     "rel" =&gt; "self",
                    "type" =&gt; "application/activity+json",
                    "href" =&gt; "https://{$server}/{$username}"
                )
            )
        );
        header( "Content-Type: application/json" );
        echo json_encode( $webfinger );
        die();
    }
</code></pre>

<h3 id="username"><a href="https://shkspr.mobi/blog/2024/02/activitypub-server-in-a-single-file/#username">Username</a></h3>

<p>Requesting <code>example.com/username</code> returns a JSON document with the user's information.</p>

<pre><code class="language-php">    function username() {
        global $username, $realName, $summary, $server, $key_public;

        $user = array(
            "@context" =&gt; [
                "https://www.w3.org/ns/activitystreams",
                "https://w3id.org/security/v1"
            ],
                                   "id" =&gt; "https://{$server}/{$username}",
                                 "type" =&gt; "Person",
                            "following" =&gt; "https://{$server}/following",
                            "followers" =&gt; "https://{$server}/followers",
                                "inbox" =&gt; "https://{$server}/inbox",
                    "preferredUsername" =&gt;  rawurldecode($username),
                                 "name" =&gt; "{$realName}",
                              "summary" =&gt; "{$summary}",
                                  "url" =&gt; "https://{$server}",
            "manuallyApprovesFollowers" =&gt;  true,
                         "discoverable" =&gt;  true,
                            "published" =&gt; "2024-02-12T11:51:00Z",
            "icon" =&gt; [
                     "type" =&gt; "Image",
                "mediaType" =&gt; "image/png",
                      "url" =&gt; "https://{$server}/icon.png"
            ],
            "publicKey" =&gt; [
                "id"           =&gt; "https://{$server}/{$username}#main-key",
                "owner"        =&gt; "https://{$server}/{$username}",
                "publicKeyPem" =&gt; $key_public
            ]
        );
        header( "Content-Type: application/activity+json" );
        echo json_encode( $user );
        die();
    }
</code></pre>

<h3 id="following-followers"><a href="https://shkspr.mobi/blog/2024/02/activitypub-server-in-a-single-file/#following-followers">Following &amp; Followers</a></h3>

<p>These JSON documents show how many users are following / followers-of this account.
The information here is self-attested. So you can lie and use any number you want.</p>

<pre><code class="language-php">function following() {
        global $server;

        $following = array(
              "@context" =&gt; "https://www.w3.org/ns/activitystreams",
                    "id" =&gt; "https://{$server}/following",
                  "type" =&gt; "Collection",
            "totalItems" =&gt; 0,
                 "items" =&gt; []
        );
        header( "Content-Type: application/activity+json" );
        echo json_encode( $following );
        die();
    }
    function followers() {
        global $server;
        $followers = array(
              "@context" =&gt; "https://www.w3.org/ns/activitystreams",
                    "id" =&gt; "https://{$server}/followers",
                  "type" =&gt; "Collection",
            "totalItems" =&gt; 0,
                 "items" =&gt; []
        );
        header( "Content-Type: application/activity+json" );
        echo json_encode( $followers );
        die();
    }
</code></pre>

<h3 id="inbox"><a href="https://shkspr.mobi/blog/2024/02/activitypub-server-in-a-single-file/#inbox">Inbox</a></h3>

<p>The <code>/inbox</code> is the main server. It receives all requests. This server only responds to "Follow" requests.
A remote server sends a follow request which is a JSON file saying who they are.
This code does not cryptographically validate the headers of the received message.
The name of the remote user's server is saved to a file so that future messages can be delivered to it.
An accept request is cryptographically signed and POST'd back to the remote server.</p>

<pre><code class="language-php">    function inbox() {
        global $body, $server, $username, $key_private;

        //  Get the message and type
        $inbox_message = $body;
        $inbox_type = $inbox_message["type"];

        //  This inbox only responds to follow requests
        if ( "Follow" != $inbox_type ) { die(); }

        //  Get the parameters
        $inbox_id    = $inbox_message["id"];
        $inbox_actor = $inbox_message["actor"];
        $inbox_host  = parse_url( $inbox_actor, PHP_URL_HOST );

        //  Does this account have any followers?
        if( file_exists( "followers.json" ) ) {
            $followers_file = file_get_contents( "followers.json" );
            $followers_json = json_decode( $followers_file, true );
        } else {
            $followers_json = array();
        }

        //  Add user to list. Don't care about duplicate users, server is what's important
        $followers_json[$inbox_host]["users"][] = $inbox_actor;

        //  Save the new followers file
        file_put_contents( "followers.json", print_r( json_encode( $followers_json ), true ) );

        //  Response Message ID
        //  This isn't used for anything important so could just be a random number
        $guid = uuid();

        //  Create the Accept message
        $message = [
            "@context" =&gt; "https://www.w3.org/ns/activitystreams",
            "id"       =&gt; "https://{$server}/{$guid}",
            "type"     =&gt; "Accept",
            "actor"    =&gt; "https://{$server}/{$username}",
            "object"   =&gt; [
                "@context" =&gt; "https://www.w3.org/ns/activitystreams",
                "id"       =&gt;  $inbox_id,
                "type"     =&gt;  $inbox_type,
                "actor"    =&gt;  $inbox_actor,
                "object"   =&gt; "https://{$server}/{$username}",
            ]
        ];

        //  The Accept is sent to the server of the user who requested the follow
        //  TODO: The path doesn't *always* end with/inbox
        $host = $inbox_host;
        $path = parse_url( $inbox_actor, PHP_URL_PATH ) . "/inbox";

        //  Get the signed headers
        $headers = generate_signed_headers( $message, $host, $path );

        //  Specify the URL of the remote server's inbox
        //  TODO: The path doesn't *always* end with /inbox
        $remoteServerUrl = $inbox_actor . "/inbox";

        //  POST the message and header to the requester's inbox
        $ch = curl_init( $remoteServerUrl );
        curl_setopt( $ch, CURLOPT_RETURNTRANSFER, true );
        curl_setopt( $ch, CURLOPT_CUSTOMREQUEST, "POST" );
        curl_setopt( $ch, CURLOPT_POSTFIELDS,     json_encode($message) );
        curl_setopt( $ch, CURLOPT_HTTPHEADER,     $headers );
        $response = curl_exec( $ch );

        //  Check for errors
        if( curl_errno( $ch ) ) {
            file_put_contents( "error.txt",  curl_error( $ch ) );
        }
        curl_close($ch);
        die();
    }
</code></pre>

<h3 id="uuid"><a href="https://shkspr.mobi/blog/2024/02/activitypub-server-in-a-single-file/#uuid">UUID</a></h3>

<p>Every message sent should have a unique ID. 
This can be anything you like. Some servers use a random number.
I prefer a date-sortable string.</p>

<pre><code class="language-php">    function uuid() {
        return sprintf( "%08x-%04x-%04x-%04x-%012x",
            time(),
            mt_rand(0, 0xffff),
            mt_rand(0, 0xffff),
            mt_rand(0, 0x3fff) | 0x8000,
            mt_rand(0, 0xffffffffffff)
        );
    }
</code></pre>

<h3 id="signing-headers"><a href="https://shkspr.mobi/blog/2024/02/activitypub-server-in-a-single-file/#signing-headers">Signing Headers</a></h3>

<p>Every message that your server sends needs to be cryptographically signed with your Private Key.
This is a complicated process. Please read "<a href="https://blog.joinmastodon.org/2018/07/how-to-make-friends-and-verify-requests/">How to make friends and verify requests</a>" for more information.</p>

<pre><code class="language-php">    function generate_signed_headers( $message, $host, $path ) {
        global $server, $username, $key_private;

        //  Encode the message to JSON
        $message_json = json_encode( $message );

        //  Location of the Public Key
        $keyId = "https://{$server}/{$username}#main-key";

        //  Generate signing variables
        $hash   = hash( "sha256", $message_json, true );
        $digest = base64_encode( $hash );
        $date   = date( "D, d M Y H:i:s \G\M\T" );

        //  Get the Private Key
        $signer = openssl_get_privatekey( $key_private );

        //  Sign the path, host, date, and digest
        $stringToSign = "(request-target): post $path\nhost: $host\ndate: $date\ndigest: SHA-256=$digest";

        //  The signing function returns the variable $signature
        //  https://www.php.net/manual/en/function.openssl-sign.php
        openssl_sign(
            $stringToSign, 
            $signature, 
            $signer, 
            OPENSSL_ALGO_SHA256
        );
        //  Encode the signature
        $signature_b64 = base64_encode( $signature );

        //  Full signature header
        $signature_header = 'keyId="' . $keyId . '",algorithm="rsa-sha256",headers="(request-target) host date digest",signature="' . $signature_b64 . '"';

        //  Header for POST reply
        $headers = array(
                    "Host: {$host}",
                    "Date: {$date}",
                  "Digest: SHA-256={$digest}",
               "Signature: {$signature_header}",
            "Content-Type: application/activity+json",
                  "Accept: application/activity+json",
        );

        return $headers;
    }
</code></pre>

<h3 id="user-interface-for-writing"><a href="https://shkspr.mobi/blog/2024/02/activitypub-server-in-a-single-file/#user-interface-for-writing">User Interface for Writing</a></h3>

<p>This creates a basic HTML form. Type in your message and your password. It then POSTs the data to the <code>/send</code> endpoint.</p>

<pre><code class="language-php">    function write() {
        //  Display an HTML form for the user to enter a message.
echo &lt;&lt;&lt; HTML
&lt;!DOCTYPE html&gt;
&lt;html lang="en-GB"&gt;
    &lt;head&gt;
        &lt;meta charset="UTF-8"&gt;
        &lt;title&gt;Send Message&lt;/title&gt;
        &lt;style&gt;
            *{font-family:sans-serif;font-size:1.1em;}
        &lt;/style&gt;
    &lt;/head&gt;
    &lt;body&gt;
        &lt;form action="/send" method="post" enctype="multipart/form-data"&gt;
            &lt;label   for="content"&gt;Your message:&lt;/label&gt;&lt;br&gt;
            &lt;textarea id="content" name="content" rows="5" cols="32"&gt;&lt;/textarea&gt;&lt;br&gt;
            &lt;label   for="password"&gt;Password&lt;/label&gt;&lt;br&gt;
            &lt;input  type="password" name="password" id="password" size="32"&gt;&lt;br&gt;
            &lt;input  type="submit"  value="Post Message"&gt; 
        &lt;/form&gt;
    &lt;/body&gt;
&lt;/html&gt;
HTML;
        die();
    }
</code></pre>

<h3 id="send-endpoint"><a href="https://shkspr.mobi/blog/2024/02/activitypub-server-in-a-single-file/#send-endpoint">Send Endpoint</a></h3>

<p>This takes the submitted message and checks the password is correct.
It reads the <code>followers.json</code> file and sends the message to every server that is following this account.</p>

<pre><code class="language-php">    function send() {
        global $password, $server, $username, $key_private;

        //  Does the posted password match the stored password?
        if( $password != $_POST["password"] ) { die(); }

        //  Get the posted content
        $content = $_POST["content"];

        //  Current time - ISO8601
        $timestamp = date( "c" );

        //  Outgoing Message ID
        $guid = uuid();

        //  Construct the Note
        //  contentMap is used to prevent unnecessary "translate this post" pop ups
        // hardcoded to English
        $note = [
            "@context"     =&gt; array(
                "https://www.w3.org/ns/activitystreams"
            ),
            "id"           =&gt; "https://{$server}/posts/{$guid}.json",
            "type"         =&gt; "Note",
            "published"    =&gt; $timestamp,
            "attributedTo" =&gt; "https://{$server}/{$username}",
            "content"      =&gt; $content,
            "contentMap"   =&gt; ["en" =&gt; $content],
            "to"           =&gt; ["https://www.w3.org/ns/activitystreams#Public"]
        ];

        //  Construct the Message
        $message = [
            "@context" =&gt; "https://www.w3.org/ns/activitystreams",
            "id"       =&gt; "https://{$server}/posts/{$guid}.json",
            "type"     =&gt; "Create",
            "actor"    =&gt; "https://{$server}/{$username}",
            "to"       =&gt; [
                "https://www.w3.org/ns/activitystreams#Public"
            ],
            "cc"       =&gt; [
                "https://{$server}/followers"
            ],
            "object"   =&gt; $note
        ];

        //  Create the context for the permalink
        $note = [ "@context" =&gt; "https://www.w3.org/ns/activitystreams", ...$note ];

        //  Save the permalink
        $note_json = json_encode( $note );
        //  Check for posts/ directory and create it
        if( ! is_dir( "posts" ) ) { mkdir( "posts"); }
        file_put_contents( "posts/{$guid}.json", print_r( $note_json, true ) );

        //  Read existing users and get their hosts
        $followers_file = file_get_contents( "followers.json" );
        $followers_json = json_decode( $followers_file, true );     
        $hosts = array_keys( $followers_json );

        //  Prepare to use the multiple cURL handle
        $mh = curl_multi_init();

        //  Loop through all the severs of the followers
        //  Each server needs its own cURL handle
        //  Each POST to an inbox needs to be signed separately
        foreach ( $hosts as $host ) {
            $path = "/inbox";

            //  Get the signed headers
            $headers = generate_signed_headers( $message, $host, $path );

            // Specify the URL of the remote server
            $remoteServerUrl = "https://{$host}{$path}";

            //  POST the message and header to the requester's inbox
            $ch = curl_init( $remoteServerUrl );

            curl_setopt( $ch, CURLOPT_RETURNTRANSFER, true );
            curl_setopt( $ch, CURLOPT_CUSTOMREQUEST, "POST" );
            curl_setopt( $ch, CURLOPT_POSTFIELDS,     json_encode($message) );
            curl_setopt( $ch, CURLOPT_HTTPHEADER,     $headers );

            //  Add the handle to the multi-handle
            curl_multi_add_handle( $mh, $ch );
        }

        //  Execute the multi-handle
        do {
            $status = curl_multi_exec( $mh, $active );
            if ( $active ) {
                curl_multi_select( $mh );
            }
        } while ( $active &amp;&amp; $status == CURLM_OK );

        //  Close the multi-handle
        curl_multi_close( $mh );

        //  Render the JSON so the user can see the POST has worked
        header( "Location: https://{$server}/posts/{$guid}.json" );
        die();
    }
</code></pre>

<h2 id="next-steps"><a href="https://shkspr.mobi/blog/2024/02/activitypub-server-in-a-single-file/#next-steps">Next Steps</a></h2>

<p>This is <em>not</em> intended to be used in production. <strong>Ever</strong>.  But if you would like to contribute more simple examples of how the protocol works, please <a href="https://gitlab.com/edent/activitypub-single-php-file/">come and play on GitLab</a>.</p>

<p>You can follow the test user <code>@example@example.viii.fi</code></p>
<img src="https://shkspr.mobi/blog/wp-content/themes/edent-wordpress-theme/info/okgo.php?ID=49641&HTTP_REFERER=RSS" alt="" width="1" height="1" loading="eager">]]></content:encoded>
					
					<wfw:commentRss>https://shkspr.mobi/blog/2024/02/activitypub-server-in-a-single-file/feed/</wfw:commentRss>
			<slash:comments>10</slash:comments>
		
		
			</item>
		<item>
		<title><![CDATA[Internationalise The Fediverse]]></title>
		<link>https://shkspr.mobi/blog/2024/02/internationalise-the-fediverse/</link>
					<comments>https://shkspr.mobi/blog/2024/02/internationalise-the-fediverse/#comments</comments>
				<dc:creator><![CDATA[@edent]]></dc:creator>
		<pubDate>Sat, 17 Feb 2024 12:34:58 +0000</pubDate>
				<category><![CDATA[/etc/]]></category>
		<category><![CDATA[ActivityPub]]></category>
		<category><![CDATA[fediverse]]></category>
		<category><![CDATA[i18n]]></category>
		<category><![CDATA[mastodon]]></category>
		<category><![CDATA[unicode]]></category>
		<guid isPermaLink="false">https://shkspr.mobi/blog/?p=49643</guid>

					<description><![CDATA[We live in the future now. It is OK to use Unicode everywhere.  It seems bizarre to me that modern Internet services sometimes &#34;forget&#34; that there&#039;s a world outside the Anglosphere. Some people have the temerity to speak foreign languages! And some of those languages have accents on their letters!! Even worse, some don&#039;t use English letters at all!!!  A decade ago, I was miffed that GitHub only…]]></description>
										<content:encoded><![CDATA[<p>We live in the future now. It is OK to use Unicode everywhere.</p>

<p>It seems bizarre to me that modern Internet services sometimes "forget" that there's a world outside the Anglosphere. Some people have the temerity to speak <em>foreign</em> languages! And some of those languages have accents on their letters!! Even worse, some don't use English letters <em>at all!!!</em></p>

<p>A decade ago, I was miffed that <a href="https://shkspr.mobi/blog/2013/06/is-github-racist/">GitHub only supported some ASCII characters</a> in its project names. There's no <em>technical</em> reason why your repo can't be called "ഹലോ വേൾഡ്".</p>

<p>Similarly, I'm frustrated that Mastodon (the largest ActivityPub service) <a href="https://github.com/mastodon/mastodon/issues/8417">doesn't allow Unicode usernames</a> and has <a href="https://jam.xwx.moe/notice/AdXsJF6Q5oYHJBEAiG">resisted efforts to change</a>.</p>

<p>So I built a small ActivityPub server which publishes content from an Actor called <a href="https://i18n.viii.fi/.well-known/webfinger"><code>@你好@i18n.viii.fi</code></a> - it is only a demo account, but it works!</p>

<p>Some ActivityPub clients report that they are able to follow it and receive messages from it. Others - like Mastodon - simply can't see anything from it.  Take a look <a href="https://mastodon.social/@Edent/111920759100955860">at the replies on Mastodon</a> to see which services work.  You can also <a href="https://fed.xnor.in/users/$Aet3ViWYORXdinGChM">see some of its posts on the Fediverse</a>.</p>

<h2 id="what-does-the-fox-spec-say"><a href="https://shkspr.mobi/blog/2024/02/internationalise-the-fediverse/#what-does-the-fox-spec-say">What Does The <del>Fox</del> Spec Say?</a></h2>

<p>The ActivityPub specification says:</p>

<blockquote><p>Building an international base of users is important in a federated network.
<a href="https://www.w3.org/TR/activitypub/#i18n-concerns">Internationalization</a></p></blockquote>

<p>I can't find anything in the specifications which limits what languages a username can be written in. But there are a few clues scattered about.</p>

<p>The user's <code>@</code> name is defined by <code>preferredUsername</code> which is:</p>

<blockquote><p>A short username which may be used to refer to the actor, with no uniqueness guarantees. 
<a href="https://www.w3.org/TR/activitypub/#preferredUsername">4.1 Actor objects</a></p></blockquote>

<p>There's nothing in there about what scripts it can contain. However, later on, the spec says:</p>

<blockquote><p>Properties containing natural language values, such as <code>name</code>, <code>preferredUsername</code>, or <code>summary</code>, make use of <a href="https://www.w3.org/TR/activitystreams-core/#naturalLanguageValues">natural language support defined in ActivityStreams</a>.
<a href="https://www.w3.org/TR/activitypub/#h-note-2">4. Actors</a></p></blockquote>

<p>So it is expected that a preferred username could be written in multiple scripts. Which implies that the default need not be limited to A-Z0-9.</p>

<p>The <a href="https://www.w3.org/TR/activitystreams-core/#marking-up-language">ActivityStreams specification talks about language mapping</a>.</p>

<p>Finally, the <a href="https://www.w3.org/TR/activitypub/#liked-property">ActivityPub specification has some examples on non-Latin text</a> in names.</p>

<p>So, I think that it is acceptable for usernames to be written in a variety of non-Latin scripts.</p>

<h2 id="but-what-about"><a href="https://shkspr.mobi/blog/2024/02/internationalise-the-fediverse/#but-what-about">But What About...?</a></h2>

<p>There are usually a few objections to "Unicode Everywhere" zealots like me. I'd like to forestall any arguments.</p>

<h3 id="what-about-homograph-attacks"><a href="https://shkspr.mobi/blog/2024/02/internationalise-the-fediverse/#what-about-homograph-attacks">What about homograph attacks?</a></h3>

<p>Well, what about them? ASCII has plenty of similar looking characters. I doubt most people would notice when a capital i is replaced by a lower L - and vice-versa. Similarly the kerning issue of an r and n looking like an m is well known. Are mixed language homographs more dangerous? I don't think so.</p>

<h3 id="what-if-people-make-names-that-cant-be-typed"><a href="https://shkspr.mobi/blog/2024/02/internationalise-the-fediverse/#what-if-people-make-names-that-cant-be-typed">What if people make names that can't be typed?</a></h3>

<p>Well, what if they do? Maybe not being found by people who can't type your language is a feature, not a bug.  But, anyway, clients can let users search for other people, or copy and paste their names.</p>

<h3 id="what-about-weird-zalgo-text"><a href="https://shkspr.mobi/blog/2024/02/internationalise-the-fediverse/#what-about-weird-zalgo-text">What about weird "Zalgo" text?</a></h3>

<p>It is up to a client to decide how they want to render text input. The "problems" of strange Unicode combinations are well known. This is not a hard computer-science problem.</p>

<h3 id="what-about-bi-directional-text"><a href="https://shkspr.mobi/blog/2024/02/internationalise-the-fediverse/#what-about-bi-directional-text">What about bi-directional text?</a></h3>

<p><a href="https://www.w3.org/TR/activitystreams-core/#h-biditext">The spec makes clear this is allowed</a>.</p>

<h3 id="do-people-even-want-a-username-in-their-own-script"><a href="https://shkspr.mobi/blog/2024/02/internationalise-the-fediverse/#do-people-even-want-a-username-in-their-own-script">Do people even want a username in their own script?</a></h3>

<p>I have no evidence for this. But I bet you'd get pretty frustrated if you had to switch keyboard just to type your own name, wouldn't you? In any case, why can't I have a username of <code>@😉</code></p>

<h2 id="whats-next"><a href="https://shkspr.mobi/blog/2024/02/internationalise-the-fediverse/#whats-next">What's Next?</a></h2>

<p>If you build ActivityPub software, give some thought to the billions of people who don't have names which easily fit into ASCII.</p>

<p>If your software can see <a href="https://i18n.viii.fi/.well-known/webfinger"><code>@你好@i18n.viii.fi</code></a> and its posts, please let me know.</p>
<img src="https://shkspr.mobi/blog/wp-content/themes/edent-wordpress-theme/info/okgo.php?ID=49643&HTTP_REFERER=RSS" alt="" width="1" height="1" loading="eager">]]></content:encoded>
					
					<wfw:commentRss>https://shkspr.mobi/blog/2024/02/internationalise-the-fediverse/feed/</wfw:commentRss>
			<slash:comments>36</slash:comments>
		
		
			</item>
		<item>
		<title><![CDATA[A (tiny, incomplete, single user, write-only) ActivityPub server in PHP]]></title>
		<link>https://shkspr.mobi/blog/2024/02/a-tiny-incomplete-single-user-write-only-activitypub-server-in-php/</link>
					<comments>https://shkspr.mobi/blog/2024/02/a-tiny-incomplete-single-user-write-only-activitypub-server-in-php/#comments</comments>
				<dc:creator><![CDATA[@edent]]></dc:creator>
		<pubDate>Sat, 03 Feb 2024 12:34:51 +0000</pubDate>
				<category><![CDATA[/etc/]]></category>
		<category><![CDATA[ActivityPub]]></category>
		<category><![CDATA[fediverse]]></category>
		<category><![CDATA[mastodon]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[Symfony]]></category>
		<guid isPermaLink="false">https://shkspr.mobi/blog/?p=49490</guid>

					<description><![CDATA[I&#039;ve written an ActivityPub server which only allows you to post messages to your followers.  That&#039;s all it does.  It won&#039;t record favourites or reposts. There&#039;s no support for following other accounts or receiving replies.  It cannot delete or update posts nor can it verify signatures. It doesn&#039;t have a database or any storage beyond flat files.  But it will happily send messages and allow…]]></description>
										<content:encoded><![CDATA[<p>I've written <a href="https://github.com/edent/location-activitypub-symfony/">an ActivityPub server which <em>only</em> allows you to post messages to your followers</a>.  That's all it does.  It won't record favourites or reposts. There's no support for following other accounts or receiving replies.  It cannot delete or update posts nor can it verify signatures. It doesn't have a database or any storage beyond flat files.</p>

<p>But it will happily send messages and allow itself to be followed.</p>

<p>This shows that it is <em>totally</em> possible to broadcast fully-featured ActivityPub messages to the Fediverse with minimal coding skills and modest resources.</p>

<h2 id="why"><a href="https://shkspr.mobi/blog/2024/02/a-tiny-incomplete-single-user-write-only-activitypub-server-in-php/#why">Why</a></h2>

<p>I wanted to create <a href="https://shkspr.mobi/blog/2024/01/rebuilding-foursquare-for-activitypub-using-openstreetmap/">a service a bit like FourSquare</a>.  For this, I needed an ActivityPub server which allows posting geotagged locations to the Fediverse.</p>

<p>I didn't want to install a fully-featured server with lots of complex parts. So I (foolishly) decided to write my own. I had a lot of trouble with HTTP Signatures.  Because they are cursed and I cannot read documentation. But mostly the cursed thing.</p>

<h2 id="how"><a href="https://shkspr.mobi/blog/2024/02/a-tiny-incomplete-single-user-write-only-activitypub-server-in-php/#how">How</a></h2>

<p>Creating a minimum viable Mastodon instance can be done with <a href="https://justingarrison.com/blog/2022-12-06-mastodon-files-instance/">half a dozen static files</a>. That gets you an account that people can see. They can't follow it or receive any posts though.</p>

<p>I wanted to use PHP to build an interactive server. PHP is supported everywhere and is simple to deploy.  Luckily, <a href="https://rknight.me/blog/building-an-activitypub-server/">Robb Knight has written an excellent tutorial</a>, so I ripped off his code and rewrote it for Symfony.</p>

<p>The structure is relatively straightforward.</p>

<ul>
<li><code>/.well-known/webfinger</code> is a static file which gives information about where to find details of the account.</li>
<li><code>/[username]</code> is a static file which has the user's metadata, public key, and links to avatar images.</li>
<li><code>/following</code> and <code>/followers</code> are also static files which say how many users are being followed / are following.</li>
<li><code>/posts/[GUID]</code> a directory with JSON files saved to disk - each ones contains the published ActivityPub note.</li>
<li><code>/photos/</code> is a directory with any uploaded media in it.</li>
<li><code>/outbox</code> is a list of all the posts which have been published.</li>
<li><code>/inbox</code> is an <em>external</em> API endpoint. An ActivityPub server sends it a follow request, the endpoint then POSTs a cryptographically signed Accept message to the follower's inbox. The follower's inbox address is saved to disk.</li>
<li><code>/logs</code> is a listing of all the messages received by the inbox.</li>
<li><code>/new</code> is a password protected page which lets you write a message. This is then sent to...</li>
<li><code>/send</code> is an <em>internal</em> API endpoint. It constructs an ActivityPub note, with attached location metadata, and POSTs it to each follower's inbox with a cryptographic signature.</li>
</ul>

<p>That's it.</p>

<p>The front-end grabs my phone's geolocation and shows the 25 nearest places within 100 metres. One click and the page posts to the <code>/send</code> endpoint which then publishes a message saying I'm checked in.  It is also possible to attach to the post a short message and a single photo with alt text.</p>

<p>There's no database. Posts are saved as JSON documents. Images are uploaded to a directory. It is single-user, so there is no account management.</p>

<h2 id="what-works"><a href="https://shkspr.mobi/blog/2024/02/a-tiny-incomplete-single-user-write-only-activitypub-server-in-php/#what-works">What Works</a></h2>

<ul>
<li style="list-style-type: '✅ ';">Users can find the account.</li>
<li style="list-style-type: '✅ ';">Users can follow the account and receive updates.</li>
<li style="list-style-type: '✅ ';">Posts contain geotag metadata.</li>
<li style="list-style-type: '✅ ';">Posts contain a description of the place.</li>
<li style="list-style-type: '✅ ';">Posts contain an OSM link to the place.</li>
<li style="list-style-type: '✅ ';">Posts contain a custom message.</li>
<li style="list-style-type: '✅ ';">Posts autolink #Hashtags (sort of).</li>
<li style="list-style-type: '✅ ';">Posts can have an image attached to them.</li>
<li style="list-style-type: '✅ ';">Messages to the inbox are recorded (but not yet integrated).</li>
</ul>

<h2 id="todo"><a href="https://shkspr.mobi/blog/2024/02/a-tiny-incomplete-single-user-write-only-activitypub-server-in-php/#todo">ToDo</a></h2>

<ul>
<li>My account only has a few dozen followers, some of whom share the same sever. Even with cURL multi handle, it takes time to post to several servers.</li>
<li>It posts plain text. It doesn't autolink websites</li>
<li>Hashtags are linked when viewed remotely, but they don't go anywhere locally.</li>
<li>There's no language selection - it is hard-coded to English.</li>
<li>The outbox isn't paginated.</li>
<li>The UI looks crap - but it is only me using it.</li>
<li>There's only a basic front-page showing a map of all my check-ins.</li>
<li>Replies are logged, but there's no easy way to see them.</li>
<li>Doesn't show any metadata about the place being checked-in to. It could use the item's website (if any) or hashtags for the type of amenity it is.</li>
<li>No way to handle being unfollowed.</li>
<li>No way to remove servers which have died.</li>
<li>Probably lots more.</li>
</ul>

<h2 id="other-resources"><a href="https://shkspr.mobi/blog/2024/02/a-tiny-incomplete-single-user-write-only-activitypub-server-in-php/#other-resources">Other Resources</a></h2>

<p>I found these resources helpful while creating this project:</p>

<ul>
<li><a href="https://tinysubversions.com/notes/activitypub-tool/">MVP ActivityPub in Python on Glitch</a></li>
<li><a href="https://seb.jambor.dev/posts/understanding-activitypub/">Understanding ActivityPub Part 1: Protocol Fundamentals</a></li>
<li><a href="https://flak.tedunangst.com/post/activity-notes">Activity Notes</a></li>
<li><a href="https://docs.gotosocial.org/en/latest/federation/">Federating with GoToSocial</a></li>
</ul>

<h2 id="whats-next"><a href="https://shkspr.mobi/blog/2024/02/a-tiny-incomplete-single-user-write-only-activitypub-server-in-php/#whats-next">What's Next?</a></h2>

<p>I've <a href="https://github.com/mastodon/mastodon/issues/29002">raised an issue on Mastodon</a> to see if they can support showing locations in posts. Hopefully, one day, they'll allow adding locations and then I can shut this down.</p>

<p>The code needs tidying up - it is very much a scratch-my-own-itch development. Probably riddled with bugs and security holes.</p>

<p>World domination?</p>

<h2 id="where"><a href="https://shkspr.mobi/blog/2024/02/a-tiny-incomplete-single-user-write-only-activitypub-server-in-php/#where">Where</a></h2>

<p>You can <a href="https://github.com/edent/location-activitypub-symfony/">laugh at my code on GitHub</a>.</p>

<p>You can <a href="https://location.edent.tel/">look at my check-ins on a map</a>.</p>

<p>You can follow my location on the Fediverse at <code>@edent_location@location.edent.tel</code></p>
<img src="https://shkspr.mobi/blog/wp-content/themes/edent-wordpress-theme/info/okgo.php?ID=49490&HTTP_REFERER=RSS" alt="" width="1" height="1" loading="eager">]]></content:encoded>
					
					<wfw:commentRss>https://shkspr.mobi/blog/2024/02/a-tiny-incomplete-single-user-write-only-activitypub-server-in-php/feed/</wfw:commentRss>
			<slash:comments>10</slash:comments>
		
		
			</item>
		<item>
		<title><![CDATA[Rebuilding FourSquare for ActivityPub using OpenStreetMap]]></title>
		<link>https://shkspr.mobi/blog/2024/01/rebuilding-foursquare-for-activitypub-using-openstreetmap/</link>
					<comments>https://shkspr.mobi/blog/2024/01/rebuilding-foursquare-for-activitypub-using-openstreetmap/#comments</comments>
				<dc:creator><![CDATA[@edent]]></dc:creator>
		<pubDate>Sat, 27 Jan 2024 12:34:55 +0000</pubDate>
				<category><![CDATA[/etc/]]></category>
		<category><![CDATA[ActivityPub]]></category>
		<category><![CDATA[fediverse]]></category>
		<category><![CDATA[FourSquare]]></category>
		<category><![CDATA[geolocation]]></category>
		<category><![CDATA[OpenStreetMap]]></category>
		<guid isPermaLink="false">https://shkspr.mobi/blog/?p=49432</guid>

					<description><![CDATA[I used to like the original FourSquare. The &#34;mayor&#34; stuff was a bit silly, and my friends never left that many reviews, but I loved being able to signal to my friends &#34;I am at this cool museum&#34; or &#34;We&#039;re at this pub if you want to meet&#34; or &#34;Spending the day at the park&#34;.  So, is there a way to recreate that early Web 2.0 experience with open data and ActivityPub? Let&#039;s find out!  This quest is…]]></description>
										<content:encoded><![CDATA[<p>I used to like the original FourSquare. The "mayor" stuff was a bit silly, and my friends never left that many reviews, but I loved being able to signal to my friends "I am at this cool museum" or "We're at this pub if you want to meet" or "Spending the day at the park".</p>

<p>So, is there a way to recreate that early Web 2.0 experience with open data and ActivityPub? Let's find out!</p>

<p>This quest is divided into two parts.</p>

<ol>
<li>Get nearby "Points of Interest" (POI) from OpenStreetMap.</li>
<li>Share a location on the Fediverse.</li>
</ol>

<h2 id="openstreetmap-api"><a href="https://shkspr.mobi/blog/2024/01/rebuilding-foursquare-for-activitypub-using-openstreetmap/#openstreetmap-api">OpenStreetMap API</a></h2>

<p>OpenStreetMap is the Wikipedia of maps. It is a freely available resource which anyone can edit (if they're skilled enough).</p>

<p>It also comes with a pretty decent API for querying things.  For example, <a href="https://overpass-turbo.eu/s/1GaE"><code>nw["amenity"]({{bbox}});</code> finds all "amenities" near a specific location</a>.</p>

<img src="https://shkspr.mobi/blog/wp-content/uploads/2024/01/amenities-fs8.png" alt="Map of a part of London. Some parts are highlighted." width="826" height="504" class="aligncenter size-full wp-image-49441">

<p>As you can see, it has highlighted <em>some</em> useful areas - a pharmacy and a pub. But it has <em>ignored</em> other useful locations - the train station and the park. It has also included some things that we may not want - bike parking and a taxi rank.</p>

<p>What API call is needed to get <em>useful</em> locations of of OverPass?</p>

<p>It's possible to specify the <em>type</em> of thing to find using <code>nw["amenity"="restaurant"];</code> - but adding every single type of thing would quickly end up with a very large query containing hundreds of types.</p>

<p>It is also possible to <em>exclude</em> specific types of places. This retrieves all amenities except for fast food joints:</p>

<pre><code class="language-_">nw["amenity"]({{bbox}});
-
nw["amenity"="fast_food"]({{bbox}});
</code></pre>

<p>Again, that would be complex.</p>

<p>Perhaps one solution is just to return <em>everything</em> and let the user decide if they want to check in to a telephone kiosk or a fire hydrant?  That's a bit user-hostile.</p>

<p>Instead, <a href="https://overpass-turbo.eu/s/1GaP">this query returns everything which has a name</a> <code>nw["name"]({{bbox}});</code></p>

<img src="https://shkspr.mobi/blog/wp-content/uploads/2024/01/names-fs8.png" alt="Map of London with several bits highlighted." width="826" height="504" class="aligncenter size-full wp-image-49442">

<p>That cuts out any unnamed things - like park benches and car-sharing spots. But it does add named roads and train lines.</p>

<p>It is possible to <a href="https://osm-queries.ldodds.com/tutorial/05-nodes-combined-filter.osm.html">use filters to exclude results from OverPass</a>. The best that I can come up with is: <a href="https://overpass-turbo.eu/s/1GaR"><code>nw["name"][!"highway"][!"railway"][!"waterway"][!"power"]({{bbox}});</code></a></p>

<p>That gets everything which has a name, but isn't a highway or railway or waterway or powerline. It isn't perfect - but it will do!</p>

<p>This is the query which will retrieve the 25 nearest things within 100 metres of a specific latitude and longitude. It includes the name and any other tags, the location, and the OSM ID.</p>

<p><a href="https://overpass-api.de/api/interpreter?data=[out:json];nw%5B%22name%22%5D%5B%21%22highway%22%5D%5B%21%22railway%22%5D%5B%21%22waterway%22%5D%5B%21%22power%22%5D(around:100,51.5202,-0.1040);out%20center%20qt%2025;"><code>overpass-api.de/api/interpreter?data=[out:json];nw["name"][!"highway"][!"railway"][!"waterway"][!"power"](around:100,51.5202,-0.1040);out center qt 25;</code></a></p>

<h2 id="activitypub"><a href="https://shkspr.mobi/blog/2024/01/rebuilding-foursquare-for-activitypub-using-openstreetmap/#activitypub">ActivityPub</a></h2>

<p>There's good news and bad news here. Firstly, ActivityStreams (which are subscribed to in ActivityPub) <a href="https://www.w3.org/TR/activitystreams-vocabulary/#places">supports the concept of "Place"</a> and <a href="https://www.w3.org/ns/activitystreams#location">"Location"</a>.</p>

<p>Once the user has a latitude and longitude, the can share it - along with a message, photo, or anything else.</p>

<p>Something like:</p>

<pre><code class="language-json">{
    "@context": "https://www.w3.org/ns/activitystreams",
    "type": "Note",
    "content": "Here in NYC! &lt;a href=\"https://www.openstreetmap.org/way/958999496\"&gt;John Lennon's Imagine Mosaic&lt;/a&gt;.",
    "attachment": [
        {
            "type": "Image",
            "mediaType": "image\/jpeg",
            "url": "https:\/\/fastly.4sqi.net\/img\/general\/590x786\/56367_9pxuZJD7d1hgPdaMFcFq1pipvTTMynBJsYcpHH-b8mU.jpg",
            "name": "A photo of a mosaic which says 'Imagine'."
        }
    ],
    "location": {
        "name": "John Lennon's Imagine",
        "type": "Place",
        "longitude": 40.77563,
        "latitude": -73.97474
    }
}
</code></pre>

<p>For example, here's <a href="https://pixelfed.social/p/dansup/75783646421848064?fs=1">a PixelFed post with an attached location</a> - and this is the <a href="https://pixelfed.social/p/dansup/75783646421848064.json">JSON representation</a>. That status can be reposted into other social networks.</p>

<p>It is worth noting that Mastodon doesn't (natively) support location - if you <a href="https://mastodon.social/@Edent/100581317169164202">view my repost of that PixelFed post</a> you'll see there's no location metadata attached. That's OK! It just means that the status needs to include human-readable data.</p>

<p>Similarly, Mastodon doesn't support the <a href="https://www.w3.org/TR/activitystreams-vocabulary/#dfn-arrive"><code>arrive</code></a> vocabulary. So this will be limited to a message with a location attached.</p>

<p><a href="https://benjojo.co.uk/u/benjojo/h/5j4yjq8JbrKY6Vp79K">Other ActivityPub services <em>do</em> support location</a>.</p>

<h2 id="putting-it-all-together"><a href="https://shkspr.mobi/blog/2024/01/rebuilding-foursquare-for-activitypub-using-openstreetmap/#putting-it-all-together">Putting it all together</a></h2>

<p>Well… that's a job for next week. Probably!</p>

<ul>
<li>Building a web site which gets the user's location is easy.</li>
<li>Getting the data from OverPass should be straightforward.</li>
<li>Creating an ActivityPub server which can post geotagged notes into the Fediverse might be a little beyond my skillset!  Some testing with <a href="https://tinysubversions.com/notes/activitypub-tool/">Darius Kazemi's AP Glitch</a> suggests this should work.</li>
</ul>

<p>If you'd like to help, please leave a comment.</p>
<img src="https://shkspr.mobi/blog/wp-content/themes/edent-wordpress-theme/info/okgo.php?ID=49432&HTTP_REFERER=RSS" alt="" width="1" height="1" loading="eager">]]></content:encoded>
					
					<wfw:commentRss>https://shkspr.mobi/blog/2024/01/rebuilding-foursquare-for-activitypub-using-openstreetmap/feed/</wfw:commentRss>
			<slash:comments>30</slash:comments>
		
		
			</item>
		<item>
		<title><![CDATA[An open(ish) redirect on Mastodon]]></title>
		<link>https://shkspr.mobi/blog/2023/10/an-openish-redirect-on-mastodon/</link>
					<comments>https://shkspr.mobi/blog/2023/10/an-openish-redirect-on-mastodon/#comments</comments>
				<dc:creator><![CDATA[@edent]]></dc:creator>
		<pubDate>Mon, 30 Oct 2023 12:34:51 +0000</pubDate>
				<category><![CDATA[/etc/]]></category>
		<category><![CDATA[ActivityPub]]></category>
		<category><![CDATA[CyberSecurity]]></category>
		<category><![CDATA[mastodon]]></category>
		<category><![CDATA[Responsible Disclosure]]></category>
		<category><![CDATA[security]]></category>
		<guid isPermaLink="false">https://shkspr.mobi/blog/?p=47287</guid>

					<description><![CDATA[I&#039;ve responsibly disclosed a small security issue with Mastodon (GHSA-8982-p7pm-7mqw). It allows a sufficiently determined attacker to use any Mastodon instance to redirect unwary users to a malicious site.  What do you think happens if you visit: https://mastodon.social/@PasswordReset/111285045683598517/admin?  If you aren&#039;t logged in to that instance, it will redirect you to a 3rd party site.…]]></description>
										<content:encoded><![CDATA[<p>I've responsibly disclosed a small security issue with Mastodon (<a href="https://github.com/mastodon/mastodon/security/advisories/GHSA-8982-p7pm-7mqw">GHSA-8982-p7pm-7mqw</a>). It allows a sufficiently determined attacker to use <em>any</em> Mastodon instance to redirect unwary users to a malicious site.</p>

<p>What do you think happens if you visit:
<a href="https://mastodon.social/@PasswordReset/111285045683598517/admin"></a><a href="https://mastodon.social/@PasswordReset/111285045683598517/admin">https://mastodon.social/@PasswordReset/111285045683598517/admin</a>?</p>

<p>If you aren't logged in to that instance, it will redirect you to a 3rd party site. Try opening it in a private browser window.</p>

<p>Here's another, less convincing, demo:</p>

<p><a href="https://mastodon.social/@mastodonopenredirect.wordpress.com@mastodonopenredirect.wordpress.com"></a><a href="https://mastodon.social/@mastodonopenredirect.wordpress.com@mastodonopenredirect.wordpress.com">https://mastodon.social/@mastodonopenredirect.wordpress.com@mastodonopenredirect.wordpress.com</a>
(You will need to not be logged in to Mastodon.Social for this to work.</p>

<p>It is possible to craft a URl which will redirect any visitor who isn't logged in. Attackers can use this as an open redirect for phishing, spam, and other attacks.</p>

<h2 id="remediation"><a href="https://shkspr.mobi/blog/2023/10/an-openish-redirect-on-mastodon/#remediation">Remediation</a></h2>

<p>This will likely be fixed by <a href="https://github.com/mastodon/mastodon/pull/26917">#26917</a>. But, in the meantime, administrators of Mastodon instances should be aware that their site could be used as an open redirect.</p>

<p>If you do spot any accounts which appear to be dodgy, admins can either block the account or the entire domain.</p>

<h2 id="background"><a href="https://shkspr.mobi/blog/2023/10/an-openish-redirect-on-mastodon/#background">Background</a></h2>

<p>Here's how it works - which involves some necessary background detail.</p>

<p>I am user <code>@edent</code> on Mastodon.social.  I can send you a URl of <a href="https://Mastodon.Social/@edent"></a><a href="https://Mastodon.Social/@edent">https://Mastodon.Social/@edent</a> and you will see my profile.  Nice!</p>

<p>But there are lots of Fediverse servers out there.  For example, I run a little bot called <code>@colours</code> on the BotsIn.Space instance.  Its URl is <a href="https://BotsIn.Space/@colours"></a><a href="https://BotsIn.Space/@colours">https://BotsIn.Space/@colours</a> - simple.</p>

<p>But what happens if I am viewing the Colours bot while on Mastodon.Social?</p>

<p>The interface shows <a href="https://Mastodon.Social/@colours@BotsIn.Space"></a><a href="https://Mastodon.Social/@colours@BotsIn.Space">https://Mastodon.Social/@colours@BotsIn.Space</a> - if you are logged in to Mastodon.Social, you will see the colours account, you can follow it, reply to it, and interact with it as though it were a user on your home instance.</p>

<p>But what if you're <em>not</em> logged in?</p>

<p>If you visit <a href="https://Mastodon.Social/@colours@BotsIn.Space"></a><a href="https://Mastodon.Social/@colours@BotsIn.Space">https://Mastodon.Social/@colours@BotsIn.Space</a> you will be <em>immediately</em> redirected to <a href="https://BotsIn.Space/@colours"></a><a href="https://BotsIn.Space/@colours">https://BotsIn.Space/@colours</a></p>

<p>In theory, this is a good thing! You get taken to their home server and you can see their latest updates etc.</p>

<p>Unfortunately, this can be abused.</p>

<p>Try and visit <a href="https://botsin.space/@blog@shkspr.mobi"></a><a href="https://botsin.space/@blog@shkspr.mobi">https://botsin.space/@blog@shkspr.mobi</a> - if you are not logged in to BotsIn.Space, you will be automatically redirected to my blog.</p>

<p>In addition, Mastodon <em>ignores</em> the <code>@username</code> when it sees a local status ID which references an external status. For example, both of these URls will go to the same place:</p>

<ul>
<li><a href="https://mastodon.social/@colours@botsin.space/111323978746693908"></a><a href="https://mastodon.social/@colours@botsin.space/111323978746693908">https://mastodon.social/@colours@botsin.space/111323978746693908</a></li>
<li><a href="https://mastodon.social/@RandomLettersAnd1234/111323978746693908"></a><a href="https://mastodon.social/@RandomLettersAnd1234/111323978746693908">https://mastodon.social/@RandomLettersAnd1234/111323978746693908</a></li>
</ul>

<h2 id="impact"><a href="https://shkspr.mobi/blog/2023/10/an-openish-redirect-on-mastodon/#impact">Impact</a></h2>

<p>A malicious user could do a few things.</p>

<p>The first is spam evasion. Email out a link to <code>mastodon.social/@user@buy_illegal_puppies.com</code> and it might skip spam filters, or confuse the user about the true destination.</p>

<p>The second is phishing. Is a user going to notice that they've been silently redirected to <code>nnast0d0n.social</code>? Stick up a convincing "Please log in again" page and you can steal their credentials.</p>

<h2 id="why-this-works"><a href="https://shkspr.mobi/blog/2023/10/an-openish-redirect-on-mastodon/#why-this-works">Why This Works</a></h2>

<p>ActivityPub uses the Well-Known / WebFinger specification.  Mastodon will use this to find data on anything which looks like a username.</p>

<p>For example, here's what my blog's account looks like in WebFinger:
<a href="https://shkspr.mobi/blog/.well-known/webfinger?resource=acct:blog@shkspr.mobi"></a><a href="https://shkspr.mobi/blog/.well-known/webfinger?resource=acct:blog@shkspr.mobi">https://shkspr.mobi/blog/.well-known/webfinger?resource=acct:blog@shkspr.mobi</a>:</p>

<pre><code class="language-json">{
  "subject": "acct:blog@shkspr.mobi",
  "aliases": [
    "https://shkspr.mobi/blog/@blog"
  ],
  "links": [
    {
      "rel": "self",
      "type": "application/activity+json",
      "href": "https://shkspr.mobi/blog/@blog"
    },
    {
      "rel": "http://webfinger.net/rel/profile-page",
      "type": "text/html",
      "href": "https://shkspr.mobi/blog/@blog"
    }
  ]
}
</code></pre>

<p>Mastodon will check that account exists, and then redirect a non-logged-in user to the "profile-page" of an account that it finds.</p>

<p>So a malicious user can create a WebFinger at <code>evil.com</code>, then send out links to <code>mastodon.example/@SexyFunTimes@evil.com</code>, and have users instantly redirected to their site.</p>

<p>Most ActivityPub instances won't do this unless they've <em>already</em> seen the user being referenced. This can be achieved by sending a private message to a user on that server which mentions the redirection account.</p>

<h2 id="remediation"><a href="https://shkspr.mobi/blog/2023/10/an-openish-redirect-on-mastodon/#remediation">Remediation</a></h2>

<p>Given that it is sensible to redirect users to an account's home instance, I think there's really only one way to solve this. An annoying interstitial.</p>

<blockquote><p>You are leaving XYZ.social. We do not control the page Illegal_Ivory_Smuggling.com. If you are sure you want to proceed, click here. Do not share your username and password with 3rd party sites etc etc etc.</p></blockquote>

<p>I reported this to Mastodon on 2023-09-20. Apparently a number of other people have also reported it. While they work on how to fix the problem, I thought it was sensible to let people know that this attack was possible.</p>

<h2 id="timeline"><a href="https://shkspr.mobi/blog/2023/10/an-openish-redirect-on-mastodon/#timeline">Timeline</a></h2>

<ul>
<li>2023-09-20 Disclosed on GitHub</li>
<li>2023-10-22 Added more details and sought agreement to publish</li>
<li>2023-10-29 Checked with various independent Mastodon server admins to see if they were aware of this behaviour - most were not</li>
<li>2023-10-30 Published</li>
</ul>
<img src="https://shkspr.mobi/blog/wp-content/themes/edent-wordpress-theme/info/okgo.php?ID=47287&HTTP_REFERER=RSS" alt="" width="1" height="1" loading="eager">]]></content:encoded>
					
					<wfw:commentRss>https://shkspr.mobi/blog/2023/10/an-openish-redirect-on-mastodon/feed/</wfw:commentRss>
			<slash:comments>1</slash:comments>
		
		
			</item>
		<item>
		<title><![CDATA[This blog is now on the Fediverse!]]></title>
		<link>https://shkspr.mobi/blog/2023/09/this-blog-is-now-on-the-fediverse/</link>
					<comments>https://shkspr.mobi/blog/2023/09/this-blog-is-now-on-the-fediverse/#comments</comments>
				<dc:creator><![CDATA[@edent]]></dc:creator>
		<pubDate>Sat, 16 Sep 2023 11:34:11 +0000</pubDate>
				<category><![CDATA[/etc/]]></category>
		<category><![CDATA[ActivityPub]]></category>
		<category><![CDATA[mastodon]]></category>
		<category><![CDATA[WordPress]]></category>
		<guid isPermaLink="false">https://shkspr.mobi/blog/?p=46869</guid>

					<description><![CDATA[You can now have this blog federated to your social media site by following  @blog@shkspr.mobi  If you&#039;re on Mastodon, it should look something like this:    You should be able to follow it on Lemmy, kBin, PixelFed, and some cool social network I&#039;ve never heard of.  How  This blog runs on WordPress. Thanks to the tireless work of Matthias Pfefferle, there&#039;s now an official WordPress ActivityPub…]]></description>
										<content:encoded><![CDATA[<p>You can now have this blog federated to your social media site by following 
<code>@blog@shkspr.mobi</code></p>

<p>If you're on Mastodon, it should look something like this:</p>

<img src="https://shkspr.mobi/blog/wp-content/uploads/2023/09/Blog-on-Mastodon-fs8.png" alt="My blog appearing as a user on Mastodon." width="725" height="788" class="aligncenter size-full wp-image-46945">

<p>You should be able to follow it on Lemmy, kBin, PixelFed, and some cool social network I've never heard of.</p>

<h2 id="how"><a href="https://shkspr.mobi/blog/2023/09/this-blog-is-now-on-the-fediverse/#how">How</a></h2>

<p>This blog runs on WordPress. Thanks to the tireless work of Matthias Pfefferle, there's now an <em>official</em> <a href="https://github.com/Automattic/wordpress-activitypub/">WordPress ActivityPub plugin</a>.</p>

<p>It's pretty easy to set up - just install and click on settings. But there are a few niggles you should know about if you run a blog in a subdirectory - for example, this site uses <code>/blog</code></p>

<p>First, you'll need to add the following to the <code>.htaccess</code> file in your website's root:</p>

<p><code>RedirectMatch "^\/\.well-known/(webfinger|nodeinfo|x-nodeinfo2)(.*)$" /blog/.well-known/$1$2</code></p>

<p>That means if someone visits <code>example.com/.well-known/webfinger</code> to find your ActivityPub account, they'll be automatically redirected to <code>example.com/blog/.well-known/webfinger</code></p>

<p>Secondly, you might need to change your blog's ActivityPub username.  For example, I log in to this blog using the username "Master_Control_Program" - but I don't want that displayed as the user. So I went to Settings → ActivityPub → Settings and unticked the "authors" box. I then gave my whole site the unsurprising name "blog":</p>

<img src="https://shkspr.mobi/blog/wp-content/uploads/2023/09/Enable-Blog-fs8.png" alt="Setting screen showing the blog being enabled." width="1000" height="423" class="aligncenter size-full wp-image-46946">

<p>If you <em>do</em> have multiple authors, each one of them can have their own unique Fediverse account.</p>

<h2 id="why"><a href="https://shkspr.mobi/blog/2023/09/this-blog-is-now-on-the-fediverse/#why">Why</a></h2>

<p>You can follow this blog using <a href="https://shkspr.mobi/blog/feed/">RSS</a> or <a href="https://shkspr.mobi/blog/feed/atom">Atom</a> - that means you need a feed reader configured to pull from my site every time you want to see if there's an update.</p>

<p>Or you can <a href="https://shkspr.mobi/blog/subscribe/">subscribe via email</a> - every time I publish a blog post it will appear in your inbox.</p>

<p>And, now, if you spend all day on social media you can get my blog's updates directly in your feed.</p>

<h2 id="fancy-features"><a href="https://shkspr.mobi/blog/2023/09/this-blog-is-now-on-the-fediverse/#fancy-features">Fancy features</a></h2>

<p>It is early days for the plugin, but there are a few nice features.</p>

<p>If you hit reply to a blog post in the Fediverse, it become a comment on my blog. This is similar to how <a href="https://brid.gy/">Brid.gy</a> syndicates comments.</p>

<p>You can see how many people followed you. And you can remove followers if you want to.</p>

<p>If you don't want to share the entire post, there are several settings which let you choose exactly what you <em>do</em> want shared.</p>

<p>Editing the WordPress post also send the edit out to the Fediverse.</p>

<p>The "joined" date is the date of your earliest blog post. See if you can find my oldest one!</p>

<h2 id="issues"><a href="https://shkspr.mobi/blog/2023/09/this-blog-is-now-on-the-fediverse/#issues">Issues</a></h2>

<p>Aside from a few glitches when setting up, there are a few points to be aware of.</p>

<p>There's no way to set a unique user avatar - it will go with whatever your blog is set to display.</p>

<p>It will only show blog posts from <em>after</em> you installed the plugin. So you can't scroll backwards into your archives.</p>

<p>Although you can see how many followers you have, I don't think there's a way to expose that to your users. And there's no simple way to say "Follow me at…"</p>

<p>As I mentioned, replying to a post converts that reply into a comment. But at the moment it doesn't support threaded comments. If I reply to a comment on the blog, it doesn't get sent back to the user as a reply on the Fediverse. Similarly, there's no way to track how many people repost or favourite your content.</p>

<p>ActivityPub doesn't support inline images. And some clients don't support formatting. So a federated blog post can look a bit weird.</p>

<p>If someone reads a blog post on the Fediverse, then they're not reading it on my website. I don't run any adverts - but I might miss out on people clicking around and reading other articles.</p>

<p>So I <em>think</em> I might only post an excerpt onto social media. I'm not sure yet. Thoughts?</p>

<h2 id="whats-next"><a href="https://shkspr.mobi/blog/2023/09/this-blog-is-now-on-the-fediverse/#whats-next">What's next?</a></h2>

<p>If you've seen this post Federated over ActivityPub - please reply! I'd love to know how far it has travelled.</p>
<img src="https://shkspr.mobi/blog/wp-content/themes/edent-wordpress-theme/info/okgo.php?ID=46869&HTTP_REFERER=RSS" alt="" width="1" height="1" loading="eager">]]></content:encoded>
					
					<wfw:commentRss>https://shkspr.mobi/blog/2023/09/this-blog-is-now-on-the-fediverse/feed/</wfw:commentRss>
			<slash:comments>6</slash:comments>
		
		
			</item>
	</channel>
</rss>
