From c380d1fa7d22bc3ef056b74c5af93413067c9a5b Mon Sep 17 00:00:00 2001 From: liam4 Date: Sat, 1 Jul 2017 15:25:57 -0300 Subject: iTunes crawler --- src/crawl-itunes.js | 103 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 103 insertions(+) create mode 100644 src/crawl-itunes.js (limited to 'src') diff --git a/src/crawl-itunes.js b/src/crawl-itunes.js new file mode 100644 index 0000000..9c119da --- /dev/null +++ b/src/crawl-itunes.js @@ -0,0 +1,103 @@ + +const fs = require('fs') +const path = require('path') +const xmldoc = require('xmldoc') + +const { promisify } = require('util') +const readFile = promisify(fs.readFile) + +function getDictValue(dict, key) { + if (dict.name !== 'dict') { + throw new Error("Not a dict: " + dict.name) + } + + for (let i = 0; i < dict.children.length; i++) { + const child = dict.children[i] + if (child.name === 'key') { + if (child.val === key) { + return dict.children.slice(i + 1).find(item => !item.text) + } + } + } + + return null +} + +async function crawl(libraryXML) { + const document = new xmldoc.XmlDocument(libraryXML) + + const libraryDict = document.children.find(child => child.name === 'dict') + + const tracksDict = getDictValue(libraryDict, 'Tracks') + + const trackDicts = tracksDict.children.filter(child => child.name === 'dict') + + const result = [] + + for (let trackDict of trackDicts) { + let kind = getDictValue(trackDict, 'Kind') + kind = kind && kind.val + kind = kind || '' + + if (!kind.includes('audio file')) { + continue + } + + let location = getDictValue(trackDict, 'Location') + location = location && location.val + location = location || '' + + if (!location) { + continue + } + + let name = getDictValue(trackDict, 'Name') + name = name && name.val + name = name || 'Unknown Name' + + let album = getDictValue(trackDict, 'Album') + album = album && album.val + album = album || 'Unknown Album' + + let artist = getDictValue(trackDict, 'Artist') + artist = artist && artist.val + artist = artist || 'Unknown Artist' + + // console.log(`${artist} - ${name} (${album})`) + + const group = (arr, title) => arr.find(g => g[0] === title) + + let artistGroup = group(result, artist) + + if (!artistGroup) { + artistGroup = [artist, []] + result.push(artistGroup) + } + + let albumGroup = group(artistGroup[1], album) + + if (!albumGroup) { + albumGroup = [album, []] + artistGroup[1].push(albumGroup) + } + + albumGroup[1].push([name, location]) + } + + return result +} + +async function main() { + const libraryPath = process.argv[3] || ( + `${process.env.HOME}/Music/iTunes/iTunes Music Library.xml` + ) + + const library = await readFile(libraryPath) + + const playlist = await crawl(library) + + console.log(JSON.stringify(playlist, null, 2)) +} + +main() + .catch(err => console.error(err)) -- cgit 1.3.0-6-gf8a5