Misskeyに記事のURLをPocketへ追加するボタンを付けるUserScript
Misskeyの記事のURLをPocketサービスへ送信するボタンを付けるUserScriptです。
Google KeepはAPI非公開、EvernoteはAPIがありますがあまりUserScript向きではないようでした。
仮想DOM生成時に実行されるため、少し重くなるかもしれません。
正常に送信が行われると緑色になります。(API送信時に確認のため色を変えているため、Pocketへ保存されている記事の色が変わるわけではありません。)
準備
Pocketに登録し、API利用のためカスタマーキーとアクセストークンを取得します。
上記サイトを参考にして取得しました。
UserScriptコード
PCブラウザ, Android, iOSでのそれぞれの導入方法はこちらの記事を参照ください。
下記のうち@match
のURLを利用するMisskeyのサーバーへ、consumer_key
、access_token
を取得したPocket APIのカスタマーキーとアクセストークンへ書き換えてください。
// ==UserScript== // @name Save URL to Pocket // @namespace @[email protected] // @version 1.0 // @description Saves the URL to Pocket when the specified button is clicked // @match https://nijimiss.moe/* // @run-at document-idle // @grant GM_xmlhttpRequest // ==/UserScript== // ボタンを生成する関数 function createPocketButton(article) { const footer = article.querySelector('footer'); if (footer) { const pocketButton = document.createElement('button'); pocketButton.classList.add('_button', 'xviCy', 'pocket-button'); pocketButton.style.height = '32px'; pocketButton.style.borderRadius = '6px'; const pocketIcon = document.createElement('img'); pocketIcon.setAttribute('src', 'https://blog.estampie.work/pocket.svg'); pocketIcon.setAttribute('width', '16'); pocketIcon.setAttribute('height', '16'); pocketIcon.classList.add('xeJ4G', 'x5kTm', 'x9Io4'); pocketButton.appendChild(pocketIcon); pocketButton.addEventListener('click', () => { const noteElement = article.querySelector('a[href^="/notes/"]'); if (noteElement) { const notePath = noteElement.getAttribute('href'); const fullURL = 'http://nijimiss.moe' + notePath; GM_xmlhttpRequest({ method: 'POST', url: 'https://getpocket.com/v3/add', headers: { 'Content-Type': 'application/json; charset=UTF-8', 'X-Accept': 'application/json', }, data: JSON.stringify({ url: fullURL, consumer_key: 'カスタマーキー', access_token: 'アクセストークン', }), onload: function(response) { if (response.status >= 200 && response.status < 300) { // API送信が成功した時の処理 pocketButton.style.backgroundColor = '#77b58c'; // ボタンの背景色を緑に変える } else { // API送信が失敗した時の処理 pocketButton.style.backgroundColor = '#FF0000'; // ボタンの背景色を赤に変える } } }); } }); footer.appendChild(pocketButton); } } // DOMが変更されたときに実行される関数 const observerCallback = function(mutationsList, observer) { for(let mutation of mutationsList) { if (mutation.type === 'childList') { const articles = document.querySelectorAll('article:not(.has-pocket-button)'); articles.forEach(article => { createPocketButton(article); article.classList.add('has-pocket-button'); }); } } }; // MutationObserverを設定 const observer = new MutationObserver(observerCallback); observer.observe(document, { childList: true, subtree: true }); // 初期ページの記事にボタンを追加 const initialArticles = document.querySelectorAll('article'); initialArticles.forEach(article => { createPocketButton(article); article.classList.add('has-pocket-button'); });
補足
下記カスタムCSSを併用すると二行にならずに済むかもしれません。数値は任意で変更してください。
.xviCy:not(:last-child) { margin-right: 14px !important; }