I know #IndieAuth has this working for the #IndieWeb, but most API:s that Mastodon support are Mastodon specific not Fediverse generic (except for ActivityPub, WebFinger and a few others)
{
"type": "entry",
"author": {
"name": "@voxpelli",
"url": "https://mastodon.social/@voxpelli",
"photo": null
},
"url": "https://mastodon.social/@voxpelli/110651480421506687",
"content": {
"html": "<p><span class=\"h-card\"><a class=\"u-url\" href=\"https://indieweb.social/@whalecoiner\">@<span>whalecoiner</span></a></span> We need to free the <a href=\"https://mastodon.social/tags/Fediverse\">#<span>Fediverse</span></a> identities from the <a href=\"https://mastodon.social/tags/Mastodon\">#<span>Mastodon</span></a>, <a href=\"https://mastodon.social/tags/Lemmy\">#<span>Lemmy</span></a>, <a href=\"https://mastodon.social/tags/Pixelfed\">#<span>Pixelfed</span></a> etc so that I can have a single identity in use across multiple places</p><p>I know <a href=\"https://mastodon.social/tags/IndieAuth\">#<span>IndieAuth</span></a> has this working for the <a href=\"https://mastodon.social/tags/IndieWeb\">#<span>IndieWeb</span></a>, but most API:s that Mastodon support are Mastodon specific not Fediverse generic (except for ActivityPub, WebFinger and a few others)</p><p><a href=\"https://www.oauth.com/oauth2-servers/indieauth/\"><span>https://www.</span><span>oauth.com/oauth2-servers/indie</span><span>auth/</span></a></p>",
"text": "@whalecoiner We need to free the #Fediverse identities from the #Mastodon, #Lemmy, #Pixelfed etc so that I can have a single identity in use across multiple placesI know #IndieAuth has this working for the #IndieWeb, but most API:s that Mastodon support are Mastodon specific not Fediverse generic (except for ActivityPub, WebFinger and a few others)https://www.oauth.com/oauth2-servers/indieauth/"
},
"published": "2023-07-03T18:06:39+00:00",
"post-type": "note",
"_id": "38186556",
"_source": "7235",
"_is_read": false
}
{
"type": "entry",
"author": {
"name": "@ghordano",
"url": "https://mastodon.social/@ghordano",
"photo": null
},
"url": "https://mastodon.social/@ghordano/110650965452343339",
"content": {
"html": "<p>Giving the <a href=\"https://mastodon.social/tags/indieweb\">#<span>indieweb</span></a> another try. </p><p>First blog post with some links of things I've been reading, listening to, and watching this week:</p><p><a href=\"https://ghordano.com/weekly/2023-07-02/\"><span>https://</span><span>ghordano.com/weekly/2023-07-02</span><span>/</span></a></p><p><a href=\"https://mastodon.social/tags/RSS\">#<span>RSS</span></a> <a href=\"https://mastodon.social/tags/WebMention\">#<span>WebMention</span></a> <a href=\"https://mastodon.social/tags/Blog\">#<span>Blog</span></a></p>",
"text": "Giving the #indieweb another try. First blog post with some links of things I've been reading, listening to, and watching this week:https://ghordano.com/weekly/2023-07-02/#RSS #WebMention #Blog"
},
"published": "2023-07-03T15:55:41+00:00",
"post-type": "note",
"_id": "38185301",
"_source": "7235",
"_is_read": false
}
{
"type": "entry",
"author": {
"name": "@jake4480",
"url": "https://c.im/@jake4480",
"photo": null
},
"url": "https://c.im/@jake4480/110648996385215599",
"content": {
"html": "<p>Making the indie web more approachable (thanks to <span class=\"h-card\"><a class=\"u-url\" href=\"https://indieweb.social/@janboddez\">@<span>janboddez</span></a></span> for tipping me off to this good writeup): <a href=\"https://tracydurnell.com/2022/11/27/making-the-indieweb-more-approachable\"><span>https://</span><span>tracydurnell.com/2022/11/27/ma</span><span>king-the-indieweb-more-approachable</span></a></p><p><a href=\"https://c.im/tags/IndieWeb\">#<span>IndieWeb</span></a> <a href=\"https://c.im/tags/WebDev\">#<span>WebDev</span></a> <a href=\"https://c.im/tags/WebDesign\">#<span>WebDesign</span></a> <a href=\"https://c.im/tags/PersonalWebsites\">#<span>PersonalWebsites</span></a></p>",
"text": "Making the indie web more approachable (thanks to @janboddez for tipping me off to this good writeup): https://tracydurnell.com/2022/11/27/making-the-indieweb-more-approachable#IndieWeb #WebDev #WebDesign #PersonalWebsites"
},
"published": "2023-07-03T07:34:55+00:00",
"post-type": "note",
"_id": "38179226",
"_source": "7235",
"_is_read": false
}
As a writer, writing and publishing online using #Indieweb principles could save your life's work. And maybe even your career. This ish ow I'm #blogging differently and avoiding the perils of #enshitiffication.
{
"type": "entry",
"author": {
"name": "@liztai",
"url": "https://hachyderm.io/@liztai",
"photo": null
},
"url": "https://hachyderm.io/@liztai/110647245182175082",
"content": {
"html": "<p>As a writer, writing and publishing online using <a href=\"https://hachyderm.io/tags/Indieweb\">#<span>Indieweb</span></a> principles could save your life's work. And maybe even your career. This ish ow I'm <a href=\"https://hachyderm.io/tags/blogging\">#<span>blogging</span></a> differently and avoiding the perils of <a href=\"https://hachyderm.io/tags/enshitiffication\">#<span>enshitiffication</span></a>.</p><p><a href=\"https://hachyderm.io/tags/SocialMedia\">#<span>SocialMedia</span></a> <a href=\"https://hachyderm.io/tags/Writing\">#<span>Writing</span></a> <a href=\"https://hachyderm.io/tags/WritingCommunity\">#<span>WritingCommunity</span></a></p><p><a href=\"https://firediarist.wordpress.com/2023/07/03/how-i-am-blogging-the-indieweb-way/\"><span>https://</span><span>firediarist.wordpress.com/2023</span><span>/07/03/how-i-am-blogging-the-indieweb-way/</span></a></p>",
"text": "As a writer, writing and publishing online using #Indieweb principles could save your life's work. And maybe even your career. This ish ow I'm #blogging differently and avoiding the perils of #enshitiffication.#SocialMedia #Writing #WritingCommunityhttps://firediarist.wordpress.com/2023/07/03/how-i-am-blogging-the-indieweb-way/"
},
"published": "2023-07-03T00:09:34+00:00",
"post-type": "note",
"_id": "38176285",
"_source": "7235",
"_is_read": false
}
{
"type": "entry",
"author": {
"name": "@lark",
"url": "https://tech.lgbt/@lark",
"photo": null
},
"url": "https://tech.lgbt/@lark/110647116636187805",
"content": {
"html": "<p><a href=\"https://tech.lgbt/tags/Introduction\">#<span>Introduction</span></a></p><p>Hewwo frens! I'm Lark! I'm a smol queer kitty who makes computers go beep boop</p><p>I make software for fun. I maintain some Rust libraries and I run a queer history website.</p><p>I hate The Algorithm\u2122 and I love the indie web. I love blogging like it's 2006. I still use an RSS reader.</p><p>I'm very queer and I love being gay with my gay-ass friends. I love confusing cis people with my presentation. I love breaking relationship norms.</p><p>I'm also autistic and will happily listen to you infodump about your special interests.</p><p>See you around!</p><p><a href=\"https://tech.lgbt/tags/Software\">#<span>Software</span></a> <a href=\"https://tech.lgbt/tags/OpenSource\">#<span>OpenSource</span></a> <a href=\"https://tech.lgbt/tags/Rust\">#<span>Rust</span></a> <a href=\"https://tech.lgbt/tags/QueerHistory\">#<span>QueerHistory</span></a> <a href=\"https://tech.lgbt/tags/IndieWeb\">#<span>IndieWeb</span></a> <a href=\"https://tech.lgbt/tags/Blogging\">#<span>Blogging</span></a> <a href=\"https://tech.lgbt/tags/Queer\">#<span>Queer</span></a> <a href=\"https://tech.lgbt/tags/Trans\">#<span>Trans</span></a> <a href=\"https://tech.lgbt/tags/Nonbinary\">#<span>Nonbinary</span></a> <a href=\"https://tech.lgbt/tags/Polyamory\">#<span>Polyamory</span></a> <a href=\"https://tech.lgbt/tags/Autistic\">#<span>Autistic</span></a> <a href=\"https://tech.lgbt/tags/Disabled\">#<span>Disabled</span></a></p>",
"text": "#IntroductionHewwo frens! I'm Lark! I'm a smol queer kitty who makes computers go beep boopI make software for fun. I maintain some Rust libraries and I run a queer history website.I hate The Algorithm\u2122 and I love the indie web. I love blogging like it's 2006. I still use an RSS reader.I'm very queer and I love being gay with my gay-ass friends. I love confusing cis people with my presentation. I love breaking relationship norms.I'm also autistic and will happily listen to you infodump about your special interests.See you around!#Software #OpenSource #Rust #QueerHistory #IndieWeb #Blogging #Queer #Trans #Nonbinary #Polyamory #Autistic #Disabled"
},
"published": "2023-07-02T23:36:53+00:00",
"post-type": "note",
"_id": "38176082",
"_source": "7235",
"_is_read": false
}
This was supposed to post to my Microblog via OwnYourSwarm but I don’t know how to set up my theme etc. to make it look like a checkin and I’d appreciate any help #MicroBlog / #IndieWeb / #micropub geeks can offer.
(I fished for help with this about a month ago but there were no bites.)
{
"type": "entry",
"author": {
"name": "#indieweb",
"url": "https://mastodon.social/tags/indieweb",
"photo": null
},
"url": "https://blog.joeross.me/2023/07/02/this-was-supposed.html",
"content": {
"html": "<p><a href=\"https://blog.joeross.me/2023/07/02/starbucks-the-early.html\">This</a> was supposed to post to my Microblog via <a href=\"https://ownyourswarm.p3k.io/\">OwnYourSwarm</a> but I don\u2019t know how to set up my theme etc. to make it look like a checkin and I\u2019d appreciate any help #MicroBlog / #IndieWeb / #micropub geeks can offer.</p><br /><p>(I fished for help with this <a href=\"https://blog.joeross.me/2023/05/21/ive-been-playing.html\">about a month ago</a> but there were no bites.)</p>",
"text": "This was supposed to post to my Microblog via OwnYourSwarm but I don\u2019t know how to set up my theme etc. to make it look like a checkin and I\u2019d appreciate any help #MicroBlog / #IndieWeb / #micropub geeks can offer.\n(I fished for help with this about a month ago but there were no bites.)"
},
"published": "2023-07-02T11:48:05+00:00",
"post-type": "note",
"_id": "38169534",
"_source": "7235",
"_is_read": false
}
This was supposed to post to my Microblog via OwnYourSwarm but I don’t know how to set up my theme etc. to make it look like a checkin and I’d appreciate any help #MicroBlog / #IndieWeb / #micropub geeks can offer.
{
"type": "entry",
"author": {
"name": "@joeross",
"url": "https://mastodon.social/@joeross",
"photo": null
},
"url": "https://mastodon.social/@joeross/110644330134821433",
"content": {
"html": "<p>This was supposed to post to my Microblog via OwnYourSwarm but I don\u2019t know how to set up my theme etc. to make it look like a checkin and I\u2019d appreciate any help <a href=\"https://mastodon.social/tags/MicroBlog\">#<span>MicroBlog</span></a> / <a href=\"https://mastodon.social/tags/IndieWeb\">#<span>IndieWeb</span></a> / <a href=\"https://mastodon.social/tags/micropub\">#<span>micropub</span></a> geeks can offer.</p><p>(I fished for help with this about a month ago but there were no bites.) <a href=\"https://blog.joeross.me/2023/07/02/starbucks-the-early.html\"><span>https://</span><span>blog.joeross.me/2023/07/02/sta</span><span>rbucks-the-early.html</span></a></p>",
"text": "This was supposed to post to my Microblog via OwnYourSwarm but I don\u2019t know how to set up my theme etc. to make it look like a checkin and I\u2019d appreciate any help #MicroBlog / #IndieWeb / #micropub geeks can offer.(I fished for help with this about a month ago but there were no bites.) https://blog.joeross.me/2023/07/02/starbucks-the-early.html"
},
"published": "2023-07-02T11:48:14+00:00",
"post-type": "note",
"_id": "38169535",
"_source": "7235",
"_is_read": false
}
{
"type": "entry",
"author": {
"name": "#indieweb",
"url": "https://mastodon.social/tags/indieweb",
"photo": null
},
"url": "https://sironi.tk/objects/4337d9a3-fd64-4813-b62b-9d0f37f77e24",
"content": {
"html": "<p>@ebassi@mastodon.socia l</p><p>i\u2019ve got a single user instance on my crappy vdsl2 line.</p><p>Wordpress got the plugin and i like how GoToSocial sites look like</p><p>in the end is <a href=\"https://sironi.tk/tag/indieweb\">#indieweb</a> again</p><p>(ciao!)</p>",
"text": "@ebassi@mastodon.socia li\u2019ve got a single user instance on my crappy vdsl2 line.Wordpress got the plugin and i like how GoToSocial sites look likein the end is #indieweb again(ciao!)"
},
"published": "2023-07-02T06:52:25+00:00",
"post-type": "note",
"_id": "38167594",
"_source": "7235",
"_is_read": false
}
So #TwitterDown is trending on #Mastodon today. Here's another lesson why using platforms like #Twitter & #Substack as your content home is a bad idea. Publish your content the POSSE/PESOS way instead.
{
"type": "entry",
"author": {
"name": "@liztai",
"url": "https://hachyderm.io/@liztai",
"photo": null
},
"url": "https://hachyderm.io/@liztai/110642231942277490",
"content": {
"html": "<p>So <a href=\"https://hachyderm.io/tags/TwitterDown\">#<span>TwitterDown</span></a> is trending on <a href=\"https://hachyderm.io/tags/Mastodon\">#<span>Mastodon</span></a> today. Here's another lesson why using platforms like <a href=\"https://hachyderm.io/tags/Twitter\">#<span>Twitter</span></a> & <a href=\"https://hachyderm.io/tags/Substack\">#<span>Substack</span></a> as your content home is a bad idea. Publish your content the POSSE/PESOS way instead.</p><p><a href=\"https://hachyderm.io/tags/IndieWeb\">#<span>IndieWeb</span></a> <a href=\"https://hachyderm.io/tags/Blog\">#<span>Blog</span></a> <a href=\"https://hachyderm.io/tags/Writing\">#<span>Writing</span></a> </p><p><a href=\"https://firediarist.wordpress.com/2023/07/02/posse-and-pesos-better-ways-to-publish-content/\"><span>https://</span><span>firediarist.wordpress.com/2023</span><span>/07/02/posse-and-pesos-better-ways-to-publish-content/</span></a></p>",
"text": "So #TwitterDown is trending on #Mastodon today. Here's another lesson why using platforms like #Twitter & #Substack as your content home is a bad idea. Publish your content the POSSE/PESOS way instead.#IndieWeb #Blog #Writing https://firediarist.wordpress.com/2023/07/02/posse-and-pesos-better-ways-to-publish-content/"
},
"published": "2023-07-02T02:54:38+00:00",
"post-type": "note",
"_id": "38166268",
"_source": "7235",
"_is_read": false
}
Not sure I ever did an introduction, but figured I would because of the influx. I'm Jake, I've been here since November 2022, and I've been loving it here. Early web vibes!
I write a bunch of things including music, and probably have way too many other hobbies. I'm Gen X, beyond lefty progressive (see bio) and dig meeting new folks. I'll definitely (try to) say hi if you do!
{
"type": "entry",
"author": {
"name": "@jake4480",
"url": "https://c.im/@jake4480",
"photo": null
},
"url": "https://c.im/@jake4480/110642191368487274",
"content": {
"html": "<p>Not sure I ever did an introduction, but figured I would because of the influx. I'm Jake, I've been here since November 2022, and I've been loving it here. Early web vibes!</p><p>I write a bunch of things including music, and probably have way too many other hobbies. I'm Gen X, beyond lefty progressive (see bio) and dig meeting new folks. I'll definitely (try to) say hi if you do! </p><p>Salesforce/healthcare = dayjob. </p><p>I post mostly about <a href=\"https://c.im/tags/tech\">#<span>tech</span></a> <a href=\"https://c.im/tags/HTML\">#<span>HTML</span></a> <a href=\"https://c.im/tags/IndieWeb\">#<span>IndieWeb</span></a> <a href=\"https://c.im/tags/WebDev\">#<span>WebDev</span></a> <a href=\"https://c.im/tags/WebDesign\">#<span>WebDesign</span></a> <a href=\"https://c.im/tags/WordPress\">#<span>WordPress</span></a> <a href=\"https://c.im/tags/writing\">#<span>writing</span></a> <a href=\"https://c.im/tags/music\">#<span>music</span></a> <a href=\"https://c.im/tags/games\">#<span>games</span></a> <a href=\"https://c.im/tags/gaming\">#<span>gaming</span></a> <a href=\"https://c.im/tags/VideoGames\">#<span>VideoGames</span></a> <a href=\"https://c.im/tags/photography\">#<span>photography</span></a> <a href=\"https://c.im/tags/art\">#<span>art</span></a> <a href=\"https://c.im/tags/nature\">#<span>nature</span></a> <a href=\"https://c.im/tags/animals\">#<span>animals</span></a> <a href=\"https://c.im/tags/WeirdStuff\">#<span>WeirdStuff</span></a> etc. </p><p>Nice to meet ya!</p><p><a href=\"https://c.im/tags/introduction\">#<span>introduction</span></a> <a href=\"https://c.im/tags/introductions\">#<span>introductions</span></a> <a href=\"https://c.im/tags/GenX\">#<span>GenX</span></a></p>",
"text": "Not sure I ever did an introduction, but figured I would because of the influx. I'm Jake, I've been here since November 2022, and I've been loving it here. Early web vibes!I write a bunch of things including music, and probably have way too many other hobbies. I'm Gen X, beyond lefty progressive (see bio) and dig meeting new folks. I'll definitely (try to) say hi if you do! Salesforce/healthcare = dayjob. I post mostly about #tech #HTML #IndieWeb #WebDev #WebDesign #WordPress #writing #music #games #gaming #VideoGames #photography #art #nature #animals #WeirdStuff etc. Nice to meet ya!#introduction #introductions #GenX"
},
"published": "2023-07-02T02:44:19+00:00",
"post-type": "note",
"_id": "38166269",
"_source": "7235",
"_is_read": false
}
@PinoBatch@Rairii Unfamiliar with #SmallWeb, but fedi is federated.. we all join one of a smaller number of servers that talk to one another (like Mastodon). #Indieweb is, well, indie-- you have your site, I have mine, but we can talk to one another. The longer I hack, the more I prefer the latter.
{
"type": "entry",
"author": {
"name": "@sp1ff",
"url": "https://indieweb.social/@sp1ff",
"photo": null
},
"url": "https://indieweb.social/@sp1ff/110641963625704541",
"content": {
"html": "<p><span class=\"h-card\"><a class=\"u-url\" href=\"https://peoplemaking.games/@PinoBatch\">@<span>PinoBatch</span></a></span> <span class=\"h-card\"><a class=\"u-url\" href=\"https://haqueers.com/@Rairii\">@<span>Rairii</span></a></span> Unfamiliar with <a href=\"https://indieweb.social/tags/SmallWeb\">#<span>SmallWeb</span></a>, but fedi is federated.. we all join one of a smaller number of servers that talk to one another (like Mastodon). <a href=\"https://indieweb.social/tags/Indieweb\">#<span>Indieweb</span></a> is, well, indie-- you have your site, I have mine, but we can talk to one another. The longer I hack, the more I prefer the latter.</p>",
"text": "@PinoBatch @Rairii Unfamiliar with #SmallWeb, but fedi is federated.. we all join one of a smaller number of servers that talk to one another (like Mastodon). #Indieweb is, well, indie-- you have your site, I have mine, but we can talk to one another. The longer I hack, the more I prefer the latter."
},
"published": "2023-07-02T01:46:24+00:00",
"post-type": "note",
"_id": "38165957",
"_source": "7235",
"_is_read": false
}
@Rairii I'm not sure how "the social web" distinguishes fedi from #IndieWeb or Aral Balkan's #SmallWeb, which are more based on each user running their own website on their own domain.
{
"type": "entry",
"author": {
"name": "@PinoBatch",
"url": "https://peoplemaking.games/@PinoBatch",
"photo": null
},
"url": "https://peoplemaking.games/@PinoBatch/110641909075143295",
"content": {
"html": "<p><span class=\"h-card\"><a class=\"u-url\" href=\"https://haqueers.com/@Rairii\">@<span>Rairii</span></a></span> I'm not sure how \"the social web\" distinguishes fedi from <a href=\"https://peoplemaking.games/tags/IndieWeb\">#<span>IndieWeb</span></a> or Aral Balkan's <a href=\"https://peoplemaking.games/tags/SmallWeb\">#<span>SmallWeb</span></a>, which are more based on each user running their own website on their own domain.</p>",
"text": "@Rairii I'm not sure how \"the social web\" distinguishes fedi from #IndieWeb or Aral Balkan's #SmallWeb, which are more based on each user running their own website on their own domain."
},
"published": "2023-07-02T01:32:32+00:00",
"post-type": "note",
"_id": "38165958",
"_source": "7235",
"_is_read": false
}
Blogged: Why organisations should have an indieweb publication strategy (or: why ITFC should have an RSS feed) ✍️ The social media behemoths are dying, so you need a plan B for making sure you can communicate with the outside world. And that’s having an RSS feed and POSSE-ing.
{
"type": "entry",
"author": {
"name": "@leonp",
"url": "https://fosstodon.org/@leonp",
"photo": null
},
"url": "https://fosstodon.org/@leonp/110640775564409812",
"content": {
"html": "<p>Blogged: Why organisations should have an indieweb publication strategy (or: why ITFC should have an RSS feed) \u270d\ufe0f The social media behemoths are dying, so you need a plan B for making sure you can communicate with the outside world. And that\u2019s having an RSS feed and POSSE-ing.<br /><br /> \ud83c\udff7 <a href=\"https://fosstodon.org/tags/ITFC\">#<span>ITFC</span></a> <a href=\"https://fosstodon.org/tags/IndieWeb\">#<span>IndieWeb</span></a> <a href=\"https://fosstodon.org/tags/POSSE\">#<span>POSSE</span></a> <a href=\"https://fosstodon.org/tags/RSS\">#<span>RSS</span></a><br /><a href=\"https://www.thisdaysportion.com/posts/itfc-indieweb/\"><span>https://www.</span><span>thisdaysportion.com/posts/itfc</span><span>-indieweb/</span></a></p>",
"text": "Blogged: Why organisations should have an indieweb publication strategy (or: why ITFC should have an RSS feed) \u270d\ufe0f The social media behemoths are dying, so you need a plan B for making sure you can communicate with the outside world. And that\u2019s having an RSS feed and POSSE-ing.\n\n \ud83c\udff7 #ITFC #IndieWeb #POSSE #RSS\nhttps://www.thisdaysportion.com/posts/itfc-indieweb/"
},
"published": "2023-07-01T20:44:16+00:00",
"post-type": "note",
"_id": "38163731",
"_source": "7235",
"_is_read": false
}
{
"type": "entry",
"published": "2023-07-01T13:32:30-0400",
"url": "https://martymcgui.re/2023/07/01/this-week-in-the-indieweb-audio-edition--june-24th---30th-2023/",
"category": [
"podcast",
"IndieWeb",
"this-week-indieweb-podcast"
],
"audio": [
"https://media.martymcgui.re/08/4e/45/a8/97e513d96ca8188452a7e889c576133606ea8ecbbf593ca02560cd43.mp3"
],
"name": "This Week in the IndieWeb Audio Edition \u2022 June 24th - 30th, 2023",
"content": {
"text": "Show/Hide Transcript\n \n Community gardening for pop-ups and Pythons. It\u2019s the audio edition for This Week in the IndieWeb for June 24th - 30th, 2023.\nYou can find all of my audio editions and subscribe with your favorite podcast app here: martymcgui.re/podcasts/indieweb/.\nMusic from Aaron Parecki\u2019s 100DaysOfMusic project: Day 85 - Suit, Day 48 - Glitch, Day 49 - Floating, Day 9, and Day 11\nThanks to everyone in the IndieWeb chat for their feedback and suggestions. Please drop me a note if there are any changes you\u2019d like to see for this audio edition!",
"html": "Show/Hide Transcript\n \n <p>Community gardening for pop-ups and Pythons. It\u2019s the audio edition for <a href=\"https://indieweb.org/this-week/2023-06-30.html\">This Week in the IndieWeb for June 24th - 30th, 2023</a>.</p>\n<p>You can find all of my audio editions and subscribe with your favorite podcast app here: <a href=\"https://martymcgui.re/podcasts/indieweb/\">martymcgui.re/podcasts/indieweb/</a>.</p>\n<p>Music from <a href=\"https://aaronparecki.com/\">Aaron Parecki</a>\u2019s <a href=\"https://100.aaronparecki.com/\">100DaysOfMusic project</a>: <a href=\"https://aaronparecki.com/2017/03/15/14/day85\">Day 85 - Suit</a>, <a href=\"https://aaronparecki.com/2017/02/06/7/day48\">Day 48 - Glitch</a>, <a href=\"https://aaronparecki.com/2017/02/07/4/day49\">Day 49 - Floating</a>, <a href=\"https://aaronparecki.com/2016/12/29/21/day-9\">Day 9</a>, and <a href=\"https://aaronparecki.com/2016/12/31/15/\">Day 11</a></p>\n<p>Thanks to everyone in the <a href=\"https://chat.indieweb.org/\">IndieWeb chat</a> for their feedback and suggestions. Please drop me a note if there are any changes you\u2019d like to see for this audio edition!</p>"
},
"author": {
"type": "card",
"name": "Marty McGuire",
"url": "https://martymcgui.re/",
"photo": "https://martymcgui.re/images/logo.jpg"
},
"post-type": "audio",
"_id": "38162214",
"_source": "175",
"_is_read": false
}
{
"type": "entry",
"author": {
"name": "#indieweb",
"url": "https://indieweb.social/tags/indieweb",
"photo": null
},
"url": "https://martymcgui.re/2023/07/01/133406/",
"content": {
"html": "<p>Community gardening for pop-ups and Pythons. It\u2019s your < 10min update on the #IndieWeb community!</p><br /><p>This Week in the IndieWeb audio edition for June 24th - 30th, 2023.<br /><a href=\"https://martymcgui.re/2023/07/01/this-week-in-the-indieweb-audio-edition--june-24th---30th-2023/\">https://martymcgui.re/2023/07/01/this-week-in-the-indieweb-audio-edition--june-24th---30th-2023/</a></p>",
"text": "Community gardening for pop-ups and Pythons. It\u2019s your < 10min update on the #IndieWeb community!\nThis Week in the IndieWeb audio edition for June 24th - 30th, 2023.\nhttps://martymcgui.re/2023/07/01/this-week-in-the-indieweb-audio-edition--june-24th---30th-2023/"
},
"published": "2023-07-01T17:34:06+00:00",
"post-type": "note",
"_id": "38161663",
"_source": "7235",
"_is_read": false
}
Here's a short Rust program using the microformats crate that checks the presence of a webmention on a certain page, properly resolving all URLs and even scanning HTML content in entry["properties"]["content"].
use std::cell::{RefCell, Ref};
use std::rc::Rc;
use clap::Parser;
use microformats::types::PropertyValue;
use microformats::html5ever;
use microformats::html5ever::tendril::TendrilSink;
#[derive(thiserror::Error, Debug)]
enum Error {
#[error("http request error: {0}")]
Http(#[from] reqwest::Error),
#[error("microformats error: {0}")]
Microformats(#[from] microformats::Error),
#[error("json error: {0}")]
Json(#[from] serde_json::Error),
#[error("url parse error: {0}")]
UrlParse(#[from] url::ParseError),
}
#[derive(Debug)]
enum MentionType {
Reply,
Like,
Repost,
Bookmark,
Mention
}
fn check_mention(document: impl AsRef<str>, base_url: &url::Url, link: &url::Url) -> Result<Option<MentionType>, Error> {
// First, check the document for MF2 markup
let document = microformats::from_html(document.as_ref(), base_url.clone())?;
// Get an iterator of all items
let items_iter = document.items.iter()
.map(AsRef::as_ref)
.map(RefCell::borrow);
for item in items_iter {
let props = item.properties.borrow();
for (prop, interaction_type) in [
("in-reply-to", MentionType::Reply), ("like-of", MentionType::Like),
("bookmark-of", MentionType::Bookmark), ("repost-of", MentionType::Repost)
] {
if let Some(propvals) = props.get(prop) {
for val in propvals {
if let PropertyValue::Url(url) = val {
if url == link {
return Ok(Some(interaction_type))
}
}
}
}
}
// Process `content`
if let Some(PropertyValue::Fragment(content)) = props.get("content")
.map(Vec::as_slice)
.unwrap_or_default()
.first()
{
let root = html5ever::parse_document(html5ever::rcdom::RcDom::default(), Default::default())
.from_utf8()
.one(content.html.to_owned().as_bytes())
.document;
// This is a trick to unwrap recursion into a loop
//
// A list of unprocessed node is made. Then, in each
// iteration, the list is "taken" and replaced with an
// empty list, which is populated with nodes for the next
// iteration of the loop.
//
// Empty list means all nodes were processed.
let mut unprocessed_nodes: Vec<Rc<html5ever::rcdom::Node>> = root.children.borrow().iter().cloned().collect();
while unprocessed_nodes.len() > 0 {
// "Take" the list out of its memory slot, replace it with an empty list
let nodes = std::mem::take(&mut unprocessed_nodes);
for node in nodes.into_iter() {
// Add children nodes to the list for the next iteration
unprocessed_nodes.extend(node.children.borrow().iter().cloned());
if let html5ever::rcdom::NodeData::Element { ref name, ref attrs, .. } = node.data {
// If it's not `<a>`, skip it
if name.local != *"a" { continue; }
for attr in attrs.borrow().iter() {
// if it's not `<a href="...">`, skip it
if attr.name.local != *"href" { continue; }
// Be forgiving in parsing URLs, and resolve them against the base URL
if let Ok(url) = base_url.join(attr.value.as_ref()) {
if &url == link {
return Ok(Some(MentionType::Mention));
}
}
}
}
}
}
}
}
Ok(None)
}
#[derive(Parser, Debug)]
#[clap(
name = "kittybox-check-webmention",
author = "Vika <vika@fireburn.ru>",
version = env!("CARGO_PKG_VERSION"),
about = "Verify an incoming webmention"
)]
struct Args {
#[clap(value_parser)]
url: url::Url,
#[clap(value_parser)]
link: url::Url
}
#[tokio::main]
async fn main() -> Result<(), self::Error> {
let args = Args::parse();
let http: reqwest::Client = {
#[allow(unused_mut)]
let mut builder = reqwest::Client::builder()
.user_agent(concat!(
env!("CARGO_PKG_NAME"), "/", env!("CARGO_PKG_VERSION")
));
builder.build().unwrap()
};
let response = http.get(args.url.clone()).send().await?;
let text = response.text().await?;
if let Some(mention_type) = check_mention(text, &args.url, &args.link)? {
println!("{:?}", mention_type);
Ok(())
} else {
std::process::exit(1)
}
}
{
"type": "entry",
"published": "2023-07-01T18:46:11.162062149+03:00",
"url": "https://fireburn.ru/posts/rust-check-webmention",
"category": [
"Kittybox",
"Rust",
"microformats2",
"IndieWeb"
],
"content": {
"text": "Here's a short Rust program using the microformats crate that checks the presence of a webmention on a certain page, properly resolving all URLs and even scanning HTML content in entry[\"properties\"][\"content\"].\nuse std::cell::{RefCell, Ref};\nuse std::rc::Rc;\n\nuse clap::Parser;\nuse microformats::types::PropertyValue;\nuse microformats::html5ever;\nuse microformats::html5ever::tendril::TendrilSink;\n\n#[derive(thiserror::Error, Debug)]\nenum Error {\n #[error(\"http request error: {0}\")]\n Http(#[from] reqwest::Error),\n #[error(\"microformats error: {0}\")]\n Microformats(#[from] microformats::Error),\n #[error(\"json error: {0}\")]\n Json(#[from] serde_json::Error),\n #[error(\"url parse error: {0}\")]\n UrlParse(#[from] url::ParseError),\n}\n\n#[derive(Debug)]\nenum MentionType {\n Reply,\n Like,\n Repost,\n Bookmark,\n Mention\n}\n\nfn check_mention(document: impl AsRef<str>, base_url: &url::Url, link: &url::Url) -> Result<Option<MentionType>, Error> {\n // First, check the document for MF2 markup\n let document = microformats::from_html(document.as_ref(), base_url.clone())?;\n\n // Get an iterator of all items\n let items_iter = document.items.iter()\n .map(AsRef::as_ref)\n .map(RefCell::borrow);\n\n for item in items_iter {\n let props = item.properties.borrow();\n for (prop, interaction_type) in [\n (\"in-reply-to\", MentionType::Reply), (\"like-of\", MentionType::Like),\n (\"bookmark-of\", MentionType::Bookmark), (\"repost-of\", MentionType::Repost)\n ] {\n if let Some(propvals) = props.get(prop) {\n for val in propvals {\n if let PropertyValue::Url(url) = val {\n if url == link {\n return Ok(Some(interaction_type))\n }\n }\n }\n }\n }\n // Process `content`\n if let Some(PropertyValue::Fragment(content)) = props.get(\"content\")\n .map(Vec::as_slice)\n .unwrap_or_default()\n .first()\n {\n let root = html5ever::parse_document(html5ever::rcdom::RcDom::default(), Default::default())\n .from_utf8()\n .one(content.html.to_owned().as_bytes())\n .document;\n\n // This is a trick to unwrap recursion into a loop\n //\n // A list of unprocessed node is made. Then, in each\n // iteration, the list is \"taken\" and replaced with an\n // empty list, which is populated with nodes for the next\n // iteration of the loop.\n //\n // Empty list means all nodes were processed.\n let mut unprocessed_nodes: Vec<Rc<html5ever::rcdom::Node>> = root.children.borrow().iter().cloned().collect();\n while unprocessed_nodes.len() > 0 {\n // \"Take\" the list out of its memory slot, replace it with an empty list\n let nodes = std::mem::take(&mut unprocessed_nodes);\n for node in nodes.into_iter() {\n // Add children nodes to the list for the next iteration\n unprocessed_nodes.extend(node.children.borrow().iter().cloned());\n\n if let html5ever::rcdom::NodeData::Element { ref name, ref attrs, .. } = node.data {\n // If it's not `<a>`, skip it\n if name.local != *\"a\" { continue; }\n for attr in attrs.borrow().iter() {\n // if it's not `<a href=\"...\">`, skip it \n if attr.name.local != *\"href\" { continue; }\n // Be forgiving in parsing URLs, and resolve them against the base URL\n if let Ok(url) = base_url.join(attr.value.as_ref()) {\n if &url == link {\n return Ok(Some(MentionType::Mention));\n }\n }\n }\n }\n }\n }\n \n }\n }\n\n Ok(None)\n}\n\n#[derive(Parser, Debug)]\n#[clap(\n name = \"kittybox-check-webmention\",\n author = \"Vika <vika@fireburn.ru>\",\n version = env!(\"CARGO_PKG_VERSION\"),\n about = \"Verify an incoming webmention\"\n)]\nstruct Args {\n #[clap(value_parser)]\n url: url::Url,\n #[clap(value_parser)]\n link: url::Url\n}\n\n#[tokio::main]\nasync fn main() -> Result<(), self::Error> {\n let args = Args::parse();\n \n let http: reqwest::Client = {\n #[allow(unused_mut)]\n let mut builder = reqwest::Client::builder()\n .user_agent(concat!(\n env!(\"CARGO_PKG_NAME\"), \"/\", env!(\"CARGO_PKG_VERSION\")\n ));\n\n builder.build().unwrap()\n };\n\n let response = http.get(args.url.clone()).send().await?;\n let text = response.text().await?;\n \n if let Some(mention_type) = check_mention(text, &args.url, &args.link)? {\n println!(\"{:?}\", mention_type);\n\n Ok(())\n } else {\n std::process::exit(1)\n }\n}",
"html": "<p>Here's a short Rust program using the <code>microformats</code> crate that checks the presence of a webmention on a certain page, properly resolving all URLs and even scanning HTML content in <code>entry[\"properties\"][\"content\"]</code>.</p>\n<pre><code>use std::cell::{RefCell, Ref};\nuse std::rc::Rc;\n\nuse clap::Parser;\nuse microformats::types::PropertyValue;\nuse microformats::html5ever;\nuse microformats::html5ever::tendril::TendrilSink;\n\n#[derive(thiserror::Error, Debug)]\nenum Error {\n #[error(\"http request error: {0}\")]\n Http(#[from] reqwest::Error),\n #[error(\"microformats error: {0}\")]\n Microformats(#[from] microformats::Error),\n #[error(\"json error: {0}\")]\n Json(#[from] serde_json::Error),\n #[error(\"url parse error: {0}\")]\n UrlParse(#[from] url::ParseError),\n}\n\n#[derive(Debug)]\nenum MentionType {\n Reply,\n Like,\n Repost,\n Bookmark,\n Mention\n}\n\nfn check_mention(document: impl AsRef<str>, base_url: &url::Url, link: &url::Url) -> Result<Option<MentionType>, Error> {\n // First, check the document for MF2 markup\n let document = microformats::from_html(document.as_ref(), base_url.clone())?;\n\n // Get an iterator of all items\n let items_iter = document.items.iter()\n .map(AsRef::as_ref)\n .map(RefCell::borrow);\n\n for item in items_iter {\n let props = item.properties.borrow();\n for (prop, interaction_type) in [\n (\"in-reply-to\", MentionType::Reply), (\"like-of\", MentionType::Like),\n (\"bookmark-of\", MentionType::Bookmark), (\"repost-of\", MentionType::Repost)\n ] {\n if let Some(propvals) = props.get(prop) {\n for val in propvals {\n if let PropertyValue::Url(url) = val {\n if url == link {\n return Ok(Some(interaction_type))\n }\n }\n }\n }\n }\n // Process `content`\n if let Some(PropertyValue::Fragment(content)) = props.get(\"content\")\n .map(Vec::as_slice)\n .unwrap_or_default()\n .first()\n {\n let root = html5ever::parse_document(html5ever::rcdom::RcDom::default(), Default::default())\n .from_utf8()\n .one(content.html.to_owned().as_bytes())\n .document;\n\n // This is a trick to unwrap recursion into a loop\n //\n // A list of unprocessed node is made. Then, in each\n // iteration, the list is \"taken\" and replaced with an\n // empty list, which is populated with nodes for the next\n // iteration of the loop.\n //\n // Empty list means all nodes were processed.\n let mut unprocessed_nodes: Vec<Rc<html5ever::rcdom::Node>> = root.children.borrow().iter().cloned().collect();\n while unprocessed_nodes.len() > 0 {\n // \"Take\" the list out of its memory slot, replace it with an empty list\n let nodes = std::mem::take(&mut unprocessed_nodes);\n for node in nodes.into_iter() {\n // Add children nodes to the list for the next iteration\n unprocessed_nodes.extend(node.children.borrow().iter().cloned());\n\n if let html5ever::rcdom::NodeData::Element { ref name, ref attrs, .. } = node.data {\n // If it's not `<a>`, skip it\n if name.local != *\"a\" { continue; }\n for attr in attrs.borrow().iter() {\n // if it's not `<a href=\"...\">`, skip it \n if attr.name.local != *\"href\" { continue; }\n // Be forgiving in parsing URLs, and resolve them against the base URL\n if let Ok(url) = base_url.join(attr.value.as_ref()) {\n if &url == link {\n return Ok(Some(MentionType::Mention));\n }\n }\n }\n }\n }\n }\n \n }\n }\n\n Ok(None)\n}\n\n#[derive(Parser, Debug)]\n#[clap(\n name = \"kittybox-check-webmention\",\n author = \"Vika <vika@fireburn.ru>\",\n version = env!(\"CARGO_PKG_VERSION\"),\n about = \"Verify an incoming webmention\"\n)]\nstruct Args {\n #[clap(value_parser)]\n url: url::Url,\n #[clap(value_parser)]\n link: url::Url\n}\n\n#[tokio::main]\nasync fn main() -> Result<(), self::Error> {\n let args = Args::parse();\n \n let http: reqwest::Client = {\n #[allow(unused_mut)]\n let mut builder = reqwest::Client::builder()\n .user_agent(concat!(\n env!(\"CARGO_PKG_NAME\"), \"/\", env!(\"CARGO_PKG_VERSION\")\n ));\n\n builder.build().unwrap()\n };\n\n let response = http.get(args.url.clone()).send().await?;\n let text = response.text().await?;\n \n if let Some(mention_type) = check_mention(text, &args.url, &args.link)? {\n println!(\"{:?}\", mention_type);\n\n Ok(())\n } else {\n std::process::exit(1)\n }\n}\n</code></pre>"
},
"author": {
"type": "card",
"name": "Vika",
"url": "https://fireburn.ru/",
"photo": "https://fireburn.ru/.kittybox/media/uploads/f1/5a/fb/9b/081efafb97b4ad59f5025cf2fd0678b8f3e20e4c292489107d52be09"
},
"post-type": "note",
"_id": "38161429",
"_source": "1371",
"_is_read": false
}
{
"type": "entry",
"author": {
"name": "@gilmae",
"url": "https://aus.social/@gilmae",
"photo": null
},
"url": "https://aus.social/@gilmae/110637980449939540",
"content": {
"html": "<p>This seems extremely cool. I am 100% here for nntp in all its glory and warts.</p><p><a href=\"https://dialup.cafe/@vga256/110637361651638656\"><span>https://</span><span>dialup.cafe/@vga256/1106373616</span><span>51638656</span></a> <a href=\"https://aus.social/tags/Indieweb\">#<span>Indieweb</span></a> <a href=\"https://aus.social/tags/retro\">#<span>retro</span></a> <a href=\"https://aus.social/tags/technology\">#<span>technology</span></a></p>",
"text": "This seems extremely cool. I am 100% here for nntp in all its glory and warts.https://dialup.cafe/@vga256/110637361651638656 #Indieweb #retro #technology"
},
"published": "2023-07-01T08:53:25+00:00",
"post-type": "note",
"_id": "38156183",
"_source": "7235",
"_is_read": false
}