Skip to content

Instantly share code, notes, and snippets.

@taktamur
Created August 14, 2024 11:39
Show Gist options
  • Save taktamur/0a54a4d57af5080fc7878e4a618e6922 to your computer and use it in GitHub Desktop.
Save taktamur/0a54a4d57af5080fc7878e4a618e6922 to your computer and use it in GitHub Desktop.
webページの内容をGPTのAPIを使って要約するuserscript
const API_KEY = 'xxxxxxxx'; // ここにAPIキーを入れる
// ==UserScript==
// @name GPT Summary Context Menu
// @namespace http://tampermonkey.net/
// @version 1.2
// @description Trigger GPT summary via context menu
// @author taktamur
// @match *://*/*
// @grant none
// @run-at context-menu
// ==/UserScript==
// run-at でコンテキストメニュー起動からの起動としている
(async function() {
'use strict';
// 要約結果を表示するエリアを作成
const summaryDiv = document.createElement('div');
summaryDiv.style.position = 'fixed';
summaryDiv.style.top = '50px';
summaryDiv.style.right = '10px';
summaryDiv.style.width = '300px';
summaryDiv.style.maxHeight = '400px';
summaryDiv.style.overflowY = 'auto';
summaryDiv.style.backgroundColor = '#f9f9f9';
summaryDiv.style.border = '1px solid #ddd';
summaryDiv.style.padding = '10px';
summaryDiv.style.display = 'none';
summaryDiv.style.zIndex = 1000;
// 閉じるボタンを作成
const closeButton = document.createElement('button');
closeButton.textContent = '閉じる';
closeButton.style.display = 'block';
closeButton.style.marginTop = '10px';
closeButton.style.backgroundColor = '#f44336';
closeButton.style.color = 'white';
closeButton.style.border = 'none';
closeButton.style.padding = '5px';
closeButton.style.cursor = 'pointer';
// コピーするボタンを作成
const copyButton = document.createElement('button');
copyButton.textContent = 'コピー';
copyButton.style.display = 'block';
copyButton.style.marginTop = '10px';
copyButton.style.backgroundColor = '#008CBA';
copyButton.style.color = 'white';
copyButton.style.border = 'none';
copyButton.style.padding = '5px';
copyButton.style.cursor = 'pointer';
summaryDiv.appendChild(copyButton);
summaryDiv.appendChild(closeButton);
document.body.appendChild(summaryDiv);
// GPT APIを使用して要約を取得する関数
async function getSummary(article) {
console.log(article.length);
const apiUrl = "https://api.openai.com/v1/chat/completions";
const requestBody = {
model: "gpt-4o-mini",
messages: [
{
role: "system",
content:
"これからwebページのテキストを投げます。その内容を箇条書きで要約してください。" +
"要約は箇条書きで、5項目程度としてください\n",
},
{
role: "user",
content: article,
},
],
max_tokens: 1000,
};
try {
const response = await fetch(apiUrl, {
method: "POST",
headers: {
Authorization: `Bearer ${API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify(requestBody),
});
if (!response.ok) {
throw new Error(`HTTP error! status: ${JSON.stringify(response.status)}`);
}
const data = await response.json();
const summary = data.choices[0].message.content.trim();
return summary;
} catch (error) {
console.error("Error summarizing text:", error);
throw error;
}
}
// コンテキストメニューに項目を追加
document.addEventListener('click', async () => {
});
// 閉じるボタンの処理
closeButton.addEventListener('click', () => {
summaryDiv.style.display = 'none';
});
// コピーするボタンの処理
copyButton.addEventListener('click', () => {
const textToCopy = summaryDiv.innerText.replace('コピー閉じる', '').trim(); // 要約テキストを取得し、不要なボタンテキストを削除
navigator.clipboard.writeText(textToCopy).then(() => {
console.log('要約がコピーされました');
}).catch(err => {
console.error('コピーに失敗しました: ', err);
});
});
const pageContent = document.body.innerText; // ページ全体のテキストを取得
summaryDiv.textContent = '要約を取得中...';
summaryDiv.style.display = 'block';
try {
const summary = await getSummary(pageContent);
summaryDiv.innerHTML = summary.replace(/\n/g, '<br>');
summaryDiv.appendChild(copyButton); // コピーするボタンを再度追加
summaryDiv.appendChild(closeButton); // 閉じるボタンを再度追加
} catch (error) {
summaryDiv.textContent = '要約の取得に失敗しました。';
summaryDiv.appendChild(copyButton); // エラーの場合もコピーするボタンを追加
summaryDiv.appendChild(closeButton); // エラーの場合も閉じるボタンを追加
}
})();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment