// ==UserScript== // @name Twitter Detail Page Save to Notion // @namespace http://tampermonkey.net/ // @version 0.1 // @description Extract images, tweets from Twitter detail page // @author CherryLover // @match https://twitter.com/* // @grant GM_xmlhttpRequest // @grant GM_setValue // @grant GM_getValue // @license MIT // @downloadURL none // ==/UserScript== (function() { 'use strict'; function extractImages() { // const className = "css-175oi2r r-1pi2tsx r-13qz1uu r-eqz5dr"; const className = 'css-175oi2r r-9aw3ui r-1s2bzr4'; let images = []; let elements = document.getElementsByClassName(className); if (elements.length <= 0) { return images; } for (let i = 0; i < elements.length; i++) { const target = elements[i]; // 查找所有属性:data-testid 为 "tweetPhoto" 的 div 元素 let divElements = target.querySelectorAll('div[data-testid=\'tweetPhoto\']'); console.log('find ' + divElements.length + ' divs'); for (let j = 0; j < divElements.length; j++) { const innerDiv = divElements[j]; let imgElements = innerDiv.querySelectorAll('img'); console.log('find ' + imgElements.length + ' imgs'); imgElements.forEach((img) => { let imgData = { src: img.src, alt: img.alt }; let imgExist = images.find(element => element.src === imgData.src); if (!imgExist) { images.push(imgData); } }); } } return images; } function getTwitterContent() { const className = 'css-175oi2r r-1s2bzr4'; // 获取所有指定类的div元素 let elements = document.getElementsByClassName(className); let text = ''; // 遍历所有获取到的元素 if (elements.length <= 0) { return text; } console.log('all element size ', elements.length); for (let i = 0; i < elements.length; i++) { // console.log("element ", i, " ", elements[i].innerText); let children = elements[i].childNodes; for (let j = 0; j < children.length; j++) { const attrDataTestId = children[j].getAttribute('data-testid'); if (attrDataTestId === 'tweetText') { const tweetText = parseUrlAndText(children[j].childNodes); // const tweetText = children[j].innerText; console.log('tweet text', tweetText); text += tweetText; } } } return text; } function parseUrlAndText(elements) { let text = ''; for (let i = 0; i < elements.length; i++) { const element = elements[i]; if (element.nodeName === 'A') { text += element.href + '\n'; } else { text += element.textContent; } } return text; } function showResults(token, databaseId) { let currentUrl = window.location.href; console.log('当前页面的URL是: ' + currentUrl); // 使用方法 let allText = ''; allText = getTwitterContent(); const imgs = extractImages(); const header = { 'Content-Type': 'application/json', 'Authorization': `Bearer ${token}`, 'Notion-Version': '2022-02-22' }; let finalText = allText + '\n\n'; // for (var i = 0; i < imgs.length; i++) { // finalText += 'img: ' + imgs[i].src + '\n'; // } console.log('token: ', token); console.log('databaseId: ', databaseId); // alert("Data has been sent to server"); // title 为 finalText 的前 10 个字符 let title = ''; if (finalText.length > 10) { title = finalText.substring(0, 10); } else { title = finalText.replaceAll('\n', ''); if (title.length === 0) { title = 'No title'; } } const requestUrl = `https://api.notion.com/v1/pages/`; const body = { 'parent': { 'database_id': databaseId }, 'properties': { 'Name': { 'title': [ { 'text': { 'content': title } } ] }, 'original': { 'url': currentUrl } }, 'children': [ { 'object': 'block', 'type': 'paragraph', 'paragraph': { 'rich_text': [ { 'type': 'text', 'text': { 'content': finalText } } ] } } ] }; imgs.forEach((img) => { // 向正文中添加图片 及 alt // body.properties.Content.text.push({ // 'image': { // 'type': 'external', // 'external': { // 'url': img.src // } // } // }); body.children.push({ 'object': 'block', 'type': 'embed', 'embed': { 'caption': [ { 'type': 'text', 'text': { 'content': img.alt } } ], 'url': img.src } }); }); console.log('request body ' + JSON.stringify(body)); GM_xmlhttpRequest({ method: 'POST', url: requestUrl, headers: header, data: JSON.stringify(body), onload: function(response) { console.log('Response: ', response); alert('Data has been sent to server'); }, onerror: function(response) { console.log('Error: ', response); alert('Error: ' + response); } }); // GM_xmlhttpRequest({ // method: "POST", // url: `https://${domain}/api/v1/memo`, // headers: header, // data: JSON.stringify({ // content: finalText, // }), // onload: function(response) { // console.log("Response: ", response); // alert("Data has been sent to server"); // }, // onerror: function(response) { // console.log("Error: ", response); // alert("Error: " + response); // } // }); } // Create input for domain let databaseIdInput = document.createElement('input'); databaseIdInput.placeholder = 'Database Id'; databaseIdInput.style.position = 'fixed'; databaseIdInput.style.bottom = '50px'; databaseIdInput.style.left = '10px'; databaseIdInput.style.zIndex = '9999'; // Create input for accessToken let tokenInput = document.createElement('input'); tokenInput.placeholder = 'Integrations Secret'; tokenInput.style.position = 'fixed'; tokenInput.style.bottom = '30px'; tokenInput.style.left = '10px'; tokenInput.style.zIndex = '9999'; // Append inputs to body document.body.appendChild(databaseIdInput); document.body.appendChild(tokenInput); // Create button let button = document.createElement('button'); button.textContent = '保存到 Notion'; button.style.position = 'fixed'; button.style.bottom = '10px'; button.style.left = '10px'; button.style.zIndex = '9999'; button.onclick = function() { const currentUrl = window.location.href; // 判断当前页面是否是推特详情页 if (!currentUrl.includes('status')) { alert('请进入具体推文详情页面后再点击'); return; } let dbId = ''; let token = ''; if (databaseIdInput.style.display === 'block') { dbId = databaseIdInput.value; } else { dbId = GM_getValue('databaseId', ''); } if (tokenInput.style.display === 'block') { token = tokenInput.value; } else { token = GM_getValue('accessToken', ''); } if (!dbId || !token) { alert('请配置 Notion 数据库 ID 和 Integrations Secret'); databaseIdInput.style.display = 'block'; tokenInput.style.display = 'block'; return; } GM_setValue('databaseId', dbId); GM_setValue('accessToken', token); databaseIdInput.style.display = 'none'; tokenInput.style.display = 'none'; showResults(token, dbId); }; // Append button to body document.body.appendChild(button); // Initially hide the inputs databaseIdInput.style.display = 'none'; tokenInput.style.display = 'none'; var settingShow = false; function toggleSettings() { settingShow = !settingShow; if (settingShow) { databaseIdInput.style.display = 'block'; tokenInput.style.display = 'block'; const cDatabaseId = GM_getValue('databaseId', ''); const cToken = GM_getValue('accessToken', ''); databaseIdInput.value = cDatabaseId; tokenInput.value = cToken; databaseIdInput.focus(); } else { GM_setValue('databaseId', databaseIdInput.value); GM_setValue('accessToken', tokenInput.value); databaseIdInput.style.display = 'none'; tokenInput.style.display = 'none'; } } window.addEventListener('keydown', function(event) { if (event.key === 'F9') { toggleSettings(); } }); })();