Wow another donation to @3xR_team for the #NAFO Hanukkah auction.
Huge h/t to @alchi93 for running the show
Thanks for your donation, and Happy Hanukkah! @Lacu_aura your forging lives on
{
"type": "entry",
"published": "2022-12-24T17:59:58+00:00",
"url": "https://twitter.com/jgmac1106/status/1606711292676509696",
"quotation-of": "https://twitter.com/alchi93/status/1606680234526662656",
"content": {
"text": "Wow another donation to @3xR_team for the #NAFO Hanukkah auction.\n\nHuge h/t to @alchi93 for running the show",
"html": "Wow another donation to <a href=\"https://twitter.com/3xR_team\">@3xR_team</a> for the <a href=\"https://twitter.com/search?q=%23NAFO\">#NAFO</a> Hanukkah auction.\n\nHuge h/t to <a href=\"https://twitter.com/alchi93\">@alchi93</a> for running the show"
},
"author": {
"type": "card",
"name": "jgregorymcverry.com",
"url": "https://twitter.com/jgmac1106",
"photo": "https://pbs.twimg.com/profile_images/1586874242913734658/3GMcjnTC.jpg"
},
"post-type": "note",
"refs": {
"https://twitter.com/alchi93/status/1606680234526662656": {
"type": "entry",
"published": "2022-12-24T15:56:33+00:00",
"url": "https://twitter.com/alchi93/status/1606680234526662656",
"photo": [
"https://pbs.twimg.com/media/FkwTIRIXgAADtbu.jpg"
],
"in-reply-to": [
"https://twitter.com/czarinaflo/status/1606670399840092160"
],
"content": {
"text": "Thanks for your donation, and Happy Hanukkah! @Lacu_aura your forging lives on",
"html": "Thanks for your donation, and Happy Hanukkah! <a href=\"https://twitter.com/Lacu_aura\">@Lacu_aura</a> your forging lives on\n<a class=\"u-mention\" href=\"https://twitter.com/3xR_team\"></a>\n<a class=\"u-mention\" href=\"https://twitter.com/czarinaflo\"></a>\n<a class=\"u-mention\" href=\"https://twitter.com/jgmac1106\"></a>"
},
"author": {
"type": "card",
"name": "(((Alchi)))",
"url": "https://twitter.com/alchi93",
"photo": "https://pbs.twimg.com/profile_images/1603611407592919042/A4W4u_bs.jpg"
},
"post-type": "reply"
}
},
"_id": "33957546",
"_source": "2773"
}
Are you pushing past your boundaries during eternal Caturday?
{
"type": "entry",
"published": "2022-12-24T09:43:03-0500",
"url": "https://martymcgui.re/2022/12/24/094303/",
"category": [
"Caturday"
],
"video": [
"https://res.cloudinary.com/schmarty/video/upload/vc_h264/mmmgre/58/b0/6f/04/d3711bd6808cd346b9f467ee4efba970002e992585a2815ecab2fdf1.mov"
],
"content": {
"text": "Are you pushing past your boundaries during eternal Caturday?",
"html": "<p>Are you pushing past your boundaries during eternal Caturday?</p>"
},
"author": {
"type": "card",
"name": "Marty McGuire",
"url": "https://martymcgui.re/",
"photo": "https://martymcgui.re/images/logo.jpg"
},
"post-type": "video",
"_id": "33957257",
"_source": "175"
}
The last week of the year doesn't count. But 2023 is going to be different, right? Livestream tomorrow (12/25) at 11:30 PST/14:30 EST about Money Resets. youtube.com/watch?v=wmNmo2…
{
"type": "entry",
"published": "2022-12-24T15:54:21+00:00",
"url": "https://twitter.com/anomalily/status/1606679681813876736",
"content": {
"text": "The last week of the year doesn't count. But 2023 is going to be different, right? Livestream tomorrow (12/25) at 11:30 PST/14:30 EST about Money Resets. youtube.com/watch?v=wmNmo2\u2026",
"html": "The last week of the year doesn't count. But 2023 is going to be different, right? Livestream tomorrow (12/25) at 11:30 PST/14:30 EST about Money Resets. <a href=\"https://www.youtube.com/watch?v=wmNmo2kyenM\">youtube.com/watch?v=wmNmo2\u2026</a>"
},
"author": {
"type": "card",
"name": "Lillian Karabaic",
"url": "https://twitter.com/anomalily",
"photo": "https://pbs.twimg.com/profile_images/1455236306162761732/jPv9ROKG.jpg"
},
"post-type": "note",
"_id": "33954293",
"_source": "2773"
}
It's gonna be a while before AI takes all our jobs though.
Or maybe not, since it speaks with the confidence of a mediocre white man while gaslighting me throughout this whole reply.
{
"type": "entry",
"published": "2022-12-24T01:45:39+00:00",
"url": "https://twitter.com/aaronpk/status/1606466100501262341",
"photo": [
"https://pbs.twimg.com/media/FktQZ7kaMAA_sMX.jpg"
],
"content": {
"text": "It's gonna be a while before AI takes all our jobs though.\n\nOr maybe not, since it speaks with the confidence of a mediocre white man while gaslighting me throughout this whole reply."
},
"author": {
"type": "card",
"name": "Aaron Parecki",
"url": "https://twitter.com/aaronpk",
"photo": "https://pbs.twimg.com/profile_images/1477113672803622912/ljLUwFLP.jpg"
},
"post-type": "photo",
"_id": "33942757",
"_source": "2773"
}
Fella Macabee Gotta Torch, a tank full of a oil, and a mission from God.
Help the Fella light the HIMARS hanukkiah and bid on this #NAFO fella
Our first Forger Hanukkah auction! Let’s continue to raise money for @3xR_team ❤️❤️❤️ #NAFO #NAFOfellas #NAFOExpansionIsNonNegotiable
twitter.com/alchi93/st...
{
"type": "entry",
"published": "2022-12-24T01:09:02+00:00",
"url": "https://twitter.com/jgmac1106/status/1606456884004896769",
"quotation-of": "https://twitter.com/Ballin_tine/status/1606453946670776320",
"content": {
"text": "Fella Macabee Gotta Torch, a tank full of a oil, and a mission from God.\n\nHelp the Fella light the HIMARS hanukkiah and bid on this #NAFO fella",
"html": "Fella Macabee Gotta Torch, a tank full of a oil, and a mission from God.\n\nHelp the Fella light the HIMARS hanukkiah and bid on this <a href=\"https://twitter.com/search?q=%23NAFO\">#NAFO</a> fella"
},
"author": {
"type": "card",
"name": "jgregorymcverry.com",
"url": "https://twitter.com/jgmac1106",
"photo": "https://pbs.twimg.com/profile_images/1586874242913734658/3GMcjnTC.jpg"
},
"post-type": "note",
"refs": {
"https://twitter.com/Ballin_tine/status/1606453946670776320": {
"type": "entry",
"published": "2022-12-24T00:57:22+00:00",
"url": "https://twitter.com/Ballin_tine/status/1606453946670776320",
"content": {
"text": "Our first Forger Hanukkah auction! Let\u2019s continue to raise money for @3xR_team \u2764\ufe0f\u2764\ufe0f\u2764\ufe0f #NAFO #NAFOfellas #NAFOExpansionIsNonNegotiable\ntwitter.com/alchi93/status\u2026",
"html": "Our first Forger Hanukkah auction! Let\u2019s continue to raise money for <a href=\"https://twitter.com/3xR_team\">@3xR_team</a> \u2764\ufe0f\u2764\ufe0f\u2764\ufe0f <a href=\"https://twitter.com/search?q=%23NAFO\">#NAFO</a> <a href=\"https://twitter.com/search?q=%23NAFOfellas\">#NAFOfellas</a> <a href=\"https://twitter.com/search?q=%23NAFOExpansionIsNonNegotiable\">#NAFOExpansionIsNonNegotiable</a>\n<a href=\"https://twitter.com/alchi93/status/1606160283990462464\">twitter.com/alchi93/status\u2026</a>"
},
"author": {
"type": "card",
"name": "bobbi",
"url": "https://twitter.com/Ballin_tine",
"photo": "https://pbs.twimg.com/profile_images/1600116021582495744/Vt8GbSeK.jpg"
},
"post-type": "note"
}
},
"_id": "33942759",
"_source": "2773"
}
AI is cool.
I just finished recording and editing 20 new video lessons for a course.
Uploaded the videos to Sonix and it created a (mostly) accurate transcript.
Uploaded the transcript to ChatGPT and asked it to create a summary of the lesson for the landing page!
{
"type": "entry",
"published": "2022-12-24T00:52:00+00:00",
"url": "https://twitter.com/aaronpk/status/1606452598596284416",
"content": {
"text": "AI is cool.\n\nI just finished recording and editing 20 new video lessons for a course.\n\nUploaded the videos to Sonix and it created a (mostly) accurate transcript. \n\nUploaded the transcript to ChatGPT and asked it to create a summary of the lesson for the landing page!"
},
"author": {
"type": "card",
"name": "Aaron Parecki",
"url": "https://twitter.com/aaronpk",
"photo": "https://pbs.twimg.com/profile_images/1477113672803622912/ljLUwFLP.jpg"
},
"post-type": "note",
"_id": "33942761",
"_source": "2773"
}
It's gonna be a while before AI takes all our jobs though.
Or maybe not, since it speaks with the confidence of a mediocre white man while gaslighting me throughout this whole reply.
{
"type": "entry",
"published": "2022-12-23T17:45:36-08:00",
"url": "https://aaronparecki.com/2022/12/23/28/chatgpt",
"category": [
"chatgpt"
],
"photo": [
"https://aperture-media.p3k.io/aaronparecki.com/435532e1f7270f4cc8249faa8c818930fc2c846bf5d08cc050bf9d94e1d36d57.png"
],
"syndication": [
"https://twitter.com/aaronpk/status/1606466100501262341"
],
"content": {
"text": "It's gonna be a while before AI takes all our jobs though. \n\nOr maybe not, since it speaks with the confidence of a mediocre white man while gaslighting me throughout this whole reply.",
"html": "It's gonna be a while before AI takes all our jobs though. <br /><br />Or maybe not, since it speaks with the confidence of a mediocre white man while gaslighting me throughout this whole reply."
},
"author": {
"type": "card",
"name": "Aaron Parecki",
"url": "https://aaronparecki.com/",
"photo": "https://aperture-media.p3k.io/aaronparecki.com/41061f9de825966faa22e9c42830e1d4a614a321213b4575b9488aa93f89817a.jpg"
},
"post-type": "photo",
"_id": "33942400",
"_source": "16"
}
AI is cool.
I just finished recording and editing 20 new video lessons for a course.
Uploaded the videos to Sonix and it created a (mostly) accurate transcript.
Uploaded the transcript to ChatGPT and asked it to create a summary of the lesson for the landing page!
{
"type": "entry",
"published": "2022-12-23T16:51:56-08:00",
"url": "https://aaronparecki.com/2022/12/23/24/chatgpt",
"category": [
"chatgpt",
"video"
],
"syndication": [
"https://twitter.com/aaronpk/status/1606452598596284416",
"https://aaronparecki.com/@aaronpk"
],
"content": {
"text": "AI is cool. \n\nI just finished recording and editing 20 new video lessons for a course. \n\nUploaded the videos to Sonix and it created a (mostly) accurate transcript. \n\nUploaded the transcript to ChatGPT and asked it to create a summary of the lesson for the landing page!",
"html": "AI is cool. <br /><br />I just finished recording and editing 20 new video lessons for a course. <br /><br />Uploaded the videos to Sonix and it created a (mostly) accurate transcript. <br /><br />Uploaded the transcript to ChatGPT and asked it to create a summary of the lesson for the landing page!"
},
"author": {
"type": "card",
"name": "Aaron Parecki",
"url": "https://aaronparecki.com/",
"photo": "https://aperture-media.p3k.io/aaronparecki.com/41061f9de825966faa22e9c42830e1d4a614a321213b4575b9488aa93f89817a.jpg"
},
"post-type": "note",
"_id": "33941650",
"_source": "16"
}
Ran across a random software article that made me, feel, well, old:
In traditional web applications, web pages are rendered on the client side. The browser receives a blob of JavaScript from the server, processes it, and paints the UI that the user sees.
This is not a “tradition” I grew up with!
(It’s also not a “tradition” I’ve ever particularly loved.)
{
"type": "entry",
"author": {
"name": null,
"url": "https://davepeck.org/micro/",
"photo": null
},
"url": "https://davepeck.org/2022/12/23/old-coder/",
"published": "2022-12-23T13:55:00-08:00",
"content": {
"html": "<p>Ran across a <a href=\"https://medium.com/meural-product-development/setting-up-server-side-rendering-with-react-redux-and-django-4d6f4d2fd705\">random software article</a> that made me, feel, well, <em>old</em>:</p>\n\n<blockquote>\n <p>In traditional web applications, web pages are rendered on the client side. The browser receives a blob of JavaScript from the server, processes it, and paints the UI that the user sees.</p>\n</blockquote>\n\n<p>This is not a \u201ctradition\u201d I grew up with!</p>\n\n<p>(It\u2019s also not a \u201ctradition\u201d I\u2019ve ever particularly loved.)</p>",
"text": "Ran across a random software article that made me, feel, well, old:\n\n\n In traditional web applications, web pages are rendered on the client side. The browser receives a blob of JavaScript from the server, processes it, and paints the UI that the user sees.\n\n\nThis is not a \u201ctradition\u201d I grew up with!\n\n(It\u2019s also not a \u201ctradition\u201d I\u2019ve ever particularly loved.)"
},
"post-type": "note",
"_id": "33941241",
"_source": "2781"
}
another #disinfo technique
"overwhelming list"
People who support #Putin try to justify by proving how evil other countries or alliances have been in the past.
Ignoring one evil does not justify another the lists are pronounced nonsense
Includes invites and peace keeping.
{
"type": "entry",
"published": "2022-12-23T23:15:33+00:00",
"url": "https://twitter.com/jgmac1106/status/1606428327572537349",
"quotation-of": "https://twitter.com/waqas552748291/status/1606427393887195136",
"content": {
"text": "another #disinfo technique\n\n \"overwhelming list\"\n\nPeople who support #Putin try to justify by proving how evil other countries or alliances have been in the past.\n\nIgnoring one evil does not justify another the lists are pronounced nonsense\n\nIncludes invites and peace keeping.",
"html": "another <a href=\"https://twitter.com/search?q=%23disinfo\">#disinfo</a> technique\n\n \"overwhelming list\"\n\nPeople who support <a href=\"https://twitter.com/search?q=%23Putin\">#Putin</a> try to justify by proving how evil other countries or alliances have been in the past.\n\nIgnoring one evil does not justify another the lists are pronounced nonsense\n\nIncludes invites and peace keeping."
},
"author": {
"type": "card",
"name": "jgregorymcverry.com",
"url": "https://twitter.com/jgmac1106",
"photo": "https://pbs.twimg.com/profile_images/1586874242913734658/3GMcjnTC.jpg"
},
"post-type": "note",
"refs": {
"https://twitter.com/waqas552748291/status/1606427393887195136": {
"type": "entry",
"published": "2022-12-23T23:11:51+00:00",
"url": "https://twitter.com/waqas552748291/status/1606427393887195136",
"photo": [
"https://pbs.twimg.com/media/FkstK07UUAAtj4b.jpg"
],
"in-reply-to": [
"https://twitter.com/jgmac1106/status/1606426929917095937"
],
"content": {
"text": "Just a reminder...",
"html": "Just a reminder...\n<a class=\"u-mention\" href=\"https://twitter.com/MarikkaVe\"></a>\n<a class=\"u-mention\" href=\"https://twitter.com/calmrainyday\"></a>\n<a class=\"u-mention\" href=\"https://twitter.com/jgmac1106\"></a>"
},
"author": {
"type": "card",
"name": "Only the Truth(Not NAFO)",
"url": "https://twitter.com/waqas552748291",
"photo": "https://pbs.twimg.com/profile_images/1582348415597367297/hF46vJYk.jpg"
},
"post-type": "reply"
}
},
"_id": "33940737",
"_source": "2773"
}
NEW: Twitter is shutting down its data center in Sacramento and downsizing another in Atlanta by early Jan, likely as a cost saving measure. This means a huge amount of traffic will be shifted to its remaining data centers, which could result in increased instability.
{
"type": "entry",
"published": "2022-12-23T21:58:08+00:00",
"url": "https://twitter.com/ZoeSchiffer/status/1606408842417512455",
"content": {
"text": "NEW: Twitter is shutting down its data center in Sacramento and downsizing another in Atlanta by early Jan, likely as a cost saving measure. This means a huge amount of traffic will be shifted to its remaining data centers, which could result in increased instability."
},
"author": {
"type": "card",
"name": "Zo\u00eb Schiffer",
"url": "https://twitter.com/ZoeSchiffer",
"photo": "https://pbs.twimg.com/profile_images/1564799885794086914/ZU6qMT_n.jpg"
},
"post-type": "note",
"_id": "33939393",
"_source": "2773"
}
{
"type": "entry",
"author": {
"name": null,
"url": "https://herestomwiththeweather.com/",
"photo": null
},
"url": "https://herestomwiththeweather.com/2022/12/23/check_webfinger/",
"published": "2022-12-23T11:37:50+00:00",
"content": {
"html": "<p>The notes I made in <a href=\"https://herestomwiththeweather.com/2022/11/15/mastodon-discovery/\">Mastodon Discovery</a> skipped over a noteworthy step. In general, after mastodon fetches and parses the \u201cwell known\u201d webfinger document (the so-called JSON Resource Descriptor), there is a 3 step process to learn about the actor referenced in that document.</p>\n\n<ol><li>fetch_resource</li>\n <li>check_webfinger!</li>\n <li>create_account</li>\n</ol><p>As mentioned previously, in the first step, a very comprehensive json document for the actor is fetched and in the third step, an account is created for that actor if does not already exist. However, between those two steps, mastodon does another webfinger lookup since, for instance, the domain serving the actor document may be a different domain than the one that originally served the first \u201cwell known\u201d webfinger document. Prior to this check, <a href=\"https://github.com/herestomwiththeweather/mastodon/blob/main/app/services/activitypub/fetch_remote_actor_service.rb#L32\">some instance variables are set</a>:</p>\n\n<pre><code> @uri = @json['id']\n @username = @json['preferredUsername']\n @domain = Addressable::URI.parse(@uri).normalized_host\n</code></pre>\n\n<p>The @uri instance variable is the location of the actor document and the @domain instance variable is the domain that serves the actor document. After these variables are set, <a href=\"https://github.com/herestomwiththeweather/mastodon/blob/main/app/services/activitypub/fetch_remote_actor_service.rb#L36\">the check is performed</a>:</p>\n\n<pre><code> check_webfinger! unless only_key\n</code></pre>\n\n<p>This check enforces that the domain component of your identifier is the domain that serves your actor document. (It <a href=\"https://github.com/herestomwiththeweather/mastodon/blob/main/app/services/activitypub/fetch_remote_actor_service.rb#L48\">inspects the subject of the \u201cwell known\u201d document</a> and if the username and domain of the subject match the instance variables above, the \u2018self\u2019 resource link is required to be the same as the @uri instance variable. If the subject does not match, one more webfinger lookup for the redirection is allowed.)</p>\n\n<p>So, from the perspective of mastodon, the domain component of your identifier you are known as is determined by which domain serves your actor document rather than the domain serving the original \u201cwell known\u201d webfinger document. It seems if your domain is a static site and you want to be known by an identifier associated with your domain, your domain needs to serve the actor document in addition to \u201cwell known\u201d webfinger document.</p>",
"text": "The notes I made in Mastodon Discovery skipped over a noteworthy step. In general, after mastodon fetches and parses the \u201cwell known\u201d webfinger document (the so-called JSON Resource Descriptor), there is a 3 step process to learn about the actor referenced in that document.\n\nfetch_resource\n check_webfinger!\n create_account\nAs mentioned previously, in the first step, a very comprehensive json document for the actor is fetched and in the third step, an account is created for that actor if does not already exist. However, between those two steps, mastodon does another webfinger lookup since, for instance, the domain serving the actor document may be a different domain than the one that originally served the first \u201cwell known\u201d webfinger document. Prior to this check, some instance variables are set:\n\n @uri = @json['id']\n @username = @json['preferredUsername']\n @domain = Addressable::URI.parse(@uri).normalized_host\n\n\nThe @uri instance variable is the location of the actor document and the @domain instance variable is the domain that serves the actor document. After these variables are set, the check is performed:\n\n check_webfinger! unless only_key\n\n\nThis check enforces that the domain component of your identifier is the domain that serves your actor document. (It inspects the subject of the \u201cwell known\u201d document and if the username and domain of the subject match the instance variables above, the \u2018self\u2019 resource link is required to be the same as the @uri instance variable. If the subject does not match, one more webfinger lookup for the redirection is allowed.)\n\nSo, from the perspective of mastodon, the domain component of your identifier you are known as is determined by which domain serves your actor document rather than the domain serving the original \u201cwell known\u201d webfinger document. It seems if your domain is a static site and you want to be known by an identifier associated with your domain, your domain needs to serve the actor document in addition to \u201cwell known\u201d webfinger document."
},
"name": "check_webfinger!",
"post-type": "note",
"_id": "33939169",
"_source": "246"
}
{
"type": "entry",
"author": {
"name": null,
"url": "https://herestomwiththeweather.com/",
"photo": null
},
"url": "https://herestomwiththeweather.com/2022/12/22/indieweb-and-mastodon/",
"published": "2022-12-22T20:06:15+00:00",
"content": {
"html": "<p>Thanks to <a href=\"https://effaustin.org/\">EFF-Austin</a> for the opportunity to talk along with <a href=\"https://www.weblogsky.com/\">Jon Lebkowsky</a> about the relationship between <a href=\"https://indieweb.org/\">Indieweb</a> and the <a href=\"https://en.wikipedia.org/wiki/Fediverse\">Fediverse</a>. (<a href=\"https://herestomwiththeweather.com/effaustin/indieweb_mastodon\">Slides</a> and <a href=\"https://www.youtube.com/watch?v=VRu3i9u9I5Q\">video</a>)</p>\n\n<p>The meetup <a href=\"https://www.meetup.com/EFF-Austin/events/nltdcrydcqbrb/\">Indieweb and Mastodon: The Time is Now</a> was coincidentally in the same room as <a href=\"https://indieweb.org/2020/Austin\">IndieWebCamp Austin 2020</a>.</p>",
"text": "Thanks to EFF-Austin for the opportunity to talk along with Jon Lebkowsky about the relationship between Indieweb and the Fediverse. (Slides and video)\n\nThe meetup Indieweb and Mastodon: The Time is Now was coincidentally in the same room as IndieWebCamp Austin 2020."
},
"name": "IndieWeb and Mastodon",
"post-type": "article",
"_id": "33939170",
"_source": "246"
}
{
"type": "entry",
"author": {
"name": null,
"url": "https://herestomwiththeweather.com/",
"photo": null
},
"url": "https://herestomwiththeweather.com/social/2022/12/02/77469/",
"published": "2022-12-02T21:31:09+00:00",
"post-type": "note",
"_id": "33939171",
"_source": "246"
}
{
"type": "entry",
"author": {
"name": null,
"url": "https://herestomwiththeweather.com/",
"photo": null
},
"url": "https://herestomwiththeweather.com/2022/11/15/mastodon-discovery/",
"published": "2022-11-15T16:42:33+00:00",
"content": {
"html": "<p>Making notes is helpful when reading and running unfamiliar code for the first time. I usually start with happy paths. Here\u2019s some notes I made while learning about Mastodon account search and discovery. It\u2019s really cool to poke around the code that so many people are using every day to find each other.</p>\n\n<p>When you search on an account identifier on Mastodon, your browser makes a request to your Mastodon instance:</p>\n\n<blockquote>\n <p>/api/v2/search?q=%40herestomwiththeweather%40mastodon.social&resolve=true&limit=5</p>\n</blockquote>\n\n<p>The resolve=true parameter tells your Mastodon instance to make a webfinger request to the target Mastodon instance if necessary. The search controller <a href=\"https://github.com/herestomwiththeweather/mastodon/blob/main/app/controllers/api/v2/search_controller.rb#L32\">makes a call to the SearchService</a></p>\n\n<pre><code> def search_results\n SearchService.new.call(\n params[:q],\n current_account,\n limit_param(RESULTS_LIMIT),\n search_params.merge(resolve: truthy_param?(:resolve), exclude_unreviewed: truthy_param?(:exclude_unreviewed))\n )\n end\n</code></pre>\n\n\n<p>and since resolve=true, SearchService <a href=\"https://github.com/herestomwiththeweather/mastodon/blob/main/app/services/account_search_service.rb#L36\">makes a call to the ResolveAccountService</a></p>\n\n<pre><code> if options[:resolve]\n ResolveAccountService.new.call(query)\n</code></pre>\n\n\n<p>The purpose of ResolveAccountService is to \u201cFind or create an account record for a remote user\u201d and return an account object to the search controller. It includes <a href=\"https://github.com/herestomwiththeweather/mastodon/blob/main/app/helpers/webfinger_helper.rb\">WebfingerHelper</a> which is a trivial module with just one one-line method named webfinger!()</p>\n\n<pre><code>module WebfingerHelper\n def webfinger!(uri)\n Webfinger.new(uri).perform\n end\nend\n</code></pre>\n\n\n<p>This method returns a webfinger object. Rather than call it directly, ResolveAccountService <a href=\"https://github.com/herestomwiththeweather/mastodon/blob/main/app/services/resolve_account_service.rb#L34\">invokes process_webfinger!</a> which <a href=\"https://github.com/herestomwiththeweather/mastodon/blob/main/app/services/resolve_account_service.rb#L86\">invokes it</a> and then asks the returned webfinger object\u2019s subject method for its username and domain and makes them instance variables of the service object.</p>\n\n<pre><code> def process_webfinger!(uri)\n @webfinger = webfinger!(\"acct:#{uri}\")\n confirmed_username, confirmed_domain = split_acct(@webfinger.subject)\n\n if confirmed_username.casecmp(@username).zero? && confirmed_domain.casecmp(@domain).zero?\n @username = confirmed_username\n @domain = confirmed_domain\n return\n end\n</code></pre>\n\n\n<p>If the Mastodon instance does not already know about this account, ResolveAccountService <a href=\"https://github.com/herestomwiththeweather/mastodon/blob/main/app/services/resolve_account_service.rb#L55\">invokes fetch_account!</a> which <a href=\"https://github.com/herestomwiththeweather/mastodon/blob/main/app/services/resolve_account_service.rb#L114\">calls the ActivityPub::FetchRemoteAccountService</a> which inherits from <a href=\"https://github.com/herestomwiththeweather/mastodon/blob/main/app/services/activitypub/fetch_remote_actor_service.rb\">ActivityPub::FetchRemoteActorService</a></p>\n\n<pre><code> @account = ActivityPub::FetchRemoteAccountService.new.call(actor_url, suppress_errors: @options[:suppress_errors])\n</code></pre>\n\n\n<p>The actor_url will look something like</p>\n\n<blockquote>\n <p>https://mastodon.social/users/herestomwiththeweather</p>\n</blockquote>\n\n<p>The ActivityPub::FetchRemoteActorService <a href=\"https://github.com/mastodon/mastodon/blob/main/app/services/activitypub/fetch_remote_actor_service.rb#L19\">passes the actor_url parameter to fetch_resource</a> to receive a json response for the remote account.</p>\n\n<pre><code> @json = begin\n if prefetched_body.nil?\n fetch_resource(uri, id)\n else\n\n</code></pre>\n\n\n<p>The response includes a lot of information including name, summary, publicKey, images and urls to fetch more information like followers and following.</p>\n\n<p>Finally, the ActivityPub::FetchRemoteActorService <a href=\"https://github.com/mastodon/mastodon/blob/main/app/services/activitypub/fetch_remote_actor_service.rb#L38\">calls the ActivityPub::ProcessAccountService</a>, passing it the json response.</p>\n\n<pre><code> ActivityPub::ProcessAccountService.new.call(@username, @domain, @json, only_key: only_key, verified_webfinger: !only_key)\n</code></pre>\n\n\n<p>If the Mastodon instance does not know about the account, ActivityPub::ProcessAccountService <a href=\"https://github.com/mastodon/mastodon/blob/main/app/services/activitypub/process_account_service.rb#L28\">invokes create_account and update_account</a> to save the username, domain and all the associated urls from the json response to a new account record in the database.</p>\n\n<pre><code> create_account if @account.nil?\n update_account\n</code></pre>\n\n\n<p>I have several questions about how following others works and will probably look at that soon. I may start out by reading <a href=\"https://tinysubversions.com/notes/reading-activitypub/\">A highly opinionated guide to learning about ActivityPub</a> which I bookmarked a while ago.</p>",
"text": "Making notes is helpful when reading and running unfamiliar code for the first time. I usually start with happy paths. Here\u2019s some notes I made while learning about Mastodon account search and discovery. It\u2019s really cool to poke around the code that so many people are using every day to find each other.\n\nWhen you search on an account identifier on Mastodon, your browser makes a request to your Mastodon instance:\n\n\n /api/v2/search?q=%40herestomwiththeweather%40mastodon.social&resolve=true&limit=5\n\n\nThe resolve=true parameter tells your Mastodon instance to make a webfinger request to the target Mastodon instance if necessary. The search controller makes a call to the SearchService\n\n def search_results\n SearchService.new.call(\n params[:q],\n current_account,\n limit_param(RESULTS_LIMIT),\n search_params.merge(resolve: truthy_param?(:resolve), exclude_unreviewed: truthy_param?(:exclude_unreviewed))\n )\n end\n\n\n\nand since resolve=true, SearchService makes a call to the ResolveAccountService\n\n if options[:resolve]\n ResolveAccountService.new.call(query)\n\n\n\nThe purpose of ResolveAccountService is to \u201cFind or create an account record for a remote user\u201d and return an account object to the search controller. It includes WebfingerHelper which is a trivial module with just one one-line method named webfinger!()\n\nmodule WebfingerHelper\n def webfinger!(uri)\n Webfinger.new(uri).perform\n end\nend\n\n\n\nThis method returns a webfinger object. Rather than call it directly, ResolveAccountService invokes process_webfinger! which invokes it and then asks the returned webfinger object\u2019s subject method for its username and domain and makes them instance variables of the service object.\n\n def process_webfinger!(uri)\n @webfinger = webfinger!(\"acct:#{uri}\")\n confirmed_username, confirmed_domain = split_acct(@webfinger.subject)\n\n if confirmed_username.casecmp(@username).zero? && confirmed_domain.casecmp(@domain).zero?\n @username = confirmed_username\n @domain = confirmed_domain\n return\n end\n\n\n\nIf the Mastodon instance does not already know about this account, ResolveAccountService invokes fetch_account! which calls the ActivityPub::FetchRemoteAccountService which inherits from ActivityPub::FetchRemoteActorService\n\n @account = ActivityPub::FetchRemoteAccountService.new.call(actor_url, suppress_errors: @options[:suppress_errors])\n\n\n\nThe actor_url will look something like\n\n\n https://mastodon.social/users/herestomwiththeweather\n\n\nThe ActivityPub::FetchRemoteActorService passes the actor_url parameter to fetch_resource to receive a json response for the remote account.\n\n @json = begin\n if prefetched_body.nil?\n fetch_resource(uri, id)\n else\n\n\n\n\nThe response includes a lot of information including name, summary, publicKey, images and urls to fetch more information like followers and following.\n\nFinally, the ActivityPub::FetchRemoteActorService calls the ActivityPub::ProcessAccountService, passing it the json response.\n\n ActivityPub::ProcessAccountService.new.call(@username, @domain, @json, only_key: only_key, verified_webfinger: !only_key)\n\n\n\nIf the Mastodon instance does not know about the account, ActivityPub::ProcessAccountService invokes create_account and update_account to save the username, domain and all the associated urls from the json response to a new account record in the database.\n\n create_account if @account.nil?\n update_account\n\n\n\nI have several questions about how following others works and will probably look at that soon. I may start out by reading A highly opinionated guide to learning about ActivityPub which I bookmarked a while ago."
},
"name": "Mastodon Discovery",
"post-type": "article",
"_id": "33939172",
"_source": "246"
}
{
"type": "entry",
"author": {
"name": null,
"url": "https://herestomwiththeweather.com/",
"photo": null
},
"url": "https://herestomwiththeweather.com/2022/10/27/rubyconf-in-houston/",
"published": "2022-10-27T21:56:20+00:00",
"content": {
"html": "<p>Earlier this week, I signed up for <a href=\"https://rubyconf.org/\">RubyConf 2022</a> which is Nov. 29 - Dec. 1 in Houston. This is my first conference since the pandemic started and I was glad to see the <a href=\"https://rubyconf.org/safety\">safety precautions</a>. The <a href=\"https://rubyconf.org/schedule\">schedule</a> also looks great! Please say \u201cHi!\u201d if you see me there.</p>",
"text": "Earlier this week, I signed up for RubyConf 2022 which is Nov. 29 - Dec. 1 in Houston. This is my first conference since the pandemic started and I was glad to see the safety precautions. The schedule also looks great! Please say \u201cHi!\u201d if you see me there."
},
"name": "RubyConf in Houston",
"post-type": "article",
"_id": "33939173",
"_source": "246"
}
{
"type": "entry",
"author": {
"name": null,
"url": "https://herestomwiththeweather.com/",
"photo": null
},
"url": "https://herestomwiththeweather.com/2022/10/25/indieauth-login-history/",
"published": "2022-10-25T16:51:16+00:00",
"content": {
"html": "<p>In my last post, I mentioned that I planned to add login history to <a href=\"https://github.com/herestomwiththeweather/irwin\">Irwin</a>. As I was testing my code, I logged into <a href=\"https://indieweb.org/\">indieweb.org</a> and noticed that I needed to update my code to support <a href=\"https://indieauth.spec.indieweb.org/#profile-url-response\">5.3.2 Profile URL Response</a> of the IndieAuth spec as this IndieAuth client does not need an access token. Here\u2019s what the history looks like on my IndieAuth server:</p>\n\n<p><img src=\"https://coffeebucks.s3.amazonaws.com/images/image/jekyll/indieauth_login_history.png\" alt=\"IndieAuth login history\" /></p>\n\n<p>If I click on a login timestamp, I have the option to revoke the access token associated with the login if it exists and has not already expired. My next step is to test some other <a href=\"https://indieweb.org/Micropub/Servers\">micropub servers</a> than the one I use to see what interoperability updates I may need to make.</p>",
"text": "In my last post, I mentioned that I planned to add login history to Irwin. As I was testing my code, I logged into indieweb.org and noticed that I needed to update my code to support 5.3.2 Profile URL Response of the IndieAuth spec as this IndieAuth client does not need an access token. Here\u2019s what the history looks like on my IndieAuth server:\n\n\n\nIf I click on a login timestamp, I have the option to revoke the access token associated with the login if it exists and has not already expired. My next step is to test some other micropub servers than the one I use to see what interoperability updates I may need to make."
},
"name": "IndieAuth login history",
"post-type": "article",
"_id": "33939174",
"_source": "246"
}
{
"type": "entry",
"author": {
"name": null,
"url": "https://herestomwiththeweather.com/",
"photo": null
},
"url": "https://herestomwiththeweather.com/2022/10/09/minimum-viable-indieauth-server/",
"published": "2022-10-09T20:38:46+00:00",
"content": {
"html": "<p>One of the building blocks of the <a href=\"https://indieweb.org/\">Indieweb</a> is <a href=\"https://indieweb.org/IndieAuth\">IndieAuth</a>. Like many others, I bootstrapped my experience with <a href=\"https://indieauth.com/\">indieauth.com</a> but as <a href=\"https://martymcgui.re/2022/07/31/switching-costs-for-an-indieauth-server/\">Marty McGuire explains</a>, there are good reasons to switch and even consider building your own. Because I wanted a server as simple to understand as possible but also wanted to be able to add features that are usually not available, I created a rails project called <a href=\"https://github.com/herestomwiththeweather/irwin\">Irwin</a> and <a href=\"https://github.com/herestomwiththeweather/herestomwiththeweather.github.io/commit/554dbaad13250a97c2b26c034fbce3dd6908c273\">recently configured my blog to use it</a>.</p>\n\n<p>This is not production ready code. While I know that <a href=\"https://github.com/voxpelli/webpage-micropub-to-github\">the micropub server I use</a> works with it, I expect others may not. Also, there is no support for refresh tokens and other things in the spec that I didn\u2019t consider high priority. It does support <a href=\"https://indieweb.org/PKCE\">PKCE</a> but not the less useful \u201cplain\u201d method.</p>\n\n<p>All of <a href=\"https://aaronparecki.com/2020/12/03/1/indieauth-2020\">IndieAuth Spec Updates 2020</a> was very clear and helpful. In one case, I made the server probably too strict (as an easy way to curtail spam registrations). It requires that the hosts for a blog\u2019s authorization endpoint and token endpoint match the host of the IndieAuth server before a user can register an account on the indieauth server.</p>\n\n<p>I plan to add an option for a user to keep a history of logins to indieauth clients soon. Please let me know if you have any questions or suggestions.</p>",
"text": "One of the building blocks of the Indieweb is IndieAuth. Like many others, I bootstrapped my experience with indieauth.com but as Marty McGuire explains, there are good reasons to switch and even consider building your own. Because I wanted a server as simple to understand as possible but also wanted to be able to add features that are usually not available, I created a rails project called Irwin and recently configured my blog to use it.\n\nThis is not production ready code. While I know that the micropub server I use works with it, I expect others may not. Also, there is no support for refresh tokens and other things in the spec that I didn\u2019t consider high priority. It does support PKCE but not the less useful \u201cplain\u201d method.\n\nAll of IndieAuth Spec Updates 2020 was very clear and helpful. In one case, I made the server probably too strict (as an easy way to curtail spam registrations). It requires that the hosts for a blog\u2019s authorization endpoint and token endpoint match the host of the IndieAuth server before a user can register an account on the indieauth server.\n\nI plan to add an option for a user to keep a history of logins to indieauth clients soon. Please let me know if you have any questions or suggestions."
},
"name": "Minimum Viable IndieAuth Server",
"post-type": "article",
"_id": "33939175",
"_source": "246"
}
{
"type": "entry",
"author": {
"name": null,
"url": "https://herestomwiththeweather.com/",
"photo": null
},
"url": "https://herestomwiththeweather.com/social/2022/09/30/84826/",
"published": "2022-09-30T23:33:46+00:00",
"post-type": "note",
"_id": "33939176",
"_source": "246"
}
{
"type": "entry",
"author": {
"name": null,
"url": "https://herestomwiththeweather.com/",
"photo": null
},
"url": "https://herestomwiththeweather.com/social/2022/09/30/2432/",
"published": "2022-09-30T00:40:32+00:00",
"post-type": "note",
"_id": "33939177",
"_source": "246"
}