Last active
February 14, 2016 21:42
-
-
Save polymorphm/745f25d695b71cd163a5 to your computer and use it in GitHub Desktop.
script for web-browser -- for bulk copy MP3 files from http://pesni-tut.net/
This file contains hidden or 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
// -*- mode: js; coding: utf-8 -*- | |
(function (global) { | |
'use strict' | |
var MAIN_NAME = 'pesni-tut-net-make-xspf' | |
var XSPF_XMLNS = 'http://xspf.org/ns/0/' | |
function replace_cycle (str, old_sub_str, new_sub_str) { | |
var new_str | |
for (;;) { | |
new_str = str.replace(old_sub_str, new_sub_str) | |
if (new_str != str) { | |
str = new_str | |
continue | |
} | |
break | |
} | |
return new_str | |
} | |
function replace_all (str, old_sub_str, new_sub_str) { | |
var marker = '*' | |
while (str.indexOf(marker) != -1) { | |
marker += Math.floor((Math.random() * 10)).toString() + '*' | |
} | |
while (new_sub_str.indexOf(marker) != -1) { | |
marker += Math.floor((Math.random() * 10)).toString() + '*' | |
} | |
var new_str = replace_cycle(str, old_sub_str, marker) | |
var new_new_str = replace_cycle(new_str, marker, new_sub_str) | |
return new_new_str | |
} | |
function XMLIndent () {} | |
XMLIndent.prototype._SPACE = ' ' | |
XMLIndent.prototype.init = function (elem, doc, level) { | |
this._elem = elem | |
this._doc = doc | |
this._level = level | |
this._first_adding = true | |
} | |
function new_xml_indent () { | |
var new_xml_indent = new XMLIndent | |
new_xml_indent.init.apply( | |
new_xml_indent, Array.prototype.slice.call(arguments)) | |
return new_xml_indent | |
} | |
XMLIndent.prototype.get_level = function () { | |
return this._level | |
} | |
XMLIndent.prototype.appendChild = function (child_elem) { | |
var pre_indent = '' | |
var post_indent = '\n' | |
for (var i = 0; i < this._level - 1; ++i) { | |
post_indent += this._SPACE | |
} | |
if (this._first_adding) { | |
this._first_adding = false | |
pre_indent = post_indent | |
} | |
pre_indent += this._SPACE | |
this._elem.appendChild(this._doc.createTextNode(pre_indent)) | |
this._elem.appendChild(child_elem) | |
this._elem.appendChild(this._doc.createTextNode(post_indent)) | |
} | |
function XSPFBuilder () {} | |
XSPFBuilder.prototype._XMLNS = XSPF_XMLNS | |
XSPFBuilder.prototype.init = function () { | |
this._doc = document.implementation.createDocument( | |
this._XMLNS, 'playlist', null) | |
this._playlist = this._doc.firstChild | |
this._playlist_indent = new_xml_indent(this._playlist, this._doc, 1) | |
this._track_list = this._doc.createElementNS(this._XMLNS, 'trackList') | |
this._track_list_indent = new_xml_indent( | |
this._track_list, this._doc, this._playlist_indent.get_level() + 1) | |
this._playlist.setAttributeNS('', 'version', '1') | |
this._playlist_indent.appendChild(this._track_list) | |
} | |
function new_xspf_builder () { | |
var xspf_builder = new XSPFBuilder | |
xspf_builder.init.apply( | |
xspf_builder, Array.prototype.slice.call(arguments)) | |
return xspf_builder | |
} | |
XSPFBuilder.prototype.add_track = function (kwargs) { | |
if (kwargs === undefined) { | |
kwargs = {} | |
} | |
var track = this._doc.createElementNS(this._XMLNS, 'track') | |
var track_indent = new_xml_indent( | |
track, this._doc, this._track_list_indent.get_level() + 1) | |
if (kwargs.creator !== undefined) { | |
var creator = this._doc.createElementNS(this._XMLNS, 'creator') | |
creator.appendChild(document.createTextNode(kwargs.creator)) | |
track_indent.appendChild(creator) | |
} | |
if (kwargs.title !== undefined) { | |
var title = this._doc.createElementNS(this._XMLNS, 'title') | |
title.appendChild(document.createTextNode(kwargs.title)) | |
track_indent.appendChild(title) | |
} | |
if (kwargs.location !== undefined) { | |
var location = this._doc.createElementNS(this._XMLNS, 'location') | |
location.appendChild(document.createTextNode(kwargs.location)) | |
track_indent.appendChild(location) | |
} | |
if (kwargs.info !== undefined) { | |
var info = this._doc.createElementNS(this._XMLNS, 'info') | |
info.appendChild(document.createTextNode(kwargs.info)) | |
track_indent.appendChild(info) | |
} | |
this._track_list_indent.appendChild(track) | |
} | |
XSPFBuilder.prototype.get_out = function () { | |
var srl = new XMLSerializer() | |
return srl.serializeToString(this._doc) | |
} | |
function FetchBuilder () {} | |
FetchBuilder.prototype.init = function () { | |
this._out_list = [] | |
} | |
FetchBuilder.prototype._quote = function (arg) { | |
return '\'' + replace_all(arg, '\'', '\'\\\'\'') + '\'' | |
} | |
FetchBuilder.prototype._next_track_no = function () { | |
var no = this._out_list.length + 1 | |
var no_str = no.toString() | |
while (no_str.length < 4) { | |
no_str = '0' + no_str | |
} | |
return no_str | |
} | |
FetchBuilder.prototype.add_track = function (kwargs) { | |
if (kwargs === undefined) { | |
kwargs = {} | |
} | |
var location = kwargs.location | |
if (!location) { | |
return | |
} | |
var title | |
if (kwargs.title) { | |
title = kwargs.title | |
} else { | |
title = '(Unknown Track)' | |
} | |
if (kwargs.creator !== undefined) { | |
title = kwargs.creator + ' - ' + title | |
} | |
title = this._next_track_no() + ' - ' + title | |
replace_all(title, '/', ' ') | |
var cmd = 'fetch_track_file ' + this._quote(title) + ' ' + this._quote(location) | |
this._out_list.push(cmd) | |
} | |
function new_fetch_builder () { | |
var fetch_builder = new FetchBuilder | |
fetch_builder.init.apply( | |
fetch_builder, Array.prototype.slice.call(arguments)) | |
return fetch_builder | |
} | |
FetchBuilder.prototype.get_out = function () { | |
if (this._out_list.length) { | |
return this._out_list.join('\n') | |
} else { | |
return '# track list is empty. nothing to do' | |
} | |
} | |
function query_selector_any(elem, sel_list) { | |
for (var i = 0; i < sel_list.length; ++i) { | |
var sel = sel_list[i] | |
var val = elem.querySelector(sel) | |
if (val) { | |
return val | |
} | |
} | |
} | |
function get_elem_value (elem) { | |
var child = elem.firstChild | |
if (!child || !child.nodeValue) { | |
return '' | |
} | |
return child.nodeValue.replace(/^\s+|\s+$/g, '').replace(/\s*\n\s*/g, ' ') | |
} | |
function get_href() { | |
return location.href | |
} | |
function get_track_id (elem) { | |
// stub only (for future) | |
return 1234567 | |
} | |
function get_location (elem, track_id) { | |
var ico_elem = elem.querySelector('.play > .ico') | |
if (!ico_elem) { | |
return | |
} | |
var data_url = ico_elem.dataset.url | |
return data_url | |
} | |
function get_title (elem, track_id) { | |
var title_elem = elem.querySelector('.isint') | |
if (!title_elem) { | |
return | |
} | |
return get_elem_value(title_elem) | |
} | |
function scan_elem (elem, add_track_callback) { | |
var track_id = get_track_id(elem) | |
if (!track_id) { | |
return | |
} | |
var location = get_location(elem, track_id) | |
if (!location) { | |
return | |
} | |
var title = get_title(elem, track_id) | |
add_track_callback({ | |
creator: undefined, | |
title: title, | |
location: location, | |
info: get_href(), | |
}) | |
} | |
function scan (add_track_callback) { | |
var elem_list = document.querySelectorAll( | |
'html > body #content_container > #content > .blok_pesni') | |
for (var i = 0, elem = elem_list.item(0); | |
elem; elem = elem_list.item(++i)) { | |
scan_elem(elem, add_track_callback) | |
} | |
} | |
function print (text) { | |
var layout = document.querySelector( | |
'html > body #footer > #footer_info') | |
var output = document.createElement('pre') | |
output.style.marginTop = '15px' | |
output.style.marginLeft = '30px' | |
output.style.marginRight = '30px' | |
output.style.marginBottom = '15px' | |
output.style.overflow = 'visible' | |
output.style.textAlign = 'left' | |
output.appendChild(document.createTextNode(text)) | |
layout.appendChild(output) | |
} | |
function main () { | |
var xspf_builder = new_xspf_builder() | |
var fetch_builder = new_fetch_builder() | |
scan(function (kwargs) { | |
xspf_builder.add_track(kwargs) | |
fetch_builder.add_track(kwargs) | |
}) | |
print( | |
'-----BEGIN XSPF FILE-----\n' + | |
'<?xml version="1.0" encoding="UTF-8"?>\n' + | |
xspf_builder.get_out() + | |
'\n-----END XSPF FILE-----' | |
) | |
print( | |
'-----BEGIN FETCH SCRIPT-----\n' + | |
'#!/usr/bin/env bash\n\n' + | |
'fetch_track_file () {\n' + | |
' curl --socks5 "127.0.0.1:1081" -C - --output "$1.mp3" -- "$2"\n' + | |
'}\n\n' + | |
fetch_builder.get_out() + | |
'\n-----END FETCH SCRIPT-----' | |
) | |
} | |
global[MAIN_NAME] = main | |
main() | |
})(this) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment