您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Import/export your Brainscape decks from/into csv files without a Pro account.
// ==UserScript== // @name Brainscape Bene // @author LucunJi // @version 1.1.0 // @match https://www.brainscape.com/l/dashboard/*/decks* // @grant none // @require https://code.jquery.com/jquery-3.6.0.min.js // @require https://cdnjs.cloudflare.com/ajax/libs/PapaParse/5.3.2/papaparse.min.js // @license MIT // @description Import/export your Brainscape decks from/into csv files without a Pro account. // @namespace https://github.com/LucunJi // @homepageURL https://github.com/LucunJi/brainscape-bene // @supportURL https://github.com/LucunJi/brainscape-bene/issues // ==/UserScript== $(document).ready(function (event) { tryReplaceBtn(event); }); function tryReplaceBtn(event) { var timer = setInterval(function () { var importBtn = $('.import-deck.pro-required'); var exportBtn = $('.export-deck.pro-required'); if (importBtn.length > 0) { importBtn = importBtn.get(0); importBtn.replaceWith(importBtn = importBtn.cloneNode(true)); importBtn.classList.remove('pro-required'); importBtn.addEventListener('click', event => { importCSV(event); event.stopImmediatePropagation(); }); } if (exportBtn.length > 0) { exportBtn = exportBtn.get(0); exportBtn.replaceWith(exportBtn = exportBtn.cloneNode(true)); exportBtn.classList.remove('pro-required'); exportBtn.addEventListener('click', event => { exportCSV(event); event.stopImmediatePropagation(); }); } }, 50); event.stopImmediatePropagation(); } function importCSV(event) { // get deck title var packId = $(event.target).parents('.pack-decks-section[data-pack-id]').attr('data-pack-id'); var deckName = prompt('Enter the title of your new deck below'); if (deckName === null) return; if (deckName.trim() === "") { alert('The title cannot be an empty string'); return; } // get input file var fileSelector = document.createElement('input'); fileSelector.type = 'file'; fileSelector.accept = '.csv'; fileSelector.onchange = function (event) { if (event.target.files.length < 1) return; var reader = new FileReader(); reader.onload = function () { var parsedCSV = Papa.parse(reader.result); if (parsedCSV['errors'].length > 0) { alert(`The csv file is not illegal: ${parsedCSV['errors'][0]['message']}`); return; } // convert to params var data = new FormData(); var timestamp = Date.now() for (var entry of parsedCSV['data']) if (entry.length >= 2) { data.append(`deck[cards_attributes][${timestamp}][reveal]`, 'false'); data.append(`deck[cards_attributes][${timestamp}][question]`, entry[0]); data.append(`deck[cards_attributes][${timestamp}][answer]`, entry[1]); timestamp++; } // send post request fetch(`https://www.brainscape.com/api/decks?packID=${packId}`, { method: 'POST', headers: { "Content-Type": "application/json" }, body: JSON.stringify({ content_type: 'text', name: deckName }) }) .then(res => res.json()) .then(res => fetch(`https://www.brainscape.com/decks/${res['deckID']}/cards/quick_add`, { method: 'POST', headers: { 'x-csrf-token': $("[name=csrf-token]").attr('content') }, body: data }) ) .then(response => location.reload()) .catch(err => alert(`failed to import new deck ${err}`)); }; reader.readAsText(event.target.files[0]); }; fileSelector.click(); } function exportCSV(event) { var packId = $(event.target).parents('.pack-decks-section[data-pack-id]').attr('data-pack-id'); var deckId = $(event.target).parents('.deck-row[id]').attr('id'); var deckName = $(event.target).parents('.deck-name').html(); fetch(`https://www.brainscape.com/api/packs/${packId}/decks/${deckId}/preview`, { method: 'GET', }) .then(res => res.json()) .then(res => { var csvData = res['cards'].map(card => [card['question'], card['answer'], card['questionHtml'], card['answerHtml'], card['level']] ); var fileDownloader = document.createElement('a'); fileDownloader.setAttribute('href', 'data:text/plain;charset=utf-8, ' + encodeURIComponent(Papa.unparse(csvData))); fileDownloader.setAttribute('download', res['deck']['name'] + '.csv'); fileDownloader.click(); }) }