Blueskyの投稿をマストドンでシェアするためのブックマークレットのコード

関連記事:見ているwebページの文章をマストドンでシェアするためのブックマークレット

Blueskyの投稿をマストドンでシェアするためのブックマークレットのコード

javascript:(function(){function formatDate(inputDate){const date=new Date(inputDate);const year=date.getFullYear();const month=date.getMonth()+1;const day=date.getDate();const hours=date.getHours();const minutes=date.getMinutes();return `${year}年${month}月${day}日 ${hours}:${minutes.toString().padStart(2,'0')}`;};function getTextBeforeEllipsis(text){const ellipsisIndex=text.indexOf('[…]');return ellipsisIndex!==-1?text.slice(0,ellipsisIndex):text;};if(document.location.hostname!=='bsky.app'){alert('このページはBlueskyではありません');return;};const check1=document.querySelector('meta[name="article:published_time"]');const check2=document.querySelector('meta[name="description"]');const titleText=document.title;const regex=/:\s?"(.+)(?=" — Bluesky)/;const match=titleText.match(regex);if(check1===null||check2===null||match===null){alert('blueskyの投稿を開いたらリロードしてください');return;};const check20=getTextBeforeEllipsis(match[1].replace(/\s+/g,'')).slice(0,300);const check21=getTextBeforeEllipsis(check2.content.trim().replace(/\s+/g,'')).slice(0,300);if(check1&&match&&check20===check21){let user=':bluesky: '+document.querySelector('meta[property="og:title"]').content;let date=check1.content;let text=check2.content;text=encodeURIComponent('\n'+formatDate(date)+'\n"\n'+text+'\n"\n');window.open('https://サーバーのドメイン/share?text='+user+text+encodeURIComponent(document.location.href));}else{alert('blueskyの投稿を開いてリロードしてください\n\n'+check20+'\n\n旧:\n'+check21);};})();

整形すると次のような感じ。

javascript: (function() {
    function formatDate(inputDate) {
        const date = new Date(inputDate);
        const year = date.getFullYear();
        const month = date.getMonth() + 1;
        const day = date.getDate();
        const hours = date.getHours();
        const minutes = date.getMinutes();
        return `${year}年${month}月${day}日 ${hours}:${minutes.toString().padStart(2, '0')}`;
    }

    function getTextBeforeEllipsis(text) {
        const ellipsisIndex = text.indexOf('[…]');
        return ellipsisIndex !== -1 ? text.slice(0, ellipsisIndex) : text;
    }

    if (document.location.hostname !== 'bsky.app') {
        alert('このページはBlueskyではありません');
        return;
    }

    const check1 = document.querySelector('meta[name="article:published_time"]');
    const check2 = document.querySelector('meta[name="description"]');
    const titleText = document.title;
    const regex = /:\s?"(.+)(?=" — Bluesky)/;
    const match = titleText.match(regex);

    if (check1 === null || check2 === null || match === null) {
      alert('blueskyの投稿を開いたらリロードしてください');
      return;
    }

    const check20 = getTextBeforeEllipsis(match[1].replace(/\s+/g, '')).slice(0, 300);
    const check21 = getTextBeforeEllipsis(check2.content.trim().replace(/\s+/g, '')).slice(0, 300);

    if (check1 && match && check20 === check21) {
        let user = ':bluesky: ' + document.querySelector('meta[property="og:title"]').content;
        let date = check1.content;
        let text = check2.content;
        text = encodeURIComponent('\n' + formatDate(date) + '\n"\n' + text + '\n"\n');
        window.open('https://サーバーのドメイン/share?text=' + user + text + encodeURIComponent(document.location.href));
    } else {
        alert('blueskyの投稿を開いてリロードしてください\n\n' + check20 + '\n\n旧:\n' + check21);
    }
})();

 サーバーのドメインを入力すれば使える。
 好みでBlueskyのアイコンが表示されるようにしているけれど、このコードはマストドンのサーバーによって異なるらしいから確認が必要。
 好みで投稿時刻を入れてある。
 エラーがあった場合に無反応だと分かりにくいのでアラートを入れるようにした。「blueskyの投稿を開いてリロードしてください」は投稿を開いた後にリロードしないと、前に見ていた投稿のテキストが選択されてシェアするような間違いが起こるから。間違いが起こってもエラーが出なかったのだけど、間違いが起こらないように見たいる投稿のtitleとシェアされるテキストを比較して、一致しなかったら投稿フォーム入力せずにエラーメッセージを出すようにした。マストドンのミラーリング投稿などで全文が表示されずに省略されている場合は省略記号までを比較するようにしてある。
 引用部分をダブルクォーテーション""で囲んでいるのは私の好み。引用文の前後で改行したのも私の好み。
 引用後に、テキストを丸々シェアするか、一部を削除するかは使う人の好み。

 いろいろな投稿で機能するようにバグをできるだけ減らしたけれど、文章に特殊なコードがあったりするとエラーになるかもしれない。無反応だったらエラーになってる。とりあえず、ブラウザを起動してウェブページを全く表示してない状態からBlueskyのユーザータイムラインを開くと無反応だったような気がする。リロードしても無反応(直した)。そもそも投稿じゃないから、反応するように修正してもエラーメッセージを出すだけ。ユーザータイムラインなどの後に投稿を開いた後は、ユーザータイムいラインのコードがブラウザ内に残っていて投稿のコードになっていないようなので、エラーメッセージを出すはず。リロードした後なら投稿フォームに入力されるはず。Blueskyのページ以外で使おうとしても無反応。このバグは修正したつもりだったけれど…(直した)。

 Blueskyでハッシュタグタイムラインを開いてリロードした後に投稿を選んで実行したときも無反応。(直した

 Blueskyの投稿はリロードしないとメモリー内のコード('meta[name="description"]')が古いままだから、更新されているtitleタグと最初から300文字を比較して一致していないとアラートを出してマストドンの投稿フォームに入力されないようにしてあるのだけど、リロードしてコード('meta[name="description"]')が表示されている投稿に一致するようになってもtitleと異なることがあるらしい。今のところ、投稿文の最後がURLの場合に何度も見られる(投稿文の最後がURLでない場合も生ずることがあり、原因は不明URLを含む投稿では、titleタグ内のURLが省略されてhttpsが削除されることが多いので、descriptionと一致しないので使えない。また、投稿が引用リポストの形式では、descriptionに引用のあることを示す文[contains quote post or other embedded content]があり、titleタグにはないので、やはり使えない。。その場合は、何度リロードしてもエラーメッセージが出るのだが、比較文字列を300文字ではなく、10文字くらいにすれば、投稿フォームに入力されるようになる。

コメント