ashi-smule
Version:
AshiTEAM Smule Song Downloader
235 lines • 12.4 kB
JavaScript
;
/// <reference path="SmuleUserData.ts"/>
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __generator = (this && this.__generator) || function (thisArg, body) {
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
function verb(n) { return function (v) { return step([n, v]); }; }
function step(op) {
if (f) throw new TypeError("Generator is already executing.");
while (_) try {
if (f = 1, y && (t = y[op[0] & 2 ? "return" : op[0] ? "throw" : "next"]) && !(t = t.call(y, op[1])).done) return t;
if (y = 0, t) op = [0, t.value];
switch (op[0]) {
case 0: case 1: t = op; break;
case 4: _.label++; return { value: op[1], done: false };
case 5: _.label++; y = op[1]; op = [0]; continue;
case 7: op = _.ops.pop(); _.trys.pop(); continue;
default:
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
if (t[2]) _.ops.pop();
_.trys.pop(); continue;
}
op = body.call(thisArg, _);
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
}
};
Object.defineProperty(exports, "__esModule", { value: true });
var SmuleUserData_1 = require("./SmuleUserData");
var SmuleRecording_1 = require("./SmuleRecording");
var SmuleSongChunk = (function () {
function SmuleSongChunk() {
}
return SmuleSongChunk;
}());
exports.SmuleSongChunk = SmuleSongChunk;
var SmuleUser = (function () {
function SmuleUser(screenName, outputFolder) {
this.SmuleURL = "https://www.smule.com/";
var os = require('os');
this.m_ScreenName = screenName;
this.m_OutputFolder = outputFolder;
if (this.m_OutputFolder === undefined || this.m_OutputFolder === null || this.m_OutputFolder == '') {
this.m_OutputFolder = os.homedir() + "/AshiSmule/";
}
var fse = require('fs-extra');
fse.ensureDir(this.m_OutputFolder, function (err) {
if (err) {
console.log("Error: " + err);
process.exit(1);
}
});
}
SmuleUser.prototype.LoadChunk = function (offset) {
var pThis = this;
return new Promise(function (resolve, reject) {
var https = require('follow-redirects').https;
var userDataURL = "https://www.smule.com/" + pThis.m_ScreenName + "/performances/json";
if (offset > 0)
userDataURL += "?offset=" + offset.toString();
https.get(userDataURL, function (res, cb) {
var sJson = '';
res.on('data', function (chunk) {
sJson += chunk;
});
res.on('end', function () {
try {
var userData = SmuleUserData_1.SmuleUserDataProxy.Parse(sJson);
var songChunk = new SmuleSongChunk();
songChunk.Songs = userData.list;
songChunk.Next_Offset = userData.next_offset;
resolve(songChunk);
}
catch (err) {
reject("Invalid screen name: " + pThis.m_ScreenName);
}
});
}).on("error", function (err) {
reject(err);
});
});
};
SmuleUser.prototype.GetHTMLPage = function (sUrl) {
var pThis = this;
return new Promise(function (resolve, reject) {
var https = require('follow-redirects').https;
https.get(sUrl, function (res, cb) {
var sHTML = '';
res.on('data', function (chunk) {
sHTML += chunk;
});
res.on('end', function () {
resolve(sHTML);
});
}).on("error", function (err) {
reject(err);
});
});
};
SmuleUser.prototype.GetSmuleRecording = function (song) {
var pRec = new SmuleRecording_1.SmuleRecording();
pRec.Init1(song, this.m_OutputFolder);
return pRec;
};
SmuleUser.prototype.DownloadAllSongsInParts = function () {
return __awaiter(this, void 0, void 0, function () {
var i, chalk, ora, spinner, logUpdate, jsdom, JSDOM, userData, userDataURL, userDataURLToUse, done, i_1, j, k, totalSoFar, totalDownloaded, songChunk, recordings, sCollabHTML, dom, aElements, pCollabs, songName, songURL, imageURL, singers, collabElement, test, temp, parentElement, pH4, artists, pRec, err_1, errMsg;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
chalk = require('chalk');
ora = require('ora');
spinner = ora();
logUpdate = require('log-update');
jsdom = require("jsdom");
JSDOM = jsdom.JSDOM;
_a.label = 1;
case 1:
_a.trys.push([1, 14, , 15]);
userData = void 0;
userDataURL = "https://www.smule.com/" + this.m_ScreenName + "/performances/json";
userDataURLToUse = userDataURL;
done = false;
j = void 0;
k = void 0;
totalSoFar = 0;
totalDownloaded = 0;
spinner.text = "" + chalk.dim('Fetching all songs for ' + this.m_ScreenName + '...');
spinner.start();
songChunk = new SmuleSongChunk();
songChunk.Next_Offset = 0;
_a.label = 2;
case 2: return [4 /*yield*/, this.LoadChunk(songChunk.Next_Offset)];
case 3:
songChunk = _a.sent();
if (totalSoFar > 0)
spinner.start();
spinner.text = chalk.dim('So far found ' + totalSoFar.toString() + ' songs');
recordings = [];
i_1 = 0;
_a.label = 4;
case 4:
if (!(i_1 < songChunk.Songs.length)) return [3 /*break*/, 8];
if (!(songChunk.Songs[i_1].child_count > 0)) return [3 /*break*/, 6];
spinner.text = chalk.dim('Getting collabs of ' + songChunk.Songs[i_1].title);
return [4 /*yield*/, this.GetHTMLPage(this.SmuleURL + songChunk.Songs[i_1].web_url)];
case 5:
sCollabHTML = _a.sent();
dom = new JSDOM(sCollabHTML);
aElements = dom.window.document.querySelectorAll('a');
pCollabs = new Array(0);
for (j = 0; j < aElements.length; ++j) {
if ((" " + aElements[j].className + " ").indexOf(" " + "album-art playable" + " ") > -1) {
pCollabs.push(aElements[j]);
}
}
songName = songChunk.Songs[i_1].title;
spinner.text = chalk.dim('Found ' + pCollabs.length + ' collaborations for song ' + songName);
totalSoFar += pCollabs.length;
for (j = 0; j < pCollabs.length; ++j) {
songURL = null;
imageURL = null;
singers = [];
collabElement = pCollabs[j];
test = collabElement.outerHTML;
if (collabElement.href !== undefined) {
songURL = this.SmuleURL + collabElement.href;
}
if (collabElement.style !== undefined) {
temp = collabElement.style.cssText;
temp = temp.replace("background-image: url(", "").trim();
if (temp.endsWith(");"))
temp = temp.substring(0, temp.length - 2);
imageURL = temp;
}
parentElement = collabElement.parentElement;
pH4 = parentElement.querySelectorAll("h4");
if (pH4.length == 1) {
artists = pH4[0].textContent.trim();
singers = artists.split('+');
}
pRec = new SmuleRecording_1.SmuleRecording();
pRec.Init2(songChunk.Songs[i_1].title, songURL, imageURL, singers, songChunk.Songs[i_1].type, this.m_OutputFolder);
recordings.push(pRec);
}
return [3 /*break*/, 7];
case 6:
totalSoFar++;
recordings.push(this.GetSmuleRecording(songChunk.Songs[i_1]));
_a.label = 7;
case 7:
++i_1;
return [3 /*break*/, 4];
case 8:
spinner.succeed(chalk.green("So far found " + totalSoFar + " songs for " + this.m_ScreenName));
k = 0;
_a.label = 9;
case 9:
if (!(k < recordings.length)) return [3 /*break*/, 12];
return [4 /*yield*/, recordings[k].Download()];
case 10:
if (_a.sent())
totalDownloaded++;
_a.label = 11;
case 11:
++k;
return [3 /*break*/, 9];
case 12:
if (songChunk.Next_Offset > 0) return [3 /*break*/, 2];
_a.label = 13;
case 13: return [2 /*return*/, { "totalDownloaded": totalDownloaded, "totalFound": totalSoFar }];
case 14:
err_1 = _a.sent();
errMsg = "Failed to load all songs for " + this.m_ScreenName + ": " + err_1;
spinner.fail("" + chalk.red.bgWhite(errMsg));
throw errMsg;
case 15: return [2 /*return*/];
}
});
});
};
return SmuleUser;
}());
exports.SmuleUser = SmuleUser;
//# sourceMappingURL=SmuleUser.js.map