pronoiac / mefi.social

2 stars 0 forks source link

Bookmarklet, for "open on my home instance" #18

Closed pronoiac closed 1 year ago

pronoiac commented 1 year ago

I think I've seen a shortcut or something, but a simple bookmarklet might be useful, easier to examine and edit.

pronoiac commented 1 year ago

this bookmarklet generator worked for me. dunno if I should save the output or anything.

pronoiac commented 1 year ago

For later reference, I got:

javascript:(function()%20%7B/*%20Mastodon%20switcher%20https://homepages.inf.ed.ac.uk/imurray2/code/mastodon.html%20*/myInstance%20=%20'mefi.social';%20/*%20usernames%20are%20@%20this%20string%20*/myInstanceURL%20=%20'mefi.social';%20%20%20%20%20/*%20Mastodon%20instance%20website%20with%20no%20https://%20or%20trailing%20slash%20*/ver3%20=%20true;%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20/*%20set%20to%20true%20if%20your%20instance%20runs%20Mastodon%20v3%20*/function%20getJsonObject(URL)%7B%20%20%20%20var%20req%20=%20new%20XMLHttpRequest();%20%20%20%20req.open('GET',%20URL,%20false);%20%20%20%20req.send(null);%20%20%20%20return%20JSON.parse(req.responseText);%7Dfunction%20mastodonURL(origURL,%20myInstance,%20myInstanceURL,%20ver3)%20%7B%20%20/*%20If%20a%20fancy%20redirection%20didn't%20work,%20back%20it%20out%20*/%20%20mm%20=%20origURL.href.match(/.*authorize_interaction%5C?uri=(.*)/);%20%20if%20(mm)%20%7B%20%20%20%20return%20decodeURIComponent(mm%5B1%5D);%20%20%7D%20%20/*%20Otherwise%20try%20to%20work%20out%20pieces%20of%20the%20URL%20*/%20%20pathname%20=%20origURL.pathname;%20%20match%20=%20pathname.match(/%5E%5C/(@%7Cusers%5C/%7Cweb%5C/@)(%5B%5E%5C/@%5D*)@?(%5B%5E%5C/%5D*)(%5C/?.*)/);%20%20user%20=%20match%5B2%5D;%20%20extra%20=%20match%5B4%5D;%20%20%20%20if%20(extra.match(/%5E%5C/%5B0-9%5D+$/))%20%7B%20%20%20%20/*%20post%20numbers%20need%20rewriting%20between%20instances,%20so%20can't%20just%20move%20URL%20pieces%20around%20*/%20%20%20%20if%20(origURL.hostname%20==%20myInstanceURL)%20%7B%20%20%20%20%20%20/*%20Our%20home%20instance%20should%20already%20have%20a%20link%20on%20the%20page%20that%20we%20can%20follow.%20*/%20%20%20%20%20%20datetimeEl%20=%20document.getElementsByClassName('detailed-status__datetime')%5B0%5D;%20%20%20%20%20%20datetimeURL%20=%20new%20URL(datetimeEl.href);%20%20%20%20%20%20if%20(datetimeURL.hostname%20==%20origURL.hostname)%20%7B%20%20%20%20%20%20%20%20/*%20In%20Mastodon%20from%20about%20v4.0.2%20datetime%20link%20stays%20on%20local%20server,%20and%20need%20to%20find%20link%20in%20pop-up%20menu.%20%20%20%20%20%20%20%20%20%20%20It%20is%20beginning%20to%20feel%20like%20chasing%20webpage%20changes%20is%20a%20losing%20battle,%20and%20should%20be%20using%20an%20API%20to%20get%20JSON%20data%20instead?%20*/%20%20%20%20%20%20%20%20datetimeEl.parentElement.parentElement.parentElement.parentElement.getElementsByClassName('detailed-status__action-bar-dropdown')%5B0%5D.children%5B0%5D.click();%20%20%20%20%20%20%20%20return%20document.getElementsByClassName('dropdown-menu__item')%5B0%5D.childNodes%5B0%5D.href;%20%20%20%20%20%20%7D%20else%20%7B%20%20%20%20%20%20%20%20return%20datetimeURL;%20%20%20%20%20%20%7D%20%20%20%20%7D%20else%20%7B%20%20%20%20%20%20/*%20Foreign%20instances%20won't%20know%20what%20link%20we%20want,%20so%20ask%20myInstance%20to%20rewrite%20the%20link%20*/%20%20%20%20%20%20return%20'https://'%20+%20myInstanceURL%20+%20'/authorize_interaction?uri='%20+%20encodeURIComponent(origURL);%20%20%20%20%7D%20%20%7D%20else%20%7B%20%20%20%20/*%20URLs%20without%20post%20numbers,%20combine%20pieces%20of%20URL%20ourselves.%20*/%20%20%20%20pageOrigInstance%20=%20match%5B3%5D;%20%20%20%20if%20(!%20pageOrigInstance)%20%7B%20%20%20%20%20%20metas%20=%20document.getElementsByTagName('meta');%20%20%20%20%20%20for%20(i=0;%20i%20%3C%20metas.length;%20i++)%20%7B%20%20%20%20%20%20%20%20if%20(metas%5Bi%5D.getAttribute('property')%20==%20'profile:username')%20%7B%20%20%20%20%20%20%20%20%20%20pageOrigInstance%20=%20metas%5Bi%5D.getAttribute('content').split('@')%5B1%5D;%20%20%20%20%20%20%20%20%7D%20%20%20%20%20%20%7D%20%20%20%20%7D%20%20%20%20pageOrigInstance%20=%20pageOrigInstance%20%7C%7C%20origURL.hostname;%20%20%20%20if%20(origURL.hostname%20==%20myInstanceURL)%20%7B%20%20%20%20%20%20/*%20redirecting%20out.%20/web/@username/%20always%20works,%20because%20in%20v4%20it's%20the%20@username@domain.ext%20form%20that%20fails%20(the%20.ext%20gets%20stripped)%20*/%20%20%20%20%20%20/*%20Frustratingly%20the%20intance's%20actual%20URL%20might%20not%20be%20the%20same%20as%20the%20domain%20in%20the%20username.%20%20%20%20%20%20Across%20Mastodon%20versions,%20hard%20to%20reliably%20pull%20instance%20URL%20out%20of%20the%20page.%20So%20have%20to%20make%20another%20request%20to%20be%20sure%20:-(%20*/%20%20%20%20%20%20data%20=%20getJsonObject('https://'%20+%20origURL.hostname%20+%20'/api/v1/accounts/lookup?acct='%20+%20user%20+%20'%40'%20+%20pageOrigInstance);%20%20%20%20%20%20pageOrigInstanceURL%20=%20(new%20URL(data.url)).hostname%20%7C%7C%20pageOrigInstance;%20%20%20%20%20%20return%20'https://'%20+%20pageOrigInstanceURL%20+%20'/web/@'%20+%20user%20+%20extra;%20%20%20%20%7D%20else%20%7B%20%20%20%20%20%20/*%20redirecting%20in.%20Bug%20in%20v4%20redirection%20https://github.com/mastodon/mastodon/issues/20145%20means%20/web/%20paths%20don't%20work%20if%20myInstance%20is%20running%20an%20early%20v4%20release,%20but%20/web/%20needed%20for%20v3.%20*/%20%20%20%20%20%20if%20(ver3)%20%7B%20%20%20%20%20%20%20%20sep%20=%20'/web/@'%20%20%20%20%20%20%7D%20else%20%7B%20%20%20%20%20%20%20%20sep%20=%20'/@'%20%20%20%20%20%20%7D%20%20%20%20%20%20%20%20if%20(pageOrigInstance%20!=%20myInstance)%20%7B%20%20%20%20%20%20%20%20user%20=%20user%20+%20'@'%20+%20pageOrigInstance;%20%20%20%20%20%20%7D%20%20%20%20%20%20return%20'https://'%20+%20myInstanceURL%20+%20sep%20+%20user%20+%20extra;%20%20%20%20%7D%20%20%7D%7Ddocument.location%20=%20mastodonURL(document.location,%20myInstance,%20myInstanceURL,%20ver3);%7D)()

Linking that in markdown doesn't work, because of way too many parentheses.

pronoiac commented 1 year ago

Within the GitHub repo for a related extension, there's an editable bookmarklet that does something similar.

pronoiac commented 1 year ago

Updated, because of an XSS issue, and maybe helpful for the Hometown upgrade:

javascript:(function() {/* Mastodon switcher https://homepages.inf.ed.ac.uk/imurray2/code/mastodon.html */myInstance = 'mefi.social'; /* usernames are @ this string */myInstanceURL = 'mefi.social';     /* Mastodon instance website with no https:// or trailing slash */ver3 = false;                   /* set to true if your instance runs Mastodon v3 */function getJsonObject(URL){    var req = new XMLHttpRequest();    req.open('GET', URL, false);    req.send(null);    return JSON.parse(req.responseText);}function mastodonURL(origURL, myInstance, myInstanceURL, ver3) {  /* If a fancy redirection didn't work, back it out */  mm = origURL.href.match(/.*authorize_interaction\?uri=(.*)/);  if (mm) {    return decodeURIComponent(mm[1]);  }  /* Otherwise try to work out pieces of the URL */  pathname = origURL.pathname;  match = pathname.match(/^\/(@|users\/|web\/@)([^\/@]*)@?([^\/]*)(\/?.*)/);  user = match[2];  extra = match[4];    if (extra.match(/^\/[0-9]+$/)) {    /* post numbers need rewriting between instances, so can't just move URL pieces around */    if (origURL.hostname == myInstanceURL) {      /* Our home instance should already have a link on the page that we can follow. */      datetimeEl = document.getElementsByClassName('detailed-status__datetime')[0];      datetimeURL = new URL(datetimeEl.href);      if (datetimeURL.hostname == origURL.hostname) {        /* In Mastodon from about v4.0.2 datetime link stays on local server, and need to find link in pop-up menu.           It is beginning to feel like chasing webpage changes is a losing battle, and should be using an API to get JSON data instead? */        datetimeEl.parentElement.parentElement.parentElement.parentElement.getElementsByClassName('detailed-status__action-bar-dropdown')[0].children[0].click();        return document.getElementsByClassName('dropdown-menu__item')[0].childNodes[0].href;      } else {        return datetimeURL;      }    } else {      /* Foreign instances won't know what link we want, so ask myInstance to rewrite the link */      return 'https://' + myInstanceURL + '/authorize_interaction?uri=' + encodeURIComponent(origURL);    }  } else {    /* URLs without post numbers, combine pieces of URL ourselves. */    pageOrigInstance = match[3];    if (! pageOrigInstance) {      metas = document.getElementsByTagName('meta');      for (i=0; i < metas.length; i++) {        if (metas[i].getAttribute('property') == 'profile:username') {          pageOrigInstance = metas[i].getAttribute('content').split('@')[1];        }      }    }    pageOrigInstance = pageOrigInstance || origURL.hostname;    if (origURL.hostname == myInstanceURL) {      /* redirecting out. /web/@username/ always works, because in v4 it's the @username@domain.ext form that fails (the .ext gets stripped) */      /* Frustratingly the intance's actual URL might not be the same as the domain in the username.      Across Mastodon versions, hard to reliably pull instance URL out of the page. So have to make another request to be sure :-( */      data = getJsonObject('https://' + origURL.hostname + '/api/v1/accounts/lookup?acct=' + user + '%40' + pageOrigInstance);      pageOrigInstanceURL = (new URL(data.url)).hostname || pageOrigInstance;      return 'https://' + pageOrigInstanceURL + '/web/@' + user + extra;    } else {      /* redirecting in. Bug in v4 redirection https://github.com/mastodon/mastodon/issues/20145 means /web/ paths don't work if myInstance is running an early v4 release, but /web/ needed for v3. */      if (ver3) {        sep = '/web/@'      } else {        sep = '/@'      }        if (pageOrigInstance != myInstance) {        user = user + '@' + pageOrigInstance;      }      return 'https://' + myInstanceURL + sep + user + extra;    }  }}newURL = mastodonURL(document.location, myInstance, myInstanceURL, ver3);/* The `if` is for XSS protection */if (newURL.match(/^https?:\/\//)) {   document.location = newURL;}})()
pronoiac commented 1 year ago

The generated bookmarklet, put through Marek Gibney's Bookmarklet Editor, then that long single line fed into Beautifier, yielded:

(function() {
    /* Mastodon switcher https://homepages.inf.ed.ac.uk/imurray2/code/mastodon.html */
    myInstance = 'mefi.social'; /* usernames are @ this string */
    myInstanceURL = 'Mefi.social'; /* Mastodon instance website with no https:// or trailing slash */
    ver3 = false; /* set to true if your instance runs Mastodon v3 */
    function getJsonObject(URL) {
      var req = new XMLHttpRequest();
      req.open('GET', URL, false);
      req.send(null);
      return JSON.parse(req.responseText);
    }

    function mastodonURL(origURL, myInstance, myInstanceURL, ver3) {
      /* If a fancy redirection didn't work, back it out */
      mm = origURL.href.match(/.*authorize_interaction\?uri=(.*)/);
      if (mm) {
        return decodeURIComponent(mm[1]);
      } /* Otherwise try to work out pieces of the URL */
      pathname = origURL.pathname;
      match = pathname.match(/^\/(@|users\/|web\/@)([^\/@]*)@?([^\/]*)(\/?.*)/);
      user = match[2];
      extra = match[4];
      if (extra.match(/^\/[0-9]+$/)) {
        /* post numbers need rewriting between instances, so can't just move URL pieces around */
        if (origURL.hostname == myInstanceURL) {
          /* Our home instance should already have a link on the page that we can follow. */
          datetimeEl = document.getElementsByClassName('detailed-status__datetime')[0];
          datetimeURL = new URL(datetimeEl.href);
          if (datetimeURL.hostname == origURL.hostname) {
            /* In Mastodon from about v4.0.2 datetime link stays on local server, and need to find link in pop-up menu.           It is beginning to feel like chasing webpage changes is a losing battle, and should be using an API to get JSON data instead? */
            datetimeEl.parentElement.parentElement.parentElement.parentElement.getElementsByClassName('detailed-status__action-bar-dropdown')[0].children[0].click();
            return document.getElementsByClassName('dropdown-menu__item')[0].childNodes[0].href;
          } else {
            return datetimeURL;
          }
        } else {
          /* Foreign instances won't know what link we want, so ask myInstance to rewrite the link */
          return 'https://' + myInstanceURL + '/authorize_interaction?uri=' + encodeURIComponent(origURL);
        }
      } else {
        /* URLs without post numbers, combine pieces of URL ourselves. */
        pageOrigInstance = match[3];
        if (!pageOrigInstance) {
          metas = document.getElementsByTagName('meta');
          for (i = 0; i < metas.length; i++) {
            if (metas[i].getAttribute('property') == 'profile:username') {
              pageOrigInstance = metas[i].getAttribute('content').split('@')[1];
            }
          }
        }
        pageOrigInstance = pageOrigInstance || origURL.hostname;
        if (origURL.hostname == myInstanceURL) {
          /* redirecting out. /web/@username/ always works, because in v4 it's the @username@domain.ext form that fails (the .ext gets stripped) */ /* Frustratingly the intance's actual URL might not be the same as the domain in the username.      Across Mastodon versions, hard to reliably pull instance URL out of the page. So have to make another request to be sure :-( */
          data = getJsonObject('https://' + origURL.hostname + '/api/v1/accounts/lookup?acct=' + user + '@' + pageOrigInstance);
          pageOrigInstanceURL = (new URL(data.url)).hostname || pageOrigInstance;
          return 'https://' + pageOrigInstanceURL + '/web/@' + user + extra;
        } else {
          /* redirecting in. Bug in v4 redirection https://github.com/mastodon/mastodon/issues/20145 means /web/ paths don't work if myInstance is running an early v4 release, but /web/ needed for v3. */
          if (ver3) {
            sep = '/web/@'
          } else {
            sep = '/@'
          }
          if (pageOrigInstance != myInstance) {
            user = user + '@' + pageOrigInstance;
          }
          return 'https://' + myInstanceURL + sep + user + extra;
        }
      }
    }
    newURL = mastodonURL(document.location, myInstance, myInstanceURL, ver3); /* The `if` is for XSS protection */
    if (newURL.match(/^https?:\/\//)) {
      document.location = newURL;
    }

I could probably recover the "original" formatting with some editing, but this worked well enough to make it easier to scrutinize.

pronoiac commented 1 year ago

From a conversation on lobste.rs:

let your_instance="masto.ai";

document.location=(
    "https://"
    + your_instance
    + "/authorize_interaction?uri="
    + encodeURIComponent(document.location)
)

I'm asking the author of the above generator, for their thoughts.

pronoiac commented 1 year ago

At times, the simpler bookmarklet hasn't worked in spots where "Instance changer" did, so I'm personally defaulting to the bigger one.

People have mentioned browser extensions for this, but I don't think that's a great idea:

This feels largely unnecessary, so I'm editing this out of the posted page, toggle_home_instance, though preserving it for context here.