init
89
backend/lib/anki.js
Normal file
@@ -0,0 +1,89 @@
|
||||
import { readFile } from 'fs/promises'
|
||||
import { open } from 'sqlite'
|
||||
import sqlite3 from 'sqlite3'
|
||||
import AdmZip from 'adm-zip'
|
||||
|
||||
// database structure: https://github.com/ankidroid/Anki-Android/wiki/Database-Structure
|
||||
// python example: https://github.com/patarapolw/ankisync2
|
||||
// old js example: https://github.com/nornagon/mkanki/blob/master/index.js
|
||||
|
||||
// to create a zip file
|
||||
// const zip = new AdmZip()
|
||||
// zip.addLocalFolder('./folder_to_zip')
|
||||
// zip.writeZip('./output.zip')
|
||||
|
||||
class Deck {
|
||||
|
||||
/**
|
||||
*
|
||||
* @param info ID of internal deck, or filename or anki export
|
||||
* @param process whether or not this is an external anki export to process
|
||||
*/
|
||||
constructor(info, process) {
|
||||
// pull out variables
|
||||
this.notes = null // this is what is edited; may create multiple cards
|
||||
this.media = null // image and audio files attached to cards/notes
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads an internal deck
|
||||
*/
|
||||
async load(id) {
|
||||
// open database
|
||||
// open media files
|
||||
}
|
||||
|
||||
/**
|
||||
* Processes an anki export for internal use. Currently only supports
|
||||
* .apkg files. In the future, may support:
|
||||
* colpkg
|
||||
* txt (notes)
|
||||
* txt (cards)
|
||||
*
|
||||
* @param filename path of file to process
|
||||
*/
|
||||
async process(filename) {
|
||||
return await this.processApkg(filename)
|
||||
}
|
||||
|
||||
/**
|
||||
* Processes a .apkg file into a database
|
||||
*
|
||||
* @param filename name of file to open and process
|
||||
*/
|
||||
async processApkg(filename) {
|
||||
// error handling
|
||||
if (!filename) throw new Error('Must specify a .apkg filename')
|
||||
|
||||
// setup
|
||||
let uuid = crypto.randomUUID()
|
||||
let location = `../data/anki/decks/${uuid}/`
|
||||
|
||||
// make the resource folder if it does not exist already
|
||||
// let resource = ''
|
||||
// if (!fs.existsSync(resource)) fs.mkdirSync(resource, { recursive: true })
|
||||
|
||||
// extract zip
|
||||
// https://stuk.github.io/jszip/documentation/howto/read_zip.html#in-nodejs
|
||||
let zip = new AdmZip(filename)
|
||||
zip.extractAllTo(location, true)
|
||||
|
||||
// extract the notes database
|
||||
let db = await open({
|
||||
filename: location + 'collection.anki2',
|
||||
driver: sqlite3.cached.Database
|
||||
})
|
||||
|
||||
let result = await db.get('SELECT sfld FROM notes WHERE id = :n', 1486785585103)
|
||||
|
||||
console.log(result);
|
||||
|
||||
// extract media files
|
||||
// ? process/rename media files and update in db?
|
||||
// load data into this obj
|
||||
|
||||
// return { notes, media }
|
||||
}
|
||||
}
|
||||
|
||||
export default Deck
|
||||
BIN
backend/lib/test.apkg
Normal file
4
backend/lib/test.js
Normal file
@@ -0,0 +1,4 @@
|
||||
import Deck from './anki.js'
|
||||
|
||||
let deck = new Deck()
|
||||
await deck.process('test.apkg');
|
||||
BIN
backend/lib/test/0
Normal file
BIN
backend/lib/test/1
Normal file
|
After Width: | Height: | Size: 14 KiB |
BIN
backend/lib/test/10
Normal file
BIN
backend/lib/test/11
Normal file
|
After Width: | Height: | Size: 14 KiB |
BIN
backend/lib/test/12
Normal file
|
After Width: | Height: | Size: 13 KiB |
BIN
backend/lib/test/13
Normal file
|
After Width: | Height: | Size: 13 KiB |
BIN
backend/lib/test/14
Normal file
|
After Width: | Height: | Size: 9.7 KiB |
BIN
backend/lib/test/15
Normal file
BIN
backend/lib/test/16
Normal file
BIN
backend/lib/test/17
Normal file
BIN
backend/lib/test/18
Normal file
BIN
backend/lib/test/19
Normal file
BIN
backend/lib/test/2
Normal file
|
After Width: | Height: | Size: 12 KiB |
BIN
backend/lib/test/20
Normal file
BIN
backend/lib/test/21
Normal file
BIN
backend/lib/test/22
Normal file
|
After Width: | Height: | Size: 7.8 KiB |
BIN
backend/lib/test/23
Normal file
|
After Width: | Height: | Size: 7.7 KiB |
BIN
backend/lib/test/24
Normal file
BIN
backend/lib/test/25
Normal file
|
After Width: | Height: | Size: 8.9 KiB |
BIN
backend/lib/test/26
Normal file
BIN
backend/lib/test/27
Normal file
|
After Width: | Height: | Size: 14 KiB |
BIN
backend/lib/test/28
Normal file
BIN
backend/lib/test/29
Normal file
|
After Width: | Height: | Size: 14 KiB |
BIN
backend/lib/test/3
Normal file
BIN
backend/lib/test/30
Normal file
BIN
backend/lib/test/31
Normal file
|
After Width: | Height: | Size: 9.9 KiB |
BIN
backend/lib/test/32
Normal file
|
After Width: | Height: | Size: 9.3 KiB |
BIN
backend/lib/test/33
Normal file
|
After Width: | Height: | Size: 11 KiB |
BIN
backend/lib/test/34
Normal file
BIN
backend/lib/test/35
Normal file
BIN
backend/lib/test/36
Normal file
|
After Width: | Height: | Size: 9.7 KiB |
BIN
backend/lib/test/37
Normal file
|
After Width: | Height: | Size: 12 KiB |
BIN
backend/lib/test/38
Normal file
|
After Width: | Height: | Size: 14 KiB |
BIN
backend/lib/test/39
Normal file
BIN
backend/lib/test/4
Normal file
BIN
backend/lib/test/40
Normal file
|
After Width: | Height: | Size: 12 KiB |
BIN
backend/lib/test/41
Normal file
|
After Width: | Height: | Size: 12 KiB |
BIN
backend/lib/test/42
Normal file
BIN
backend/lib/test/43
Normal file
|
After Width: | Height: | Size: 12 KiB |
BIN
backend/lib/test/44
Normal file
|
After Width: | Height: | Size: 11 KiB |
BIN
backend/lib/test/45
Normal file
|
After Width: | Height: | Size: 9.8 KiB |
BIN
backend/lib/test/46
Normal file
BIN
backend/lib/test/47
Normal file
BIN
backend/lib/test/48
Normal file
BIN
backend/lib/test/49
Normal file
BIN
backend/lib/test/5
Normal file
BIN
backend/lib/test/50
Normal file
|
After Width: | Height: | Size: 11 KiB |
BIN
backend/lib/test/51
Normal file
|
After Width: | Height: | Size: 13 KiB |
BIN
backend/lib/test/52
Normal file
|
After Width: | Height: | Size: 12 KiB |
BIN
backend/lib/test/53
Normal file
|
After Width: | Height: | Size: 7.8 KiB |
BIN
backend/lib/test/54
Normal file
BIN
backend/lib/test/55
Normal file
BIN
backend/lib/test/56
Normal file
BIN
backend/lib/test/57
Normal file
|
After Width: | Height: | Size: 15 KiB |
BIN
backend/lib/test/58
Normal file
|
After Width: | Height: | Size: 11 KiB |
BIN
backend/lib/test/59
Normal file
|
After Width: | Height: | Size: 11 KiB |
BIN
backend/lib/test/6
Normal file
BIN
backend/lib/test/60
Normal file
|
After Width: | Height: | Size: 9.8 KiB |
BIN
backend/lib/test/61
Normal file
BIN
backend/lib/test/62
Normal file
|
After Width: | Height: | Size: 10 KiB |
BIN
backend/lib/test/63
Normal file
BIN
backend/lib/test/64
Normal file
BIN
backend/lib/test/65
Normal file
|
After Width: | Height: | Size: 9.2 KiB |
BIN
backend/lib/test/66
Normal file
BIN
backend/lib/test/67
Normal file
BIN
backend/lib/test/68
Normal file
BIN
backend/lib/test/69
Normal file
BIN
backend/lib/test/7
Normal file
BIN
backend/lib/test/70
Normal file
BIN
backend/lib/test/71
Normal file
|
After Width: | Height: | Size: 8.0 KiB |
BIN
backend/lib/test/72
Normal file
BIN
backend/lib/test/73
Normal file
BIN
backend/lib/test/74
Normal file
|
After Width: | Height: | Size: 14 KiB |
BIN
backend/lib/test/75
Normal file
|
After Width: | Height: | Size: 13 KiB |
BIN
backend/lib/test/8
Normal file
|
After Width: | Height: | Size: 12 KiB |
BIN
backend/lib/test/9
Normal file
BIN
backend/lib/test/collection.anki2
Normal file
1
backend/lib/test/media
Normal file
@@ -0,0 +1 @@
|
||||
{"66": "rec1486791173.mp3", "12": "paste-5909874999552.jpg", "49": "rec1486790484.mp3", "54": "rec1486789453.mp3", "59": "paste-6051608920308.jpg", "75": "paste-7176890351876.jpg", "50": "paste-5952824672506.jpg", "11": "paste-5342939316470.jpg", "3": "rec1486790515.mp3", "73": "rec1486791444.mp3", "58": "paste-6743098654966.jpg", "26": "rec1486791092.mp3", "60": "paste-5596342386925.jpg", "68": "rec1486787151.mp3", "69": "rec1486790743.mp3", "0": "rec1486791250.mp3", "8": "paste-6219112644848.jpg", "18": "rec1486790648.mp3", "57": "paste-6880537608452.jpg", "61": "rec1486789557.mp3", "33": "paste-6343666696438.jpg", "7": "rec1486791037.mp3", "21": "rec1486786900.mp3", "44": "paste-5476083302645.jpg", "17": "rec1486790321.mp3", "9": "rec1486790979.mp3", "55": "rec1486790707.mp3", "64": "rec1486790888.mp3", "71": "paste-7563437408511.jpg", "53": "paste-6532645257453.jpg", "36": "paste-6322191859961.jpg", "31": "paste-7687991460090.jpg", "28": "rec1486790193.mp3", "47": "rec1486791121.mp3", "39": "rec1486791213.mp3", "14": "paste-7022271529203.jpg", "37": "paste-7288559501563.jpg", "15": "rec1486789738.mp3", "51": "paste-2929167696123.jpg", "25": "paste-7597797146867.jpg", "20": "rec1486790550.mp3", "19": "rec1486790446.mp3", "48": "rec1486788047.mp3", "74": "paste-5849745457397.jpg", "30": "rec1486791007.mp3", "10": "rec1486788946.mp3", "29": "paste-6846177870075.jpg", "4": "rec1486790287.mp3", "56": "rec1486789680.mp3", "62": "paste-5755256176881.jpg", "38": "paste-2143188680961.jpg", "70": "rec1486790804.mp3", "42": "rec1486790858.mp3", "43": "paste-7430293422343.jpg", "23": "paste-6158983102706.jpg", "72": "rec1486789502.mp3", "34": "rec1486790589.mp3", "16": "rec1486791310.mp3", "52": "paste-6266357285108.jpg", "32": "paste-687194767612.jpg", "65": "paste-6708738916592.jpg", "2": "paste-7142530613495.jpg", "40": "paste-816043786497.jpg", "1": "paste-1090921693442.jpg", "67": "rec1486791391.mp3", "5": "rec1486790677.mp3", "6": "rec1486791362.mp3", "46": "rec1486790948.mp3", "22": "paste-7073811136753.jpg", "63": "rec1486790918.mp3", "24": "rec1486790620.mp3", "27": "paste-4939212390648.jpg", "45": "paste-6644314407145.jpg", "41": "paste-5811090751727.jpg", "35": "rec1486789528.mp3", "13": "paste-6442450944247.jpg"}
|
||||
1
backend/lib/utils.js
Normal file
@@ -0,0 +1 @@
|
||||
export {}
|
||||