Created
February 9, 2025 21:19
-
-
Save siveryt/f5d17cfc114a64679dc33f67beb9a472 to your computer and use it in GitHub Desktop.
Buffl Exporter
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
const url = "https://api.buffl.co/api/cardsets/" + window.location.pathname.split("/")[3] + "/editable"; | |
const headers = { | |
"Accept": "application/json, text/plain, */*", | |
"Authorization": localStorage.getItem("JWT_TOKEN") | |
}; | |
// Fetch the data | |
fetch(url, { method: 'GET', headers: headers }) | |
.then(response => { | |
if (!response.ok) { | |
throw new Error('Network response was not ok ' + response.statusText); | |
} | |
return response.json(); // Parse the JSON from the response | |
}) | |
.then((data /** @type {BufflExport} */) => { | |
const choice = prompt("Do you want the full object, a simplified version, or a CSV table? (full/simplified/csv)"); | |
let fileextension = '.json'; | |
let filename = data.cardSet.title; | |
let blob = new Blob([JSON.stringify(data, null, 2)], { type: 'application/json' }); | |
if (choice === 'simplified') { | |
data = { | |
title: data.cardSet.title, | |
cards: data.cardSet.cards.map(card => ({ | |
question: card.front.content[0].content[0].text, | |
answer: card.back.content[0].content[0].text | |
})) | |
}; | |
blob = new Blob([JSON.stringify(data, null, 2)], { type: 'application/json' }); | |
} else if (choice === 'csv') { | |
const csvRows = [ | |
['Question', 'Answer'], | |
...data.cardSet.cards.map(card => [card.front.content[0].content[0].text, card.back.content[0].content[0].text]) | |
]; | |
const csvContent = csvRows.map(e => e.join(";")).join("\n"); | |
data = csvContent; | |
fileextension = '.csv'; | |
blob = new Blob([data], { type: 'text/csv' }); | |
} | |
// Create a blob from the JSON data | |
const url = window.URL.createObjectURL(blob); | |
// Create a link element | |
const a = document.createElement('a'); | |
a.href = url; | |
a.download = filename + fileextension; // Set the file name | |
document.body.appendChild(a); | |
a.click(); // Programmatically click the link to trigger the download | |
a.remove(); // Remove the link from the document | |
window.URL.revokeObjectURL(url); // Clean up the URL object | |
}) | |
.catch(error => { | |
console.error('There was a problem with the fetch operation:', error); | |
}); | |
// TYPEDEF | |
/** | |
* @typedef {Object} BufflExport | |
* @property {CardSet} cardSet | |
* @property {ACL} acl | |
*/ | |
/** | |
* @typedef {Object} ACL | |
* @property {boolean} isStudent | |
* @property {boolean} isEditing | |
* @property {boolean} isOwner | |
*/ | |
/** | |
* @typedef {Object} CardSet | |
* @property {string} title | |
* @property {string} owner | |
* @property {Course} course | |
* @property {string} type | |
* @property {boolean} isProgressing | |
* @property {number} card_inserts | |
* @property {number} card_updates | |
* @property {number} card_deletions | |
* @property {Card[]} cards | |
* @property {boolean} locked | |
* @property {boolean} preventDelete | |
* @property {boolean} publishedForSale | |
* @property {boolean} draft | |
* @property {boolean} deleted | |
* @property {Member[]} members | |
* @property {Date} updatedAt | |
* @property {Date} createdAt | |
* @property {ID} id | |
*/ | |
/** | |
* @typedef {Object} Card | |
* @property {Config} hotspotConfig | |
* @property {Config} mcConfig | |
* @property {Config} sortConfig | |
* @property {GapConfig} gapConfig | |
* @property {CloudConfig} cloudConfig | |
* @property {Back} front | |
* @property {Back} back | |
* @property {string} answer_content | |
* @property {string} typeVersion | |
* @property {null} answer_image | |
* @property {null} answer_list | |
* @property {string} question_content | |
* @property {null} question_image | |
* @property {null} question_list | |
* @property {number} position | |
* @property {number} sec_position | |
* @property {number} answer_alignement | |
* @property {number} question_alignement | |
* @property {boolean} unActive | |
* @property {LegacyData} legacyData | |
* @property {ID} cardset | |
* @property {string} id | |
* @property {Date} [createdAt] | |
* @property {Date} [updatedAt] | |
*/ | |
/** | |
* @typedef {Object} Back | |
* @property {BackType} type | |
* @property {Attrs} attrs | |
* @property {BackContent[]} content | |
*/ | |
/** | |
* @typedef {Object} Attrs | |
* @property {number} version | |
*/ | |
/** | |
* @typedef {Object} BackContent | |
* @property {FluffyType} type | |
* @property {ContentContent[]} content | |
*/ | |
/** | |
* @typedef {Object} ContentContent | |
* @property {PurpleType} type | |
* @property {string} text | |
*/ | |
/** | |
* @enum {string} | |
*/ | |
const PurpleType = { | |
Text: "text", | |
}; | |
/** | |
* @enum {string} | |
*/ | |
const FluffyType = { | |
Paragraph: "paragraph", | |
}; | |
/** | |
* @enum {string} | |
*/ | |
const BackType = { | |
Doc: "doc", | |
}; | |
/** | |
* @enum {string} | |
*/ | |
const ID = { | |
The67A8C10Fd0D4D261258E3Ea0: "67a8c10fd0d4d261258e3ea0", | |
}; | |
/** | |
* @typedef {Object} CloudConfig | |
* @property {any[]} answerFragments | |
* @property {any[]} falseOptions | |
*/ | |
/** | |
* @typedef {Object} GapConfig | |
* @property {FillMethod} fillMethod | |
* @property {boolean} caseSensitive | |
* @property {any[]} answerFragments | |
* @property {any[]} falseOptions | |
*/ | |
/** | |
* @enum {string} | |
*/ | |
const FillMethod = { | |
FreeText: "FREE_TEXT", | |
}; | |
/** | |
* @typedef {Object} Config | |
* @property {any[]} options | |
*/ | |
/** | |
* @typedef {Object} LegacyData | |
* @property {string} question_content | |
* @property {string} answer_content | |
*/ | |
/** | |
* @typedef {Object} Course | |
* @property {string} owner | |
* @property {any[]} editors | |
* @property {string} id | |
*/ | |
/** | |
* @typedef {Object} Member | |
* @property {Preview} preview | |
* @property {string} role | |
* @property {string} member | |
* @property {string} type | |
* @property {string} id | |
*/ | |
/** | |
* @typedef {Object} Preview | |
* @property {string} email | |
* @property {string} firstName | |
* @property {string} lastName | |
*/ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
You can add it to your Bookmark, when you copy the code over to my Bookmarklet Generator :)