// Modules to install separately
const puppeteer = require('puppeteer');
const request = require('request');
const fs = require('fs');
const path = require('path');
var timeRefresh = 120;
const musicPath = './files/';
var clientId = '';
function randomUUI(a,b){for(b=a='';a++<36;b+=a*51&52?(a^15?8^Math.random()*(a^20?16:4):4).toString(16):'');return b}
const getConfigInfo = async () => {
const browser = await puppeteer.launch({ headless: true });
const page = await browser.newPage();
await page.setRequestInterception(true);
page.on('request', async (request) => {
if (request.url().indexOf('https://api-v2.soundcloud.com/search?') == 0){
const url = request.url();
const params = url.split('&');
const client_id = params.find(el => el.indexOf('client_id') == 0).replace('client_id=', '');
clientId = client_id || '';
}
request.continue();
});
await page.goto('https://soundcloud.com/search?q=dance%20monkey', {
waitUntil: 'load',
timeout: 0
});
await browser.close();
}
function escapeRegExp(string){
return string.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
}
function replaceAll(str, term, replacement) {
return str.replace(new RegExp(escapeRegExp(term), 'g'), replacement);
}
function replaceEspecialCharacter(str){
var chars={
"á":"a", "é":"e", "í":"i", "ó":"o", "ú":"u",
"à":"a", "è":"e", "ì":"i", "ò":"o", "ù":"u",
"Á":"A", "É":"E", "Í":"I", "Ó":"O", "Ú":"U",
"À":"A", "È":"E", "Ì":"I", "Ò":"O", "Ù":"U"}
var expr=/[áàéèíìóòúù]/ig;
var res=str.replace(expr,function(e){return chars[e]});
return res;
}
var downloadMp3 = async function(in_url){
return new Promise(function(resolve, reject) {
let uui = randomUUI();
let mp3File = path.join(__dirname, `${musicPath}${uui}.mp3`);
request(in_url)
.on('error', (err) => {
reject('Error');
})
.pipe(fs.createWriteStream(mp3File))
.on('close', () => resolve(mp3File))
.on('error', error => reject('Error'))
})
}
var searchProgressiveMp3 = async function(in_url, client_id){
return new Promise(function(resolve, reject) {
request(`${in_url}?client_id=${client_id}`, { json: true }, (err, res, body) => {
if (err) {
reject('Error');
}else{
resolve(body);
}
});
})
}
var searchTrack = async function (in_search, client_id){
return new Promise(function(resolve, reject) {
request(`https://api-v2.soundcloud.com/search/tracks?kind=%27user%27&client_id=${client_id}&q=${replaceEspecialCharacter(in_search)}`, { json: true }, (err, res, body) => {
if (err) {
reject('Error');
}else{
resolve(body);
}
});
})
}
const defaultConfig = {
idChat: '',
search: '',
messageError: '*Ooops, An error occurred while trying to get the requested song, please try again later*',
messageNoDataFound: '*The requested song could not be found, please try another*',
messageValidClientId: '*A valid clientId must be provided*'
}
/**
* Plugin to get a song in mp3 format directly from soundcloud
* @function music
* @memberof Plugins
* @param {string} idChat - Chat id to send the new image to
* @param {string} search - Customer search parameter
* @param {string} messageError - Message to send in case of error
* @param {string} messageNoDataFound - Message to send in case of not finding information
* @param {string} messageValidClientId - Message to send when a clientId is not indicated in the initial configuration
* @see {@link https://soundcloud.com|SoundCloud}
*/
module.exports = {
/**
* Id - Name of the plugin to use
* @property {string} id - Name of the plugin to use
*/
id: 'music',
/**
* Initial setting function to pass the parameters manually (no longer necessary, there is a process that does it)
* @param {object} data - Initial information for the plugin
* @param {string} data.clientId
*/
setup(data) {
if (typeof data.clientId !== 'undefined') {
clientId = data.clientId
}
},
/**
* Initial function triggered only if the user adds this plugin to the initial configuration
*/
init() {
// REFRESH Config Info EVERY X MINUTES
getConfigInfo();
setInterval(() => {
getConfigInfo();
}, 60000 * timeRefresh);
},
plugin(_args) {
let _this = this;
const args = _this.mergeOpts(defaultConfig, _args);
if (args.idChat !== '' && args.search !== '') {
if (clientId !== ''){
searchTrack(args.search.toLowerCase().trim(), clientId.trim())
.then(data => {
if(typeof data.collection === 'undefined' || data.collection === undefined || data.collection.length === 0){
_this.sendMessage({
"idChat": args.idChat,
"message": args.messageNoDataFound
});
}else{
let track, media, progressiveUrl;
let found_ = false;
for(var x=0; x < data.collection.length; x++){
track = data.collection[x];
// Para prevenir descargar canciones Preview
if (track.duration > 30000){
media = track.media.transcodings.find(obj => obj.format.protocol === 'progressive');
if(media !== undefined){
found_ = true;
progressiveUrl = media.url;
break;
}
}
}
if(!found_){
_this.sendMessage({
"idChat": args.idChat,
"message": args.messageNoDataFound
});
}else {
searchProgressiveMp3(progressiveUrl, clientId.trim())
.then(dataMp3 => {
downloadMp3(dataMp3.url)
.then(file_ => {
var bitmap = fs.readFileSync(file_);
var encodedstring = new Buffer.from(bitmap).toString('base64');
fs.unlinkSync(file_);
_this.sendMusic({
"idChat": args.idChat,
"file": encodedstring
})
})
.catch(err => {
_this.sendMessage({
"idChat": args.idChat,
"message": args.messageError
});
})
})
.catch(err => {
_this.sendMessage({
"idChat": args.idChat,
"message": args.messageError
});
})
}
}
})
.catch(err => {
_this.sendMessage({
"idChat": args.idChat,
"message": args.messageError
});
})
} else {
_this.sendMessage({
"idChat": args.idChat,
"message": args.messageValidClientId
});
}
}
}
};
Source