Last active
March 6, 2024 12:22
-
-
Save yuki2021/7c387f6f4f7fd3442f38e36983b48cd5 to your computer and use it in GitHub Desktop.
TampermonkeyでScrapboxからはてなブログに投稿するスクリプト
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// ==UserScript== | |
// @name Scrapbox to Hatena Blog Post | |
// @namespace http://tampermonkey.net/ | |
// @version 0.4 | |
// @description Scrapboxのページデータを取得してはてなブログに投稿するスクリプト | |
// @author yuki2021 | |
// @match https://scrapbox.io/* | |
// @grant GM_xmlhttpRequest | |
// ==/UserScript== | |
// ユーザーIDとAPIキー | |
const userId = '{{はてなのuser id}}'; | |
const apiKey = '{{はてなブログのAPI Key}}'; | |
const basicAuthUrl = 'https://blog.hatena.ne.jp/{{はてなのuser id}}/{{はてなのベースURL}}/atom/entry'; | |
// Scrapboxのページデータを取得 | |
async function fetchScrapboxPage(project, title) { | |
try { | |
const url = `https://scrapbox.io/api/pages/${project}/${title}/text`; | |
const response = await fetch(url); | |
return response.ok ? response.text() : null; | |
} catch (error) { | |
console.error('Error fetching Scrapbox page:', error); | |
return null; | |
} | |
} | |
// GM_xmlhttpRequestではてなブログに投稿する | |
function postToHatenaBlog(postData) { | |
// Basic認証のためのユーザーIDとAPIキーをBase64エンコード | |
const authHeader = `Basic ${btoa(`${userId}:${apiKey}`)}`; | |
// GM_xmlhttpRequestでPOSTリクエストを送信 | |
GM_xmlhttpRequest({ | |
method: 'POST', | |
url: basicAuthUrl, | |
headers: { | |
"Authorization": authHeader, | |
"Content-type": "application/xml", | |
}, | |
data: postData, | |
onload: function(response) { | |
console.log(response.responseText); | |
alert('投稿に成功しました'); | |
}, | |
onerror: function(response) { | |
console.log(response.responseText); | |
alert('投稿に失敗しました'); | |
} | |
}); | |
} | |
// ポストデータを整形する処理 | |
function createBlogPostXml(title, pageData, isDraft) { | |
const updatedTime = new Date().toISOString(); | |
// isDraftがtrueの場合は下書きとして投稿 | |
const draft = isDraft === '1' ? 'yes' : 'no'; | |
console.log('draft:', draft); | |
// pageDataから'[と]'を削除 | |
pageData = pageData.replace(/\[|\]/g, ''); | |
// はてなブログの投稿データを整形 | |
return `<?xml version="1.0" encoding="utf-8"?> | |
<entry xmlns="http://www.w3.org/2005/Atom" | |
xmlns:app="http://www.w3.org/2007/app"> | |
<title>${title}</title> | |
<author><name>${userId}</name></author> | |
<content type="text/plain">${pageData}</content> | |
<updated>${updatedTime}</updated> | |
<app:control> | |
<app:draft>${draft}</app:draft> | |
</app:control> | |
</entry>`; | |
} | |
// contentの一行目をタイトルとして取得 | |
function getFirstLine(content) { | |
// contentの一行目をタイトルとして取得 | |
const firstLine = content.split('\n')[0]; | |
// contentの一行目はタイトルとして使うため削除 | |
const updatedContent = content.replace(firstLine + '\n', ''); | |
return [firstLine, updatedContent]; | |
} | |
// optoinキーとQキーが押されたときの処理 | |
async function handleKeyPress(event) { | |
if (event.altKey && event.code === 'KeyQ') { | |
event.preventDefault(); // イベントのデフォルトの動作をキャンセル | |
// 現在のページのURLを取得 | |
const urlMatch = window.location.href.match(/^https:\/\/scrapbox.io\/([^\/]+)\/(.+)$/); | |
if (urlMatch) { | |
const [_, project, title] = urlMatch; | |
// pageDataGet関数でページデータを取得 | |
const content = await fetchScrapboxPage(project, title); | |
// 取得したデータが存在する場合はデータを整形して投稿 | |
if (content) { | |
// contentの一行目をタイトルとして取得 | |
const [firstLine, updatedContent] = getFirstLine(content); | |
// titleを尋ねるアラートを表示 | |
const postTitle = prompt('タイトルを入力してください', firstLine); | |
// promptがキャンセルされた場合は処理を中断 | |
if (!postTitle) return; | |
// 下書きかどうかを尋ねるアラートを表示 | |
const isDraft = prompt('下書き保存しますか? Yes:1, No:0', '1'); | |
// promptがキャンセルされた場合は処理を中断 | |
if (!isDraft) return; | |
const postXml = createBlogPostXml(postTitle, updatedContent, isDraft); | |
postToHatenaBlog(postXml); | |
} else { | |
console.log("Scrapboxのページデータが取得できませんでした。"); | |
} | |
} else { | |
console.log("ScrapboxのページURLの形式が正しくありません。"); | |
} | |
} | |
} | |
document.addEventListener('keydown', handleKeyPress, true); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment